mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-13 01:07:24 -05:00
DCR: Add SB0 Lich Code 0x08 and decode CSM as Alias, if present; #323
NXDN: Fix Type-C SCCH CRC Check (Pass 2); NXDN: Fix CRC12 Issues;
This commit is contained in:
@@ -1274,7 +1274,7 @@ void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint
|
||||
void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[288], uint8_t type);
|
||||
//DCR Mode
|
||||
void nxdn_deperm_sacch2(dsd_opts * opts, dsd_state * state, uint8_t bits[60]);
|
||||
void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144]);
|
||||
void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144], uint8_t lich);
|
||||
//MT and Voice
|
||||
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]);
|
||||
|
||||
@@ -123,11 +123,11 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
|
||||
}
|
||||
|
||||
crc = crc12f (trellis_buf, 84); //80
|
||||
crc = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[84+i]; //80
|
||||
check = check | trellis_buf[80+i];
|
||||
}
|
||||
|
||||
//debug
|
||||
@@ -146,11 +146,11 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
//fill m_data bytes with trellis_buf
|
||||
for(int i = 0; i < 12; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc = crc12f (trellis_buf, 84);
|
||||
crc = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[i+84];
|
||||
check = check | trellis_buf[i+80];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,7 +582,10 @@ void nxdn_deperm_sacch2(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
int bf_idx = sf_full-sf_size; //index position for buffer to superframe
|
||||
|
||||
if (sf_fb && sf_pof) //single unit message
|
||||
{
|
||||
memset (state->dmr_pdu_sf[0], 0, sizeof(state->dmr_pdu_sf[0]));
|
||||
memcpy(state->dmr_pdu_sf[0]+0, trellis_buf+bf_idx, sf_size*sizeof(uint8_t));
|
||||
}
|
||||
else //multiple unit message
|
||||
memcpy(state->dmr_pdu_sf[0]+sf_idx, trellis_buf+bf_idx, sf_size*sizeof(uint8_t));
|
||||
|
||||
@@ -598,8 +601,10 @@ void nxdn_deperm_sacch2(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
state->nxdn_last_ran = 7;
|
||||
state->nxdn_last_tg = 777;
|
||||
state->nxdn_last_rid = 777;
|
||||
sprintf (state->generic_talker_alias[0], "%s", "JPN DCR");
|
||||
sprintf (state->event_history_s[0].Event_History_Items[0].alias, "%s; ", "JPN DCR");
|
||||
|
||||
//disabled with CSM going into Alias Value
|
||||
// sprintf (state->generic_talker_alias[0], "%s", "JPN DCR");
|
||||
// sprintf (state->event_history_s[0].Event_History_Items[0].alias, "%s; ", "JPN DCR");
|
||||
|
||||
//sf_fb is the head message in a multi part, or the only message in a single part message
|
||||
if (sf_fb)
|
||||
@@ -671,12 +676,18 @@ void nxdn_deperm_sacch2(dsd_opts * opts, dsd_state * state, uint8_t bits[60])
|
||||
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
|
||||
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
|
||||
}
|
||||
else if (sf_fb && sf_pof) //single
|
||||
{
|
||||
memset (state->dmr_pdu_sf[0], 0, sizeof(state->dmr_pdu_sf[0]));
|
||||
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
|
||||
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//PICH or TCH 144 bit (JPN DCR)
|
||||
//SEE: https://web.archive.org/web/20150417175725/http://arib.or.jp/english/html/overview/doc/1-STD-T98v1_4.pdf
|
||||
void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144], uint8_t lich)
|
||||
{
|
||||
uint8_t deperm[144]; //144
|
||||
uint8_t depunc[192]; //192
|
||||
@@ -733,11 +744,11 @@ void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
|
||||
}
|
||||
|
||||
crc = crc12f (trellis_buf, 84); //80
|
||||
crc = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[84+i]; //80
|
||||
check = check | trellis_buf[80+i];
|
||||
}
|
||||
|
||||
//debug
|
||||
@@ -756,11 +767,11 @@ void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
//fill m_data bytes with trellis_buf
|
||||
for(int i = 0; i < 12; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc = crc12f (trellis_buf, 84);
|
||||
crc = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[i+84];
|
||||
check = check | trellis_buf[i+80];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,33 +784,72 @@ void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
uint16_t source = (uint16_t)ConvertBitIntoBytes(&trellis_buf[24], 16);
|
||||
uint16_t target = (uint16_t)ConvertBitIntoBytes(&trellis_buf[40], 16);
|
||||
|
||||
//may only be relevant on MFID 0x30 "F.R.C." Radios
|
||||
if (opcode == 0x0F)
|
||||
//SB0 with CSM
|
||||
if (lich == 0x08)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Source: %d; Target: %d; ", source, target);
|
||||
if (gi)
|
||||
fprintf (stderr, "Private; ");
|
||||
else fprintf (stderr, "Group; ");
|
||||
|
||||
fprintf (stderr, "Data Preamble; ");
|
||||
uint8_t countdown = (uint8_t)ConvertBitIntoBytes(&trellis_buf[64], 8);
|
||||
fprintf (stderr, "Countdown: %d; ", countdown);
|
||||
unsigned long long int csm = 0;
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
csm <<= 4;
|
||||
uint8_t bcd = (uint8_t)ConvertBitIntoBytes(&trellis_buf[0+(i*4)], 4);
|
||||
|
||||
// if (bcd < 10)
|
||||
// csm |= bcd;
|
||||
// else csm |= 0;
|
||||
|
||||
csm |= bcd;
|
||||
}
|
||||
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Call Sign Memory: %09llX; ", csm);
|
||||
|
||||
//Assigning this to talker alias, see notes below on decimal value
|
||||
sprintf (state->generic_talker_alias[0], "CSM %09llX", csm);
|
||||
sprintf (state->event_history_s[0].Event_History_Items[0].alias, "CSM %09llX", csm);
|
||||
|
||||
//convert from hex to string to decimal w/ sscanf
|
||||
// char csm_str[32]; memset(csm_str, 0, sizeof(csm_str));
|
||||
// sprintf (csm_str, "%llX", csm);
|
||||
// unsigned long long int csm_dec = 0;
|
||||
// sscanf(csm_str, "%lld", &csm_dec);
|
||||
|
||||
//the issue is that this value will exceed the bit allotment for nxdn src value (needs long long at 36-bit)
|
||||
//even values in range 100000000 - 200000000 are 33-bits minimum
|
||||
// fprintf (stderr, "Call Sign Memory: %09lld; ", csm_dec);
|
||||
}
|
||||
|
||||
//may only be relevant on MFID 0x30 "F.R.C." Radios
|
||||
if (opcode == 0x32)
|
||||
//anything else
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Source: %d; Target: %d; ", source, target);
|
||||
if (gi)
|
||||
fprintf (stderr, "Private; ");
|
||||
else fprintf (stderr, "Group; ");
|
||||
|
||||
fprintf (stderr, "Precoded Message; ");
|
||||
uint8_t idx = (uint8_t)ConvertBitIntoBytes(&trellis_buf[64], 8);
|
||||
fprintf (stderr, "Index#: %d;", idx);
|
||||
|
||||
//may only be relevant on MFID 0x30 "F.R.C." Radios
|
||||
if (opcode == 0x0F)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Source: %d; Target: %d; ", source, target);
|
||||
if (gi)
|
||||
fprintf (stderr, "Private; ");
|
||||
else fprintf (stderr, "Group; ");
|
||||
|
||||
fprintf (stderr, "Data Preamble; ");
|
||||
uint8_t countdown = (uint8_t)ConvertBitIntoBytes(&trellis_buf[64], 8);
|
||||
fprintf (stderr, "Countdown: %d; ", countdown);
|
||||
|
||||
}
|
||||
|
||||
//may only be relevant on MFID 0x30 "F.R.C." Radios
|
||||
if (opcode == 0x32)
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "Source: %d; Target: %d; ", source, target);
|
||||
if (gi)
|
||||
fprintf (stderr, "Private; ");
|
||||
else fprintf (stderr, "Group; ");
|
||||
|
||||
fprintf (stderr, "Precoded Message; ");
|
||||
uint8_t idx = (uint8_t)ConvertBitIntoBytes(&trellis_buf[64], 8);
|
||||
fprintf (stderr, "Index#: %d;", idx);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -813,14 +863,18 @@ void nxdn_deperm_pich_tch(dsd_opts * opts, dsd_state * state, uint8_t bits[144])
|
||||
{
|
||||
fprintf (stderr, "\n ");
|
||||
fprintf (stderr, "%s", KRED);
|
||||
fprintf (stderr, "TCH (CRC ERR)");
|
||||
if (lich == 0x08)
|
||||
fprintf (stderr, "PICH (CRC ERR)");
|
||||
else fprintf (stderr, "TCH (CRC ERR)");
|
||||
fprintf (stderr, "%s", KNRM);
|
||||
}
|
||||
|
||||
if (opts->payload == 1)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
fprintf (stderr, " TCH Payload ");
|
||||
if (lich == 0x08)
|
||||
fprintf (stderr, " PICH Payload ");
|
||||
else fprintf (stderr, " TCH Payload ");
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
fprintf (stderr, "[%02X]", m_data[i]);
|
||||
@@ -1301,7 +1355,7 @@ void nxdn_deperm_scch(dsd_opts * opts, dsd_state * state, uint8_t bits[60], uint
|
||||
for(int i = 0; i < 4; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc = crc7_scch(trellis_buf, 25);
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
check = check << 1;
|
||||
check = check | trellis_buf[i+25];
|
||||
@@ -1435,11 +1489,11 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
|
||||
trellis_buf[(i*8)+7] = (m_data[i] >> 0) & 1;
|
||||
}
|
||||
|
||||
crc[j] = crc12f (trellis_buf, 84); //84
|
||||
crc[j] = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check[j] = check[j] << 1;
|
||||
check[j] = check[j] | trellis_buf[84+i]; //84
|
||||
check[j] = check[j] | trellis_buf[80+i];
|
||||
|
||||
}
|
||||
|
||||
@@ -1459,11 +1513,11 @@ void nxdn_deperm_facch3_udch2(dsd_opts * opts, dsd_state * state, uint8_t bits[2
|
||||
//fill m_data bytes with trellis_buf
|
||||
for(int i = 0; i < 12; i++)
|
||||
m_data[i] = (uint8_t)ConvertBitIntoBytes(&trellis_buf[i*8], 8);
|
||||
crc[j] = crc12f (trellis_buf, 84);
|
||||
crc[j] = crc12f (trellis_buf, 80);
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
check[j] = check[j] << 1;
|
||||
check[j] = check[j] | trellis_buf[i+84];
|
||||
check[j] = check[j] | trellis_buf[i+80];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
|
||||
lich = lich_full >> 1;
|
||||
|
||||
//special cases on DCR where parity is computed over 7 bits, and not 4 bits
|
||||
if (lich == 0x4A || lich == 0x48 || lich == 0x46)
|
||||
if (lich == 0x08 || lich == 0x4A || lich == 0x48 || lich == 0x46)
|
||||
lich_parity_computed = ((lich_full >> 7) + (lich_full >> 6) + (lich_full >> 5) + (lich_full >> 4) + (lich_full >> 3) + (lich_full >> 2) + (lich_full >> 1)) & 1;
|
||||
|
||||
if (lich_parity_received != lich_parity_computed)
|
||||
@@ -223,9 +223,13 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
|
||||
sacch2 = 1;
|
||||
break;
|
||||
|
||||
//DCR Data or End Frame
|
||||
//DCR SB0, Data or End Frame
|
||||
case 0x08: //SB0 w/ CSM 9 digit BCD found here
|
||||
sacch2 = 1;
|
||||
pich_tch = 1; //observed 2nd PICH is zero fill
|
||||
break;
|
||||
case 0x48:
|
||||
pich_tch = 3;
|
||||
pich_tch = 3; //may be 1, or 2 TCH (observed possibly both)
|
||||
case 0x4A:
|
||||
sacch2 = 1;
|
||||
break;
|
||||
@@ -561,8 +565,8 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state)
|
||||
|
||||
//DCR
|
||||
if (sacch2) nxdn_deperm_sacch2(opts, state, sacch_bits);
|
||||
if (pich_tch & 1) nxdn_deperm_pich_tch(opts, state, facch_bits_a);
|
||||
if (pich_tch & 2) nxdn_deperm_pich_tch(opts, state, facch_bits_b);
|
||||
if (pich_tch & 1) nxdn_deperm_pich_tch(opts, state, facch_bits_a, lich);
|
||||
if (pich_tch & 2) nxdn_deperm_pich_tch(opts, state, facch_bits_b, lich);
|
||||
|
||||
//only run facch in second slot if its not equal to the first one
|
||||
//ideally, this would work better AFTER decoding/FEC
|
||||
|
||||
Reference in New Issue
Block a user