P25 Trunking Initial Commit;

This commit is contained in:
lwvmobile 2022-11-13 23:04:50 -05:00
parent c73d45d553
commit 94dbd1512d
5 changed files with 793 additions and 144 deletions

View File

@ -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

View File

@ -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)
{

View File

@ -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
}

View File

@ -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)

View File

@ -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;