mod: --softin from test-branch

pull/27/head
Zilog80 2020-06-14 14:43:47 +02:00
rodzic 2e770cee8b
commit 7b00d3a678
12 zmienionych plików z 1007 dodań i 1804 usunięć

Wyświetl plik

@ -59,4 +59,9 @@ alternative decoders using cross-correlation for better header-synchronization
The difference between hard and soft viterbi becomes only apparent at lower SNR. The inner convolutional The difference between hard and soft viterbi becomes only apparent at lower SNR. The inner convolutional
code does most of the error correction. The concatenated outer Reed-Solomon code kicks in only at low SNR. code does most of the error correction. The concatenated outer Reed-Solomon code kicks in only at low SNR.
soft input:<br />
Option `--softin` expects float32 symbols as input, with `s>0` corresponding to `bit=1`.<br />
(remark/caution: often soft bits are defined as `bit=0 -> s=+1` and `bit=1 -> s=-1` such that the identity element `0`
for addition mod 2 corresponds to the identity element `+1` for multiplication.)

Wyświetl plik

@ -24,6 +24,8 @@
/* ------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------ */
#ifndef EXT_FSK
static void raw_dft(dft_t *dft, float complex *Z) { static void raw_dft(dft_t *dft, float complex *Z) {
int s, l, l2, i, j, k; int s, l, l2, i, j, k;
float complex w1, w2, T; float complex w1, w2, T;
@ -126,7 +128,7 @@ static int dft_window(dft_t *dft, int w) {
dft->win[n] = 0.5 * ( 1.0 - cos(2*M_PI*n/(float)(dft->N2-1)) ); dft->win[n] = 0.5 * ( 1.0 - cos(2*M_PI*n/(float)(dft->N2-1)) );
break ; break ;
case 2: // Hamming case 2: // Hamming
dft->win[n] = 25/46.0 + (1.0 - 25/46.0)*cos(2*M_PI*n / (float)(dft->N2-1)); dft->win[n] = 25/46.0 - (1.0 - 25/46.0)*cos(2*M_PI*n / (float)(dft->N2-1));
break ; break ;
case 3: // Blackmann case 3: // Blackmann
dft->win[n] = 7938/18608.0 dft->win[n] = 7938/18608.0
@ -942,6 +944,96 @@ int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, i
return 0; return 0;
} }
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1) {
// symlen==2: manchester2 10->0,01->1: 2.bit
float sample, sample1;
float avg;
float ths = 0.5, scale = 0.27;
double sum = 0.0, sum1 = 0.0;
double mid;
//double l = 1.0;
double bg = pos*dsp->symlen*dsp->sps;
double dc = 0.0;
ui8_t bit = 0, bit1 = 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];
sample1 = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs-1 + 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;
sample1 -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) {
sum -= sample;
sum1 -= sample1;
}
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];
sample1 = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs-1 + 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;
sample1 -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) {
sum += sample;
sum1 += sample1;
}
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
if (sum >= 0) bit = 1;
else bit = 0;
shb->hb = bit;
shb->sb = (float)sum;
if (sum1 >= 0) bit1 = 1;
else bit1 = 0;
shb1->hb = bit1;
shb1->sb = (float)sum1;
return 0;
}
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
#define IF_SAMPLE_RATE 48000 #define IF_SAMPLE_RATE 48000
@ -1275,12 +1367,6 @@ int free_buffers(dsp_t *dsp) {
/* ------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------ */
ui32_t get_sample(dsp_t *dsp) {
return dsp->sample_out;
}
/* ------------------------------------------------------------------------------------ */
int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) { int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
ui32_t k = 0; ui32_t k = 0;
@ -1345,3 +1431,145 @@ int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
return EOF; return EOF;
} }
/* ------------------------------------------------------------------------------------ */
#else
// external FSK demod: read float32 soft symbols
float read_wav_header(pcm_t *pcm, FILE *fp) {}
int f32buf_sample(dsp_t *dsp, int inv) {}
int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spike) {}
int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike) {}
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1) {}
int init_buffers(dsp_t *dsp) {}
int free_buffers(dsp_t *dsp) {}
int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {}
#endif
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->thb ) {
*score = mv;
return 1;
}
}
return EOF;
}
static float corr_softhdb(hdb_t *hdb) { // max score in window probably not needed
int i, j;
int headlen = hdb->len;
double sum = 0.0;
double normx = 0.0,
normy = 0.0;
float x, y;
i = 0;
j = hdb->bufpos + 1;
while (i < headlen) {
if (j >= headlen) j = 0;
x = hdb->sbuf[j];
y = 2.0*(hdb->hdr[i]&0x1) - 1.0;
sum += y * hdb->sbuf[j];
normx += x*x;
normy += y*y;
j++;
i++;
}
sum /= sqrt(normx*normy);
return sum;
}
int f32soft_read(FILE *fp, float *s) {
unsigned int word = 0;
short *b = (short*)&word;
float *f = (float*)&word;
int bps = 32;
if (fread( &word, bps/8, 1, fp) != 1) return EOF;
if (bps == 32) {
*s = *f;
}
else {
if (bps == 8) { *b -= 128; }
*s = *b/128.0;
if (bps == 16) { *s /= 256.0; }
}
return 0;
}
int find_softbinhead(FILE *fp, hdb_t *hdb, float *score) {
int headlen = hdb->len;
float sbit;
float mv;
//*score = 0.0;
while ( f32soft_read(fp, &sbit) != EOF )
{
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->sbuf[hdb->bufpos] = sbit;
mv = corr_softhdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}

Wyświetl plik

@ -144,16 +144,30 @@ typedef struct {
} hsbit_t; } hsbit_t;
typedef struct {
char *hdr;
char *buf;
float *sbuf;
int len;
int bufpos;
float thb;
float ths;
} hdb_t;
float read_wav_header(pcm_t *, FILE *); float read_wav_header(pcm_t *, FILE *);
int f32buf_sample(dsp_t *, int); int f32buf_sample(dsp_t *, int);
int read_slbit(dsp_t *, int*, int, int, int, float, 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 read_softbit(dsp_t *, hsbit_t *, int, int, int, float, int);
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1);
int init_buffers(dsp_t *); int init_buffers(dsp_t *);
int free_buffers(dsp_t *); int free_buffers(dsp_t *);
ui32_t get_sample(dsp_t *);
int find_header(dsp_t *, float, int, int, int); int find_header(dsp_t *, float, int, int, int);
int f32soft_read(FILE *fp, float *s);
int find_binhead(FILE *fp, hdb_t *hdb, float *score);
int find_softbinhead(FILE *fp, hdb_t *hdb, float *score);

