hamnet70/impl/test/test_rx_file_l2dbg.c

217 lines
5.3 KiB
C
Raw Permalink Normal View History

/*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Copyright (C) 2024 Thomas Kolb
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <liquid/liquid.h>
#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 <dump-file>", 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();
}