11#if DETWS_ENABLE_NTRIP_CASTER
19uint32_t rtcm3_crc24q(
const uint8_t *data,
size_t len)
22 for (
size_t i = 0; i < len; i++)
24 crc ^= (uint32_t)data[i] << 16;
25 for (
int b = 0; b < 8; b++)
32 return crc & 0xFFFFFFu;
39void rtcm_bw_init(RtcmBitWriter *w, uint8_t *buf,
size_t cap)
42 w->cap_bits = cap * 8;
47void rtcm_bw_u(RtcmBitWriter *w, uint64_t val, uint8_t nbits)
51 if (nbits == 0 || nbits > 64 || w->pos + nbits > w->cap_bits)
56 for (
int i = (
int)nbits - 1; i >= 0; i--)
61 w->buf[bp >> 3] |= (uint8_t)(0x80u >> (bp & 7u));
67void rtcm_bw_s(RtcmBitWriter *w, int64_t val, uint8_t nbits)
69 uint64_t mask = (nbits >= 64) ? ~0ULL : ((1ULL << nbits) - 1ULL);
70 rtcm_bw_u(w, (uint64_t)val & mask, nbits);
73uint64_t rtcm_br_u(
const uint8_t *buf,
size_t *pos, uint8_t nbits)
76 for (uint8_t i = 0; i < nbits; i++)
79 uint64_t bit = (buf[bp >> 3] >> (7u - (bp & 7u))) & 1u;
85int64_t rtcm_br_s(
const uint8_t *buf,
size_t *pos, uint8_t nbits)
87 uint64_t v = rtcm_br_u(buf, pos, nbits);
88 if (nbits < 64 && (v & (1ULL << (nbits - 1))))
89 v |= ~((1ULL << nbits) - 1ULL);
97size_t rtcm3_sync(
const uint8_t *buf,
size_t len)
99 for (
size_t i = 0; i < len; i++)
100 if (buf[i] == RTCM3_PREAMBLE)
105size_t rtcm3_frame_parse(
const uint8_t *buf,
size_t len, Rtcm3Frame *out)
107 if (len < RTCM3_HDR_LEN || buf[0] != RTCM3_PREAMBLE)
109 uint16_t payload_len = (uint16_t)(((buf[1] & 0x03u) << 8) | buf[2]);
110 size_t frame_len = (size_t)RTCM3_HDR_LEN + payload_len + RTCM3_CRC_LEN;
113 const uint8_t *payload = buf + RTCM3_HDR_LEN;
114 uint32_t crc_calc = rtcm3_crc24q(buf, (
size_t)RTCM3_HDR_LEN + payload_len);
116 ((uint32_t)payload[payload_len] << 16) | ((uint32_t)payload[payload_len + 1] << 8) | payload[payload_len + 2];
119 out->payload = payload;
120 out->payload_len = payload_len;
121 out->crc_ok = (crc_calc == crc_frame);
123 out->msg_type = (payload_len >= 2) ? (uint16_t)rtcm_br_u(payload, &p, 12) : 0;
128size_t rtcm3_frame_build(uint8_t *out,
size_t cap,
const uint8_t *payload, uint16_t payload_len)
130 if (payload_len > RTCM3_MAX_PAYLOAD)
132 size_t frame_len = (size_t)RTCM3_HDR_LEN + payload_len + RTCM3_CRC_LEN;
133 if (!out || cap < frame_len)
135 out[0] = RTCM3_PREAMBLE;
136 out[1] = (uint8_t)((payload_len >> 8) & 0x03u);
137 out[2] = (uint8_t)(payload_len & 0xFFu);
138 if (payload_len && payload)
139 memcpy(out + RTCM3_HDR_LEN, payload, payload_len);
140 uint32_t crc = rtcm3_crc24q(out, (
size_t)RTCM3_HDR_LEN + payload_len);
141 out[RTCM3_HDR_LEN + payload_len] = (uint8_t)((crc >> 16) & 0xFFu);
142 out[RTCM3_HDR_LEN + payload_len + 1] = (uint8_t)((crc >> 8) & 0xFFu);
143 out[RTCM3_HDR_LEN + payload_len + 2] = (uint8_t)(crc & 0xFFu);
153size_t build_arp(uint8_t *out,
size_t cap, uint16_t msg, uint16_t station_id, int64_t x, int64_t y, int64_t z,
154 bool with_h, uint16_t h)
157 memset(payload, 0,
sizeof payload);
159 rtcm_bw_init(&w, payload,
sizeof payload);
160 rtcm_bw_u(&w, msg, 12);
161 rtcm_bw_u(&w, station_id & 0xFFF, 12);
167 rtcm_bw_s(&w, x, 38);
170 rtcm_bw_s(&w, y, 38);
172 rtcm_bw_s(&w, z, 38);
173 uint16_t body_bytes = 19;
176 rtcm_bw_u(&w, h, 16);
181 return rtcm3_frame_build(out, cap, payload, body_bytes);
185size_t rtcm3_build_1005(uint8_t *out,
size_t cap, uint16_t station_id, int64_t ecef_x_01mm, int64_t ecef_y_01mm,
188 return build_arp(out, cap, 1005, station_id, ecef_x_01mm, ecef_y_01mm, ecef_z_01mm,
false, 0);
191size_t rtcm3_build_1006(uint8_t *out,
size_t cap, uint16_t station_id, int64_t ecef_x_01mm, int64_t ecef_y_01mm,
192 int64_t ecef_z_01mm, uint16_t antenna_height_01mm)
194 return build_arp(out, cap, 1006, station_id, ecef_x_01mm, ecef_y_01mm, ecef_z_01mm,
true, antenna_height_01mm);
197bool rtcm3_parse_1005(
const uint8_t *payload, uint16_t payload_len, Rtcm3StationArp *out)
199 if (!payload || !out || payload_len < 19)
202 uint16_t msg = (uint16_t)rtcm_br_u(payload, &p, 12);
203 if (msg != 1005 && msg != 1006)
205 if (msg == 1006 && payload_len < 21)
207 out->station_id = (uint16_t)rtcm_br_u(payload, &p, 12);
208 rtcm_br_u(payload, &p, 6);
209 rtcm_br_u(payload, &p, 1);
210 rtcm_br_u(payload, &p, 1);
211 rtcm_br_u(payload, &p, 1);
212 rtcm_br_u(payload, &p, 1);
213 out->ecef_x_01mm = rtcm_br_s(payload, &p, 38);
214 rtcm_br_u(payload, &p, 1);
215 rtcm_br_u(payload, &p, 1);
216 out->ecef_y_01mm = rtcm_br_s(payload, &p, 38);
217 rtcm_br_u(payload, &p, 2);
218 out->ecef_z_01mm = rtcm_br_s(payload, &p, 38);
221 out->antenna_height_01mm = (uint16_t)rtcm_br_u(payload, &p, 16);
222 out->has_height =
true;
226 out->antenna_height_01mm = 0;
227 out->has_height =
false;
RTCM 3.x framing + station-reference message codec (DETWS_ENABLE_NTRIP_CASTER).