EDACS: Display cached call source on Standard, tune group calls on assignment (#241)

* Trim trailing whitespace

* EDACS: Display cached call source on Standard

The logic in `edacs-fme.c` didn't work, in retrospect, because it would have depended on getting back-to-back messages for the same call. In practice, that is unlikely even on an idle system as system state gets displayed.

Instead, cache on the display end, for a "better" user experience.

* EDACS: Pad channel freq to "000.000000 MHz"

* EDACS: Process/tune group calls on assignment
This commit is contained in:
ilyacodes 2024-03-24 17:48:46 -04:00 committed by GitHub
parent 8d432e8b3e
commit c8d00846b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 246 additions and 178 deletions

View File

@ -210,8 +210,8 @@ typedef struct
SF_INFO *audio_in_file_info; SF_INFO *audio_in_file_info;
uint32_t rtlsdr_center_freq; uint32_t rtlsdr_center_freq;
int rtlsdr_ppm_error; int rtlsdr_ppm_error;
int audio_in_type; int audio_in_type;
char audio_out_dev[1024]; char audio_out_dev[1024];
int audio_out_fd; int audio_out_fd;
int audio_out_fdR; //right channel audio for OSS hack int audio_out_fdR; //right channel audio for OSS hack
@ -367,7 +367,7 @@ typedef struct
char group_in_file[1024]; char group_in_file[1024];
char lcn_in_file[1024]; char lcn_in_file[1024];
char chan_in_file[1024]; char chan_in_file[1024];
char key_in_file[1024]; char key_in_file[1024];
//end import filenames //end import filenames
//reverse mute //reverse mute
@ -454,7 +454,7 @@ typedef struct
short s_ru[160*6]; //single sample right short s_ru[160*6]; //single sample right
short s_l4u[4][160*6]; //quad sample for up to a P25p2 4V short s_l4u[4][160*6]; //quad sample for up to a P25p2 4V
short s_r4u[4][160*6]; //quad sample for up to a P25p2 4V short s_r4u[4][160*6]; //quad sample for up to a P25p2 4V
//end //end
int audio_out_idx; int audio_out_idx;
int audio_out_idx2; int audio_out_idx2;
int audio_out_idxR; int audio_out_idxR;
@ -616,7 +616,7 @@ typedef struct
char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify char dmr_cach_fragment[4][17]; //unsure of size, will need to check/verify
int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet. int dmr_cach_counter; //counter for dmr_cach_fragments 0-3; not sure if needed yet.
//dmr talker alias new/fixed stuff //dmr talker alias new/fixed stuff
uint8_t dmr_alias_format[2]; //per slot uint8_t dmr_alias_format[2]; //per slot
uint8_t dmr_alias_len[2]; //per slot uint8_t dmr_alias_len[2]; //per slot
@ -1188,7 +1188,7 @@ bool crc8_ok(uint8_t bits[], unsigned int len);
//modified CRC functions for SB/RC //modified CRC functions for SB/RC
uint8_t crc7(uint8_t bits[], unsigned int len); uint8_t crc7(uint8_t bits[], unsigned int len);
uint8_t crc3(uint8_t bits[], unsigned int len); uint8_t crc3(uint8_t bits[], unsigned int len);
uint8_t crc4(uint8_t bits[], unsigned int len); uint8_t crc4(uint8_t bits[], unsigned int len);
//LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/ //LFSR and LFSRP code courtesy of https://github.com/mattames/LFSR/
void LFSR(dsd_state * state); void LFSR(dsd_state * state);

View File

@ -7,6 +7,9 @@
* *
* LWVMOBILE * LWVMOBILE
* 2022-08 DSD-FME Florida Man Edition * 2022-08 DSD-FME Florida Man Edition
*
* ilyacodes
* 2024-03 EDACS-FME display improvements
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
@ -110,13 +113,13 @@ char * DMRBusrtTypes[32] = {
"R34D ", "R34D ",
"IDLE ", "IDLE ",
"R1_D ", "R1_D ",
"ERR ", "ERR ",
"DUID ERR ", "DUID ERR ",
"R-S ERR ", "R-S ERR ",
"CRC ERR ", "CRC ERR ",
"NULL ", "NULL ",
"VOICE", "VOICE",
" ", " ",
"INIT ", "INIT ",
"INIT ", "INIT ",
"PTT", //20 MAC "PTT", //20 MAC
@ -188,7 +191,7 @@ void beeper (dsd_opts * opts, dsd_state * state, int lr)
if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 0) if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 0)
pa_simple_write(opts->pulse_digi_dev_out, samp_s, 160*2, NULL); pa_simple_write(opts->pulse_digi_dev_out, samp_s, 160*2, NULL);
} }
else if (opts->audio_out_type == 8) //UDP Audio else if (opts->audio_out_type == 8) //UDP Audio
@ -204,7 +207,7 @@ void beeper (dsd_opts * opts, dsd_state * state, int lr)
if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 0) if (opts->pulse_digi_out_channels == 1 && opts->floating_point == 0)
udp_socket_blaster (opts, state, 160*2, samp_s); udp_socket_blaster (opts, state, 160*2, samp_s);
} }
else if (opts->audio_out_type == 1) //STDOUT else if (opts->audio_out_type == 1) //STDOUT
@ -245,10 +248,10 @@ void beeper (dsd_opts * opts, dsd_state * state, int lr)
samp_su[(i*6)+4] = outbuf[4]; samp_su[(i*6)+4] = outbuf[4];
samp_su[(i*6)+5] = outbuf[5]; samp_su[(i*6)+5] = outbuf[5];
} }
write (opts->audio_out_fd, samp_su, 960*2); write (opts->audio_out_fd, samp_su, 960*2);
} }
} }
} }
@ -328,7 +331,7 @@ char *choicesc[] = {
"Setup and Start RTL Input ", "Setup and Start RTL Input ",
"Retune RTL Dongle ", "Retune RTL Dongle ",
"Toggle C4FM/QPSK (P2 TDMA CC)", "Toggle C4FM/QPSK (P2 TDMA CC)",
"Toggle C4FM/QPSK (P1 FDMA CC)", "Toggle C4FM/QPSK (P1 FDMA CC)",
"Start TCP Direct Link Audio", "Start TCP Direct Link Audio",
"Configure RIGCTL", "Configure RIGCTL",
"Stop All Decoded WAV Saving", "Stop All Decoded WAV Saving",
@ -415,7 +418,7 @@ void ncursesOpen (dsd_opts * opts, dsd_state * state)
//this is primarily used to push a quick audio blip through OSS so it will show up in the mixer immediately //this is primarily used to push a quick audio blip through OSS so it will show up in the mixer immediately
// if (opts->audio_out_type == 2 || opts->audio_out_type == 5) // if (opts->audio_out_type == 2 || opts->audio_out_type == 5)
// beeper (opts, state, 0); //causes crash in Cygwin when mixed input/output // beeper (opts, state, 0); //causes crash in Cygwin when mixed input/output
//terminate all values //terminate all values
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
sprintf (alias_ch[i], "%s", ""); sprintf (alias_ch[i], "%s", "");
@ -462,7 +465,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
closePulseOutput (opts); closePulseOutput (opts);
} }
//close OSS output //close OSS output
if (opts->audio_out_type == 2 || opts->audio_out_type == 5) if (opts->audio_out_type == 2 || opts->audio_out_type == 5)
{ {
close (opts->audio_out_fd); close (opts->audio_out_fd);
@ -760,7 +763,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->rtl_dev_index = i; opts->rtl_dev_index = i;
break; break;
} }
} }
entry_win = newwin(17, WIDTH+20, starty+10, startx+10); entry_win = newwin(17, WIDTH+20, starty+10, startx+10);
@ -861,7 +864,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
// if (opts->audio_out == 0) // if (opts->audio_out == 0)
// { // {
// opts->audio_out = 1; // opts->audio_out = 1;
// opts->audio_out_type = 0; // opts->audio_out_type = 0;
// // state->audio_out_buf_p = 0; // // state->audio_out_buf_p = 0;
// // state->audio_out_buf_pR = 0; // // state->audio_out_buf_pR = 0;
// state->audio_out_idx = 0; // state->audio_out_idx = 0;
@ -933,7 +936,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
opts->audio_in_type = 0; opts->audio_in_type = 0;
} }
else opts->audio_in_type = 5; else opts->audio_in_type = 5;
} }
state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing state->audio_smoothing = 0; //disable smoothing to prevent random crackling/buzzing
@ -1222,7 +1225,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
wscanw(entry_win, "%lld", &state->R); wscanw(entry_win, "%lld", &state->R);
noecho(); noecho();
if (state->R > 0x7FFF) state->R = 0x7FFF; if (state->R > 0x7FFF) state->R = 0x7FFF;
state->keyloader = 0; //turn off keyloader state->keyloader = 0; //turn off keyloader
} }
//toggle enforcement of basic privacy key over enc bit set on traffic //toggle enforcement of basic privacy key over enc bit set on traffic
@ -1844,7 +1847,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
{ {
openOSSOutput (opts); openOSSOutput (opts);
} }
if (opts->audio_in_type == 0) //reopen pulse input if it is the specified input method if (opts->audio_in_type == 0) //reopen pulse input if it is the specified input method
{ {
@ -1854,7 +1857,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 3) //open rtl input if it is the specified input method if (opts->audio_in_type == 3) //open rtl input if it is the specified input method
{ {
// ncursesPrinter (opts, state); //not sure why this was placed here originally, but causes a double free core dump when calling free(timestr) // ncursesPrinter (opts, state); //not sure why this was placed here originally, but causes a double free core dump when calling free(timestr)
#ifdef USE_RTLSDR #ifdef USE_RTLSDR
if (opts->rtl_started == 0) if (opts->rtl_started == 0)
{ {
opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again
@ -1892,7 +1895,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN - if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
{ {
timeout(0); // timeout(0); //
c = getch(); // c = getch(); //
} }
@ -1908,7 +1911,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Variable reset/set section //Variable reset/set section
//set lls sync types //set lls sync types
if (state->synctype >= 0 && state->synctype < 39) if (state->synctype >= 0 && state->synctype < 39)
{ {
lls = state->synctype; lls = state->synctype;
} }
@ -2002,16 +2005,22 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Edacs - ProVoice //Edacs - ProVoice
if ( (lls == 14 || lls == 15 || lls == 37 || lls == 38) && state->carrier == 1) if ( (lls == 14 || lls == 15 || lls == 37 || lls == 38) && state->carrier == 1)
{ {
if (state->edacs_vc_lcn != -1) if (state->edacs_vc_lcn != -1)
{ {
call_matrix[state->edacs_vc_lcn][0] = lls; call_matrix[state->edacs_vc_lcn][0] = lls;
call_matrix[state->edacs_vc_lcn][1] = state->edacs_vc_lcn; call_matrix[state->edacs_vc_lcn][1] = state->edacs_vc_lcn;
call_matrix[state->edacs_vc_lcn][2] = state->lasttg; call_matrix[state->edacs_vc_lcn][2] = state->lasttg;
call_matrix[state->edacs_vc_lcn][3] = state->lastsrc; //EDACS standard does not provide source LIDs on channel update messages; instead, for the sake of display, let's
//assume the prior source for a given LCN is still accurate, unless we have an updated one provided.
//
//If you MUST have perfectly-accurate source LIDs, look at the logged CC messages yourself - incorrect source LIDs
//may be displayed if we miss an initial call channel assignment.
if (state->ea_mode == 1 || state->lastsrc != 0)
call_matrix[state->edacs_vc_lcn][3] = state->lastsrc;
call_matrix[state->edacs_vc_lcn][4] = 1; call_matrix[state->edacs_vc_lcn][4] = 1;
call_matrix[state->edacs_vc_lcn][5] = time(NULL); call_matrix[state->edacs_vc_lcn][5] = time(NULL);
} }
} }
@ -2074,7 +2083,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
} }
//TODO: Find better placement for these //TODO: Find better placement for these
if ( strcmp(state->str50a, "") != 0 ) if ( strcmp(state->str50a, "") != 0 )
sprintf (alias_ch[9], "%s", state->str50a); sprintf (alias_ch[9], "%s", state->str50a);
@ -2257,7 +2266,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// state->lastsrc = 0; // state->lastsrc = 0;
// rd = 0; // rd = 0;
// tg = 0; // tg = 0;
// } // }
// if (state->dmrburstR == 2 && state->dmr_end_alert[1] == 0) //if TLC and flag not tripped // if (state->dmrburstR == 2 && state->dmr_end_alert[1] == 0) //if TLC and flag not tripped
// { // {
// beeper (opts, state, 1); // beeper (opts, state, 1);
@ -2266,7 +2275,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// state->lastsrcR = 0; // state->lastsrcR = 0;
// rdR = 0; // rdR = 0;
// tgR = 0; // tgR = 0;
// } // }
// } // }
//Start Printing Section //Start Printing Section
@ -2276,7 +2285,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "AW (20231015)"); printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "AW (20231015)");
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
} }
#elif LIMAZULUTWEAKS #elif LIMAZULUTWEAKS
if (opts->ncurses_compact == 1) if (opts->ncurses_compact == 1)
@ -2318,7 +2327,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
#elif ZDEV_BUILD #elif ZDEV_BUILD
if (i == 5) printw (" %s ", "AW "); if (i == 5) printw (" %s ", "AW ");
if (i == 6) printw (" %s \n", GIT_TAG); if (i == 6) printw (" %s \n", GIT_TAG);
#else #else
if (i == 5) printw (" %s ", "AW "); if (i == 5) printw (" %s ", "AW ");
if (i == 6) printw (" %s \n", GIT_TAG); if (i == 6) printw (" %s \n", GIT_TAG);
#endif #endif
@ -2383,7 +2392,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw (" SQ: %i;", opts->rtl_squelch_level); printw (" SQ: %i;", opts->rtl_squelch_level);
printw (" RMS: %04li;", opts->rtl_rms); printw (" RMS: %04li;", opts->rtl_rms);
printw (" BW: %i kHz;", opts->rtl_bandwidth); printw (" BW: %i kHz;", opts->rtl_bandwidth);
printw (" FRQ: %i;", opts->rtlsdr_center_freq); printw (" FRQ: %i;", opts->rtlsdr_center_freq);
if (opts->rtl_udp_port != 0) printw ("\n| External RTL Tuning on UDP Port: %i", opts->rtl_udp_port); if (opts->rtl_udp_port != 0) printw ("\n| External RTL Tuning on UDP Port: %i", opts->rtl_udp_port);
printw ("\n"); printw ("\n");
} }
@ -2529,7 +2538,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(2)); attron(COLOR_PAIR(2));
printw (" Standard/Network"); printw (" Standard/Network");
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
printw (" Extended Address"); printw (" Extended Address");
} }
printw (" Mode (S);"); printw (" Mode (S);");
@ -2556,7 +2565,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else if (state->ea_mode == 1) else if (state->ea_mode == 1)
{ {
printw (" standard/network"); printw (" standard/network");
printw (" EXTENDED ADDRESS"); printw (" EXTENDED ADDRESS");
} }
printw (" Mode (S);"); printw (" Mode (S);");
@ -2581,9 +2590,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->scanner_mode == 1) if (opts->scanner_mode == 1)
{ {
printw ("| Scan Mode: "); printw ("| Scan Mode: ");
if (state->lcn_freq_roll != 0) if (state->lcn_freq_roll != 0)
printw (" Frequency: %.06lf Mhz", (double)state->trunk_lcn_freq[state->lcn_freq_roll-1]/1000000); printw (" Frequency: %.06lf Mhz", (double)state->trunk_lcn_freq[state->lcn_freq_roll-1]/1000000);
printw (" Speed: %.02lf sec \n", opts->trunk_hangtime); //not sure values less than 1 make a difference, may be system/environment dependent printw (" Speed: %.02lf sec \n", opts->trunk_hangtime); //not sure values less than 1 make a difference, may be system/environment dependent
} }
if (opts->reverse_mute == 1) printw ("| Reverse Mute - Muting Unencrypted Voice\n"); if (opts->reverse_mute == 1) printw ("| Reverse Mute - Muting Unencrypted Voice\n");
@ -2625,7 +2634,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
printw ("\n"); printw ("\n");
printw ("| In Level: [%02d%%] \n", level); printw ("| In Level: [%02d%%] \n", level);
if (opts->dmr_stereo == 0) if (opts->dmr_stereo == 0)
{ {
printw ("| Voice Error: [%i][%i]", state->errs, state->errs2); printw ("| Voice Error: [%i][%i]", state->errs, state->errs2);
@ -2648,7 +2657,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("------------------------------------------------------------------------------\n"); printw ("------------------------------------------------------------------------------\n");
printw ("--Call Info-------------------------------------------------------------------\n"); printw ("--Call Info-------------------------------------------------------------------\n");
//DSTAR //DSTAR
if (lls == 6 || lls == 7 || lls == 18 || lls == 19) if (lls == 6 || lls == 7 || lls == 18 || lls == 19)
{ {
@ -2689,7 +2698,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("RESERVED (%012llx) ", state->m17_dst); printw("RESERVED (%012llx) ", state->m17_dst);
else else
printw("%s", state->m17_dst_str); printw("%s", state->m17_dst_str);
printw ("\n"); printw ("\n");
printw ("| "); printw ("| ");
@ -2699,7 +2708,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else else
printw("%s", state->m17_src_str); printw("%s", state->m17_src_str);
printw ("\n"); printw ("\n");
printw ("| "); printw ("| ");
@ -2726,7 +2735,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (state->m17_enc == 3) if (state->m17_enc == 3)
{ {
printw (" Reserved Enc - Type: %d", state->m17_enc_st); printw (" Reserved Enc - Type: %d", state->m17_enc_st);
} }
printw ("\n"); printw ("\n");
@ -2787,7 +2796,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// printw ("%c", state->ysf_txt[i][j]); // printw ("%c", state->ysf_txt[i][j]);
// } // }
// // printw (" "); //just a single space between each 'block' // // printw (" "); //just a single space between each 'block'
// } // }
printw ("\n"); printw ("\n");
@ -2810,7 +2819,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
printw (" - Frequency: %.06lf Mhz ", (double)state->p25_cc_freq/1000000); printw (" - Frequency: %.06lf Mhz ", (double)state->p25_cc_freq/1000000);
} }
} }
else if (opts->p25_is_tuned == 1) else if (opts->p25_is_tuned == 1)
{ {
if (idas == 0) printw ("Monitoring RTCH Channel"); //Traffic Channel if (idas == 0) printw ("Monitoring RTCH Channel"); //Traffic Channel
@ -2823,8 +2832,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("\n"); printw ("\n");
} }
printw ("| "); printw ("| ");
// #ifdef LIMAZULUTWEAKS // #ifdef LIMAZULUTWEAKS
@ -2922,10 +2931,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
//Active Trunking Channels (NXDN and IDAS) //Active Trunking Channels (NXDN and IDAS)
if (1 == 1) //opts->p25_trunk if (1 == 1) //opts->p25_trunk
{ {
printw ("\n"); printw ("\n");
printw ("| "); printw ("| ");
//active channel display //active channel display
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
@ -2943,8 +2952,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw("\n"); printw("\n");
} }
//P25 and DMR BS/MS //P25 and DMR BS/MS
if ( lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 || if ( lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 ||
lls == 11 || lls == 32 || lls == 33 || lls == 34 || lls == 35 || lls == 36) lls == 11 || lls == 32 || lls == 33 || lls == 34 || lls == 35 || lls == 36)
{ {
@ -2955,7 +2964,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// printw ("%s %s", state->dmr_branding, state->dmr_branding_sub); // printw ("%s %s", state->dmr_branding, state->dmr_branding_sub);
printw ("%s ", state->dmr_branding); printw ("%s ", state->dmr_branding);
printw ("%s", state->dmr_branding_sub); printw ("%s", state->dmr_branding_sub);
printw ("%s", state->dmr_site_parms); //site id, net id, etc printw ("%s", state->dmr_site_parms); //site id, net id, etc
if (state->dmr_rest_channel > 0) if (state->dmr_rest_channel > 0)
{ {
printw ("Rest LSN: %02d; ", state->dmr_rest_channel); printw ("Rest LSN: %02d; ", state->dmr_rest_channel);
@ -2968,7 +2977,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
printw ("Freq: %.06lf MHz", (double)state->p25_cc_freq/1000000); printw ("Freq: %.06lf MHz", (double)state->p25_cc_freq/1000000);
} }
} }
else if (lls == 32 || lls == 33 || lls == 34) else if (lls == 32 || lls == 33 || lls == 34)
{ {
@ -2997,7 +3006,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw (" Phase 2 Invalid Parameters "); printw (" Phase 2 Invalid Parameters ");
attron(COLOR_PAIR(3)); attron(COLOR_PAIR(3));
} }
else else
{ {
if (state->p25_cc_freq != 0) if (state->p25_cc_freq != 0)
{ {
@ -3119,7 +3128,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Not always correct, or correct at all, depends on context //Not always correct, or correct at all, depends on context
//this is already in the call_string anyways //this is already in the call_string anyways
// if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000 // if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000
// { // {
// attron(COLOR_PAIR(2)); // attron(COLOR_PAIR(2));
@ -3156,13 +3165,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Embedded GPS (not LRRP) //Embedded GPS (not LRRP)
printw ("%s ", state->dmr_embedded_gps[0]); printw ("%s ", state->dmr_embedded_gps[0]);
//Embedded Talker Alias Blocks //Embedded Talker Alias Blocks
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
for (int j = 0; j < 7; j++) for (int j = 0; j < 7; j++)
{ {
printw ("%s", state->dmr_alias_block_segment[0][i][j]); printw ("%s", state->dmr_alias_block_segment[0][i][j]);
} }
} }
@ -3205,7 +3214,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//Slot 2 [1] -- Also Including DMR MS now to keep the display more 'uniform' in nature //Slot 2 [1] -- Also Including DMR MS now to keep the display more 'uniform' in nature
// if (lls < 30 || lls == 35 || lls == 36) // if (lls < 30 || lls == 35 || lls == 36)
{ {
printw ("| SLOT 2 - "); printw ("| SLOT 2 - ");
if (state->dmrburstR < 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0) if (state->dmrburstR < 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0)
{ {
@ -3221,10 +3230,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
printw ("%s | ", state->call_string[1]); printw ("%s | ", state->call_string[1]);
printw ("%s ", DMRBusrtTypes[state->dmrburstR]); printw ("%s ", DMRBusrtTypes[state->dmrburstR]);
if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && ( state->dmrburstL == 16 || state->dmrburstL == 21) && (state->dmrburstR == 16 || state->dmrburstR == 21) ) printw ("*M*"); if (opts->slot_preference == 0 && opts->audio_out_type == 5 && opts->audio_out == 1 && ( state->dmrburstL == 16 || state->dmrburstL == 21) && (state->dmrburstR == 16 || state->dmrburstR == 21) ) printw ("*M*");
printw ("\n"); printw ("\n");
printw ("| V XTRA | "); //10 spaces printw ("| V XTRA | "); //10 spaces
if(state->dmrburstR == 16 && state->payload_algidR == 0 && (state->dmr_soR & 0xCF) == 0x40) //4F or CF mask? if(state->dmrburstR == 16 && state->payload_algidR == 0 && (state->dmr_soR & 0xCF) == 0x40) //4F or CF mask?
@ -3345,7 +3354,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if(state->dmrburstR == 16 || state->dmrburstR == 21) //only during call if(state->dmrburstR == 16 || state->dmrburstR == 21) //only during call
{ {
//Embedded GPS (not LRRP) //Embedded GPS (not LRRP)
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
printw ("%s ", state->dmr_embedded_gps[1]); printw ("%s ", state->dmr_embedded_gps[1]);
@ -3355,7 +3364,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
for (int j = 0; j < 7; j++) for (int j = 0; j < 7; j++)
{ {
printw ("%s", state->dmr_alias_block_segment[1][i][j]); printw ("%s", state->dmr_alias_block_segment[1][i][j]);
} }
} }
@ -3373,7 +3382,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attron(COLOR_PAIR(4)); attron(COLOR_PAIR(4));
printw ("%s", state->dmr_lrrp_gps[1]); printw ("%s", state->dmr_lrrp_gps[1]);
} }
//Group Name Labels from CSV import //Group Name Labels from CSV import
if (state->dmrburstR == 16 || state->dmrburstR > 19) if (state->dmrburstR == 16 || state->dmrburstR > 19)
{ {
@ -3461,7 +3470,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//EDACS and ProVoice //EDACS and ProVoice
if (lls == 14 || lls == 15 || lls == 37 || lls == 38) if (lls == 14 || lls == 15 || lls == 37 || lls == 38)
{ {
attroff (COLOR_PAIR(3)); //colors off for EDACS attroff (COLOR_PAIR(3)); //colors off for EDACS
if (state->edacs_site_id != 0) if (state->edacs_site_id != 0)
{ {
if (opts->p25_is_tuned == 0) if (opts->p25_is_tuned == 0)
@ -3472,8 +3481,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
printw ("| Monitoring Voice Channel - LCN [%02d]\n", state->edacs_tuned_lcn); printw ("| Monitoring Voice Channel - LCN [%02d]\n", state->edacs_tuned_lcn);
//since we are tuned, keep updating the time so it doesn't disappear during call //since we are tuned, keep updating the time so it doesn't disappear during call
call_matrix[state->edacs_tuned_lcn][5] = time(NULL); call_matrix[state->edacs_tuned_lcn][5] = time(NULL);
} }
printw ("| SITE [%03lld][%02llX]", state->edacs_site_id, state->edacs_site_id); printw ("| SITE [%03lld][%02llX]", state->edacs_site_id, state->edacs_site_id);
if (state->ea_mode == 1) if (state->ea_mode == 1)
@ -3493,8 +3502,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// Compute 4:4:3 AFS for display purposes only // Compute 4:4:3 AFS for display purposes only
int a = (call_matrix[i][2] >> 7) & 0xF; int a = (call_matrix[i][2] >> 7) & 0xF;
int fs = call_matrix[i][2] & 0x7F; int fs = call_matrix[i][2] & 0x7F;
printw ("| - LCN [%02d][%.06lf] MHz", i, (double)state->trunk_lcn_freq[i-1]/1000000); printw ("| - LCN [%02d][%010.06lf] MHz", i, (double)state->trunk_lcn_freq[i-1]/1000000);
//print Control Channel on LCN line with the current Control Channel //print Control Channel on LCN line with the current Control Channel
if ( (i) == state->edacs_cc_lcn) if ( (i) == state->edacs_cc_lcn)
{ {
@ -3503,9 +3512,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
attroff (COLOR_PAIR(1)); attroff (COLOR_PAIR(1));
} }
//print active calls on corresponding LCN line //print active calls on corresponding LCN line
if ((i != state->edacs_cc_lcn) && time(NULL) - call_matrix[i][5] < 2) if ((i != state->edacs_cc_lcn) && time(NULL) - call_matrix[i][5] < 2)
{ {
attron (COLOR_PAIR(3)); attron (COLOR_PAIR(3));
if (state->ea_mode == 1) { if (state->ea_mode == 1) {
if (call_matrix[i][2] + 1 == 0) if (call_matrix[i][2] + 1 == 0)
// System all-call // System all-call
@ -3544,12 +3553,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
break; break;
} }
} }
attroff (COLOR_PAIR(3)); attroff (COLOR_PAIR(3));
} }
//print dying or dead calls in red for x seconds longer //print dying or dead calls in red for x seconds longer
if ( (i != state->edacs_cc_lcn) && (time(NULL) - call_matrix[i][5] >= 2) && (time(NULL) - call_matrix[i][5] < 5) ) if ( (i != state->edacs_cc_lcn) && (time(NULL) - call_matrix[i][5] >= 2) && (time(NULL) - call_matrix[i][5] < 5) )
{ {
attron (COLOR_PAIR(2)); attron (COLOR_PAIR(2));
if (state->ea_mode == 1) { if (state->ea_mode == 1) {
if (call_matrix[i][2] + 1 == 0) if (call_matrix[i][2] + 1 == 0)
// System all-call // System all-call
@ -3588,14 +3597,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
break; break;
} }
} }
attroff (COLOR_PAIR(2)); attroff (COLOR_PAIR(2));
} }
if (i == state->edacs_tuned_lcn && opts->p25_is_tuned == 1) printw (" **T**"); //asterisk which lcn is opened if (i == state->edacs_tuned_lcn && opts->p25_is_tuned == 1) printw (" **T**"); //asterisk which lcn is opened
printw ("\n"); printw ("\n");
} }
if (state->carrier == 1) if (state->carrier == 1)
{ {
attron (COLOR_PAIR(3)); attron (COLOR_PAIR(3));
} }
} }
@ -3687,10 +3696,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//EDACS and ProVoice, outside of timestamp loop //EDACS and ProVoice, outside of timestamp loop
if (call_matrix[j][0] == 14 || call_matrix[j][0] == 15 || call_matrix[j][0] == 37 || call_matrix[j][0] == 38 ) if (call_matrix[j][0] == 14 || call_matrix[j][0] == 15 || call_matrix[j][0] == 37 || call_matrix[j][0] == 38 )
{ {
if (call_matrix[j][2] != 0) if (call_matrix[j][2] != 0)
{ {
printw ("| "); printw ("| ");
printw ("%s ", getDateC(call_matrix[j][5]) ); printw ("%s ", getDateC(call_matrix[j][5]) );
printw ("%s ", getTimeC(call_matrix[j][5]) ); printw ("%s ", getTimeC(call_matrix[j][5]) );
printw ("LCN [%2lld] ", call_matrix[j][1]); printw ("LCN [%2lld] ", call_matrix[j][1]);
if (state->ea_mode == 1) if (state->ea_mode == 1)
@ -3705,10 +3714,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// Group call // Group call
printw ("Target [%8lld] Source [%8lld]", call_matrix[j][2], call_matrix[j][3]); printw ("Target [%8lld] Source [%8lld]", call_matrix[j][2], call_matrix[j][3]);
} }
else else
{ {
// Compute 4:4:3 AFS for display purposes only // Compute 4:4:3 AFS for display purposes only
int a = (call_matrix[j][2] >> 7) & 0xF; int a = (call_matrix[j][2] >> 7) & 0xF;
int fs = call_matrix[j][2] & 0x7F; int fs = call_matrix[j][2] & 0x7F;
if (call_matrix[j][2] + 1 == 0) if (call_matrix[j][2] + 1 == 0)
// System all-call // System all-call
@ -3719,7 +3728,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else else
// Group call // Group call
printw ("Target [%6lld][%02d-%03d] Source [%5lld]", call_matrix[j][2], a, fs, call_matrix[j][3]); printw ("Target [%6lld][%02d-%03d] Source [%5lld]", call_matrix[j][2], a, fs, call_matrix[j][3]);
} }
//test //test
for (int k = 0; k < state->group_tally; k++) for (int k = 0; k < state->group_tally; k++)
{ {
@ -3739,7 +3748,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
//end test //end test
printw ("\n"); printw ("\n");
} }
} }
} //end Call History } //end Call History
//fence bottom //fence bottom
@ -3796,7 +3805,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else if (opts->slot1_on == 0) else if (opts->slot1_on == 0)
{ {
opts->slot1_on = 1; opts->slot1_on = 1;
if (opts->audio_out_type == 5) //OSS 48k/1 if (opts->audio_out_type == 5) //OSS 48k/1
{ {
opts->slot_preference = 0; //slot 1 opts->slot_preference = 0; //slot 1
// opts->slot2_on = 0; //turn off slot 2 // opts->slot2_on = 0; //turn off slot 2
@ -3822,7 +3831,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
else if (opts->slot2_on == 0) else if (opts->slot2_on == 0)
{ {
opts->slot2_on = 1; opts->slot2_on = 1;
if (opts->audio_out_type == 5) //OSS 48k/1 if (opts->audio_out_type == 5) //OSS 48k/1
{ {
opts->slot_preference = 1; //slot 2 opts->slot_preference = 1; //slot 2
// opts->slot1_on = 0; //turn off slot 1 // opts->slot1_on = 0; //turn off slot 1
@ -4028,14 +4037,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
fprintf (stderr, "-T %s wav file directory does not exist\n", wav_file_directory); fprintf (stderr, "-T %s wav file directory does not exist\n", wav_file_directory);
fprintf (stderr, "Creating directory %s to save decoded wav files\n", wav_file_directory); fprintf (stderr, "Creating directory %s to save decoded wav files\n", wav_file_directory);
mkdir(wav_file_directory, 0700); mkdir(wav_file_directory, 0700);
} }
opts->dmr_stereo_wav = 1; opts->dmr_stereo_wav = 1;
//catch all in case of no file name set, won't crash or something //catch all in case of no file name set, won't crash or something
sprintf (opts->wav_out_file, "./%s/DSD-FME-T1.wav", opts->wav_out_dir); sprintf (opts->wav_out_file, "./%s/DSD-FME-T1.wav", opts->wav_out_dir);
sprintf (opts->wav_out_fileR, "./%s/DSD-FME-T2.wav", opts->wav_out_dir); sprintf (opts->wav_out_fileR, "./%s/DSD-FME-T2.wav", opts->wav_out_dir);
openWavOutFileL (opts, state); openWavOutFileL (opts, state);
openWavOutFileR (opts, state); openWavOutFileR (opts, state);
} }
//this one could cause issues, but seems okay //this one could cause issues, but seems okay
@ -4052,15 +4061,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// //
#ifdef AERO_BUILD //this might be okay on Aero as well, will need to look into and/or test #ifdef AERO_BUILD //this might be okay on Aero as well, will need to look into and/or test
// //
#else #else
if (c == 115) //'s' key, stop playing wav or symbol in files if (c == 115) //'s' key, stop playing wav or symbol in files
{ {
if (opts->symbolfile != NULL) if (opts->symbolfile != NULL)
{ {
if (opts->audio_in_type == 4) if (opts->audio_in_type == 4)
{ {
fclose(opts->symbolfile); fclose(opts->symbolfile);
} }
} }
@ -4074,12 +4083,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
opts->audio_in_type = 0; opts->audio_in_type = 0;
openPulseInput(opts); openPulseInput(opts);
} }
else opts->audio_in_type = 5; //exitflag = 1; else opts->audio_in_type = 5; //exitflag = 1;
} }
#endif #endif
//makes buzzing sound when locked out in new audio config and short, probably something to do with processaudio running or not running //makes buzzing sound when locked out in new audio config and short, probably something to do with processaudio running or not running
if (state->lasttg != 0 && opts->frame_provoice != 1 && c == 33) //SHIFT+'1' key (exclamation point), lockout slot 1 or conventional tg from tuning/playback during session if (state->lasttg != 0 && opts->frame_provoice != 1 && c == 33) //SHIFT+'1' key (exclamation point), lockout slot 1 or conventional tg from tuning/playback during session
{ {
state->group_array[state->group_tally].groupNumber = state->lasttg; state->group_array[state->group_tally].groupNumber = state->lasttg;
@ -4215,40 +4224,40 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
// if (c == 48) //'0' key, toggle upsampled audio smoothing // if (c == 48) //'0' key, toggle upsampled audio smoothing
// { // {
// if (state->audio_smoothing == 1) state->audio_smoothing = 0; // if (state->audio_smoothing == 1) state->audio_smoothing = 0;
// else state->audio_smoothing = 1; // else state->audio_smoothing = 1;
// } // }
if (opts->p25_trunk == 1 && c == 119) //'w' key, toggle white list/black list mode if (opts->p25_trunk == 1 && c == 119) //'w' key, toggle white list/black list mode
{ {
if (opts->trunk_use_allow_list == 1) opts->trunk_use_allow_list = 0; if (opts->trunk_use_allow_list == 1) opts->trunk_use_allow_list = 0;
else opts->trunk_use_allow_list = 1; else opts->trunk_use_allow_list = 1;
} }
if (opts->p25_trunk == 1 && c == 117) //'u' key, toggle tune private calls if (opts->p25_trunk == 1 && c == 117) //'u' key, toggle tune private calls
{ {
if (opts->trunk_tune_private_calls == 1) opts->trunk_tune_private_calls = 0; if (opts->trunk_tune_private_calls == 1) opts->trunk_tune_private_calls = 0;
else opts->trunk_tune_private_calls = 1; else opts->trunk_tune_private_calls = 1;
} }
if (opts->p25_trunk == 1 && c == 100) //'d' key, toggle tune data calls if (opts->p25_trunk == 1 && c == 100) //'d' key, toggle tune data calls
{ {
if (opts->trunk_tune_data_calls == 1) opts->trunk_tune_data_calls = 0; if (opts->trunk_tune_data_calls == 1) opts->trunk_tune_data_calls = 0;
else opts->trunk_tune_data_calls = 1; else opts->trunk_tune_data_calls = 1;
} }
if (opts->p25_trunk == 1 && c == 101) //'e' key, toggle tune enc calls (P25 only on certain grants) if (opts->p25_trunk == 1 && c == 101) //'e' key, toggle tune enc calls (P25 only on certain grants)
{ {
if (opts->trunk_tune_enc_calls == 1) opts->trunk_tune_enc_calls = 0; if (opts->trunk_tune_enc_calls == 1) opts->trunk_tune_enc_calls = 0;
else opts->trunk_tune_enc_calls = 1; else opts->trunk_tune_enc_calls = 1;
} }
if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls if (opts->p25_trunk == 1 && c == 103) //'g' key, toggle tune group calls
{ {
if (opts->trunk_tune_group_calls == 1) opts->trunk_tune_group_calls = 0; if (opts->trunk_tune_group_calls == 1) opts->trunk_tune_group_calls = 0;
else opts->trunk_tune_group_calls = 1; else opts->trunk_tune_group_calls = 1;
} }
if (c == 70) //'F' key - toggle agressive sync/crc failure/ras if (c == 70) //'F' key - toggle agressive sync/crc failure/ras
{ {
if (opts->aggressive_framesync == 0) opts->aggressive_framesync = 1; if (opts->aggressive_framesync == 0) opts->aggressive_framesync = 1;
else opts->aggressive_framesync = 0; else opts->aggressive_framesync = 0;
@ -4256,7 +4265,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (c == 68) //'D' key - Reset DMR Site Parms/Call Strings, etc. if (c == 68) //'D' key - Reset DMR Site Parms/Call Strings, etc.
{ {
//dmr trunking/ncurses stuff //dmr trunking/ncurses stuff
state->dmr_rest_channel = -1; //init on -1 state->dmr_rest_channel = -1; //init on -1
state->dmr_mfid = -1; // state->dmr_mfid = -1; //
@ -4318,7 +4327,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (opts->audio_in_type == 0) closePulseInput(opts); if (opts->audio_in_type == 0) closePulseInput(opts);
fprintf (stderr, "TCP Socket Connected Successfully.\n"); fprintf (stderr, "TCP Socket Connected Successfully.\n");
opts->audio_in_type = 8; opts->audio_in_type = 8;
} }
} }
else fprintf (stderr, "TCP Socket Connection Error.\n"); else fprintf (stderr, "TCP Socket Connection Error.\n");
} }
@ -4390,7 +4399,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
state->symbolCenter = 3; state->symbolCenter = 3;
} }
fprintf (stderr, "\n User Activated Return to CC; \n "); fprintf (stderr, "\n User Activated Return to CC; \n ");
} }
@ -4436,15 +4445,15 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
state->lcn_freq_roll++; state->lcn_freq_roll++;
//check roll again if greater than expected, then go back to zero //check roll again if greater than expected, then go back to zero
if (state->lcn_freq_roll >= state->lcn_freq_count) if (state->lcn_freq_roll >= state->lcn_freq_count)
{ {
state->lcn_freq_roll = 0; //reset to zero state->lcn_freq_roll = 0; //reset to zero
} }
} }
} }
//check that we have a non zero value first, then tune next frequency //check that we have a non zero value first, then tune next frequency
if (state->trunk_lcn_freq[state->lcn_freq_roll] != 0) if (state->trunk_lcn_freq[state->lcn_freq_roll] != 0)
{ {
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
@ -4461,7 +4470,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
fprintf (stderr, "\n User Activated Channel Cycle;"); fprintf (stderr, "\n User Activated Channel Cycle;");
fprintf (stderr, " Tuning to Frequency: %.06lf MHz\n", fprintf (stderr, " Tuning to Frequency: %.06lf MHz\n",
(double)state->trunk_lcn_freq[state->lcn_freq_roll]/1000000); (double)state->trunk_lcn_freq[state->lcn_freq_roll]/1000000);
} }
@ -4483,18 +4492,18 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
{ {
state->samplesPerSymbol = 8; state->samplesPerSymbol = 8;
state->symbolCenter = 3; state->symbolCenter = 3;
} }
} }
if (opts->m17encoder == 1 && c == 92) //'\' key - toggle M17 encoder Encode + TX if (opts->m17encoder == 1 && c == 92) //'\' key - toggle M17 encoder Encode + TX
{ {
if (state->m17encoder_tx == 0) state->m17encoder_tx = 1; if (state->m17encoder_tx == 0) state->m17encoder_tx = 1;
else state->m17encoder_tx = 0; else state->m17encoder_tx = 0;
//flag on the EOT marker to send last frame after toggling encoder to zero //flag on the EOT marker to send last frame after toggling encoder to zero
if (state->m17encoder_tx == 0) state->m17encoder_eot = 1; if (state->m17encoder_tx == 0) state->m17encoder_eot = 1;
} }
if(opts->frame_provoice == 1 && c == 65) //'A' Key, toggle ESK mask 0xA0 if(opts->frame_provoice == 1 && c == 65) //'A' Key, toggle ESK mask 0xA0
@ -4523,7 +4532,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
} }
//anything with an entry box will need the inputs and outputs stopped first //anything with an entry box will need the inputs and outputs stopped first
//so probably just write a function to handle c input, and when c = certain values //so probably just write a function to handle c input, and when c = certain values
//needing an entry box, then stop all of those //needing an entry box, then stop all of those
//allocated memory pointer needs to be free'd each time //allocated memory pointer needs to be free'd each time

