diff --git a/README.md b/README.md index 077e213..d837664 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ sudo make install P25 - 7000; NXDN48 - 4000; DMR - 7000; EDACS/PV - 12500; May vary based on system stregnth, etc. -t Set Trunking VC/sync loss hangtime in seconds. (default = 1 second) -q Reverse Mute - Mute Unencrypted Voice and Unmute Encrypted Voice + -D Manually Set TIII DMR Location Area n bit len (0-10)(10 max) ``` diff --git a/include/dsd.h b/include/dsd.h index 240e91e..b4d135c 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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; diff --git a/src/dmr_csbk.c b/src/dmr_csbk.c index 478f454..07d317b 100644 --- a/src/dmr_csbk.c +++ b/src/dmr_csbk.c @@ -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); diff --git a/src/dmr_flco.c b/src/dmr_flco.c index b34e245..1b4f9d3 100644 --- a/src/dmr_flco.c +++ b/src/dmr_flco.c @@ -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 { diff --git a/src/dsd_main.c b/src/dsd_main.c index 780400f..f439beb 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -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 Manually Set P2 Parameters (WACN, SYSID, CC/NAC)\n"); printf (" (-X BEE00ABC123)\n"); + printf (" -D 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 QPSK modulation auto detection threshold (default=26)\n"); printf (" -S 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;