Channel to Frequency Map CSV Importer;
This commit is contained in:
parent
0f227e40c3
commit
66f710e877
|
|
@ -3,4 +3,3 @@
|
|||
*.dylib
|
||||
build
|
||||
*.sh
|
||||
*.csv
|
||||
|
|
@ -50,6 +50,8 @@ sudo make install
|
|||
-----command line switches here subject to change------------------
|
||||
-1 <file> Import LCN Frequencies from csv file (numeral 'one')
|
||||
(See lcn.csv for example)
|
||||
-7 <file> Import Channel to Frequency Map from csv file (numeral 'seven')
|
||||
(See channel_map.csv for example)
|
||||
-2 <file> Import Group List Allow/Block and Label from csv file (numeral 'two')
|
||||
(See group.csv for example)
|
||||
-3 Enable Experimental Trunking Features (P25/EDACS/NXDN-ish for now) with RIGCTL/TCP or RTL Input
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
ChannelNumber(dec),frequency(Hz)
|
||||
1,851375000
|
||||
800,154987500
|
||||
801,451375000
|
||||
|
|
|
@ -364,6 +364,7 @@ typedef struct
|
|||
//csv import filenames
|
||||
char group_in_file[1024];
|
||||
char lcn_in_file[1024];
|
||||
char chan_in_file[1024];
|
||||
//end import filenames
|
||||
|
||||
} dsd_opts;
|
||||
|
|
@ -632,6 +633,7 @@ typedef struct
|
|||
|
||||
//trunking group and lcn freq list
|
||||
long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully
|
||||
long int trunk_chan_map[0xFFFF]; //NXDN - 10 bit; P25 - 16 bit; DMR up to 12 bit (standard TIII)
|
||||
groupinfo group_array[0x3FF]; //max supported by Cygwin is 3FFF, I hope nobody actually tries to import this many groups
|
||||
unsigned int group_tally; //tally number of groups imported from CSV file for referencing later
|
||||
int lcn_freq_count;
|
||||
|
|
@ -830,14 +832,8 @@ void nxdn_deperm_facch2_udch (dsd_opts * opts, dsd_state * state, uint8_t bits[3
|
|||
void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType);
|
||||
void nxdn_voice (dsd_opts * opts, dsd_state * state, int voice, uint8_t dbuf[182]);
|
||||
|
||||
//utility functions from OP25 needed by NXDN frame handler
|
||||
//OP25 NXDN CRC functions
|
||||
static inline int load_i(const uint8_t val[], int len);
|
||||
static inline void cfill(uint8_t result[], const uint8_t src[], int len);
|
||||
|
||||
static inline void trellis_encode(uint8_t result[], const uint8_t source[], int result_len, int reg);
|
||||
static inline void trellis_decode(uint8_t result[], const uint8_t source[], int result_len);
|
||||
|
||||
//OP25 CRC functions
|
||||
static uint8_t crc6(const uint8_t buf[], int len);
|
||||
static uint16_t crc12f(const uint8_t buf[], int len);
|
||||
static uint16_t crc15(const uint8_t buf[], int len);
|
||||
|
|
@ -969,7 +965,7 @@ void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156]
|
|||
long int process_channel_to_freq (dsd_opts * opts, dsd_state * state, int channel);
|
||||
|
||||
//NXDN Channel to Frequency, Courtesy of IcomIcR20 on RR Forums
|
||||
long int nxdn_channel_to_frequency (dsd_opts * opts, uint16_t channel);
|
||||
long int nxdn_channel_to_frequency (dsd_opts * opts, dsd_state * state, uint16_t channel);
|
||||
|
||||
//rigctl functions and TCP/UDP functions
|
||||
void error(char *msg);
|
||||
|
|
@ -1000,6 +996,7 @@ unsigned long long int edacs_bch (unsigned long long int message);
|
|||
//csv imports
|
||||
int csvGroupImport(dsd_opts * opts, dsd_state * state);
|
||||
int csvLCNImport(dsd_opts * opts, dsd_state * state);
|
||||
int csvChanImport(dsd_opts * opts, dsd_state * state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ int csvGroupImport(dsd_opts * opts, dsd_state * state)
|
|||
FILE * fp;
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Unable to open file '%s'\n", filename);
|
||||
printf("Unable to open group file '%s'\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
int row_count = 0;
|
||||
|
|
@ -64,7 +64,7 @@ int csvLCNImport(dsd_opts * opts, dsd_state * state) //LCN/LSN import for EDACS/
|
|||
FILE * fp;
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Unable to open file '%s'\n", filename);
|
||||
printf("Unable to open lcn file '%s'\n", filename);
|
||||
//have this return -1 and handle it inside of main
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -94,3 +94,50 @@ int csvLCNImport(dsd_opts * opts, dsd_state * state) //LCN/LSN import for EDACS/
|
|||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int csvChanImport(dsd_opts * opts, dsd_state * state) //channel map import
|
||||
{
|
||||
char filename[1024] = "filename.csv";
|
||||
sprintf (filename, "%s", opts->chan_in_file);
|
||||
|
||||
char buffer[BSIZE];
|
||||
FILE * fp;
|
||||
fp = fopen(filename, "r");
|
||||
if (fp == NULL) {
|
||||
printf("Unable to open channel map file '%s'\n", filename);
|
||||
//have this return -1 and handle it inside of main
|
||||
exit(1);
|
||||
}
|
||||
int row_count = 0;
|
||||
int field_count = 0;
|
||||
|
||||
long int chan_number;
|
||||
|
||||
while (fgets(buffer, BSIZE, fp)) {
|
||||
field_count = 0;
|
||||
row_count++;
|
||||
if (row_count == 1)
|
||||
continue; //don't want labels
|
||||
char * field = strtok(buffer, ","); //seperate by comma
|
||||
while (field) {
|
||||
|
||||
if (field_count == 0)
|
||||
{
|
||||
sscanf (field, "%ld", &chan_number);
|
||||
}
|
||||
|
||||
if (field_count == 1)
|
||||
{
|
||||
sscanf (field, "%ld", &state->trunk_chan_map[chan_number]);
|
||||
}
|
||||
|
||||
field = strtok(NULL, ",");
|
||||
field_count++;
|
||||
}
|
||||
fprintf (stderr, "Channel [%05ld] [%09ld]", chan_number, state->trunk_chan_map[chan_number]);
|
||||
fprintf (stderr, "\n");
|
||||
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -307,6 +307,11 @@ initOpts (dsd_opts * opts)
|
|||
opts->wav_out_file_raw[0] = 0;
|
||||
opts->symbol_out_file[0] = 0;
|
||||
opts->lrrp_out_file[0] = 0;
|
||||
//csv import filenames
|
||||
opts->group_in_file[0] = 0;
|
||||
opts->lcn_in_file[0] = 0;
|
||||
opts->chan_in_file[0] = 0;
|
||||
//end import filenames
|
||||
opts->szNumbers[0] = 0;
|
||||
opts->symbol_out_f = NULL;
|
||||
opts->symbol_out = 0;
|
||||
|
|
@ -699,6 +704,7 @@ initState (dsd_state * state)
|
|||
|
||||
//trunking
|
||||
memset (state->trunk_lcn_freq, 0, sizeof(state->trunk_lcn_freq));
|
||||
memset (state->trunk_chan_map, 0, sizeof(state->trunk_chan_map));
|
||||
state->group_tally = 0;
|
||||
state->lcn_freq_count = 0; //number of frequncies imported from LCN
|
||||
state->lcn_freq_roll = 0; //needs reset if sync is found?
|
||||
|
|
@ -850,6 +856,8 @@ usage ()
|
|||
printf (" Experimental Functions and Features---------------------------------------------------\n");
|
||||
printf (" -1 <file> Import LCN Frequencies from csv file (numeral 'one') \n");
|
||||
printf (" (See lcn.csv for example)\n");
|
||||
printf (" -7 <file> Import Channel to Frequency Map from csv file (numeral 'seven') \n");
|
||||
printf (" (See channel_map.csv for example)\n");
|
||||
printf (" -2 <file> Import Group List Allow/Block and Label from csv file (numeral 'two')\n");
|
||||
printf (" (See group.csv for example)\n");
|
||||
printf (" -3 Enable Extremely Experimental Trunking Features (NXDN/P25/EDACS for now) with RIGCTL/TCP or RTL Input\n");
|
||||
|
|
@ -1086,7 +1094,7 @@ main (int argc, char **argv)
|
|||
exitflag = 0;
|
||||
signal (SIGINT, sigfun);
|
||||
|
||||
while ((c = getopt (argc, argv, "haep:P:qs:tv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:H:X:NQWrlZTF1:2:345:6:")) != -1)
|
||||
while ((c = getopt (argc, argv, "haep:P:qs:tv:z:i:o:d:c:g:nw:B:C:R:f:m:u:x:A:S:M:G:D:L:V:U:Y:K:H:X:NQWrlZTF1:2:345:6:7:")) != -1)
|
||||
{
|
||||
opterr = 0;
|
||||
switch (c)
|
||||
|
|
@ -1100,13 +1108,19 @@ main (int argc, char **argv)
|
|||
opts.call_alert = 1;
|
||||
break;
|
||||
//placeholder until letters get re-arranged (or opt_long switched in)
|
||||
case '1': //LCN/Frequency CSV
|
||||
case '1': //LCN to Frequency CSV Import
|
||||
strncpy(opts.lcn_in_file, optarg, 1023);
|
||||
opts.lcn_in_file[1023] = '\0';
|
||||
csvLCNImport (&opts, &state);
|
||||
break;
|
||||
//placeholder until letters get re-arranged
|
||||
case '2': //Group Label CSV
|
||||
case '7': //Channel Map Frequency CSV Import
|
||||
strncpy(opts.chan_in_file, optarg, 1023);
|
||||
opts.chan_in_file[1023] = '\0';
|
||||
csvChanImport (&opts, &state);
|
||||
break;
|
||||
//placeholder until letters get re-arranged
|
||||
case '2': //Group CSV Import
|
||||
strncpy(opts.group_in_file, optarg, 1023);
|
||||
opts.group_in_file[1023] = '\0';
|
||||
csvGroupImport(&opts, &state);
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
|||
|
||||
//run process to figure out frequency value from the channel, or from lcn import array
|
||||
long int freq = 0;
|
||||
freq = nxdn_channel_to_frequency(opts, Channel);
|
||||
freq = nxdn_channel_to_frequency(opts, state, Channel);
|
||||
|
||||
//run group/source analysis and tune if available/desired
|
||||
//group list mode so we can look and see if we need to block tuning any groups, etc
|
||||
|
|
@ -373,8 +373,8 @@ void NXDN_decode_cch_info(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
|||
else if (channel1sts & 0x10) fprintf (stderr, "New ");
|
||||
else if (channel1sts & 0x8) fprintf (stderr, "Candidate Added ");
|
||||
else if (channel1sts & 0x4) fprintf (stderr, "Candidate Deleted ");
|
||||
freq1 = nxdn_channel_to_frequency (opts, channel1);
|
||||
freq2 = nxdn_channel_to_frequency (opts, channel2);
|
||||
freq1 = nxdn_channel_to_frequency (opts, state, channel1);
|
||||
freq2 = nxdn_channel_to_frequency (opts, state, channel2);
|
||||
|
||||
//add handling for adding (or deleting?) frequencies to CC list
|
||||
if (channel1sts & 0x20 || channel1sts & 0x8) //current or new only
|
||||
|
|
@ -497,12 +497,12 @@ void NXDN_decode_site_info(dsd_opts * opts, dsd_state * state, uint8_t * Message
|
|||
if (channel1 != 0)
|
||||
{
|
||||
fprintf (stderr, "\n Control Channel 1 [%03X][%04d] ", channel1, channel1 );
|
||||
freq1 = nxdn_channel_to_frequency (opts, channel1);
|
||||
freq1 = nxdn_channel_to_frequency (opts, state, channel1);
|
||||
}
|
||||
if (channel2 != 0)
|
||||
{
|
||||
fprintf (stderr, "\n Control Channel 2 [%03X][%04d] ", channel2, channel2 );
|
||||
freq2 = nxdn_channel_to_frequency (opts, channel2);
|
||||
freq2 = nxdn_channel_to_frequency (opts, state, channel2);
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
|
|
|||
|
|
@ -31,23 +31,36 @@ long int process_channel_to_freq (dsd_opts * opts, dsd_state * state, int channe
|
|||
int type = state->p25_chan_type[iden];
|
||||
int slots_per_carrier[16] = {1,1,1,2,4,2,2,2,2,2,2,2,2,2,2,2}; //from OP25
|
||||
int step = (channel & 0xFFF) / slots_per_carrier[type];
|
||||
|
||||
if (state->p25_base_freq[iden] != 0)
|
||||
|
||||
//first, check channel map
|
||||
if (state->trunk_chan_map[channel] != 0)
|
||||
{
|
||||
freq = (state->p25_base_freq[iden] * 5) + ( step * state->p25_chan_spac[iden] * 125);
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
freq = state->trunk_chan_map[channel];
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "\n Base Frequency Not Found - Iden [%d]", iden);
|
||||
return (0);
|
||||
}
|
||||
|
||||
//if not found, attempt to find it via calculation
|
||||
else
|
||||
{
|
||||
if (state->p25_base_freq[iden] != 0)
|
||||
{
|
||||
freq = (state->p25_base_freq[iden] * 5) + ( step * state->p25_chan_spac[iden] * 125);
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "\n Base Frequency Not Found - Iden [%d]", iden);
|
||||
fprintf(stderr, "\n or Channel not found in import file");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//NXDN Channel to Frequency, Courtesy of IcomIcR20 on RR Forums
|
||||
long int nxdn_channel_to_frequency(dsd_opts * opts, uint16_t channel)
|
||||
long int nxdn_channel_to_frequency(dsd_opts * opts, dsd_state * state, uint16_t channel)
|
||||
{
|
||||
long int freq;
|
||||
long int base = 0;
|
||||
|
|
@ -55,33 +68,41 @@ long int nxdn_channel_to_frequency(dsd_opts * opts, uint16_t channel)
|
|||
//the base freq value is per EricCottrell in the Understanding NXDN Trunking Forum Thread
|
||||
//will need to do some research or tests to confirm these values are accurate
|
||||
|
||||
if ((channel > 0) && (channel <= 400))
|
||||
//first, check channel map
|
||||
if (state->trunk_chan_map[channel] != 0)
|
||||
{
|
||||
if (opts->frame_nxdn48 == 1) base = 450000000;
|
||||
else base = 451000000;
|
||||
|
||||
freq = base + (channel - 1) * 12500;
|
||||
freq = state->trunk_chan_map[channel];
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else if ((channel >= 401) && (channel <= 800))
|
||||
{
|
||||
if (opts->frame_nxdn48 == 1) base = 460000000;
|
||||
else base = 461000000;
|
||||
|
||||
freq = base + (channel - 401) * 12500;
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else if (channel > 800)
|
||||
{
|
||||
//write function to check the LCN import array for custom frequency values!
|
||||
//return (freq);
|
||||
}
|
||||
//if not found, attempt to find it via calculation
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\n This LCN is used for a non-standard frequency. No frequency can be reported");
|
||||
return (0);
|
||||
if ((channel > 0) && (channel <= 400))
|
||||
{
|
||||
if (opts->frame_nxdn48 == 1) base = 450000000;
|
||||
else base = 451000000;
|
||||
|
||||
freq = base + (channel - 1) * 12500;
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else if ((channel >= 401) && (channel <= 800))
|
||||
{
|
||||
if (opts->frame_nxdn48 == 1) base = 460000000;
|
||||
else base = 461000000;
|
||||
|
||||
freq = base + (channel - 401) * 12500;
|
||||
fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
return (freq);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "\n Non-standard frequency or channel not found in import file");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue