antirez / dump1090

Dump1090 is a simple Mode S decoder for RTLSDR devices
2.45k stars 1.33k forks source link

Not Compiling #165

Closed tomcass240 closed 9 months ago

tomcass240 commented 3 years ago

Getting the following error when typing make as per the instructions.

gcc -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o pkg-config --libs librtlsdr -lpthread -lm /usr/bin/ld: interactive.o:/home/z/git/dump1090/dump1090.h:373: multiple definition of Modes'; dump1090.o:/home/z/git/dump1090/dump1090.h:373: first defined here /usr/bin/ld: interactive.o:/home/z/git/dump1090/dump1090.h:238: multiple definition oftDF'; dump1090.o:/home/z/git/dump1090/dump1090.h:238: first defined here /usr/bin/ld: mode_ac.o:/home/z/git/dump1090/dump1090.h:373: multiple definition of Modes'; dump1090.o:/home/z/git/dump1090/dump1090.h:373: first defined here /usr/bin/ld: mode_ac.o:/home/z/git/dump1090/dump1090.h:238: multiple definition oftDF'; dump1090.o:/home/z/git/dump1090/dump1090.h:238: first defined here /usr/bin/ld: mode_s.o:/home/z/git/dump1090/dump1090.h:373: multiple definition of Modes'; dump1090.o:/home/z/git/dump1090/dump1090.h:373: first defined here /usr/bin/ld: mode_s.o:/home/z/git/dump1090/dump1090.h:238: multiple definition oftDF'; dump1090.o:/home/z/git/dump1090/dump1090.h:238: first defined here /usr/bin/ld: net_io.o:/home/z/git/dump1090/dump1090.h:373: multiple definition of Modes'; dump1090.o:/home/z/git/dump1090/dump1090.h:373: first defined here /usr/bin/ld: net_io.o:/home/z/git/dump1090/dump1090.h:238: multiple definition oftDF'; dump1090.o:/home/z/git/dump1090/dump1090.h:238: first defined here collect2: error: ld returned 1 exit status make: *** [Makefile:24: dump1090] Error 1

Zorglu commented 2 years ago

the same

hoopertsau commented 2 years ago

change the Modes and tDF define in dump1090.h. just define the struct type, not the instance. struct stModes { XXX XXX XXX .... }; struct stDF { XX XXX ... };

and declare extern extern struct stModes Modes; extern struct stDF tDF;

finnally,put the Modes and tDF instance define into dump1090.c and view1090.c

struct stModes Modes; struct stDF tDF;

you can now make it.

jamesg31 commented 2 years ago

change the Modes and tDF define in dump1090.h. just define the struct type, not the instance. struct stModes { XXX XXX XXX .... }; struct stDF { XX XXX ... };

and declare extern extern struct stModes Modes; extern struct stDF tDF;

finnally,put the Modes and tDF instance define into dump1090.c and view1090.c

struct stModes Modes; struct stDF tDF;

you can now make it.

I am having the same issue on a raspberry pi 4. Can you go into more detail with these instructions? I do not understand.

akshitmehra commented 2 years ago

I had the same issue, recently. You can follow the steps below:

  1. Open dump1090.h file
  2. Go to line 238 and change to just };
  3. Go to line 241 and change to struct stModes {
  4. Go to line 373 and change to just };
  5. Open dump1090.c file
  6. Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF;
  7. Open view1090.c file
  8. Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF;
  9. Run make -B

It should work fine now.

AgentSmith0 commented 2 years ago

@akshitmehra Thank you so much for your help, but I am trying to compile this fork: https://github.com/MalcolmRobb/dump1090 But I get the following error messages:

gcc -g -o dump1090 dump1090.o anet.o interactive.o mode_ac.o mode_s.o net_io.o `pkg-config --libs librtlsdr` -lpthread -lm 
/usr/bin/ld: interactive.o:/home/pi/dump1090/dump1090.h:373: multiple definition of `Modes'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: interactive.o:/home/pi/dump1090/dump1090.h:238: multiple definition of `tDF'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: mode_ac.o:/home/pi/dump1090/dump1090.h:373: multiple definition of `Modes'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: mode_ac.o:/home/pi/dump1090/dump1090.h:238: multiple definition of `tDF'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: mode_s.o:/home/pi/dump1090/dump1090.h:373: multiple definition of `Modes'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: mode_s.o:/home/pi/dump1090/dump1090.h:238: multiple definition of `tDF'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: net_io.o:/home/pi/dump1090/dump1090.h:373: multiple definition of `Modes'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
/usr/bin/ld: net_io.o:/home/pi/dump1090/dump1090.h:238: multiple definition of `tDF'; dump1090.o:/home/pi/dump1090/dump1090.c:32: first defined here
collect2: error: ld returned 1 exit status
make: *** [Makefile:24: dump1090] Error 1

Do you know how I can fix these errors? And maybe you can create a PR for the fix?

McCavity commented 2 years ago

@AgentSmith0 I got the same and I could work around it by following @akshitmehra's instructions and adding one more step that was mentioned by @hoopertsau but was missing in @akshitmehra's instructions:

and declare extern extern struct stModes Modes; extern struct stDF tDF;

So to get it working you need to insert another step in @akshitmehra's instructions:

4a. Insert a line below line 373 and paste extern struct stModes Modes; extern struct stDF tDF;

After doing that make -B worked just fine for me.

AgentSmith0 commented 2 years ago

@McCavity Thank you so much for your help!!! It works fine now.

daniyals48 commented 2 years ago

I had the same issue, recently. You can follow the steps below:

1. Open `dump1090.h` file

2. Go to line 238 and change to just `};`

3. Go to line 241 and change to `struct stModes {`

4. Go to line 373 and change to just `};`

5. Open `dump1090.c` file

6. Insert a line below line 31 and paste `struct stModes Modes; struct stDF tDF;`

7. Open `view1090.c` file

8. Insert a line below line 31 and paste `struct stModes Modes; struct stDF tDF;`

9. Run `make -B`

It should work fine now.

Hello Can you share both of the files because in dump1090.c files there are comments and no code.

AgentSmith0 commented 2 years ago

Here are my files: dump1090.h:

// dump1090, a Mode S messages decoder for RTLSDR devices.
//
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//  *  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.
//
#ifndef __DUMP1090_H
#define __DUMP1090_H

// File Version number
// ====================
// Format is : MajorVer.MinorVer.DayMonth.Year"
// MajorVer changes only with significant changes
// MinorVer changes when additional features are added, but not for bug fixes (range 00-99)
// DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update
//
#define MODES_DUMP1090_VERSION     "1.10.3010.14"

// ============================= Include files ==========================

#ifndef _WIN32
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <stdint.h>
    #include <errno.h>
    #include <unistd.h>
    #include <math.h>
    #include <sys/time.h>
    #include <sys/timeb.h>
    #include <signal.h>
    #include <fcntl.h>
    #include <ctype.h>
    #include <sys/stat.h>
    #include <sys/ioctl.h>
    #include "rtl-sdr.h"
    #include "anet.h"
#else
    #include "winstubs.h" //Put everything Windows specific in here
    #include "rtl-sdr.h"
    #include "anet.h"
#endif

// ============================= #defines ===============================
//
// If you have a valid coaa.h, these values will come from it. If not,
// then you can enter your own values in the #else section here
//
#ifdef USER_LATITUDE
    #define MODES_USER_LATITUDE_DFLT   (USER_LATITUDE)
    #define MODES_USER_LONGITUDE_DFLT  (USER_LONGITUDE)
#else
    #define MODES_USER_LATITUDE_DFLT   (0.0)
    #define MODES_USER_LONGITUDE_DFLT  (0.0)
#endif

#define MODES_DEFAULT_PPM          52
#define MODES_DEFAULT_RATE         2000000
#define MODES_DEFAULT_FREQ         1090000000
#define MODES_DEFAULT_WIDTH        1000
#define MODES_DEFAULT_HEIGHT       700
#define MODES_ASYNC_BUF_NUMBER     16
#define MODES_ASYNC_BUF_SIZE       (16*16384)                 // 256k
#define MODES_ASYNC_BUF_SAMPLES    (MODES_ASYNC_BUF_SIZE / 2) // Each sample is 2 bytes
#define MODES_AUTO_GAIN            -100                       // Use automatic gain
#define MODES_MAX_GAIN             999999                     // Use max available gain
#define MODES_MSG_SQUELCH_LEVEL    0x02FF                     // Average signal strength limit
#define MODES_MSG_ENCODER_ERRS     3                          // Maximum number of encoding errors

// When changing, change also fixBitErrors() and modesInitErrorTable() !!
#define MODES_MAX_BITERRORS        2                          // Global max for fixable bit erros

#define MODEAC_MSG_SAMPLES       (25 * 2)                     // include up to the SPI bit
#define MODEAC_MSG_BYTES          2
#define MODEAC_MSG_SQUELCH_LEVEL  0x07FF                      // Average signal strength limit
#define MODEAC_MSG_FLAG          (1<<0)
#define MODEAC_MSG_MODES_HIT     (1<<1)
#define MODEAC_MSG_MODEA_HIT     (1<<2)
#define MODEAC_MSG_MODEC_HIT     (1<<3)
#define MODEAC_MSG_MODEA_ONLY    (1<<4)
#define MODEAC_MSG_MODEC_OLD     (1<<5)

#define MODES_PREAMBLE_US        8              // microseconds = bits
#define MODES_PREAMBLE_SAMPLES  (MODES_PREAMBLE_US       * 2)
#define MODES_PREAMBLE_SIZE     (MODES_PREAMBLE_SAMPLES  * sizeof(uint16_t))
#define MODES_LONG_MSG_BYTES     14
#define MODES_SHORT_MSG_BYTES    7
#define MODES_LONG_MSG_BITS     (MODES_LONG_MSG_BYTES    * 8)
#define MODES_SHORT_MSG_BITS    (MODES_SHORT_MSG_BYTES   * 8)
#define MODES_LONG_MSG_SAMPLES  (MODES_LONG_MSG_BITS     * 2)
#define MODES_SHORT_MSG_SAMPLES (MODES_SHORT_MSG_BITS    * 2)
#define MODES_LONG_MSG_SIZE     (MODES_LONG_MSG_SAMPLES  * sizeof(uint16_t))
#define MODES_SHORT_MSG_SIZE    (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t))

#define MODES_RAWOUT_BUF_SIZE   (1500)
#define MODES_RAWOUT_BUF_FLUSH  (MODES_RAWOUT_BUF_SIZE - 200)
#define MODES_RAWOUT_BUF_RATE   (1000)            // 1000 * 64mS = 1 Min approx

#define MODES_ICAO_CACHE_LEN 1024 // Power of two required
#define MODES_ICAO_CACHE_TTL 60   // Time to live of cached addresses
#define MODES_UNIT_FEET 0
#define MODES_UNIT_METERS 1

#define MODES_USER_LATLON_VALID (1<<0)

#define MODES_ACFLAGS_LATLON_VALID   (1<<0)  // Aircraft Lat/Lon is decoded
#define MODES_ACFLAGS_ALTITUDE_VALID (1<<1)  // Aircraft altitude is known
#define MODES_ACFLAGS_HEADING_VALID  (1<<2)  // Aircraft heading is known
#define MODES_ACFLAGS_SPEED_VALID    (1<<3)  // Aircraft speed is known
#define MODES_ACFLAGS_VERTRATE_VALID (1<<4)  // Aircraft vertical rate is known
#define MODES_ACFLAGS_SQUAWK_VALID   (1<<5)  // Aircraft Mode A Squawk is known
#define MODES_ACFLAGS_CALLSIGN_VALID (1<<6)  // Aircraft Callsign Identity
#define MODES_ACFLAGS_EWSPEED_VALID  (1<<7)  // Aircraft East West Speed is known
#define MODES_ACFLAGS_NSSPEED_VALID  (1<<8)  // Aircraft North South Speed is known
#define MODES_ACFLAGS_AOG            (1<<9)  // Aircraft is On the Ground
#define MODES_ACFLAGS_LLEVEN_VALID   (1<<10) // Aircraft Even Lot/Lon is known
#define MODES_ACFLAGS_LLODD_VALID    (1<<11) // Aircraft Odd Lot/Lon is known
#define MODES_ACFLAGS_AOG_VALID      (1<<12) // MODES_ACFLAGS_AOG is valid
#define MODES_ACFLAGS_FS_VALID       (1<<13) // Aircraft Flight Status is known
#define MODES_ACFLAGS_NSEWSPD_VALID  (1<<14) // Aircraft EW and NS Speed is known
#define MODES_ACFLAGS_LATLON_REL_OK  (1<<15) // Indicates it's OK to do a relative CPR

#define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
#define MODES_ACFLAGS_LLBOTH_VALID   (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)
#define MODES_ACFLAGS_AOG_GROUND     (MODES_ACFLAGS_AOG_VALID    | MODES_ACFLAGS_AOG)

#define MODES_DEBUG_DEMOD (1<<0)
#define MODES_DEBUG_DEMODERR (1<<1)
#define MODES_DEBUG_BADCRC (1<<2)
#define MODES_DEBUG_GOODCRC (1<<3)
#define MODES_DEBUG_NOPREAMBLE (1<<4)
#define MODES_DEBUG_NET (1<<5)
#define MODES_DEBUG_JS (1<<6)

