From d29b7af19235270f8ad11639713f9300d55c3687 Mon Sep 17 00:00:00 2001 From: Zilog80 Date: Sun, 6 Feb 2022 20:27:45 +0100 Subject: [PATCH] (test->master) dfm09/17: guess DFM subtype, check delta(diff(cnt,sec)) --- demod/mod/dfm09mod.c | 704 +++++++++++++++++++++++++++---------------- 1 file changed, 452 insertions(+), 252 deletions(-) diff --git a/demod/mod/dfm09mod.c b/demod/mod/dfm09mod.c index 951c0b3..9ffd667 100644 --- a/demod/mod/dfm09mod.c +++ b/demod/mod/dfm09mod.c @@ -34,6 +34,28 @@ #include "demod_mod.h" +enum dfmtyp_keys_t { + UNDEF, + UNKNW, + DFM06, + PS15, + DFM09, + DFM09P, + DFM17, + DFM17P +}; + +static char *DFM_types[] = { + [UNDEF] = "", + [UNKNW] = "DFMxX", + [DFM06] = "DFM06", + [PS15] = "PS15", + [DFM09] = "DFM09", + [DFM09P] = "DFM09P", + [DFM17] = "DFM17", + [DFM17P] = "DFM17P" +}; + typedef struct { i8_t vbs; // verbose output i8_t raw; // raw frames @@ -75,14 +97,19 @@ typedef struct { int sonde_typ; ui32_t SN6; ui32_t SN; - int week; int gpssec; + int week; int tow; ui32_t sec_gps; int jahr; int monat; int tag; int std; int min; float sek; double lat; double lon; double alt; double dir; double horiV; double vertV; - float meas24[5+2]; - float status[2]; + //float T; + float Rf; float _frmcnt; + float meas24[9]; + float status[2]; + ui32_t val24[9]; + ui8_t cfgchk24[9]; + int cfgchk; char sonde_id[16]; // "ID__:xxxxxxxx\0\0" hsbit_t frame[BITFRAME_LEN+4]; // char frame_bits[BITFRAME_LEN+4]; char dat_str[9][13+1]; @@ -90,8 +117,11 @@ typedef struct { pcksts_t pck[9]; option_t option; int ptu_out; + char sensortyp0xC; + char *dfmtyp; int jsn_freq; // freq/kHz (SDR) gpsdat_t gps; + int prev_cntsec_diff; } gpx_t; @@ -434,24 +464,26 @@ static float get_Temp(gpx_t *gpx) { // meas[0..4] // meas0 = g*(R + Rs) // meas3 = g*Rs , Rs: dfm6:10k, dfm9:20k // meas4 = g*Rf , Rf=220k + float T = 0; // T/Kelvin float f = gpx->meas24[0], f1 = gpx->meas24[3], f2 = gpx->meas24[4]; - if (gpx->ptu_out >= 0xC) { + if (gpx->sensortyp0xC == 'P') { // 0xC: "P+" DFM-09P , "T-" DFM-17TU ; 0xD: "P-" DFM-17P ? f = gpx->meas24[0+1]; f1 = gpx->meas24[3+2]; f2 = gpx->meas24[4+2]; } - //float *meas = gpx->meas24; - float B0 = 3260.0; // B/Kelvin, fit -55C..+40C - float T0 = 25 + 273.15; // t0=25C - float R0 = 5.0e3; // R0=R25=5k - float Rf = 220e3; // Rf = 220k - float g = f2/Rf; - float R = (f-f1) / g; // meas[0,3,4] > 0 ? - float T = 0; // T/Kelvin - if (f*f1*f2 == 0) R = 0; - if (R > 0) T = 1/(1/T0 + 1/B0 * log(R/R0)); + if (gpx->cfgchk) { + //float *meas = gpx->meas24; + float B0 = 3260.0; // B/Kelvin, fit -55C..+40C + float T0 = 25 + 273.15; // t0=25C + float R0 = 5.0e3; // R0=R25=5k + float Rf = gpx->Rf; // Rf = DFM09:220k , DFM17:332k + float g = f2/Rf; + float R = (f-f1) / g; // meas[0,3,4] > 0 ? + if (f*f1*f2 == 0) R = 0; + if (R > 0) T = 1/(1/T0 + 1/B0 * log(R/R0)); + } return T - 273.15; // Celsius // DFM-06: meas20 * 16 = meas24 // -> (meas24[0]-meas24[3])/meas24[4]=(meas20[0]-meas20[3])/meas20[4] @@ -468,7 +500,7 @@ static float get_Temp2(gpx_t *gpx) { // meas[0..4] float f = gpx->meas24[0], f1 = gpx->meas24[3], f2 = gpx->meas24[4]; - if (gpx->ptu_out >= 0xC) { + if (gpx->ptu_out >= 0xC && gpx->meas24[6] < 220e3) { f = gpx->meas24[0+1]; f1 = gpx->meas24[3+2]; f2 = gpx->meas24[4+2]; @@ -476,7 +508,7 @@ static float get_Temp2(gpx_t *gpx) { // meas[0..4] float B0 = 3260.0; // B/Kelvin, fit -55C..+40C float T0 = 25 + 273.15; // t0=25C float R0 = 5.0e3; // R0=R25=5k - float Rf2 = 220e3; // Rf2 = Rf = 220k + float Rf2 = 220e3; // Rf2 = Rf = DFM09:220k , DFM17:332k float g_o = f2/Rf2; // approx gain float Rs_o = f1/g_o; // = Rf2 * f1/f2; float Rf1 = Rs_o; // Rf1 = Rs: dfm6:10k, dfm9:20k @@ -494,7 +526,7 @@ static float get_Temp2(gpx_t *gpx) { // meas[0..4] R = (f-f1)/g; // meas[0,3,4] > 0 ? if (R > 0) T = 1/(1/T0 + 1/B0 * log(R/R0)); - if (gpx->option.ptu && gpx->ptu_out && gpx->option.dbg) { + if (gpx->option.ptu && gpx->ptu_out && gpx->option.dbg && gpx->option.vbs == 3) { printf(" (Rso: %.1f , Rb: %.1f)", Rs_o/1e3, Rb/1e3); } @@ -533,13 +565,13 @@ static float get_Temp4(gpx_t *gpx) { // meas[0..4] float f = gpx->meas24[0], f1 = gpx->meas24[3], f2 = gpx->meas24[4]; - if (gpx->ptu_out >= 0xC) { + if (gpx->ptu_out >= 0xC && gpx->meas24[6] < 220e3) { f = gpx->meas24[0+1]; f1 = gpx->meas24[3+2]; f2 = gpx->meas24[4+2]; } //float *meas = gpx->meas24; - float Rf = 220e3; // Rf = 220k + float Rf = 220e3; // Rf = DFM09:220k , DFM17:332k float g = f2/Rf; float R = (f-f1) / g; // f,f1,f2 > 0 ? float T = 0; // T/Kelvin @@ -550,6 +582,14 @@ static float get_Temp4(gpx_t *gpx) { // meas[0..4] } +static int reset_cfgchk(gpx_t *gpx) { + int j; + for (j = 0; j < 9; j++) gpx->cfgchk24[j] = 0; + gpx->cfgchk = 0; + gpx->ptu_out = 0; + return 0; +} + #define SNbit 0x0100 static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { int ret = 0; @@ -571,17 +611,18 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { { // reset if 0x5A, 0x5B (DFM-06) gpx->sonde_typ = 0; gpx->snc.max_ch = conf_id; + reset_cfgchk(gpx); } if (conf_id > 5 && conf_id > gpx->snc.max_ch && ec == 0) { // mind. 6 Kanaele if (bits2val(conf_bits+4, 4) == 0xC) { // 0xsCaaaab gpx->snc.max_ch = conf_id; // reset? } -/* + /* if (bits2val(conf_bits, 8) == 0x70) { // 0x70aaaab gpx->snc.max_ch = conf_id; // reset? } -*/ + */ } // SN: mind. 6 Kanaele @@ -595,10 +636,11 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { if (SN6 == gpx->SN6 && SN6 != 0) { // nur Nibble-Werte 0..9 gpx->sonde_typ = SNbit | 6; gpx->ptu_out = 6; // <-> DFM-06 - sprintf(gpx->sonde_id, "ID06:%6X", gpx->SN6); + sprintf(gpx->sonde_id, "IDx%1X:%6X", gpx->sonde_typ & 0xF, gpx->SN6); } else { // reset gpx->sonde_typ = 0; + reset_cfgchk(gpx); } gpx->SN6 = SN6; } // SN in last pck/channel, #{pcks} depends on (sensor) config; observed: @@ -614,6 +656,7 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { gpx->snc.chXbit = 0; gpx->snc.chX[0] = 0; gpx->snc.chX[1] = 0; + reset_cfgchk(gpx); } gpx->snc.sn_ch = sn_ch; gpx->snc.chX[hl] = (val >> 4) & 0xFFFF; @@ -628,19 +671,17 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { gpx->ptu_out = 0; if (sn_ch == 0xA /*&& (sn2_ch & 0xF) == 0xC*/) gpx->ptu_out = sn_ch; // <+> DFM-09 if (sn_ch == 0xB /*&& (sn2_ch & 0xF) == 0xC*/) gpx->ptu_out = sn_ch; // <-> DFM-17 - if (sn_ch == 0xC) gpx->ptu_out = sn_ch; // <+> DFM-09P(?) - if (sn_ch == 0xD) gpx->ptu_out = sn_ch; // <-> DFM-17P? + if (sn_ch == 0xC) gpx->ptu_out = sn_ch; // <+> DFM-09P(?) , <-> DFM-17TU(?) + if (sn_ch == 0xD) gpx->ptu_out = sn_ch; // <-> DFM-17P(?) // PS-15 ? (sn2_ch & 0xF) == 0x0 : gpx->ptu_out = 0 // <-> PS-15 - if ( (gpx->sonde_typ & 0xF) == 0xA) { - sprintf(gpx->sonde_id, "ID09:%6u", gpx->SN); - } - else { - sprintf(gpx->sonde_id, "ID-%1X:%6u", gpx->sonde_typ & 0xF, gpx->SN); + if ( (gpx->sonde_typ & 0xF) > 6) { + sprintf(gpx->sonde_id, "IDx%1X:%6u", gpx->sonde_typ & 0xF, gpx->SN); } } else { // reset gpx->sonde_typ = 0; + reset_cfgchk(gpx); } gpx->snc.SN_X = SN; gpx->snc.chXbit = 0; @@ -651,41 +692,80 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) { } - if (conf_id >= 0 && conf_id <= 4) { + if (conf_id >= 0 && conf_id <= 8) { + gpx->cfgchk24[conf_id] = 1; val = bits2val(conf_bits+4, 4*6); - gpx->meas24[conf_id] = fl24(val); + gpx->val24[conf_id] = val; + gpx->meas24[conf_id] = fl24(val); //0xA: 0..4 // DFM-09 (STM32): 24bit 0exxxxx // DFM-06 (NXP8): 20bit 0exxxx0 // fl20(bits2val(conf_bits+4, 4*5)) // = fl20(exxxx) // = fl24(exxxx0)/2^4 // meas20 * 16 = meas24 + gpx->cfgchk = 0; + if (gpx->ptu_out >= 0x5) gpx->cfgchk = gpx->cfgchk24[0]*gpx->cfgchk24[1]*gpx->cfgchk24[2] + *gpx->cfgchk24[3]*gpx->cfgchk24[4]*gpx->cfgchk24[5]; + if (gpx->ptu_out >= 0x7) gpx->cfgchk *= gpx->cfgchk24[6]*gpx->cfgchk24[7]; + if (gpx->ptu_out >= 0x8) gpx->cfgchk *= gpx->cfgchk24[8]; } - if (gpx->ptu_out >= 0xC) { // DFM>=09(P) - if (conf_id >= 5 && conf_id <= 6) { - val = bits2val(conf_bits+4, 4*6); - gpx->meas24[conf_id] = fl24(val); + + gpx->sensortyp0xC = 'T'; + gpx->Rf = 220e3; + if (gpx->cfgchk) + { // 0xC: "P+" DFM-09P , "T-" DFM-17TU ; 0xD: "P-" DFM-17P ? + if (gpx->ptu_out >= 0xD || (gpx->ptu_out >= 0xC && gpx->meas24[6] < 220e3)) { // gpx->meas24[6] < 220e3 <=> gpx->meas24[0] > 1e6 ? + gpx->sensortyp0xC = 'P'; // gpx->meas24[0] > 1e6 ? + } + if ( ((gpx->ptu_out == 0xB || gpx->ptu_out == 0xC) && gpx->sensortyp0xC == 'T') || gpx->ptu_out >= 0xD) gpx->Rf = 332e3; // DFM-17 ? + + // STM32-status: Bat, MCU-Temp + if (gpx->ptu_out >= 0xA) { // DFM>=09(P) (STM32) + ui8_t ofs = 0; + if (gpx->sensortyp0xC == 'P') ofs = 2; + // + if (conf_id == 0x5+ofs) { // voltage + val = bits2val(conf_bits+8, 4*4); + gpx->status[0] = val/1000.0; + } + if (conf_id == 0x6+ofs) { // T-intern (STM32) + val = bits2val(conf_bits+8, 4*4); + gpx->status[1] = val/100.0; + } + } + else { + gpx->status[0] = 0; + gpx->status[1] = 0; } } - // STM32-status: Bat, MCU-Temp - if (gpx->ptu_out >= 0xA) { // DFM>=09(P) (STM32) - ui8_t ofs = 0; - if (gpx->ptu_out >= 0xC) ofs = 2; - if (conf_id == 0x5+ofs) { // voltage - val = bits2val(conf_bits+8, 4*4); - gpx->status[0] = val/1000.0; - } - if (conf_id == 0x6+ofs) { // T-intern (STM32) - val = bits2val(conf_bits+8, 4*4); - gpx->status[1] = val/100.0; - } + /* guess DFM type + V/Ti Tf012 Rf + 0xA DFM-09 5/6 0,3,4 'T+' 220k + 0xC DFM-09P 7/8 1,5,6 'P+' 220k + 0xB DFM-17 5/6 0,3,4 'T-' 332k + 0xC DFM-17TU 5/6 0,3,4 'T-' 332k + 0xD DFM-17P 7/8 1,5,6 'P-' 332k + */ + gpx->dfmtyp = DFM_types[UNDEF]; + switch (gpx->sonde_typ & 0xF) { + case 0x6: gpx->dfmtyp = DFM_types[DFM06]; + break; + case 0x7: + case 0x8: gpx->dfmtyp = DFM_types[PS15]; + break; + case 0xA: gpx->dfmtyp = DFM_types[DFM09]; + break; + case 0xB: gpx->dfmtyp = DFM_types[DFM17]; + break; + case 0xC: if (gpx->sensortyp0xC == 'P') gpx->dfmtyp = DFM_types[DFM09P]; + else /*'T'*/ gpx->dfmtyp = DFM_types[DFM17]; + break; + case 0xD: gpx->dfmtyp = DFM_types[DFM17P]; + break; + default: gpx->dfmtyp = DFM_types[UNKNW]; + break; } - else { - gpx->status[0] = 0; - gpx->status[1] = 0; - } - return ret; } @@ -721,6 +801,27 @@ static void print_gpx(gpx_t *gpx) { jsonout = 0; } + if (!gpx->option.raw || gpx->option.jsn) { + + // seconds since GPS (ignoring leap seconds, DFM=UTC) + datetime2GPSweek(gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, (int)(gpx->sek+0.5), &(gpx->week), &(gpx->tow)); + gpx->sec_gps = gpx->week*604800 + gpx->tow; // SECONDS_IN_WEEK=7*86400=604800 + + if (contgps) { + ui8_t secmod256 = (ui8_t)gpx->sec_gps; // % 256 + int cntsec_diff = secmod256 - gpx->frnr; + if (cntsec_diff < 0) cntsec_diff += 256; + // DFM06: cntsec_diff might drift slowly (30sec sync), but recovers faster + // DFM09: delta(diff)=1 could indicate decoding error + if (gpx->option.jsn && cntsec_diff != gpx->prev_cntsec_diff) { // only ecc-valid/json diffs ? + jsonout = 0; + gpx->sonde_typ = 0; + reset_cfgchk(gpx); + } + gpx->prev_cntsec_diff = cntsec_diff; + } + } + if (output & 0xF000) { if (gpx->option.raw == 2) { @@ -746,34 +847,45 @@ static void print_gpx(gpx_t *gpx) { printf(" vH: %5.2f ", gpx->horiV); printf(" D: %5.1f ", gpx->dir); printf(" vV: %5.2f ", gpx->vertV); - if (gpx->option.ptu && gpx->ptu_out) { - float t = get_Temp(gpx); - if (t > -270.0) printf(" T=%.1fC ", t); - if (gpx->option.dbg) { - float t2 = get_Temp2(gpx); - float t4 = get_Temp4(gpx); - if (t2 > -270.0) printf(" T2=%.1fC ", t2); - if (t4 > -270.0) printf(" T4=%.1fC ", t4); - printf(" f0: %.2f ", gpx->meas24[0]); - printf(" f1: %.2f ", gpx->meas24[1]); - printf(" f2: %.2f ", gpx->meas24[2]); - printf(" f3: %.2f ", gpx->meas24[3]); - printf(" f4: %.2f ", gpx->meas24[4]); - if (gpx->ptu_out >= 0xC) { - printf(" f5: %.2f ", gpx->meas24[5]); - printf(" f6: %.2f ", gpx->meas24[6]); - } + if (gpx->cfgchk) + { + if (gpx->option.ptu && gpx->ptu_out) { + float t = get_Temp(gpx); + if (t > -270.0) { + printf(" T=%.1fC ", t); // 0xC:P+ DFM-09P , 0xC:T- DFM-17TU , 0xD:P- DFM-17P ? + if (gpx->option.vbs == 3) printf(" (0x%X:%c%c) ", gpx->sonde_typ & 0xF, gpx->sensortyp0xC, gpx->option.inv?'-':'+'); + } + if (gpx->option.dbg) { + float t2 = get_Temp2(gpx); + float t4 = get_Temp4(gpx); + if (t2 > -270.0) printf(" T2=%.1fC ", t2); + if (t4 > -270.0) printf(" T4=%.1fC ", t4); + } + } + if (gpx->option.vbs == 3 && gpx->ptu_out >= 0xA) { + if (gpx->status[0]> 0.0) printf(" U: %.2fV ", gpx->status[0]); + if (gpx->status[1]> 0.0) printf(" Ti: %.1fK ", gpx->status[1]); } } - if (gpx->option.vbs == 3 && gpx->ptu_out >= 0xA) { - printf(" U: %.2fV ", gpx->status[0]); - printf(" Ti: %.1fK ", gpx->status[1]); + if (gpx->option.dbg) { + printf(" f0:%.1f", gpx->meas24[0]); + printf(" f1:%.1f", gpx->meas24[1]); + printf(" f2:%.1f", gpx->meas24[2]); + printf(" f3:%.1f", gpx->meas24[3]); + printf(" f4:%.1f", gpx->meas24[4]); + if (gpx->ptu_out >= 0xA /*0xC*/) { + printf(" f5:%.1f", gpx->meas24[5]); + printf(" f6:%.1f", gpx->meas24[6]); + } + printf(" "); } if (gpx->option.vbs) { if (gpx->sonde_typ & SNbit) { - printf(" (%s) ", gpx->sonde_id); + printf(" (%s", gpx->sonde_id); + if (gpx->option.vbs > 1 && *gpx->dfmtyp) printf(":%s", gpx->dfmtyp); + printf(") "); gpx->sonde_typ ^= SNbit; } } @@ -793,26 +905,21 @@ static void print_gpx(gpx_t *gpx) { if (gpx->option.jsn && jsonout && gpx->sek < 60.0) { char *ver_jsn = NULL; - unsigned long sec_gps = 0; - int week = 0; - int tow = 0; char json_sonde_id[] = "DFM-xxxxxxxx\0\0"; - ui8_t dfm_typ = (gpx->sonde_typ & 0xF); - switch ( dfm_typ ) { + ui8_t dfmXtyp = (gpx->sonde_typ & 0xF); + switch ( dfmXtyp ) { case 0: sprintf(json_sonde_id, "DFM-xxxxxxxx"); break; //json_sonde_id[0] = '\0'; case 6: sprintf(json_sonde_id, "DFM-%6X", gpx->SN6); break; // DFM-06 case 0xA: sprintf(json_sonde_id, "DFM-%6u", gpx->SN); break; // DFM-09 - // 0x7:PS-15?, 0xB:DFM-17? 0xC:DFM-09P? 0xD:DFM-17P? + // 0x7:PS-15?, 0xB:DFM-17? 0xC:DFM-09P?DFM-17TU? 0xD:DFM-17P? default : sprintf(json_sonde_id, "DFM-%6u", gpx->SN); } - // JSON frame counter: seconds since GPS (ignoring leap seconds, DFM=UTC) - datetime2GPSweek(gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, (int)(gpx->sek+0.5), &week, &tow); - sec_gps = week*604800 + tow; // SECONDS_IN_WEEK=7*86400=604800 + // JSON frame counter: gpx->sec_gps , seconds since GPS (ignoring leap seconds, DFM=UTC) // Print JSON blob // valid sonde_ID? printf("{ \"type\": \"%s\"", "DFM"); - printf(", \"frame\": %lu, ", sec_gps); // gpx->frnr + printf(", \"frame\": %u, ", gpx->sec_gps); // gpx->frnr printf("\"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"sats\": %d", json_sonde_id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->horiV, gpx->dir, gpx->vertV, gpx->gps.nSV); if (gpx->ptu_out >= 0xA && gpx->status[0] > 0) { // DFM>=09(P): Battery (STM32) @@ -822,7 +929,12 @@ static void print_gpx(gpx_t *gpx) { float t = get_Temp(gpx); // ecc-valid temperature? if (t > -270.0) printf(", \"temp\": %.1f", t); } - if (dfm_typ > 0) printf(", \"subtype\": \"0x%1X\"", dfm_typ); + //if (dfmXtyp > 0) printf(", \"subtype\": \"0x%1X\"", dfmXtyp); + if (dfmXtyp > 0) { + printf(", \"subtype\": \"0x%1X", dfmXtyp); + if (*gpx->dfmtyp) printf(":%s", gpx->dfmtyp); + printf("\""); + } if (gpx->jsn_freq > 0) { printf(", \"freq\": %d", gpx->jsn_freq); } @@ -863,7 +975,28 @@ static int print_frame(gpx_t *gpx) { ret2 = hamming(gpx->option.ecc, hamming_dat2, 13, block_dat2); ret = ret0 | ret1 | ret2; - if (gpx->option.raw == 1) { + if (gpx->option.raw == 9) { + int diff = 0; + for (i = 0; i < CONF; i++) { + diff += ( (gpx->frame[i].hb & 1) != (dfm_header[i] & 1) ); + } + if (diff == 0) + { + ui8_t byte = 0; + printf("%c", gpx->option.inv?'-':'+'); + printf("<%7.1f> ", gpx->_frmcnt); + for (i = CONF; i < BITFRAME_LEN; i++) { + if (i == DAT1 || i == DAT2) printf(" "); + byte |= (gpx->frame[i].hb&1)<<(i%4); // little endian + if (i % 4 == 3) { + printf("%1X", byte & 0xF); + byte = 0; + } + } + printf("\n"); + } + } + else if (gpx->option.raw == 1) { for (i = 0; i < 7; i++) { nib = bits2val(block_conf+S*i, S); @@ -903,7 +1036,7 @@ static int print_frame(gpx_t *gpx) { printf("\n"); } - if ( gpx->option.raw != 1 || gpx->option.jsn ) + if ( (gpx->option.raw&1) != 1 || gpx->option.jsn ) { if (gpx->option.ecc) { @@ -959,6 +1092,7 @@ int main(int argc, char **argv) { int wavloaded = 0; int sel_wavch = 0; // audio channel: left int spike = 0; + int rawhex = 0; int cfreq = -1; FILE *fp = NULL; @@ -1026,6 +1160,9 @@ int main(int argc, char **argv) { else if ( (strcmp(*argv, "-R") == 0) || (strcmp(*argv, "--RAW") == 0) ) { option_raw = 2; } + else if ( (strcmp(*argv, "--rawecc") == 0) ) { + option_raw = 9; + } else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) { option_inv = 0x1; } @@ -1098,6 +1235,7 @@ int main(int argc, char **argv) { } else if (strcmp(*argv, "--dbg") == 0) { gpx.option.dbg = 1; } else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; } + else if (strcmp(*argv, "--rawhex") == 0) { rawhex = 1; } // raw hex input else if (strcmp(*argv, "-") == 0) { int sample_rate = 0, bits_sample = 0, channels = 0; ++argv; @@ -1182,196 +1320,258 @@ int main(int argc, char **argv) { } #endif - if (!option_bin && !option_softin) { - if (option_iq == 0 && option_pcmraw) { - fclose(fp); - fprintf(stderr, "error: raw data not IQ\n"); - return -1; - } - if (option_iq) sel_wavch = 0; + if (!rawhex) { - pcm.sel_ch = sel_wavch; - if (option_pcmraw == 0) { - k = read_wav_header(&pcm, fp); - if ( k < 0 ) { + if (!option_bin && !option_softin) { + + if (option_iq == 0 && option_pcmraw) { 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; + } + } + + if (cfreq > 0) { + int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3; + gpx.jsn_freq = fq_kHz; + } + + // dfm: BT=1?, h=2.4? + 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 = dfm_rawheader; + dsp.hdrlen = strlen(dfm_rawheader); + dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5 + dsp.h = 1.8; // 2.4 modulation index abzgl. BT + dsp.opt_iq = option_iq; + dsp.opt_iqdc = option_iqdc; + dsp.opt_lp = option_lp; + dsp.lpIQ_bw = lpIQ_bw; // 12e3; // 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\n"); + } + + + k = init_buffers(&dsp); + if ( k < 0 ) { + fprintf(stderr, "error: init buffers\n"); + return -1; + } + + bitofs += shift; + } + else { + if (option_bin && option_softin) option_bin = 0; + // init circular header bit buffer + hdb.hdr = dfm_rawheader; + hdb.len = strlen(dfm_rawheader); + hdb.thb = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !! + hdb.bufpos = -1; + hdb.buf = calloc(hdb.len, sizeof(char)); + if (hdb.buf == NULL) { + fprintf(stderr, "error: malloc\n"); + 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; } } - if (cfreq > 0) { - int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3; - gpx.jsn_freq = fq_kHz; - } - // dfm: BT=1?, h=2.4? - 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 = dfm_rawheader; - dsp.hdrlen = strlen(dfm_rawheader); - dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5 - dsp.h = 1.8; // 2.4 modulation index abzgl. BT - dsp.opt_iq = option_iq; - dsp.opt_iqdc = option_iqdc; - dsp.opt_lp = option_lp; - dsp.lpIQ_bw = lpIQ_bw; // 12e3; // 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\n"); - } - - - k = init_buffers(&dsp); - if ( k < 0 ) { - fprintf(stderr, "error: init buffers\n"); - return -1; - } - - bitofs += shift; - } - else { - if (option_bin && option_softin) option_bin = 0; - // init circular header bit buffer - hdb.hdr = dfm_rawheader; - hdb.len = strlen(dfm_rawheader); - hdb.thb = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !! - hdb.bufpos = -1; - hdb.buf = calloc(hdb.len, sizeof(char)); - if (hdb.buf == NULL) { - fprintf(stderr, "error: malloc\n"); - 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; - } - } - - - while ( 1 ) - { - if (option_bin) { // aka find_binrawhead() - header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits? - hdrcnt += nfrms; - } - 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 - _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 (header_found) + while ( 1 ) { - bitpos = 0; - pos = headerlen; - pos /= 2; + if (option_bin) { // aka find_binrawhead() + header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits? + hdrcnt += nfrms; + } + 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 + _mv = dsp.mv; + } + if (header_found == EOF) break; - //if (fabs(mv) > 0.85) nfrms = 8; else nfrms = 4; // test OK/KO/NO count + // mv == correlation score + if (_mv *(0.5-gpx.option.inv) < 0) { + if (gpx.option.aut == 0) header_found = 0; + else gpx.option.inv ^= 0x1; + } - frm = 0; - while ( frm < nfrms ) { // nfrms=1,2,4,8 - if (option_bin || option_softin) { - gpx._frmcnt = hdrcnt + frm; - } - else { - gpx._frmcnt = dsp.mv_pos/(2.0*dsp.sps*BITFRAME_LEN) + frm; - } - while ( pos < BITFRAME_LEN ) - { - if (option_bin) { - // symbols or bits? - // manchester1 1->10,0->01: 1.bit (DFM-06) - // manchester2 0->10,1->01: 2.bit (DFM-09) - bitQ = fgetc(fp); - if (bitQ != EOF) { - hsbit.hb = bitQ & 0x1; - bitQ = fgetc(fp); // check: rbit0^rbit1=1 (Manchester) - if (bitQ != EOF) hsbit.hb = bitQ & 0x1; // 2.bit (DFM-09) - 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); - } - } + if (header_found) + { + bitpos = 0; + pos = headerlen; + pos /= 2; + + //if (fabs(mv) > 0.85) nfrms = 8; else nfrms = 4; // test OK/KO/NO count + + frm = 0; + while ( frm < nfrms ) { // nfrms=1,2,4,8 + if (option_bin || option_softin) { + gpx._frmcnt = hdrcnt + frm; } else { - float bl = -1; - if (option_iq >= 2) spike = 0; - if (option_iq > 2) bl = 4.0; - bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike); // symlen=2 - // optional: - // normalize soft bit s_j by - // rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1] + gpx._frmcnt = dsp.mv_pos/(2.0*dsp.sps*BITFRAME_LEN) + frm; } - if ( bitQ == EOF ) { frm = nfrms; break; } // liest 2x EOF + while ( pos < BITFRAME_LEN ) + { + if (option_bin) { + // symbols or bits? + // manchester1 1->10,0->01: 1.bit (DFM-06) + // manchester2 0->10,1->01: 2.bit (DFM-09) + bitQ = fgetc(fp); + if (bitQ != EOF) { + hsbit.hb = bitQ & 0x1; + bitQ = fgetc(fp); // check: rbit0^rbit1=1 (Manchester) + if (bitQ != EOF) hsbit.hb = bitQ & 0x1; // 2.bit (DFM-09) + 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 { + float bl = -1; + if (option_iq >= 2) spike = 0; + if (option_iq > 2) bl = 4.0; + bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike); // symlen=2 + // optional: + // normalize soft bit s_j by + // rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1] + } + if ( bitQ == EOF ) { frm = nfrms; break; } // liest 2x EOF - if (gpx.option.inv) { - hsbit.hb ^= 1; - hsbit.sb = -hsbit.sb; + if (gpx.option.inv) { + hsbit.hb ^= 1; + hsbit.sb = -hsbit.sb; + } + + gpx.frame[pos] = hsbit; + pos++; + bitpos += 1; } - gpx.frame[pos] = hsbit; - pos++; - bitpos += 1; + if (pos < BITFRAME_LEN) break; + ret = print_frame(&gpx); + pos = 0; + frm += 1; + //if (ret < 0) frms += 1; } - - ret = print_frame(&gpx); - if (pos < BITFRAME_LEN) break; - pos = 0; - frm += 1; - //if (ret < 0) frms += 1; } + + header_found = 0; + pos = headerlen; } - header_found = 0; - pos = headerlen; + + if (!option_bin && !option_softin) free_buffers(&dsp); + else { + if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; } + } + } + else //if (rawhex) + { + #define BUFLEN (BITFRAME_LEN/4+12) + char buffer_rawhex[BUFLEN+1]; // no header + char *pbuf = NULL; + int len, i, j; + int ch = 0; + int pos = 0; + float _frmcnt = -1.0f; + + memset(buffer_rawhex, BUFLEN+1, 0); + + while ( (ch=fgetc(fp)) != EOF) + { + if (ch == ' ') continue; + if (ch == '\n') { + buffer_rawhex[pos] = '\0'; + // + // +/- gpx.frame[].hb ... + // + gpx.option.inv = buffer_rawhex[0]=='-' ? 1 : 0; + sscanf(buffer_rawhex+1, "<%f>", &_frmcnt); + pbuf = strchr(buffer_rawhex, '>'); + if (pbuf != NULL) + { + pbuf++; + len = strlen(pbuf); + if (len*4 == BITFRAME_LEN-CONF) { + gpx._frmcnt = _frmcnt; + for (i = 0; i < len; i++) { + ui8_t nib = 0xFF; + sscanf(pbuf+i, "%1hhx", &nib); + for (j = 0; j < 4; j++) { + gpx.frame[CONF+4*i+j].hb = (nib>>j) & 0x1; // little endian + gpx.frame[CONF+4*i+j].sb = 2*gpx.frame[CONF+4*i+j].hb - 1; + } + } + print_frame(&gpx); + } + } + pos = 0; + } + else { + if ( ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F' + || ch == '+' || ch == '-' || ch == '<' || ch == '.' || ch == '>') { + if (pos < BUFLEN) { + buffer_rawhex[pos] = ch; + pos++; + } + } + else { + // frame error + } + } + + } } - if (!option_bin && !option_softin) free_buffers(&dsp); - else { - if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; } - } - fclose(fp); return 0;