diff --git a/auto_rx/autorx/__init__.py b/auto_rx/autorx/__init__.py index e59b75c..bf7cd15 100644 --- a/auto_rx/autorx/__init__.py +++ b/auto_rx/autorx/__init__.py @@ -12,7 +12,7 @@ from queue import Queue # MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus. # PATCH - Small changes, or minor feature additions. -__version__ = "1.6.0-beta15" +__version__ = "1.6.0-beta16" # Global Variables diff --git a/auto_rx/test/generate_lowsnr.py b/auto_rx/test/generate_lowsnr.py index c62b462..4540af0 100644 --- a/auto_rx/test/generate_lowsnr.py +++ b/auto_rx/test/generate_lowsnr.py @@ -46,7 +46,8 @@ SAMPLES = [ ['rsngp_96k_float.bin', 2400, -100.0, 96000], # RS92-NGP - wider bandwidth. ['lms6-400_96k_float.bin', 4800, -100, 96000], # LMS6, 400 MHz variant. Continuous signal. ['mrz_96k_float.bin', 2400, -100, 96000], # MRZ Continuous signal. - ['m20_96k_float.bin', 9600, -15, 96000] # M20, kind of continuous signal? residual carrier when not transmitting + ['m20_96k_float.bin', 9600, -15, 96000], # M20, kind of continuous signal? residual carrier when not transmitting + ['mts01_96k_float.bin', 1200, -20, 96000] ] diff --git a/auto_rx/test/test_demod.py b/auto_rx/test/test_demod.py index b5d21c5..6098761 100644 --- a/auto_rx/test/test_demod.py +++ b/auto_rx/test/test_demod.py @@ -370,7 +370,18 @@ processing_type = { "post_process" : "| grep -F [OK] | wc -l", # ECC 'files' : "./generated/imet4*.bin" }, + 'mts01_fsk_demod_soft_centre': { + # cat ./generated/dfm09_96k_float_15.0dB.bin | csdr shift_addition_cc 0.25000 2>/dev/null | csdr convert_f_s16 | + #./tsrc - - 1.041666 | ../fsk_demod --cs16 -b 1 -u 45000 2 100000 2500 - - 2>/dev/null | + #python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null| + #../dfm09ecc -vv --json --dist --auto + 'demod': '| csdr convert_f_s16 | ../tsrc - - 0.500|', # ../fsk_demod --cs16 -b -10000 -u 10000 -s --stats=5 2 48000 1200 - - 2>stats.txt |',#' python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null| ', + 'decode': '../meteosis_mod --json --IQ 0.0 --lpIQ --dc - 48000 16 2>/dev/null', + "post_process" : " | grep frame | wc -l", # ECC + #"post_process" : "| grep -o '\[OK\]' | wc -l", # No ECC + 'files' : "./generated/mts01*.bin" + }, } @@ -705,7 +716,7 @@ _demod_command = "| csdr convert_f_s16 | ./tsrc - - %.4f |" % (_resample) processing_type['dft_detect_iq'] = { 'demod': _demod_command, - 'decode': "../dft_detect -t 5 --iq --bw 32 --dc - 48000 16 2>/dev/null", + 'decode': "../dft_detect -t 5 --iq --bw 20 --dc - 48000 16 2>/dev/null", # Grep out the line containing the detected sonde type. "post_process" : " | grep \:", 'files' : "./generated/*.bin" @@ -799,7 +810,7 @@ def run_analysis(mode, file_mask=None, shift=0.0, verbose=False, log_output = No _runtime = time.time() - _start - _result = "%s, %s, %.1f" % (os.path.basename(_file), _output.strip(), _runtime) + _result = "%s, %s, %.3f" % (os.path.basename(_file), _output.strip(), _runtime) print(_result) if log_output is not None: diff --git a/scan/Makefile b/scan/Makefile index 9da89ba..80a9814 100644 --- a/scan/Makefile +++ b/scan/Makefile @@ -1,4 +1,4 @@ -CFLAGS = -O3 -w -Wno-unused-variable -DNOC34C50 +CFLAGS = -O3 -w -Wno-unused-variable -DNOC34C50 -DNOIMET1AB LDLIBS = -lm PROGRAMS := dft_detect diff --git a/scan/dft_detect.c b/scan/dft_detect.c index 65b2646..abac760 100644 --- a/scan/dft_detect.c +++ b/scan/dft_detect.c @@ -75,6 +75,13 @@ static char mrz_header[] = "1001100110011001""1001101010101010"; // 0xAA 0xBF //int imet54_sps = 4800; static char imet54_header[] = "0000000001""0101010101""0001001001""0001001001"; // 0x00 0xAA 0x24 0x24 +// Meteosis MTS01 1200 baud +// Lmax +// len(AA AA B4 2B)=32 -> L=1280 // more accurate, +19% slower +// len(AA B4 2B)=24 -> L=960 // same L as meisei, +7% slower +static char mts01_header[] = "10101010""10101010" // preamble: AA AA + "10110100""00101011"; // 10000000: B4 2B //80 + // imet_9600 / 1200 Hz; static char imet_preamble[] = //"11110000111100001111000011110000" @@ -121,8 +128,9 @@ typedef struct { float df; // Df = df*sr_base; } rsheader_t; -static float lpFM_bw[2] = { 4e3, 10e3 }; // FM-audio lowpass bandwidth -static float lpIQ_bw[3] = { 12e3, 22e3, 200e3 }; // IF iq lowpass bandwidth +#define N_bwIQ 4 +static float lpFM_bw[2] = { 4e3, 10e3 }; // FM-audio lowpass bandwidth +static float lpIQ_bw[N_bwIQ] = { 6e3, 12e3, 22e3, 200e3 }; // IF iq lowpass bandwidth static float set_lpIQ = 0.0; #define tn_DFM 2 @@ -133,6 +141,7 @@ static float set_lpIQ = 0.0; #define tn_LMS6 8 #define tn_MEISEI 9 #define tn_MRZ 12 +#define tn_MTS01 13 #define tn_C34C50 15 #define tn_MK2LMS 18 #define tn_IMET5 24 @@ -141,27 +150,32 @@ static float set_lpIQ = 0.0; #define tn_IMET1rs 28 #define tn_IMET1ab 29 -#define Nrs 14 -#define idxIMETafsk 11 -#define idxRS 12 -#define idxI4 13 +#define Nrs 15 +#define idxIMETafsk 12 +#define idxRS 13 +#define idxI4 14 static rsheader_t rs_hdr[Nrs] = { - { 2500, 0, 0, dfm_header, 1.0, 0.0, 0.65, 2, NULL, "DFM9", tn_DFM, 0, 0, 0.0, 0.0}, // DFM6: -2 ? - { 4800, 0, 0, rs41_header, 0.5, 0.0, 0.70, 2, NULL, "RS41", tn_RS41, 0, 0, 0.0, 0.0}, - { 4800, 0, 0, rs92_header, 0.5, 0.0, 0.70, 3, NULL, "RS92", tn_RS92, 0, 0, 0.0, 0.0}, // RS92NGP: 1680/400=4.2 - { 4800, 0, 0, lms6_header, 1.0, 0.0, 0.60, 8, NULL, "LMS6", tn_LMS6, 0, 0, 0.0, 0.0}, // lmsX: 7? - { 4800, 0, 0, imet54_header, 0.5, 0.0, 0.80, 2, NULL, "IMET5", tn_IMET5, 0, 0, 0.0, 0.0}, // (rs_hdr[idxI5]) - { 9616, 0, 0, mk2a_header, 1.0, 0.0, 0.70, 2, NULL, "MK2LMS", tn_MK2LMS, 1, 2, 0.0, 0.0}, // Mk2a/LMS6-1680 , --IQ: decimate > 170kHz ... - { 9608, 0, 0, m10_header, 1.0, 0.0, 0.76, 2, NULL, "M10", tn_M10, 1, 1, 0.0, 0.0}, // M10.tn=5 (baud=9616) , M20.tn=6 (baud=9600) - { 2400, 0, 0, meisei_header, 1.0, 0.0, 0.70, 2, NULL, "MEISEI", tn_MEISEI, 0, 1, 0.0, 0.0}, - { 2400, 0, 0, mrz_header, 1.5, 0.0, 0.80, 2, NULL, "MRZ", tn_MRZ, 0, 0, 0.0, 0.0}, - { 5800, 0, 0, c34_preheader, 1.5, 0.0, 0.80, 2, NULL, "C34C50", tn_C34C50, 0, 1, 0.0, 0.0}, // C34/C50 2900 Hz tone - { 9600, 0, 0, imet1ab_header, 1.0, 0.0, 0.80, 2, NULL, "IMET1AB", tn_IMET1ab, 1, 2, 0.0, 0.0}, // (rs_hdr[idxAB]) - { 9600, 0, 0, imet_preamble, 0.5, 0.0, 0.80, 4, NULL, "IMETafsk", tn_IMETa , 1, 0, 0.0, 0.0}, // IMET1AB, IMET1RS (IQ)IMET4 - { 9600, 0, 0, imet1rs_header, 0.5, 0.0, 0.80, 2, NULL, "IMET1RS", tn_IMET1rs, 0, 2, 0.0, 0.0}, // (rs_hdr[idxRS]) IMET4: lpIQ=0 ... - { 9600, 0, 0, imet1rs_header, 0.5, 0.0, 0.80, 2, NULL, "IMET4", tn_IMET4, 1, 0, 0.0, 0.0}, // (rs_hdr[idxI4]) + { 2500, 0, 0, dfm_header, 1.0, 0.0, 0.65, 2, NULL, "DFM9", tn_DFM, 0, 1, 0.0, 0.0}, // DFM6: -2 ? + { 4800, 0, 0, rs41_header, 0.5, 0.0, 0.70, 2, NULL, "RS41", tn_RS41, 0, 1, 0.0, 0.0}, + { 4800, 0, 0, rs92_header, 0.5, 0.0, 0.70, 3, NULL, "RS92", tn_RS92, 0, 1, 0.0, 0.0}, // RS92NGP: 1680/400=4.2 + { 4800, 0, 0, lms6_header, 1.0, 0.0, 0.60, 8, NULL, "LMS6", tn_LMS6, 0, 1, 0.0, 0.0}, // lmsX: 7? + { 4800, 0, 0, imet54_header, 0.5, 0.0, 0.80, 2, NULL, "IMET5", tn_IMET5, 0, 1, 0.0, 0.0}, // (rs_hdr[idxI5]) + { 9616, 0, 0, mk2a_header, 1.0, 0.0, 0.70, 2, NULL, "MK2LMS", tn_MK2LMS, 1, 3, 0.0, 0.0}, // Mk2a/LMS6-1680 , --IQ: decimate > 170kHz ... + { 9608, 0, 0, m10_header, 1.0, 0.0, 0.76, 2, NULL, "M10", tn_M10, 1, 2, 0.0, 0.0}, // M10.tn=5 (baud=9616) , M20.tn=6 (baud=9600) + { 2400, 0, 0, meisei_header, 1.0, 0.0, 0.70, 2, NULL, "MEISEI", tn_MEISEI, 0, 2, 0.0, 0.0}, + { 2400, 0, 0, mrz_header, 1.5, 0.0, 0.80, 2, NULL, "MRZ", tn_MRZ, 0, 1, 0.0, 0.0}, + { 1200, 0, 0, mts01_header, 1.0, 0.0, 0.65, 2, NULL, "MTS01", tn_MTS01, 0, 0, 0.0, 0.0}, + { 5800, 0, 0, c34_preheader, 1.5, 0.0, 0.80, 2, NULL, "C34C50", tn_C34C50, 0, 2, 0.0, 0.0}, // C34/C50 2900 Hz tone + { 9600, 0, 0, imet1ab_header, 1.0, 0.0, 0.80, 2, NULL, "IMET1AB", tn_IMET1ab, 1, 3, 0.0, 0.0}, // (rs_hdr[idxAB]) + { 9600, 0, 0, imet_preamble, 0.5, 0.0, 0.80, 4, NULL, "IMETafsk", tn_IMETa , 1, 1, 0.0, 0.0}, // IMET1AB, IMET1RS (IQ)IMET4 + { 9600, 0, 0, imet1rs_header, 0.5, 0.0, 0.80, 2, NULL, "IMET1RS", tn_IMET1rs, 0, 3, 0.0, 0.0}, // (rs_hdr[idxRS]) IMET4: lpIQ=0 ... + { 9600, 0, 0, imet1rs_header, 0.5, 0.0, 0.80, 2, NULL, "IMET4", tn_IMET4, 1, 1, 0.0, 0.0}, // (rs_hdr[idxI4]) }; +static int idx_MTS01 = -1, + idx_C34C50 = -1, + idx_IMET1AB = -1; + /* // m10-false-positive: @@ -196,7 +210,7 @@ static ui32_t sample_in, sample_out, delay; static int M; -static float *buf_fm[3]; +static float *buf_fm[N_bwIQ]; static float *bufs = NULL; static char *rawbits = NULL; @@ -232,7 +246,7 @@ static int dsp__lpFMtaps; // ui32_t static float complex *Y; static float complex *WS[2]; // IF: lowpass -static float *ws_lpIQ[2]; +static float *ws_lpIQ[N_bwIQ]; // only N_bwIQ-1 used static int dsp__lpIQtaps; // ui32_t static float complex *lpIQ_buf; @@ -681,11 +695,12 @@ static float complex lowpass2(float complex buffer[], ui32_t sample, ui32_t taps static int f32buf_sample(FILE *fp, int inv) { float _s = 0.0; - float s[3]; + float s[N_bwIQ]; static float complex z0_fm0; static float complex z0_fm1; + static float complex z0_fm2; static float complex z0; - float complex z_fm0=0, z_fm1=0; + float complex z_fm0=0, z_fm1=0, z_fm2=0; float complex z, w; double gain = FM_GAIN; int i; @@ -708,11 +723,12 @@ static int f32buf_sample(FILE *fp, int inv) { // IF-lowpass // a) detect signal bandwidth/center-fq (not reliable), or - // b) 3 FM-streams + // b) N_bwIQ FM-streams // lpIQ_buf[sample_in % dsp__lpIQtaps] = z; z_fm0 = lowpass(lpIQ_buf, sample_in+1, dsp__lpIQtaps, ws_lpIQ[0]); z_fm1 = lowpass(lpIQ_buf, sample_in+1, dsp__lpIQtaps, ws_lpIQ[1]); + z_fm2 = lowpass(lpIQ_buf, sample_in+1, dsp__lpIQtaps, ws_lpIQ[2]); // IQ: different modulation indices h=h(rs) -> FM-demod w = z_fm0 * conj(z0_fm0); @@ -723,17 +739,21 @@ static int f32buf_sample(FILE *fp, int inv) { s[1] = gain * carg(w)/M_PI; z0_fm1 = z_fm1; - w = z * conj(z0); + w = z_fm2 * conj(z0_fm2); s[2] = gain * carg(w)/M_PI; + z0_fm2 = z_fm2; + + w = z * conj(z0); + s[3] = gain * carg(w)/M_PI; z0 = z; } else { if (f32read_sample(fp, &_s) == EOF) return EOF; - for (i = 0; i < 3; i++) s[i] = _s; + for (i = 0; i < N_bwIQ; i++) s[i] = _s; } - for (i = 0; i < 3; i++) { + for (i = 0; i < N_bwIQ; i++) { if (inv) s[i]= -s[i]; buf_fm[i][sample_in % M] = s[i]; } @@ -1052,14 +1072,18 @@ static int init_buffers() { if (set_lpIQ > 100.0) { // set_lpIQ > 100Hz: overwrite lpIQ_bw[] lpIQ_bw[0] = set_lpIQ; lpIQ_bw[1] = set_lpIQ; + lpIQ_bw[2] = set_lpIQ; } // - f_lp = lpIQ_bw[0]/(float)sample_rate/2.0; // RS41,DFM: 12kHz (IF/IQ) + f_lp = lpIQ_bw[0]/(float)sample_rate/2.0; // MTS01: 6kHz (IF/IQ) taps = lowpass_init(f_lp, taps, &ws_lpIQ[0]); if (taps < 0) return -1; // - f_lp = lpIQ_bw[1]/(float)sample_rate/2.0; // M10: 22kHz (IF/IQ) + f_lp = lpIQ_bw[1]/(float)sample_rate/2.0; // RS41,DFM: 12kHz (IF/IQ) taps = lowpass_init(f_lp, taps, &ws_lpIQ[1]); if (taps < 0) return -1; // + f_lp = lpIQ_bw[2]/(float)sample_rate/2.0; // M10: 22kHz (IF/IQ) + taps = lowpass_init(f_lp, taps, &ws_lpIQ[2]); if (taps < 0) return -1; + // dsp__lpIQtaps = taps; lpIQ_buf = calloc( dsp__lpIQtaps+3, sizeof(float complex)); if (lpIQ_buf == NULL) return -1; @@ -1071,12 +1095,26 @@ static int init_buffers() { if (dsp__decM > 1) IQdc.maxcnt *= dsp__decM; + for (j = 0; j < Nrs; j++) { + #ifdef NOMTS01 + if ( strncmp(rs_hdr[j].type, "MTS01", 5) == 0 ) idx_MTS01 = j; + #endif + #ifdef NOC34C50 + if ( strncmp(rs_hdr[j].type, "C34C50", 6) == 0 ) idx_C34C50 = j; + #endif + #ifdef NOIMET1AB + if ( strncmp(rs_hdr[j].type, "IMET1AB", 7) == 0 ) idx_IMET1AB = j; + #endif + } + for (j = 0; j < Nrs; j++) { rs_hdr[j].spb = sample_rate/(float)rs_hdr[j].sps; rs_hdr[j].hLen = strlen(rs_hdr[j].header); rs_hdr[j].L = rs_hdr[j].hLen * rs_hdr[j].spb + 0.5; - if (rs_hdr[j].hLen > hLen) hLen = rs_hdr[j].hLen; - if (rs_hdr[j].L > Lmax) Lmax = rs_hdr[j].L; + if (j != idx_MTS01 && j != idx_C34C50 && j != idx_IMET1AB) { + if (rs_hdr[j].hLen > hLen) hLen = rs_hdr[j].hLen; + if (rs_hdr[j].L > Lmax) Lmax = rs_hdr[j].L; + } } // L = hLen * sample_rate/2500.0 + 0.5; // max(hLen*spb) @@ -1100,10 +1138,10 @@ static int init_buffers() { rawbits = (char *)calloc( hLen+1, sizeof(char)); if (rawbits == NULL) return -100; - for (j = 0; j < 3; j++) { + for (j = 0; j < N_bwIQ; j++) { buf_fm[j] = (float *)calloc( M+1, sizeof(float)); if (buf_fm[j] == NULL) return -100; } - bufs = buf_fm[2]; + bufs = buf_fm[N_bwIQ-1]; xn = calloc(N_DFT+1, sizeof(float)); if (xn == NULL) return -1; @@ -1184,7 +1222,7 @@ static int init_buffers() { static int free_buffers() { int j; - for (j = 0; j < 3; j++) { + for (j = 0; j < N_bwIQ; j++) { if (buf_fm[j]) { free(buf_fm[j]); buf_fm[j] = NULL; } } @@ -1219,7 +1257,7 @@ static int free_buffers() { } if (Y) { free(Y); Y = NULL; } - for (j = 0; j < 1; j++) { + for (j = 0; j < N_bwIQ-1; j++) { if (ws_lpIQ[j]) { free(ws_lpIQ[j]); ws_lpIQ[j] = NULL; } } if (lpIQ_buf) { free(lpIQ_buf); lpIQ_buf = NULL; } @@ -1297,9 +1335,10 @@ int main(int argc, char **argv) { } else if ( (strcmp(*argv, "-L") == 0) ) { // L-band 1680kHz (IQ: decimation not limited) - lpIQ_bw[0] = 32e3; - lpIQ_bw[1] = 200e3; - lpIQ_bw[2] = 400e3; + lpIQ_bw[0] = 20e3; + lpIQ_bw[1] = 32e3; + lpIQ_bw[2] = 200e3; + lpIQ_bw[3] = 400e3; } else if ( (strcmp(*argv, "-c") == 0) || (strcmp(*argv, "--cnt") == 0) ) { option_cont = 1; @@ -1385,9 +1424,9 @@ int main(int argc, char **argv) { if (k >= K-4) { for (j = 0; j <= idxIMETafsk; j++) { // incl. IMET-preamble - #ifdef NOC34C50 - if ( strncmp(rs_hdr[j].type, "C34C50", 6) == 0 ) continue; - #endif + if ( j == idx_MTS01 ) continue; // only ifdef NOMTS01 + if ( j == idx_C34C50 ) continue; // only ifdef NOC34C50 + if ( j == idx_IMET1AB ) continue; // only ifdef NOIMET1AB mv0_pos[j] = mv_pos[j]; mp[j] = getCorrDFT(K, 0, mv+j, mv_pos+j, rs_hdr+j);