M17: UDP IP Frame Decoder over STDIN;

This commit is contained in:
lwvmobile 2024-04-07 14:14:44 -04:00
parent 5c9416313a
commit d22f9ddfe3
3 changed files with 188 additions and 2 deletions

View File

@ -303,6 +303,7 @@ typedef struct
int m17encoder;
int m17encoderbrt;
int m17encoderpkt;
int m17decoderip;
int delay;
int use_cosine_filter;
int unmute_encrypted_p25;
@ -1098,6 +1099,7 @@ void processYSF(dsd_opts * opts, dsd_state * state); //YSF
void processM17STR(dsd_opts * opts, dsd_state * state); //M17 (STR)
void processM17PKT(dsd_opts * opts, dsd_state * state); //M17 (PKT)
void processM17LSF(dsd_opts * opts, dsd_state * state); //M17 (LSF)
void processM17IPF(dsd_opts * opts, dsd_state * state); //M17 (IPF)
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

View File

@ -636,6 +636,7 @@ initOpts (dsd_opts * opts)
opts->m17encoder = 0;
opts->m17encoderbrt = 0;
opts->m17encoderpkt = 0;
opts->m17decoderip = 0;
opts->delay = 0;
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0;
@ -1600,6 +1601,9 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state)
if (opts->udp_sockfdA)
close (opts->udp_sockfdA);
if (opts->m17_udp_sock)
close (opts->m17_udp_sock);
//close MBE out files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
@ -2724,6 +2728,13 @@ main (int argc, char **argv)
opts.pulse_digi_out_channels = 1;
sprintf (opts.output_name, "M17 Packet");
}
else if (optarg[0] == 'U') //Captial U to Run the M17 UDP IPF decoder
{
opts.m17decoderip = 1;
opts.pulse_digi_rate_out = 8000;
opts.pulse_digi_out_channels = 1;
sprintf (opts.output_name, "M17 IP Frame");
}
break;
//don't mess with the modulations unless you really need to
case 'm':
@ -3335,7 +3346,7 @@ main (int argc, char **argv)
// fprintf (stderr, " %s;", state.m17dat);
//debug print
fprintf (stderr, " M17:%d:%s:%s:%d; \n ", state.m17_can_en, state.str50c, state.str50b, state.m17_rate);
fprintf (stderr, " M17:%d:%s:%s:%d:%d:%d; \n ", state.m17_can_en, state.str50c, state.str50b, state.m17_rate, state.m17_vox, opts.m17_use_ip);
}
if (opts.playfiles == 1)
@ -3387,6 +3398,14 @@ main (int argc, char **argv)
encodeM17PKT(&opts, &state);
}
else if (opts.m17decoderip == 1)
{
opts.pulse_digi_rate_out = 8000;
//open any outputs, if not already opened
if (opts.audio_out_type == 0) openPulseOutput(&opts);
processM17IPF(&opts, &state);
}
else
{

167
src/m17.c
View File

@ -2226,6 +2226,10 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
processM17STR_debug(opts, state, m17_t4s);
else fprintf (stderr, " To Audio Out Device Type: %d; ", opts->audio_out_type);
//show UDP if active
if (use_ip == 1 && lich_cnt != 5)
fprintf (stderr, " UDP: %s:%d", opts->m17_hostname, udpport);
//debug RMS Value
if (state->m17_vox == 1)
{
@ -2427,6 +2431,10 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
processM17STR_debug(opts, state, m17_t4s);
else fprintf (stderr, " To Audio Out Device Type: %d; ", opts->audio_out_type);
//show UDP if active
if (use_ip == 1 && lich_cnt != 5)
fprintf (stderr, " UDP: %s:%d", opts->m17_hostname, udpport);
//debug RMS Value
if (state->m17_vox == 1)
{
@ -3297,4 +3305,161 @@ void processM17PKT(dsd_opts * opts, dsd_state * state)
//ending linebreak
fprintf (stderr, "\n");
} //end processM17PKT
} //end processM17PKT
//Process Received IP Frames
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
int i, j, k;
//Standard IP Framing
uint8_t byte = 0;
uint8_t ip_frame[54]; memset (ip_frame, 0, sizeof(ip_frame));
uint8_t headr[4]; memset (headr, 0, sizeof(headr));
uint8_t magic[4] = {0x4D, 0x31, 0x37, 0x20};
uint8_t ackn[4] = {0x41, 0x43, 0x4B, 0x4E};
uint8_t nack[4] = {0x4E, 0x41, 0x43, 0x4B};
uint8_t conn[4] = {0x43, 0x4F, 0x4E, 0x4E};
uint8_t disc[4] = {0x44, 0x49, 0x53, 0x43};
uint8_t ping[4] = {0x50, 0x49, 0x4E, 0x47};
uint8_t pong[4] = {0x50, 0x4F, 0x4E, 0x47};
while (!exitflag)
{
//read in one byte from stdin
fread(&byte, 1, 1, stdin)<1;
//push new byte
for(i = 0; i < 54; i++)
ip_frame[i]=ip_frame[i+1];
ip_frame[53]=byte;
//copy top of ip_frame to headr
memcpy (headr, ip_frame, 4);
//compare headr to magic and decode IP voice frame w/ M17 magic header
if (memcmp(headr, magic, 4) == 0)
{
//convert bytes to bits
k = 0;
uint8_t ip_bits[462]; memset(ip_bits, 0, sizeof(ip_bits));
for (i = 0; i < 54; i++)
{
for (j = 0; j < 8; j++)
ip_bits[k++] = (ip_frame[i] >> (7-j)) & 1;
}
//copy stream ID
uint16_t sid = (uint16_t)ConvertBitIntoBytes(&ip_bits[32], 16);
//copy LSF
for (i = 0; i < 224; i++)
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];
fprintf (stderr, "\n M17 IP SID: %04X; FN: %05d; EOT: %d", sid, fn, eot);
//copy payload
uint8_t payload[128]; memset(payload, 0, sizeof(payload));
for (i = 0; i < 128; i++)
payload[i] = ip_bits[i+288];
//copy received CRC
uint16_t crc_ext = (ip_frame[52] << 8) + ip_frame[53];
//calculate CRC on received packet
uint16_t crc_cmp = crc16m17(ip_frame, 52);
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);
else if (state->m17_str_dt == 3)
M17processCodec2_1600(opts, state, payload);
if (opts->payload == 1)
{
fprintf (stderr, "\n IP:");
for (i = 0; i < 54; i++)
{
if ( (i%14) == 0 ) fprintf (stderr, "\n ");
fprintf (stderr, "[%02X]", ip_frame[i]);
}
fprintf (stderr, " E-%04X; C-%04X (CRC CHK)", crc_ext, crc_cmp);
}
if (crc_ext != crc_cmp) fprintf (stderr, " IP CRC ERR");
//clear frame
memset (ip_frame, 0, sizeof(ip_frame));
}
//other headers from UDP IP
else if (memcmp(headr, ackn, 4) == 0)
{
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; ");
//clear frame
memset (ip_frame, 0, sizeof(ip_frame));
}
else if (memcmp(headr, conn, 4) == 0)
{
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; ");
//clear frame
memset (ip_frame, 0, sizeof(ip_frame));
}
else if (memcmp(headr, ping, 4) == 0)
{
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; ");
//clear frame
memset (ip_frame, 0, sizeof(ip_frame));
}
//debug
// else if (opts->payload == 1)
// {
// fprintf (stderr, "\n DUMP:");
// for (i = 0; i < 54; i++)
// {
// if ( (i%14) == 0 ) fprintf (stderr, "\n ");
// fprintf (stderr, "[%02X]", ip_frame[i]);
// }
// }
}
}