// When debug is set to MODES_DEBUG_NOPREAMBLE, the first sample must be
// at least greater than a given level for us to dump the signal.
#define MODES_DEBUG_NOPREAMBLE_LEVEL 25

#define MODES_INTERACTIVE_REFRESH_TIME 250      // Milliseconds
#define MODES_INTERACTIVE_ROWS          22      // Rows on screen
#define MODES_INTERACTIVE_DELETE_TTL   300      // Delete from the list after 300 seconds
#define MODES_INTERACTIVE_DISPLAY_TTL   60      // Delete from display after 60 seconds

#define MODES_NET_HEARTBEAT_RATE       900      // Each block is approx 65mS - default is > 1 min

#define MODES_NET_SERVICES_NUM          6
#define MODES_NET_INPUT_RAW_PORT    30001
#define MODES_NET_OUTPUT_RAW_PORT   30002
#define MODES_NET_OUTPUT_SBS_PORT   30003
#define MODES_NET_INPUT_BEAST_PORT  30004
#define MODES_NET_OUTPUT_BEAST_PORT 30005
#define MODES_NET_HTTP_PORT          8080
#define MODES_CLIENT_BUF_SIZE  1024
#define MODES_NET_SNDBUF_SIZE (1024*64)
#define MODES_NET_SNDBUF_MAX  (7)

#ifndef HTMLPATH
#define HTMLPATH   "./public_html"      // default path for gmap.html etc
#endif

#define MODES_NOTUSED(V) ((void) V)

//======================== structure declarations =========================

// Structure used to describe a networking client
struct client {
    struct client*  next;                // Pointer to next client
    int    fd;                           // File descriptor
    int    service;                      // TCP port the client is connected to
    int    buflen;                       // Amount of data on buffer
    char   buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer
};

// Structure used to describe an aircraft in iteractive mode
struct aircraft {
    uint32_t      addr;           // ICAO address
    char          flight[16];     // Flight number
    unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
    int           altitude;       // Altitude
    int           speed;          // Velocity
    int           track;          // Angle of flight
    int           vert_rate;      // Vertical rate.
    time_t        seen;           // Time at which the last packet was received
    time_t        seenLatLon;     // Time at which the last lat long was calculated
    uint64_t      timestamp;      // Timestamp at which the last packet was received
    uint64_t      timestampLatLon;// Timestamp at which the last lat long was calculated
    long          messages;       // Number of Mode S messages received
    int           modeA;          // Squawk
    int           modeC;          // Altitude
    long          modeAcount;     // Mode A Squawk hit Count
    long          modeCcount;     // Mode C Altitude hit Count
    int           modeACflags;    // Flags for mode A/C recognition

    // Encoded latitude and longitude as extracted by odd and even CPR encoded messages
    int           odd_cprlat;
    int           odd_cprlon;
    int           even_cprlat;
    int           even_cprlon;
    uint64_t      odd_cprtime;
    uint64_t      even_cprtime;
    double        lat, lon;       // Coordinated obtained from CPR encoded data
    int           bFlags;         // Flags related to valid fields in this structure
    struct aircraft *next;        // Next aircraft in our linked list
};

struct stDF {
    struct stDF     *pNext;                      // Pointer to next item in the linked list
    struct stDF     *pPrev;                      // Pointer to previous item in the linked list
    struct aircraft *pAircraft;                  // Pointer to the Aircraft structure for this DF
    time_t           seen;                       // Dos/UNIX Time at which the this packet was received
    uint64_t         llTimestamp;                // Timestamp at which the this packet was received
    uint32_t         addr;                       // Timestamp at which the this packet was received
    unsigned char    msg[MODES_LONG_MSG_BYTES];  // the binary
};

// Program global state
struct stModes {                             // Internal state
    pthread_t       reader_thread;

    pthread_mutex_t data_mutex;      // Mutex to synchronize buffer access
    pthread_cond_t  data_cond;       // Conditional variable associated
    uint16_t       *pData          [MODES_ASYNC_BUF_NUMBER]; // Raw IQ sample buffers from RTL
    struct timeb    stSystemTimeRTL[MODES_ASYNC_BUF_NUMBER]; // System time when RTL passed us this block
    int             iDataIn;         // Fifo input pointer
    int             iDataOut;        // Fifo output pointer
    int             iDataReady;      // Fifo content count
    int             iDataLost;       // Count of missed buffers

    uint16_t       *pFileData;       // Raw IQ samples buffer (from a File)
    uint16_t       *magnitude;       // Magnitude vector
    uint64_t        timestampBlk;    // Timestamp of the start of the current block
    struct timeb    stSystemTimeBlk; // System time when RTL passed us currently processing this block
    int             fd;              // --ifile option file descriptor
    uint32_t       *icao_cache;      // Recently seen ICAO addresses cache
    uint16_t       *maglut;          // I/Q -> Magnitude lookup table
    int             exit;            // Exit from the main loop when true

    // RTLSDR
    int           dev_index;
    int           gain;
    int           enable_agc;
    rtlsdr_dev_t *dev;
    int           freq;
    int           ppm_error;

    // Networking
    char           aneterr[ANET_ERR_LEN];
    struct client *clients;          // Our clients
    int            sbsos;            // SBS output listening socket
    int            ros;              // Raw output listening socket
    int            ris;              // Raw input listening socket
    int            bos;              // Beast output listening socket
    int            bis;              // Beast input listening socket
    int            https;            // HTTP listening socket
    char          *rawOut;           // Buffer for building raw output data
    int            rawOutUsed;       // How much of the buffer is currently used
    char          *beastOut;         // Buffer for building beast output data
    int            beastOutUsed;     // How much if the buffer is currently used
#ifdef _WIN32
    WSADATA        wsaData;          // Windows socket initialisation
#endif

    // Configuration
    char *filename;                  // Input form file, --ifile option
    int   phase_enhance;             // Enable phase enhancement if true
    int   nfix_crc;                  // Number of crc bit error(s) to correct
    int   check_crc;                 // Only display messages with good CRC
    int   raw;                       // Raw output format
    int   beast;                     // Beast binary format output
    int   mode_ac;                   // Enable decoding of SSR Modes A & C
    int   debug;                     // Debugging mode
    int   net;                       // Enable networking
    int   net_only;                  // Enable just networking
    int   net_heartbeat_count;       // TCP heartbeat counter
    int   net_heartbeat_rate;        // TCP heartbeat rate
    int   net_output_sbs_port;       // SBS output TCP port
    int   net_output_raw_size;       // Minimum Size of the output raw data
    int   net_output_raw_rate;       // Rate (in 64mS increments) of output raw data
    int   net_output_raw_rate_count; // Rate (in 64mS increments) of output raw data
    int   net_output_raw_port;       // Raw output TCP port
    int   net_input_raw_port;        // Raw input TCP port
    int   net_output_beast_port;     // Beast output TCP port
    int   net_input_beast_port;      // Beast input TCP port
    char  *net_bind_address;         // Bind address
    int   net_http_port;             // HTTP port
    int   net_sndbuf_size;           // TCP output buffer size (64Kb * 2^n)
    int   quiet;                     // Suppress stdout
    int   interactive;               // Interactive mode
    int   interactive_rows;          // Interactive mode: max number of rows
    int   interactive_display_ttl;   // Interactive mode: TTL display
    int   interactive_delete_ttl;    // Interactive mode: TTL before deletion
    int   stats;                     // Print stats at exit in --ifile mode
    int   onlyaddr;                  // Print only ICAO addresses
    int   metric;                    // Use metric units
    int   mlat;                      // Use Beast ascii format for raw data output, i.e. @...; iso *...;
    int   interactive_rtl1090;       // flight table in interactive mode is formatted like RTL1090

    // User details
    double fUserLat;                // Users receiver/antenna lat/lon needed for initial surface location
    double fUserLon;                // Users receiver/antenna lat/lon needed for initial surface location
    int    bUserFlags;              // Flags relating to the user details

    // Interactive mode
    struct aircraft *aircrafts;
    uint64_t         interactive_last_update; // Last screen update in milliseconds
    time_t           last_cleanup_time;       // Last cleanup time in seconds

    // DF List mode
    int             bEnableDFLogging; // Set to enable DF Logging
    pthread_mutex_t pDF_mutex;        // Mutex to synchronize pDF access
    struct stDF    *pDF;              // Pointer to DF list

    // Statistics
    unsigned int stat_valid_preamble;
    unsigned int stat_demodulated0;
    unsigned int stat_demodulated1;
    unsigned int stat_demodulated2;
    unsigned int stat_demodulated3;
    unsigned int stat_goodcrc;
    unsigned int stat_badcrc;
    unsigned int stat_fixed;

    // Histogram of fixed bit errors: index 0 for single bit erros,
    // index 1 for double bit errors etc.
    unsigned int stat_bit_fix[MODES_MAX_BITERRORS];

    unsigned int stat_http_requests;
    unsigned int stat_sbs_connections;
    unsigned int stat_raw_connections;
    unsigned int stat_beast_connections;
    unsigned int stat_out_of_phase;
    unsigned int stat_ph_demodulated0;
    unsigned int stat_ph_demodulated1;
    unsigned int stat_ph_demodulated2;
    unsigned int stat_ph_demodulated3;
    unsigned int stat_ph_goodcrc;
    unsigned int stat_ph_badcrc;
    unsigned int stat_ph_fixed;
    // Histogram of fixed bit errors: index 0 for single bit erros,
    // index 1 for double bit errors etc.
    unsigned int stat_ph_bit_fix[MODES_MAX_BITERRORS];

    unsigned int stat_DF_Len_Corrected;
    unsigned int stat_DF_Type_Corrected;
    unsigned int stat_ModeAC;

    unsigned int stat_blocks_processed;
    unsigned int stat_blocks_dropped;
};
extern struct stModes Modes; extern struct stDF tDF;

// The struct we use to store information about a decoded message.
struct modesMessage {
    // Generic fields
    unsigned char msg[MODES_LONG_MSG_BYTES];      // Binary message.
    int           msgbits;                        // Number of bits in message 
    int           msgtype;                        // Downlink format #
    int           crcok;                          // True if CRC was valid
    uint32_t      crc;                            // Message CRC
    int           correctedbits;                  // No. of bits corrected 
    char          corrected[MODES_MAX_BITERRORS]; // corrected bit positions
    uint32_t      addr;                           // ICAO Address from bytes 1 2 and 3
    int           phase_corrected;                // True if phase correction was applied
    uint64_t      timestampMsg;                   // Timestamp of the message
    int           remote;                         // If set this message is from a remote station
    unsigned char signalLevel;                    // Signal Amplitude

    // DF 11
    int  ca;                    // Responder capabilities
    int  iid;

    // DF 17, DF 18
    int    metype;              // Extended squitter message type.
    int    mesub;               // Extended squitter message subtype.
    int    heading;             // Reported by aircraft, or computed from from EW and NS velocity
    int    raw_latitude;        // Non decoded latitude.
    int    raw_longitude;       // Non decoded longitude.
    double fLat;                // Coordinates obtained from CPR encoded data if/when decoded
    double fLon;                // Coordinates obtained from CPR encoded data if/when decoded
    char   flight[16];          // 8 chars flight number.
    int    ew_velocity;         // E/W velocity.
    int    ns_velocity;         // N/S velocity.
    int    vert_rate;           // Vertical rate.
    int    velocity;            // Reported by aircraft, or computed from from EW and NS velocity

    // DF4, DF5, DF20, DF21
    int  fs;                    // Flight status for DF4,5,20,21
    int  modeA;                 // 13 bits identity (Squawk).

    // Fields used by multiple message types.
    int  altitude;
    int  unit; 
    int  bFlags;                // Flags related to fields in this structure
};

// ======================== function declarations =========================

#ifdef __cplusplus
extern "C" {
#endif

//
// Functions exported from mode_ac.c
//
int  detectModeA       (uint16_t *m, struct modesMessage *mm);
void decodeModeAMessage(struct modesMessage *mm, int ModeA);
int  ModeAToModeC      (unsigned int ModeA);

//
// Functions exported from mode_s.c
//
void detectModeS        (uint16_t *m, uint32_t mlen);
void decodeModesMessage (struct modesMessage *mm, unsigned char *msg);
void displayModesMessage(struct modesMessage *mm);
void useModesMessage    (struct modesMessage *mm);
void computeMagnitudeVector(uint16_t *pData);
int  decodeCPR          (struct aircraft *a, int fflag, int surface);
int  decodeCPRrelative  (struct aircraft *a, int fflag, int surface);
void modesInitErrorInfo ();
//
// Functions exported from interactive.c
//
struct aircraft* interactiveReceiveData(struct modesMessage *mm);
void  interactiveShowData(void);
void  interactiveRemoveStaleAircrafts(void);
int   decodeBinMessage   (struct client *c, char *p);
struct aircraft *interactiveFindAircraft(uint32_t addr);
struct stDF     *interactiveFindDF      (uint32_t addr);

//
// Functions exported from net_io.c
//
void modesInitNet         (void);
void modesReadFromClients (void);
void modesSendAllClients  (int service, void *msg, int len);
void modesQueueOutput     (struct modesMessage *mm);
void modesReadFromClient(struct client *c, char *sep, int(*handler)(struct client *, char *));

#ifdef __cplusplus
}
#endif

