From 3f1b8ff7367cb93eb8e42b206cd0d1ae65afbd1b Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Wed, 5 Jul 2023 14:27:25 -0400 Subject: [PATCH] M17 Initial Support (Non-Working State); --- include/dsd.h | 19 ++++++- src/dsd_dibit.c | 9 ++-- src/dsd_frame.c | 8 +++ src/dsd_frame_sync.c | 123 ++++++++++++++++++++++++++++++++----------- src/dsd_main.c | 81 +++++++++++++++++++++++----- 5 files changed, 189 insertions(+), 51 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index c30b2ab..4063985 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -309,6 +309,9 @@ typedef struct int inverted_ysf; short int aggressive_framesync; + int frame_m17; + int inverted_m17; + FILE *symbolfile; int call_alert; @@ -720,14 +723,25 @@ typedef struct char ysf_rm4[6]; char ysf_txt[21][21]; //text storage blocks + //M17 Storage + uint8_t m17_lsf_err[6]; //golay segment FEC validity + uint8_t m17_lsf[280]; + } dsd_state; /* * Frame sync patterns */ -#define FUSION_SYNC "31111311313113131131" //HA! -#define INV_FUSION_SYNC "13333133131331313313" //HA! +//The inverse of LSF also seems to be Stream Frame Type, only going to work on Stream mode for now +// #define M17_LSF_PRE "1311113313" +#define M17_LSF "11113313" //"11113313" +#define M17_STR "33331131" //"33331131" +// #define M17_BRT "31331111" +// #define M17_PKT "13113333" + +#define FUSION_SYNC "31111311313113131131" +#define INV_FUSION_SYNC "13333133131331313313" #define INV_P25P1_SYNC "333331331133111131311111" #define P25P1_SYNC "111113113311333313133333" @@ -893,6 +907,7 @@ void processX2TDMAdata (dsd_opts * opts, dsd_state * state); void processX2TDMAvoice (dsd_opts * opts, dsd_state * state); void processDSTAR_HD (dsd_opts * opts, dsd_state * state); void processYSF(dsd_opts * opts, dsd_state * state); //YSF +void processM17(dsd_opts * opts, dsd_state * state); //M17 void processP2(dsd_opts * opts, dsd_state * state); //P2 void processTSBK(dsd_opts * opts, dsd_state * state); //P25 Trunking Single Block void processMPDU(dsd_opts * opts, dsd_state * state); //P25 Multi Block PDU (SAP 0x61 FMT 0x15 or 0x17 for Trunking Blocks) diff --git a/src/dsd_dibit.c b/src/dsd_dibit.c index d7a9705..e1fd90a 100644 --- a/src/dsd_dibit.c +++ b/src/dsd_dibit.c @@ -265,15 +265,16 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) else if ((state->synctype == 1) || (state->synctype == 3) || (state->synctype == 5) || (state->synctype == 31) || (state->synctype == 11) || (state->synctype == 13) || - (state->synctype == 17) || (state->synctype == 29) || (state->synctype == 36) ) + (state->synctype == 17) || (state->synctype == 29) || (state->synctype == 36) || (state->synctype == 16) ) { // 1 -P25p1 // 3 -X2-TDMA (inverted signal voice frame) // 5 -X2-TDMA (inverted signal data frame) + // 9 -M17 LSR // 11 -DMR (inverted signal voice frame) // 13 -DMR (inverted signal data frame) - // 17 -NXDN (inverted data frame) + // 17 -M17 STR // 29 -NXDN (inverted FSW) // 31 -YSF // 36 -P25p2 @@ -335,10 +336,10 @@ static int digitize (dsd_opts* opts, dsd_state* state, int symbol) // 0 +P25p1 // 2 +X2-TDMA (non inverted signal data frame) // 4 +X2-TDMA (non inverted signal voice frame) - // 8 +NXDN (non inverted voice frame) + // 8 +M17 LSF // 10 +DMR (non inverted signal data frame) // 12 +DMR (non inverted signal voice frame) - // 16 +NXDN (non inverted data frame) + // 16 +M17 STR // 28 +NXND (FSW) // 30 +YSF // 35 +p25p2 diff --git a/src/dsd_frame.c b/src/dsd_frame.c index 324d339..6b35e63 100644 --- a/src/dsd_frame.c +++ b/src/dsd_frame.c @@ -294,6 +294,14 @@ processFrame (dsd_opts * opts, dsd_state * state) processYSF(opts, state); return; } + //M17 + else if ((state->synctype == 16) || (state->synctype == 9) || (state->synctype == 17) || (state->synctype == 8) ) + { + // processM17(opts, state); //disabled until more work can be done + skipDibit(opts, state, 184); + fprintf (stderr, "\n"); + return; + } //P25 P2 else if ((state->synctype == 35) || (state->synctype == 36)) { diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index be8ed58..0cf8ca4 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -114,16 +114,16 @@ getFrameSync (dsd_opts * opts, dsd_state * state) * 5 = -X2-TDMA (inverted signal data frame) * 6 = +D-STAR * 7 = -D-STAR - * 8 = +NXDN (non inverted voice frame) - * 9 = -NXDN (inverted voice frame) + * 8 = +M17 STR (non inverted stream frame) + * 9 = -M17 STR (inverted stream frame) * 10 = +DMR (non inverted signal data frame) * 11 = -DMR (inverted signal voice frame) * 12 = +DMR (non inverted signal voice frame) * 13 = -DMR (inverted signal data frame) * 14 = +ProVoice * 15 = -ProVoice - * 16 = +NXDN (non inverted data frame) - * 17 = -NXDN (inverted data frame) + * 16 = +M17 LSF (non inverted link frame) + * 17 = -M17 LSF (inverted link frame) * 18 = +D-STAR_HD * 19 = -D-STAR_HD * 20 = +dPMR Frame Sync 1 @@ -215,6 +215,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) char synctest20[21]; //YSF char synctest21[22]; //P25 S-OEMI (SACCH) char synctest48[49]; //EDACS + char synctest8[9]; //M17 char modulation[8]; char *synctest_p; int symboltest_pos; //symbol test position, match to synctest_pos @@ -233,6 +234,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) { t_max = 12; //based on Frame_Sync_2 pattern } + else if (opts->frame_m17 == 1) + { + t_max = 8; //pfffffft....why (test with multiples of 8?) (might be an idea to do t_max *= 5 or something...for tests) + } else if (state->lastsynctype == 30 || state->lastsynctype == 31 ) { t_max = 20; //20 on YSF @@ -578,42 +583,96 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } //YSF sync strncpy(synctest20, (synctest_p - 19), 20); - if(opts->frame_ysf == 1) //(opts->frame_ysf == 1 + if(opts->frame_ysf == 1) { - if (0 == 0) //opts->inverted_ysf == 0 + if (strcmp(synctest20, FUSION_SYNC) == 0) { - if (strcmp(synctest20, FUSION_SYNC) == 0) - { - printFrameSync (opts, state, "+YSF ", synctest_pos + 1, modulation); - state->carrier = 1; - state->offset = synctest_pos; - state->max = ((state->max) + lmax) / 2; - state->min = ((state->min) + lmin) / 2; - opts->inverted_ysf = 0; - state->lastsynctype = 30; - return (30); - } + printFrameSync (opts, state, "+YSF ", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + opts->inverted_ysf = 0; + state->lastsynctype = 30; + return (30); } - } - if(opts->frame_ysf == 1) //(opts->frame_ysf == 1 - { - if (0 == 0) //opts->inverted_ysf == 1 + else if (strcmp(synctest20, INV_FUSION_SYNC) == 0) { - if (strcmp(synctest20, INV_FUSION_SYNC) == 0) - { - printFrameSync (opts, state, "-YSF ", synctest_pos + 1, modulation); - state->carrier = 1; - state->offset = synctest_pos; - state->max = ((state->max) + lmax) / 2; - state->min = ((state->min) + lmin) / 2; - opts->inverted_ysf = 1; - state->lastsynctype = 31; - return (31); - } + printFrameSync (opts, state, "-YSF ", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + opts->inverted_ysf = 1; + state->lastsynctype = 31; + return (31); } } //end YSF sync + //M17 Sync -- Just Voice and LSF for now + strncpy(synctest8, (synctest_p - 7), 8); + if(opts->frame_m17 == 1) + { + //may need to try the contents of this frame much like NXDN, only + //printFrameSync after good LICH validation etc + if (strcmp(synctest8, M17_STR) == 0) + { + if (opts->inverted_m17 == 0) + { + printFrameSync (opts, state, "+M17 STR", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->lastsynctype == 16) + return (16); //reusing some of those old NXDN returns + state->lastsynctype = 16; + fprintf (stderr, "\n"); + } + else + { + printFrameSync (opts, state, "-M17 LSF", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->lastsynctype == 9) + return (9); //reusing some of those old NXDN returns + state->lastsynctype = 9; + fprintf (stderr, "\n"); + } + } + else if (strcmp(synctest8, M17_LSF) == 0) + { + if (opts->inverted_m17 == 1) + { + printFrameSync (opts, state, "-M17 STR", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->lastsynctype == 17) + return (17); //reusing some of those old NXDN returns + state->lastsynctype = 17; + fprintf (stderr, "\n"); + } + else + { + printFrameSync (opts, state, "+M17 LSF", synctest_pos + 1, modulation); + state->carrier = 1; + state->offset = synctest_pos; + state->max = ((state->max) + lmax) / 2; + state->min = ((state->min) + lmin) / 2; + if (state->lastsynctype == 8) + return (8); //reusing some of those old NXDN returns + state->lastsynctype = 8; + fprintf (stderr, "\n"); + } + } + } + //end M17 + //P25 P2 sync S-ISCH VCH strncpy(synctest20, (synctest_p - 19), 20); if(opts->frame_p25p2 == 1) diff --git a/src/dsd_main.c b/src/dsd_main.c index e4723c2..dc476f3 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -461,6 +461,10 @@ noCarrier (dsd_opts * opts, dsd_state * state) state->ysf_fi = 9; state->ysf_cm = 9; + //M17 Storage + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); + memset (state->m17_lsf_err, 0, sizeof(state->m17_lsf_err)); + } //nocarrier void @@ -537,12 +541,14 @@ initOpts (dsd_opts * opts) opts->frame_dpmr = 0; opts->frame_provoice = 0; opts->frame_ysf = 1; + opts->frame_m17 = 0; opts->mod_c4fm = 1; opts->mod_qpsk = 0; opts->mod_gfsk = 0; opts->uvquality = 3; opts->inverted_x2tdma = 1; // most transmitter + scanner + sound card combinations show inverted signals for this opts->inverted_dmr = 0; // most transmitter + scanner + sound card combinations show non-inverted signals for this + opts->inverted_m17 = 0; opts->mod_threshold = 26; opts->ssize = 128; //36 default, max is 128, much cleaner data decodes on Phase 2 cqpsk at max opts->msize = 1024; //15 default, max is 1024, much cleaner data decodes on Phase 2 cqpsk at max @@ -1041,6 +1047,9 @@ initState (dsd_state * state) state->ysf_fi = 9; state->ysf_cm = 9; + //M17 Storage + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); + memset (state->m17_lsf_err, 0, sizeof(state->m17_lsf_err)); } //init_state @@ -1127,6 +1136,7 @@ usage () printf (" -fd Decode only D-STAR\n"); printf (" -fx Decode only X2-TDMA\n"); printf (" -fy Decode only YSF\n"); + printf (" -fz Decode only M17*(not working)\n"); printf (" -fi Decode only NXDN48* (6.25 kHz) / IDAS*\n"); printf (" -fn Decode only NXDN96* (12.5 kHz)\n"); printf (" -fp Decode only EDACS/ProVoice*\n"); @@ -1136,6 +1146,7 @@ usage () printf (" -xx Expect non-inverted X2-TDMA signal\n"); printf (" -xr Expect inverted DMR signal\n"); printf (" -xd Expect inverted ICOM dPMR signal\n"); + printf (" -xz Expect inverted M17 signal\n"); printf ("\n"); printf (" * denotes frame types that cannot be auto-detected.\n"); printf (" ** Phase 2 Single Frequency may require user to manually set WACN/SYSID/CC parameters if MAC_SIGNAL not present.\n"); @@ -1775,6 +1786,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 1; + opts.frame_m17 = 0; opts.pulse_digi_rate_out = 48000; // /dev/dsp does need this set to 48000 to properly process the upsampling opts.pulse_digi_out_channels = 1; opts.dmr_stereo = 0; //switching in 'stereo' for 'mono' @@ -1795,6 +1807,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.pulse_digi_rate_out = 48000; opts.pulse_digi_out_channels = 1; opts.dmr_stereo = 0; @@ -1816,6 +1829,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.pulse_digi_rate_out = 48000; opts.pulse_digi_out_channels = 1; opts.dmr_stereo = 0; @@ -1836,6 +1850,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 1; opts.frame_ysf = 0; + opts.frame_m17 = 0; state.samplesPerSymbol = 5; state.symbolCenter = 2; opts.mod_c4fm = 0; @@ -1867,6 +1882,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.dmr_stereo = 0; state.dmr_stereo = 0; opts.mod_c4fm = 1; @@ -1896,6 +1912,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; state.samplesPerSymbol = 20; state.symbolCenter = 10; opts.mod_c4fm = 1; @@ -1925,6 +1942,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 1; + opts.frame_m17 = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; opts.mod_gfsk = 0; @@ -1949,6 +1967,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; state.samplesPerSymbol = 8; state.symbolCenter = 3; opts.mod_c4fm = 1; @@ -1975,6 +1994,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; opts.mod_gfsk = 0; @@ -2001,6 +2021,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 1; + opts.frame_m17 = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; opts.mod_gfsk = 0; @@ -2027,6 +2048,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; opts.mod_gfsk = 0; @@ -2052,6 +2074,7 @@ main (int argc, char **argv) opts.frame_dpmr = 0; opts.frame_provoice = 0; opts.frame_ysf = 0; + opts.frame_m17 = 0; opts.mod_c4fm = 1; opts.mod_qpsk = 0; opts.mod_gfsk = 0; // @@ -2078,7 +2101,8 @@ main (int argc, char **argv) opts.frame_dmr = 0; opts.frame_provoice = 0; opts.frame_dpmr = 1; - opts.frame_ysf = 0; //testing with NXDN48 parameters + opts.frame_ysf = 0; + opts.frame_m17 = 0; state.samplesPerSymbol = 20; //same as NXDN48 - 20 state.symbolCenter = 10; //same as NXDN48 - 10 opts.mod_c4fm = 1; @@ -2094,6 +2118,32 @@ main (int argc, char **argv) fprintf(stderr, "Notice: dPMR cannot autodetect polarity. \n Use -xd option if Inverted Signal expected.\n"); fprintf(stderr, "Decoding only dPMR frames.\n"); } + else if (optarg[0] == 'z') //placeholder letter + { + opts.frame_dstar = 0; + opts.frame_x2tdma = 0; + opts.frame_p25p1 = 0; + opts.frame_p25p2 = 0; + opts.frame_nxdn48 = 0; + opts.frame_nxdn96 = 0; + opts.frame_dmr = 0; + opts.frame_provoice = 0; + opts.frame_dpmr = 0; + opts.frame_ysf = 0; + opts.frame_m17 = 1; + opts.mod_c4fm = 1; + opts.mod_qpsk = 0; + opts.mod_gfsk = 0; + state.rf_mod = 0; + opts.pulse_digi_rate_out = 8000; + opts.pulse_digi_out_channels = 1; + opts.dmr_stereo = 0; + opts.dmr_mono = 0; + state.dmr_stereo = 0; + sprintf (opts.output_name, "M17"); + fprintf(stderr, "Notice: M17 cannot autodetect polarity. \n Use -xz option if Inverted Signal expected.\n"); + fprintf(stderr, "Decoding only M17 frames.(Not Working)\n"); + } break; //don't mess with the modulations unless you really need to case 'm': @@ -2179,20 +2229,25 @@ main (int argc, char **argv) break; case 'x': if (optarg[0] == 'x') - { - opts.inverted_x2tdma = 0; - fprintf (stderr,"Expecting non-inverted X2-TDMA signals.\n"); - } + { + opts.inverted_x2tdma = 0; + fprintf (stderr,"Expecting non-inverted X2-TDMA signals.\n"); + } else if (optarg[0] == 'r') - { - opts.inverted_dmr = 1; - fprintf (stderr,"Expecting inverted DMR signals.\n"); - } + { + opts.inverted_dmr = 1; + fprintf (stderr,"Expecting inverted DMR signals.\n"); + } else if (optarg[0] == 'd') - { - opts.inverted_dpmr = 1; - fprintf (stderr, "Expecting inverted ICOM dPMR signals.\n"); - } + { + opts.inverted_dpmr = 1; + fprintf (stderr, "Expecting inverted ICOM dPMR signals.\n"); + } + else if (optarg[0] == 'z') + { + opts.inverted_m17 = 1; + fprintf (stderr, "Expecting inverted M17 signals.\n"); + } break; case 'A': sscanf (optarg, "%i", &opts.mod_threshold);