DMR rc crc7 fix and rc element decode #187; fix/revamp p_clear and p_protect trunking logic; MTL patch; g_dmr patch; Misc;

This commit is contained in:
lwvmobile
2024-02-05 11:11:56 -05:00
parent ffa8b053d7
commit ed85d508ed
10 changed files with 793 additions and 113 deletions

View File

@@ -313,11 +313,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr,"%s ", getTime());
//simplifying things
char polarity[3];
// char polarity[3];
char light[18];
sprintf (light, "%s", " [SLOT1] slot2 ");
fprintf (stderr,"Sync: %sDMR %s", polarity, light);
fprintf (stderr,"Sync: DMR %s", light);
fprintf (stderr, "%s", KCYN);
fprintf (stderr, "| Frame Sync Err: %d", vc1);
fprintf (stderr, "%s", KNRM);
@@ -334,11 +334,11 @@ void dmrBS (dsd_opts * opts, dsd_state * state)
fprintf (stderr,"%s ", getTime());
//simplifying things
char polarity[3];
// char polarity[3];
char light[18];
sprintf (light, "%s", " slot1 [SLOT2] ");
fprintf (stderr,"Sync: %sDMR %s", polarity, light);
fprintf (stderr,"Sync: DMR %s", light);
fprintf (stderr, "%s", KCYN);
fprintf (stderr, "| Frame Sync Err: %d", vc2);
fprintf (stderr, "%s", KNRM);

View File

