DMR Cap+ CSBK Improvements;

This commit is contained in:
lwvmobile 2023-02-03 22:15:13 -05:00
parent e581c96560
commit 4e2c4577d5
5 changed files with 311 additions and 96 deletions

View File

@ -537,6 +537,7 @@ typedef struct
//new stuff below here
uint8_t data_conf_data[2]; //flag for confirmed data blocks per slot
uint8_t dmr_pdu_sf[2][288]; //unified pdu 'superframe' //[slot][byte]
uint8_t cap_plus_csbk_bits[12*8*4]; //CSBK Cap+ FL initial and appended block bit storage
uint8_t data_block_crc_valid[2][25]; //flag each individual block as good crc on confirmed data
char dmr_embedded_signalling[2][7][48]; //embedded signalling 2 slots by 6 vc by 48 bits (replacing TS1SuperFrame.TimeSlotRawVoiceFrame.Sync structure)

View File

@ -556,4 +556,5 @@ void dmr_reset_blocks (dsd_opts * opts, dsd_state * state)
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
memset (state->dmr_lrrp_source, 0, sizeof(state->dmr_lrrp_source));
memset (state->dmr_cach_fragment, 1, sizeof (state->dmr_cach_fragment));
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
}

View File

@ -620,12 +620,11 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
}
//Capacity+ Section
//Reworked Cap+ for Multi Block FL PDU and Private/Data Calls
//experimental, but seems to be working well
if (csbk_fid == 0x10)
{
//not quite sure how these tuning rules will go over
//if they don't work so well, may just fall back to
//a 'follow rest channel on no sync' only approach
//Cap+ Channel Status PDU
if (csbk_o == 0x3E)
{
@ -634,28 +633,42 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
fprintf (stderr, "%s", KYEL);
uint8_t fl = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 2);
uint8_t ts = cs_pdu_bits[18]; //accurate?
uint8_t res = cs_pdu_bits[19]; //unknown??
uint8_t ts = cs_pdu_bits[18]; //timeslot this PDU occurs in
uint8_t res = cs_pdu_bits[19]; //unknown, always seems to be 0
uint8_t rest_channel = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[20], 4);
uint8_t group_tally = 0; //set this to the number of active group channels tallied
uint8_t ch[8]; //one bit per channel
uint8_t pch[8]; //private or data call channel bits
uint8_t tg = 0;
uint32_t tghex = 0; //combined all tgs for debug
int i, j, k;
//tg and channel info for trunking purposes
uint8_t t_tg[9];
memset (t_tg, 0, sizeof(t_tg));
k = 0;
//initialize group ch and private/data channel bit arrays
for (i = 0; i < 8; i++)
{
ch[i] = 0;
pch[i] = 0;
}
//treating FL as a form of LCSS
if (fl != 1) //initial or single block (fl2 or fl3)
{
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
for (i = 0; i < 10*8; i++) state->cap_plus_csbk_bits[i] = cs_pdu_bits[i];
}
else //appended block (fl1)
{
for (i = 0; i < 7*8; i++) state->cap_plus_csbk_bits[i+80] = cs_pdu_bits[i+24];
}
if (rest_channel != state->dmr_rest_channel)
{
state->dmr_rest_channel = rest_channel;
}
for (int i = 0; i < 8; i++)
{
ch[i] = cs_pdu_bits[i+24];
}
//assign to cc freq to follow during no sync
if (state->trunk_chan_map[rest_channel] != 0)
@ -664,96 +677,297 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//set to always tuned
opts->p25_is_tuned = 1;
}
fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest Channel %d", fl, ts, res, rest_channel);
if (fl == 1) fprintf (stderr, " - Appended Block");
if (fl == 2) fprintf (stderr, " - Initial Block");
if (fl == 3) fprintf (stderr, " - Single Block");
fprintf (stderr, "\n ");
for (i = 0; i < 8; i++)
//look at each group channel bit -- run this PRIOR to checking private or data calls
//or else we will overwrite the ch bits we set below for private calls with zeroes
//these also seem to indicate data calls -- can't find a distinction of which is which
for (int i = 0; i < 8; i++)
{
fprintf (stderr, "Ch%d: ", i+1);
if (ch[i] != 0)
{
tg = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[k*8+32], 8);
if (tg != 0) fprintf (stderr, " %03d ", tg);
else fprintf (stderr, "Priv "); //observed 000s for TG value seem to appear during a Cap+ Private TXI call
//add values to trunking tg/channel potentials
t_tg[i] = tg;
k++;
}
else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
else fprintf (stderr, "Idle ");
ch[i] = state->cap_plus_csbk_bits[i+24];
if (ch[i] == 1) group_tally++; //figure out where to start looking in the byte stream for the 0x80 flag
}
if (i == 3) fprintf (stderr, "\n ");
}
tghex = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
//fprintf (stderr, "\n TG Hex = 0x%06X", tghex);
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
//check for private/data calls
uint8_t pdflag = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[40+(group_tally*8)], 8); //seems to be 0x80 (last block flag?) on samples I have
uint16_t private_target = 0;
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
sprintf(state->dmr_site_parms, "%s", "");
fprintf (stderr, "%s", KNRM);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
//don't tune if currently a vc on the current channel
if ( (time(NULL) - state->last_vc_sync_time > 2) )
//first, check to see if we have a completed PDU
if (fl != 2)
{
for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
//then check to see if this byte has a value, should be 0x80
//this bytes location seems to shift depending on level of activity
if (pdflag != 0) //now looking to see if any appended data was added
{
char mode[8]; //allow, block, digital, enc, etc
//if we are using allow/whitelist mode, then write 'B' to mode for block
//comparison below will look for an 'A' to write to mode if it is allowed
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
for (int i = 0; i < state->group_tally; i++)
k = 0; //= 0
fprintf (stderr, "\n");
fprintf (stderr, " F%X Private or Data Call", pdflag);
for (int i = 0; i < 8; i++)
{
if (state->group_array[i].groupNumber == t_tg[j])
pch[i] = state->cap_plus_csbk_bits[i+48+(group_tally*8)];
if (pch[i] == 1)
{
fprintf (stderr, " [%s]", state->group_array[i].groupName);
strcpy (mode, state->group_array[i].groupMode);
}
fprintf (stderr, " Ch%d:", i+1);
private_target = (uint16_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[56+(k*16)+(group_tally*8)], 16);
fprintf (stderr, " TGT %d;", private_target);
if (opts->trunk_tune_private_calls == 1) t_tg[i] = private_target; //set here for tuning allow/block
k++;
}
}
//no more 0 reporting, that was some bad code that caused that issue
//without priority, this will tune the first one it finds (if group isn't blocked)
if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
{
if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
{
//RIGCTL
if (opts->use_rigctl == 1)
{
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
j = 11; //break loop
}
//rtl_udp
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1;
j = 11; //break loop
}
}
}
}
}
//end private/data call check
if (fl != 2)
{
fprintf (stderr, "\n ");
k = 0;
for (i = 0; i < 8; i++)
{
fprintf (stderr, "Ch%d: ", i+1);
if (ch[i] == 1) //group voice channels
{
tg = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[k*8+32], 8);
if (tg != 0) fprintf (stderr, " %03d ", tg);
else fprintf (stderr, "Actv ");
//add values to trunking tg/channel potentials
t_tg[i] = tg;
if (tg != 0) k++;
}
else if (pch[i] == 1) //private or data channels
{
fprintf (stderr, "P||D ");
//flag as available for tuning if enabled
if (opts->trunk_tune_private_calls == 1) ch[i] = 1;
}
else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
else fprintf (stderr, "Idle ");
if (i == 3) fprintf (stderr, "\n ");
}
state->dmr_mfid = 0x10;
sprintf (state->dmr_branding, "%s", "Motorola");
sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
//nullify any previous TIII data (bugfix for bad assignments or system type switching)
sprintf(state->dmr_site_parms, "%s", "");
fprintf (stderr, "%s", KNRM);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
//don't tune if vc on the current channel
if ( (time(NULL) - state->last_vc_sync_time > 2) )
{
for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
{
char mode[8]; //allow, block, digital, enc, etc
//if we are using allow/whitelist mode, then write 'B' to mode for block
//comparison below will look for an 'A' to write to mode if it is allowed
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
for (int i = 0; i < state->group_tally; i++)
{
if (state->group_array[i].groupNumber == t_tg[j])
{
fprintf (stderr, " [%s]", state->group_array[i].groupName);
strcpy (mode, state->group_array[i].groupMode);
}
}
//without priority, this will tune the first one it finds (if group isn't blocked)
if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
{
if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
{
//RIGCTL
if (opts->use_rigctl == 1)
{
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
j = 11; //break loop
}
//rtl_udp
else if (opts->audio_in_type == 3)
{
rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
opts->p25_is_tuned = 1;
j = 11; //break loop
}
}
}
}
} //end tuning
SKIPCAP: ;
//debug print
if (fl == 1 && opts->payload == 1)
{
fprintf (stderr, "%s\n", KYEL);
fprintf (stderr, " CAP+ Multi Block PDU ");
uint8_t fl_bytes = 0;
for (i = 0; i < 17; i++)
{
fl_bytes = (uint8_t)ConvertBitIntoBytes(&state->cap_plus_csbk_bits[i*8], 8);
fprintf (stderr, "[%02X]", fl_bytes);
}
fprintf (stderr, "%s", KNRM);
}
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
} //fl != 2
} //opcode == 0x3E
} //fid == 0x10
//Capacity+ Section -- fallback if issues arise
// if (csbk_fid == 0x10)
// {
// //not quite sure how these tuning rules will go over
// //if they don't work so well, may just fall back to
// //a 'follow rest channel on no sync' only approach
// if (csbk_o == 0x3E)
// {
// //initial line break
// fprintf (stderr, "\n");
// fprintf (stderr, "%s", KYEL);
// uint8_t fl = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 2);
// uint8_t ts = cs_pdu_bits[18]; //accurate?
// uint8_t res = cs_pdu_bits[19]; //unknown??
// uint8_t rest_channel = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[20], 4);
// uint8_t ch[8]; //one bit per channel
// uint8_t tg = 0;
// uint32_t tghex = 0; //combined all tgs for debug
// int i, j, k;
// //tg and channel info for trunking purposes
// uint8_t t_tg[9];
// memset (t_tg, 0, sizeof(t_tg));
// k = 0;
// if (rest_channel != state->dmr_rest_channel)
// {
// state->dmr_rest_channel = rest_channel;
// }
// for (int i = 0; i < 8; i++)
// {
// ch[i] = cs_pdu_bits[i+24];
// }
// //assign to cc freq to follow during no sync
// if (state->trunk_chan_map[rest_channel] != 0)
// {
// state->p25_cc_freq = state->trunk_chan_map[rest_channel];
// //set to always tuned
// opts->p25_is_tuned = 1;
// }
}
SKIPCAP: ; //do nothing
}
// fprintf (stderr, " Capacity Plus Channel Status - FL: %d TS: %d RS: %d - Rest Channel %d", fl, ts, res, rest_channel);
// fprintf (stderr, "\n ");
// for (i = 0; i < 8; i++)
// {
// fprintf (stderr, "Ch%d: ", i+1);
// if (ch[i] != 0)
// {
// tg = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[k*8+32], 8);
// if (tg != 0) fprintf (stderr, " %03d ", tg);
// else fprintf (stderr, "Priv "); //observed 000s for TG value seem to appear during a Cap+ Private TXI call
// //add values to trunking tg/channel potentials
// t_tg[i] = tg;
// k++;
// }
// else if (i+1 == rest_channel) fprintf (stderr, "Rest ");
// else fprintf (stderr, "Idle ");
// if (i == 3) fprintf (stderr, "\n ");
// }
// tghex = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
// //fprintf (stderr, "\n TG Hex = 0x%06X", tghex);
// state->dmr_mfid = 0x10;
// sprintf (state->dmr_branding, "%s", "Motorola");
// sprintf (state->dmr_branding_sub, "%s", "Cap+ ");
// //nullify any previous TIII data (bugfix for bad assignments or system type switching)
// sprintf(state->dmr_site_parms, "%s", "");
// fprintf (stderr, "%s", KNRM);
// //Skip tuning group calls if group calls are disabled
// if (opts->trunk_tune_group_calls == 0) goto SKIPCAP;
// //don't tune if currently a vc on the current channel
// if ( (time(NULL) - state->last_vc_sync_time > 2) )
// {
// for (j = 0; j < 8; j++) //go through the channels stored looking for active ones to tune to
// {
// char mode[8]; //allow, block, digital, enc, etc
// //if we are using allow/whitelist mode, then write 'B' to mode for block
// //comparison below will look for an 'A' to write to mode if it is allowed
// if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
// for (int i = 0; i < state->group_tally; i++)
// {
// if (state->group_array[i].groupNumber == t_tg[j])
// {
// fprintf (stderr, " [%s]", state->group_array[i].groupName);
// strcpy (mode, state->group_array[i].groupMode);
// }
// }
// //no more 0 reporting, that was some bad code that caused that issue
// //without priority, this will tune the first one it finds (if group isn't blocked)
// if (t_tg[j] != 0 && state->p25_cc_freq != 0 && opts->p25_trunk == 1 && (strcmp(mode, "B") != 0) && (strcmp(mode, "DE") != 0))
// {
// if (state->trunk_chan_map[j+1] != 0) //if we have a valid frequency
// {
// //RIGCTL
// if (opts->use_rigctl == 1)
// {
// if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
// SetFreq(opts->rigctl_sockfd, state->trunk_chan_map[j+1]);
// state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
// opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
// j = 11; //break loop
// }
// //rtl_udp
// else if (opts->audio_in_type == 3)
// {
// rtl_udp_tune (opts, state, state->trunk_chan_map[j+1]);
// state->p25_vc_freq[0] = state->p25_vc_freq[1] = state->trunk_chan_map[j+1];
// opts->p25_is_tuned = 1;
// j = 11; //break loop
// }
// }
// }
// }
// }
// }
// SKIPCAP: ; //do nothing
// }
//Connect+ Section
if (csbk_fid == 0x06)

View File

@ -52,7 +52,7 @@ char * FM_banner[9] = {
" ██║ ██║ ╚═══██╗██║ ██║   ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
" ██████╔╝██████╔╝██████╔╝   ██║ ██║ ╚═╝ ██║███████╗",
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝",
" 'Lite' Edition v2.0.0-26-g6666424 Windows 32-bit RC2d "
" 'Lite' Edition v2.0.0-27-g630d3f3 Windows 32-bit RC3 "
};
int
@ -303,6 +303,7 @@ noCarrier (dsd_opts * opts, dsd_state * state)
//initialize unified dmr pdu 'superframe'
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
//init confirmed data individual block crc as invalid
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));
@ -804,9 +805,6 @@ initState (dsd_state * state)
//dmr trunking/ncurses stuff
state->dmr_rest_channel = -1; //init on -1
state->dmr_mfid = -1; //
state->dmr_tuned_lcn = -1; //logical slot, lcn * ts?
state->dmr_vc_lcn = -1; //
state->dmr_vc_lsn = -1;
//new nxdn stuff
state->nxdn_part_of_frame = 0;
@ -835,6 +833,7 @@ initState (dsd_state * state)
//initialize unified dmr pdu 'superframe'
memset (state->dmr_pdu_sf, 0, sizeof (state->dmr_pdu_sf));
memset (state->cap_plus_csbk_bits, 0, sizeof(state->cap_plus_csbk_bits));
//init confirmed data individual block crc as invalid
memset (state->data_block_crc_valid, 0, sizeof(state->data_block_crc_valid));

View File

@ -2053,7 +2053,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->ncurses_compact == 1)
{
printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-26-g6666424 RC2d");
printw ("| Digital Speech Decoder: Florida Man Edition - Win32 %s \n", "v2.0.0-27-g630d3f3 RC3");
}
if (opts->ncurses_compact == 0)
{
@ -2064,8 +2064,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (i == 1) printw (" ESC to Menu");
if (i == 2) printw (" 'q' to Quit ");
if (i == 4) printw (" MBElib %s", versionstr);
if (i == 5) printw (" %s ", "Win32 RC2d"); //printw (" %s \n", GIT_TAG);
if (i == 6) printw (" %s \n", "v2.0.0-26-g6666424"); //printw (" %s \n", GIT_TAG);
if (i == 5) printw (" %s ", "Win32 RC3"); //printw (" %s \n", GIT_TAG);
if (i == 6) printw (" %s \n", "v2.0.0-27-g630d3f3"); //printw (" %s \n", GIT_TAG);
else printw ("\n");
}
attroff(COLOR_PAIR(6)); //6