#endif // __DUMP1090_H

dump1090.c:

// dump1090, a Mode S messages decoder for RTLSDR devices.
//
// Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//  *  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.
//
#include "coaa.h"
#include "dump1090.h"
struct stModes Modes; struct stDF tDF;
//
// ============================= Utility functions ==========================
//
void sigintHandler(int dummy) {
    MODES_NOTUSED(dummy);
    signal(SIGINT, SIG_DFL);  // reset signal handler - bit extra safety
    Modes.exit = 1;           // Signal to threads that we are done
}
//
// =============================== 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
//
// =============================== Initialization ===========================
//
void modesInitConfig(void) {
    // Default everything to zero/NULL
    memset(&Modes, 0, sizeof(Modes));

    // Now initialise things that should not be 0/NULL to their defaults
    Modes.gain                    = MODES_MAX_GAIN;
    Modes.freq                    = MODES_DEFAULT_FREQ;
    Modes.ppm_error               = MODES_DEFAULT_PPM;
    Modes.check_crc               = 1;
    Modes.net_heartbeat_rate      = MODES_NET_HEARTBEAT_RATE;
    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;
    Modes.interactive_rows        = getTermRows();
    Modes.interactive_delete_ttl  = MODES_INTERACTIVE_DELETE_TTL;
    Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
    Modes.fUserLat                = MODES_USER_LATITUDE_DFLT;
    Modes.fUserLon                = MODES_USER_LONGITUDE_DFLT;
}
//
//=========================================================================
//
void modesInit(void) {
    int i, q;

    pthread_mutex_init(&Modes.pDF_mutex,NULL);
    pthread_mutex_init(&Modes.data_mutex,NULL);
    pthread_cond_init(&Modes.data_cond,NULL);

    // Allocate the various buffers used by Modes
    if ( ((Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2)                  ) == NULL) ||
         ((Modes.pFileData  = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE)                                         ) == NULL) ||
         ((Modes.magnitude  = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE) ) == NULL) ||
         ((Modes.maglut     = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256)                                 ) == NULL) ||
         ((Modes.beastOut   = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) ||
         ((Modes.rawOut     = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) ) 
    {
        fprintf(stderr, "Out of memory allocating data buffer.\n");
        exit(1);
    }

    // Clear the buffers that have just been allocated, just in-case
    memset(Modes.icao_cache, 0,   sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2);
    memset(Modes.pFileData,127,   MODES_ASYNC_BUF_SIZE);
    memset(Modes.magnitude,  0,   MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE);

    // 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;
    }

    // Limit the maximum requested raw output size to less than one Ethernet Block 
    if (Modes.net_output_raw_size > (MODES_RAWOUT_BUF_FLUSH))
      {Modes.net_output_raw_size = MODES_RAWOUT_BUF_FLUSH;}
    if (Modes.net_output_raw_rate > (MODES_RAWOUT_BUF_RATE))
      {Modes.net_output_raw_rate = MODES_RAWOUT_BUF_RATE;}
    if (Modes.net_sndbuf_size > (MODES_NET_SNDBUF_MAX))
      {Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}

    // Initialise the Block Timers to something half sensible
    ftime(&Modes.stSystemTimeBlk);
    for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++)
      {Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;}

    // Each I and Q value varies from 0 to 255, which represents a range from -1 to +1. To get from the 
    // unsigned (0-255) range you therefore subtract 127 (or 128 or 127.5) from each I and Q, giving you 
    // a range from -127 to +128 (or -128 to +127, or -127.5 to +127.5)..
    //
    // To decode the AM signal, you need the magnitude of the waveform, which is given by sqrt((I^2)+(Q^2))
    // The most this could be is if I&Q are both 128 (or 127 or 127.5), so you could end up with a magnitude 
    // of 181.019 (or 179.605, or 180.312)
    //
    // However, in reality the magnitude of the signal should never exceed the range -1 to +1, because the 
    // values are I = rCos(w) and Q = rSin(w). Therefore the integer computed magnitude should (can?) never 
    // exceed 128 (or 127, or 127.5 or whatever)
    //
    // If we scale up the results so that they range from 0 to 65535 (16 bits) then we need to multiply 
    // by 511.99, (or 516.02 or 514). antirez's original code multiplies by 360, presumably because he's 
    // assuming the maximim calculated amplitude is 181.019, and (181.019 * 360) = 65166.
    //
    // So lets see if we can improve things by subtracting 127.5, Well in integer arithmatic we can't
    // subtract half, so, we'll double everything up and subtract one, and then compensate for the doubling 
    // in the multiplier at the end.
    //
    // If we do this we can never have I or Q equal to 0 - they can only be as small as +/- 1.
    // This gives us a minimum magnitude of root 2 (0.707), so the dynamic range becomes (1.414-255). This 
    // also affects our scaling value, which is now 65535/(255 - 1.414), or 258.433254
    //
    // The sums then become mag = 258.433254 * (sqrt((I*2-255)^2 + (Q*2-255)^2) - 1.414)
    //                   or mag = (258.433254 * sqrt((I*2-255)^2 + (Q*2-255)^2)) - 365.4798
    //
    // We also need to clip mag just incaes any rogue I/Q values somehow do have a magnitude greater than 255.
    //

    for (i = 0; i <= 255; i++) {
        for (q = 0; q <= 255; q++) {
            int mag, mag_i, mag_q;

            mag_i = (i * 2) - 255;
            mag_q = (q * 2) - 255;

            mag = (int) round((sqrt((mag_i*mag_i)+(mag_q*mag_q)) * 258.433254) - 365.4798);

            Modes.maglut[(i*256)+q] = (uint16_t) ((mag < 65535) ? mag : 65535);
        }
    }

    // Prepare error correction tables
    modesInitErrorInfo();
}
//
// =============================== RTLSDR handling ==========================
//
void modesInitRTLSDR(void) {
    int j;
    int device_count;
    char vendor[256], product[256], serial[256];

    device_count = rtlsdr_get_device_count();
    if (!device_count) {
        fprintf(stderr, "No supported RTLSDR devices found.\n");
        exit(1);
    }

    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,
            (j == Modes.dev_index) ? "(currently selected)" : "");
    }

    if (rtlsdr_open(&Modes.dev, Modes.dev_index) < 0) {
        fprintf(stderr, "Error opening the RTLSDR device: %s\n",
            strerror(errno));
        exit(1);
    }

    // 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) {
        if (Modes.gain == MODES_MAX_GAIN) {
            // Find the maximum gain available
            int numgains;
            int gains[100];

            numgains = rtlsdr_get_tuner_gains(Modes.dev, gains);
            Modes.gain = gains[numgains-1];
            fprintf(stderr, "Max available gain is: %.2f\n", Modes.gain/10.0);
        }
        rtlsdr_set_tuner_gain(Modes.dev, Modes.gain);
        fprintf(stderr, "Setting gain to: %.2f\n", Modes.gain/10.0);
    } else {
        fprintf(stderr, "Using automatic gain control.\n");
    }
    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);
    rtlsdr_set_sample_rate(Modes.dev, MODES_DEFAULT_RATE);
    rtlsdr_reset_buffer(Modes.dev);
    fprintf(stderr, "Gain reported by device: %.2f\n",
        rtlsdr_get_tuner_gain(Modes.dev)/10.0);
}
//
//=========================================================================
//
// We use a thread reading data in background, while the main thread
// handles decoding and visualization of data to the user.
//
// The reading thread calls the RTLSDR API to read data asynchronously, and
// uses a callback to populate the data buffer.
//
// A Mutex is used to avoid races with the decoding thread.
//
void rtlsdrCallback(unsigned char *buf, uint32_t len, void *ctx) {

    MODES_NOTUSED(ctx);

    // Lock the data buffer variables before accessing them
    pthread_mutex_lock(&Modes.data_mutex);

    Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!

    // Get the system time for this block
    ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);

    if (len > MODES_ASYNC_BUF_SIZE) {len = MODES_ASYNC_BUF_SIZE;}

    // Queue the new data
    Modes.pData[Modes.iDataIn] = (uint16_t *) buf;
    Modes.iDataIn    = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1);
    Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);   

    if (Modes.iDataReady == 0) {
      // Ooooops. We've just received the MODES_ASYNC_BUF_NUMBER'th outstanding buffer
      // This means that RTLSDR is currently overwriting the MODES_ASYNC_BUF_NUMBER+1
      // buffer, but we havent yet processed it, so we're going to lose it. There
      // isn't much we can do to recover the lost data, but we can correct things to
      // avoid any additional problems.
      Modes.iDataOut   = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut+1);
      Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1);   
      Modes.iDataLost++;
    }

    // Signal to the other thread that new data is ready, and unlock
    pthread_cond_signal(&Modes.data_cond);
    pthread_mutex_unlock(&Modes.data_mutex);
}
//
//=========================================================================
//
// This is used when --ifile is specified in order to read data from file
// instead of using an RTLSDR device
//
void readDataFromFile(void) {
    pthread_mutex_lock(&Modes.data_mutex);
    while(Modes.exit == 0) {
        ssize_t nread, toread;
        unsigned char *p;

        if (Modes.iDataReady) {
            pthread_cond_wait(&Modes.data_cond, &Modes.data_mutex);
            continue;
        }

        if (Modes.interactive) {
            // When --ifile and --interactive are used together, slow down
            // playing at the natural rate of the RTLSDR received.
            pthread_mutex_unlock(&Modes.data_mutex);
            usleep(64000);
            pthread_mutex_lock(&Modes.data_mutex);
        }

        toread = MODES_ASYNC_BUF_SIZE;
        p = (unsigned char *) Modes.pFileData;
        while(toread) {
            nread = read(Modes.fd, p, toread);
            if (nread <= 0) {
                Modes.exit = 1; // Signal the other threads to exit.
                break;
            }
            p += nread;
            toread -= nread;
        }
        if (toread) {
            // Not enough data on file to fill the buffer? Pad with no signal.
            memset(p,127,toread);
        }

        Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!

        // Get the system time for this block
        ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);

        // Queue the new data
        Modes.pData[Modes.iDataIn] = Modes.pFileData;
        Modes.iDataIn    = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1);
        Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);   

        // Signal to the other thread that new data is ready
        pthread_cond_signal(&Modes.data_cond);
    }
}
//
//=========================================================================
//
// We read data using a thread, so the main thread only handles decoding
// without caring about data acquisition
//
void *readerThreadEntryPoint(void *arg) {
    MODES_NOTUSED(arg);

    if (Modes.filename == NULL) {
        rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL,
                              MODES_ASYNC_BUF_NUMBER,
                              MODES_ASYNC_BUF_SIZE);
    } else {
        readDataFromFile();
    }
    // Signal to the other thread that new data is ready - dummy really so threads don't mutually lock
    pthread_cond_signal(&Modes.data_cond);
    pthread_mutex_unlock(&Modes.data_mutex);
#ifndef _WIN32
    pthread_exit(NULL);
#else
    return NULL;
#endif
}
//
// ============================== Snip mode =================================
//
// Get raw IQ samples and filter everything is < than the specified level
// for more than 256 samples in order to reduce example file size
//
void snipMode(int level) {
    int i, q;
    uint64_t c = 0;

    while ((i = getchar()) != EOF && (q = getchar()) != EOF) {
        if (abs(i-127) < level && abs(q-127) < level) {
            c++;
            if (c > MODES_PREAMBLE_SIZE) continue;
        } else {
            c = 0;
        }
        putchar(i);
        putchar(q);
    }
}
//
// ================================ Main ====================================
//
void showHelp(void) {
    printf(
"-----------------------------------------------------------------------------\n"
"|                        dump1090 ModeS Receiver         Ver : " MODES_DUMP1090_VERSION " |\n"
"-----------------------------------------------------------------------------\n"
"--device-index <index>   Select RTL device (default: 0)\n"
"--gain <db>              Set gain (default: max gain. Use -10 for auto-gain)\n"
"--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"
"--interactive            Interactive mode refreshing data on screen\n"
"--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"
"--modeac                 Enable decoding of SSR Modes 3/A & 3/C\n"
"--net-beast              TCP raw output in Beast binary format\n"
"--net-only               Enable just networking, no RTL device or file used\n"
"--net-bind-address <ip>  IP address to bind to (default: Any; Use 127.0.0.1 for private)\n"
"--net-http-port <port>   HTTP server port (default: 8080)\n"
"--net-ri-port <port>     TCP raw input listen port  (default: 30001)\n"
"--net-ro-port <port>     TCP raw output listen port (default: 30002)\n"
"--net-sbs-port <port>    TCP BaseStation output listen port (default: 30003)\n"
"--net-bi-port <port>     TCP Beast input listen port  (default: 30004)\n"
"--net-bo-port <port>     TCP Beast output listen port (default: 30005)\n"
"--net-ro-size <size>     TCP raw output minimum size (default: 0)\n"
"--net-ro-rate <rate>     TCP raw output memory flush rate (default: 0)\n"
"--net-heartbeat <rate>   TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n"
"--net-buffer <n>         TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n"
"--lat <latitude>         Reference/receiver latitude for surface posn (opt)\n"
"--lon <longitude>        Reference/receiver longitude for surface posn (opt)\n"
"--fix                    Enable single-bits error correction using CRC\n"
"--no-fix                 Disable single-bits error correction using CRC\n"
"--no-crc-check           Disable messages with broken CRC (discouraged)\n"
"--phase-enhance          Enable phase enhancement\n"
"--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"
"--stats-every <seconds>  Show and reset stats every <seconds> seconds\n"
"--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"
"--ppm <error>            Set receiver error in parts per million (default 0)\n"
"--help                   Show this help\n"
"\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"
"                  j = Log frames to frames.js, loadable by debug.html\n"
    );
}