View File

@ -1,5 +1,5 @@
/*------------------------------------------------------------------------------- /*-------------------------------------------------------------------------------
* EDACS-FME * EDACS-FME
* A program for decoding EDACS (ported to DSD-FME) * A program for decoding EDACS (ported to DSD-FME)
* https://github.com/lwvmobile/edacs-fm * https://github.com/lwvmobile/edacs-fm
* *
@ -15,9 +15,9 @@
* *
* LWVMOBILE * LWVMOBILE
* 2023-11 Version EDACS-FM Florida Man Edition * 2023-11 Version EDACS-FM Florida Man Edition
* *
* ilyacodes * ilyacodes
* 2024-03 added EA i-call and login message decoding * 2024-03 rewrite EDACS standard parsing to spec, add reverse-engineered EA messages
*-----------------------------------------------------------------------------*/ *-----------------------------------------------------------------------------*/
#include "dsd.h" #include "dsd.h"
@ -88,7 +88,7 @@ void openWavOutFile48k (dsd_opts * opts, dsd_state * state)
//generic rms type function //generic rms type function
long int gen_rms(short *samples, int len, int step) long int gen_rms(short *samples, int len, int step)
{ {
int i; int i;
long int rms; long int rms;
long p, t, s; long p, t, s;
@ -184,7 +184,7 @@ void analog_dc_block_filter(short * input, int len)
avg = sum / len; avg = sum / len;
avg = (avg + dc_avg * 9) / 10; avg = (avg + dc_avg * 9) / 10;
for (i=0; i < len; i++) for (i=0; i < len; i++)
input[i] -= (short)avg; input[i] -= (short)avg;
dc_avg = avg; dc_avg = avg;
} }
@ -202,7 +202,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
short analog1[960]; short analog1[960];
short analog2[960]; short analog2[960];
short analog3[960]; short analog3[960];
short sample = 0; short sample = 0;
state->last_cc_sync_time = time(NULL); state->last_cc_sync_time = time(NULL);
state->last_vc_sync_time = time(NULL); state->last_vc_sync_time = time(NULL);
@ -217,7 +217,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
fprintf (stderr, "\n"); fprintf (stderr, "\n");
while (!exitflag && count > 0) while (!exitflag && count > 0)
{ {
//this will only work on 48k/1 short output //this will only work on 48k/1 short output
if (opts->audio_in_type == 0) if (opts->audio_in_type == 0)
{ {
@ -243,7 +243,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
} }
//NOTE: The core dumps observed previously were due to SDR++ Remote Server connection dropping due to Internet/Other issues //NOTE: The core dumps observed previously were due to SDR++ Remote Server connection dropping due to Internet/Other issues
//and unlike in the main livescanner loop where it just hangs, this loop will cause a core dump. The observed issue //and unlike in the main livescanner loop where it just hangs, this loop will cause a core dump. The observed issue
//has not occurred when using SDR++ on local hardware, just the remote server software over the Internet. //has not occurred when using SDR++ on local hardware, just the remote server software over the Internet.
//NOTE: The fix below does not apply to above observed issue, as the TCP connection will not drop, there will just //NOTE: The fix below does not apply to above observed issue, as the TCP connection will not drop, there will just
@ -291,7 +291,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
} }
analog3[i] = sample; analog3[i] = sample;
} }
//this rms will only work properly (for now) with squelch enabled in SDR++ //this rms will only work properly (for now) with squelch enabled in SDR++
rms = gen_rms(analog3, 960, 1); rms = gen_rms(analog3, 960, 1);
} }
@ -427,7 +427,7 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
if (count > 0) fprintf (stderr, "\n"); if (count > 0) fprintf (stderr, "\n");
} }
} }
@ -437,7 +437,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
unsigned long long int fr_1 = 0xFFFFFFFFFF; //40-bit frames unsigned long long int fr_1 = 0xFFFFFFFFFF; //40-bit frames
unsigned long long int fr_2 = 0; //each is a 40 bit frame that repeats 3 times unsigned long long int fr_2 = 0; //each is a 40 bit frame that repeats 3 times
unsigned long long int fr_3 = 0; //two messages per frame unsigned long long int fr_3 = 0; //two messages per frame
unsigned long long int fr_4 = 0xFFFFFFFFFF; unsigned long long int fr_4 = 0xFFFFFFFFFF;
unsigned long long int fr_5 = 0; unsigned long long int fr_5 = 0;
unsigned long long int fr_6 = 0; unsigned long long int fr_6 = 0;
@ -473,18 +473,18 @@ void edacs(dsd_opts * opts, dsd_state * state)
{ {
//only fr_1 and fr4 are going to matter //only fr_1 and fr4 are going to matter
fr_1 = fr_1 << 1; fr_1 = fr_1 << 1;
fr_1 = fr_1 | edacs_bit[i]; fr_1 = fr_1 | edacs_bit[i];
fr_2 = fr_2 << 1; fr_2 = fr_2 << 1;
fr_2 = fr_2 | edacs_bit[i+40]; fr_2 = fr_2 | edacs_bit[i+40];
fr_3 = fr_3 << 1; fr_3 = fr_3 << 1;
fr_3 = fr_3 | edacs_bit[i+80]; fr_3 = fr_3 | edacs_bit[i+80];
fr_4 = fr_4 << 1; fr_4 = fr_4 << 1;
fr_4 = fr_4 | edacs_bit[i+120]; fr_4 = fr_4 | edacs_bit[i+120];
fr_5 = fr_5 << 1; fr_5 = fr_5 << 1;
fr_5 = fr_5 | edacs_bit[i+160]; fr_5 = fr_5 | edacs_bit[i+160];
fr_6 = fr_6 << 1; fr_6 = fr_6 << 1;
fr_6 = fr_6 | edacs_bit[i+200]; fr_6 = fr_6 | edacs_bit[i+200];
} }
@ -508,7 +508,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
else //BCH Pass, continue from here. else //BCH Pass, continue from here.
{ {
//Auto Detection Modes Have Been Removed due to reliability issues, //Auto Detection Modes Have Been Removed due to reliability issues,
//users will now need to manually specify these options: //users will now need to manually specify these options:
/* /*
-fh Decode only EDACS Standard/ProVoice*\n"); -fh Decode only EDACS Standard/ProVoice*\n");
@ -521,7 +521,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
//TODO: Consider re-adding the auto code to make a suggestion to users //TODO: Consider re-adding the auto code to make a suggestion to users
//as to which mode to proceed in? //as to which mode to proceed in?
//Color scheme: //Color scheme:
// - KRED - critical information (emergency, failsoft, etc) // - KRED - critical information (emergency, failsoft, etc)
// - KYEL - system data // - KYEL - system data
@ -536,7 +536,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
fr_1t = fr_1t ^ fr_esk_mask; fr_1t = fr_1t ^ fr_esk_mask;
fr_4t = fr_4t ^ fr_esk_mask; fr_4t = fr_4t ^ fr_esk_mask;
//Start Extended Addressing Mode //Start Extended Addressing Mode
if (state->ea_mode == 1) if (state->ea_mode == 1)
{ {
unsigned char mt1 = (fr_1t & 0xF800000000) >> 35; unsigned char mt1 = (fr_1t & 0xF800000000) >> 35;
@ -555,7 +555,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
// MT2 is meaningless if MT1 is not 0x1F // MT2 is meaningless if MT1 is not 0x1F
if (mt1 == 0x1F) if (mt1 == 0x1F)
fprintf (stderr, "; MT2: %X) ", mt2); fprintf (stderr, "; MT2: %X) ", mt2);
else else
fprintf (stderr, ") "); fprintf (stderr, ") ");
} }
@ -601,7 +601,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (((fr_4t >> 12) & 0x1F) != 0) if (((fr_4t >> 12) & 0x1F) != 0)
{ {
state->edacs_cc_lcn = ((fr_4t >> 12) & 0x1F); state->edacs_cc_lcn = ((fr_4t >> 12) & 0x1F);
if (state->edacs_cc_lcn > state->edacs_lcn_count && lcn < 26) //26, or 27. shouldn't matter don't think cc lcn will give a status lcn val if (state->edacs_cc_lcn > state->edacs_lcn_count && lcn < 26) //26, or 27. shouldn't matter don't think cc lcn will give a status lcn val
{ {
state->edacs_lcn_count = state->edacs_cc_lcn; state->edacs_lcn_count = state->edacs_cc_lcn;
} }
@ -682,7 +682,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
fprintf (stderr, " FR_4 [%010llX]", fr_4t); fprintf (stderr, " FR_4 [%010llX]", fr_4t);
} }
} }
} }
//TDMA Group Grant Update (never observed, unknown if ever used on any EDACS system) //TDMA Group Grant Update (never observed, unknown if ever used on any EDACS system)
else if (mt1 == 0x1) else if (mt1 == 0x1)
@ -713,7 +713,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
lcn = (fr_1t & 0x3E0000000) >> 29; lcn = (fr_1t & 0x3E0000000) >> 29;
//LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc" //LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc"
if (lcn > state->edacs_lcn_count && lcn < 26) if (lcn > state->edacs_lcn_count && lcn < 26)
{ {
state->edacs_lcn_count = lcn; state->edacs_lcn_count = lcn;
} }
@ -768,7 +768,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (state->tg_hold != 0 && state->tg_hold == group) sprintf (mode, "%s", "A"); if (state->tg_hold != 0 && state->tg_hold == group) sprintf (mode, "%s", "A");
//this is working now with the new import setup //this is working now with the new import setup
if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block
{ {
if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise) if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise)
{ {
@ -781,11 +781,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
else else
openWavOutFile48k (opts, state); openWavOutFile48k (opts, state);
} }
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well //do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
{ {
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn; state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
@ -805,7 +805,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
} }
} }
} }
} }
//I-Call Grant Update //I-Call Grant Update
@ -814,7 +814,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
lcn = (fr_4t & 0x1F00000000) >> 32; lcn = (fr_4t & 0x1F00000000) >> 32;
//LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc" //LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc"
if (lcn > state->edacs_lcn_count && lcn < 26) if (lcn > state->edacs_lcn_count && lcn < 26)
{ {
state->edacs_lcn_count = lcn; state->edacs_lcn_count = lcn;
} }
@ -843,7 +843,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B"); if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
//this is working now with the new import setup //this is working now with the new import setup
if (opts->trunk_tune_private_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block if (opts->trunk_tune_private_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block
{ {
if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise) if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise)
{ {
@ -856,11 +856,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
else else
openWavOutFile48k (opts, state); openWavOutFile48k (opts, state);
} }
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well //do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
{ {
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn; state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
@ -897,7 +897,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
lcn = (fr_1t & 0x3E0000000) >> 29; lcn = (fr_1t & 0x3E0000000) >> 29;
//LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc" //LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc"
if (lcn > state->edacs_lcn_count && lcn < 26) if (lcn > state->edacs_lcn_count && lcn < 26)
{ {
state->edacs_lcn_count = lcn; state->edacs_lcn_count = lcn;
} }
@ -914,7 +914,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
else fprintf (stderr, " Digital System All-Call"); else fprintf (stderr, " Digital System All-Call");
if (is_update == 0) fprintf (stderr, " Assignment"); if (is_update == 0) fprintf (stderr, " Assignment");
else fprintf (stderr, " Update"); 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, get_lcn_status_string(lcn));
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
@ -925,7 +925,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "A"); if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "A");
//this is working now with the new import setup //this is working now with the new import setup
if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block
{ {
if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise) if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise)
{ {
@ -938,11 +938,11 @@ void edacs(dsd_opts * opts, dsd_state * state)
else else
openWavOutFile48k (opts, state); openWavOutFile48k (opts, state);
} }
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well //do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
{ {
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn; state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1; opts->p25_is_tuned = 1;
@ -962,7 +962,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
} }
} }
} }
} }
//Login //Login
@ -1055,7 +1055,78 @@ void edacs(dsd_opts * opts, dsd_state * state)
} }
fprintf (stderr, "%s", KNRM); fprintf (stderr, "%s", KNRM);
// TODO: Actually process the call //LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc)
if (lcn > state->edacs_lcn_count && lcn < 26)
{
state->edacs_lcn_count = lcn;
}
state->edacs_vc_lcn = lcn;
state->lasttg = group;
state->lastsrc = lid;
char mode[8]; //allow, block, digital enc
sprintf (mode, "%s", "");
//if we are using allow/whitelist mode, then write 'B' to mode for block
//comparison below will look for an 'A' to write to mode if it is allowed
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
//Get group mode for calls that are in the allow/whitelist
for (int i = 0; i < state->group_tally; i++)
{
if (state->group_array[i].groupNumber == group)
{
strcpy (mode, state->group_array[i].groupMode);
break;
}
}
//TG hold on EDACS Standard/Net -- block non-matching target, allow matching group
if (state->tg_hold != 0 && state->tg_hold != group) sprintf (mode, "%s", "B");
if (state->tg_hold != 0 && state->tg_hold == group) sprintf (mode, "%s", "A");
//NOTE: Restructured below so that analog and digital are handled the same, just that when
//its analog, it will now start edacs_analog which will while loop analog samples until
//signal level drops (RMS, or a dotting sequence is detected)
//this is working now with the new import setup
if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block
{
if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise)
{
//openwav file and do per call right here
if (opts->dmr_stereo_wav == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3))
{
sprintf (opts->wav_out_file, "./WAV/%s %s EDACS Site %lld TG %04d SRC %05d.wav", getDateE(), timestr, state->edacs_site_id, group, lid);
if (is_digital == 0) openWavOutFile48k (opts, state); //analog at 48k
else openWavOutFile (opts, state); //digital
}
if (opts->use_rigctl == 1)
{
//only set bandwidth IF we have an original one to fall back to (experimental, but requires user to set the -B 12000 or -B 24000 value manually)
if (opts->setmod_bw != 0)
{
if (is_digital == 0) SetModulation(opts->rigctl_sockfd, 7000); //narrower bandwidth, but has issues with dotting sequence
else SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
}
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because our index starts at zero
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (is_digital == 0) edacs_analog(opts, state, group, lcn);
}
if (opts->audio_in_type == 3) //rtl dongle
{
#ifdef USE_RTLSDR
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (is_digital == 0) edacs_analog(opts, state, group, lcn);
#endif
}
}
}
} }
//Data Call Channel Assignment (6.2.4.3) //Data Call Channel Assignment (6.2.4.3)
else if (mt_a == 0x5) else if (mt_a == 0x5)
@ -1114,7 +1185,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
//Abstract away to a target, and be sure to check whether it's an individual call later //Abstract away to a target, and be sure to check whether it's an individual call later
int target = (is_individual_id == 0) ? group : lid; int target = (is_individual_id == 0) ? group : lid;
fprintf (stderr, "%s", KMAG); fprintf (stderr, "%s", KMAG);
fprintf (stderr, " Interconnect Channel Assignment :: Type"); fprintf (stderr, " Interconnect Channel Assignment :: Type");
if (mt_c == 0x2) fprintf (stderr, " [Voice]"); if (mt_c == 0x2) fprintf (stderr, " [Voice]");
@ -1138,7 +1209,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
//Abstract away to a target, and be sure to check whether it's an individual call later //Abstract away to a target, and be sure to check whether it's an individual call later
int target = (is_individual == 0) ? group : lid; int target = (is_individual == 0) ? group : lid;
//Technically only MT-C 0x1 and 0x3 are defined in TSB 69.3 - using and extrapolating on legacy code //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_tx_trunk = (mt_c == 2 || mt_c == 3) ? 1 : 0;
int is_digital = (mt_c == 1 || mt_c == 3) ? 1 : 0; int is_digital = (mt_c == 1 || mt_c == 3) ? 1 : 0;
@ -1173,23 +1244,12 @@ void edacs(dsd_opts * opts, dsd_state * state)
} }
state->edacs_vc_lcn = lcn; state->edacs_vc_lcn = lcn;
//If we have the same target already in progress, we can keep the source ID since we know it (and don't get //Use IDs > 10000 to represent i-call targets to differentiate from TGs
//it in this CC message). But if we have a different target, we should clear out to a source ID of 0. if (is_individual == 0) state->lasttg = target;
if (is_individual == 0) else state->lasttg = target + 10000;
{
if (state->lasttg != target) { //Alas, EDACS standard does not provide a source LID on channel updates - try to work around this on the display end instead
state->lasttg = target; state->lastsrc = 0;
state->lastsrc = 0;
}
}
else
{
//Use IDs > 10000 to represent i-call targets to differentiate from TGs
if (state->lasttg != target + 10000) {
state->lasttg = target + 10000;
state->lastsrc = 0;
}
}
char mode[8]; //allow, block, digital enc char mode[8]; //allow, block, digital enc
sprintf (mode, "%s", ""); sprintf (mode, "%s", "");
@ -1259,7 +1319,6 @@ void edacs(dsd_opts * opts, dsd_state * state)
#endif #endif
} }
} }
} }
} }
//System Assigned ID (6.2.4.8) //System Assigned ID (6.2.4.8)
@ -1455,7 +1514,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
state->edacs_site_id = site_id; state->edacs_site_id = site_id;
//LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc) //LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc)
if (state->edacs_cc_lcn > state->edacs_lcn_count && cc_lcn < 26) if (state->edacs_cc_lcn > state->edacs_lcn_count && cc_lcn < 26)
{ {
state->edacs_lcn_count = state->edacs_cc_lcn; state->edacs_lcn_count = state->edacs_cc_lcn;
} }
@ -1580,7 +1639,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
} //end Standard or Networked } //end Standard or Networked
//let users know they need to select an operational mode with the switches below //let users know they need to select an operational mode with the switches below
else else
{ {
fprintf (stderr, " Detected: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk;"); fprintf (stderr, " Detected: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk;");
fprintf (stderr, "\n"); fprintf (stderr, "\n");
@ -1608,13 +1667,13 @@ void eot_cc(dsd_opts * opts, dsd_state * state)
//jump back to CC here //jump back to CC here
if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1)
{ {
//rigctl //rigctl
if (opts->use_rigctl == 1) if (opts->use_rigctl == 1)
{ {
state->lasttg = 0; state->lasttg = 0;
state->lastsrc = 0; state->lastsrc = 0;
state->payload_algid = 0; state->payload_algid = 0;
state->payload_keyid = 0; state->payload_keyid = 0;
state->payload_miP = 0; state->payload_miP = 0;
//reset some strings //reset some strings
@ -1625,7 +1684,7 @@ void eot_cc(dsd_opts * opts, dsd_state * state)
opts->p25_is_tuned = 0; opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0; state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq); SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
} }
//rtl //rtl
@ -1651,4 +1710,4 @@ void eot_cc(dsd_opts * opts, dsd_state * state)
} }
} }