Skip to content

Commit

Permalink
Simplify the LSF processing to allow changed META field data changed
Browse files Browse the repository at this point in the history
through.
  • Loading branch information
g4klx committed Aug 26, 2021
1 parent ef6ce0e commit d1dc6bb
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 114 deletions.
156 changes: 106 additions & 50 deletions M17Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,12 @@ m_rfFrames(0U),
m_netFrames(0U),
m_rfErrs(0U),
m_rfBits(1U),
m_rfLSF(),
m_rfLSF1(),
m_rfLSF2(),
m_rfLSF3(),
m_rfLSFn(0U),
m_netLSF(),
m_netLSFn(0U),
m_rssiMapper(rssiMapper),
m_rssi(0U),
m_maxRSSI(0U),
Expand Down Expand Up @@ -106,8 +109,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
unsigned char type = data[0U];

if (type == TAG_LOST && (m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA_AUDIO)) {
std::string source = m_rfLSF.getSource();
std::string dest = m_rfLSF.getDest();
std::string source = m_rfLSF1.getSource();
std::string dest = m_rfLSF1.getDest();

if (m_rssi != 0U)
LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
Expand Down Expand Up @@ -160,19 +163,19 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
interleaver(temp, data + 2U);

if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_HEADER) {
m_rfLSF.reset();
m_rfLSF1.reset();

CM17Convolution conv;
unsigned char frame[M17_LSF_LENGTH_BYTES];
unsigned int ber = conv.decodeLinkSetup(data + 2U + M17_SYNC_LENGTH_BYTES, frame);

bool valid = CM17CRC::checkCRC16(frame, M17_LSF_LENGTH_BYTES);
if (valid) {
m_rfLSF.setLinkSetup(frame);
m_rfLSF1.setLinkSetup(frame);

bool ret = processRFHeader(false);
if (!ret) {
m_rfLSF.reset();
m_rfLSF1.reset();
return false;
}

Expand All @@ -181,16 +184,15 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
m_rfFrames = 0U;
m_rfErrs = ber;
m_rfBits = 368U;
m_rfLSF2.reset();
m_rfLSF3.reset();
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
m_rfLSFn = 0U;

if (m_network != NULL)
m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), frame);

#if defined(DUMP_M17)
openFile();
#endif
Expand All @@ -203,7 +205,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)

if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_DATA) {
m_rfState = RS_RF_LATE_ENTRY;
m_rfLSF.reset();
m_rfLSF1.reset();
}

if (m_rfState == RS_RF_LATE_ENTRY && data[0U] == TAG_DATA) {
Expand All @@ -220,31 +222,27 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);

m_rfLSFn = (lich4 >> 5) & 0x07U;
m_rfLSF.setFragment(lich, m_rfLSFn);
m_rfLSF1.setFragment(lich, m_rfLSFn);

bool valid = m_rfLSF.isValid();
bool valid = m_rfLSF1.isValid();
if (valid) {
bool ret = processRFHeader(true);
if (!ret) {
m_rfLSF.reset();
m_rfLSF1.reset();
return false;
}

m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
m_rfLSF2.reset();
m_rfLSF3.reset();
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;

if (m_network != NULL) {
unsigned char lsf[M17_LSF_LENGTH_BYTES];
m_rfLSF.getNetwork(lsf);
m_network->writeHeader(m_rfLSF.getSource(), m_rfLSF.getDest(), lsf);
}

#if defined(DUMP_M17)
openFile();
#endif
Expand All @@ -258,6 +256,37 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
#if defined(DUMP_M17)
writeFile(data + 2U);
#endif
// Keep looking at the running LSF in case of changed META field data
unsigned int lich1, lich2, lich3, lich4;
bool valid1 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 0U, lich1);
bool valid2 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 3U, lich2);
bool valid3 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 6U, lich3);
bool valid4 = CGolay24128::decode24128(data + 2U + M17_SYNC_LENGTH_BYTES + 9U, lich4);

if (valid1 && valid2 && valid3 && valid4) {
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);

unsigned int n = (lich4 >> 5) & 0x07U;
m_rfLSF2.setFragment(lich, n);

// If the latest LSF is valid, save it and start collecting the next one
bool valid = m_rfLSF2.isValid();
if (valid) {
m_rfLSF3 = m_rfLSF2;
m_rfLSF2.reset();
}
}

