mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 09:17:20 -05:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d522e25c4 | ||
|
|
b1013c15ad | ||
|
|
23d8d0cc77 | ||
|
|
6e60a4e7d1 | ||
|
|
48a3d55231 | ||
|
|
aef12ff74d | ||
|
|
2353601719 | ||
|
|
668f70c1ba | ||
|
|
ec292ae738 | ||
|
|
9e56356e27 | ||
|
|
3d2a68b4bb | ||
|
|
443c53e2ba | ||
|
|
6153f7bc4c | ||
|
|
4bbae54542 | ||
|
|
6e7f2962f0 | ||
|
|
d917f85926 | ||
|
|
76d2866498 | ||
|
|
2e098d52bc |
@@ -134,14 +134,16 @@ Trunking Note1: All samples above can also be run with the RTL input method and
|
||||
|
||||
Trunking Note2: QPSK Phase 1 and Phase 2 Systems may be subceptible to LSM distortion issues, but seem to do okay, but require really good signal. Some CRC issues still occur with Phase 2 TDMA LCCH Mac Signal that can affect reliability, I believe this issue is ultimately caused by the PSK demodulation inside of FME. I also don't believe this will work on 8-level PSK, but I cannot determine that at the moment. Update: I have improved the LCCH Mac Signal decoding my increasing the QPSK decision point buffers to their maximum values.
|
||||
|
||||
Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have been carried out. Cap+, Con+, and TIII systems seem to do well with trunking now. Placing the frequency for the control channel at channel map 0 in your channel_map.csv file is not required now if using RIGCTL or the RTL Input, both can poll the VFO for the current frequency if it believes its on a control channel, but setting a fake channel number (i.e. 999) first with the CC frequency will result in finding the CC faster on startup if desired. If you need to map out your channels for TIII, you can observe the console output and look for channel numbers. For conveniece I have included the DSDPlus channel numbering (as best as I can figure it, but they seem consistent) into the console print so it will make it easier for users from DSDPlus to map frequencies into the channel_map.csv file. Make sure your channel numbers are the Cd (channel decimal) values from the log, and not the C+ (dsdplus) values. Notice: TIII Site ID value needs work to determine proper DMRLA values for system area and sub area.
|
||||
Trunking Note3: DMR Trunking has been coded, and some testing and tweaks have been carried out. Cap+, Con+, and TIII systems seem to do well with trunking now. Placing the frequency for the control channel at channel map 0 in your channel_map.csv file is not required now if using RIGCTL or the RTL Input, both can poll the VFO for the current frequency if it believes its on a control channel, but setting a fake channel number (i.e. 999) first with the CC frequency will result in finding the CC faster on startup if desired. If you need to map out your channels for TIII, you can observe the console output and look for channel numbers. For conveniece I have included the DSDPlus style LSN-esque numbering into the console print so it will make it easier for users from DSDPlus to map frequencies into the channel_map.csv file. Make sure your channel numbers are the lpcn (12-bit logical physical channel number - decimal format) values from the log, and not the LPCN+TS (13-bit DSDPlus LSN) values. Notice: TIII Site ID value needs work to determine proper DMRLA values for system area and sub area.
|
||||
|
||||
```
|
||||
00:43:00 Sync: +DMR [slot1] slot2 | Color Code=00 | CSBK
|
||||
Talkgroup Voice Channel Grant (TV_GRANT) - Logical
|
||||
Ch [036] Cd [0054] C+ [0110] - TS [1] - Target [01900500] - Source [01900505]
|
||||
LPCN: 0075; TS: 2; LPCN+TS: 0152; Target: 16518173 - Source: 16533625
|
||||
|
||||
```
|
||||
|
||||
Use channel 54 in your import file, which would correspond to dsdplus channels 109 and 110 (109 = TS0 / 110 = TS1).
|
||||
Use channel 75 in your import file, which would correspond to dsdplus channels 151 and 152 (151 = TS1 / 152 = TS2).
|
||||
|
||||
For Connect Plus, enumerate your list from 1 to the last channel and add the frequency. For Capacity Plus, LSN 1 and 2 will share the same frequency, 3 and 4 will share, 5 and 6 will share, and 7-8 will share, as Capacity Plus counts each 'channel' as two seperate channels (LSN), one for each time slot. Capacity Plus Quirk: DSD-FME makes its best effort to follow the rest channel in the event that the sync is lost for longer than the hangtime, but occassionally, DSD-FME may lose the rest channel and will have to hunt through all frequencies to find it again.
|
||||
|
||||
|
||||
@@ -656,6 +656,7 @@ typedef struct
|
||||
int dmr_vc_lcn;
|
||||
int dmr_vc_lsn;
|
||||
int dmr_tuned_lcn;
|
||||
uint16_t dmr_cc_lpcn; //dmr t3 logical physical channel number
|
||||
|
||||
//edacs
|
||||
int ea_mode;
|
||||
@@ -824,6 +825,10 @@ typedef struct
|
||||
#define INV_PROVOICE_EA_SYNC "13313133113113333311313133133311"
|
||||
#define PROVOICE_EA_SYNC "31131311331331111133131311311133"
|
||||
|
||||
//EDACS/PV EOT dotting sequence
|
||||
#define DOTTING_SEQUENCE_A "131313131313131313131313131313131313131313131313" //0xAAAA...
|
||||
#define DOTTING_SEQUENCE_B "313131313131313131313131313131313131313131313131" //0x5555...
|
||||
|
||||
//define the provoice conventional string pattern to default 85/85 if not enabled, else mute it so we won't double sync on accident in frame_sync
|
||||
#ifdef PVCONVENTIONAL
|
||||
#define PROVOICE_CONV "00000000000000000000000000000000" //all zeroes should be unobtainable string in the frame_sync synctests
|
||||
@@ -832,7 +837,7 @@ typedef struct
|
||||
#define PROVOICE_CONV "13131333111311311313131313131313" //TX 85 RX 85 (default programming value)
|
||||
#define INV_PROVOICE_CONV "31313111333133133131313131313131" //TX 85 RX 85 (default programming value)
|
||||
#endif
|
||||
//we use the short sync instead of the default 85/85 wnen PVCONVENTIONAL is defined by cmake
|
||||
//we use the short sync instead of the default 85/85 when PVCONVENTIONAL is defined by cmake
|
||||
#define PROVOICE_CONV_SHORT "1313133311131131" //16-bit short pattern, last 16-bits change based on TX an RX values
|
||||
#define INV_PROVOICE_CONV_SHORT "3131311133313313"
|
||||
//In this pattern (inverted polarity, the norm for PV) 3 is bit 0, and 1 is bit 1 (2 level GFSK)
|
||||
@@ -878,6 +883,7 @@ void openAudioInDevice (dsd_opts * opts);
|
||||
|
||||
int getDibit (dsd_opts * opts, dsd_state * state);
|
||||
int get_dibit_and_analog_signal (dsd_opts * opts, dsd_state * state, int * out_analog_signal);
|
||||
int digitize (dsd_opts* opts, dsd_state* state, int symbol);
|
||||
|
||||
void skipDibit (dsd_opts * opts, dsd_state * state, int count);
|
||||
void saveImbe4400Data (dsd_opts * opts, dsd_state * state, char *imbe_d);
|
||||
@@ -1043,6 +1049,7 @@ void dmr_slco (dsd_opts * opts, dsd_state * state, uint8_t slco_bits[]);
|
||||
uint8_t dmr_cach (dsd_opts * opts, dsd_state * state, uint8_t cach_bits[25]);
|
||||
uint32_t dmr_34(uint8_t * input, uint8_t treturn[18]); //simplier trellis decoder
|
||||
void beeper (dsd_opts * opts, dsd_state * state, int type); //the tone beeper function
|
||||
void dmr_gateway_identifier (uint32_t source, uint32_t target); //translate special addresses
|
||||
|
||||
//Embedded Alias and GPS
|
||||
void dmr_embedded_alias_header (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[]);
|
||||
@@ -1167,7 +1174,8 @@ int UDPBind (char *hostname, int portno);
|
||||
|
||||
//EDACS
|
||||
void edacs(dsd_opts * opts, dsd_state * state);
|
||||
unsigned long long int edacs_bch (unsigned long long int message);
|
||||
unsigned long long int edacs_bch (unsigned long long int message);
|
||||
void eot_cc(dsd_opts * opts, dsd_state * state); //end of TX return to CC
|
||||
|
||||
//csv imports
|
||||
int csvGroupImport(dsd_opts * opts, dsd_state * state);
|
||||
|
||||
176
src/dmr_csbk.c
176
src/dmr_csbk.c
@@ -64,7 +64,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
fprintf (stderr, "%s", KYEL);
|
||||
|
||||
//7.1.1.1.1 Channel Grant CSBK/MBC PDU
|
||||
if (csbk_o > 47 && csbk_o < 55 )
|
||||
if (csbk_o >= 48 && csbk_o <= 56 )
|
||||
{
|
||||
|
||||
//maintain this to allow users to hardset the cc freq as map[0]; otherwise, set from rigctl or rtl freq at c_aloha_sys_parms
|
||||
@@ -83,6 +83,8 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
if (csbk_o == 52) fprintf (stderr, " Talkgroup Data Channel Grant: Single Item (TD_GRANT)");
|
||||
if (csbk_o == 53) fprintf (stderr, " Duplex Private Voice Channel Grant (PV_GRANT_DX)");
|
||||
if (csbk_o == 54) fprintf (stderr, " Duplex Private Data Channel Grant (PD_GRANT_DX)");
|
||||
if (csbk_o == 55) fprintf (stderr, " Private Data Channel Grant: Multi Item (PD_GRANT)");
|
||||
if (csbk_o == 56) fprintf (stderr, " Talkgroup Data Channel Grant: Multi Item (TD_GRANT)");
|
||||
|
||||
//Logical Physical Channel Number
|
||||
uint16_t lpchannum = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 12);
|
||||
@@ -104,6 +106,14 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
uint32_t target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
|
||||
uint32_t source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24);
|
||||
|
||||
//broadcast calls show no tgt/src info in ETSI manaual, but seem to correspond with same values in embedded link control
|
||||
// if (csbk_o == 50)
|
||||
// {
|
||||
// //seeting to all MS units and Dispatch? May need to just set to 0 and see what emb pulls out of it
|
||||
// target = 0xFFFFFF; //ALLMSI
|
||||
// source = 0xFFFECB; //DISPATI
|
||||
// }
|
||||
|
||||
//move mbc variables out of if statement
|
||||
uint8_t mbc_lb = 0; //
|
||||
uint8_t mbc_pf = 0;
|
||||
@@ -120,10 +130,14 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
uint16_t mbc_abs_rx_step = 0;
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
//added my best guess as to how dsdplus arrives at a dmr channel value (seems pretty consistent) as C+
|
||||
fprintf (stderr, " Ch [%03X] Cd [%04d] C+ [%04d] - TS [%d] - Target [%08d] - Source [%08d]", lpchannum, lpchannum, pluschannum, lcn, target, source);
|
||||
//rewrote this to make it clear which is the lpcn, timeslot (lcn), and the combination of both (DSDPlus style combined LSN) on channel numbering
|
||||
//the TS is displayed as a +1 since while the bit values are 0 or 1, the slot numbering in the manual specifically states TDMA channel (slot) 1 or TDMA channel (slot) 2
|
||||
fprintf (stderr, " LPCN: %04d; TS: %d; LPCN+TS: %04d; Target: %08d - Source: %08d ", lpchannum, lcn+1, pluschannum, target, source);
|
||||
|
||||
if (st2) fprintf (stderr, " Emergency");
|
||||
if (st2) fprintf (stderr, "Emergency; ");
|
||||
|
||||
//check for special gateway identifiers (probably just on broadcast?)
|
||||
dmr_gateway_identifier (source, target);
|
||||
|
||||
if (lpchannum == 0xFFF) //This is from an MBC, signalling an absolute and not a logical
|
||||
{
|
||||
@@ -149,7 +163,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
//tx_int (Mhz) + (tx_step * 125) = tx_freq
|
||||
//rx_int (Mhz) + (rx_step * 125) = rx_freq
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " ABS-CHAN [%03X][%04d] - RX INT [%d][%X] - RX STEP [%d][%X]", mbc_lpchannum, mbc_lpchannum, mbc_abs_rx_int, mbc_abs_rx_int, mbc_abs_rx_step, mbc_abs_rx_step );
|
||||
fprintf (stderr, " RX ABS LPCN: %04d; RX INT: %d; RX STEP: %d;", mbc_lpchannum, mbc_abs_rx_int, mbc_abs_rx_step );
|
||||
//The Frequency we want to tune is the RX Frequency
|
||||
freq = (mbc_abs_rx_int * 1000000 ) + (mbc_abs_rx_step * 125);
|
||||
}
|
||||
@@ -157,13 +171,16 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
}
|
||||
|
||||
//print frequency from absolute
|
||||
if (freq != 0 && lpchannum == 0xFFF) fprintf (stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
if (freq != 0 && lpchannum == 0xFFF)
|
||||
fprintf (stderr, "\n Frequency: %.6lf MHz", (double)freq/1000000);
|
||||
|
||||
//run external channel map function on logical
|
||||
if (lpchannum != 0 && lpchannum != 0xFFF)
|
||||
{
|
||||
freq = state->trunk_chan_map[lpchannum];
|
||||
(stderr, "\n Frequency [%.6lf] MHz", (double)freq/1000000);
|
||||
if (freq != 0)
|
||||
fprintf (stderr, "\n Frequency: %.6lf MHz", (double)freq/1000000);
|
||||
else fprintf (stderr, "\n Frequency Not Found in Channel Map;");
|
||||
}
|
||||
|
||||
//add active channel string to display
|
||||
@@ -188,7 +205,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
if (csbk_o == 50) csbk_o = 49; //flip to normal group call for group tuning
|
||||
|
||||
//Allow tuning of data calls if user wishes by flipping the csbk_o to a group voice call
|
||||
if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54)
|
||||
if (csbk_o == 51 || csbk_o == 52 || csbk_o == 54 || csbk_o == 55 || csbk_o == 56)
|
||||
{
|
||||
if (opts->trunk_tune_data_calls == 1) csbk_o = 49;
|
||||
}
|
||||
@@ -221,6 +238,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
if ( (time(NULL) - state->last_vc_sync_time > 2) )
|
||||
{
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -232,6 +250,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,6 +261,18 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
//RIGCTL
|
||||
if (opts->use_rigctl == 1)
|
||||
{
|
||||
//we will want to set these values here, some Tier 3 systems prefer P_Protects (Tait) over VLC and TLC headers
|
||||
//and is faster than waiting on good embedded link control
|
||||
if (lcn == 0)
|
||||
{
|
||||
state->lasttg = target;
|
||||
state->lastsrc = source;
|
||||
}
|
||||
if (lcn == 1)
|
||||
{
|
||||
state->lasttgR = target;
|
||||
state->lastsrcR = source;
|
||||
}
|
||||
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
|
||||
SetFreq(opts->rigctl_sockfd, freq);
|
||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||
@@ -253,6 +284,18 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
else if (opts->audio_in_type == 3)
|
||||
{
|
||||
#ifdef USE_RTLSDR
|
||||
//we will want to set these values here, some Tier 3 systems prefer P_Protects (Tait) over VLC and TLC headers
|
||||
//and is faster than waiting on good embedded link control
|
||||
if (lcn == 0)
|
||||
{
|
||||
state->lasttg = target;
|
||||
state->lastsrc = source;
|
||||
}
|
||||
if (lcn == 1)
|
||||
{
|
||||
state->lasttgR = target;
|
||||
state->lastsrcR = source;
|
||||
}
|
||||
rtl_dev_tune (opts, freq);
|
||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||
opts->p25_is_tuned = 1;
|
||||
@@ -437,7 +480,10 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
if (p_kind == 3) fprintf (stderr, " Enable Target MS PTT (EN_PTT_ONE_MS)");
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " Target [%08d] - Source [%08d]", target, source);
|
||||
fprintf (stderr, " Source: %08d; Target: %08d; ", source, target);
|
||||
|
||||
//check the source and/or target for special gateway identifiers
|
||||
dmr_gateway_identifier (source, target);
|
||||
|
||||
}
|
||||
|
||||
@@ -568,21 +614,82 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
{
|
||||
//initial line break
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " C_AHOY ");
|
||||
fprintf (stderr, " C_AHOY - ");
|
||||
//C_AHOY is always a single block CSBK, no need to check or deal with continuation blocks
|
||||
uint16_t svc_opt = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 7);
|
||||
uint8_t svc_flag = cs_pdu_bits[23]; //service kind flag
|
||||
uint8_t als_flag = cs_pdu_bits[24]; //ambient listening service requested
|
||||
uint8_t ahoy_gi = cs_pdu_bits[25]; //group or individual
|
||||
uint8_t ahoy_bf = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[26], 2); //UDT blocks to follow (if required)
|
||||
uint8_t svc_kind = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[28], 4); //'Call' Type
|
||||
uint32_t ahoy_target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24);
|
||||
uint32_t ahoy_source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24);
|
||||
|
||||
|
||||
if (ahoy_gi == 0) fprintf (stderr, "Private ");
|
||||
else fprintf (stderr, "Group ");
|
||||
|
||||
//need to put SVC OPT decoding in here, maybe just copy and paste from FLC?
|
||||
|
||||
fprintf (stderr, "FID: %02X SVC: %02X ", csbk_fid, svc_opt);
|
||||
if (svc_kind == 0 || svc_kind == 1) fprintf (stderr, "Voice Call ");
|
||||
else if (svc_kind == 2 || svc_kind == 3) fprintf (stderr, "Packet Data Call ");
|
||||
else if (svc_kind == 4 || svc_kind == 5) fprintf (stderr, "UDT Short Data Call ");
|
||||
else if (svc_kind == 6) fprintf (stderr, "UDT Short Data Polling Service ");
|
||||
else if (svc_kind == 7) fprintf (stderr, "Status Transport Service ");
|
||||
else if (svc_kind == 8) fprintf (stderr, "Call Diversion Service ");
|
||||
else if (svc_kind == 9) fprintf (stderr, "Call Answer Service ");
|
||||
else if (svc_kind == 10) fprintf (stderr, "Full Duplex Voice Call ");
|
||||
else if (svc_kind == 11) fprintf (stderr, "Full Duplex Packet Data Call ");
|
||||
else if (svc_kind == 12) fprintf (stderr, "Reserved ");
|
||||
else if (svc_kind == 13) fprintf (stderr, "Supplimentary Service (Stun/Revive/Kill/Auth): ");
|
||||
else if (svc_kind == 14) fprintf (stderr, "Registration/Authentication ");
|
||||
else if (svc_kind == 15) fprintf (stderr, "Cancel Call Service ");
|
||||
|
||||
fprintf (stderr, "Target: %d; Source: %d; ", ahoy_target, ahoy_source);
|
||||
|
||||
//check the source and/or target for special gateway identifiers
|
||||
dmr_gateway_identifier (ahoy_source, ahoy_target);
|
||||
|
||||
}
|
||||
|
||||
if (csbk_o == 42)
|
||||
{
|
||||
//initial line break
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " P_MAINT ");
|
||||
fprintf (stderr, " P_MAINT -");
|
||||
|
||||
//I can't recall ever seeing a p_maint use, always see a p_clear though
|
||||
uint16_t pm_res1 = (uint16_t)ConvertBitIntoBytes(&cs_pdu_bits[16], 12);
|
||||
uint8_t pm_kind = (uint8_t)ConvertBitIntoBytes(&cs_pdu_bits[28], 3);
|
||||
uint8_t pm_res2 = cs_pdu_bits[31];
|
||||
uint32_t pm_target = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[32], 24); //should be TSI (clear the call)
|
||||
uint32_t pm_source = (uint32_t)ConvertBitIntoBytes(&cs_pdu_bits[56], 24);
|
||||
|
||||
if (pm_kind == 0) fprintf (stderr, "Disconnect; ");
|
||||
else fprintf (stderr, " Res Kind: %02X", pm_kind);
|
||||
|
||||
if (pm_res1) fprintf (stderr, "Res A: %03X", pm_res1);
|
||||
if (pm_res2) fprintf (stderr, "Res B: 1");
|
||||
|
||||
fprintf (stderr, "Target: %d; Source: %d; ", pm_target, pm_source);
|
||||
|
||||
//check the source and/or target for special gateway identifiers
|
||||
dmr_gateway_identifier (pm_source, pm_target);
|
||||
}
|
||||
|
||||
if (csbk_o == 30)
|
||||
{
|
||||
//initial line break
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " C_ACKVIT ");
|
||||
fprintf (stderr, " C_ACKVIT (Ackvitation/Authorization) ");
|
||||
}
|
||||
|
||||
if (csbk_o == 33)
|
||||
{
|
||||
//initial line break
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " C_ACKD (Acknowledgement)");
|
||||
}
|
||||
|
||||
if (csbk_o == 31)
|
||||
@@ -1027,6 +1134,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
for (j = start; j < end; j++) //go through the channels stored looking for active ones to tune to
|
||||
{
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -1038,6 +1146,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1171,6 +1280,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
}
|
||||
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -1182,6 +1292,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1366,6 +1477,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
for (j = 0; j < 6; j++) //go through the channels stored looking for active ones to tune to
|
||||
{
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -1380,6 +1492,7 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1485,4 +1598,43 @@ void dmr_cspdu (dsd_opts * opts, dsd_state * state, uint8_t cs_pdu_bits[], uint8
|
||||
END:
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
|
||||
}
|
||||
|
||||
//translate special gateway identifier addresses
|
||||
void dmr_gateway_identifier (uint32_t source, uint32_t target)
|
||||
{
|
||||
int i;
|
||||
uint32_t id;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
if (i == 0) id = source;
|
||||
else id = target;
|
||||
if (id == 0xFFFEC0) fprintf (stderr, "PSTNI; ");
|
||||
if (id == 0xFFFEC1) fprintf (stderr, "PABXI; ");
|
||||
if (id == 0xFFFEC2) fprintf (stderr, "LINEI; ");
|
||||
if (id == 0xFFFEC3) fprintf (stderr, "IPI; ");
|
||||
if (id == 0xFFFEC4) fprintf (stderr, "SUPLI; ");
|
||||
if (id == 0xFFFEC5) fprintf (stderr, "SDMI; ");
|
||||
if (id == 0xFFFEC6) fprintf (stderr, "REGI; ");
|
||||
if (id == 0xFFFEC7) fprintf (stderr, "MSI; ");
|
||||
if (id == 0xFFFEC8) fprintf (stderr, "RESERVED; ");
|
||||
if (id == 0xFFFEC9) fprintf (stderr, "DIVERTI; ");
|
||||
if (id == 0xFFFECA) fprintf (stderr, "TSI; ");
|
||||
if (id == 0xFFFECB) fprintf (stderr, "DISPATI; ");
|
||||
if (id == 0xFFFECC) fprintf (stderr, "STUNI; ");
|
||||
if (id == 0xFFFECD) fprintf (stderr, "AUTHI; ");
|
||||
if (id == 0xFFFECE) fprintf (stderr, "GPI; ");
|
||||
if (id == 0xFFFECF) fprintf (stderr, "KILLI; ");
|
||||
if (id == 0xFFFED0) fprintf (stderr, "PSTNDI; ");
|
||||
if (id == 0xFFFED1) fprintf (stderr, "PABXDI; ");
|
||||
if (id == 0xFFFED2) fprintf (stderr, "LINEDI; ");
|
||||
if (id == 0xFFFED3) fprintf (stderr, "DISPATDI; ");
|
||||
if (id == 0xFFFED4) fprintf (stderr, "ALLMSI; ");
|
||||
if (id == 0xFFFED5) fprintf (stderr, "IPDI; ");
|
||||
if (id == 0xFFFED6) fprintf (stderr, "DGNAI; ");
|
||||
if (id == 0xFFFED7) fprintf (stderr, "TATTSI; ");
|
||||
if (id == 0xFFFFFD) fprintf (stderr, "ALLMSIDL; ");
|
||||
if (id == 0xFFFFFE) fprintf (stderr, "ALLMSIDZ; ");
|
||||
if (id == 0xFFFFFF) fprintf (stderr, "ALLMSID; ");
|
||||
}
|
||||
}
|
||||
@@ -417,17 +417,17 @@ void dmr_flco (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[], uint32_t C
|
||||
//REMUS! Uncomment Line Below if desired
|
||||
// else strcat (state->call_string[slot], " ");
|
||||
|
||||
//Motorola FID 0x10 Only
|
||||
if (fid == 0x10)
|
||||
|
||||
if (1 == 1) //fid == 0x10
|
||||
{
|
||||
/* Check the "Service Option" bits */
|
||||
if(so & 0x20)
|
||||
if( (fid == 0x10) && (so & 0x20) ) //Motorola FID 0x10 Only
|
||||
{
|
||||
//REMUS! Uncomment Line Below if desired
|
||||
// strcat (state->call_string[slot], " TXI");
|
||||
fprintf(stderr, "TXI ");
|
||||
}
|
||||
if (so & 0x10)
|
||||
if ( (fid == 0x10) && (so & 0x10) ) //Motorola FID 0x10 Only
|
||||
{
|
||||
//REMUS! Uncomment Line Below if desired
|
||||
// strcat (state->call_string[slot], " RPT");
|
||||
@@ -742,6 +742,7 @@ uint8_t dmr_cach (dsd_opts * opts, dsd_state * state, uint8_t cach_bits[25])
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, " SLCO CRC ERR");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
if (opts->payload == 1) fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -217,8 +217,7 @@ invert_dibit(int dibit)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int digitize (dsd_opts* opts, dsd_state* state, int symbol)
|
||||
//int digitize (dsd_opts* opts, dsd_state* state, int symbol)
|
||||
int digitize (dsd_opts* opts, dsd_state* state, int symbol)
|
||||
{
|
||||
// determine dibit state
|
||||
if ((state->synctype == 6) || (state->synctype == 14)|| (state->synctype == 18) || (state->synctype == 37))
|
||||
|
||||
@@ -534,7 +534,7 @@ void openWavOutFileRaw (dsd_opts * opts, dsd_state * state)
|
||||
info.samplerate = 48000; //8000
|
||||
info.channels = 1;
|
||||
info.format = SF_FORMAT_WAV | SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE;
|
||||
opts->wav_out_raw = sf_open (opts->wav_out_file_raw, SFM_RDWR, &info);
|
||||
opts->wav_out_raw = sf_open (opts->wav_out_file_raw, SFM_WRITE, &info);
|
||||
if (opts->wav_out_raw == NULL)
|
||||
{
|
||||
fprintf (stderr,"Error - could not open raw wav output file %s\n", opts->wav_out_file_raw);
|
||||
|
||||
@@ -1142,56 +1142,61 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//ProVoice and EDACS sync
|
||||
if (opts->frame_provoice == 1)
|
||||
{
|
||||
strncpy (synctest32, (synctest_p - 31), 32);
|
||||
strncpy (synctest48, (synctest_p - 47), 48);
|
||||
if ((strcmp (synctest32, PROVOICE_SYNC) == 0) || (strcmp (synctest32, PROVOICE_EA_SYNC) == 0))
|
||||
{
|
||||
strncpy (synctest32, (synctest_p - 31), 32);
|
||||
strncpy (synctest48, (synctest_p - 47), 48);
|
||||
if ((strcmp (synctest32, PROVOICE_SYNC) == 0) || (strcmp (synctest32, PROVOICE_EA_SYNC) == 0))
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
sprintf (state->ftype, "ProVoice ");
|
||||
if (opts->errorbars == 1)
|
||||
printFrameSync (opts, state, "+PV ", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 14;
|
||||
return (14);
|
||||
}
|
||||
else if ((strcmp (synctest32, INV_PROVOICE_SYNC) == 0) || (strcmp (synctest32, INV_PROVOICE_EA_SYNC) == 0))
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
sprintf (state->ftype, "ProVoice ");
|
||||
printFrameSync (opts, state, "-PV ", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 15;
|
||||
return (15);
|
||||
}
|
||||
else if ( strcmp (synctest48, EDACS_SYNC) == 0)
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
printFrameSync (opts, state, "-EDACS", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 38;
|
||||
return (38);
|
||||
}
|
||||
else if ( strcmp (synctest48, INV_EDACS_SYNC) == 0)
|
||||
{
|
||||
sprintf (state->ftype, "ProVoice ");
|
||||
if (opts->errorbars == 1)
|
||||
printFrameSync (opts, state, "+PV ", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 14;
|
||||
return (14);
|
||||
}
|
||||
else if ((strcmp (synctest32, INV_PROVOICE_SYNC) == 0) || (strcmp (synctest32, INV_PROVOICE_EA_SYNC) == 0))
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
printFrameSync (opts, state, "+EDACS", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 37;
|
||||
return (37);
|
||||
}
|
||||
sprintf (state->ftype, "ProVoice ");
|
||||
printFrameSync (opts, state, "-PV ", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 15;
|
||||
return (15);
|
||||
}
|
||||
else if ( strcmp (synctest48, EDACS_SYNC) == 0)
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
printFrameSync (opts, state, "-EDACS", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 38;
|
||||
return (38);
|
||||
}
|
||||
else if ( strcmp (synctest48, INV_EDACS_SYNC) == 0)
|
||||
{
|
||||
state->last_cc_sync_time = time(NULL);
|
||||
state->carrier = 1;
|
||||
state->offset = synctest_pos;
|
||||
state->max = ((state->max) + lmax) / 2;
|
||||
state->min = ((state->min) + lmin) / 2;
|
||||
printFrameSync (opts, state, "+EDACS", synctest_pos + 1, modulation);
|
||||
state->lastsynctype = 37;
|
||||
return (37);
|
||||
}
|
||||
else if ((strcmp (synctest48, DOTTING_SEQUENCE_A) == 0) || (strcmp (synctest48, DOTTING_SEQUENCE_B) == 0))
|
||||
{
|
||||
printFrameSync (opts, state, " EDACS DOTTING SEQUENCE: ", synctest_pos + 1, modulation);
|
||||
eot_cc (opts, state);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#include "provoice_const.h"
|
||||
#include "git_ver.h"
|
||||
|
||||
#ifdef USE_RTLSDR
|
||||
#include <rtl-sdr.h>
|
||||
#endif
|
||||
|
||||
volatile uint8_t exitflag; //fix for issue #136
|
||||
|
||||
int pretty_colors()
|
||||
@@ -971,6 +975,7 @@ initState (dsd_state * state)
|
||||
//dmr trunking/ncurses stuff
|
||||
state->dmr_rest_channel = -1; //init on -1
|
||||
state->dmr_mfid = -1; //
|
||||
state->dmr_cc_lpcn = 0;
|
||||
|
||||
//new nxdn stuff
|
||||
state->nxdn_part_of_frame = 0;
|
||||
@@ -1136,6 +1141,7 @@ usage ()
|
||||
printf (" -r <files> Read/Play saved mbe data from file(s)\n");
|
||||
printf (" -g <num> Audio output gain (default = 0 = auto, disable = -1)\n");
|
||||
printf (" -w <file> Output synthesized speech to a .wav file, legacy auto modes only.\n");
|
||||
printf (" -6 <file> Output raw audio .wav file (48K/1). (WARNING! Large File Sizes 1 Hour ~= 360 MB)\n");
|
||||
printf (" -8 Enable Experimental Source Audio Monitor (OSS at 48k1 and Pulse Audio)\n");
|
||||
printf (" (Its recommended to use Squelch in SDR++ or GQRX, etc, if monitoring mixed analog/digital)\n");
|
||||
printf (" -P Enable Per Call WAV file saving in XDMA and NXDN decoding classes\n");
|
||||
@@ -1154,7 +1160,7 @@ usage ()
|
||||
printf ("RTL-SDR options:\n");
|
||||
printf (" Usage: rtl:dev:freq:gain:ppm:bw:sq:udp\n");
|
||||
printf (" NOTE: all arguments after rtl are optional now for trunking, but user configuration is recommended\n");
|
||||
printf (" dev <num> RTL-SDR Device Index Number\n");
|
||||
printf (" dev <num> RTL-SDR Device Index Number or 8 Digit Serial Number, no strings! (default 0)\n");
|
||||
printf (" freq <num> RTL-SDR Frequency (851800000 or 851.8M) \n");
|
||||
printf (" gain <num> RTL-SDR Device Gain (0-49)(default = 0; Hardware AGC recommended)\n");
|
||||
printf (" ppm <num> RTL-SDR PPM Error (default = 0)\n");
|
||||
@@ -1468,7 +1474,7 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
#ifdef AERO_BUILD
|
||||
fprintf (stderr, "Build Version: v2.1b (20230901)\n");
|
||||
fprintf (stderr, "Build Version: v2.1b (20230915)\n");
|
||||
#else
|
||||
fprintf (stderr, "Build Version: %s \n", GIT_TAG);
|
||||
#endif
|
||||
@@ -1839,6 +1845,13 @@ main (int argc, char **argv)
|
||||
openWavOutFile (&opts, &state);
|
||||
break;
|
||||
|
||||
case '6':
|
||||
strncpy(opts.wav_out_file_raw, optarg, 1023);
|
||||
opts.wav_out_file_raw[1023] = '\0';
|
||||
fprintf (stderr,"Writing raw audio to file %s\n", opts.wav_out_file_raw);
|
||||
openWavOutFileRaw (&opts, &state);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (optarg[0] == 'a')
|
||||
{
|
||||
@@ -2428,6 +2441,10 @@ main (int argc, char **argv)
|
||||
if((strncmp(opts.audio_in_dev, "rtl", 3) == 0)) //rtl dongle input
|
||||
{
|
||||
uint8_t rtl_ok = 0;
|
||||
//use to list out all detected RTL dongles
|
||||
char vendor[256], product[256], serial[256], userdev[256];
|
||||
int device_count = 0;
|
||||
|
||||
#ifdef USE_RTLSDR
|
||||
fprintf (stderr, "RTL Input: ");
|
||||
char * curr;
|
||||
@@ -2476,6 +2493,34 @@ main (int argc, char **argv)
|
||||
else goto RTLEND;
|
||||
|
||||
RTLEND:
|
||||
|
||||
device_count = rtlsdr_get_device_count();
|
||||
if (!device_count)
|
||||
{
|
||||
fprintf(stderr, "No supported devices found.\n");
|
||||
exitflag = 1;
|
||||
}
|
||||
else fprintf(stderr, "Found %d device(s):\n", device_count);
|
||||
for (int i = 0; i < device_count; i++)
|
||||
{
|
||||
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
|
||||
fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial);
|
||||
|
||||
sprintf (userdev, "%08d", opts.rtl_dev_index);
|
||||
|
||||
//check by index first, then by serial
|
||||
if (opts.rtl_dev_index == i)
|
||||
{
|
||||
fprintf (stderr, "Selected Device #%d with Serial Number: %s \n", i, serial);
|
||||
}
|
||||
else if (strcmp (userdev, serial) == 0)
|
||||
{
|
||||
fprintf (stderr, "Selected Device #%d with Serial Number: %s \n", i, serial);
|
||||
opts.rtl_dev_index = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fprintf (stderr, "Dev %d ", opts.rtl_dev_index);
|
||||
fprintf (stderr, "Freq %d ", opts.rtlsdr_center_freq);
|
||||
fprintf (stderr, "Gain %d ", opts.rtl_gain_value);
|
||||
|
||||
@@ -190,10 +190,10 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
int x;
|
||||
|
||||
//these conditions should ensure no clashing with the BP/HBP/Scrambler key loading machanisms already coded in
|
||||
if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->payload_keyid != 0 && state->keyloader == 1)
|
||||
if (state->currentslot == 0 && state->payload_algid != 0 && state->payload_algid != 0x80 && state->keyloader == 1)
|
||||
keyring (opts, state);
|
||||
|
||||
if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->payload_keyidR != 0 && state->keyloader == 1)
|
||||
if (state->currentslot == 1 && state->payload_algidR != 0 && state->payload_algidR != 0x80 && state->keyloader == 1)
|
||||
keyring (opts, state);
|
||||
|
||||
//24-bit TG to 16-bit hash
|
||||
@@ -216,6 +216,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
|
||||
//set playback mode for this frame
|
||||
char mode[8];
|
||||
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
|
||||
@@ -231,6 +232,7 @@ processMbeFrame (dsd_opts * opts, dsd_state * state, char imbe_fr[8][23], char a
|
||||
if (state->group_array[i].groupNumber == groupNumber)
|
||||
{
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
#include "dsd.h"
|
||||
#include "git_ver.h"
|
||||
|
||||
#ifdef USE_RTLSDR
|
||||
#include <rtl-sdr.h>
|
||||
//use to list out all detected RTL dongles
|
||||
char vendor[256], product[256], serial[256], userdev[256];
|
||||
int device_count = 0;
|
||||
#endif
|
||||
|
||||
#define BSIZE 999
|
||||
#define UDP_BUFLEN 5 //maximum UDP buffer length
|
||||
@@ -669,7 +675,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
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, 2, 2, " RTL Device Index or Serial Number:");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -678,7 +684,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
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, 2, 2, " RTL Device PPM Error:");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -687,7 +693,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
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, 2, 2, " Frequency in Hz (851.8 MHz is 851800000 Hz): ");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -696,7 +702,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||||
box (entry_win, 0, 0);
|
||||
mvwprintw(entry_win, 2, 2, " Enter BW (8, 12, 24, 48)(12 Recommended)");
|
||||
mvwprintw(entry_win, 2, 2, " BW (8, 12, 24, 48)(12 Recommended): ");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -705,7 +711,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
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 = AGC)");
|
||||
mvwprintw(entry_win, 2, 2, " RTL Gain Value (0-49) (0 = AGC): ");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -714,7 +720,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
entry_win = newwin(6, WIDTH+18, starty+10, startx+10);
|
||||
box (entry_win, 0, 0);
|
||||
mvwprintw(entry_win, 2, 2, " Enter RTL UDP Port - Optional (Default = 0)");
|
||||
mvwprintw(entry_win, 2, 2, " RTL UDP Port - Legacy/Optional (Default = 0): ");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
@@ -723,18 +729,47 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
entry_win = newwin(8, WIDTH+22, starty+10, startx+10);
|
||||
box (entry_win, 0, 0);
|
||||
mvwprintw(entry_win, 2, 2, " Enter RTL RMS Squelch Level (NXDN/dPMR only)");
|
||||
mvwprintw(entry_win, 2, 2, " RTL RMS Squelch Level (NXDN/dPMR/Analog/Raw only): ");
|
||||
mvwprintw(entry_win, 3, 3, " ");
|
||||
echo();
|
||||
refresh();
|
||||
wscanw(entry_win, "%d", &opts->rtl_squelch_level);
|
||||
noecho();
|
||||
|
||||
//use to list out all detected RTL dongles
|
||||
device_count = rtlsdr_get_device_count();
|
||||
if (!device_count)
|
||||
{
|
||||
fprintf(stderr, "No supported devices found.\n");
|
||||
}
|
||||
else fprintf(stderr, "Found %d device(s):\n", device_count);
|
||||
for (int i = 0; i < device_count; i++)
|
||||
{
|
||||
rtlsdr_get_device_usb_strings(i, vendor, product, serial);
|
||||
fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial);
|
||||
|
||||
sprintf (userdev, "%08d", opts->rtl_dev_index);
|
||||
|
||||
//check by index first, then by serial
|
||||
if (opts->rtl_dev_index == i)
|
||||
{
|
||||
fprintf (stderr, "Selected Device #%d with Serial Number: %s \n", i, serial);
|
||||
break;
|
||||
}
|
||||
else if (strcmp (userdev, serial) == 0)
|
||||
{
|
||||
fprintf (stderr, "Selected Device #%d with Serial Number: %s \n", i, serial);
|
||||
opts->rtl_dev_index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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, 5, 2, " RTL Device Index Number: %d; SN:%s", opts->rtl_dev_index, serial);
|
||||
mvwprintw(entry_win, 6, 2, " RTL Device 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);
|
||||
@@ -2229,7 +2264,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
if (opts->ncurses_compact == 1)
|
||||
{
|
||||
printw ("------------------------------------------------------------------------------\n");
|
||||
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.1b (20230901)");
|
||||
printw ("| Digital Speech Decoder: Florida Man Edition - Aero %s \n", "v2.1b (20230915)");
|
||||
printw ("------------------------------------------------------------------------------\n");
|
||||
}
|
||||
#elif LIMAZULUTWEAKS
|
||||
@@ -2261,7 +2296,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
#endif
|
||||
#ifdef AERO_BUILD
|
||||
if (i == 5) printw (" %s ", "Aero Build");
|
||||
if (i == 6) printw (" v2.1b (20230901) \n");
|
||||
if (i == 6) printw (" v2.1b (20230915) \n");
|
||||
#else
|
||||
if (i == 5) printw (" %s ", "Main Build");
|
||||
if (i == 6) printw (" %s \n", GIT_TAG);
|
||||
@@ -2345,9 +2380,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
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)
|
||||
if (opts->wav_out_raw)
|
||||
{
|
||||
printw ("| Appending Raw Sig Audio WAV to file %s\n", opts->wav_out_file_raw);
|
||||
printw ("| Raw Audio Output: %s\n", opts->wav_out_file_raw);
|
||||
}
|
||||
if (opts->symbol_out_file[0] != 0 && opts->symbol_out == 1)
|
||||
{
|
||||
|
||||
@@ -265,7 +265,7 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
}
|
||||
|
||||
//Source Audio Monitoring
|
||||
if (have_sync == 0 && opts->monitor_input_audio == 1)
|
||||
if (have_sync == 0)
|
||||
{
|
||||
//sanity check to prevent an overflow
|
||||
if (state->analog_sample_counter > 959)
|
||||
@@ -276,18 +276,18 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
if (state->analog_sample_counter == 960)
|
||||
{
|
||||
//get an rms value if not using the rtl built in version
|
||||
if (opts->audio_in_type != 3)
|
||||
if (opts->audio_in_type != 3 && opts->monitor_input_audio == 1)
|
||||
opts->rtl_rms = raw_rms(state->analog_out, 960, 1);
|
||||
|
||||
//debug
|
||||
// opts->rtl_rms = 101;
|
||||
|
||||
//make it a little quieter
|
||||
for (int x = 0; x < 960; x++)
|
||||
state->analog_out[x] /= 4;
|
||||
// for (int x = 0; x < 960; x++)
|
||||
// state->analog_out[x] /= 4;
|
||||
|
||||
//seems to be working now, but RMS values are lower on actual analog signal than on no signal but noise
|
||||
if ( opts->rtl_rms > opts->rtl_squelch_level )
|
||||
if ( (opts->rtl_rms > opts->rtl_squelch_level) && (opts->monitor_input_audio == 1) )
|
||||
{
|
||||
if (opts->audio_out_type == 0)
|
||||
pa_simple_write(opts->pulse_raw_dev_out, state->analog_out, 960*2, NULL);
|
||||
@@ -301,17 +301,41 @@ getSymbol (dsd_opts * opts, dsd_state * state, int have_sync)
|
||||
state->last_vc_sync_time = time(NULL);
|
||||
}
|
||||
|
||||
//raw wav file saving -- only write when not NXDN, dPMR, or M17 due to noise that can cause tons of false positives when no sync
|
||||
if (opts->wav_out_raw != NULL && opts->frame_nxdn48 == 0 && opts->frame_nxdn96 == 0 && opts->frame_dpmr == 0 && opts->frame_m17 == 0)
|
||||
{
|
||||
sf_write_short(opts->wav_out_raw, state->analog_out, 960);
|
||||
sf_write_sync (opts->wav_out_raw);
|
||||
}
|
||||
|
||||
memset (state->analog_out, 0, sizeof(state->analog_out));
|
||||
state->analog_sample_counter = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (have_sync == 1 && opts->monitor_input_audio == 1)
|
||||
if (have_sync == 1)
|
||||
{
|
||||
//zero out and reset counter
|
||||
memset (state->analog_out, 0, sizeof(state->analog_out));
|
||||
state->analog_sample_counter = 0;
|
||||
//sanity check to prevent an overflow
|
||||
if (state->analog_sample_counter > 959)
|
||||
state->analog_sample_counter = 959;
|
||||
|
||||
state->analog_out[state->analog_sample_counter++] = sample;
|
||||
|
||||
if (state->analog_sample_counter == 960)
|
||||
{
|
||||
//raw wav file saving -- file size on this blimps pretty fast 1 min ~= 6 MB; 1 hour ~= 360 MB;
|
||||
if (opts->wav_out_raw != NULL)
|
||||
{
|
||||
sf_write_short(opts->wav_out_raw, state->analog_out, 960);
|
||||
sf_write_sync (opts->wav_out_raw);
|
||||
}
|
||||
|
||||
//zero out and reset counter
|
||||
memset (state->analog_out, 0, sizeof(state->analog_out));
|
||||
state->analog_sample_counter = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (opts->use_cosine_filter)
|
||||
|
||||
@@ -215,7 +215,6 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
|
||||
fprintf (stderr, " AFS [0x%03X] [%02d-%03d] LCN [%02d]", afs, afs >> 7, afs & 0x7F, lcn);
|
||||
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
if (rms > sql) fprintf (stderr, "\n");
|
||||
|
||||
//Update Ncurses Terminal
|
||||
if (opts->use_ncurses_terminal == 1)
|
||||
@@ -230,6 +229,26 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
|
||||
sf_write_short(opts->wav_out_f, analog2, 960);
|
||||
sf_write_short(opts->wav_out_f, analog3, 960);
|
||||
}
|
||||
|
||||
//digitize analog samples for a dotting sequence check
|
||||
unsigned long long int sr = 0;
|
||||
for (i = 0; i < 960; i+=5) //Samples Per Symbol is 5, so incrememnt every 5
|
||||
{
|
||||
sr = sr << 1;
|
||||
sr += digitize (opts, state, (int)analog1[i]);
|
||||
}
|
||||
|
||||
//debug
|
||||
// fprintf (stderr, " SR: %016llX", sr);
|
||||
|
||||
if (sr == 0xAAAAAAAAAAAAAAAA || sr == 0x5555555555555555)
|
||||
{
|
||||
fprintf (stderr, " EDACS DOTTING SEQUENCE: ");
|
||||
rms = 0; //break while loop by dropping rms value
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
if (rms > sql) fprintf (stderr, "\n");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -443,6 +462,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, " Group [%05d] Source [%08d] LCN[%02d]", group, source, lcn);
|
||||
|
||||
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
|
||||
@@ -454,6 +474,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +599,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
||||
fprintf (stderr, " AFS [0x%03X] [%02d-%03d] LCN [%02d]", afs, a, fs, lcn);
|
||||
|
||||
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
|
||||
@@ -589,6 +611,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,4 +694,55 @@ void edacs(dsd_opts * opts, dsd_state * state)
|
||||
|
||||
}
|
||||
|
||||
void eot_cc(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
|
||||
fprintf (stderr, "EOT; \n");
|
||||
|
||||
//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_keyid = 0;
|
||||
state->payload_miP = 0;
|
||||
//reset some strings
|
||||
sprintf (state->call_string[0], "%s", " "); //21 spaces
|
||||
sprintf (state->call_string[1], "%s", " "); //21 spaces
|
||||
sprintf (state->active_channel[0], "%s", "");
|
||||
sprintf (state->active_channel[1], "%s", "");
|
||||
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);
|
||||
}
|
||||
|
||||
//rtl
|
||||
else if (opts->audio_in_type == 3)
|
||||
{
|
||||
#ifdef USE_RTLSDR
|
||||
state->lasttg = 0;
|
||||
state->lastsrc = 0;
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
state->payload_miP = 0;
|
||||
//reset some strings
|
||||
sprintf (state->call_string[0], "%s", " "); //21 spaces
|
||||
sprintf (state->call_string[1], "%s", " "); //21 spaces
|
||||
sprintf (state->active_channel[0], "%s", "");
|
||||
sprintf (state->active_channel[1], "%s", "");
|
||||
opts->p25_is_tuned = 0;
|
||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
|
||||
rtl_dev_tune (opts, state->p25_cc_freq);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -537,6 +537,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
||||
//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
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -544,16 +545,18 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
||||
|
||||
for (int i = 0; i < state->group_tally; i++)
|
||||
{
|
||||
if (state->group_array[i].groupNumber == DestinationID) //source, or destination?
|
||||
if (state->group_array[i].groupNumber == DestinationID && DestinationID != 0) //destination, if it isn't 0
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
//might not be ideal if both source and group/target are both in the array
|
||||
else if (state->group_array[i].groupNumber == SourceUnitID) //source, or destination?
|
||||
else if (state->group_array[i].groupNumber == SourceUnitID && DestinationID == 0) //source, if destination is 0
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1389,6 +1392,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
|
||||
//run group/tgt analysis and tune if available/desired
|
||||
//group list mode so we can look and see if we need to block tuning any groups, etc
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -1400,6 +1404,7 @@ void NXDN_decode_scch(dsd_opts * opts, dsd_state * state, uint8_t * Message, uin
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -164,6 +164,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//group list mode so we can look and see if we need to block tuning any groups, etc
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -320,6 +321,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,6 +419,7 @@ void processMPDU(dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
|
||||
//group list mode so we can look and see if we need to block tuning any groups, etc
|
||||
char mode[8]; //allow, block, digital, enc, etc
|
||||
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
|
||||
@@ -106,6 +107,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +184,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,6 +296,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,6 +393,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,6 +484,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,6 +632,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,6 +801,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,6 +915,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1005,6 +1014,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
|
||||
{
|
||||
fprintf (stderr, " [%s]", state->group_array[i].groupName);
|
||||
strcpy (mode, state->group_array[i].groupMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ void processProVoice (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
fprintf (stderr, "%s", KGRN);
|
||||
fprintf (stderr, " Site: %lld AFS: %d-%d LCN: %d ",
|
||||
state->edacs_site_id, (state->lasttg >> 7) & 0xF, state->lasttg & 0x7F, state->edacs_tuned_lcn);
|
||||
state->edacs_site_id, (state->lastsrc >> 7) & 0xF, state->lastsrc & 0x7F, state->edacs_tuned_lcn);
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user