From 3ae1292e634ea2ea70378e6c2e323d76e852a15d Mon Sep 17 00:00:00 2001 From: Zilog80 Date: Sun, 13 Nov 2022 22:53:23 +0100 Subject: [PATCH] dft_detect: add Meteosis MTS01 (cf. test) --- scan/dft_detect.c | 144 +++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 46 deletions(-) diff --git a/scan/dft_detect.c b/scan/dft_detect.c index 65b2646..3198971 100644 --- a/scan/dft_detect.c +++ b/scan/dft_detect.c @@ -33,6 +33,7 @@ static int option_verbose = 0, // ausfuehrliche Anzeige option_silent = 0, option_cont = 0, option_pcmraw = 0, + option_singleLpIQ = 0, wavloaded = 0; static int wav_channel = 0; // audio channel: left @@ -75,6 +76,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 +129,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 +142,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 +151,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]) + { 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, 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]) + { 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 +211,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 +247,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 +696,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,32 +724,48 @@ 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]); - + if (option_singleLpIQ) { + z_fm1 = z_fm0; + z_fm2 = z_fm0; + } + else { + 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); s[0] = gain * carg(w)/M_PI; z0_fm0 = z_fm0; - w = z_fm1 * conj(z0_fm1); - s[1] = gain * carg(w)/M_PI; - z0_fm1 = z_fm1; + if (option_singleLpIQ) { + s[1] = s[0]; z0_fm1 = z_fm1; + s[2] = s[0]; z0_fm2 = z_fm2; + } + else { + w = z_fm1 * conj(z0_fm1); + s[1] = gain * carg(w)/M_PI; + z0_fm1 = z_fm1; + + w = z_fm2 * conj(z0_fm2); + s[2] = gain * carg(w)/M_PI; + z0_fm2 = z_fm2; + } w = z * conj(z0); - s[2] = gain * carg(w)/M_PI; + 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 +1084,19 @@ 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; + option_singleLpIQ = 1; } // - 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 +1108,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 +1151,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 +1235,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 +1270,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 +1348,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 +1437,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);