#ifdef _WIN32
void showCopyright(void) {
    uint64_t llTime = time(NULL) + 1;

    printf(
"-----------------------------------------------------------------------------\n"
"|                        dump1090 ModeS Receiver         Ver : " MODES_DUMP1090_VERSION " |\n"
"-----------------------------------------------------------------------------\n"
"\n"
" Copyright (C) 2012 by Salvatore Sanfilippo <antirez@gmail.com>\n"
" Copyright (C) 2014 by Malcolm Robb <support@attavionics.com>\n"
"\n"
" All rights reserved.\n"
"\n"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
" ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
" HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
"\n"
" For further details refer to <https://github.com/MalcolmRobb/dump1090>\n" 
"\n"
    );

  // delay for 1 second to give the user a chance to read the copyright
  while (llTime >= time(NULL)) {}
}
#endif

static void display_stats(void) {
    int j;
    time_t now = time(NULL);

    printf("\n\n");
    if (Modes.interactive)
        interactiveShowData();

    printf("Statistics as at %s", ctime(&now));

    printf("%d sample blocks processed\n",                    Modes.stat_blocks_processed);
    printf("%d sample blocks dropped\n",                      Modes.stat_blocks_dropped);

    printf("%d ModeA/C detected\n",                           Modes.stat_ModeAC);
    printf("%d valid Mode-S preambles\n",                     Modes.stat_valid_preamble);
    printf("%d DF-?? fields corrected for length\n",          Modes.stat_DF_Len_Corrected);
    printf("%d DF-?? fields corrected for type\n",            Modes.stat_DF_Type_Corrected);
    printf("%d demodulated with 0 errors\n",                  Modes.stat_demodulated0);
    printf("%d demodulated with 1 error\n",                   Modes.stat_demodulated1);
    printf("%d demodulated with 2 errors\n",                  Modes.stat_demodulated2);
    printf("%d demodulated with > 2 errors\n",                Modes.stat_demodulated3);
    printf("%d with good crc\n",                              Modes.stat_goodcrc);
    printf("%d with bad crc\n",                               Modes.stat_badcrc);
    printf("%d errors corrected\n",                           Modes.stat_fixed);

    for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
        printf("   %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors");
    }

    if (Modes.phase_enhance) {
        printf("%d phase enhancement attempts\n",                 Modes.stat_out_of_phase);
        printf("%d phase enhanced demodulated with 0 errors\n",   Modes.stat_ph_demodulated0);
        printf("%d phase enhanced demodulated with 1 error\n",    Modes.stat_ph_demodulated1);
        printf("%d phase enhanced demodulated with 2 errors\n",   Modes.stat_ph_demodulated2);
        printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3);
        printf("%d phase enhanced with good crc\n",               Modes.stat_ph_goodcrc);
        printf("%d phase enhanced with bad crc\n",                Modes.stat_ph_badcrc);
        printf("%d phase enhanced errors corrected\n",            Modes.stat_ph_fixed);

        for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
            printf("   %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors");
        }
    }

    printf("%d total usable messages\n",                      Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed);
    fflush(stdout);

    Modes.stat_blocks_processed =
        Modes.stat_blocks_dropped = 0;

    Modes.stat_ModeAC =
        Modes.stat_valid_preamble =
        Modes.stat_DF_Len_Corrected =
        Modes.stat_DF_Type_Corrected =
        Modes.stat_demodulated0 =
        Modes.stat_demodulated1 =
        Modes.stat_demodulated2 =
        Modes.stat_demodulated3 =
        Modes.stat_goodcrc =
        Modes.stat_badcrc =
        Modes.stat_fixed = 0;

    Modes.stat_out_of_phase =
        Modes.stat_ph_demodulated0 =
        Modes.stat_ph_demodulated1 =
        Modes.stat_ph_demodulated2 =
        Modes.stat_ph_demodulated3 =
        Modes.stat_ph_goodcrc =
        Modes.stat_ph_badcrc =
        Modes.stat_ph_fixed = 0;

    for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
        Modes.stat_ph_bit_fix[j] = 0;
        Modes.stat_bit_fix[j] = 0;
    }
}

//
//=========================================================================
//
// 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
//
void backgroundTasks(void) {
    static time_t next_stats;

    if (Modes.net) {
        modesReadFromClients();
    }    

    // If Modes.aircrafts is not NULL, remove any stale aircraft
    if (Modes.aircrafts) {
        interactiveRemoveStaleAircrafts();
    }

    // Refresh screen when in interactive mode
    if (Modes.interactive) {
        interactiveShowData();
    }

    if (Modes.stats > 0) {
        time_t now = time(NULL);
        if (now > next_stats) {
            if (next_stats != 0)
                display_stats();
            next_stats = now + Modes.stats;
        }
    }
}
//
//=========================================================================
//
int verbose_device_search(char *s)
{
        int i, device_count, device, offset;
        char *s2;
        char vendor[256], product[256], serial[256];
        device_count = rtlsdr_get_device_count();
        if (!device_count) {
                fprintf(stderr, "No supported devices found.\n");
                return -1;
        }
        fprintf(stderr, "Found %d device(s):\n", device_count);
        for (i = 0; i < device_count; i++) {
                rtlsdr_get_device_usb_strings(i, vendor, product, serial);
                fprintf(stderr, "  %d:  %s, %s, SN: %s\n", i, vendor, product, serial);
        }
        fprintf(stderr, "\n");
        /* does string look like raw id number */
        device = (int)strtol(s, &s2, 0);
        if (s2[0] == '\0' && device >= 0 && device < device_count) {
                fprintf(stderr, "Using device %d: %s\n",
                        device, rtlsdr_get_device_name((uint32_t)device));
                return device;
        }
        /* does string exact match a serial */
        for (i = 0; i < device_count; i++) {
                rtlsdr_get_device_usb_strings(i, vendor, product, serial);
                if (strcmp(s, serial) != 0) {
                        continue;}
                device = i;
                fprintf(stderr, "Using device %d: %s\n",
                        device, rtlsdr_get_device_name((uint32_t)device));
                return device;
        }
        /* does string prefix match a serial */
        for (i = 0; i < device_count; i++) {
                rtlsdr_get_device_usb_strings(i, vendor, product, serial);
                if (strncmp(s, serial, strlen(s)) != 0) {
                        continue;}
                device = i;
                fprintf(stderr, "Using device %d: %s\n",
                        device, rtlsdr_get_device_name((uint32_t)device));
                return device;
        }
        /* does string suffix match a serial */
        for (i = 0; i < device_count; i++) {
                rtlsdr_get_device_usb_strings(i, vendor, product, serial);
                offset = strlen(serial) - strlen(s);
                if (offset < 0) {
                        continue;}
                if (strncmp(s, serial+offset, strlen(s)) != 0) {
                        continue;}
                device = i;
                fprintf(stderr, "Using device %d: %s\n",
                        device, rtlsdr_get_device_name((uint32_t)device));
                return device;
        }
        fprintf(stderr, "No matching devices found.\n");
        return -1;
}
//
//=========================================================================
//
int main(int argc, char **argv) {
    int j;

    // Set sane defaults
    modesInitConfig();
    signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)

    // Parse the command line options
    for (j = 1; j < argc; j++) {
        int more = j+1 < argc; // There are more arguments

        if (!strcmp(argv[j],"--device-index") && more) {
            Modes.dev_index = verbose_device_search(argv[++j]);
        } else if (!strcmp(argv[j],"--gain") && more) {
            Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs
        } else if (!strcmp(argv[j],"--enable-agc")) {
            Modes.enable_agc++;
        } else if (!strcmp(argv[j],"--freq") && more) {
            Modes.freq = (int) strtoll(argv[++j],NULL,10);
        } else if (!strcmp(argv[j],"--ifile") && more) {
            Modes.filename = strdup(argv[++j]);
        } else if (!strcmp(argv[j],"--fix")) {
            Modes.nfix_crc = 1;
        } else if (!strcmp(argv[j],"--no-fix")) {
            Modes.nfix_crc = 0;
        } else if (!strcmp(argv[j],"--no-crc-check")) {
            Modes.check_crc = 0;
        } else if (!strcmp(argv[j],"--phase-enhance")) {
            Modes.phase_enhance = 1;
        } else if (!strcmp(argv[j],"--raw")) {
            Modes.raw = 1;
        } else if (!strcmp(argv[j],"--net")) {
            Modes.net = 1;
        } else if (!strcmp(argv[j],"--modeac")) {
            Modes.mode_ac = 1;
        } else if (!strcmp(argv[j],"--net-beast")) {
            Modes.beast = 1;
        } else if (!strcmp(argv[j],"--net-only")) {
            Modes.net = 1;
            Modes.net_only = 1;
       } else if (!strcmp(argv[j],"--net-heartbeat") && more) {
            Modes.net_heartbeat_rate = atoi(argv[++j]) * 15;
       } else if (!strcmp(argv[j],"--net-ro-size") && more) {
            Modes.net_output_raw_size = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--net-ro-rate") && more) {
            Modes.net_output_raw_rate = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--net-ro-port") && more) {
            if (Modes.beast) // Required for legacy backward compatibility
                {Modes.net_output_beast_port = atoi(argv[++j]);;}
            else
                {Modes.net_output_raw_port = atoi(argv[++j]);}
        } else if (!strcmp(argv[j],"--net-ri-port") && more) {
            Modes.net_input_raw_port = atoi(argv[++j]);
        } 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]);
        } else if (!strcmp(argv[j],"--net-bind-address") && more) {
            Modes.net_bind_address = strdup(argv[++j]);
        } else if (!strcmp(argv[j],"--net-http-port") && more) {
            Modes.net_http_port = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--net-sbs-port") && more) {
            Modes.net_output_sbs_port = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--net-buffer") && more) {
            Modes.net_sndbuf_size = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--onlyaddr")) {
            Modes.onlyaddr = 1;
        } else if (!strcmp(argv[j],"--metric")) {
            Modes.metric = 1;
        } else if (!strcmp(argv[j],"--aggressive")) {
            Modes.nfix_crc = MODES_MAX_BITERRORS;
        } else if (!strcmp(argv[j],"--interactive")) {
            Modes.interactive = 1;
        } else if (!strcmp(argv[j],"--interactive-rows") && more) {
            Modes.interactive_rows = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--interactive-ttl") && more) {
            Modes.interactive_display_ttl = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--lat") && more) {
            Modes.fUserLat = atof(argv[++j]);
        } else if (!strcmp(argv[j],"--lon") && more) {
            Modes.fUserLon = atof(argv[++j]);
        } else if (!strcmp(argv[j],"--debug") && more) {
            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++;
            }
        } else if (!strcmp(argv[j],"--stats")) {
            Modes.stats = -1;
        } else if (!strcmp(argv[j],"--stats-every") && more) {
            Modes.stats = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--snip") && more) {
            snipMode(atoi(argv[++j]));
            exit(0);
        } else if (!strcmp(argv[j],"--help")) {
            showHelp();
            exit(0);
        } else if (!strcmp(argv[j],"--ppm") && more) {
            Modes.ppm_error = atoi(argv[++j]);
        } else if (!strcmp(argv[j],"--quiet")) {
            Modes.quiet = 1;
        } else if (!strcmp(argv[j],"--mlat")) {
            Modes.mlat = 1;
        } else if (!strcmp(argv[j],"--interactive-rtl1090")) {
            Modes.interactive = 1;
            Modes.interactive_rtl1090 = 1;
        } else {
            fprintf(stderr,
                "Unknown or not enough arguments for option '%s'.\n\n",
                argv[j]);
            showHelp();
            exit(1);
        }
    }

#ifdef _WIN32
    // Try to comply with the Copyright license conditions for binary distribution
    if (!Modes.quiet) {showCopyright();}
#endif

#ifndef _WIN32
    // Setup for SIGWINCH for handling lines
    if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);}
