From c5742350d141d023b39c25341647df76ba7b2a3f Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 6 Apr 2024 22:45:13 -0400 Subject: [PATCH] M17: Use 3200 or 1600 Voice in STR Encoder; 1600 Arbitrary Data Encoder / Decoder; --- include/dsd.h | 1 + src/dsd_main.c | 4 +- src/m17.c | 148 ++++++++++++++++++++++++++++++++++--------------- 3 files changed, 106 insertions(+), 47 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index cf87d51..74c4b1a 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -1101,6 +1101,7 @@ void processM17LSF(dsd_opts * opts, dsd_state * state); //M17 (LSF) void encodeM17STR(dsd_opts * opts, dsd_state * state); //M17 (STR) encoder void encodeM17BRT(dsd_opts * opts, dsd_state * state); //M17 (BRT) encoder void encodeM17PKT(dsd_opts * opts, dsd_state * state); //M17 (PKT) encoder +void decodeM17PKT(dsd_opts * opts, dsd_state * state, uint8_t * input, int len); //M17 (PKT) decoder 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_main.c b/src/dsd_main.c index 2328569..7f44171 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1347,7 +1347,8 @@ usage () printf (" BASE40: ' ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.'\n"); printf (" Input Rate Default is 48000; Use Multiples of 8000 up to 48000.\n"); printf (" Values not entered into the M17: string are set to default values.\n"); - printf (" -S M17 Encoding Packet SMS String: No more than 772 chars, use single quotations (see example above).\n"); + printf (" -S M17 Packet Encoder SMS String: No more than 772 chars, use single quotations (see example above).\n"); + printf (" -S M17 Stream Encoder SMS String: No more than 48 chars, activates 1600 voice (best if broken into six 8 char chunks).\n"); printf ("Decoder options:\n"); printf (" -fa Auto Detection\n"); printf (" -fA Passive Analog Audio Monitor\n"); @@ -1710,6 +1711,7 @@ main (int argc, char **argv) case 'S': strncpy(state.m17sms, optarg, 772); state.m17sms[772] = '\0'; + state.m17_str_dt = 3; //flip this so that STR encoder knows to use 1600 voice + data break; //specify TG Hold value diff --git a/src/m17.c b/src/m17.c index bf0e2e8..6397c4d 100644 --- a/src/m17.c +++ b/src/m17.c @@ -419,6 +419,14 @@ void M17processCodec2_1600(dsd_opts * opts, dsd_state * state, uint8_t * payload #endif + //handle arbitrary data + uint8_t adata[9]; adata[0] = 99; //set so pkt decoder will rip these out as just utf-8 chars + for (i = 0; i < 8; i++) + adata[i+1] = (unsigned char)ConvertBitIntoBytes(&payload[i*8+64], 8); + + fprintf (stderr, "\n"); //linebreak + decodeM17PKT (opts, state, adata, 9); //decode Arbitrary Data as UTF-8 + } void M17processCodec2_3200(dsd_opts * opts, dsd_state * state, uint8_t * payload) @@ -1463,6 +1471,11 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type) void encodeM17STR(dsd_opts * opts, dsd_state * state) { + //set stream type value here so we can change 3200 or 1600 accordingly + uint8_t st = 2; //stream type: 0 = res; 1 = data; 2 = voice(3200); 3 = voice(1600) + data; + if (state->m17_str_dt == 3) st = 3; //this is flagged on IF -S user text string is called at CLI + else st = 2; //otherwise, just use 1600 voice (if data is required, using PKT mode is probably preferred over Stream Data) + //WIP: IP Frame Things and User Variables for Reflectors, etc uint8_t nil[368]; //empty array to send to RF during Preamble, EOT Marker, or Dead Air memset (nil, 0, sizeof(nil)); @@ -1580,7 +1593,11 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) // fprintf (stderr, " %02X", nonce[i]); #ifdef USE_CODEC2 - nsam = codec2_samples_per_frame(state->codec2_3200); + if (st == 2) + nsam = codec2_samples_per_frame(state->codec2_3200); + else if (st == 3) + nsam = codec2_samples_per_frame(state->codec2_1600); + else nsam = 320; //safety default #endif short * samp1 = malloc (sizeof(short) * nsam); @@ -1603,7 +1620,7 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) //NOTE: Most lich and lsf_chunk bits can be pre-set before the while loop, //only need to refresh the lich_cnt value, nonce, and golay uint16_t lsf_ps = 1; //packet or stream indicator bit - uint16_t lsf_dt = 2; //voice (3200bps) + uint16_t lsf_dt = st; //stream type uint16_t lsf_et = 0; //encryption type uint16_t lsf_es = 0; //encryption sub-type uint16_t lsf_cn = can; //can value @@ -1812,11 +1829,14 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) voice1[i] = sample; //only store the 6th sample } - for (i = 0; i < nsam; i++) + if (st == 2) { - for (j = 0; j < dec; j++) - pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL ); - voice2[i] = sample; //only store the 6th sample + for (i = 0; i < nsam; i++) + { + for (j = 0; j < dec; j++) + pa_simple_read(opts->pulse_digi_dev_in, &sample, 2, NULL ); + voice2[i] = sample; //only store the 6th sample + } } } @@ -1838,18 +1858,21 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) } } - for (i = 0; i < nsam; i++) + if (st == 2) { - for (j = 0; j < dec; j++) - result = sf_read_short(opts->audio_in_file, &sample, 1); - voice2[i] = sample; - if (result == 0) + for (i = 0; i < nsam; i++) { - sf_close(opts->audio_in_file); - fprintf (stderr, "Connection to STDIN Disconnected.\n"); - fprintf (stderr, "Closing DSD-FME.\n"); - exitflag = 1; - break; + for (j = 0; j < dec; j++) + result = sf_read_short(opts->audio_in_file, &sample, 1); + voice2[i] = sample; + if (result == 0) + { + sf_close(opts->audio_in_file); + fprintf (stderr, "Connection to STDIN Disconnected.\n"); + fprintf (stderr, "Closing DSD-FME.\n"); + exitflag = 1; + break; + } } } } @@ -1863,11 +1886,14 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) voice1[i] = sample; } - for (i = 0; i < nsam; i++) + if (st == 2) { - for (j = 0; j < dec; j++) - read (opts->audio_in_fd, &sample, 2); - voice2[i] = sample; + for (i = 0; i < nsam; i++) + { + for (j = 0; j < dec; j++) + read (opts->audio_in_fd, &sample, 2); + voice2[i] = sample; + } } } @@ -1889,18 +1915,21 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) } } - for (i = 0; i < nsam; i++) + if (st == 2) { - for (j = 0; j < dec; j++) - result = sf_read_short(opts->tcp_file_in, &sample, 1); - voice2[i] = sample; - if (result == 0) + for (i = 0; i < nsam; i++) { - sf_close(opts->tcp_file_in); - fprintf (stderr, "Connection to TCP Server Disconnected.\n"); - fprintf (stderr, "Closing DSD-FME.\n"); - exitflag = 1; - break; + for (j = 0; j < dec; j++) + result = sf_read_short(opts->tcp_file_in, &sample, 1); + voice2[i] = sample; + if (result == 0) + { + sf_close(opts->tcp_file_in); + fprintf (stderr, "Connection to TCP Server Disconnected.\n"); + fprintf (stderr, "Closing DSD-FME.\n"); + exitflag = 1; + break; + } } } } @@ -1917,15 +1946,18 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) voice1[i] = sample; } - for (i = 0; i < nsam; i++) + if (st == 2) { - for (j = 0; j < dec; j++) - if (get_rtlsdr_sample(&sample, opts, state) < 0) - cleanupAndExit(opts, state); - sample *= opts->rtl_volume_multiplier; - voice2[i] = sample; + for (i = 0; i < nsam; i++) + { + for (j = 0; j < dec; j++) + if (get_rtlsdr_sample(&sample, opts, state) < 0) + cleanupAndExit(opts, state); + sample *= opts->rtl_volume_multiplier; + voice2[i] = sample; + } } - + #endif } @@ -1937,35 +1969,40 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) if (opts->use_lpf == 1) { lpf (state, voice1, 160); - lpf (state, voice2, 160); + if (st == 2) + lpf (state, voice2, 160); } //high pass filter if (opts->use_hpf == 1) { hpf (state, voice1, 160); - hpf (state, voice2, 160); + if (st == 2) + hpf (state, voice2, 160); } //passband filter if (opts->use_pbf == 1) { pbf (state, voice1, 160); - pbf (state, voice2, 160); + if (st == 2) + pbf (state, voice2, 160); } //manual gain control if (opts->audio_gainA > 0.0f) { analog_gain (opts, state, voice1, 160); - analog_gain (opts, state, voice2, 160); + if (st == 2) + analog_gain (opts, state, voice2, 160); } //automatic gain control else { agsm (opts, state, voice1, 160); - agsm (opts, state, voice2, 160); + if (st == 2) + agsm (opts, state, voice2, 160); } //NOTE: Similar to EDACS analog, if calculating raw rms here after filtering, @@ -1979,10 +2016,19 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) uint8_t vc2_bytes[8]; memset (vc2_bytes, 0, sizeof(vc2_bytes)); #ifdef USE_CODEC2 - codec2_encode(state->codec2_3200, vc1_bytes, voice1); - codec2_encode(state->codec2_3200, vc2_bytes, voice2); + if (st == 2) + { + codec2_encode(state->codec2_3200, vc1_bytes, voice1); + codec2_encode(state->codec2_3200, vc2_bytes, voice2); + } + if (st == 3) + codec2_encode(state->codec2_1600, vc1_bytes, voice1); #endif + //Fill vc2_bytes with arbitrary data, UTF-8 chars (up to 48) + if (st == 3) + memcpy (vc2_bytes, state->m17sms+(lich_cnt*8), 8); + //initialize and start assembling the completed frame //Data/Voice Portion of Stream Data Link Layer w/ FSN @@ -2099,8 +2145,8 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) // lsf_chunk[lich_cnt][44] = (lsf_cn >> 1) & 1; // lsf_chunk[lich_cnt][45] = (lsf_cn >> 0) & 1; - lsf_chunk[lich_cnt][46] = (lsf_dt >> 1) & 1; - lsf_chunk[lich_cnt][47] = (lsf_dt >> 0) & 1; + // lsf_chunk[lich_cnt][46] = (lsf_dt >> 1) & 1; + // lsf_chunk[lich_cnt][47] = (lsf_dt >> 0) & 1; //encode with golay 24,12 and load into m17_l1g Golay_24_12_encode (lsf_chunk[lich_cnt]+00, m17_l1g+00); @@ -3005,6 +3051,7 @@ void decodeM17PKT(dsd_opts * opts, dsd_state * state, uint8_t * input, int len) else if (protocol == 4) fprintf (stderr, " IPv4;"); else if (protocol == 5) fprintf (stderr, " SMS;"); else if (protocol == 6) fprintf (stderr, " Winlink;"); + else if (protocol == 99)fprintf (stderr, " 1600 Arbitrary Data;"); //internal format only else fprintf (stderr, " Res: %02X;", protocol); //simple UTF-8 SMS Decoder @@ -3020,6 +3067,15 @@ void decodeM17PKT(dsd_opts * opts, dsd_state * state, uint8_t * input, int len) fprintf (stderr, "\n "); } } + else if (protocol == 99) //Just dump the 1600 Arbitrary Data as UTF-8 Encoded Test w/ len 9 + { + fprintf (stderr, " "); + for (i = 1; i < len; i++) + { + fprintf (stderr, "%c", input[i]); + + } + } else //if { //decode or just dump the raw data?