Add RF end of transmission when either RF or network is lost.

This commit is contained in:
Jonathan Naylor 2016-02-07 20:12:24 +00:00
parent 91a328935f
commit fb3d76787a
4 changed files with 56 additions and 161 deletions

View file

@ -75,7 +75,7 @@ void CDMRSlot::writeModem(unsigned char *data)
if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) { if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
if (m_bits == 0U) m_bits = 1U; if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, float(m_errs * 100U) / float(m_bits)); LogMessage("DMR Slot %u, transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, float(m_errs * 100U) / float(m_bits));
writeEndOfTransmission(); writeEndOfTransmission(true);
return; return;
} }
@ -118,7 +118,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -153,7 +153,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -171,7 +171,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Set the Data Sync to be from the BS // Set the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_EOT; data[0U] = TAG_EOT;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -210,7 +210,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -253,7 +253,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -280,7 +280,7 @@ void CDMRSlot::writeModem(unsigned char *data)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
m_frames--; m_frames--;
@ -302,7 +302,7 @@ void CDMRSlot::writeModem(unsigned char *data)
if (m_state == RS_RELAYING_RF_AUDIO) { if (m_state == RS_RELAYING_RF_AUDIO) {
// Convert the Audio Sync to be from the BS // Convert the Audio Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_AUDIO); sync.addAudioSync(data + 2U);
unsigned char fid = m_lc->getFID(); unsigned char fid = m_lc->getFID();
if (fid == FID_ETSI || fid == FID_DMRA) if (fid == FID_ETSI || fid == FID_DMRA)
@ -352,7 +352,7 @@ void CDMRSlot::writeModem(unsigned char *data)
unsigned char start[DMR_FRAME_LENGTH_BYTES + 2U]; unsigned char start[DMR_FRAME_LENGTH_BYTES + 2U];
CDMRSync sync; CDMRSync sync;
sync.addSync(start + 2U, DST_BS_DATA); sync.addDataSync(start + 2U);
CFullLC fullLC; CFullLC fullLC;
fullLC.encode(*m_lc, start + 2U, DT_VOICE_LC_HEADER); fullLC.encode(*m_lc, start + 2U, DT_VOICE_LC_HEADER);
@ -421,7 +421,7 @@ unsigned int CDMRSlot::readModem(unsigned char* data)
return len; return len;
} }
void CDMRSlot::writeEndOfTransmission() void CDMRSlot::writeEndOfTransmission(bool writeEnd)
{ {
m_state = RS_LISTENING; m_state = RS_LISTENING;
@ -439,6 +439,29 @@ void CDMRSlot::writeEndOfTransmission()
m_errs = 0U; m_errs = 0U;
m_bits = 0U; m_bits = 0U;
if (writeEnd) {
// Create a dummy start end frame
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];
CDMRSync sync;
sync.addDataSync(data + 2U);
CFullLC fullLC;
fullLC.encode(*m_lc, data + 2U, DT_TERMINATOR_WITH_LC);
CSlotType slotType;
slotType.setColorCode(m_colorCode);
slotType.setDataType(DT_TERMINATOR_WITH_LC);
slotType.getData(data + 2U);
data[0U] = TAG_DATA;
data[1U] = 0x00U;
// 480ms of terminator to space things out
for (unsigned int i = 0U; i < 8U; i++)
writeQueue(data);
}
delete m_lc; delete m_lc;
m_lc = NULL; m_lc = NULL;
@ -478,7 +501,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -520,7 +543,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -542,7 +565,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_EOT; data[0U] = TAG_EOT;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -587,7 +610,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -655,7 +678,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Audio Sync to be from the BS // Convert the Audio Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_AUDIO); sync.addAudioSync(data + 2U);
writeQueue(data); writeQueue(data);
@ -734,7 +757,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
data[1U] = 0x00U; data[1U] = 0x00U;
@ -766,7 +789,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// Convert the Data Sync to be from the BS // Convert the Data Sync to be from the BS
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA); sync.addDataSync(data + 2U);
m_frames--; m_frames--;
@ -801,7 +824,7 @@ void CDMRSlot::clock(unsigned int ms)
m_frames += 1U; m_frames += 1U;
if (m_bits == 0U) m_bits = 1U; if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits)); LogMessage("DMR Slot %u, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));
writeEndOfTransmission(); writeEndOfTransmission(true);
#if defined(DUMP_DMR) #if defined(DUMP_DMR)
closeFile(); closeFile();
#endif #endif
@ -1068,7 +1091,7 @@ void CDMRSlot::insertSilence(unsigned int count)
if (n == 0U) { if (n == 0U) {
CDMRSync sync; CDMRSync sync;
sync.addSync(data + 2U, DST_BS_AUDIO); sync.addAudioSync(data + 2U);
} else { } else {
// Set the Embedded LC to 0x00 // Set the Embedded LC to 0x00
::memset(data + 2U + 13U, 0x00U, 5U); ::memset(data + 2U + 13U, 0x00U, 5U);

View file

@ -87,7 +87,7 @@ private:
void writeNetwork(const unsigned char* data, unsigned char dataType); void writeNetwork(const unsigned char* data, unsigned char dataType);
void writeNetwork(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId); void writeNetwork(const unsigned char* data, unsigned char dataType, FLCO flco, unsigned int srcId, unsigned int dstId);
void writeEndOfTransmission(); void writeEndOfTransmission(bool writeEnd = false);
bool openFile(); bool openFile();
bool writeFile(const unsigned char* data); bool writeFile(const unsigned char* data);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 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
@ -22,24 +22,6 @@
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
const unsigned int BITS_LOOKUP[] = {0U, 1U, 1U, 2U, 1U, 2U, 2U, 3U, 1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U,
1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U, 2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U,
1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U, 2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U, 2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U, 4U, 5U, 5U, 6U, 5U, 6U, 6U, 7U,
1U, 2U, 2U, 3U, 2U, 3U, 3U, 4U, 2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U, 4U, 5U, 5U, 6U, 5U, 6U, 6U, 7U,
2U, 3U, 3U, 4U, 3U, 4U, 4U, 5U, 3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U,
3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U, 4U, 5U, 5U, 6U, 5U, 6U, 6U, 7U,
3U, 4U, 4U, 5U, 4U, 5U, 5U, 6U, 4U, 5U, 5U, 6U, 5U, 6U, 6U, 7U,
4U, 5U, 5U, 6U, 5U, 6U, 6U, 7U, 5U, 6U, 6U, 7U, 6U, 7U, 7U, 8U};
const unsigned int THRESHOLD = 4U;
CDMRSync::CDMRSync() CDMRSync::CDMRSync()
{ {
@ -49,107 +31,18 @@ CDMRSync::~CDMRSync()
{ {
} }
DMR_SYNC_TYPE CDMRSync::matchDirectSync(const unsigned char* bytes) const void CDMRSync::addDataSync(unsigned char* data) const
{
assert(bytes != NULL);
unsigned int diffs = compareBytes(bytes + 13U, DIRECT_SLOT1_AUDIO_SYNC);
if (diffs < THRESHOLD)
return DST_DIRECT_SLOT1_AUDIO;
diffs = compareBytes(bytes + 13U, DIRECT_SLOT2_AUDIO_SYNC);
if (diffs < THRESHOLD)
return DST_DIRECT_SLOT2_AUDIO;
diffs = compareBytes(bytes + 13U, DIRECT_SLOT1_DATA_SYNC);
if (diffs < THRESHOLD)
return DST_DIRECT_SLOT1_DATA;
diffs = compareBytes(bytes + 13U, DIRECT_SLOT2_DATA_SYNC);
if (diffs < THRESHOLD)
return DST_DIRECT_SLOT2_DATA;
return DST_NONE;
}
DMR_SYNC_TYPE CDMRSync::matchMSSync(const unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned int diffs = compareBytes(bytes + 13U, MS_SOURCED_AUDIO_SYNC);
if (diffs < THRESHOLD)
return DST_MS_AUDIO;
diffs = compareBytes(bytes + 13U, MS_SOURCED_DATA_SYNC);
if (diffs < THRESHOLD)
return DST_MS_DATA;
return DST_NONE;
}
DMR_SYNC_TYPE CDMRSync::matchBSSync(const unsigned char* bytes) const
{
assert(bytes != NULL);
unsigned int diffs = compareBytes(bytes + 13U, BS_SOURCED_AUDIO_SYNC);
if (diffs < THRESHOLD)
return DST_BS_AUDIO;
diffs = compareBytes(bytes + 13U, BS_SOURCED_DATA_SYNC);
if (diffs < THRESHOLD)
return DST_BS_DATA;
return DST_NONE;
}
void CDMRSync::addSync(unsigned char* data, DMR_SYNC_TYPE type) const
{ {
assert(data != NULL); assert(data != NULL);
const unsigned char* sync = NULL; for (unsigned int i = 0U; i < 7U; i++)
switch (type) { data[i + 13U] = (data[i + 13U] & ~SYNC_MASK[i]) | BS_SOURCED_DATA_SYNC[i];
case DST_BS_AUDIO: }
sync = BS_SOURCED_AUDIO_SYNC;
break; void CDMRSync::addAudioSync(unsigned char* data) const
case DST_BS_DATA: {
sync = BS_SOURCED_DATA_SYNC; assert(data != NULL);
break;
case DST_MS_AUDIO:
sync = MS_SOURCED_AUDIO_SYNC;
break;
case DST_MS_DATA:
sync = MS_SOURCED_DATA_SYNC;
break;
case DST_DIRECT_SLOT1_AUDIO:
sync = DIRECT_SLOT1_AUDIO_SYNC;
break;
case DST_DIRECT_SLOT1_DATA:
sync = DIRECT_SLOT1_DATA_SYNC;
break;
case DST_DIRECT_SLOT2_AUDIO:
sync = DIRECT_SLOT2_AUDIO_SYNC;
break;
case DST_DIRECT_SLOT2_DATA:
sync = DIRECT_SLOT2_DATA_SYNC;
break;
default:
return;
}
for (unsigned int i = 0U; i < 7U; i++) for (unsigned int i = 0U; i < 7U; i++)
data[i + 13U] = (data[i + 13U] & ~SYNC_MASK[i]) | sync[i]; data[i + 13U] = (data[i + 13U] & ~SYNC_MASK[i]) | BS_SOURCED_AUDIO_SYNC[i];
}
unsigned int CDMRSync::compareBytes(const unsigned char *bytes1, const unsigned char* bytes2) const
{
assert(bytes1 != NULL);
assert(bytes2 != NULL);
unsigned int diffs = 0U;
for (unsigned int i = 0U; i < 7U; i++) {
unsigned char b = SYNC_MASK[i] & (bytes1[i] ^ bytes2[i]);
diffs += BITS_LOOKUP[b];
}
return diffs;
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 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,38 +19,17 @@
#if !defined(DMRSYNC_H) #if !defined(DMRSYNC_H)
#define DMRSYNC_H #define DMRSYNC_H
enum DMR_SYNC_TYPE {
DST_BS_AUDIO,
DST_BS_DATA,
DST_MS_AUDIO,
DST_MS_DATA,
DST_DIRECT_SLOT1_AUDIO,
DST_DIRECT_SLOT1_DATA,
DST_DIRECT_SLOT2_AUDIO,
DST_DIRECT_SLOT2_DATA,
DST_NONE
};
class CDMRSync class CDMRSync
{ {
public: public:
CDMRSync(); CDMRSync();
~CDMRSync(); ~CDMRSync();
DMR_SYNC_TYPE matchDirectSync(const unsigned char* bytes) const; void addDataSync(unsigned char* data) const;
DMR_SYNC_TYPE matchMSSync(const unsigned char* bytes) const; void addAudioSync(unsigned char* data) const;
DMR_SYNC_TYPE matchBSSync(const unsigned char* bytes) const;
void addSync(unsigned char* data, DMR_SYNC_TYPE type) const;
private: private:
unsigned int compareBytes(const unsigned char* bytes1, const unsigned char* bytes2) const;
}; };
#endif #endif