Overcook DMRLA and T3 Site ID Things;

This commit is contained in:
lwvmobile 2022-12-19 04:59:00 -05:00
parent 209d4e039e
commit 73824084ad
5 changed files with 170 additions and 22 deletions

View File

@ -81,6 +81,7 @@ sudo make install
P25 - 7000; NXDN48 - 4000; DMR - 7000; EDACS/PV - 12500; May vary based on system stregnth, etc.
-t <secs> Set Trunking VC/sync loss hangtime in seconds. (default = 1 second)
-q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice
-D <dec> Manually Set TIII DMR Location Area n bit len (0-10)(10 max)
```

View File

@ -332,6 +332,10 @@ typedef struct
//setmod bandwidth
int setmod_bw;
//DMR Location Area - DMRLA B***S***
uint8_t dmr_dmrla_is_set; //flag to tell us dmrla is set by the user
uint8_t dmr_dmrla_n; //n value for dmrla
} dsd_opts;
typedef struct
@ -518,6 +522,7 @@ typedef struct
char dmr_embedded_gps[2][200]; //2 slots by 99 char string for string embedded gps
char dmr_lrrp_gps[2][200]; //2 slots by 99 char string for string lrrp gps
char dmr_site_parms[200]; //string for site/net info depending on type of DMR system (TIII or Con+)
char call_string[2][200]; //string for call information
dPMRVoiceFS2Frame_t dPMRVoiceFS2Frame;

View File

@ -231,7 +231,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//tiny n 1-3; small 1-5; large 1-8; huge 1-10
uint16_t n = 1; //The minimum value of DMRLA is normally ≥ 1, 0 is reserved
//TODO: Add logic to set n and sub_mask values for DMRLA
char model_str[8];
char par_str[8]; //category A, B, AB, or reserved
@ -244,26 +243,56 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 9);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[51], 3);
sprintf (model_str, "%s", "Tiny");
n = 3;
}
else if (model == 1) //Small
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 7);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[49], 5);
sprintf (model_str, "%s", "Small");
n = 5;
}
else if (model == 2) //Large
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 4);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[46], 8);
sprintf (model_str, "%s", "Large");
n = 8;
}
else if (model == 3) //Huge
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 2);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[44], 10);
sprintf (model_str, "%s", "Huge");
n = 10;
}
//honestly can't say that this is accurate, just a guess
uint8_t is_capmax = 0; //capmax(mot) flag
if (csbk_fid == 0x10)
{
n = 0;
is_capmax = 1;
opts->dmr_dmrla_is_set = 1;
opts->dmr_dmrla_n = 0;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "CapMax ");
}
if (opts->dmr_dmrla_is_set == 1) n = opts->dmr_dmrla_n;
if (n == 0) sub_mask = 0x0;
if (n == 1) sub_mask = 0x1;
if (n == 2) sub_mask = 0x3;
if (n == 3) sub_mask = 0x7;
if (n == 4) sub_mask = 0xF;
if (n == 5) sub_mask = 0x1F;
if (n == 6) sub_mask = 0x3F;
if (n == 7) sub_mask = 0x7F;
if (n == 8) sub_mask = 0xFF;
if (n == 9) sub_mask = 0x1FF;
if (n == 10) sub_mask = 0x3FF;
uint8_t par = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[54], 2);
if (par == 1) sprintf (par_str, "%s", "A ");
if (par == 2) sprintf (par_str, "%s", "B ");
@ -271,10 +300,13 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
uint32_t target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24);
fprintf (stderr, " C_ALOHA_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d Cat: %s\n Reg Req: %d V: %d Mask: %02X MS: %d", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, par_str, regreq, version, mask, target);
if (n != 0) fprintf (stderr, " C_ALOHA_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d Cat: %s\n Reg Req: %d V: %d Mask: %02X MS: %d", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, par_str, regreq, version, mask, target);
else fprintf (stderr, " C_ALOHA_SYS_PARMS - %s - Net ID: %d Site ID: %d Cat: %s\n Reg Req: %d V: %d Mask: %02X MS: %d", model_str, net, site, par_str, regreq, version, mask, target);
if (is_capmax) fprintf (stderr, " Capacity Max ");
//add string for ncurses terminal display
sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
if (n != 0) sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
else sprintf (state->dmr_site_parms, "TIII - %s %d-%d ", model_str, net, site);
//if using rigctl we can set an unknown cc frequency by polling rigctl for the current frequency
if (opts->use_rigctl == 1 && state->p25_cc_freq == 0) //if not set from channel map 0
@ -291,11 +323,12 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
}
//nullify any previous branding sub (bugfix for bad assignments or system type switching)
sprintf(state->dmr_branding_sub, "%s", "");
//sprintf(state->dmr_branding_sub, "%s", "");
//debug print
uint16_t syscode = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[40], 16);
//fprintf (stderr, "\n SYSCODE: %016b", syscode);
//fprintf (stderr, "\n SYSCODE: %02b.%b.%b", model, net, site); //won't show leading zeroes, but may not be required
//fprintf (stderr, "\n SYSCODE: %04X", syscode);
}
@ -379,8 +412,6 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//tiny n 1-3; small 1-5; large 1-8; huge 1-10
uint16_t n = 1; //The minimum value of DMRLA is normally ≥ 1, 0 is reserved
//TODO: Add logic to set n and sub_mask values for DMRLA
//channel number from Broadcast Parms 2
uint16_t lpchannum = 0;
@ -395,26 +426,56 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 9);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[51], 3);
sprintf (model_str, "%s", "Tiny");
n = 3;
}
else if (model == 1) //Small
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 7);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[49], 5);
sprintf (model_str, "%s", "Small");
n = 5;
}
else if (model == 2) //Large
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 4);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[46], 8);
sprintf (model_str, "%s", "Large");
n = 8;
}
else if (model == 3) //Huge
{
net = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[42], 2);
site = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[44], 10);
sprintf (model_str, "%s", "Huge");
n = 10;
}
//honestly can't say that this is accurate, just a guess
uint8_t is_capmax = 0; //capmax(mot) flag
if (csbk_fid == 0x10)
{
n = 0;
is_capmax = 1;
opts->dmr_dmrla_is_set = 1;
opts->dmr_dmrla_n = 0;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "CapMax ");
}
if (opts->dmr_dmrla_is_set == 1) n = opts->dmr_dmrla_n;
if (n == 0) sub_mask = 0x0;
if (n == 1) sub_mask = 0x1;
if (n == 2) sub_mask = 0x3;
if (n == 3) sub_mask = 0x7;
if (n == 4) sub_mask = 0xF;
if (n == 5) sub_mask = 0x1F;
if (n == 6) sub_mask = 0x3F;
if (n == 7) sub_mask = 0x7F;
if (n == 8) sub_mask = 0xFF;
if (n == 9) sub_mask = 0x1FF;
if (n == 10) sub_mask = 0x3FF;
uint8_t par = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[54], 2);
if (par == 1) sprintf (par_str, "%s", "A ");
if (par == 2) sprintf (par_str, "%s", "B ");
@ -424,13 +485,16 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
lpchannum = parms2 & 0xFFF; //7.2.19.7, for DSDPlus, this value is (lpchannum << 1) + 1;
fprintf (stderr, "\n");
fprintf (stderr, " C_BCAST_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d Cat: %s Cd: %d C+: %d", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, par_str, lpchannum, (lpchannum << 1)+1 );
if (n != 0) fprintf (stderr, " C_BCAST_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d Cat: %s Cd: %d C+: %d", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, par_str, lpchannum, (lpchannum << 1)+1 );
else fprintf (stderr, " C_BCAST_SYS_PARMS - %s - Net ID: %d Site ID: %d Cat: %s Cd: %d C+: %d", model_str, net, site, par_str, lpchannum, (lpchannum << 1)+1 );
if (is_capmax) fprintf (stderr, " Capacity Max");
//add string for ncurses terminal display, if not adjacent site info
if (a_type != 6) sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1);
if (a_type != 6 && n != 0) sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1);
if (a_type != 6 && n == 0) sprintf (state->dmr_site_parms, "TIII - %s %d-%d ", model_str, net, site);
//nullify any previous branding sub (bugfix for bad assignments or system type switching)
sprintf(state->dmr_branding_sub, "%s", "");
//sprintf(state->dmr_branding_sub, "%s", "");
uint16_t syscode = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[40], 16);
//fprintf (stderr, "\n SYSCODE: %016b", syscode);

View File

@ -29,6 +29,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
int is_cap_plus = 0;
int is_alias = 0;
int is_gps = 0;
uint8_t slot = state->currentslot;
pf = (uint8_t)(lc_bits[0]); //Protect Flag
@ -142,15 +143,32 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
fprintf(stderr, "TGT=%u SRC=%u ", target, source);
if (opts->payload == 1) fprintf(stderr, "FLCO=0x%02X FID=0x%02X SVC=0x%02X ", flco, fid, so);
if (flco == 3) fprintf (stderr, "Private "); //UU_V_Ch_Usr
else fprintf (stderr, "Group "); //Grp_V_Ch_Usr
if (flco == 3) //UU_V_Ch_Usr
{
sprintf (state->call_string[slot], " Private");
fprintf (stderr, "Private ");
}
else //Grp_V_Ch_Usr
{
sprintf (state->call_string[slot], " Group");
fprintf (stderr, "Group ");
}
if(so & 0x80)
{
strcat (state->call_string[slot], " Emergency ");
fprintf (stderr, "%s", KRED);
fprintf(stderr, "Emergency ");
}
else strcat (state->call_string[slot], " ");
if(so & 0x80) fprintf(stderr, "Emergency ");
if(so & 0x40)
{
// strcat (state->call_string[slot], " Encrypted");
fprintf (stderr, "%s", KRED);
fprintf(stderr, "Encrypted ");
fprintf(stderr, "Encrypted ");
}
// else strcat (state->call_string[slot], " ");
/* Check the "Service Option" bits */
if(so & 0x30)
@ -169,7 +187,7 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
else if((so & 0x03) == 0x03) fprintf(stderr, "Priority 3 ");
else fprintf(stderr, "No Priority "); /* We should never go here */
}
fprintf(stderr, "Call ");
fprintf (stderr, "%s", KRED);
@ -420,6 +438,7 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
uint16_t n = 1; //The minimum value of DMRLA is normally ≥ 1, 0 is reserved
//TODO: Add logic to set n and sub_mask values for DMRLA
//assigning n as largest possible value for model type
//Sys_Parms
if (slco == 0x2 || slco == 0x3)
@ -429,25 +448,44 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
net = (uint16_t)ConvertBitIntoBytes(&slco_bits[6], 9);
site = (uint16_t)ConvertBitIntoBytes(&slco_bits[15], 3);
sprintf (model_str, "%s", "Tiny");
n = 3;
}
else if (model == 1) //Small
{
net = (uint16_t)ConvertBitIntoBytes(&slco_bits[6], 7);
site = (uint16_t)ConvertBitIntoBytes(&slco_bits[13], 5);
sprintf (model_str, "%s", "Small");
n = 5;
}
else if (model == 2) //Large
{
net = (uint16_t)ConvertBitIntoBytes(&slco_bits[6], 4);
site = (uint16_t)ConvertBitIntoBytes(&slco_bits[10], 8);
sprintf (model_str, "%s", "Large");
n = 8;
}
else if (model == 3) //Huge
{
net = (uint16_t)ConvertBitIntoBytes(&slco_bits[6], 2);
site = (uint16_t)ConvertBitIntoBytes(&slco_bits[8], 10);
sprintf (model_str, "%s", "Huge");
n = 10;
}
if (opts->dmr_dmrla_is_set == 1) n = opts->dmr_dmrla_n;
if (n == 0) sub_mask = 0x0;
if (n == 1) sub_mask = 0x1;
if (n == 2) sub_mask = 0x3;
if (n == 3) sub_mask = 0x7;
if (n == 4) sub_mask = 0xF;
if (n == 5) sub_mask = 0x1F;
if (n == 6) sub_mask = 0x3F;
if (n == 7) sub_mask = 0x7F;
if (n == 8) sub_mask = 0xFF;
if (n == 9) sub_mask = 0x1FF;
if (n == 10) sub_mask = 0x3FF;
}
//Con+
@ -462,10 +500,12 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
if (slco == 0x2) //C_SYS_Parms
{
fprintf (stderr, " C_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d - Reg Req: %d - CSC: %d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, reg, csc);
if (n != 0) fprintf (stderr, " C_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d - Reg Req: %d - CSC: %d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, reg, csc);
else fprintf (stderr, " C_SYS_PARMS - %s - Net ID: %d Site ID: %d - Reg Req: %d - CSC: %d ", model_str, net, site, reg, csc);
//add string for ncurses terminal display
sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
if (n != 0) sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
else sprintf (state->dmr_site_parms, "TIII - %s %d-%d ", model_str, net, site);
//if using rigctl we can set an unknown cc frequency by polling rigctl for the current frequency
@ -475,18 +515,31 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
if (ccfreq != 0) state->p25_cc_freq = ccfreq;
}
//nullify any previous branding sub (bugfix for naughty assignments or system type switching)
sprintf(state->dmr_branding_sub, "%s", "");
//nullify any previous branding sub (bugfix for bad assignments or system type switching)
//sprintf(state->dmr_branding_sub, "%s", "");
//debug print
uint16_t syscode = (uint16_t)ConvertBitIntoBytes(&slco_bits[4], 14);
//fprintf (stderr, "\n SYSCODE: %014b", syscode);
//fprintf (stderr, "\n SYSCODE: %02b.%b.%b", model, net, site); //won't show leading zeroes, but may not be required
}
else if (slco == 0x3) //P_SYS_Parms
{
fprintf (stderr, " P_SYS_PARMS - %s - Net ID: %d Site ID: %d.%d - Comp CC: %d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1, reg);
//add string for ncurses terminal display
sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
if (n != 0) sprintf (state->dmr_site_parms, "TIII - %s %d-%d.%d ", model_str, net+1, (site>>n)+1, (site & sub_mask)+1 );
else sprintf (state->dmr_site_parms, "TIII - %s %d-%d ", model_str, net, site);
//nullify any previous branding sub (bugfix for bad assignments or system type switching)
sprintf(state->dmr_branding_sub, "%s", "");
//sprintf(state->dmr_branding_sub, "%s", "");
//debug print
uint16_t syscode = (uint16_t)ConvertBitIntoBytes(&slco_bits[4], 14);
//fprintf (stderr, "\n SYSCODE: %014b", syscode);
//fprintf (stderr, "\n SYSCODE: %02b.%b.%b", model, net, site); //won't show leading zeroes, but may not be required
}
else if (slco == 0x0) //null
fprintf (stderr, " SLCO NULL ");
@ -508,7 +561,7 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[])
sprintf (state->dmr_branding_sub, "%s", "Con+ ");
fprintf (stderr, " SLCO Connect Plus Control Channel - Net ID: %d Site ID: %d", con_netid, con_siteid);
sprintf (state->dmr_site_parms, "%d-%d ", con_netid, con_siteid);
//if using rigctl we can set an unknown cc frequency by polling rigctl for the current frequency
if (opts->use_rigctl == 1 && state->p25_cc_freq == 0) //if not set from channel map 0
{

View File

@ -314,6 +314,10 @@ noCarrier (dsd_opts * opts, dsd_state * state)
memset(state->dmr_embedded_gps, 0, sizeof(state->dmr_embedded_gps));
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
//multi-purpose call_string
sprintf (state->call_string[0], "%s", " "); //20 spaces
sprintf (state->call_string[1], "%s", " "); //20 spaces
if (time(NULL) - state->last_cc_sync_time > 30) //thirty seconds of no carrier
{
state->dmr_rest_channel = -1;
@ -479,6 +483,10 @@ initOpts (dsd_opts * opts)
//setmod bandwidth
opts->setmod_bw = 0; //default to 0 - off
//DMR Location Area - DMRLA B***S***
opts->dmr_dmrla_is_set = 0;
opts->dmr_dmrla_n = 0;
} //initopts
void
@ -789,6 +797,10 @@ initState (dsd_state * state)
memset(state->dmr_embedded_gps, 0, sizeof(state->dmr_embedded_gps));
memset(state->dmr_lrrp_gps, 0, sizeof(state->dmr_lrrp_gps));
//multi-purpose call_string
sprintf (state->call_string[0], "%s", " "); //20 spaces
sprintf (state->call_string[1], "%s", " "); //20 spaces
//late entry mi fragments
memset (state->late_entry_mi_fragment, 0, sizeof (state->late_entry_mi_fragment));
@ -888,6 +900,9 @@ usage ()
printf ("Advanced Decoder options:\n");
printf (" -X <hex> Manually Set P2 Parameters (WACN, SYSID, CC/NAC)\n");
printf (" (-X BEE00ABC123)\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");
printf ("\n");
printf (" -A <num> QPSK modulation auto detection threshold (default=26)\n");
printf (" -S <num> Symbol buffer size for QPSK decision point tracking\n");
@ -1152,12 +1167,20 @@ main (int argc, char **argv)
opts.call_alert = 1;
break;
//Free'd up switches include e,p,v,Q,V,D,Y,z
//Free'd up switches include e,p,v,Q,V,Y,z
//make sure to put a colon : after each if they need an argument
//or remove colon if no argument required
//Disabled the Serial Port Dev and Baud Rate, etc, If somebody uses that function, sorry...
case 'D': //user set DMRLA n value
sscanf (optarg, "%c", &opts.dmr_dmrla_n);
if (opts.dmr_dmrla_n > 10) opts.dmr_dmrla_n = 10; //max out at 10;
// if (opts.dmr_dmrla_n != 0) opts.dmr_dmrla_is_set = 1; //zero will fix a capmax site id value...I think
opts.dmr_dmrla_is_set = 1;
fprintf (stderr, "DMRLA n value set to %d. \n", opts.dmr_dmrla_n);
break;
case 'C': //new letter assignment for Channel import, flow down to allow temp numbers
case '1': //LCN to Frequency CSV Import <--> flow down to chanimport now, tell users to use a channel map for edacs
case '7': //Channel Map Frequency CSV Import
@ -1859,6 +1882,7 @@ main (int argc, char **argv)
opts.mod_qpsk = 1;
opts.mod_gfsk = 0;
state.rf_mod = 1;
opts.setmod_bw = 12500;
fprintf (stderr,"Enabling only QPSK modulation optimizations.\n");
}
else if (optarg[0] == '2')
@ -1869,6 +1893,7 @@ main (int argc, char **argv)
state.rf_mod = 1;
state.samplesPerSymbol = 8;
state.symbolCenter = 3;
opts.setmod_bw = 12500;
fprintf (stderr,"Enabling 6000 sps P25p2 CQPSK.\n");
}
break;