/* * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver * Copyright (C) 2012 by Steve Markgraf * Copyright (C) 2012 by Hoernchen * Copyright (C) 2012 by Kyle Keen * Copyright (C) 2012 by Youssef Touil * Copyright (C) 2012 by Ian Gilmour * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #ifndef _WIN32 #include #else #include #include #include #include "getopt/getopt.h" #endif #include #include #include "rtl-sdr.h" #include "convenience/convenience.h" #ifdef _WIN32 #define sleep Sleep #if defined(_MSC_VER) && (_MSC_VER < 1800) #define round(x) (x > 0.0 ? floor(x + 0.5): ceil(x - 0.5)) #endif #endif #define ADSB_RATE 2000000 #define ADSB_FREQ 1090000000 #define DEFAULT_ASYNC_BUF_NUMBER 12 #define DEFAULT_BUF_LENGTH (16 * 16384) #define AUTO_GAIN -100 #define MESSAGEGO 253 #define OVERWRITE 254 #define BADSAMPLE 255 static pthread_t demod_thread; static pthread_cond_t ready; static pthread_mutex_t ready_m; static volatile int do_exit = 0; static rtlsdr_dev_t *dev = NULL; uint16_t squares[256]; /* todo, bundle these up in a struct */ uint8_t *buffer; /* also abused for uint16_t */ int verbose_output = 0; int short_output = 0; int quality = 10; int allowed_errors = 5; FILE *file; int adsb_frame[14]; #define preamble_len 16 #define long_frame 112 #define short_frame 56 /* signals are not threadsafe by default */ #define safe_cond_signal(n, m) pthread_mutex_lock(m); pthread_cond_signal(n); pthread_mutex_unlock(m) #define safe_cond_wait(n, m) pthread_mutex_lock(m); pthread_cond_wait(n, m); pthread_mutex_unlock(m) void usage(void) { fprintf(stderr, "rtl_adsb, a simple ADS-B decoder\n\n" "Use:\trtl_adsb [-R] [-g gain] [-p ppm] [output file]\n" "\t[-d device_index or serial (default: 0)]\n" "\t[-V verbove output (default: off)]\n" "\t[-S show short frames (default: off)]\n" "\t[-Q quality (0: no sanity checks, 0.5: half bit, 1: one bit (default), 2: two bits)]\n" "\t[-e allowed_errors (default: 5)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-p ppm_error (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n\n" "Streaming with netcat:\n" "\trtl_adsb | netcat -lp 8080\n" "\twhile true; do rtl_adsb | nc -lp 8080; done\n" "Streaming with socat:\n" "\trtl_adsb | socat -u - TCP4:sdrsharp.com:47806\n" "\n"); exit(1); } #ifdef _WIN32 BOOL WINAPI sighandler(int signum) { if (CTRL_C_EVENT == signum) { fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dev); return TRUE; } return FALSE; } #else static void sighandler(int signum) { signal(SIGPIPE, SIG_IGN); fprintf(stderr, "Signal caught, exiting!\n"); do_exit = 1; rtlsdr_cancel_async(dev); } #endif void display(int *frame, int len) { int i, df; if (!short_output && len <= short_frame) { return;} df = (frame[0] >> 3) & 0x1f; if (quality == 0 && !(df==11 || df==17 || df==18 || df==19)) { return;} fprintf(file, "*"); for (i=0; i<((len+7)/8); i++) { fprintf(file, "%02x", frame[i]);} fprintf(file, ";\r\n"); if (!verbose_output) { return;} fprintf(file, "DF=%i CA=%i\n", df, frame[0] & 0x07); fprintf(file, "ICAO Address=%06x\n", frame[1] << 16 | frame[2] << 8 | frame[3]); if (len <= short_frame) { return;} fprintf(file, "PI=0x%06x\n", frame[11] << 16 | frame[12] << 8 | frame[13]); fprintf(file, "Type Code=%i S.Type/Ant.=%x\n", (frame[4] >> 3) & 0x1f, frame[4] & 0x07); fprintf(file, "--------------\n"); } int abs8(int x) /* do not subtract 127 from the raw iq, this handles it */ { if (x >= 127) { return x - 127;} return 127 - x; } void squares_precompute(void) /* equiv to abs(x-128) ^ 2 */ { int i, j; // todo, check if this LUT is actually any faster for (i=0; i<256; i++) { j = abs8(i); squares[i] = (uint16_t)(j*j); } } int magnitute(uint8_t *buf, int len) /* takes i/q, changes buf in place (16 bit), returns new len (16 bit) */ { int i; uint16_t *m; for (i=0; i b; bit = c > d; if (quality == 0) { return bit;} if (quality == 5) { if ( bit && bit_p && b > c) { return BADSAMPLE;} if (!bit && !bit_p && b < c) { return BADSAMPLE;} return bit; } if (quality == 10) { if ( bit && bit_p && c > b) { return 1;} if ( bit && !bit_p && d < b) { return 1;} if (!bit && bit_p && d > b) { return 0;} if (!bit && !bit_p && c < b) { return 0;} return BADSAMPLE; } if ( bit && bit_p && c > b && d < a) { return 1;} if ( bit && !bit_p && c > a && d < b) { return 1;} if (!bit && bit_p && c < a && d > b) { return 0;} if (!bit && !bit_p && c < b && d > a) { return 0;} return BADSAMPLE; } static inline uint16_t min16(uint16_t a, uint16_t b) { return ab ? a : b; } static inline int preamble(uint16_t *buf, int i) /* returns 0/1 for preamble at index i */ { int i2; uint16_t low = 0; uint16_t high = 65535; for (i2=0; i2 allowed_errors) { buf[i2] = BADSAMPLE; break; } else { bit = a > b; /* these don't have to match the bit */ a = 0; b = 65535; } } buf[i] = buf[i+1] = OVERWRITE; buf[i2] = bit; } } } void messages(uint16_t *buf, int len) { int i, data_i, index, shift, frame_len; // todo, allow wrap across buffers for (i=0; i 1) { continue;} frame_len = long_frame; data_i = 0; for (index=0; index<14; index++) { adsb_frame[index] = 0;} for(; i= 0 ? r : -r; }