mirror of https://github.com/lwvmobile/dsd-fme.git
Merge pull request #251 from ilyacodes/testcall
EDACS: Test Call improvements
This commit is contained in:
commit
ca506672a8
|
|
@ -763,14 +763,16 @@ typedef struct
|
|||
int edacs_s_mask; //Calculated Mask for S Bits
|
||||
|
||||
//flags for EDACS call type
|
||||
#define EDACS_IS_VOICE 0x01
|
||||
#define EDACS_IS_DIGITAL 0x02
|
||||
#define EDACS_IS_EMERGENCY 0x04
|
||||
#define EDACS_IS_GROUP 0x08
|
||||
#define EDACS_IS_INDIVIDUAL 0x10
|
||||
#define EDACS_IS_ALL_CALL 0x20
|
||||
#define EDACS_IS_INTERCONNECT 0x40
|
||||
#define EDACS_IS_TESTCALL 0x100
|
||||
#define EDACS_IS_VOICE 0x01
|
||||
#define EDACS_IS_DIGITAL 0x02
|
||||
#define EDACS_IS_EMERGENCY 0x04
|
||||
#define EDACS_IS_GROUP 0x08
|
||||
#define EDACS_IS_INDIVIDUAL 0x10
|
||||
#define EDACS_IS_ALL_CALL 0x20
|
||||
#define EDACS_IS_INTERCONNECT 0x40
|
||||
#define EDACS_IS_TEST_CALL 0x80
|
||||
#define EDACS_IS_AGENCY_CALL 0x100
|
||||
#define EDACS_IS_FLEET_CALL 0x200
|
||||
|
||||
//trunking group and lcn freq list
|
||||
long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully
|
||||
|
|
|
|||
|
|
@ -315,6 +315,107 @@ char * getTimeC(time_t t) //get pretty hh:mm:ss timestamp
|
|||
return curr;
|
||||
}
|
||||
|
||||
int isCustomAfsString(dsd_state * state) {
|
||||
return state->edacs_a_bits != 4 || state->edacs_f_bits != 4 || state->edacs_s_bits != 3;
|
||||
}
|
||||
|
||||
//Get the string length we need for an AFS string, math-style
|
||||
int getAfsStringLength(dsd_state * state) {
|
||||
if (!isCustomAfsString(state))
|
||||
return 6;
|
||||
|
||||
int length = 0;
|
||||
length += (state->edacs_a_bits + 2) / 3;
|
||||
length += (state->edacs_f_bits + 2) / 3;
|
||||
length += (state->edacs_s_bits + 2) / 3;
|
||||
length += 2; //colon separators
|
||||
|
||||
// This will be either 6 or 7
|
||||
return length;
|
||||
}
|
||||
|
||||
//Format the AFS string, Florida-style
|
||||
int getAfsString(dsd_state * state, char * buffer, int a, int f, int s) {
|
||||
if (!isCustomAfsString(state))
|
||||
{
|
||||
sprintf(buffer, "%02d-%02d%01d", a, f, s);
|
||||
return 6;
|
||||
}
|
||||
|
||||
int printed_chars = 0;
|
||||
switch (state->edacs_a_bits)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
sprintf(buffer, "%01d:", a);
|
||||
printed_chars += 1;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
sprintf(buffer, "%02d:", a);
|
||||
printed_chars += 2;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
sprintf(buffer, "%03d:", a);
|
||||
printed_chars += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buffer + printed_chars, ":");
|
||||
printed_chars++;
|
||||
|
||||
switch (state->edacs_f_bits) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
sprintf(buffer + printed_chars, "%01d", f);
|
||||
printed_chars += 1;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
sprintf(buffer + printed_chars, "%02d", f);
|
||||
printed_chars += 2;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
sprintf(buffer + printed_chars, "%03d", f);
|
||||
printed_chars += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(buffer + printed_chars, ":");
|
||||
printed_chars++;
|
||||
|
||||
switch (state->edacs_s_bits) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
sprintf(buffer + printed_chars, "%01d", s);
|
||||
printed_chars += 1;
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
sprintf(buffer + printed_chars, "%02d", s);
|
||||
printed_chars += 2;
|
||||
break;
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
sprintf(buffer + printed_chars, "%03d", s);
|
||||
printed_chars += 3;
|
||||
break;
|
||||
}
|
||||
|
||||
return printed_chars;
|
||||
}
|
||||
|
||||
//testing a few things, going to put this into ncursesMenu
|
||||
#define WIDTH 36
|
||||
#define HEIGHT 25
|
||||
|
|
@ -951,7 +1052,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
TCP_END: ; //do nothing
|
||||
|
||||
|
|
@ -2608,7 +2709,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
int f = (state->tg_hold >> state->edacs_f_shift) & state->edacs_f_mask;
|
||||
int s = state->tg_hold & state->edacs_s_mask;
|
||||
if (state->ea_mode == 1) printw ("\n| \\TG HOLD: %d; ", state->tg_hold);
|
||||
else printw ("\n| \\TG HOLD: %d [%02d-%02d%01d]; ", state->tg_hold, a, f, s);
|
||||
else
|
||||
{
|
||||
char afs_str[8];
|
||||
getAfsString(state, afs_str, a, f, s);
|
||||
printw ("\n| \\TG HOLD: %d [%s]; ", state->tg_hold, afs_str);
|
||||
}
|
||||
}
|
||||
|
||||
attron(COLOR_PAIR(4));
|
||||
|
|
@ -2649,7 +2755,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
int f = (state->tg_hold >> state->edacs_f_shift) & state->edacs_f_mask;
|
||||
int s = state->tg_hold & state->edacs_s_mask;
|
||||
if (state->ea_mode == 1) printw ("\n| \\TG HOLD: %d; ", state->tg_hold);
|
||||
else printw ("\n| \\TG HOLD: %d [%02d-%02d%01d]; ", state->tg_hold, a, f, s);
|
||||
else
|
||||
{
|
||||
char afs_str[8];
|
||||
getAfsString(state, afs_str, a, f, s);
|
||||
printw ("\n| \\TG HOLD: %d [%s]; ", state->tg_hold, afs_str);
|
||||
}
|
||||
}
|
||||
|
||||
printw ("\n");
|
||||
|
|
@ -3608,7 +3719,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
// Voice call
|
||||
if ((call_matrix[i][4] & EDACS_IS_VOICE) != 0)
|
||||
{
|
||||
// System all-call
|
||||
// Group call
|
||||
if ((call_matrix[i][4] & EDACS_IS_GROUP) != 0)
|
||||
printw (" TGT [%8lld] SRC [%8lld]", call_matrix[i][2], call_matrix[i][3] );
|
||||
// I-Call
|
||||
|
|
@ -3621,14 +3732,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
else if ((call_matrix[i][4] & EDACS_IS_INTERCONNECT) != 0)
|
||||
printw (" TGT [ SYSTEM ] SRC [%8lld] Interconnect", call_matrix[i][3] );
|
||||
// Test call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0)
|
||||
printw (" TEST CALL");
|
||||
else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0)
|
||||
printw (" TGT [ SYSTEM ] SRC [ SYSTEM ] Test Call");
|
||||
// Unknown call
|
||||
else
|
||||
printw (" Unknown call type" );
|
||||
|
||||
// Call flags
|
||||
if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {}
|
||||
if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {}
|
||||
else if ((call_matrix[i][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
|
||||
else printw (" [Dig]");
|
||||
if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
|
||||
|
|
@ -3644,32 +3755,53 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
{
|
||||
// Group call
|
||||
if ((call_matrix[i][4] & EDACS_IS_GROUP) != 0)
|
||||
printw (" TGT [%6lld][%02d-%02d%01d] SRC [%5lld]", call_matrix[i][2], a, f, s, call_matrix[i][3] );
|
||||
{
|
||||
char afs_str[8];
|
||||
getAfsString(state, afs_str, a, f, s);
|
||||
printw (" TGT [%6lld][%s] SRC [%5lld]", call_matrix[i][2], afs_str, call_matrix[i][3] );
|
||||
}
|
||||
// I-Call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_INDIVIDUAL) != 0)
|
||||
printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] );
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] );
|
||||
else
|
||||
printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] );
|
||||
// System all-call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_ALL_CALL) != 0)
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] );
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] );
|
||||
else
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] );
|
||||
// Interconnect call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_INTERCONNECT) != 0)
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] );
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] );
|
||||
else
|
||||
printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] );
|
||||
// Test call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0)
|
||||
printw (" TEST CALL");
|
||||
else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0)
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call");
|
||||
else
|
||||
printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call");
|
||||
// Unknown call
|
||||
else
|
||||
printw (" Unknown call type" );
|
||||
|
||||
// Call flags
|
||||
if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {}
|
||||
if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {}
|
||||
else if ((call_matrix[i][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
|
||||
else printw (" [Dig]");
|
||||
if ((call_matrix[i][4] & EDACS_IS_AGENCY_CALL) != 0) printw ("[A]");
|
||||
if ((call_matrix[i][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]");
|
||||
if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
|
||||
}
|
||||
// Data call
|
||||
else
|
||||
// Data call
|
||||
printw (" TGT [ DATA ] SRC [%8lld] Data", call_matrix[i][3] );
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] );
|
||||
else
|
||||
printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] );
|
||||
}
|
||||
for (int k = 0; k < state->group_tally; k++)
|
||||
{
|
||||
|
|
@ -3814,14 +3946,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0)
|
||||
printw ("Target [ SYSTEM ] Source [%8lld] Interconnect", call_matrix[j][3]);
|
||||
// Test call
|
||||
else if ((call_matrix[j][4] & EDACS_IS_TESTCALL) != 0)
|
||||
printw ("TEST CALL");
|
||||
else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0)
|
||||
printw ("Target [ SYSTEM ] Source [ SYSTEM ] Test Call");
|
||||
// Unknown call
|
||||
else
|
||||
printw ("Unknown call type");
|
||||
|
||||
// Call flags
|
||||
if ((call_matrix[j][4] & EDACS_IS_TESTCALL) != 0) {}
|
||||
if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {}
|
||||
else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
|
||||
else printw (" [Dig]");
|
||||
if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
|
||||
|
|
@ -3841,33 +3973,53 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
|||
int s = call_matrix[j][2] & state->edacs_s_mask;
|
||||
|
||||
// Group call
|
||||
if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0)
|
||||
printw ("Target [%6lld][%02d-%02d%01d] Source [%5lld]", call_matrix[j][2], a, f, s, call_matrix[j][3]);
|
||||
if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0) {
|
||||
char afs_str[8];
|
||||
getAfsString(state, afs_str, a, f, s);
|
||||
printw ("Target [%6lld][%s] Source [%5lld]", call_matrix[j][2], afs_str, call_matrix[j][3]);
|
||||
}
|
||||
// I-Call
|
||||
else if ((call_matrix[j][4] & EDACS_IS_INDIVIDUAL) != 0)
|
||||
printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
|
||||
else
|
||||
printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]);
|
||||
// System all-call
|
||||
else if ((call_matrix[j][4] & EDACS_IS_ALL_CALL) != 0)
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]);
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]);
|
||||
else
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]);
|
||||
// Interconnect
|
||||
else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0)
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]);
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]);
|
||||
else
|
||||
printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]);
|
||||
// Test call
|
||||
else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0)
|
||||
printw (" TEST CALL");
|
||||
else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0)
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw ("Target [ SYSTEM ] Source [ SYS ] Test Call");
|
||||
else
|
||||
printw ("Target [ SYSTEM ] Source [ SYS ] Test Call");
|
||||
// Unknown call
|
||||
else
|
||||
printw ("Unknown call type");
|
||||
|
||||
// Call flags
|
||||
if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {}
|
||||
if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {}
|
||||
else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]");
|
||||
else printw (" [Dig]");
|
||||
if ((call_matrix[j][4] & EDACS_IS_AGENCY_CALL) != 0) printw ("[A]");
|
||||
if ((call_matrix[j][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]");
|
||||
if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]");
|
||||
}
|
||||
// Data call
|
||||
else
|
||||
// Data call
|
||||
printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]);
|
||||
if (getAfsStringLength(state) == 6)
|
||||
printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]);
|
||||
else
|
||||
printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]);
|
||||
}
|
||||
//test
|
||||
for (int k = 0; k < state->group_tally; k++)
|
||||
|
|
|
|||
307
src/edacs-fme.c
307
src/edacs-fme.c
|
|
@ -53,7 +53,7 @@ char * getTimeE(void) //get pretty hhmmss timestamp
|
|||
return curr;
|
||||
}
|
||||
|
||||
char* get_lcn_status_string(int lcn)
|
||||
char * getLcnStatusString(int lcn)
|
||||
{
|
||||
if (lcn == 26 || lcn == 27)
|
||||
return "[Reserved LCN Status]";
|
||||
|
|
@ -69,8 +69,22 @@ char* get_lcn_status_string(int lcn)
|
|||
return "";
|
||||
}
|
||||
|
||||
int isAgencyCallGroup(int afs, dsd_state * state)
|
||||
{
|
||||
int fs_mask = state->edacs_s_mask | (state->edacs_f_mask << state->edacs_f_shift);
|
||||
return (afs & fs_mask) == 0;
|
||||
}
|
||||
|
||||
int isFleetCallGroup(int afs, dsd_state * state)
|
||||
{
|
||||
if (isAgencyCallGroup(afs, state))
|
||||
return 0;
|
||||
|
||||
return (afs & state->edacs_s_mask) == 0;
|
||||
}
|
||||
|
||||
//Bitwise vote-compare the three copies of a message received. Note that fr_2 and fr_5 are transmitted inverted.
|
||||
unsigned long long int edacs_vote_fr(unsigned long long int fr_1_4, unsigned long long int fr_2_5, unsigned long long int fr_3_6)
|
||||
unsigned long long int edacsVoteFr(unsigned long long int fr_1_4, unsigned long long int fr_2_5, unsigned long long int fr_3_6)
|
||||
{
|
||||
fr_2_5 = (~fr_2_5) & 0xFFFFFFFFFF;
|
||||
|
||||
|
|
@ -453,36 +467,10 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
state->edacs_a_shift = state->edacs_f_bits + state->edacs_s_bits;
|
||||
state->edacs_f_shift = state->edacs_s_bits;
|
||||
|
||||
//calculate masks via overkill copy and paste
|
||||
if (state->edacs_a_bits == 1) state->edacs_a_mask = 0x1;
|
||||
if (state->edacs_a_bits == 2) state->edacs_a_mask = 0x3;
|
||||
if (state->edacs_a_bits == 3) state->edacs_a_mask = 0x7;
|
||||
if (state->edacs_a_bits == 4) state->edacs_a_mask = 0xF;
|
||||
if (state->edacs_a_bits == 5) state->edacs_a_mask = 0x1F;
|
||||
if (state->edacs_a_bits == 6) state->edacs_a_mask = 0x3F;
|
||||
if (state->edacs_a_bits == 7) state->edacs_a_mask = 0x7F;
|
||||
if (state->edacs_a_bits == 8) state->edacs_a_mask = 0xFF;
|
||||
if (state->edacs_a_bits == 9) state->edacs_a_mask = 0x1FF;
|
||||
|
||||
if (state->edacs_f_bits == 1) state->edacs_s_mask = 0x1;
|
||||
if (state->edacs_f_bits == 2) state->edacs_s_mask = 0x3;
|
||||
if (state->edacs_f_bits == 3) state->edacs_s_mask = 0x7;
|
||||
if (state->edacs_f_bits == 4) state->edacs_s_mask = 0xF;
|
||||
if (state->edacs_f_bits == 5) state->edacs_s_mask = 0x1F;
|
||||
if (state->edacs_f_bits == 6) state->edacs_s_mask = 0x3F;
|
||||
if (state->edacs_f_bits == 7) state->edacs_s_mask = 0x7F;
|
||||
if (state->edacs_f_bits == 8) state->edacs_s_mask = 0xFF;
|
||||
if (state->edacs_f_bits == 9) state->edacs_s_mask = 0x1FF;
|
||||
|
||||
if (state->edacs_s_bits == 1) state->edacs_s_mask = 0x1;
|
||||
if (state->edacs_s_bits == 2) state->edacs_s_mask = 0x3;
|
||||
if (state->edacs_s_bits == 3) state->edacs_s_mask = 0x7;
|
||||
if (state->edacs_s_bits == 4) state->edacs_s_mask = 0xF;
|
||||
if (state->edacs_s_bits == 5) state->edacs_s_mask = 0x1F;
|
||||
if (state->edacs_s_bits == 6) state->edacs_s_mask = 0x3F;
|
||||
if (state->edacs_s_bits == 7) state->edacs_s_mask = 0x7F;
|
||||
if (state->edacs_s_bits == 8) state->edacs_s_mask = 0xFF;
|
||||
if (state->edacs_s_bits == 9) state->edacs_s_mask = 0x1FF;
|
||||
//calculate masks using bitwise math
|
||||
state->edacs_a_mask = (1 << state->edacs_a_bits) - 1;
|
||||
state->edacs_f_mask = (1 << state->edacs_f_bits) - 1;
|
||||
state->edacs_s_mask = (1 << state->edacs_s_bits) - 1;
|
||||
|
||||
char * timestr; //add timestr here, so we can assign it and also free it to prevent memory leak
|
||||
timestr = getTimeE();
|
||||
|
|
@ -528,8 +516,8 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
|
||||
//Take our 3 copies of the first and second message and vote them to extract the two "error-corrected" messages
|
||||
unsigned long long int msg_1_ec = edacs_vote_fr(fr_1, fr_2, fr_3);
|
||||
unsigned long long int msg_2_ec = edacs_vote_fr(fr_4, fr_5, fr_6);
|
||||
unsigned long long int msg_1_ec = edacsVoteFr(fr_1, fr_2, fr_3);
|
||||
unsigned long long int msg_2_ec = edacsVoteFr(fr_4, fr_5, fr_6);
|
||||
|
||||
//Get just the 28-bit message portion
|
||||
unsigned long long int msg_1_ec_m = msg_1_ec >> 12;
|
||||
|
|
@ -569,9 +557,9 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
// - KYEL - system data
|
||||
// - KGRN - voice group calls
|
||||
// - KCYN - voice individual calls
|
||||
// - KMAG - voice other calls (interconnect, all-call, etc)
|
||||
// - KMAG - voice other calls (interconnect, all-call, test call, etc)
|
||||
// - KBLU - subscriber data
|
||||
// - KWHT - unknown/reserved
|
||||
// - KWHT - unknown/reserved/special
|
||||
|
||||
//Account for ESK, if any
|
||||
unsigned long long int fr_esk_mask = ((unsigned long long int)state->esk_mask) << 20;
|
||||
|
|
@ -607,17 +595,15 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
if (mt1 == 0x1F)
|
||||
{
|
||||
|
||||
//Test Call (not seen in the wild, see US patent US7546135B2, Figure 2b)
|
||||
//Finally Captured in the wild, along with the "I-Call" with zero target and zero source
|
||||
//Initiate Test Call (finally captured in the wild on SLERS EA, along with the "I-Call" with target and source of 0)
|
||||
if (mt2 == 0x0)
|
||||
{
|
||||
|
||||
// MSG_1 [F802180] MSG_2 [0000000] (MT1: 1F; MT2: 0) Initiate Test Call
|
||||
int cc_lcn = (msg_1 & 0x3E000) >> 13; //shifted to allow this example to be CC LCN 1, as was reported at the time of capture
|
||||
int wc_lcn = (msg_1 & 0xF80) >> 7;
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Initiate Test Call :: CC LCN: %02d; WC LCN: %02d;", cc_lcn, wc_lcn);
|
||||
fprintf (stderr, " Initiate Test Call :: CC LCN [%02d] WC LCN [%02d]", cc_lcn, wc_lcn);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
state->edacs_vc_lcn = wc_lcn;
|
||||
|
|
@ -625,7 +611,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
//and overwrite current values in the matrix
|
||||
state->lasttg = 999999999;
|
||||
state->lastsrc = 999999999;
|
||||
state->edacs_vc_call_type = 0x101; //manually set to 0x101 to trigger voice call in ncurses, but no other flags
|
||||
state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL;
|
||||
}
|
||||
//Adjacent Sites
|
||||
else if (mt2 == 0x1)
|
||||
|
|
@ -633,11 +619,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int adj_lcn = (msg_1 & 0x1F000) >> 12;
|
||||
int adj_idx = (msg_1 & 0xF00) >> 8; //site 177 has 8 adj_sites, so this appears to be a 4-bit value
|
||||
int adj_site = (msg_1 & 0xFF);
|
||||
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Adjacent Site");
|
||||
if (adj_site > 0)
|
||||
fprintf (stderr, " :: Site ID [%02X][%03d] Index [%d] on CC LCN [%02d]%s", adj_site, adj_site, adj_idx, adj_lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: Site ID [%02X][%03d] Index [%d] on CC LCN [%02d]%s", adj_site, adj_site, adj_idx, adj_lcn, getLcnStatusString(lcn));
|
||||
else fprintf (stderr, " :: Total Indexed [%d]", adj_idx); //if site value is 0, then this tells us the total number of adjacent sites
|
||||
|
||||
if (adj_site == 0 && adj_idx == 0) fprintf (stderr, " [Adjacency Table Reset]");
|
||||
|
|
@ -687,7 +673,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
{
|
||||
state->edacs_lcn_count = state->edacs_cc_lcn;
|
||||
}
|
||||
fprintf (stderr, " :: System ID [%04X] Control Channel LCN [%d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: System ID [%04X] CC LCN [%02d]%s", system, state->edacs_cc_lcn, getLcnStatusString(lcn));
|
||||
|
||||
//check for control channel lcn frequency if not provided in channel map or in the lcn list
|
||||
if (state->trunk_lcn_freq[state->edacs_cc_lcn-1] == 0)
|
||||
|
|
@ -808,24 +794,88 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Patch Groups / Dynamic Regroup -- Reverse Engineer WIP from observations and guesswork
|
||||
//Patch Groups / Dynamic Regroup -- Current Code
|
||||
// else if (mt2 == 0xC)
|
||||
// {
|
||||
// //Note: First 9 bits of msg_1 are the mt1 and mt2 bits
|
||||
// int unk1 = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID
|
||||
// int sgid = (msg_1 & 0xFFFF); //patched supergroup ID
|
||||
|
||||
// //Updated Observation: The 'SSN' value may not be unique in this instance, so may be an entirely different value
|
||||
// //altogether. Its function is still unknown, but for the sake of displaying patches, is not required.
|
||||
|
||||
// int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN
|
||||
// int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup
|
||||
|
||||
// fprintf (stderr, "%s", KWHT);
|
||||
// fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target);
|
||||
// if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be 7 for an active patch, 0 for a termination of a patch
|
||||
// if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID, is FE for termination of a patch
|
||||
// fprintf (stderr, "%s", KNRM);
|
||||
// }
|
||||
|
||||
//Patch Groups / Dynamic Regroup -- Reverse Engineer WIP from observations, guesswork, and documented P25 MFID A4 regroup operations
|
||||
else if (mt2 == 0xC)
|
||||
{
|
||||
|
||||
//Note: Due to the method used to reverse engineer this patch using conventions from a newer documented P25 source (MFID A4 L3Harris),
|
||||
//its possible that the conventions, terminology, and bits signalled in this message are not entirely accurate, but are just speculation
|
||||
|
||||
//Note: First 9 bits of msg_1 are the mt1 and mt2 bits
|
||||
int unk1 = (msg_1 & 0x70000) >> 20; //unknown 3 bit value preceeding the SGID
|
||||
int sgid = (msg_1 & 0xFFFF); //patched supergroup ID
|
||||
// FF80000 (visualization aide)
|
||||
int tga = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID (TGA?)
|
||||
int unk1 = (msg_1 & 0xFF00) >> 8; //unknown 8 bit value preceeding the TGA/Options
|
||||
int sgid = (msg_1 & 0xFF); //patched supergroup ID expressed as an 8 bit value
|
||||
|
||||
//Note: SSN is the supergroup sequence number in P25 Harris lingo, but you would think this would be kind of redundant
|
||||
//since the SGID is itself a unique number as well (waste of bits), but guess that's how their systems work
|
||||
//that being said, the SSN is always the same for each SGID, so those values seem to go together here as well
|
||||
int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN
|
||||
int unk2 = (msg_2 & 0xF0000) >> 16; //unknown 4 bit value preceeding 20-bit target value of patch
|
||||
int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup
|
||||
//Observation: The SSN value appears to be unique, but also different between sites, as in, each site
|
||||
//has its own SSN for the same SGID patching, possibly a first come first serve pool value?
|
||||
int ssn = (msg_2 & 0xF800000) >> 23; //this value seems to incrememnt based on SGID, 5-bit value
|
||||
int unk2 = (msg_2 & 0x700000) >> 20; //unknown 3-bit value, possibly linked to TGA when patch is deleted
|
||||
int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup
|
||||
|
||||
//look at the 'zero' fields when on 'delete'
|
||||
// MSG_1 [FE00045] MSG_2 [FE00045]
|
||||
// FF80000 (visualization aide)
|
||||
int unk3 = (msg_1 & 0x7FF00) >> 8;
|
||||
int unk4 = (msg_2 & 0x7FF00) >> 8;
|
||||
|
||||
//Ilya, please don't nit fix my logging format for these, it breaks grep when parsing a bunch of these all at once
|
||||
fprintf (stderr, "%s", KWHT);
|
||||
fprintf (stderr, " System Dynamic Regroup :: SP-WGID: %03d; Target: %07d;", sgid, target);
|
||||
|
||||
if (sgid != target)
|
||||
{
|
||||
//decode potential TGA values (assumming same as Harris P25)
|
||||
//decided to disable the info presented below since I cannot confirm this
|
||||
// if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect
|
||||
// else fprintf (stderr, " Two-Way"); //Patch
|
||||
// if (tga & 2) fprintf (stderr, " Group");
|
||||
// else fprintf (stderr, " Radio"); //Individual
|
||||
fprintf (stderr, " Patch");
|
||||
if (tga & 1) fprintf (stderr, " Active;");
|
||||
else fprintf (stderr, " Delete;");
|
||||
|
||||
//switched from using the TGA nomenclature to a more generic OPTion since I think this value is still a form of option
|
||||
fprintf (stderr, " OPT: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value)
|
||||
if (unk1)
|
||||
fprintf (stderr, " UNK1: %01X;", unk1);
|
||||
if (unk2)
|
||||
fprintf (stderr, " UNK2: %02X;", unk2);
|
||||
fprintf (stderr, " SSN: %02X;", ssn); //this may or may not be a unique value to each SGID, is 1F for termination of a patch
|
||||
}
|
||||
|
||||
//07:25:17 Sync: +EDACS MSG_1 [FE00045] MSG_2 [FE00045] (MT1: 1F; MT2: C) System Dynamic Regroup :: SP-WGID: 069; Target: 0000069; One-Way Group Patch Delete TGA: 6;
|
||||
//Upon Reflection, thinking the same MT1 and MT2 values are in both messages, so appears to just be the SP-WGID here and a bunch of zeroes leading into it, and not a TGA value
|
||||
|
||||
else
|
||||
{
|
||||
fprintf (stderr, " Patch Delete;");
|
||||
if (unk3)
|
||||
fprintf (stderr, " UNK3: %01X;", unk3);
|
||||
if (unk4)
|
||||
fprintf (stderr, " UNK4: %02X;", unk4);
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s", KMAG); //just make it stick out for now
|
||||
fprintf (stderr, " System Dynamic Regroup :: SSN: %03d; SGID: %05d; Target: %07d;", ssn, sgid, target);
|
||||
if (unk1) fprintf (stderr, " UNK1: %X;", unk1); //this value seems to always be zero
|
||||
if (unk2) fprintf (stderr, " UNK2: %X;", unk2); //this value seems to always be zero
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b)
|
||||
|
|
@ -858,7 +908,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int source = (msg_2 & 0xFFFFF);
|
||||
|
||||
fprintf (stderr, "%s", KGRN);
|
||||
fprintf (stderr, " TDMA Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " TDMA Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Data Group Grant Update
|
||||
|
|
@ -869,7 +919,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int source = (msg_2 & 0xFFFFF);
|
||||
|
||||
fprintf (stderr, "%s", KBLU);
|
||||
fprintf (stderr, " Data Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " Data Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Voice Call Grant Update
|
||||
|
|
@ -908,7 +958,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
else fprintf (stderr, " Digital Group Call");
|
||||
if (is_update == 0) fprintf (stderr, " Assignment");
|
||||
else fprintf (stderr, " Update");
|
||||
fprintf (stderr, " :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn));
|
||||
|
||||
//Trunking mode is correlated to (but not guaranteed to match) the type of call:
|
||||
// - emergency calls - usually message trunking
|
||||
|
|
@ -983,7 +1033,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
|
||||
}
|
||||
}
|
||||
//I-Call Grant Update
|
||||
//I-Call/Test Call Assignment/Update
|
||||
else if (mt1 == 0x10)
|
||||
{
|
||||
lcn = (msg_2 & 0x1F00000) >> 20;
|
||||
|
|
@ -1005,34 +1055,34 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
if (source != 0) state->lastsrc = source;
|
||||
|
||||
//Call type for state
|
||||
state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL;
|
||||
if (target == 0 && source == 0) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL;
|
||||
else state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
|
||||
fprintf (stderr, "%s", KCYN);
|
||||
//Test calls are just I-Calls with source and target of 0
|
||||
if (target == 0 && source == 0)
|
||||
{
|
||||
//this seems to be the continuation of the Initiate Test Call Command
|
||||
//normally, this appears as an "Analog I-Call", but with 0 tg and src,
|
||||
//its possible that those values could still be present, and that all
|
||||
//"Analog I-Call" is meant to be the assignment and update of the initiation
|
||||
if (is_update) fprintf (stderr, " Test Call Update :: LCN: %02d;", lcn);
|
||||
else fprintf (stderr, " Test Call Assignment :: LCN: %02d;", lcn);
|
||||
fprintf (stderr, "%s", KMAG);
|
||||
fprintf (stderr, " Test Call");
|
||||
if (is_update == 0) fprintf (stderr, " Assignment");
|
||||
else fprintf (stderr, " Update");
|
||||
fprintf (stderr, " :: LCN [%02d]%s", lcn, getLcnStatusString(lcn));
|
||||
state->edacs_vc_lcn = lcn;
|
||||
//assign bogus values so that this will show up in ncurses terminal
|
||||
//and overwrite current values in the matrix
|
||||
state->lasttg = 999999999;
|
||||
state->lastsrc = 999999999;
|
||||
state->edacs_vc_call_type = 0x101; //manually set to 0x101 to trigger voice call in ncurses, but no other flags
|
||||
lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s", KCYN);
|
||||
if (is_digital == 0) fprintf (stderr, " Analog I-Call");
|
||||
else fprintf (stderr, " Digital I-Call");
|
||||
if (is_update == 0) fprintf (stderr, " Assignment");
|
||||
else fprintf (stderr, " Update");
|
||||
|
||||
fprintf (stderr, " :: Target [%08d] Source [%08d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: Target [%08d] Source [%08d] LCN [%02d]%s", target, source, lcn, getLcnStatusString(lcn));
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
|
@ -1104,7 +1154,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int source = (msg_2 & 0xFFFFF);
|
||||
|
||||
fprintf (stderr, "%s", KBLU);
|
||||
fprintf (stderr, " Channel Assignment (Unknown Data) :: Source [%08d] LCN [%02d]%s", source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " Channel Assignment (Unknown Data) :: Source [%08d] LCN [%02d]%s", source, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc"
|
||||
|
|
@ -1150,7 +1200,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
if (is_update == 0) fprintf (stderr, " Assignment");
|
||||
else fprintf (stderr, " Update");
|
||||
|
||||
fprintf (stderr, " :: Source [%08d] LCN [%02d]%s", source, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: Source [%08d] LCN [%02d]%s", source, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
char mode[8]; //allow, block, digital enc
|
||||
|
|
@ -1276,18 +1326,22 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
//Emergency Voice Group Channel Assignment (6.2.4.2)
|
||||
if (mt_a == 0x0 || mt_a == 0x1 || mt_a == 0x2 || mt_a == 0x3)
|
||||
{
|
||||
int is_digital = (mt_a == 0x2 || mt_a == 0x3) ? 1 : 0;
|
||||
int is_emergency = (mt_a == 0x1 || mt_a == 0x3) ? 1 : 0;
|
||||
int lid = ((msg_1 & 0x1FC0000) >> 11) | ((msg_2 & 0xFE0000) >> 17);
|
||||
int lcn = (msg_1 & 0x1F000) >> 12;
|
||||
int is_tx_trunk = (msg_1 & 0x800) >> 11;
|
||||
int group = (msg_1 & 0x7FF);
|
||||
int is_digital = (mt_a == 0x2 || mt_a == 0x3) ? 1 : 0;
|
||||
int is_emergency = (mt_a == 0x1 || mt_a == 0x3) ? 1 : 0;
|
||||
int lid = ((msg_1 & 0x1FC0000) >> 11) | ((msg_2 & 0xFE0000) >> 17);
|
||||
int lcn = (msg_1 & 0x1F000) >> 12;
|
||||
int is_tx_trunk = (msg_1 & 0x800) >> 11;
|
||||
int group = (msg_1 & 0x7FF);
|
||||
int is_agency_call = isAgencyCallGroup(group, state);
|
||||
int is_fleet_call = isFleetCallGroup(group, state);
|
||||
|
||||
fprintf (stderr, "%s", KGRN);
|
||||
fprintf (stderr, " Voice Group Channel Assignment ::");
|
||||
if (is_digital == 0) fprintf (stderr, " Analog");
|
||||
else fprintf (stderr, " Digital");
|
||||
fprintf (stderr, " Group [%04d] LID [%05d] LCN [%02d]%s", group, lid, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " Group [%04d] LID [%05d] LCN [%02d]%s", group, lid, lcn, getLcnStatusString(lcn));
|
||||
if (is_agency_call == 1) fprintf (stderr, " [Agency]");
|
||||
else if (is_agency_call == 1) fprintf (stderr, " [Fleet]");
|
||||
if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]");
|
||||
if (is_emergency == 1)
|
||||
{
|
||||
|
|
@ -1308,9 +1362,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
state->lastsrc = lid;
|
||||
|
||||
//Call type for state
|
||||
state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY;
|
||||
state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY;
|
||||
if (is_agency_call) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL;
|
||||
else if (is_fleet_call) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL;
|
||||
|
||||
char mode[8]; //allow, block, digital enc
|
||||
sprintf (mode, "%s", "");
|
||||
|
|
@ -1398,7 +1454,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
else fprintf (stderr, " Group [%04d]", target);
|
||||
if (is_from_lid == 1) fprintf (stderr, " -->");
|
||||
else fprintf (stderr, " <--");
|
||||
fprintf (stderr, " Port [%02d] LCN [%02d]%s", port, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " Port [%02d] LCN [%02d]%s", port, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc)
|
||||
|
|
@ -1461,7 +1517,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
else fprintf (stderr, " Digital");
|
||||
if (is_individual_id == 1) fprintf (stderr, " LID [%05d]", target);
|
||||
else fprintf (stderr, " Group [%04d]", target);
|
||||
fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc)
|
||||
|
|
@ -1481,19 +1537,25 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
//Channel Updates (6.2.4.7)
|
||||
//Source/caller being present in individual call channel updates reverse engineered from Montreal STM system
|
||||
//Test calls reverse engineered from HartLink system
|
||||
else if (mt_b == 0x3)
|
||||
{
|
||||
int mt_c = (msg_1 & 0x300000) >> 20;
|
||||
int lcn = (msg_1 & 0xF8000) >> 15;
|
||||
int is_individual = (msg_1 & 0x4000) >> 14;
|
||||
int is_emergency = (is_individual == 0) ? (msg_1 & 0x2000) >> 13 : 0;
|
||||
int group = (msg_1 & 0x7FF);
|
||||
int lid = (msg_1 & 0x3FFF);
|
||||
int source = (msg_2 & 0x3FFF); //Source only present in individual calls
|
||||
int mt_c = (msg_1 & 0x300000) >> 20;
|
||||
int lcn = (msg_1 & 0xF8000) >> 15;
|
||||
int is_individual = (msg_1 & 0x4000) >> 14;
|
||||
int is_emergency = (is_individual == 0) ? (msg_1 & 0x2000) >> 13 : 0;
|
||||
int group = (msg_1 & 0x7FF);
|
||||
int lid = (msg_1 & 0x3FFF);
|
||||
int source = (msg_2 & 0x3FFF); //Source only present in individual calls
|
||||
int is_agency_call = is_individual == 0 && isAgencyCallGroup(group, state);
|
||||
int is_fleet_call = is_individual == 0 && isFleetCallGroup(group, state);
|
||||
|
||||
//Abstract away to a target, and be sure to check whether it's an individual call later
|
||||
int target = (is_individual == 0) ? group : lid;
|
||||
|
||||
//Test calls are just individual calls with source and target of 0
|
||||
int is_test_call = (target == 0 && source == 0);
|
||||
|
||||
//Technically only MT-C 0x1 and 0x3 are defined in TSB 69.3 - using and extrapolating on legacy code
|
||||
int is_tx_trunk = (mt_c == 2 || mt_c == 3) ? 1 : 0;
|
||||
int is_digital = (mt_c == 1 || mt_c == 3) ? 1 : 0;
|
||||
|
|
@ -1503,16 +1565,23 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
fprintf (stderr, "%s", KGRN);
|
||||
fprintf (stderr, " Voice Group Channel Update ::");
|
||||
}
|
||||
else
|
||||
else if (is_test_call == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KCYN);
|
||||
fprintf (stderr, " Voice Individual Channel Update ::");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Voice Test Channel Update ::");
|
||||
}
|
||||
if (is_digital == 0) fprintf (stderr, " Analog");
|
||||
else fprintf (stderr, " Digital");
|
||||
if (is_individual == 0) fprintf (stderr, " Group [%04d]", target);
|
||||
else fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source);
|
||||
fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn));
|
||||
if (is_individual == 0) fprintf (stderr, " Group [%04d]", target);
|
||||
else if (is_test_call == 0) fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source);
|
||||
fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn));
|
||||
if (is_agency_call == 1) fprintf (stderr, " [Agency]");
|
||||
else if (is_fleet_call == 1) fprintf (stderr, " [Fleet]");
|
||||
if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]");
|
||||
if (is_emergency == 1)
|
||||
{
|
||||
|
|
@ -1539,6 +1608,8 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY;
|
||||
if (is_agency_call) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL;
|
||||
else if (is_fleet_call) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL;
|
||||
|
||||
char mode[8]; //allow, block, digital enc
|
||||
sprintf (mode, "%s", "");
|
||||
|
|
@ -1626,6 +1697,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
}
|
||||
//Individual Call Channel Assignment (6.2.4.9)
|
||||
//Analog and digital flag reverse engineered from Montreal STM system
|
||||
//Test calls reverse engineered from HartLink system
|
||||
else if (mt_b == 0x5)
|
||||
{
|
||||
int is_tx_trunk = (msg_1 & 0x200000) >> 21;
|
||||
|
|
@ -1634,12 +1706,26 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int target = (msg_1 & 0x3FFF);
|
||||
int source = (msg_2 & 0x3FFF);
|
||||
|
||||
fprintf (stderr, "%s", KCYN);
|
||||
fprintf (stderr, " Individual Call Channel Assignment ::");
|
||||
if (is_digital == 0) fprintf (stderr, " Analog");
|
||||
else fprintf (stderr, " Digital");
|
||||
fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn));
|
||||
if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]");
|
||||
if (target == 0 && source == 0)
|
||||
{
|
||||
fprintf (stderr, "%s", KMAG);
|
||||
fprintf (stderr, " Test Call Channel Assignment ::");
|
||||
fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn));
|
||||
|
||||
state->edacs_vc_lcn = lcn;
|
||||
//assign bogus values so that this will show up in ncurses terminal and overwrite current values in the matrix
|
||||
state->lasttg = 999999999;
|
||||
state->lastsrc = 999999999;
|
||||
lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it
|
||||
}
|
||||
else {
|
||||
fprintf (stderr, "%s", KCYN);
|
||||
fprintf (stderr, " Voice Individual Channel Assignment ::");
|
||||
if (is_digital == 0) fprintf (stderr, " Analog");
|
||||
else fprintf (stderr, " Digital");
|
||||
fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, getLcnStatusString(lcn));
|
||||
if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]");
|
||||
}
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
//LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc)
|
||||
|
|
@ -1654,8 +1740,9 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
state->lastsrc = source;
|
||||
|
||||
//Call type for state
|
||||
state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
if (target == 0 && source == 0) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL;
|
||||
else state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL;
|
||||
if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL;
|
||||
|
||||
char mode[8]; //allow, block, digital enc
|
||||
sprintf (mode, "%s", "");
|
||||
|
|
@ -1719,7 +1806,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
fprintf (stderr, " Console ");
|
||||
if (is_drop == 0) fprintf (stderr, " Unkey");
|
||||
else fprintf (stderr, " Drop");
|
||||
fprintf (stderr, " :: LID [%05d] LCN [%02d]%s", lid, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " :: LID [%05d] LCN [%02d]%s", lid, lcn, getLcnStatusString(lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Use MT-D
|
||||
|
|
@ -1743,7 +1830,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int adj_site_id = (msg_1 & 0x1F0) >> 4;
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Adjacent Site Control Channel :: Site ID [%02X][%03d] Index [%1d] LCN [%02d]%s", adj_site_id, adj_site_id, adj_site_index, adj_cc_lcn, get_lcn_status_string(adj_cc_lcn));
|
||||
fprintf (stderr, " Adjacent Site Control Channel :: Site ID [%02X][%03d] Index [%1d] LCN [%02d]%s", adj_site_id, adj_site_id, adj_site_index, adj_cc_lcn, getLcnStatusString(adj_cc_lcn));
|
||||
if (adj_site_id == 0 && adj_site_index == 0) fprintf (stderr, " [Adjacency Table Reset]");
|
||||
else if (adj_site_id != 0 && adj_site_index == 0) fprintf (stderr, " [Priority System Definition]");
|
||||
else if (adj_site_id == 0 && adj_site_index != 0) fprintf (stderr, " [Adjacencies Table Length Definition]");
|
||||
|
|
@ -1824,7 +1911,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int group = (msg_1 & 0x7FF);
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Assignment to Auxiliary CC :: Group [%04d] Aux CC LCN [%02d]%s", group, aux_cc_lcn, get_lcn_status_string(aux_cc_lcn));
|
||||
fprintf (stderr, " Assignment to Auxiliary CC :: Group [%04d] Aux CC LCN [%02d]%s", group, aux_cc_lcn, getLcnStatusString(aux_cc_lcn));
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
//Initiate Test Call Command (6.2.4.16)
|
||||
|
|
@ -1863,7 +1950,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
int site_id = (msg_1 & 0x1F);
|
||||
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
fprintf (stderr, " Standard/Networked :: Site ID [%02X][%03d] Priority [%1d] CC LCN [%02d]%s", site_id, site_id, priority, cc_lcn, get_lcn_status_string(cc_lcn));
|
||||
fprintf (stderr, " Standard/Networked :: Site ID [%02X][%03d] Priority [%1d] CC LCN [%02d]%s", site_id, site_id, priority, cc_lcn, getLcnStatusString(cc_lcn));
|
||||
if (is_failsoft == 1)
|
||||
{
|
||||
fprintf (stderr, "%s", KRED);
|
||||
|
|
@ -1932,7 +2019,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
fprintf (stderr, " ::");
|
||||
if (is_digital == 0) fprintf (stderr, " Analog");
|
||||
else fprintf (stderr, " Digital");
|
||||
fprintf (stderr, " LID [%05d] LCN [%02d]%s", lid, lcn, get_lcn_status_string(lcn));
|
||||
fprintf (stderr, " LID [%05d] LCN [%02d]%s", lid, lcn, getLcnStatusString(lcn));
|
||||
if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
|
|
@ -2069,7 +2156,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
|||
//let users know they need to select an operational mode with the switches below
|
||||
else
|
||||
{
|
||||
fprintf (stderr, " Detected: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk;");
|
||||
fprintf (stderr, " Detected EDACS: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk to specify the type");
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " MSG_1 [%07llX]", msg_1);
|
||||
fprintf (stderr, " MSG_2 [%07llX]", msg_2);
|
||||
|
|
|
|||
|
|
@ -1897,13 +1897,13 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state)
|
|||
voice2[i] = sample;
|
||||
}
|
||||
}
|
||||
|
||||
opts->rtl_rms = rtl_return_rms();
|
||||
#endif
|
||||
}
|
||||
|
||||
//read in RMS value for vox function; NOTE: will not work correctly SOCAT STDIO TCP due to blocking when no samples to read
|
||||
if (opts->audio_in_type == 3) opts->rtl_rms = rtl_return_rms();
|
||||
else opts->rtl_rms = raw_rms(voice1, nsam, 1) / 2; //dividing by two so mic isn't so sensitive on vox
|
||||
if (opts->audio_in_type != 3)
|
||||
opts->rtl_rms = raw_rms(voice1, nsam, 1) / 2; //dividing by two so mic isn't so sensitive on vox
|
||||
|
||||
//low pass filter
|
||||
if (opts->use_lpf == 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue