aboutsummaryrefslogtreecommitdiffstats
path: root/src/rtl_fm.c
diff options
context:
space:
mode:
authorKyle Keen <keenerd@gmail.com>2012-05-30 10:54:18 -0400
committerSteve Markgraf <steve@steve-m.de>2012-07-17 20:42:03 +0200
commitc3dde1db9198a2cb552f11dde6dc1b4446bbed8d (patch)
treed22a29840bf0273e62b2b1fafbcfc82bf1c31a45 /src/rtl_fm.c
parentdefa7af74b93b7f62ef727e777cbf1b37a3e4568 (diff)
rtl_fm: multithreaded and frequency scanning
Signed-off-by: Steve Markgraf <steve@steve-m.de>
Diffstat (limited to 'src/rtl_fm.c')
-rw-r--r--src/rtl_fm.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/src/rtl_fm.c b/src/rtl_fm.c
index fc58497..c48e4d6 100644
--- a/src/rtl_fm.c
+++ b/src/rtl_fm.c
@@ -1,6 +1,8 @@
/*
* rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver
* Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
+ * Copyright (C) 2012 by Hoernchen <la@tfc-server.de>
+ * Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com>
*
* 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
@@ -20,14 +22,12 @@
/*
* written because people could not do real time
* FM demod on Atom hardware with GNU radio
- * based on rtl_sdr.c
+ * based on rtl_sdr.c and rtl_tcp.c
* todo: realtime ARMv5
* remove float math (disqualifies complex.h)
* replace atan2 with a fast approximation
* in-place array operations
* wide band support
- * refactor to look like rtl_tcp
- * multiple frequency scanning
*/
#include <errno.h>
@@ -43,6 +43,10 @@
#include <Windows.h>
#endif
+#include <semaphore.h>
+#include <pthread.h>
+#include <libusb.h>
+
#include "rtl-sdr.h"
#define DEFAULT_SAMPLE_RATE 24000
@@ -51,6 +55,8 @@
#define MINIMAL_BUF_LENGTH 512
#define MAXIMAL_BUF_LENGTH (256 * 16384)
+static pthread_t demod_thread;
+static sem_t data_ready;
static int do_exit = 0;
static rtlsdr_dev_t *dev = NULL;
@@ -64,6 +70,8 @@ struct fm_state
int downsample; /* min 4, max 256 */
int output_scale;
int squelch_level;
+ uint8_t buf[DEFAULT_BUF_LENGTH];
+ uint32_t buf_len;
int signal[2048]; /* 16 bit signed i/q pairs */
int16_t signal2[2048]; /* signal has lowpass, signal2 has demod */
int signal_len;
@@ -92,7 +100,7 @@ void usage(void)
"\t[-l squelch_level (default: 150)]\n"
"\t[-E freq sets lower edge (default: center)]\n"
"\tfilename (a '-' dumps samples to stdout)\n\n"
- "Produces signed 16 bit ints, use sox to hear them.\n"
+ "Produces signed 16 bit ints, use Sox to hear them.\n"
"\trtl_fm ... | play -t raw -r 24k -e signed-integer -b 16 -c 1 -\n\n");
#endif
exit(1);
@@ -258,14 +266,9 @@ static void optimal_settings(struct fm_state *fm, int freq, int hopping)
}
-static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
+void full_demod(unsigned char *buf, uint32_t len, struct fm_state *fm2)
{
- struct fm_state *fm2;
int sr, freq_next;
- if (!ctx) {
- return;
- }
- fm2 = (struct fm_struct*)(ctx); // warning?
rotate_90(buf, len);
low_pass(fm2, buf, len);
fm_demod(fm2);
@@ -275,14 +278,41 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
if (fm2->freq_len > 1 && !sr) {
freq_next = (fm2->freq_now + 1) % fm2->freq_len;
optimal_settings(fm2, freq_next, 1);
- rtlsdr_reset_buffer(dev);
- //rtlsdr_read_async(dev, rtlsdr_callback, ctx,
- // DEFAULT_ASYNC_BUF_NUMBER, DEFAULT_BUF_LENGTH);
- //rtlsdr_wait_async(dev, rtlsdr_callback, (void *)0);
- //rtlsdr_wait_async(dev, rtlsdr_callback, ctx);
+ // wait for settling and dump buffer
+ usleep(5000);
+ rtlsdr_read_sync(dev, NULL, 4096, NULL);
}
}
+static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
+{
+ struct fm_state *fm2;
+ int dr_val;
+ if (do_exit) {
+ return;}
+ if (!ctx) {
+ return;}
+ fm2 = (struct fm_struct*)(ctx); // warning?
+ //full_demod(buf, len, fm2);
+ memcpy(fm2->buf, buf, len);
+ fm2->buf_len = len;
+ sem_getvalue(&data_ready, &dr_val);
+ if (!dr_val) {
+ sem_post(&data_ready);}
+}
+
+static void *demod_thread_fn(void *arg)
+{
+ struct fm_state *fm2;
+ int r = 0;
+ fm2 = (struct fm_struct*)(arg); // warning?
+ while (!do_exit) {
+ sem_wait(&data_ready);
+ full_demod(fm2->buf, fm2->buf_len, fm2);
+ }
+ return 0;
+}
+
int main(int argc, char **argv)
{
#ifndef _WIN32
@@ -295,13 +325,13 @@ int main(int argc, char **argv)
int i, gain = -10; // tenths of a dB
uint8_t *buffer;
uint32_t dev_index = 0;
- uint32_t out_block_size = DEFAULT_BUF_LENGTH;
int device_count;
char vendor[256], product[256], serial[256];
fm.freqs[0] = 100000000;
fm.sample_rate = DEFAULT_SAMPLE_RATE;
fm.squelch_level = 150;
fm.freq_len = 0;
+ sem_init(&data_ready, 0, 0);
#ifndef _WIN32
while ((opt = getopt(argc, argv, "d:f:g:s:b:l:E::")) != -1) {
switch (opt) {
@@ -345,9 +375,9 @@ int main(int argc, char **argv)
fm.freq_len = 1;
filename = argv[5];
#endif
- out_block_size = DEFAULT_BUF_LENGTH;
- buffer = malloc(out_block_size * sizeof(uint8_t));
+ buffer = malloc(DEFAULT_BUF_LENGTH * sizeof(uint8_t));
+ //buffer = fm.buf;
device_count = rtlsdr_get_device_count();
if (!device_count) {
@@ -406,9 +436,9 @@ int main(int argc, char **argv)
if (r < 0)
fprintf(stderr, "WARNING: Failed to reset buffers.\n");
- fprintf(stderr, "Reading samples in async mode...\n");
- r = rtlsdr_read_async(dev, rtlsdr_callback, (void *)(&fm),
- DEFAULT_ASYNC_BUF_NUMBER, out_block_size);
+ pthread_create(&demod_thread, NULL, demod_thread_fn, (void *)(&fm));
+ rtlsdr_read_async(dev, rtlsdr_callback, (void *)(&fm),
+ DEFAULT_ASYNC_BUF_NUMBER, DEFAULT_BUF_LENGTH);
if (do_exit)
fprintf(stderr, "\nUser cancel, exiting...\n");