rs_multi: test -> master

pull/43/head
Zilog80 2021-04-27 18:59:46 +02:00
rodzic 2ce01d8b9a
commit a07ac0cceb
8 zmienionych plików z 860 dodań i 257 usunięć

Wyświetl plik

@ -15,13 +15,24 @@ simultaneous decoding
     `-lm -pthread -o rs_multi`
#### Usage/Examples
`./rs_multi --rs41 <fq0> --dfm <fq1> --m10 <fq2> --lms <fq3> <iq_baseband.wav>` <br />
`./rs_multi --rs41 <fq0> --dfm <fq1> --m10 <fq2> --lms <fq3> - <sr> <bs> <iq_baseband.raw>` <br />
`$ ./rs_multi --rs41 <fq0> --dfm <fq1> --m10 <fq2> --lms <fq3> <iq_baseband.wav>` <br />
`$ ./rs_multi --rs41 <fq0> --dfm <fq1> --m10 <fq2> --lms <fq3> - <sr> <bs> <iq_baseband.raw>` <br />
where <br />
&nbsp;&nbsp;&nbsp;&nbsp; `-0.5 < fq < 0.5`: (relative) frequency, `fq=freq/sr` <br />
&nbsp;&nbsp;&nbsp;&nbsp; `-0.5 < fqX < 0.5`: (relative) frequency, `fq=freq/sr` <br />
&nbsp;&nbsp;&nbsp;&nbsp; `<sr>`: sample rate <br />
&nbsp;&nbsp;&nbsp;&nbsp; `<bs>=8,16,32`: bits per (real) sample (u8, s16 or f32) <br />
decodes up to `MAX_FQ=5 (demod_base.h)` signals. Decoding more signals than number of CPUs/cores is not recommended. <br />
c.f.
https://youtu.be/5YXP9LYUgLs
decodes up to `MAX_FQ=5 (demod_base.h)` signals. Decoding more signals than number of CPUs/cores is not recommended.<br />
Note: If the baseband sample rate has no appropriate factors (e.g. if prime), the IF sample rate might be high and IF-processing slow.<br />
Sending add/remove commands via fifo: <br />
[terminal 1]<br />
`$ rtl_sdr -f 403.0M -s 1920000 - | ./rs_multi --fifo rsfifo --rs41 <fq0> --dfm <fq1> - 1920000 8`<br />
where `<fqX>` is the (relative) frequency of signal `X`<br />
[terminal 2]<br />
*add M10 on `<fq2>`*:<br /> `$ echo "m10 <fq2>" > rsfifo`<br />
*remove `<fq1>`*:<br /> `$ echo "-1" > rsfifo`<br />
If there is no decode for `SEC_NO_SIGNAL=10 (demod_base.c)` seconds, the signal is removed,
unless option `-c` is used.<br />
`--json` output is also possible.

Wyświetl plik