@@ -380,90 +380,150 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//NOTE: Do not zero out lasttg/lastsrc in TLC FLCO when using p_clear, otherwise,
//it will affect the conditions below and fail to trigger on tg_hold
//test misc conditions to trigger a clear and immediately return to CC
//test misc conditions to trigger a clear and immediately return to CC, or remain on current VC;
int clear = 0;
int pslot = state->currentslot; //this slot
int oslot = (state->currentslot ^ 1) & 1; //opposite slot
pslot++; oslot++; //set to 1 and 2 and not 0 and 1
//if no voice activity or data call (when enabled) within trunk_hangtime seconds
if ( ((time(NULL) - state->last_vc_sync_time) > opts->trunk_hangtime) && opts->trunk_tune_data_calls == 0) clear = 1;
//if the other slot is IDLE or TLC condition -- May consider disabling this one
// if (state->currentslot == 0 && (state->dmrburstR == 9 && state->dmrburstR == 7)) clear = 1;
// if (state->currentslot == 0 && (state->dmrburstL == 9 && state->dmrburstL == 7)) clear = 1;
//if no voice in the opposite slot currently or data call (when enabled) -- might can disable data call condition here
if (state->currentslot == 0 && state->dmrburstR != 16) clear = 2; //&& opts->trunk_tune_data_calls == 0
if (state->currentslot == 1 && state->dmrburstL != 16) clear = 3; //&& opts->trunk_tune_data_calls == 0
//if no voice header, pi header, or voice sync in the opposite slot currently
if (state->currentslot == 0 && (state->dmrburstR != 16 && state->dmrburstR != 0 && state->dmrburstR != 1)) clear = 2;
if (state->currentslot == 1 && (state->dmrburstL != 16 && state->dmrburstL != 0 && state->dmrburstL != 1)) clear = 3;
//if we have a tg hold in place that matches traffic that was just on this slot (this will override other calls in the opposite slot)
if (state->currentslot == 0 && state->tg_hold == state->lasttg && state->tg_hold != 0) clear = 4;
if (state->currentslot == 1 && state->tg_hold == state->lasttgR && state->tg_hold != 0) clear = 5;
if (state->currentslot == 1 && state->tg_hold == state->lasttgR && state->tg_hold != 0) clear = 5;
//if tuning and decoding data is desired, then do a secondary check here for data headers and blocks in the opposite slot
if (opts->trunk_tune_data_calls == 1)
{
//if no data header or data block sync in the opposite slot currently
if (state->currentslot == 0 && (state->dmrburstR == 6 || state->dmrburstR == 7 || state->dmrburstR == 8 || state->dmrburstR == 10)) clear = 21;
if (state->currentslot == 1 && (state->dmrburstL == 6 || state->dmrburstL == 7 || state->dmrburstL == 8 || state->dmrburstL == 10)) clear = 22;
}
//initial line break
fprintf (stderr, "\n");
fprintf (stderr, " Clear (P_CLEAR) %d", clear);
fprintf (stderr, " Clear (P_CLEAR) ");
#ifdef PCLEAR_TUNE_AWAY
//check to see if this is a dummy csbk sent from link control to signal return to tscc
if (clear && csbk_fid == 255) fprintf (stderr, " No Encrypted Call Trunking; Return to CC; ");
if (!clear && csbk_fid == 255) fprintf (stderr, " No Encrypted Call Trunking; Other Slot Busy; ");
if (clear)
if (opts->p25_trunk == 1)
{
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
//check the p_clear logic and report status
if (clear && csbk_fid == 255) fprintf (stderr, " Slot %d No Encrypted Call Trunking; Slot %d Free; Return to CC; ", pslot, oslot);
else if (!clear && csbk_fid == 255) fprintf (stderr, " Slot %d No Encrypted Call Trunking; Slot %d Busy; Remain on VC;", pslot, oslot);
else if (!clear) fprintf (stderr, " Slot %d Clear; Slot %d Busy; Remain on VC;", pslot, oslot);
else if (clear == 1) fprintf (stderr, " Slot %d Clear; Slot %d Idle; Return to CC;", pslot, oslot);
else if (clear == 2 || clear == 3) fprintf (stderr, " Slot %d Clear; Slot %d Free; Return to CC;", pslot, oslot);
else if (clear == 4 || clear == 5) fprintf (stderr, " Slot %d Clear w/ TG Hold %d; Slot %d Activity Override; Return to CC; ", pslot, state->tg_hold, oslot);
//NOTE: Below clears are just conditions for reporting, and not clear to tune away, so they are set back to zero
else if (clear == 21 || clear == 22)
{
//display/le bug fix when p_clear activated
// if (state->currentslot == 0)
// {
// state->payload_mi = 0;
// state->payload_algid = 0;
// state->payload_keyid = 0;
// state->dmr_so = 0;
// }
// if (state->currentslot == 1)
// {
// state->payload_miR = 0;
// state->payload_algidR = 0;
// state->payload_keyidR = 0;
// state->dmr_soR = 0;
// }
//rigctl
if (opts->use_rigctl == 1)
{
//Guess I forgot to add this condition here
if (GetCurrentFreq(opts->rigctl_sockfd) != state->p25_cc_freq)
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away from current frequency
//reset some strings
sprintf (state->call_string[state->currentslot], "%s", " "); //21 spaces
sprintf (state->active_channel[state->currentslot], "%s", "");
state->last_vc_sync_time = 0;
state->last_cc_sync_time = time(NULL);
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
if (GetCurrentFreq(opts->rigctl_sockfd) != state->p25_cc_freq)
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//Guess I forgot to add this condition here
uint32_t tempf = (uint32_t)state->p25_cc_freq;
if (opts->rtlsdr_center_freq != tempf)
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away from current frequency
//reset some strings
sprintf (state->call_string[state->currentslot], "%s", " "); //21 spaces
sprintf (state->active_channel[state->currentslot], "%s", "");
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = 0;
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->rtlsdr_center_freq != tempf)
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
fprintf (stderr, " Slot %d Clear; Slot %d Data; Remain on DC;", pslot, oslot);
clear = 0; //flag as 0 so we won't tune away until data call is completed
}
}
#endif
if (clear)
{
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
{
//display/le/buzzer bug fix when p_clear activated (unsure why this was disabled)
//clear only the current slot initially, then clear both if tuning to a different freq
if (state->currentslot == 0)
{
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
}
if (state->currentslot == 1)
{
state->payload_miR = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmr_soR = 0;
}
//rigctl
if (opts->use_rigctl == 1)
{
//Guess I forgot to add this condition here
if (GetCurrentFreq(opts->rigctl_sockfd) != state->p25_cc_freq)
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away from current frequency
//clear both if tuning away to another frequency
if (GetCurrentFreq(opts->rigctl_sockfd) != state->p25_cc_freq)
{
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
state->payload_miR = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmr_soR = 0;
}
//reset some strings
sprintf (state->call_string[state->currentslot], "%s", " "); //21 spaces
sprintf (state->active_channel[state->currentslot], "%s", "");
state->last_vc_sync_time = 0;
state->last_cc_sync_time = time(NULL);
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
if (GetCurrentFreq(opts->rigctl_sockfd) != state->p25_cc_freq)
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
//Guess I forgot to add this condition here
uint32_t tempf = (uint32_t)state->p25_cc_freq;
if (opts->rtlsdr_center_freq != tempf)
dmr_reset_blocks (opts, state); //reset all block gathering since we are tuning away from current frequency
//clear both if tuning away to another frequency
if (opts->rtlsdr_center_freq != tempf)
{
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
state->payload_miR = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmr_soR = 0;
}
//reset some strings
sprintf (state->call_string[state->currentslot], "%s", " "); //21 spaces
sprintf (state->active_channel[state->currentslot], "%s", "");
state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = 0;
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->rtlsdr_center_freq != tempf)
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
}
}
} //end if trunking is enabled
#else
UNUSED (clear); UNUSED(pslot); UNUSED(oslot);
#endif //end if PCLEAR_TUNE_AWAY is enabled in code
}
//(P_PROTECT)
@@ -493,6 +553,21 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
//check the source and/or target for special gateway identifiers
dmr_gateway_identifier (source, target);
//change this slot burst type to VLC so the revamped p_clear doesn't tune away
if (opts->p25_trunk == 1)
{
if (gi && opts->trunk_tune_group_calls == 1)
{
if (state->currentslot == 0) state->dmrburstL = 1;
else state->dmrburstR = 1;
}
if (!gi && opts->trunk_tune_private_calls == 1)
{
if (state->currentslot == 0) state->dmrburstL = 1;
else state->dmrburstR = 1;
}
}
}
if (csbk_o == 40) //0x28

