mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-09 15:27:22 -05:00
NXDN: Tweak to Frame Sync, restore other sync patterns based on polarity; Fixes random frame skips on NXDN96 trunking;
NXDN: Initial GPS Report Commit; NXDN: Don't assign GI, TG/RID in VCALL_ASSGN; Leads to duplicate entries in Event History, particularly when private call; NMEA: Sentence Checker with start, end, checksum, and supplimentary string checks P25p1 Tier 1 Location Service and Also observed on old Type-D system; LRRP: Fix LRRP.exe style reports to use date/time strings with colons and slashes; NXDN: Tweak to DCALL to check for a selective retry when blk_num is not equal to pf_num and invalidate, we don't have the memory of the last PDU attempt (and may have successfully received it anyways, even if the radio did not);
This commit is contained in:
@@ -1409,6 +1409,7 @@ void harris_lptt (dsd_opts * opts, dsd_state * state, uint8_t * input, uint32_t
|
||||
void nxdn_gps_report(dsd_opts * opts, dsd_state * state, uint8_t * input, uint32_t src);
|
||||
void utf16_to_text (dsd_state * state, uint8_t wr, uint16_t len, uint8_t * input);
|
||||
void utf8_to_text (dsd_state * state, uint8_t wr, uint16_t len, uint8_t * input);
|
||||
uint8_t nmea_sentence_checker(dsd_opts * opts, dsd_state * state, uint8_t * input, uint8_t slot, int len);
|
||||
|
||||
//"DMR STEREO"
|
||||
void dmrBSBootstrap (dsd_opts * opts, dsd_state * state);
|
||||
|
||||
@@ -995,8 +995,9 @@ void dmr_locn (dsd_opts * opts, dsd_state * state, uint16_t len, uint8_t * DMR_P
|
||||
//write to LRRP file
|
||||
if (opts->lrrp_file_output == 1)
|
||||
{
|
||||
char * timestr = getTimeC();
|
||||
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//open file by name that is supplied in the ncurses terminal, or cli
|
||||
FILE * pFile; //file pointer
|
||||
|
||||
@@ -1212,8 +1212,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
strncpy (synctest10, (synctest_p - 9), 10); //FSW only
|
||||
if (
|
||||
(strcmp (synctest10, "3131331131") == 0 ) //this seems to be the most common 'correct' pattern on Type-C
|
||||
|| (strcmp (synctest10, "3331331131") == 0 ) //this seems to be the most common 'correct' pattern on Conventional
|
||||
(strcmp (synctest10, "3131331131") == 0 )
|
||||
|| (strcmp (synctest10, "3331331131") == 0 )
|
||||
|| (strcmp (synctest10, "3131331111") == 0 )
|
||||
// || (strcmp (synctest10, "3331331111") == 0 )
|
||||
// || (strcmp (synctest10, "3131311131") == 0 )
|
||||
)
|
||||
{
|
||||
|
||||
@@ -1239,8 +1242,11 @@ getFrameSync (dsd_opts * opts, dsd_state * state)
|
||||
{
|
||||
strncpy (synctest10, (synctest_p - 9), 10); //FSW only
|
||||
if (
|
||||
(strcmp (synctest10, "1313113313") == 0 ) //this seems to be the most common 'correct' pattern on Type-C
|
||||
|| (strcmp (synctest10, "1113113313") == 0 ) //this seems to be the most common 'correct' pattern on Conventional
|
||||
(strcmp (synctest10, "1313113313") == 0 )
|
||||
|| (strcmp (synctest10, "1113113313") == 0 )
|
||||
|| (strcmp (synctest10, "1313113333") == 0 )
|
||||
// || (strcmp (synctest10, "1113113333") == 0 )
|
||||
// || (strcmp (synctest10, "1313133313") == 0 )
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
255
src/dsd_gps.c
255
src/dsd_gps.c
@@ -129,8 +129,8 @@ void lip_protocol_decoder (dsd_opts * opts, dsd_state * state, uint8_t * input)
|
||||
if (opts->lrrp_file_output == 1)
|
||||
{
|
||||
|
||||
char * datestr = getDate();
|
||||
char * timestr = getTime();
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//open file by name that is supplied in the ncurses terminal, or cli
|
||||
pFile = fopen (opts->lrrp_out_file, "a");
|
||||
@@ -247,8 +247,8 @@ void nmea_iec_61162_1 (dsd_opts * opts, dsd_state * state, uint8_t * input, uint
|
||||
if (opts->lrrp_file_output == 1)
|
||||
{
|
||||
|
||||
char * datestr = getDate();
|
||||
char * timestr = getTime();
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
int s = (int)fkph; //rounded interger format for the log report
|
||||
int a = 0;
|
||||
@@ -406,8 +406,8 @@ void harris_lptt (dsd_opts * opts, dsd_state * state, uint8_t * input, uint32_t
|
||||
if (opts->lrrp_file_output == 1 && src != 0 && gps_quality != 3)
|
||||
{
|
||||
|
||||
char * datestr = getDate();
|
||||
char * timestr = getTime();
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//rounded interger formats for the log report
|
||||
int s = (int)fkph;
|
||||
@@ -536,8 +536,8 @@ void dmr_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[])
|
||||
if (opts->lrrp_file_output == 1)
|
||||
{
|
||||
|
||||
char * datestr = getDate();
|
||||
char * timestr = getTime();
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//open file by name that is supplied in the ncurses terminal, or cli
|
||||
pFile = fopen (opts->lrrp_out_file, "a");
|
||||
@@ -644,8 +644,9 @@ void apx_embedded_gps (dsd_opts * opts, dsd_state * state, uint8_t lc_bits[])
|
||||
FILE * pFile; //file pointer
|
||||
if (opts->lrrp_file_output == 1)
|
||||
{
|
||||
char * datestr = getDate();
|
||||
char * timestr = getTime();
|
||||
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//open file by name that is supplied in the ncurses terminal, or cli
|
||||
pFile = fopen (opts->lrrp_out_file, "a");
|
||||
@@ -719,11 +720,235 @@ void decode_ars(dsd_opts * opts, dsd_state * state, uint8_t * input, int len)
|
||||
UNUSED(len);
|
||||
}
|
||||
|
||||
//WIP: Based on Denny's always brilliant reverse-engineering of GPS reports
|
||||
void nxdn_gps_report(dsd_opts * opts, dsd_state * state, uint8_t * input, uint32_t src)
|
||||
{
|
||||
//TODO: This
|
||||
UNUSED(opts);
|
||||
UNUSED(state);
|
||||
UNUSED(input);
|
||||
UNUSED(src);
|
||||
|
||||
// Basic fields
|
||||
// uint8_t quality = (uint8_t)convert_bits_into_output(input+8, 4); //can't seem to work these first two out correctly
|
||||
// uint8_t num_sat = (uint8_t)convert_bits_into_output(input+12, 4); //can't seem to work these first two out correctly
|
||||
int16_t elevation = (int16_t)convert_bits_into_output(input+56, 16);
|
||||
|
||||
// Speed & Heading (in tenths)
|
||||
uint16_t speed_raw = (uint16_t)convert_bits_into_output(input+74, 14);
|
||||
uint16_t heading_raw = (uint16_t)convert_bits_into_output(input+92, 12);
|
||||
double speed = speed_raw / 10.0; //knots or k/h
|
||||
double heading = heading_raw / 10.0;
|
||||
|
||||
//Date
|
||||
uint16_t year = (uint16_t)(convert_bits_into_output(input+136,7) + 2000);
|
||||
uint8_t month = (uint8_t) convert_bits_into_output(input+143,4);
|
||||
uint8_t day = (uint8_t)(convert_bits_into_output(input+147,5) + 1);
|
||||
|
||||
// Longitude (DDMM.mmmm format)
|
||||
uint16_t lon_degmin = (uint16_t)convert_bits_into_output(input+152, 16);
|
||||
uint16_t lon_frac = (uint16_t)convert_bits_into_output(input+16, 15);
|
||||
uint8_t lon_hem = (uint8_t) convert_bits_into_output(input+183, 1);
|
||||
double lon_minutes = (lon_degmin % 100) + (lon_frac / 10000.0);
|
||||
double lon_decimal = (lon_degmin / 100) + (lon_minutes / 60.0);
|
||||
double longitude = (lon_hem == 0) ? lon_decimal : -lon_decimal;
|
||||
|
||||
// Latitude (DDMM.mmmm format)
|
||||
uint16_t lat_degmin = (uint16_t)convert_bits_into_output(input+184,16);
|
||||
uint16_t lat_frac = (uint16_t)convert_bits_into_output(input+200,15);
|
||||
uint8_t lat_hem = (uint8_t) convert_bits_into_output(input+215,1);
|
||||
double lat_minutes = (lat_degmin % 100) + (lat_frac / 10000.0);
|
||||
double lat_decimal = (lat_degmin / 100) + (lat_minutes / 60.0);
|
||||
double latitude = (lat_hem == 0) ? lat_decimal : -lat_decimal;
|
||||
|
||||
//Time
|
||||
// uint8_t hour = (uint8_t) convert_bits_into_output(input+247,5);
|
||||
// uint8_t minute = (uint8_t) convert_bits_into_output(input+252,6);
|
||||
// uint8_t second = (uint8_t) convert_bits_into_output(input+258,6); //this seems to be zero, recheck time
|
||||
|
||||
char deg_glyph[4];
|
||||
sprintf (deg_glyph, "%s", "°");
|
||||
|
||||
//Report
|
||||
fprintf (stderr, "\n GPS: (%f%s, %f%s) ", latitude, deg_glyph, longitude, deg_glyph);
|
||||
fprintf (stderr, "Speed: %lf k/h; ", speed);
|
||||
fprintf (stderr, "COG: %lf; ", heading);
|
||||
fprintf (stderr, "Elevation: %i; ", elevation);
|
||||
// fprintf (stderr, "Quality: %d / %d; ", quality, num_sat);
|
||||
fprintf (stderr, "Date: %04d/%02d/%02d ", year, month, day);
|
||||
// fprintf (stderr, "Time: %02d:%02d:%02d ", hour, minute, second);
|
||||
|
||||
//save to LRRP report for mapping/logging
|
||||
if (opts->lrrp_file_output == 1 && src != 0) //&& quality?
|
||||
{
|
||||
|
||||
char * datestr = getDateS();
|
||||
char * timestr = getTimeC();
|
||||
|
||||
//rounded interger formats for the log report
|
||||
int s = (int)speed;
|
||||
int a = (int)heading;
|
||||
|
||||
//open file by name that is supplied in the ncurses terminal, or cli
|
||||
FILE * pFile; //file pointer
|
||||
pFile = fopen (opts->lrrp_out_file, "a");
|
||||
fprintf (pFile, "%s\t", datestr );
|
||||
fprintf (pFile, "%s\t", timestr );
|
||||
fprintf (pFile, "%08d\t", src);
|
||||
fprintf (pFile, "%.6lf\t", latitude);
|
||||
fprintf (pFile, "%.6lf\t", longitude);
|
||||
fprintf (pFile, "%d\t ", s);
|
||||
fprintf (pFile, "%d\t ", a);
|
||||
fprintf (pFile, "\n");
|
||||
fclose (pFile);
|
||||
|
||||
if (timestr != NULL)
|
||||
{
|
||||
free (timestr);
|
||||
timestr = NULL;
|
||||
}
|
||||
if (datestr != NULL)
|
||||
{
|
||||
free (datestr);
|
||||
datestr = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//reset source and target from PDU storage
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_target[0] = 0;
|
||||
}
|
||||
|
||||
uint8_t nmea_sentence_checker(dsd_opts * opts, dsd_state * state, uint8_t * input, uint8_t slot, int len)
|
||||
{
|
||||
|
||||
//Check Start and End, and Validity w/ Checksum
|
||||
int i;
|
||||
uint8_t start_value = (uint8_t)ConvertBitIntoBytes(input, 8);
|
||||
uint8_t end_value = 0;
|
||||
uint8_t checksum_calc = 0;
|
||||
uint8_t checksum_ext = 0;
|
||||
char checksum_str[3];
|
||||
memset(checksum_str, 0, sizeof(checksum_str));
|
||||
uint8_t valid = 0;
|
||||
|
||||
if (start_value == '$' || start_value == '!')
|
||||
{
|
||||
//debug
|
||||
// fprintf (stderr, "Start Okay! ");
|
||||
|
||||
for (i = 1; i < len; i++)
|
||||
{
|
||||
uint8_t value = (uint8_t)ConvertBitIntoBytes(input+(i*8), 8);
|
||||
if (value == '*')
|
||||
{
|
||||
end_value = value;
|
||||
checksum_str[0] = (uint8_t)ConvertBitIntoBytes(input+(i*8)+8, 8);
|
||||
checksum_str[1] = (uint8_t)ConvertBitIntoBytes(input+(i*8)+16, 8);
|
||||
checksum_str[2] = 0;
|
||||
sscanf (checksum_str, "%hhX", &checksum_ext);
|
||||
break;
|
||||
}
|
||||
else if (value >= 0x20 && value < 0x7F)
|
||||
{
|
||||
checksum_calc ^= value;
|
||||
continue;
|
||||
}
|
||||
else break; //anything else that isn't ascii range values
|
||||
}
|
||||
|
||||
//debug
|
||||
// if (end_value == '*')
|
||||
// fprintf (stderr, "Checksum Present! ");
|
||||
|
||||
if (checksum_ext == checksum_calc)
|
||||
{
|
||||
// fprintf (stderr, "Checksum Okay! (%02X / %02X)", checksum_calc, checksum_ext);
|
||||
valid = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fprintf (stderr, "Checksum Err! (%02X / %02X) ", checksum_calc, checksum_ext);
|
||||
valid = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//dump, if valid
|
||||
memset(state->event_history_s[slot].Event_History_Items[0].text_message, 0, sizeof(state->event_history_s[slot].Event_History_Items[0].text_message));
|
||||
if (valid)
|
||||
{
|
||||
uint8_t ascii = 0;
|
||||
uint16_t crlf = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
ascii = (uint8_t)ConvertBitIntoBytes(input+(i*8), 8);
|
||||
crlf = (uint16_t)ConvertBitIntoBytes(input+(i*8), 16);
|
||||
if (ascii >= 0x20 && ascii < 0x7F)
|
||||
{
|
||||
fprintf (stderr, "%c", ascii);
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i] = ascii;
|
||||
}
|
||||
else if (crlf == 0x0D0A) //NMEA Sentences end with 0x0D 0x0A (CR/LF)
|
||||
{
|
||||
fprintf (stderr, "%s", " ");
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i+0] = 0x20; //Space
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i+1] = 0x20; //Space
|
||||
i+=2;
|
||||
break;
|
||||
}
|
||||
else break; //anything else that isn't ascii range values
|
||||
}
|
||||
|
||||
//check for supplimentary string i.e., $PP25
|
||||
ascii = (uint8_t)ConvertBitIntoBytes(input+(i*8), 8);
|
||||
if (crlf == 0x0D0A && ascii == '$')
|
||||
{
|
||||
for (i = i; i < len; i++)
|
||||
{
|
||||
ascii = (uint8_t)ConvertBitIntoBytes(input+(i*8), 8);
|
||||
crlf = (uint16_t)ConvertBitIntoBytes(input+(i*8), 16);
|
||||
|
||||
if (ascii >= 0x20 && ascii < 0x7F)
|
||||
{
|
||||
fprintf (stderr, "%c", ascii);
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i] = ascii;
|
||||
}
|
||||
else if (crlf == 0x0D0A) //Supplimentary Sentences end with 0x0D 0x0A (CR/LF)
|
||||
{
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i] = 0x20;
|
||||
break;
|
||||
}
|
||||
else break; //anything else that isn't ascii range values
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//debug
|
||||
// fprintf(stderr, "\n %s", state->event_history_s[slot].Event_History_Items[0].text_message);
|
||||
|
||||
//dump to event history
|
||||
state->event_history_s[slot].Event_History_Items[0].text_message[i] = '\0';
|
||||
uint32_t source = state->dmr_lrrp_source[slot];
|
||||
uint32_t target = state->dmr_lrrp_target[slot];
|
||||
char comp_string[500]; memset (comp_string, 0, sizeof(comp_string));
|
||||
sprintf (comp_string, "NMEA SRC: %d; TGT: %d;", source, target);
|
||||
watchdog_event_datacall (opts, state, source, target, comp_string, slot);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (start_value != '$' && start_value != '!')
|
||||
fprintf (stderr, " Not an NMEA Sentence Structure;");
|
||||
else if ( (start_value == '$' || start_value == '!') && end_value != '*')
|
||||
fprintf (stderr, " Possible NMEA Sentence, Missing Ending *;");
|
||||
else if ( start_value != '$' && start_value != '!' && end_value == '*')
|
||||
fprintf (stderr, " Possible NMEA Sentence, Missing Starting $ or !;");
|
||||
else if (checksum_calc != checksum_ext)
|
||||
fprintf (stderr, " NMEA Checksum Error (%02X / %02X);", checksum_calc, checksum_ext);
|
||||
}
|
||||
|
||||
//TODO: Convert to LRRP data and report / GPS on Event History
|
||||
|
||||
state->dmr_lrrp_source[slot] = 0;
|
||||
state->dmr_lrrp_target[slot] = 0;
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
@@ -186,6 +186,10 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, uint8_t Cr
|
||||
//reset header validity
|
||||
state->data_header_valid[0] = 0;
|
||||
|
||||
//set source and target
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_target[0] = 0;
|
||||
|
||||
//reset encryption variables (for pdu)
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
@@ -220,6 +224,10 @@ void NXDN_Elements_Content_decode(dsd_opts * opts, dsd_state * state, uint8_t Cr
|
||||
//reset header validity
|
||||
state->data_header_valid[0] = 0;
|
||||
|
||||
//set source and target
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_target[0] = 0;
|
||||
|
||||
//reset encryption variables (for pdu)
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
@@ -712,23 +720,6 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||
opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop
|
||||
|
||||
//set rid and tg when we actually tune to it
|
||||
//only assign rid if not spare and not reserved (happens on private calls, unsure of its significance)
|
||||
if ( (VoiceCallOption & 0xF) < 4) //ideally, only want 0, 2, or 3
|
||||
state->nxdn_last_rid = SourceUnitID;
|
||||
state->nxdn_last_tg = DestinationID;
|
||||
sprintf (state->nxdn_call_type, "%s", NXDN_Call_Type_To_Str(CallType));
|
||||
|
||||
if (CallType == 3)
|
||||
{
|
||||
state->gi[0] = 1; //Private Call
|
||||
//unassign these, sometimes, when trunking, these may be reversed by the time listened,
|
||||
//and this will plant an extra private call in the event_history
|
||||
state->nxdn_last_rid = 0;
|
||||
state->nxdn_last_tg = 0;
|
||||
}
|
||||
else state->gi[0] = 0; //Group Call
|
||||
|
||||
//Call String for Per Call WAV File
|
||||
sprintf (state->call_string[0], "%s", NXDN_Call_Type_To_Str(CallType));
|
||||
if (CCOption & 0x80) strcat (state->call_string[0], " Emergency");
|
||||
@@ -760,23 +751,6 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa
|
||||
state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq;
|
||||
opts->p25_is_tuned = 1;
|
||||
|
||||
//set rid and tg when we actually tune to it
|
||||
//only assign rid if not spare and not reserved (happens on private calls, unsure of its significance)
|
||||
if ( (VoiceCallOption & 0xF) < 4) //ideally, only want 0, 2, or 3
|
||||
state->nxdn_last_rid = SourceUnitID;
|
||||
state->nxdn_last_tg = DestinationID;
|
||||
sprintf (state->nxdn_call_type, "%s", NXDN_Call_Type_To_Str(CallType));
|
||||
|
||||
if (CallType == 3)
|
||||
{
|
||||
state->gi[0] = 1; //Private Call
|
||||
//unassign these, sometimes, when trunking, these may be reversed by the time listened,
|
||||
//and this will plant an extra private call in the event_history
|
||||
state->nxdn_last_rid = 0;
|
||||
state->nxdn_last_tg = 0;
|
||||
}
|
||||
else state->gi[0] = 0; //Group Call
|
||||
|
||||
//Call String for Per Call WAV File
|
||||
sprintf (state->call_string[0], "%s", NXDN_Call_Type_To_Str(CallType));
|
||||
if (CCOption & 0x80) strcat (state->call_string[0], " Emergency");
|
||||
@@ -2586,6 +2560,10 @@ void nxdn_sdcall_header(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
|
||||
//set this is a valid header
|
||||
state->data_header_valid[0] = 1;
|
||||
|
||||
//set source and target
|
||||
state->dmr_lrrp_source[0] = source;
|
||||
state->dmr_lrrp_target[0] = target;
|
||||
|
||||
}
|
||||
|
||||
@@ -2659,7 +2637,7 @@ void nxdn_dcall_header(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
NXDN_Data_Call_Option_To_Str(dcall_opt, duplex_string, dcall_string);
|
||||
|
||||
fprintf (stderr, "\n %s", KCYN);
|
||||
fprintf (stderr, "Data Call Header (%04X) ", pkt_info);
|
||||
fprintf (stderr, "Data Call Header (%06X) ", pkt_info);
|
||||
if (idas == 0)
|
||||
fprintf (stderr, "Source: %d; Target: %d; ", source, target);
|
||||
else
|
||||
@@ -2732,6 +2710,10 @@ void nxdn_dcall_header(dsd_opts * opts, dsd_state * state, uint8_t * Message)
|
||||
|
||||
//set this is a valid header
|
||||
state->data_header_valid[0] = 1;
|
||||
|
||||
//set source and target
|
||||
state->dmr_lrrp_source[0] = source;
|
||||
state->dmr_lrrp_target[0] = target;
|
||||
|
||||
}
|
||||
|
||||
@@ -2739,8 +2721,9 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
{
|
||||
UNUSED(opts);
|
||||
|
||||
//packet frame number and block number, observation shows these seem to be the same value (observed Type-D)
|
||||
//but the manual does not quite explain these values indicate super packet of up to 16 big packets, and 1 packet is up to 16 blocks?
|
||||
//if this is a full packet delivery, both of these numbers match typically,
|
||||
//but if this is a selective retry resending blocks, the second number is the
|
||||
//number of the retry block, and the first number is the remaining blocks
|
||||
uint8_t pf_num = (uint8_t)ConvertBitIntoBytes(Message+8, 4);
|
||||
uint8_t blk_num = (uint8_t)ConvertBitIntoBytes(Message+12, 4);
|
||||
|
||||
@@ -2783,6 +2766,18 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Part 1-B Basic Operation Ver.2.0 page 34
|
||||
//if this is a retry, we don't have memory of the other pieces, so just nuke it
|
||||
//although, I suppose its possible that, for example, there were originally 4 blocks,
|
||||
//but the retry is going to retry 3,3,2,0 blocks all sequentially, or similar,
|
||||
//and this would potentially miss it, but the CRC32 will determine success then.
|
||||
if (pf_num != blk_num)
|
||||
{
|
||||
fprintf (stderr, "Partial Selective Retry, Previous Delivery Not Retained in Memory; ");
|
||||
state->data_header_valid[0] = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (total_bytes < 4) //this shouldn't even happen in code
|
||||
{
|
||||
fprintf (stderr, "Total Bytes After Padding Less Than Required; ");
|
||||
@@ -2797,7 +2792,7 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
memcpy(state->dmr_pdu_sf[0]+ptr, Message+16, byte_len*8*sizeof(uint8_t));
|
||||
|
||||
//Finished Assembly
|
||||
if (blk_num == 0)
|
||||
if (pf_num == 0)
|
||||
{
|
||||
|
||||
//KS creation and application, if applicable
|
||||
@@ -2933,18 +2928,13 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
if (crc_ext == crc_chk)
|
||||
{
|
||||
uint8_t opcode = (uint8_t)ConvertBitIntoBytes(state->dmr_pdu_sf[0], 8);
|
||||
uint8_t nmea = (uint8_t)ConvertBitIntoBytes(state->dmr_pdu_sf[0]+8, 8);
|
||||
uint32_t reverse = (uint8_t)ConvertBitIntoBytes(state->dmr_pdu_sf[0], 24); //observed 3 bytes of zeroes
|
||||
if (opcode == 0x06)
|
||||
if (opcode == 0x06 && (nmea == '$' || nmea == '!')) //may only need to check one of the other
|
||||
{
|
||||
//String Data Dump if first byte is 0x06 (NMEA sentences observed here)
|
||||
//Check NMEA Sentence
|
||||
fprintf (stderr, "\n ");
|
||||
for (int i = 1; i < total_bytes; i++)
|
||||
{
|
||||
uint8_t ascii = (uint8_t)ConvertBitIntoBytes(state->dmr_pdu_sf[0]+(i*8), 8);
|
||||
if (ascii >= 0x20 && ascii < 0x7F)
|
||||
fprintf (stderr, "%c", ascii);
|
||||
else break;
|
||||
}
|
||||
nmea_sentence_checker(opts, state, state->dmr_pdu_sf[0]+8, 0, total_bytes);
|
||||
}
|
||||
else if (reverse == 0)
|
||||
{
|
||||
@@ -2962,7 +2952,7 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
|
||||
//Debug Data Dump
|
||||
fprintf (stderr, "\n REV: ");
|
||||
for (int i = 0; i < total_bytes-4-4+1; i++) //sans the CRC and the leading zeroes
|
||||
for (int i = 0; i < total_bytes-7; i++) //sans the CRC and the leading zeroes
|
||||
fprintf (stderr, "%02X", reverse_bytes[i]);
|
||||
|
||||
uint8_t reverse_byte_bits[total_bytes*8];
|
||||
@@ -2971,7 +2961,7 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
|
||||
//GPS report on 0xFFFC? or is that just any odd Kenwood message?
|
||||
if ((uint16_t)convert_bits_into_output(reverse_byte_bits, 16) == 0xFFFC)
|
||||
nxdn_gps_report(opts, state, reverse_byte_bits+16, state->nxdn_last_rid); //src is probably reset on cac
|
||||
nxdn_gps_report(opts, state, reverse_byte_bits+16, state->dmr_lrrp_source[0]);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -3000,6 +2990,10 @@ int nxdn_dcall_data(dsd_opts * opts, dsd_state * state, int type, uint8_t * Mess
|
||||
//reset header validity
|
||||
state->data_header_valid[0] = 0;
|
||||
|
||||
//set source and target
|
||||
state->dmr_lrrp_source[0] = 0;
|
||||
state->dmr_lrrp_target[0] = 0;
|
||||
|
||||
//reset encryption variables
|
||||
state->payload_algid = 0;
|
||||
state->payload_keyid = 0;
|
||||
|
||||
@@ -457,8 +457,18 @@ void p25_decode_pdu_data(dsd_opts * opts, dsd_state * state, uint8_t * input, in
|
||||
if (sap == 0 || sap == 4) //User Data or Packet Data (both are UDP typically, same format dmr UDP/IP data)
|
||||
decode_ip_pdu (opts, state, len+1, input+ptr);
|
||||
|
||||
else if (sap == 48) //Tier 1 Location Service (or does it depend on the io bit?)
|
||||
utf8_to_text(state, 1, len-ptr+1, input+ptr); //TODO, read initial string, i.e., $GPRMC and properly decode
|
||||
//NMEA Tier 1 Location Reporting w/ Supplimentary $PP25 string
|
||||
else if (sap == 48)
|
||||
{
|
||||
len += 12; //not sure how we ended up off by up to 12 on this, above negation too much?
|
||||
state->dmr_lrrp_source[state->currentslot] = state->lastsrc;
|
||||
state->dmr_lrrp_source[state->currentslot] = state->lasttg;
|
||||
uint8_t input_bits[(len+1)*8];
|
||||
memset(input_bits, 0, sizeof(input_bits));
|
||||
unpack_byte_array_into_bit_array(input, input_bits, len);
|
||||
fprintf (stderr, "\n ");
|
||||
nmea_sentence_checker(opts, state, input_bits+ptr*8, state->currentslot, len*8);
|
||||
}
|
||||
|
||||
// else //default catch all (debug only)
|
||||
// {
|
||||
|
||||
Reference in New Issue
Block a user