@ -404,9 +404,9 @@ static int f32read_csample(dsp_t *dsp, float complex *z) {
}
static volatile int bufeof = 0; // threads exit
volatile int bufeof = 0; // threads exit
volatile int rbf1;
static volatile int rbf;
extern int rbf1;
static int __f32read_cblock_nocond(dsp_t *dsp) { // blk
@ -417,136 +417,165 @@ static int __f32read_cblock_nocond(dsp_t *dsp) { // blk
if (bufeof) return 0;
pthread_mutex_lock( dsp->thd.mutex );
pthread_mutex_lock( dsp->thd->mutex );
if (rbf == 0)
{
if (dsp->bps == 8) { //uint8
ui8_t u[2*BL];
len = fread( u, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) dsp->thd.blk[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
for (n = 0; n < len; n++) dsp->thd->blk[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
}
else if (dsp->bps == 16) { //int16
short b[2*BL];
len = fread( b, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) dsp->thd.blk[n] = b[2*n]/32768.0 + I*b[2*n+1]/32768.0;
for (n = 0; n < len; n++) dsp->thd->blk[n] = b[2*n]/32768.0 + I*b[2*n+1]/32768.0;
}
else { // dsp->bps == 32 //float32
float f[2*BL];
len = fread( f, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) dsp->thd.blk[n] = f[2*n] + I*f[2*n+1];
for (n = 0; n < len; n++) dsp->thd->blk[n] = f[2*n] + I*f[2*n+1];
}
if (len < BL) bufeof = 1;
rbf = rbf1; // set all bits
}
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
while ((rbf & dsp->thd.tn_bit) == 0) ; // only if #{fqs} leq #{cores} ...
while ((rbf & dsp->thd->tn_bit) == 0) ; // only if #{fqs} leq #{cores} ...
for (n = 0; n < dsp->decM; n++) dsp->decMbuf[n] = dsp->thd.blk[dsp->decM*dsp->blk_cnt + n];
for (n = 0; n < dsp->decM; n++) dsp->decMbuf[n] = dsp->thd->blk[dsp->decM*dsp->blk_cnt + n];
dsp->blk_cnt += 1;
if (dsp->blk_cnt == blk_sz) {
pthread_mutex_lock( dsp->thd.mutex );
rbf &= ~(dsp->thd.tn_bit); // clear bit(tn)
pthread_mutex_lock( dsp->thd->mutex );
rbf &= ~(dsp->thd->tn_bit); // clear bit(tn)
dsp->blk_cnt = 0;
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
}
return len;
}
static int f32read_cblock(dsp_t *dsp) { // blk_cond
static int f32_cblk(dsp_t *dsp) {
int n;
int BL = dsp->decM * blk_sz;
int len = BL;
float x, y;
if (bufeof) return 0;
if (dsp->bps == 8) { //uint8
ui8_t u[2*BL];
len = fread( u, dsp->bps/8, 2*BL, dsp->fp) / 2;
//for (n = 0; n < len; n++) dsp->thd->blk[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
// u8: 0..255, 128 -> 0V
for (n = 0; n < len; n++) {
x = (u[2*n ]-128)/128.0;
y = (u[2*n+1]-128)/128.0;
dsp->thd->blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
else if (dsp->bps == 16) { //int16
short b[2*BL];
len = fread( b, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) {
x = b[2*n ]/32768.0;
y = b[2*n+1]/32768.0;
dsp->thd->blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
else { // dsp->bps == 32 //float32
float f[2*BL];
len = fread( f, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) {
x = f[2*n];
y = f[2*n+1];
dsp->thd->blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
if (len < BL) bufeof = 1;
pthread_mutex_lock( dsp->thd.mutex );
return len;
}
static int f32read_cblock(dsp_t *dsp) { // blk_cond
int n;
int len = dsp->decM;
if (bufeof) return 0;
//if (dsp->thd->used == 0) { }
pthread_mutex_lock( dsp->thd->mutex );
if (rbf == 0)
{
if (dsp->bps == 8) { //uint8
ui8_t u[2*BL];
len = fread( u, dsp->bps/8, 2*BL, dsp->fp) / 2;
//for (n = 0; n < len; n++) dsp->thd.blk[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
// u8: 0..255, 128 -> 0V
for (n = 0; n < len; n++) {
x = (u[2*n ]-128)/128.0;
y = (u[2*n+1]-128)/128.0;
dsp->thd.blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
else if (dsp->bps == 16) { //int16
short b[2*BL];
len = fread( b, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) {
x = b[2*n ]/32768.0;
y = b[2*n+1]/32768.0;
dsp->thd.blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
else { // dsp->bps == 32 //float32
float f[2*BL];
len = fread( f, dsp->bps/8, 2*BL, dsp->fp) / 2;
for (n = 0; n < len; n++) {
x = f[2*n];
y = f[2*n+1];
dsp->thd.blk[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
IQdc.sumIQx += x;
IQdc.sumIQy += y;
IQdc.cnt += 1;
if (IQdc.cnt == IQdc.maxcnt) {
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
}
}
}
if (len < BL) bufeof = 1;
len = f32_cblk(dsp);
rbf = rbf1; // set all bits
pthread_cond_broadcast( dsp->thd.cond );
pthread_cond_broadcast( dsp->thd->cond );
}
while ((rbf & dsp->thd.tn_bit) == 0) pthread_cond_wait( dsp->thd.cond, dsp->thd.mutex );
while ((rbf & dsp->thd->tn_bit) == 0) pthread_cond_wait( dsp->thd->cond, dsp->thd->mutex );
for (n = 0; n < dsp->decM; n++) dsp->decMbuf[n] = dsp->thd.blk[dsp->decM*dsp->blk_cnt + n];
for (n = 0; n < dsp->decM; n++) dsp->decMbuf[n] = dsp->thd->blk[dsp->decM*dsp->blk_cnt + n];
dsp->blk_cnt += 1;
if (dsp->blk_cnt == blk_sz) {
rbf &= ~(dsp->thd.tn_bit); // clear bit(tn)
rbf &= ~(dsp->thd->tn_bit); // clear bit(tn)
dsp->blk_cnt = 0;
}
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
return len;
}
int reset_blockread(dsp_t *dsp) {
int len = 0;
pthread_mutex_lock( dsp->thd->mutex );
rbf1 &= ~(dsp->thd->tn_bit);
if ( (rbf & dsp->thd->tn_bit) == dsp->thd->tn_bit )
{
len = f32_cblk(dsp);
rbf = rbf1; // set all bits
pthread_cond_broadcast( dsp->thd->cond );
}
pthread_mutex_unlock( dsp->thd->mutex );
return len;
}
// decimate lowpass
static float *ws_dec;
@ -654,6 +683,7 @@ int f32buf_sample(dsp_t *dsp, int inv) {
ui32_t s_reset = dsp->dectaps*dsp->lut_len;
int j;
if ( f32read_cblock(dsp) < dsp->decM ) return EOF;
//if ( f32read_cblock(dsp) < dsp->decM * blk_sz) return EOF;
for (j = 0; j < dsp->decM; j++) {
dsp->decXbuffer[dsp->sample_dec % dsp->dectaps] = dsp->decMbuf[j] * dsp->ex[dsp->sample_dec % dsp->lut_len];
dsp->sample_dec += 1;
@ -749,14 +779,14 @@ int f32buf_sample(dsp_t *dsp, int inv) {
if (inv) s = -s;
dsp->bufs[dsp->sample_in % dsp->M] = s;
/*
xneu = dsp->bufs[(dsp->sample_in ) % dsp->M];
xalt = dsp->bufs[(dsp->sample_in+dsp->M - dsp->Nvar) % dsp->M];
dsp->xsum += xneu - xalt; // + xneu - xalt
dsp->qsum += (xneu - xalt)*(xneu + xalt); // + xneu*xneu - xalt*xalt
dsp->xs[dsp->sample_in % dsp->M] = dsp->xsum;
dsp->qs[dsp->sample_in % dsp->M] = dsp->qsum;
*/
dsp->sample_out = dsp->sample_in - dsp->delay;
@ -870,7 +900,7 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
}
sample -= dc;
if ( l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
@ -888,9 +918,9 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
sample = avg + scale*(sample - avg); // spikes
}
sample -= dc;
sample -= dc;
if ( l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
@ -902,6 +932,81 @@ int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spi
return 0;
}
int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike) {
// symlen==2: manchester2 10->0,01->1: 2.bit
float sample;
float avg;
float ths = 0.5, scale = 0.27;
double sum = 0.0;
double mid;
//double l = 1.0;
double bg = pos*dsp->symlen*dsp->sps;
double dc = 0.0;
ui8_t bit = 0;
if (dsp->opt_dc && dsp->opt_iq < 2) dc = dsp->dc;
if (pos == 0) {
bg = 0;
dsp->sc = 0;
}
if (dsp->symlen == 2) {
mid = bg + (dsp->sps-1)/2.0;
bg += dsp->sps;
do {
if (dsp->buffered > 0) dsp->buffered -= 1;
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
if (spike && fabs(sample - avg) > ths) {
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
sample = avg + scale*(sample - avg); // spikes
}
sample -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum -= sample;
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
}
mid = bg + (dsp->sps-1)/2.0;
bg += dsp->sps;
do {
if (dsp->buffered > 0) dsp->buffered -= 1;
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
if (spike && fabs(sample - avg) > ths) {
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
sample = avg + scale*(sample - avg); // spikes
}
sample -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) sum += sample;
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
if (sum >= 0) bit = 1;
else bit = 0;
shb->hb = bit;
shb->sb = (float)sum;
return 0;
}
/* -------------------------------------------------------------------------- */
#define IF_TRANSITION_BW (4e3) // 4kHz transition width
@ -952,7 +1057,7 @@ int init_buffers(dsp_t *dsp) {
// lookup table, exp-rotation
int W = 2*8; // 16 Hz window
int d = 1; // 1..W , groesster Teiler d <= W von sr_base
int freq = (int)( dsp->thd.xlt_fq * (double)dsp->sr_base + 0.5);
int freq = (int)( dsp->thd->xlt_fq * (double)dsp->sr_base + 0.5);
int freq0 = freq; // init
double f0 = freq0 / (double)dsp->sr_base; // init
@ -1037,6 +1142,7 @@ int init_buffers(dsp_t *dsp) {
dsp->delay = L/16;
dsp->sample_in = 0;
dsp->last_detect = 0;
p2 = 1;
while (p2 < M) p2 <<= 1;
@ -1059,10 +1165,10 @@ int init_buffers(dsp_t *dsp) {
dsp->bufs = (float *)calloc( M+1, sizeof(float)); if (dsp->bufs == NULL) return -100;
dsp->match = (float *)calloc( L+1, sizeof(float)); if (dsp->match == NULL) return -100;
/*
dsp->xs = (float *)calloc( M+1, sizeof(float)); if (dsp->xs == NULL) return -100;
dsp->qs = (float *)calloc( M+1, sizeof(float)); if (dsp->qs == NULL) return -100;
*/
dsp->rawbits = (char *)calloc( 2*dsp->hdrlen+1, sizeof(char)); if (dsp->rawbits == NULL) return -100;
@ -1143,10 +1249,11 @@ int free_buffers(dsp_t *dsp) {
if (dsp->match) { free(dsp->match); dsp->match = NULL; }
if (dsp->bufs) { free(dsp->bufs); dsp->bufs = NULL; }
if (dsp->rawbits) { free(dsp->rawbits); dsp->rawbits = NULL; }
/*
if (dsp->xs) { free(dsp->xs); dsp->xs = NULL; }
if (dsp->qs) { free(dsp->qs); dsp->qs = NULL; }
if (dsp->rawbits) { free(dsp->rawbits); dsp->rawbits = NULL; }
*/
if (dsp->DFT.xn) { free(dsp->DFT.xn); dsp->DFT.xn = NULL; }
if (dsp->DFT.ew) { free(dsp->DFT.ew); dsp->DFT.ew = NULL; }
if (dsp->DFT.Fm) { free(dsp->DFT.Fm); dsp->DFT.Fm = NULL; }
@ -1196,6 +1303,7 @@ ui32_t get_sample(dsp_t *dsp) {
/* ------------------------------------------------------------------------------------ */
#define SEC_NO_SIGNAL 10
int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
ui32_t k = 0;
@ -1212,6 +1320,16 @@ int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
mp = getCorrDFT(dsp); // correlation score -> dsp->mv
//if (option_auto == 0 && dsp->mv < 0) mv = 0;
k = 0;
// signal lost
if ( dsp->thd->used == 0 ||
(!dsp->opt_cnt && dsp->mv_pos - dsp->last_detect > SEC_NO_SIGNAL*dsp->sr) )
{
pthread_mutex_lock( dsp->thd->mutex );
fprintf(stdout, "<%d: close>\n", dsp->thd->tn);
pthread_mutex_unlock( dsp->thd->mutex );
return EOF;
}
}
else {
dsp->mv = 0.0;
@ -1249,6 +1367,8 @@ int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
herrs = headcmp(dsp, opt_dc);
if (herrs <= hdmax) header_found = 1; // max bitfehler in header
dsp->last_detect = dsp->mv_pos;
if (header_found) return 1;
}
}

Wyświetl plik

@ -36,6 +36,7 @@ typedef struct {
int max_fq;
double xlt_fq;
float complex *blk;
int used;
} thd_t;
@ -80,13 +81,16 @@ typedef struct {
float *bufs;
float mv;
ui32_t mv_pos;
ui32_t last_detect;
//
int N_norm;
int Nvar;
/*
float xsum;
float qsum;
float *xs;
float *qs;
*/
// IQ-data
int opt_iq;
@ -149,7 +153,9 @@ typedef struct {
float *lpFM_buf;
float *fm_buffer;
thd_t thd;
int opt_cnt;
thd_t *thd;
} dsp_t;
@ -167,12 +173,18 @@ typedef struct {
} pcm_t;
typedef struct {
ui8_t hb;
float sb;
} hsbit_t;
typedef struct {
pcm_t pcm;
thd_t thd;
int option_jsn;
int option_dc;
int option_cnt;
int jsn_freq;
} thargs_t;
@ -181,6 +193,7 @@ typedef struct {
float read_wav_header(pcm_t *);
int f32buf_sample(dsp_t *, int);
int read_slbit(dsp_t *, int*, int, int, int, float, int);
int read_softbit(dsp_t *, hsbit_t *, int, int, int, float, int );
int init_buffers(dsp_t *);
int free_buffers(dsp_t *);
@ -193,3 +206,6 @@ int decimate_init(float f, int taps);
int decimate_free(void);
int iq_dc_init(pcm_t *);
int reset_blockread(dsp_t *);

Wyświetl plik

@ -772,21 +772,26 @@ static int print_frame(gpx_t *gpx, dsp_t *dsp) {
if (ret1 == 0 || ret1 > 0) {
frid = dat_out(gpx, block_dat1, ret1);
if (frid == 8) {
pthread_mutex_lock( dsp->thd.mutex );
fprintf(stdout, "<%d> ", dsp->thd.tn);
pthread_mutex_lock( dsp->thd->mutex );
fprintf(stdout, "<%d> ", dsp->thd->tn);
ret1 = print_gpx(gpx);
if (ret1==0) fprintf(stdout, "\n");
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
}
}
if (ret2 == 0 || ret2 > 0) {
frid = dat_out(gpx, block_dat2, ret2);
if (frid == 8) {
pthread_mutex_lock( dsp->thd.mutex );
fprintf(stdout, "<%d> ", dsp->thd.tn);
pthread_mutex_lock( dsp->thd->mutex );
//fprintf(stdout, "<%d> ", dsp->thd->tn);
fprintf(stdout, "<%d: ", dsp->thd->tn);
fprintf(stdout, "s=%+.4f, ", dsp->mv);
fprintf(stdout, "f=%+.4f", -dsp->thd->xlt_fq);
if (dsp->opt_dc) fprintf(stdout, "%+.6f", dsp->Df/(double)dsp->sr);
fprintf(stdout, "> ");
ret2 = print_gpx(gpx);
if (ret2==0) fprintf(stdout, "\n");
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
}
}
@ -879,7 +884,7 @@ void *thd_dfm09(void *targs) {
dsp.dectaps = pcm->dectaps;
dsp.decM = pcm->decM;
dsp.thd = tharg->thd;
dsp.thd = &(tharg->thd);
dsp.bps = pcm->bps;
dsp.nch = pcm->nch;
@ -897,17 +902,18 @@ void *thd_dfm09(void *targs) {
dsp.opt_lp = 1;
dsp.lpIQ_bw = 12e3; // IF lowpass bandwidth
dsp.lpFM_bw = 4e3; // FM audio lowpass
dsp.opt_dc = tharg->option_dc;
dsp.opt_dc = tharg->option_dc;
dsp.opt_cnt = tharg->option_cnt;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low\n");
//fprintf(stderr, "note: sample rate low\n");
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return NULL;
goto exit_thread;
};
@ -975,6 +981,9 @@ void *thd_dfm09(void *targs) {
free_buffers(&dsp);
exit_thread:
reset_blockread(&dsp);
(dsp.thd)->used = 0;
return NULL;
}

Wyświetl plik

@ -107,12 +107,11 @@ typedef struct {
ui8_t bIn;
ui8_t codeIn;
ui8_t prevState; // 0..M=64
int w; // > 255 : if (w>250): w=250 ?
//float sw;
float w;
} states_t;
typedef struct {
char rawbits[RAWBITFRAME_LEN+OVERLAP*BITS*2 +8];
hsbit_t rawbits[RAWBITFRAME_LEN+OVERLAP*BITS*2 +8];
states_t state[RAWBITFRAME_LEN+OVERLAP +8][M];
states_t d[N];
} VIT_t;
@ -129,7 +128,7 @@ typedef struct {
double lat; double lon; double alt;
double vH; double vD; double vV;
double vE; double vN; double vU;
char blk_rawbits[RAWBITBLOCK_LEN+SYNC_LEN*BITS*2 +9];
hsbit_t blk_rawbits[RAWBITBLOCK_LEN+SYNC_LEN*BITS*2 +9];
ui8_t frame[FRM_LEN]; // = { 0x24, 0x54, 0x00, 0x00}; // dataheader
int frm_pos; // ecc_blk <-> frm_blk
int sf6;
@ -205,12 +204,16 @@ static int vit_initCodes(gpx_t *gpx) {
return 0;
}
static int vit_dist(int c, char *rc) {
return (((c>>1)^rc[0])&1) + ((c^rc[1])&1);
static float vit_dist2(int c, hsbit_t *rc) {
int c0 = 2*((c>>1) & 1)-1; // {0,1} -> {-1,+1}
int c1 = 2*(c & 1)-1;
float d2 = (c0-rc[0].sb)*(c0-rc[0].sb) + (c1-rc[1].sb)*(c1-rc[1].sb);
return d2;
}
static int vit_start(VIT_t *vit, char *rc) {
int t, m, j, c, d;
static int vit_start(VIT_t *vit, hsbit_t *rc) {
int t, m, j, c;
float d;
t = L-1;
m = M;
@ -228,7 +231,7 @@ static int vit_start(VIT_t *vit, char *rc) {
c = vit_code[j];
vit->state[t][j].bIn = j % 2;
vit->state[t][j].codeIn = c;
d = vit_dist( c, rc+2*(t-1) );
d = vit_dist2( c, rc+2*(t-1) );
vit->state[t][j].w = vit->state[t-1][vit->state[t][j].prevState].w + d;
}
m *= 2;
@ -237,7 +240,7 @@ static int vit_start(VIT_t *vit, char *rc) {
return t;
}
static int vit_next(VIT_t *vit, int t, char *rc) {
static int vit_next(VIT_t *vit, int t, hsbit_t *rc) {
int b, nstate;
int j, index;
@ -247,7 +250,7 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
vit->d[nstate].bIn = b;
vit->d[nstate].codeIn = vit_code[nstate];
vit->d[nstate].prevState = j;
vit->d[nstate].w = vit->state[t][j].w + vit_dist( vit->d[nstate].codeIn, rc );
vit->d[nstate].w = vit->state[t][j].w + vit_dist2( vit->d[nstate].codeIn, rc );
}
}
@ -264,11 +267,11 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
static int vit_path(VIT_t *vit, int j, int t) {
int c;
vit->rawbits[2*t] = '\0';
vit->rawbits[2*t].hb = '\0';
while (t > 0) {
c = vit->state[t][j].codeIn;
vit->rawbits[2*t -2] = 0x30 + ((c>>1) & 1);
vit->rawbits[2*t -1] = 0x30 + (c & 1);
vit->rawbits[2*t -2].hb = 0x30 + ((c>>1) & 1);
vit->rawbits[2*t -1].hb = 0x30 + (c & 1);
j = vit->state[t][j].prevState;
t--;
}
@ -276,13 +279,20 @@ static int vit_path(VIT_t *vit, int j, int t) {
return 0;
}
static int viterbi(VIT_t *vit, char *rc) {
static int hbstr_len(hsbit_t *hsbit) {
int len = 0;
while (hsbit[len].hb) len++;
return len;
}
static int viterbi(VIT_t *vit, hsbit_t *rc) {
int t, tmax;
int j, j_min, w_min;
int j, j_min;
float w_min;
vit_start(vit, rc);
tmax = strlen(rc)/2;
tmax = hbstr_len(rc)/2;
for (t = L-1; t < tmax; t++)
{
@ -307,15 +317,15 @@ static int viterbi(VIT_t *vit, char *rc) {
// ------------------------------------------------------------------------
static int deconv(char* rawbits, char *bits) {
static int deconv(hsbit_t *rawbits, char *bits) {
int j, n, bitA, bitB;
char *p;
hsbit_t *p;
int len;
int errors = 0;
int m = L-1;
len = strlen(rawbits);
len = hbstr_len(rawbits);
for (j = 0; j < m; j++) bits[j] = '0';
n = 0;
while ( 2*(m+n) < len ) {
@ -325,10 +335,10 @@ static int deconv(char* rawbits, char *bits) {
bitA ^= (bits[n+j]&1) & (polyA[j]&1);
bitB ^= (bits[n+j]&1) & (polyB[j]&1);
}
if ( (bitA^(p[0]&1))==(polyA[m]&1) && (bitB^(p[1]&1))==(polyB[m]&1) ) bits[n+m] = '1';
else if ( (bitA^(p[0]&1))==0 && (bitB^(p[1]&1))==0 ) bits[n+m] = '0';
if ( (bitA^(p[0].hb&1))==(polyA[m]&1) && (bitB^(p[1].hb&1))==(polyB[m]&1) ) bits[n+m] = '1';
else if ( (bitA^(p[0].hb&1))==0 && (bitB^(p[1].hb&1))==0 ) bits[n+m] = '0';
else {
if ( (bitA^(p[0]&1))!=(polyA[m]&1) && (bitB^(p[1]&1))==(polyB[m]&1) ) bits[n+m] = 0x39;
if ( (bitA^(p[0].hb&1))!=(polyA[m]&1) && (bitB^(p[1].hb&1))==(polyB[m]&1) ) bits[n+m] = 0x39;
else bits[n+m] = 0x38;
errors = n;
break;
@ -754,11 +764,16 @@ static int print_frame(gpx_t *gpx, int crc_err, int len) {
static int print_thd_frame(gpx_t *gpx, int crc_err, int len, dsp_t *dsp) {
int ret = 0;
pthread_mutex_lock( dsp->thd.mutex );
printf("<%d> ", dsp->thd.tn);
pthread_mutex_lock( dsp->thd->mutex );
//printf("<%d> ", dsp->thd->tn);
fprintf(stdout, "<%d: ", dsp->thd->tn);
fprintf(stdout, "s=%+.4f, ", dsp->mv);
fprintf(stdout, "f=%+.4f", -dsp->thd->xlt_fq);
if (dsp->opt_dc) fprintf(stdout, "%+.6f", dsp->Df/(double)dsp->sr);
fprintf(stdout, "> ");
ret = print_frame(gpx, crc_err, len);
if (ret==0) printf("\n");
pthread_mutex_unlock( dsp->thd.mutex );
if (ret==0) fprintf(stdout, "\n");
pthread_mutex_unlock( dsp->thd->mutex );
return ret;
}
@ -803,7 +818,7 @@ static void proc_frame(gpx_t *gpx, int len, dsp_t *dsp) {
ui8_t block_bytes[FRAME_LEN+8];
ui8_t rs_cw[rs_N];
char frame_bits[BITFRAME_LEN+OVERLAP*BITS +8]; // init L-1 bits mit 0
char *rawbits = NULL;
hsbit_t *rawbits = NULL;
int i, j;
int err = 0;
int errs = 0;
@ -812,13 +827,17 @@ static void proc_frame(gpx_t *gpx, int len, dsp_t *dsp) {
if ((len % 8) > 4) {
while (len % 8) gpx->blk_rawbits[len++] = '0';
while (len % 8) {
gpx->blk_rawbits[len].hb = '0';
gpx->blk_rawbits[len].sb = -1;
len++;
}
}
gpx->blk_rawbits[len] = '\0';
gpx->blk_rawbits[len].hb = '\0';
flen = len / (2*BITS);
if (gpx->option.vit == 1) {
if (gpx->option.vit) {
viterbi(gpx->vit, gpx->blk_rawbits);
rawbits = gpx->vit->rawbits;
}
@ -948,14 +967,14 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
int k;
int bit, rbit;
hsbit_t hsbit, rhsbit;
int bitpos = 0;
int bitQ = 0;
int pos;
int header_found = 0;
float thres = 0.68;
float thres = 0.65;
float _mv = 0.0;
int symlen = 1;
@ -996,17 +1015,21 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
//gpx->option.ptu = 1;
gpx->option.jsn = tharg->option_jsn;
gpx->option.vit = 1;
gpx->option.vit = 2;
gpx->option.ecc = 1;
gpx->jsn_freq = tharg->jsn_freq;
memcpy(gpx->blk_rawbits, blk_syncbits, sizeof(blk_syncbits));
memcpy(gpx->frame, frm_sync6, sizeof(frm_sync6));
gpx->frm_pos = 0; // ecc_blk <-> frm_blk
gpx->sf6 = 0;
gpx->sfX = 0;
//memcpy(gpx->blk_rawbits, blk_syncbits, sizeof(blk_syncbits));
for (k = 0; k < strlen(blk_syncbits); k++) { // strlen(blk_syncbits)=BLOCKSTART
int hbit = blk_syncbits[k] & 1;
gpx->blk_rawbits[k].hb = hbit + 0x30;
gpx->blk_rawbits[k].sb = 2*hbit-1;
}
gpx->week = gpsweek;
@ -1023,7 +1046,7 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.dectaps = pcm->dectaps;
dsp.decM = pcm->decM;
dsp.thd = tharg->thd;
dsp.thd = &(tharg->thd);
dsp.bps = pcm->bps;
dsp.nch = pcm->nch;
@ -1041,23 +1064,26 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.opt_lp = 1;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = tharg->option_dc;
dsp.opt_dc = tharg->option_dc;
dsp.opt_cnt = tharg->option_cnt;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
//fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
k = init_buffers(&dsp); // baud difference not significant
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return NULL;
goto exit_thread;
};
if (gpx->option.vit) {
k = vit_initCodes(gpx);
if (k < 0) return NULL;
if (k < 0) {
goto exit_thread;
}
}
if (gpx->option.ecc) {
rs_init_RS255ccsds(&gpx->RS); // bch_ecc.c
@ -1090,7 +1116,7 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
bitQ = 0;
while ( 1 && bitQ != EOF )
{
header_found = find_header(&dsp, thres, 6, bitofs, dsp.opt_dc);
header_found = find_header(&dsp, thres, 10, bitofs, dsp.opt_dc);
_mv = dsp.mv;
if (header_found == EOF) break;
@ -1115,19 +1141,26 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
while ( pos < rawbitblock_len ) {
bitQ = read_slbit(&dsp, &rbit, 0, bitofs, bitpos, -1, 0); // symlen=1
bitQ = read_softbit(&dsp, &rhsbit, 0, bitofs, bitpos, -1, 0); // symlen=1
if (bitQ == EOF) { break; }
bit = rbit ^ (bc%2); // (c0,inv(c1))
gpx->blk_rawbits[pos] = 0x30 + bit;
hsbit.hb = rhsbit.hb ^ (bc%2); // (c0,inv(c1))
int sgn = -2*(((unsigned int)bc)%2)+1;
hsbit.sb = sgn * rhsbit.sb;
if (gpx->option.vit == 1) { // hard decision
hsbit.sb = 2*hsbit.hb -1;
}
gpx->blk_rawbits[pos] = hsbit;
gpx->blk_rawbits[pos].hb += 0x30;
bc++;
pos++;
bitpos += 1;
}
gpx->blk_rawbits[pos] = '\0';
gpx->blk_rawbits[pos].hb = '\0';
time_elapsed_sec = dsp.sample_in / (double)dsp.sr;
proc_frame(gpx, pos, &dsp);
@ -1173,6 +1206,9 @@ void *thd_lms6X(void *targs) { // pcm_t *pcm, double xlt_fq
free_buffers(&dsp);
if (gpx->vit) { free(gpx->vit); gpx->vit = NULL; }
exit_thread:
reset_blockread(&dsp);
(dsp.thd)->used = 0;
return NULL;
}

Wyświetl plik

@ -1101,11 +1101,16 @@ static int print_frame(gpx_t *gpx, int pos, dsp_t *dsp) {
}
else {
int ret = 0;
pthread_mutex_lock( dsp->thd.mutex );
fprintf(stdout, "<%d> ", dsp->thd.tn);
pthread_mutex_lock( dsp->thd->mutex );
//fprintf(stdout, "<%d> ", dsp->thd->tn);
fprintf(stdout, "<%d: ", dsp->thd->tn);
fprintf(stdout, "s=%+.4f, ", dsp->mv);
fprintf(stdout, "f=%+.4f", -dsp->thd->xlt_fq);
if (dsp->opt_dc) fprintf(stdout, "%+.6f", dsp->Df/(double)dsp->sr);
fprintf(stdout, "> ");
ret = print_pos(gpx, cs1 == cs2);
if (ret==0) fprintf(stdout, "\n");
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
}
return (gpx->frame_bytes[0]<<8)|gpx->frame_bytes[1];
@ -1179,7 +1184,7 @@ void *thd_m10(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.dectaps = pcm->dectaps;
dsp.decM = pcm->decM;
dsp.thd = tharg->thd;
dsp.thd = &(tharg->thd);
dsp.bps = pcm->bps;
dsp.nch = pcm->nch;
@ -1197,10 +1202,11 @@ void *thd_m10(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.opt_lp = 1;
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
dsp.lpFM_bw = 10e3; // FM audio lowpass
dsp.opt_dc = tharg->option_dc;
dsp.opt_dc = tharg->option_dc;
dsp.opt_cnt = tharg->option_cnt;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
//fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
@ -1208,7 +1214,7 @@ void *thd_m10(void *targs) { // pcm_t *pcm, double xlt_fq
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return NULL;
goto exit_thread;
};
@ -1274,6 +1280,10 @@ void *thd_m10(void *targs) { // pcm_t *pcm, double xlt_fq
free_buffers(&dsp);
exit_thread:
reset_blockread(&dsp);
(dsp.thd)->used = 0;
return NULL;
}

Wyświetl plik

@ -40,7 +40,8 @@ typedef struct {
i8_t crc; // CRC check output
i8_t ecc; // Reed-Solomon ECC
i8_t sat; // GPS sat data
i8_t ptu; // PTU: temperature
i8_t ptu; // PTU: temperature humidity (pressure)
i8_t dwp; // PTU derived: dew point
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
@ -77,7 +78,8 @@ typedef struct {
int std; int min; float sek;
double lat; double lon; double alt;
double vH; double vD; double vV;
float T; float RH;
float T; float RH; float TH;
float P; float RH2;
ui32_t crc;
ui8_t frame[FRAME_LEN];
ui8_t calibytes[51*16];
@ -89,6 +91,12 @@ typedef struct {
float ptu_co2[3]; // { -243.911 , 0.187654 , 8.2e-06 }
float ptu_calT2[3]; // calibration T2-Hum
float ptu_calH[2]; // calibration Hum
float ptu_mtxH[42];
float ptu_corHp[3];
float ptu_corHt[12];
float ptu_Cf1;
float ptu_Cf2;
float ptu_calP[25];
ui32_t freq; // freq/kHz (RS41)
int jsn_freq; // freq/kHz (SDR)
float batt; // battery voltage (V)
@ -203,6 +211,13 @@ static ui32_t u2(ui8_t *bytes) { // 16bit unsigned int
return bytes[0] | (bytes[1]<<8);
}
static int i2(ui8_t *bytes) { // 16bit signed int
//return (i16_t)u2(bytes);
int val = bytes[0] | (bytes[1]<<8);
if (val & 0x8000) val -= 0x10000;
return val;
}
/*
double r8(ui8_t *bytes) {
double val = 0;
@ -342,7 +357,7 @@ static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4
return ft;
}
static int get_FrameNb(gpx_t *gpx, int ofs) {
static int get_FrameNb(gpx_t *gpx, int crc, int ofs) {
int i;
unsigned byte;
ui8_t frnr_bytes[2];
@ -363,14 +378,14 @@ static int get_BattVolts(gpx_t *gpx, int ofs) {
int i;
unsigned byte;
ui8_t batt_bytes[2];
float batt_volts;
ui16_t batt_volts; // signed voltage?
for (i = 0; i < 2; i++) {
byte = gpx->frame[pos_BattVolts+ofs + i];
batt_bytes[i] = byte;
}
batt_volts = (float)(batt_bytes[0] + (batt_bytes[1] << 8));
// 2 bytes? V > 25.5 ?
batt_volts = batt_bytes[0]; // + (batt_bytes[1] << 8);
gpx->batt = batt_volts/10.0;
return 0;
@ -402,6 +417,8 @@ static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
// don't reset gpx->frame[] !
gpx->T = -273.15;
gpx->RH = -1.0;
gpx->P = -1.0;
gpx->RH2 = -1.0;
// new ID:
memcpy(gpx->id, sondeid_bytes, 8);
gpx->id[8] = '\0';
@ -421,7 +438,7 @@ static int get_FrameConf(gpx_t *gpx, int ofs) {
err = crc;
err |= get_SondeID(gpx, crc, ofs);
err |= get_FrameNb(gpx, ofs);
err |= get_FrameNb(gpx, crc, ofs);
err |= get_BattVolts(gpx, ofs);
if (crc == 0) {
@ -440,6 +457,8 @@ static int get_FrameConf(gpx_t *gpx, int ofs) {
static int get_CalData(gpx_t *gpx) {
int j;
memcpy(&(gpx->ptu_Rf1), gpx->calibytes+61, 4); // 0x03*0x10+13
memcpy(&(gpx->ptu_Rf2), gpx->calibytes+65, 4); // 0x04*0x10+ 1
@ -450,6 +469,7 @@ static int get_CalData(gpx_t *gpx) {
memcpy(gpx->ptu_calT1+0, gpx->calibytes+89, 4); // 0x05*0x10+ 9
memcpy(gpx->ptu_calT1+1, gpx->calibytes+93, 4); // 0x05*0x10+13
memcpy(gpx->ptu_calT1+2, gpx->calibytes+97, 4); // 0x06*0x10+ 1
// ptu_calT1[3..6]
memcpy(gpx->ptu_calH+0, gpx->calibytes+117, 4); // 0x07*0x10+ 5
memcpy(gpx->ptu_calH+1, gpx->calibytes+121, 4); // 0x07*0x10+ 9
@ -461,82 +481,236 @@ static int get_CalData(gpx_t *gpx) {
memcpy(gpx->ptu_calT2+0, gpx->calibytes+305, 4); // 0x13*0x10+ 1
memcpy(gpx->ptu_calT2+1, gpx->calibytes+309, 4); // 0x13*0x10+ 5
memcpy(gpx->ptu_calT2+2, gpx->calibytes+313, 4); // 0x13*0x10+ 9
// ptu_calT2[3..6]
// cf. DF9DQ
memcpy(&(gpx->ptu_Cf1), gpx->calibytes+69, 4); // 0x04*0x10+ 5
memcpy(&(gpx->ptu_Cf2), gpx->calibytes+73, 4); // 0x04*0x10+ 9
for (j = 0; j < 42; j++) { // 0x07*0x10+13 = 0x07D = 125
memcpy(gpx->ptu_mtxH+j, gpx->calibytes+125+4*j, 4);
}
for (j = 0; j < 3; j++) { // 0x2A*0x10+6 = 0x2A6 = 678
memcpy(gpx->ptu_corHp+j, gpx->calibytes+678+4*j, 4);
}
for (j = 0; j < 12; j++) { // 0x2B*0x10+A = 0x2BA = 698
memcpy(gpx->ptu_corHt+j, gpx->calibytes+698+4*j, 4);
}
// cf. DF9DQ or stsst/RS-fork
memcpy(gpx->ptu_calP+0, gpx->calibytes+606, 4); // 0x25*0x10+14 = 0x25E
memcpy(gpx->ptu_calP+4, gpx->calibytes+610, 4); // ..
memcpy(gpx->ptu_calP+8, gpx->calibytes+614, 4);
memcpy(gpx->ptu_calP+12, gpx->calibytes+618, 4);
memcpy(gpx->ptu_calP+16, gpx->calibytes+622, 4);
memcpy(gpx->ptu_calP+20, gpx->calibytes+626, 4);
memcpy(gpx->ptu_calP+24, gpx->calibytes+630, 4);
memcpy(gpx->ptu_calP+1, gpx->calibytes+634, 4);
memcpy(gpx->ptu_calP+5, gpx->calibytes+638, 4);
memcpy(gpx->ptu_calP+9, gpx->calibytes+642, 4);
memcpy(gpx->ptu_calP+13, gpx->calibytes+646, 4);
memcpy(gpx->ptu_calP+2, gpx->calibytes+650, 4);
memcpy(gpx->ptu_calP+6, gpx->calibytes+654, 4);
memcpy(gpx->ptu_calP+10, gpx->calibytes+658, 4);
memcpy(gpx->ptu_calP+14, gpx->calibytes+662, 4);
memcpy(gpx->ptu_calP+3, gpx->calibytes+666, 4);
memcpy(gpx->ptu_calP+7, gpx->calibytes+670, 4); // ..
memcpy(gpx->ptu_calP+11, gpx->calibytes+674, 4); // 0x2A*0x10+ 2
return 0;
}
/*
static float get_Tc0(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) {
// y = (f - f1) / (f2 - f1);
// y1 = (f - f1) / f2; // = (1 - f1/f2)*y
float a = 3.9083e-3, // Pt1000 platinum resistance
b = -5.775e-7,
c = -4.183e-12; // below 0C, else C=0
float *cal = gpx->ptu_calT1;
float Rb = (f1*gpx->ptu_Rf2-f2*gpx->ptu_Rf1)/(f2-f1), // ofs
Ra = f * (gpx->ptu_Rf2-gpx->ptu_Rf1)/(f2-f1) - Rb,
raw = Ra/1000.0,
g_r = 0.8024*cal[0] + 0.0176, // empirisch
r_o = 0.0705*cal[1] + 0.0011, // empirisch
r = raw * g_r + r_o,
t = (-a + sqrt(a*a + 4*b*(r-1)))/(2*b); // t>0: c=0
// R/R0 = 1 + at + bt^2 + c(t-100)t^3 , R0 = 1000 Ohm, t/Celsius
return t;
}
*/
// T_RH-sensor
static float get_TH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) {
float *p = gpx->ptu_co2;
float *c = gpx->ptu_calT2;
// temperature, platinum resistor
// T-sensor: gpx->ptu_co1 , gpx->ptu_calT1
// T_RH-sensor: gpx->ptu_co2 , gpx->ptu_calT2
static float get_T(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float *ptu_co, float *ptu_calT) {
float *p = ptu_co;
float *c = ptu_calT;
float g = (float)(f2-f1)/(gpx->ptu_Rf2-gpx->ptu_Rf1), // gain
Rb = (f1*gpx->ptu_Rf2-f2*gpx->ptu_Rf1)/(float)(f2-f1), // ofs
Rc = f/g - Rb,
//R = (Rc + c[1]) * c[0],
//T = p[0] + p[1]*R + p[2]*R*R;
R = Rc * c[0],
T = (p[0] + p[1]*R + p[2]*R*R + c[1])*(1.0 + c[2]);
return T;
}
// T-sensor, platinum resistor
static float get_Tc(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) {
float *p = gpx->ptu_co1;
float *c = gpx->ptu_calT1;
float g = (float)(f2-f1)/(gpx->ptu_Rf2-gpx->ptu_Rf1), // gain
Rb = (f1*gpx->ptu_Rf2-f2*gpx->ptu_Rf1)/(float)(f2-f1), // ofs
Rc = f/g - Rb,
//R = (Rc + c[1]) * c[0],
//T = p[0] + p[1]*R + p[2]*R*R;
R = Rc * c[0],
T = (p[0] + p[1]*R + p[2]*R*R + c[1])*(1.0 + c[2]);
return T;
return T; // [Celsius]
}
// rel.hum., capacitor
// (data:) ftp://ftp-cdc.dwd.de/climate_environment/CDC/observations_germany/radiosondes/
// (diffAlt: Ellipsoid-Geoid)
// (note: humidity sensor has significant time-lag at low temperatures)
static float get_RH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T) {
float a0 = 7.5; // empirical
float a1 = 350.0/gpx->ptu_calH[0]; // empirical
float fh = (f-f1)/(float)(f2-f1);
float rh = 100.0 * ( a1*fh - a0 );
float T0 = 0.0, T1 = -25.0; // T/C
rh += T0 - T/5.5; // empir. temperature compensation
if (T < T1) rh *= 1.0 + (T1-T)/90.0; // empir. temperature compensation
float T0 = 0.0, T1 = -20.0, T2 = -40.0; // T/C v0.4
rh += T0 - T/5.5; // empir. temperature compensation
if (T < T1) rh *= 1.0 + (T1-T)/100.0; // empir. temperature compensation
if (T < T2) rh *= 1.0 + (T2-T)/120.0; // empir. temperature compensation
if (rh < 0.0) rh = 0.0;
if (rh > 100.0) rh = 100.0;
if (T < -273.0) rh = -1.0;
return rh;
}
static int get_PTU(gpx_t *gpx, int ofs, int pck) {
// ---------------------------------------------------------------------------------------
//
// cf. github DF9DQ
// water vapor saturation pressure (Hyland and Wexler)
static float vaporSatP(float Tc) {
double T = Tc + 273.15;
// Apply some correction magic
// T = -0.4931358 + (1.0 + 4.61e-3) * T - 1.3746454e-5 * T*T + 1.2743214e-8 * T*T*T;
// H+W equation
double p = expf(-5800.2206 / T
+1.3914993
+6.5459673 * log(T)
-4.8640239e-2 * T
+4.1764768e-5 * T*T
-1.4452093e-8 * T*T*T
);
return (float)p; // [Pa]
}
// cf. github DF9DQ
static float get_RH2adv(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T, float TH, float P) {
float rh = 0.0;
float cfh = (f-f1)/(float)(f2-f1);
float cap = gpx->ptu_Cf1+(gpx->ptu_Cf2-gpx->ptu_Cf1)*cfh;
double Cp = (cap / gpx->ptu_calH[0] - 1.0) * gpx->ptu_calH[1];
double Trh_20_180 = (TH - 20.0) / 180.0;
double _rh = 0.0;
double aj = 1.0;
double bk = 1.0, b[6];
int j, k;
bk = 1.0;
for (k = 0; k < 6; k++) {
b[k] = bk; // Tp^k
bk *= Trh_20_180;
}
if (P > 0.0) // in particular if P<200hPa , T<-40
{
double _p = P / 1000.0; // bar
double _cpj = 1.0;
double corrCp = 0.0;
double bt, bp[3];
for (j = 0; j < 3; j++) {
bp[j] = gpx->ptu_corHp[j] * (_p/(1.0 + gpx->ptu_corHp[j]*_p) - _cpj/(1.0 + gpx->ptu_corHp[j]));
_cpj *= Cp; // Cp^j
}
corrCp = 0.0;
for (j = 0; j < 3; j++) {
bt = 0.0;
for (k = 0; k < 4; k++) {
bt += gpx->ptu_corHt[4*j+k] * b[k];
}
corrCp += bp[j] * bt;
}
Cp -= corrCp;
}
aj = 1.0;
for (j = 0; j < 7; j++) {
for (k = 0; k < 6; k++) {
_rh += aj * b[k] * gpx->ptu_mtxH[6*j+k];
}
aj *= Cp;
}
if ( P <= 0.0 ) { // empirical correction
float T2 = -40;
if (T < T2) { _rh += (T-T2)/12.0; }
}
rh = _rh * vaporSatP(TH)/vaporSatP(T);
if (rh < 0.0) rh = 0.0;
if (rh > 100.0) rh = 100.0;
return rh;
}
//
// cf. github DF9DQ or stsst/RS-fork
static float get_P(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, int fx)
{
double p = 0.0;
double a0, a1, a0j, a1k;
int j, k;
if (f1 == f2 || f1 == f) return 0.0;
a0 = gpx->ptu_calP[24] / ((float)(f - f1) / (float)(f2 - f1));
a1 = fx * 0.01;
a0j = 1.0;
for (j = 0; j < 6; j++) {
a1k = 1.0;
for (k = 0; k < 4; k++) {
p += a0j * a1k * gpx->ptu_calP[j*4+k];
a1k *= a1;
}
a0j *= a0;
}
return (float)p;
}
// ---------------------------------------------------------------------------------------
//
// barometric formula https://en.wikipedia.org/wiki/Barometric_formula
static float Ph(float h) {
double Pb, Tb, Lb, hb;
//double RgM = 8.31446/(9.80665*0.0289644);
double gMR = 9.80665*0.0289644/8.31446;
float P = 0.0;
if (h > 32000.0) { //P < 8.6802
Pb = 8.6802;
Tb = 228.65;
Lb = 0.0028;
hb = 32000.0;
}
else if (h > 20000.0) { // P < 54.7489 (&& P >= 8.6802)
Pb = 54.7489;
Tb = 216.65;
Lb = 0.001;
hb = 20000.0;
}
else if (h > 11000.0) { // P < 226.321 (&& P >= 54.7489)
Pb = 226.321;
Tb = 216.65;
Lb = 0.0;
hb = 11000.0;
}
else { // P >= 226.321
Pb = 1013.25;
Tb = 288.15;
Lb = -0.0065;
hb = 0.0;
}
//if (Lb == 0.0) altP = -RgM*Tb * log(P/Pb) + hb;
//else altP = Tb/Lb * (pow(P/Pb, -RgM*Lb)-1.0) + hb;
if (Lb == 0.0) P = Pb * exp( -gMR*(h-hb)/Tb );
else P = Pb * pow( 1.0+Lb*(h-hb)/Tb , -gMR/Lb);
return P;
}
static int get_PTU(gpx_t *gpx, int ofs, int pck, int valid_alt) {
int err=0, i;
int bR, bc1, bT1,
bc2, bT2;
int bH;
int bH2;
int bP;
ui32_t meas[12];
float Tc = -273.15;
float TH = -273.15;
float RH = -1.0;
float RH2 = -1.0;
float P = -1.0;
get_CalData(gpx);
@ -558,21 +732,53 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
bT2 = gpx->calfrchk[0x13];
bH = gpx->calfrchk[0x07];
bH2 = gpx->calfrchk[0x07] && gpx->calfrchk[0x08]
&& gpx->calfrchk[0x09] && gpx->calfrchk[0x0A]
&& gpx->calfrchk[0x0B] && gpx->calfrchk[0x0C]
&& gpx->calfrchk[0x0D] && gpx->calfrchk[0x0E]
&& gpx->calfrchk[0x0F] && gpx->calfrchk[0x10]
&& gpx->calfrchk[0x11] && gpx->calfrchk[0x12]
&& gpx->calfrchk[0x2A] && gpx->calfrchk[0x2B]
&& gpx->calfrchk[0x2C] && gpx->calfrchk[0x2D]
&& gpx->calfrchk[0x2E];
bP = gpx->calfrchk[0x21] && gpx->calibytes[0x21F] == 'P'
&& gpx->calfrchk[0x25] && gpx->calfrchk[0x26]
&& gpx->calfrchk[0x27] && gpx->calfrchk[0x28]
&& gpx->calfrchk[0x29] && gpx->calfrchk[0x2A];
if (bR && bc1 && bT1) {
Tc = get_Tc(gpx, meas[0], meas[1], meas[2]);
//Tc0 = get_Tc0(gpx, meas[0], meas[1], meas[2]);
Tc = get_T(gpx, meas[0], meas[1], meas[2], gpx->ptu_co1, gpx->ptu_calT1);
}
gpx->T = Tc;
if (bR && bc2 && bT2) {
TH = get_TH(gpx, meas[6], meas[7], meas[8]);
TH = get_T(gpx, meas[6], meas[7], meas[8], gpx->ptu_co2, gpx->ptu_calT2);
}
gpx->TH = TH;
if (bH) {
if (bH && Tc > -273.0) {
RH = get_RH(gpx, meas[3], meas[4], meas[5], Tc); // TH, TH-Tc (sensorT - T)
}
gpx->RH = RH;
// cf. DF9DQ, stsst/RS-fork
if (bP) {
P = get_P(gpx, meas[9], meas[10], meas[11], i2(gpx->frame+pos_PTU+ofs+2+38));
}
gpx->P = P;
if (gpx->option.ptu == 2) {
float _P = -1.0;
if (bP) _P = P;
else { // approx
if (valid_alt > 0) _P = Ph(gpx->alt);
}
if (bH && bH2 && Tc > -273.0 && TH > -273.0) {
RH2 = get_RH2adv(gpx, meas[3], meas[4], meas[5], Tc, TH, _P);
}
}
gpx->RH2 = RH2;
if (gpx->option.vbs == 4 && (gpx->crc & (crc_PTU | crc_GPS3))==0)
{
@ -585,7 +791,7 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
printf("3: %8d %8d %8d", meas[6], meas[7], meas[8]);
printf(" # ");
//if (Tc > -273.0 && RH > -0.5)
if (0 && Tc > -273.0 && RH > -0.5)
{
printf(" ");
printf(" Tc:%.2f ", Tc);
@ -696,6 +902,7 @@ static int get_GPS2(gpx_t *gpx, int ofs) {
return err;
}
// WGS84/GRS80 Ellipsoid
#define EARTH_a 6378137.0
#define EARTH_b 6356752.31424518
#define EARTH_a2_b2 (EARTH_a*EARTH_a - EARTH_b*EARTH_b)
@ -889,10 +1096,10 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
byte = gpx->frame[pos_CalData+ofs+1+i];
fprintf(stdout, "%02x ", byte);
}
/*
/*
if (err == 0) fprintf(stdout, "[OK]");
else fprintf(stdout, "[NO]");
*/
*/
fprintf(stdout, " ");
}
@ -1001,7 +1208,7 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
if (gpx->option.ecc == 2 && (errors1 < 0 || errors2 < 0))
{ // 2nd pass
{ // 2nd pass: set packet-IDs
gpx->frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; gpx->frame[pos_FRAME+1] = pck_FRAME&0xFF;
gpx->frame[pos_PTU] = (pck_PTU >>8)&0xFF; gpx->frame[pos_PTU +1] = pck_PTU &0xFF;
gpx->frame[pos_GPS1] = (pck_GPS1 >>8)&0xFF; gpx->frame[pos_GPS1 +1] = pck_GPS1 &0xFF;
@ -1073,12 +1280,32 @@ static int prn_frm(gpx_t *gpx) {
static int prn_ptu(gpx_t *gpx) {
fprintf(stdout, " ");
if (gpx->T > -273.0) fprintf(stdout, " T=%.1fC ", gpx->T);
if (gpx->RH > -0.5) fprintf(stdout, " RH=%.0f%% ", gpx->RH);
if (gpx->RH > -0.5 && gpx->option.ptu != 2) fprintf(stdout, " _RH=%.0f%% ", gpx->RH);
if (gpx->P > 0.0) {
if (gpx->P < 100.0) fprintf(stdout, " P=%.2fhPa ", gpx->P);
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
}
if (gpx->option.ptu == 2) {
if (gpx->RH2 > -0.5) fprintf(stdout, " RH2=%.0f%% ", gpx->RH2);
}
// dew point
if (gpx->option.dwp)
{
float rh = gpx->RH;
float Td = -273.15f; // dew point Td
if (gpx->option.ptu == 2) rh = gpx->RH2;
if (rh > 0.0f && gpx->T > -273.0f) {
float gamma = logf(rh / 100.0f) + (17.625f * gpx->T / (243.04f + gpx->T));
Td = 243.04f * gamma / (17.625f - gamma);
fprintf(stdout, " Td=%.1fC ", Td);
}
}
return 0;
}
static int prn_gpstime(gpx_t *gpx) {
Gps2Date(gpx);
//Gps2Date(gpx);
fprintf(stdout, "%s ", weekday[gpx->wday]);
fprintf(stdout, "%04d-%02d-%02d %02d:%02d:%06.3f",
gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek);
@ -1154,7 +1381,7 @@ static int prn_sat3(gpx_t *gpx, int ofs) {
pDOP = gpx->frame[pos_pDOP+ofs]/10.0; if (gpx->frame[pos_pDOP+ofs] == 0xFF) pDOP = -1.0;
fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP);
/*
/*
fprintf(stdout, "CRC: ");
fprintf(stdout, " %04X", pck_GPS1);
if (check_CRC(gpx, pos_GPS1+ofs, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]");
@ -1167,12 +1394,12 @@ static int prn_sat3(gpx_t *gpx, int ofs) {
//fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3));
fprintf(stdout, "\n");
*/
*/
return 0;
}
static int print_position(gpx_t *gpx, int ec) {
int i, j;
int i;
int err, err0, err1, err2, err3;
//int output, out_mask;
int encrypted = 0;
@ -1180,6 +1407,7 @@ static int print_position(gpx_t *gpx, int ec) {
int out = 1;
int sat = 0;
int pos_aux = 0, cnt_aux = 0;
int ofs_ptu = 0, pck_ptu = 0;
int ret = 0;
//gpx->out = 0;
@ -1234,10 +1462,11 @@ static int print_position(gpx_t *gpx, int ec) {
break;
case pck_PTU: // 0x7A2A
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck_PTU);
if ( 0 && !err0 && gpx->option.ptu ) {
prn_ptu(gpx);
ofs_ptu = pos - pos_PTU;
pck_ptu = pck_PTU;
if ( 0 && gpx->option.ptu ) {
//err0 = get_PTU(gpx, ofs_ptu, pck_ptu);
// if (!err0) prn_ptu(gpx);
}
break;
@ -1245,6 +1474,7 @@ static int print_position(gpx_t *gpx, int ec) {
ofs = pos - pos_GPS1;
err1 = get_GPS1(gpx, ofs);
if ( !err1 ) {
Gps2Date(gpx);
if (out) prn_gpstime(gpx);
if (sat) prn_sat1(gpx, ofs);
}
@ -1268,8 +1498,11 @@ static int print_position(gpx_t *gpx, int ec) {
break;
case pck_SGM_xTU: // 0x7F1B
ofs = pos - pos_PTU;
err0 = get_PTU(gpx, ofs, pck);
ofs_ptu = pos - pos_PTU;
pck_ptu = pck;
if ( 0 ) {
//err0 = get_PTU(gpx, ofs_ptu, pck_ptu);
}
break;
case pck_SGM_CRYPT: // 0x80A7
@ -1301,9 +1534,11 @@ static int print_position(gpx_t *gpx, int ec) {
if ( pos > frm_end ) // end of (sub)frame
{
if (gpx->option.ptu && out && !sat && !err0 && !encrypted) {
prn_ptu(gpx);
if (gpx->option.ptu && !sat && !encrypted && pck_ptu > 0) {
err0 = get_PTU(gpx, ofs_ptu, pck_ptu, !err3);
if (!err0 && out) prn_ptu(gpx);
}
pck_ptu = 0;
get_Calconf(gpx, out, ofs_cal);
@ -1325,11 +1560,18 @@ static int print_position(gpx_t *gpx, int ec) {
fprintf(stdout, "{ \"type\": \"%s\"", "RS41");
fprintf(stdout, ", \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d, \"bt\": %d, \"batt\": %.2f",
gpx->frnr, gpx->id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
}
if (gpx->option.ptu && !err0 && gpx->RH > -0.5) {
fprintf(stdout, ", \"humidity\": %.1f", gpx->RH );
if (gpx->option.ptu && !err0) {
float _RH = gpx->RH;
if (gpx->option.ptu == 2) _RH = gpx->RH2;
if (gpx->T > -273.0) {
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
}
if (_RH > -0.5) {
fprintf(stdout, ", \"humidity\": %.1f", _RH );
}
if (gpx->P > 0.0) {
fprintf(stdout, ", \"pressure\": %.2f", gpx->P );
}
}
if (gpx->aux) { // <=> gpx->xdata[0]!='\0'
fprintf(stdout, ", \"aux\": \"%s\"", gpx->xdata );
@ -1374,13 +1616,16 @@ static int print_position(gpx_t *gpx, int ec) {
ofs = 0;
if (pck < 0x8000) {
err0 = get_PTU(gpx, 0, pck);
//err0 = get_PTU(gpx, 0, pck, 0);
if (pck == pck_PTU) ofs = 0;
else if (pck == pck_SGM_xTU) ofs = 0x1B-0x2A;
err1 = get_GPS1(gpx, ofs);
err2 = get_GPS2(gpx, ofs);
err3 = get_GPS3(gpx, ofs);
if (!err1) Gps2Date(gpx);
err0 = get_PTU(gpx, 0, pck, !err3);
if (out) {
@ -1464,11 +1709,16 @@ static void print_frame(gpx_t *gpx, int len, dsp_t *dsp) {
fprintf(stdout, "\n");
}
else {
pthread_mutex_lock( dsp->thd.mutex );
fprintf(stdout, "<%d> ", dsp->thd.tn);
pthread_mutex_lock( dsp->thd->mutex );
//fprintf(stdout, "<%d> ", dsp->thd->tn);
fprintf(stdout, "<%d: ", dsp->thd->tn);
fprintf(stdout, "s=%+.4f, ", dsp->mv);
fprintf(stdout, "f=%+.4f", -dsp->thd->xlt_fq);
if (dsp->opt_dc) fprintf(stdout, "%+.6f", dsp->Df/(double)dsp->sr);
fprintf(stdout, "> ");
ret = print_position(gpx, ec);
if (ret==0) fprintf(stdout, "\n");
pthread_mutex_unlock( dsp->thd.mutex );
pthread_mutex_unlock( dsp->thd->mutex );
}
}
@ -1518,7 +1768,7 @@ void *thd_rs41(void *targs) { // pcm_t *pcm, double xlt_fq
// init gpx
gpx.option.vbs = 1;
gpx.option.ptu = 1;
gpx.option.ptu = 2;
gpx.option.aut = 1;
gpx.option.jsn = tharg->option_jsn;
@ -1546,7 +1796,7 @@ void *thd_rs41(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.dectaps = pcm->dectaps;
dsp.decM = pcm->decM;
dsp.thd = tharg->thd;
dsp.thd = &(tharg->thd);
dsp.bps = pcm->bps;
dsp.nch = pcm->nch;
@ -1564,17 +1814,18 @@ void *thd_rs41(void *targs) { // pcm_t *pcm, double xlt_fq
dsp.opt_lp = 1;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = tharg->option_dc;
dsp.opt_dc = tharg->option_dc;
dsp.opt_cnt = tharg->option_cnt;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
//fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return NULL;
goto exit_thread;
};
//if (option_iq: 2,3) bitofs += 1; // FM: +1 , IQ: +2, IQ5: +1
@ -1634,6 +1885,9 @@ void *thd_rs41(void *targs) { // pcm_t *pcm, double xlt_fq
free_buffers(&dsp);
exit_thread:
reset_blockread(&dsp);
(dsp.thd)->used = 0;
return NULL;
}

Wyświetl plik

@ -1,5 +1,6 @@
/*
gcc -O2 -c demod_base.c
gcc -O2 -c bch_ecc_mod.c
gcc -O2 -c rs41base.c
@ -10,13 +11,26 @@ gcc -O2 rs_multi.c demod_base.o bch_ecc_mod.o rs41base.o dfm09base.o m10base.o l
./a.out --rs41 <fq0> --dfm <fq1> --m10 <fq2> baseband_IQ.wav
-0.5 < fq < 0.5 , fq=freq/sr
e.g.
[terminal 1]
./a.out --dc --fifo rsfifo --m10 -0.28034 --lms 0.12636 baseband_IQ.wav
[terminal 2]
echo "m10 -0.36" > rsfifo
echo "-1" > rsfifo
echo "lms 0.02428" > rsfifo
*/
#include <stdio.h>
#include <sys/stat.h> // mkfifo()
#include <unistd.h> // open(),close(),unlink()
#include <fcntl.h> // O_RDONLY //... setmode()/cygwin
#ifdef CYGWIN
#include <fcntl.h> // cygwin: _setmode()
//#include <fcntl.h> // cygwin: _setmode()
#include <io.h>
#endif
@ -29,8 +43,8 @@ static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static float complex *block_decMB;
int rbf1; // extern in demod_base.c
extern int rbf1; // demod_base.c
extern int bufeof; // demod_base.c
void *thd_rs41(void *);
void *thd_dfm09(void *);
@ -85,6 +99,7 @@ static int pcm_dec_init(pcm_t *p) {
return 0;
}
#define FIFOBUF_LEN 20
int main(int argc, char **argv) {
@ -98,7 +113,15 @@ int main(int argc, char **argv) {
int option_pcmraw = 0,
option_jsn = 0,
option_dc = 0,
option_min = 0;
option_min = 0,
option_cont = 0;
// FIFO
int option_fifo = 0;
char *rs_fifo = NULL;
int fd = -1;
char fifo_buf[FIFOBUF_LEN];
int th_used = 0;
#ifdef CYGWIN
_setmode(fileno(stdin), _O_BINARY); // _fileno(stdin)
@ -115,8 +138,7 @@ int main(int argc, char **argv) {
if (strcmp(*argv, "--rs41") == 0) {
double fq = 0.0;
++argv;
if (*argv) fq = atof(*argv);
else return -1;
if (*argv) fq = atof(*argv); else return -1;
if (fq < -0.5) fq = -0.5;
if (fq > 0.5) fq = 0.5;
if (xlt_cnt < MAX_FQ) {
@ -128,8 +150,7 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "--dfm") == 0) {
double fq = 0.0;
++argv;
if (*argv) fq = atof(*argv);
else return -1;
if (*argv) fq = atof(*argv); else return -1;
if (fq < -0.5) fq = -0.5;
if (fq > 0.5) fq = 0.5;
if (xlt_cnt < MAX_FQ) {
@ -141,8 +162,7 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "--m10") == 0) {
double fq = 0.0;
++argv;
if (*argv) fq = atof(*argv);
else return -1;
if (*argv) fq = atof(*argv); else return -1;
if (fq < -0.5) fq = -0.5;
if (fq > 0.5) fq = 0.5;
if (xlt_cnt < MAX_FQ) {
@ -154,8 +174,7 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "--lms") == 0) {
double fq = 0.0;
++argv;
if (*argv) fq = atof(*argv);
else return -1;
if (*argv) fq = atof(*argv); else return -1;
if (fq < -0.5) fq = -0.5;
if (fq > 0.5) fq = 0.5;
if (xlt_cnt < MAX_FQ) {
@ -180,6 +199,18 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "--min") == 0) {
option_min = 1;
}
else if ( (strcmp(*argv, "-c") == 0) || (strcmp(*argv, "--cnt") == 0) ) {
option_cont = 1;
}
else if (strcmp(*argv, "--fifo") == 0) {
++argv;
if (*argv) rs_fifo = *argv; else return -1;
unlink(rs_fifo);
if (mkfifo(rs_fifo, 0666) < 0) { // evtl. mode : S_IWUSR | S_IRUSR
//fprintf(stderr, "error open %s\n", rs_fifo); // exit, if exists ?
}
option_fifo = 1;
}
else if (strcmp(*argv, "-") == 0) {
int sample_rate = 0, bits_sample = 0, channels = 0;
++argv;
@ -199,7 +230,7 @@ int main(int argc, char **argv) {
else {
fp = fopen(*argv, "rb");
if (fp == NULL) {
fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv);
fprintf(stderr, "error open %s\n", *argv);
return -1;
}
wavloaded = 1;
@ -229,7 +260,8 @@ int main(int argc, char **argv) {
block_decMB = calloc(pcm.decM*blk_sz+1, sizeof(float complex)); if (block_decMB == NULL) return -1;
thargs_t tharg[xlt_cnt];
thargs_t tharg[MAX_FQ]; // xlt_cnt<=MAX_FQ
for (k = 0; k < MAX_FQ; k++) tharg[k].thd.used = 0;
for (k = 0; k < xlt_cnt; k++) {
tharg[k].thd.tn = k;
@ -249,8 +281,10 @@ int main(int argc, char **argv) {
tharg[k].option_jsn = option_jsn;
tharg[k].option_dc = option_dc;
tharg[k].option_cnt = option_cont;
rbf1 |= tharg[k].thd.tn_bit;
tharg[k].thd.used = 1;
}
for (k = 0; k < xlt_cnt; k++) {
@ -258,16 +292,129 @@ int main(int argc, char **argv) {
}
// FIFO
//
if (option_fifo)
{
fd = open(rs_fifo, O_RDONLY | O_NONBLOCK); //fcntl.h
if (fd < 0) {
fprintf(stderr, "error open %s\n", rs_fifo);
return -1;
}
while ( !bufeof ) {
int l = 0;
memset(fifo_buf, 0, FIFOBUF_LEN);
th_used = 0;
for (k = 0; k < MAX_FQ; k++) th_used += tharg[k].thd.used;
if (th_used == 0) break;
l = read(fd, fifo_buf, FIFOBUF_LEN);
if ( l > 1 ) {
void *rstype = NULL;
char *fifo_fq = fifo_buf;
while (l > 1 && fifo_buf[l-1] < 0x20) l--;
fifo_buf[l] = '\0'; // remove \n, terminate string
if (strncmp(fifo_buf, "rs41", 4) == 0) {
fifo_fq = fifo_buf + 4;
rstype = thd_rs41;
}
else if (strncmp(fifo_buf, "dfm", 3) == 0) {
fifo_fq = fifo_buf + 3;
rstype = thd_dfm09;
}
else if (strncmp(fifo_buf, "m10", 3) == 0) {
fifo_fq = fifo_buf + 3;
rstype = thd_m10;
}
else if (strncmp(fifo_buf, "lms", 3) == 0) {
fifo_fq = fifo_buf + 3;
rstype = thd_lms6X;
}
else {
if (fifo_buf[0] == '-') { // -<n> : close <n>
int num = atoi(fifo_buf+1);
if (num >= 0 && num < MAX_FQ) {
if (tharg[num].thd.used) {
tharg[num].thd.used = 0;
}
}
}
continue;
}
double fq = 0.0;
if (fifo_fq) fq = atof(fifo_fq);
else return -1;
if (fq < -0.5) fq = -0.5;
if (fq > 0.5) fq = 0.5;
// find slot
for (k = 0; k < MAX_FQ; k++) {
if (tharg[k].thd.used == 0) break;
}
if (k < MAX_FQ) {
double base_fq = fq;
tharg[k].thd.tn = k;
tharg[k].thd.tn_bit = (1<<k);
tharg[k].thd.mutex = &mutex;
tharg[k].thd.cond = &cond;
//tharg[k].thd.lock = &lock;
tharg[k].thd.blk = block_decMB;
tharg[k].thd.xlt_fq = -base_fq;
if (cfreq > 0) {
int fq_kHz = (cfreq - tharg[k].thd.xlt_fq*pcm.sr_base + 500)/1e3;
tharg[k].jsn_freq = fq_kHz;
}
tharg[k].pcm = pcm;
tharg[k].option_jsn = option_jsn;
tharg[k].option_dc = option_dc;
rbf1 |= tharg[k].thd.tn_bit;
tharg[k].thd.used = 1;
pthread_create(&tharg[k].thd.tid, NULL, rstype, &tharg[k]);
pthread_mutex_lock( &mutex );
fprintf(stdout, "<%d: add f=%+.4f>\n", k, base_fq);
pthread_mutex_unlock( &mutex );
k++;
if (k > xlt_cnt) xlt_cnt = k;
for (k = 0; k < xlt_cnt; k++) {
tharg[k].thd.max_fq = xlt_cnt;
}
}
}
sleep(1);
}
}
for (k = 0; k < xlt_cnt; k++) {
pthread_join(tharg[k].thd.tid, NULL);
}
th_used = 1;
while (th_used) {
th_used = 0;
for (k = 0; k < MAX_FQ; k++) th_used += tharg[k].thd.used;
}
if (block_decMB) { free(block_decMB); block_decMB = NULL; }
decimate_free();
fclose(fp);
if (fd >= 0) { // FIFO
close(fd);
unlink(rs_fifo);
}
return 0;
}