From 079de99eecd1b3135770f3f0a1dd78a1393deeae Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Fri, 29 May 2015 18:13:47 +0100 Subject: [PATCH] Add --iformat option that controls the format of the data read from --ifile. This currently understands: UC8 (original rtl_sdr format, 8-bit unsigned complex); SC16 (16-bit signed complex, full width); SC16Q11 (bladeRF native format: 16-bit signed complex with 11 bits of magnitude) --- dump1090.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++------- dump1090.h | 3 ++ 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/dump1090.c b/dump1090.c index 504d8f1..020bc62 100644 --- a/dump1090.c +++ b/dump1090.c @@ -50,6 +50,7 @@ #include "dump1090.h" #include +#include static int verbose_device_search(char *s); @@ -494,17 +495,37 @@ void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) { void readDataFromFile(void) { int eof = 0; struct timespec next_buffer_delivery; + void *readbuf; + int bytes_per_sample = 0; + + switch (Modes.file_format) { + case INPUT_UC8: + bytes_per_sample = 2; + break; + case INPUT_SC16: + case INPUT_SC16Q11: + bytes_per_sample = 4; + break; + } + + if (!(readbuf = malloc(MODES_MAG_BUF_SAMPLES * bytes_per_sample))) { + fprintf(stderr, "failed to allocate read buffer\n"); + exit(1); + } clock_gettime(CLOCK_MONOTONIC, &next_buffer_delivery); pthread_mutex_lock(&Modes.data_mutex); while (!Modes.exit && !eof) { ssize_t nread, toread; + void *r; - uint16_t *p; + uint16_t *in, *out; + struct mag_buf *outbuf, *lastbuf; unsigned next_free_buffer; unsigned slen; + unsigned i; next_free_buffer = (Modes.first_free_buffer + 1) % MODES_MAG_BUFFERS; if (next_free_buffer == Modes.first_filled_buffer) { @@ -528,15 +549,15 @@ void readDataFromFile(void) { if (lastbuf->length >= Modes.trailing_samples) { memcpy(outbuf->data, lastbuf->data + lastbuf->length - Modes.trailing_samples, Modes.trailing_samples * sizeof(uint16_t)); } else { - memset(outbuf->data, 127, Modes.trailing_samples * sizeof(uint16_t)); + memset(outbuf->data, 0, Modes.trailing_samples * sizeof(uint16_t)); } // Get the system time for the start of this block clock_gettime(CLOCK_REALTIME, &outbuf->sysTimestamp); - toread = MODES_RTL_BUF_SIZE; - r = (void *) (outbuf->data + Modes.trailing_samples); - while(toread) { + toread = MODES_MAG_BUF_SAMPLES * bytes_per_sample; + r = readbuf; + while (toread) { nread = read(Modes.fd, r, toread); if (nread <= 0) { // Done. @@ -547,13 +568,44 @@ void readDataFromFile(void) { toread -= nread; } - slen = outbuf->length = (MODES_RTL_BUF_SIZE - toread) / 2; + slen = outbuf->length = MODES_MAG_BUF_SAMPLES - toread/bytes_per_sample; // Convert the new data - p = (uint16_t*) (outbuf->data + Modes.trailing_samples); - while (slen-- > 0) { - *p = Modes.maglut[*p]; - ++p; + out = outbuf->data + Modes.trailing_samples; + in = (uint16_t*)readbuf; + switch (Modes.file_format) { + case INPUT_UC8: + for (i = 0; i < slen; ++i) + *out++ = Modes.maglut[*in++]; + break; + + case INPUT_SC16: + for (i = 0; i < slen; ++i) { + int16_t I, Q; + float mag; + + I = (int16_t)le16toh(*in++); + Q = (int16_t)le16toh(*in++); + mag = sqrtf(I*I + Q*Q) * (65536.0 / 32768.0); + if (mag > 65535) + mag = 65535; + *out++ = (uint16_t)mag; + } + break; + + case INPUT_SC16Q11: + for (i = 0; i < slen; ++i) { + int16_t I, Q; + float mag; + + I = (int16_t)le16toh(*in++); + Q = (int16_t)le16toh(*in++); + mag = sqrtf(I*I + Q*Q) * (65536.0 / 2048.0); + if (mag > 65535) + mag = 65535; + *out++ = (uint16_t)mag; + } + break; } if (Modes.interactive) { @@ -575,6 +627,8 @@ void readDataFromFile(void) { pthread_cond_signal(&Modes.data_cond); } + free(readbuf); + // Wait for the main thread to consume all data while (!Modes.exit && Modes.first_filled_buffer != Modes.first_free_buffer) pthread_cond_wait(&Modes.data_cond, &Modes.data_mutex); @@ -917,6 +971,19 @@ int main(int argc, char **argv) { Modes.freq = (int) strtoll(argv[++j],NULL,10); } else if (!strcmp(argv[j],"--ifile") && more) { Modes.filename = strdup(argv[++j]); + } else if (!strcmp(argv[j],"--iformat") && more) { + ++j; + if (!strcasecmp(argv[j], "uc8")) { + Modes.file_format = INPUT_UC8; + } else if (!strcasecmp(argv[j], "sc16")) { + Modes.file_format = INPUT_SC16; + } else if (!strcasecmp(argv[j], "sc16q11")) { + Modes.file_format = INPUT_SC16Q11; + } else { + fprintf(stderr, "Input format '%s' not understood (supported values: UC8, SC16, SC16Q11)\n", + argv[j]); + exit(1); + } } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { diff --git a/dump1090.h b/dump1090.h index 16b7125..4b63690 100644 --- a/dump1090.h +++ b/dump1090.h @@ -250,6 +250,8 @@ struct mag_buf { uint32_t dropped; // Number of dropped samples preceding this buffer }; +typedef enum { INPUT_UC8=0, INPUT_SC16, INPUT_SC16Q11 } input_format_t; + // Program global state struct { // Internal state pthread_t reader_thread; @@ -265,6 +267,7 @@ struct { // Internal state unsigned trailing_samples; // extra trailing samples in magnitude buffers int fd; // --ifile option file descriptor + input_format_t file_format; // --iformat option uint16_t *maglut; // I/Q -> Magnitude lookup table uint16_t *log10lut; // Magnitude -> log10 lookup table int exit; // Exit from the main loop when true