Skip to content

Commit

Permalink
Change the network late entry and be less aggressive at filling silence.
Browse files Browse the repository at this point in the history
  • Loading branch information
g4klx committed Jan 22, 2016
1 parent 435ad79 commit 73375fb
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 156 deletions.
242 changes: 91 additions & 151 deletions DMRSlot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ m_seqNo(0U),
m_n(0U),
m_networkWatchdog(1000U, 0U, 1500U),
m_timeoutTimer(1000U, timeout),
m_packetTimer(1000U, 0U, 200U),
m_packetTimer(1000U, 0U, 300U),
m_elapsed(),
m_frames(0U),
m_lost(0U),
Expand All @@ -75,17 +75,16 @@ void CDMRSlot::writeModem(unsigned char *data)

if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_DATA) {
LogMessage("DMR Slot %u, transmission lost", m_slotNo);
writeTerminator(true);
writeEndOfTransmission();
return;
}

if (data[0U] == TAG_LOST && m_state == RS_RF_LATE_ENTRY) {
if (data[0U] == TAG_LOST && m_state == RS_LATE_ENTRY) {
m_state = RS_LISTENING;
return;
}

if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA || m_state == RS_NETWORK_LATE_ENTRY)
if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA)
return;

bool dataSync = (data[1U] & DMR_SYNC_DATA) == DMR_SYNC_DATA;
Expand Down Expand Up @@ -249,7 +248,7 @@ void CDMRSlot::writeModem(unsigned char *data)
writeQueue(data);
writeNetwork(data, DT_VOICE_SYNC);
} else if (m_state == RS_LISTENING) {
m_state = RS_RF_LATE_ENTRY;
m_state = RS_LATE_ENTRY;
}
} else {
CEMB emb;
Expand All @@ -272,7 +271,7 @@ void CDMRSlot::writeModem(unsigned char *data)

writeQueue(data);
writeNetwork(data, DT_VOICE);
} else if (m_state == RS_RF_LATE_ENTRY) {
} else if (m_state == RS_LATE_ENTRY) {
// If we haven't received an LC yet, then be strict on the color code
unsigned char colorCode = emb.getColorCode();
if (colorCode != m_colorCode)
Expand Down Expand Up @@ -375,7 +374,7 @@ void CDMRSlot::writeEndOfTransmission()

void CDMRSlot::writeNetwork(const CDMRData& dmrData)
{
if (m_state == RS_RELAYING_RF_AUDIO || m_state == RS_RELAYING_RF_DATA || m_state == RS_RF_LATE_ENTRY)
if (m_state == RS_RELAYING_RF_AUDIO || m_state == RS_RELAYING_RF_DATA || m_state == RS_LATE_ENTRY)
return;

m_networkWatchdog.start();
Expand Down Expand Up @@ -519,48 +518,31 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// LogMessage("DMR Slot %u, received network data header from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId());
LogMessage("DMR Slot %u, received network data header", m_slotNo);
} else if (dataType == DT_VOICE_SYNC) {
if (m_state == RS_RELAYING_NETWORK_AUDIO) {
// Initialise the lost packet data
if (m_frames == 0U) {
m_seqNo = dmrData.getSeqNo();
m_n = dmrData.getN();
m_elapsed.start();
m_lost = 0U;
} else {
insertSilence(dmrData.getSeqNo());
}
if (m_state == RS_LISTENING) {
m_lc = new CLC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId());

// Convert the Audio Sync to be from the BS
CDMRSync sync;
sync.addSync(data + 2U, DST_BS_AUDIO);
m_timeoutTimer.start();

unsigned char fid = m_lc->getFID();
if (fid == FID_ETSI || fid == FID_DMRA)
m_errs += m_fec.regenerateDMR(data + 2U);
m_bits += 216U;
// 540ms of idle to give breathing space for lost frames
for (unsigned int i = 0U; i < 9U; i++)
writeQueue(m_idle);

data[0U] = TAG_DATA;
data[1U] = 0x00U;
#if defined(DUMP_DMR)
openFile();
#endif
m_frames = 0U;

writeQueue(data);
m_bits = 1U;
m_errs = 0U;

m_packetTimer.start();
m_frames++;
m_state = RS_RELAYING_NETWORK_AUDIO;

// Save details in case we need to infill data
m_seqNo = dmrData.getSeqNo();
m_n = dmrData.getN();
setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO());

#if defined(DUMP_DMR)
writeFile(data);
#endif
} else {
m_state = RS_NETWORK_LATE_ENTRY;
m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId());

LogMessage("DMR Slot %u, received network late entry from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId());
}
}
else if (dataType == DT_VOICE) {
CEMB emb;
emb.putData(data + 2U);

if (m_state == RS_RELAYING_NETWORK_AUDIO) {
// Initialise the lost packet data
Expand All @@ -570,18 +552,20 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_elapsed.start();
m_lost = 0U;
} else {
insertSilence(dmrData.getSeqNo());
bool allow = insertSilence(dmrData);
if (!allow)
return;
}

// Convert the Audio Sync to be from the BS
CDMRSync sync;
sync.addSync(data + 2U, DST_BS_AUDIO);

unsigned char fid = m_lc->getFID();
if (fid == FID_ETSI || fid == FID_DMRA)
m_errs += m_fec.regenerateDMR(data + 2U);
m_bits += 216U;

// Change the color code in the EMB
emb.setColorCode(m_colorCode);
emb.getData(data + 2U);

data[0U] = TAG_DATA;
data[1U] = 0x00U;

Expand All @@ -597,79 +581,49 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
#if defined(DUMP_DMR)
writeFile(data);
#endif
} else if (m_state == RS_NETWORK_LATE_ENTRY) {
// If we haven't received an LC yet, then be strict on the color code
unsigned char colorCode = emb.getColorCode();
if (colorCode != m_colorCode)
return;

m_lc = m_embeddedLC.addData(data + 2U, emb.getLCSS());
if (m_lc != NULL) {
// Create a dummy start frame to replace the received frame
unsigned char start[DMR_FRAME_LENGTH_BYTES + 2U];

CDMRSync sync;
sync.addSync(start + 2U, DST_BS_DATA);

CFullLC fullLC;
fullLC.encode(*m_lc, start + 2U, DT_VOICE_LC_HEADER);

CSlotType slotType;
slotType.setColorCode(m_colorCode);
slotType.setDataType(DT_VOICE_LC_HEADER);
slotType.getData(start + 2U);

m_timeoutTimer.start();

// 540ms of idle to give breathing space for lost frames
for (unsigned int i = 0U; i < 9U; i++)
writeQueue(m_idle);

for (unsigned int i = 0U; i < 3U; i++)
writeQueue(start);
}
} else if (dataType == DT_VOICE) {
if (m_state != RS_RELAYING_NETWORK_AUDIO)
return;

#if defined(DUMP_DMR)
openFile();
writeFile(start);
#endif
// Initialise the lost packet data
if (m_frames == 0U) {
m_seqNo = dmrData.getSeqNo();
m_n = dmrData.getN();
m_elapsed.start();
m_lost = 0U;
} else {
bool allow = insertSilence(dmrData);
if (!allow)
return;
}

// Change the color code in the EMB
emb.setColorCode(m_colorCode);
emb.getData(data + 2U);
unsigned char fid = m_lc->getFID();
if (fid == FID_ETSI || fid == FID_DMRA)
m_errs += m_fec.regenerateDMR(data + 2U);
m_bits += 216U;

// Initialise the lost packet data
m_seqNo = dmrData.getSeqNo();
m_n = dmrData.getN();
m_elapsed.start();
m_lost = 0U;
// Change the color code in the EMB
CEMB emb;
emb.putData(data + 2U);
emb.setColorCode(m_colorCode);
emb.getData(data + 2U);

// Send the original audio frame out
unsigned char fid = m_lc->getFID();
if (fid == FID_ETSI || fid == FID_DMRA)
m_errs = m_fec.regenerateDMR(data + 2U);
m_bits = 216U;
data[0U] = TAG_DATA;
data[1U] = 0x00U;

data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeQueue(data);

writeQueue(data);
m_packetTimer.start();
m_frames++;

m_packetTimer.start();
m_frames = 1U;
// Save details in case we need to infill data
m_seqNo = dmrData.getSeqNo();
m_n = dmrData.getN();

#if defined(DUMP_DMR)
writeFile(data);
writeFile(data);
#endif

m_state = RS_RELAYING_NETWORK_AUDIO;

setShortLC(m_slotNo, m_lc->getDstId(), m_lc->getFLCO());

m_display->writeDMR(m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP, m_lc->getDstId());

LogMessage("DMR Slot %u, received network late entry from %u to %s%u", m_slotNo, m_lc->getSrcId(), m_lc->getFLCO() == FLCO_GROUP ? "TG " : "", m_lc->getDstId());
}
}
} else {
// Change the Color Code of the Slot Type
CSlotType slotType;
Expand All @@ -696,27 +650,24 @@ void CDMRSlot::clock(unsigned int ms)
{
m_timeoutTimer.clock(ms);

if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA || m_state == RS_NETWORK_LATE_ENTRY) {
if (m_state == RS_RELAYING_NETWORK_AUDIO || m_state == RS_RELAYING_NETWORK_DATA) {
m_networkWatchdog.clock(ms);

if (m_networkWatchdog.hasExpired()) {
if (m_state == RS_RELAYING_NETWORK_AUDIO) {
// We've received the voice header haven't we?
m_frames += 1U;
LogMessage("DMR Slot %u, network watchdog has expired, %u%% packet loss, BER: %u%%", m_slotNo, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
writeTerminator(false);
writeEndOfTransmission();
#if defined(DUMP_DMR)
closeFile();
#endif
} else if (m_state == RS_RELAYING_NETWORK_DATA) {
} else {
LogMessage("DMR Slot %u, network watchdog has expired", m_slotNo);
writeEndOfTransmission();
#if defined(DUMP_DMR)
closeFile();
#endif
} else {
m_state = RS_LISTENING;
}
}
}
Expand All @@ -730,8 +681,9 @@ void CDMRSlot::clock(unsigned int ms)
if (frames > m_frames) {
unsigned int count = frames - m_frames;
if (count > 3U) {
LogMessage("DMR Slot %u, lost audio for 200ms filling in", m_slotNo);
insertSilence(m_seqNo + count - 1U);
count -= 1U;
LogMessage("DMR Slot %u, lost audio for 300ms filling in", m_slotNo);
insertSilence(m_seqNo + count);
}
}

Expand All @@ -752,41 +704,6 @@ void CDMRSlot::writeQueue(const unsigned char *data)
m_queue.addData(data, len);
}

// XXX Once the PF flag is fixed in the LC, always use this for the terminator
void CDMRSlot::writeTerminator(bool toNetwork)
{
unsigned char data[DMR_FRAME_LENGTH_BYTES + 2U];

// Generate the LC
CFullLC fullLC;
fullLC.encode(*m_lc, data + 2U, DT_TERMINATOR_WITH_LC);

// Generate the Slot Type
CSlotType slotType;
slotType.setColorCode(m_colorCode);
slotType.setDataType(DT_TERMINATOR_WITH_LC);
slotType.getData(data + 2U);

// Set the Data Sync to be from the BS
CDMRSync sync;
sync.addSync(data + 2U, DST_BS_DATA);

data[0U] = TAG_EOT;
data[1U] = 0x00U;

// 480ms of terminator to space things out
for (unsigned int i = 0U; i < 8U; i++)
writeQueue(data);

if (toNetwork)
writeNetwork(data, DT_TERMINATOR_WITH_LC);

#if defined(DUMP_DMR)
writeFile(data);
closeFile();
#endif
}

void CDMRSlot::writeNetwork(const unsigned char* data, unsigned char dataType)
{
assert(m_lc != NULL);
Expand Down Expand Up @@ -946,6 +863,29 @@ void CDMRSlot::closeFile()
}
}

bool CDMRSlot::insertSilence(const CDMRData& dmrData)
{
unsigned int oldSeqNo = m_seqNo;
unsigned int newSeqNo = dmrData.getSeqNo();

unsigned int count;
if (newSeqNo > oldSeqNo)
count = newSeqNo - oldSeqNo;
else
count = (256U + newSeqNo) - oldSeqNo;

if (count > 10U) {
LogMessage("DMR Slot %u, rejecting frame as being too old", m_slotNo);
return false;
}

insertSilence(dmrData.getSeqNo());

// Store frame for last frame here if needed

return true;
}

void CDMRSlot::insertSilence(unsigned char newSeqNo)
{
// Check to see if we have any spaces to fill
Expand Down
2 changes: 1 addition & 1 deletion DMRSlot.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ class CDMRSlot {
void writeQueue(const unsigned char* data);
void writeNetwork(const unsigned char* data, unsigned char dataType);

void writeTerminator(bool toNetwork);
void writeEndOfTransmission();

bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();

bool insertSilence(const CDMRData& dmrData);
void insertSilence(unsigned char seqNo);

static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP);
Expand Down
3 changes: 1 addition & 2 deletions Defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ const unsigned char TAG_EOT = 0x03U;

enum RPT_STATE {
RS_LISTENING,
RS_RF_LATE_ENTRY,
RS_NETWORK_LATE_ENTRY,
RS_LATE_ENTRY,
RS_RELAYING_RF_AUDIO,
RS_RELAYING_NETWORK_AUDIO,
RS_RELAYING_RF_DATA,
Expand Down
Loading

0 comments on commit 73375fb

Please sign in to comment.