From 77b24cf591485b126afbfeac04281a7d912c2926 Mon Sep 17 00:00:00 2001 From: Thomas Kolb Date: Sat, 20 Jul 2024 22:31:13 +0200 Subject: [PATCH] tests: Added variant of rx_file test for layer2 debugging --- impl/test/CMakeLists.txt | 43 +++++++ impl/test/test_rx_file_l2dbg.c | 210 +++++++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 impl/test/test_rx_file_l2dbg.c diff --git a/impl/test/CMakeLists.txt b/impl/test/CMakeLists.txt index 54cc4cf..0c93622 100644 --- a/impl/test/CMakeLists.txt +++ b/impl/test/CMakeLists.txt @@ -116,6 +116,49 @@ target_link_libraries( #------------------------------------ +add_executable( + test_rx_file_l2dbg + ../src/layer1/correlator.c + ../src/layer1/correlator.h + ../src/layer1/freq_est.c + ../src/layer1/freq_est.h + ../src/layer1/rx.c + ../src/layer1/rx.h + ../src/layer1/whitening.c + ../src/layer1/whitening.h + ../src/layer1/modcod.c + ../src/layer1/modcod.h + ../src/layer1/preamble.c + ../src/layer1/preamble.h + ../src/utils.c + ../src/utils.h + ../src/logger.c + ../src/logger.h + ../src/options.c + ../src/options.h + ../src/var_array.c + ../src/var_array.h + ../src/config.h + ../src/jsonlogger.c + ../src/jsonlogger.h + ../src/debug_structs.h + ../src/layer2/packet_structs.c + ../src/layer2/packet_structs.h + ../src/layer2/ham64.c + ../src/layer2/ham64.h + test_rx_file_l2dbg.c +) + +target_link_libraries( + test_rx_file_l2dbg + fec + fftw3f + m + liquid +) + +#------------------------------------ + add_executable( test_jsonlogger ../src/jsonlogger.c diff --git a/impl/test/test_rx_file_l2dbg.c b/impl/test/test_rx_file_l2dbg.c new file mode 100644 index 0000000..e37f971 --- /dev/null +++ b/impl/test/test_rx_file_l2dbg.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include + +#include "logger.h" +#include "layer1/rx.h" +#include "layer2/packet_structs.h" + +#include "config.h" + +#define RESULT_CHECK(stmt) { \ + result_t res = stmt; \ + if(res != OK) { \ + LOG(LVL_ERR, "Error %d in %s:%d!", res, __FILE__, __LINE__); \ + exit(1); \ + } \ +} + +#define CHUNKSIZE_INPUT 256000 +#define CHUNKSIZE_RF (CHUNKSIZE_INPUT/2) +#define CHUNKSIZE_BB (CHUNKSIZE_RF/SDR_OVERSAMPLING) + +#define JSONLOGGER 0 + +#if JSONLOGGER + #include "jsonlogger.h" +#endif + +static rx_stats_t m_rx_stats; + + +static result_t sdr_rf_to_baseband(nco_crcf nco, firdecim_crcf decim, + const float complex *rf_samples, size_t nrf, + float complex *bb_samples, size_t *nbb) +{ + if((*nbb * SDR_OVERSAMPLING) < nrf) { + LOG(LVL_ERR, "sdr_rf_to_baseband: result would not fit in output: %zd * %d < %zd", *nbb, SDR_OVERSAMPLING, nrf); + return ERR_SIZE; + } + + *nbb = nrf / SDR_OVERSAMPLING; + + for(size_t i = 0; i < *nbb; i++) { + float complex tmp[SDR_OVERSAMPLING]; + + assert(i*SDR_OVERSAMPLING < nrf); + + nco_crcf_mix_block_down(nco, + (complex float*)(rf_samples + i * SDR_OVERSAMPLING), + tmp, + SDR_OVERSAMPLING); + + firdecim_crcf_execute(decim, tmp, bb_samples + i); + } + + return OK; +} + + +void cb_rx(rx_evt_t evt, const layer1_rx_t *rx, uint8_t *packet_data, size_t packet_len) +{ + (void)packet_data; + (void)packet_len; + (void)rx; + + unsigned int data_size; + + switch(evt) + { + case RX_EVT_DECODE_FAILED: + //LOG(LVL_WARN, "Received a message of %zu bytes, but decoding failed.", packet_len); + //LOG(LVL_INFO, "=== FAILED PAYLOAD ==="); + //hexdump(packet_data, packet_len); + //LOG(LVL_INFO, "======================="); + m_rx_stats.failed_decodes++; + break; + + case RX_EVT_HEADER_ERROR: + m_rx_stats.header_errors++; + break; + + case RX_EVT_PACKET_RECEIVED: + //LOG(LVL_INFO, "A message of %zu bytes was decoded successfully.", packet_len); + //LOG(LVL_INFO, "=== DECODED PAYLOAD (%4zu bytes) ===", packet_len); + //hexdump(packet_data, packet_len < 64 ? packet_len : 64); + //LOG(LVL_INFO, "===================================="); + + data_size = packet_len - crc_sizeof_key(PAYLOAD_CRC_SCHEME); + + // CRC check + if(!crc_check_key(PAYLOAD_CRC_SCHEME, packet_data, data_size)) { + LOG(LVL_ERR, "Payload CRC check failed!"); + } else { + m_rx_stats.successful_decodes++; + } + + // decode and dump the layer 2 header + layer2_packet_header_t header; + if(!layer2_decode_packet_header(packet_data, data_size, &header)) { + LOG(LVL_ERR, "Header decoding failed!"); + break; + } + + layer2_dump_packet_header(LVL_DUMP, &header); + break; + + case RX_EVT_PREAMBLE_FOUND: + //LOG(LVL_INFO, "Found preamble!"); + m_rx_stats.preambles_found++; + break; + + case RX_EVT_PACKET_DEBUG_INFO_COMPLETE: +#if JSONLOGGER + jsonlogger_log_rx_packet_info(&rx->packet_debug_info); +#endif + break; + } + +#if JSONLOGGER + jsonlogger_log_rx_stats(&m_rx_stats); +#endif +} + + +int main(int argc, char **argv) +{ + logger_init(); + + if(argc < 2) { + LOG(LVL_FATAL, "Not enough arguments!"); + LOG(LVL_INFO, "usage: %s ", argv[0]); + LOG(LVL_INFO, "dump-file: HackRF dump in 8-bit signed interleaved I/Q format."); + return 1; + } + + layer1_rx_t rx; + FILE *inputfile; + float rbuf[CHUNKSIZE_INPUT]; + + // ** Initialize ** + +#if JSONLOGGER + if(!jsonlogger_init("jsonlog_test.fifo")) { + LOG(LVL_FATAL, "Could not initialize JSON logger."); + return EXIT_FAILURE; + } +#endif + + firdecim_crcf decim = firdecim_crcf_create_kaiser(SDR_OVERSAMPLING, 9, 60.0f); + nco_crcf rx_nco = nco_crcf_create(LIQUID_NCO); + nco_crcf_set_frequency(rx_nco, 2 * 3.14159 * (SDR_RX_IF_SHIFT + 31e3) / SDR_RX_SAMPLING_RATE); + + inputfile = fopen(argv[1], "rb"); + if(!inputfile) { + LOG(LVL_FATAL, "Could not open input file!"); + return 1; + } + + RESULT_CHECK(layer1_rx_init(&rx, cb_rx)); + + // ** Process packets ** + + size_t nread; + while((nread = fread(rbuf, sizeof(float), CHUNKSIZE_INPUT, inputfile)) != 0) { + assert(nread % 2 == 0); + + LOG(LVL_DEBUG, "Read %zu samples.", nread/2); + + // ** Receive signal ** + + float complex rf_samples[CHUNKSIZE_RF]; + float complex bb_samples[CHUNKSIZE_BB]; + + size_t n_rf_samples = CHUNKSIZE_RF; + size_t n_bb_samples = CHUNKSIZE_BB; + + for(size_t iout = 0; iout < CHUNKSIZE_RF; iout++) { + //rf_samples[iout] = 0.0078125f * (rbuf[2*iout + 0] + I * rbuf[2*iout + 1]); + rf_samples[iout] = rbuf[2*iout + 0] + I * rbuf[2*iout + 1]; + } + + RESULT_CHECK(sdr_rf_to_baseband(rx_nco, decim, rf_samples, n_rf_samples, bb_samples, &n_bb_samples)); + + RESULT_CHECK(layer1_rx_process(&rx, bb_samples, n_bb_samples)); + + LOG(LVL_INFO, "Receiver statistics:"); + LOG(LVL_INFO, " Preambles found: %8zd", m_rx_stats.preambles_found); + LOG(LVL_INFO, " Successful decodes: %8zd (%6.2f %%)", + m_rx_stats.successful_decodes, m_rx_stats.successful_decodes * 100.0f / m_rx_stats.preambles_found); + LOG(LVL_INFO, " Header errors: %8zd (%6.2f %%)", + m_rx_stats.header_errors, m_rx_stats.header_errors * 100.0f / m_rx_stats.preambles_found); + LOG(LVL_INFO, " Failed decodes: %8zd (%6.2f %%)", + m_rx_stats.failed_decodes, m_rx_stats.failed_decodes * 100.0f / m_rx_stats.preambles_found); + + } + + // ** Cleanup ** + + layer1_rx_shutdown(&rx); + +#if JSONLOGGER + jsonlogger_shutdown(); +#endif + + LOG(LVL_INFO, "Done."); + + logger_shutdown(); +}