#endif

    // Initialization
    modesInit();

    if (Modes.net_only) {
        fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
    } else if (Modes.filename == NULL) {
        modesInitRTLSDR();
    } else {
        if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
            Modes.fd = STDIN_FILENO;
        } else if ((Modes.fd = open(Modes.filename,
#ifdef _WIN32
                                    (O_RDONLY | O_BINARY)
#else
                                    (O_RDONLY)
#endif
                                    )) == -1) {
            perror("Opening data file");
            exit(1);
        }
    }
    if (Modes.net) modesInitNet();

    // If the user specifies --net-only, just run in order to serve network
    // clients without reading data from the RTL device
    while (Modes.net_only) {
        if (Modes.exit) exit(0); // If we exit net_only nothing further in main()
        backgroundTasks();
        usleep(100000);
    }

    // Create the thread that will read the data from the device.
    pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL);
    pthread_mutex_lock(&Modes.data_mutex);

    while (Modes.exit == 0) {

        if (Modes.iDataReady == 0) {
            pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); // This unlocks Modes.data_mutex, and waits for Modes.data_cond 
            continue;                                              // Once (Modes.data_cond) occurs, it locks Modes.data_mutex
        }

        // Modes.data_mutex is Locked, and (Modes.iDataReady != 0)
        if (Modes.iDataReady) { // Check we have new data, just in case!!

            Modes.iDataOut &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase

            // Translate the next lot of I/Q samples into Modes.magnitude
            computeMagnitudeVector(Modes.pData[Modes.iDataOut]);

            Modes.stSystemTimeBlk = Modes.stSystemTimeRTL[Modes.iDataOut];

            // Update the input buffer pointer queue
            Modes.iDataOut   = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut + 1); 
            Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);   

            // If we lost some blocks, correct the timestamp
            if (Modes.iDataLost) {
                Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost);
                Modes.stat_blocks_dropped += Modes.iDataLost;
                Modes.iDataLost = 0;
            }

            // It's safe to release the lock now
            pthread_cond_signal (&Modes.data_cond);
            pthread_mutex_unlock(&Modes.data_mutex);

            // Process data after releasing the lock, so that the capturing
            // thread can read data while we perform computationally expensive
            // stuff at the same time.
            detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES);

            // Update the timestamp ready for the next block
            Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6);
            Modes.stat_blocks_processed++;
        } else {
            pthread_cond_signal (&Modes.data_cond);
            pthread_mutex_unlock(&Modes.data_mutex);
        }

        backgroundTasks();
        pthread_mutex_lock(&Modes.data_mutex);
    }

    // If --stats were given, print statistics
    if (Modes.stats) {
        display_stats();
    }

    if (Modes.filename == NULL) {
        rtlsdr_cancel_async(Modes.dev);  // Cancel rtlsdr_read_async will cause data input thread to terminate cleanly
        rtlsdr_close(Modes.dev);
    }
    pthread_cond_destroy(&Modes.data_cond);     // Thread cleanup
    pthread_mutex_destroy(&Modes.data_mutex);
    pthread_join(Modes.reader_thread,NULL);     // Wait on reader thread exit
#ifndef _WIN32
    pthread_exit(0);
#else
    return (0);
#endif
}
//
//=========================================================================
//
daniyals48 commented 2 years ago

Thank you so much. I was wondering if have any time and you can help me with my college final years project? Since you have a lot of knowledge and I am newbie

On Thu, Sep 8, 2022, 8:53 PM Agent Smith @.***> wrote:

Here are my files: dump1090.h:

// dump1090, a Mode S messages decoder for RTLSDR devices. // // Copyright (C) 2012 by Salvatore Sanfilippo @.**> // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 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. //

ifndef __DUMP1090_H

define __DUMP1090_H

// File Version number // ==================== // Format is : MajorVer.MinorVer.DayMonth.Year" // MajorVer changes only with significant changes // MinorVer changes when additional features are added, but not for bug fixes (range 00-99) // DayDate & Year changes for all changes, including for bug fixes. It represent the release date of the update //

define MODES_DUMP1090_VERSION "1.10.3010.14"

// ============================= Include files ==========================

ifndef _WIN32

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "rtl-sdr.h"
#include "anet.h"

else

#include "winstubs.h" //Put everything Windows specific in here
#include "rtl-sdr.h"
#include "anet.h"

endif

// ============================= #defines =============================== // // If you have a valid coaa.h, these values will come from it. If not, // then you can enter your own values in the #else section here //

ifdef USER_LATITUDE

#define MODES_USER_LATITUDE_DFLT   (USER_LATITUDE)
#define MODES_USER_LONGITUDE_DFLT  (USER_LONGITUDE)

else

#define MODES_USER_LATITUDE_DFLT   (0.0)
#define MODES_USER_LONGITUDE_DFLT  (0.0)

endif

define MODES_DEFAULT_PPM 52

define MODES_DEFAULT_RATE 2000000

define MODES_DEFAULT_FREQ 1090000000

define MODES_DEFAULT_WIDTH 1000

define MODES_DEFAULT_HEIGHT 700

define MODES_ASYNC_BUF_NUMBER 16

define MODES_ASYNC_BUF_SIZE (16*16384) // 256k

define MODES_ASYNC_BUF_SAMPLES (MODES_ASYNC_BUF_SIZE / 2) // Each sample is 2 bytes

define MODES_AUTO_GAIN -100 // Use automatic gain

define MODES_MAX_GAIN 999999 // Use max available gain

define MODES_MSG_SQUELCH_LEVEL 0x02FF // Average signal strength limit

define MODES_MSG_ENCODER_ERRS 3 // Maximum number of encoding errors

// When changing, change also fixBitErrors() and modesInitErrorTable() !!

define MODES_MAX_BITERRORS 2 // Global max for fixable bit erros

define MODEAC_MSG_SAMPLES (25 * 2) // include up to the SPI bit

define MODEAC_MSG_BYTES 2

define MODEAC_MSG_SQUELCH_LEVEL 0x07FF // Average signal strength limit

define MODEAC_MSG_FLAG (1<<0)

define MODEAC_MSG_MODES_HIT (1<<1)

define MODEAC_MSG_MODEA_HIT (1<<2)

define MODEAC_MSG_MODEC_HIT (1<<3)

define MODEAC_MSG_MODEA_ONLY (1<<4)

define MODEAC_MSG_MODEC_OLD (1<<5)

define MODES_PREAMBLE_US 8 // microseconds = bits

define MODES_PREAMBLE_SAMPLES (MODES_PREAMBLE_US * 2)

define MODES_PREAMBLE_SIZE (MODES_PREAMBLE_SAMPLES * sizeof(uint16_t))

define MODES_LONG_MSG_BYTES 14

define MODES_SHORT_MSG_BYTES 7

define MODES_LONG_MSG_BITS (MODES_LONG_MSG_BYTES * 8)

define MODES_SHORT_MSG_BITS (MODES_SHORT_MSG_BYTES * 8)

define MODES_LONG_MSG_SAMPLES (MODES_LONG_MSG_BITS * 2)

define MODES_SHORT_MSG_SAMPLES (MODES_SHORT_MSG_BITS * 2)

define MODES_LONG_MSG_SIZE (MODES_LONG_MSG_SAMPLES * sizeof(uint16_t))

define MODES_SHORT_MSG_SIZE (MODES_SHORT_MSG_SAMPLES * sizeof(uint16_t))

define MODES_RAWOUT_BUF_SIZE (1500)

define MODES_RAWOUT_BUF_FLUSH (MODES_RAWOUT_BUF_SIZE - 200)

define MODES_RAWOUT_BUF_RATE (1000) // 1000 * 64mS = 1 Min approx

define MODES_ICAO_CACHE_LEN 1024 // Power of two required

define MODES_ICAO_CACHE_TTL 60 // Time to live of cached addresses

define MODES_UNIT_FEET 0

define MODES_UNIT_METERS 1

define MODES_USER_LATLON_VALID (1<<0)

define MODES_ACFLAGS_LATLON_VALID (1<<0) // Aircraft Lat/Lon is decoded

define MODES_ACFLAGS_ALTITUDE_VALID (1<<1) // Aircraft altitude is known

define MODES_ACFLAGS_HEADING_VALID (1<<2) // Aircraft heading is known

define MODES_ACFLAGS_SPEED_VALID (1<<3) // Aircraft speed is known

define MODES_ACFLAGS_VERTRATE_VALID (1<<4) // Aircraft vertical rate is known

define MODES_ACFLAGS_SQUAWK_VALID (1<<5) // Aircraft Mode A Squawk is known

define MODES_ACFLAGS_CALLSIGN_VALID (1<<6) // Aircraft Callsign Identity

define MODES_ACFLAGS_EWSPEED_VALID (1<<7) // Aircraft East West Speed is known

define MODES_ACFLAGS_NSSPEED_VALID (1<<8) // Aircraft North South Speed is known

define MODES_ACFLAGS_AOG (1<<9) // Aircraft is On the Ground

define MODES_ACFLAGS_LLEVEN_VALID (1<<10) // Aircraft Even Lot/Lon is known

define MODES_ACFLAGS_LLODD_VALID (1<<11) // Aircraft Odd Lot/Lon is known

define MODES_ACFLAGS_AOG_VALID (1<<12) // MODES_ACFLAGS_AOG is valid

define MODES_ACFLAGS_FS_VALID (1<<13) // Aircraft Flight Status is known

define MODES_ACFLAGS_NSEWSPD_VALID (1<<14) // Aircraft EW and NS Speed is known

define MODES_ACFLAGS_LATLON_REL_OK (1<<15) // Indicates it's OK to do a relative CPR

define MODES_ACFLAGS_LLEITHER_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)

define MODES_ACFLAGS_LLBOTH_VALID (MODES_ACFLAGS_LLEVEN_VALID | MODES_ACFLAGS_LLODD_VALID)

define MODES_ACFLAGS_AOG_GROUND (MODES_ACFLAGS_AOG_VALID | MODES_ACFLAGS_AOG)

define MODES_DEBUG_DEMOD (1<<0)

define MODES_DEBUG_DEMODERR (1<<1)

define MODES_DEBUG_BADCRC (1<<2)

define MODES_DEBUG_GOODCRC (1<<3)

define MODES_DEBUG_NOPREAMBLE (1<<4)

define MODES_DEBUG_NET (1<<5)

define MODES_DEBUG_JS (1<<6)

// When debug is set to MODES_DEBUG_NOPREAMBLE, the first sample must be // at least greater than a given level for us to dump the signal.

define MODES_DEBUG_NOPREAMBLE_LEVEL 25

define MODES_INTERACTIVE_REFRESH_TIME 250 // Milliseconds

define MODES_INTERACTIVE_ROWS 22 // Rows on screen

define MODES_INTERACTIVE_DELETE_TTL 300 // Delete from the list after 300 seconds

define MODES_INTERACTIVE_DISPLAY_TTL 60 // Delete from display after 60 seconds

define MODES_NET_HEARTBEAT_RATE 900 // Each block is approx 65mS - default is > 1 min

define MODES_NET_SERVICES_NUM 6

define MODES_NET_INPUT_RAW_PORT 30001

define MODES_NET_OUTPUT_RAW_PORT 30002

define MODES_NET_OUTPUT_SBS_PORT 30003

define MODES_NET_INPUT_BEAST_PORT 30004

define MODES_NET_OUTPUT_BEAST_PORT 30005

define MODES_NET_HTTP_PORT 8080

define MODES_CLIENT_BUF_SIZE 1024

define MODES_NET_SNDBUF_SIZE (1024*64)

define MODES_NET_SNDBUF_MAX (7)

ifndef HTMLPATH

define HTMLPATH "./public_html" // default path for gmap.html etc

endif

define MODES_NOTUSED(V) ((void) V)

//======================== structure declarations =========================

// Structure used to describe a networking client struct client { struct client* next; // Pointer to next client int fd; // File descriptor int service; // TCP port the client is connected to int buflen; // Amount of data on buffer char buf[MODES_CLIENT_BUF_SIZE+1]; // Read buffer };

// Structure used to describe an aircraft in iteractive mode struct aircraft { uint32_t addr; // ICAO address char flight[16]; // Flight number unsigned char signalLevel[8]; // Last 8 Signal Amplitudes int altitude; // Altitude int speed; // Velocity int track; // Angle of flight int vert_rate; // Vertical rate. time_t seen; // Time at which the last packet was received time_t seenLatLon; // Time at which the last lat long was calculated uint64_t timestamp; // Timestamp at which the last packet was received uint64_t timestampLatLon;// Timestamp at which the last lat long was calculated long messages; // Number of Mode S messages received int modeA; // Squawk int modeC; // Altitude long modeAcount; // Mode A Squawk hit Count long modeCcount; // Mode C Altitude hit Count int modeACflags; // Flags for mode A/C recognition

// Encoded latitude and longitude as extracted by odd and even CPR encoded messages
int           odd_cprlat;
int           odd_cprlon;
int           even_cprlat;
int           even_cprlon;
uint64_t      odd_cprtime;
uint64_t      even_cprtime;
double        lat, lon;       // Coordinated obtained from CPR encoded data
int           bFlags;         // Flags related to valid fields in this structure
struct aircraft *next;        // Next aircraft in our linked list

};

