Files
PLFM_RADAR/9_Firmware/tests/cross_layer/stm32_settings_stub.cpp
T
Jason 0537b40dcc feat: add cross-layer contract tests (Python/Verilog/C) with CI job
Three-tier test orchestrator validates opcode maps, bit widths, packet
layouts, and round-trip correctness across FPGA RTL, Python GUI, and
STM32 firmware. Catches 3 real bugs:

- status_words[0] 37-bit truncation in both USB interfaces
- Python radar_mode readback at wrong bit position (bit 21 vs 24)
- RadarSettings.cpp buffer overread (min check 74 vs required 82)

29 tests: 24 pass, 5 xfail (documenting confirmed bugs).
4th CI job added: cross-layer-tests (Python + iverilog + cc).
2026-04-12 16:04:59 +05:45

87 lines
2.6 KiB
C++

/**
* stm32_settings_stub.cpp
*
* Standalone stub that wraps the real RadarSettings class.
* Reads a binary settings packet from a file (argv[1]),
* parses it using RadarSettings::parseFromUSB(), and prints
* all parsed field=value pairs to stdout.
*
* Compile: c++ -std=c++11 -o stm32_settings_stub stm32_settings_stub.cpp \
* ../../9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/RadarSettings.cpp \
* -I../../9_Firmware/9_1_Microcontroller/9_1_1_C_Cpp_Libraries/
*
* Usage: ./stm32_settings_stub packet.bin
* Prints: field=value lines (one per field)
* Exit code: 0 if parse succeeded, 1 if failed
*/
#include "RadarSettings.h"
#include <cstdio>
#include <cstdlib>
int main(int argc, char* argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <packet.bin>\n", argv[0]);
return 2;
}
// Read binary packet from file
FILE* f = fopen(argv[1], "rb");
if (!f) {
fprintf(stderr, "ERROR: Cannot open %s\n", argv[1]);
return 2;
}
fseek(f, 0, SEEK_END);
long file_size = ftell(f);
fseek(f, 0, SEEK_SET);
if (file_size <= 0 || file_size > 4096) {
fprintf(stderr, "ERROR: Invalid file size %ld\n", file_size);
fclose(f);
return 2;
}
uint8_t* buf = (uint8_t*)malloc(file_size);
if (!buf) {
fprintf(stderr, "ERROR: malloc failed\n");
fclose(f);
return 2;
}
size_t nread = fread(buf, 1, file_size, f);
fclose(f);
if ((long)nread != file_size) {
fprintf(stderr, "ERROR: Short read (%zu of %ld)\n", nread, file_size);
free(buf);
return 2;
}
// Parse using the real RadarSettings class
RadarSettings settings;
bool ok = settings.parseFromUSB(buf, (uint32_t)file_size);
free(buf);
if (!ok) {
printf("parse_ok=false\n");
return 1;
}
// Print all fields with full precision
// Python orchestrator will compare these against expected values
printf("parse_ok=true\n");
printf("system_frequency=%.17g\n", settings.getSystemFrequency());
printf("chirp_duration_1=%.17g\n", settings.getChirpDuration1());
printf("chirp_duration_2=%.17g\n", settings.getChirpDuration2());
printf("chirps_per_position=%u\n", settings.getChirpsPerPosition());
printf("freq_min=%.17g\n", settings.getFreqMin());
printf("freq_max=%.17g\n", settings.getFreqMax());
printf("prf1=%.17g\n", settings.getPRF1());
printf("prf2=%.17g\n", settings.getPRF2());
printf("max_distance=%.17g\n", settings.getMaxDistance());
printf("map_size=%.17g\n", settings.getMapSize());
return 0;
}