Files
gnss-sdr/utils/code_generation/generate_beidou_b1c_codes.py
T

188 lines
6.0 KiB
Python

#!/usr/bin/env python3
"""
Generate Beidou_B1C_codes.h/.cc from ICD Weil parameters in Beidou_B1C_prn.h.
-----------------------------------------------------------------------------
GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
This file is part of GNSS-SDR.
Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
SPDX-License-Identifier: GPL-3.0-or-later
Author: Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn
-----------------------------------------------------------------------------
"""
from __future__ import annotations
import re
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
PRN_HEADER = ROOT / "src/core/system_parameters/Beidou_B1C_prn.h"
OUT_HEADER = ROOT / "src/core/system_parameters/Beidou_B1C_codes.h"
OUT_SOURCE = ROOT / "src/core/system_parameters/Beidou_B1C_codes.cc"
def extract(name: str, text: str) -> list[int]:
match = re.search(rf"{name}\[63\]\s*=\s*\{{([^}}]+)\}}", text, re.S)
if not match:
raise RuntimeError(f"Could not parse {name}")
return [int(x.strip()) for x in match.group(1).split(",") if x.strip()]
def legendre(n: int) -> list[int]:
seq = [0] * n
for x in range(1, n):
seq[(x * x) % n] = 1
return seq
def weil_code(L: list[int], weil_len: int, w: int, p: int, out_len: int) -> list[int]:
W = [L[k] ^ L[(k + w) % weil_len] for k in range(weil_len)]
return [W[(n + p - 1) % weil_len] for n in range(out_len)]
def chips_to_hex(chips: list[int]) -> str:
out = ""
for i in range(0, len(chips), 4):
chunk = chips[i : i + 4]
value = 0
for bit in chunk:
value = (value << 1) | bit
while len(chunk) < 4:
value <<= 1
chunk.append(0)
out += format(value, "X")
return out
def chips_to_binstr(chips: list[int]) -> str:
return "".join(str(c) for c in chips)
# Keep generated source under the CI long-line limit (512 chars).
# Match the historical 76-char fragment width used in Beidou_B1C_codes.h.
_CODE_LINE_WIDTH = 76
def emit_array_decl(name: str, rows: list[str]) -> str:
return f"extern const char {name}[63][{len(rows[0]) + 1}];"
def emit_wrapped_string(row: str) -> list[str]:
"""Emit one array element as adjacent string literals, one chunk per line."""
chunks = [row[i : i + _CODE_LINE_WIDTH] for i in range(0, len(row), _CODE_LINE_WIDTH)]
if not chunks:
chunks = [""]
out: list[str] = []
for idx, chunk in enumerate(chunks):
suffix = "," if idx == len(chunks) - 1 else ""
out.append(f' "{chunk}"{suffix}')
return out
def emit_array_def(name: str, rows: list[str]) -> str:
lines = [f"const char {name}[63][{len(rows[0]) + 1}] = {{"]
for row in rows:
lines.extend(emit_wrapped_string(row))
lines.append("};")
return "\n".join(lines)
def main() -> None:
text = PRN_HEADER.read_text(encoding="utf-8")
data_w = extract("BEIDOU_B1C_DATA_PRN_W", text)
data_p = extract("BEIDOU_B1C_DATA_PRN_P", text)
pilot_w = extract("BEIDOU_B1C_PILOT_PRN_W", text)
pilot_p = extract("BEIDOU_B1C_PILOT_PRN_P", text)
sec_w = extract("BEIDOU_B1C_PILOT_SECONDARY_W", text)
sec_p = extract("BEIDOU_B1C_PILOT_SECONDARY_P", text)
L10243 = legendre(10243)
L3607 = legendre(3607)
data_hex = [
chips_to_hex(weil_code(L10243, 10243, data_w[i], data_p[i], 10230)) for i in range(63)
]
pilot_hex = [
chips_to_hex(weil_code(L10243, 10243, pilot_w[i], pilot_p[i], 10230)) for i in range(63)
]
sec_bin = [chips_to_binstr(weil_code(L3607, 3607, sec_w[i], sec_p[i], 1800)) for i in range(63)]
expected = "101011111111011001001110"
assert "".join(str(b) for b in weil_code(L10243, 10243, data_w[0], data_p[0], 10230)[:24]) == expected
script_name = Path(__file__).name
header = f"""/*!
* \\file Beidou_B1C_codes.h
* \\brief Precomputed BeiDou B1C primary and secondary codes (declarations)
* \\author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn
*
* Auto-generated by {script_name}. Do not edit manually.
* Definitions live in Beidou_B1C_codes.cc.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_BEIDOU_B1C_CODES_H
#define GNSS_SDR_BEIDOU_B1C_CODES_H
#include <cstddef>
constexpr size_t BEIDOU_B1C_PRIMARY_CODE_STR_LENGTH = 2558;
constexpr size_t BEIDOU_B1C_PILOT_SECONDARY_CODE_STR_LENGTH = 1800;
{emit_array_decl("BEIDOU_B1C_DATA_PRIMARY_CODE", data_hex)}
{emit_array_decl("BEIDOU_B1C_PILOT_PRIMARY_CODE", pilot_hex)}
{emit_array_decl("BEIDOU_B1C_PILOT_SECONDARY_CODE", sec_bin)}
#endif
"""
source = f"""/*!
* \\file Beidou_B1C_codes.cc
* \\brief Precomputed BeiDou B1C primary and secondary codes
* \\author Wenhao Ou, 2026. ouwh(at)mail2.sysu.edu.cn
*
* Auto-generated by {script_name}. Do not edit manually.
*
* -----------------------------------------------------------------------------
*
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
*/
#include "Beidou_B1C_codes.h"
{emit_array_def("BEIDOU_B1C_DATA_PRIMARY_CODE", data_hex)}
{emit_array_def("BEIDOU_B1C_PILOT_PRIMARY_CODE", pilot_hex)}
{emit_array_def("BEIDOU_B1C_PILOT_SECONDARY_CODE", sec_bin)}
"""
OUT_HEADER.write_text(header, encoding="utf-8")
OUT_SOURCE.write_text(source, encoding="utf-8")
print(f"Wrote {OUT_HEADER} ({len(header)} bytes)")
print(f"Wrote {OUT_SOURCE} ({len(source)} bytes)")
if __name__ == "__main__":
main()