From 3eefa3365f83135b1bb1090795ce9f2c54dbc0b6 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 8 Apr 2024 02:45:47 -0400 Subject: [PATCH] M17: IP Frame Encoder / Decoder Fixes; --- src/dsd_main.c | 3 +- src/m17.c | 106 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/dsd_main.c b/src/dsd_main.c index 73bf0ec..9cbf36b 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -1371,7 +1371,8 @@ usage () printf (" -fe Decode only EDACS EA/ProVoice*\n"); printf (" -fE Decode only EDACS EA/ProVoice with ESK 0xA0*\n"); printf (" -fm Decode only dPMR*\n"); - printf (" -l Disable DMR, dPMR, and NXDN input filtering\n"); + printf (" -fm Decode only M17 UDP-IP Frames From STDIN***(Testing)\n"); + printf (" -l Disable DMR, dPMR, NXDN, M17 input filtering\n"); printf (" -u Unvoiced speech quality (default=3)\n"); printf (" -xx Expect non-inverted X2-TDMA signal\n"); printf (" -xr Expect inverted DMR signal\n"); diff --git a/src/m17.c b/src/m17.c index 0d9b3c0..e95f471 100644 --- a/src/m17.c +++ b/src/m17.c @@ -1561,6 +1561,11 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) int udp_return = 0; UNUSED(udp_return); uint8_t sid[2]; memset (sid, 0, sizeof(sid)); + //IP Frame + 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; + //NONCE time_t ts = time(NULL); //timestamp since epoch / "Unix Time" srand(ts); //randomizer seed based on timestamp @@ -2241,12 +2246,8 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) encodeM17RF (opts, state, m17_t4s, 2); //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; - - //NOTE: The Manual doesn't say much about this area, so assuming - //the elements are arranged as per the table + memset (m17_ip_frame, 0, sizeof(m17_ip_frame)); + memset (m17_ip_packed, 0, sizeof(m17_ip_packed)); //add MAGIC k = 0; @@ -2329,6 +2330,59 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) else //if not tx, reset values, drop carrier and sync { + + //Send last IP Frame with EOT, pack this before resetting + memset (m17_ip_frame, 0, sizeof(m17_ip_frame)); + memset (m17_ip_packed, 0, sizeof(m17_ip_packed)); + + //add MAGIC + k = 0; + for (j = 0; j < 4; j++) + { + for (i = 0; i < 8; i++) + m17_ip_frame[k++] = (magic[j] >> 7-i) &1; + } + + //add StreamID + for (j = 0; j < 2; j++) + { + for (i = 0; i < 8; i++) + m17_ip_frame[k++] = (sid[j] >> 7-i) &1; + } + + //add the current LSF, sans CRC + for (i = 0; i < 224; i++) + m17_ip_frame[k++] = m17_lsf[i]; + + //add eot bit flag + m17_ip_frame[k++] = eot&1; + + //add current fsn value + for (i = 0; i < 15; i++) + m17_ip_frame[k++] = (fsn >> 14-i)&1; + + //voice and/or data payload + for (i = 0; i < 64; i++) + m17_ip_frame[k++] = v1_bits[i]; + + //voice and/or data payload + for (i = 0; i < 64; i++) + m17_ip_frame[k++] = v2_bits[i]; + + //pack current bit array into a byte array for a CRC check + for (i = 0; i < 52; i++) + m17_ip_packed[i] = (uint8_t)ConvertBitIntoBytes(&m17_ip_frame[i*8], 8); + ip_crc = crc16m17(m17_ip_packed, 52); + + //add CRC value to the ip frame + for (i = 0; i < 16; i++) + m17_ip_frame[k++] = (ip_crc >> 15-i)&1; + + //pack CRC into the byte array as well + for (i = 52; i < 54; i++) + m17_ip_packed[i] = (uint8_t)ConvertBitIntoBytes(&m17_ip_frame[i*8], 8); + + //reset lich_cnt = 0; fsn = 0; state->carrier = 0; @@ -2451,6 +2505,18 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) for (i = 0; i < 25; i++) encodeM17RF (opts, state, nil, 99); + //send IP Frame with EOT bit + if (use_ip == 1) + udp_return = m17_socket_blaster (opts, state, 54, m17_ip_packed); + + //debug print packed byte output for IP frame + // fprintf (stderr, "\n IP: "); + // for (i = 0; i < 54; i++) + // { + // if ( (i%12)==0) fprintf (stderr, "\n"); + // fprintf (stderr, " %02X", m17_ip_packed[i]); + // } + //reset indicators eot = 0; eot_out = 1; @@ -3313,6 +3379,8 @@ void processM17IPF(dsd_opts * opts, dsd_state * state) //encode with: dsd-fme -fZ -M M17:1:lwvmobile:all:48000:0:1 -N 2> /dev/null -o null //decode with: socat stdio udp-listen:17000 | dsd-fme -fU + //TODO: Handle UDP Internally (test reading from socket, but may need threaded application for it) + int i, j, k; //Standard IP Framing @@ -3354,7 +3422,7 @@ void processM17IPF(dsd_opts * opts, dsd_state * state) ip_bits[k++] = (ip_frame[i] >> (7-j)) & 1; } - //copy stream ID + //copy Stream ID uint16_t sid = (uint16_t)ConvertBitIntoBytes(&ip_bits[32], 16); //copy LSF @@ -3362,10 +3430,14 @@ void processM17IPF(dsd_opts * opts, dsd_state * state) state->m17_lsf[i] = ip_bits[i+48]; //get FN and EOT bit - uint16_t fn = (uint16_t)ConvertBitIntoBytes(&ip_bits[272], 16); - uint8_t eot = ip_bits[272]; + uint16_t fn = (uint16_t)ConvertBitIntoBytes(&ip_bits[273], 15); + uint8_t eot = ip_bits[272]; - fprintf (stderr, "\n M17 IP SID: %04X; FN: %05d; EOT: %d", sid, fn, eot); + //update IV CTR from FN + state->m17_meta[14] = (uint16_t)ConvertBitIntoBytes(&ip_bits[273], 7); + state->m17_meta[15] = (uint16_t)ConvertBitIntoBytes(&ip_bits[280], 8); + + fprintf (stderr, "\n M17 IP Stream: %04X; FN: %05d; EOT: %d", sid, fn, eot); //copy payload uint8_t payload[128]; memset(payload, 0, sizeof(payload)); @@ -3380,8 +3452,6 @@ void processM17IPF(dsd_opts * opts, dsd_state * state) if (crc_ext == crc_cmp) M17decodeLSF(state); - else if (opts->aggressive_framesync == 0) - M17decodeLSF(state); if (state->m17_str_dt == 2) M17processCodec2_3200(opts, state, payload); @@ -3410,42 +3480,42 @@ void processM17IPF(dsd_opts * opts, dsd_state * state) //other headers from UDP IP else if (memcmp(headr, ackn, 4) == 0) { - fprintf (stderr, "\n M17 IP: ACNK; "); + fprintf (stderr, "\n M17 IP ACNK "); //clear frame memset (ip_frame, 0, sizeof(ip_frame)); } else if (memcmp(headr, nack, 4) == 0) { - fprintf (stderr, "\n M17 IP: NACK; "); + fprintf (stderr, "\n M17 IP NACK "); //clear frame memset (ip_frame, 0, sizeof(ip_frame)); } else if (memcmp(headr, conn, 4) == 0) { - fprintf (stderr, "\n M17 IP: CONN; "); + fprintf (stderr, "\n M17 IP CONN "); //clear frame memset (ip_frame, 0, sizeof(ip_frame)); } else if (memcmp(headr, disc, 4) == 0) { - fprintf (stderr, "\n M17 IP: DISC; "); + fprintf (stderr, "\n M17 IP DISC "); //clear frame memset (ip_frame, 0, sizeof(ip_frame)); } else if (memcmp(headr, ping, 4) == 0) { - fprintf (stderr, "\n M17 IP: PING; "); + fprintf (stderr, "\n M17 IP PING "); //clear frame memset (ip_frame, 0, sizeof(ip_frame)); } else if (memcmp(headr, pong, 4) == 0) { - fprintf (stderr, "\n M17 IP: PONG; "); + fprintf (stderr, "\n M17 IP PONG "); //clear frame memset (ip_frame, 0, sizeof(ip_frame));