From b656896f668c7887bbf2cefb2047fe9078de5ae2 Mon Sep 17 00:00:00 2001 From: Steve Markgraf Date: Tue, 29 Jan 2013 00:30:09 +0100 Subject: lib: remove "e.g. hama nano" from the default device description This caused some confusion... Signed-off-by: Steve Markgraf --- src/librtlsdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 4224163..b0185d2 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -229,7 +229,7 @@ typedef struct rtlsdr_dongle { * Please add your device here and send a patch to osmocom-sdr@lists.osmocom.org */ static rtlsdr_dongle_t known_devices[] = { - { 0x0bda, 0x2832, "Generic RTL2832U (e.g. hama nano)" }, + { 0x0bda, 0x2832, "Generic RTL2832U" }, { 0x0bda, 0x2838, "ezcap USB 2.0 DVB-T/DAB/FM dongle" }, { 0x0ccd, 0x00a9, "Terratec Cinergy T Stick Black (rev 1)" }, { 0x0ccd, 0x00b3, "Terratec NOXON DAB/DAB+ USB dongle (rev 1)" }, -- cgit v1.3.1 From c6a731a0dcff882edb4777a816865f525966464d Mon Sep 17 00:00:00 2001 From: Kyle Keen Date: Tue, 29 Jan 2013 20:31:49 -0500 Subject: rtl_adsb: 16 bit magnitudes Signed-off-by: Steve Markgraf --- src/rtl_adsb.c | 92 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 49 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c index 2fb7418..a625d31 100644 --- a/src/rtl_adsb.c +++ b/src/rtl_adsb.c @@ -54,16 +54,19 @@ #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 sem_t data_ready; static volatile int do_exit = 0; static rtlsdr_dev_t *dev = NULL; -/* look up table, could be made smaller */ -uint8_t pyth[129][129]; +uint16_t squares[256]; /* todo, bundle these up in a struct */ -uint8_t *buffer; +uint8_t *buffer; /* also abused for uint16_t */ int verbose_output = 0; int short_output = 0; double quality = 1.0; @@ -141,17 +144,7 @@ void display(int *frame, int len) fprintf(file, "--------------\n"); } -void pyth_precompute(void) -{ - int x, y; - double scale = 1.408 ; /* use the full 8 bits */ - for (x=0; x<129; x++) { - for (y=0; y<129; y++) { - pyth[x][y] = (uint8_t)round(scale * sqrt(x*x + y*y)); - }} -} - -inline uint8_t abs8(uint8_t x) +int abs8(int x) /* do not subtract 128 from the raw iq, this handles it */ { if (x >= 128) { @@ -159,18 +152,31 @@ inline uint8_t abs8(uint8_t x) return 128 - 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, returns new 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; @@ -181,9 +187,9 @@ inline uint8_t single_manchester(uint8_t a, uint8_t b, uint8_t c, uint8_t d) if (quality == 0.5) { if ( bit && bit_p && b > c) { - return 255;} + return BADSAMPLE;} if (!bit && !bit_p && b < c) { - return 255;} + return BADSAMPLE;} return bit; } @@ -196,7 +202,7 @@ inline uint8_t single_manchester(uint8_t a, uint8_t b, uint8_t c, uint8_t d) return 0;} if (!bit && !bit_p && c < b) { return 0;} - return 255; + return BADSAMPLE; } if ( bit && bit_p && c > b && d < a) { @@ -207,36 +213,36 @@ inline uint8_t single_manchester(uint8_t a, uint8_t b, uint8_t c, uint8_t d) return 0;} if (!bit && !bit_p && c < b && d > a) { return 0;} - return 255; + return BADSAMPLE; } -inline uint8_t min8(uint8_t a, uint8_t b) +inline uint16_t min16(uint16_t a, uint16_t b) { return ab ? a : b; } -inline int preamble(uint8_t *buf, int len, int i) +inline int preamble(uint16_t *buf, int i) /* returns 0/1 for preamble at index i */ { int i2; - uint8_t low = 0; - uint8_t high = 255; + uint16_t low = 0; + uint16_t high = 65535; for (i2=0; i2 allowed_errors) { - buf[i2] = 255; + buf[i2] = BADSAMPLE; break; } else { bit = a > b; /* these don't have to match the bit */ a = 0; - b = 255; + b = 65535; } } - buf[i] = buf[i+1] = 254; /* to be overwritten */ + buf[i] = buf[i+1] = OVERWRITE; buf[i2] = bit; } } } -void messages(uint8_t *buf, int len) +void messages(uint16_t *buf, int len) { int i, i2, start, preamble_found; int data_i, index, shift, frame_len; @@ -343,8 +349,8 @@ static void *demod_thread_fn(void *arg) while (!do_exit) { sem_wait(&data_ready); len = magnitute(buffer, DEFAULT_BUF_LENGTH); - manchester(buffer, len); - messages(buffer, len); + manchester((uint16_t*)buffer, len); + messages((uint16_t*)buffer, len); } rtlsdr_cancel_async(dev); return 0; @@ -363,7 +369,7 @@ int main(int argc, char **argv) int ppm_error = 0; char vendor[256], product[256], serial[256]; sem_init(&data_ready, 0, 0); - pyth_precompute(); + squares_precompute(); while ((opt = getopt(argc, argv, "d:g:p:e:Q:VS")) != -1) { -- cgit v1.3.1 From c85cab2dae0ed59e244a2160fa632596c9707eb9 Mon Sep 17 00:00:00 2001 From: Kyle Keen Date: Tue, 29 Jan 2013 21:38:27 -0500 Subject: rtl_fm: Miroslav Slugeň's atan lut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Steve Markgraf --- src/rtl_fm.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 75 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 45f8e06..8009876 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -72,6 +72,10 @@ static int do_exit = 0; static rtlsdr_dev_t *dev = NULL; static int lcm_post[17] = {1,1,1,3,1,5,3,7,1,9,5,11,3,13,7,15,1}; +static int *atan_lut = NULL; +static int atan_lut_size = 131072; /* 512 KB */ +static int atan_lut_coef = 8; + struct fm_state { int now_r; @@ -128,7 +132,7 @@ void usage(void) "\t[-E sets lower edge tuning (default: center)]\n" "\t[-N enables NBFM mode (default: on)]\n" "\t[-W enables WBFM mode (default: off)]\n" - "\t (-N -s 170k -o 4 -A -r 32k -l 0 -D)\n" + "\t (-N -s 170k -o 4 -A fast -r 32k -l 0 -D)\n" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n\n" "Experimental options:\n" @@ -142,7 +146,7 @@ void usage(void) "\t[-R enables raw mode (default: off, 2x16 bit output)]\n" "\t[-F enables high quality FIR (default: off/square)]\n" "\t[-D enables de-emphasis (default: off)]\n" - "\t[-A enables high speed arctan (default: off)]\n\n" + "\t[-A std/fast/lut choose atan math (default: std)]\n\n" "Produces signed 16 bit ints, use Sox or aplay to hear them.\n" "\trtl_fm ... - | play -t raw -r 24k -e signed-integer -b 16 -c 1 -V1 -\n" "\t | aplay -r 24k -f S16_LE -t raw -c 1\n" @@ -343,6 +347,57 @@ int polar_disc_fast(int ar, int aj, int br, int bj) return fast_atan2(cj, cr); } +int atan_lut_init() +{ + int i = 0; + + atan_lut = malloc(atan_lut_size * sizeof(int)); + + for (i = 0; i < atan_lut_size; i++) { + atan_lut[i] = (int) (atan((double) i / (1< 0) + {return 1 << 13;} + if (cr == 0 && cj < 0) + {return -(1 << 13);} + if (cj == 0 && cr > 0) + {return 0;} + if (cj == 0 && cr < 0) + {return 1 << 14;} + } + + /* real range -32768 - 32768 use 64x range -> absolute maximum: 2097152 */ + x = (cj << atan_lut_coef) / cr; + x_abs = abs(x); + + if (x_abs >= atan_lut_size) { + /* we can use linear range, but it is not necessary */ + return (cj > 0) ? 1<<13 : -1<<13; + } + + if (x > 0) { + return (cj > 0) ? atan_lut[x] : atan_lut[x] - (1<<14); + } else { + return (cj > 0) ? (1<<14) - atan_lut[-x] : -atan_lut[-x]; + } + + return 0; +} + void fm_demod(struct fm_state *fm) { int i, pcm; @@ -350,12 +405,19 @@ void fm_demod(struct fm_state *fm) fm->pre_r, fm->pre_j); fm->signal2[0] = (int16_t)pcm; for (i = 2; i < (fm->signal_len); i += 2) { - if (fm->custom_atan) { + switch (fm->custom_atan) { + case 0: + pcm = polar_discriminant(fm->signal[i], fm->signal[i+1], + fm->signal[i-2], fm->signal[i-1]); + break; + case 1: pcm = polar_disc_fast(fm->signal[i], fm->signal[i+1], fm->signal[i-2], fm->signal[i-1]); - } else { - pcm = polar_discriminant(fm->signal[i], fm->signal[i+1], + break; + case 2: + pcm = polar_disc_lut(fm->signal[i], fm->signal[i+1], fm->signal[i-2], fm->signal[i-1]); + break; } fm->signal2[i/2] = (int16_t)pcm; } @@ -640,7 +702,7 @@ int main(int argc, char **argv) fm.mode_demod = &fm_demod; sem_init(&data_ready, 0, 0); - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFANWMULRD")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFA:NWMULRD")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); @@ -688,7 +750,13 @@ int main(int argc, char **argv) fm.fir_enable = 1; break; case 'A': - fm.custom_atan = 1; + if (strcmp("std", optarg) == 0) { + fm.custom_atan = 0;} + if (strcmp("fast", optarg) == 0) { + fm.custom_atan = 1;} + if (strcmp("lut", optarg) == 0) { + atan_lut_init(); + fm.custom_atan = 2;} break; case 'D': fm.deemph = 1; -- cgit v1.3.1 From e8e735caf4786d55e65cff4bcff7b34c71b6d552 Mon Sep 17 00:00:00 2001 From: Kyle Keen Date: Tue, 29 Jan 2013 23:05:09 -0500 Subject: rtl_fm: bugfixes from TonberryKing Signed-off-by: Steve Markgraf --- src/rtl_fm.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 8009876..4bf7eef 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -672,6 +672,32 @@ void frequency_range(struct fm_state *fm, char *arg) step[-1] = ':'; } +void fm_init(struct fm_state *fm) +{ + fm->freqs[0] = 100000000; + fm->sample_rate = DEFAULT_SAMPLE_RATE; + fm->squelch_level = 0; + fm->conseq_squelch = 20; + fm->terminate_on_squelch = 0; + fm->squelch_hits = 0; + fm->freq_len = 0; + fm->edge = 0; + fm->fir_enable = 0; + fm->prev_index = 0; + fm->post_downsample = 1; // once this works, default = 4 + fm->custom_atan = 0; + fm->deemph = 0; + fm->output_rate = -1; // flag for disabled + fm->mode_demod = &fm_demod; + fm->pre_j = 0; + fm->pre_r = 0; + fm->now_r = 0; + fm->now_j = 0; + fm->prev_lpr_index = 0; + fm->deemph_a = 0; + fm->now_lpr = 0; +} + int main(int argc, char **argv) { #ifndef _WIN32 @@ -686,20 +712,7 @@ int main(int argc, char **argv) int device_count; int ppm_error = 0; char vendor[256], product[256], serial[256]; - fm.freqs[0] = 100000000; - fm.sample_rate = DEFAULT_SAMPLE_RATE; - fm.squelch_level = 0; - fm.conseq_squelch = 20; - fm.terminate_on_squelch = 0; - fm.freq_len = 0; - fm.edge = 0; - fm.fir_enable = 0; - fm.prev_index = 0; - fm.post_downsample = 1; // once this works, default = 4 - fm.custom_atan = 0; - fm.deemph = 0; - fm.output_rate = -1; // flag for disabled - fm.mode_demod = &fm_demod; + fm_init(&fm); sem_init(&data_ready, 0, 0); while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFA:NWMULRD")) != -1) { @@ -794,6 +807,11 @@ int main(int argc, char **argv) /* quadruple sample_rate to limit to Δθ to ±π/2 */ fm.sample_rate *= fm.post_downsample; + if (fm.freq_len == 0) { + fprintf(stderr, "Please specify a frequency.\n"); + exit(1); + } + if (fm.freq_len > 1) { fm.terminate_on_squelch = 0; } -- cgit v1.3.1 From 8d358b44d4f0c85ee2c3397df45b844068547588 Mon Sep 17 00:00:00 2001 From: Kyle Keen Date: Wed, 30 Jan 2013 00:33:11 -0500 Subject: rtl_fm: dc block from TonberryKing Signed-off-by: Steve Markgraf --- src/rtl_fm.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 4bf7eef..b3525cf 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -78,18 +78,13 @@ static int atan_lut_coef = 8; struct fm_state { - int now_r; - int now_j; - int pre_r; - int pre_j; + int now_r, now_j; + int pre_r, pre_j; int prev_index; int downsample; /* min 1, max 256 */ int post_downsample; int output_scale; - int squelch_level; - int conseq_squelch; - int squelch_hits; - int terminate_on_squelch; + int squelch_level, conseq_squelch, squelch_hits, terminate_on_squelch; int exit_flag; uint8_t buf[MAXIMUM_BUF_LENGTH]; uint32_t buf_len; @@ -108,10 +103,10 @@ struct fm_state int fir[256]; /* fir_len == downsample */ int fir_sum; int custom_atan; - int deemph; - int deemph_a; + int deemph, deemph_a; int now_lpr; int prev_lpr_index; + int dc_block, dc_avg; void (*mode_demod)(struct fm_state*); }; @@ -146,6 +141,7 @@ void usage(void) "\t[-R enables raw mode (default: off, 2x16 bit output)]\n" "\t[-F enables high quality FIR (default: off/square)]\n" "\t[-D enables de-emphasis (default: off)]\n" + "\t[-C enables DC blocking of output (default: off)]\n" "\t[-A std/fast/lut choose atan math (default: std)]\n\n" "Produces signed 16 bit ints, use Sox or aplay to hear them.\n" "\trtl_fm ... - | play -t raw -r 24k -e signed-integer -b 16 -c 1 -V1 -\n" @@ -488,6 +484,21 @@ void deemph_filter(struct fm_state *fm) } } +void dc_block_filter(struct fm_state *fm) +{ + int i, avg; + int64_t sum = 0; + for (i=0; i < fm->signal2_len; i++) { + sum += fm->signal2[i]; + } + avg = sum / fm->signal2_len; + avg = (avg + fm->dc_avg * 9) / 10; + for (i=0; i < fm->signal2_len; i++) { + fm->signal2[i] -= avg; + } + fm->dc_avg = avg; +} + int mad(int *samples, int len, int step) /* mean average deviation */ { @@ -591,6 +602,8 @@ void full_demod(struct fm_state *fm) } if (fm->deemph) { deemph_filter(fm);} + if (fm->dc_block) { + dc_block_filter(fm);} /* ignore under runs for now */ fwrite(fm->signal2, 2, fm->signal2_len, fm->file); if (hop) { @@ -689,13 +702,12 @@ void fm_init(struct fm_state *fm) fm->deemph = 0; fm->output_rate = -1; // flag for disabled fm->mode_demod = &fm_demod; - fm->pre_j = 0; - fm->pre_r = 0; - fm->now_r = 0; - fm->now_j = 0; + fm->pre_j = fm->pre_r = fm->now_r = fm->now_j = 0; fm->prev_lpr_index = 0; fm->deemph_a = 0; fm->now_lpr = 0; + fm->dc_block = 0; + fm->dc_avg = 0; } int main(int argc, char **argv) @@ -715,7 +727,7 @@ int main(int argc, char **argv) fm_init(&fm); sem_init(&data_ready, 0, 0); - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFA:NWMULRD")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFA:NWMULRDC")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); @@ -774,6 +786,9 @@ int main(int argc, char **argv) case 'D': fm.deemph = 1; break; + case 'C': + fm.dc_block = 1; + break; case 'N': fm.mode_demod = &fm_demod; break; -- cgit v1.3.1 From ea4dbd242d268e50163acb8df1ac662485b43632 Mon Sep 17 00:00:00 2001 From: Kyle Keen Date: Wed, 30 Jan 2013 17:40:00 -0500 Subject: rtl_fm: osx does not like semaphores Signed-off-by: Steve Markgraf --- src/rtl_adsb.c | 14 ++++++-------- src/rtl_fm.c | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c index a625d31..44b62e2 100644 --- a/src/rtl_adsb.c +++ b/src/rtl_adsb.c @@ -37,7 +37,6 @@ #include "getopt/getopt.h" #endif -#include #include #include @@ -59,7 +58,7 @@ #define BADSAMPLE 255 static pthread_t demod_thread; -static sem_t data_ready; +static pthread_mutex_t data_ready; /* locked when no data available */ static volatile int do_exit = 0; static rtlsdr_dev_t *dev = NULL; @@ -334,20 +333,18 @@ void messages(uint16_t *buf, int len) static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { - int dr_val; if (do_exit) { return;} memcpy(buffer, buf, len); - sem_getvalue(&data_ready, &dr_val); - if (dr_val <= 0) { - sem_post(&data_ready);} + pthread_mutex_trylock(&data_ready); + pthread_mutex_unlock(&data_ready); } static void *demod_thread_fn(void *arg) { int len; while (!do_exit) { - sem_wait(&data_ready); + pthread_mutex_lock(&data_ready); len = magnitute(buffer, DEFAULT_BUF_LENGTH); manchester((uint16_t*)buffer, len); messages((uint16_t*)buffer, len); @@ -368,7 +365,7 @@ int main(int argc, char **argv) int device_count; int ppm_error = 0; char vendor[256], product[256], serial[256]; - sem_init(&data_ready, 0, 0); + pthread_mutex_init(&data_ready, NULL); squares_precompute(); while ((opt = getopt(argc, argv, "d:g:p:e:Q:VS")) != -1) @@ -507,6 +504,7 @@ int main(int argc, char **argv) else { fprintf(stderr, "\nLibrary error %d, exiting...\n", r);} rtlsdr_cancel_async(dev); + pthread_mutex_destroy(&data_ready); if (file != stdout) { fclose(file);} diff --git a/src/rtl_fm.c b/src/rtl_fm.c index b3525cf..e8ebb77 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -3,6 +3,7 @@ * Copyright (C) 2012 by Steve Markgraf * Copyright (C) 2012 by Hoernchen * Copyright (C) 2012 by Kyle Keen + * Copyright (C) 2013 by Elias Oenal * * 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 @@ -53,7 +54,6 @@ #define round(x) (x > 0.0 ? floor(x + 0.5): ceil(x - 0.5)) #endif -#include #include #include @@ -67,7 +67,8 @@ #define AUTO_GAIN -100 static pthread_t demod_thread; -static sem_t data_ready; +static pthread_mutex_t data_ready; /* locked when no fresh data available */ +static pthread_mutex_t data_write; /* locked when r/w buffer */ static int do_exit = 0; static rtlsdr_dev_t *dev = NULL; static int lcm_post[17] = {1,1,1,3,1,5,3,7,1,9,5,11,3,13,7,15,1}; @@ -579,6 +580,7 @@ void full_demod(struct fm_state *fm) } else { low_pass(fm, fm->buf, fm->buf_len); } + pthread_mutex_unlock(&data_write); fm->mode_demod(fm); if (fm->mode_demod == &raw_demod) { fwrite(fm->signal2, 2, fm->signal2_len, fm->file); @@ -619,25 +621,23 @@ void full_demod(struct fm_state *fm) static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { struct fm_state *fm2 = ctx; - int dr_val; if (do_exit) { return;} if (!ctx) { return;} + pthread_mutex_lock(&data_write); memcpy(fm2->buf, buf, len); fm2->buf_len = len; + pthread_mutex_unlock(&data_ready); /* single threaded uses 25% less CPU? */ /* full_demod(fm2); */ - sem_getvalue(&data_ready, &dr_val); - if (dr_val <= 0) { - sem_post(&data_ready);} } static void *demod_thread_fn(void *arg) { struct fm_state *fm2 = arg; while (!do_exit) { - sem_wait(&data_ready); + pthread_mutex_lock(&data_ready); full_demod(fm2); if (fm2->exit_flag) { do_exit = 1; @@ -725,7 +725,8 @@ int main(int argc, char **argv) int ppm_error = 0; char vendor[256], product[256], serial[256]; fm_init(&fm); - sem_init(&data_ready, 0, 0); + pthread_mutex_init(&data_ready, NULL); + pthread_mutex_init(&data_write, NULL); while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFA:NWMULRDC")) != -1) { switch (opt) { @@ -929,6 +930,8 @@ int main(int argc, char **argv) else { fprintf(stderr, "\nLibrary error %d, exiting...\n", r);} rtlsdr_cancel_async(dev); + pthread_mutex_destroy(&data_ready); + pthread_mutex_destroy(&data_write); if (fm.file != stdout) { fclose(fm.file);} -- cgit v1.3.1