struct stDF { struct stDF pNext; // Pointer to next item in the linked list struct stDF pPrev; // Pointer to previous item in the linked list struct aircraft *pAircraft; // Pointer to the Aircraft structure for this DF time_t seen; // Dos/UNIX Time at which the this packet was received uint64_t llTimestamp; // Timestamp at which the this packet was received uint32_t addr; // Timestamp at which the this packet was received unsigned char msg[MODES_LONG_MSG_BYTES]; // the binary };

// Program global state struct stModes { // Internal state pthread_t reader_thread;

pthread_mutex_t data_mutex;      // Mutex to synchronize buffer access
pthread_cond_t  data_cond;       // Conditional variable associated
uint16_t       *pData          [MODES_ASYNC_BUF_NUMBER]; // Raw IQ sample buffers from RTL
struct timeb    stSystemTimeRTL[MODES_ASYNC_BUF_NUMBER]; // System time when RTL passed us this block
int             iDataIn;         // Fifo input pointer
int             iDataOut;        // Fifo output pointer
int             iDataReady;      // Fifo content count
int             iDataLost;       // Count of missed buffers

uint16_t       *pFileData;       // Raw IQ samples buffer (from a File)
uint16_t       *magnitude;       // Magnitude vector
uint64_t        timestampBlk;    // Timestamp of the start of the current block
struct timeb    stSystemTimeBlk; // System time when RTL passed us currently processing this block
int             fd;              // --ifile option file descriptor
uint32_t       *icao_cache;      // Recently seen ICAO addresses cache
uint16_t       *maglut;          // I/Q -> Magnitude lookup table
int             exit;            // Exit from the main loop when true

// RTLSDR
int           dev_index;
int           gain;
int           enable_agc;
rtlsdr_dev_t *dev;
int           freq;
int           ppm_error;

// Networking
char           aneterr[ANET_ERR_LEN];
struct client *clients;          // Our clients
int            sbsos;            // SBS output listening socket
int            ros;              // Raw output listening socket
int            ris;              // Raw input listening socket
int            bos;              // Beast output listening socket
int            bis;              // Beast input listening socket
int            https;            // HTTP listening socket
char          *rawOut;           // Buffer for building raw output data
int            rawOutUsed;       // How much of the buffer is currently used
char          *beastOut;         // Buffer for building beast output data
int            beastOutUsed;     // How much if the buffer is currently used

ifdef _WIN32

WSADATA        wsaData;          // Windows socket initialisation

endif

// Configuration
char *filename;                  // Input form file, --ifile option
int   phase_enhance;             // Enable phase enhancement if true
int   nfix_crc;                  // Number of crc bit error(s) to correct
int   check_crc;                 // Only display messages with good CRC
int   raw;                       // Raw output format
int   beast;                     // Beast binary format output
int   mode_ac;                   // Enable decoding of SSR Modes A & C
int   debug;                     // Debugging mode
int   net;                       // Enable networking
int   net_only;                  // Enable just networking
int   net_heartbeat_count;       // TCP heartbeat counter
int   net_heartbeat_rate;        // TCP heartbeat rate
int   net_output_sbs_port;       // SBS output TCP port
int   net_output_raw_size;       // Minimum Size of the output raw data
int   net_output_raw_rate;       // Rate (in 64mS increments) of output raw data
int   net_output_raw_rate_count; // Rate (in 64mS increments) of output raw data
int   net_output_raw_port;       // Raw output TCP port
int   net_input_raw_port;        // Raw input TCP port
int   net_output_beast_port;     // Beast output TCP port
int   net_input_beast_port;      // Beast input TCP port
char  *net_bind_address;         // Bind address
int   net_http_port;             // HTTP port
int   net_sndbuf_size;           // TCP output buffer size (64Kb * 2^n)
int   quiet;                     // Suppress stdout
int   interactive;               // Interactive mode
int   interactive_rows;          // Interactive mode: max number of rows
int   interactive_display_ttl;   // Interactive mode: TTL display
int   interactive_delete_ttl;    // Interactive mode: TTL before deletion
int   stats;                     // Print stats at exit in --ifile mode
int   onlyaddr;                  // Print only ICAO addresses
int   metric;                    // Use metric units
int   mlat;                      // Use Beast ascii format for raw data output, i.e. @...; iso *...;
int   interactive_rtl1090;       // flight table in interactive mode is formatted like RTL1090

// User details
double fUserLat;                // Users receiver/antenna lat/lon needed for initial surface location
double fUserLon;                // Users receiver/antenna lat/lon needed for initial surface location
int    bUserFlags;              // Flags relating to the user details

// Interactive mode
struct aircraft *aircrafts;
uint64_t         interactive_last_update; // Last screen update in milliseconds
time_t           last_cleanup_time;       // Last cleanup time in seconds

// DF List mode
int             bEnableDFLogging; // Set to enable DF Logging
pthread_mutex_t pDF_mutex;        // Mutex to synchronize pDF access
struct stDF    *pDF;              // Pointer to DF list

// Statistics
unsigned int stat_valid_preamble;
unsigned int stat_demodulated0;
unsigned int stat_demodulated1;
unsigned int stat_demodulated2;
unsigned int stat_demodulated3;
unsigned int stat_goodcrc;
unsigned int stat_badcrc;
unsigned int stat_fixed;

// Histogram of fixed bit errors: index 0 for single bit erros,
// index 1 for double bit errors etc.
unsigned int stat_bit_fix[MODES_MAX_BITERRORS];

unsigned int stat_http_requests;
unsigned int stat_sbs_connections;
unsigned int stat_raw_connections;
unsigned int stat_beast_connections;
unsigned int stat_out_of_phase;
unsigned int stat_ph_demodulated0;
unsigned int stat_ph_demodulated1;
unsigned int stat_ph_demodulated2;
unsigned int stat_ph_demodulated3;
unsigned int stat_ph_goodcrc;
unsigned int stat_ph_badcrc;
unsigned int stat_ph_fixed;
// Histogram of fixed bit errors: index 0 for single bit erros,
// index 1 for double bit errors etc.
unsigned int stat_ph_bit_fix[MODES_MAX_BITERRORS];

unsigned int stat_DF_Len_Corrected;
unsigned int stat_DF_Type_Corrected;
unsigned int stat_ModeAC;

unsigned int stat_blocks_processed;
unsigned int stat_blocks_dropped;

}; extern struct stModes Modes; extern struct stDF tDF;

// The struct we use to store information about a decoded message. struct modesMessage { // Generic fields unsigned char msg[MODES_LONG_MSG_BYTES]; // Binary message. int msgbits; // Number of bits in message int msgtype; // Downlink format # int crcok; // True if CRC was valid uint32_t crc; // Message CRC int correctedbits; // No. of bits corrected char corrected[MODES_MAX_BITERRORS]; // corrected bit positions uint32_t addr; // ICAO Address from bytes 1 2 and 3 int phase_corrected; // True if phase correction was applied uint64_t timestampMsg; // Timestamp of the message int remote; // If set this message is from a remote station unsigned char signalLevel; // Signal Amplitude

// DF 11
int  ca;                    // Responder capabilities
int  iid;

// DF 17, DF 18
int    metype;              // Extended squitter message type.
int    mesub;               // Extended squitter message subtype.
int    heading;             // Reported by aircraft, or computed from from EW and NS velocity
int    raw_latitude;        // Non decoded latitude.
int    raw_longitude;       // Non decoded longitude.
double fLat;                // Coordinates obtained from CPR encoded data if/when decoded
double fLon;                // Coordinates obtained from CPR encoded data if/when decoded
char   flight[16];          // 8 chars flight number.
int    ew_velocity;         // E/W velocity.
int    ns_velocity;         // N/S velocity.
int    vert_rate;           // Vertical rate.
int    velocity;            // Reported by aircraft, or computed from from EW and NS velocity

// DF4, DF5, DF20, DF21
int  fs;                    // Flight status for DF4,5,20,21
int  modeA;                 // 13 bits identity (Squawk).

// Fields used by multiple message types.
int  altitude;
int  unit;
int  bFlags;                // Flags related to fields in this structure

};

// ======================== function declarations =========================

ifdef __cplusplus

extern "C" {

endif

// // Functions exported from mode_ac.c // int detectModeA (uint16_t m, struct modesMessage mm); void decodeModeAMessage(struct modesMessage *mm, int ModeA); int ModeAToModeC (unsigned int ModeA);

// // Functions exported from mode_s.c // void detectModeS (uint16_t m, uint32_t mlen); void decodeModesMessage (struct modesMessage mm, unsigned char msg); void displayModesMessage(struct modesMessage mm); void useModesMessage (struct modesMessage mm); void computeMagnitudeVector(uint16_t pData); int decodeCPR (struct aircraft a, int fflag, int surface); int decodeCPRrelative (struct aircraft a, int fflag, int surface); void modesInitErrorInfo (); // // Functions exported from interactive.c // struct aircraft interactiveReceiveData(struct modesMessage mm); void interactiveShowData(void); void interactiveRemoveStaleAircrafts(void); int decodeBinMessage (struct client c, char p); struct aircraft interactiveFindAircraft(uint32_t addr); struct stDF interactiveFindDF (uint32_t addr);

// // Functions exported from net_io.c // void modesInitNet (void); void modesReadFromClients (void); void modesSendAllClients (int service, void msg, int len); void modesQueueOutput (struct modesMessage mm); void modesReadFromClient(struct client c, char sep, int(handler)(struct client , char *));

ifdef __cplusplus

}

endif

endif // __DUMP1090_H

dump1090.c:

// dump1090, a Mode S messages decoder for RTLSDR devices. // // Copyright (C) 2012 by Salvatore Sanfilippo @.**> // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 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. //

include "coaa.h"

include "dump1090.h"

struct stModes Modes; struct stDF tDF; // // ============================= Utility functions ========================== // void sigintHandler(int dummy) { MODES_NOTUSED(dummy); signal(SIGINT, SIG_DFL); // reset signal handler - bit extra safety Modes.exit = 1; // Signal to threads that we are done } // // =============================== 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

// // =============================== Initialization =========================== // void modesInitConfig(void) { // Default everything to zero/NULL memset(&Modes, 0, sizeof(Modes));

// Now initialise things that should not be 0/NULL to their defaults
Modes.gain                    = MODES_MAX_GAIN;
Modes.freq                    = MODES_DEFAULT_FREQ;
Modes.ppm_error               = MODES_DEFAULT_PPM;
Modes.check_crc               = 1;
Modes.net_heartbeat_rate      = MODES_NET_HEARTBEAT_RATE;
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;
Modes.interactive_rows        = getTermRows();
Modes.interactive_delete_ttl  = MODES_INTERACTIVE_DELETE_TTL;
Modes.interactive_display_ttl = MODES_INTERACTIVE_DISPLAY_TTL;
Modes.fUserLat                = MODES_USER_LATITUDE_DFLT;
Modes.fUserLon                = MODES_USER_LONGITUDE_DFLT;

} // //========================================================================= // void modesInit(void) { int i, q;

pthread_mutex_init(&Modes.pDF_mutex,NULL);
pthread_mutex_init(&Modes.data_mutex,NULL);
pthread_cond_init(&Modes.data_cond,NULL);

// Allocate the various buffers used by Modes
if ( ((Modes.icao_cache = (uint32_t *) malloc(sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2)                  ) == NULL) ||
     ((Modes.pFileData  = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE)                                         ) == NULL) ||
     ((Modes.magnitude  = (uint16_t *) malloc(MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE) ) == NULL) ||
     ((Modes.maglut     = (uint16_t *) malloc(sizeof(uint16_t) * 256 * 256)                                 ) == NULL) ||
     ((Modes.beastOut   = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) ||
     ((Modes.rawOut     = (char     *) malloc(MODES_RAWOUT_BUF_SIZE)                                        ) == NULL) )
{
    fprintf(stderr, "Out of memory allocating data buffer.\n");
    exit(1);
}

// Clear the buffers that have just been allocated, just in-case
memset(Modes.icao_cache, 0,   sizeof(uint32_t) * MODES_ICAO_CACHE_LEN * 2);
memset(Modes.pFileData,127,   MODES_ASYNC_BUF_SIZE);
memset(Modes.magnitude,  0,   MODES_ASYNC_BUF_SIZE+MODES_PREAMBLE_SIZE+MODES_LONG_MSG_SIZE);

// 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;
}

// Limit the maximum requested raw output size to less than one Ethernet Block
if (Modes.net_output_raw_size > (MODES_RAWOUT_BUF_FLUSH))
  {Modes.net_output_raw_size = MODES_RAWOUT_BUF_FLUSH;}
if (Modes.net_output_raw_rate > (MODES_RAWOUT_BUF_RATE))
  {Modes.net_output_raw_rate = MODES_RAWOUT_BUF_RATE;}
if (Modes.net_sndbuf_size > (MODES_NET_SNDBUF_MAX))
  {Modes.net_sndbuf_size = MODES_NET_SNDBUF_MAX;}

// Initialise the Block Timers to something half sensible
ftime(&Modes.stSystemTimeBlk);
for (i = 0; i < MODES_ASYNC_BUF_NUMBER; i++)
  {Modes.stSystemTimeRTL[i] = Modes.stSystemTimeBlk;}

