mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 09:17:20 -05:00
Checkdown for Valid P2 Parameters --if invalid parameters specified by user for P2 WACN, SYSID, and CC (too large) then treat same as missing parameters and skip processing P2 frames that require scrambling.
2395 lines
73 KiB
C
2395 lines
73 KiB
C
/*-------------------------------------------------------------------------------
|
||
* dsd_ncurses.c
|
||
* A dsd ncurses terminal printer with menu system
|
||
*
|
||
* ASCII art generated by:
|
||
* https://fsymbols.com/generators/carty/
|
||
*
|
||
* LWVMOBILE
|
||
* 2022-08 DSD-FME Florida Man Edition
|
||
*-----------------------------------------------------------------------------*/
|
||
/*
|
||
* Copyright (C) 2010 DSD Author
|
||
* GPG Key ID: 0x3F1D7FD0 (74EF 430D F7F2 0A48 FCE6 F630 FAA2 635D 3F1D 7FD0)
|
||
*
|
||
* Permission to use, copy, modify, and/or distribute this software for any
|
||
* purpose with or without fee is hereby granted, provided that the above
|
||
* copyright notice and this permission notice appear in all copies.
|
||
*
|
||
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
|
||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||
* PERFORMANCE OF THIS SOFTWARE.
|
||
*/
|
||
|
||
#include "dsd.h"
|
||
#include "git_ver.h"
|
||
|
||
//UDP Remote
|
||
#include <arpa/inet.h>
|
||
// #include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
|
||
#define BSIZE 999
|
||
#define UDP_BUFLEN 5 //maximum UDP buffer length
|
||
#define SRV_IP "127.0.0.1" //IP
|
||
#define UDP_PORT 6020 //UDP port
|
||
|
||
int handle; //for UDP
|
||
unsigned short udp_port = UDP_PORT;
|
||
char data[UDP_BUFLEN] = {0};
|
||
struct sockaddr_in address;
|
||
|
||
uint32_t temp_freq = -1;
|
||
//
|
||
|
||
//struct for checking existence of directory to write to
|
||
struct stat st_wav = {0};
|
||
|
||
int reset = 0;
|
||
|
||
int tg;
|
||
int tgR;
|
||
int tgn;
|
||
int rd;
|
||
int rdR;
|
||
int rn;
|
||
int nc;
|
||
int src;
|
||
int lls = -1;
|
||
int dcc = -1;
|
||
int i = 0;
|
||
char versionstr[25];
|
||
unsigned long long int call_matrix[33][6];
|
||
|
||
char * FM_bannerN[9] = {
|
||
" ESC or Arrow Keys For Menu ",
|
||
" ██████╗ ██████╗██████╗ ███████╗███╗ ███╗███████╗ ",
|
||
" ██╔══██╗██╔════╝██╔══██╗ ██╔════╝████╗ ████║██╔════╝ ",
|
||
" ██║ ██║╚█████╗ ██║ ██║ █████╗ ██╔████╔██║█████╗ ",
|
||
" ██║ ██║ ╚═══██╗██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══╝ ",
|
||
" ██████╔╝██████╔╝██████╔╝ ██║ ██║ ╚═╝ ██║███████╗ ",
|
||
" ╚═════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝ ",
|
||
" ",
|
||
" "
|
||
};
|
||
|
||
char * SyncTypes[44] = {
|
||
"P25P1",
|
||
"P25P1",
|
||
"X2TDMA DATA",
|
||
"X2TDMA DATA",
|
||
"X2TDMA VOICE",
|
||
"X2TDMA VOICE",
|
||
"DSTAR",
|
||
"DSTAR",
|
||
"NXDN VOICE",
|
||
"NXDN VOICE",
|
||
"DMR DATA", //10
|
||
"DMR DATA",
|
||
"DMR VOICE",
|
||
"DMR VOICE",
|
||
"PROVOICE",
|
||
"PROVOICE",
|
||
"NXDN DATA",
|
||
"NXDN DATA",
|
||
"DSTAR HD",
|
||
"DSTAR HD",
|
||
"dPMR", //20
|
||
"dPMR",
|
||
"dPMR",
|
||
"dPMR",
|
||
"dPMR",
|
||
"dPMR",
|
||
"dPMR",
|
||
"dPMR",
|
||
"NXDN (sync only)",
|
||
"NXDN (sync only)",
|
||
"YSF", //30
|
||
"YSF",
|
||
"DMR MS VOICE",
|
||
"DMR MS DATA",
|
||
"DMR RC DATA",
|
||
"P25P2",
|
||
"P25P2",
|
||
"FDMA", //37
|
||
"TDMA", //38
|
||
"",
|
||
""
|
||
};
|
||
|
||
char * DMRBusrtTypes[32] = {
|
||
"PI Header ",
|
||
"VOICE LC HDR ",
|
||
"TLC ",
|
||
"CSBK ",
|
||
"MBC Header ",
|
||
"MBC Cont ",
|
||
"DATA Header ",
|
||
"RATE 1/2 DATA ",
|
||
"RATE 3/4 DATA ",
|
||
"Slot Idle ",
|
||
"Rate 1 DATA ",
|
||
"ERR ", //These values for ERR may be Reserved for use in future?
|
||
"DUID ERR ",
|
||
"R-S ERR ",
|
||
"CRC ERR ",
|
||
"NULL ",
|
||
"Voice ", //Using 16 for Voice since its higher than possible value in DMR
|
||
"INITIAL ", //17 is assigned on start up
|
||
"INITIAL ",
|
||
"INITIAL ",//expanded to include P1/2 signalling
|
||
"MAC PTT", //20
|
||
"MAC ACTIVE", //21
|
||
"MAC HANGTIME", //22
|
||
"MAC PTT END", //23
|
||
"MAC IDLE", //24
|
||
"HDU",
|
||
"VOICE LDU", //26
|
||
"VOICE LDU",
|
||
"TDU/TDULC",
|
||
"TSBK",
|
||
"MAC_SIGNAL",
|
||
"MAC_SIGNAL"
|
||
|
||
};
|
||
|
||
char * getDateN(void) {
|
||
char datename[99]; //bug in 32-bit Ubuntu when using date in filename, date is garbage text
|
||
char * curr2;
|
||
struct tm * to;
|
||
time_t t;
|
||
t = time(NULL);
|
||
to = localtime( & t);
|
||
strftime(datename, sizeof(datename), "%Y-%m-%d", to);
|
||
curr2 = strtok(datename, " ");
|
||
return curr2;
|
||
}
|
||
|
||
time_t nowN;
|
||
char * getTimeN(void) //get pretty hh:mm:ss timestamp
|
||
{
|
||
time_t t = time(NULL);
|
||
|
||
char * curr;
|
||
char * stamp = asctime(localtime( & t));
|
||
|
||
curr = strtok(stamp, " ");
|
||
curr = strtok(NULL, " ");
|
||
curr = strtok(NULL, " ");
|
||
curr = strtok(NULL, " ");
|
||
|
||
return curr;
|
||
}
|
||
|
||
//testing a few things, going to put this into ncursesMenu
|
||
#define WIDTH 36
|
||
#define HEIGHT 23
|
||
|
||
int startx = 0;
|
||
int starty = 0;
|
||
|
||
char *choicesc[] = {
|
||
"Return",
|
||
"Save Decoded Audio WAV (Legacy Mode)",
|
||
"Save Signal to Symbol Capture Bin",
|
||
"Toggle Muting Encrypted Traffic ",
|
||
"Save Per Call Decoded WAV (XDMA and NXDN)",
|
||
"Setup and Start RTL Input ",
|
||
"Retune RTL Dongle ",
|
||
" ",
|
||
" ", //removing options no longer necesary or not recommended
|
||
"Toggle NCurses Compact Mode",
|
||
"Toggle NCurses Call History",
|
||
"Stop All Decoded WAV Saving",
|
||
"Read OP25/FME Symbol Capture Bin",
|
||
"Replay Last Symbol Capture Bin",
|
||
"Stop & Close Symbol Capture Bin Playback",
|
||
"Stop & Close Symbol Capture Bin Saving",
|
||
" ",
|
||
"Resume Decoding"
|
||
};
|
||
|
||
char *choices[] = {
|
||
"Resume Decoding",
|
||
"Decode Legacy Auto**",
|
||
"Decode XDMA (P25 and DMR BS/MS)",
|
||
"Decode D-STAR*",
|
||
"Decode P25-P1*",
|
||
"Decode ProVoice",
|
||
"Decode DMR* (LEH)",
|
||
"Decode dPMR",
|
||
"Decode NXDN48",
|
||
"Decode NXDN96",
|
||
"Decode X2-TDMA*",
|
||
"Toggle Signal Inversion",
|
||
"Privacy Key Entry",
|
||
// " ",
|
||
"Reset Call History",
|
||
"Toggle Payloads to Console",
|
||
"Manually Set P2 Parameters", //16
|
||
"Input & Output Options",
|
||
"LRRP Data to File",
|
||
"Exit DSD-FME",
|
||
// "Test"
|
||
};
|
||
|
||
|
||
int n_choices = sizeof(choices) / sizeof(char *);
|
||
// int n_choicesb = sizeof(choicesb) / sizeof(char *);
|
||
int n_choicesc = sizeof(choicesc) / sizeof(char *);
|
||
|
||
void print_menu(WINDOW *menu_win, int highlight)
|
||
{
|
||
int x, y, i;
|
||
|
||
x = 2;
|
||
y = 2;
|
||
box(menu_win, 0, 0);
|
||
for(i = 0; i < n_choices; ++i)
|
||
{ if(highlight == i + 1) /* High light the present choice */
|
||
{ wattron(menu_win, A_REVERSE);
|
||
mvwprintw(menu_win, y, x, "%s", choices[i]);
|
||
wattroff(menu_win, A_REVERSE);
|
||
}
|
||
else
|
||
mvwprintw(menu_win, y, x, "%s", choices[i]);
|
||
++y;
|
||
}
|
||
wrefresh(menu_win);
|
||
}
|
||
|
||
// void print_menub(WINDOW *menu_win, int highlight)
|
||
// {
|
||
// int x, y, i;
|
||
//
|
||
// x = 2;
|
||
// y = 2;
|
||
// box(menu_win, 0, 0);
|
||
// for(i = 0; i < n_choicesb; ++i)
|
||
// { if(highlight == i + 1) /* High light the present choice */
|
||
// { wattron(menu_win, A_REVERSE);
|
||
// mvwprintw(menu_win, y, x, "%s", choicesb[i]);
|
||
// wattroff(menu_win, A_REVERSE);
|
||
// }
|
||
// else
|
||
// mvwprintw(menu_win, y, x, "%s", choicesb[i]);
|
||
// ++y;
|
||
// }
|
||
// wrefresh(menu_win);
|
||
// }
|
||
|
||
void print_menuc(WINDOW *menu_win, int highlight)
|
||
{
|
||
int x, y, i;
|
||
|
||
x = 2;
|
||
y = 2;
|
||
box(menu_win, 0, 0);
|
||
for(i = 0; i < n_choicesc; ++i)
|
||
{ if(highlight == i + 1) /* High light the present choice */
|
||
{ wattron(menu_win, A_REVERSE);
|
||
mvwprintw(menu_win, y, x, "%s", choicesc[i]);
|
||
wattroff(menu_win, A_REVERSE);
|
||
}
|
||
else
|
||
mvwprintw(menu_win, y, x, "%s", choicesc[i]);
|
||
++y;
|
||
}
|
||
wrefresh(menu_win);
|
||
}
|
||
|
||
//end Testing
|
||
|
||
void ncursesOpen (dsd_opts * opts, dsd_state * state)
|
||
{
|
||
// state->menuopen = 1; //flag the menu is open, stop processing getFrameSync
|
||
mbe_printVersion (versionstr);
|
||
setlocale(LC_ALL, "");
|
||
initscr(); //Initialize NCURSES screen window
|
||
start_color();
|
||
init_pair(1, COLOR_YELLOW, COLOR_BLACK); //Yellow/Amber for frame sync/control channel, NV style
|
||
init_pair(2, COLOR_RED, COLOR_BLACK); //Red for Terminated Calls
|
||
init_pair(3, COLOR_GREEN, COLOR_BLACK); //Green for Active Calls
|
||
init_pair(4, COLOR_CYAN, COLOR_BLACK); //Cyan for Site Extra and Patches
|
||
init_pair(5, COLOR_MAGENTA, COLOR_BLACK); //Magenta for no frame sync/signal
|
||
init_pair(6, COLOR_WHITE, COLOR_BLACK); //White Card Color Scheme
|
||
noecho();
|
||
cbreak();
|
||
|
||
}
|
||
|
||
//ncursesMenu
|
||
void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||
{
|
||
// state->menuopen = 1; //flag the menu is open, stop processing getFrameSync
|
||
closePulseOutput (opts);
|
||
|
||
if (opts->audio_in_type == 0) //close pulse input if it is the specified input method
|
||
{
|
||
closePulseInput(opts);
|
||
}
|
||
|
||
state->payload_keyid = 0;
|
||
state->payload_keyidR = 0;
|
||
|
||
//zero out to fix call history 'scrolling' bug when changing decoding types
|
||
state->nxdn_last_tg = 0;
|
||
state->nxdn_last_ran = 0;
|
||
state->nxdn_last_rid = 0;
|
||
|
||
WINDOW *menu_win;
|
||
WINDOW *test_win;
|
||
WINDOW *entry_win;
|
||
WINDOW *info_win;
|
||
int highlight = 1;
|
||
int highlightb = 1;
|
||
int highlightc = 1;
|
||
int choice = 0;
|
||
int choiceb = 0;
|
||
int choicec = 0;
|
||
int c;
|
||
int d;
|
||
int e;
|
||
|
||
startx = 2;
|
||
starty = 1;
|
||
|
||
menu_win = newwin(HEIGHT, WIDTH, starty, startx);
|
||
keypad(menu_win, TRUE);
|
||
mvprintw(0, 0, " Use arrow keys to go up and down, Press ENTER to select a choice.");
|
||
refresh();
|
||
print_menu(menu_win, highlight);
|
||
while(1)
|
||
{ c = wgetch(menu_win);
|
||
switch(c)
|
||
{ case KEY_UP:
|
||
if(highlight == 1)
|
||
highlight = n_choices;
|
||
else
|
||
--highlight;
|
||
break;
|
||
case KEY_DOWN:
|
||
if(highlight == n_choices)
|
||
highlight = 1;
|
||
else
|
||
++highlight;
|
||
break;
|
||
case 10:
|
||
choice = highlight;
|
||
break;
|
||
default:
|
||
//mvprintw(24, 0, "Character pressed is = %3d Hopefully it can be printed as '%c'", c, c);
|
||
refresh();
|
||
break;
|
||
}
|
||
|
||
print_menu(menu_win, highlight);
|
||
|
||
//test print info boxes on side of certain options
|
||
if (highlight == 2)
|
||
{
|
||
info_win = newwin(6, WIDTH+18, starty, startx+20);
|
||
box (info_win, 0, 0);
|
||
mvwprintw(info_win, 2, 2, " Legacy Auto can only detect the following:");
|
||
mvwprintw(info_win, 3, 2, " P25-P1, D-STAR, DMR LEH, and X2-TDMA");
|
||
wrefresh(info_win);
|
||
}
|
||
|
||
if (highlight == 3)
|
||
{
|
||
info_win = newwin(7, WIDTH+18, starty, startx+20);
|
||
box (info_win, 0, 0);
|
||
mvwprintw(info_win, 2, 2, " XDMA Decoding Class Supports the following:");
|
||
mvwprintw(info_win, 3, 2, " P25-P1, P25-P2, DMR Stereo BS/MS and X2-TDMA");
|
||
mvwprintw(info_win, 4, 2, " --C4FM / FSK4 only, and OP25 P2 Capture Bins");
|
||
wrefresh(info_win);
|
||
}
|
||
|
||
//Input Output Options
|
||
if (choice == 17)
|
||
{
|
||
//test making a new window while other window is open
|
||
test_win = newwin(HEIGHT-1, WIDTH+9, starty+5, startx+5);
|
||
keypad(menu_win, FALSE);
|
||
keypad(test_win, TRUE);
|
||
mvprintw(0, 0, "Input & Output Options ");
|
||
refresh();
|
||
print_menuc(test_win, highlightc);
|
||
while(1)
|
||
{ e = wgetch(test_win);
|
||
switch(e)
|
||
{ case KEY_UP:
|
||
if(highlightc == 1)
|
||
highlightc = n_choicesc;
|
||
else
|
||
--highlightc;
|
||
break;
|
||
case KEY_DOWN:
|
||
if(highlightc == n_choicesc)
|
||
highlightc = 1;
|
||
else
|
||
++highlightc;
|
||
break;
|
||
case 10:
|
||
choicec = highlightc;
|
||
break;
|
||
default:
|
||
//mvprintw(24, 0, "Character pressed is = %3d Hopefully it can be printed as '%c'", c, c);
|
||
refresh();
|
||
break;
|
||
}
|
||
print_menuc(test_win, highlightc);
|
||
if (choicec == 2)
|
||
{
|
||
sprintf (opts->wav_out_file, "%s %s DSD-FME-DECODED.wav", getDateN(), getTimeN());
|
||
openWavOutFile (opts, state);
|
||
}
|
||
if (choicec == 3)
|
||
{
|
||
//read in filename for symbol capture bin
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter FME Symbol Capture Bin Filename");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%s", &opts->symbol_out_file);
|
||
noecho();
|
||
|
||
if (opts->symbol_out_file[0] != 0) //NULL
|
||
{
|
||
opts->symbol_out = 1; //set flag to 1
|
||
openSymbolOutFile (opts, state);
|
||
}
|
||
|
||
}
|
||
if (choicec == 4)
|
||
{
|
||
//toggle all mutes
|
||
if (opts->unmute_encrypted_p25 == 0)
|
||
{
|
||
opts->unmute_encrypted_p25 = 1;
|
||
}
|
||
else opts->unmute_encrypted_p25 = 0;
|
||
|
||
if (opts->dmr_mute_encL == 0)
|
||
{
|
||
opts->dmr_mute_encL = 1;
|
||
}
|
||
else opts->dmr_mute_encL = 0;
|
||
|
||
if (opts->dmr_mute_encR == 0)
|
||
{
|
||
opts->dmr_mute_encR = 1;
|
||
}
|
||
else opts->dmr_mute_encR = 0;
|
||
|
||
}
|
||
if (choicec == 5)
|
||
{
|
||
char wav_file_directory[1024];
|
||
sprintf (wav_file_directory, "./WAV");
|
||
wav_file_directory[1023] = '\0';
|
||
if (stat(wav_file_directory, &st_wav) == -1)
|
||
{
|
||
fprintf (stderr, "%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);
|
||
}
|
||
opts->dmr_stereo_wav = 1;
|
||
//catch all in case of no file name set, won't crash or something
|
||
sprintf (opts->wav_out_file, "./WAV/DSD-FME-X1.wav");
|
||
sprintf (opts->wav_out_fileR, "./WAV/DSD-FME-X2.wav");
|
||
openWavOutFileL (opts, state);
|
||
openWavOutFileR (opts, state);
|
||
|
||
}
|
||
|
||
if (choicec == 6)
|
||
{
|
||
int confirm = 0;
|
||
|
||
#ifdef USE_RTLSDR
|
||
|
||
//could also benefit from having some control aside from UDP remote
|
||
//BUG: When squelch enabled, all processing halts, no more ncursesprinter until squelch broken
|
||
//make another submenu to control these values if tests go well
|
||
|
||
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter RTL Device Index Number");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtl_dev_index);
|
||
noecho();
|
||
|
||
//this is NOT scanning (or printing) in the variable for some reason...why?
|
||
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter RTL Device PPM Error");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtlsdr_ppm_error);
|
||
noecho();
|
||
//opts->rtlsdr_ppm_error = -1; //hard set override for testing
|
||
|
||
//apparently, scanning in an lld nukes later box entries for some reason
|
||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter Frequency in Hz (851.8 MHz is 851800000 Hz) ");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq); //ld, or lld?
|
||
noecho();
|
||
|
||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter VFO Bandwidth (6, 8, 12, 16, 24, 48)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtl_bandwidth);
|
||
noecho();
|
||
|
||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter RTL Gain Value (0-49) (0 = Auto Gain)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtl_gain_value);
|
||
noecho();
|
||
|
||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter RTL UDP Remote Port (Default = 6020)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtl_udp_port);
|
||
noecho();
|
||
if (opts->rtl_udp_port == 0)
|
||
{
|
||
opts->rtl_udp_port = 6020;
|
||
}
|
||
|
||
entry_win = newwin(8, WIDTH+22, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter RTL Device Squelch Level or Enter 0");
|
||
mvwprintw(entry_win, 3, 2, " WARNING! Renders Terminal Unresponsive When No Signal!");
|
||
mvwprintw(entry_win, 4, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtl_squelch_level);
|
||
noecho();
|
||
|
||
entry_win = newwin(17, WIDTH+20, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Starting RTL Input. Cannot Release/Stop Until Exit.");
|
||
mvwprintw(entry_win, 4, 2, " RTL Frequency: %d Hz", opts->rtlsdr_center_freq);
|
||
mvwprintw(entry_win, 5, 2, " RTL Device Index Number: %d", opts->rtl_dev_index);
|
||
mvwprintw(entry_win, 6, 2, " RTL Device VFO Bandwidth: %d kHz", opts->rtl_bandwidth);
|
||
mvwprintw(entry_win, 7, 2, " RTL Device Gain: %d", opts->rtl_gain_value);
|
||
mvwprintw(entry_win, 8, 2, " RTL Device UDP Port: %d", opts->rtl_udp_port);
|
||
mvwprintw(entry_win, 9, 2, " RTL Device PPM: %d", opts->rtlsdr_ppm_error);
|
||
mvwprintw(entry_win, 10, 2, " RTL Device Squelch: %d", opts->rtl_squelch_level);
|
||
mvwprintw(entry_win, 12, 2, " Are You Sure?");
|
||
mvwprintw(entry_win, 13, 2, " 1 = Yes, 2 = No ");
|
||
mvwprintw(entry_win, 14, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &confirm);
|
||
noecho();
|
||
|
||
refresh();
|
||
|
||
//works well, but can't release dongle later, so its a one way trip until exit
|
||
if (confirm == 1)
|
||
{
|
||
opts->audio_in_type = 3; //RTL input, only set this on confirm
|
||
choicec = 18; //exit to decoder screen only if confirmed, otherwise, just go back
|
||
}
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
if (choicec == 10)
|
||
{
|
||
if (opts->ncurses_compact == 0)
|
||
{
|
||
opts->ncurses_compact = 1;
|
||
}
|
||
else opts->ncurses_compact = 0;
|
||
|
||
}
|
||
|
||
if (choicec == 11)
|
||
{
|
||
if (opts->ncurses_history == 0)
|
||
{
|
||
opts->ncurses_history = 1;
|
||
}
|
||
else opts->ncurses_history = 0;
|
||
}
|
||
|
||
if (choicec == 12)
|
||
{
|
||
//flesh out all closewavs and sprint "" wav filenames
|
||
closeWavOutFile (opts, state);
|
||
closeWavOutFileL (opts, state);
|
||
closeWavOutFileR (opts, state);
|
||
//closeWavOutFileRaw (opts, state);
|
||
sprintf (opts->wav_out_file, "%s", "");
|
||
sprintf (opts->wav_out_fileR, "%s", "");
|
||
opts->dmr_stereo_wav = 0;
|
||
}
|
||
|
||
if (choicec == 13) //lucky number 13 for OP25 Symbol Capture Bin Files
|
||
{
|
||
//read in filename for symbol capture bin
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter OP25 Symbol Capture Bin Filename");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%s", &opts->audio_in_dev);
|
||
noecho();
|
||
//do the thing with the thing
|
||
struct stat stat_buf;
|
||
if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
||
{
|
||
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
|
||
goto SKIP;
|
||
}
|
||
if (S_ISREG(stat_buf.st_mode))
|
||
{
|
||
opts->symbolfile = fopen(opts->audio_in_dev, "r");
|
||
opts->audio_in_type = 4; //symbol capture bin files
|
||
}
|
||
SKIP:
|
||
choicec = 18;
|
||
}
|
||
|
||
if (choicec == 14) //replay last file
|
||
{
|
||
struct stat stat_buf;
|
||
if (stat(opts->audio_in_dev, &stat_buf) != 0)
|
||
{
|
||
fprintf (stderr,"Error, couldn't open %s\n", opts->audio_in_dev);
|
||
goto SKIPR;
|
||
}
|
||
if (S_ISREG(stat_buf.st_mode))
|
||
{
|
||
opts->symbolfile = fopen(opts->audio_in_dev, "r");
|
||
opts->audio_in_type = 4; //symbol capture bin files
|
||
}
|
||
SKIPR:
|
||
choicec = 18; //exit
|
||
}
|
||
|
||
if (choicec == 15) //stop/close last file PLAYBACK
|
||
{
|
||
if (opts->symbolfile != NULL)
|
||
{
|
||
if (opts->audio_in_type == 4) //check first, or issuing a second fclose will crash the SOFTWARE
|
||
{
|
||
fclose(opts->symbolfile); //free(): double free detected in tcache 2 (this is a new one) happens when closing more than once
|
||
|
||
}
|
||
|
||
}
|
||
opts->audio_in_type = 0; //set after closing to prevent above crash condition
|
||
|
||
choicec = 18; //exit
|
||
}
|
||
|
||
if (choicec == 16) //stop/close last file RECORDING
|
||
{
|
||
if (opts->symbol_out == 1)
|
||
{
|
||
if (opts->symbol_out_file[0] != 0) //NULL
|
||
{
|
||
fclose(opts->symbol_out_f); //free(): double free detected in tcache 2 (this is a new one) happens when closing more than once
|
||
sprintf (opts->audio_in_dev, "%s", opts->symbol_out_file); //swap output bin filename to input for quick replay
|
||
}
|
||
|
||
opts->symbol_out = 0; //set flag to 1
|
||
|
||
}
|
||
choicec = 18; //exit
|
||
}
|
||
|
||
if (choicec == 7) //RTL UDP Retune
|
||
{
|
||
//read in new rtl frequency
|
||
#ifdef USE_RTLSDR
|
||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter Frequency in Hz (851.8 MHz is 851800000 Hz) ");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &opts->rtlsdr_center_freq); //ld, or lld?
|
||
noecho();
|
||
//do the thing with the thing
|
||
data[0] = 0;
|
||
data[1] = opts->rtlsdr_center_freq & 0xFF;
|
||
data[2] = (opts->rtlsdr_center_freq >> 8) & 0xFF;
|
||
data[3] = (opts->rtlsdr_center_freq >> 16) & 0xFF;
|
||
data[4] = (opts->rtlsdr_center_freq >> 24) & 0xFF;
|
||
|
||
temp_freq = opts->rtlsdr_center_freq;
|
||
#endif
|
||
choicec = 18;
|
||
}
|
||
|
||
if (choicec != 0 && choicec != 18 ) //return to last menu
|
||
{
|
||
//return
|
||
choice = 0;
|
||
choicec = 0;
|
||
|
||
keypad(test_win, FALSE);
|
||
keypad(menu_win, TRUE);
|
||
delwin(test_win);
|
||
print_menu(menu_win, highlight);
|
||
//wrefresh(menu_win);
|
||
break;
|
||
}
|
||
if (choicec == 18) //exit both menus
|
||
{
|
||
//exit
|
||
choice = 1;
|
||
choicec = 0;
|
||
|
||
keypad(test_win, FALSE);
|
||
keypad(menu_win, TRUE);
|
||
delwin(test_win);
|
||
print_menu(menu_win, highlight);
|
||
break;
|
||
}
|
||
}
|
||
clrtoeol(); //clear to end of line?
|
||
refresh();
|
||
}
|
||
|
||
//Privacy Key Entry
|
||
if (choice == 13)
|
||
{
|
||
state->payload_keyid = 0;
|
||
state->payload_keyidR = 0;
|
||
short int option = 0;
|
||
entry_win = newwin(11, WIDTH+6, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, "Key Type Selection");
|
||
mvwprintw(entry_win, 3, 2, " ");
|
||
mvwprintw(entry_win, 4, 2, "1 - DMRA Privacy ");
|
||
mvwprintw(entry_win, 5, 2, "2 - **tera Privacy ");
|
||
mvwprintw(entry_win, 6, 2, "3 - NXDN Scrambler ");
|
||
mvwprintw(entry_win, 7, 2, "4 - Force Key Priority ");
|
||
mvwprintw(entry_win, 8, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &option);
|
||
noecho();
|
||
opts->dmr_mute_encL = 0;
|
||
opts->dmr_mute_encR = 0;
|
||
if (option == 1)
|
||
{
|
||
state->K = 0;
|
||
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, "DMRA Privacy Key Number (DEC):");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%lld", &state->K);
|
||
noecho();
|
||
if (state->K > 255)
|
||
{
|
||
state->K = 255;
|
||
}
|
||
}
|
||
if (option == 2)
|
||
{
|
||
state->K1 = 0;
|
||
state->K2 = 0;
|
||
state->K3 = 0;
|
||
state->K4 = 0;
|
||
state->H = 0;
|
||
|
||
entry_win = newwin(7, WIDTH+8, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value (HEX) ");
|
||
mvwprintw(entry_win, 3, 2, " 10 Char or First 16 for 32/64");
|
||
mvwprintw(entry_win, 4, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%llX", &state->H);
|
||
noecho();
|
||
state->K1 = state->H;
|
||
|
||
entry_win = newwin(7, WIDTH+8, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 2 (HEX) ");
|
||
mvwprintw(entry_win, 3, 2, " Second 16 Chars or Zero");
|
||
mvwprintw(entry_win, 4, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%llX", &state->K2);
|
||
noecho();
|
||
|
||
entry_win = newwin(7, WIDTH+8, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 3 (HEX) ");
|
||
mvwprintw(entry_win, 3, 2, " Third 16 Chars or Zero");
|
||
mvwprintw(entry_win, 4, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%llX", &state->K3);
|
||
noecho();
|
||
|
||
entry_win = newwin(7, WIDTH+8, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter **tera Privacy Key Value 4 (HEX) ");
|
||
mvwprintw(entry_win, 3, 2, " Fourth 16 Chars or Zero");
|
||
mvwprintw(entry_win, 4, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%llX", &state->K4);
|
||
noecho();
|
||
|
||
}
|
||
if (option == 3)
|
||
{
|
||
state->R = 0;
|
||
entry_win = newwin(6, WIDTH+6, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, "NXDN Scrambler Key Value (DEC):");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%lld", &state->R);
|
||
noecho();
|
||
if (state->K > 0x7FFF)
|
||
{
|
||
state->K = 0x7FFF;
|
||
}
|
||
}
|
||
//toggle enforcement of privacy key over enc bit set on traffic
|
||
if (option == 4)
|
||
{
|
||
if (state->M == 0)
|
||
{
|
||
state->M = 1;
|
||
}
|
||
else state->M = 0;
|
||
}
|
||
if (state->K == 0 && state->K1 == 0)
|
||
{
|
||
opts->dmr_mute_encL = 1;
|
||
opts->dmr_mute_encR = 1;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
if (choice == 2)
|
||
{
|
||
//setup Auto parameters--default ones
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
sprintf (opts->output_name, "Legacy Auto");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 1;
|
||
opts->frame_x2tdma = 1;
|
||
opts->frame_p25p1 = 1;
|
||
opts->frame_p25p2 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 1;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
opts->unmute_encrypted_p25 = 0;
|
||
break;
|
||
|
||
}
|
||
if (choice == 6)
|
||
{
|
||
//ProVoice Specifics
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 5;
|
||
state->symbolCenter = 2;
|
||
sprintf (opts->output_name, "ProVoice");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_p25p2 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 1;
|
||
opts->mod_c4fm = 0;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 1;
|
||
state->rf_mod = 2;
|
||
break;
|
||
}
|
||
if (choice == 4)
|
||
{
|
||
//DSTAR
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
sprintf (opts->output_name, "D-STAR");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 1;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_p25p2 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
// state->rf_mod = 2;
|
||
opts->unmute_encrypted_p25 = 0;
|
||
break;
|
||
}
|
||
if (choice == 5)
|
||
{
|
||
//P25 P1
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
opts->frame_p25p1 = 1;
|
||
opts->frame_p25p2 = 0;
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
state->rf_mod = 0;
|
||
sprintf (opts->output_name, "P25P1");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
//opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
// state->rf_mod = 0;
|
||
opts->unmute_encrypted_p25 = 0;
|
||
break;
|
||
}
|
||
|
||
if (choice == 3)
|
||
{
|
||
//XDMA Stereo P25 1, 2, and DMR
|
||
resetState (state); //use sparingly, seems to cause issue when switching back to other formats
|
||
opts->frame_dmr = 1;
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
state->rf_mod = 0;
|
||
sprintf (opts->output_name, "XDMA");
|
||
opts->dmr_stereo = 1; //this value is the end user option
|
||
state->dmr_stereo = 1; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 24000;
|
||
opts->pulse_digi_out_channels = 2;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 1;
|
||
opts->frame_p25p1 = 1;
|
||
opts->frame_p25p2 = 1;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
break;
|
||
}
|
||
if (choice == 7)
|
||
{
|
||
//set legacy DMR settings
|
||
resetState (state); //use sparingly, seems to cause issue when switching back to other formats
|
||
opts->frame_dmr = 1;
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
state->rf_mod = 0;
|
||
sprintf (opts->output_name, "DMR LEH");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
//opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
break;
|
||
}
|
||
if (choice == 8)
|
||
{
|
||
//dPMR
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 20;
|
||
state->symbolCenter = 10;
|
||
sprintf (opts->output_name, "dPMR");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 1;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
//opts->unmute_encrypted_p25 = 0;
|
||
break;
|
||
}
|
||
if (choice == 9)
|
||
{
|
||
//NXDN48
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
opts->frame_nxdn48 = 1;
|
||
state->samplesPerSymbol = 20;
|
||
state->symbolCenter = 10;
|
||
state->rf_mod = 0;
|
||
sprintf (opts->output_name, "NXDN48");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 1;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
//opts->unmute_encrypted_p25 = 0;
|
||
// opts->mod_qpsk = 0;
|
||
// opts->mod_gfsk = 0;
|
||
// state->rf_mod = 0;
|
||
}
|
||
if (choice == 10)
|
||
{
|
||
//NXDN96
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
sprintf (opts->output_name, "NXDN96");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 0;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 1;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
//opts->unmute_encrypted_p25 = 0;
|
||
}
|
||
if (choice == 11)
|
||
{
|
||
//Decode X2-TDMA
|
||
//NXDN96
|
||
resetState (state); //use sparingly, may cause memory leak
|
||
state->samplesPerSymbol = 10;
|
||
state->symbolCenter = 4;
|
||
sprintf (opts->output_name, "X2-TDMA");
|
||
opts->dmr_stereo = 0; //this value is the end user option
|
||
state->dmr_stereo = 0; //this values toggles on and off depending on voice or data handling
|
||
opts->pulse_digi_rate_out = 8000;
|
||
opts->pulse_digi_out_channels = 1;
|
||
opts->frame_dstar = 0;
|
||
opts->frame_x2tdma = 1;
|
||
opts->frame_p25p1 = 0;
|
||
opts->frame_nxdn48 = 0;
|
||
opts->frame_nxdn96 = 0;
|
||
opts->frame_dmr = 0;
|
||
opts->frame_dpmr = 0;
|
||
opts->frame_provoice = 0;
|
||
opts->mod_c4fm = 1;
|
||
opts->mod_qpsk = 0;
|
||
opts->mod_gfsk = 0;
|
||
state->rf_mod = 0;
|
||
//opts->unmute_encrypted_p25 = 0;
|
||
}
|
||
if (choice == 12)
|
||
{
|
||
//Set all signal for inversion or uninversion
|
||
if (opts->inverted_dmr == 0)
|
||
{
|
||
opts->inverted_dmr = 1;
|
||
opts->inverted_dpmr = 1;
|
||
opts->inverted_x2tdma = 1;
|
||
opts->inverted_ysf = 1;
|
||
}
|
||
else
|
||
{
|
||
opts->inverted_dmr = 0;
|
||
opts->inverted_dpmr = 0;
|
||
opts->inverted_x2tdma = 0;
|
||
opts->inverted_ysf = 0;
|
||
}
|
||
|
||
}
|
||
if (choice == 14) //reset call history (usually if janky output when switching modes)
|
||
{
|
||
for (short int k = 0; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = 0;
|
||
call_matrix[k][1] = 0;
|
||
call_matrix[k][2] = 0;
|
||
call_matrix[k][3] = 0;
|
||
call_matrix[k][4] = 0;
|
||
call_matrix[k][5] = 0;
|
||
}
|
||
src = 0;
|
||
rn = 0;
|
||
tgn = 0;
|
||
dcc = 0;
|
||
tg = 0;
|
||
tgR = 0;
|
||
rd = 0;
|
||
rdR = 0;
|
||
state->lastsrc = 0;
|
||
state->lastsrcR = 0;
|
||
state->lasttg = 0;
|
||
state->lasttgR = 0;
|
||
}
|
||
|
||
if (choice == 15) //toggle payload printing
|
||
{
|
||
if (opts->payload == 0)
|
||
{
|
||
opts->payload = 1;
|
||
fprintf(stderr, "Payload on\n");
|
||
}
|
||
else
|
||
{
|
||
opts->payload = 0;
|
||
fprintf(stderr, "Payload Off\n");
|
||
}
|
||
}
|
||
if (choice == 16)
|
||
{
|
||
//hardset P2 WACN, SYSID, and NAC
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter Phase 2 WACN (HEX)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%X", &state->p2_wacn);
|
||
if (state->p2_wacn > 0xFFFFF)
|
||
{
|
||
state->p2_wacn = 0xFFFFF;
|
||
}
|
||
noecho();
|
||
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter Phase 2 SYSID (HEX)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%X", &state->p2_sysid);
|
||
if (state->p2_sysid > 0xFFF)
|
||
{
|
||
state->p2_sysid = 0xFFF;
|
||
}
|
||
noecho();
|
||
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter Phase 2 NAC/CC (HEX)");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%X", &state->p2_cc);
|
||
if (state->p2_cc > 0xFFF)
|
||
{
|
||
state->p2_cc = 0xFFF;
|
||
}
|
||
noecho();
|
||
|
||
//need handling to truncate larger than expected values
|
||
|
||
//set our hardset flag to 1 if values inserted, else set to 0 so we can attempt to get them from TSBK/LCCH
|
||
if (state->p2_wacn != 0 && state->p2_sysid != 0 && state->p2_cc != 0)
|
||
{
|
||
state->p2_hardset = 1;
|
||
}
|
||
else state->p2_hardset = 0;
|
||
|
||
|
||
}
|
||
if (choice == 18)
|
||
{
|
||
short int lrrpchoice = 0;
|
||
entry_win = newwin(10, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enable or Disable LRRP Data File");
|
||
mvwprintw(entry_win, 3, 2, " 1 - ~/lrrp.txt (QGis)");
|
||
mvwprintw(entry_win, 4, 2, " 2 - ./DSDPlus.LRRP (LRRP.exe)");
|
||
mvwprintw(entry_win, 5, 2, " 3 - ./Custom Filename");
|
||
mvwprintw(entry_win, 6, 2, " 4 - Cancel/Stop");
|
||
mvwprintw(entry_win, 7, 2, " ");
|
||
mvwprintw(entry_win, 8, 2, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%d", &lrrpchoice);
|
||
noecho();
|
||
|
||
if (lrrpchoice == 1)
|
||
{
|
||
//find user home directory and append directory and filename.
|
||
char * filename = "/lrrp.txt";
|
||
char * home_dir = getenv("HOME");
|
||
char * filepath = malloc(strlen(home_dir) + strlen(filename) + 1);
|
||
strncpy (filepath, home_dir, strlen(home_dir) + 1);
|
||
strncat (filepath, filename, strlen(filename) + 1);
|
||
//assign home directory/filename to lrrp_out_file
|
||
sprintf (opts->lrrp_out_file, "%s", filepath); //double check make sure this still works
|
||
opts->lrrp_file_output = 1;
|
||
}
|
||
|
||
else if (lrrpchoice == 2)
|
||
{
|
||
sprintf (opts->lrrp_out_file, "DSDPlus.LRRP");
|
||
opts->lrrp_file_output = 1;
|
||
}
|
||
|
||
else if (lrrpchoice == 3)
|
||
{
|
||
//read in filename for symbol capture bin
|
||
opts->lrrp_out_file[0] = 0;
|
||
entry_win = newwin(6, WIDTH+16, starty+10, startx+10);
|
||
box (entry_win, 0, 0);
|
||
mvwprintw(entry_win, 2, 2, " Enter LRRP Data Filename");
|
||
mvwprintw(entry_win, 3, 3, " ");
|
||
echo();
|
||
refresh();
|
||
wscanw(entry_win, "%s", &opts->lrrp_out_file);
|
||
noecho();
|
||
if (opts->lrrp_out_file[0] != 0) //NULL
|
||
{
|
||
opts->lrrp_file_output = 1;
|
||
}
|
||
else
|
||
{
|
||
opts->lrrp_file_output = 0;
|
||
sprintf (opts->lrrp_out_file, "%s", "");
|
||
opts->lrrp_out_file[0] = 0;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
opts->lrrp_file_output = 0;
|
||
sprintf (opts->lrrp_out_file, "%s", "");
|
||
opts->lrrp_out_file[0] = 0;
|
||
}
|
||
}
|
||
if (choice == 19)
|
||
{
|
||
ncursesClose();
|
||
//cleanup_rtlsdr_stream();
|
||
cleanupAndExit (opts, state);
|
||
}
|
||
|
||
if(choice != 0 && choice != 20) /* User did a choice come out of the infinite loop */
|
||
break;
|
||
|
||
}
|
||
|
||
clrtoeol(); //clear to end of line?
|
||
refresh();
|
||
state->menuopen = 0; //flag the menu is closed, resume processing getFrameSync
|
||
|
||
//reopen pulse output with new parameters
|
||
openPulseOutput (opts);
|
||
|
||
if (opts->audio_in_type == 0) //reopen pulse input if it is the specified input method
|
||
{
|
||
openPulseInput(opts);
|
||
}
|
||
#ifdef USE_RTLSDR
|
||
if (opts->audio_in_type == 3) //open rtl input if it is the specified input method
|
||
{
|
||
ncursesPrinter (opts, state); //run one rep to clear menu boxes out
|
||
if (opts->rtl_started == 0)
|
||
{
|
||
opts->rtl_started = 1; //set here so ncurses terminal doesn't attempt to open it again
|
||
open_rtlsdr_stream(opts);
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
}
|
||
//end Ncurses Menu
|
||
|
||
void
|
||
ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||
{
|
||
int level = 0;
|
||
int c = 0;
|
||
|
||
if (opts->audio_in_type != 1) //can't run getch/menu when using STDIN -
|
||
{
|
||
timeout(0);
|
||
c = getch();
|
||
}
|
||
|
||
//testing sending UDP commands to the socket inside of rtl_sdr_fm.cpp
|
||
//this works, but we will want to make an init func open one time, and have sendto here
|
||
#ifdef USE_RTLSDR
|
||
if (temp_freq == opts->rtlsdr_center_freq)
|
||
{
|
||
handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||
|
||
memset((char * ) & address, 0, sizeof(address));
|
||
address.sin_family = AF_INET;
|
||
address.sin_addr.s_addr = inet_addr(SRV_IP); //address of host
|
||
address.sin_port = htons(udp_port);
|
||
sendto(handle, data, UDP_BUFLEN, 0, (const struct sockaddr * ) & address, sizeof(struct sockaddr_in));
|
||
|
||
temp_freq = -1;
|
||
}
|
||
#endif
|
||
|
||
//Variable reset/set section
|
||
|
||
//carrier reset
|
||
if (state->carrier == 0) //reset these to 0 when no carrier
|
||
{
|
||
sprintf(state->dmr_branding, "%s", "");
|
||
}
|
||
|
||
//set lls sync types
|
||
if (state->synctype >= 0 && state->synctype < 37) //not sure if this will be okay
|
||
{
|
||
lls = state->synctype;
|
||
}
|
||
|
||
//reset DMR alias block and embedded gps if burst type is not 16 or carrier drop
|
||
if (state->dmrburstL != 16 || state->carrier == 0)
|
||
{
|
||
for (short i = 0; i < 6; i++)
|
||
{
|
||
sprintf (state->dmr_callsign[0][i], "%s", "");
|
||
}
|
||
}
|
||
if (state->dmrburstR != 16 || state->carrier == 0)
|
||
{
|
||
for (short i = 0; i < 6; i++)
|
||
{
|
||
sprintf (state->dmr_callsign[1][i], "%s", "");
|
||
}
|
||
}
|
||
|
||
//reset DMR LRRP when call is active on current slot if burst type is not data or carrier drop
|
||
if (state->dmrburstL == 16 || state->carrier == 0)
|
||
{
|
||
for (short i = 0; i < 6; i++)
|
||
{
|
||
sprintf (state->dmr_lrrp[0][i], "%s", "");
|
||
}
|
||
}
|
||
if (state->dmrburstR == 16 || state->carrier == 0)
|
||
{
|
||
for (short i = 0; i < 6; i++)
|
||
{
|
||
sprintf (state->dmr_lrrp[1][i], "%s", "");
|
||
}
|
||
}
|
||
|
||
//NXDN
|
||
if (state->nxdn_last_rid > 0 && state->nxdn_last_rid != src);
|
||
{
|
||
src = state->nxdn_last_rid;
|
||
}
|
||
if (state->nxdn_last_ran > -1 && state->nxdn_last_ran != rn);
|
||
{
|
||
rn = state->nxdn_last_ran;
|
||
}
|
||
if (state->nxdn_last_tg > 0 && state->nxdn_last_tg != tgn);
|
||
{
|
||
tgn = state->nxdn_last_tg;
|
||
}
|
||
|
||
//DMR CC
|
||
if (state->color_code_ok && state->dmr_color_code != -1 && (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32 || lls == 33) )
|
||
{
|
||
dcc = state->dmr_color_code;
|
||
}
|
||
|
||
//DMR SRC
|
||
if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) )
|
||
{
|
||
if (state->dmrburstL == 16 && state->lastsrc > 0) //state->currentslot == 0 &&
|
||
{
|
||
rd = state->lastsrc;
|
||
}
|
||
|
||
if (state->dmrburstR == 16 && state->lastsrcR > 0) //state->currentslot == 1 &&
|
||
{
|
||
rdR = state->lastsrcR;
|
||
}
|
||
//move to seperate P25 version plz
|
||
//opts->p25enc = 0;
|
||
}
|
||
|
||
//DMR TG
|
||
if ( (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 32) )
|
||
{
|
||
if (state->dmrburstL == 16 && state->lasttg > 0) //state->currentslot == 0 &&
|
||
{
|
||
tg = state->lasttg;
|
||
|
||
}
|
||
|
||
if (state->dmrburstR == 16 && state->lasttgR > 0) //state->currentslot == 1 &&
|
||
{
|
||
tgR = state->lasttgR;
|
||
|
||
}
|
||
//opts->p25enc = 0;
|
||
|
||
}
|
||
|
||
//P25 P1 and VCH0
|
||
if (state->p2_cc > 0)
|
||
{
|
||
nc = state->p2_cc;
|
||
}
|
||
if ( state->lasttg > 0 && (lls == 0 || lls == 1 || lls == 35 || lls == 36) )
|
||
{
|
||
tg = state->lasttg;
|
||
}
|
||
if ( state->lastsrc > 0 && (lls == 0 || lls == 1 || lls == 35 || lls == 36) )
|
||
{
|
||
rd = state->lastsrc;
|
||
}
|
||
//P25 P2 VCH2
|
||
if (state->lasttgR > 0 && (lls == 35 || lls == 36) )
|
||
{
|
||
tgR = state->lasttgR;
|
||
}
|
||
if (state->lastsrcR > 0 && (lls == 35 || lls == 36) )
|
||
{
|
||
rdR = state->lastsrcR;
|
||
}
|
||
//P25 P2 NAC to dcc for matrix shim
|
||
if (state->p2_cc > 0 && (lls == 35 || lls == 36) )
|
||
{
|
||
dcc = state->p2_cc;
|
||
}
|
||
|
||
//Call History Matrix Shuffling
|
||
//ProVoice
|
||
if ( (lls == 14 || lls == 15) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1)
|
||
{
|
||
for (short int k = 0; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = 1;
|
||
call_matrix[9][2] = 1;
|
||
call_matrix[9][3] = 1;
|
||
call_matrix[9][4] = 1;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
}
|
||
|
||
//D-STAR, work on adding the headers later
|
||
if ( (lls == 6 || lls == 7 || lls == 18 || lls == 19) && (time(NULL) - call_matrix[9][5] > 5) && state->carrier == 1)
|
||
{
|
||
for (short int k = 0; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = 1;
|
||
call_matrix[9][2] = 1;
|
||
call_matrix[9][3] = 1;
|
||
call_matrix[9][4] = 1;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
}
|
||
|
||
//NXDN
|
||
if ( call_matrix[9][2] != src && src > 0 && rn > -1 )
|
||
{
|
||
for (short int k = 0; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = rn;
|
||
call_matrix[9][2] = src;
|
||
call_matrix[9][3] = 0;
|
||
call_matrix[9][4] = tgn;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
//open wav file if enabled and both rd and tg are not 0
|
||
if (opts->dmr_stereo_wav == 1 && src != 0 && tgn != 0)
|
||
{
|
||
//close old first, assign name based on time and radio, open wav file
|
||
closeWavOutFileL (opts, state);
|
||
sprintf (opts->wav_out_file, "./WAV/%s NXDN - RAN %d - TGT %d - SRC %d.wav", getTimeN(), rn, tgn, src);
|
||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||
}
|
||
|
||
}
|
||
|
||
//DMR MS
|
||
if ( call_matrix[9][2] != rd && (lls == 32 || lls == 33 || lls == 34) )
|
||
{
|
||
|
||
for (short int k = 0; k < 10; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = tg;
|
||
call_matrix[9][2] = rd;
|
||
call_matrix[9][3] = 1; //hard set slot number
|
||
call_matrix[9][4] = dcc;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
//open wav file if enabled and both rd and tg are not 0
|
||
if (opts->dmr_stereo_wav == 1 && rd != 0 && tg != 0)
|
||
{
|
||
//close old first, assign name based on time and radio, open wav file
|
||
closeWavOutFileL (opts, state);
|
||
sprintf (opts->wav_out_file, "./WAV/%s MS - CC %d - TG %d - RD %d.wav", getTimeN(), dcc, tg, rd);
|
||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||
}
|
||
|
||
}
|
||
|
||
//DMR BS Slot 1 - matrix 0-4
|
||
if ( call_matrix[4][2] != rd && (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 35 || lls == 36) )
|
||
{
|
||
|
||
for (short int k = 0; k < 4; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[4][0] = lls;
|
||
call_matrix[4][1] = tg;
|
||
call_matrix[4][2] = rd;
|
||
call_matrix[4][3] = 1; //hard set slot number
|
||
call_matrix[4][4] = dcc;
|
||
call_matrix[4][5] = time(NULL);
|
||
|
||
//open wav file if enabled and both rd and tg are not 0
|
||
if (opts->dmr_stereo_wav == 1 && rd != 0 && tg != 0)
|
||
{
|
||
//close old first, assign name based on time and radio, open wav file
|
||
closeWavOutFileL (opts, state);
|
||
|
||
sprintf (opts->wav_out_file, "./WAV/%s X1 - CC %d - TG %d - RD %d.wav", getTimeN(), dcc, tg, rd);
|
||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||
}
|
||
|
||
}
|
||
|
||
//DMR BS Slot 2 - matrix 5-9
|
||
if ( call_matrix[9][2] != rdR && (lls == 12 || lls == 13 || lls == 10 || lls == 11 || lls == 35 || lls == 36) )
|
||
{
|
||
|
||
for (short int k = 5; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = tgR;
|
||
call_matrix[9][2] = rdR;
|
||
call_matrix[9][3] = 2; //hard set slot number
|
||
call_matrix[9][4] = dcc;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
//open wav file if enabled and both rdR and tgR are not 0
|
||
if (opts->dmr_stereo_wav == 1 && rdR != 0 && tgR != 0)
|
||
{
|
||
//close old first, assign name based on time and radio, open wav file
|
||
closeWavOutFileR (opts, state);
|
||
sprintf (opts->wav_out_fileR, "./WAV/%s X2 - CC %d - TG %d - RD %d.wav", getTimeN(), dcc, tgR, rdR);
|
||
openWavOutFileR (opts, state); //testing for now, will want to move to per call later
|
||
}
|
||
|
||
}
|
||
|
||
//P25 P1
|
||
if ( (lls == 0 || lls == 1) && call_matrix[9][2] != rd && nc > 0 && tg > 0 && state->dmrburstL == 26)
|
||
{
|
||
for (short int k = 0; k < 9; k++)
|
||
{
|
||
call_matrix[k][0] = call_matrix[k+1][0];
|
||
call_matrix[k][1] = call_matrix[k+1][1];
|
||
call_matrix[k][2] = call_matrix[k+1][2];
|
||
call_matrix[k][3] = call_matrix[k+1][3];
|
||
call_matrix[k][4] = call_matrix[k+1][4];
|
||
call_matrix[k][5] = call_matrix[k+1][5];
|
||
}
|
||
|
||
call_matrix[9][0] = lls;
|
||
call_matrix[9][1] = tg;
|
||
call_matrix[9][2] = rd;
|
||
call_matrix[9][3] = 0;
|
||
call_matrix[9][4] = nc;
|
||
call_matrix[9][5] = time(NULL);
|
||
|
||
//open wav file if enabled and both rd and tg are not 0
|
||
if (opts->dmr_stereo_wav == 1 && rd != 0 && tg != 0)
|
||
{
|
||
//close old first, assign name based on time and radio, open wav file
|
||
closeWavOutFileL (opts, state);
|
||
sprintf (opts->wav_out_file, "./WAV/%s P1 - NAC %X - TGT %d - SRC %d.wav", getTimeN(), nc, tg, rd);
|
||
openWavOutFileL (opts, state); //testing for now, will want to move to per call later
|
||
}
|
||
|
||
}
|
||
|
||
//Start Printing Section
|
||
erase();
|
||
if (opts->ncurses_compact == 1)
|
||
{
|
||
printw ("------------------------------------------------------------------------------\n");
|
||
printw ("| Digital Speech Decoder: Florida Man Edition %s \n", GIT_TAG);
|
||
}
|
||
if (opts->ncurses_compact == 0)
|
||
{
|
||
attron(COLOR_PAIR(6)); //6
|
||
for (short int i = 0; i < 7; i++)
|
||
{
|
||
printw("%s \n", FM_bannerN[i]);
|
||
}
|
||
printw (" https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n");
|
||
printw (" Github Build Version: %s \n", GIT_TAG);
|
||
attroff(COLOR_PAIR(6)); //6
|
||
// printw ("--Build Info------------------------------------------------------------------\n");
|
||
// printw ("| https://github.com/lwvmobile/dsd-fme/tree/pulseaudio\n"); //http link
|
||
// printw ("| Digital Speech Decoder: Florida Man Edition\n");
|
||
// printw ("| Github Build Version: %s \n", GIT_TAG);
|
||
// printw ("| MBElib version %s\n", versionstr);
|
||
// printw ("------------------------------------------------------------------------------\n");
|
||
attron(COLOR_PAIR(4));
|
||
}
|
||
|
||
printw ("--Input Output----------------------------------------------------------------\n");
|
||
if (opts->audio_in_type == 0)
|
||
{
|
||
printw ("| Pulse Audio Input: [%2i] kHz [%i] Channel\n", opts->pulse_digi_rate_in/1000, opts->pulse_digi_in_channels);
|
||
}
|
||
if (opts->audio_in_type == 4)
|
||
{
|
||
printw ("| Symbol Capture Input: %s \n", opts->audio_in_dev);
|
||
}
|
||
if (opts->audio_in_type == 1)
|
||
{
|
||
printw ("| STDIN Standard Input: - Menu Disabled when using STDIN!\n");
|
||
// printw ("| NCURSES Menu Disabled when using STDIN! - Use CTRL + C to Close. \n");
|
||
}
|
||
if (opts->audio_in_type == 3)
|
||
{
|
||
printw ("| RTL2838UHIDIR Device #[%d]", opts->rtl_dev_index);
|
||
printw (" Gain [%i] dB -", opts->rtl_gain_value);
|
||
printw (" Squelch [%i]", opts->rtl_squelch_level);
|
||
printw (" VFO [%i] kHz\n", opts->rtl_bandwidth);
|
||
printw ("| Freq: [%lld] Hz", opts->rtlsdr_center_freq);
|
||
printw (" - Tuning available on UDP Port [%i]\n", opts->rtl_udp_port);
|
||
}
|
||
if (opts->audio_out_type == 0)
|
||
{
|
||
printw ("| Pulse Audio Output: [%2i] kHz [%i] Channel\n", opts->pulse_digi_rate_out/1000, opts->pulse_digi_out_channels);
|
||
}
|
||
if (opts->monitor_input_audio == 1)
|
||
{
|
||
printw ("| Monitoring Source Audio when Carrier Present and No Sync Detected\n");
|
||
}
|
||
if (opts->mbe_out_dir[0] != 0 && opts->dmr_stereo == 0)
|
||
{
|
||
printw ("| Writing MBE data files to directory %s\n", opts->mbe_out_dir);
|
||
}
|
||
if (opts->wav_out_file_raw[0] != 0 && opts->audio_in_type == 0)
|
||
{
|
||
printw ("| Appending Raw Sig Audio WAV to file %s\n", opts->wav_out_file_raw);
|
||
}
|
||
if (opts->symbol_out_file[0] != 0 && opts->symbol_out == 1)
|
||
{
|
||
printw ("| Writing Symbol Capture to Bin File: %s\n", opts->symbol_out_file);
|
||
}
|
||
if (opts->wav_out_file[0] != 0 && opts->dmr_stereo == 0)
|
||
{
|
||
printw ("| Writing Decoded Audio to WAV File: %s\n", opts->wav_out_file);
|
||
}
|
||
if (opts->dmr_stereo_wav == 1) //opts->wav_out_file[0] != 0 &&
|
||
{
|
||
printw ("| Per Call WAV S1 - %s\n", opts->wav_out_file);
|
||
printw ("| Per Call WAV S2 - %s\n", opts->wav_out_fileR);
|
||
}
|
||
|
||
|
||
printw ("------------------------------------------------------------------------------\n");
|
||
attroff(COLOR_PAIR(4));
|
||
|
||
if (state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(3));
|
||
level = (int) state->max / 164; //only update on carrier present
|
||
reset = 1;
|
||
}
|
||
if (state->carrier == 0 && opts->reset_state == 1 && reset == 1)
|
||
{
|
||
resetState (state);
|
||
reset = 0;
|
||
}
|
||
|
||
printw ("--Audio Decode----------------------------------------------------------------\n");
|
||
printw ("| Decoding: [%s] \n", opts->output_name);
|
||
printw ("| In Level: [%3i%%] \n", level);
|
||
if (opts->dmr_stereo == 0)
|
||
{
|
||
printw ("| Voice Error: [%i][%i] \n", state->errs, state->errs2);
|
||
}
|
||
|
||
if (opts->dmr_stereo == 1)
|
||
{
|
||
printw ("| Voice ErrS1: [%i][%i] \n", state->errs, state->errs2);
|
||
printw ("| Voice ErrS2: [%i][%i] \n", state->errsR, state->errs2R);
|
||
}
|
||
printw ("------------------------------------------------------------------------------\n");
|
||
|
||
printw ("--Call Info-------------------------------------------------------------------\n");
|
||
//DSTAR...what a pain...
|
||
if (lls == 6 || lls == 7 || lls == 18 || lls == 19)
|
||
{
|
||
if (state->dstarradioheader[3] != 0) //
|
||
{
|
||
printw ("| RPT 2: [%c%c%c%c%c%c%c%c] ", state->dstarradioheader[3], state->dstarradioheader[4],
|
||
state->dstarradioheader[5], state->dstarradioheader[6], state->dstarradioheader[7], state->dstarradioheader[8],
|
||
state->dstarradioheader[9], state->dstarradioheader[10]);
|
||
printw ("RPT 1: [%c%c%c%c%c%c%c%c] \n| ", state->dstarradioheader[11], state->dstarradioheader[12],
|
||
state->dstarradioheader[13], state->dstarradioheader[14], state->dstarradioheader[15], state->dstarradioheader[16],
|
||
state->dstarradioheader[17], state->dstarradioheader[18]);
|
||
printw ("YOUR: [%c%c%c%c%c%c%c%c] ", state->dstarradioheader[19], state->dstarradioheader[20],
|
||
state->dstarradioheader[21], state->dstarradioheader[22], state->dstarradioheader[23], state->dstarradioheader[24],
|
||
state->dstarradioheader[25], state->dstarradioheader[26]);
|
||
printw ("MY: [%c%c%c%c%c%c%c%c] [%c%c%c%c]\n", state->dstarradioheader[27],
|
||
state->dstarradioheader[28], state->dstarradioheader[29], state->dstarradioheader[30], state->dstarradioheader[31],
|
||
state->dstarradioheader[32], state->dstarradioheader[33], state->dstarradioheader[34], state->dstarradioheader[35],
|
||
state->dstarradioheader[36], state->dstarradioheader[37], state->dstarradioheader[38]);
|
||
}
|
||
}
|
||
|
||
//NXDN
|
||
if (lls == 8 || lls == 9 || lls == 16 || lls == 17)
|
||
{
|
||
printw ("| RAN: [%2d] ", rn);
|
||
printw ("TID: [%4d] ", tgn);
|
||
printw ("RID: [%4d] \n| ALG: [0x%02X] KEY: [0x%02X] ", src, state->nxdn_cipher_type, state->nxdn_key);
|
||
if (state->carrier == 1)
|
||
{
|
||
printw("%s ", state->nxdn_call_type);
|
||
}
|
||
if (state->nxdn_cipher_type == 0x1 && state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw ("Scrambler ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
if (state->R != 0)
|
||
{
|
||
//printw ("\n| ");
|
||
attron(COLOR_PAIR(1));
|
||
printw ("KEY VALUE: [%05lld] ", state->R );
|
||
printw ("SEED: [%04llX]", state->payload_miN);
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
}
|
||
if (state->nxdn_cipher_type == 0x2 && state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw ("DES-OFB ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->nxdn_cipher_type == 0x3 && state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw ("AES-256 ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->nxdn_cipher_type > 0x3 && state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw ("Unknown Encryption ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
printw("\n");
|
||
}
|
||
|
||
//P25-P1
|
||
// if (lls == 0 || lls == 1)
|
||
// {
|
||
// // printw("| TID:[%8i] RID:[%8i] ", tg, rd);
|
||
// printw("| TID:[%8i] RID:[%8i] ", state->lasttg, state->lastsrc);
|
||
// printw(" MFID:[0x%02X] ", state->payload_mfid);
|
||
// printw("NAC: [0x%3X] \n", nc);
|
||
// printw("| ALG:[0x%02X] ", state->payload_algid);
|
||
// printw(" KID:[0x%04X] ", state->payload_keyid);
|
||
// printw(" MI:[0x%016llX] ", state->payload_miP);
|
||
//
|
||
// if (state->payload_algid != 0x80 && state->payload_algid != 0x0 && state->carrier == 1 && state->R == 0)
|
||
// {
|
||
// attron(COLOR_PAIR(2));
|
||
// printw("**ENC**");
|
||
// attroff(COLOR_PAIR(2));
|
||
// attron(COLOR_PAIR(3));
|
||
// if (state->payload_algid == 0xAA)
|
||
// {
|
||
// attron(COLOR_PAIR(1));
|
||
// printw(" RC4");
|
||
// attron(COLOR_PAIR(3));
|
||
// }
|
||
// if (state->payload_algid == 0x81)
|
||
// {
|
||
// attron(COLOR_PAIR(1));
|
||
// printw(" DES-OFB");
|
||
// attron(COLOR_PAIR(3));
|
||
// }
|
||
// }
|
||
// printw("\n");
|
||
// }
|
||
|
||
//DMR BS/MS Voice and Data Types
|
||
if ( lls == 0 || lls == 1 || lls == 12 || lls == 13 || lls == 10 ||
|
||
lls == 11 || lls == 32 || lls == 33 || lls == 34 || lls == 35 || lls == 36)
|
||
{
|
||
printw ("| ");
|
||
if (lls > 1 && lls < 30)
|
||
{
|
||
printw ("DMR BS - DCC: [%02i] ", dcc);
|
||
}
|
||
else if (lls == 32 || lls == 33 || lls == 34)
|
||
{
|
||
printw ("DMR MS - DCC: [%02i] ", dcc);
|
||
}
|
||
else if (lls == 0 || lls == 1) //P1
|
||
{
|
||
printw ("P25 P1 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
||
}
|
||
else if (lls == 35 || lls == 36) //P2
|
||
{
|
||
printw ("P25 P2 - WACN: [%05llX] SYS: [%03llX] NAC: [%03llX] ", state->p2_wacn, state->p2_sysid, state->p2_cc);
|
||
if (state->p2_wacn == 0 || state->p2_sysid == 0 || state->p2_cc == 0)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" Phase 2 Missing Parameters ");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->p2_wacn == 0xFFFFF || state->p2_sysid == 0xFFF || state->p2_cc == 0xFFF)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" Phase 2 Invalid Parameters ");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
}
|
||
|
||
printw ("\n");
|
||
//Slot 1 [0]
|
||
printw ("| SLOT 1 - ");
|
||
if (state->dmrburstL < 16 && state->carrier == 1 && state->lasttg > 0 && state->lastsrc > 0)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
}
|
||
printw ("TGT: [%8i] SRC: [%8i] ", state->lasttg, state->lastsrc);
|
||
if (state->dmrburstL != 16 && state->carrier == 1 && state->lasttg > 0 && state->lastsrc > 0)
|
||
{
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
printw ("FID: [%02X] SVC: [%02X] ", state->dmr_fid, state->dmr_so);
|
||
printw ("%s ", DMRBusrtTypes[state->dmrburstL]);
|
||
printw ("\n");
|
||
//printw ("| | "); //10 spaces
|
||
printw ("| V XTRA | "); //10 spaces
|
||
|
||
if(state->dmrburstL == 16 && state->payload_algid == 0 && (state->dmr_so & 0xCF) == 0x40) //4F or CF mask? & 0xCF currently
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
printw (" **Pr** ");
|
||
attroff(COLOR_PAIR(5));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
if(state->dmrburstL == 16 && state->payload_algid == 0 && state->K > 0 && state->dmr_fid == 0x10 && (state->dmr_so & 0xCF) == 0x40)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("DMRA Pr Key [%3lld] ", state->K);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
if(state->dmrburstL == 16 && state->payload_algid == 0 && state->H > 0 && state->dmr_fid == 0x68 && ((state->dmr_so & 0xCF) == 0x40) )
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("**tera Pr Key [%010llX] ", state->H);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
//ALG, KeyID, MI //was key_id
|
||
if(state->dmrburstL == 16 && state->payload_algid > 0 && (state->dmr_so & 0xCF) == 0x40)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algid, state->payload_keyid, state->payload_mi);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
//P25 FDMA/TDMA
|
||
if(state->dmrburstL > 19 && state->payload_algid > 0 && state->payload_algid != 0x80)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algid, state->payload_keyid, state->payload_miP);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
if (state->payload_algid == 0xAA || state->payload_algid == 0x21)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("ADP-RC4");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algid == 0x81 || state->payload_algid == 0x22)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("DES-OFB");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algid == 0x83 || state->payload_algid == 0x23)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("Triple DES");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algid == 0x85 || state->payload_algid == 0x24)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("AES-128");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algid == 0x84 || state->payload_algid == 0x25)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("AES-256");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algid == 0x02)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("Hytera Full Encrypt");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
if(state->dmrburstL == 16 && state->dmr_so == 0x40 && state->R == 0) //0100 0000
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **ENC** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if(state->dmrburstL == 16 && state->dmr_so == 0x80)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **Emergency** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if(state->dmrburstL == 16 && state->dmr_so == 0x30) //0010 0000
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **Private Call** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
printw ("\n");
|
||
//Alias Blocks and Embedded GPS
|
||
//printw ("| | "); //10 spaces
|
||
printw ("| D XTRA | ");
|
||
if(state->dmrburstL == 16) //only during call
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
for (short i = 0; i < 5; i++)
|
||
{
|
||
printw ("%s", state->dmr_callsign[0][i]);
|
||
}
|
||
//Embedded GPS (not LRRP)
|
||
printw ("%s", state->dmr_callsign[0][5] );
|
||
attroff(COLOR_PAIR(5));
|
||
if (state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
//LRRP
|
||
if(state->dmrburstL != 16) //only during data
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
for (short i = 0; i < 5; i++)
|
||
{
|
||
printw ("%s", state->dmr_lrrp[0][i]);
|
||
}
|
||
attroff(COLOR_PAIR(5));
|
||
if (state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
}
|
||
}
|
||
printw ("\n");
|
||
|
||
//Slot 2 [1]
|
||
if (lls < 30 || lls == 35 || lls == 36){ //Don't print on MS mode
|
||
printw ("| SLOT 2 - ");
|
||
if (state->dmrburstR < 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
}
|
||
printw ("TGT: [%8i] SRC: [%8i] ", state->lasttgR, state->lastsrcR);
|
||
if (state->dmrburstR != 16 && state->carrier == 1 && state->lasttgR > 0 && state->lastsrcR > 0)
|
||
{
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
printw ("FID: [%02X] SVC: [%02X] ", state->dmr_fidR, state->dmr_soR);
|
||
printw ("%s ", DMRBusrtTypes[state->dmrburstR]);
|
||
printw ("\n");
|
||
//printw ("| | "); //12 spaces
|
||
printw ("| V XTRA | "); //10 spaces
|
||
|
||
if(state->dmrburstR == 16 && state->payload_algidR == 0 && (state->dmr_soR & 0xCF) == 0x40) //4F or CF mask?
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
printw (" **Pr** ");
|
||
attroff(COLOR_PAIR(5));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
|
||
if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->K > 0 && ((state->dmr_soR & 0xCF) == 0x40) && state->dmr_fidR == 0x10)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("DMRA Pr Key [%3lld] ", state->K);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if(state->dmrburstR == 16 && state->payload_algidR == 0 && state->H > 0 && ((state->dmr_soR & 0xCF) == 0x40) && state->dmr_fidR == 0x68)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("**tera Pr Key [%010llX] ", state->H);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
//ALG, KeyID, MI 2 //was keyidR
|
||
if(state->dmrburstR == 16 && state->payload_algidR > 0 && (state->dmr_soR & 0xCF) == 0x40)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("ALG: [0x%02X] KEY: [0x%02X] MI: [0x%08X] ", state->payload_algidR, state->payload_keyidR, state->payload_miR);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
//P25-P1 and P2
|
||
if(state->dmrburstR > 19 && state->payload_algidR > 0 && state->payload_algidR != 0x80)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw ("ALG: [0x%02X] KEY: [0x%04X] MI: [0x%016llX] ", state->payload_algidR, state->payload_keyidR, state->payload_miN);
|
||
attroff(COLOR_PAIR(1));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0xAA || state->payload_algidR == 0x21)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("ADP-RC4");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0x81 || state->payload_algidR == 0x22)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("DES-OFB");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0x83 || state->payload_algidR == 0x23)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("Triple DES");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0x85 || state->payload_algidR == 0x24)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("AES-128");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x25)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("AES-256");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if (state->payload_algidR == 0x02)
|
||
{
|
||
attron(COLOR_PAIR(1));
|
||
printw("Hytera Full Encrypt");
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
//Call Types, may switch to the more robust version later?
|
||
if(state->dmrburstR == 16 && state->dmr_soR == 0x40 && state->R == 0) //0100 0000
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **ENC** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if(state->dmrburstR == 16 && state->dmr_soR == 0x80)
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **Emergency** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
if(state->dmrburstR == 16 && state->dmr_soR == 0x30) //0010 0000
|
||
{
|
||
attron(COLOR_PAIR(2));
|
||
printw (" **Private Call** ");
|
||
attroff(COLOR_PAIR(2));
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
printw ("\n");
|
||
//Alias Blocks and Embedded GPS
|
||
//printw ("| | ");
|
||
printw ("| D XTRA | ");
|
||
if(state->dmrburstR == 16) //only during call
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
for (short i = 0; i < 5; i++)
|
||
{
|
||
printw ("%s", state->dmr_callsign[1][i]);
|
||
}
|
||
//Embedded GPS (not LRRP)
|
||
printw ("%s", state->dmr_callsign[1][5] );
|
||
attroff(COLOR_PAIR(5));
|
||
if (state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
}
|
||
//LRRP
|
||
if(state->dmrburstR != 16) //only during data
|
||
{
|
||
attron(COLOR_PAIR(5));
|
||
for (short i = 0; i < 5; i++)
|
||
{
|
||
printw ("%s", state->dmr_lrrp[1][i]);
|
||
}
|
||
attroff(COLOR_PAIR(5));
|
||
if (state->carrier == 1)
|
||
{
|
||
attron(COLOR_PAIR(3));
|
||
}
|
||
}
|
||
printw ("\n");
|
||
} // end if not MS
|
||
} //end DMR BS Types
|
||
|
||
//dPMR
|
||
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)
|
||
{
|
||
printw ("| DCC: [%i] ", state->dpmr_color_code);
|
||
printw ("TID: [%s] RID: [%s] \n", state->dpmr_target_id, state->dpmr_caller_id);
|
||
}
|
||
|
||
if (lls == 6 || lls == 7 || lls == 18 || lls == 19 || lls == 14 || lls == 15)
|
||
{
|
||
printw ("| %s ", SyncTypes[lls]);
|
||
//printw ("%s", state->dmr_branding);
|
||
printw ("\n");
|
||
}
|
||
//fence bottom
|
||
printw ("------------------------------------------------------------------------------\n");
|
||
//colors off
|
||
if (state->carrier == 1){ //same as above
|
||
attroff(COLOR_PAIR(3));
|
||
}
|
||
//only print call history if enabled
|
||
if (opts->ncurses_history == 1)
|
||
{
|
||
attron(COLOR_PAIR(4)); //cyan for history
|
||
printw ("--Call History----------------------------------------------------------------\n");
|
||
for (short int j = 0; j < 10; j++)
|
||
{
|
||
//only print if a valid time was assinged to the matrix
|
||
if ( ((time(NULL) - call_matrix[9-j][5]) < 9999) )
|
||
{
|
||
printw ("| %s ", SyncTypes[call_matrix[9-j][0]]);
|
||
if (lls == 8 || lls == 9 || lls == 16 || lls == 17)
|
||
{
|
||
printw ("RAN [%2lld] ", call_matrix[9-j][1]);
|
||
printw ("TG [%4lld] ", call_matrix[9-j][4]);
|
||
printw ("RID [%4lld] ", call_matrix[9-j][2]);
|
||
}
|
||
//dPMR
|
||
if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27)
|
||
{
|
||
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
|
||
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
||
printw ("DCC [%2lld] ", call_matrix[9-j][4]);
|
||
}
|
||
//P25
|
||
if (call_matrix[9-j][0] == 0 || call_matrix[9-j][0] == 1 || call_matrix[9-j][0] == 35 || call_matrix[9-j][0] == 36)
|
||
{
|
||
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
|
||
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
||
printw ("NAC [0x%03llX] ", call_matrix[9-j][4]);
|
||
}
|
||
//DMR BS Types
|
||
if (call_matrix[9-j][0] == 12 || call_matrix[9-j][0] == 13 || call_matrix[9-j][0] == 10 || call_matrix[9-j][0] == 11 )
|
||
{
|
||
printw ("S[%d] ", call_matrix[9-j][3]);
|
||
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
|
||
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
||
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
|
||
}
|
||
//DMR MS Types
|
||
if (call_matrix[9-j][0] == 32 || call_matrix[9-j][0] == 33 || call_matrix[9-j][0] == 34 )
|
||
{
|
||
//printw ("S[%d] ", call_matrix[9-j][3]);
|
||
printw ("TGT [%8lld] ", call_matrix[9-j][1]);
|
||
printw ("SRC [%8lld] ", call_matrix[9-j][2]);
|
||
printw ("DCC [%02lld] ", call_matrix[9-j][4]);
|
||
}
|
||
printw ("%lld secs ago\n", time(NULL) - call_matrix[9-j][5]);
|
||
}
|
||
} //end Call History
|
||
//fence bottom
|
||
printw ("------------------------------------------------------------------------------\n");
|
||
attroff(COLOR_PAIR(4)); //cyan for history
|
||
}
|
||
|
||
refresh();
|
||
if (c == 27) //esc key
|
||
{
|
||
ncursesMenu (opts, state); //just a quick test
|
||
}
|
||
|
||
} //end ncursesPrinter
|
||
|
||
void ncursesClose ()
|
||
{
|
||
endwin();
|
||
//printf("Press CTRL+C again to close. Thanks.\n");
|
||
//printf("Run 'reset' in your terminal to clean up if necessary.\n");
|
||
}
|