From 079de99eecd1b3135770f3f0a1dd78a1393deeae Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Fri, 29 May 2015 18:13:47 +0100 Subject: [PATCH 1/4] 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 From a60270e20ef76da82d8c22a4aaa3199132ad28e7 Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Sat, 30 May 2015 01:09:41 +0100 Subject: [PATCH 2/4] Don't hang if the ICAO hashtable fills up. --- icao_filter.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/icao_filter.c b/icao_filter.c index 70f32b4..0284de1 100644 --- a/icao_filter.c +++ b/icao_filter.c @@ -68,16 +68,27 @@ void icaoFilterInit() void icaoFilterAdd(uint32_t addr) { - uint32_t h = icaoHash(addr); - while (icao_filter_active[h] && icao_filter_active[h] != addr) + uint32_t h, h0; + h0 = h = icaoHash(addr); + while (icao_filter_active[h] && icao_filter_active[h] != addr) { h = (h+1) & (ICAO_FILTER_SIZE-1); + if (h == h0) { + fprintf(stderr, "ICAO hash table full, increase ICAO_FILTER_SIZE\n"); + return; + } + } if (!icao_filter_active[h]) icao_filter_active[h] = addr; // also add with a zeroed top byte, for handling DF20/21 with Data Parity - h = icaoHash(addr & 0x00ffff); - while (icao_filter_active[h] && (icao_filter_active[h] & 0x00ffff) != (addr & 0x00ffff)) + h0 = h = icaoHash(addr & 0x00ffff); + while (icao_filter_active[h] && (icao_filter_active[h] & 0x00ffff) != (addr & 0x00ffff)) { h = (h+1) & (ICAO_FILTER_SIZE-1); + if (h == h0) { + fprintf(stderr, "ICAO hash table full, increase ICAO_FILTER_SIZE\n"); + return; + } + } if (!icao_filter_active[h]) icao_filter_active[h] = addr; } @@ -87,15 +98,21 @@ int icaoFilterTest(uint32_t addr) uint32_t h, h0; h0 = h = icaoHash(addr); - while (icao_filter_a[h] && icao_filter_a[h] != addr) + while (icao_filter_a[h] && icao_filter_a[h] != addr) { h = (h+1) & (ICAO_FILTER_SIZE-1); - if (icao_filter_a[h]) + if (h == h0) + break; + } + if (icao_filter_a[h] == addr) return 1; h = h0; - while (icao_filter_b[h] && icao_filter_b[h] != addr) + while (icao_filter_b[h] && icao_filter_b[h] != addr) { h = (h+1) & (ICAO_FILTER_SIZE-1); - if (icao_filter_b[h]) + if (h == h0) + break; + } + if (icao_filter_b[h] == addr) return 1; return 0; @@ -107,15 +124,21 @@ uint32_t icaoFilterTestFuzzy(uint32_t partial) partial &= 0x00ffff; h0 = h = icaoHash(partial); - while (icao_filter_a[h] && (icao_filter_a[h] & 0x00ffff) != partial) + while (icao_filter_a[h] && (icao_filter_a[h] & 0x00ffff) != partial) { h = (h+1) & (ICAO_FILTER_SIZE-1); - if (icao_filter_a[h]) + if (h == h0) + break; + } + if ((icao_filter_a[h] & 0x00ffff) == partial) return icao_filter_a[h]; h = h0; - while (icao_filter_b[h] && (icao_filter_b[h] & 0x00ffff) != partial) + while (icao_filter_b[h] && (icao_filter_b[h] & 0x00ffff) != partial) { h = (h+1) & (ICAO_FILTER_SIZE-1); - if (icao_filter_b[h]) + if (h == h0) + break; + } + if ((icao_filter_b[h] & 0x00ffff) == partial) return icao_filter_b[h]; return 0; From 03ba828f8d79badc6c0582352b48069cea1e50a3 Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Sun, 7 Jun 2015 12:07:08 +0100 Subject: [PATCH 3/4] Rearrange position cleanup to be a bit more obvious. Previously it forgot to advance to the next aircraft and only happened to work because it cleared the position bitflags and so the next iteration (on the same aircraft) would advance. --- track.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/track.c b/track.c index b858609..8907f2c 100644 --- a/track.c +++ b/track.c @@ -636,10 +636,11 @@ static void trackRemoveStaleAircraft(uint64_t now) } else { prev->next = a->next; free(a); a = prev->next; } - } else if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (now - a->seenLatLon) > TRACK_AIRCRAFT_POSITION_TTL) { - /* Position is too old and no longer valid */ - a->bFlags &= ~(MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK); } else { + if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (now - a->seenLatLon) > TRACK_AIRCRAFT_POSITION_TTL) { + /* Position is too old and no longer valid */ + a->bFlags &= ~(MODES_ACFLAGS_LATLON_VALID | MODES_ACFLAGS_LATLON_REL_OK); + } prev = a; a = a->next; } } From f58ff14d7cd76abe6e38c02960f1f61f862ca8ab Mon Sep 17 00:00:00 2001 From: Oliver Jowett Date: Sun, 7 Jun 2015 23:00:24 +0100 Subject: [PATCH 4/4] Fix queueing/resending very old Mode A/C messages. Fixes #47. --- debian/changelog | 1 + mode_s.c | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/debian/changelog b/debian/changelog index 09f2459..7787566 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,6 +12,7 @@ dump1090-mutability (1.15~dev) UNRELEASED; urgency=medium received data clobbering old data under CPU overload. * Fix endian issues affecting big-endian hosts in Beast input/output and avrmlat output. (github issue #44) + * Fix queueing/resending very old Mode A/C messages (github issue #47) -- Oliver Jowett Thu, 19 Feb 2015 22:39:19 +0000 diff --git a/mode_s.c b/mode_s.c index 090aff6..53fd806 100644 --- a/mode_s.c +++ b/mode_s.c @@ -1221,18 +1221,17 @@ void useModesMessage(struct modesMessage *mm) { // Otherwise, apply a sanity-check filter and only // forward messages when we have seen two of them. - // TODO: buffer the original message and forward it when we - // see a second message? - if (Modes.net) { - if (Modes.net_verbatim || a->messages > 1) { + if (Modes.net_verbatim || mm->msgtype == 32) { + // Unconditionally send + modesQueueOutput(mm); + } else if (a->messages > 1) { // If this is the second message, and we // squelched the first message, then re-emit the // first message now. if (!Modes.net_verbatim && a->messages == 2) { modesQueueOutput(&a->first_message); } - modesQueueOutput(mm); } }