// Update the currently transmitted LSF when the fragement number is zero
if (m_rfLSFn == 0U) {
bool valid = m_rfLSF3.isValid();
if (valid) {
m_rfLSF1 = m_rfLSF3;
m_rfLSF3.reset();
}
}

CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES];
unsigned int errors = conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
Expand All @@ -282,7 +311,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
CSync::addM17StreamSync(rfData + 2U);

unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_rfLSF.getFragment(lich, m_rfLSFn);
m_rfLSF1.getFragment(lich, m_rfLSFn);

// Add the fragment number
lich[5U] = (m_rfLSFn & 0x07U) << 5;
Expand All @@ -309,13 +338,16 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
}

if (m_network != NULL && m_rfTimeoutTimer.isRunning() && !m_rfTimeoutTimer.hasExpired()) {
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_rfLSF.getFragment(lich, m_rfLSFn);
unsigned char netData[M17_LSF_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];

// Add the fragment number
lich[5U] = (m_rfLSFn & 0x07U) << 5;
m_rfLSF1.getNetwork(netData + 0U);

m_network->writeData(m_rfLSF.getSource(), m_rfLSF.getDest(), lich, frame);
// Copy the FN and payload from the frame
::memcpy(netData + M17_LSF_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);

// The CRC is added in the networking code

m_network->write(netData);
}

m_rfFrames++;
Expand All @@ -328,8 +360,8 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
bool bEnd = (fn & 0x8000U) == 0x8000U;

if (bValid && bEnd) {
std::string source = m_rfLSF.getSource();
std::string dest = m_rfLSF.getDest();
std::string source = m_rfLSF1.getSource();
std::string dest = m_rfLSF1.getDest();

if (m_rssi != 0U)
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
Expand Down Expand Up @@ -365,7 +397,9 @@ void CM17Control::writeEndRF()

m_rfTimeoutTimer.stop();

m_rfLSF.reset();
m_rfLSF1.reset();
m_rfLSF2.reset();
m_rfLSF3.reset();

if (m_netState == RS_NET_IDLE) {
m_display->clearM17();
Expand Down Expand Up @@ -409,17 +443,17 @@ void CM17Control::writeNetwork()

m_networkWatchdog.start();

if (netData[0U] == TAG_HEADER) {
m_netLSF.setNetwork(netData + 19U);
m_netLSF.setCAN(m_can);

if (!m_allowEncryption) {
unsigned char type = m_netLSF.getEncryptionType();
if (type != M17_ENCRYPTION_TYPE_NONE) {
m_network->reset();
return;
}
if (!m_allowEncryption) {
unsigned char type = m_netLSF.getEncryptionType();
if (type != M17_ENCRYPTION_TYPE_NONE) {
m_network->reset();
return;
}
}

if (m_netState == RS_NET_IDLE) {
m_netLSF.setNetwork(netData);
m_netLSF.setCAN(m_can);

std::string source = m_netLSF.getSource();
std::string dest = m_netLSF.getDest();
Expand All @@ -439,7 +473,7 @@ void CM17Control::writeNetwork()
m_netState = RS_NET_DATA_AUDIO;
break;
default:
LogMessage("M17, received unknown network transmission from %s to %s", source.c_str(), dest.c_str());
LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str());
m_network->reset();
break;
}
Expand All @@ -449,6 +483,7 @@ void CM17Control::writeNetwork()
m_netTimeoutTimer.start();
m_elapsed.start();
m_netFrames = 0U;
m_netLSFn = 0U;

// Create a dummy start message
unsigned char start[M17_FRAME_LENGTH_BYTES + 2U];
Expand All @@ -473,7 +508,13 @@ void CM17Control::writeNetwork()
writeQueueNet(start);
}

if (netData[0U] == TAG_DATA) {
if (m_netState == RS_NET_AUDIO || m_netState == RS_NET_DATA_AUDIO) {
// Refresh the LSF every six frames in case the META field changes
if (m_netLSFn == 0U) {
m_netLSF.setNetwork(netData);
m_netLSF.setCAN(m_can);
}

unsigned char data[M17_FRAME_LENGTH_BYTES + 2U];

data[0U] = TAG_DATA;
Expand All @@ -484,8 +525,15 @@ void CM17Control::writeNetwork()

m_netFrames++;

// Add the fragment LICH
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_netLSF.getFragment(lich, m_netLSFn);

// Add the fragment number
lich[5U] = (m_netLSFn & 0x07U) << 5;

unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICH(netData + 19U, frag1, frag2, frag3, frag4);
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);

// Add Golay to the LICH fragment here
unsigned int lich1 = CGolay24128::encode24128(frag1);
Expand All @@ -495,18 +543,26 @@ void CM17Control::writeNetwork()

CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, data + 2U + M17_SYNC_LENGTH_BYTES);

// Add the FN and the data/audio
unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES];
::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);

