diff --git a/include/dsd.h b/include/dsd.h index b69abaa..e572674 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -599,9 +599,11 @@ typedef struct int p25_chan_spac[16]; long int p25_base_freq[16]; - //p25 frequency storage for display in ncurses + //p25 frequency storage for trunking and display in ncurses long int p25_cc_freq; //cc freq from net_stat long int p25_vc_freq[2]; //vc freq from voice grant updates, etc + int p25_cc_is_tdma; //flag to tell us that the P25 control channel is TDMA so we can change symbol rate when required + //experimental symbol file capture read throttle int symbol_throttle; //throttle speed diff --git a/src/dsd_frame_sync.c b/src/dsd_frame_sync.c index 7d5363e..f9b2bf8 100644 --- a/src/dsd_frame_sync.c +++ b/src/dsd_frame_sync.c @@ -152,6 +152,13 @@ getFrameSync (dsd_opts * opts, dsd_state * state) //will need to assign frequencies to a CC array for P25 since that isn't imported from CSV if (opts->p25_is_tuned == 0 && opts->p25_trunk == 1 && time(NULL) - state->last_cc_sync_time > 3) { + //test to switch back to 10/4 P1 QPSK for P25 FDMA CC + if (opts->mod_qpsk == 1 && state->p25_cc_is_tdma == 0) + { + state->samplesPerSymbol = 10; + state->symbolCenter = 4; + } + //start going through the lcn/frequencies CC/signal hunting fprintf (stderr, "Control Channel Signal Lost. Searching for Control Channel.\n"); //make sure our current roll value doesn't exceed value of frequencies imported @@ -212,11 +219,10 @@ getFrameSync (dsd_opts * opts, dsd_state * state) //if Phase 2 (or YSF in future), then only 20 else if (state->lastsynctype == 35 || state->lastsynctype == 36) //P2 { - t_max = 20; + t_max = 20; } - else t_max = 24; //was 18, but everything else seems to be based on 24 dibit sync pattern + else t_max = 24; //24 for everything else - //int lbuf[11], lbuf2[11]; //24 each //10 was woking good on NXDN, but not going well on P25, probably others too int lbuf[t_max], lbuf2[t_max]; int lsum; char spectrum[64]; @@ -224,19 +230,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) memset (lbuf, 0, sizeof(lbuf)); memset (lbuf2, 0, sizeof(lbuf2)); - - //test changing these values, and the qsort and other values down below sync - //also, add max min shit to the sync pattern for NXDN FSW - //and maybe also try making a more variable based t >= and also user opt filters (op25, original) - - //also also, go back to post commit version of this file, and try to copy shit back again and not - //break things this time, this version is a shim from BJ - // for (i = 18; i < 24; i++) //was 18, changing to 10, revert if issues arise - // { - // lbuf[i] = 0; - // lbuf2[i] = 0; - // } - // detect frame sync t = 0; synctest10[10] = 0; @@ -292,7 +285,7 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->sidx++; } - if (lastt == 23) //issue for QPSK on shorter sync pattern? + if (lastt == t_max) //issue for QPSK on shorter sync pattern? //23 { lastt = 0; if (state->numflips > opts->mod_threshold) @@ -418,20 +411,19 @@ getFrameSync (dsd_opts * opts, dsd_state * state) } } - // *state->dmr_payload_p = 1; //test just setting all sync with 3, see if it gets rejected by fec state->dmr_payload_p++; // end digitize and dmr buffer testing - *synctest_p = dibit; //here's your problem, lady! well, more like the assignment dibit gets up above + *synctest_p = dibit; if (t >= t_max) //works excelent now with short sync patterns, and no issues with large ones! { for (i = 0; i < t_max; i++) //24 { lbuf2[i] = lbuf[i]; } - qsort (lbuf2, t_max, sizeof (int), comp); //24 + qsort (lbuf2, t_max, sizeof (int), comp); lmin = (lbuf2[1] + lbuf2[2] + lbuf2[3]) / 3; - lmax = (lbuf2[t_max - 3] + lbuf2[t_max - 2] + lbuf2[t_max - 1]) / 3; //7,8,9 for NXDN + lmax = (lbuf2[t_max - 3] + lbuf2[t_max - 2] + lbuf2[t_max - 1]) / 3; if (state->rf_mod == 1) { @@ -467,20 +459,6 @@ getFrameSync (dsd_opts * opts, dsd_state * state) state->minref = state->min; } - // if (state->rf_mod == 0) - // { - // sprintf (modulation, "C4FM"); - // } - // else if (state->rf_mod == 1) - // { - // sprintf (modulation, "QPSK"); - // } - // else if (state->rf_mod == 2) - // { - // sprintf (modulation, "GFSK"); - // } - //tempted to shitcan this datascope - strncpy (synctest, (synctest_p - 23), 24); if (opts->frame_p25p1 == 1) { diff --git a/src/dsd_main.c b/src/dsd_main.c index 7ad007f..6fea574 100644 --- a/src/dsd_main.c +++ b/src/dsd_main.c @@ -80,12 +80,11 @@ noCarrier (dsd_opts * opts, dsd_state * state) //tune back to last knwon CC when using trunking if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1) { - if (state->p25_cc_freq != 0) //still need a con+ way to set this accurately, or atleast guess, maybe shim p25_cc_freq to lcn index 0? + if (state->p25_cc_freq != 0) { - //maybe I should make a seperate tuning function that can handle multiple tuning types if (opts->use_rigctl == 1) //rigctl tuning { - SetModulation(opts->rigctl_sockfd, 12500); //could use the bw field on iden_up for P25 to determine a good bw, but honestly it really depends on signal stregth + SetModulation(opts->rigctl_sockfd, 12500); SetFreq(opts->rigctl_sockfd, state->p25_cc_freq); } @@ -97,20 +96,20 @@ noCarrier (dsd_opts * opts, dsd_state * state) opts->p25_is_tuned = 0; state->edacs_tuned_lcn = -1; + + //only for EDACS/PV + if (opts->frame_provoice == 1 && opts->wav_out_file != NULL) + { + closeWavOutFile(opts, state); + } + state->last_cc_sync_time = time(NULL); + //test to switch back to 10/4 P1 QPSK for P25 FDMA CC + if (opts->mod_qpsk == 1 && state->p25_cc_is_tdma == 0) + { + state->samplesPerSymbol = 10; + state->symbolCenter = 4; + } } - //only for EDACS right now, disable this later on or work around - if (opts->wav_out_file != NULL) - { - closeWavOutFile(opts, state); - } - state->last_cc_sync_time = time(NULL); - //test to revert back to 10/4 P1 QPSK - if (opts->mod_qpsk == 1) - { - state->samplesPerSymbol = 10; - state->symbolCenter = 4; - } - } state->dibit_buf_p = state->dibit_buf + 200; @@ -397,7 +396,7 @@ initOpts (dsd_opts * opts) opts->tcp_hostname = "localhost"; opts->p25_trunk = 0; //0 disabled, 1 is enabled - opts->p25_is_tuned = 0; //set to 1 if currently on VC, set back to 0 if on CC + opts->p25_is_tuned = 0; //set to 1 if currently on VC, set back to 0 on carrier drop } diff --git a/src/p25p1_tsbk.c b/src/p25p1_tsbk.c index a2d832f..de851b0 100644 --- a/src/p25p1_tsbk.c +++ b/src/p25p1_tsbk.c @@ -124,6 +124,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state) fprintf (stderr, "\n Network Status Broadcast TSBK - Abbreviated \n"); fprintf (stderr, " WACN [%05lX] SYSID [%03X] NAC [%03llX]", wacn, sysid, state->p2_cc); state->p25_cc_freq = process_channel_to_freq(opts, state, channel); + state->p25_cc_is_tdma = 0; //flag off for CC tuning purposes when system is qpsk //only set IF these values aren't already hard set by the user if (state->p2_hardset == 0) diff --git a/src/p25p2_vpdu.c b/src/p25p2_vpdu.c index 709353a..3730e1f 100644 --- a/src/p25p2_vpdu.c +++ b/src/p25p2_vpdu.c @@ -62,7 +62,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon else slot = state->currentslot; //assigning here if OECI MAC SIGNAL, after passing RS and CRC - if (state->p2_is_lcch) + if (state->p2_is_lcch = 1) { if (slot == 1) state->dmrburstL = 30; else state->dmrburstR = 30; @@ -74,10 +74,766 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon goto END_PDU; } + //group list mode so we can look and see if we need to block tuning any groups, etc + char mode[8]; //allow, block, digital, enc, etc + for (int i = 0; i < 2; i++) { - //New PDUs added below here as of 10-23-2022 + //MFID90 Voice Grants, A3, A4, and A5 + //MFID90 Group Regroup Channel Grant - Implicit + if (MAC[1+len_a] == 0xA3 && MAC[2+len_a] == 0x90) + { + int mfid = MAC[2+len_a]; + int channel = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int sgroup = (MAC[7+len_a] << 8) | MAC[8+len_a]; + long int freq = 0; + fprintf (stderr, "\n MFID90 Group Regroup Channel Grant - Implicit"); + fprintf (stderr, "\n CHAN [%04X] Group [%d][%04X]", channel, sgroup, sgroup); + freq = process_channel_to_freq (opts, state, channel); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == sgroup) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[channel >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, freq); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + opts->p25_is_tuned = 1; + } + } + } + //if playing back files, and we still want to see what freqs are in use in the ncurses terminal + //might only want to do these on a grant update, and not a grant by itself? + if (opts->p25_trunk == 0) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + } + } + + //MFID90 Group Regroup Channel Grant - Explicit + if (MAC[1+len_a] == 0xA4 && MAC[2+len_a] == 0x90) + { + int mfid = MAC[2+len_a]; + int channel = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int channelr = (MAC[7+len_a] << 8) | MAC[8+len_a]; + int sgroup = (MAC[9+len_a] << 8) | MAC[10+len_a]; + long int freq = 0; + fprintf (stderr, "\n MFID90 Group Regroup Channel Grant - Explicit"); + fprintf (stderr, "\n CHAN [%04X] Group [%d][%04X]", channel, sgroup, sgroup); + freq = process_channel_to_freq (opts, state, channel); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == sgroup) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[channel >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, freq); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + opts->p25_is_tuned = 1; + } + } + } + //if playing back files, and we still want to see what freqs are in use in the ncurses terminal + //might only want to do these on a grant update, and not a grant by itself? + if (opts->p25_trunk == 0) + { + if (sgroup == state->lasttg || sgroup == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + } + } + } + + //MFID90 Group Regroup Channel Grant Update + if (MAC[1+len_a] == 0xA5 && MAC[2+len_a] == 0x90) + { + int channel1 = (MAC[4+len_a] << 8) | MAC[5+len_a]; + int group1 = (MAC[6+len_a] << 8) | MAC[7+len_a]; + int channel2 = (MAC[8+len_a] << 8) | MAC[9+len_a]; + int group2 = (MAC[10+len_a] << 8) | MAC[11+len_a]; + long int freq1 = 0; + long int freq2 = 0; + + fprintf (stderr, "\n MFID90 Group Regroup Channel Grant Update"); + fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1); + freq1 = process_channel_to_freq (opts, state, channel1); + fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); + freq2 = process_channel_to_freq (opts, state, channel2); + + //monstrocity below should get us evaluating and tuning groups...hopefully, will be first come first served though, no priority + //see how many loops we need to run on when to tune if first group is blocked + int loop = 1; + if (channel1 == channel2) loop = 1; + else loop = 2; + //assigned inside loop + long int tunable_freq = 0; + int tunable_chan = 0; + int tunable_group = 0; + + for (int j = 0; j < loop; j++) + { + //assign our internal variables for check down on if to tune one freq/group or not + if (j == 0) + { + tunable_freq = freq1; + tunable_chan = channel1; + tunable_group = group1; + } + else + { + tunable_freq = freq2; + tunable_chan = channel2; + tunable_group = group2; + } + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == tunable_group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //check to see if the group candidate is blocked first + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[tunable_chan >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, tunable_freq); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + opts->p25_is_tuned = 1; + } + } + } + //if playing back files, and we still want to see what freqs are in use in the ncurses terminal + //might only want to do these on a grant update, and not a grant by itself? + if (opts->p25_trunk == 0) + { + if (tunable_group == state->lasttg || tunable_group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = tunable_freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + } + } + } + } + + //Standard P25 Tunable Commands + //Group Voice Channel Grant (GRP_V_CH_GRANT) + if (MAC[1+len_a] == 0x40) + { + int svc = MAC[2+len_a]; + int channel = (MAC[3+len_a] << 8) | MAC[4+len_a]; + int group = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int source = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a]; + long int freq = 0; + + fprintf (stderr, "\n Group Voice Channel Grant Update"); + fprintf (stderr, "\n SVC [%02X] CHAN [%04X] Group [%d] Source [%d]", svc, channel, group, source); + freq = process_channel_to_freq (opts, state, channel); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[channel >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, freq); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + opts->p25_is_tuned = 1; + } + } + } + //if playing back files, and we still want to see what freqs are in use in the ncurses terminal + //might only want to do these on a grant update, and not a grant by itself? + if (opts->p25_trunk == 0) + { + if (group == state->lasttg || group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + } + } + } + + //Unit-to-Unit Voice Service Channel Grant (UU_V_CH_GRANT), or Grant Update (same format) + if (MAC[1+len_a] == 0x44 || MAC[1+len_a] == 0x46) + { + int channel = (MAC[2+len_a] << 8) | MAC[3+len_a]; + int target = (MAC[4+len_a] << 16) | (MAC[5+len_a] << 8) | MAC[6+len_a]; + int source = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a]; + long int freq = 0; + + fprintf (stderr, "\n Unit to Unit Channel Grant"); + if ( MAC[1+len_a] == 0x46) fprintf (stderr, " Update"); + fprintf (stderr, "\n CHAN [%04X] Source [%d] Target [%d]", channel, source, target); + freq = process_channel_to_freq (opts, state, channel); + + //unit to unit needs work, may fail under certain conditions (first blocked, second allowed, etc) (labels should still work though) + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == source || state->group_array[i].groupNumber == target) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && freq != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[channel >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, freq); + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; + opts->p25_is_tuned = 1; + } + } + } + if (opts->p25_trunk == 0) + { + if (target == state->lasttg || target == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq; + } + } + } + + //Group Voice Channel Grant Update Multiple - Explicit + if (MAC[1+len_a] == 0x25) + { + int svc1 = MAC[2+len_a]; + int channelt1 = (MAC[3+len_a] << 8) | MAC[4+len_a]; + int channelr1 = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int group1 = (MAC[7+len_a] << 8) | MAC[8+len_a]; + int svc2 = MAC[9+len_a]; + int channelt2 = (MAC[10+len_a] << 8) | MAC[11+len_a]; + int channelr2 = (MAC[12+len_a] << 8) | MAC[13+len_a]; + int group2 = (MAC[14+len_a] << 8) | MAC[15+len_a]; + long int freq1t = 0; + long int freq1r = 0; + long int freq2t = 0; + long int freq2r = 0; + fprintf (stderr, "\n Group Voice Channel Grant Update Multiple - Explicit"); + fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] Group [%d][%04X]", svc1, channelt1, channelr1, group1, group1); + freq1t = process_channel_to_freq (opts, state, channelt1); + 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); + freq1t = process_channel_to_freq (opts, state, channelt2); + freq1r = process_channel_to_freq (opts, state, channelr2); + + int loop = 1; + if (channelt2 == channelt2) loop = 1; + else loop = 2; + //assigned inside loop + long int tunable_freq = 0; + int tunable_chan = 0; + int tunable_group = 0; + + for (int j = 0; j < loop; j++) + { + //assign our internal variables for check down on if to tune one freq/group or not + if (j == 0) + { + tunable_freq = freq1t; + tunable_chan = channelt1; + tunable_group = group1; + } + else + { + tunable_freq = freq2t; + tunable_chan = channelt2; + tunable_group = group2; + } + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == tunable_group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[tunable_chan >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, tunable_freq); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + opts->p25_is_tuned = 1; + } + } + } + if (opts->p25_trunk == 0) + { + if (tunable_group == state->lasttg || tunable_group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = tunable_freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + } + } + } + } + + //Group Voice Channel Grant Update Multiple - Implicit + if (MAC[1+len_a] == 0x05) //wonder if this is MAC_SIGNAL only? Too long for a TSBK + { + int so1 = MAC[2+len_a]; + int channel1 = (MAC[3+len_a] << 8) | MAC[4+len_a]; + int group1 = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int so2 = MAC[7+len_a]; + int channel2 = (MAC[8+len_a] << 8) | MAC[9+len_a]; + int group2 = (MAC[10+len_a] << 8) | MAC[11+len_a]; + int so3 = MAC[12+len_a]; + int channel3 = (MAC[13+len_a] << 8) | MAC[14+len_a]; + int group3 = (MAC[15+len_a] << 8) | MAC[16+len_a]; + long int freq1 = 0; + long int freq2 = 0; + long int freq3 = 0; + + fprintf (stderr, "\n Group Voice Channel Grant Update Multiple - Implicit"); + fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1); + freq1 = process_channel_to_freq (opts, state, channel1); + fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); + freq2 = process_channel_to_freq (opts, state, channel2); + fprintf (stderr, "\n Channel 3 [%04X] Group 3 [%d][%04X]", channel3, group3, group3); + freq3 = process_channel_to_freq (opts, state, channel3); + + int loop = 3; + + long int tunable_freq = 0; + int tunable_chan = 0; + int tunable_group = 0; + + for (int j = 0; j < loop; j++) + { + //assign our internal variables for check down on if to tune one freq/group or not + if (j == 0) + { + tunable_freq = freq1; + tunable_chan = channel1; + tunable_group = group1; + } + else if (j == 1) + { + tunable_freq = freq2; + tunable_chan = channel2; + tunable_group = group2; + } + else + { + tunable_freq = freq3; + tunable_chan = channel3; + tunable_group = group3; + } + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == tunable_group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //check to see if the group candidate is blocked first + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[tunable_chan >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, 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; + } + } + } + if (opts->p25_trunk == 0) + { + if (tunable_group == state->lasttg || tunable_group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = tunable_freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + } + } + } + } + + //Group Voice Channel Grant Update - Implicit + if (MAC[1+len_a] == 0x42) + { + int channel1 = (MAC[2+len_a] << 8) | MAC[3+len_a]; + int group1 = (MAC[4+len_a] << 8) | MAC[5+len_a]; + int channel2 = (MAC[6+len_a] << 8) | MAC[7+len_a]; + int group2 = (MAC[8+len_a] << 8) | MAC[9+len_a]; + long int freq1 = 0; + long int freq2 = 0; + + fprintf (stderr, "\n Group Voice Channel Grant Update - Implicit"); + fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1); + freq1 = process_channel_to_freq (opts, state, channel1); + fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); + freq2 = process_channel_to_freq (opts, state, channel2); + + int loop = 1; + if (channel1 == channel2) loop = 1; + else loop = 2; + //assigned inside loop + long int tunable_freq = 0; + int tunable_chan = 0; + int tunable_group = 0; + + for (int j = 0; j < loop; j++) + { + //assign our internal variables for check down on if to tune one freq/group or not + if (j == 0) + { + tunable_freq = freq1; + tunable_chan = channel1; + tunable_group = group1; + } + else + { + tunable_freq = freq2; + tunable_chan = channel2; + tunable_group = group2; + } + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == tunable_group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //check to see if the group candidate is blocked first + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) //DE is digital encrypted, B is block + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && tunable_freq != 0) //if we aren't already on a VC and have a valid frequency already + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[tunable_chan >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, 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; + } + } + } + if (opts->p25_trunk == 0) + { + if (tunable_group == state->lasttg || tunable_group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = tunable_freq; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = tunable_freq; + } + } + } + } + + //Group Voice Channel Grant Update - Explicit + if (MAC[1+len_a] == 0xC3) + { + int svc = MAC[2+len_a]; + int channelt = (MAC[3+len_a] << 8) | MAC[4+len_a]; + int channelr = (MAC[5+len_a] << 8) | MAC[6+len_a]; + int group = (MAC[7+len_a] << 8) | MAC[8+len_a]; + long int freq1 = 0; + long int freq2 = 0; + + fprintf (stderr, "\n 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 (slot == 0) + { + state->lasttg = group; + } + else state->lasttgR = group; + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + } + } + + //tune if tuning available + if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency + { + //testing switch to P2 channel symbol rate with qpsk enabled, we need to know if we are going to a TDMA channel or an FDMA channel + if (opts->mod_qpsk == 1) + { + int spacing = state->p25_chan_spac[channelt >> 12]; + if (spacing == 0x64) //tdma should always be 0x64, and fdma should always be 0x32 + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + SetModulation(opts->rigctl_sockfd, 12500); + 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 + } + //rtl_udp + else if (opts->audio_in_type == 3) + { + rtl_udp_tune (opts, state, freq1); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + opts->p25_is_tuned = 1; + } + } + } + if (opts->p25_trunk == 0) + { + if (group == state->lasttg || group == state->lasttgR) + { + //P1 FDMA + if (state->synctype == 0 || state->synctype == 1) state->p25_vc_freq[0] = freq1; + //P2 TDMA + else state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + } + } + } //SNDCP Data Channel Announcement if (MAC[1+len_a] == 0xD6) @@ -139,35 +895,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon process_channel_to_freq (opts, state, channelr); } - //End New PDUs added - - //Group Voice Channel Grant (GRP_V_CH_GRANT) - if (MAC[1+len_a] == 0x40) - { - int svc = MAC[2+len_a]; - int channel = (MAC[3+len_a] << 8) | MAC[4+len_a]; - int group = (MAC[5+len_a] << 8) | MAC[6+len_a]; - int source = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a]; - - fprintf (stderr, "\n Group Voice Channel Grant Update"); - fprintf (stderr, "\n SVC [%02X] CHAN [%04X] Group [%d] Source [%d]", svc, channel, group, source); - process_channel_to_freq (opts, state, channel); - - } - - //Unit-to-Unit Voice Service Channel Grant (UU_V_CH_GRANT) - if (MAC[1+len_a] == 0x44) - { - int channel = (MAC[2+len_a] << 8) | MAC[3+len_a]; - int target = (MAC[4+len_a] << 16) | (MAC[5+len_a] << 8) | MAC[6+len_a]; - int source = (MAC[7+len_a] << 16) | (MAC[8+len_a] << 8) | MAC[9+len_a]; - - fprintf (stderr, "\n Unit to Unit Channel Grant"); - fprintf (stderr, "\n CHAN [%04X] Source [%d] Target [%d]", channel, source, target); - process_channel_to_freq (opts, state, channel); - - } - //Unit-to-Unit Answer Request (UU_ANS_REQ) if (MAC[1+len_a] == 0x45) { @@ -337,66 +1064,6 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon } - //Group Voice Channel Grant Update - Implicit - if (MAC[1+len_a] == 0x42) - { - int channel1 = (MAC[2+len_a] << 8) | MAC[3+len_a]; - int group1 = (MAC[4+len_a] << 8) | MAC[5+len_a]; - int channel2 = (MAC[6+len_a] << 8) | MAC[7+len_a]; - int group2 = (MAC[8+len_a] << 8) | MAC[9+len_a]; - - fprintf (stderr, "\n Group Voice Channel Grant Update - Implicit"); - fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1); - - if (state->lasttg == group1) - { - state->p25_vc_freq[0] = process_channel_to_freq (opts, state, channel1); - } - else if (state->lasttgR == group1) - { - state->p25_vc_freq[1] = process_channel_to_freq (opts, state, channel1); - } - else process_channel_to_freq (opts, state, channel1); - //only run next channel if not identical to first channel - if (group1 != group2) - { - fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2); - if (state->lasttg == group2) - { - state->p25_vc_freq[0] = process_channel_to_freq (opts, state, channel2); - } - else if (state->lasttgR == group2) - { - state->p25_vc_freq[1] = process_channel_to_freq (opts, state, channel2); - } - else process_channel_to_freq (opts, state, channel2); - - } - - - - } - - //Group Voice Channel Grant Update - Explicit - if (MAC[1+len_a] == 0xC3) - { - int svc = MAC[2+len_a]; - int channelt = (MAC[3+len_a] << 8) | MAC[4+len_a]; - int channelr = (MAC[5+len_a] << 8) | MAC[6+len_a]; - int group = (MAC[7+len_a] << 8) | MAC[8+len_a]; - - fprintf (stderr, "\n 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); - process_channel_to_freq (opts, state, channelt); - process_channel_to_freq (opts, state, channelr); - if (slot == 0) - { - state->lasttg = group; - } - else state->lasttgR = group; - - } - //MFID90 Group Regroup Voice Channel User - Abbreviated if (MAC[1+len_a] == 0x80 && MAC[2+len_a] == 0x90) { @@ -545,6 +1212,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, "\n Network Status Broadcast - Abbreviated \n"); fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X]", lra, lwacn, lsysid, lcolorcode, channel); state->p25_cc_freq = process_channel_to_freq (opts, state, channel); + state->p25_cc_is_tdma = 1; //flag on for CC tuning purposes when system is qpsk if (state->p2_hardset == 0 ) //state->p2_is_lcch == 1 shim until CRC is working, prevent bogus data { state->p2_wacn = lwacn; @@ -567,6 +1235,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon fprintf (stderr, " LRA [%02X] WACN [%05X] SYSID [%03X] NAC [%03X] CHAN-T [%04X] CHAN-R [%04X]", lra, lwacn, lsysid, lcolorcode, channelt, channelr); process_channel_to_freq (opts, state, channelt); process_channel_to_freq (opts, state, channelr); + state->p25_cc_is_tdma = 1; //flag on for CC tuning purposes when system is qpsk if (state->p2_hardset == 0 ) //state->p2_is_lcch == 1 shim until CRC is working, prevent bogus data { state->p2_wacn = lwacn;