From e6c43382b9930fa48fb029b03d6feba55cd9436d Mon Sep 17 00:00:00 2001 From: papasven Date: Sun, 1 Jun 2014 02:14:40 +0200 Subject: [PATCH 01/16] Incorrect value for auto-gain Incorrect value for auto-gain option the Modes.gain is multiplied by 10. --- dump1090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dump1090.c b/dump1090.c index 3d683ae..585b4f8 100644 --- a/dump1090.c +++ b/dump1090.c @@ -394,7 +394,7 @@ void showHelp(void) { "| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" "-----------------------------------------------------------------------------\n" "--device-index Select RTL device (default: 0)\n" -"--gain Set gain (default: max gain. Use -100 for auto-gain)\n" +"--gain Set gain (default: max gain. Use -10 for auto-gain)\n" "--enable-agc Enable the Automatic Gain Control (default: off)\n" "--freq Set frequency (default: 1090 Mhz)\n" "--ifile Read data from file (use '-' for stdin)\n" From 506be6e054eccb546d1e73ed6c0aa3e8e542e897 Mon Sep 17 00:00:00 2001 From: hhm Date: Sun, 22 Jun 2014 13:05:39 -0400 Subject: [PATCH 02/16] B"H decode more data, etc. - decodes a bit more information - misc. small changes --- mode_s.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/mode_s.c b/mode_s.c index 780e650..e92cd9b 100644 --- a/mode_s.c +++ b/mode_s.c @@ -746,7 +746,7 @@ int decodeMovementField(int movement) { // // Capability table char *ca_str[8] = { - /* 0 */ "Level 1 (Survillance Only)", + /* 0 */ "Level 1 (Surveillance Only)", /* 1 */ "Level 2 (DF0,4,5,11)", /* 2 */ "Level 3 (DF0,4,5,11,20,21)", /* 3 */ "Level 4 (DF0,4,5,11,20,21,24)", @@ -779,6 +779,20 @@ char *fs_str[8] = { /* 6 */ "Value 6 is not assigned", /* 7 */ "Value 7 is not assigned" }; + +// Emergency state table +// from https://www.ll.mit.edu/mission/aviation/publications/publication-files/atc-reports/Grappel_2007_ATC-334_WW-15318.pdf +// and 1090-DO-260B_FRAC +char *es_str[8] = { + /* 0 */ "No emergency", + /* 1 */ "General emergency (squawk 7700)", + /* 2 */ "Lifeguard/Medical", + /* 3 */ "Minimum fuel", + /* 4 */ "No communications (squawk 7600)", + /* 5 */ "Unlawful interference (squawk 7500)", + /* 6 */ "Downed Aircraft", + /* 7 */ "Reserved" +}; // //========================================================================= // @@ -797,6 +811,8 @@ char *getMEDescription(int metype, int mesub) { mename = "Airborne Position (GNSS Height)"; else if (metype == 23 && mesub == 0) mename = "Test Message"; + else if (metype == 23 && mesub == 7) + mename = "Test Message -- Squawk"; else if (metype == 24 && mesub == 1) mename = "Surface System Status"; else if (metype == 28 && mesub == 1) @@ -944,7 +960,7 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) { if ( (mm->msgtype == 17) || ((mm->msgtype == 18) && ((mm->ca == 0) || (mm->ca == 1) || (mm->ca == 6)) )) { int metype = mm->metype = msg[4] >> 3; // Extended squitter message type - int mesub = mm->mesub = msg[4] & 7; // Extended squitter message subtype + int mesub = mm->mesub = (metype == 29 ? ((msg[4]&6)>>1) : (msg[4] & 7)); // Extended squitter message subtype // Decode the extended squitter message @@ -1060,7 +1076,23 @@ void decodeModesMessage(struct modesMessage *mm, unsigned char *msg) { mm->heading = ((((msg[5] & 0x03) << 8) | msg[6]) * 45) >> 7; } } - } + } else if (mm->metype == 23) { // Test metype squawk field + if (mm->mesub == 7) { // (see 1090-WP-15-20) + int ID13Field = (((msg[5] << 8) | msg[6]) & 0xFFF1)>>3; + if (ID13Field) { + mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; + mm->modeA = decodeID13Field(ID13Field); + } + } + } else if (mm->metype == 28) { // Emergency status squawk field + if (mm->mesub == 1) { + int ID13Field = (((msg[5] << 8) | msg[6]) & 0x1FFF); + if (ID13Field) { + mm->bFlags |= MODES_ACFLAGS_SQUAWK_VALID; + mm->modeA = decodeID13Field(ID13Field); + } + } + } } // Fields for DF20, DF21 Comm-B @@ -1159,8 +1191,8 @@ void displayModesMessage(struct modesMessage *mm) { } else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory printf(" BDS 3,0 ACAS Active Resolution Advisory\n"); - } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergecy/Priority Status - printf(" BDS 6,1 Emergecy/Priority Status\n"); + } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status + printf(" BDS 6,1 Emergency/Priority Status\n"); } else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status printf(" BDS 6,2 Target State and Status\n"); @@ -1177,7 +1209,7 @@ void displayModesMessage(struct modesMessage *mm) { printf(" Flight Status : %s\n", fs_str[mm->fs]); printf(" DR : %d\n", ((mm->msg[1] >> 3) & 0x1F)); printf(" UM : %d\n", (((mm->msg[1] & 7) << 3) | (mm->msg[2] >> 5))); - printf(" Squawk : %x\n", mm->modeA); + printf(" Squawk : %04x\n", mm->modeA); printf(" ICAO Address : %06x\n", mm->addr); if (mm->msgtype == 21) { @@ -1193,8 +1225,8 @@ void displayModesMessage(struct modesMessage *mm) { } else if ( mm->msg[4] == 0x30) { // BDS 3,0 ACAS Active Resolution Advisory printf(" BDS 3,0 ACAS Active Resolution Advisory\n"); - } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergecy/Priority Status - printf(" BDS 6,1 Emergecy/Priority Status\n"); + } else if ((mm->msg[4] >> 3) == 28) { // BDS 6,1 Extended Squitter Emergency/Priority Status + printf(" BDS 6,1 Emergency/Priority Status\n"); } else if ((mm->msg[4] >> 3) == 29) { // BDS 6,2 Target State and Status printf(" BDS 6,2 Target State and Status\n"); @@ -1275,6 +1307,20 @@ void displayModesMessage(struct modesMessage *mm) { //} else if (mm->metype >= 20 && mm->metype <= 22) { // Airborne position GNSS + } else if (mm->metype == 28) { // Extended Squitter Aircraft Status + if (mm->mesub == 1) { + printf(" Emergency State: %s\n", es_str[(mm->msg[5] & 0xE0) >> 5]); + printf(" Squawk: %04x\n", mm->modeA); + } else { + printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); + } + + } else if (mm->metype == 23) { // Test Message + if (mm->mesub == 7) { + printf(" Squawk: %04x\n", mm->modeA); + } else { + printf(" Unrecognized ME subtype: %d subtype: %d\n", mm->metype, mm->mesub); + } } else { printf(" Unrecognized ME type: %d subtype: %d\n", mm->metype, mm->mesub); } From 59984ac8af30f54a9c8852905dd9e0ba42e62b52 Mon Sep 17 00:00:00 2001 From: hhm Date: Tue, 24 Jun 2014 23:58:46 -0400 Subject: [PATCH 03/16] B"H allow disable ports, doc disable net heartbeat --- dump1090.c | 2 +- net_io.c | 95 +++++++++++++++++++++++++++++------------------------- 2 files changed, 52 insertions(+), 45 deletions(-) diff --git a/dump1090.c b/dump1090.c index 585b4f8..286fb05 100644 --- a/dump1090.c +++ b/dump1090.c @@ -415,7 +415,7 @@ void showHelp(void) { "--net-bo-port TCP Beast output listen port (default: 30005)\n" "--net-ro-size TCP raw output minimum size (default: 0)\n" "--net-ro-rate TCP raw output memory flush rate (default: 0)\n" -"--net-heartbeat TCP heartbeat rate in seconds (default: 60 sec)\n" +"--net-heartbeat TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n" "--net-buffer TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n" "--lat Reference/receiver latitude for surface posn (opt)\n" "--lon Reference/receiver longitude for surface posn (opt)\n" diff --git a/net_io.c b/net_io.c index 9462154..2f4c950 100644 --- a/net_io.c +++ b/net_io.c @@ -46,21 +46,29 @@ // // Networking "stack" initialization // +struct service { + char *descr; + int *socket; + int port; + int enabled; +}; + +struct service services[MODES_NET_SERVICES_NUM]; + void modesInitNet(void) { - struct { - char *descr; - int *socket; - int port; - } services[MODES_NET_SERVICES_NUM] = { - {"Raw TCP output", &Modes.ros, Modes.net_output_raw_port}, - {"Raw TCP input", &Modes.ris, Modes.net_input_raw_port}, - {"Beast TCP output", &Modes.bos, Modes.net_output_beast_port}, - {"Beast TCP input", &Modes.bis, Modes.net_input_beast_port}, - {"HTTP server", &Modes.https, Modes.net_http_port}, - {"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port} - }; int j; + struct service svc[MODES_NET_SERVICES_NUM] = { + {"Raw TCP output", &Modes.ros, Modes.net_output_raw_port, 1}, + {"Raw TCP input", &Modes.ris, Modes.net_input_raw_port, 1}, + {"Beast TCP output", &Modes.bos, Modes.net_output_beast_port, 1}, + {"Beast TCP input", &Modes.bis, Modes.net_input_beast_port, 1}, + {"HTTP server", &Modes.https, Modes.net_http_port, 1}, + {"Basestation TCP output", &Modes.sbsos, Modes.net_output_sbs_port, 1} + }; + + memcpy(&services, &svc, sizeof(svc));//services = svc; + Modes.clients = NULL; #ifdef _WIN32 @@ -75,14 +83,19 @@ void modesInitNet(void) { #endif for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - int s = anetTcpServer(Modes.aneterr, services[j].port, NULL); - if (s == -1) { - fprintf(stderr, "Error opening the listening port %d (%s): %s\n", - services[j].port, services[j].descr, strerror(errno)); - exit(1); - } - anetNonBlock(Modes.aneterr, s); - *services[j].socket = s; + services[j].enabled = (services[j].port != 0); + if (services[j].enabled) { + int s = anetTcpServer(Modes.aneterr, services[j].port, NULL); + if (s == -1) { + fprintf(stderr, "Error opening the listening port %d (%s): %s\n", + services[j].port, services[j].descr, strerror(errno)); + exit(1); + } + anetNonBlock(Modes.aneterr, s); + *services[j].socket = s; + } else { + if (Modes.debug & MODES_DEBUG_NET) printf("%s port is disabled\n", services[j].descr); + } } #ifndef _WIN32 @@ -99,36 +112,30 @@ struct client * modesAcceptClients(void) { int fd, port; unsigned int j; struct client *c; - int services[6]; - - services[0] = Modes.ros; - services[1] = Modes.ris; - services[2] = Modes.bos; - services[3] = Modes.bis; - services[4] = Modes.https; - services[5] = Modes.sbsos; for (j = 0; j < MODES_NET_SERVICES_NUM; j++) { - fd = anetTcpAccept(Modes.aneterr, services[j], NULL, &port); - if (fd == -1) continue; + if (services[j].enabled) { + fd = anetTcpAccept(Modes.aneterr, *services[j].socket, NULL, &port); + if (fd == -1) continue; - anetNonBlock(Modes.aneterr, fd); - c = (struct client *) malloc(sizeof(*c)); - c->service = services[j]; - c->next = Modes.clients; - c->fd = fd; - c->buflen = 0; - Modes.clients = c; - anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size)); + anetNonBlock(Modes.aneterr, fd); + c = (struct client *) malloc(sizeof(*c)); + c->service = *services[j].socket; + c->next = Modes.clients; + c->fd = fd; + c->buflen = 0; + Modes.clients = c; + anetSetSendBuffer(Modes.aneterr,fd, (MODES_NET_SNDBUF_SIZE << Modes.net_sndbuf_size)); - if (services[j] == Modes.sbsos) Modes.stat_sbs_connections++; - if (services[j] == Modes.ros) Modes.stat_raw_connections++; - if (services[j] == Modes.bos) Modes.stat_beast_connections++; + if (*services[j].socket == Modes.sbsos) Modes.stat_sbs_connections++; + if (*services[j].socket == Modes.ros) Modes.stat_raw_connections++; + if (*services[j].socket == Modes.bos) Modes.stat_beast_connections++; - j--; // Try again with the same listening port + j--; // Try again with the same listening port - if (Modes.debug & MODES_DEBUG_NET) - printf("Created new client %d\n", fd); + if (Modes.debug & MODES_DEBUG_NET) + printf("Created new client %d\n", fd); + } } return Modes.clients; } From 96015e38c895db145937b756beb78a4e7fb497aa Mon Sep 17 00:00:00 2001 From: hhm Date: Wed, 2 Jul 2014 07:38:46 -0400 Subject: [PATCH 04/16] B"H view1090: handle disconnection - keep trying to reconnect to server if disconnected --- view1090.c | 58 +++++++++++++++++++++++++++++++++++------------------- view1090.h | 2 ++ 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/view1090.c b/view1090.c index 4830bca..59498be 100644 --- a/view1090.c +++ b/view1090.c @@ -115,6 +115,33 @@ void view1090Init(void) { // Prepare error correction tables modesInitErrorInfo(); } + +// Set up data connection +int setupConnection(struct client *c) { + int fd; + + // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. + if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) != ANET_ERR) { + // + // Setup a service callback client structure for a beast binary input (from dump1090) + // This is a bit dodgy under Windows. The fd parameter is a handle to the internet + // socket on which we are receiving data. Under Linux, these seem to start at 0 and + // count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0. + // dump1090 limits fd to values less than 1024, and then uses the fd parameter to + // index into an array of clients. This is ok-ish if handles are allocated up from 0. + // However, there is no gaurantee that Windows will behave like this, and if Windows + // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, + // the first Windows handle is usually in the 0x54 (84 decimal) region. + + c->next = NULL; + c->buflen = 0; + c->fd = + c->service = + Modes.bis = fd; + Modes.clients = c; + } + return fd; +} // // ================================ Main ==================================== // @@ -181,6 +208,7 @@ void showCopyright(void) { int main(int argc, char **argv) { int j, fd; struct client *c; + char pk_buf[8]; // Set sane defaults @@ -244,34 +272,24 @@ int main(int argc, char **argv) { view1090Init(); // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. - if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) == ANET_ERR) { + c = (struct client *) malloc(sizeof(*c)); + if ((fd = setupConnection(c)) == ANET_ERR) { fprintf(stderr, "Failed to connect to %s:%d\n", View1090.net_input_beast_ipaddr, Modes.net_input_beast_port); exit(1); } - // - // Setup a service callback client structure for a beast binary input (from dump1090) - // This is a bit dodgy under Windows. The fd parameter is a handle to the internet - // socket on which we are receiving data. Under Linux, these seem to start at 0 and - // count upwards. However, Windows uses "HANDLES" and these don't nececeriy start at 0. - // dump1090 limits fd to values less than 1024, and then uses the fd parameter to - // index into an array of clients. This is ok-ish if handles are allocated up from 0. - // However, there is no gaurantee that Windows will behave like this, and if Windows - // allocates a handle greater than 1024, then dump1090 won't like it. On my test machine, - // the first Windows handle is usually in the 0x54 (84 decimal) region. - - c = (struct client *) malloc(sizeof(*c)); - c->next = NULL; - c->buflen = 0; - c->fd = - c->service = - Modes.bis = fd; - Modes.clients = c; // Keep going till the user does something that stops us while (!Modes.exit) { - modesReadFromClient(c,"",decodeBinMessage); interactiveRemoveStaleAircrafts(); interactiveShowData(); + if ((fd == ANET_ERR) || (recv(c->fd, pk_buf, sizeof(pk_buf), MSG_PEEK | MSG_DONTWAIT) == 0)) { + free(c); + usleep(1000000); + c = (struct client *) malloc(sizeof(*c)); + fd = setupConnection(c); + continue; + } + modesReadFromClient(c,"",decodeBinMessage); } // The user has stopped us, so close any socket we opened diff --git a/view1090.h b/view1090.h index c4c97fe..03ad96d 100644 --- a/view1090.h +++ b/view1090.h @@ -49,6 +49,8 @@ #include #include #include + #include + #include #include "rtl-sdr.h" #include "anet.h" #else From 350a57f858567a2ef85d40f63a7a2cc196eb1446 Mon Sep 17 00:00:00 2001 From: hhm Date: Wed, 2 Jul 2014 07:41:43 -0400 Subject: [PATCH 05/16] B"H view1090: do not block - do not block on network data --- view1090.c | 1 + 1 file changed, 1 insertion(+) diff --git a/view1090.c b/view1090.c index 59498be..2dbd323 100644 --- a/view1090.c +++ b/view1090.c @@ -122,6 +122,7 @@ int setupConnection(struct client *c) { // Try to connect to the selected ip address and port. We only support *ONE* input connection which we initiate.here. if ((fd = anetTcpConnect(Modes.aneterr, View1090.net_input_beast_ipaddr, Modes.net_input_beast_port)) != ANET_ERR) { + anetNonBlock(Modes.aneterr, fd); // // Setup a service callback client structure for a beast binary input (from dump1090) // This is a bit dodgy under Windows. The fd parameter is a handle to the internet From ec09cc7a71d6c2aa8b341568120af7fd68ab9f17 Mon Sep 17 00:00:00 2001 From: hhm Date: Thu, 3 Jul 2014 02:41:06 -0400 Subject: [PATCH 06/16] B"H view1090: sleep a bit between loops view1090 was using close to 100% CPU before, with the non-blocking commits and the reconnection code. sleep a bit between loop iterations to keep CPU usage low. CPU usage with this addition was down to <1% in testing. --- view1090.c | 1 + 1 file changed, 1 insertion(+) diff --git a/view1090.c b/view1090.c index 2dbd323..5ce15ad 100644 --- a/view1090.c +++ b/view1090.c @@ -291,6 +291,7 @@ int main(int argc, char **argv) { continue; } modesReadFromClient(c,"",decodeBinMessage); + usleep(100000); } // The user has stopped us, so close any socket we opened From a86eb7a61c1f5af57b74b851713627973982e720 Mon Sep 17 00:00:00 2001 From: hhm Date: Sun, 6 Jul 2014 05:58:44 -0400 Subject: [PATCH 07/16] B"H view1090: do not use pthreads It *seems* that pthreads are used in dump1090 for I/! sample reading only. So view1090 need not use pthread_exit. --- view1090.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/view1090.c b/view1090.c index 5ce15ad..644245d 100644 --- a/view1090.c +++ b/view1090.c @@ -298,11 +298,7 @@ int main(int argc, char **argv) { if (fd != ANET_ERR) {close(fd);} -#ifndef _WIN32 - pthread_exit(0); -#else return (0); -#endif } // //========================================================================= From 8110549fee881a0b104b9003618f030d04492b3e Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 15:12:46 -0500 Subject: [PATCH 08/16] Update dump1090.c --- dump1090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dump1090.c b/dump1090.c index 286fb05..281ac0c 100644 --- a/dump1090.c +++ b/dump1090.c @@ -515,7 +515,7 @@ int main(int argc, char **argv) { int more = j+1 < argc; // There are more arguments if (!strcmp(argv[j],"--device-index") && more) { - Modes.dev_index = atoi(argv[++j]); + Modes.dev_index = verbose_device_search(argv[++j]); } else if (!strcmp(argv[j],"--gain") && more) { Modes.gain = (int) atof(argv[++j])*10; // Gain is in tens of DBs } else if (!strcmp(argv[j],"--enable-agc")) { From 50b05c538e02fb9d66a5e4fc47ed676462c46c60 Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 16:54:30 -0500 Subject: [PATCH 09/16] Create convienience.h --- convienience.h | 150 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 convienience.h diff --git a/convienience.h b/convienience.h new file mode 100644 index 0000000..e1244af --- /dev/null +++ b/convienience.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2013-2014 by Kyle Keen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* a collection of user friendly tools */ + +/*! + * Convert standard suffixes (k, M, G) to double + * + * \param s a string to be parsed + * \return double + */ + +double atofs(char *s); + +/*! + * Convert time suffixes (s, m, h) to double + * + * \param s a string to be parsed + * \return seconds as double + */ + +double atoft(char *s); + +/*! + * Convert percent suffixe (%) to double + * + * \param s a string to be parsed + * \return double + */ + +double atofp(char *s); + +/*! + * Find nearest supported gain + * + * \param dev the device handle given by rtlsdr_open() + * \param target_gain in tenths of a dB + * \return 0 on success + */ + +int nearest_gain(rtlsdr_dev_t *dev, int target_gain); + +/*! + * Set device frequency and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \param frequency in Hz + * \return 0 on success + */ + +int verbose_set_frequency(rtlsdr_dev_t *dev, uint32_t frequency); + +/*! + * Set device sample rate and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \param samp_rate in samples/second + * \return 0 on success + */ + +int verbose_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate); + +/*! + * Enable or disable the direct sampling mode and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \param on 0 means disabled, 1 I-ADC input enabled, 2 Q-ADC input enabled + * \return 0 on success + */ + +int verbose_direct_sampling(rtlsdr_dev_t *dev, int on); + +/*! + * Enable offset tuning and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on success + */ + +int verbose_offset_tuning(rtlsdr_dev_t *dev); + +/*! + * Enable auto gain and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on success + */ + +int verbose_auto_gain(rtlsdr_dev_t *dev); + +/*! + * Set tuner gain and report status on stderr + * + * \param dev the device handle given by rtlsdr_open() + * \param gain in tenths of a dB + * \return 0 on success + */ + +int verbose_gain_set(rtlsdr_dev_t *dev, int gain); + +/*! + * Set the frequency correction value for the device and report status on stderr. + * + * \param dev the device handle given by rtlsdr_open() + * \param ppm_error correction value in parts per million (ppm) + * \return 0 on success + */ + +int verbose_ppm_set(rtlsdr_dev_t *dev, int ppm_error); + +/*! + * Attempts to extract a correction value from eeprom and store it to an int. + * + * \param dev the device handle given by rtlsdr_open() + * \param ppm_error correction value in parts per million (ppm) + * \return 0 on success + */ +int verbose_ppm_eeprom(rtlsdr_dev_t *dev, int *ppm_error); + +/*! + * Reset buffer + * + * \param dev the device handle given by rtlsdr_open() + * \return 0 on success + */ + +int verbose_reset_buffer(rtlsdr_dev_t *dev); + +/*! + * Find the closest matching device. + * + * \param s a string to be parsed + * \return dev_index int, -1 on error + */ + +int verbose_device_search(char *s); From a190677ad41125b88cf0c548ad1278d6e7a2a33f Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 16:55:16 -0500 Subject: [PATCH 10/16] Create convienience.c --- convienience.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 334 insertions(+) create mode 100644 convienience.c diff --git a/convienience.c b/convienience.c new file mode 100644 index 0000000..6565e1a --- /dev/null +++ b/convienience.c @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2013-2014 by Kyle Keen + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* a collection of user friendly tools + * todo: use strtol for more flexible int parsing + * */ + +#include +#include +#include + +#ifndef _WIN32 +#include +#else +#include +#include +#include +#define _USE_MATH_DEFINES +#endif + +#include + +#include "rtl-sdr.h" + +double atofs(char *s) +/* standard suffixes */ +{ + char last; + int len; + double suff = 1.0; + len = strlen(s); + last = s[len-1]; + s[len-1] = '\0'; + switch (last) { + case 'g': + case 'G': + suff *= 1e3; + case 'm': + case 'M': + suff *= 1e3; + case 'k': + case 'K': + suff *= 1e3; + suff *= atof(s); + s[len-1] = last; + return suff; + } + s[len-1] = last; + return atof(s); +} + +double atoft(char *s) +/* time suffixes, returns seconds */ +{ + char last; + int len; + double suff = 1.0; + len = strlen(s); + last = s[len-1]; + s[len-1] = '\0'; + switch (last) { + case 'h': + case 'H': + suff *= 60; + case 'm': + case 'M': + suff *= 60; + case 's': + case 'S': + suff *= atof(s); + s[len-1] = last; + return suff; + } + s[len-1] = last; + return atof(s); +} + +double atofp(char *s) +/* percent suffixes */ +{ + char last; + int len; + double suff = 1.0; + len = strlen(s); + last = s[len-1]; + s[len-1] = '\0'; + switch (last) { + case '%': + suff *= 0.01; + suff *= atof(s); + s[len-1] = last; + return suff; + } + s[len-1] = last; + return atof(s); +} + +int nearest_gain(rtlsdr_dev_t *dev, int target_gain) +{ + int i, r, err1, err2, count, nearest; + int* gains; + r = rtlsdr_set_tuner_gain_mode(dev, 1); + if (r < 0) { + fprintf(stderr, "WARNING: Failed to enable manual gain.\n"); + return r; + } + count = rtlsdr_get_tuner_gains(dev, NULL); + if (count <= 0) { + return 0; + } + gains = malloc(sizeof(int) * count); + count = rtlsdr_get_tuner_gains(dev, gains); + nearest = gains[0]; + for (i=0; i=0; i--) { + if (serial[i] != start_char) { + continue;} + fprintf(stderr, "PPM calibration found in eeprom.\n"); + status = 0; + *ppm_error = atoi(serial + i + 1); + break; + } + serial[len-1] = stop_char; + return status; +} + +int verbose_reset_buffer(rtlsdr_dev_t *dev) +{ + int r; + r = rtlsdr_reset_buffer(dev); + if (r < 0) { + fprintf(stderr, "WARNING: Failed to reset buffers.\n");} + return r; +} + +int verbose_device_search(char *s) +{ + int i, device_count, device, offset; + char *s2; + char vendor[256], product[256], serial[256]; + device_count = rtlsdr_get_device_count(); + if (!device_count) { + fprintf(stderr, "No supported devices found.\n"); + return -1; + } + fprintf(stderr, "Found %d device(s):\n", device_count); + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); + } + fprintf(stderr, "\n"); + /* does string look like raw id number */ + device = (int)strtol(s, &s2, 0); + if (s2[0] == '\0' && device >= 0 && device < device_count) { + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string exact match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + if (strcmp(s, serial) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string prefix match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + if (strncmp(s, serial, strlen(s)) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string suffix match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + offset = strlen(serial) - strlen(s); + if (offset < 0) { + continue;} + if (strncmp(s, serial+offset, strlen(s)) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + fprintf(stderr, "No matching devices found.\n"); + return -1; +} + +// vim: tabstop=8:softtabstop=8:shiftwidth=8:noexpandtab From d0207569b6294e182aad07a1647ad433072ab65e Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 16:56:03 -0500 Subject: [PATCH 11/16] Update dump1090.c --- dump1090.c | 1 + 1 file changed, 1 insertion(+) diff --git a/dump1090.c b/dump1090.c index 281ac0c..dfd962c 100644 --- a/dump1090.c +++ b/dump1090.c @@ -29,6 +29,7 @@ // #include "coaa.h" #include "dump1090.h" +#include "convienience.h // // ============================= Utility functions ========================== // From 652af93b88bad90ad8828b5ffdccd4a5722cde87 Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 16:58:23 -0500 Subject: [PATCH 12/16] Update dump1090.c --- dump1090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dump1090.c b/dump1090.c index dfd962c..fcfaa6e 100644 --- a/dump1090.c +++ b/dump1090.c @@ -29,7 +29,7 @@ // #include "coaa.h" #include "dump1090.h" -#include "convienience.h +#include "convienience.h" // // ============================= Utility functions ========================== // From 3043e860964bed3144b3bdc2d0ce9b23920b9bb1 Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 17:32:16 -0500 Subject: [PATCH 13/16] Delete convienience.h --- convienience.h | 150 ------------------------------------------------- 1 file changed, 150 deletions(-) delete mode 100644 convienience.h diff --git a/convienience.h b/convienience.h deleted file mode 100644 index e1244af..0000000 --- a/convienience.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2013-2014 by Kyle Keen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* a collection of user friendly tools */ - -/*! - * Convert standard suffixes (k, M, G) to double - * - * \param s a string to be parsed - * \return double - */ - -double atofs(char *s); - -/*! - * Convert time suffixes (s, m, h) to double - * - * \param s a string to be parsed - * \return seconds as double - */ - -double atoft(char *s); - -/*! - * Convert percent suffixe (%) to double - * - * \param s a string to be parsed - * \return double - */ - -double atofp(char *s); - -/*! - * Find nearest supported gain - * - * \param dev the device handle given by rtlsdr_open() - * \param target_gain in tenths of a dB - * \return 0 on success - */ - -int nearest_gain(rtlsdr_dev_t *dev, int target_gain); - -/*! - * Set device frequency and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \param frequency in Hz - * \return 0 on success - */ - -int verbose_set_frequency(rtlsdr_dev_t *dev, uint32_t frequency); - -/*! - * Set device sample rate and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \param samp_rate in samples/second - * \return 0 on success - */ - -int verbose_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate); - -/*! - * Enable or disable the direct sampling mode and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \param on 0 means disabled, 1 I-ADC input enabled, 2 Q-ADC input enabled - * \return 0 on success - */ - -int verbose_direct_sampling(rtlsdr_dev_t *dev, int on); - -/*! - * Enable offset tuning and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on success - */ - -int verbose_offset_tuning(rtlsdr_dev_t *dev); - -/*! - * Enable auto gain and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on success - */ - -int verbose_auto_gain(rtlsdr_dev_t *dev); - -/*! - * Set tuner gain and report status on stderr - * - * \param dev the device handle given by rtlsdr_open() - * \param gain in tenths of a dB - * \return 0 on success - */ - -int verbose_gain_set(rtlsdr_dev_t *dev, int gain); - -/*! - * Set the frequency correction value for the device and report status on stderr. - * - * \param dev the device handle given by rtlsdr_open() - * \param ppm_error correction value in parts per million (ppm) - * \return 0 on success - */ - -int verbose_ppm_set(rtlsdr_dev_t *dev, int ppm_error); - -/*! - * Attempts to extract a correction value from eeprom and store it to an int. - * - * \param dev the device handle given by rtlsdr_open() - * \param ppm_error correction value in parts per million (ppm) - * \return 0 on success - */ -int verbose_ppm_eeprom(rtlsdr_dev_t *dev, int *ppm_error); - -/*! - * Reset buffer - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on success - */ - -int verbose_reset_buffer(rtlsdr_dev_t *dev); - -/*! - * Find the closest matching device. - * - * \param s a string to be parsed - * \return dev_index int, -1 on error - */ - -int verbose_device_search(char *s); From c80582274b86b81628e1a6a2fdcf057b87d92d14 Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 17:32:30 -0500 Subject: [PATCH 14/16] Delete convienience.c --- convienience.c | 334 ------------------------------------------------- 1 file changed, 334 deletions(-) delete mode 100644 convienience.c diff --git a/convienience.c b/convienience.c deleted file mode 100644 index 6565e1a..0000000 --- a/convienience.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 2013-2014 by Kyle Keen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/* a collection of user friendly tools - * todo: use strtol for more flexible int parsing - * */ - -#include -#include -#include - -#ifndef _WIN32 -#include -#else -#include -#include -#include -#define _USE_MATH_DEFINES -#endif - -#include - -#include "rtl-sdr.h" - -double atofs(char *s) -/* standard suffixes */ -{ - char last; - int len; - double suff = 1.0; - len = strlen(s); - last = s[len-1]; - s[len-1] = '\0'; - switch (last) { - case 'g': - case 'G': - suff *= 1e3; - case 'm': - case 'M': - suff *= 1e3; - case 'k': - case 'K': - suff *= 1e3; - suff *= atof(s); - s[len-1] = last; - return suff; - } - s[len-1] = last; - return atof(s); -} - -double atoft(char *s) -/* time suffixes, returns seconds */ -{ - char last; - int len; - double suff = 1.0; - len = strlen(s); - last = s[len-1]; - s[len-1] = '\0'; - switch (last) { - case 'h': - case 'H': - suff *= 60; - case 'm': - case 'M': - suff *= 60; - case 's': - case 'S': - suff *= atof(s); - s[len-1] = last; - return suff; - } - s[len-1] = last; - return atof(s); -} - -double atofp(char *s) -/* percent suffixes */ -{ - char last; - int len; - double suff = 1.0; - len = strlen(s); - last = s[len-1]; - s[len-1] = '\0'; - switch (last) { - case '%': - suff *= 0.01; - suff *= atof(s); - s[len-1] = last; - return suff; - } - s[len-1] = last; - return atof(s); -} - -int nearest_gain(rtlsdr_dev_t *dev, int target_gain) -{ - int i, r, err1, err2, count, nearest; - int* gains; - r = rtlsdr_set_tuner_gain_mode(dev, 1); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to enable manual gain.\n"); - return r; - } - count = rtlsdr_get_tuner_gains(dev, NULL); - if (count <= 0) { - return 0; - } - gains = malloc(sizeof(int) * count); - count = rtlsdr_get_tuner_gains(dev, gains); - nearest = gains[0]; - for (i=0; i=0; i--) { - if (serial[i] != start_char) { - continue;} - fprintf(stderr, "PPM calibration found in eeprom.\n"); - status = 0; - *ppm_error = atoi(serial + i + 1); - break; - } - serial[len-1] = stop_char; - return status; -} - -int verbose_reset_buffer(rtlsdr_dev_t *dev) -{ - int r; - r = rtlsdr_reset_buffer(dev); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to reset buffers.\n");} - return r; -} - -int verbose_device_search(char *s) -{ - int i, device_count, device, offset; - char *s2; - char vendor[256], product[256], serial[256]; - device_count = rtlsdr_get_device_count(); - if (!device_count) { - fprintf(stderr, "No supported devices found.\n"); - return -1; - } - fprintf(stderr, "Found %d device(s):\n", device_count); - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); - } - fprintf(stderr, "\n"); - /* does string look like raw id number */ - device = (int)strtol(s, &s2, 0); - if (s2[0] == '\0' && device >= 0 && device < device_count) { - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string exact match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - if (strcmp(s, serial) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string prefix match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - if (strncmp(s, serial, strlen(s)) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - /* does string suffix match a serial */ - for (i = 0; i < device_count; i++) { - rtlsdr_get_device_usb_strings(i, vendor, product, serial); - offset = strlen(serial) - strlen(s); - if (offset < 0) { - continue;} - if (strncmp(s, serial+offset, strlen(s)) != 0) { - continue;} - device = i; - fprintf(stderr, "Using device %d: %s\n", - device, rtlsdr_get_device_name((uint32_t)device)); - return device; - } - fprintf(stderr, "No matching devices found.\n"); - return -1; -} - -// vim: tabstop=8:softtabstop=8:shiftwidth=8:noexpandtab From 6f14ecf7dd7b0b28b6fb6469d96be12b25ec2771 Mon Sep 17 00:00:00 2001 From: matthewbrandes Date: Tue, 8 Jul 2014 17:34:43 -0500 Subject: [PATCH 15/16] Update dump1090.c --- dump1090.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/dump1090.c b/dump1090.c index fcfaa6e..bbe408e 100644 --- a/dump1090.c +++ b/dump1090.c @@ -29,7 +29,6 @@ // #include "coaa.h" #include "dump1090.h" -#include "convienience.h" // // ============================= Utility functions ========================== // @@ -504,6 +503,68 @@ void backgroundTasks(void) { // //========================================================================= // +int verbose_device_search(char *s) +{ + int i, device_count, device, offset; + char *s2; + char vendor[256], product[256], serial[256]; + device_count = rtlsdr_get_device_count(); + if (!device_count) { + fprintf(stderr, "No supported devices found.\n"); + return -1; + } + fprintf(stderr, "Found %d device(s):\n", device_count); + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); + } + fprintf(stderr, "\n"); + /* does string look like raw id number */ + device = (int)strtol(s, &s2, 0); + if (s2[0] == '\0' && device >= 0 && device < device_count) { + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string exact match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + if (strcmp(s, serial) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string prefix match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + if (strncmp(s, serial, strlen(s)) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + /* does string suffix match a serial */ + for (i = 0; i < device_count; i++) { + rtlsdr_get_device_usb_strings(i, vendor, product, serial); + offset = strlen(serial) - strlen(s); + if (offset < 0) { + continue;} + if (strncmp(s, serial+offset, strlen(s)) != 0) { + continue;} + device = i; + fprintf(stderr, "Using device %d: %s\n", + device, rtlsdr_get_device_name((uint32_t)device)); + return device; + } + fprintf(stderr, "No matching devices found.\n"); + return -1; +} +// +//========================================================================= +// int main(int argc, char **argv) { int j; From d1b37ad1c59cfc19930df245174321eada76147b Mon Sep 17 00:00:00 2001 From: hhm Date: Mon, 14 Jul 2014 04:03:07 -0400 Subject: [PATCH 16/16] B"H decoding: use last air position to calculate ground position --- mode_s.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/mode_s.c b/mode_s.c index e92cd9b..61ecda4 100644 --- a/mode_s.c +++ b/mode_s.c @@ -2022,12 +2022,24 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) { double rlat0 = AirDlat0 * (cprModFunction(j,60) + lat0 / 131072); double rlat1 = AirDlat1 * (cprModFunction(j,59) + lat1 / 131072); + time_t now = time(NULL); + double surface_rlat = MODES_USER_LATITUDE_DFLT; + double surface_rlon = MODES_USER_LONGITUDE_DFLT; + if (surface) { - // If we're on the ground, make sure we have our receiver base station Lat/Lon - if (0 == (Modes.bUserFlags & MODES_USER_LATLON_VALID)) - {return;} - rlat0 += floor(Modes.fUserLat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant - rlat1 += floor(Modes.fUserLat / 90.0) * 90.0; + // If we're on the ground, make sure we have a (likely) valid Lat/Lon + if ((a->bFlags & MODES_ACFLAGS_LATLON_VALID) && (((int)(now - a->seenLatLon)) < Modes.interactive_display_ttl)) { + surface_rlat = a->lat; + surface_rlon = a->lon; + } else if (Modes.bUserFlags & MODES_USER_LATLON_VALID) { + surface_rlat = Modes.fUserLat; + surface_rlon = Modes.fUserLon; + } else { + surface_rlat = Modes.fUserLat; + return; + } + rlat0 += floor(surface_rlat / 90.0) * 90.0; // Move from 1st quadrant to our quadrant + rlat1 += floor(surface_rlat / 90.0) * 90.0; } else { if (rlat0 >= 270) rlat0 -= 360; if (rlat1 >= 270) rlat1 -= 360; @@ -2052,7 +2064,7 @@ void decodeCPR(struct aircraft *a, int fflag, int surface) { } if (surface) { - a->lon += floor(Modes.fUserLon / 90.0) * 90.0; // Move from 1st quadrant to our quadrant + a->lon += floor(surface_rlon / 90.0) * 90.0; // Move from 1st quadrant to our quadrant } else if (a->lon > 180) { a->lon -= 360; }