More work with decoding and regenerating P25.

This commit is contained in:
Jonathan Naylor 2016-09-13 18:27:50 +01:00
parent 30467a749c
commit 0dc1f1bdad
22 changed files with 442 additions and 156 deletions

View File

@ -179,6 +179,54 @@ void CHamming::encode1393(bool* d)
d[12] = d[0] ^ d[2] ^ d[4] ^ d[5] ^ d[8];
}
// Hamming (10,6,3) check a boolean data array
bool CHamming::decode1063(bool* d)
{
assert(d != NULL);
// Calculate the checksum this column should have
bool c0 = d[0] ^ d[1] ^ d[2] ^ d[5];
bool c1 = d[0] ^ d[1] ^ d[3] ^ d[5];
bool c2 = d[0] ^ d[2] ^ d[3] ^ d[4];
bool c3 = d[1] ^ d[2] ^ d[3] ^ d[4];
unsigned char n = 0x00U;
n |= (c0 != d[6]) ? 0x01U : 0x00U;
n |= (c1 != d[7]) ? 0x02U : 0x00U;
n |= (c2 != d[8]) ? 0x04U : 0x00U;
n |= (c3 != d[9]) ? 0x08U : 0x00U;
switch (n) {
// Parity bit errors
case 0x01U: d[6] = !d[6]; return true;
case 0x02U: d[7] = !d[7]; return true;
case 0x04U: d[8] = !d[8]; return true;
case 0x08U: d[9] = !d[9]; return true;
// Data bit erros
case 0x07U: d[0] = !d[0]; return true;
case 0x0BU: d[1] = !d[1]; return true;
case 0x0DU: d[2] = !d[2]; return true;
case 0x0EU: d[3] = !d[3]; return true;
case 0x0CU: d[4] = !d[4]; return true;
case 0x03U: d[5] = !d[5]; return true;
// No bit errors
default: return false;
}
}
void CHamming::encode1063(bool* d)
{
assert(d != NULL);
// Calculate the checksum this column should have
d[6] = d[0] ^ d[1] ^ d[2] ^ d[5];
d[7] = d[0] ^ d[1] ^ d[3] ^ d[5];
d[8] = d[0] ^ d[2] ^ d[3] ^ d[4];
d[9] = d[1] ^ d[2] ^ d[3] ^ d[4];
}
// A Hamming (16,11,4) Check
bool CHamming::decode16114(bool* d)
{

View File

@ -30,6 +30,9 @@ public:
static void encode1393(bool* d);
static bool decode1393(bool* d);
static void encode1063(bool* d);
static bool decode1063(bool* d);
static void encode16114(bool* d);
static bool decode16114(bool* d);

View File

@ -47,7 +47,7 @@ TXLevel=50
OscOffset=0
RSSIMultiplier=1
RSSIOffset=10
Debug=1
Debug=0
[D-Star]
Enable=1

View File

@ -185,7 +185,9 @@
<ClInclude Include="P25Control.h" />
<ClInclude Include="P25Defines.h" />
<ClInclude Include="P25Data.h" />
<ClInclude Include="P25LowSpeedData.h" />
<ClInclude Include="P25NID.h" />
<ClInclude Include="P25Utils.h" />
<ClInclude Include="QR1676.h" />
<ClInclude Include="RingBuffer.h" />
<ClInclude Include="RS129.h" />
@ -242,7 +244,9 @@
<ClCompile Include="P25Audio.cpp" />
<ClCompile Include="P25Control.cpp" />
<ClCompile Include="P25Data.cpp" />
<ClCompile Include="P25LowSpeedData.cpp" />
<ClCompile Include="P25NID.cpp" />
<ClCompile Include="P25Utils.cpp" />
<ClCompile Include="QR1676.cpp" />
<ClCompile Include="RS129.cpp" />
<ClCompile Include="SerialController.cpp" />

View File

@ -188,6 +188,12 @@
<ClInclude Include="P25Data.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="P25LowSpeedData.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPTC19696.cpp">
@ -346,5 +352,11 @@
<ClCompile Include="P25Data.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="P25LowSpeedData.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -9,8 +9,8 @@ LDFLAGS = -g
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o Log.o MMDVMHost.o \
Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o \
Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o Log.o \
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o \
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o \
StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o Log.o \
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o \
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o \
StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o OLED.o Log.o \
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o \
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o \
StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o Log.o \
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o \
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
MMDVMHost.o Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o \
StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -9,8 +9,8 @@ LDFLAGS = -g
OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLookup.o DMRLC.o \
DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o Log.o MMDVMHost.o \
Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25NID.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
Modem.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25NID.o P25Utils.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o \
Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost

View File

@ -17,15 +17,11 @@
*/
#include "P25Audio.h"
#include "P25Utils.h"
#include <cstdio>
#include <cassert>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CP25Audio::CP25Audio() :
m_fec()
{
@ -43,65 +39,41 @@ unsigned int CP25Audio::process(unsigned char* data)
unsigned char imbe[18U];
read(data, imbe, 114U, 262U, 142U, 143U, 214U, 215U);
CP25Utils::decode(data, imbe, 114U, 262U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 114U, 262U, 142U, 143U, 214U, 215U);
CP25Utils::encode(imbe, data, 114U, 262U);
read(data, imbe, 262U, 410U, 286U, 287U, 358U, 359U);
CP25Utils::decode(data, imbe, 262U, 410U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 262U, 410U, 286U, 287U, 358U, 359U);
CP25Utils::encode(imbe, data, 262U, 410U);
read(data, imbe, 452U, 600U, 502U, 503U, 574U, 575U);
CP25Utils::decode(data, imbe, 452U, 600U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 452U, 600U, 502U, 503U, 574U, 575U);
CP25Utils::encode(imbe, data, 452U, 600U);
read(data, imbe, 640U, 788U, 646U, 647U, 718U, 719U);
CP25Utils::decode(data, imbe, 640U, 788U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 640U, 788U, 646U, 647U, 718U, 719U);
CP25Utils::encode(imbe, data, 640U, 788U);
read(data, imbe, 830U, 978U, 862U, 863U, 934U, 935U);
CP25Utils::decode(data, imbe, 830U, 978U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 830U, 978U, 862U, 863U, 934U, 935U);
CP25Utils::encode(imbe, data, 830U, 978U);
read(data, imbe, 1020U, 1168U, 1078U, 1079U, 1150U, 1151U);
CP25Utils::decode(data, imbe, 1020U, 1168U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 1020U, 1168U, 1078U, 1079U, 1150U, 1151U);
CP25Utils::encode(imbe, data, 1020U, 1168U);
read(data, imbe, 1208U, 1356U, 1222U, 1223U, 1294U, 1295U);
CP25Utils::decode(data, imbe, 1208U, 1356U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 1208U, 1356U, 1222U, 1223U, 1294U, 1295U);
CP25Utils::encode(imbe, data, 1208U, 1356U);
read(data, imbe, 1398U, 1546U, 1438U, 1439U, 1510U, 1511U);
CP25Utils::decode(data, imbe, 1398U, 1546U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 1398U, 1546U, 1438U, 1439U, 1510U, 1511U);
CP25Utils::encode(imbe, data, 1398U, 1546U);
read(data, imbe, 1578U, 1726U, 1582U, 1583U, 1654U, 1655U);
CP25Utils::decode(data, imbe, 1578U, 1726U);
errs += m_fec.regenerateIMBE(imbe);
write(data, imbe, 1578U, 1726U, 1582U, 1583U, 1654U, 1655U);
CP25Utils::encode(imbe, data, 1578U, 1726U);
return errs;
}
void CP25Audio::read(const unsigned char* data, unsigned char* out, unsigned int start, unsigned int stop, unsigned int avoid1, unsigned int avoid2, unsigned int avoid3, unsigned int avoid4)
{
unsigned int n = 0U;
for (unsigned int offset = start; offset < stop; offset++) {
if (offset != avoid1 && offset != avoid2 && offset != avoid3 && offset != avoid4) {
bool b = READ_BIT(data, offset);
WRITE_BIT(out, n, b);
n++;
}
}
}
void CP25Audio::write(unsigned char* data, const unsigned char* in, unsigned int start, unsigned int stop, unsigned int avoid1, unsigned int avoid2, unsigned int avoid3, unsigned int avoid4)
{
unsigned int n = 0U;
for (unsigned int offset = start; offset < stop; offset++) {
if (offset != avoid1 && offset != avoid2 && offset != avoid3 && offset != avoid4) {
bool b = READ_BIT(in, n);
WRITE_BIT(data, offset, b);
n++;
}
}
}

View File

@ -30,9 +30,6 @@ public:
private:
CAMBEFEC m_fec;
void read(const unsigned char* data, unsigned char* out, unsigned int start, unsigned int stop, unsigned int avoid1, unsigned int avoid2, unsigned int avoid3, unsigned int avoid4);
void write(unsigned char* data, const unsigned char* in, unsigned int start, unsigned int stop, unsigned int avoid1, unsigned int avoid2, unsigned int avoid3, unsigned int avoid4);
};
#endif