View File

@@ -354,6 +354,19 @@ dmr_data_sync (dsd_opts * opts, dsd_state * state)
memset (state->active_channel, 0, sizeof(state->active_channel));
state->last_cc_sync_time = time(NULL);
state->is_con_plus = 0; //con+ flag off
//display/le/buzzer bug fix when con+ cc return (bug not observed here,
//but could happen like it does on TIII with mixed enc and clear calls w/ ENC LO is activated)
state->payload_mi = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmr_so = 0;
state->payload_miR = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmr_soR = 0;
}
}

View File

@@ -445,18 +445,18 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
//if group doesn't exist, or isn't locked out, then do so now.
if (lo == 0)
{
{ //changing from DE to B to fit the rest of the lockout logic ("Buzzer Fix")
state->group_array[state->group_tally].groupNumber = target;
sprintf (state->group_array[state->group_tally].groupMode, "%s", "DE");
sprintf (state->group_array[state->group_tally].groupMode, "%s", "B");
sprintf (state->group_array[state->group_tally].groupName, "%s", "ENC LO");
sprintf (gm, "%s", "DE");
sprintf (gm, "%s", "B");
sprintf (gn, "%s", "ENC LO");
state->group_tally++;
}
//Craft a fake CSBK pdu send it to run as a p_clear to return to CC if available
uint8_t dummy[12]; uint8_t* dbits; memset (dummy, 0, sizeof(dummy)); dummy[0] = 46; dummy[1] = 255;
if ( (strcmp(gm, "DE") == 0) && (strcmp(gn, "ENC LO") == 0) ) //&& (opts->trunk_tune_data_calls == 0)
if ( (strcmp(gm, "B") == 0) && (strcmp(gn, "ENC LO") == 0) ) //&& (opts->trunk_tune_data_calls == 0)
dmr_cspdu (opts, state, dbits, dummy, 1, 0);
}

