Rewrite NXDN Dibit PN95 Code and allow custom seed value; #318

This commit is contained in:
lwvmobile
2025-10-07 06:13:19 -04:00
parent f3b89f1c51
commit 748bb5b191
5 changed files with 58 additions and 22 deletions

View File

@@ -1,4 +1,4 @@
Build Version: AW 2025-182-g24c1dd9
Build Version: AW 2025-197-gf3b89f1
MBElib Version: 1.3.4
CODEC2 Support Enabled
@@ -137,6 +137,8 @@ Decoder options:
Advanced Decoder options:
-X <hex> Manually Set P2 Parameters (WACN, SYSID, CC/NAC)
(-X BEE00ABC123)
-* <dec> Manually Set NXDN PN95 Dibit Scrambler Seed (1-511)
(-* 261)
-D <dec> Manually Set TIII DMR Location Area n bit len (0-10)(10 max)
(Value defaults to max n bit value for site model size)
(Setting 0 will show full Site ID, no area/subarea)

View File

@@ -898,6 +898,7 @@ typedef struct
uint8_t nxdn_sacch_frame_segcrc[4];
uint8_t nxdn_alias_block_number;
char nxdn_alias_block_segment[4][4][8];
uint16_t nxdn_pn95_seed;
//site/srv/cch info
char nxdn_location_category[14];
@@ -1281,7 +1282,7 @@ void ncursesClose ();
//new NXDN Functions start here!
void nxdn_frame (dsd_opts * opts, dsd_state * state);
void nxdn_descramble (uint8_t dibits[], int len);
void nxdn_pn95_dibit_scrambler(dsd_state * state, uint8_t * dibits, int len);
//nxdn deinterleaving/depuncturing functions
void nxdn_deperm_facch (dsd_opts * opts, dsd_state * state, uint8_t bits[144]);
void nxdn_deperm_sacch (dsd_opts * opts, dsd_state * state, uint8_t bits[60]);

View File

@@ -1214,6 +1214,7 @@
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
state->nxdn_alias_block_number = 0;
memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment));
state->nxdn_pn95_seed = 228; //default value
//site/srv/cch info
state->nxdn_location_site_code = 0;
@@ -1526,6 +1527,8 @@
printf ("Advanced Decoder options:\n");
printf (" -X <hex> Manually Set P2 Parameters (WACN, SYSID, CC/NAC)\n");
printf (" (-X BEE00ABC123)\n");
printf (" -* <dec> Manually Set NXDN PN95 Dibit Scrambler Seed (1-511)\n");
printf (" (-* 261)\n");
printf (" -D <dec> Manually Set TIII DMR Location Area n bit len (0-10)(10 max)\n");
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");
@@ -1906,7 +1909,7 @@
exitflag = 0;
while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF@:!:01:2:345:6:7:89:Ek:I:J:O")) != -1)
while ((c = getopt (argc, argv, "~yhaepPqs:t:v:z:i:o:d:c:g:n:w:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:YK:b:H:X:NQ:WrlZTF@:!:01:2:345:6:7:8*:9:Ek:I:J:O")) != -1)
{
switch (c)
@@ -2217,7 +2220,15 @@
if (state.R > 0x7FFF) state.R = 0x7FFF;
//disable keyloader in case user tries to use this and it at the same time
state.keyloader = 0;
fprintf (stderr, "NXDN Scrambler Key set to: %05d;", state.R);
break;
case '*':
sscanf (optarg, "%hu", &state.nxdn_pn95_seed);
if (state.nxdn_pn95_seed > 0x1FF) state.nxdn_pn95_seed = 0x1FF;
else if (state.nxdn_pn95_seed == 0) state.nxdn_pn95_seed = 228;
fprintf (stderr, "NXDN PN9 Seed Value set to: %03d;", state.nxdn_pn95_seed);
break;
case 'H':
//new handling for 10/32/64 Char Key

View File

@@ -25,26 +25,48 @@
#include "dsd.h"
#include "nxdn_const.h"
//NOTE: Descrambling was having an issue without a value inside the brackets, but only when
//the PARITY table was disabled, was this due to a memory issue or overflow?
static const uint8_t scramble_t[182] = { //values are the position values we need to invert in the descramble
2, 5, 6, 7, 10, 12, 14, 16, 17, 22, 23, 25, 26, 27, 28, 30, 33, 34, 36, 37, 38, 41, 45, 47,
52, 54, 56, 57, 59, 62, 63, 64, 65, 66, 67, 69, 70, 73, 76, 79, 81, 82, 84, 85, 86, 87, 88,
89, 92, 95, 96, 98, 100, 103, 104, 107, 108, 116, 117, 121, 122, 125, 127, 131, 132, 134,
137, 139, 140, 141, 142, 143, 144, 145, 147, 151, 153, 154, 158, 159, 160, 162, 164, 165,
168, 170, 171, 174, 175, 176, 177, 181
};
//decoding functions here
void nxdn_descramble(uint8_t dibits[], int len)
void nxdn_pn95_dibit_scrambler(dsd_state * state, uint8_t * dibits, int len)
{
for (int i=0; i<len; i++)
uint16_t lfsr = state->nxdn_pn95_seed; //default value is 228 / 0xE4
//debug hard set
// lfsr = 261;
uint16_t bit = 0;
uint8_t pN95[182]; memset (pN95, 0, sizeof(pN95));
for (int i = 0; i < len; i++)
{
if (scramble_t[i] >= len)
break;
dibits[scramble_t[i]] ^= 0x2; // invert sign of scrambled dibits
//before feedback, take the bit
pN95[i] = lfsr & 1;
//since this is right shift, the taps are 0 and 4, and not 8 and 4 (9,5)
bit = ((lfsr >> 4) ^ (lfsr >> 0)) & 1;
lfsr >>= 1;
lfsr |= (bit << 8);
}
//convert the pN sequence to a scramble table
uint8_t scramble_table[182]; memset(scramble_table, 0, sizeof(scramble_table));
int k = 0;
for (int i = 0; i < len; i++)
{
if (pN95[i] == 1)
scramble_table[k++] = i;
}
//the entries into the scramble_table are the dibits (symbols) that are inverted
for (int i = 0; i < k; i++)
{
dibits[scramble_table[i]] ^= 0x2;
dibits[scramble_table[i]] &= 0x3;
}
//debug, make sure we don't overflow dibits array
// fprintf (stderr, " PN95: K: %d; Len: %d; ", k, len);
}
void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])

View File

@@ -90,7 +90,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
//collect lich bits first, if they are good, then we can collect the rest of them
for (int i = 0; i < 8; i++) lich_dibits[i] = dbuf[i] = getDibit(opts, state);
nxdn_descramble (lich_dibits, 8);
nxdn_pn95_dibit_scrambler (state, lich_dibits, 8);
lich = 0;
for (int i=0; i<8; i++) lich |= (lich_dibits[i] >> 1) << (7-i);
@@ -343,7 +343,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
dbuf[i+8] = getDibit(opts, state);
}
nxdn_descramble (dbuf, 182); //sizeof(dbuf)
nxdn_pn95_dibit_scrambler (state, dbuf, 182);
//seperate our dbuf (dibit_buffer) into individual bit array
for (int i = 0; i < 182; i++)