View File

@ -17,6 +17,7 @@
*/
#include "P25Control.h"
#include "P25LowSpeedData.h"
#include "P25Defines.h"
#include "Sync.h"
#include "Log.h"
@ -62,7 +63,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
{
assert(data != NULL);
CUtils::dump(1U, "P25 Data", data, len);
// CUtils::dump(1U, "P25 Data", data, len);
bool sync = data[1U] == 0x01U;
@ -129,6 +130,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
// Regenerate LDU1 Data
m_rfData.processLDU1(data + 2U);
// Regenerate the Low Speed Data
CP25LowSpeedData::process(data + 2U);
// Regenerate Audio
unsigned int errors = m_audio.process(data + 2U);
LogDebug("P25, LDU1 audio, errs: %u/1233", errors);
@ -159,13 +163,14 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
if (m_rfState == RS_RF_LISTENING)
return false;
// Decode LDU2
m_rfData.processLDU2(data + 2U);
// Regenerate Sync
CSync::addP25Sync(data + 2U);
// Regenerate LDU2 Data
m_rfData.processLDU2(data + 2U);
// Regenerate the Low Speed Data
CP25LowSpeedData::process(data + 2U);
// Regenerate Audio
unsigned int errors = m_audio.process(data + 2U);

View File

@ -17,6 +17,10 @@
*/
#include "P25Data.h"
#include "P25Defines.h"
#include "P25Utils.h"
#include "Hamming.h"
#include "Utils.h"
#include "Log.h"
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
@ -37,96 +41,130 @@ CP25Data::~CP25Data()
void CP25Data::processHeader(unsigned char* data)
{
unsigned char raw[81U];
CP25Utils::decode(data, raw, 114U, 780U);
CUtils::dump(1U, "P25, raw header", raw, 81U);
// XXX Need to add FEC code
}
void CP25Data::processLDU1(unsigned char* data)
{
// XXX No FEC done yet
bool b[24U];
b[7U] = READ_BIT(data, 411U);
b[6U] = READ_BIT(data, 410U);
b[5U] = READ_BIT(data, 413U);
b[4U] = READ_BIT(data, 412U);
b[3U] = READ_BIT(data, 415U);
b[2U] = READ_BIT(data, 414U);
b[1U] = READ_BIT(data, 421U);
b[0U] = READ_BIT(data, 420U);
unsigned char rs[18U];
unsigned char format = 0U;
unsigned char mult = 1U;
for (unsigned int i = 0U; i < 8U; i++, mult <<= 1)
format += b[i] ? mult : 0U;
unsigned char raw[5U];
CP25Utils::decode(data, raw, 410U, 452U);
decodeLDUHamming(raw, rs + 0U);
LogDebug("P25, LC_format = $%02X", format);
CP25Utils::decode(data, raw, 600U, 640U);
decodeLDUHamming(raw, rs + 3U);
if (format == 0x03U) {
LogDebug("P25, non talk group destination");
m_group = false;
} else {
m_group = true;
CP25Utils::decode(data, raw, 788U, 830U);
decodeLDUHamming(raw, rs + 6U);
b[15U] = READ_BIT(data, 613U); // 39
b[14U] = READ_BIT(data, 612U);
b[13U] = READ_BIT(data, 615U); // 37
b[12U] = READ_BIT(data, 614U);
b[11U] = READ_BIT(data, 621U); // 35
b[10U] = READ_BIT(data, 620U);
b[9U] = READ_BIT(data, 623U); // 33
b[8U] = READ_BIT(data, 622U);
b[7U] = READ_BIT(data, 625U); // 31
b[6U] = READ_BIT(data, 624U);
b[5U] = READ_BIT(data, 631U); // 29
b[4U] = READ_BIT(data, 630U);
b[3U] = READ_BIT(data, 633U); // 27
b[2U] = READ_BIT(data, 632U);
b[1U] = READ_BIT(data, 635U);
b[0U] = READ_BIT(data, 634U); // 24
CP25Utils::decode(data, raw, 978U, 1020U);
decodeLDUHamming(raw, rs + 9U);
mult = 1U;
for (unsigned int i = 0U; i < 16U; i++, mult <<= 1)
m_dest += b[i] ? mult : 0U;
CP25Utils::decode(data, raw, 1168U, 1208U);
decodeLDUHamming(raw, rs + 12U);
LogDebug("P25, TG ID = %u", m_dest);
CP25Utils::decode(data, raw, 1356U, 1398U);
decodeLDUHamming(raw, rs + 15U);
CUtils::dump(1U, "P25, LDU1 Data after Hamming", rs, 18U);
switch (rs[0U]) {
case P25_LCF_GROUP:
m_dest = (rs[4U] << 8) + rs[5U];
m_source = (rs[6U] << 16) + (rs[7U] << 8) + rs[8U];
m_group = true;
break;
case P25_LCF_PRIVATE:
m_dest = (rs[3U] << 16) + (rs[4U] << 8) + rs[5U];
m_source = (rs[6U] << 16) + (rs[7U] << 8) + rs[8U];
m_group = false;
break;
default:
LogMessage("P25, unknown LCF value in LDU1 - $%02X", rs[0U]);
break;
}
b[23U] = READ_BIT(data, 789U);
b[22U] = READ_BIT(data, 788U);
b[21U] = READ_BIT(data, 793U);
b[20U] = READ_BIT(data, 792U);
b[19U] = READ_BIT(data, 795U);
b[18U] = READ_BIT(data, 794U);
b[17U] = READ_BIT(data, 801U);
b[16U] = READ_BIT(data, 800U);
b[15U] = READ_BIT(data, 803U);
b[14U] = READ_BIT(data, 802U);
b[13U] = READ_BIT(data, 805U);
b[12U] = READ_BIT(data, 804U);
b[11U] = READ_BIT(data, 811U);
b[10U] = READ_BIT(data, 810U);
b[9U] = READ_BIT(data, 813U);
b[8U] = READ_BIT(data, 812U);
b[7U] = READ_BIT(data, 815U);
b[6U] = READ_BIT(data, 814U);
b[5U] = READ_BIT(data, 821U);
b[4U] = READ_BIT(data, 820U);
b[3U] = READ_BIT(data, 823U);
b[2U] = READ_BIT(data, 822U);
b[1U] = READ_BIT(data, 825U);
b[0U] = READ_BIT(data, 824U);
// XXX Need to add FEC code
mult = 1U;
for (unsigned int i = 0U; i < 24U; i++, mult <<= 1)
m_source += b[i] ? mult : 0U;
encodeLDUHamming(raw, rs + 0U);
CP25Utils::encode(raw, data, 410U, 452U);
LogDebug("P25, SRC ID = %u", m_source);
encodeLDUHamming(raw, rs + 3U);
CP25Utils::encode(raw, data, 600U, 640U);
encodeLDUHamming(raw, rs + 6U);
CP25Utils::encode(raw, data, 788U, 830U);
encodeLDUHamming(raw, rs + 9U);
CP25Utils::encode(raw, data, 978U, 1020U);
encodeLDUHamming(raw, rs + 12U);
CP25Utils::encode(raw, data, 1168U, 1208U);
encodeLDUHamming(raw, rs + 15U);
CP25Utils::encode(raw, data, 1356U, 1398U);
}
void CP25Data::processLDU2(unsigned char* data)
{
unsigned char rs[18U];
unsigned char raw[5U];
CP25Utils::decode(data, raw, 410U, 452U);
decodeLDUHamming(raw, rs + 0U);
CP25Utils::decode(data, raw, 600U, 640U);
decodeLDUHamming(raw, rs + 3U);
CP25Utils::decode(data, raw, 788U, 830U);
decodeLDUHamming(raw, rs + 6U);
CP25Utils::decode(data, raw, 978U, 1020U);
decodeLDUHamming(raw, rs + 9U);
CP25Utils::decode(data, raw, 1168U, 1208U);
decodeLDUHamming(raw, rs + 12U);
CP25Utils::decode(data, raw, 1356U, 1398U);
decodeLDUHamming(raw, rs + 15U);
CUtils::dump(1U, "P25, LDU2 Data after Hamming", rs, 18U);
// XXX Need to add FEC code
encodeLDUHamming(raw, rs + 0U);
CP25Utils::encode(raw, data, 410U, 452U);
encodeLDUHamming(raw, rs + 3U);
CP25Utils::encode(raw, data, 600U, 640U);
encodeLDUHamming(raw, rs + 6U);
CP25Utils::encode(raw, data, 788U, 830U);
encodeLDUHamming(raw, rs + 9U);
CP25Utils::encode(raw, data, 978U, 1020U);
encodeLDUHamming(raw, rs + 12U);
CP25Utils::encode(raw, data, 1168U, 1208U);
encodeLDUHamming(raw, rs + 15U);
CP25Utils::encode(raw, data, 1356U, 1398U);
}
void CP25Data::processTerminator(unsigned char* data)
{
unsigned char raw[36U];
CP25Utils::decode(data, raw, 114U, 210U);
CUtils::dump(1U, "P25, raw terminator", raw, 36U);
// XXX Need to add FEC code, or do we?
}
unsigned int CP25Data::getSource() const
@ -149,3 +187,45 @@ void CP25Data::reset()
m_source = 0U;
m_dest = 0U;
}
void CP25Data::decodeLDUHamming(const unsigned char* data, unsigned char* raw)
{
unsigned int n = 0U;
unsigned int m = 0U;
for (unsigned int i = 0U; i < 4U; i++) {
bool hamming[10U];
for (unsigned int j = 0U; j < 10U; j++) {
hamming[j] = READ_BIT(data, n);
n++;
}
CHamming::decode1063(hamming);
for (unsigned int j = 0U; j < 6U; j++) {
WRITE_BIT(raw, m, hamming[j]);
m++;
}
}
}
void CP25Data::encodeLDUHamming(unsigned char* data, const unsigned char* raw)
{
unsigned int n = 0U;
unsigned int m = 0U;
for (unsigned int i = 0U; i < 4U; i++) {
bool hamming[10U];
for (unsigned int j = 0U; j < 6U; j++) {
hamming[j] = READ_BIT(raw, m);
m++;
}
CHamming::encode1063(hamming);
for (unsigned int j = 0U; j < 10U; j++) {
WRITE_BIT(data, n, hamming[j]);
n++;
}
}
}

View File

@ -43,6 +43,9 @@ private:
unsigned int m_source;
bool m_group;
unsigned int m_dest;
void decodeLDUHamming(const unsigned char* raw, unsigned char* data);
void encodeLDUHamming(unsigned char* data, const unsigned char* raw);
};
#endif