// Each I and Q value varies from 0 to 255, which represents a range from -1 to +1. To get from the
// unsigned (0-255) range you therefore subtract 127 (or 128 or 127.5) from each I and Q, giving you
// a range from -127 to +128 (or -128 to +127, or -127.5 to +127.5)..
//
// To decode the AM signal, you need the magnitude of the waveform, which is given by sqrt((I^2)+(Q^2))
// The most this could be is if I&Q are both 128 (or 127 or 127.5), so you could end up with a magnitude
// of 181.019 (or 179.605, or 180.312)
//
// However, in reality the magnitude of the signal should never exceed the range -1 to +1, because the
// values are I = rCos(w) and Q = rSin(w). Therefore the integer computed magnitude should (can?) never
// exceed 128 (or 127, or 127.5 or whatever)
//
// If we scale up the results so that they range from 0 to 65535 (16 bits) then we need to multiply
// by 511.99, (or 516.02 or 514). antirez's original code multiplies by 360, presumably because he's
// assuming the maximim calculated amplitude is 181.019, and (181.019 * 360) = 65166.
//
// So lets see if we can improve things by subtracting 127.5, Well in integer arithmatic we can't
// subtract half, so, we'll double everything up and subtract one, and then compensate for the doubling
// in the multiplier at the end.
//
// If we do this we can never have I or Q equal to 0 - they can only be as small as +/- 1.
// This gives us a minimum magnitude of root 2 (0.707), so the dynamic range becomes (1.414-255). This
// also affects our scaling value, which is now 65535/(255 - 1.414), or 258.433254
//
// The sums then become mag = 258.433254 * (sqrt((I*2-255)^2 + (Q*2-255)^2) - 1.414)
//                   or mag = (258.433254 * sqrt((I*2-255)^2 + (Q*2-255)^2)) - 365.4798
//
// We also need to clip mag just incaes any rogue I/Q values somehow do have a magnitude greater than 255.
//

for (i = 0; i <= 255; i++) {
    for (q = 0; q <= 255; q++) {
        int mag, mag_i, mag_q;

        mag_i = (i * 2) - 255;
        mag_q = (q * 2) - 255;

        mag = (int) round((sqrt((mag_i*mag_i)+(mag_q*mag_q)) * 258.433254) - 365.4798);

        Modes.maglut[(i*256)+q] = (uint16_t) ((mag < 65535) ? mag : 65535);
    }
}

// Prepare error correction tables
modesInitErrorInfo();

} // // =============================== RTLSDR handling ========================== // void modesInitRTLSDR(void) { int j; int device_count; char vendor[256], product[256], serial[256];

device_count = rtlsdr_get_device_count();
if (!device_count) {
    fprintf(stderr, "No supported RTLSDR devices found.\n");
    exit(1);
}

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,
        (j == Modes.dev_index) ? "(currently selected)" : "");
}

if (rtlsdr_open(&Modes.dev, Modes.dev_index) < 0) {
    fprintf(stderr, "Error opening the RTLSDR device: %s\n",
        strerror(errno));
    exit(1);
}

// 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) {
    if (Modes.gain == MODES_MAX_GAIN) {
        // Find the maximum gain available
        int numgains;
        int gains[100];

        numgains = rtlsdr_get_tuner_gains(Modes.dev, gains);
        Modes.gain = gains[numgains-1];
        fprintf(stderr, "Max available gain is: %.2f\n", Modes.gain/10.0);
    }
    rtlsdr_set_tuner_gain(Modes.dev, Modes.gain);
    fprintf(stderr, "Setting gain to: %.2f\n", Modes.gain/10.0);
} else {
    fprintf(stderr, "Using automatic gain control.\n");
}
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);
rtlsdr_set_sample_rate(Modes.dev, MODES_DEFAULT_RATE);
rtlsdr_reset_buffer(Modes.dev);
fprintf(stderr, "Gain reported by device: %.2f\n",
    rtlsdr_get_tuner_gain(Modes.dev)/10.0);

} // //========================================================================= // // We use a thread reading data in background, while the main thread // handles decoding and visualization of data to the user. // // The reading thread calls the RTLSDR API to read data asynchronously, and // uses a callback to populate the data buffer. // // A Mutex is used to avoid races with the decoding thread. // void rtlsdrCallback(unsigned char buf, uint32_t len, void ctx) {

MODES_NOTUSED(ctx);

// Lock the data buffer variables before accessing them
pthread_mutex_lock(&Modes.data_mutex);

Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!

// Get the system time for this block
ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);

if (len > MODES_ASYNC_BUF_SIZE) {len = MODES_ASYNC_BUF_SIZE;}

// Queue the new data
Modes.pData[Modes.iDataIn] = (uint16_t *) buf;
Modes.iDataIn    = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1);
Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);

if (Modes.iDataReady == 0) {
  // Ooooops. We've just received the MODES_ASYNC_BUF_NUMBER'th outstanding buffer
  // This means that RTLSDR is currently overwriting the MODES_ASYNC_BUF_NUMBER+1
  // buffer, but we havent yet processed it, so we're going to lose it. There
  // isn't much we can do to recover the lost data, but we can correct things to
  // avoid any additional problems.
  Modes.iDataOut   = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut+1);
  Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1);
  Modes.iDataLost++;
}

// Signal to the other thread that new data is ready, and unlock
pthread_cond_signal(&Modes.data_cond);
pthread_mutex_unlock(&Modes.data_mutex);

} // //========================================================================= // // This is used when --ifile is specified in order to read data from file // instead of using an RTLSDR device // void readDataFromFile(void) { pthread_mutex_lock(&Modes.data_mutex); while(Modes.exit == 0) { ssize_t nread, toread; unsigned char *p;

    if (Modes.iDataReady) {
        pthread_cond_wait(&Modes.data_cond, &Modes.data_mutex);
        continue;
    }

    if (Modes.interactive) {
        // When --ifile and --interactive are used together, slow down
        // playing at the natural rate of the RTLSDR received.
        pthread_mutex_unlock(&Modes.data_mutex);
        usleep(64000);
        pthread_mutex_lock(&Modes.data_mutex);
    }

    toread = MODES_ASYNC_BUF_SIZE;
    p = (unsigned char *) Modes.pFileData;
    while(toread) {
        nread = read(Modes.fd, p, toread);
        if (nread <= 0) {
            Modes.exit = 1; // Signal the other threads to exit.
            break;
        }
        p += nread;
        toread -= nread;
    }
    if (toread) {
        // Not enough data on file to fill the buffer? Pad with no signal.
        memset(p,127,toread);
    }

    Modes.iDataIn &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase!!!

    // Get the system time for this block
    ftime(&Modes.stSystemTimeRTL[Modes.iDataIn]);

    // Queue the new data
    Modes.pData[Modes.iDataIn] = Modes.pFileData;
    Modes.iDataIn    = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn + 1);
    Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);

    // Signal to the other thread that new data is ready
    pthread_cond_signal(&Modes.data_cond);
}

} // //========================================================================= // // We read data using a thread, so the main thread only handles decoding // without caring about data acquisition // void readerThreadEntryPoint(void arg) { MODES_NOTUSED(arg);

if (Modes.filename == NULL) {
    rtlsdr_read_async(Modes.dev, rtlsdrCallback, NULL,
                          MODES_ASYNC_BUF_NUMBER,
                          MODES_ASYNC_BUF_SIZE);
} else {
    readDataFromFile();
}
// Signal to the other thread that new data is ready - dummy really so threads don't mutually lock
pthread_cond_signal(&Modes.data_cond);
pthread_mutex_unlock(&Modes.data_mutex);

ifndef _WIN32

pthread_exit(NULL);

else

return NULL;

endif

} // // ============================== Snip mode ================================= // // Get raw IQ samples and filter everything is < than the specified level // for more than 256 samples in order to reduce example file size // void snipMode(int level) { int i, q; uint64_t c = 0;

while ((i = getchar()) != EOF && (q = getchar()) != EOF) {
    if (abs(i-127) < level && abs(q-127) < level) {
        c++;
        if (c > MODES_PREAMBLE_SIZE) continue;
    } else {
        c = 0;
    }
    putchar(i);
    putchar(q);
}

} // // ================================ Main ==================================== // void showHelp(void) { printf( "-----------------------------------------------------------------------------\n" "| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" "-----------------------------------------------------------------------------\n" "--device-index Select RTL device (default: 0)\n" "--gain Set gain (default: max gain. Use -10 for auto-gain)\n" "--enable-agc Enable the Automatic Gain Control (default: off)\n" "--freq Set frequency (default: 1090 Mhz)\n" "--ifile Read data from file (use '-' for stdin)\n" "--interactive Interactive mode refreshing data on screen\n" "--interactive-rows Max number of rows in interactive mode (default: 15)\n" "--interactive-ttl Remove from list if idle for (default: 60)\n" "--interactive-rtl1090 Display flight table in RTL1090 format\n" "--raw Show only messages hex values\n" "--net Enable networking\n" "--modeac Enable decoding of SSR Modes 3/A & 3/C\n" "--net-beast TCP raw output in Beast binary format\n" "--net-only Enable just networking, no RTL device or file used\n" "--net-bind-address IP address to bind to (default: Any; Use 127.0.0.1 for private)\n" "--net-http-port HTTP server port (default: 8080)\n" "--net-ri-port TCP raw input listen port (default: 30001)\n" "--net-ro-port TCP raw output listen port (default: 30002)\n" "--net-sbs-port TCP BaseStation output listen port (default: 30003)\n" "--net-bi-port TCP Beast input listen port (default: 30004)\n" "--net-bo-port TCP Beast output listen port (default: 30005)\n" "--net-ro-size TCP raw output minimum size (default: 0)\n" "--net-ro-rate TCP raw output memory flush rate (default: 0)\n" "--net-heartbeat TCP heartbeat rate in seconds (default: 60 sec; 0 to disable)\n" "--net-buffer TCP buffer size 64Kb * (2^n) (default: n=0, 64Kb)\n" "--lat Reference/receiver latitude for surface posn (opt)\n" "--lon Reference/receiver longitude for surface posn (opt)\n" "--fix Enable single-bits error correction using CRC\n" "--no-fix Disable single-bits error correction using CRC\n" "--no-crc-check Disable messages with broken CRC (discouraged)\n" "--phase-enhance Enable phase enhancement\n" "--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" "--stats-every Show and reset stats every seconds\n" "--onlyaddr Show only ICAO addresses (testing purposes)\n" "--metric Use metric units (meters, km/h, ...)\n" "--snip Strip IQ file removing samples < level\n" "--debug Debug mode (verbose), see README for details\n" "--quiet Disable output to stdout. Use for daemon applications\n" "--ppm Set receiver error in parts per million (default 0)\n" "--help Show this help\n" "\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" " j = Log frames to frames.js, loadable by debug.html\n" ); }

ifdef _WIN32

void showCopyright(void) { uint64_t llTime = time(NULL) + 1;

printf(

"-----------------------------------------------------------------------------\n" "| dump1090 ModeS Receiver Ver : " MODES_DUMP1090_VERSION " |\n" "-----------------------------------------------------------------------------\n" "\n" " Copyright (C) 2012 by Salvatore Sanfilippo @.>\n" " Copyright (C) 2014 by Malcolm Robb @.>\n" "\n" " All rights reserved.\n" "\n" " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" " ""AS IS"" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" " LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" " A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" " HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" " SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" " LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" " DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" " THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" " (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" " OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" "\n" " For further details refer to https://github.com/MalcolmRobb/dump1090\n" "\n" );

// delay for 1 second to give the user a chance to read the copyright while (llTime >= time(NULL)) {} }

endif

static void display_stats(void) { int j; time_t now = time(NULL);

printf("\n\n");
if (Modes.interactive)
    interactiveShowData();

printf("Statistics as at %s", ctime(&now));

printf("%d sample blocks processed\n",                    Modes.stat_blocks_processed);
printf("%d sample blocks dropped\n",                      Modes.stat_blocks_dropped);

printf("%d ModeA/C detected\n",                           Modes.stat_ModeAC);
printf("%d valid Mode-S preambles\n",                     Modes.stat_valid_preamble);
printf("%d DF-?? fields corrected for length\n",          Modes.stat_DF_Len_Corrected);
printf("%d DF-?? fields corrected for type\n",            Modes.stat_DF_Type_Corrected);
printf("%d demodulated with 0 errors\n",                  Modes.stat_demodulated0);
printf("%d demodulated with 1 error\n",                   Modes.stat_demodulated1);
printf("%d demodulated with 2 errors\n",                  Modes.stat_demodulated2);
printf("%d demodulated with > 2 errors\n",                Modes.stat_demodulated3);
printf("%d with good crc\n",                              Modes.stat_goodcrc);
printf("%d with bad crc\n",                               Modes.stat_badcrc);
printf("%d errors corrected\n",                           Modes.stat_fixed);

for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
    printf("   %d with %d bit %s\n", Modes.stat_bit_fix[j], j+1, (j==0)?"error":"errors");
}

if (Modes.phase_enhance) {
    printf("%d phase enhancement attempts\n",                 Modes.stat_out_of_phase);
    printf("%d phase enhanced demodulated with 0 errors\n",   Modes.stat_ph_demodulated0);
    printf("%d phase enhanced demodulated with 1 error\n",    Modes.stat_ph_demodulated1);
    printf("%d phase enhanced demodulated with 2 errors\n",   Modes.stat_ph_demodulated2);
    printf("%d phase enhanced demodulated with > 2 errors\n", Modes.stat_ph_demodulated3);
    printf("%d phase enhanced with good crc\n",               Modes.stat_ph_goodcrc);
    printf("%d phase enhanced with bad crc\n",                Modes.stat_ph_badcrc);
    printf("%d phase enhanced errors corrected\n",            Modes.stat_ph_fixed);

    for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
        printf("   %d with %d bit %s\n", Modes.stat_ph_bit_fix[j], j+1, (j==0)?"error":"errors");
    }
}

