mod: more modular/encapsulated decoders/components

pull/11/head
Zilog80 2019-03-16 10:15:11 +01:00
rodzic 529666f37f
commit 35136f908f
5 zmienionych plików z 1438 dodań i 169 usunięć

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,97 @@
/*
* BCH / Reed-Solomon
* encoder()
* decoder() (Euklid. Alg.)
*
*
* author: zilog80
*
*
*/
#ifdef INCLUDESTATIC
#define INCSTAT static
#else
typedef unsigned char ui8_t;
typedef unsigned int ui32_t;
#define INCSTAT
#endif
#define MAX_DEG 254 // max N-1
typedef struct {
ui32_t f;
ui32_t ord;
ui8_t alpha;
ui8_t exp_a[256];
ui8_t log_a[256];
} GF_t;
typedef struct {
ui8_t N;
ui8_t t;
ui8_t R; // RS: R=2t, BCH: R<=mt
ui8_t K; // K=N-R
ui8_t b;
ui8_t p; ui8_t ip; // p*ip = 1 mod N
ui8_t g[MAX_DEG+1]; // ohne g[] eventuell als init_return
GF_t GF;
} RS_t;
static GF_t GF256RS = { f : 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
ord : 256, // 2^8
alpha: 0x02, // generator: alpha = X
exp_a: {0},
log_a: {0} };
static GF_t GF256RSccsds = { f : 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
ord : 256, // 2^8
alpha: 0x02, // generator: alpha = X
exp_a: {0},
log_a: {0} };
static GF_t GF64BCH = { f : 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
ord : 64, // 2^6
alpha: 0x02, // generator: alpha = X
exp_a: {0},
log_a: {0} };
static GF_t GF16RS = { f : 0x13, // RS-GF(2^4): X^4 + X + 1 : 0x13
ord : 16, // 2^4
alpha: 0x02, // generator: alpha = X
exp_a: {0},
log_a: {0} };
static GF_t GF256AES = { f : 0x11B, // AES-GF(2^8): X^8 + X^4 + X^3 + X + 1 : 0x11B
ord : 256, // 2^8
alpha: 0x03, // generator: alpha = X+1
exp_a: {0},
log_a: {0} };
static RS_t RS256 = { 255, 12, 24, 231, 0, 1, 1, {0}, {0} };
static RS_t RS256ccsds = { 255, 16, 32, 223, 112, 11, 116, {0}, {0} };
static RS_t BCH64 = { 63, 2, 12, 51, 1, 1, 1, {0}, {0} };
// static RS_t RS16_0 = { 15, 3, 6, 9, 0, 1, 1, {0}, {0} };
static RS_t RS16ccsds = { 15, 2, 4, 11, 6, 1, 1, {0}, {0} };
#ifndef INCLUDESTATIC
int rs_init_RS255(RS_t *RS);
int rs_init_RS255ccsds(RS_t *RS);
int rs_init_RS15ccsds(RS_t *RS);
int rs_init_BCH64(RS_t *RS);
int rs_encode(RS_t *RS, ui8_t cw[]);
int rs_decode(RS_t *RS, ui8_t cw[], ui8_t *err_pos, ui8_t *err_val);
int rs_decode_ErrEra(RS_t *RS, ui8_t cw[], int nera, ui8_t era_pos[], ui8_t *err_pos, ui8_t *err_val);
int rs_decode_bch_gf2t2(RS_t *RS, ui8_t cw[], ui8_t *err_pos, ui8_t *err_val);
#endif

Wyświetl plik

