M17 - Simple BRT Encoder; Setup for PKT Encoder;

This commit is contained in:
lwvmobile
2024-03-09 19:38:09 -05:00
parent a77fa83c80
commit 0f5612fdd4
3 changed files with 190 additions and 9 deletions

View File

@@ -271,6 +271,8 @@ typedef struct
int msize;
int playfiles;
int m17encoder;
int m17encoderbrt;
int m17encoderpkt;
int delay;
int use_cosine_filter;
int unmute_encrypted_p25;
@@ -1016,6 +1018,8 @@ void processYSF(dsd_opts * opts, dsd_state * state); //YSF
void processM17STR(dsd_opts * opts, dsd_state * state); //M17 (STR)
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 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)

View File

@@ -626,6 +626,8 @@ initOpts (dsd_opts * opts)
opts->msize = 1024; //15 default, max is 1024, much cleaner data decodes on Phase 2 cqpsk at max
opts->playfiles = 0;
opts->m17encoder = 0;
opts->m17encoderbrt = 0;
opts->m17encoderpkt = 0;
opts->delay = 0;
opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0;
@@ -1288,6 +1290,11 @@ usage ()
printf (" Example: dsd-fme -fZ -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 ("\n");
printf ("Decoder options:\n");
printf (" -fa Auto Detection\n");
printf (" -ft TDMA Trunking P25p1 Control and Voice, P25p2 Trunked Channels, and DMR\n");
@@ -2387,13 +2394,27 @@ main (int argc, char **argv)
fprintf(stderr, "Notice: M17 cannot autodetect polarity. \n Use -xz option if Inverted Signal expected.\n");
fprintf(stderr, "Decoding only M17 frames.\n");
}
else if (optarg[0] == 'Z') //Captial Z to Run the M17 encoder
else if (optarg[0] == 'Z') //Captial Z to Run the M17 STR encoder
{
opts.m17encoder = 1;
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
sprintf (opts.output_name, "M17 Encoder");
}
else if (optarg[0] == 'B') //Captial B to Run the M17 BRT encoder
{
opts.m17encoderbrt = 1;
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
sprintf (opts.output_name, "M17 BERT");
}
else if (optarg[0] == 'P') //Captial P to Run the M17 PKT encoder
{
opts.m17encoderpkt = 1;
opts.pulse_digi_rate_out = 48000;
opts.pulse_digi_out_channels = 1;
sprintf (opts.output_name, "M17 Packet");
}
break;
//don't mess with the modulations unless you really need to
case 'm':
@@ -2951,6 +2972,22 @@ main (int argc, char **argv)
encodeM17STR(&opts, &state);
}
else if (opts.m17encoderbrt == 1)
{
opts.pulse_digi_rate_out = 8000;
//open any outputs, if not already opened
if (opts.audio_out_type == 0) openPulseOutput(&opts);
encodeM17BRT(&opts, &state);
}
else if (opts.m17encoderpkt == 1)
{
opts.pulse_digi_rate_out = 8000;
//open any outputs, if not already opened
if (opts.audio_out_type == 0) openPulseOutput(&opts);
encodeM17PKT(&opts, &state);
}
else
{

156
src/m17.c
View File

@@ -1118,7 +1118,7 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type)
}
//Preamble (just repeat the preamble 12 times to make 192 symbols)
if (type == 33) //B Pattern prepends ??? (last symbol opposite of first symbol to prevent zero-crossing)
if (type == 33) //B Pattern prepends BRT (last symbol opposite of first symbol to prevent zero-crossing)
{
for (i = 0; i < 192; i++)
output_dibits[i] = (m17_preamble_b[ (i*2+0)%16 ] << 1) + (m17_preamble_b[ (i*2+1)%16 ] << 0);
@@ -1144,18 +1144,18 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type)
output_dibits[i] = (m17_str_fs[i*2+0] << 1) + (m17_str_fs[i*2+1] << 0);
}
if (type == 3) //PKT
{
for (i = 0; i < 8; i++)
output_dibits[i] = (m17_pkt_fs[i*2+0] << 1) + (m17_pkt_fs[i*2+1] << 0);
}
if (type == 4) //BRT
if (type == 3) //BRT
{
for (i = 0; i < 8; i++)
output_dibits[i] = (m17_brt_fs[i*2+0] << 1) + (m17_brt_fs[i*2+1] << 0);
}
if (type == 4) //PKT
{
for (i = 0; i < 8; i++)
output_dibits[i] = (m17_pkt_fs[i*2+0] << 1) + (m17_pkt_fs[i*2+1] << 0);
}
//load rest of frame (if not preamble, EOT marker, or dead air)
if (type < 5)
{
@@ -1210,6 +1210,10 @@ void encodeM17RF (dsd_opts * opts, dsd_state * state, uint8_t * input, int type)
// fprintf (stderr, " %d", baseband[i]);
// }
//debug insert random 'noise' into the baseband audio
// for (i = 0; i < 40; i++)
// baseband[i] -= rand()& 0x7FFF;
//dead air type, output to all enabled formats zero sample to simulate dead air
//NOTE: 25 rounds is approximately 1 second even, seems optimal
if (type == 99)
@@ -2084,3 +2088,139 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
free(samp2);
}
//encode and create audio of a Project M17 BERT signal
void encodeM17BRT(dsd_opts * opts, dsd_state * state)
{
//NOTE: BERT will not use the nucrses terminal,
//just strictly for making a BERT test signal
uint8_t nil[368]; //empty array
memset (nil, 0, sizeof(nil));
int i, j, k, x; //basic utility counters
//send dead air with type 99
for (i = 0; i < 25; i++)
encodeM17RF (opts, state, nil, 99);
//send preamble_b for the BERT frame
encodeM17RF (opts, state, nil, 33);
//BERT - 197 bits generated from a PRBS9 Generator
uint8_t m17_b1[201]; memset (m17_b1, 0, sizeof(m17_b1));
uint16_t lfsr = 1; //starting value of the LFSR
uint16_t bit = 1; //result bit of taps XOR
m17_b1[0] = 1;
while (!exitflag)
{
//Generate sequence (if doing 197 at a time)
// for (j = 0; j < 197; j++)
// {
// bit = ( (lfsr >> 8) ^ (lfsr ^ 4) ) & 1;
// lfsr = (lfsr << 1) | bit;
// m17_b1[j] = bit;
// }
//BERT (reversed sequence for output)
uint8_t m17_b1r[208]; memset (m17_b1r, 0, sizeof(m17_b1r));
//BERT (after Convolutional Encode)
uint8_t m17_b1c[402]; memset (m17_b1c, 0, sizeof(m17_b1c));
//BERT (after P2 Puncturing)
uint8_t m17_b2p[368]; memset (m17_b2p, 0, sizeof(m17_b2p));
//BERT (Interleaved Bits)
uint8_t m17_b3i[368]; memset (m17_b3i, 0, sizeof(m17_b3i));
//BERT (Scrambling Applied)
uint8_t m17_b4s[368]; memset (m17_b4s, 0, sizeof(m17_b4s));
simple_conv_encoder (m17_b1, m17_b1c, 201); //197+4
//use the P2 puncture to...puncture and collapse the BERT Frame
k = 0; x = 0;
for (i = 0; i < 34; i++)
{
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
//quit early on last set of i when 368 k bits reached
//index from 0 to 367,so 368 is breakpoint with k++
if (k == 368) break;
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
m17_b2p[k++] = m17_b1c[x++];
x++;
}
//debug K and X bit positions
fprintf (stderr, " K: %d; X: %d", k, x);
//interleave the bit array using Quadratic Permutation Polynomial
//function π(x) = (45x + 92x^2 ) mod 368
for (i = 0; i < 368; i++)
{
x = ((45*i)+(92*i*i)) % 368;
m17_b3i[x] = m17_b2p[i];
}
//scramble/randomize the frame
for (i = 0; i < 368; i++)
m17_b4s[i] = (m17_b3i[i] ^ m17_scramble[i]) & 1;
//debug insert 3 random bit flip in the finished BERT frame
// int rnd1 = rand()%368;
// int rnd2 = rand()%368;
// int rnd3 = rand()%368;
// m17_b4s[rnd1] ^= 1;
// m17_b4s[rnd2] ^= 1;
// m17_b4s[rnd3] ^= 1;
//-----------------------------------------
fprintf (stderr, "\n M17 BERT (ENCODER): ");
//reverse the sequence and shift so it appears correct on display
for (i = 0; i < 197; i++)
m17_b1r[i+3] = m17_b1[196-i];
//Dump Output of the BERT array (reversed and shifted sequence)
for (i = 0; i < 25; i++)
fprintf (stderr, "%02X", (uint8_t)ConvertBitIntoBytes(&m17_b1r[i*8], 8));
//convert bit array into symbols and RF/Audio
encodeM17RF (opts, state, m17_b4s, 3);
//advance sequence if doing 1 bit each BERT frame
bit = ( (lfsr >> 8) ^ (lfsr ^ 4) ) & 1;
lfsr = (lfsr << 1) | bit;
//shift the array once and put the result bit into the zero position
//NOTE: The endian-ness of this may be opposite of what is expected
for (j = 1; j < 197; j++)
m17_b1[197-j] = m17_b1[197-j-1];
m17_b1[0] = bit;
//end sequence advancement
}
}
//encode and create audio of a Project M17 PKT signal
void encodeM17PKT(dsd_opts * opts, dsd_state * state)
{
UNUSED(opts); UNUSED(state);
//TODO: This whole thing
fprintf (stderr, "\n M17 Packet (ENCODER): ");
}