2015-01-20 17:49:01 +01:00
|
|
|
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// dump1090.c: main program & miscellany
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// Copyright (c) 2014,2015 Oliver Jowett <oliver@mutability.co.uk>
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// This file is free software: you may copy, redistribute 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.
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// This file 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.
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
// This file incorporates work covered by the following copyright and
|
|
|
|
// permission notice:
|
|
|
|
//
|
|
|
|
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
|
|
|
|
//
|
|
|
|
// All rights reserved.
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2015-01-20 17:49:01 +01:00
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
|
|
// documentation and/or other materials provided with the distribution.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
2013-05-25 00:32:12 +02:00
|
|
|
#include "dump1090.h"
|
2015-01-04 21:08:33 +01:00
|
|
|
|
2015-06-26 18:49:21 +02:00
|
|
|
#include <rtl-sdr.h>
|
|
|
|
|
2015-02-17 22:40:26 +01:00
|
|
|
#include <stdarg.h>
|
2015-09-03 05:41:00 +02:00
|
|
|
|
2015-01-04 21:08:33 +01:00
|
|
|
static int verbose_device_search(char *s);
|
|
|
|
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
|
|
|
// ============================= Utility functions ==========================
|
|
|
|
//
|
2015-02-17 22:40:26 +01:00
|
|
|
|
|
|
|
static void log_with_timestamp(const char *format, ...) __attribute__((format (printf, 1, 2) ));
|
|
|
|
|
|
|
|
static void log_with_timestamp(const char *format, ...)
|
|
|
|
{
|
|
|
|
char timebuf[128];
|
|
|
|
char msg[1024];
|
|
|
|
time_t now;
|
|
|
|
struct tm local;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
now = time(NULL);
|
|
|
|
localtime_r(&now, &local);
|
|
|
|
strftime(timebuf, 128, "%c %Z", &local);
|
|
|
|
timebuf[127] = 0;
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
vsnprintf(msg, 1024, format, ap);
|
|
|
|
va_end(ap);
|
|
|
|
msg[1023] = 0;
|
|
|
|
|
|
|
|
fprintf(stderr, "%s %s\n", timebuf, msg);
|
|
|
|
}
|
|
|
|
|
2015-02-17 22:41:40 +01:00
|
|
|
static void sigintHandler(int dummy) {
|
2013-04-29 23:14:06 +02:00
|
|
|
MODES_NOTUSED(dummy);
|
2013-05-21 13:08:35 +02:00
|
|
|
signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety
|
|
|
|
Modes.exit = 1; // Signal to threads that we are done
|
2015-02-17 22:41:40 +01:00
|
|
|
log_with_timestamp("Caught SIGINT, shutting down..\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sigtermHandler(int dummy) {
|
|
|
|
MODES_NOTUSED(dummy);
|
|
|
|
signal(SIGTERM, SIG_DFL); // reset signal handler - bit extra safety
|
|
|
|
Modes.exit = 1; // Signal to threads that we are done
|
|
|
|
log_with_timestamp("Caught SIGTERM, shutting down..\n");
|
2013-04-29 23:14:06 +02:00
|
|
|
}
|
2013-08-19 16:55:17 +02:00
|
|
|
//
|
2014-02-22 23:11:11 +01:00
|
|
|
// =============================== Terminal handling ========================
|
|
|
|
//
|
|
|
|
#ifndef _WIN32
|
|
|
|
// Get the number of rows after the terminal changes size.
|
|
|
|
int getTermRows() {
|
|
|
|
struct winsize w;
|
|
|
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
|
|
return (w.ws_row);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle resizing terminal
|
|
|
|
void sigWinchCallback() {
|
|
|
|
signal(SIGWINCH, SIG_IGN);
|
|
|
|
Modes.interactive_rows = getTermRows();
|
|
|
|
interactiveShowData();
|
|
|
|
signal(SIGWINCH, sigWinchCallback);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
int getTermRows() { return MODES_INTERACTIVE_ROWS;}
|
|
|
|
#endif
|
2015-01-23 02:22:22 +01:00
|
|
|
|
|
|
|
static void start_cpu_timing(struct timespec *start_time)
|
|
|
|
{
|
|
|
|
clock_gettime(CLOCK_THREAD_CPUTIME_ID, start_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void end_cpu_timing(const struct timespec *start_time, struct timespec *add_to)
|
|
|
|
{
|
|
|
|
struct timespec end_time;
|
|
|
|
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end_time);
|
|
|
|
add_to->tv_sec += (end_time.tv_sec - start_time->tv_sec - 1);
|
|
|
|
add_to->tv_nsec += (1000000000L + end_time.tv_nsec - start_time->tv_nsec);
|
|
|
|
add_to->tv_sec += add_to->tv_nsec / 1000000000L;
|
|
|
|
add_to->tv_nsec = add_to->tv_nsec % 1000000000L;
|
|
|
|
}
|
|
|
|
|
2014-02-22 23:11:11 +01:00
|
|
|
//
|
2013-08-19 16:55:17 +02:00
|
|
|
// =============================== Initialization ===========================
|
|
|
|
//
|
2013-01-05 13:52:25 +01:00
|
|
|
void modesInitConfig(void) {
|
2013-05-02 14:05:25 +02:00
|
|
|
// Default everything to zero/NULL
|
|
|
|
memset(&Modes, 0, sizeof(Modes));
|
|
|
|
|
|
|
|
// Now initialise things that should not be 0/NULL to their defaults
|
2013-08-19 16:55:17 +02:00
|
|
|
Modes.gain = MODES_MAX_GAIN;
|
|
|
|
Modes.freq = MODES_DEFAULT_FREQ;
|
2014-07-10 19:11:13 +02:00
|
|
|
Modes.ppm_error = MODES_DEFAULT_PPM;
|
2013-08-19 16:55:17 +02:00
|
|
|
Modes.check_crc = 1;
|
2014-10-03 23:55:21 +02:00
|
|
|
Modes.net_heartbeat_interval = MODES_NET_HEARTBEAT_INTERVAL;
|
2013-08-19 16:55:17 +02:00
|
|
|
Modes.net_output_sbs_port = MODES_NET_OUTPUT_SBS_PORT;
|
|
|
|
Modes.net_output_raw_port = MODES_NET_OUTPUT_RAW_PORT;
|
|
|
|
Modes.net_input_raw_port = MODES_NET_INPUT_RAW_PORT;
|
|
|
|
Modes.net_output_beast_port = MODES_NET_OUTPUT_BEAST_PORT;
|
|
|
|
Modes.net_input_beast_port = MODES_NET_INPUT_BEAST_PORT;
|
|
|
|
Modes.net_http_port = MODES_NET_HTTP_PORT;
|
2014-12-08 20:56:45 +01:00
|
|
|
Modes.net_fatsv_port = MODES_NET_OUTPUT_FA_TSV_PORT;
|
2014-02-22 23:11:11 +01:00
|
|
|
Modes.interactive_rows = getTermRows();
|
2013-08-19 16:55:17 +02:00
|
|
|
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
|
2015-09-14 20:48:17 +02:00
|
|
|
Modes.html_dir = HTMLPATH;
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.json_interval = 1000;
|
2014-12-27 21:52:56 +01:00
|
|
|
Modes.json_location_accuracy = 1;
|
2015-01-13 21:03:34 +01:00
|
|
|
Modes.maxRange = 1852 * 300; // 300NM default max range
|
2013-01-05 13:52:25 +01:00
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
2013-01-05 13:52:25 +01:00
|
|
|
void modesInit(void) {
|
|
|
|
int i, q;
|
|
|
|
|
|
|
|
pthread_mutex_init(&Modes.data_mutex,NULL);
|
|
|
|
pthread_cond_init(&Modes.data_cond,NULL);
|
2013-04-10 13:16:25 +02:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
if (Modes.oversample)
|
|
|
|
Modes.sample_rate = 2400000.0;
|
|
|
|
else
|
|
|
|
Modes.sample_rate = 2000000.0;
|
|
|
|
|
2013-04-10 13:16:25 +02:00
|
|
|
// Allocate the various buffers used by Modes
|
2015-06-15 23:14:37 +02:00
|
|
|
Modes.trailing_samples = (MODES_PREAMBLE_US + MODES_LONG_MSG_BITS + 16) * 1e-6 * Modes.sample_rate;
|
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
if ( ((Modes.maglut = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256) ) == NULL) ||
|
2014-10-04 00:04:09 +02:00
|
|
|
((Modes.log10lut = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256) ) == NULL) )
|
2013-04-10 13:16:25 +02:00
|
|
|
{
|
2013-01-05 13:52:25 +01:00
|
|
|
fprintf(stderr, "Out of memory allocating data buffer.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2013-04-10 13:16:25 +02:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
for (i = 0; i < MODES_MAG_BUFFERS; ++i) {
|
|
|
|
if ( (Modes.mag_buffers[i].data = calloc(MODES_MAG_BUF_SAMPLES+Modes.trailing_samples, sizeof(uint16_t))) == NULL ) {
|
|
|
|
fprintf(stderr, "Out of memory allocating magnitude buffer.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Modes.mag_buffers[i].length = 0;
|
|
|
|
Modes.mag_buffers[i].dropped = 0;
|
|
|
|
Modes.mag_buffers[i].sampleTimestamp = 0;
|
|
|
|
}
|
2013-05-02 14:05:25 +02:00
|
|
|
|
2013-05-09 12:29:18 +02:00
|
|
|
// Validate the users Lat/Lon home location inputs
|
|
|
|
if ( (Modes.fUserLat > 90.0) // Latitude must be -90 to +90
|
|
|
|
|| (Modes.fUserLat < -90.0) // and
|
|
|
|
|| (Modes.fUserLon > 360.0) // Longitude must be -180 to +360
|
|
|
|
|| (Modes.fUserLon < -180.0) ) {
|
|
|
|
Modes.fUserLat = Modes.fUserLon = 0.0;
|
|
|
|
} else if (Modes.fUserLon > 180.0) { // If Longitude is +180 to +360, make it -180 to 0
|
|
|
|
Modes.fUserLon -= 360.0;
|
|
|
|
}
|
|
|
|
// If both Lat and Lon are 0.0 then the users location is either invalid/not-set, or (s)he's in the
|
|
|
|
// Atlantic ocean off the west coast of Africa. This is unlikely to be correct.
|
|
|
|
// Set the user LatLon valid flag only if either Lat or Lon are non zero. Note the Greenwich meridian
|
|
|
|
// is at 0.0 Lon,so we must check for either fLat or fLon being non zero not both.
|
|
|
|
// Testing the flag at runtime will be much quicker than ((fLon != 0.0) || (fLat != 0.0))
|
|
|
|
Modes.bUserFlags &= ~MODES_USER_LATLON_VALID;
|
|
|
|
if ((Modes.fUserLat != 0.0) || (Modes.fUserLon != 0.0)) {
|
|
|
|
Modes.bUserFlags |= MODES_USER_LATLON_VALID;
|
|
|
|
}
|
|
|
|
|
2013-04-14 23:51:50 +02:00
|
|
|
// Limit the maximum requested raw output size to less than one Ethernet Block
|
2014-10-03 23:55:21 +02:00
|
|
|
if (Modes.net_output_flush_size > (MODES_OUT_FLUSH_SIZE))
|
|
|
|
{Modes.net_output_flush_size = MODES_OUT_FLUSH_SIZE;}
|
|
|
|
if (Modes.net_output_flush_interval > (MODES_OUT_FLUSH_INTERVAL))
|
|
|
|
{Modes.net_output_flush_interval = MODES_OUT_FLUSH_INTERVAL;}
|
2014-05-27 14:16:57 +02:00
|
|
|
if (Modes.net_sndbuf_size > (MODES_NET_SNDBUF_MAX))
|
|
|
|
{Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}
|
2013-04-14 23:51:50 +02:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
// compute UC8 magnitude lookup table
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
for (i = 0; i <= 255; i++) {
|
|
|
|
for (q = 0; q <= 255; q++) {
|
2015-06-15 23:14:37 +02:00
|
|
|
float fI, fQ, magsq;
|
2013-04-12 23:39:33 +02:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
fI = (i - 127.5) / 127.5;
|
|
|
|
fQ = (q - 127.5) / 127.5;
|
|
|
|
magsq = fI * fI + fQ * fQ;
|
|
|
|
if (magsq > 1)
|
|
|
|
magsq = 1;
|
2013-04-07 17:22:02 +02:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
Modes.maglut[le16toh((i*256)+q)] = (uint16_t) round(sqrtf(magsq) * 65535.0);
|
2013-04-13 02:37:02 +02:00
|
|
|
}
|
2013-01-10 20:58:13 +01:00
|
|
|
}
|
2013-04-12 12:15:52 +02:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
// Prepare the log10 lookup table: 100log10(x)
|
|
|
|
Modes.log10lut[0] = 0; // poorly defined..
|
|
|
|
for (i = 1; i <= 65535; i++) {
|
|
|
|
Modes.log10lut[i] = (uint16_t) round(100.0 * log10(i));
|
2014-09-22 15:53:06 +02:00
|
|
|
}
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// Prepare error correction tables
|
2015-01-21 00:04:05 +01:00
|
|
|
modesChecksumInit(Modes.nfix_crc);
|
2015-01-21 00:53:26 +01:00
|
|
|
icaoFilterInit();
|
2015-02-23 00:01:54 +01:00
|
|
|
|
|
|
|
if (Modes.show_only)
|
|
|
|
icaoFilterAdd(Modes.show_only);
|
2015-06-15 23:14:37 +02:00
|
|
|
|
|
|
|
// Prepare sample conversion
|
|
|
|
if (!Modes.net_only) {
|
|
|
|
if (Modes.filename == NULL) // using a real RTLSDR, use UC8 input always
|
|
|
|
Modes.input_format = INPUT_UC8;
|
|
|
|
|
|
|
|
Modes.converter_function = init_converter(Modes.input_format,
|
|
|
|
Modes.sample_rate,
|
|
|
|
Modes.dc_filter,
|
|
|
|
Modes.measure_noise, /* total power is interesting if we want noise */
|
|
|
|
&Modes.converter_state);
|
|
|
|
if (!Modes.converter_function) {
|
|
|
|
fprintf(stderr, "Can't initialize sample converter, giving up.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void convert_samples(void *iq,
|
|
|
|
uint16_t *mag,
|
|
|
|
unsigned nsamples,
|
|
|
|
double *power)
|
|
|
|
{
|
|
|
|
Modes.converter_function(iq, mag, nsamples, Modes.converter_state, power);
|
2013-01-10 20:58:13 +01:00
|
|
|
}
|
2015-06-15 23:14:37 +02:00
|
|
|
|
2013-05-10 18:27:34 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// =============================== RTLSDR handling ==========================
|
2013-05-10 18:27:34 +02:00
|
|
|
//
|
2015-01-02 23:29:29 +01:00
|
|
|
int modesInitRTLSDR(void) {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
int j;
|
2015-01-02 23:29:29 +01:00
|
|
|
int device_count, dev_index = 0;
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
char vendor[256], product[256], serial[256];
|
2013-05-10 18:27:34 +02:00
|
|
|
|
2015-01-02 23:29:29 +01:00
|
|
|
if (Modes.dev_name) {
|
|
|
|
if ( (dev_index = verbose_device_search(Modes.dev_name)) < 0 )
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
device_count = rtlsdr_get_device_count();
|
|
|
|
if (!device_count) {
|
|
|
|
fprintf(stderr, "No supported RTLSDR devices found.\n");
|
2015-01-02 23:29:29 +01:00
|
|
|
return -1;
|
2013-05-10 18:27:34 +02:00
|
|
|
}
|
2013-04-12 23:03:04 +02:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
fprintf(stderr, "Found %d device(s):\n", device_count);
|
|
|
|
for (j = 0; j < device_count; j++) {
|
|
|
|
rtlsdr_get_device_usb_strings(j, vendor, product, serial);
|
|
|
|
fprintf(stderr, "%d: %s, %s, SN: %s %s\n", j, vendor, product, serial,
|
2015-01-02 23:29:29 +01:00
|
|
|
(j == dev_index) ? "(currently selected)" : "");
|
2013-05-10 18:27:34 +02:00
|
|
|
}
|
2013-01-20 00:13:01 +01:00
|
|
|
|
2015-01-02 23:29:29 +01:00
|
|
|
if (rtlsdr_open(&Modes.dev, dev_index) < 0) {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
fprintf(stderr, "Error opening the RTLSDR device: %s\n",
|
|
|
|
strerror(errno));
|
2015-01-02 23:29:29 +01:00
|
|
|
return -1;
|
2013-05-10 18:27:34 +02:00
|
|
|
}
|
2013-04-12 23:03:04 +02:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// Set gain, frequency, sample rate, and reset the device
|
|
|
|
rtlsdr_set_tuner_gain_mode(Modes.dev,
|
|
|
|
(Modes.gain == MODES_AUTO_GAIN) ? 0 : 1);
|
|
|
|
if (Modes.gain != MODES_AUTO_GAIN) {
|
2015-01-11 00:52:37 +01:00
|
|
|
int *gains;
|
|
|
|
int numgains;
|
|
|
|
|
|
|
|
numgains = rtlsdr_get_tuner_gains(Modes.dev, NULL);
|
|
|
|
if (numgains <= 0) {
|
|
|
|
fprintf(stderr, "Error getting tuner gains\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
gains = malloc(numgains * sizeof(int));
|
|
|
|
if (rtlsdr_get_tuner_gains(Modes.dev, gains) != numgains) {
|
|
|
|
fprintf(stderr, "Error getting tuner gains\n");
|
|
|
|
free(gains);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
if (Modes.gain == MODES_MAX_GAIN) {
|
2015-01-11 00:52:37 +01:00
|
|
|
int highest = -1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < numgains; ++i) {
|
|
|
|
if (gains[i] > highest)
|
|
|
|
highest = gains[i];
|
|
|
|
}
|
2013-04-12 23:03:04 +02:00
|
|
|
|
2015-01-11 00:52:37 +01:00
|
|
|
Modes.gain = highest;
|
|
|
|
fprintf(stderr, "Max available gain is: %.2f dB\n", Modes.gain/10.0);
|
|
|
|
} else {
|
|
|
|
int closest = -1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < numgains; ++i) {
|
|
|
|
if (closest == -1 || abs(gains[i] - Modes.gain) < abs(closest - Modes.gain))
|
|
|
|
closest = gains[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (closest != Modes.gain) {
|
|
|
|
Modes.gain = closest;
|
|
|
|
fprintf(stderr, "Closest available gain: %.2f dB\n", Modes.gain/10.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
free(gains);
|
|
|
|
|
|
|
|
fprintf(stderr, "Setting gain to: %.2f dB\n", Modes.gain/10.0);
|
|
|
|
if (rtlsdr_set_tuner_gain(Modes.dev, Modes.gain) < 0) {
|
|
|
|
fprintf(stderr, "Error setting tuner gains\n");
|
|
|
|
return -1;
|
2013-05-10 18:27:34 +02:00
|
|
|
}
|
2013-01-20 00:13:01 +01:00
|
|
|
} else {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
fprintf(stderr, "Using automatic gain control.\n");
|
2013-01-17 19:12:23 +01:00
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
rtlsdr_set_freq_correction(Modes.dev, Modes.ppm_error);
|
|
|
|
if (Modes.enable_agc) rtlsdr_set_agc_mode(Modes.dev, 1);
|
|
|
|
rtlsdr_set_center_freq(Modes.dev, Modes.freq);
|
2015-06-15 23:14:37 +02:00
|
|
|
rtlsdr_set_sample_rate(Modes.dev, (unsigned)Modes.sample_rate);
|
2014-09-26 23:42:38 +02:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
rtlsdr_reset_buffer(Modes.dev);
|
2015-01-11 00:52:37 +01:00
|
|
|
fprintf(stderr, "Gain reported by device: %.2f dB\n",
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
rtlsdr_get_tuner_gain(Modes.dev)/10.0);
|
2015-01-04 21:08:33 +01:00
|
|
|
|
|
|
|
return 0;
|
2013-01-17 19:12:23 +01:00
|
|
|
}
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//=========================================================================
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// We use a thread reading data in background, while the main thread
|
|
|
|
// handles decoding and visualization of data to the user.
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// The reading thread calls the RTLSDR API to read data asynchronously, and
|
|
|
|
// uses a callback to populate the data buffer.
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// A Mutex is used to avoid races with the decoding thread.
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
2015-01-23 02:22:22 +01:00
|
|
|
|
|
|
|
static struct timespec reader_thread_start;
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {
|
2015-04-09 19:51:31 +02:00
|
|
|
struct mag_buf *outbuf;
|
|
|
|
struct mag_buf *lastbuf;
|
|
|
|
uint32_t slen;
|
|
|
|
unsigned next_free_buffer;
|
|
|
|
unsigned free_bufs;
|
|
|
|
unsigned block_duration;
|
|
|
|
|
|
|
|
static int was_odd = 0; // paranoia!!
|
|
|
|
static int dropping = 0;
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
MODES_NOTUSED(ctx);
|
2013-04-24 21:46:59 +02:00
|
|
|
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
// Lock the data buffer variables before accessing them
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
2015-01-23 02:20:22 +01:00
|
|
|
if (Modes.exit) {
|
|
|
|
rtlsdr_cancel_async(Modes.dev); // ask our caller to exit
|
|
|
|
}
|
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
next_free_buffer = (Modes.first_free_buffer + 1) % MODES_MAG_BUFFERS;
|
|
|
|
outbuf = &Modes.mag_buffers[Modes.first_free_buffer];
|
|
|
|
lastbuf = &Modes.mag_buffers[(Modes.first_free_buffer + MODES_MAG_BUFFERS - 1) % MODES_MAG_BUFFERS];
|
|
|
|
free_bufs = (Modes.first_filled_buffer - next_free_buffer + MODES_MAG_BUFFERS) % MODES_MAG_BUFFERS;
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// Paranoia! Unlikely, but let's go for belt and suspenders here
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
if (len != MODES_RTL_BUF_SIZE) {
|
|
|
|
fprintf(stderr, "weirdness: rtlsdr gave us a block with an unusual size (got %u bytes, expected %u bytes)\n",
|
|
|
|
(unsigned)len, (unsigned)MODES_RTL_BUF_SIZE);
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
if (len > MODES_RTL_BUF_SIZE) {
|
|
|
|
// wat?! Discard the start.
|
|
|
|
unsigned discard = (len - MODES_RTL_BUF_SIZE + 1) / 2;
|
|
|
|
outbuf->dropped += discard;
|
|
|
|
buf += discard*2;
|
|
|
|
len -= discard*2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (was_odd) {
|
|
|
|
// Drop a sample so we are in sync with I/Q samples again (hopefully)
|
|
|
|
++buf;
|
|
|
|
--len;
|
|
|
|
++outbuf->dropped;
|
|
|
|
}
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
was_odd = (len & 1);
|
|
|
|
slen = len/2;
|
|
|
|
|
|
|
|
if (free_bufs == 0 || (dropping && free_bufs < MODES_MAG_BUFFERS/2)) {
|
|
|
|
// FIFO is full. Drop this block.
|
|
|
|
dropping = 1;
|
|
|
|
outbuf->dropped += slen;
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
|
|
|
return;
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
}
|
2015-01-23 02:22:22 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
dropping = 0;
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
|
|
|
|
|
|
|
// Compute the sample timestamp and system timestamp for the start of the block
|
2015-06-15 23:14:37 +02:00
|
|
|
outbuf->sampleTimestamp = lastbuf->sampleTimestamp + 12e6 * (lastbuf->length + outbuf->dropped) / Modes.sample_rate;
|
|
|
|
block_duration = 1e9 * slen / Modes.sample_rate;
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
// Get the approx system time for the start of this block
|
|
|
|
clock_gettime(CLOCK_REALTIME, &outbuf->sysTimestamp);
|
|
|
|
outbuf->sysTimestamp.tv_nsec -= block_duration;
|
|
|
|
normalize_timespec(&outbuf->sysTimestamp);
|
|
|
|
|
|
|
|
// Copy trailing data from last block (or reset if not valid)
|
|
|
|
if (outbuf->dropped == 0 && lastbuf->length >= Modes.trailing_samples) {
|
|
|
|
memcpy(outbuf->data, lastbuf->data + lastbuf->length - Modes.trailing_samples, Modes.trailing_samples * sizeof(uint16_t));
|
|
|
|
} else {
|
2015-06-15 23:14:37 +02:00
|
|
|
memset(outbuf->data, 0, Modes.trailing_samples * sizeof(uint16_t));
|
2015-04-09 19:51:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Convert the new data
|
|
|
|
outbuf->length = slen;
|
2015-06-15 23:14:37 +02:00
|
|
|
convert_samples(buf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->total_power);
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
// Push the new data to the demodulation thread
|
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
|
|
|
|
|
|
|
Modes.mag_buffers[next_free_buffer].dropped = 0;
|
|
|
|
Modes.mag_buffers[next_free_buffer].length = 0; // just in case
|
|
|
|
Modes.first_free_buffer = next_free_buffer;
|
|
|
|
|
2015-01-23 02:22:22 +01:00
|
|
|
// accumulate CPU while holding the mutex, and restart measurement
|
|
|
|
end_cpu_timing(&reader_thread_start, &Modes.reader_cpu_accumulator);
|
|
|
|
start_cpu_timing(&reader_thread_start);
|
2015-04-09 19:51:31 +02:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
pthread_cond_signal(&Modes.data_cond);
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
2013-01-12 11:46:32 +01:00
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
|
|
|
// This is used when --ifile is specified in order to read data from file
|
|
|
|
// instead of using an RTLSDR device
|
|
|
|
//
|
|
|
|
void readDataFromFile(void) {
|
2015-04-09 19:51:31 +02:00
|
|
|
int eof = 0;
|
|
|
|
struct timespec next_buffer_delivery;
|
2015-05-29 19:13:47 +02:00
|
|
|
void *readbuf;
|
|
|
|
int bytes_per_sample = 0;
|
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
switch (Modes.input_format) {
|
2015-05-29 19:13:47 +02:00
|
|
|
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);
|
|
|
|
}
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &next_buffer_delivery);
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
2015-04-09 19:51:31 +02:00
|
|
|
while (!Modes.exit && !eof) {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
ssize_t nread, toread;
|
2015-04-09 19:51:31 +02:00
|
|
|
void *r;
|
|
|
|
struct mag_buf *outbuf, *lastbuf;
|
|
|
|
unsigned next_free_buffer;
|
|
|
|
unsigned slen;
|
|
|
|
|
|
|
|
next_free_buffer = (Modes.first_free_buffer + 1) % MODES_MAG_BUFFERS;
|
|
|
|
if (next_free_buffer == Modes.first_filled_buffer) {
|
|
|
|
// no space for output yet
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
pthread_cond_wait(&Modes.data_cond, &Modes.data_mutex);
|
2013-05-24 23:29:00 +02:00
|
|
|
continue;
|
|
|
|
}
|
2013-01-13 01:39:29 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
outbuf = &Modes.mag_buffers[Modes.first_free_buffer];
|
|
|
|
lastbuf = &Modes.mag_buffers[(Modes.first_free_buffer + MODES_MAG_BUFFERS - 1) % MODES_MAG_BUFFERS];
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
|
|
|
|
|
|
|
// Compute the sample timestamp and system timestamp for the start of the block
|
2015-06-15 23:14:37 +02:00
|
|
|
outbuf->sampleTimestamp = lastbuf->sampleTimestamp + 12e6 * lastbuf->length / Modes.sample_rate;
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
// Copy trailing data from last block (or reset if not valid)
|
|
|
|
if (lastbuf->length >= Modes.trailing_samples) {
|
|
|
|
memcpy(outbuf->data, lastbuf->data + lastbuf->length - Modes.trailing_samples, Modes.trailing_samples * sizeof(uint16_t));
|
|
|
|
} else {
|
2015-05-29 19:13:47 +02:00
|
|
|
memset(outbuf->data, 0, Modes.trailing_samples * sizeof(uint16_t));
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
}
|
2013-01-13 01:39:29 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// Get the system time for the start of this block
|
|
|
|
clock_gettime(CLOCK_REALTIME, &outbuf->sysTimestamp);
|
|
|
|
|
2015-05-29 19:13:47 +02:00
|
|
|
toread = MODES_MAG_BUF_SAMPLES * bytes_per_sample;
|
|
|
|
r = readbuf;
|
|
|
|
while (toread) {
|
2015-04-09 19:51:31 +02:00
|
|
|
nread = read(Modes.fd, r, toread);
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
if (nread <= 0) {
|
2015-01-02 23:34:35 +01:00
|
|
|
// Done.
|
2015-04-09 19:51:31 +02:00
|
|
|
eof = 1;
|
|
|
|
break;
|
2013-01-15 00:35:21 +01:00
|
|
|
}
|
2015-04-09 19:51:31 +02:00
|
|
|
r += nread;
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
toread -= nread;
|
2013-05-09 16:59:26 +02:00
|
|
|
}
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-05-29 19:13:47 +02:00
|
|
|
slen = outbuf->length = MODES_MAG_BUF_SAMPLES - toread/bytes_per_sample;
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
// Convert the new data
|
2015-06-15 23:14:37 +02:00
|
|
|
convert_samples(readbuf, &outbuf->data[Modes.trailing_samples], slen, &outbuf->total_power);
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-06-18 12:24:01 +02:00
|
|
|
if (Modes.throttle) {
|
2015-04-09 19:51:31 +02:00
|
|
|
// Wait until we are allowed to release this buffer to the main thread
|
|
|
|
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_buffer_delivery, NULL) == EINTR)
|
|
|
|
;
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// compute the time we can deliver the next buffer.
|
2015-06-15 23:14:37 +02:00
|
|
|
next_buffer_delivery.tv_nsec += outbuf->length * 1e9 / Modes.sample_rate;
|
2015-04-09 19:51:31 +02:00
|
|
|
normalize_timespec(&next_buffer_delivery);
|
|
|
|
}
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// Push the new data to the main thread
|
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
|
|
|
Modes.first_free_buffer = next_free_buffer;
|
2015-01-23 02:22:22 +01:00
|
|
|
// accumulate CPU while holding the mutex, and restart measurement
|
|
|
|
end_cpu_timing(&reader_thread_start, &Modes.reader_cpu_accumulator);
|
|
|
|
start_cpu_timing(&reader_thread_start);
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
pthread_cond_signal(&Modes.data_cond);
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
2015-01-02 23:34:35 +01:00
|
|
|
|
2015-05-29 19:13:47 +02:00
|
|
|
free(readbuf);
|
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// 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);
|
|
|
|
|
2015-01-02 23:34:35 +01:00
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
}
|
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
|
|
|
// We read data using a thread, so the main thread only handles decoding
|
|
|
|
// without caring about data acquisition
|
|
|
|
//
|
2015-01-02 23:29:29 +01:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
void *readerThreadEntryPoint(void *arg) {
|
|
|
|
MODES_NOTUSED(arg);
|
2013-01-13 01:39:29 +01:00
|
|
|
|
2015-01-23 02:22:22 +01:00
|
|
|
start_cpu_timing(&reader_thread_start); // we accumulate in rtlsdrCallback() or readDataFromFile()
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
if (Modes.filename == NULL) {
|
2015-01-02 23:29:29 +01:00
|
|
|
while (!Modes.exit) {
|
|
|
|
rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL,
|
2015-04-09 19:51:31 +02:00
|
|
|
MODES_RTL_BUFFERS,
|
|
|
|
MODES_RTL_BUF_SIZE);
|
2015-01-02 23:29:29 +01:00
|
|
|
|
|
|
|
if (!Modes.exit) {
|
2015-02-17 22:40:26 +01:00
|
|
|
log_with_timestamp("Warning: lost the connection to the RTLSDR device.");
|
2015-01-02 23:29:29 +01:00
|
|
|
rtlsdr_close(Modes.dev);
|
2015-01-23 02:20:22 +01:00
|
|
|
Modes.dev = NULL;
|
2015-01-02 23:29:29 +01:00
|
|
|
|
|
|
|
do {
|
|
|
|
sleep(5);
|
2015-02-17 22:40:26 +01:00
|
|
|
log_with_timestamp("Trying to reconnect to the RTLSDR device..");
|
2015-01-02 23:29:29 +01:00
|
|
|
} while (!Modes.exit && modesInitRTLSDR() < 0);
|
|
|
|
}
|
|
|
|
}
|
2015-01-23 02:20:22 +01:00
|
|
|
|
|
|
|
if (Modes.dev != NULL) {
|
|
|
|
rtlsdr_close(Modes.dev);
|
|
|
|
Modes.dev = NULL;
|
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
} else {
|
|
|
|
readDataFromFile();
|
2013-01-15 00:35:21 +01:00
|
|
|
}
|
2015-01-02 23:29:29 +01:00
|
|
|
|
|
|
|
// Wake the main thread (if it's still waiting)
|
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
2015-01-02 23:34:35 +01:00
|
|
|
Modes.exit = 1; // just in case
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
pthread_cond_signal(&Modes.data_cond);
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
2015-01-02 23:29:29 +01:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
#ifndef _WIN32
|
|
|
|
pthread_exit(NULL);
|
|
|
|
#else
|
|
|
|
return NULL;
|
|
|
|
#endif
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// ============================== Snip mode =================================
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// Get raw IQ samples and filter everything is < than the specified level
|
|
|
|
// for more than 256 samples in order to reduce example file size
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
void snipMode(int level) {
|
|
|
|
int i, q;
|
|
|
|
uint64_t c = 0;
|
2013-05-24 23:29:00 +02:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
while ((i = getchar()) != EOF && (q = getchar()) != EOF) {
|
|
|
|
if (abs(i-127) < level && abs(q-127) < level) {
|
|
|
|
c++;
|
|
|
|
if (c > MODES_PREAMBLE_SIZE) continue;
|
2013-05-24 23:29:00 +02:00
|
|
|
} else {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
c = 0;
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
putchar(i);
|
|
|
|
putchar(q);
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
|
|
|
}
|
2013-05-24 23:29:00 +02:00
|
|
|
//
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// ================================ Main ====================================
|
|
|
|
//
|
2013-01-05 13:52:25 +01:00
|
|
|
void showHelp(void) {
|
|
|
|
printf(
|
2013-04-14 23:03:19 +02:00
|
|
|
"-----------------------------------------------------------------------------\n"
|
2014-12-10 13:44:00 +01:00
|
|
|
"| dump1090 ModeS Receiver %45s |\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"-----------------------------------------------------------------------------\n"
|
|
|
|
"--device-index <index> Select RTL device (default: 0)\n"
|
2014-06-01 02:14:40 +02:00
|
|
|
"--gain <db> Set gain (default: max gain. Use -10 for auto-gain)\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--enable-agc Enable the Automatic Gain Control (default: off)\n"
|
|
|
|
"--freq <hz> Set frequency (default: 1090 Mhz)\n"
|
|
|
|
"--ifile <filename> Read data from file (use '-' for stdin)\n"
|
2015-06-15 23:14:37 +02:00
|
|
|
"--iformat <format> Sample format for --ifile: UC8 (default), SC16, or SC16Q11\n"
|
2015-06-18 12:24:01 +02:00
|
|
|
"--throttle When reading from a file, play back in realtime, not at max speed\n"
|
|
|
|
"--interactive Interactive mode refreshing data on screen. Implies --throttle\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--interactive-rows <num> Max number of rows in interactive mode (default: 15)\n"
|
|
|
|
"--interactive-ttl <sec> Remove from list if idle for <sec> (default: 60)\n"
|
|
|
|
"--interactive-rtl1090 Display flight table in RTL1090 format\n"
|
|
|
|
"--raw Show only messages hex values\n"
|
|
|
|
"--net Enable networking\n"
|
2013-04-23 00:31:59 +02:00
|
|
|
"--modeac Enable decoding of SSR Modes 3/A & 3/C\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--net-only Enable just networking, no RTL device or file used\n"
|
2014-10-30 13:06:03 +01:00
|
|
|
"--net-bind-address <ip> IP address to bind to (default: Any; Use 127.0.0.1 for private)\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--net-http-port <port> HTTP server port (default: 8080)\n"
|
2013-05-24 23:29:00 +02:00
|
|
|
"--net-ri-port <port> TCP raw input listen port (default: 30001)\n"
|
|
|
|
"--net-ro-port <port> TCP raw output listen port (default: 30002)\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--net-sbs-port <port> TCP BaseStation output listen port (default: 30003)\n"
|
2013-05-24 23:29:00 +02:00
|
|
|
"--net-bi-port <port> TCP Beast input listen port (default: 30004)\n"
|
|
|
|
"--net-bo-port <port> TCP Beast output listen port (default: 30005)\n"
|
2014-12-08 20:56:45 +01:00
|
|
|
"--net-fatsv-port <port> FlightAware TSV output port (default: 10001)\n"
|
2014-10-03 23:55:21 +02:00
|
|
|
"--net-ro-size <size> TCP output minimum size (default: 0)\n"
|
|
|
|
"--net-ro-interval <rate> TCP output memory flush rate in seconds (default: 0)\n"
|
2014-06-25 05:58:46 +02:00
|
|
|
"--net-heartbeat <rate> TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
|
2014-05-27 14:16:57 +02:00
|
|
|
"--net-buffer <n> TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
|
2015-01-22 20:56:38 +01:00
|
|
|
"--net-verbatim Do not apply CRC corrections to messages we forward; send unchanged\n"
|
2015-07-03 22:56:23 +02:00
|
|
|
"--forward-mlat Allow forwarding of received mlat results to output ports\n"
|
2013-10-10 00:44:58 +02:00
|
|
|
"--lat <latitude> Reference/receiver latitude for surface posn (opt)\n"
|
2013-05-09 12:29:18 +02:00
|
|
|
"--lon <longitude> Reference/receiver longitude for surface posn (opt)\n"
|
2015-01-13 21:03:34 +01:00
|
|
|
"--max-range <distance> Absolute maximum range for position decoding (in nm, default: 300)\n"
|
2013-04-26 11:12:47 +02:00
|
|
|
"--fix Enable single-bits error correction using CRC\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--no-fix Disable single-bits error correction using CRC\n"
|
|
|
|
"--no-crc-check Disable messages with broken CRC (discouraged)\n"
|
2013-05-22 14:23:54 +02:00
|
|
|
"--phase-enhance Enable phase enhancement\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--aggressive More CPU for more messages (two bits fixes, ...)\n"
|
|
|
|
"--mlat display raw messages in Beast ascii mode\n"
|
|
|
|
"--stats With --ifile print stats at exit. No other output\n"
|
2015-06-19 18:29:14 +02:00
|
|
|
"--stats-range Collect/show range histogram\n"
|
2014-09-25 21:33:50 +02:00
|
|
|
"--stats-every <seconds> Show and reset stats every <seconds> seconds\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--onlyaddr Show only ICAO addresses (testing purposes)\n"
|
|
|
|
"--metric Use metric units (meters, km/h, ...)\n"
|
|
|
|
"--snip <level> Strip IQ file removing samples < level\n"
|
|
|
|
"--debug <flags> Debug mode (verbose), see README for details\n"
|
|
|
|
"--quiet Disable output to stdout. Use for daemon applications\n"
|
2015-02-23 00:01:54 +01:00
|
|
|
"--show-only <addr> Show only messages from the given ICAO on stdout\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--ppm <error> Set receiver error in parts per million (default 0)\n"
|
2015-09-14 21:05:27 +02:00
|
|
|
"--html-dir <dir> Use <dir> as base directory for the internal HTTP server. Defaults to " HTMLPATH "\n"
|
2014-11-23 17:02:11 +01:00
|
|
|
"--write-json <dir> Periodically write json output to <dir> (for serving by a separate webserver)\n"
|
|
|
|
"--write-json-every <t> Write json output every t seconds (default 1)\n"
|
2014-12-27 21:52:56 +01:00
|
|
|
"--json-location-accuracy <n> Accuracy of receiver location in json metadata: 0=no location, 1=approximate, 2=exact\n"
|
2015-06-15 23:14:37 +02:00
|
|
|
"--oversample Use the 2.4MHz demodulator\n"
|
|
|
|
"--dcfilter Apply a 1Hz DC filter to input data (requires lots more CPU)\n"
|
|
|
|
"--measure-noise Measure noise power (requires slightly more CPU)\n"
|
2013-04-14 23:03:19 +02:00
|
|
|
"--help Show this help\n"
|
2013-01-26 01:07:43 +01:00
|
|
|
"\n"
|
|
|
|
"Debug mode flags: d = Log frames decoded with errors\n"
|
|
|
|
" D = Log frames decoded with zero errors\n"
|
|
|
|
" c = Log frames with bad CRC\n"
|
|
|
|
" C = Log frames with good CRC\n"
|
|
|
|
" p = Log frames with bad preamble\n"
|
|
|
|
" n = Log network debugging info\n"
|
2014-12-10 13:25:43 +01:00
|
|
|
" j = Log frames to frames.js, loadable by debug.html\n",
|
2014-12-10 13:44:00 +01:00
|
|
|
MODES_DUMP1090_VARIANT " " MODES_DUMP1090_VERSION
|
2013-01-05 13:52:25 +01:00
|
|
|
);
|
|
|
|
}
|
2014-04-25 15:48:14 +02:00
|
|
|
|
2015-01-20 18:16:35 +01:00
|
|
|
static void display_total_stats(void)
|
|
|
|
{
|
|
|
|
struct stats added;
|
|
|
|
add_stats(&Modes.stats_alltime, &Modes.stats_current, &added);
|
|
|
|
display_stats(&added);
|
2014-09-25 21:33:50 +02:00
|
|
|
}
|
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
|
|
|
// This function is called a few times every second by main in order to
|
|
|
|
// perform tasks we need to do continuously, like accepting new clients
|
|
|
|
// from the net, refreshing the screen in interactive mode, and so forth
|
|
|
|
//
|
2013-01-13 01:39:29 +01:00
|
|
|
void backgroundTasks(void) {
|
2015-02-10 23:24:22 +01:00
|
|
|
static uint64_t next_stats_display;
|
|
|
|
static uint64_t next_stats_update;
|
|
|
|
static uint64_t next_json, next_history;
|
2015-01-15 21:55:55 +01:00
|
|
|
|
2015-02-10 23:24:22 +01:00
|
|
|
uint64_t now = mstime();
|
2014-09-25 21:33:50 +02:00
|
|
|
|
2015-01-21 00:53:26 +01:00
|
|
|
icaoFilterExpire();
|
2015-02-08 15:27:03 +01:00
|
|
|
trackPeriodicUpdate();
|
2015-01-21 00:53:26 +01:00
|
|
|
|
2013-01-13 01:39:29 +01:00
|
|
|
if (Modes.net) {
|
2014-10-03 23:55:21 +02:00
|
|
|
modesNetPeriodicWork();
|
2013-04-25 00:47:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Refresh screen when in interactive mode
|
2013-08-19 16:55:17 +02:00
|
|
|
if (Modes.interactive) {
|
2013-04-25 00:47:08 +02:00
|
|
|
interactiveShowData();
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
2014-09-25 21:33:50 +02:00
|
|
|
|
2015-01-20 18:16:35 +01:00
|
|
|
// always update end time so it is current when requests arrive
|
|
|
|
Modes.stats_current.end = now;
|
|
|
|
|
|
|
|
if (now >= next_stats_update) {
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (next_stats_update == 0) {
|
2015-02-10 23:24:22 +01:00
|
|
|
next_stats_update = now + 60000;
|
2015-01-20 18:16:35 +01:00
|
|
|
} else {
|
|
|
|
Modes.stats_latest_1min = (Modes.stats_latest_1min + 1) % 15;
|
|
|
|
Modes.stats_1min[Modes.stats_latest_1min] = Modes.stats_current;
|
|
|
|
|
|
|
|
add_stats(&Modes.stats_current, &Modes.stats_alltime, &Modes.stats_alltime);
|
|
|
|
add_stats(&Modes.stats_current, &Modes.stats_periodic, &Modes.stats_periodic);
|
|
|
|
|
|
|
|
reset_stats(&Modes.stats_5min);
|
|
|
|
for (i = 0; i < 5; ++i)
|
|
|
|
add_stats(&Modes.stats_1min[(Modes.stats_latest_1min - i + 15) % 15], &Modes.stats_5min, &Modes.stats_5min);
|
|
|
|
|
|
|
|
reset_stats(&Modes.stats_15min);
|
|
|
|
for (i = 0; i < 15; ++i)
|
|
|
|
add_stats(&Modes.stats_1min[i], &Modes.stats_15min, &Modes.stats_15min);
|
|
|
|
|
|
|
|
reset_stats(&Modes.stats_current);
|
|
|
|
Modes.stats_current.start = Modes.stats_current.end = now;
|
|
|
|
|
|
|
|
if (Modes.json_dir)
|
|
|
|
writeJsonToFile("stats.json", generateStatsJson);
|
|
|
|
|
2015-02-10 23:24:22 +01:00
|
|
|
next_stats_update += 60000;
|
2015-01-20 18:16:35 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 23:24:22 +01:00
|
|
|
if (Modes.stats && now >= next_stats_display) {
|
2015-01-20 18:16:35 +01:00
|
|
|
if (next_stats_display == 0) {
|
|
|
|
next_stats_display = now + Modes.stats;
|
|
|
|
} else {
|
|
|
|
add_stats(&Modes.stats_periodic, &Modes.stats_current, &Modes.stats_periodic);
|
|
|
|
display_stats(&Modes.stats_periodic);
|
|
|
|
reset_stats(&Modes.stats_periodic);
|
|
|
|
|
|
|
|
next_stats_display += Modes.stats;
|
2015-12-19 19:28:12 +01:00
|
|
|
if (next_stats_display <= now) {
|
|
|
|
/* something has gone wrong, perhaps the system clock jumped */
|
|
|
|
next_stats_display = now + Modes.stats;
|
|
|
|
}
|
2014-09-25 21:33:50 +02:00
|
|
|
}
|
|
|
|
}
|
2014-11-23 17:02:11 +01:00
|
|
|
|
2015-01-20 18:16:35 +01:00
|
|
|
if (Modes.json_dir && now >= next_json) {
|
2015-01-15 21:54:22 +01:00
|
|
|
writeJsonToFile("aircraft.json", generateAircraftJson);
|
|
|
|
next_json = now + Modes.json_interval;
|
2014-11-23 17:02:11 +01:00
|
|
|
}
|
2015-01-15 21:55:55 +01:00
|
|
|
|
|
|
|
if ((Modes.json_dir || Modes.net_http_port) && now >= next_history) {
|
2015-01-15 23:23:53 +01:00
|
|
|
int rewrite_receiver_json = (Modes.json_aircraft_history[HISTORY_SIZE-1].content == NULL);
|
2015-01-15 21:55:55 +01:00
|
|
|
|
|
|
|
free(Modes.json_aircraft_history[Modes.json_aircraft_history_next].content); // might be NULL, that's OK.
|
|
|
|
Modes.json_aircraft_history[Modes.json_aircraft_history_next].content =
|
|
|
|
generateAircraftJson("/data/aircraft.json", &Modes.json_aircraft_history[Modes.json_aircraft_history_next].clen);
|
|
|
|
|
2015-01-20 18:16:35 +01:00
|
|
|
if (Modes.json_dir) {
|
|
|
|
char filebuf[PATH_MAX];
|
|
|
|
snprintf(filebuf, PATH_MAX, "history_%d.json", Modes.json_aircraft_history_next);
|
|
|
|
writeJsonToFile(filebuf, generateHistoryJson);
|
|
|
|
}
|
2015-01-15 21:55:55 +01:00
|
|
|
|
|
|
|
Modes.json_aircraft_history_next = (Modes.json_aircraft_history_next+1) % HISTORY_SIZE;
|
2015-01-15 23:23:53 +01:00
|
|
|
|
|
|
|
if (rewrite_receiver_json)
|
|
|
|
writeJsonToFile("receiver.json", generateReceiverJson); // number of history entries changed
|
|
|
|
|
2015-01-15 21:55:55 +01:00
|
|
|
next_history = now + HISTORY_INTERVAL;
|
|
|
|
}
|
2013-01-13 01:39:29 +01:00
|
|
|
}
|
2014-12-10 18:05:22 +01:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
2014-07-09 00:34:43 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|
2013-01-05 13:52:25 +01:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
int j;
|
|
|
|
|
2013-04-29 23:14:06 +02:00
|
|
|
// Set sane defaults
|
2013-01-05 13:52:25 +01:00
|
|
|
modesInitConfig();
|
2015-02-17 22:41:40 +01:00
|
|
|
|
|
|
|
// signal handlers:
|
|
|
|
signal(SIGINT, sigintHandler);
|
|
|
|
signal(SIGTERM, sigtermHandler);
|
2013-01-05 13:52:25 +01:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// Parse the command line options
|
2013-01-05 13:52:25 +01:00
|
|
|
for (j = 1; j < argc; j++) {
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
int more = j+1 < argc; // There are more arguments
|
2013-01-05 13:52:25 +01:00
|
|
|
|
|
|
|
if (!strcmp(argv[j],"--device-index") && more) {
|
2015-01-02 23:29:29 +01:00
|
|
|
Modes.dev_name = strdup(argv[++j]);
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--gain") && more) {
|
2014-09-24 21:01:06 +02:00
|
|
|
Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--enable-agc")) {
|
|
|
|
Modes.enable_agc++;
|
|
|
|
} else if (!strcmp(argv[j],"--freq") && more) {
|
2013-04-10 00:56:20 +02:00
|
|
|
Modes.freq = (int) strtoll(argv[++j],NULL,10);
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--ifile") && more) {
|
|
|
|
Modes.filename = strdup(argv[++j]);
|
2015-05-29 19:13:47 +02:00
|
|
|
} else if (!strcmp(argv[j],"--iformat") && more) {
|
|
|
|
++j;
|
|
|
|
if (!strcasecmp(argv[j], "uc8")) {
|
2015-06-15 23:14:37 +02:00
|
|
|
Modes.input_format = INPUT_UC8;
|
2015-05-29 19:13:47 +02:00
|
|
|
} else if (!strcasecmp(argv[j], "sc16")) {
|
2015-06-15 23:14:37 +02:00
|
|
|
Modes.input_format = INPUT_SC16;
|
2015-05-29 19:13:47 +02:00
|
|
|
} else if (!strcasecmp(argv[j], "sc16q11")) {
|
2015-06-15 23:14:37 +02:00
|
|
|
Modes.input_format = INPUT_SC16Q11;
|
2015-05-29 19:13:47 +02:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "Input format '%s' not understood (supported values: UC8, SC16, SC16Q11)\n",
|
|
|
|
argv[j]);
|
|
|
|
exit(1);
|
|
|
|
}
|
2015-06-15 23:14:37 +02:00
|
|
|
} else if (!strcmp(argv[j],"--dcfilter")) {
|
|
|
|
Modes.dc_filter = 1;
|
|
|
|
} else if (!strcmp(argv[j],"--measure-noise")) {
|
|
|
|
Modes.measure_noise = 1;
|
2013-04-26 11:12:47 +02:00
|
|
|
} else if (!strcmp(argv[j],"--fix")) {
|
2013-05-24 22:51:44 +02:00
|
|
|
Modes.nfix_crc = 1;
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--no-fix")) {
|
2013-05-24 22:51:44 +02:00
|
|
|
Modes.nfix_crc = 0;
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--no-crc-check")) {
|
|
|
|
Modes.check_crc = 0;
|
2013-05-22 14:23:54 +02:00
|
|
|
} else if (!strcmp(argv[j],"--phase-enhance")) {
|
|
|
|
Modes.phase_enhance = 1;
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--raw")) {
|
|
|
|
Modes.raw = 1;
|
2013-01-10 20:58:13 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net")) {
|
|
|
|
Modes.net = 1;
|
2013-04-23 00:31:59 +02:00
|
|
|
} else if (!strcmp(argv[j],"--modeac")) {
|
|
|
|
Modes.mode_ac = 1;
|
2013-04-07 17:22:02 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-beast")) {
|
|
|
|
Modes.beast = 1;
|
2013-01-13 01:39:29 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-only")) {
|
|
|
|
Modes.net = 1;
|
|
|
|
Modes.net_only = 1;
|
2014-03-11 02:09:49 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-heartbeat") && more) {
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.net_heartbeat_interval = (uint64_t)(1000 * atof(argv[++j]));
|
2014-03-11 02:09:49 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-ro-size") && more) {
|
2014-10-03 23:55:21 +02:00
|
|
|
Modes.net_output_flush_size = atoi(argv[++j]);
|
2013-04-16 00:17:08 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-ro-rate") && more) {
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.net_output_flush_interval = 1000 * atoi(argv[++j]) / 15; // backwards compatibility
|
2014-10-03 23:55:21 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-ro-interval") && more) {
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.net_output_flush_interval = (uint64_t)(1000 * atof(argv[++j]));
|
2013-01-10 20:58:13 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-ro-port") && more) {
|
2013-05-24 23:29:00 +02:00
|
|
|
if (Modes.beast) // Required for legacy backward compatibility
|
2013-05-25 00:32:12 +02:00
|
|
|
{Modes.net_output_beast_port = atoi(argv[++j]);;}
|
|
|
|
else
|
|
|
|
{Modes.net_output_raw_port = atoi(argv[++j]);}
|
2013-01-12 11:46:32 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-ri-port") && more) {
|
|
|
|
Modes.net_input_raw_port = atoi(argv[++j]);
|
2013-05-24 23:29:00 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-bo-port") && more) {
|
|
|
|
Modes.net_output_beast_port = atoi(argv[++j]);
|
|
|
|
} else if (!strcmp(argv[j],"--net-bi-port") && more) {
|
|
|
|
Modes.net_input_beast_port = atoi(argv[++j]);
|
2014-10-25 21:33:45 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-bind-address") && more) {
|
2014-10-30 13:06:03 +01:00
|
|
|
Modes.net_bind_address = strdup(argv[++j]);
|
2013-01-13 01:39:29 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-http-port") && more) {
|
|
|
|
Modes.net_http_port = atoi(argv[++j]);
|
2014-12-08 20:56:45 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-fatsv-port") && more) {
|
|
|
|
Modes.net_fatsv_port = atoi(argv[++j]);
|
2013-01-17 19:12:23 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-sbs-port") && more) {
|
|
|
|
Modes.net_output_sbs_port = atoi(argv[++j]);
|
2014-05-27 14:16:57 +02:00
|
|
|
} else if (!strcmp(argv[j],"--net-buffer") && more) {
|
|
|
|
Modes.net_sndbuf_size = atoi(argv[++j]);
|
2015-01-22 20:56:38 +01:00
|
|
|
} else if (!strcmp(argv[j],"--net-verbatim")) {
|
|
|
|
Modes.net_verbatim = 1;
|
2015-07-03 22:56:23 +02:00
|
|
|
} else if (!strcmp(argv[j],"--forward-mlat")) {
|
|
|
|
Modes.forward_mlat = 1;
|
2013-01-06 17:09:31 +01:00
|
|
|
} else if (!strcmp(argv[j],"--onlyaddr")) {
|
|
|
|
Modes.onlyaddr = 1;
|
2013-01-08 19:46:50 +01:00
|
|
|
} else if (!strcmp(argv[j],"--metric")) {
|
|
|
|
Modes.metric = 1;
|
2013-01-15 01:41:10 +01:00
|
|
|
} else if (!strcmp(argv[j],"--aggressive")) {
|
2013-05-24 22:51:44 +02:00
|
|
|
Modes.nfix_crc = MODES_MAX_BITERRORS;
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--interactive")) {
|
2015-06-18 12:24:01 +02:00
|
|
|
Modes.interactive = Modes.throttle = 1;
|
|
|
|
} else if (!strcmp(argv[j],"--throttle")) {
|
|
|
|
Modes.throttle = 1;
|
2013-05-09 12:29:18 +02:00
|
|
|
} else if (!strcmp(argv[j],"--interactive-rows") && more) {
|
2013-01-05 21:41:09 +01:00
|
|
|
Modes.interactive_rows = atoi(argv[++j]);
|
2013-05-09 12:29:18 +02:00
|
|
|
} else if (!strcmp(argv[j],"--interactive-ttl") && more) {
|
2015-02-10 22:49:37 +01:00
|
|
|
Modes.interactive_display_ttl = (uint64_t)(1000 * atof(argv[++j]));
|
2013-05-09 12:29:18 +02:00
|
|
|
} else if (!strcmp(argv[j],"--lat") && more) {
|
|
|
|
Modes.fUserLat = atof(argv[++j]);
|
|
|
|
} else if (!strcmp(argv[j],"--lon") && more) {
|
|
|
|
Modes.fUserLon = atof(argv[++j]);
|
2015-01-13 21:03:34 +01:00
|
|
|
} else if (!strcmp(argv[j],"--max-range") && more) {
|
|
|
|
Modes.maxRange = atof(argv[++j]) * 1852.0; // convert to metres
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--debug") && more) {
|
2013-01-26 01:07:43 +01:00
|
|
|
char *f = argv[++j];
|
|
|
|
while(*f) {
|
|
|
|
switch(*f) {
|
|
|
|
case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break;
|
|
|
|
case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break;
|
|
|
|
case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break;
|
|
|
|
case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break;
|
|
|
|
case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break;
|
|
|
|
case 'n': Modes.debug |= MODES_DEBUG_NET; break;
|
|
|
|
case 'j': Modes.debug |= MODES_DEBUG_JS; break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "Unknown debugging flag: %c\n", *f);
|
|
|
|
exit(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
f++;
|
|
|
|
}
|
2013-01-06 15:13:40 +01:00
|
|
|
} else if (!strcmp(argv[j],"--stats")) {
|
2015-02-10 23:24:22 +01:00
|
|
|
if (!Modes.stats)
|
|
|
|
Modes.stats = (uint64_t)1 << 60; // "never"
|
2015-06-19 18:29:14 +02:00
|
|
|
} else if (!strcmp(argv[j],"--stats-range")) {
|
|
|
|
Modes.stats_range_histo = 1;
|
2014-09-25 21:33:50 +02:00
|
|
|
} else if (!strcmp(argv[j],"--stats-every") && more) {
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.stats = (uint64_t) (1000 * atof(argv[++j]));
|
2013-01-05 13:52:25 +01:00
|
|
|
} else if (!strcmp(argv[j],"--snip") && more) {
|
|
|
|
snipMode(atoi(argv[++j]));
|
|
|
|
exit(0);
|
|
|
|
} else if (!strcmp(argv[j],"--help")) {
|
|
|
|
showHelp();
|
|
|
|
exit(0);
|
2013-04-08 17:42:27 +02:00
|
|
|
} else if (!strcmp(argv[j],"--ppm") && more) {
|
2013-04-09 01:58:32 +02:00
|
|
|
Modes.ppm_error = atoi(argv[++j]);
|
|
|
|
} else if (!strcmp(argv[j],"--quiet")) {
|
|
|
|
Modes.quiet = 1;
|
2015-02-23 00:01:54 +01:00
|
|
|
} else if (!strcmp(argv[j],"--show-only") && more) {
|
|
|
|
Modes.show_only = (uint32_t) strtoul(argv[++j], NULL, 16);
|
2013-04-12 12:15:52 +02:00
|
|
|
} else if (!strcmp(argv[j],"--mlat")) {
|
2013-04-13 02:37:02 +02:00
|
|
|
Modes.mlat = 1;
|
2013-04-12 12:30:18 +02:00
|
|
|
} else if (!strcmp(argv[j],"--interactive-rtl1090")) {
|
2013-04-13 02:37:02 +02:00
|
|
|
Modes.interactive = 1;
|
|
|
|
Modes.interactive_rtl1090 = 1;
|
2014-09-26 23:42:38 +02:00
|
|
|
} else if (!strcmp(argv[j],"--oversample")) {
|
|
|
|
Modes.oversample = 1;
|
2015-09-14 19:58:59 +02:00
|
|
|
} else if (!strcmp(argv[j], "--html-dir") && more) {
|
|
|
|
Modes.html_dir = strdup(argv[++j]);
|
2014-11-23 17:02:11 +01:00
|
|
|
#ifndef _WIN32
|
|
|
|
} else if (!strcmp(argv[j], "--write-json") && more) {
|
2015-01-15 21:54:22 +01:00
|
|
|
Modes.json_dir = strdup(argv[++j]);
|
2014-11-23 17:02:11 +01:00
|
|
|
} else if (!strcmp(argv[j], "--write-json-every") && more) {
|
2015-02-10 23:24:22 +01:00
|
|
|
Modes.json_interval = (uint64_t)(1000 * atof(argv[++j]));
|
|
|
|
if (Modes.json_interval < 100) // 0.1s
|
|
|
|
Modes.json_interval = 100;
|
2014-12-27 21:52:56 +01:00
|
|
|
} else if (!strcmp(argv[j], "--json-location-accuracy") && more) {
|
|
|
|
Modes.json_location_accuracy = atoi(argv[++j]);
|
2014-11-23 17:02:11 +01:00
|
|
|
#endif
|
2013-04-09 01:58:32 +02:00
|
|
|
} else {
|
2013-01-05 13:52:25 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
"Unknown or not enough arguments for option '%s'.\n\n",
|
|
|
|
argv[j]);
|
|
|
|
showHelp();
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 15:48:14 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
// Try to comply with the Copyright license conditions for binary distribution
|
|
|
|
if (!Modes.quiet) {showCopyright();}
|
|
|
|
#endif
|
|
|
|
|
2014-02-22 23:11:11 +01:00
|
|
|
#ifndef _WIN32
|
|
|
|
// Setup for SIGWINCH for handling lines
|
|
|
|
if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);}
|
|
|
|
#endif
|
|
|
|
|
2014-12-27 22:25:32 +01:00
|
|
|
if (Modes.mode_ac && Modes.oversample) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"Warning: --modeac is currently ignored when --oversample is used;\n"
|
|
|
|
" no ModeA/C messages will be decoded.\n");
|
|
|
|
}
|
|
|
|
|
2013-04-29 23:14:06 +02:00
|
|
|
// Initialization
|
2015-02-17 22:43:17 +01:00
|
|
|
log_with_timestamp("%s %s starting up.", MODES_DUMP1090_VARIANT, MODES_DUMP1090_VERSION);
|
2013-01-05 13:52:25 +01:00
|
|
|
modesInit();
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
|
2013-01-13 01:39:29 +01:00
|
|
|
if (Modes.net_only) {
|
|
|
|
fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
|
|
|
|
} else if (Modes.filename == NULL) {
|
2015-01-02 23:29:29 +01:00
|
|
|
if (modesInitRTLSDR() < 0) {
|
|
|
|
exit(1);
|
|
|
|
}
|
2013-01-05 13:52:25 +01:00
|
|
|
} else {
|
|
|
|
if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
|
|
|
|
Modes.fd = STDIN_FILENO;
|
2014-10-01 13:17:51 +02:00
|
|
|
} else if ((Modes.fd = open(Modes.filename,
|
|
|
|
#ifdef _WIN32
|
|
|
|
(O_RDONLY | O_BINARY)
|
|
|
|
#else
|
|
|
|
(O_RDONLY)
|
|
|
|
#endif
|
|
|
|
)) == -1) {
|
2013-01-05 13:52:25 +01:00
|
|
|
perror("Opening data file");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
2013-01-10 20:58:13 +01:00
|
|
|
if (Modes.net) modesInitNet();
|
2013-01-05 13:52:25 +01:00
|
|
|
|
2015-01-20 18:16:35 +01:00
|
|
|
// init stats:
|
2015-02-11 02:14:21 +01:00
|
|
|
Modes.stats_current.start = Modes.stats_current.end =
|
|
|
|
Modes.stats_alltime.start = Modes.stats_alltime.end =
|
|
|
|
Modes.stats_periodic.start = Modes.stats_periodic.end =
|
|
|
|
Modes.stats_5min.start = Modes.stats_5min.end =
|
|
|
|
Modes.stats_15min.start = Modes.stats_15min.end = mstime();
|
|
|
|
|
|
|
|
for (j = 0; j < 15; ++j)
|
|
|
|
Modes.stats_1min[j].start = Modes.stats_1min[j].end = Modes.stats_current.start;
|
2015-01-20 18:16:35 +01:00
|
|
|
|
|
|
|
// write initial json files so they're not missing
|
|
|
|
writeJsonToFile("receiver.json", generateReceiverJson);
|
|
|
|
writeJsonToFile("stats.json", generateStatsJson);
|
|
|
|
writeJsonToFile("aircraft.json", generateAircraftJson);
|
2014-12-10 18:05:22 +01:00
|
|
|
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
// If the user specifies --net-only, just run in order to serve network
|
|
|
|
// clients without reading data from the RTL device
|
2015-02-17 22:44:30 +01:00
|
|
|
if (Modes.net_only) {
|
|
|
|
while (!Modes.exit) {
|
|
|
|
struct timespec start_time;
|
2015-01-23 02:22:22 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
start_cpu_timing(&start_time);
|
|
|
|
backgroundTasks();
|
|
|
|
end_cpu_timing(&start_time, &Modes.stats_current.background_cpu);
|
2015-01-23 02:22:22 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
usleep(100000);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Create the thread that will read the data from the device.
|
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
|
|
|
pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL);
|
2013-01-13 01:39:29 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
while (Modes.exit == 0) {
|
|
|
|
struct timespec start_time;
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
if (Modes.first_free_buffer == Modes.first_filled_buffer) {
|
2015-02-17 22:44:30 +01:00
|
|
|
/* wait for more data.
|
|
|
|
* we should be getting data every 50-60ms. wait for max 100ms before we give up and do some background work.
|
|
|
|
* this is fairly aggressive as all our network I/O runs out of the background work!
|
|
|
|
*/
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
struct timespec ts;
|
|
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
|
|
ts.tv_nsec += 100000000;
|
|
|
|
normalize_timespec(&ts);
|
2015-02-17 22:07:36 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
pthread_cond_timedwait(&Modes.data_cond, &Modes.data_mutex, &ts); // This unlocks Modes.data_mutex, and waits for Modes.data_cond
|
|
|
|
}
|
2015-02-17 22:07:36 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
// Modes.data_mutex is locked, and possibly we have data.
|
2013-01-05 13:52:25 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
// copy out reader CPU time and reset it
|
|
|
|
add_timespecs(&Modes.reader_cpu_accumulator, &Modes.stats_current.reader_cpu, &Modes.stats_current.reader_cpu);
|
|
|
|
Modes.reader_cpu_accumulator.tv_sec = 0;
|
|
|
|
Modes.reader_cpu_accumulator.tv_nsec = 0;
|
2015-02-17 22:07:36 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
if (Modes.first_free_buffer != Modes.first_filled_buffer) {
|
|
|
|
// FIFO is not empty, process one buffer.
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
struct mag_buf *buf;
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
start_cpu_timing(&start_time);
|
|
|
|
buf = &Modes.mag_buffers[Modes.first_filled_buffer];
|
2015-02-17 22:44:30 +01:00
|
|
|
|
|
|
|
// Process data after releasing the lock, so that the capturing
|
|
|
|
// thread can read data while we perform computationally expensive
|
|
|
|
// stuff at the same time.
|
2015-04-09 19:51:31 +02:00
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
2015-02-17 22:44:30 +01:00
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
if (Modes.oversample) {
|
2015-04-09 19:51:31 +02:00
|
|
|
demodulate2400(buf);
|
2015-06-15 23:14:37 +02:00
|
|
|
} else {
|
2015-04-09 19:51:31 +02:00
|
|
|
demodulate2000(buf);
|
2015-06-15 23:14:37 +02:00
|
|
|
}
|
2015-02-17 22:44:30 +01:00
|
|
|
|
2015-04-09 19:51:31 +02:00
|
|
|
Modes.stats_current.samples_processed += buf->length;
|
|
|
|
Modes.stats_current.samples_dropped += buf->dropped;
|
2015-02-17 22:44:30 +01:00
|
|
|
end_cpu_timing(&start_time, &Modes.stats_current.demod_cpu);
|
2015-04-09 19:51:31 +02:00
|
|
|
|
|
|
|
// Mark the buffer we just processed as completed.
|
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
|
|
|
Modes.first_filled_buffer = (Modes.first_filled_buffer + 1) % MODES_MAG_BUFFERS;
|
|
|
|
pthread_cond_signal(&Modes.data_cond);
|
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
2015-02-17 22:44:30 +01:00
|
|
|
} else {
|
2015-04-09 19:51:31 +02:00
|
|
|
// Nothing to process this time around.
|
2015-02-17 22:44:30 +01:00
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
}
|
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
start_cpu_timing(&start_time);
|
|
|
|
backgroundTasks();
|
|
|
|
end_cpu_timing(&start_time, &Modes.stats_current.background_cpu);
|
2015-01-23 02:22:22 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
pthread_mutex_lock(&Modes.data_mutex);
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
}
|
2013-01-05 13:52:25 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
pthread_mutex_unlock(&Modes.data_mutex);
|
2015-01-23 02:22:22 +01:00
|
|
|
|
2015-02-17 22:44:30 +01:00
|
|
|
pthread_join(Modes.reader_thread,NULL); // Wait on reader thread exit
|
|
|
|
pthread_cond_destroy(&Modes.data_cond); // Thread cleanup - only after the reader thread is dead!
|
|
|
|
pthread_mutex_destroy(&Modes.data_mutex);
|
2013-01-05 13:52:25 +01:00
|
|
|
}
|
|
|
|
|
2013-04-29 23:14:06 +02:00
|
|
|
// If --stats were given, print statistics
|
|
|
|
if (Modes.stats) {
|
2015-01-20 18:16:35 +01:00
|
|
|
display_total_stats();
|
2013-01-06 15:13:40 +01:00
|
|
|
}
|
|
|
|
|
2015-06-15 23:14:37 +02:00
|
|
|
cleanup_converter(Modes.converter_state);
|
2015-02-17 22:43:17 +01:00
|
|
|
log_with_timestamp("Normal exit.");
|
2015-01-02 23:29:29 +01:00
|
|
|
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
#ifndef _WIN32
|
2013-05-21 13:08:35 +02:00
|
|
|
pthread_exit(0);
|
BUGFIX : Missed data causes timestamp slip
The Mutex on the RTL data reader thread does not "force" the data
processing thread to execute. Therefore, if the processor is busy, it is
possible for a second RTL callback to occur before the data from the
first has been processed. This will cause the loss of the first data,
but worse, it will cause a slip in the timestamp. This upsets Beamfinder
and MLAT operation in PlanePlotter.
To solve this, keep a Fifo buffer which is filled by the callback
thread, and emptied by the data processing thread. The fifo is the same
size as the number of buffers requested in the call to
rtlsdr_read_async().
Note - we only put the value of the pointer supplied in the callback
into the fifo. We do not attempt to cache the data in the buffer pointed
to by the pointer. This would require us to memcopy() 2Mbytes per
second, which we don't want to do if we don't have to because it will
only make the processor loading worse. Instead, we assume that the data
in the buffer will remain valid after the callback returns, at least
until it is overwritten by new data.
It is still possible for us to lose data if we can't process it quickly
enough. However, we can now detect this loss of data when the fifo is
almost full, and correct the timestamp for the lost block/blocks.
2014-02-23 00:11:13 +01:00
|
|
|
#else
|
|
|
|
return (0);
|
|
|
|
#endif
|
2013-01-05 13:52:25 +01:00
|
|
|
}
|
Split into separate module files
Ok - this is likely to upset some people. Up until now, the vast
majority of the code has been in just one file - dump1090.c. This file
has grown so that it was approaching of 5000 lines long, and it was
becoming unmanagable. So I've split the file into several modules,
hopefully along fairly logical boundaries. The files are :
1) dump1090.c : Basically just the main() entry function, the help
function, the RTL dongle hardware interface, and a few orphan functions
that don't really fit anywhere else.
2) mode_s.c : This contains all the mode S / ADSB decoding functions.
3) mode_ac.c : This contains all the mode A & C decoding functions
4) interactive.c : This contains all the functions to maintain an
internal list of aircraft seen over the last period, and functions to
print them out to the local console.
5) net_io.c : This contains all the network input/output functions
allowing data to be passed in/out to/from other receivers, in formats
such as SBS-1/3, Beast, AVR and JavaScript.
Hopefully this should provide an easier way forward if/when more
functions are added.
2013-08-19 19:57:03 +02:00
|
|
|
//
|
|
|
|
//=========================================================================
|
|
|
|
//
|