View File

@ -37,6 +37,9 @@ const unsigned int P25_NID_LENGTH_BYTES = 8U;
const unsigned char P25_SYNC_BYTES[] = {0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU};
const unsigned char P25_SYNC_BYTES_LENGTH = 6U;
const unsigned char P25_LCF_GROUP = 0x00U;
const unsigned char P25_LCF_PRIVATE = 0x03U;
const unsigned int P25_SS0_START = 70U;
const unsigned int P25_SS1_START = 71U;
const unsigned int P25_SS_INCREMENT = 72U;

33
P25LowSpeedData.cpp Normal file
View File

@ -0,0 +1,33 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "P25LowSpeedData.h"
#include "P25Utils.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
void CP25LowSpeedData::process(unsigned char* data)
{
unsigned char lsd[4U];
CP25Utils::decode(data, lsd, 1546U, 1578U);
CUtils::dump(1U, "P25, Low Speed Data", lsd, 4U);
}

29
P25LowSpeedData.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(P25LowSpeedData_H)
#define P25LowSpeedData_H
class CP25LowSpeedData {
public:
static void process(unsigned char* data);
private:
};
#endif

View File

@ -18,15 +18,11 @@
#include "P25NID.h"
#include "P25Defines.h"
#include "P25Utils.h"
#include <cstdio>
#include <cassert>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CP25NID::CP25NID() :
m_duid(0U),
m_nac(0U)
@ -43,14 +39,7 @@ void CP25NID::process(unsigned char* data)
unsigned char nid[P25_NID_LENGTH_BYTES];
unsigned int n = 0U;
for (unsigned int offset = 48U; offset < 114U; offset++) {
if (offset != P25_SS0_START && offset != P25_SS1_START) {
bool b = READ_BIT(data, offset);
WRITE_BIT(nid, n, b);
n++;
}
}
CP25Utils::decode(data, nid, 48U, 114U);
// XXX Process FEC here
@ -59,14 +48,7 @@ void CP25NID::process(unsigned char* data)
m_nac = (nid[0U] << 4) & 0xFF0U;
m_nac |= (nid[1U] >> 4) & 0x00FU;
n = 0U;
for (unsigned int offset = 48U; offset < 114U; offset++) {
if (offset != P25_SS0_START && offset != P25_SS1_START) {
bool b = READ_BIT(nid, n);
WRITE_BIT(data, offset, b);
n++;
}
}
CP25Utils::encode(nid, data, 48U, 114U);
}
unsigned char CP25NID::getDUID() const