printf("%d total usable messages\n",                      Modes.stat_goodcrc + Modes.stat_ph_goodcrc + Modes.stat_fixed + Modes.stat_ph_fixed);
fflush(stdout);

Modes.stat_blocks_processed =
    Modes.stat_blocks_dropped = 0;

Modes.stat_ModeAC =
    Modes.stat_valid_preamble =
    Modes.stat_DF_Len_Corrected =
    Modes.stat_DF_Type_Corrected =
    Modes.stat_demodulated0 =
    Modes.stat_demodulated1 =
    Modes.stat_demodulated2 =
    Modes.stat_demodulated3 =
    Modes.stat_goodcrc =
    Modes.stat_badcrc =
    Modes.stat_fixed = 0;

Modes.stat_out_of_phase =
    Modes.stat_ph_demodulated0 =
    Modes.stat_ph_demodulated1 =
    Modes.stat_ph_demodulated2 =
    Modes.stat_ph_demodulated3 =
    Modes.stat_ph_goodcrc =
    Modes.stat_ph_badcrc =
    Modes.stat_ph_fixed = 0;

for (j = 0;  j < MODES_MAX_BITERRORS;  j++) {
    Modes.stat_ph_bit_fix[j] = 0;
    Modes.stat_bit_fix[j] = 0;
}

}

// //========================================================================= // // 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 // void backgroundTasks(void) { static time_t next_stats;

if (Modes.net) {
    modesReadFromClients();
}

// If Modes.aircrafts is not NULL, remove any stale aircraft
if (Modes.aircrafts) {
    interactiveRemoveStaleAircrafts();
}

// Refresh screen when in interactive mode
if (Modes.interactive) {
    interactiveShowData();
}

if (Modes.stats > 0) {
    time_t now = time(NULL);
    if (now > next_stats) {
        if (next_stats != 0)
            display_stats();
        next_stats = now + Modes.stats;
    }
}

} // //========================================================================= // int verbose_device_search(char s) { int i, device_count, device, offset; char s2; char vendor[256], product[256], serial[256]; device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported devices found.\n"); return -1; } fprintf(stderr, "Found %d device(s):\n", device_count); for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); } fprintf(stderr, "\n"); / does string look like raw id number / device = (int)strtol(s, &s2, 0); if (s2[0] == '\0' && device >= 0 && device < device_count) { fprintf(stderr, "Using device %d: %s\n", device, rtlsdr_get_device_name((uint32_t)device)); return device; } / does string exact match a serial / for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); if (strcmp(s, serial) != 0) { continue;} device = i; fprintf(stderr, "Using device %d: %s\n", device, rtlsdr_get_device_name((uint32_t)device)); return device; } / does string prefix match a serial / for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); if (strncmp(s, serial, strlen(s)) != 0) { continue;} device = i; fprintf(stderr, "Using device %d: %s\n", device, rtlsdr_get_device_name((uint32_t)device)); return device; } / does string suffix match a serial / for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); offset = strlen(serial) - strlen(s); if (offset < 0) { continue;} if (strncmp(s, serial+offset, strlen(s)) != 0) { continue;} device = i; fprintf(stderr, "Using device %d: %s\n", device, rtlsdr_get_device_name((uint32_t)device)); return device; } fprintf(stderr, "No matching devices found.\n"); return -1; } // //========================================================================= // int main(int argc, char **argv) { int j;

// Set sane defaults
modesInitConfig();
signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program)

// Parse the command line options
for (j = 1; j < argc; j++) {
    int more = j+1 < argc; // There are more arguments

    if (!strcmp(argv[j],"--device-index") && more) {
        Modes.dev_index = verbose_device_search(argv[++j]);
    } else if (!strcmp(argv[j],"--gain") && more) {
        Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs
    } else if (!strcmp(argv[j],"--enable-agc")) {
        Modes.enable_agc++;
    } else if (!strcmp(argv[j],"--freq") && more) {
        Modes.freq = (int) strtoll(argv[++j],NULL,10);
    } else if (!strcmp(argv[j],"--ifile") && more) {
        Modes.filename = strdup(argv[++j]);
    } else if (!strcmp(argv[j],"--fix")) {
        Modes.nfix_crc = 1;
    } else if (!strcmp(argv[j],"--no-fix")) {
        Modes.nfix_crc = 0;
    } else if (!strcmp(argv[j],"--no-crc-check")) {
        Modes.check_crc = 0;
    } else if (!strcmp(argv[j],"--phase-enhance")) {
        Modes.phase_enhance = 1;
    } else if (!strcmp(argv[j],"--raw")) {
        Modes.raw = 1;
    } else if (!strcmp(argv[j],"--net")) {
        Modes.net = 1;
    } else if (!strcmp(argv[j],"--modeac")) {
        Modes.mode_ac = 1;
    } else if (!strcmp(argv[j],"--net-beast")) {
        Modes.beast = 1;
    } else if (!strcmp(argv[j],"--net-only")) {
        Modes.net = 1;
        Modes.net_only = 1;
   } else if (!strcmp(argv[j],"--net-heartbeat") && more) {
        Modes.net_heartbeat_rate = atoi(argv[++j]) * 15;
   } else if (!strcmp(argv[j],"--net-ro-size") && more) {
        Modes.net_output_raw_size = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--net-ro-rate") && more) {
        Modes.net_output_raw_rate = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--net-ro-port") && more) {
        if (Modes.beast) // Required for legacy backward compatibility
            {Modes.net_output_beast_port = atoi(argv[++j]);;}
        else
            {Modes.net_output_raw_port = atoi(argv[++j]);}
    } else if (!strcmp(argv[j],"--net-ri-port") && more) {
        Modes.net_input_raw_port = atoi(argv[++j]);
    } 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]);
    } else if (!strcmp(argv[j],"--net-bind-address") && more) {
        Modes.net_bind_address = strdup(argv[++j]);
    } else if (!strcmp(argv[j],"--net-http-port") && more) {
        Modes.net_http_port = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--net-sbs-port") && more) {
        Modes.net_output_sbs_port = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--net-buffer") && more) {
        Modes.net_sndbuf_size = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--onlyaddr")) {
        Modes.onlyaddr = 1;
    } else if (!strcmp(argv[j],"--metric")) {
        Modes.metric = 1;
    } else if (!strcmp(argv[j],"--aggressive")) {
        Modes.nfix_crc = MODES_MAX_BITERRORS;
    } else if (!strcmp(argv[j],"--interactive")) {
        Modes.interactive = 1;
    } else if (!strcmp(argv[j],"--interactive-rows") && more) {
        Modes.interactive_rows = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--interactive-ttl") && more) {
        Modes.interactive_display_ttl = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--lat") && more) {
        Modes.fUserLat = atof(argv[++j]);
    } else if (!strcmp(argv[j],"--lon") && more) {
        Modes.fUserLon = atof(argv[++j]);
    } else if (!strcmp(argv[j],"--debug") && more) {
        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++;
        }
    } else if (!strcmp(argv[j],"--stats")) {
        Modes.stats = -1;
    } else if (!strcmp(argv[j],"--stats-every") && more) {
        Modes.stats = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--snip") && more) {
        snipMode(atoi(argv[++j]));
        exit(0);
    } else if (!strcmp(argv[j],"--help")) {
        showHelp();
        exit(0);
    } else if (!strcmp(argv[j],"--ppm") && more) {
        Modes.ppm_error = atoi(argv[++j]);
    } else if (!strcmp(argv[j],"--quiet")) {
        Modes.quiet = 1;
    } else if (!strcmp(argv[j],"--mlat")) {
        Modes.mlat = 1;
    } else if (!strcmp(argv[j],"--interactive-rtl1090")) {
        Modes.interactive = 1;
        Modes.interactive_rtl1090 = 1;
    } else {
        fprintf(stderr,
            "Unknown or not enough arguments for option '%s'.\n\n",
            argv[j]);
        showHelp();
        exit(1);
    }
}

ifdef _WIN32

// Try to comply with the Copyright license conditions for binary distribution
if (!Modes.quiet) {showCopyright();}

endif

ifndef _WIN32

// Setup for SIGWINCH for handling lines
if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);}

endif

// Initialization
modesInit();

if (Modes.net_only) {
    fprintf(stderr,"Net-only mode, no RTL device or file open.\n");
} else if (Modes.filename == NULL) {
    modesInitRTLSDR();
} else {
    if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') {
        Modes.fd = STDIN_FILENO;
    } else if ((Modes.fd = open(Modes.filename,

ifdef _WIN32

                                (O_RDONLY | O_BINARY)

else

                                (O_RDONLY)

endif

                                )) == -1) {
        perror("Opening data file");
        exit(1);
    }
}
if (Modes.net) modesInitNet();

// If the user specifies --net-only, just run in order to serve network
// clients without reading data from the RTL device
while (Modes.net_only) {
    if (Modes.exit) exit(0); // If we exit net_only nothing further in main()
    backgroundTasks();
    usleep(100000);
}

// Create the thread that will read the data from the device.
pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL);
pthread_mutex_lock(&Modes.data_mutex);

while (Modes.exit == 0) {

    if (Modes.iDataReady == 0) {
        pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); // This unlocks Modes.data_mutex, and waits for Modes.data_cond
        continue;                                              // Once (Modes.data_cond) occurs, it locks Modes.data_mutex
    }

    // Modes.data_mutex is Locked, and (Modes.iDataReady != 0)
    if (Modes.iDataReady) { // Check we have new data, just in case!!

        Modes.iDataOut &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase

        // Translate the next lot of I/Q samples into Modes.magnitude
        computeMagnitudeVector(Modes.pData[Modes.iDataOut]);

        Modes.stSystemTimeBlk = Modes.stSystemTimeRTL[Modes.iDataOut];

        // Update the input buffer pointer queue
        Modes.iDataOut   = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut + 1);
        Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut);

        // If we lost some blocks, correct the timestamp
        if (Modes.iDataLost) {
            Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost);
            Modes.stat_blocks_dropped += Modes.iDataLost;
            Modes.iDataLost = 0;
        }

        // It's safe to release the lock now
        pthread_cond_signal (&Modes.data_cond);
        pthread_mutex_unlock(&Modes.data_mutex);

        // Process data after releasing the lock, so that the capturing
        // thread can read data while we perform computationally expensive
        // stuff at the same time.
        detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES);

        // Update the timestamp ready for the next block
        Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6);
        Modes.stat_blocks_processed++;
    } else {
        pthread_cond_signal (&Modes.data_cond);
        pthread_mutex_unlock(&Modes.data_mutex);
    }

    backgroundTasks();
    pthread_mutex_lock(&Modes.data_mutex);
}

// If --stats were given, print statistics
if (Modes.stats) {
    display_stats();
}

if (Modes.filename == NULL) {
    rtlsdr_cancel_async(Modes.dev);  // Cancel rtlsdr_read_async will cause data input thread to terminate cleanly
    rtlsdr_close(Modes.dev);
}
pthread_cond_destroy(&Modes.data_cond);     // Thread cleanup
pthread_mutex_destroy(&Modes.data_mutex);
pthread_join(Modes.reader_thread,NULL);     // Wait on reader thread exit

ifndef _WIN32

pthread_exit(0);

else

return (0);

endif

} // //========================================================================= //

— Reply to this email directly, view it on GitHub https://github.com/antirez/dump1090/issues/165#issuecomment-1240907119, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUXXJDYA3GQJ2ZJLMKQZNMTV5IDYRANCNFSM5E2WDMGQ . You are receiving this because you commented.Message ID: @.***>

AgentSmith0 commented 2 years ago

@daniyals48 I don't think I am the right person for that, but I am sure you will find someone else. (-: I also recommended reading articles or doing other kind of researches to find solutions or learn new things.

gx1400 commented 1 year ago

This resolved for me as well on an rPi4 8GB

  1. Open dump1090.h file

  2. Go to line 238 and change to just };

  3. Go to line 241 and change to struct stModes {

  4. Go to line 373 and change to just }; 4a. Insert a line below line 373 and paste extern struct stModes Modes; extern struct stDF tDF;

  5. Open dump1090.c file

  6. Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF;

  7. Open view1090.c file

  8. Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF;

  9. Run make -B

daniyals48 commented 1 year ago

Thank you for your steps... I test these steps for learning but I found an easy solution for this... I used dragon OS which has the newer version and it supports this feature by default. 😊😊

On Wed, Nov 16, 2022, 2:16 AM gx1400 @.***> wrote:

This resolved for me as well on an rPi4 8GB

1.

Open dump1090.h file 2.

Go to line 238 and change to just }; 3.

Go to line 241 and change to struct stModes { 4.

Go to line 373 and change to just }; 4a. Insert a line below line 373 and paste extern struct stModes Modes; extern struct stDF tDF; 5.

Open dump1090.c file 6.

Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF; 7.

Open view1090.c file 8.

Insert a line below line 31 and paste struct stModes Modes; struct stDF tDF; 9.

Run make -B

— Reply to this email directly, view it on GitHub https://github.com/antirez/dump1090/issues/165#issuecomment-1315873955, or unsubscribe https://github.com/notifications/unsubscribe-auth/AUXXJD2Y5DMMZ7X7HUIFIO3WIP4TNANCNFSM5E2WDMGQ . You are receiving this because you were mentioned.Message ID: @.***>