More work on constructing RF P25 from network data.

This commit is contained in:
Jonathan Naylor 2016-09-20 20:13:13 +01:00
parent 1c7fbc0de5
commit 4c5d1492ce
6 changed files with 189 additions and 29 deletions

View file

@ -18,9 +18,10 @@
#include "P25Control.h"
#include "P25Defines.h"
#include "P25Utils.h"
#include "Utils.h"
#include "Sync.h"
#include "Log.h"
#include "Utils.h"
#include <cassert>
#include <ctime>
@ -50,8 +51,6 @@ m_rfFrames(0U),
m_rfBits(0U),
m_rfErrs(0U),
m_netFrames(0U),
m_netBits(0U),
m_netErrs(0U),
m_netLost(0U),
m_nid(nac),
m_lastDUID(P25_DUID_TERM),
@ -158,8 +157,6 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
data[1U] = 0x00U;
writeQueueRF(data, P25_HDR_FRAME_LENGTH_BYTES + 2U);
}
LogMessage("P25, received RF header");
} else if (duid == P25_DUID_LDU1) {
if (m_rfState == RS_RF_LISTENING) {
m_rfFrames = 0U;
@ -212,7 +209,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
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);
LogMessage("P25, received RF transmission 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;
}
@ -265,8 +262,7 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
// Regenerate NID
m_nid.encode(data + 2U, P25_DUID_TERM_LC);
// Regenerate LDU1 Data
m_rfData.processTerminator(data + 2U);
// Leave the termination LC untouched
// Add busy bits
addBusyBits(data + 2U, P25_TERMLC_FRAME_LENGTH_BITS, false, true);
@ -413,12 +409,6 @@ void CP25Control::writeNetwork()
case 0x73U:
::memcpy(m_netLDU2 + 200U, data, 16U);
if (m_netState != RS_NET_IDLE) {
m_netState = RS_NET_AUDIO;
m_netTimeout.start();
m_netBits = 1U;
m_netErrs = 0U;
m_netFrames = 0U;
m_netLost = 0U;
createHeader();
createLDU1();
}
@ -444,7 +434,7 @@ void CP25Control::clock(unsigned int ms)
m_networkWatchdog.clock(ms);
if (m_networkWatchdog.hasExpired()) {
LogMessage("P25, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_netFrames) / 5.56F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
LogMessage("P25, network watchdog has expired, %.1f seconds, %u%% packet loss", float(m_netFrames) / 5.56F, (m_netLost * 100U) / m_netFrames);
m_display->clearP25();
m_networkWatchdog.stop();
m_netState = RS_NET_IDLE;
@ -531,14 +521,103 @@ void CP25Control::addBusyBits(unsigned char* data, unsigned int length, bool b1,
void CP25Control::createHeader()
{
unsigned char buffer[P25_HDR_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_HDR_FRAME_LENGTH_BYTES + 2U);
buffer[0U] = TAG_HEADER;
buffer[1U] = 0x00U;
// Add the sync
CSync::addP25Sync(buffer + 2U);
// Add the NID
m_nid.encode(buffer + 2U, P25_DUID_HEADER);
// Add the dummy header
m_netData.createHeader(buffer + 2U);
// Add busy bits
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_HDR_FRAME_LENGTH_BYTES + 2U);
bool grp = m_netLDU1[51U] == 0x00U;
unsigned int dst = (m_netLDU1[76U] << 16) + (m_netLDU1[77U] << 8) + m_netLDU1[78U];
unsigned int src = (m_netLDU1[101U] << 16) + (m_netLDU1[102U] << 8) + m_netLDU1[103U];
std::string source = m_lookup->find(src);
LogMessage("P25, received network transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dst);
m_display->writeP25(source.c_str(), grp, dst, "N");
m_netData.setSource(src);
m_netData.setGroup(grp);
m_netData.setDest(dst);
m_netState = RS_NET_AUDIO;
m_netTimeout.start();
m_netFrames = 0U;
m_netLost = 0U;
}
void CP25Control::createLDU1()
{
unsigned char buffer[P25_LDU_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 2U);
buffer[0U] = TAG_DATA;
buffer[1U] = 0x00U;
// Add the sync
CSync::addP25Sync(buffer + 2U);
// Add the NID
m_nid.encode(buffer + 2U, P25_DUID_LDU1);
// Add the LDU1 data
m_netData.createLDU1(buffer + 2U);
// Add the Audio
// Add the Low Speed Data
m_lsd.encode(buffer + 2U, m_netLDU1[201U], m_netLDU1[202U]);
// Add busy bits
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
m_netFrames++;
}
void CP25Control::createLDU2()
{
unsigned char buffer[P25_LDU_FRAME_LENGTH_BYTES + 2U];
::memset(buffer, 0x00U, P25_LDU_FRAME_LENGTH_BYTES + 2U);
buffer[0U] = TAG_DATA;
buffer[1U] = 0x00U;
// Add the sync
CSync::addP25Sync(buffer + 2U);
// Add the NID
m_nid.encode(buffer + 2U, P25_DUID_LDU2);
// Add the dummy LDU2 data
m_netData.createLDU2(buffer + 2U);
// Add the Audio
// Add the Low Speed Data
m_lsd.encode(buffer + 2U, m_netLDU2[201U], m_netLDU2[202U]);
// Add busy bits
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
m_netFrames++;
}
void CP25Control::createTerminator(const unsigned char* data)
@ -565,7 +644,7 @@ void CP25Control::createTerminator(const unsigned char* data)
writeQueueNet(buffer, P25_TERM_FRAME_LENGTH_BYTES + 2U);
LogMessage("P25, network end of transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_netFrames) / 5.56F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
LogMessage("P25, network end of transmission, %.1f seconds, %u%% packet loss", float(m_netFrames) / 5.56F, (m_netLost * 100U) / m_netFrames);
m_display->clearP25();
m_netTimeout.stop();

View file

@ -62,8 +62,6 @@ private:
unsigned int m_rfBits;
unsigned int m_rfErrs;
unsigned int m_netFrames;
unsigned int m_netBits;
unsigned int m_netErrs;
unsigned int m_netLost;
CP25NID m_nid;
unsigned char m_lastDUID;

View file

@ -23,6 +23,21 @@
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
const unsigned char DUMMY_HEADER[] = {
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x08U, 0xDCU, 0x60U,
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U, 0x93U, 0xE7U, 0x73U, 0x77U, 0x57U, 0xD6U, 0xD3U, 0xCFU, 0x77U,
0xEEU, 0x82U, 0x93U, 0xE2U, 0x2FU, 0xF3U, 0xD5U, 0xF5U, 0xBEU, 0xBCU, 0x54U, 0x0DU, 0x9CU, 0x29U, 0x3EU, 0x46U,
0xE3U, 0x28U, 0xB0U, 0xB7U, 0x73U, 0x76U, 0x1EU, 0x26U, 0x0CU, 0x75U, 0x5BU, 0xF7U, 0x4DU, 0x5FU, 0x5AU, 0x37U,
0x18U};
const unsigned char DUMMY_LDU2[] = {
0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0xACU, 0xB8U, 0xA4U, 0x9BU,
0xDCU, 0x75U};
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])
@ -43,16 +58,27 @@ CP25Data::~CP25Data()
void CP25Data::processHeader(unsigned char* data)
{
assert(data != NULL);
unsigned char raw[81U];
CP25Utils::decode(data, raw, 114U, 780U);
CUtils::dump(1U, "P25, raw header", raw, 81U);
// CUtils::dump(1U, "P25, raw header", raw, 81U);
// XXX Need to add FEC code
}
void CP25Data::createHeader(unsigned char* data)
{
assert(data != NULL);
CP25Utils::encode(DUMMY_HEADER, data, 114U, 780U);
}
void CP25Data::processLDU1(unsigned char* data)
{
assert(data != NULL);
unsigned char rs[18U];
unsigned char raw[5U];
@ -76,7 +102,7 @@ void CP25Data::processLDU1(unsigned char* data)
m_rs241213.decode(rs);
CUtils::dump(1U, "P25, LDU1 Data", rs, 9U);
// CUtils::dump(1U, "P25, LDU1 Data", rs, 9U);
switch (rs[0U]) {
case P25_LCF_GROUP:
@ -113,8 +139,15 @@ void CP25Data::processLDU1(unsigned char* data)
CP25Utils::encode(raw, data, 1356U, 1398U);
}
void CP25Data::createLDU1(unsigned char* data)
{
assert(data != NULL);
}
void CP25Data::processLDU2(unsigned char* data)
{
assert(data != NULL);
unsigned char rs[18U];
unsigned char raw[5U];
@ -138,7 +171,7 @@ void CP25Data::processLDU2(unsigned char* data)
m_rs24169.decode(rs);
CUtils::dump(1U, "P25, LDU2 Data", rs, 12U);
// CUtils::dump(1U, "P25, LDU2 Data", rs, 18U);
encodeLDUHamming(raw, rs + 0U);
CP25Utils::encode(raw, data, 410U, 452U);
@ -159,14 +192,33 @@ void CP25Data::processLDU2(unsigned char* data)
CP25Utils::encode(raw, data, 1356U, 1398U);
}
void CP25Data::processTerminator(unsigned char* data)
void CP25Data::createLDU2(unsigned char* data)
{
unsigned char raw[36U];
CP25Utils::decode(data, raw, 114U, 210U);
assert(data != NULL);
CUtils::dump(1U, "P25, raw terminator", raw, 36U);
unsigned char raw[5U];
encodeLDUHamming(raw, DUMMY_LDU2 + 0U);
CP25Utils::encode(raw, data, 410U, 452U);
// XXX Need to add FEC code, or do we?
encodeLDUHamming(raw, DUMMY_LDU2 + 3U);
CP25Utils::encode(raw, data, 600U, 640U);
encodeLDUHamming(raw, DUMMY_LDU2 + 6U);
CP25Utils::encode(raw, data, 788U, 830U);
encodeLDUHamming(raw, DUMMY_LDU2 + 9U);
CP25Utils::encode(raw, data, 978U, 1020U);
encodeLDUHamming(raw, DUMMY_LDU2 + 12U);
CP25Utils::encode(raw, data, 1168U, 1208U);
encodeLDUHamming(raw, DUMMY_LDU2 + 15U);
CP25Utils::encode(raw, data, 1356U, 1398U);
}
void CP25Data::setSource(unsigned int source)
{
m_source = source;
}
unsigned int CP25Data::getSource() const
@ -174,11 +226,21 @@ unsigned int CP25Data::getSource() const
return m_source;
}
void CP25Data::setGroup(bool yes)
{
m_group = yes;
}
bool CP25Data::getGroup() const
{
return m_group;
}
void CP25Data::setDest(unsigned int dest)
{
m_dest = dest;
}
unsigned int CP25Data::getDest() const
{
return m_dest;

View file

@ -27,16 +27,21 @@ public:
~CP25Data();
void processHeader(unsigned char* data);
void createHeader(unsigned char* data);
void processLDU1(unsigned char* data);
void createLDU1(unsigned char* data);
void processLDU2(unsigned char* data);
void createLDU2(unsigned char* data);
void processTerminator(unsigned char* data);
void setSource(unsigned int source);
unsigned int getSource() const;
void setGroup(bool yes);
bool getGroup() const;
void setDest(unsigned int dest);
unsigned int getDest() const;
void reset();

View file

@ -82,6 +82,21 @@ void CP25LowSpeedData::process(unsigned char* data) const
break;
}
}
CP25Utils::encode(lsd, data, 1546U, 1578U);
}
void CP25LowSpeedData::encode(unsigned char* data, unsigned char lsd1, unsigned char lsd2) const
{
assert(data != NULL);
unsigned char lsd[4U];
lsd[0U] = lsd1;
lsd[1U] = encode(lsd1);
lsd[2U] = lsd2;
lsd[3U] = encode(lsd2);
CP25Utils::encode(lsd, data, 1546U, 1578U);
}
unsigned char CP25LowSpeedData::encode(unsigned char in) const

View file

@ -26,9 +26,10 @@ public:
void process(unsigned char* data) const;
unsigned char encode(const unsigned char in) const;
void encode(unsigned char* data, unsigned char lsd1, unsigned char lsd2) const;
private:
unsigned char encode(const unsigned char in) const;
};
#endif