@ -2,7 +2,7 @@
/*
* sync header: correlation/matched filter
* compile:
* gcc -c demod_iq.c
* gcc -c demod_mod.c
*
* author: zilog80
*/
@ -13,7 +13,7 @@
#include <stdlib.h>
#include <string.h>
#include "demod_iq.h"
#include "demod_mod.h"
/* ------------------------------------------------------------------------------------ */
@ -137,7 +137,7 @@ static int dft_window(dft_t *dft, int w) {
/* ------------------------------------------------------------------------------------ */
int getCorrDFT(dsp_t *dsp, ui32_t pos, float *maxv, ui32_t *maxvpos) {
static int getCorrDFT(dsp_t *dsp) {
int i;
int mp = -1;
float mx = 0.0;
@ -146,13 +146,14 @@ int getCorrDFT(dsp_t *dsp, ui32_t pos, float *maxv, ui32_t *maxvpos) {
float xnorm = 1;
ui32_t mpos = 0;
ui32_t pos = dsp->sample_out;
dsp->mv = 0.0;
dsp->dc = 0.0;
if (dsp->K + dsp->L > dsp->DFT.N) return -1;
if (dsp->sample_out < dsp->L) return -2;
if (pos == 0) pos = dsp->sample_out;
dsp->dc = get_bufmu(dsp, pos - dsp->sample_out); //oder unten: dft_dc = creal(X[0])/(K+L);
// wenn richtige Stelle (Varianz pruefen, kein M10-carrier?), dann von bufs[] subtrahieren
@ -196,8 +197,8 @@ int getCorrDFT(dsp_t *dsp, ui32_t pos, float *maxv, ui32_t *maxvpos) {
mx /= xnorm*(dsp->DFT).N;
*maxv = mx;
*maxvpos = mpos;
dsp->mv = mx;
dsp->mv_pos = mpos;
if (pos == dsp->sample_out) dsp->buffered = dsp->sample_out - mpos;
@ -431,7 +432,7 @@ static int read_bufbit(dsp_t *dsp, int symlen, char *bits, ui32_t mvp, int pos)
// symlen==2: manchester2 0->10,1->01->1: 2.bit
float rbitgrenze = pos*symlen*dsp->sps;
ui32_t rcount = rbitgrenze+0.99; // ceil
ui32_t rcount = ceil(rbitgrenze);//+0.99; // dfm?
double sum = 0.0;
@ -463,19 +464,20 @@ static int read_bufbit(dsp_t *dsp, int symlen, char *bits, ui32_t mvp, int pos)
return 0;
}
int headcmp(dsp_t *dsp, int symlen, ui32_t mvp, int inv, int option_dc) {
static int headcmp(dsp_t *dsp, int opt_dc) {
int errs = 0;
int pos;
int step = 1;
char sign = 0;
int len = dsp->hdrlen/symlen;
int len = dsp->hdrlen/dsp->symhd;
int inv = dsp->mv < 0;
if (symlen != 1) step = 2;
if (dsp->symhd != 1) step = 2;
if (inv) sign=1;
for (pos = 0; pos < len; pos++) { // L = dsp->hdrlen * dsp->sps + 0.5;
//read_bufbit(dsp, symlen, dsp->rawbits+pos*step, mvp+1-(int)(len*dsp->sps), pos);
read_bufbit(dsp, symlen, dsp->rawbits+pos*step, mvp+1-dsp->L, pos);
for (pos = 0; pos < len; pos++) { // L = dsp->hdrlen * dsp->sps + 0.5;
//read_bufbit(dsp, dsp->symhd, dsp->rawbits+pos*step, mvp+1-(int)(len*dsp->sps), pos);
read_bufbit(dsp, dsp->symhd, dsp->rawbits+pos*step, dsp->mv_pos+1-dsp->L, pos);
}
dsp->rawbits[pos] = '\0';
@ -484,7 +486,7 @@ int headcmp(dsp_t *dsp, int symlen, ui32_t mvp, int inv, int option_dc) {
len--;
}
if (option_dc && errs < 3) {
if (opt_dc && errs < 3) {
dsp->dc_ofs += dsp->dc;
}
@ -533,10 +535,10 @@ int get_fqofs_rs41(dsp_t *dsp, ui32_t mvp, float *freq, float *snr) {
/* -------------------------------------------------------------------------- */
int read_slbit(dsp_t *dsp, int symlen, int *bit, int inv, int ofs, int pos, float l, int spike) {
int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spike) {
// symlen==2: manchester2 10->0,01->1: 2.bit
float bitgrenze = pos*symlen*dsp->sps;
float bitgrenze = pos*dsp->symlen*dsp->sps;
ui32_t scount = ceil(bitgrenze);//+0.99; // dfm?
float sample;
@ -549,7 +551,7 @@ int read_slbit(dsp_t *dsp, int symlen, int *bit, int inv, int ofs, int pos, floa
if (pos == 0) scount = 0;
if (symlen == 2) {
if (dsp->symlen == 2) {
mid = bitgrenze + (dsp->sps-1)/2.0;
bitgrenze += dsp->sps;
do {
@ -557,11 +559,13 @@ int read_slbit(dsp_t *dsp, int symlen, int *bit, int inv, int ofs, int pos, floa
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
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]);
if (spike && fabs(sample - avg) > ths) sample = avg + scale*(sample - avg); // spikes
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
}
if ( l < 0 || (mid-l < scount && scount < mid+l)) sum -= sample;
if ( l < 0 || (mid-l < scount && scount < mid+l) ) sum -= sample;
scount++;
} while (scount < bitgrenze); // n < dsp->sps
@ -574,11 +578,13 @@ int read_slbit(dsp_t *dsp, int symlen, int *bit, int inv, int ofs, int pos, floa
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
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]);
if (spike && fabs(sample - avg) > ths) sample = avg + scale*(sample - avg); // spikes
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
}
if ( l < 0 || (mid-l < scount && scount < mid+l)) sum += sample;
if ( l < 0 || (mid-l < scount && scount < mid+l) ) sum += sample;
scount++;
} while (scount < bitgrenze); // n < dsp->sps
@ -771,3 +777,44 @@ 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) {
ui32_t k = 0;
ui32_t mvpos0 = 0;
int mp;
int header_found = 0;
int herrs;
while ( f32buf_sample(dsp, 0) != EOF ) {
k += 1;
if (k >= dsp->K-4) {
mvpos0 = dsp->mv_pos;
mp = getCorrDFT(dsp); // correlation score -> dsp->mv
//if (option_auto == 0 && dsp->mv < 0) mv = 0;
k = 0;
}
else {
dsp->mv = 0.0;
continue;
}
if (dsp->mv > thres || dsp->mv < -thres) {
if (dsp->mv_pos > mvpos0) {
header_found = 0;
herrs = headcmp(dsp, opt_dc);
if (herrs <= hdmax) header_found = 1; // max bitfehler in header
if (header_found) return 1;
}
}
}
return EOF;
}

Wyświetl plik

@ -35,6 +35,7 @@ typedef struct {
int ch; // select channel
//
int symlen;
int symhd;
float sps; // samples per symbol
float _spb; // samples per bit
float br; // baud rate
@ -50,6 +51,8 @@ typedef struct {
float *bufs;
float dc_ofs;
float dc;
float mv;
ui32_t mv_pos;
//
int N_norm;
int Nvar;
@ -100,10 +103,8 @@ typedef struct {
float read_wav_header(pcm_t *, FILE *);
int f32buf_sample(dsp_t *, int);
int read_slbit(dsp_t *, int, int*, int, int, int, float, int);
int read_slbit(dsp_t *, int*, int, int, int, float, int);
int getCorrDFT(dsp_t *, ui32_t, float *, ui32_t *);
int headcmp(dsp_t *, int, ui32_t, int, int);
int get_fqofs_rs41(dsp_t *, ui32_t, float *, float *);
float get_bufvar(dsp_t *, int);
float get_bufmu(dsp_t *, int);
@ -113,3 +114,5 @@ int free_buffers(dsp_t *);
ui32_t get_sample(dsp_t *);
int find_header(dsp_t *, float, int, int, int);

Wyświetl plik

@ -2,10 +2,15 @@
/*
* rs41
* sync header: correlation/matched filter
* files: rs41dm_iq.c bch_ecc.c demod_iq.c demod_iq.h
* compile:
* gcc -c demod_iq.c
* gcc rs41dm_iq.c demod_iq.o -lm -o rs41dm_iq
* files: rs41mod.c bch_ecc_mod.c demod_mod.c demod_mod.h
* compile, either (a) or (b):
* (a)
* gcc -c demod_mod.c
* gcc -DINCLUDESTATIC rs41mod.c demod_mod.o -lm -o rs41mod
* (b)
* gcc -c demod_mod.c
* gcc -c bch_ecc_mod.c
* gcc rs41mod.c demod_mod.o bch_ecc_mod.o -lm -o rs41mod
*
* author: zilog80
*/
@ -20,10 +25,20 @@
#include <io.h>
#endif
//typedef unsigned char ui8_t;
//typedef unsigned short ui16_t;
//typedef unsigned int ui32_t;
//typedef short i16_t;
//typedef int i32_t;
#include "demod_iq.h"
#include "demod_mod.h"
#include "bch_ecc.c" // RS/ecc/
//#define INCLUDESTATIC 1
#ifdef INCLUDESTATIC
#include "bch_ecc_mod.c"
#else
#include "bch_ecc_mod.h"
#endif
typedef struct {
@ -33,6 +48,8 @@ typedef struct {
i8_t ecc; // Reed-Solomon ECC
i8_t sat; // GPS sat data
i8_t ptu; // PTU: temperature
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
} option_t;
@ -79,6 +96,7 @@ typedef struct {
float ptu_co2[3]; // { -243.911 , 0.187654 , 8.2e-06 }
float ptu_calT2[3]; // calibration T2-Hum
ui16_t conf_fw; // firmware
ui8_t conf_cd; // kill countdown (sec) (kt or bt)
ui16_t conf_kt; // kill timer (sec)
ui16_t conf_bt; // burst timer (sec)
ui8_t conf_bk; // burst kill
@ -87,6 +105,7 @@ typedef struct {
int aux;
char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ...
option_t option;
RS_t RS;
} gpx_t;
@ -94,10 +113,10 @@ typedef struct {
#define HEADLEN 64
#define FRAMESTART ((HEADLEN)/BITS)
/* 10 B6 CA 11 22 96 12 F8 */
static char header[] = "0000100001101101010100111000100001000100011010010100100000011111";
/* 10 B6 CA 11 22 96 12 F8 */
static char rs41_header[] = "0000100001101101010100111000100001000100011010010100100000011111";
static ui8_t header_bytes[8] = { 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60};
static ui8_t rs41_header_bytes[8] = { 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60};
#define MASK_LEN 64
static ui8_t mask[MASK_LEN] = { 0x96, 0x83, 0x3E, 0x51, 0xB1, 0x49, 0x08, 0x98,
@ -425,6 +444,7 @@ static int get_SondeID(gpx_t *gpx, int crc) {
gpx->id[8] = '\0';
// conf data
gpx->conf_fw = 0;
gpx->conf_cd = -1;
gpx->conf_kt = -1;
gpx->conf_bt = 0;
gpx->conf_bk = 0;
@ -845,21 +865,6 @@ static int get_Calconf(gpx_t *gpx, int out) {
if (err == 0)
{
if (calfr == 0x01) {
fw = gpx->frame[pos_CalData+6] | (gpx->frame[pos_CalData+7]<<8);
if (out && gpx->option.vbs) fprintf(stdout, ": fw 0x%04x ", fw);
gpx->conf_fw = fw;
}
if (calfr == 0x02) {
ui8_t bk = gpx->frame[pos_Calburst]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[0x5A] + (gpx->frame[0x5B] << 8); // killtimer (short?)
if (out && gpx->option.vbs) fprintf(stdout, ": BK %02X ", bk);
if (out && gpx->option.vbs && kt != 0xFFFF ) fprintf(stdout, ": kt %.1fmin ", kt/60.0);
gpx->conf_bk = bk;
gpx->conf_kt = kt;
}
if (calfr == 0x00) {
byte = gpx->frame[pos_Calfreq] & 0xC0; // erstmal nur oberste beiden bits
f0 = (byte * 10) / 64; // 0x80 -> 1/2, 0x40 -> 1/4 ; dann mal 40
@ -870,13 +875,34 @@ static int get_Calconf(gpx_t *gpx, int out) {
gpx->freq = freq;
}
if (calfr == 0x31) {
ui16_t bt = gpx->frame[0x59] + (gpx->frame[0x5A] << 8); // burst timer (short?)
if (calfr == 0x01) {
fw = gpx->frame[pos_CalData+6] | (gpx->frame[pos_CalData+7]<<8);
if (out && gpx->option.vbs) fprintf(stdout, ": fw 0x%04x ", fw);
gpx->conf_fw = fw;
}
if (calfr == 0x02) { // 0x5E, 0x5A..0x5B
ui8_t bk = gpx->frame[pos_Calburst]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant
ui16_t kt = gpx->frame[pos_CalData+8] + (gpx->frame[pos_CalData+9] << 8); // killtimer (short?)
if (out && gpx->option.vbs) fprintf(stdout, ": BK %02X ", bk);
if (out && gpx->option.vbs && kt != 0xFFFF ) fprintf(stdout, ": kt %.1fmin ", kt/60.0);
gpx->conf_bk = bk;
gpx->conf_kt = kt;
}
if (calfr == 0x31) { // 0x59..0x5A
ui16_t bt = gpx->frame[pos_CalData+7] + (gpx->frame[pos_CalData+8] << 8); // burst timer (short?)
// fw >= 0x4ef5: default=[88 77]=0x7788sec=510min
if (out && gpx->option.vbs && bt != 0x0000 && gpx->conf_bk) fprintf(stdout, ": bt %.1fmin ", bt/60.0);
gpx->conf_bt = bt;
}
if (calfr == 0x32) {
ui16_t cd = gpx->frame[pos_CalData+1] + (gpx->frame[pos_CalData+2] << 8); // countdown (bt or kt) (short?)
if (out && gpx->option.vbs && cd != 0xFFFF) fprintf(stdout, ": cd %.1fmin ", cd/60.0);
gpx->conf_cd = cd;
}
if (calfr == 0x21) { // ... eventuell noch 2 bytes in 0x22
for (i = 0; i < 9; i++) sondetyp[i] = 0;
for (i = 0; i < 8; i++) {
@ -923,8 +949,8 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
errors1 = rs_decode(cw1, err_pos1, err_val1);
errors2 = rs_decode(cw2, err_pos2, err_val2);
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
if (gpx->option.ecc == 2 && (errors1 < 0 || errors2 < 0))
@ -949,8 +975,8 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
}
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
errors1 = rs_decode(cw1, err_pos1, err_val1);
errors2 = rs_decode(cw2, err_pos2, err_val2);
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
}
@ -1013,6 +1039,8 @@ static int print_position(gpx_t *gpx, int ec) {
gpx->out = 1; // cf. gpx->crc
if (!err && gpx->option.aut && gpx->option.vbs == 3) fprintf(stdout, "<%c> ", gpx->option.inv?'-':'+');
if (!err) {
fprintf(stdout, "[%5d] ", gpx->frnr);
fprintf(stdout, "(%s) ", gpx->id);
@ -1120,6 +1148,7 @@ static void print_frame(gpx_t *gpx, int len) {
if (ft >= 0) len = NDATA_LEN; // ft >= 0: NDATA_LEN (default)
else len = FRAME_LEN; // ft < 0: FRAME_LEN (aux)
if (gpx->option.ecc) {
ec = rs41_ecc(gpx, len);
}
@ -1150,43 +1179,110 @@ 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 option_inv = 0; // invertiert Signal
//int option_inv = 0; // invertiert Signal
int option_iq = 0;
int option_ofs = 0;
int option_bin = 0;
int wavloaded = 0;
int sel_wavch = 0; // audio channel: left
int rawhex = 0, xorhex = 0;
FILE *fp;
char *fpname = NULL;
int k;
char bitbuf[8];
int bit_count = 0,
bitpos = 0,
byte_count = FRAMESTART,
header_found = 0;
int bitpos = 0,
b8pos = 0,
byte_count = FRAMESTART;
int bit, byte;
int herrs;
int bitQ;
int k, K;
float mv;
ui32_t mv_pos, mv0_pos;
int mp = 0;
int header_found = 0;
float thres = 0.7;
float thres = 0.7; // dsp.mv threshold
float _mv = 0.0;
int symlen = 1;
int bitofs = 2;
int bitofs = 2; // +0 .. +3
int shift = 0;
pcm_t pcm = {0};
dsp_t dsp = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
gpx_t gpx = {0};
hdb_t hdb = {0};
#ifdef CYGWIN
_setmode(fileno(stdin), _O_BINARY); // _fileno(stdin)
@ -1194,10 +1290,6 @@ int main(int argc, char *argv[]) {
setbuf(stdout, NULL);
// init gpx
memcpy(gpx.frame, header_bytes, sizeof(header_bytes)); // 8 header bytes
fpname = argv[0];
++argv;
while ((*argv) && (!wavloaded)) {
@ -1224,7 +1316,7 @@ int main(int argc, char *argv[]) {
gpx.option.raw = 1;
}
else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) {
option_inv = 1;
gpx.option.inv = 1;
}
else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; }
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
@ -1236,6 +1328,8 @@ int main(int argc, char *argv[]) {
gpx.option.crc = 1;
}
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, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
@ -1271,127 +1365,142 @@ int main(int argc, char *argv[]) {
if (!wavloaded) fp = stdin;
if (gpx.option.ecc < 2) gpx.option.ecc = 1;
if (gpx.option.ecc < 2) gpx.option.ecc = 1; // turn off for ber-measurement
if (gpx.option.ecc) {
rs_init_RS255(); // ... rs_init_RS255(&RS);
rs_init_RS255(&gpx.RS); // RS, GF
}
// init gpx
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes
if (!rawhex) {
if (option_iq) sel_wavch = 0;
if (!option_bin) {
pcm.sel_ch = sel_wavch;
k = read_wav_header(&pcm, fp);
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
// rs41: BT=0.5, h=0.8,1.0 ?
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 = symlen;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rs41_header;
dsp.hdrlen = strlen(rs41_header);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 0.8; //0.7; // 0.7..0.8? modulation index abzgl. BT
dsp.opt_iq = option_iq;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
}
else {
// init circular header bit buffer
hdb.hdr = rs41_header;
hdb.len = strlen(rs41_header);
hdb.ths = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
// rs41: BT=0.5, h=0.8,1.0 ?
symlen = 1;
// init dsp
//
//memset(&dsp, 0, sizeof(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._spb = dsp.sps*symlen;
dsp.hdr = header;
dsp.hdrlen = strlen(header);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 1.0; // 0.8..0.9? modulation index
dsp.opt_iq = option_iq;
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;
};
//if (option_iq >= 2) bitofs += 1;
bitofs += shift; // +0 .. +3 // FM: +1 , IQ: +2
//if (option_iq >= 2) bitofs += 1; // FM: +1 , IQ: +2
bitofs += shift;
k = 0;
mv = 0.0;
mv_pos = 0;
while ( f32buf_sample(&dsp, option_inv) != EOF ) {
k += 1;
if (k >= dsp.K-4) {
mv0_pos = mv_pos;
mp = getCorrDFT(&dsp, 0, &mv, &mv_pos);
k = 0;
while ( 1 )
{
if (option_bin) {
header_found = find_binhead(fp, &hdb, &_mv);
}
else {
mv = 0.0;
continue;
header_found = find_header(&dsp, thres, 3, bitofs, 0);
_mv = dsp.mv;
}
if (header_found == EOF) break;
// mv == correlation score
if (_mv *(0.5-gpx.option.inv) < 0) {
if (gpx.option.aut == 0) header_found = 0;
else gpx.option.inv ^= 0x1;
}
if (mv > thres && mp > 0) {
if (mv_pos > mv0_pos) {
if (header_found)
{
byte_count = FRAMESTART;
bitpos = 0; // byte_count*8-HEADLEN
b8pos = 0;
header_found = 0;
herrs = headcmp(&dsp, symlen, mv_pos, mv<0, 0); // symlen=1
if (herrs <= 3) header_found = 1; // herrs <= 3 bitfehler in header
if (header_found) {
if (/*preamble &&*/ option_ofs /*option_iq*/)
{
float freq = 0.0;
float snr = 0.0;
int er = get_fqofs_rs41(&dsp, mv_pos, &freq, &snr);
while ( byte_count < FRAME_LEN )
{
if (option_bin) {
bitQ = fgetc(fp);
if (bitQ != EOF) bit = bitQ & 0x1;
}
else {
if (option_iq >= 2) {
float bl = -1;
if (option_iq > 2) bl = 1.0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0);
}
byte_count = FRAMESTART;
bit_count = 0; // byte_count*8-HEADLEN
bitpos = 0;
while ( byte_count < FRAME_LEN ) {
if (option_iq >= 2) {
bitQ = read_slbit(&dsp, symlen, &bit, option_inv, bitofs, bit_count, 1.0, 0);
}
else {
bitQ = read_slbit(&dsp, symlen, &bit, option_inv, bitofs, bit_count, -1, 0);
}
if ( bitQ == EOF) break;
bit_count += 1;
bitbuf[bitpos] = bit;
bitpos++;
if (bitpos == BITS) {
bitpos = 0;
byte = bits2byte(bitbuf);
gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN];
byte_count++;
}
else {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, 0);
}
}
if ( bitQ == EOF ) break; // liest 2x EOF
print_frame(&gpx, byte_count);
byte_count = FRAMESTART;
header_found = 0;
if (gpx.option.inv) bit ^= 1;
bitpos += 1;
bitbuf[b8pos] = bit;
b8pos++;
if (b8pos == BITS) {
b8pos = 0;
byte = bits2byte(bitbuf);
gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN];
byte_count++;
}
}
}
print_frame(&gpx, byte_count);
byte_count = FRAMESTART;
header_found = 0;
}
}
free_buffers(&dsp);
if (!option_bin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
}
else //if (rawhex)
{