Wyświetl plik

@ -885,67 +885,6 @@ static int print_frame(gpx_t *gpx) {
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
// header bit buffer
typedef struct {
char *hdr;
char *buf;
char len;
int bufpos;
float ths;
} hdb_t;
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
static int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -961,6 +900,7 @@ int main(int argc, char **argv) {
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_bin = 0; int option_bin = 0;
int option_softin = 0;
int option_json = 0; // JSON blob output (for auto_rx) int option_json = 0; // JSON blob output (for auto_rx)
int option_pcmraw = 0; int option_pcmraw = 0;
int wavloaded = 0; int wavloaded = 0;
@ -1042,12 +982,13 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "--spike") == 0) ) { else if ( (strcmp(*argv, "--spike") == 0) ) {
spike = 1; spike = 1;
} }
else if ( (strcmp(*argv, "--auto") == 0) ) { option_auto = 1; } else if (strcmp(*argv, "--auto") == 0) { option_auto = 1; }
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if ( (strcmp(*argv, "--dist") == 0) ) { option_dist = 1; option_ecc = 1; } else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if ( (strcmp(*argv, "--json") == 0) ) { option_json = 1; option_ecc = 1; } else if (strcmp(*argv, "--dist") == 0) { option_dist = 1; option_ecc = 1; }
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--json") == 0) { option_json = 1; option_ecc = 1; }
else if ( (strcmp(*argv, "--ths") == 0) ) { else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
thres = atof(*argv); thres = atof(*argv);
@ -1150,7 +1091,14 @@ int main(int argc, char **argv) {
headerlen = strlen(dfm_rawheader); headerlen = strlen(dfm_rawheader);
if (!option_bin) { #ifdef EXT_FSK
if (!option_bin && !option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_bin && !option_softin) {
if (option_iq == 0 && option_pcmraw) { if (option_iq == 0 && option_pcmraw) {
fclose(fp); fclose(fp);
@ -1198,38 +1146,48 @@ int main(int argc, char **argv) {
if ( dsp.sps < 8 ) { 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 -1;
}
bitofs += shift;
} }
else { else {
if (option_bin && option_softin) option_bin = 0;
// init circular header bit buffer // init circular header bit buffer
hdb.hdr = dfm_rawheader; hdb.hdr = dfm_rawheader;
hdb.len = strlen(dfm_rawheader); hdb.len = strlen(dfm_rawheader);
hdb.ths = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !! hdb.thb = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !!
hdb.bufpos = -1; hdb.bufpos = -1;
hdb.buf = calloc(hdb.len, sizeof(char)); hdb.buf = calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) { if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n"); fprintf(stderr, "error: malloc\n");
return -1; return -1;
} }
hdb.ths = 0.7; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
} }
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
while ( 1 ) while ( 1 )
{ {
if (option_bin) { // aka find_binrawhead() if (option_bin) { // aka find_binrawhead()
header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits? header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits?
hdrcnt += nfrms; hdrcnt += nfrms;
} }
else { // FM-audio: else if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
hdrcnt += nfrms;
}
else { //2 (false positive) // FM-audio:
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0 header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv; _mv = dsp.mv;
} }
@ -1251,7 +1209,7 @@ int main(int argc, char **argv) {
frm = 0; frm = 0;
while ( frm < nfrms ) { // nfrms=1,2,4,8 while ( frm < nfrms ) { // nfrms=1,2,4,8
if (option_bin) { if (option_bin || option_softin) {
gpx._frmcnt = hdrcnt + frm; gpx._frmcnt = hdrcnt + frm;
} }
else { else {
@ -1271,15 +1229,25 @@ int main(int argc, char **argv) {
hsbit.sb = 2*hsbit.hb - 1; hsbit.sb = 2*hsbit.hb - 1;
} }
} }
else if (option_softin) {
float s1 = 0.0;
float s2 = 0.0;
float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
hsbit.sb = s;
hsbit.hb = (s>=0.0);
}
}
}
else { else {
if (option_iq >= 2) { float bl = -1;
float bl = -1; if (option_iq >= 2) spike = 0;
if (option_iq > 2) bl = 4.0; if (option_iq > 2) bl = 4.0;
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0); bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike); // symlen=2
}
else {
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, -1, spike);
}
// optional: // optional:
// normalize soft bit s_j by // normalize soft bit s_j by
// rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1] // rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1]
@ -1309,7 +1277,7 @@ int main(int argc, char **argv) {
} }
if (!option_bin) free_buffers(&dsp); if (!option_bin && !option_softin) free_buffers(&dsp);
else { else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; } if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
} }

Wyświetl plik