// Add the Convolution FEC
CM17Convolution conv;
conv.encodeData(netData + 25U, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);
conv.encodeData(payload, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);

unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);

writeQueueNet(data);

m_netLSFn++;
if (m_netLSFn >= 6U)
m_netLSFn = 0U;

// EOT handling
uint16_t fn = (netData[25U] << 8) + (netData[26U] << 0);
uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0);
if ((fn & 0x8000U) == 0x8000U) {
std::string source = m_netLSF.getSource();
std::string dest = m_netLSF.getDest();
Expand All @@ -518,19 +574,19 @@ void CM17Control::writeNetwork()

bool CM17Control::processRFHeader(bool lateEntry)
{
unsigned char packetStream = m_rfLSF.getPacketStream();
unsigned char packetStream = m_rfLSF1.getPacketStream();
if (packetStream == M17_PACKET_TYPE)
return false;

unsigned char can = m_rfLSF.getCAN();
unsigned char can = m_rfLSF1.getCAN();
if (can != m_can)
return false;

std::string source = m_rfLSF.getSource();
std::string dest = m_rfLSF.getDest();
std::string source = m_rfLSF1.getSource();
std::string dest = m_rfLSF1.getDest();

if (!m_allowEncryption) {
unsigned char type = m_rfLSF.getEncryptionType();
unsigned char type = m_rfLSF1.getEncryptionType();
if (type != M17_ENCRYPTION_TYPE_NONE) {
LogMessage("M17, access attempt with encryption from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_REJECTED;
Expand All @@ -547,7 +603,7 @@ bool CM17Control::processRFHeader(bool lateEntry)
}
}

unsigned char dataType = m_rfLSF.getDataType();
unsigned char dataType = m_rfLSF1.getDataType();
switch (dataType) {
case M17_DATA_TYPE_DATA:
LogMessage("M17, received RF%sdata transmission from %s to %s", lateEntry ? " late entry " : " ", source.c_str(), dest.c_str());
Expand Down Expand Up @@ -580,7 +636,7 @@ bool CM17Control::processRFHeader(bool lateEntry)
CSync::addM17LinkSetupSync(data + 2U);

unsigned char setup[M17_LSF_LENGTH_BYTES];
m_rfLSF.getLinkSetup(setup);
m_rfLSF1.getLinkSetup(setup);

// Add the convolution FEC
CM17Convolution conv;
Expand Down
5 changes: 4 additions & 1 deletion M17Control.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,12 @@ class CM17Control {
unsigned int m_netFrames;
unsigned int m_rfErrs;
unsigned int m_rfBits;
CM17LSF m_rfLSF;
CM17LSF m_rfLSF1;
CM17LSF m_rfLSF2;
CM17LSF m_rfLSF3;
unsigned int m_rfLSFn;
CM17LSF m_netLSF;
unsigned int m_netLSFn;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
unsigned char m_maxRSSI;
Expand Down
19 changes: 19 additions & 0 deletions M17LSF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
#include <cassert>
#include <cstring>

CM17LSF::CM17LSF(const CM17LSF& lsf) :
m_lsf(NULL),
m_valid(lsf.m_valid)
{
m_lsf = new unsigned char[M17_LSF_LENGTH_BYTES];

::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES);
}

CM17LSF::CM17LSF() :
m_lsf(NULL),
m_valid(false)
Expand Down Expand Up @@ -197,3 +206,13 @@ void CM17LSF::setFragment(const unsigned char* data, unsigned int n)

m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
}

CM17LSF& CM17LSF::operator=(const CM17LSF& lsf)
{
if (&lsf != this) {
::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES);
m_valid = lsf.m_valid;
}

return *this;
}
Loading

0 comments on commit d1dc6bb

Please sign in to comment.