View File

@@ -252,7 +252,7 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
crc_extracted = crc_extracted | sbrc_return[i+4];
}
crc_extracted = crc_extracted ^ 0x7A;
crc_computed = crc7((uint8_t *) sbrc_return, 7);
crc_computed = crc7((uint8_t *) sbrc_return, 4); //#187 fix
if (crc_extracted == crc_computed) crc7_okay = 1;
}
else //if (txi == 1) //if TXI -- but TXI systems also carry the non-crc protected ENC identifiers
@@ -332,7 +332,18 @@ void dmr_sbrc (dsd_opts * opts, dsd_state * state, uint8_t power)
else if (crc7_okay == 1)
{
//do something with the reverse channel information
//decode the reverse channel information ETSI TS 102 361-4 V1.12.1 (2023-07) p 103 Table 6.32: MS Reverse Channel (RC) Command Information Elements
if (opts->payload == 0) fprintf (stderr, "\n");
fprintf (stderr, "%s", KCYN);
sbrc_hex = sbrc_hex >> 7; //set value to its 4-bit form
if (sbrc_hex == 0) fprintf (stderr, " RC: Increase Power By One Step;");
else if (sbrc_hex == 1) fprintf (stderr, " RC: Decrease Power By One Step;");
else if (sbrc_hex == 2) fprintf (stderr, " RC: Set Power To Highest;");
else if (sbrc_hex == 3) fprintf (stderr, " RC: Set Power To Lowest;");
else if (sbrc_hex == 4) fprintf (stderr, " RC: Cease Transmission Command;");
else if (sbrc_hex == 5) fprintf (stderr, " RC: Cease Transmission Request;");
else fprintf (stderr, " RC: Reserved %02X;", sbrc_hex);
fprintf (stderr, "%s", KNRM);
}
//if the call is interruptable (TXI) and the crc3 is okay and TXI Opcode

View File

