Skip to content

Commit

Permalink
rtl_ais.c
Browse files Browse the repository at this point in the history
stereo.bl_len now computes fine on PC.
Droop compensation added.
Change default samplerate to 24k, audio data drops 3db about 8khz (still low). 
It decode AIS mesages piping data to aisdecoder. 
Works fine on Windows, but aisdecoder must be recoded to accept data from standard input and, set stdin mode to binary.
  • Loading branch information
dgiardini committed Jun 4, 2015
1 parent 0df2bf2 commit 8ff1ba2
Showing 1 changed file with 72 additions and 7 deletions.
79 changes: 72 additions & 7 deletions ais/rtl_ais.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <unistd.h>
#ifdef WIN32
#include <fcntl.h>
#endif


#include <pthread.h>
#include <libusb.h>
Expand Down Expand Up @@ -77,6 +80,10 @@ struct downsample_state
int16_t lp_i_hist[10][6];
int16_t lp_q_hist[10][6];
pthread_rwlock_t rw;
//droop compensation
int16_t droop_i_hist[9];
int16_t droop_q_hist[9];

};

struct demod_state
Expand All @@ -88,6 +95,7 @@ struct demod_state
int now_r, now_j;
int pre_r, pre_j;
int dc_avg; // really should get its own struct

};

struct upsample_stereo
Expand Down Expand Up @@ -122,7 +130,7 @@ void usage(void)
"\t[-r right_frequency (default: 162.025M)]\n"
"\t left freq < right freq\n"
"\t frequencies must be within 1.2MHz\n"
"\t[-s sample_rate (default: 12k)]\n"
"\t[-s sample_rate (default: 24k)]\n"
"\t minimum value, might be up to 2x specified\n"
"\t[-o output_rate (default: 48k)]\n"
"\t must be equal or greater than twice -s value\n"
Expand All @@ -146,6 +154,20 @@ static void sighandler(int signum)
do_exit = 1;
rtlsdr_cancel_async(dev);
}
int cic_9_tables[][10] = {
{0,},
{9, -156, -97, 2798, -15489, 61019, -15489, 2798, -97, -156},
{9, -128, -568, 5593, -24125, 74126, -24125, 5593, -568, -128},
{9, -129, -639, 6187, -26281, 77511, -26281, 6187, -639, -129},
{9, -122, -612, 6082, -26353, 77818, -26353, 6082, -612, -122},
{9, -120, -602, 6015, -26269, 77757, -26269, 6015, -602, -120},
{9, -120, -582, 5951, -26128, 77542, -26128, 5951, -582, -120},
{9, -119, -580, 5931, -26094, 77505, -26094, 5931, -580, -119},
{9, -119, -578, 5921, -26077, 77484, -26077, 5921, -578, -119},
{9, -119, -577, 5917, -26067, 77473, -26067, 5917, -577, -119},
{9, -199, -362, 5303, -25505, 77489, -25505, 5303, -362, -199},
};


void rotate_90(int16_t *buf, int len)
/* 90 rotation is 1+0j, 0+1j, -1+0j, 0-1j
Expand Down Expand Up @@ -218,14 +240,43 @@ void fifth_order(int16_t *data, int length, int16_t *hist)
hist[5] = f;
}

void generic_fir(int16_t *data, int length, int *fir, int16_t *hist)
/* Okay, not at all generic. Assumes length 9, fix that eventually. */
{
int d, temp, sum;
for (d=0; d<length; d+=2) {
temp = data[d];
sum = 0;
sum += (hist[0] + hist[8]) * fir[1];
sum += (hist[1] + hist[7]) * fir[2];
sum += (hist[2] + hist[6]) * fir[3];
sum += (hist[3] + hist[5]) * fir[4];
sum += hist[4] * fir[5];
data[d] = sum >> 15 ;
hist[0] = hist[1];
hist[1] = hist[2];
hist[2] = hist[3];
hist[3] = hist[4];
hist[4] = hist[5];
hist[5] = hist[6];
hist[6] = hist[7];
hist[7] = hist[8];
hist[8] = temp;
}
}

