diff --git a/include/dsd.h b/include/dsd.h index f521dee..04e61f7 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -210,8 +210,8 @@ typedef struct SF_INFO *audio_in_file_info; uint32_t rtlsdr_center_freq; - int rtlsdr_ppm_error; - int audio_in_type; + int rtlsdr_ppm_error; + int audio_in_type; char audio_out_dev[1024]; int audio_out_fd; int audio_out_fdR; //right channel audio for OSS hack @@ -367,7 +367,7 @@ typedef struct char group_in_file[1024]; char lcn_in_file[1024]; char chan_in_file[1024]; - char key_in_file[1024]; + char key_in_file[1024]; //end import filenames //reverse mute @@ -454,7 +454,7 @@ typedef struct short s_ru[160*6]; //single sample right 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 - //end + //end int audio_out_idx; int audio_out_idx2; int audio_out_idxR; @@ -616,7 +616,7 @@ typedef struct 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. - + //dmr talker alias new/fixed stuff uint8_t dmr_alias_format[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 uint8_t crc7(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/ void LFSR(dsd_state * state); diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index ec35821..9b791eb 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -7,6 +7,9 @@ * * LWVMOBILE * 2022-08 DSD-FME Florida Man Edition + * + * ilyacodes + * 2024-03 EDACS-FME display improvements *-----------------------------------------------------------------------------*/ @@ -110,13 +113,13 @@ char * DMRBusrtTypes[32] = { "R34D ", "IDLE ", "R1_D ", - "ERR ", + "ERR ", "DUID ERR ", "R-S ERR ", "CRC ERR ", "NULL ", - "VOICE", - " ", + "VOICE", + " ", "INIT ", "INIT ", "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) pa_simple_write(opts->pulse_digi_dev_out, samp_s, 160*2, NULL); - + } 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) udp_socket_blaster (opts, state, 160*2, samp_s); - + } 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)+5] = outbuf[5]; } - + write (opts->audio_out_fd, samp_su, 960*2); } - + } } @@ -328,7 +331,7 @@ char *choicesc[] = { "Setup and Start RTL Input ", "Retune RTL Dongle ", "Toggle C4FM/QPSK (P2 TDMA CC)", - "Toggle C4FM/QPSK (P1 FDMA CC)", + "Toggle C4FM/QPSK (P1 FDMA CC)", "Start TCP Direct Link Audio", "Configure RIGCTL", "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 // if (opts->audio_out_type == 2 || opts->audio_out_type == 5) // beeper (opts, state, 0); //causes crash in Cygwin when mixed input/output - + //terminate all values for (int i = 0; i < 10; i++) sprintf (alias_ch[i], "%s", ""); @@ -462,7 +465,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) closePulseOutput (opts); } - //close OSS output + //close OSS output if (opts->audio_out_type == 2 || opts->audio_out_type == 5) { close (opts->audio_out_fd); @@ -760,7 +763,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) opts->rtl_dev_index = i; break; } - + } 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) // { // opts->audio_out = 1; - // opts->audio_out_type = 0; + // opts->audio_out_type = 0; // // state->audio_out_buf_p = 0; // // state->audio_out_buf_pR = 0; // state->audio_out_idx = 0; @@ -933,7 +936,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) opts->audio_in_type = 0; } else opts->audio_in_type = 5; - + } 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); noecho(); if (state->R > 0x7FFF) state->R = 0x7FFF; - + state->keyloader = 0; //turn off keyloader } //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); } - + 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 { // 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) { 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 - { - timeout(0); // + timeout(0); // c = getch(); // } @@ -1908,7 +1911,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //Variable reset/set section //set lls sync types - if (state->synctype >= 0 && state->synctype < 39) + if (state->synctype >= 0 && state->synctype < 39) { lls = state->synctype; } @@ -2002,16 +2005,22 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //Edacs - ProVoice 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][1] = state->edacs_vc_lcn; - call_matrix[state->edacs_vc_lcn][2] = state->lasttg; - call_matrix[state->edacs_vc_lcn][3] = state->lastsrc; + call_matrix[state->edacs_vc_lcn][2] = state->lasttg; + //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][5] = time(NULL); - } + } } @@ -2074,7 +2083,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } } - + //TODO: Find better placement for these if ( strcmp(state->str50a, "") != 0 ) sprintf (alias_ch[9], "%s", state->str50a); @@ -2257,7 +2266,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // state->lastsrc = 0; // rd = 0; // tg = 0; - // } + // } // if (state->dmrburstR == 2 && state->dmr_end_alert[1] == 0) //if TLC and flag not tripped // { // beeper (opts, state, 1); @@ -2266,7 +2275,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // state->lastsrcR = 0; // rdR = 0; // tgR = 0; - // } + // } // } //Start Printing Section @@ -2276,7 +2285,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { printw ("------------------------------------------------------------------------------\n"); printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "AW (20231015)"); - printw ("------------------------------------------------------------------------------\n"); + printw ("------------------------------------------------------------------------------\n"); } #elif LIMAZULUTWEAKS if (opts->ncurses_compact == 1) @@ -2318,7 +2327,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) #elif ZDEV_BUILD if (i == 5) printw (" %s ", "AW "); if (i == 6) printw (" %s \n", GIT_TAG); - #else + #else if (i == 5) printw (" %s ", "AW "); if (i == 6) printw (" %s \n", GIT_TAG); #endif @@ -2383,7 +2392,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw (" SQ: %i;", opts->rtl_squelch_level); printw (" RMS: %04li;", opts->rtl_rms); 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); printw ("\n"); } @@ -2529,7 +2538,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) attron(COLOR_PAIR(2)); printw (" Standard/Network"); attron(COLOR_PAIR(4)); - printw (" Extended Address"); + printw (" Extended Address"); } printw (" Mode (S);"); @@ -2556,7 +2565,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if (state->ea_mode == 1) { printw (" standard/network"); - printw (" EXTENDED ADDRESS"); + printw (" EXTENDED ADDRESS"); } printw (" Mode (S);"); @@ -2581,9 +2590,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (opts->scanner_mode == 1) { 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 (" 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"); @@ -2625,7 +2634,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } printw ("\n"); printw ("| In Level: [%02d%%] \n", level); - + if (opts->dmr_stereo == 0) { printw ("| Voice Error: [%i][%i]", state->errs, state->errs2); @@ -2648,7 +2657,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("------------------------------------------------------------------------------\n"); printw ("--Call Info-------------------------------------------------------------------\n"); - + //DSTAR 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); else printw("%s", state->m17_dst_str); - + printw ("\n"); printw ("| "); @@ -2699,7 +2708,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else printw("%s", state->m17_src_str); - + printw ("\n"); printw ("| "); @@ -2726,7 +2735,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (state->m17_enc == 3) { printw (" Reserved Enc - Type: %d", state->m17_enc_st); - } + } printw ("\n"); @@ -2787,7 +2796,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // printw ("%c", state->ysf_txt[i][j]); // } // // printw (" "); //just a single space between each 'block' - // } + // } printw ("\n"); @@ -2810,7 +2819,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { printw (" - Frequency: %.06lf Mhz ", (double)state->p25_cc_freq/1000000); } - } + } else if (opts->p25_is_tuned == 1) { if (idas == 0) printw ("Monitoring RTCH Channel"); //Traffic Channel @@ -2823,8 +2832,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("\n"); } - - + + printw ("| "); // #ifdef LIMAZULUTWEAKS @@ -2922,10 +2931,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } //Active Trunking Channels (NXDN and IDAS) - if (1 == 1) //opts->p25_trunk + if (1 == 1) //opts->p25_trunk { printw ("\n"); - printw ("| "); + printw ("| "); //active channel display attron(COLOR_PAIR(4)); @@ -2943,8 +2952,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw("\n"); } - - //P25 and DMR BS/MS + + //P25 and DMR BS/MS if ( lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 || 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 ", state->dmr_branding); 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) { 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); } - + } else if (lls == 32 || lls == 33 || lls == 34) { @@ -2997,7 +3006,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw (" Phase 2 Invalid Parameters "); attron(COLOR_PAIR(3)); } - else + else { 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 //this is already in the call_string anyways - + // if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000 // { // attron(COLOR_PAIR(2)); @@ -3156,13 +3165,13 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //Embedded GPS (not LRRP) printw ("%s ", state->dmr_embedded_gps[0]); - + //Embedded Talker Alias Blocks for (int i = 0; i < 4; i++) { 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 // if (lls < 30 || lls == 35 || lls == 36) - { + { printw ("| SLOT 2 - "); 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 ", 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 ("| V XTRA | "); //10 spaces 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 { - + //Embedded GPS (not LRRP) attron(COLOR_PAIR(4)); 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++) { - 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)); printw ("%s", state->dmr_lrrp_gps[1]); } - + //Group Name Labels from CSV import if (state->dmrburstR == 16 || state->dmrburstR > 19) { @@ -3461,7 +3470,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //EDACS and ProVoice 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 (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); //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); 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 int a = (call_matrix[i][2] >> 7) & 0xF; 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 if ( (i) == state->edacs_cc_lcn) { @@ -3503,9 +3512,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) attroff (COLOR_PAIR(1)); } //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 (call_matrix[i][2] + 1 == 0) // System all-call @@ -3544,12 +3553,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) break; } } - attroff (COLOR_PAIR(3)); + attroff (COLOR_PAIR(3)); } - //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) ) + //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) ) { - attron (COLOR_PAIR(2)); + attron (COLOR_PAIR(2)); if (state->ea_mode == 1) { if (call_matrix[i][2] + 1 == 0) // System all-call @@ -3588,14 +3597,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) 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 printw ("\n"); } 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 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 ("%s ", getDateC(call_matrix[j][5]) ); + printw ("%s ", getDateC(call_matrix[j][5]) ); printw ("%s ", getTimeC(call_matrix[j][5]) ); printw ("LCN [%2lld] ", call_matrix[j][1]); if (state->ea_mode == 1) @@ -3705,10 +3714,10 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // Group call printw ("Target [%8lld] Source [%8lld]", call_matrix[j][2], call_matrix[j][3]); } - else + else { // 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; if (call_matrix[j][2] + 1 == 0) // System all-call @@ -3719,7 +3728,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else // Group call printw ("Target [%6lld][%02d-%03d] Source [%5lld]", call_matrix[j][2], a, fs, call_matrix[j][3]); - } + } //test for (int k = 0; k < state->group_tally; k++) { @@ -3739,7 +3748,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) //end test printw ("\n"); } - + } } //end Call History //fence bottom @@ -3796,7 +3805,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if (opts->slot1_on == 0) { 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->slot2_on = 0; //turn off slot 2 @@ -3822,7 +3831,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if (opts->slot2_on == 0) { 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->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, "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; //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_fileR, "./%s/DSD-FME-T2.wav", opts->wav_out_dir); - openWavOutFileL (opts, state); - openWavOutFileR (opts, state); + openWavOutFileL (opts, state); + openWavOutFileR (opts, state); } //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 - // + // #else if (c == 115) //'s' key, stop playing wav or symbol in files { 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; openPulseInput(opts); } - else opts->audio_in_type = 5; //exitflag = 1; - + else opts->audio_in_type = 5; //exitflag = 1; + } #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 { 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 (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; - 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->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->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->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->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; 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. { - //dmr trunking/ncurses stuff + //dmr trunking/ncurses stuff state->dmr_rest_channel = -1; //init on -1 state->dmr_mfid = -1; // @@ -4318,7 +4327,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (opts->audio_in_type == 0) closePulseInput(opts); fprintf (stderr, "TCP Socket Connected Successfully.\n"); opts->audio_in_type = 8; - } + } } else fprintf (stderr, "TCP Socket Connection Error.\n"); } @@ -4390,7 +4399,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) 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++; //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 - } + } } } //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 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, " Tuning to Frequency: %.06lf MHz\n", + fprintf (stderr, " Tuning to Frequency: %.06lf MHz\n", (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->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; else state->m17encoder_tx = 0; //flag on the EOT marker to send last frame after toggling encoder to zero if (state->m17encoder_tx == 0) state->m17encoder_eot = 1; - + } 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 - //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 //allocated memory pointer needs to be free'd each time diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 15f931f..043e30a 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1,5 +1,5 @@ /*------------------------------------------------------------------------------- - * EDACS-FME + * EDACS-FME * A program for decoding EDACS (ported to DSD-FME) * https://github.com/lwvmobile/edacs-fm * @@ -15,9 +15,9 @@ * * LWVMOBILE * 2023-11 Version EDACS-FM Florida Man Edition - * + * * 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" @@ -88,7 +88,7 @@ void openWavOutFile48k (dsd_opts * opts, dsd_state * state) //generic rms type function long int gen_rms(short *samples, int len, int step) { - + int i; long int rms; long p, t, s; @@ -184,7 +184,7 @@ void analog_dc_block_filter(short * input, int len) avg = sum / len; avg = (avg + dc_avg * 9) / 10; for (i=0; i < len; i++) - input[i] -= (short)avg; + input[i] -= (short)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 analog2[960]; short analog3[960]; - short sample = 0; + short sample = 0; state->last_cc_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"); while (!exitflag && count > 0) - { + { //this will only work on 48k/1 short output 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 - //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. //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; } - + //this rms will only work properly (for now) with squelch enabled in SDR++ 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); 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_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_4 = 0xFFFFFFFFFF; + unsigned long long int fr_4 = 0xFFFFFFFFFF; unsigned long long int fr_5 = 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 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 | edacs_bit[i+40]; fr_3 = fr_3 << 1; fr_3 = fr_3 | edacs_bit[i+80]; - - fr_4 = fr_4 << 1; - fr_4 = fr_4 | edacs_bit[i+120]; + + fr_4 = fr_4 << 1; + fr_4 = fr_4 | edacs_bit[i+120]; fr_5 = fr_5 << 1; fr_5 = fr_5 | edacs_bit[i+160]; 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. { - //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: /* -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 //as to which mode to proceed in? - + //Color scheme: // - KRED - critical information (emergency, failsoft, etc) // - KYEL - system data @@ -536,7 +536,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fr_1t = fr_1t ^ fr_esk_mask; fr_4t = fr_4t ^ fr_esk_mask; - //Start Extended Addressing Mode + //Start Extended Addressing Mode if (state->ea_mode == 1) { 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 if (mt1 == 0x1F) fprintf (stderr, "; MT2: %X) ", mt2); - else + else fprintf (stderr, ") "); } @@ -601,7 +601,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (((fr_4t >> 12) & 0x1F) != 0) { 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; } @@ -682,7 +682,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " FR_4 [%010llX]", fr_4t); } } - + } //TDMA Group Grant Update (never observed, unknown if ever used on any EDACS system) else if (mt1 == 0x1) @@ -713,7 +713,7 @@ void edacs(dsd_opts * opts, dsd_state * state) lcn = (fr_1t & 0x3E0000000) >> 29; //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; } @@ -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"); //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) { @@ -781,11 +781,11 @@ void edacs(dsd_opts * opts, dsd_state * state) else openWavOutFile48k (opts, state); } - + //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->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 state->edacs_tuned_lcn = lcn; opts->p25_is_tuned = 1; @@ -805,7 +805,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } } - + } } //I-Call Grant Update @@ -814,7 +814,7 @@ void edacs(dsd_opts * opts, dsd_state * state) lcn = (fr_4t & 0x1F00000000) >> 32; //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; } @@ -843,7 +843,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B"); //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) { @@ -856,11 +856,11 @@ void edacs(dsd_opts * opts, dsd_state * state) else openWavOutFile48k (opts, state); } - + //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->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 state->edacs_tuned_lcn = lcn; opts->p25_is_tuned = 1; @@ -897,7 +897,7 @@ void edacs(dsd_opts * opts, dsd_state * state) lcn = (fr_1t & 0x3E0000000) >> 29; //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; } @@ -914,7 +914,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else fprintf (stderr, " Digital System All-Call"); 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, "%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"); //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) { @@ -938,11 +938,11 @@ void edacs(dsd_opts * opts, dsd_state * state) else openWavOutFile48k (opts, state); } - + //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->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 state->edacs_tuned_lcn = lcn; opts->p25_is_tuned = 1; @@ -962,7 +962,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } } - + } } //Login @@ -1055,7 +1055,78 @@ void edacs(dsd_opts * opts, dsd_state * state) } 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) 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 int target = (is_individual_id == 0) ? group : lid; - + fprintf (stderr, "%s", KMAG); fprintf (stderr, " Interconnect Channel Assignment :: Type"); 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 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 int is_tx_trunk = (mt_c == 2 || 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; - //If we have the same target already in progress, we can keep the source ID since we know it (and don't get - //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) - { - if (state->lasttg != target) { - state->lasttg = target; - 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; - } - } + //Use IDs > 10000 to represent i-call targets to differentiate from TGs + if (is_individual == 0) state->lasttg = target; + else state->lasttg = target + 10000; + + //Alas, EDACS standard does not provide a source LID on channel updates - try to work around this on the display end instead + state->lastsrc = 0; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); @@ -1259,7 +1319,6 @@ void edacs(dsd_opts * opts, dsd_state * state) #endif } } - } } //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; //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; } @@ -1580,7 +1639,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } //end Standard or Networked //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, "\n"); @@ -1608,13 +1667,13 @@ void eot_cc(dsd_opts * opts, dsd_state * state) //jump back to CC here if (opts->p25_trunk == 1 && state->p25_cc_freq != 0 && opts->p25_is_tuned == 1) { - + //rigctl if (opts->use_rigctl == 1) { state->lasttg = 0; state->lastsrc = 0; - state->payload_algid = 0; + state->payload_algid = 0; state->payload_keyid = 0; state->payload_miP = 0; //reset some strings @@ -1625,7 +1684,7 @@ void eot_cc(dsd_opts * opts, dsd_state * state) opts->p25_is_tuned = 0; state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0; 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 @@ -1651,4 +1710,4 @@ void eot_cc(dsd_opts * opts, dsd_state * state) } } - +