From 6c4584a00a444f38ea6f5b4c2b57e2da6c4a8ed6 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Tue, 12 Mar 2024 13:46:55 -0400 Subject: [PATCH] M17 - User CAN/DST/SRC and SMS at CLI; --- include/dsd.h | 5 +- src/dsd_main.c | 154 ++++++++++++++++++++++++++++++++++++------------- src/m17.c | 56 +++++++++++++++--- 3 files changed, 164 insertions(+), 51 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index 70ac975..3e70d55 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -784,7 +784,8 @@ typedef struct unsigned long long int m17_dst; unsigned long long int m17_src; - uint8_t m17_can; + uint8_t m17_can; //can value that was decoded from signal + uint8_t m17_can_en; //can value supplied to the encoding side char m17_dst_csd[20]; char m17_src_csd[20]; @@ -801,6 +802,8 @@ typedef struct //misc str storage char str50a[50]; char str50b[50]; + char m17dat[50]; //user supplied m17 data input string + char m17sms[800]; //user supplied sms text string //Codec2 #ifdef USE_CODEC2 diff --git a/src/dsd_main.c b/src/dsd_main.c index 9d0d7c9..ca89bde 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -495,14 +495,15 @@ noCarrier (dsd_opts * opts, dsd_state * state) sprintf (state->dstar_gps, "%s", " "); //8 spaces //M17 Storage - memset (state->m17_lsf, 1, sizeof(state->m17_lsf)); - memset (state->m17_pkt, 1, sizeof(state->m17_pkt)); + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); + memset (state->m17_pkt, 0, sizeof(state->m17_pkt)); state->m17_pbc_ct = 0; state->m17_str_dt = 9; state->m17_dst = 0; state->m17_src = 0; - state->m17_can = 0; + state->m17_can = 0; //can value that was decoded from signal + state->m17_can_en = 0; //can value supplied to the encoding side memset(state->m17_dst_csd, 0, sizeof(state->m17_dst_csd)); memset(state->m17_src_csd, 0, sizeof(state->m17_src_csd)); sprintf (state->m17_dst_str, "%s", ""); @@ -513,8 +514,10 @@ noCarrier (dsd_opts * opts, dsd_state * state) memset(state->m17_meta, 0, sizeof(state->m17_meta)); //misc str storage - sprintf (state->str50a, "%s", ""); - sprintf (state->str50b, "%s", ""); + memset (state->str50a, 0, 50*sizeof(char)); + memset (state->str50b, 0, 50*sizeof(char)); + memset (state->m17sms, 0, 800*sizeof(char)); + sprintf (state->m17dat, "%s", ""); //set float temp buffer to baseline memset (state->audio_out_temp_buf, 0.0f, sizeof(state->audio_out_temp_buf)); @@ -1171,8 +1174,8 @@ initState (dsd_state * state) sprintf (state->dstar_gps, "%s", " "); //8 spaces //M17 Storage - memset (state->m17_lsf, 1, sizeof(state->m17_lsf)); - memset (state->m17_pkt, 1, sizeof(state->m17_pkt)); + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); + memset (state->m17_pkt, 0, sizeof(state->m17_pkt)); state->m17_pbc_ct = 0; state->m17_str_dt = 9; @@ -1288,17 +1291,22 @@ usage () printf ("\n"); printf ("Encoder options:\n"); printf (" -fZ M17 Stream Voice Encoder\n"); - printf (" Example: dsd-fme -fZ -i pulse -6 m17signal.wav -N 2> m17encoderlog.ans\n"); + printf (" Example: dsd-fme -fZ -M M17:9:DSD-FME:LWVMOBILE -i pulse -6 m17signal.wav -N 2> m17encoderlog.ans\n"); printf (" Run M17 Encoding, listening to pulse audio server, with internal decode/playback and output to 48k/1 wav file\n"); printf ("\n"); - printf (" Example: dsd-fme -fZ -i tcp -8 -o pulse -N 2> m17encoderlog.ans\n"); + printf (" Example: dsd-fme -fZ -M M17:9:DSD-FME:LWVMOBILE -i tcp -8 -o pulse -N 2> m17encoderlog.ans\n"); printf (" Run M17 Encoding, listening to default tcp input, without internal decode/playback and output to 48k/1 analog output device\n"); printf ("\n"); - printf (" -fB M17 BERT Encoder\n"); - printf (" Example: dsd-fme -fB -6 m17bert.wav\n"); printf (" -fP M17 Packet Encoder\n"); - printf (" Example: dsd-fme -fP -6 m17pkt.wav (NOTE: WIP)\n"); + printf (" Example: dsd-fme -fP -M M17:9:DSD-FME:LWVMOBILE -6 m17pkt.wav -S 'Hello World'\n"); printf ("\n"); + printf (" -fB M17 BERT Encoder\n"); + printf (" Example: dsd-fme -fB -M M17:9:DSD-FME:LWVMOBILE -6 m17bert.wav\n"); + printf ("\n"); + printf (" -M M17 Encoding User Configuration String: M17:CAN:SRC:DST (see examples above).\n"); + printf (" CAN 1-15; SRC and DST have to be no more than 9 UPPER base40 characters\n"); + printf (" BASE40: ' ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.'\n"); + printf (" -S M17 Encoding Packet SMS String: No more than 772 chars, use single quotations (see example above).\n"); printf ("Decoder options:\n"); printf (" -fa Auto Detection\n"); printf (" -ft TDMA Trunking P25p1 Control and Voice, P25p2 Trunked Channels, and DMR\n"); @@ -1330,11 +1338,11 @@ usage () printf (" (Value defaults to max n bit value for site model size)\n"); printf (" (Setting 0 will show full Site ID, no area/subarea)\n"); printf ("\n"); - printf (" -A QPSK modulation auto detection threshold (default=26)\n"); - printf (" -S Symbol buffer size for QPSK decision point tracking\n"); - printf (" (default=36)\n"); - printf (" -M Min/Max buffer size for QPSK decision point tracking\n"); - printf (" (default=15)\n"); + // printf (" -A QPSK modulation auto detection threshold (default=26)\n"); + // printf (" -S Symbol buffer size for QPSK decision point tracking\n"); + // printf (" (default=36)\n"); + // printf (" -M Min/Max buffer size for QPSK decision point tracking\n"); + // printf (" (default=15)\n"); printf (" -ma Auto-select modulation optimizations\n"); printf (" -mc Use only C4FM modulation optimizations (default)\n"); printf (" -mg Use only GFSK modulation optimizations\n"); @@ -1642,6 +1650,19 @@ main (int argc, char **argv) //NOTE: The 'K' option for single BP key has been swapped to 'b' //'K' is now used for hexidecimal key.csv imports + //Specify M17 encoder User Data (CAN, DST, SRC values) + //NOTE: Disabled QPSK settings by borrowing these switches (nobody probalby used them anyways) + case 'M': + strncpy(state.m17dat, optarg, 49); + state.m17dat[49] = '\0'; + break; + + //Specify M17 encoder SMS Message (truncates at 772) + case 'S': + strncpy(state.m17sms, optarg, 772); + state.m17sms[772] = '\0'; + break; + //specify TG Hold value case 'I': sscanf (optarg, "%d", &state.tg_hold); @@ -2527,30 +2548,34 @@ main (int argc, char **argv) case 'A': sscanf (optarg, "%i", &opts.mod_threshold); fprintf (stderr,"Setting C4FM/QPSK auto detection threshold to %i\n", opts.mod_threshold); - case 'S': - sscanf (optarg, "%i", &opts.ssize); - if (opts.ssize > 128) - { - opts.ssize = 128; - } - else if (opts.ssize < 1) - { - opts.ssize = 1; - } - fprintf (stderr,"Setting QPSK symbol buffer to %i\n", opts.ssize); - break; - case 'M': - sscanf (optarg, "%i", &opts.msize); - if (opts.msize > 1024) - { - opts.msize = 1024; - } - else if (opts.msize < 1) - { - opts.msize = 1; - } - fprintf (stderr,"Setting QPSK Min/Max buffer to %i\n", opts.msize); - break; + break; //this was missing a break + + //Disabled and switches reassigned to M17 User Data Argumeents + // case 'S': //disabled, using for M17 encoder user SMS message + // sscanf (optarg, "%i", &opts.ssize); + // if (opts.ssize > 128) + // { + // opts.ssize = 128; + // } + // else if (opts.ssize < 1) + // { + // opts.ssize = 1; + // } + // fprintf (stderr,"Setting QPSK symbol buffer to %i\n", opts.ssize); + // break; + // case 'M': //disabled, using for M17 user data + // sscanf (optarg, "%i", &opts.msize); + // if (opts.msize > 1024) + // { + // opts.msize = 1024; + // } + // else if (opts.msize < 1) + // { + // opts.msize = 1; + // } + // fprintf (stderr,"Setting QPSK Min/Max buffer to %i\n", opts.msize); + // break; + case 'r': opts.playfiles = 1; opts.errorbars = 0; @@ -2949,6 +2974,53 @@ main (int argc, char **argv) signal(SIGINT, handler); signal(SIGTERM, handler); + //read in any user supplied M17 CAN and/or CSD data + if((strncmp(state.m17dat, "M17", 3) == 0)) + { + //read in values + //string in format of M17:can:src_csd:dst_csd + + fprintf (stderr, "M17 User Data: "); + char * curr; + + // if((strncmp(state.m17dat, "M17", 3) == 0)) + // goto M17END; + + curr = strtok(state.m17dat, ":"); //should be 'M17' + if (curr != NULL) ; //continue + else goto M17END; //end early with preset values + + curr = strtok(NULL, ":"); //m17 channel access number + if (curr != NULL) + state.m17_can_en = atoi(curr); + + curr = strtok(NULL, ":"); //m17 src address + if (curr != NULL) + { + strncpy (state.str50a, curr, 9); //only read first 9 + state.str50a[9] = '\0'; + } + + curr = strtok(NULL, ":"); //m17 dst address + if (curr != NULL) + { + strncpy (state.str50b, curr, 9); //only read first 9 + state.str50b[9] = '\0'; + } + + M17END: ; //do nothing + + //check to make sure can value is no greater than 15 (4 bit value) + if (state.m17_can_en > 15) + state.m17_can_en = 15; + + //debug print m17dat string + // fprintf (stderr, " %s;", state.m17dat); + + //debug print + fprintf (stderr, " M17:%d:%s:%s; \n ", state.m17_can_en, state.str50a, state.str50b); + } + if (opts.playfiles == 1) { diff --git a/src/m17.c b/src/m17.c index 5311e7b..b6486cd 100644 --- a/src/m17.c +++ b/src/m17.c @@ -301,7 +301,7 @@ int M17processLICH(dsd_state * state, dsd_opts * opts, uint8_t * lich_bits) } } - memset (state->m17_lsf, 1, sizeof(state->m17_lsf)); + memset (state->m17_lsf, 0, sizeof(state->m17_lsf)); //debug // fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp); @@ -1109,7 +1109,7 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type) //BRT frame sync pattern - 0xDF55 (-3, +3, -3, -3, +3, +3, +3, +3) uint8_t m17_brt_fs[16] = {1,1,0,1, 1,1,1,1, 0,1,0,1, 0,1,0,1}; - //load bits inti a dibit array plus the framesync bits + //load bits into a dibit array plus the framesync bits uint8_t output_dibits[192]; memset (output_dibits, 0, sizeof(output_dibits)); //Preamble (just repeat the preamble 12 times to make 192 symbols) @@ -1256,7 +1256,7 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type) sf_write_sync (opts->wav_out_raw); } - //NOTE: May need to disable the debug decoding when playing out real audio? Could lag/stutter. + //NOTE: Internal voice decoding is disabled when tx audio over a hardware device, wav/bin still enabled UNUSED(state); } @@ -1285,10 +1285,21 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) unsigned long long int dst = 0; unsigned long long int src = 0; //DST and SRC Callsign Data (pick up to 9 characters from the b40 char array) - char d40[] = "DSD-FME "; //DST - char s40[] = "DSD-FME "; //SRC + char d40[11] = "DSD-FME "; //DST + char s40[11] = "DSD-FME "; //SRC //end User Defined Variables + //configure User Defined Variables, if defined at CLI + if (state->m17_can_en != 0) //is 0 a valid number? + can = state->m17_can_en; + + if (state->str50a[0] != 0) + sprintf (s40, "%s", state->str50a); + + if (state->str50b[0] != 0) + sprintf (d40, "%s", state->str50b); + //end + int i, j, k, x; //basic utility counters short sample = 0; //individual audio sample from source size_t nsam = 160; //number of samples to be read in (default is for codec2 3200 bps) @@ -1856,7 +1867,7 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) //Contruct an IP frame using previously created arrays uint8_t m17_ip_frame[432]; memset (m17_ip_frame, 0, sizeof(m17_ip_frame)); uint8_t m17_ip_packed[54]; memset (m17_ip_packed, 0, sizeof(m17_ip_packed)); - uint16_t ip_crc = 0; UNUSED(ip_crc); + uint16_t ip_crc = 0; //NOTE: The Manual doesn't say much about this area, so assuming //the elements are arranged as per the table @@ -2234,8 +2245,8 @@ void encodeM17PKT(dsd_opts * opts, dsd_state * state) unsigned long long int dst = 0; unsigned long long int src = 0; //DST and SRC Callsign Data (pick up to 9 characters from the b40 char array) - char d40[] = "DSD-FME "; //DST - char s40[] = "DSD-FME "; //SRC + char d40[11] = "DSD-FME "; //DST + char s40[11] = "DSD-FME "; //SRC // dst = 0xEE6B28000000; //viterbi debug values // src = 0xEE6B28000000; //viterbi debug values @@ -2261,6 +2272,30 @@ void encodeM17PKT(dsd_opts * opts, dsd_state * state) //end User Defined Variables + //configure User Defined Variables, if defined at CLI + if (state->m17_can_en != 0) //is 0 a valid number? + can = state->m17_can_en; + + if (state->str50a[0] != 0) + sprintf (s40, "%s", state->str50a); + + if (state->str50b[0] != 0) + sprintf (d40, "%s", state->str50b); + + if (state->m17sms[0] != 0) + sprintf (text, "%s", state->m17sms); + + // switch to this if issues crop up (cygwin, etc) + // strncpy (s40, state->str50a, 9); + // strncpy (d40, state->str50b, 9); + // s40[10] = '\0'; + // d40[10] = '\0'; + + //debug + // fprintf (stderr, " SRC: %s; DST: %s; SRC_D: %llX; DST_D: %llX; SLEN %d; DLEN: %d;", s40, d40, src, dst, strlen(s40), strlen(d40) ); + + //end CLI Configuration + //send dead air with type 99 for (i = 0; i < 25; i++) encodeM17RF (opts, state, nil, 99); @@ -2323,6 +2358,9 @@ void encodeM17PKT(dsd_opts * opts, dsd_state * state) } //end CSD conversion + //debug + // fprintf (stderr, "\n SRC: %s; DST: %s; SRC_D: %llX; DST_D: %llX", s40, d40, src, dst); + //load dst and src values into the LSF for (i = 0; i < 48; i++) m17_lsf[i] = (dst >> 47ULL-(unsigned long long int)i) & 1; for (i = 0; i < 48; i++) m17_lsf[i+48] = (src >> 47ULL-(unsigned long long int)i) & 1; @@ -2788,7 +2826,7 @@ void processM17PKT(dsd_opts * opts, dsd_state * state) } //reset after processing - memset (state->m17_pkt, 1, sizeof(state->m17_pkt)); + memset (state->m17_pkt, 0, sizeof(state->m17_pkt)); state->m17_pbc_ct = 0; }