kopia lustrzana https://github.com/rs1729/RS
mod: --softin from test-branch
rodzic
2e770cee8b
commit
7b00d3a678
|
@ -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.)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
BIN
iq/iq_demod.pdf
BIN
iq/iq_demod.pdf
Plik binarny nie jest wyświetlany.
Ładowanie…
Reference in New Issue