Add embedded data dumping.

This commit is contained in:
Jonathan Naylor 2017-01-05 19:00:01 +00:00
parent 1fa1a58867
commit 8debea45e4
4 changed files with 116 additions and 73 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -26,21 +26,26 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
CDMREmbeddedLC::CDMREmbeddedLC() : CDMREmbeddedLC::CDMREmbeddedLC(unsigned int slotNo) :
m_rawLC(NULL), m_slotNo(slotNo),
m_state(LCS_NONE) m_raw(NULL),
m_state(LCS_NONE),
m_data(NULL),
m_FLCO(FLCO_GROUP),
m_valid(false)
{ {
// Allow for multi-block non embedded LC data m_raw = new bool[128U];
m_rawLC = new bool[300U]; m_data = new bool[72U];
} }
CDMREmbeddedLC::~CDMREmbeddedLC() CDMREmbeddedLC::~CDMREmbeddedLC()
{ {
delete[] m_rawLC; delete[] m_raw;
delete[] m_data;
} }
// Add LC data (which may consist of 4 blocks) to the data store // Add LC data (which may consist of 4 blocks) to the data store
CDMRLC* CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss) bool CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss)
{ {
assert(data != NULL); assert(data != NULL);
@ -54,49 +59,48 @@ CDMRLC* CDMREmbeddedLC::addData(const unsigned char* data, unsigned char lcss)
// Is this the first block of a 4 block embedded LC ? // Is this the first block of a 4 block embedded LC ?
if (lcss == 1U) { if (lcss == 1U) {
for (unsigned int a = 0U; a < 32U; a++) for (unsigned int a = 0U; a < 32U; a++)
m_rawLC[a] = rawData[a + 4U]; m_raw[a] = rawData[a + 4U];
// Show we are ready for the next LC block // Show we are ready for the next LC block
m_state = LCS_FIRST; m_state = LCS_FIRST;
return NULL; m_valid = false;
return false;
} }
// Is this the 2nd block of a 4 block embedded LC ? // Is this the 2nd block of a 4 block embedded LC ?
if (lcss == 3U && m_state == LCS_FIRST) { if (lcss == 3U && m_state == LCS_FIRST) {
for (unsigned int a = 0U; a < 32U; a++) for (unsigned int a = 0U; a < 32U; a++)
m_rawLC[a + 32U] = rawData[a + 4U]; m_raw[a + 32U] = rawData[a + 4U];
// Show we are ready for the next LC block // Show we are ready for the next LC block
m_state = LCS_SECOND; m_state = LCS_SECOND;
return NULL; return false;
} }
// Is this the 3rd block of a 4 block embedded LC ? // Is this the 3rd block of a 4 block embedded LC ?
if (lcss == 3U && m_state == LCS_SECOND) { if (lcss == 3U && m_state == LCS_SECOND) {
for (unsigned int a = 0U; a < 32U; a++) for (unsigned int a = 0U; a < 32U; a++)
m_rawLC[a + 64U] = rawData[a + 4U]; m_raw[a + 64U] = rawData[a + 4U];
// Show we are ready for the final LC block // Show we are ready for the final LC block
m_state = LCS_THIRD; m_state = LCS_THIRD;
return NULL; return false;
} }
// Is this the final block of a 4 block embedded LC ? // Is this the final block of a 4 block embedded LC ?
if (lcss == 2U && m_state == LCS_THIRD) { if (lcss == 2U && m_state == LCS_THIRD) {
for (unsigned int a = 0U; a < 32U; a++) for (unsigned int a = 0U; a < 32U; a++)
m_rawLC[a + 96U] = rawData[a + 4U]; m_raw[a + 96U] = rawData[a + 4U];
// Process the complete data block // Process the complete data block
return processMultiBlockEmbeddedLC(); return processEmbeddedData();
} }
// Is this a single block embedded LC // Is this a single block embedded LC
if (lcss == 0U) { if (lcss == 0U)
processSingleBlockEmbeddedLC(rawData + 4U); return false;
return NULL;
}
return NULL; return false;
} }
void CDMREmbeddedLC::setData(const CDMRLC& lc) void CDMREmbeddedLC::setData(const CDMRLC& lc)
@ -143,7 +147,7 @@ void CDMREmbeddedLC::setData(const CDMRLC& lc)
// The data is packed downwards in columns // The data is packed downwards in columns
b = 0U; b = 0U;
for (unsigned int a = 0U; a < 128U; a++) { for (unsigned int a = 0U; a < 128U; a++) {
m_rawLC[a] = data[b]; m_raw[a] = data[b];
b += 16U; b += 16U;
if (b > 127U) if (b > 127U)
b -= 127U; b -= 127U;
@ -159,7 +163,7 @@ unsigned char CDMREmbeddedLC::getData(unsigned char* data, unsigned char n) cons
bool bits[40U]; bool bits[40U];
::memset(bits, 0x00U, 40U * sizeof(bool)); ::memset(bits, 0x00U, 40U * sizeof(bool));
::memcpy(bits + 4U, m_rawLC + n * 32U, 32U * sizeof(bool)); ::memcpy(bits + 4U, m_raw + n * 32U, 32U * sizeof(bool));
unsigned char bytes[5U]; unsigned char bytes[5U];
CUtils::bitsToByteBE(bits + 0U, bytes[0U]); CUtils::bitsToByteBE(bits + 0U, bytes[0U]);
@ -194,7 +198,7 @@ unsigned char CDMREmbeddedLC::getData(unsigned char* data, unsigned char n) cons
} }
// Unpack and error check an embedded LC // Unpack and error check an embedded LC
CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC() bool CDMREmbeddedLC::processEmbeddedData()
{ {
// The data is unpacked downwards in columns // The data is unpacked downwards in columns
bool data[128U]; bool data[128U];
@ -202,7 +206,7 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC()
unsigned int b = 0U; unsigned int b = 0U;
for (unsigned int a = 0U; a < 128U; a++) { for (unsigned int a = 0U; a < 128U; a++) {
data[b] = m_rawLC[a]; data[b] = m_raw[a];
b += 16U; b += 16U;
if (b > 127U) if (b > 127U)
b -= 127U; b -= 127U;
@ -211,33 +215,32 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC()
// Hamming (16,11,4) check each row except the last one // Hamming (16,11,4) check each row except the last one
for (unsigned int a = 0U; a < 112U; a += 16U) { for (unsigned int a = 0U; a < 112U; a += 16U) {
if (!CHamming::decode16114(data + a)) if (!CHamming::decode16114(data + a))
return NULL; return false;
} }
// Check the parity bits // Check the parity bits
for (unsigned int a = 0U; a < 16U; a++) { for (unsigned int a = 0U; a < 16U; a++) {
bool parity = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U] ^ data[a + 112U]; bool parity = data[a + 0U] ^ data[a + 16U] ^ data[a + 32U] ^ data[a + 48U] ^ data[a + 64U] ^ data[a + 80U] ^ data[a + 96U] ^ data[a + 112U];
if (parity) if (parity)
return NULL; return false;
} }
// We have passed the Hamming check so extract the actual payload // We have passed the Hamming check so extract the actual payload
bool lcData[72U];
b = 0U; b = 0U;
for (unsigned int a = 0U; a < 11U; a++, b++) for (unsigned int a = 0U; a < 11U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 16U; a < 27U; a++, b++) for (unsigned int a = 16U; a < 27U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 32U; a < 42U; a++, b++) for (unsigned int a = 32U; a < 42U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 48U; a < 58U; a++, b++) for (unsigned int a = 48U; a < 58U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 64U; a < 74U; a++, b++) for (unsigned int a = 64U; a < 74U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 80U; a < 90U; a++, b++) for (unsigned int a = 80U; a < 90U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
for (unsigned int a = 96U; a < 106U; a++, b++) for (unsigned int a = 96U; a < 106U; a++, b++)
lcData[b] = data[a]; m_data[b] = data[a];
// Extract the 5 bit CRC // Extract the 5 bit CRC
unsigned int crc = 0U; unsigned int crc = 0U;
@ -248,45 +251,63 @@ CDMRLC* CDMREmbeddedLC::processMultiBlockEmbeddedLC()
if (data[106]) crc += 1U; if (data[106]) crc += 1U;
// Now CRC check this // Now CRC check this
if (!CCRC::checkFiveBit(lcData, crc)) if (!CCRC::checkFiveBit(m_data, crc))
return NULL; return false;
CDMRLC* lc = new CDMRLC(lcData); // Extract the FLCO
unsigned char flco;
CUtils::bitsToByteBE(m_data + 0U, flco);
m_FLCO = FLCO(flco & 0x3FU);
char text[80U];
// Only generate the LC when it's the correct FLCO // Only generate the LC when it's the correct FLCO
switch (lc->getFLCO()) { switch (m_FLCO) {
case FLCO_GROUP: case FLCO_GROUP:
case FLCO_USER_USER: case FLCO_USER_USER:
return lc; ::sprintf(text, "DMR Slot %u, Embedded LC Data", m_slotNo);
CUtils::dump(1U, text, m_data, 72U);
return true;
case FLCO_GPS_INFO: case FLCO_GPS_INFO:
CUtils::dump(1U, "DMR, Embedded GPS Info", lcData, 72U); ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return true;
case FLCO_TALKER_ALIAS_HEADER: case FLCO_TALKER_ALIAS_HEADER:
CUtils::dump(1U, "DMR, Embedded Talker Alias Header", lcData, 72U); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return true;
case FLCO_TALKER_ALIAS_BLOCK1: case FLCO_TALKER_ALIAS_BLOCK1:
CUtils::dump(1U, "DMR, Embedded Talker Alias Block 1", lcData, 72U); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return true;
case FLCO_TALKER_ALIAS_BLOCK2: case FLCO_TALKER_ALIAS_BLOCK2:
CUtils::dump(1U, "DMR, Embedded Talker Alias Block 2", lcData, 72U); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return true;
case FLCO_TALKER_ALIAS_BLOCK3: case FLCO_TALKER_ALIAS_BLOCK3:
CUtils::dump(1U, "DMR, Embedded Talker Alias Block 3", lcData, 72U); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return true;
default: default:
CUtils::dump(1U, "DMR, Unknown Embedded Data", lcData, 72U); ::sprintf(text, "DMR Slot %u, Unknown Embedded Data", m_slotNo);
delete lc; CUtils::dump(1U, text, m_data, 72U);
return NULL; return false;
} }
} }
// Deal with a single block embedded LC CDMRLC* CDMREmbeddedLC::getLC() const
void CDMREmbeddedLC::processSingleBlockEmbeddedLC(const bool* data)
{ {
// Nothing interesting, or just NULL (I think) if (!m_valid)
return NULL;
if (m_FLCO != FLCO_GROUP && m_FLCO != FLCO_USER_USER)
return NULL;
return new CDMRLC(m_data);
} }
void CDMREmbeddedLC::reset()
{
m_state = LCS_NONE;
m_valid = false;
}

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -19,6 +19,7 @@
#ifndef DMREmbeddedLC_H #ifndef DMREmbeddedLC_H
#define DMREmbeddedLC_H #define DMREmbeddedLC_H
#include "DMRDefines.h"
#include "DMRLC.h" #include "DMRLC.h"
enum LC_STATE { enum LC_STATE {
@ -31,20 +32,27 @@ enum LC_STATE {
class CDMREmbeddedLC class CDMREmbeddedLC
{ {
public: public:
CDMREmbeddedLC(); CDMREmbeddedLC(unsigned int slotNo);
~CDMREmbeddedLC(); ~CDMREmbeddedLC();
CDMRLC* addData(const unsigned char* data, unsigned char lcss); bool addData(const unsigned char* data, unsigned char lcss);
CDMRLC* getLC() const;
void setData(const CDMRLC& lc); void setData(const CDMRLC& lc);
unsigned char getData(unsigned char* data, unsigned char n) const; unsigned char getData(unsigned char* data, unsigned char n) const;
private: void reset();
bool* m_rawLC;
LC_STATE m_state;
CDMRLC* processMultiBlockEmbeddedLC(); private:
void processSingleBlockEmbeddedLC(const bool* data); unsigned int m_slotNo;
bool* m_raw;
LC_STATE m_state;
bool* m_data;
FLCO m_FLCO;
bool m_valid;
bool processEmbeddedData();
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -58,7 +58,8 @@ m_slotNo(slotNo),
m_queue(5000U, "DMR Slot"), m_queue(5000U, "DMR Slot"),
m_rfState(RS_RF_LISTENING), m_rfState(RS_RF_LISTENING),
m_netState(RS_NET_IDLE), m_netState(RS_NET_IDLE),
m_rfEmbeddedLC(), m_rfEmbeddedLC(slotNo),
m_netEmbeddedLC(slotNo),
m_rfLC(NULL), m_rfLC(NULL),
m_netLC(NULL), m_netLC(NULL),
m_rfDataHeader(), m_rfDataHeader(),
@ -176,6 +177,7 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
data[1U] = 0x00U; data[1U] = 0x00U;
m_rfTimeoutTimer.start(); m_rfTimeoutTimer.start();
m_rfEmbeddedLC.reset();
m_rfFrames = 0U; m_rfFrames = 0U;
m_rfSeqNo = 0U; m_rfSeqNo = 0U;
@ -433,11 +435,14 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
m_rfEmbeddedLC.reset();
if (m_duplex) if (m_duplex)
writeQueueRF(data); writeQueueRF(data);
writeNetworkRF(data, DT_VOICE_SYNC, errors); writeNetworkRF(data, DT_VOICE_SYNC, errors);
} else if (m_rfState == RS_RF_LISTENING) { } else if (m_rfState == RS_RF_LISTENING) {
m_rfEmbeddedLC.reset();
m_rfState = RS_RF_LATE_ENTRY; m_rfState = RS_RF_LATE_ENTRY;
} }
} else { } else {
@ -458,6 +463,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_rfErrs += errors; m_rfErrs += errors;
} }
m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS());
m_rfBits += 141U; m_rfBits += 141U;
m_rfFrames++; m_rfFrames++;
@ -478,7 +485,8 @@ void CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (colorCode != m_colorCode) if (colorCode != m_colorCode)
return; return;
CDMRLC* lc = m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS()); m_rfEmbeddedLC.addData(data + 2U, emb.getLCSS());
CDMRLC* lc = m_rfEmbeddedLC.getLC();
if (lc != NULL) { if (lc != NULL) {
unsigned int srcId = lc->getSrcId(); unsigned int srcId = lc->getSrcId();
unsigned int dstId = lc->getDstId(); unsigned int dstId = lc->getDstId();
@ -778,6 +786,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastFrameValid = false; m_lastFrameValid = false;
m_netTimeoutTimer.start(); m_netTimeoutTimer.start();
m_netEmbeddedLC.reset();
m_netFrames = 0U; m_netFrames = 0U;
m_netLost = 0U; m_netLost = 0U;
@ -823,6 +832,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastFrameValid = false; m_lastFrameValid = false;
m_netTimeoutTimer.start(); m_netTimeoutTimer.start();
m_netEmbeddedLC.reset();
if (m_duplex) { if (m_duplex) {
m_queue.clear(); m_queue.clear();
@ -1071,6 +1081,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
writeQueueNet(data); writeQueueNet(data);
m_netEmbeddedLC.reset();
m_packetTimer.start(); m_packetTimer.start();
m_elapsed.start(); m_elapsed.start();
@ -1098,6 +1109,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_lastEMB.setColorCode(m_colorCode); m_lastEMB.setColorCode(m_colorCode);
m_lastEMB.getData(data + 2U); m_lastEMB.getData(data + 2U);
m_netEmbeddedLC.addData(data + 2U, m_lastEMB.getLCSS());
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -59,6 +59,7 @@ private:
RPT_RF_STATE m_rfState; RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState; RPT_NET_STATE m_netState;
CDMREmbeddedLC m_rfEmbeddedLC; CDMREmbeddedLC m_rfEmbeddedLC;
CDMREmbeddedLC m_netEmbeddedLC;
CDMRLC* m_rfLC; CDMRLC* m_rfLC;
CDMRLC* m_netLC; CDMRLC* m_netLC;
CDMRDataHeader m_rfDataHeader; CDMRDataHeader m_rfDataHeader;