MRTKLIB 0.7.14
Modernized GNSS Positioning Library
Loading...
Searching...
No Matches
mrtk_l6.h
Go to the documentation of this file.
1/*------------------------------------------------------------------------------
2 * mrtk_l6.h : QZSS L6 frame header parsing and service classification
3 *
4 * Copyright (C) 2026 H.SHIONO (MRTKLIB Project)
5 *
6 * References:
7 * [1] IS-QZSS-L6-008, 4.1.2 (L6 message structure, Table 4.1.2-2), 4.1.2.3
8 * (null message)
9 * [2] IS-QZSS-MDC-004, 4.2.1 (Tables 4.2.1-2, 4.2.1-3)
10 * [3] IS-QZSS-SAS-001, 6.10 (Table 6-8: L6 vendor ID and service name)
11 *
12 * SPDX-License-Identifier: BSD-2-Clause
13 *----------------------------------------------------------------------------*/
14/**
15 * @file mrtk_l6.h
16 * @brief MRTKLIB L6 Module — QZSS L6 frame header parsing.
17 *
18 * Every QZSS L6 frame (L6D and L6E) starts with a 49-bit header: 32-bit
19 * preamble, 8-bit PRN, 8-bit L6 message type ID and 1-bit alert flag,
20 * followed by 1695 data bits and a 256-bit Reed-Solomon parity. The service
21 * carried by a frame (CLAS, MADOCA-PPP, QZNMA) is identified by the vendor
22 * ID in the message type ID [3], never by the PRN: L6E PRNs time-multiplex
23 * MADOCA-PPP and QZNMA frames, and PRN-to-service assignments change over
24 * time.
25 *
26 * The functions here are stateless; byte synchronisation and subframe
27 * assembly stay with each service decoder.
28 */
29#ifndef MRTK_L6_H
30#define MRTK_L6_H
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36#include <stdint.h>
37
38/*============================================================================
39 * Frame Constants
40 *===========================================================================*/
41
42#define L6_PREAMBLE 0x1ACFFC1DU /* L6 frame preamble */
43#define L6_FRAME_LEN 218 /* frame length without R-S parity (bytes) */
44#define L6_RAW_LEN 250 /* frame length with R-S parity (bytes) */
45#define L6_HEADER_BITS 49 /* preamble + PRN + type ID + alert (bits) */
46#define L6_DATA_BITS 1695 /* data part (bits) */
47#define L6_FILE_SCAN_BYTES 65536 /* read chunk of l6_file_service() */
48
49#define L6_VID_MADOCA 2 /* vendor ID 010b: MADOCA-PPP (L6D and L6E) [3] */
50#define L6_VID_QZNMA 3 /* vendor ID 011b: QZNMA (L6E only) [3] */
51#define L6_VID_CLAS 5 /* vendor ID 101b: CLAS (L6D only) [3] */
52
53/*============================================================================
54 * Types
55 *===========================================================================*/
56
57/** @brief Service carried by an L6 frame. */
58typedef enum {
59 L6_SVC_UNKNOWN = 0, /**< bad preamble or reserved vendor ID */
60 L6_SVC_NULL, /**< null message [1] 4.1.2.3 */
61 L6_SVC_CLAS, /**< CLAS (vendor 101b) */
62 L6_SVC_MADOCA, /**< MADOCA-PPP clock/ephemeris (vendor 010b, CSID 0) */
63 L6_SVC_MADOCA_IONO, /**< MADOCA-PPP ionospheric corrections (vendor 010b, CSID 1) */
64 L6_SVC_QZNMA /**< QZNMA (vendor 011b) */
66
67/** @brief Decoded L6 frame header. Raw bit fields; no service-specific remapping. */
68typedef struct {
69 uint32_t preamble; /**< 32-bit preamble (L6_PREAMBLE when valid) */
70 uint8_t prn; /**< L6 PRN (header byte 4; L6E PRNs exceed MAXPRNQZS) */
71 uint8_t msgid; /**< L6 message type ID (header byte 5) */
72 uint8_t vid; /**< vendor ID, msgid bits 7-5 */
73 uint8_t fac; /**< msgid bits 4-3 (CLAS: facility + pattern ID; MADOCA: facility) */
74 uint8_t ptn; /**< msgid bits 2-1 (CLAS transmit pattern ID) */
75 uint8_t csid; /**< msgid bit 2 (MADOCA correction service ID: 0 clk/eph, 1 iono) */
76 uint8_t anme; /**< msgid bit 1 (MADOCA applicable navigation message extension) */
77 uint8_t sf_ind; /**< msgid bit 0 (subframe indicator: 1 = first data part) */
78 uint8_t alert; /**< alert flag */
79 l6_service_t svc; /**< service classification */
81
82/**
83 * @brief Auxiliary per-PRN information for one L6 PRN.
84 *
85 * Nominal assignments from the PRN code assignment tables of [2] and [3]
86 * and the CLAS transmit-pattern table of [1] (Table 4.1.1-1). Used for
87 * logging, for consistency warnings and for the MADOCA ionospheric region
88 * slot, never for service classification: assignments change over time
89 * (PRN 197 moved from technology demonstration to CLAS in MDC revision 002)
90 * and L6E PRNs carry both MADOCA-PPP and QZNMA.
91 */
92typedef struct {
93 uint8_t prn; /**< L6 PRN */
94 const char* sat; /**< satellite name, e.g. "QZS2" */
95 uint8_t l6e; /**< 0: L6D PRN, 1: L6E PRN */
96 l6_service_t svc; /**< nominal service (L6E: MADOCA, QZNMA also expected) */
97 int8_t iono_slot; /**< MADOCA iono decoder slot (L6D PRN 200/201), -1 otherwise */
98 uint8_t pair_prn; /**< PRN of the other L6 signal of the same satellite, 0 if none */
100
101/*============================================================================
102 * Functions
103 *===========================================================================*/
104
105/**
106 * @brief Parse the header of one L6 frame and classify its service.
107 * @param[in] frame L6 frame starting at the preamble; at least L6_FRAME_LEN bytes.
108 * @param[out] h Decoded header. All fields are filled even when the preamble is invalid.
109 * @return 1 if the preamble is valid, 0 otherwise (h->svc is L6_SVC_UNKNOWN).
110 */
111int l6_parse_header(const uint8_t* frame, l6_header_t* h);
112
113/**
114 * @brief Test whether an L6 frame is a null message.
115 *
116 * Null message [1] 4.1.2.3: message type ID 0, alert flag 1, data part
117 * "0101010"b followed by repeated "10101010"b, i.e. bytes 6..217 all 0xAA.
118 *
119 * @param[in] frame L6 frame starting at the preamble; at least L6_FRAME_LEN bytes.
120 * @return 1 if the frame is a null message, 0 otherwise.
121 */
122int l6_is_null(const uint8_t* frame);
123
124/**
125 * @brief Look up the auxiliary information of an L6 PRN.
126 * @param[in] prn L6 PRN (header byte 4).
127 * @return Table entry, or NULL if the PRN has no nominal L6 assignment.
128 */
129const l6_prn_info_t* l6_prn_info(int prn);
130
131/**
132 * @brief Test whether a classified frame matches the nominal assignment of its PRN.
133 *
134 * Null messages always match; on L6E PRNs both MADOCA and QZNMA match.
135 *
136 * @param[in] h Parsed header.
137 * @return 1 if consistent, 0 if the PRN is unassigned or carries an unexpected service.
138 */
139int l6_service_expected(const l6_header_t* h);
140
141/** @brief QZSS L6 file type from the file name extension. */
142typedef enum {
143 L6_FILE_NONE = 0, /**< not an L6 file */
144 L6_FILE_L6, /**< ".l6" (legacy: CLAS L6D or MADOCA-PPP L6E) */
145 L6_FILE_L6D, /**< ".l6d" */
146 L6_FILE_L6E /**< ".l6e" */
148
149/**
150 * @brief Classify a file name by its QZSS L6 extension (case-insensitive).
151 * @param[in] file File path or name.
152 * @return L6 file type, L6_FILE_NONE if the extension is not .l6/.l6d/.l6e.
153 */
154l6_file_type_t l6_file_type(const char* file);
155
156/**
157 * @brief Service of an L6 frame file, from the first non-null frame header.
158 *
159 * Scans the start of the file (concatenated 218- or 250-byte frames, as
160 * written by receivers and archives) for the preamble and classifies the
161 * first frame that is not a null message.
162 *
163 * @param[in] file File path (no keyword expansion).
164 * @return Service, or L6_SVC_UNKNOWN if the file cannot be read or holds no
165 * classifiable frame. The file is read in L6_FILE_SCAN_BYTES chunks
166 * until the first classifiable frame, so a leading run of null
167 * messages of any length is skipped.
168 */
169l6_service_t l6_file_service(const char* file);
170
171/**
172 * @brief Short name of an L6 service, for logs.
173 * @param[in] svc Service.
174 * @return Static string (e.g. "CLAS", "MADOCA", "QZNMA").
175 */
176const char* l6_service_name(l6_service_t svc);
177
178#ifdef __cplusplus
179}
180#endif
181
182#endif /* MRTK_L6_H */
const l6_prn_info_t * l6_prn_info(int prn)
Look up the auxiliary information of an L6 PRN.
Definition mrtk_l6.c:74
int l6_service_expected(const l6_header_t *h)
Test whether a classified frame matches the nominal assignment of its PRN.
Definition mrtk_l6.c:85
l6_service_t
Service carried by an L6 frame.
Definition mrtk_l6.h:58
@ L6_SVC_UNKNOWN
Definition mrtk_l6.h:59
@ L6_SVC_NULL
Definition mrtk_l6.h:60
@ L6_SVC_QZNMA
Definition mrtk_l6.h:64
@ L6_SVC_CLAS
Definition mrtk_l6.h:61
@ L6_SVC_MADOCA
Definition mrtk_l6.h:62
@ L6_SVC_MADOCA_IONO
Definition mrtk_l6.h:63
l6_file_type_t l6_file_type(const char *file)
Classify a file name by its QZSS L6 extension (case-insensitive).
Definition mrtk_l6.c:100
int l6_parse_header(const uint8_t *frame, l6_header_t *h)
Parse the header of one L6 frame and classify its service.
Definition mrtk_l6.c:44
l6_service_t l6_file_service(const char *file)
Service of an L6 frame file, from the first non-null frame header.
Definition mrtk_l6.c:120
l6_file_type_t
QZSS L6 file type from the file name extension.
Definition mrtk_l6.h:142
@ L6_FILE_L6E
Definition mrtk_l6.h:146
@ L6_FILE_L6
Definition mrtk_l6.h:144
@ L6_FILE_NONE
Definition mrtk_l6.h:143
@ L6_FILE_L6D
Definition mrtk_l6.h:145
int l6_is_null(const uint8_t *frame)
Test whether an L6 frame is a null message.
Definition mrtk_l6.c:29
const char * l6_service_name(l6_service_t svc)
Short name of an L6 service, for logs.
Definition mrtk_l6.c:162
Decoded L6 frame header. Raw bit fields; no service-specific remapping.
Definition mrtk_l6.h:68
uint8_t prn
Definition mrtk_l6.h:70
uint8_t anme
Definition mrtk_l6.h:76
uint8_t alert
Definition mrtk_l6.h:78
uint8_t csid
Definition mrtk_l6.h:75
uint8_t msgid
Definition mrtk_l6.h:71
l6_service_t svc
Definition mrtk_l6.h:79
uint8_t fac
Definition mrtk_l6.h:73
uint8_t vid
Definition mrtk_l6.h:72
uint8_t ptn
Definition mrtk_l6.h:74
uint32_t preamble
Definition mrtk_l6.h:69
uint8_t sf_ind
Definition mrtk_l6.h:77
Auxiliary per-PRN information for one L6 PRN.
Definition mrtk_l6.h:92
l6_service_t svc
Definition mrtk_l6.h:96
uint8_t l6e
Definition mrtk_l6.h:95
const char * sat
Definition mrtk_l6.h:94
uint8_t prn
Definition mrtk_l6.h:93
int8_t iono_slot
Definition mrtk_l6.h:97
uint8_t pair_prn
Definition mrtk_l6.h:98