@ -3,6 +3,10 @@
* LMS6 * LMS6
* (403 MHz) * (403 MHz)
* *
* soft decision test:
* IQ-decoding: --vit2 (soft decision) better performance (low dB)
* FM-decoding: --vit1 (hard decision) better than --vit2
*
* sync header: correlation/matched filter * sync header: correlation/matched filter
* files: lms6Xmod.c demod_mod.c demod_mod.h bch_ecc_mod.c bch_ecc_mod.h * files: lms6Xmod.c demod_mod.c demod_mod.h bch_ecc_mod.c bch_ecc_mod.h
* compile, either (a) or (b): * compile, either (a) or (b):
@ -16,7 +20,8 @@
* *
* usage: * usage:
* ./lms6Xmod --vit --ecc <audio.wav> * ./lms6Xmod --vit --ecc <audio.wav>
* ( --vit recommended) * ./lms6Xmod --vit2 --ecc --IQ 0.0 <iq_data.wav>
* ( --vit/--vit2 recommended)
* author: zilog80 * author: zilog80
*/ */
@ -116,12 +121,11 @@ typedef struct {
ui8_t bIn; ui8_t bIn;
ui8_t codeIn; ui8_t codeIn;
ui8_t prevState; // 0..M=64 ui8_t prevState; // 0..M=64
int w; // > 255 : if (w>250): w=250 ? float w;
//float sw;
} states_t; } states_t;
typedef struct { 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 state[RAWBITFRAME_LEN+OVERLAP +8][M];
states_t d[N]; states_t d[N];
} VIT_t; } VIT_t;
@ -138,7 +142,7 @@ typedef struct {
double lat; double lon; double alt; double lat; double lon; double alt;
double vH; double vD; double vV; double vH; double vD; double vV;
double vE; double vN; double vU; 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 ui8_t frame[FRM_LEN]; // = { 0x24, 0x54, 0x00, 0x00}; // dataheader
int frm_pos; // ecc_blk <-> frm_blk int frm_pos; // ecc_blk <-> frm_blk
int sf6; int sf6;
@ -213,12 +217,16 @@ static int vit_initCodes(gpx_t *gpx) {
return 0; return 0;
} }
static int vit_dist(int c, char *rc) { static float vit_dist2(int c, hsbit_t *rc) {
return (((c>>1)^rc[0])&1) + ((c^rc[1])&1); 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) { static int vit_start(VIT_t *vit, hsbit_t *rc) {
int t, m, j, c, d; int t, m, j, c;
float d;
t = L-1; t = L-1;
m = M; m = M;
@ -236,7 +244,7 @@ static int vit_start(VIT_t *vit, char *rc) {
c = vit_code[j]; c = vit_code[j];
vit->state[t][j].bIn = j % 2; vit->state[t][j].bIn = j % 2;
vit->state[t][j].codeIn = c; 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; vit->state[t][j].w = vit->state[t-1][vit->state[t][j].prevState].w + d;
} }
m *= 2; m *= 2;
@ -245,7 +253,7 @@ static int vit_start(VIT_t *vit, char *rc) {
return t; 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 b, nstate;
int j, index; int j, index;
@ -255,7 +263,7 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
vit->d[nstate].bIn = b; vit->d[nstate].bIn = b;
vit->d[nstate].codeIn = vit_code[nstate]; vit->d[nstate].codeIn = vit_code[nstate];
vit->d[nstate].prevState = j; 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 );
} }
} }
@ -272,11 +280,11 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
static int vit_path(VIT_t *vit, int j, int t) { static int vit_path(VIT_t *vit, int j, int t) {
int c; int c;
vit->rawbits[2*t] = '\0'; vit->rawbits[2*t].hb = '\0';
while (t > 0) { while (t > 0) {
c = vit->state[t][j].codeIn; c = vit->state[t][j].codeIn;
vit->rawbits[2*t -2] = 0x30 + ((c>>1) & 1); vit->rawbits[2*t -2].hb = 0x30 + ((c>>1) & 1);
vit->rawbits[2*t -1] = 0x30 + (c & 1); vit->rawbits[2*t -1].hb = 0x30 + (c & 1);
j = vit->state[t][j].prevState; j = vit->state[t][j].prevState;
t--; t--;
} }
@ -284,13 +292,20 @@ static int vit_path(VIT_t *vit, int j, int t) {
return 0; 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 t, tmax;
int j, j_min, w_min; int j, j_min;
float w_min;
vit_start(vit, rc); vit_start(vit, rc);
tmax = strlen(rc)/2; tmax = hbstr_len(rc)/2;
for (t = L-1; t < tmax; t++) for (t = L-1; t < tmax; t++)
{ {
@ -315,15 +330,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; int j, n, bitA, bitB;
char *p; hsbit_t *p;
int len; int len;
int errors = 0; int errors = 0;
int m = L-1; int m = L-1;
len = strlen(rawbits); len = hbstr_len(rawbits);
for (j = 0; j < m; j++) bits[j] = '0'; for (j = 0; j < m; j++) bits[j] = '0';
n = 0; n = 0;
while ( 2*(m+n) < len ) { while ( 2*(m+n) < len ) {
@ -333,10 +348,10 @@ static int deconv(char* rawbits, char *bits) {
bitA ^= (bits[n+j]&1) & (polyA[j]&1); bitA ^= (bits[n+j]&1) & (polyA[j]&1);
bitB ^= (bits[n+j]&1) & (polyB[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'; 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]&1))==0 && (bitB^(p[1]&1))==0 ) bits[n+m] = '0'; else if ( (bitA^(p[0].hb&1))==0 && (bitB^(p[1].hb&1))==0 ) bits[n+m] = '0';
else { 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; else bits[n+m] = 0x38;
errors = n; errors = n;
break; break;
@ -795,7 +810,7 @@ static void proc_frame(gpx_t *gpx, int len) {
ui8_t block_bytes[FRAME_LEN+8]; ui8_t block_bytes[FRAME_LEN+8];
ui8_t rs_cw[rs_N]; ui8_t rs_cw[rs_N];
char frame_bits[BITFRAME_LEN+OVERLAP*BITS +8]; // init L-1 bits mit 0 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 i, j;
int err = 0; int err = 0;
int errs = 0; int errs = 0;
@ -804,13 +819,17 @@ static void proc_frame(gpx_t *gpx, int len) {
if ((len % 8) > 4) { 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); flen = len / (2*BITS);
if (gpx->option.vit == 1) { if (gpx->option.vit) {
viterbi(gpx->vit, gpx->blk_rawbits); viterbi(gpx->vit, gpx->blk_rawbits);
rawbits = gpx->vit->rawbits; rawbits = gpx->vit->rawbits;
} }
@ -922,6 +941,8 @@ static void proc_frame(gpx_t *gpx, int len) {
} }
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -930,6 +951,7 @@ int main(int argc, char **argv) {
int option_iq = 0; int option_iq = 0;
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0; int option_pcmraw = 0;
int wavloaded = 0; int wavloaded = 0;
int sel_wavch = 0; // audio channel: left int sel_wavch = 0; // audio channel: left
@ -940,7 +962,7 @@ int main(int argc, char **argv) {
int k; int k;
int bit, rbit; hsbit_t hsbit, rhsbit, rhsbit1;
int bitpos = 0; int bitpos = 0;
int bitQ; int bitQ;
int pos; int pos;
@ -948,15 +970,17 @@ int main(int argc, char **argv) {
int header_found = 0; int header_found = 0;
float thres = 0.68; float thres = 0.65;
float _mv = 0.0; float _mv = 0.0;
float lpIQ_bw = 16e3;
int symlen = 1; int symlen = 1;
int bitofs = 0; int bitofs = 0;
int shift = 0; int shift = 0;
int bitofs6 = 1; // +1 .. +2 int bitofs6 = 0; // -1 .. +2
int bitofsX = 0; // 0 .. +1 int bitofsX = 0; // -1 .. +1
unsigned int bc = 0; unsigned int bc = 0;
@ -966,17 +990,21 @@ int main(int argc, char **argv) {
pcm_t pcm = {0}; pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp)); dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
/*
hdb_t hdb = {0};
/*
// gpx_t _gpx = {0}; gpx_t *gpx = &_gpx; // stack size ... // gpx_t _gpx = {0}; gpx_t *gpx = &_gpx; // stack size ...
gpx_t *gpx = NULL; gpx_t *gpx = NULL;
gpx = calloc(1, sizeof(gpx_t)); gpx = calloc(1, sizeof(gpx_t));
//memset(gpx, 0, sizeof(gpx_t)); //memset(gpx, 0, sizeof(gpx_t));
*/ */
gpx_t _gpx = {0}; gpx_t *gpx = &_gpx; gpx_t _gpx = {0}; gpx_t *gpx = &_gpx;
gpx->auto_detect = 1; gpx->auto_detect = 1;
gpx->reset_dsp = 0; gpx->reset_dsp = 0;
#ifdef CYGWIN #ifdef CYGWIN
_setmode(fileno(stdin), _O_BINARY); // _setmode(_fileno(stdin), _O_BINARY); _setmode(fileno(stdin), _O_BINARY); // _setmode(_fileno(stdin), _O_BINARY);
#endif #endif
@ -1010,7 +1038,9 @@ int main(int argc, char **argv) {
gpx->option.raw = 1; // bytes - rs_ecc_codewords gpx->option.raw = 1; // bytes - rs_ecc_codewords
} }
else if (strcmp(*argv, "--ecc" ) == 0) { gpx->option.ecc = 1; } // RS-ECC else if (strcmp(*argv, "--ecc" ) == 0) { gpx->option.ecc = 1; } // RS-ECC
else if (strcmp(*argv, "--vit" ) == 0) { gpx->option.vit = 1; } // viterbi else if (strcmp(*argv, "--ecc3") == 0) { gpx->option.ecc = 3; } // RS-ECC
else if (strcmp(*argv, "--vit" ) == 0) { gpx->option.vit = 1; } // viterbi-hard
else if (strcmp(*argv, "--vit2" ) == 0) { gpx->option.vit = 2; } // viterbi-soft
else if ( (strcmp(*argv, "--gpsweek") == 0) ) { else if ( (strcmp(*argv, "--gpsweek") == 0) ) {
++argv; ++argv;
if (*argv) { if (*argv) {
@ -1022,8 +1052,9 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) { else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) {
option_inv = 1; // nicht noetig option_inv = 1; // nicht noetig
} }
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) { else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
thres = atof(*argv); thres = atof(*argv);
@ -1053,6 +1084,14 @@ int main(int argc, char **argv) {
option_iq = 5; option_iq = 5;
} }
else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass
else if (strcmp(*argv, "--lpbw") == 0) { // IQ lowpass BW / kHz
double bw = 0.0;
++argv;
if (*argv) bw = atof(*argv);
else return -1;
if (bw > 4.6 && bw < 24.0) lpIQ_bw = bw*1e3;
option_lp = 1;
}
else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; } else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; }
else if (strcmp(*argv, "--min") == 0) { else if (strcmp(*argv, "--min") == 0) {
option_min = 1; option_min = 1;
@ -1094,71 +1133,113 @@ int main(int argc, char **argv) {
if (gpx->option.raw == 4) gpx->option.ecc = 1; if (gpx->option.raw == 4) gpx->option.ecc = 1;
// init gpx // init gpx
memcpy(gpx->blk_rawbits, blk_syncbits, sizeof(blk_syncbits));
memcpy(gpx->frame, frm_sync6, sizeof(frm_sync6)); memcpy(gpx->frame, frm_sync6, sizeof(frm_sync6));
gpx->frm_pos = 0; // ecc_blk <-> frm_blk gpx->frm_pos = 0; // ecc_blk <-> frm_blk
gpx->sf6 = 0; gpx->sf6 = 0;
gpx->sfX = 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->option.inv = option_inv; // irrelevant gpx->option.inv = option_inv; // irrelevant
gpx->week = gpsweek; gpx->week = gpsweek;
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch; #ifdef EXT_FSK
if (option_pcmraw == 0) { if (!option_softin) {
k = read_wav_header(&pcm, fp); option_softin = 1;
if ( k < 0 ) { fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp); fclose(fp);
fprintf(stderr, "error: wav header\n"); fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq == 0 && gpx->option.vit == 2) { // FM-demodulated data not recommended
gpx->option.vit = 1; // for soft-decoding
fprintf(stderr, "info: soft decoding only for IQ\n");
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE6;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0 // BT(lmsX) < BT(lms6) ? -> init_buffers()
dsp.h = 0.9; // 0.95 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = lpIQ_bw; // 16e3; // IF lowpass bandwidth // soft decoding?
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp); // baud difference not significant
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1; return -1;
} }
} }
else {
symlen = 1; // init circular header bit buffer
hdb.hdr = rawheader;
// init dsp hdb.len = strlen(rawheader);
// //hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
dsp.fp = fp; hdb.bufpos = -1;
dsp.sr = pcm.sr; hdb.buf = NULL;
dsp.bps = pcm.bps; /*
dsp.nch = pcm.nch; calloc(hdb.len, sizeof(char));
dsp.ch = pcm.sel_ch; if (hdb.buf == NULL) {
dsp.br = (float)BAUD_RATE6; fprintf(stderr, "error: malloc\n");
dsp.sps = (float)dsp.sr/dsp.br; return -1;
dsp.symlen = symlen; }
dsp.symhd = 1; */
dsp._spb = dsp.sps*symlen; hdb.ths = 0.7; // caution/test false positive
dsp.hdr = rawheader; hdb.sbuf = calloc(hdb.len, sizeof(float));
dsp.hdrlen = strlen(rawheader); if (hdb.sbuf == NULL) {
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0 // BT(lmsX) < BT(lms6) ? -> init_buffers() fprintf(stderr, "error: malloc\n");
dsp.h = 0.9; // 0.95 modulation index return -1;
dsp.opt_iq = option_iq; }
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
} }
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp); // baud difference not significant
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
if (gpx->option.vit) { if (gpx->option.vit) {
k = vit_initCodes(gpx); k = vit_initCodes(gpx);
@ -1194,9 +1275,13 @@ int main(int argc, char **argv) {
while ( 1 ) while ( 1 )
{ {
// FM-audio: if (option_softin) {
header_found = find_header(&dsp, thres, 6, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0 header_found = find_softbinhead(fp, &hdb, &_mv);
_mv = dsp.mv; }
else { // FM-audio:
header_found = find_header(&dsp, thres, 10, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break; if (header_found == EOF) break;
@ -1220,19 +1305,49 @@ int main(int argc, char **argv) {
while ( pos < rawbitblock_len ) { while ( pos < rawbitblock_len ) {
bitQ = read_slbit(&dsp, &rbit, 0, bitofs, bitpos, -1, 0); // symlen=1 if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) {
rhsbit.sb = s;
rhsbit.hb = (s>=0.0);
}
}
else {
//bitQ = read_softbit(&dsp, &rhsbit, 0, bitofs, bitpos, -1, 0); // symlen=1
bitQ = read_softbit2p(&dsp, &rhsbit, 0, bitofs, bitpos, -1, 0, &rhsbit1); // symlen=1
if (gpx->option.ecc == 3) {
if (rhsbit.sb*rhsbit1.sb < 0) {
rhsbit.sb += rhsbit1.sb;
rhsbit.hb = (rhsbit.sb>=0.0);
}
}
}
if (bitQ == EOF) { break; } if (bitQ == EOF) { break; }
bit = rbit ^ (bc%2); // (c0,inv(c1)) // optional:
gpx->blk_rawbits[pos] = 0x30 + bit; // normalize soft bit s_j by
// rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1]
// or at the end by max|s_j| over all bits in rawframe
// (only if |sj| >> 1 by factor 100)
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++; bc++;
pos++; pos++;
bitpos += 1; bitpos += 1;
} }
gpx->blk_rawbits[pos] = '\0'; gpx->blk_rawbits[pos].hb = '\0';
time_elapsed_sec = dsp.sample_in / (double)dsp.sr; time_elapsed_sec = dsp.sample_in / (double)dsp.sr;
proc_frame(gpx, pos); proc_frame(gpx, pos);
@ -1276,7 +1391,11 @@ int main(int argc, char **argv) {
} }
free_buffers(&dsp); if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
if (gpx->vit) { free(gpx->vit); gpx->vit = NULL; } if (gpx->vit) { free(gpx->vit); gpx->vit = NULL; }
fclose(fp); fclose(fp);

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1102,6 +1102,8 @@ static int print_frame(gpx_t *gpx, int pos) {
return (gpx->frame_bytes[0]<<8)|gpx->frame_bytes[1]; return (gpx->frame_bytes[0]<<8)|gpx->frame_bytes[1];
} }
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv) { int main(int argc, char **argv) {
@ -1115,6 +1117,8 @@ int main(int argc, char **argv) {
int option_iq = 0; int option_iq = 0;
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_chk = 0;
int option_softin = 0;
int option_pcmraw = 0; int option_pcmraw = 0;
int wavloaded = 0; int wavloaded = 0;
int sel_wavch = 0; // audio channel: left int sel_wavch = 0; // audio channel: left
@ -1129,6 +1133,7 @@ int main(int argc, char **argv) {
int bitpos = 0; int bitpos = 0;
int bitQ; int bitQ;
int pos; int pos;
hsbit_t hsbit, hsbit1;
//int headerlen = 0; //int headerlen = 0;
@ -1144,6 +1149,8 @@ int main(int argc, char **argv) {
pcm_t pcm = {0}; pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp)); dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0}; gpx_t gpx = {0};
@ -1185,8 +1192,10 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "--spike") == 0) ) { else if ( (strcmp(*argv, "--spike") == 0) ) {
spike = 1; spike = 1;
} }
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--chk3") == 0) { option_chk = 3; }
else if ( (strcmp(*argv, "--ths") == 0) ) { else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
thres = atof(*argv); thres = atof(*argv);
@ -1250,6 +1259,7 @@ int main(int argc, char **argv) {
if (!wavloaded) fp = stdin; if (!wavloaded) fp = stdin;
// init gpx
gpx.option.inv = option_inv; // irrelevant gpx.option.inv = option_inv; // irrelevant
gpx.option.vbs = option_verbose; gpx.option.vbs = option_verbose;
gpx.option.raw = option_raw; gpx.option.raw = option_raw;
@ -1257,71 +1267,105 @@ int main(int argc, char **argv) {
gpx.option.col = option_color; gpx.option.col = option_color;
// init gpx #ifdef EXT_FSK
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) { option_softin = 1;
fclose(fp); fprintf(stderr, "reading float32 soft symbols\n");
fprintf(stderr, "error: raw data not IQ\n");
return -1;
} }
if (option_iq) sel_wavch = 0; #endif
pcm.sel_ch = sel_wavch; if (!option_softin) {
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp); if (option_iq == 0 && option_pcmraw) {
if ( k < 0 ) {
fclose(fp); fclose(fp);
fprintf(stderr, "error: wav header\n"); fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
// m10: BT>1?, h=1.2 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1; // M10!header
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0
dsp.h = 0.9; // 1.2 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
dsp.lpFM_bw = 10e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rawheader;
hdb.len = strlen(rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
hdb.ths = 0.8; // caution 0.7: false positive / offset
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1; return -1;
} }
} }
// m10: BT>1?, h=1.2 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1; // M10!header
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0
dsp.h = 0.9; // 1.2 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
dsp.lpFM_bw = 10e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
while ( 1 ) while ( 1 )
{ {
// FM-audio: if (option_softin) {
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0 header_found = find_softbinhead(fp, &hdb, &_mv);
_mv = dsp.mv; }
else { // FM-audio:
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break; if (header_found == EOF) break;
@ -1339,15 +1383,31 @@ int main(int argc, char **argv) {
while ( pos < BITFRAME_LEN+BITAUX_LEN ) { while ( pos < BITFRAME_LEN+BITAUX_LEN ) {
if (option_iq >= 2) { if (option_softin) {
float bl = -1; float s1 = 0.0;
if (option_iq > 2) bl = 4.0; float s2 = 0.0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0); float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
bit = (s>=0.0); // no soft decoding
}
}
} }
else { else {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, spike); // symlen=2 float bl = -1;
if (option_iq >= 2) spike = 0;
if (option_iq > 2) bl = 4.0;
//bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, spike); // symlen=2
bitQ = read_softbit2p(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike, &hsbit1); // symlen=1
bit = hsbit.hb;
if (option_chk == 3 && option_iq) {
//if (hsbit.sb*hsbit1.sb < 0)
bit = (hsbit.sb+0.25*hsbit1.sb)>=0;
}
} }
if ( bitQ == EOF ) { break; } if ( bitQ == EOF ) { break; }
gpx.frame_bits[pos] = 0x31 ^ (bit0 ^ bit); gpx.frame_bits[pos] = 0x31 ^ (bit0 ^ bit);
@ -1364,7 +1424,13 @@ int main(int argc, char **argv) {
// bis Ende der Sekunde vorspulen; allerdings Doppel-Frame alle 10 sek // bis Ende der Sekunde vorspulen; allerdings Doppel-Frame alle 10 sek
if (gpx.option.vbs < 3) { // && (regulare frame) // print_frame-return? if (gpx.option.vbs < 3) { // && (regulare frame) // print_frame-return?
while ( bitpos < 5*BITFRAME_LEN ) { while ( bitpos < 5*BITFRAME_LEN ) {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, spike); // symlen=2 if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
}
else {
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=2
}
if ( bitQ == EOF) break; if ( bitQ == EOF) break;
bitpos++; bitpos++;
} }
@ -1374,7 +1440,11 @@ int main(int argc, char **argv) {
} }
} }
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
fclose(fp); fclose(fp);

Wyświetl plik

@ -212,6 +212,7 @@ int main(int argc, char **argv) {
int option_iq = 0; int option_iq = 0;
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0; int option_pcmraw = 0;
int sel_wavch = 0; int sel_wavch = 0;
int wavloaded = 0; int wavloaded = 0;
@ -267,6 +268,8 @@ int main(int argc, char **argv) {
pcm_t pcm = {0}; pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp)); dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0}; gpx_t gpx = {0};
@ -308,8 +311,9 @@ int main(int argc, char **argv) {
} }
else return -1; else return -1;
} }
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) { else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
thres = atof(*argv); thres = atof(*argv);
@ -378,63 +382,98 @@ int main(int argc, char **argv) {
if (!wavloaded) fp = stdin; if (!wavloaded) fp = stdin;
if (option_iq == 0 && option_pcmraw) { #ifdef EXT_FSK
fclose(fp); if (!option_softin) {
fprintf(stderr, "error: raw data not IQ\n"); option_softin = 1;
return -1; fprintf(stderr, "reading float32 soft symbols\n");
} }
if (option_iq) sel_wavch = 0; #endif
pcm.sel_ch = sel_wavch; if (!option_softin) {
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp); if (option_iq == 0 && option_pcmraw) {
if ( k < 0 ) {
fclose(fp); fclose(fp);
fprintf(stderr, "error: wav header\n"); fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0
dsp.h = 2.4; // 2.8
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 16e3; // IF lowpass bandwidth
dsp.lpFM_bw = 4e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
if (baudrate > 0) {
dsp.br = (float)baudrate;
dsp.sps = (float)dsp.sr/dsp.br;
fprintf(stderr, "sps corr: %.4f\n", dsp.sps);
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rawheader;
hdb.len = strlen(rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
hdb.ths = 0.8; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1; return -1;
} }
} }
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0
dsp.h = 2.4; // 2.8
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 16e3; // IF lowpass bandwidth
dsp.lpFM_bw = 4e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
if (baudrate > 0) {
dsp.br = (float)baudrate;
dsp.sps = (float)dsp.sr/dsp.br;
fprintf(stderr, "sps corr: %.4f\n", dsp.sps);
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
if (option_ecc) { if (option_ecc) {
rs_init_BCH64(&gpx.RS); rs_init_BCH64(&gpx.RS);
@ -442,14 +481,16 @@ int main(int argc, char **argv) {
gpx.sn = -1; gpx.sn = -1;
bitofs += shift;
while ( 1 ) while ( 1 )
{ {
// FM-audio: if (option_softin) {
header_found = find_header(&dsp, thres, 1, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0 header_found = find_softbinhead(fp, &hdb, &_mv);
_mv = dsp.mv; }
else { // FM-audio:
header_found = find_header(&dsp, thres, 1, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break; if (header_found == EOF) break;
@ -462,9 +503,14 @@ int main(int argc, char **argv) {
while (bitpos < RAWBITFRAME_LEN/2-RAWHEADLEN) { // 2*600-48 while (bitpos < RAWBITFRAME_LEN/2-RAWHEADLEN) { // 2*600-48
if (option_softin) {
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=1 float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) bit = (s>=0.0); // no soft decoding
}
else {
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=1
}
if (bitQ == EOF) { break; } if (bitQ == EOF) { break; }
gpx.frame_rawbits[bitpos] = 0x30 + bit; gpx.frame_rawbits[bitpos] = 0x30 + bit;
@ -768,7 +814,11 @@ int main(int argc, char **argv) {
printf("\n"); printf("\n");
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
fclose(fp); fclose(fp);

Wyświetl plik

@ -87,6 +87,7 @@ typedef struct {
float T; float RH; float T; float RH;
ui32_t crc; ui32_t crc;
ui8_t frame[FRAME_LEN]; ui8_t frame[FRAME_LEN];
ui8_t dfrm[FRAME_LEN];
ui8_t calibytes[51*16]; ui8_t calibytes[51*16];
ui8_t calfrchk[51]; ui8_t calfrchk[51];
float ptu_Rf1; // ref-resistor f1 (750 Ohm) float ptu_Rf1; // ref-resistor f1 (750 Ohm)
@ -1006,7 +1007,27 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2); errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
if (gpx->option.ecc == 2 && (errors1 < 0 || errors2 < 0)) if (gpx->option.ecc >= 2) // option_softin: mark weak dfrm[]
{ // 2nd pass
if (errors1 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
if (errors1 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
}
}
if (errors2 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
if (errors2 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
}
}
}
if (gpx->option.ecc >= 2 && (errors1 < 0 || errors2 < 0))
{ // 2nd pass { // 2nd pass
gpx->frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; gpx->frame[pos_FRAME+1] = pck_FRAME&0xFF; 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_PTU] = (pck_PTU >>8)&0xFF; gpx->frame[pos_PTU +1] = pck_PTU &0xFF;
@ -1032,6 +1053,14 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2); errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
} }
if (gpx->option.ecc >= 3)
{ // 3nd pass: erasures ...
if (errors1 < 0) {
}
if (errors2 < 0) {
}
}
// Wenn Fehler im 00-padding korrigiert wurden, // Wenn Fehler im 00-padding korrigiert wurden,
// war entweder der frame zu kurz, oder // war entweder der frame zu kurz, oder
@ -1448,7 +1477,7 @@ static void print_frame(gpx_t *gpx, int len) {
} }
if (gpx->option.ecc) { if (gpx->option.ecc) {
if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]"); if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
if (gpx->option.ecc /*== 2*/) { if (gpx->option.ecc /*>= 2*/) {
if (ec > 0) fprintf(stdout, " (%d)", ec); if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) { if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)"); if (ec == -1) fprintf(stdout, " (-+)");
@ -1467,69 +1496,6 @@ static void print_frame(gpx_t *gpx, int len) {
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
// header bit buffer
typedef struct {
char *hdr;
char *buf;
char len;
int bufpos;
float ths;
} hdb_t;
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
static int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
//int option_inv = 0; // invertiert Signal //int option_inv = 0; // invertiert Signal
@ -1538,6 +1504,7 @@ int main(int argc, char *argv[]) {
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_bin = 0; int option_bin = 0;
int option_softin = 0;
int option_pcmraw = 0; int option_pcmraw = 0;
int wavloaded = 0; int wavloaded = 0;
int sel_wavch = 0; // audio channel: left int sel_wavch = 0; // audio channel: left
@ -1554,12 +1521,16 @@ int main(int argc, char *argv[]) {
byte_count = FRAMESTART; byte_count = FRAMESTART;
int bit, byte; int bit, byte;
int bitQ; int bitQ;
int difbyte = 0;
hsbit_t hsbit, hsbit1;
int header_found = 0; int header_found = 0;
float thres = 0.7; // dsp.mv threshold float thres = 0.7; // dsp.mv threshold
float _mv = 0.0; float _mv = 0.0;
float lpIQ_bw = 7.4e3;
int symlen = 1; int symlen = 1;
int bitofs = 2; // +0 .. +3 int bitofs = 2; // +0 .. +3
int shift = 0; int shift = 0;
@ -1608,12 +1579,14 @@ int main(int argc, char *argv[]) {
} }
else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; } else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; }
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; } else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
else if (strcmp(*argv, "--ecc3") == 0) { gpx.option.ecc = 3; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; } else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; } else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; }
else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; } else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--auto") == 0) { gpx.option.aut = 1; } else if (strcmp(*argv, "--auto") == 0) { gpx.option.aut = 1; }
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) { else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
@ -1644,6 +1617,14 @@ int main(int argc, char *argv[]) {
option_iq = 5; option_iq = 5;
} }
else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass
else if (strcmp(*argv, "--lpbw") == 0) { // IQ lowpass BW / kHz
double bw = 0.0;
++argv;
if (*argv) bw = atof(*argv);
else return -1;
if (bw > 4.6 && bw < 24.0) lpIQ_bw = bw*1e3;
option_lp = 1;
}
else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; } else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; }
else if (strcmp(*argv, "--min") == 0) { else if (strcmp(*argv, "--min") == 0) {
option_min = 1; option_min = 1;
@ -1694,9 +1675,16 @@ int main(int argc, char *argv[]) {
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes
#ifdef EXT_FSK
if (!option_bin && !option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!rawhex) { if (!rawhex) {
if (!option_bin) { if (!option_bin && !option_softin) {
if (option_iq == 0 && option_pcmraw) { if (option_iq == 0 && option_pcmraw) {
fclose(fp); fclose(fp);
@ -1736,7 +1724,7 @@ int main(int argc, char *argv[]) {
dsp.h = 0.6; //0.7; // 0.7..0.8? modulation index abzgl. BT dsp.h = 0.6; //0.7; // 0.7..0.8? modulation index abzgl. BT
dsp.opt_iq = option_iq; dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp; dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth dsp.lpIQ_bw = lpIQ_bw; // 7.4e3 (6e3..8e3) // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc; dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min; dsp.opt_IFmin = option_min;
@ -1744,37 +1732,48 @@ int main(int argc, char *argv[]) {
if ( dsp.sps < 8 ) { 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 -1;
}
//if (option_iq >= 2) bitofs += 1; // FM: +1 , IQ: +2
bitofs += shift;
} }
else { else {
if (option_bin && option_softin) option_bin = 0;
// init circular header bit buffer // init circular header bit buffer
hdb.hdr = rs41_header; hdb.hdr = rs41_header;
hdb.len = strlen(rs41_header); hdb.len = strlen(rs41_header);
hdb.ths = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1; hdb.bufpos = -1;
hdb.buf = calloc(hdb.len, sizeof(char)); hdb.buf = calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) { if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n"); fprintf(stderr, "error: malloc\n");
return -1; return -1;
} }
hdb.ths = 0.7; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
} }
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
//if (option_iq >= 2) bitofs += 1; // FM: +1 , IQ: +2
bitofs += shift;
while ( 1 ) while ( 1 )
{ {
if (option_bin) { if (option_bin) {
header_found = find_binhead(fp, &hdb, &_mv); header_found = find_binhead(fp, &hdb, &_mv);
} }
else if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else { // FM-audio: else { // FM-audio:
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0 header_found = find_header(&dsp, thres, 4, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv; _mv = dsp.mv;
} }
if (header_found == EOF) break; if (header_found == EOF) break;
@ -1790,6 +1789,7 @@ int main(int argc, char *argv[]) {
byte_count = FRAMESTART; byte_count = FRAMESTART;
bitpos = 0; // byte_count*8-HEADLEN bitpos = 0; // byte_count*8-HEADLEN
b8pos = 0; b8pos = 0;
difbyte = 0;
while ( byte_count < FRAME_LEN ) while ( byte_count < FRAME_LEN )
{ {
@ -1797,14 +1797,21 @@ int main(int argc, char *argv[]) {
bitQ = fgetc(fp); bitQ = fgetc(fp);
if (bitQ != EOF) bit = bitQ & 0x1; if (bitQ != EOF) bit = bitQ & 0x1;
} }
else if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) bit = (s>=0.0); // no soft decoding
}
else { else {
if (option_iq >= 2) { float bl = -1;
float bl = -1; if (option_iq > 2) bl = 2.0;
if (option_iq > 2) bl = 1.0; //bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, 0); // symlen=1
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0); bitQ = read_softbit2p(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0, &hsbit1); // symlen=1
} bit = hsbit.hb;
else { if (gpx.option.ecc == 3) bit = (hsbit.sb+hsbit1.sb)>=0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, 0);
if (bitpos < FRAME_LEN*BITS && hsbit.sb*hsbit1.sb < 0) {
difbyte |= 1<<b8pos;
} }
} }
if ( bitQ == EOF ) break; // liest 2x EOF if ( bitQ == EOF ) break; // liest 2x EOF
@ -1818,6 +1825,8 @@ int main(int argc, char *argv[]) {
b8pos = 0; b8pos = 0;
byte = bits2byte(bitbuf); byte = bits2byte(bitbuf);
gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN]; gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN];
gpx.dfrm[byte_count] = difbyte;
difbyte = 0;
byte_count++; byte_count++;
} }
} }
@ -1828,7 +1837,7 @@ int main(int argc, char *argv[]) {
} }
} }
if (!option_bin) free_buffers(&dsp); if (!option_bin && !option_softin) free_buffers(&dsp);
else { else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; } if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
} }

Wyświetl plik

@ -1221,11 +1221,13 @@ static void print_frame(gpx_t *gpx, int len) {
if (ec < 0) fprintf(stdout, " (-)"); if (ec < 0) fprintf(stdout, " (-)");
} }
fprintf(stdout, "\n"); fprintf(stdout, "\n");
// fprintf(stdout, "\n"); // fprintf(stdout, "\n");
} }
else print_position(gpx, ec); else print_position(gpx, ec);
} }
/* -------------------------------------------------------------------------- */
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
@ -1237,6 +1239,7 @@ int main(int argc, char *argv[]) {
int option_iq = 0; int option_iq = 0;
int option_lp = 0; int option_lp = 0;
int option_dc = 0; int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0; int option_pcmraw = 0;
int sel_wavch = 0; // audio channel: left int sel_wavch = 0; // audio channel: left
int spike = 0; int spike = 0;
@ -1265,6 +1268,8 @@ int main(int argc, char *argv[]) {
pcm_t pcm = {0}; pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp)); dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0}; gpx_t gpx = {0};
gpx.gps.prn32toggle = 0x1; gpx.gps.prn32toggle = 0x1;
@ -1375,18 +1380,19 @@ int main(int argc, char *argv[]) {
} }
else return -1; else return -1;
} }
else if (strcmp(*argv, "-g1") == 0) { gpx.gps.opt_vergps = 1; } // verbose1 GPS else if (strcmp(*argv, "-g1") == 0) { gpx.gps.opt_vergps = 1; } // verbose1 GPS
else if (strcmp(*argv, "-g2") == 0) { gpx.gps.opt_vergps = 2; } // verbose2 GPS (bancroft) else if (strcmp(*argv, "-g2") == 0) { gpx.gps.opt_vergps = 2; } // verbose2 GPS (bancroft)
else if (strcmp(*argv, "-gg") == 0) { gpx.gps.opt_vergps = 8; } // vverbose GPS else if (strcmp(*argv, "-gg") == 0) { gpx.gps.opt_vergps = 8; } // vverbose GPS
else if (strcmp(*argv, "--json") == 0) { else if (strcmp(*argv, "--json") == 0) {
gpx.option.jsn = 1; gpx.option.jsn = 1;
gpx.option.ecc = 2; gpx.option.ecc = 2;
gpx.option.crc = 1; gpx.option.crc = 1;
gpx.gps.opt_vel = 4; gpx.gps.opt_vel = 4;
} }
else if (strcmp(*argv, "--spike") == 0) { spike = 1; } else if (strcmp(*argv, "--spike") == 0) { spike = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--ths") == 0) { else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv; ++argv;
if (*argv) { if (*argv) {
thres = atof(*argv); thres = atof(*argv);
@ -1480,70 +1486,112 @@ int main(int argc, char *argv[]) {
// init gpx // init gpx
memcpy(gpx.frame, rs92_header_bytes, sizeof(rs92_header_bytes)); // 6 header bytes memcpy(gpx.frame, rs92_header_bytes, sizeof(rs92_header_bytes)); // 6 header bytes
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch; #ifdef EXT_FSK
if (option_pcmraw == 0) { if (!option_softin) {
k = read_wav_header(&pcm, fp); option_softin = 1;
if ( k < 0 ) { fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp); fclose(fp);
fprintf(stderr, "error: wav header\n"); fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
// rs92-sgp: BT=0.5, h=1.0 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = symlen;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rs92_rawheader;
dsp.hdrlen = strlen(rs92_rawheader);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 0.8; // 1.0 modulation index abzgl. BT
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if (gpx.option.ngp) { // L-band rs92-ngp
dsp.h = 3.8; // RS92-NGP: 1680/400=4.2, 4.2*0.9=3.8=4.75*0.8
dsp.lpIQ_bw = 32e3; // IF lowpass bandwidth // 32e3=4.2*7.6e3
}
if ( dsp.sps < 8 ) {
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 -1;
};
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rs92_rawheader;
hdb.len = strlen(rs92_rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
// caution ths=0.7: -3 byte offset, false positive
// 2A 2A 2A 2A 2A 10|65 10 ..
// header sync could be extended into the frame
hdb.ths = 0.8;
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1; return -1;
} }
} }
// rs92-sgp: BT=0.5, h=1.0 ?
symlen = 2;
// init dsp while ( 1 )
// {
dsp.fp = fp; if (option_softin) {
dsp.sr = pcm.sr; for (k = 0; k < hdb.len; k++) hdb.sbuf[k] = 0.0;
dsp.bps = pcm.bps; header_found = find_softbinhead(fp, &hdb, &_mv);
dsp.nch = pcm.nch; }
dsp.ch = pcm.sel_ch; else {
dsp.br = (float)BAUD_RATE; header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc);
dsp.sps = (float)dsp.sr/dsp.br; _mv = dsp.mv;
dsp.symlen = symlen; }
dsp.symhd = symlen;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rs92_rawheader;
dsp.hdrlen = strlen(rs92_rawheader);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 0.8; // 1.0 modulation index abzgl. BT
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if (gpx.option.ngp) { // L-band rs92-ngp
dsp.h = 3.8; // RS92-NGP: 1680/400=4.2, 4.2*0.9=3.8=4.75*0.8
dsp.lpIQ_bw = 32e3; // IF lowpass bandwidth // 32e3=4.2*7.6e3
}
if ( dsp.sps < 8 ) {
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 -1;
};
bitofs += shift;
while ( 1 ) {
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc);
_mv = dsp.mv;
if (header_found == EOF) break; if (header_found == EOF) break;
@ -1560,9 +1608,25 @@ int main(int argc, char *argv[]) {
b8pos = 0; b8pos = 0;
while ( byte_count < FRAME_LEN ) { while ( byte_count < FRAME_LEN ) {
float bl = -1;
if (option_iq > 2) bl = 4.0; if (option_softin) {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, spike); float s1 = 0.0;
float s2 = 0.0;
float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
bit = (s>=0.0); // no soft decoding
}
}
}
else {
float bl = -1;
if (option_iq > 2) bl = 4.0;
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, spike); // symlen=2
}
if ( bitQ == EOF) break; if ( bitQ == EOF) break;
if (gpx.option.inv) bit ^= 1; if (gpx.option.inv) bit ^= 1;
@ -1586,9 +1650,13 @@ int main(int argc, char *argv[]) {
} }
free_buffers(&dsp); if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
if (gpx.gps.ephs) free(gpx.gps.ephs); if (gpx.gps.ephs) free(gpx.gps.ephs);
fclose(fp); fclose(fp);
return 0; return 0;

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.