STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
fake_gnss.c
Go to the documentation of this file.
1#include "fake_gnss.h"
2
3#include <string.h>
4
5static void queue(fake_gnss_t* f, const uint8_t* b, size_t n) {
6 if (f->pending_len + n <= sizeof(f->pending)) {
7 memcpy(f->pending + f->pending_len, b, n);
8 f->pending_len += n;
9 }
10}
11
12static void ack(fake_gnss_t* f, bool ok) {
13 const uint8_t acked[2] = {UBX_CLASS_CFG, UBX_ID_CFG_VALSET};
14 uint8_t frame[16];
15 size_t n = ubx_frame(frame, sizeof(frame), UBX_CLASS_ACK,
16 ok ? UBX_ID_ACK_ACK : UBX_ID_ACK_NAK, acked, 2);
17 queue(f, frame, n);
18 ok ? f->acks++ : f->naks++;
19}
20
21/* Value size from the key ID, bits 30..28 (Interface Description p.124). */
22static int value_size(uint32_t key) {
23 switch ((key >> 28) & 7U) {
24 case 1:
25 case 2:
26 return 1;
27 case 3:
28 return 2;
29 case 4:
30 return 4;
31 case 5:
32 return 8;
33 default:
34 return -1;
35 }
36}
37
38static void on_valset(fake_gnss_t* f, const uint8_t* p, uint16_t len) {
39 f->valsets++;
40 if (len < 4 || p[0] != 0 || !(p[1] & 1U)) { /* version 0, RAM layer */
41 ack(f, false);
42 return;
43 }
44 uint32_t new_baud = 0;
45 bool config = false;
46 for (uint16_t o = 4; o + 4 <= len;) {
47 uint32_t key = (uint32_t)p[o] | (uint32_t)p[o + 1] << 8 |
48 (uint32_t)p[o + 2] << 16 | (uint32_t)p[o + 3] << 24;
49 int size = value_size(key);
50 if (size < 0 || o + 4 + size > len) {
51 ack(f, false);
52 return;
53 }
54 uint32_t v = 0;
55 for (int k = 0; k < size && k < 4; ++k)
56 v |= (uint32_t)p[o + 4 + k] << (8 * k);
57 switch (key) {
59 new_baud = v;
60 break;
62 f->nmea_on = v != 0;
63 config = true;
64 break;
66 f->pvt_on = v != 0;
67 config = true;
68 break;
70 f->rate_ms = (uint16_t)v;
71 config = true;
72 break;
74 f->dynmodel = (uint8_t)v;
75 config = true;
76 break;
77 default:
78 ack(f, false);
79 return; /* unknown key: NAK, nothing applied */
80 }
81 o = (uint16_t)(o + 4 + size);
82 }
83 if (new_baud) {
84 f->module_baud = new_baud; /* takes effect at once */
85 f->baud_changes++;
86 }
87 if (config) {
88 if (f->nak_next) {
89 f->nak_next = false;
90 ack(f, false);
91 return;
92 }
93 ack(f, true);
94 }
95}
96
97static void module_rx(void* ctx, const uint8_t* bytes, uint16_t len) {
98 fake_gnss_t* f = ctx;
99 if (f->mute)
100 return;
101 if (f->uart_baud != f->module_baud) {
102 f->garbled_rx++;
103 return;
104 }
105 for (uint16_t i = 0; i < len; ++i) {
106 if (gnss_frame_feed(&f->rx, bytes[i]) == GNSS_FRAME_UBX &&
107 f->rx.ubx_class == UBX_CLASS_CFG &&
109 on_valset(f, f->rx.ubx_payload, f->rx.ubx_len);
110 }
111 }
112}
113
114static void set_baud(void* ctx, uint32_t baud) {
115 ((fake_gnss_t*)ctx)->uart_baud = baud;
116}
117
119 memset(f, 0, sizeof(*f));
120 f->module_baud = baud;
121 f->nmea_on = true;
122 f->rate_ms = 1000;
123 f->truth = truth;
124 f->next_nmea_us = 300000;
125 gnss_frame_init(&f->rx);
126}
127
128void fake_gnss_power_cycle(fake_gnss_t* f, uint32_t now_us) {
130 uint32_t uart = f->uart_baud;
131 fake_gnss_init(f, 9600, truth);
132 f->uart_baud = uart;
133 f->next_nmea_us = now_us + 300000;
134}
135
137 gnss_io_t io = {module_rx, set_baud, f};
138 return io;
139}
140
141static void pvt(fake_gnss_t* f, uint32_t t) {
142 ubx_pvt_t v;
143 memset(&v, 0, sizeof(v));
144 if (f->truth)
145 f->truth(t, &v);
146 uint8_t p[UBX_NAV_PVT_LEN] = {0};
147 /* Interface Description 3.15.11 offsets, written independently. */
148#define PUT32(o, x) \
149 do { \
150 uint32_t y = (uint32_t)(x); \
151 p[o] = (uint8_t)y; \
152 p[o + 1] = (uint8_t)(y >> 8); \
153 p[o + 2] = (uint8_t)(y >> 16); \
154 p[o + 3] = (uint8_t)(y >> 24); \
155 } while (0)
156 PUT32(0, v.itow_ms);
157 p[20] = v.fix_type;
158 p[21] = v.flags;
159 p[23] = v.num_sv;
160 PUT32(24, v.lon_e7);
161 PUT32(28, v.lat_e7);
162 PUT32(36, v.hmsl_mm);
163 PUT32(40, v.hacc_mm);
164 PUT32(44, v.vacc_mm);
165 PUT32(48, v.vel_n_mms);
166 PUT32(52, v.vel_e_mms);
167 PUT32(56, v.vel_d_mms);
168 p[76] = (uint8_t)v.pdop_e2;
169 p[77] = (uint8_t)(v.pdop_e2 >> 8);
170#undef PUT32
171 uint8_t frame[UBX_NAV_PVT_LEN + 8];
172 size_t n = ubx_frame(frame, sizeof(frame), UBX_CLASS_NAV, UBX_ID_NAV_PVT, p,
174 queue(f, frame, n);
175}
176
177size_t fake_gnss_emit(fake_gnss_t* f, uint32_t now_us, uint8_t* out,
178 size_t cap) {
179 if (!f->mute) {
180 if (f->nmea_on && (int32_t)(now_us - f->next_nmea_us) >= 0) {
181 static const char gga[] =
182 "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,"
183 "*47\r\n";
184 queue(f, (const uint8_t*)gga, sizeof(gga) - 1);
185 f->next_nmea_us += 1000000U;
186 }
187 if (f->pvt_on && (int32_t)(now_us - f->next_pvt_us) >= 0) {
188 pvt(f, now_us);
189 f->next_pvt_us = now_us + f->rate_ms * 1000U;
190 }
191 }
192 size_t n = f->pending_len < cap ? f->pending_len : cap;
193 if (f->uart_baud == f->module_baud) {
194 memcpy(out, f->pending, n);
195 } else {
196 memset(out, 0xF0, n); /* wrong baud: the UART sees garbage */
197 }
198 memmove(f->pending, f->pending + n, f->pending_len - n);
199 f->pending_len -= n;
200 return n;
201}
void fake_gnss_power_cycle(fake_gnss_t *f, uint32_t now_us)
Definition fake_gnss.c:128
static void queue(fake_gnss_t *f, const uint8_t *b, size_t n)
Definition fake_gnss.c:5
static int value_size(uint32_t key)
Definition fake_gnss.c:22
size_t fake_gnss_emit(fake_gnss_t *f, uint32_t now_us, uint8_t *out, size_t cap)
Definition fake_gnss.c:177
static void module_rx(void *ctx, const uint8_t *bytes, uint16_t len)
Definition fake_gnss.c:97
static void pvt(fake_gnss_t *f, uint32_t t)
Definition fake_gnss.c:141
gnss_io_t fake_gnss_io(fake_gnss_t *f)
Definition fake_gnss.c:136
#define PUT32(o, x)
static void on_valset(fake_gnss_t *f, const uint8_t *p, uint16_t len)
Definition fake_gnss.c:38
void fake_gnss_init(fake_gnss_t *f, uint32_t baud, fake_gnss_truth_t truth)
Definition fake_gnss.c:118
static void set_baud(void *ctx, uint32_t baud)
Definition fake_gnss.c:114
void(* fake_gnss_truth_t)(uint32_t t_us, ubx_pvt_t *out)
Definition fake_gnss.h:23
static bool ok
Definition flight_e2e.c:435
int32_t p
Definition flight_e2e.c:78
gnss_frame_kind_t gnss_frame_feed(gnss_frame_parser_t *p, uint8_t byte)
Definition gnss_frame.c:57
void gnss_frame_init(gnss_frame_parser_t *parser)
Definition gnss_frame.c:35
@ GNSS_FRAME_UBX
Definition gnss_frame.h:24
static void set_baud(void *ctx, uint32_t baud)
Definition gnss_task.c:32
static const idle_config_t config
Definition idle_task.c:17
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
Definition json.hpp:13878
return o
Definition json.hpp:13897
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474
uint32_t next_pvt_us
Definition fake_gnss.h:31
uint32_t module_baud
Definition fake_gnss.h:26
unsigned acks
Definition fake_gnss.h:33
gnss_frame_parser_t rx
Definition fake_gnss.h:32
bool nak_next
Definition fake_gnss.h:30
uint16_t rate_ms
Definition fake_gnss.h:28
fake_gnss_truth_t truth
Definition fake_gnss.h:34
uint32_t uart_baud
Definition fake_gnss.h:26
uint8_t pending[512]
Definition fake_gnss.h:35
size_t pending_len
Definition fake_gnss.h:36
unsigned garbled_rx
Definition fake_gnss.h:33
uint32_t next_nmea_us
Definition fake_gnss.h:31
uint8_t dynmodel
Definition fake_gnss.h:29
unsigned naks
Definition fake_gnss.h:33
bool pvt_on
Definition fake_gnss.h:27
unsigned valsets
Definition fake_gnss.h:33
unsigned baud_changes
Definition fake_gnss.h:33
bool nmea_on
Definition fake_gnss.h:27
uint8_t ubx_payload[GNSS_FRAME_UBX_CAPTURE]
Definition gnss_frame.h:46
int32_t lon_e7
Definition ubx.h:71
uint16_t pdop_e2
Definition ubx.h:76
int32_t lat_e7
Definition ubx.h:71
uint8_t fix_type
Definition ubx.h:68
int32_t vel_n_mms
Definition ubx.h:74
int32_t vel_d_mms
Definition ubx.h:74
uint32_t hacc_mm
Definition ubx.h:73
int32_t hmsl_mm
Definition ubx.h:72
uint8_t num_sv
Definition ubx.h:70
uint32_t itow_ms
Definition ubx.h:65
int32_t vel_e_mms
Definition ubx.h:74
uint8_t flags
Definition ubx.h:69
uint32_t vacc_mm
Definition ubx.h:73
static std::vector< uint8_t > frame(uint8_t hi, uint8_t lo, size_t payload_len, uint8_t fill)
One wire packet: len(4, LE) then len bytes of body, where the first 4 body bytes are ty/packet_id(2)/...
static void truth(uint32_t t, ubx_pvt_t *v)
static const uint8_t ack[]
static const char gga[]
size_t ubx_frame(uint8_t *out, size_t cap, uint8_t cls, uint8_t id, const uint8_t *payload, uint16_t len)
Definition ubx.c:5
#define UBX_CLASS_CFG
Definition ubx.h:33
#define UBX_CLASS_ACK
Definition ubx.h:32
#define UBX_CLASS_NAV
Definition ubx.h:31
#define UBX_KEY_UART1OUTPROT_NMEA
Definition ubx.h:44
#define UBX_ID_ACK_NAK
Definition ubx.h:39
#define UBX_ID_CFG_VALSET
Definition ubx.h:40
#define UBX_ID_ACK_ACK
Definition ubx.h:38
#define UBX_KEY_UART1_BAUDRATE
Definition ubx.h:43
#define UBX_KEY_NAVSPG_DYNMODEL
Definition ubx.h:47
#define UBX_NAV_PVT_LEN
Definition ubx.h:41
#define UBX_ID_NAV_PVT
Definition ubx.h:35
#define UBX_KEY_MSGOUT_NAV_PVT_UART1
Definition ubx.h:45
#define UBX_KEY_RATE_MEAS
Definition ubx.h:46