diff --git a/include/dsd.h b/include/dsd.h index c214014..205fb4b 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -651,6 +651,7 @@ typedef struct int lcn_freq_roll; //number we have 'rolled' to in search of the CC time_t last_cc_sync_time; //use this to start hunting for CC after signal lost time_t last_vc_sync_time; //flag for voice activity bursts, tune back on con+ after more than x seconds no voice + time_t last_active_time; //time the a 'call grant' was received, used to clear the active_channel strings after x seconds int is_con_plus; //con_plus flag for knowing its safe to skip payload channel after x seconds of no voice sync //new nxdn stuff diff --git a/src/dmr_csbk.c b/src/dmr_csbk.c index 57c05b2..80f98fc 100644 --- a/src/dmr_csbk.c +++ b/src/dmr_csbk.c @@ -45,7 +45,12 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 if(IrrecoverableErrors == 0 && CRCCorrect == 1) { - + //clear stale Active Channel messages here + if ( ((time(NULL) - state->last_active_time) > 3) && ((time(NULL) - state->last_vc_sync_time) > 3)) + { + memset (state->active_channel, 0, sizeof(state->active_channel)); + } + //update time to prevent random 'Control Channel Signal Lost' hopping //in the middle of voice call on current Control Channel (con+ and t3) state->last_cc_sync_time = time(NULL); @@ -99,6 +104,21 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 uint32_t target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24); uint32_t source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24); + //move mbc variables out of if statement + uint8_t mbc_lb = 0; // + uint8_t mbc_pf = 0; + uint8_t mbc_csbko = 0; + uint8_t mbc_res = 0; + uint8_t mbc_cc = 0; + uint8_t mbc_cdeftype = 0; + uint8_t mbc_res2 = 0; + unsigned long long int mbc_cdefparms = 0; + uint16_t mbc_lpchannum = 0; + uint16_t mbc_abs_tx_int = 0; + uint16_t mbc_abs_tx_step = 0; + uint16_t mbc_abs_rx_int = 0; + uint16_t mbc_abs_rx_step = 0; + fprintf (stderr, "\n"); //added my best guess as to how dsdplus arrives at a dmr channel value (seems pretty consistent) as C+ fprintf (stderr, " Ch [%03X] Cd [%04d] C+ [%04d] - TS [%d] - Target [%08d] - Source [%08d]", lpchannum, lpchannum, pluschannum, lcn, target, source); @@ -107,36 +127,33 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 if (lpchannum == 0xFFF) //This is from an MBC, signalling an absolute and not a logical { - //7.1.1.1.2 Channel Grant Absolute Parameters CG_AP appended MBC PDU - uint8_t mbc_lb = cs_pdu_bits[96]; // - uint8_t mbc_pf = cs_pdu_bits[97]; - uint8_t mbc_csbko = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[98], 6); - uint8_t mbc_res = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[104], 4); - uint8_t mbc_cc = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[108], 4); - uint8_t mbc_cdeftype = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[112], 4); //see 7.2.19.7 = 0 for channel parms, 1 through FFFF reserved - uint8_t mbc_res2 = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[116], 2); - unsigned long long int mbc_cdefparms = (unsigned long long int)ConvertBitIntoBytes(&cs_pdu_bits[118], 58); //see 7.2.19.7.1 + mbc_lb = cs_pdu_bits[96]; // + mbc_pf = cs_pdu_bits[97]; + mbc_csbko = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[98], 6); + mbc_res = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[104], 4); + mbc_cc = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[108], 4); + mbc_cdeftype = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[112], 4); //see 7.2.19.7 = 0 for channel parms, 1 through FFFF reserved + mbc_res2 = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[116], 2); + long long int mbc_cdefparms = (unsigned long long int)ConvertBitIntoBytes(&cs_pdu_bits[118], 58); //see 7.2.19.7.1 //this is how you read the 58 parm bits according to the appendix 7.2.19.7.1 if (mbc_cdeftype == 0) //if 0, then absolute channel parms { - uint16_t mbc_lpchannum = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[118], 12); - uint16_t mbc_abs_tx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[130], 10); - uint16_t mbc_abs_tx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[140], 13); - uint16_t mbc_abs_rx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[153], 10); - uint16_t mbc_abs_rx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[163], 13); + mbc_lpchannum = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[118], 12); + mbc_abs_tx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[130], 10); + mbc_abs_tx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[140], 13); + mbc_abs_rx_int = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[153], 10); + mbc_abs_rx_step = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[163], 13); //tx_int (Mhz) + (tx_step * 125) = tx_freq //rx_int (Mhz) + (rx_step * 125) = rx_freq fprintf (stderr, "\n"); fprintf (stderr, " ABS-CHAN [%03X][%04d] - RX INT [%d][%X] - RX STEP [%d][%X]", mbc_lpchannum, mbc_lpchannum, mbc_abs_rx_int, mbc_abs_rx_int, mbc_abs_rx_step, mbc_abs_rx_step ); - //DOULBE CHECK APPENDIX C - C.1.1.2 Fixed Channel Plan for accurate information (found it after figuring out calc, so might be worth double checking) //The Frequency we want to tune is the RX Frequency freq = (mbc_abs_rx_int * 1000000 ) + (mbc_abs_rx_step * 125); - //tx_freq = (mbc_abs_tx_int * 1000000 ) + (mbc_abs_tx_step * 125); - } + else fprintf (stderr, "\n MBC Channel Grant - Unknown Parms: %015llX", mbc_cdefparms); //for any reserved values } //print frequency from absolute @@ -150,9 +167,20 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 } //add active channel string to display - //NOTE: Need to reconfigure mbc variables so I can print them here when needed, just using abs freq for now - if (lpchannum != 0 && lpchannum != 0xFFF) sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", lpchannum, target); - else if (lpchannum == 0xFFF) sprintf (state->active_channel[0], "Active Freq: %.6lf TG: %d; ", (double)freq/1000000, target); + if (lpchannum != 0 && lpchannum != 0xFFF) + { + if (csbk_o == 49 || csbk_o == 50) sprintf (state->active_channel[lcn], "Active Group Ch: %d TG: %d; ", lpchannum, target); + else if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54) sprintf (state->active_channel[lcn], "Active Data Ch: %d TG: %d; ", lpchannum, target); + else sprintf (state->active_channel[lcn], "Active Private Ch: %d TG: %d; ", lpchannum, target); + } + else if (lpchannum == 0xFFF) + { + if (csbk_o == 49 || csbk_o == 50) sprintf (state->active_channel[lcn], "Active Group Ch: %d TG: %d; ", mbc_lpchannum, target); + else if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54) sprintf (state->active_channel[lcn], "Active Data Ch: %d TG: %d; ", mbc_lpchannum, target); + else sprintf (state->active_channel[lcn], "Active Private Ch: %d TG: %d; ", mbc_lpchannum, target); + } + //update last active channel time + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0 && csbk_o == 49) goto SKIPCALL; //TV_GRANT @@ -883,6 +911,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 //additive strings for active channels memset (state->active_channel, 0, sizeof(state->active_channel)); sprintf (state->active_channel[0], "Cap+ "); + state->last_active_time = time(NULL); k = 0; x = 0; @@ -1106,6 +1135,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 //add active channel string for display sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", lcn, grpAddr); + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0) goto SKIPCON; @@ -1230,6 +1260,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8 char xpt_active[20]; if (xpt_seq == 0) sprintf (state->active_channel[0], "XPT "); //add initial if sequence 0 else sprintf (state->active_channel[xpt_seq], "%s", ""); //blank current sequence to re-write to + state->last_active_time = time(NULL); //Print List of LCN with LSN Activity for (i = 0; i < 6; i++) diff --git a/src/dsd_main.c b/src/dsd_main.c index fe918f1..bf3b484 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -856,6 +856,7 @@ initState (dsd_state * state) state->lcn_freq_roll = 0; //needs reset if sync is found? state->last_cc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL); + state->last_active_time = time(NULL); state->is_con_plus = 0; //dmr trunking/ncurses stuff diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 759427b..f16d25d 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2308,6 +2308,28 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } printw ("]"); } + + //Group Name Labels from CSV import + for (int k = 0; k < state->group_tally; k++) + { + if (state->group_array[k].groupNumber == tgn) + { + attron(COLOR_PAIR(4)); + printw (" [%s]", state->group_array[k].groupName); + printw ("[%s] ", state->group_array[k].groupMode); + } + else if (state->group_array[k].groupNumber == src) + { + attron(COLOR_PAIR(4)); + printw (" [%s]", state->group_array[k].groupName); + printw ("[%s] ", state->group_array[k].groupMode); + } + if (state->carrier == 1) + { + attron(COLOR_PAIR(3)); + } + } + if (state->carrier == 1) { printw(" %s ", state->nxdn_call_type); diff --git a/src/nxdn_element.c b/src/nxdn_element.c index de1a095..7fd55a0 100644 --- a/src/nxdn_element.c +++ b/src/nxdn_element.c @@ -96,6 +96,8 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, //SRV_INFO case 0x19: + state->nxdn_last_rid = 0; + state->nxdn_last_tg = 0; NXDN_decode_srv_info(opts, state, ElementsContent); break; @@ -124,6 +126,7 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, //DISC case 0x11: NXDN_decode_VCALL(opts, state, ElementsContent); + memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment)); //tune back to CC here - save about 1-2 seconds if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) @@ -461,6 +464,8 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa if (state->nxdn_rcn == 1) sprintf (state->active_channel[0], "Active Ch: %d TG: %d; ", OFN, DestinationID); + state->last_active_time = time(NULL); + //Add support for tuning data and group/private calls on trunking systems uint8_t tune = 0; @@ -606,14 +611,14 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa void NXDN_decode_Alias(dsd_opts * opts, dsd_state * state, uint8_t * Message) { - uint8_t Alias1 = 0x0; //value of an ascii 'NULL' character - uint8_t Alias2 = 0x0; - uint8_t Alias3 = 0x0; - uint8_t Alias4 = 0x0; + uint8_t Alias1 = 0x20; //value of an ascii 'space' character + uint8_t Alias2 = 0x20; + uint8_t Alias3 = 0x20; + uint8_t Alias4 = 0x20; uint8_t blocknumber = 0; uint8_t CrcCorrect = 0; - //alias can also hit on a facch1 so that would be with a non_sf_sacch attached + //alias can also hit on a facch1 -- do we still need this checkdown? if (state->nxdn_sacch_non_superframe == FALSE) { CrcCorrect = state->NxdnElementsContent.VCallCrcIsGood; @@ -628,25 +633,25 @@ void NXDN_decode_Alias(dsd_opts * opts, dsd_state * state, uint8_t * Message) Alias3 = (uint8_t)ConvertBitIntoBytes(&Message[56], 8); Alias4 = (uint8_t)ConvertBitIntoBytes(&Message[64], 8); //sanity check to prevent OOB array assignment - if (blocknumber > 0 && blocknumber < 5) + if (blocknumber > 0 && blocknumber < 4) //last 'block' may have been assigning garbage name values -- needs testing { //assign to index -1, since block number conveyed here is 1,2,3,4, and index values are 0,1,2,3 //only assign if within valid range of ascii characters (not including diacritical extended alphabet) - //else assign "null" ascii character + //else assign "space" ascii character //since we are zeroing out the blocks on tx_rel and other conditions, better to just set nothing to bad Alias bytes //tends to zero out otherwise already good blocks set in a previous repitition. if (Alias1 > 0x19 && Alias1 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", Alias1); - else ;// sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", 0); + else ;// sprintf (state->nxdn_alias_block_segment[blocknumber-1][0], "%c", 32); //space if (Alias2 > 0x19 && Alias2 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", Alias2); - else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", 0); + else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][1], "%c", 0); //space if (Alias3 > 0x19 && Alias3 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", Alias3); - else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", 0); + else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][2], "%c", 0); //space if (Alias4 > 0x19 && Alias4 < 0x7F) sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", Alias4); - else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", 0); + else ; //sprintf (state->nxdn_alias_block_segment[blocknumber-1][3], "%c", 0); //space } //crc errs in one repitition may occlude an otherwise good alias, so test and change if needed @@ -803,6 +808,12 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message) } } + //clear stale active channel listing -- consider best placement for this (NXDN Type C Trunking -- inside SRV_INFO) + if ( (time(NULL) - state->last_active_time) > 3 ) + { + memset (state->active_channel, 0, sizeof(state->active_channel)); + } + } void NXDN_decode_site_info(dsd_opts * opts, dsd_state * state, uint8_t * Message) @@ -1291,12 +1302,20 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin //OSM messages if (opcode == 0x4 || opcode == 0x0) //INFO 4 { + //clear stale active channel listing -- consider best placement for this (NXDN Type D Trunking -- inside a particular OSM Message?) + if ( (time(NULL) - state->last_active_time) > 3 ) + { + memset (state->active_channel, 0, sizeof(state->active_channel)); + } + if (id == 2046) { fprintf (stderr, "Idle Repeater Message - "); fprintf (stderr, "Area: %d; ", area); fprintf (stderr, "Repeater 1: %d; ", rep1); fprintf (stderr, "Repeater 2: %d; ", rep2); + sprintf (state->active_channel[rep1], "%s", ""); + sprintf (state->active_channel[rep2], "%s", ""); } else if (id == 2045) @@ -1366,6 +1385,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin { if (gu == 0) sprintf (state->active_channel[rep1], "Active Ch: %d TG: %d-%d; ", rep1, rep2, id); //Group TG else sprintf (state->active_channel[rep1], "Active Ch: %d TGT: %d-%d; ", rep1, rep2, id); //Private TGT + state->last_active_time = time(NULL); } //start tuning section here diff --git a/src/p25_lcw.c b/src/p25_lcw.c index 3d58018..ea4cff5 100644 --- a/src/p25_lcw.c +++ b/src/p25_lcw.c @@ -1,3 +1,11 @@ +/*------------------------------------------------------------------------------- + * p25_lcw.c + * P25p1 Link Control Word Decoding + * + * LWVMOBILE + * 2023-05 DSD-FME Florida Man Edition + *-----------------------------------------------------------------------------*/ + #include "dsd.h" //new p25_lcw function here -- TIA-102.AABF-D LCW Format Messages (if anybody wants to fill the rest out) @@ -94,12 +102,14 @@ void p25_lcw (dsd_opts * opts, dsd_state * state, uint8_t LCW_bits[], uint8_t ir { fprintf (stderr, "Ch: %04X TG: %d; ", channel1, group1); sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; ", channel1, group1); + state->last_active_time = time(NULL); } if (channel2 && group2 && group1 != group2) { fprintf (stderr, "Ch: %04X TG: %d; ", channel2, group2); sprintf (state->active_channel[1], "Active Ch: %04X TG: %d; ", channel2, group2); + state->last_active_time = time(NULL); } } diff --git a/src/p25p1_mdpu.c b/src/p25p1_mdpu.c index 1e0fa98..bfbb4a1 100644 --- a/src/p25p1_mdpu.c +++ b/src/p25p1_mdpu.c @@ -28,6 +28,12 @@ void processMPDU(dsd_opts * opts, dsd_state * state) //reset some strings when returning from a call in case they didn't get zipped already sprintf (state->call_string[0], "%s", " "); //21 spaces sprintf (state->call_string[1], "%s", " "); //21 spaces + + //clear stale Active Channel messages here + if ( (time(NULL) - state->last_active_time) > 3 ) + { + memset (state->active_channel, 0, sizeof(state->active_channel)); + } int tsbkbit[196]; //tsbk bit array, 196 trellis encoded bits int tsbk_dibit[98]; @@ -306,6 +312,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state) //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TG: %d ", channelt, group); + state->last_active_time = time(NULL); for (int i = 0; i < state->group_tally; i++) { @@ -346,6 +353,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state) SetFreq(opts->rigctl_sockfd, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -353,6 +361,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state) rtl_udp_tune (opts, state, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } @@ -428,7 +437,8 @@ void processMPDU(dsd_opts * opts, dsd_state * state) if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -436,6 +446,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state) rtl_udp_tune (opts, state, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } diff --git a/src/p25p1_tsbk.c b/src/p25p1_tsbk.c index 4d2a239..b6b22f1 100644 --- a/src/p25p1_tsbk.c +++ b/src/p25p1_tsbk.c @@ -14,6 +14,12 @@ void processTSBK(dsd_opts * opts, dsd_state * state) //reset some strings when returning from a call in case they didn't get zipped already sprintf (state->call_string[0], "%s", " "); //21 spaces sprintf (state->call_string[1], "%s", " "); //21 spaces + + //clear stale Active Channel messages here + if ( (time(NULL) - state->last_active_time) > 3 ) + { + memset (state->active_channel, 0, sizeof(state->active_channel)); + } int tsbkbit[196]; //tsbk bit array, 196 trellis encoded bits int tsbk_dibit[98]; diff --git a/src/p25p2_frame.c b/src/p25p2_frame.c index cddddea..2d33f53 100644 --- a/src/p25p2_frame.c +++ b/src/p25p2_frame.c @@ -711,6 +711,7 @@ void process_P2_DUID (dsd_opts * opts, dsd_state * state) { opts->p25_is_tuned = 0; state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0; + memset (state->active_channel, 0, sizeof (state->active_channel)); //zero out here? I think this will be fine } if (duid_decoded == 0) diff --git a/src/p25p2_vpdu.c b/src/p25p2_vpdu.c index b72941b..33563b7 100644 --- a/src/p25p2_vpdu.c +++ b/src/p25p2_vpdu.c @@ -98,6 +98,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; ", channel, sgroup); + state->last_active_time = time(NULL); for (int i = 0; i < state->group_tally; i++) { @@ -144,7 +145,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -152,6 +154,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } @@ -180,6 +183,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d ", channel, sgroup); + state->last_active_time = time(NULL); for (int i = 0; i < state->group_tally; i++) { @@ -225,7 +229,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -233,6 +238,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } @@ -268,6 +274,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; Ch: %04X SG: %d; ", channel1, group1, channel2, group2); + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; @@ -341,7 +348,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon SetFreq(opts->rigctl_sockfd, tunable_freq); //probably best to only set these when really tuning state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); j = 8; //break loop } @@ -351,6 +359,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, tunable_freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); j = 8; //break loop } } @@ -399,6 +408,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; ", channel, group); + state->last_active_time = time(NULL); for (int i = 0; i < state->group_tally; i++) { @@ -449,6 +459,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon SetFreq(opts->rigctl_sockfd, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -456,6 +467,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } @@ -488,6 +500,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TGT: %d; ", channel, target); + state->last_active_time = time(NULL); //Skip tuning private calls if private calls is disabled if (opts->trunk_tune_private_calls == 0) goto SKIPCALL; @@ -538,7 +551,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, freq); if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -546,6 +560,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, freq); if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } } @@ -591,7 +606,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, " Priority %d", svc1 & 0x7); //call priority } freq1t = process_channel_to_freq (opts, state, channelt1); - freq1r = process_channel_to_freq (opts, state, channelr1); + if (channelr1 != 0 && channelr1 != 0xFFFF) freq1r = process_channel_to_freq (opts, state, channelr1); fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc2, channelt2, channelr2, group2, group2); if (svc2 & 0x80) fprintf (stderr, " Emergency"); @@ -605,10 +620,11 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, " Priority %d", svc2 & 0x7); //call priority } freq1t = process_channel_to_freq (opts, state, channelt2); - freq1r = process_channel_to_freq (opts, state, channelr2); + if (channelr2 != 0 && channelr2 != 0xFFFF) freq1r = process_channel_to_freq (opts, state, channelr2); //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channelt1, group1, channelt2, group2); + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; @@ -690,7 +706,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, tunable_freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); j = 8; //break loop } //rtl_udp @@ -699,6 +716,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, tunable_freq); state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); j = 8; //break loop } } @@ -774,6 +792,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2, channel3, group3); + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; @@ -866,7 +885,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon SetFreq(opts->rigctl_sockfd, tunable_freq); //probably best to only set these when really tuning state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); j = 8; //break loop } //rtl_udp @@ -876,6 +896,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //probably best to only set these when really tuning state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); j = 8; //break loop } } @@ -911,6 +932,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //add active channel to string for ncurses display sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2); + state->last_active_time = time(NULL); //Skip tuning group calls if group calls are disabled if (opts->trunk_tune_group_calls == 0) goto SKIPCALL; @@ -986,6 +1008,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //probably best to only set these when really tuning state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); j = 8; //break loop } //rtl_udp @@ -995,6 +1018,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon //probably best to only set these when really tuning state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); j = 8; //break loop } } @@ -1038,7 +1062,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, " Group Voice Channel Grant Update - Explicit"); fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc, channelt, channelr, group, group); freq1 = process_channel_to_freq (opts, state, channelt); - freq2 = process_channel_to_freq (opts, state, channelr); + if (channelr != 0 && channelr != 0xFFFF) freq2 = process_channel_to_freq (opts, state, channelr); //one system had this as channel 0xFFFF -- look up any particular meaning for that //don't set the tg here, one multiple grant updates, will mess up the TG value on current call // if (slot == 0) @@ -1095,7 +1119,8 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); SetFreq(opts->rigctl_sockfd, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; - opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); } //rtl_udp else if (opts->audio_in_type == 3) @@ -1103,6 +1128,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon rtl_udp_tune (opts, state, freq1); state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); } } }