@@ -17,6 +17,13 @@ void dmr_pi (dsd_opts * opts, dsd_state * state, uint8_t PI_BYTE[], uint32_t CRC
if((IrrecoverableErrors == 0))
{
//update cc amd vc sync time for trunking purposes (particularly Con+)
if (opts->p25_is_tuned == 1)
{
state->last_vc_sync_time = time(NULL);
state->last_cc_sync_time = time(NULL);
}
if (state->currentslot == 0)
{
state->payload_algid = PI_BYTE[0];

View File

@@ -817,9 +817,9 @@ void playSynthesizedVoiceSS (dsd_opts * opts, dsd_state * state)
state->audio_out_idx = 0;
state->audio_out_idxR = 0;
//set float temp buffer to baseline
memset (state->s_l, 1, sizeof(state->s_l));
memset (state->s_r, 1, sizeof(state->s_r));
//set short temp buffer to baseline
memset (state->s_l, 0, sizeof(state->s_l));
memset (state->s_r, 0, sizeof(state->s_r));
if (state->audio_out_idx2 >= 800000)
{
@@ -855,9 +855,9 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
short stereo_samp2[320]; //8k 2-channel stereo interleave mix
short stereo_samp3[320]; //8k 2-channel stereo interleave mix
memset (stereo_samp1, 1, sizeof(stereo_samp1));
memset (stereo_samp2, 1, sizeof(stereo_samp2));
memset (stereo_samp3, 1, sizeof(stereo_samp3));
memset (stereo_samp1, 0, sizeof(stereo_samp1));
memset (stereo_samp2, 0, sizeof(stereo_samp2));
memset (stereo_samp3, 0, sizeof(stereo_samp3));
//dmr enc checkdown for whether or not to fill the stereo sample or not for playback or writing
encL = encR = 0;
@@ -1007,9 +1007,9 @@ void playSynthesizedVoiceSS3 (dsd_opts * opts, dsd_state * state)
state->audio_out_idx = 0;
state->audio_out_idxR = 0;
//set float temp buffer to baseline
memset (state->s_l4, 1, sizeof(state->s_l4));
memset (state->s_r4, 1, sizeof(state->s_r4));
//set short temp buffer to baseline
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
if (state->audio_out_idx2 >= 800000)
{
@@ -1048,12 +1048,12 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
short empty[320]; //this is used to see if we want to play a single 2v or double 2v or not
memset (stereo_samp1, 1, sizeof(stereo_samp1));
memset (stereo_samp2, 1, sizeof(stereo_samp2));
memset (stereo_samp3, 1, sizeof(stereo_samp3));
memset (stereo_samp4, 1, sizeof(stereo_samp4));
memset (stereo_samp1, 0, sizeof(stereo_samp1));
memset (stereo_samp2, 0, sizeof(stereo_samp2));
memset (stereo_samp3, 0, sizeof(stereo_samp3));
memset (stereo_samp4, 0, sizeof(stereo_samp4));
memset (empty, 1, sizeof(empty));
memset (empty, 0, sizeof(empty));
//p25p2 enc checkdown for whether or not to fill the stereo sample or not for playback or writing
@@ -1214,9 +1214,9 @@ void playSynthesizedVoiceSS4 (dsd_opts * opts, dsd_state * state)
state->audio_out_idx = 0;
state->audio_out_idxR = 0;
//set float temp buffer to baseline
memset (state->s_l4, 1, sizeof(state->s_l4));
memset (state->s_r4, 1, sizeof(state->s_r4));
//set short temp buffer to baseline
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
if (state->audio_out_idx2 >= 800000)
{

View File

@@ -527,15 +527,15 @@ if(opts->frame_m17 == 1) //&& opts->audio_in_type == 5
memset (state->f_r4, 0.0f, sizeof(state->f_r4));
//zero out the short sample storage buffers
memset (state->s_l, 1, sizeof(state->s_l));
memset (state->s_r, 1, sizeof(state->s_r));
memset (state->s_l4, 1, sizeof(state->s_l4));
memset (state->s_r4, 1, sizeof(state->s_r4));
memset (state->s_l, 0, sizeof(state->s_l));
memset (state->s_r, 0, sizeof(state->s_r));
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
memset (state->s_lu, 1, sizeof(state->s_lu));
memset (state->s_ru, 1, sizeof(state->s_ru));
memset (state->s_l4u, 1, sizeof(state->s_l4u));
memset (state->s_r4u, 1, sizeof(state->s_r4u));
memset (state->s_lu, 0, sizeof(state->s_lu));
memset (state->s_ru, 0, sizeof(state->s_ru));
memset (state->s_l4u, 0, sizeof(state->s_l4u));
memset (state->s_r4u, 0, sizeof(state->s_r4u));
} //nocarrier
@@ -792,15 +792,15 @@ initState (dsd_state * state)
memset (state->f_r4, 0.0f, sizeof(state->f_r4));
//zero out the short sample storage buffers
memset (state->s_l, 1, sizeof(state->s_l));
memset (state->s_r, 1, sizeof(state->s_r));
memset (state->s_l4, 1, sizeof(state->s_l4));
memset (state->s_r4, 1, sizeof(state->s_r4));
memset (state->s_l, 0, sizeof(state->s_l));
memset (state->s_r, 0, sizeof(state->s_r));
memset (state->s_l4, 0, sizeof(state->s_l4));
memset (state->s_r4, 0, sizeof(state->s_r4));
memset (state->s_lu, 1, sizeof(state->s_lu));
memset (state->s_ru, 1, sizeof(state->s_ru));
memset (state->s_l4u, 1, sizeof(state->s_l4u));
memset (state->s_r4u, 1, sizeof(state->s_r4u));
memset (state->s_lu, 0, sizeof(state->s_lu));
memset (state->s_ru, 0, sizeof(state->s_ru));
memset (state->s_l4u, 0, sizeof(state->s_l4u));
memset (state->s_r4u, 0, sizeof(state->s_r4u));
state->audio_out_buf = malloc (sizeof (short) * 1000000);
state->audio_out_bufR = malloc (sizeof (short) * 1000000);