84
P25Utils.cpp Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "P25Utils.h"
#include "P25Defines.h"
#include <cstdio>
#include <cassert>
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
void CP25Utils::decode(const unsigned char* in, unsigned char* out, unsigned int start, unsigned int stop)
{
assert(in != NULL);
assert(out != NULL);
// Move the SSx positions to the range needed
unsigned int ss0Pos = P25_SS0_START;
unsigned int ss1Pos = P25_SS1_START;
while (ss0Pos < start) {
ss0Pos += P25_SS_INCREMENT;
ss1Pos += P25_SS_INCREMENT;
}
unsigned int n = 0U;
for (unsigned int i = start; i < stop; i++) {
if (i == ss0Pos) {
ss0Pos += P25_SS_INCREMENT;
} else if (i == ss1Pos) {
ss1Pos += P25_SS_INCREMENT;
} else {
bool b = READ_BIT(in, i);
WRITE_BIT(out, n, b);
n++;
}
}
}
void CP25Utils::encode(const unsigned char* in, unsigned char* out, unsigned int start, unsigned int stop)
{
assert(in != NULL);
assert(out != NULL);
// Move the SSx positions to the range needed
unsigned int ss0Pos = P25_SS0_START;
unsigned int ss1Pos = P25_SS1_START;
while (ss0Pos < start) {
ss0Pos += P25_SS_INCREMENT;
ss1Pos += P25_SS_INCREMENT;
}
unsigned int n = 0U;
for (unsigned int i = start; i < stop; i++) {
if (i == ss0Pos) {
ss0Pos += P25_SS_INCREMENT;
} else if (i == ss1Pos) {
ss1Pos += P25_SS_INCREMENT;
} else {
bool b = READ_BIT(in, n);
WRITE_BIT(out, i, b);
n++;
}
}
}

31
P25Utils.h Normal file
View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(P25Utils_H)
#define P25Utils_H
class CP25Utils {
public:
static void encode(const unsigned char* in, unsigned char* out, unsigned int start, unsigned int stop);
static void decode(const unsigned char* in, unsigned char* out, unsigned int start, unsigned int stop);
private:
};
#endif