void downsample(struct downsample_state *d)
{
int i, ds_p;
ds_p = d->downsample_passes;
for (i=0; i<ds_p; i++) {
for (i=0; i<ds_p; i++)
{
fifth_order(d->buf, (d->len_in >> i), d->lp_i_hist[i]);
fifth_order(d->buf+1, (d->len_in >> i)-1, d->lp_q_hist[i]);
}
// droop compensation
generic_fir(d->buf, d->len_in >> ds_p,cic_9_tables[ds_p], d->droop_i_hist);
generic_fir(d->buf+1, (d->len_in>> ds_p)-1,cic_9_tables[ds_p], d->droop_q_hist);
}

void multiply(int ar, int aj, int br, int bj, int *cr, int *cj)
Expand Down Expand Up @@ -280,6 +331,7 @@ void demodulate(struct demod_state *d)
int16_t *result = d->result;
pcm = polar_disc_fast(buf[0], buf[1],
d->pre_r, d->pre_j);

result[0] = (int16_t)pcm;
for (i = 2; i < (d->buf_len-1); i += 2) {
// add the other atan types?
Expand Down Expand Up @@ -370,6 +422,7 @@ static void *demod_thread_fn(void *arg)
dc_block_filter(&left_demod);}
//if (oversample) {
// downsample(&left);}
//fprintf(stderr,"\nUpsample result_len:%d stereo.bl_len:%d :%f\n",left_demod.result_len,stereo.bl_len,(float)stereo.bl_len/(float)left_demod.result_len);
arbitrary_upsample(left_demod.result, stereo.buf_left, left_demod.result_len, stereo.bl_len);
rotate_m90(right.buf, right.len_in);
downsample(&right);
Expand All @@ -392,6 +445,7 @@ void downsample_init(struct downsample_state *dss)
int i, j;
dss->buf = malloc(dss->len_in * sizeof(int16_t));
dss->rate_out = dss->rate_in / dss->downsample;

//dss->downsample_passes = (int)log2(dss->downsample);
dss->len_out = dss->len_in / dss->downsample;
for (i=0; i<10; i++) { for (j=0; j<6; j++) {
Expand All @@ -416,7 +470,9 @@ void stereo_init(struct upsample_stereo *us)

int main(int argc, char **argv)
{
#ifndef WIN32
struct sigaction sigact;
#endif
char *filename = NULL;
int r, opt;
int i, gain = AUTO_GAIN; /* tenths of a dB */
Expand All @@ -426,7 +482,7 @@ int main(int argc, char **argv)
int custom_ppm = 0;
int left_freq = 161975000;
int right_freq = 162025000;
int sample_rate = 12000;
int sample_rate = 24000;
int output_rate = 48000;
int dongle_freq, dongle_rate, delta;
int edge = 0;
Expand Down Expand Up @@ -550,7 +606,8 @@ int main(int argc, char **argv)
left_demod.result_len = left_demod.buf_len / 2;
right_demod.buf_len = left_demod.buf_len;
right_demod.result_len = left_demod.result_len;
stereo.bl_len = (int)((long)(DEFAULT_BUF_LENGTH/2) * (long)output_rate / (long)dongle_rate);
// stereo.bl_len = (int)((long)(DEFAULT_BUF_LENGTH/2) * (long)output_rate / (long)dongle_rate); -> Doesn't work on Linux
stereo.bl_len = (int)((double)(DEFAULT_BUF_LENGTH/2) * (double)output_rate / (double)dongle_rate);
stereo.br_len = stereo.bl_len;
stereo.result_len = stereo.br_len * 2;
stereo.rate = output_rate;
Expand All @@ -575,16 +632,23 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index);
exit(1);
}
#ifndef WIN32
sigact.sa_handler = sighandler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, NULL);
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGQUIT, &sigact, NULL);
sigaction(SIGPIPE, &sigact, NULL);

#else
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
#endif
if (strcmp(filename, "-") == 0) { /* Write samples to stdout */
file = stdout;
#ifdef WIN32
setmode(fileno(stdout), O_BINARY); // Binary mode, avoid text mode
#endif
setvbuf(stdout, NULL, _IONBF, 0);
} else {
file = fopen(filename, "wb");
Expand All @@ -593,7 +657,6 @@ int main(int argc, char **argv)
exit(1);
}
}

/* Set the tuner gain */
if (gain == AUTO_GAIN) {
verbose_auto_gain(dev);
Expand All @@ -605,7 +668,9 @@ int main(int argc, char **argv)
if (!custom_ppm) {
verbose_ppm_eeprom(dev, &ppm_error);
}

verbose_ppm_set(dev, ppm_error);

//r = rtlsdr_set_agc_mode(dev, 1);

/* Set the tuner frequency */
Expand Down

0 comments on commit 8ff1ba2

Please sign in to comment.