A semi-working P25 repeater without much FEC.
This commit is contained in:
parent
7171af365d
commit
34e0d10343
29 changed files with 713 additions and 74 deletions
|
@ -596,7 +596,7 @@ unsigned int CAMBEFEC::regenerateDStar(unsigned char* bytes) const
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CAMBEFEC::regenerateYSF1(unsigned char* bytes) const
|
unsigned int CAMBEFEC::regenerateYSFDN(unsigned char* bytes) const
|
||||||
{
|
{
|
||||||
assert(bytes != NULL);
|
assert(bytes != NULL);
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ unsigned int CAMBEFEC::regenerateYSF1(unsigned char* bytes) const
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CAMBEFEC::regenerateYSF3(unsigned char* bytes) const
|
unsigned int CAMBEFEC::regenerateIMBE(unsigned char* bytes) const
|
||||||
{
|
{
|
||||||
assert(bytes != NULL);
|
assert(bytes != NULL);
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,9 @@ public:
|
||||||
|
|
||||||
unsigned int regenerateDStar(unsigned char* bytes) const;
|
unsigned int regenerateDStar(unsigned char* bytes) const;
|
||||||
|
|
||||||
unsigned int regenerateYSF1(unsigned char* bytes) const;
|
unsigned int regenerateYSFDN(unsigned char* bytes) const;
|
||||||
|
|
||||||
unsigned int regenerateYSF3(unsigned char* bytes) const;
|
unsigned int regenerateIMBE(unsigned char* bytes) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const;
|
unsigned int regenerate(unsigned int& a, unsigned int& b, unsigned int& c, bool b23) const;
|
||||||
|
|
10
Conf.cpp
10
Conf.cpp
|
@ -111,7 +111,7 @@ m_dmrCallHang(3U),
|
||||||
m_dmrTXHang(4U),
|
m_dmrTXHang(4U),
|
||||||
m_fusionEnabled(true),
|
m_fusionEnabled(true),
|
||||||
m_p25Enabled(true),
|
m_p25Enabled(true),
|
||||||
m_p25Id(0U),
|
m_p25NAC(0x293U),
|
||||||
m_dstarNetworkEnabled(true),
|
m_dstarNetworkEnabled(true),
|
||||||
m_dstarGatewayAddress(),
|
m_dstarGatewayAddress(),
|
||||||
m_dstarGatewayPort(0U),
|
m_dstarGatewayPort(0U),
|
||||||
|
@ -438,8 +438,8 @@ bool CConf::read()
|
||||||
} else if (section == SECTION_P25) {
|
} else if (section == SECTION_P25) {
|
||||||
if (::strcmp(key, "Enable") == 0)
|
if (::strcmp(key, "Enable") == 0)
|
||||||
m_p25Enabled = ::atoi(value) == 1;
|
m_p25Enabled = ::atoi(value) == 1;
|
||||||
else if (::strcmp(key, "Id") == 0)
|
else if (::strcmp(key, "NAC") == 0)
|
||||||
m_p25Id = (unsigned int)::atoi(value);
|
m_p25NAC = (unsigned int)::strtoul(value, NULL, 16);
|
||||||
} else if (section == SECTION_DSTAR_NETWORK) {
|
} else if (section == SECTION_DSTAR_NETWORK) {
|
||||||
if (::strcmp(key, "Enable") == 0)
|
if (::strcmp(key, "Enable") == 0)
|
||||||
m_dstarNetworkEnabled = ::atoi(value) == 1;
|
m_dstarNetworkEnabled = ::atoi(value) == 1;
|
||||||
|
@ -849,9 +849,9 @@ bool CConf::getP25Enabled() const
|
||||||
return m_p25Enabled;
|
return m_p25Enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int CConf::getP25Id() const
|
unsigned int CConf::getP25NAC() const
|
||||||
{
|
{
|
||||||
return m_p25Id;
|
return m_p25NAC;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CConf::getDStarNetworkEnabled() const
|
bool CConf::getDStarNetworkEnabled() const
|
||||||
|
|
4
Conf.h
4
Conf.h
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
// The P25 section
|
// The P25 section
|
||||||
bool getP25Enabled() const;
|
bool getP25Enabled() const;
|
||||||
unsigned int getP25Id() const;
|
unsigned int getP25NAC() const;
|
||||||
|
|
||||||
// The D-Star Network section
|
// The D-Star Network section
|
||||||
bool getDStarNetworkEnabled() const;
|
bool getDStarNetworkEnabled() const;
|
||||||
|
@ -243,7 +243,7 @@ private:
|
||||||
bool m_fusionEnabled;
|
bool m_fusionEnabled;
|
||||||
|
|
||||||
bool m_p25Enabled;
|
bool m_p25Enabled;
|
||||||
unsigned int m_p25Id;
|
unsigned int m_p25NAC;
|
||||||
|
|
||||||
bool m_dstarNetworkEnabled;
|
bool m_dstarNetworkEnabled;
|
||||||
std::string m_dstarGatewayAddress;
|
std::string m_dstarGatewayAddress;
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF, const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRIPSC* network, CDisplay* display, bool duplex, const std::string& lookupFile, int rssiMultiplier, int rssiOffset, unsigned int jitter) :
|
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF, const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRIPSC* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter) :
|
||||||
m_id(id),
|
m_id(id),
|
||||||
m_colorCode(colorCode),
|
m_colorCode(colorCode),
|
||||||
m_selfOnly(selfOnly),
|
m_selfOnly(selfOnly),
|
||||||
|
@ -30,15 +30,13 @@ m_modem(modem),
|
||||||
m_network(network),
|
m_network(network),
|
||||||
m_slot1(1U, timeout),
|
m_slot1(1U, timeout),
|
||||||
m_slot2(2U, timeout),
|
m_slot2(2U, timeout),
|
||||||
m_lookup(NULL)
|
m_lookup(lookup)
|
||||||
{
|
{
|
||||||
assert(modem != NULL);
|
assert(modem != NULL);
|
||||||
assert(display != NULL);
|
assert(display != NULL);
|
||||||
|
assert(lookup != NULL);
|
||||||
|
|
||||||
m_lookup = new CDMRLookup(lookupFile);
|
CDMRSlot::init(id, colorCode, callHang, selfOnly, prefixes, blackList, DstIdBlacklistSlot1RF, DstIdWhitelistSlot1RF, DstIdBlacklistSlot2RF, DstIdWhitelistSlot2RF, DstIdBlacklistSlot1NET, DstIdWhitelistSlot1NET, DstIdBlacklistSlot2NET, DstIdWhitelistSlot2NET, modem, network, display, duplex, lookup, rssiMultiplier, rssiOffset, jitter);
|
||||||
m_lookup->read();
|
|
||||||
|
|
||||||
CDMRSlot::init(id, colorCode, callHang, selfOnly, prefixes, blackList, DstIdBlacklistSlot1RF, DstIdWhitelistSlot1RF, DstIdBlacklistSlot2RF, DstIdWhitelistSlot2RF, DstIdBlacklistSlot1NET, DstIdWhitelistSlot1NET, DstIdBlacklistSlot2NET, DstIdWhitelistSlot2NET, modem, network, display, duplex, m_lookup, rssiMultiplier, rssiOffset, jitter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CDMRControl::~CDMRControl()
|
CDMRControl::~CDMRControl()
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
class CDMRControl {
|
class CDMRControl {
|
||||||
public:
|
public:
|
||||||
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF,const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRIPSC* network, CDisplay* display, bool duplex, const std::string& lookupFile, int rssiMultiplier, int rssiOffset, unsigned int jitter);
|
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blackList, const std::vector<unsigned int>& DstIdBlacklistSlot1RF, const std::vector<unsigned int>& DstIdWhitelistSlot1RF, const std::vector<unsigned int>& DstIdBlacklistSlot2RF, const std::vector<unsigned int>& DstIdWhitelistSlot2RF,const std::vector<unsigned int>& DstIdBlacklistSlot1NET, const std::vector<unsigned int>& DstIdWhitelistSlot1NET, const std::vector<unsigned int>& DstIdBlacklistSlot2NET, const std::vector<unsigned int>& DstIdWhitelistSlot2NET, unsigned int timeout, CModem* modem, CDMRIPSC* network, CDisplay* display, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset, unsigned int jitter);
|
||||||
~CDMRControl();
|
~CDMRControl();
|
||||||
|
|
||||||
bool processWakeup(const unsigned char* data);
|
bool processWakeup(const unsigned char* data);
|
||||||
|
|
|
@ -37,7 +37,7 @@ bool CDMRLookup::read()
|
||||||
{
|
{
|
||||||
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
LogWarning("Cannot open the DMR Id lookup file - %s", m_filename.c_str());
|
LogWarning("Cannot open the Id lookup file - %s", m_filename.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ bool CDMRLookup::read()
|
||||||
if (size == 0U)
|
if (size == 0U)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LogInfo("Loaded %u DMR Ids to the callsign lookup table", size);
|
LogInfo("Loaded %u Ids to the callsign lookup table", size);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ TXLevel=50
|
||||||
OscOffset=0
|
OscOffset=0
|
||||||
RSSIMultiplier=1
|
RSSIMultiplier=1
|
||||||
RSSIOffset=10
|
RSSIOffset=10
|
||||||
Debug=0
|
Debug=1
|
||||||
|
|
||||||
[D-Star]
|
[D-Star]
|
||||||
Enable=1
|
Enable=1
|
||||||
|
@ -79,7 +79,7 @@ Enable=1
|
||||||
|
|
||||||
[P25]
|
[P25]
|
||||||
Enable=1
|
Enable=1
|
||||||
Id=123456
|
NAC=293
|
||||||
|
|
||||||
[D-Star Network]
|
[D-Star Network]
|
||||||
Enable=1
|
Enable=1
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "DStarControl.h"
|
#include "DStarControl.h"
|
||||||
#include "DMRControl.h"
|
#include "DMRControl.h"
|
||||||
|
#include "DMRLookup.h"
|
||||||
#include "TFTSerial.h"
|
#include "TFTSerial.h"
|
||||||
#include "NullDisplay.h"
|
#include "NullDisplay.h"
|
||||||
#include "YSFControl.h"
|
#include "YSFControl.h"
|
||||||
|
@ -267,6 +268,16 @@ int CMMDVMHost::run()
|
||||||
CTimer dmrBeaconTimer(1000U, 4U);
|
CTimer dmrBeaconTimer(1000U, 4U);
|
||||||
bool dmrBeaconsEnabled = m_dmrEnabled && m_conf.getDMRBeacons();
|
bool dmrBeaconsEnabled = m_dmrEnabled && m_conf.getDMRBeacons();
|
||||||
|
|
||||||
|
// For DMR and P25 we try to map IDs to callsigns
|
||||||
|
CDMRLookup* lookup = NULL;
|
||||||
|
if (m_dmrEnabled || m_p25Enabled) {
|
||||||
|
std::string lookupFile = m_conf.getDMRLookupFile();
|
||||||
|
LogInfo("ID lookup File: %s", lookupFile.length() > 0U ? lookupFile.c_str() : "None");
|
||||||
|
|
||||||
|
lookup = new CDMRLookup(lookupFile);
|
||||||
|
lookup->read();
|
||||||
|
}
|
||||||
|
|
||||||
CStopWatch stopWatch;
|
CStopWatch stopWatch;
|
||||||
stopWatch.start();
|
stopWatch.start();
|
||||||
|
|
||||||
|
@ -308,7 +319,6 @@ int CMMDVMHost::run()
|
||||||
std::vector<unsigned int> dstIDBlackListSlot2NET = m_conf.getDMRDstIdBlacklistSlot2NET();
|
std::vector<unsigned int> dstIDBlackListSlot2NET = m_conf.getDMRDstIdBlacklistSlot2NET();
|
||||||
std::vector<unsigned int> dstIDWhiteListSlot1NET = m_conf.getDMRDstIdWhitelistSlot1NET();
|
std::vector<unsigned int> dstIDWhiteListSlot1NET = m_conf.getDMRDstIdWhitelistSlot1NET();
|
||||||
std::vector<unsigned int> dstIDWhiteListSlot2NET = m_conf.getDMRDstIdWhitelistSlot2NET();
|
std::vector<unsigned int> dstIDWhiteListSlot2NET = m_conf.getDMRDstIdWhitelistSlot2NET();
|
||||||
std::string lookupFile = m_conf.getDMRLookupFile();
|
|
||||||
unsigned int callHang = m_conf.getDMRCallHang();
|
unsigned int callHang = m_conf.getDMRCallHang();
|
||||||
unsigned int txHang = m_conf.getDMRTXHang();
|
unsigned int txHang = m_conf.getDMRTXHang();
|
||||||
int rssiMultiplier = m_conf.getModemRSSIMultiplier();
|
int rssiMultiplier = m_conf.getModemRSSIMultiplier();
|
||||||
|
@ -348,7 +358,6 @@ int CMMDVMHost::run()
|
||||||
if (dstIDWhiteListSlot2NET.size() > 0U)
|
if (dstIDWhiteListSlot2NET.size() > 0U)
|
||||||
LogInfo(" Slot 2 NET Destination ID White List: %u entries", dstIDWhiteListSlot2NET.size());
|
LogInfo(" Slot 2 NET Destination ID White List: %u entries", dstIDWhiteListSlot2NET.size());
|
||||||
|
|
||||||
LogInfo(" Lookup File: %s", lookupFile.length() > 0U ? lookupFile.c_str() : "None");
|
|
||||||
LogInfo(" Call Hang: %us", callHang);
|
LogInfo(" Call Hang: %us", callHang);
|
||||||
LogInfo(" TX Hang: %us", txHang);
|
LogInfo(" TX Hang: %us", txHang);
|
||||||
|
|
||||||
|
@ -357,7 +366,7 @@ int CMMDVMHost::run()
|
||||||
LogInfo(" RSSI Offset: %d", rssiOffset);
|
LogInfo(" RSSI Offset: %d", rssiOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
dmr = new CDMRControl(id, colorCode, callHang, selfOnly, prefixes, blackList,dstIDBlackListSlot1RF,dstIDWhiteListSlot1RF, dstIDBlackListSlot2RF, dstIDWhiteListSlot2RF, dstIDBlackListSlot1NET,dstIDWhiteListSlot1NET, dstIDBlackListSlot2NET, dstIDWhiteListSlot2NET, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, lookupFile, rssiMultiplier, rssiOffset, jitter);
|
dmr = new CDMRControl(id, colorCode, callHang, selfOnly, prefixes, blackList,dstIDBlackListSlot1RF,dstIDWhiteListSlot1RF, dstIDBlackListSlot2RF, dstIDWhiteListSlot2RF, dstIDBlackListSlot1NET,dstIDWhiteListSlot1NET, dstIDBlackListSlot2NET, dstIDWhiteListSlot2NET, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, lookup, rssiMultiplier, rssiOffset, jitter);
|
||||||
|
|
||||||
m_dmrTXTimer.setTimeout(txHang);
|
m_dmrTXTimer.setTimeout(txHang);
|
||||||
}
|
}
|
||||||
|
@ -379,19 +388,19 @@ int CMMDVMHost::run()
|
||||||
|
|
||||||
CP25Control* p25 = NULL;
|
CP25Control* p25 = NULL;
|
||||||
if (m_p25Enabled) {
|
if (m_p25Enabled) {
|
||||||
unsigned int id = m_conf.getP25Id();
|
unsigned int nac = m_conf.getP25NAC();
|
||||||
int rssiMultiplier = m_conf.getModemRSSIMultiplier();
|
int rssiMultiplier = m_conf.getModemRSSIMultiplier();
|
||||||
int rssiOffset = m_conf.getModemRSSIOffset();
|
int rssiOffset = m_conf.getModemRSSIOffset();
|
||||||
|
|
||||||
LogInfo("P25 Parameters");
|
LogInfo("P25 Parameters");
|
||||||
LogInfo(" Id: %u", id);
|
LogInfo(" NAC: $%03X", nac);
|
||||||
|
|
||||||
if (rssiMultiplier != 0) {
|
if (rssiMultiplier != 0) {
|
||||||
LogInfo(" RSSI Multiplier: %d", rssiMultiplier);
|
LogInfo(" RSSI Multiplier: %d", rssiMultiplier);
|
||||||
LogInfo(" RSSI Offset: %d", rssiOffset);
|
LogInfo(" RSSI Offset: %d", rssiOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
p25 = new CP25Control(id, m_display, m_timeout, m_duplex, rssiMultiplier, rssiOffset);
|
p25 = new CP25Control(nac, m_display, m_timeout, m_duplex, lookup, rssiMultiplier, rssiOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
setMode(MODE_IDLE);
|
setMode(MODE_IDLE);
|
||||||
|
|
|
@ -181,8 +181,11 @@
|
||||||
<ClInclude Include="Modem.h" />
|
<ClInclude Include="Modem.h" />
|
||||||
<ClInclude Include="Nextion.h" />
|
<ClInclude Include="Nextion.h" />
|
||||||
<ClInclude Include="NullDisplay.h" />
|
<ClInclude Include="NullDisplay.h" />
|
||||||
|
<ClInclude Include="P25Audio.h" />
|
||||||
<ClInclude Include="P25Control.h" />
|
<ClInclude Include="P25Control.h" />
|
||||||
<ClInclude Include="P25Defines.h" />
|
<ClInclude Include="P25Defines.h" />
|
||||||
|
<ClInclude Include="P25Data.h" />
|
||||||
|
<ClInclude Include="P25NID.h" />
|
||||||
<ClInclude Include="QR1676.h" />
|
<ClInclude Include="QR1676.h" />
|
||||||
<ClInclude Include="RingBuffer.h" />
|
<ClInclude Include="RingBuffer.h" />
|
||||||
<ClInclude Include="RS129.h" />
|
<ClInclude Include="RS129.h" />
|
||||||
|
@ -236,7 +239,10 @@
|
||||||
<ClCompile Include="Modem.cpp" />
|
<ClCompile Include="Modem.cpp" />
|
||||||
<ClCompile Include="Nextion.cpp" />
|
<ClCompile Include="Nextion.cpp" />
|
||||||
<ClCompile Include="NullDisplay.cpp" />
|
<ClCompile Include="NullDisplay.cpp" />
|
||||||
|
<ClCompile Include="P25Audio.cpp" />
|
||||||
<ClCompile Include="P25Control.cpp" />
|
<ClCompile Include="P25Control.cpp" />
|
||||||
|
<ClCompile Include="P25Data.cpp" />
|
||||||
|
<ClCompile Include="P25NID.cpp" />
|
||||||
<ClCompile Include="QR1676.cpp" />
|
<ClCompile Include="QR1676.cpp" />
|
||||||
<ClCompile Include="RS129.cpp" />
|
<ClCompile Include="RS129.cpp" />
|
||||||
<ClCompile Include="SerialController.cpp" />
|
<ClCompile Include="SerialController.cpp" />
|
||||||
|
|
|
@ -179,6 +179,15 @@
|
||||||
<ClInclude Include="P25Control.h">
|
<ClInclude Include="P25Control.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="P25NID.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="P25Audio.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="P25Data.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="BPTC19696.cpp">
|
<ClCompile Include="BPTC19696.cpp">
|
||||||
|
@ -328,5 +337,14 @@
|
||||||
<ClCompile Include="P25Control.cpp">
|
<ClCompile Include="P25Control.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="P25NID.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="P25Audio.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="P25Data.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
4
Makefile
4
Makefile
|
@ -9,8 +9,8 @@ LDFLAGS = -g
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.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 \
|
||||||
YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.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 \
|
||||||
UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.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 \
|
||||||
Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.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 \
|
||||||
UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.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 \
|
||||||
UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Thread.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g
|
||||||
OBJECTS = \
|
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 \
|
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 \
|
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 P25Control.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o Utils.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 \
|
||||||
YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||||
|
|
||||||
all: MMDVMHost
|
all: MMDVMHost
|
||||||
|
|
||||||
|
|
117
Modem.cpp
117
Modem.cpp
|
@ -36,6 +36,98 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const unsigned char P25_DATA[6U][222U] = {
|
||||||
|
{ 0xE0U, 0x67U, 0x30U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU, 0x29U, 0x30U, 0x0EU, 0xCEU, 0xD7U, 0x7EU,
|
||||||
|
0x00U, 0x70U, 0x80U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U, 0x00U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
|
||||||
|
0x0AU, 0x37U, 0x18U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x8EU,
|
||||||
|
0xB5U, 0xE0U, 0x96U, 0x52U, 0x7CU, 0x2AU, 0x23U, 0x54U, 0x0DU, 0x9FU, 0x34U, 0x7EU, 0xF1U, 0xD4U, 0x1EU, 0x42U,
|
||||||
|
0x1EU, 0xA2U, 0x35U, 0x8BU, 0xFEU, 0x31U, 0x2AU, 0x5EU, 0x37U, 0x18U, 0x4AU, 0x96U, 0x51U, 0xBAU, 0x30U, 0xA4U,
|
||||||
|
0xF8U, 0x0CU, 0x75U, 0x4CU, 0x75U, 0x10U, 0x02U, 0x00U, 0x00U, 0x0FU, 0x3AU, 0x14U, 0xE9U, 0x4DU, 0x8CU, 0xCEU,
|
||||||
|
0xE7U, 0x52U, 0x17U, 0x28U, 0xD6U, 0x45U, 0x77U, 0xF0U, 0xD2U, 0x23U, 0x25U, 0x6BU, 0x00U, 0x00U, 0x27U, 0x6CU,
|
||||||
|
0xF2U, 0x86U, 0x46U, 0x45U, 0xE0U, 0x1AU, 0x90U, 0xD1U, 0x27U, 0x00U, 0x0AU, 0xD0U, 0x02U, 0x67U, 0x6AU, 0x13U,
|
||||||
|
0x36U, 0xF9U, 0x4AU, 0xFEU, 0xFEU, 0x2AU, 0x8CU, 0x41U, 0xC3U, 0xCFU, 0x94U, 0x30U, 0x56U, 0xEBU, 0x10U, 0xC0U,
|
||||||
|
0x8AU, 0xEFU, 0x5FU, 0x14U, 0xB3U, 0x82U, 0xE7U, 0xC4U, 0x4FU, 0x55U, 0x18U, 0xDEU, 0x33U, 0xDCU, 0x7EU, 0x69U,
|
||||||
|
0x71U, 0xFFU, 0xB1U, 0xE9U, 0x10U, 0x27U, 0xD8U, 0x1AU, 0x28U, 0xF4U, 0xBFU, 0xB6U, 0x85U, 0x9AU, 0x12U, 0xB7U,
|
||||||
|
0x92U, 0x42U, 0x33U, 0xB9U, 0x55U, 0xE0U, 0x8FU, 0x22U, 0x2FU, 0xD6U, 0x2FU, 0x71U, 0x07U, 0x61U, 0x38U, 0xFDU,
|
||||||
|
0xF8U, 0x22U, 0xB2U, 0x11U, 0xCBU, 0x8FU, 0x3EU, 0x69U, 0x88U, 0x6FU, 0xDDU, 0x22U, 0x00U, 0x00U },
|
||||||
|
|
||||||
|
{ 0xE0U, 0xDEU, 0x31U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU, 0x29U, 0x35U, 0x56U, 0x7BU, 0xCBU, 0x19U,
|
||||||
|
0x4DU, 0x0DU, 0xDBU, 0x10U, 0xBAU, 0x16U, 0xDEU, 0x2EU, 0x82U, 0x69U, 0x36U, 0x3DU, 0x98U, 0x1FU, 0x9AU, 0xF8U,
|
||||||
|
0x8EU, 0xC6U, 0x2BU, 0x80U, 0x11U, 0xB1U, 0x0BU, 0xA2U, 0x5DU, 0xE2U, 0xE8U, 0x26U, 0x93U, 0x63U, 0xD9U, 0x81U,
|
||||||
|
0xFAU, 0x6FU, 0x88U, 0xECU, 0x62U, 0xB8U, 0x01U, 0x80U, 0x00U, 0x02U, 0x00U, 0x00U, 0x06U, 0xC4U, 0x2EU, 0x85U,
|
||||||
|
0xDEU, 0x2EU, 0x82U, 0x9AU, 0x4DU, 0x8FU, 0x66U, 0x07U, 0xE6U, 0xF8U, 0x8EU, 0xC6U, 0x8AU, 0xE0U, 0x04U, 0x00U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x1CU, 0x6EU, 0x10U, 0xBAU, 0x17U, 0x78U, 0xBAU, 0x09U, 0xA4U, 0xD8U, 0xF6U, 0x98U, 0x1FU,
|
||||||
|
0x9BU, 0xE2U, 0x3BU, 0x18U, 0xAEU, 0x00U, 0x62U, 0x00U, 0x00U, 0x0FU, 0x3AU, 0x14U, 0xE9U, 0x4DU, 0x8CU, 0xCEU,
|
||||||
|
0xE7U, 0x52U, 0x17U, 0x28U, 0xD6U, 0x45U, 0x77U, 0xF0U, 0xD2U, 0x23U, 0x25U, 0x6BU, 0x00U, 0x00U, 0x27U, 0x6CU,
|
||||||
|
0xF2U, 0x86U, 0x46U, 0x45U, 0xE0U, 0x1AU, 0x90U, 0xD1U, 0x27U, 0x00U, 0x0AU, 0xD0U, 0x02U, 0x67U, 0x6AU, 0x13U,
|
||||||
|
0x36U, 0xF9U, 0x4AU, 0xFEU, 0xFEU, 0x2AU, 0x8CU, 0x41U, 0xC3U, 0xCFU, 0x94U, 0x30U, 0x56U, 0xEBU, 0x10U, 0xC0U,
|
||||||
|
0x8AU, 0xEFU, 0x5FU, 0x14U, 0xB3U, 0x82U, 0xE7U, 0xC4U, 0x4FU, 0x55U, 0x18U, 0xDEU, 0x33U, 0xDCU, 0x7EU, 0x69U,
|
||||||
|
0x71U, 0xFFU, 0xB1U, 0xE9U, 0x10U, 0x27U, 0xD8U, 0x1AU, 0x28U, 0xF4U, 0xBFU, 0xB6U, 0x85U, 0x9AU, 0x12U, 0xB7U,
|
||||||
|
0x92U, 0x42U, 0x33U, 0xB9U, 0x55U, 0xE0U, 0x8FU, 0x22U, 0x2FU, 0xD6U, 0x2FU, 0x71U, 0x07U, 0x61U, 0x38U, 0xFDU,
|
||||||
|
0xF8U, 0x22U, 0xB2U, 0x11U, 0xCBU, 0x8FU, 0x3EU, 0x69U, 0x88U, 0x6FU, 0xDDU, 0x22U, 0x00U, 0x00U },
|
||||||
|
|
||||||
|
{ 0xE0U, 0xDCU, 0x31U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xFEU, 0x77U, 0xFFU, 0x29U, 0x3AU, 0xBAU, 0xA4U, 0xEFU, 0xB0U,
|
||||||
|
0x9AU, 0x8AU, 0xCEU, 0x9DU, 0xADU, 0x1EU, 0xCDU, 0x06U, 0xFBU, 0xF6U, 0xA8U, 0x28U, 0xEDU, 0x7BU, 0x5AU, 0x8CU,
|
||||||
|
0x15U, 0xC7U, 0x08U, 0xEEU, 0x38U, 0xD1U, 0x4BU, 0xEEU, 0xA5U, 0xE7U, 0xE0U, 0xD5U, 0x5DU, 0x49U, 0x05U, 0x0DU,
|
||||||
|
0x72U, 0xFAU, 0xB0U, 0xD4U, 0xA6U, 0x08U, 0x64U, 0x40U, 0x00U, 0x02U, 0x00U, 0x00U, 0x07U, 0xA3U, 0x36U, 0x5CU,
|
||||||
|
0x96U, 0x5AU, 0x26U, 0xFDU, 0xD6U, 0x35U, 0x64U, 0x11U, 0x82U, 0x0CU, 0x8DU, 0xFAU, 0x75U, 0xF6U, 0xD7U, 0x00U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x00U, 0x72U, 0x20U, 0x56U, 0x60U, 0xA5U, 0xEBU, 0x24U, 0x6BU, 0xF6U, 0x1AU, 0x83U, 0xECU,
|
||||||
|
0xA9U, 0x39U, 0xACU, 0x7DU, 0x44U, 0xC4U, 0x42U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x4AU, 0x00U, 0xDAU, 0x66U,
|
||||||
|
0xF2U, 0x8FU, 0x3BU, 0xBAU, 0xA5U, 0x8EU, 0x9BU, 0xC4U, 0x0EU, 0x49U, 0x17U, 0xE9U, 0x5AU, 0x14U, 0xA0U, 0xE0U,
|
||||||
|
0x00U, 0x02U, 0x00U, 0x03U, 0x75U, 0xD6U, 0xB9U, 0x6CU, 0x54U, 0x24U, 0x56U, 0x5CU, 0xACU, 0x5AU, 0x81U, 0xA5U,
|
||||||
|
0x9BU, 0x06U, 0x47U, 0x96U, 0xE9U, 0x49U, 0xAEU, 0x8BU, 0x48U, 0xB6U, 0x49U, 0x9CU, 0x42U, 0xD8U, 0xA1U, 0x5DU,
|
||||||
|
0x58U, 0xC0U, 0x70U, 0xC4U, 0xBAU, 0xEEU, 0x39U, 0x99U, 0xC8U, 0x2EU, 0xFFU, 0x31U, 0x37U, 0xA9U, 0xAAU, 0xF4U,
|
||||||
|
0xF1U, 0xFDU, 0x63U, 0x0BU, 0xC2U, 0x71U, 0xD9U, 0x12U, 0xA7U, 0x35U, 0x13U, 0x15U, 0xBAU, 0x31U, 0x1EU, 0xAEU,
|
||||||
|
0x6EU, 0xC7U, 0x3CU, 0x70U, 0x96U, 0x7CU, 0x41U, 0x1CU, 0x1CU, 0xE2U, 0xA2U, 0x44U, 0x59U, 0xE8U, 0x46U, 0x88U,
|
||||||
|
0x3AU, 0x70U, 0xFEU, 0xD3U, 0xD3U, 0x13U, 0x44U, 0xA1U, 0x67U, 0xECU, 0xF8U, 0xAEU },
|
||||||
|
|
||||||
|
{ 0xE0U, 0xDCU, 0x31U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xFEU, 0x77U, 0xFFU, 0x29U, 0x35U, 0x56U, 0x7BU, 0xCBU, 0x19U,
|
||||||
|
0x4DU, 0x0DU, 0xFDU, 0x2AU, 0x9AU, 0x12U, 0x2BU, 0x2AU, 0xE1U, 0xB0U, 0xA1U, 0xDBU, 0x88U, 0x26U, 0x82U, 0x5FU,
|
||||||
|
0x40U, 0xFEU, 0x15U, 0x3DU, 0x20U, 0x92U, 0x1BU, 0x2EU, 0x49U, 0xF3U, 0xACU, 0x3FU, 0xB3U, 0x8DU, 0x39U, 0x2AU,
|
||||||
|
0xF6U, 0x09U, 0x14U, 0x58U, 0xF1U, 0xE7U, 0x23U, 0x80U, 0x00U, 0x02U, 0x00U, 0x00U, 0x04U, 0x23U, 0x01U, 0xC3U,
|
||||||
|
0x59U, 0x60U, 0xFAU, 0xD9U, 0xE1U, 0x12U, 0x6DU, 0x32U, 0x23U, 0x44U, 0x86U, 0xEEU, 0x11U, 0x87U, 0x68U, 0x00U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x1CU, 0x52U, 0xB4U, 0xD1U, 0x4DU, 0x55U, 0x33U, 0x6EU, 0x63U, 0x92U, 0x42U, 0x8CU, 0xB1U,
|
||||||
|
0x9BU, 0x37U, 0xE9U, 0x42U, 0x9BU, 0x2DU, 0xA2U, 0x00U, 0x00U, 0x0FU, 0x3AU, 0x17U, 0x2EU, 0xDBU, 0x20U, 0x0EU,
|
||||||
|
0x55U, 0xA3U, 0x6FU, 0x53U, 0xF1U, 0x25U, 0x31U, 0x3EU, 0xDEU, 0x12U, 0x42U, 0x69U, 0xA3U, 0x42U, 0x67U, 0x6CU,
|
||||||
|
0xF2U, 0x86U, 0x46U, 0x4DU, 0x6AU, 0x91U, 0x60U, 0x8FU, 0x64U, 0xAAU, 0x1EU, 0xCAU, 0x52U, 0xA0U, 0x60U, 0x49U,
|
||||||
|
0xA9U, 0x0CU, 0x70U, 0xCAU, 0x4EU, 0x3BU, 0x8CU, 0x41U, 0xC3U, 0xCFU, 0x90U, 0x80U, 0xBAU, 0x5EU, 0x59U, 0x39U,
|
||||||
|
0x21U, 0x12U, 0x19U, 0x3FU, 0xEFU, 0x4AU, 0x2CU, 0xA6U, 0x36U, 0x1AU, 0x07U, 0xCBU, 0xFEU, 0x4CU, 0x7EU, 0x69U,
|
||||||
|
0x71U, 0xFFU, 0xB1U, 0xF1U, 0xC7U, 0xE9U, 0x42U, 0x86U, 0xCFU, 0xE9U, 0x48U, 0xC0U, 0xAEU, 0xA4U, 0x58U, 0x97U,
|
||||||
|
0xA6U, 0xE6U, 0x71U, 0x82U, 0x52U, 0xEAU, 0x90U, 0xAAU, 0x90U, 0x82U, 0x67U, 0x51U, 0xB5U, 0x5AU, 0x12U, 0xB8U,
|
||||||
|
0x1BU, 0xFDU, 0x8AU, 0xBAU, 0xCBU, 0x93U, 0x21U, 0xEEU, 0xA3U, 0x60U, 0x46U, 0x66U },
|
||||||
|
|
||||||
|
{ 0xE0U, 0xDCU, 0x31U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xEFU, 0x77U, 0xFFU, 0x29U, 0x3AU, 0xBAU, 0xA4U, 0xEEU, 0xB0U,
|
||||||
|
0x9AU, 0x8AU, 0xC5U, 0x11U, 0xD1U, 0xA2U, 0x0CU, 0x58U, 0xF4U, 0x8DU, 0xC8U, 0xF1U, 0xEDU, 0xA6U, 0x6EU, 0x2CU,
|
||||||
|
0x67U, 0xA9U, 0x57U, 0xD1U, 0x38U, 0x02U, 0x91U, 0x2AU, 0xEBU, 0x63U, 0x28U, 0x49U, 0x1AU, 0xAFU, 0xA9U, 0xC6U,
|
||||||
|
0xBAU, 0x3CU, 0xD3U, 0x61U, 0x2DU, 0x13U, 0x31U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x05U, 0x2BU, 0x48U, 0x4DU,
|
||||||
|
0x8DU, 0x7EU, 0x82U, 0x7DU, 0xECU, 0x39U, 0x61U, 0x82U, 0x1DU, 0x3EU, 0xBCU, 0xF2U, 0x66U, 0x8BU, 0x02U, 0x00U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x00U, 0x06U, 0x31U, 0x30U, 0x79U, 0xF1U, 0xBBU, 0x5AU, 0x5AU, 0x51U, 0xB6U, 0x74U, 0x17U,
|
||||||
|
0xEEU, 0x3EU, 0xA8U, 0x2BU, 0xA0U, 0xC3U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0xCAU, 0x9CU, 0xA2U, 0x2AU,
|
||||||
|
0x82U, 0xC7U, 0x03U, 0x4DU, 0xF1U, 0xE8U, 0xF1U, 0x20U, 0xAEU, 0xA9U, 0xC4U, 0xE9U, 0x1CU, 0xC0U, 0xA0U, 0xE0U,
|
||||||
|
0x00U, 0x02U, 0x00U, 0x05U, 0x4AU, 0x05U, 0x38U, 0xE3U, 0x4EU, 0xEAU, 0x92U, 0x7AU, 0x51U, 0x23U, 0x32U, 0x12U,
|
||||||
|
0xDEU, 0x69U, 0x0BU, 0x42U, 0x3AU, 0x85U, 0xAEU, 0x8BU, 0x48U, 0xB6U, 0x49U, 0x0AU, 0x36U, 0x16U, 0x9DU, 0xFDU,
|
||||||
|
0x51U, 0x67U, 0xD0U, 0x76U, 0x44U, 0x6AU, 0x6DU, 0x4AU, 0x22U, 0x47U, 0xA1U, 0x91U, 0xEAU, 0xA9U, 0xAAU, 0xF4U,
|
||||||
|
0xF1U, 0xFDU, 0x62U, 0x9FU, 0x1BU, 0x80U, 0xAFU, 0x4EU, 0xEEU, 0x4DU, 0x48U, 0x7CU, 0x99U, 0x41U, 0xA9U, 0xFAU,
|
||||||
|
0x62U, 0xEFU, 0x9DU, 0x79U, 0x92U, 0x6AU, 0x90U, 0xA0U, 0x8FU, 0x2AU, 0xDDU, 0x20U, 0x70U, 0x62U, 0x1CU, 0xF1U,
|
||||||
|
0x5FU, 0x71U, 0x4EU, 0xC0U, 0x54U, 0x80U, 0xE2U, 0x76U, 0x71U, 0xA9U, 0x30U, 0xCAU },
|
||||||
|
|
||||||
|
{ 0xE0U, 0xDCU, 0x31U, 0x01U, 0x55U, 0x75U, 0xF5U, 0xFEU, 0x77U, 0xFFU, 0x29U, 0x33U, 0x3AU, 0x5DU, 0xDCU, 0xA3U,
|
||||||
|
0x3BU, 0x5BU, 0x80U, 0x00U, 0x00U, 0x02U, 0x16U, 0x60U, 0x02U, 0x80U, 0x08U, 0x00U, 0x20U, 0x20U, 0x00U, 0x80U,
|
||||||
|
0x00U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0x25U, 0x88U, 0x00U, 0x28U, 0x22U, 0x20U, 0x01U, 0xB3U, 0x81U, 0x6AU,
|
||||||
|
0x95U, 0x16U, 0x61U, 0x23U, 0xE7U, 0x20U, 0x00U, 0xD8U, 0xDFU, 0xE9U, 0xACU, 0xC9U, 0x07U, 0x69U, 0xB6U, 0x41U,
|
||||||
|
0x92U, 0x04U, 0x63U, 0x4AU, 0xF4U, 0xA1U, 0x6FU, 0xF4U, 0xA7U, 0xEAU, 0xACU, 0xE6U, 0xD8U, 0x71U, 0xE3U, 0xE6U,
|
||||||
|
0x95U, 0x2DU, 0x3CU, 0xBAU, 0x64U, 0x9EU, 0x97U, 0xF3U, 0x4AU, 0x66U, 0x85U, 0x40U, 0x73U, 0xDCU, 0x28U, 0x83U,
|
||||||
|
0x7AU, 0x71U, 0xC7U, 0x01U, 0x5DU, 0xFCU, 0x19U, 0xBAU, 0x61U, 0xD1U, 0xCAU, 0xC7U, 0x82U, 0x96U, 0xF7U, 0x29U,
|
||||||
|
0x7BU, 0xD2U, 0xB0U, 0xFBU, 0x21U, 0x13U, 0x31U, 0x54U, 0xFFU, 0x1BU, 0x50U, 0x0DU, 0xD7U, 0x68U, 0x76U, 0xCBU,
|
||||||
|
0xA5U, 0xA7U, 0x86U, 0x5EU, 0xE0U, 0x21U, 0x45U, 0x7AU, 0x31U, 0x3EU, 0x50U, 0xAEU, 0x2AU, 0x30U, 0x80U, 0x25U,
|
||||||
|
0xA9U, 0x9BU, 0x7DU, 0x4AU, 0x0EU, 0x17U, 0x92U, 0x2AU, 0xA6U, 0xD4U, 0xB2U, 0x60U, 0xCAU, 0xC7U, 0x9AU, 0x5EU,
|
||||||
|
0x0AU, 0x14U, 0xD3U, 0xE2U, 0x35U, 0x04U, 0x48U, 0xBAU, 0xE6U, 0x44U, 0xE9U, 0x2EU, 0x73U, 0xB8U, 0xAEU, 0xD8U,
|
||||||
|
0xA9U, 0x66U, 0x0DU, 0xA4U, 0x8AU, 0xB2U, 0x5FU, 0xE6U, 0x01U, 0x97U, 0xF4U, 0x1AU, 0x33U, 0x09U, 0x60U, 0x44U,
|
||||||
|
0x8EU, 0xA6U, 0xB5U, 0xACU, 0x43U, 0x50U, 0xAFU, 0x5BU, 0xF6U, 0x42U, 0xA3U, 0x27U, 0x01U, 0x44U, 0xAFU, 0x7AU,
|
||||||
|
0xB1U, 0x05U, 0x01U, 0x9FU, 0xA4U, 0xFDU, 0x2DU, 0x8FU, 0x48U, 0xA3U, 0xC1U, 0xA3U } };
|
||||||
|
|
||||||
|
|
||||||
const unsigned char MMDVM_FRAME_START = 0xE0U;
|
const unsigned char MMDVM_FRAME_START = 0xE0U;
|
||||||
|
|
||||||
const unsigned char MMDVM_GET_VERSION = 0x00U;
|
const unsigned char MMDVM_GET_VERSION = 0x00U;
|
||||||
|
@ -127,7 +219,8 @@ m_p25Space(0U),
|
||||||
m_tx(false),
|
m_tx(false),
|
||||||
m_lockout(false),
|
m_lockout(false),
|
||||||
m_error(false),
|
m_error(false),
|
||||||
m_hwType(HWT_UNKNOWN)
|
m_hwType(HWT_UNKNOWN),
|
||||||
|
m_nn(0U)
|
||||||
{
|
{
|
||||||
assert(!port.empty());
|
assert(!port.empty());
|
||||||
|
|
||||||
|
@ -214,6 +307,28 @@ void CModem::clock(unsigned int ms)
|
||||||
if (m_statusTimer.hasExpired()) {
|
if (m_statusTimer.hasExpired()) {
|
||||||
readStatus();
|
readStatus();
|
||||||
m_statusTimer.start();
|
m_statusTimer.start();
|
||||||
|
|
||||||
|
|
||||||
|
const unsigned char* dat = P25_DATA[m_nn];
|
||||||
|
if (m_nn == 0U) {
|
||||||
|
unsigned char data = 101U;
|
||||||
|
m_rxP25Data.addData(&data, 1U);
|
||||||
|
|
||||||
|
data = TAG_HEADER;
|
||||||
|
m_rxP25Data.addData(&data, 1U);
|
||||||
|
|
||||||
|
m_rxP25Data.addData(dat + 3U, 100U);
|
||||||
|
} else if (m_nn > 0U && m_nn < 6U) {
|
||||||
|
unsigned char data = 220U;
|
||||||
|
m_rxP25Data.addData(&data, 1U);
|
||||||
|
|
||||||
|
data = TAG_DATA;
|
||||||
|
m_rxP25Data.addData(&data, 1U);
|
||||||
|
|
||||||
|
m_rxP25Data.addData(dat + 3U, 219U);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_nn++;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_inactivityTimer.clock(ms);
|
m_inactivityTimer.clock(ms);
|
||||||
|
|
1
Modem.h
1
Modem.h
|
@ -129,6 +129,7 @@ private:
|
||||||
bool m_lockout;
|
bool m_lockout;
|
||||||
bool m_error;
|
bool m_error;
|
||||||
HW_TYPE m_hwType;
|
HW_TYPE m_hwType;
|
||||||
|
unsigned int m_nn;
|
||||||
|
|
||||||
bool readVersion();
|
bool readVersion();
|
||||||
bool readStatus();
|
bool readStatus();
|
||||||
|
|
107
P25Audio.cpp
Normal file
107
P25Audio.cpp
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* 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 "P25Audio.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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CP25Audio::~CP25Audio()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CP25Audio::process(unsigned char* data)
|
||||||
|
{
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
unsigned int errs = 0U;
|
||||||
|
|
||||||
|
unsigned char imbe[18U];
|
||||||
|
|
||||||
|
read(data, imbe, 114U, 262U, 142U, 143U, 214U, 215U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 114U, 262U, 142U, 143U, 214U, 215U);
|
||||||
|
|
||||||
|
read(data, imbe, 262U, 410U, 286U, 287U, 358U, 359U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 262U, 410U, 286U, 287U, 358U, 359U);
|
||||||
|
|
||||||
|
read(data, imbe, 452U, 600U, 502U, 503U, 574U, 575U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 452U, 600U, 502U, 503U, 574U, 575U);
|
||||||
|
|
||||||
|
read(data, imbe, 640U, 788U, 646U, 647U, 718U, 719U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 640U, 788U, 646U, 647U, 718U, 719U);
|
||||||
|
|
||||||
|
read(data, imbe, 830U, 978U, 862U, 863U, 934U, 935U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 830U, 978U, 862U, 863U, 934U, 935U);
|
||||||
|
|
||||||
|
read(data, imbe, 1020U, 1168U, 1078U, 1079U, 1150U, 1151U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 1020U, 1168U, 1078U, 1079U, 1150U, 1151U);
|
||||||
|
|
||||||
|
read(data, imbe, 1208U, 1356U, 1222U, 1223U, 1294U, 1295U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 1208U, 1356U, 1222U, 1223U, 1294U, 1295U);
|
||||||
|
|
||||||
|
read(data, imbe, 1398U, 1546U, 1438U, 1439U, 1510U, 1511U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 1398U, 1546U, 1438U, 1439U, 1510U, 1511U);
|
||||||
|
|
||||||
|
read(data, imbe, 1578U, 1726U, 1582U, 1583U, 1654U, 1655U);
|
||||||
|
errs += m_fec.regenerateIMBE(imbe);
|
||||||
|
write(data, imbe, 1578U, 1726U, 1582U, 1583U, 1654U, 1655U);
|
||||||
|
|
||||||
|
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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
P25Audio.h
Normal file
38
P25Audio.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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(P25Audio_H)
|
||||||
|
#define P25Audio_H
|
||||||
|
|
||||||
|
#include "AMBEFEC.h"
|
||||||
|
|
||||||
|
class CP25Audio {
|
||||||
|
public:
|
||||||
|
CP25Audio();
|
||||||
|
~CP25Audio();
|
||||||
|
|
||||||
|
unsigned int process(unsigned char* data);
|
||||||
|
|
||||||
|
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
|
|
@ -20,6 +20,7 @@
|
||||||
#include "P25Defines.h"
|
#include "P25Defines.h"
|
||||||
#include "Sync.h"
|
#include "Sync.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -29,10 +30,11 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U
|
||||||
#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 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])
|
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||||
|
|
||||||
CP25Control::CP25Control(unsigned int id, CDisplay* display, unsigned int timeout, bool duplex, int rssiMultiplier, int rssiOffset) :
|
CP25Control::CP25Control(unsigned int nac, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset) :
|
||||||
m_id(id),
|
m_nac(nac),
|
||||||
m_display(display),
|
m_display(display),
|
||||||
m_duplex(duplex),
|
m_duplex(duplex),
|
||||||
|
m_lookup(lookup),
|
||||||
m_rssiMultiplier(rssiMultiplier),
|
m_rssiMultiplier(rssiMultiplier),
|
||||||
m_rssiOffset(rssiOffset),
|
m_rssiOffset(rssiOffset),
|
||||||
m_queue(1000U, "P25 Control"),
|
m_queue(1000U, "P25 Control"),
|
||||||
|
@ -42,9 +44,14 @@ m_rfTimeout(1000U, timeout),
|
||||||
m_netTimeout(1000U, timeout),
|
m_netTimeout(1000U, timeout),
|
||||||
m_rfFrames(0U),
|
m_rfFrames(0U),
|
||||||
m_rfBits(0U),
|
m_rfBits(0U),
|
||||||
m_rfErrs(0U)
|
m_rfErrs(0U),
|
||||||
|
m_nid(),
|
||||||
|
m_audio(),
|
||||||
|
m_rfData(),
|
||||||
|
m_netData()
|
||||||
{
|
{
|
||||||
assert(display != NULL);
|
assert(display != NULL);
|
||||||
|
assert(lookup != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CP25Control::~CP25Control()
|
CP25Control::~CP25Control()
|
||||||
|
@ -55,6 +62,8 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
{
|
{
|
||||||
assert(data != NULL);
|
assert(data != NULL);
|
||||||
|
|
||||||
|
CUtils::dump(1U, "P25 Data", data, len);
|
||||||
|
|
||||||
bool sync = data[1U] == 0x01U;
|
bool sync = data[1U] == 0x01U;
|
||||||
|
|
||||||
if (data[0U] == TAG_LOST && m_rfState == RS_RF_LISTENING)
|
if (data[0U] == TAG_LOST && m_rfState == RS_RF_LISTENING)
|
||||||
|
@ -62,24 +71,34 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
|
|
||||||
if (data[0U] == TAG_LOST) {
|
if (data[0U] == TAG_LOST) {
|
||||||
LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||||
|
m_display->clearP25();
|
||||||
m_rfState = RS_RF_LISTENING;
|
m_rfState = RS_RF_LISTENING;
|
||||||
m_rfTimeout.stop();
|
m_rfTimeout.stop();
|
||||||
|
m_rfData.reset();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sync && m_rfState == RS_RF_LISTENING)
|
if (!sync && m_rfState == RS_RF_LISTENING)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Put into the NID decoder
|
// Regenerate the NID
|
||||||
unsigned char duid = 0U; // XXX
|
m_nid.process(data + 2U);
|
||||||
|
unsigned char duid = m_nid.getDUID();
|
||||||
|
unsigned int nac = m_nid.getNAC();
|
||||||
|
|
||||||
|
LogDebug("P25, DUID=$%X NAC=$%03X", duid, nac);
|
||||||
|
|
||||||
|
if (m_rfState == RS_RF_LISTENING && nac != m_nac)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (data[0U] == TAG_HEADER) {
|
if (data[0U] == TAG_HEADER) {
|
||||||
|
m_rfData.reset();
|
||||||
|
|
||||||
// Regenerate Sync
|
// Regenerate Sync
|
||||||
CSync::addP25Sync(data + 2U);
|
CSync::addP25Sync(data + 2U);
|
||||||
|
|
||||||
// Regenerate NID
|
|
||||||
|
|
||||||
// Regenerate Enc Data
|
// Regenerate Enc Data
|
||||||
|
m_rfData.processHeader(data + 2U);
|
||||||
|
|
||||||
// Add busy bits
|
// Add busy bits
|
||||||
addBusyBits(data + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
|
addBusyBits(data + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
|
||||||
|
@ -102,18 +121,16 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
m_rfErrs = 0U;
|
m_rfErrs = 0U;
|
||||||
m_rfBits = 1U;
|
m_rfBits = 1U;
|
||||||
m_rfTimeout.start();
|
m_rfTimeout.start();
|
||||||
// Decode LDU1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regenerate Sync
|
// Regenerate Sync
|
||||||
CSync::addP25Sync(data + 2U);
|
CSync::addP25Sync(data + 2U);
|
||||||
|
|
||||||
// Regenerate NID
|
|
||||||
|
|
||||||
// Regenerate LDU1 Data
|
// Regenerate LDU1 Data
|
||||||
|
m_rfData.processLDU1(data + 2U);
|
||||||
|
|
||||||
// Regenerate Audio
|
// Regenerate Audio
|
||||||
unsigned int errors = 0U; // XXX
|
unsigned int errors = m_audio.process(data + 2U);
|
||||||
LogDebug("P25, LDU1 audio, errs: %u/1233", errors);
|
LogDebug("P25, LDU1 audio, errs: %u/1233", errors);
|
||||||
|
|
||||||
m_rfBits += 1233U;
|
m_rfBits += 1233U;
|
||||||
|
@ -130,7 +147,12 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_rfState == RS_RF_LISTENING) {
|
if (m_rfState == RS_RF_LISTENING) {
|
||||||
// LogMessage("P25, received RF LC from %8.8s/%4.4s to %8.8s", my1, my2, your);
|
unsigned int src = m_rfData.getSource();
|
||||||
|
bool grp = m_rfData.getGroup();
|
||||||
|
unsigned int dst = m_rfData.getDest();
|
||||||
|
std::string source = m_lookup->find(src);
|
||||||
|
LogMessage("P25, received RF from %s to %s%u", source.c_str(), grp ? "TG" : "", dst);
|
||||||
|
m_display->writeP25(source.c_str(), grp, dst, "R");
|
||||||
m_rfState = RS_RF_AUDIO;
|
m_rfState = RS_RF_AUDIO;
|
||||||
}
|
}
|
||||||
} else if (duid == P25_DUID_LDU2) {
|
} else if (duid == P25_DUID_LDU2) {
|
||||||
|
@ -138,16 +160,15 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Decode LDU2
|
// Decode LDU2
|
||||||
|
m_rfData.processLDU2(data + 2U);
|
||||||
|
|
||||||
// Regenerate Sync
|
// Regenerate Sync
|
||||||
CSync::addP25Sync(data + 2U);
|
CSync::addP25Sync(data + 2U);
|
||||||
|
|
||||||
// Regenerate NID
|
|
||||||
|
|
||||||
// Regenerate LDU2 Data
|
// Regenerate LDU2 Data
|
||||||
|
|
||||||
// Regenerate Audio
|
// Regenerate Audio
|
||||||
unsigned int errors = 0U; // XXX
|
unsigned int errors = m_audio.process(data + 2U);
|
||||||
LogDebug("P25, LDU2 audio, errs: %u/1233", errors);
|
LogDebug("P25, LDU2 audio, errs: %u/1233", errors);
|
||||||
|
|
||||||
m_rfBits += 1233U;
|
m_rfBits += 1233U;
|
||||||
|
@ -169,17 +190,18 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
// Regenerate Sync
|
// Regenerate Sync
|
||||||
CSync::addP25Sync(data + 2U);
|
CSync::addP25Sync(data + 2U);
|
||||||
|
|
||||||
// Regenerate NID
|
|
||||||
|
|
||||||
// Regenerate LDU1 Data
|
// Regenerate LDU1 Data
|
||||||
|
m_rfData.processTerminator(data + 2U);
|
||||||
|
|
||||||
// Add busy bits
|
// Add busy bits
|
||||||
addBusyBits(data + 2U, P25_TERMLC_FRAME_LENGTH_BITS, false, true);
|
addBusyBits(data + 2U, P25_TERMLC_FRAME_LENGTH_BITS, false, true);
|
||||||
|
|
||||||
m_rfState = RS_RF_LISTENING;
|
m_rfState = RS_RF_LISTENING;
|
||||||
m_rfTimeout.stop();
|
m_rfTimeout.stop();
|
||||||
|
m_rfData.reset();
|
||||||
|
|
||||||
LogMessage("P25, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
LogMessage("P25, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||||
|
m_display->clearP25();
|
||||||
|
|
||||||
if (m_duplex) {
|
if (m_duplex) {
|
||||||
data[0U] = TAG_EOT;
|
data[0U] = TAG_EOT;
|
||||||
|
@ -193,15 +215,15 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
||||||
// Regenerate Sync
|
// Regenerate Sync
|
||||||
CSync::addP25Sync(data + 2U);
|
CSync::addP25Sync(data + 2U);
|
||||||
|
|
||||||
// Regenerate NID
|
|
||||||
|
|
||||||
// Add busy bits
|
// Add busy bits
|
||||||
addBusyBits(data + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true);
|
addBusyBits(data + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true);
|
||||||
|
|
||||||
m_rfState = RS_RF_LISTENING;
|
m_rfState = RS_RF_LISTENING;
|
||||||
m_rfTimeout.stop();
|
m_rfTimeout.stop();
|
||||||
|
m_rfData.reset();
|
||||||
|
|
||||||
LogMessage("P25, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
LogMessage("P25, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||||
|
m_display->clearP25();
|
||||||
|
|
||||||
if (m_duplex) {
|
if (m_duplex) {
|
||||||
data[0U] = TAG_EOT;
|
data[0U] = TAG_EOT;
|
||||||
|
|
13
P25Control.h
13
P25Control.h
|
@ -20,14 +20,18 @@
|
||||||
#define P25Control_H
|
#define P25Control_H
|
||||||
|
|
||||||
#include "RingBuffer.h"
|
#include "RingBuffer.h"
|
||||||
|
#include "DMRLookup.h"
|
||||||
|
#include "P25Audio.h"
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "Display.h"
|
#include "Display.h"
|
||||||
|
#include "P25Data.h"
|
||||||
|
#include "P25NID.h"
|
||||||
#include "Modem.h"
|
#include "Modem.h"
|
||||||
#include "Timer.h"
|
#include "Timer.h"
|
||||||
|
|
||||||
class CP25Control {
|
class CP25Control {
|
||||||
public:
|
public:
|
||||||
CP25Control(unsigned int id, CDisplay* display, unsigned int timeout, bool duplex, int rssiMultiplier, int rssiOffset);
|
CP25Control(unsigned int nac, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, int rssiMultiplier, int rssiOffset);
|
||||||
~CP25Control();
|
~CP25Control();
|
||||||
|
|
||||||
bool writeModem(unsigned char* data, unsigned int len);
|
bool writeModem(unsigned char* data, unsigned int len);
|
||||||
|
@ -37,9 +41,10 @@ public:
|
||||||
void clock(unsigned int ms);
|
void clock(unsigned int ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_id;
|
unsigned int m_nac;
|
||||||
CDisplay* m_display;
|
CDisplay* m_display;
|
||||||
bool m_duplex;
|
bool m_duplex;
|
||||||
|
CDMRLookup* m_lookup;
|
||||||
int m_rssiMultiplier;
|
int m_rssiMultiplier;
|
||||||
int m_rssiOffset;
|
int m_rssiOffset;
|
||||||
CRingBuffer<unsigned char> m_queue;
|
CRingBuffer<unsigned char> m_queue;
|
||||||
|
@ -50,6 +55,10 @@ private:
|
||||||
unsigned int m_rfFrames;
|
unsigned int m_rfFrames;
|
||||||
unsigned int m_rfBits;
|
unsigned int m_rfBits;
|
||||||
unsigned int m_rfErrs;
|
unsigned int m_rfErrs;
|
||||||
|
CP25NID m_nid;
|
||||||
|
CP25Audio m_audio;
|
||||||
|
CP25Data m_rfData;
|
||||||
|
CP25Data m_netData;
|
||||||
|
|
||||||
void writeQueueRF(const unsigned char* data, unsigned int length);
|
void writeQueueRF(const unsigned char* data, unsigned int length);
|
||||||
void addBusyBits(unsigned char* data, unsigned int length, bool b1, bool b2);
|
void addBusyBits(unsigned char* data, unsigned int length, bool b1, bool b2);
|
||||||
|
|
151
P25Data.cpp
Normal file
151
P25Data.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* 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 "P25Data.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
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])
|
||||||
|
|
||||||
|
CP25Data::CP25Data() :
|
||||||
|
m_source(0U),
|
||||||
|
m_group(true),
|
||||||
|
m_dest(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CP25Data::~CP25Data()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25Data::processHeader(unsigned char* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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 format = 0U;
|
||||||
|
unsigned char mult = 1U;
|
||||||
|
for (unsigned int i = 0U; i < 8U; i++, mult <<= 1)
|
||||||
|
format += b[i] ? mult : 0U;
|
||||||
|
|
||||||
|
LogDebug("P25, LC_format = $%02X", format);
|
||||||
|
|
||||||
|
if (format == 0x03U) {
|
||||||
|
LogDebug("P25, non talk group destination");
|
||||||
|
m_group = false;
|
||||||
|
} else {
|
||||||
|
m_group = true;
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
mult = 1U;
|
||||||
|
for (unsigned int i = 0U; i < 16U; i++, mult <<= 1)
|
||||||
|
m_dest += b[i] ? mult : 0U;
|
||||||
|
|
||||||
|
LogDebug("P25, TG ID = %u", m_dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
mult = 1U;
|
||||||
|
for (unsigned int i = 0U; i < 24U; i++, mult <<= 1)
|
||||||
|
m_source += b[i] ? mult : 0U;
|
||||||
|
|
||||||
|
LogDebug("P25, SRC ID = %u", m_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25Data::processLDU2(unsigned char* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25Data::processTerminator(unsigned char* data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CP25Data::getSource() const
|
||||||
|
{
|
||||||
|
return m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CP25Data::getGroup() const
|
||||||
|
{
|
||||||
|
return m_group;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CP25Data::getDest() const
|
||||||
|
{
|
||||||
|
return m_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25Data::reset()
|
||||||
|
{
|
||||||
|
m_source = 0U;
|
||||||
|
m_dest = 0U;
|
||||||
|
}
|
48
P25Data.h
Normal file
48
P25Data.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
* 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(P25Data_H)
|
||||||
|
#define P25Data_H
|
||||||
|
|
||||||
|
class CP25Data {
|
||||||
|
public:
|
||||||
|
CP25Data();
|
||||||
|
~CP25Data();
|
||||||
|
|
||||||
|
void processHeader(unsigned char* data);
|
||||||
|
|
||||||
|
void processLDU1(unsigned char* data);
|
||||||
|
|
||||||
|
void processLDU2(unsigned char* data);
|
||||||
|
|
||||||
|
void processTerminator(unsigned char* data);
|
||||||
|
|
||||||
|
unsigned int getSource() const;
|
||||||
|
|
||||||
|
bool getGroup() const;
|
||||||
|
unsigned int getDest() const;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned int m_source;
|
||||||
|
bool m_group;
|
||||||
|
unsigned int m_dest;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -40,7 +40,7 @@ const unsigned char P25_SYNC_BYTES_LENGTH = 6U;
|
||||||
const unsigned char P25_DUID_HEADER = 0x00U;
|
const unsigned char P25_DUID_HEADER = 0x00U;
|
||||||
const unsigned char P25_DUID_TERM = 0x03U;
|
const unsigned char P25_DUID_TERM = 0x03U;
|
||||||
const unsigned char P25_DUID_LDU1 = 0x05U;
|
const unsigned char P25_DUID_LDU1 = 0x05U;
|
||||||
const unsigned char P25_DUID_LDU2 = 0x09U;
|
const unsigned char P25_DUID_LDU2 = 0x0AU;
|
||||||
const unsigned char P25_DUID_PDU = 0x0CU;
|
const unsigned char P25_DUID_PDU = 0x0CU;
|
||||||
const unsigned char P25_DUID_TERM_LC = 0x0FU;
|
const unsigned char P25_DUID_TERM_LC = 0x0FU;
|
||||||
|
|
||||||
|
|
80
P25NID.cpp
Normal file
80
P25NID.cpp
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* 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 "P25NID.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])
|
||||||
|
|
||||||
|
CP25NID::CP25NID() :
|
||||||
|
m_duid(0U),
|
||||||
|
m_nac(0U)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CP25NID::~CP25NID()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CP25NID::process(unsigned char* data)
|
||||||
|
{
|
||||||
|
assert(data != NULL);
|
||||||
|
|
||||||
|
unsigned char nid[P25_NID_LENGTH_BYTES];
|
||||||
|
|
||||||
|
unsigned int n = 0U;
|
||||||
|
for (unsigned int offset = 48U; offset < 114U; offset++) {
|
||||||
|
if (offset != 70U && offset != 71U) {
|
||||||
|
bool b = READ_BIT(data, offset);
|
||||||
|
WRITE_BIT(nid, n, b);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Process FEC here
|
||||||
|
|
||||||
|
m_duid = nid[1U] & 0x0FU;
|
||||||
|
|
||||||
|
m_nac = (nid[0U] << 4) & 0xFF0U;
|
||||||
|
m_nac |= (nid[1U] >> 4) & 0x00FU;
|
||||||
|
|
||||||
|
n = 0U;
|
||||||
|
for (unsigned int offset = 48U; offset < 114U; offset++) {
|
||||||
|
if (offset != 70U && offset != 71U) {
|
||||||
|
bool b = READ_BIT(nid, n);
|
||||||
|
WRITE_BIT(data, offset, b);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char CP25NID::getDUID() const
|
||||||
|
{
|
||||||
|
return m_duid;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CP25NID::getNAC() const
|
||||||
|
{
|
||||||
|
return m_nac;
|
||||||
|
}
|
37
P25NID.h
Normal file
37
P25NID.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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(P25NID_H)
|
||||||
|
#define P25NID_H
|
||||||
|
|
||||||
|
class CP25NID {
|
||||||
|
public:
|
||||||
|
CP25NID();
|
||||||
|
~CP25NID();
|
||||||
|
|
||||||
|
void process(unsigned char* data);
|
||||||
|
|
||||||
|
unsigned char getDUID() const;
|
||||||
|
unsigned int getNAC() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char m_duid;
|
||||||
|
unsigned int m_nac;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -257,11 +257,11 @@ unsigned int CYSFPayload::processVDMode1Audio(unsigned char* data)
|
||||||
|
|
||||||
// Regenerate the AMBE FEC
|
// Regenerate the AMBE FEC
|
||||||
unsigned int errors = 0U;
|
unsigned int errors = 0U;
|
||||||
errors += m_fec.regenerateYSF1(data + 9U);
|
errors += m_fec.regenerateYSFDN(data + 9U);
|
||||||
errors += m_fec.regenerateYSF1(data + 27U);
|
errors += m_fec.regenerateYSFDN(data + 27U);
|
||||||
errors += m_fec.regenerateYSF1(data + 45U);
|
errors += m_fec.regenerateYSFDN(data + 45U);
|
||||||
errors += m_fec.regenerateYSF1(data + 63U);
|
errors += m_fec.regenerateYSFDN(data + 63U);
|
||||||
errors += m_fec.regenerateYSF1(data + 81U);
|
errors += m_fec.regenerateYSFDN(data + 81U);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
@ -788,13 +788,13 @@ unsigned int CYSFPayload::processVoiceFRModeAudio(unsigned char* data)
|
||||||
|
|
||||||
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
|
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
|
||||||
|
|
||||||
// Regenerate the AMBE FEC
|
// Regenerate the IMBE FEC
|
||||||
unsigned int errors = 0U;
|
unsigned int errors = 0U;
|
||||||
errors += m_fec.regenerateYSF3(data + 0U);
|
errors += m_fec.regenerateIMBE(data + 0U);
|
||||||
errors += m_fec.regenerateYSF3(data + 18U);
|
errors += m_fec.regenerateIMBE(data + 18U);
|
||||||
errors += m_fec.regenerateYSF3(data + 36U);
|
errors += m_fec.regenerateIMBE(data + 36U);
|
||||||
errors += m_fec.regenerateYSF3(data + 54U);
|
errors += m_fec.regenerateIMBE(data + 54U);
|
||||||
errors += m_fec.regenerateYSF3(data + 72U);
|
errors += m_fec.regenerateIMBE(data + 72U);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue