diff --git a/demod/multi/README.md b/demod/multi/README.md index 88fcd60..b1bf414 100644 --- a/demod/multi/README.md +++ b/demod/multi/README.md @@ -15,13 +15,24 @@ simultaneous decoding      `-lm -pthread -o rs_multi` #### Usage/Examples - `./rs_multi --rs41 --dfm --m10 --lms `
- `./rs_multi --rs41 --dfm --m10 --lms - `
+ `$ ./rs_multi --rs41 --dfm --m10 --lms `
+ `$ ./rs_multi --rs41 --dfm --m10 --lms - `
where
-      `-0.5 < fq < 0.5`: (relative) frequency, `fq=freq/sr`
+      `-0.5 < fqX < 0.5`: (relative) frequency, `fq=freq/sr`
     ``: sample rate
     `=8,16,32`: bits per (real) sample (u8, s16 or f32)
- decodes up to `MAX_FQ=5 (demod_base.h)` signals. Decoding more signals than number of CPUs/cores is not recommended.
- 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.
+ 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.
+ + Sending add/remove commands via fifo:
+ [terminal 1]
+ `$ rtl_sdr -f 403.0M -s 1920000 - | ./rs_multi --fifo rsfifo --rs41 --dfm - 1920000 8`
+ where `` is the (relative) frequency of signal `X`
+ [terminal 2]
+ *add M10 on ``*:
`$ echo "m10 " > rsfifo`
+ *remove ``*:
`$ echo "-1" > rsfifo`
+ + If there is no decode for `SEC_NO_SIGNAL=10 (demod_base.c)` seconds, the signal is removed, + unless option `-c` is used.
+ `--json` output is also possible. diff --git a/demod/multi/demod_base.c b/demod/multi/demod_base.c index 9a68d94..879be30 100644 --- a/demod/multi/demod_base.c +++ b/demod/multi/demod_base.c @@ -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; } } diff --git a/demod/multi/demod_base.h b/demod/multi/demod_base.h index ef50139..09fe5a8 100644 --- a/demod/multi/demod_base.h +++ b/demod/multi/demod_base.h @@ -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 *); + + diff --git a/demod/multi/dfm09base.c b/demod/multi/dfm09base.c index cebbb59..3ba2d07 100644 --- a/demod/multi/dfm09base.c +++ b/demod/multi/dfm09base.c @@ -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; } diff --git a/demod/multi/lms6Xbase.c b/demod/multi/lms6Xbase.c index 169e0e8..048dca1 100644 --- a/demod/multi/lms6Xbase.c +++ b/demod/multi/lms6Xbase.c @@ -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; } diff --git a/demod/multi/m10base.c b/demod/multi/m10base.c index a24f165..3bb9a4e 100644 --- a/demod/multi/m10base.c +++ b/demod/multi/m10base.c @@ -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; } diff --git a/demod/multi/rs41base.c b/demod/multi/rs41base.c index 17ce4f5..d40def2 100644 --- a/demod/multi/rs41base.c +++ b/demod/multi/rs41base.c @@ -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; } diff --git a/demod/multi/rs_multi.c b/demod/multi/rs_multi.c index ab82811..b905f03 100644 --- a/demod/multi/rs_multi.c +++ b/demod/multi/rs_multi.c @@ -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 --dfm --m10 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 +#include // mkfifo() +#include // open(),close(),unlink() +#include // O_RDONLY //... setmode()/cygwin + #ifdef CYGWIN - #include // cygwin: _setmode() + //#include // cygwin: _setmode() #include #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] == '-') { // - : close + 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< 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; }