Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Decoder #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ To use this on very slow systems it helps to increase the priority of rtl_sdr an
This approach requires ```pv``` to also be installed.
With the priority increase and buffering the Raspberry PI for example can demodulate 2 to 3 channels at the same time as long as they do not transmit for many minutes at a time.

### Custom Decoder

Instead of saving each channel to a file, a custom decoder can be specified. The command receives two arguments: The frequency and the time elapsed since the start. The following example shows a simple wrapper script to decode AFSK1200 on the fly:

$ cat decode.sh
#!/bin/sh
rtl_fm -f $1 -s 22050 -P -C -i 46 -t 5 - | multimon-ng -t raw -c -a AFSK1200 -A >$1-$2.log
$ rtl_sdr -f ... | fm_multimix -f ... -c ./decode.sh


Warning
-------
Expand Down
75 changes: 39 additions & 36 deletions demod_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/wait.h>
#include "fft.h"
#include "demod_proc.h"

demodproc* bin_list[FFT_LEN];
demodproc* short_proc_list[FFT_LEN];
int process_count=0;

int create_process(int bin, long long int totalread, int filter_sub, int center_freq, int fast, int squelch)
int create_process(int bin, long long int totalread, int filter_sub, int center_freq, int fast, int squelch, char* command)
{
int i;
int in[2], out[2], pid;
Expand All @@ -44,8 +45,6 @@ int create_process(int bin, long long int totalread, int filter_sub, int center_

if((pid=fork()) == 0)
{
char cmdstring[255];
int filt_bot;
char datestr[200];
time_t t;
struct tm *tmp;
Expand All @@ -62,56 +61,60 @@ int create_process(int bin, long long int totalread, int filter_sub, int center_

close(in[0]);
close(out[1]);
if(filter_sub)
{
filt_bot=300;
}
else
{
filt_bot=0;
}

t = time(NULL);
tmp = gmtime(&t);
if (tmp == NULL) {
perror("gmtime");
exit(EXIT_FAILURE);
}
// ISO8601 date/time format
if (strftime(datestr, sizeof(datestr), "%FT%TZ", tmp) == 0) {
if (strftime(datestr, sizeof(datestr), "%Y%m%d-%H%M%S", tmp) == 0) {
fprintf(stderr, "strftime returned 0");
exit(EXIT_FAILURE);
}

if(fast)
int frequency = (bin-(FFT_LEN/2))*SAMP_RATE/FFT_LEN+center_freq;
long long int elapsed = totalread/SAMP_RATE/2;

if(command)
{
char frequency_str[20];
char elapsed_str[20];
snprintf(frequency_str, 20, "%d", frequency);
snprintf(elapsed_str, 20, "%lld", elapsed);

fprintf(stderr, "Starting decoder: %s %s %s\n", command, frequency_str, elapsed_str);
execlp(command, command, frequency_str, elapsed_str, (char*)NULL);
}
else if(fast)
{
char squelch_str[20];
char filestr[255];
snprintf(filestr, 255, "%d_%s_%lld.pcm", (bin-(FFT_LEN/2))*SAMP_RATE/FFT_LEN+center_freq, datestr, totalread/SAMP_RATE/2);
snprintf(filestr, 255, "%d_%s_%lld.pcm", frequency, datestr, elapsed);
snprintf(squelch_str, 20, "%d", squelch);
fprintf(stderr, "writing raw 22050Hz 16bit audio to %s\n", filestr);
execlp("rtl_fm", "rtl_fm", "-s", "22050", "-P", "-C", "-i", "46", "-t", "5", "-l", squelch_str, filestr, (char*)NULL);

perror("Failed to start child process");
exit(1);
fprintf(stderr, "Writing raw 22050Hz 16bit audio to %s\n", filestr);
execlp("rtl_fm", "rtl_fm", "-s", "22050", "-P", "-C", "-i", "46", "-t", "5", "-l", squelch_str, filestr, (char*)NULL);
}
else
{
fprintf(stderr, "writing audio to %d_%s_%lld.wav\n", (bin-(FFT_LEN/2))*SAMP_RATE/FFT_LEN+center_freq, datestr, totalread/SAMP_RATE/2);
snprintf(cmdstring, 255, "rtl_fm -s 22050 -P -C -i 46 -l %d -t 5 - |"
"sox -t raw -r 22050 -e signed-integer -b 16 -c 1 -L - "
"-r 8000 %d_%s_%lld.wav sinc %d-3000 -n 16 ",
squelch,
(bin-(FFT_LEN/2))*SAMP_RATE/FFT_LEN+center_freq,
datestr,
totalread/SAMP_RATE/2, filt_bot);

execl("/bin/sh", "sh", "-c", cmdstring , (char *)NULL);

fprintf(stderr,"Failed to start child process\n");
exit(1);
char cmdstring[255];
char filestr[255];
snprintf(filestr, 255, "%d_%s_%lld.wav", frequency, datestr, elapsed);
snprintf(cmdstring, 255, "rtl_fm -s 22050 -P -C -i 46 -l %d -t 5 - | "
"sox -t raw -r 22050 -e signed-integer -b 16 -c 1 -L - "
"-r 8000 %s sinc %d-3000 -n 16",
squelch,
filestr,
(filter_sub ? 300 : 0)
);

fprintf(stderr, "Writing audio to %s\n", filestr);
execl("/bin/sh", "sh", "-c", cmdstring, (char *)NULL);
}

fprintf(stderr, "Failed to start child process\n");
exit(1);
}

newproc->pid=pid;
Expand Down Expand Up @@ -161,7 +164,7 @@ void end_process(demodproc* proc)
int i;
close(proc->outpipe);
close(proc->inpipe);
waitpid(proc->pid, NULL);
waitpid(proc->pid, NULL, 0);
bin_list[proc->bin]=0;
free(proc);

Expand All @@ -187,8 +190,8 @@ int get_process_count()
return process_count;
}

void check_processes(double* bins, int* freqs, int freqcount,
long long int total_read, int misses, int center_freq, int filter_sub, int fast, int squelch)
void check_processes(double* bins, int* freqs, int freqcount,
long long int total_read, int misses, int center_freq, int filter_sub, int fast, int squelch, char* command)
{
int i,j;
int miss =1;
Expand All @@ -206,7 +209,7 @@ void check_processes(double* bins, int* freqs, int freqcount,
{
fprintf(stderr, "Creating process to demodulate %d Hz\n",
(freqs[i]-(FFT_LEN/2))*SAMP_RATE/FFT_LEN+center_freq);
create_process(freqs[i],total_read,filter_sub,center_freq, fast, squelch);
create_process(freqs[i], total_read, filter_sub, center_freq, fast, squelch, command);
}
miss =0;
bin_list[freqs[i]]->detection_misses=0;
Expand Down
6 changes: 3 additions & 3 deletions demod_proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ typedef struct demodproc_struct
}
demodproc;

int create_process(int bin, long long int totalread, int filter_sub, int center_freq, int fast, int squelch);
int create_process(int bin, long long int totalread, int filter_sub, int center_freq, int fast, int squelch, char* command);
void end_process(demodproc* proc);

demodproc** get_process_list();
int get_process_count();

//checks if process exists and creates if not,
//should handle small frequency instabilities
void check_processes(double* bins, int* freqs, int freqcount,
long long int total_read, int misses, int center_freq, int filter_sub, int fast, int squelch);
void check_processes(double* bins, int* freqs, int freqcount,
long long int total_read, int misses, int center_freq, int filter_sub, int fast, int squelch, char* command);

#endif
17 changes: 13 additions & 4 deletions fm_multimix.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ int filter_sub=0;
struct circ_buf circ_buffer;
int fast_mode=0;
int squelch=0;
char* command=0;

void mix_signal(demodproc* proc, uint8_t* inbuf, uint8_t* outbuf)
{
Expand Down Expand Up @@ -162,7 +163,7 @@ int read_data()
}
}
check_processes(results, freqs, freq_count, samples_read,
detection_misses, center_freq, filter_sub, fast_mode, squelch);
detection_misses, center_freq, filter_sub, fast_mode, squelch, command);
}
skip = 120;
}
Expand Down Expand Up @@ -247,8 +248,9 @@ void arg_msg()
"\tbefore recording will stop (default 10, approx 10 seconds)]\n"
"\t[-s Filter out sub audible (<300 Hz) tones.]\n"
"\t[-S Speed boost. Turns of nice features like output filtering\n"
"\tin an attempt to improve speed. (default off)]\n"
"\t[-l Squelch level passed to rtl-fm. (default 0)]\n"
"\tin an attempt to improve speed. (defualt off)]\n"
"\t[-c The command which is executed to decode a channel]\n"
);
exit(1);
}
Expand All @@ -259,7 +261,7 @@ int main(int argc, char *argv[])
int running =1;
int opt;

while ((opt = getopt(argc, argv, "f:t:m:vsSl:")) != -1)
while ((opt = getopt(argc, argv, "f:t:m:vsSl:c:")) != -1)
{
switch (opt)
{
Expand All @@ -284,6 +286,9 @@ int main(int argc, char *argv[])
case 'l':
squelch = (int)atoi(optarg);
break;
case 'c':
command = optarg;
break;
default:
arg_msg();
break;
Expand Down Expand Up @@ -340,7 +345,11 @@ int main(int argc, char *argv[])
{
arg_msg();
}


if(command && (filter_sub || squelch)) {
fprintf(stderr, "Filters can not be applied when a custom decoder is used.\n");
exit(1);
}

for(i=0;i<freq_count;i++)
{
Expand Down