28#define BENCH_GPS_ONLY 1
37#ifndef BENCH_TX_PERIOD_MS
38#define BENCH_TX_PERIOD_MS 1000U
43static
void say(const
char* fmt, ...) {
47 int n = vsnprintf(line,
sizeof line, fmt, ap);
69static void emmc_line(
const char* phase) {
73 say(
" eMMC %-9s %-9s records %lu chunks written %lu "
74 "write errors %lu dropped %lu backlog %u\r\n",
79 static bool card_said;
80 if (c && !card_said) {
82 say(
" eMMC card: maker 0x%02x part %s rev %u %lu MB "
83 "serial %08lx life used A/B %u/%u (1 = 0-10%%) pre-EOL %u "
84 "issues 0x%02lx session %lu at LBA %lu\r\n",
86 (
unsigned long)(c->
sec_count / 2048U), (
unsigned long)c->
psn,
92static long mg(
long raw,
long ug_per_lsb) {
93 return raw * ug_per_lsb / 1000L;
98static void deg_e7(
char* out,
size_t n, int32_t v) {
99 long a = v < 0 ? -(long)v : (long)v;
100 snprintf(out,
n,
"%s%ld.%07ld", v < 0 ?
"-" :
"",
a / 10000000L,
104static const char* fix_name(uint8_t t) {
125static void gps_only_loop(
void) {
126 uint32_t last_fix = 0;
128 say(
"\r\nSTAR flight computer bench build: GPS only (BENCH_GPS_ONLY)\r\n");
136 uint32_t hz =
dt ? (
g->fixes - last_fix) * 1000U / dt : 0U;
138 const char* st =
g->state ==
GNSS_RUN ?
"run"
141 char lat[16], lon[16];
142 deg_e7(lat,
sizeof lat, f->lat_e7);
143 deg_e7(lon,
sizeof lon, f->lon_e7);
146 say(
"t=%lus GPS %-6s listen %lu heard %lu rx %lu err %lu ovf %lu "
147 "%2luHz fix %-7s sats %2u "
148 "lat %s lon %s alt %ld m hacc %lu m pdop %u.%02u\r\n",
149 (
unsigned long)(now / 1000U), st, (
unsigned long)
g->baud,
150 (
unsigned long)
g->detected_baud,
154 fix_name(f->fix_type), f->num_sv, lat, lon,
155 (
long)(f->hmsl_mm / 1000), (
unsigned long)(f->hacc_mm / 1000U),
156 f->pdop_e2 / 100U, f->pdop_e2 % 100U);
157 static const char*
const ant[] = {
"init",
"unknown",
"OK",
"SHORT",
159 static const char*
const pwr[] = {
"off",
"on",
"unknown"};
160 static const char*
const jam[] = {
"unknown",
"ok",
"WARNING",
164 say(
" antenna %s (power %s) jamming %s noise %u agc %u "
165 "| sats listed %u signal %u locked %u used %u best %u dB-Hz "
166 "(reports rf %lu sat %lu)\r\n",
167 r->ant_status < 5U ? ant[
r->ant_status] :
"?",
168 r->ant_power < 3U ? pwr[
r->ant_power] :
"?", jam[
r->jamming & 3U],
170 v->
best_cno, (
unsigned long)
g->rf_reports,
171 (
unsigned long)
g->sat_reports);
179static void fixed(
char* out,
size_t n,
long v,
long den) {
180 long a = v < 0 ? -v : v;
181 long frac = (
a % den) * (den == 2 ? 5 : 25);
182 snprintf(out,
n,
"%s%ld.%0*ld", v < 0 ?
"-" :
"",
a / den, den == 2 ? 1 : 2,
186static void radio_header(
const char* role) {
189 say(
"\r\nSTAR flight computer bench build: radio link test, %s\r\n"
190 " LoRa 915 MHz, SF9, BW 125 kHz, CR 4/5, sync 0x1424"
191#ifdef STAR_RADIO_POWER_DBM
196#ifdef STAR_RADIO_POWER_DBM
205static void wait_radio_ready(
void) {
210 say(
" radio ready (start-up attempt %lu)\r\n",
215 say(
" radio NOT ready: start-up stopped at step %u (attempt %lu, "
216 "device errors 0x%04x); retrying\r\n",
225static void radio_rx_loop(
void) {
226 radio_header(
"RX (this board listens)");
229 uint16_t first_seq = 0, last_seq = 0;
230 long rssi_sum = 0, snr_sum = 0;
231 int best_rssi = -1000, worst_rssi = 1000;
237 if (rx.
count != seen) {
238 uint32_t missed_here = rx.
count -
seen - 1U;
240 if (got == 0U || (uint16_t)(rx.
seq - last_seq) > 1000U) {
242 say(
" -- sequence jumped %u -> %u: the TX board "
243 "restarted, counting again --\r\n",
248 rssi_sum = snr_sum = 0;
252 got += 1U + missed_here;
254 uint32_t sent = (uint16_t)(rx.
seq - first_seq) + 1U;
255 uint32_t lost = sent > got ? sent - got : 0U;
264 char rssi[12], snr[12];
265 fixed(rssi,
sizeof rssi, rx.
rssi_x2, 2);
266 fixed(snr,
sizeof snr, rx.
snr_x4, 4);
267 uint32_t counter = 0;
269 counter = (uint32_t)rx.
payload[1] |
271 (uint32_t)rx.
payload[3] << 16 |
274 say(
"t=%lu.%03lus RX seq %5u type 0x%02x len %u RSSI %s dBm "
275 "SNR %s dB%s | got %lu of %lu lost %lu CRC errors %lu "
276 "bad frames %lu (TX count %lu)\r\n",
277 (
unsigned long)(now / 1000U), (
unsigned long)(now % 1000U),
279 rx.
quality_ok ?
"" :
" (no status)", (
unsigned long)got,
280 (
unsigned long)sent, (
unsigned long)lost,
282 (
unsigned long)counter);
284 }
else if (now - last_report >= 5000U) {
288 char avg_rssi[12], avg_snr[12], lo[12], hi[12];
289 fixed(avg_rssi,
sizeof avg_rssi, rssi_sum / (
long)seen, 2);
290 fixed(avg_snr,
sizeof avg_snr, snr_sum / (
long)seen, 4);
291 fixed(lo,
sizeof lo, worst_rssi, 2);
292 fixed(hi,
sizeof hi, best_rssi, 2);
293 say(
"t=%lus ... nothing for 5 s. So far: got %lu, avg RSSI %s "
294 "dBm (%s .. %s), avg SNR %s dB, CRC errors %lu\r\n",
295 (
unsigned long)(now / 1000U), (
unsigned long)got, avg_rssi,
296 lo, hi, avg_snr, (
unsigned long)st.
crc_errors);
298 say(
"t=%lus listening... no frames yet (CRC errors %lu, "
299 "bad frames %lu, radio errors %lu)\r\n",
300 (
unsigned long)(now / 1000U), (
unsigned long)st.
crc_errors,
311static void radio_tx_loop(
void) {
312 radio_header(
"TX (this board sends one frame a second)");
316 next += BENCH_TX_PERIOD_MS;
320 (uint8_t)(counter >> 8),
321 (uint8_t)(counter >> 16),
322 (uint8_t)(counter >> 24),
331 static const char*
const names[] = {
"OK",
"TIMEOUT (no TxDone)",
332 "NO RADIO",
"BAD FRAME"};
334 say(
"t=%lu.%03lus TX #%lu %s in %lu ms | sent ok %lu timeouts %lu"
336 (
unsigned long)(now / 1000U), (
unsigned long)(now % 1000U),
337 (
unsigned long)counter,
r < 4 ? names[
r] :
"?", (
unsigned long)took,
341 osDelay(wait > 0 ? (uint32_t)wait : 1U);
347static void bench_task(
void* argument) {
351#elif BENCH_RADIO == 2
358 uint32_t last_imu = 0, last_highg = 0, last_baro = 0, last_fix = 0;
360 say(
"\r\nSTAR flight computer bench build: sensors + GPS live, no Idle, "
361 "no eMMC, no pyro\r\n");
364 const uint32_t rec_start_ms = 5000U, rec_stop_ms = 15000U;
365 bool rec_started =
false, rec_stopped =
false;
369 if (!rec_started && up >= rec_start_ms) {
371 say(
"--- eMMC test: ARMED for 10 s, recording ---\r\n");
373 }
else if (rec_started && !rec_stopped && up >= rec_stop_ms) {
378 say(
"--- eMMC test: stopped, flushing ---\r\n");
380 emmc_line(!rec_started ?
"waiting"
381 : rec_stopped ?
"done"
388 uint32_t imu_hz = (s.
imu.
samples - last_imu) * 1000U / dt;
389 uint32_t hg_hz = (s.
highg.
samples - last_highg) * 1000U / dt;
390 uint32_t baro_hz = (s.
baro.
samples - last_baro) * 1000U / dt;
396 long t100 = 2500L + (long)i->temp * 100L / 256L;
397 say(
"t=%lu.%01lus IMU %s %3luHz acc mg %6ld %6ld %6ld "
398 "gyro dps %5ld %5ld %5ld %ld.%02ldC\r\n",
399 (
unsigned long)(now / 1000U), (
unsigned long)(now % 1000U / 100U),
400 s.
imu.
ok ?
"ok " :
"ERR", (
unsigned long)imu_hz,
401 mg(i->accel[0], 488), mg(i->accel[1], 488), mg(i->accel[2], 488),
402 (
long)i->gyro[0] * 140L / 1000L, (
long)i->gyro[1] * 140L / 1000L,
403 (
long)i->gyro[2] * 140L / 1000L, t100 / 100L,
404 (t100 < 0 ? -t100 : t100) % 100L);
407 say(
" high-g %s %3luHz acc mg %6ld %6ld %6ld\r\n",
408 s.
highg.
ok ?
"ok " :
"ERR", (
unsigned long)hg_hz,
409 (
long)h->accel[0] * 780L, (
long)h->accel[1] * 780L,
410 (
long)h->accel[2] * 780L);
413 long tc =
b->temp_c100;
414 say(
" baro %s %3luHz %ld.%02ld hPa %ld.%02ldC\r\n",
415 s.
baro.
ok ?
"ok " :
"ERR", (
unsigned long)baro_hz,
416 (
long)
b->pressure_pa / 100L, (
long)
b->pressure_pa % 100L, tc / 100L,
417 (tc < 0 ? -tc : tc) % 100L);
420 const char* st =
g->state ==
GNSS_RUN ?
"run"
423 say(
" GPS %-6s %lu baud fixes %lu (+%lu) fix %u sats %u"
424 " lat %ld lon %ld (1e-7 deg) alt %ld m\r\n",
425 st, (
unsigned long)
g->detected_baud, (
unsigned long)
g->fixes,
426 (
unsigned long)(
g->fixes - last_fix), f->fix_type, f->num_sv,
427 (
long)f->lat_e7, (
long)f->lon_e7, (
long)(f->hmsl_mm / 1000));
bool bench_task_start(void)
uint32_t board_now_ms(void)
uint32_t board_uart9_overflows(void)
uint32_t board_uart9_rx_bytes(void)
uint32_t board_uart9_errors(void)
osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr)
Create a thread and add it to Active Threads.
uint32_t osKernelGetTickCount(void)
Get the RTOS kernel tick count.
@ osPriorityLow
Priority: low.
osStatus_t osDelay(uint32_t ticks)
Wait for Timeout (Time Delay).
static emmc_status_t format(emmc_log_t *log)
uint8_t emmc_log_backlog(const emmc_log_t *log)
const emmc_card_info_t * emmc_stm32_card(uint32_t *issues)
emmc_log_t * emmc_stm32_log(void)
void gnss_task_set_active(bool on)
const gnss_core_t * gnss_task_core(void)
void gnss_task_poll_status(bool on)
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
*brief create JSON pointer *sa reference_tokens const string_t & a
void app_set_state(flight_state_t to)
*brief user defined string literal for JSON values *sa std::size_t n
dict[str, object] line(str eid, str a, str b, str from_port="", str to_port="")
void radio_task_status(radio_status_t *out)
void radio_task_last_rx(radio_rx_t *out)
radio_send_result_t radio_task_send_frame(uint8_t type, const uint8_t *payload, uint8_t len)
uint32_t rtt_log_write(const char *s, uint32_t n)
void sensors_task_snapshot(sensors_core_t *out)
void sensors_task_set_active(bool on)
Attributes structure for thread.