Skip to content

Commit

Permalink
Add the status ack to D-Star.
Browse files Browse the repository at this point in the history
  • Loading branch information
g4klx committed Feb 1, 2016
1 parent 279a709 commit 2947888
Show file tree
Hide file tree
Showing 10 changed files with 270 additions and 50 deletions.
8 changes: 4 additions & 4 deletions DMRSlot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ void CDMRSlot::writeModem(unsigned char *data)
{
if (data[0U] == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, transmission lost, %.1f seconds, BER: %u%%", m_slotNo, float(m_frames) / 16.667F, (m_errs * 100U) / 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();
return;
}
Expand Down Expand Up @@ -184,7 +184,7 @@ void CDMRSlot::writeModem(unsigned char *data)
writeQueue(data);

if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %u%%", m_slotNo, float(m_frames) / 16.667F, (m_errs * 100U) / m_bits);
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_frames) / 16.667F, float(m_errs * 100U) / float(m_bits));

writeEndOfTransmission();
} else if (dataType == DT_DATA_HEADER) {
Expand Down Expand Up @@ -560,7 +560,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// We've received the voice header and terminator haven't we?
m_frames += 2U;
if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, received network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %u%%", m_slotNo, float(m_frames) / 16.667F, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
LogMessage("DMR Slot %u, received network end of voice transmission, %.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));
} else if (dataType == DT_DATA_HEADER) {
if (m_state == RS_RELAYING_NETWORK_DATA)
return;
Expand Down Expand Up @@ -800,7 +800,7 @@ void CDMRSlot::clock(unsigned int ms)
// We've received the voice header haven't we?
m_frames += 1U;
if (m_bits == 0U) m_bits = 1U;
LogMessage("DMR Slot %u, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %u%%", m_slotNo, float(m_frames) / 16.667F, (m_lost * 100U) / m_frames, (m_errs * 100U) / 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();
#if defined(DUMP_DMR)
closeFile();
Expand Down
125 changes: 92 additions & 33 deletions DStarControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ m_network(network),
m_display(display),
m_duplex(duplex),
m_queue(1000U),
m_header(),
m_state(RS_LISTENING),
m_net(false),
m_slowData(),
Expand All @@ -37,6 +38,7 @@ m_networkWatchdog(1000U, 0U, 1500U),
m_holdoffTimer(1000U, 0U, 500U),
m_timeoutTimer(1000U, timeout),
m_packetTimer(1000U, 0U, 300U),
m_ackTimer(1000U, 0U, 750U),
m_elapsed(),
m_frames(0U),
m_lost(0U),
Expand Down Expand Up @@ -82,7 +84,8 @@ void CDStarControl::writeModem(unsigned char *data)

if (type == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
if (m_bits == 0U) m_bits = 1U;
LogMessage("D-Star, transmission lost, %.1f seconds, BER: %u%%", float(m_frames) / 50.0F, (m_errs * 100U) / m_bits);
LogMessage("D-Star, transmission lost, %.1f seconds, BER: %.1f%%", float(m_frames) / 50.0F, float(m_errs * 100U) / float(m_bits));
m_ackTimer.start();
writeEndOfTransmission();
return;
}
Expand Down Expand Up @@ -124,18 +127,24 @@ void CDStarControl::writeModem(unsigned char *data)
m_net = ::memcmp(gateway, m_gateway, DSTAR_LONG_CALLSIGN_LENGTH) == 0;

if (m_state == RS_LISTENING) {
// Only reset the timeout if the ack is not pending
if (!m_ackTimer.isRunning()) {
m_timeoutTimer.start();
m_bits = 1U;
m_errs = 0U;
}

m_header = header;

m_networkWatchdog.stop();
m_timeoutTimer.start();
m_holdoffTimer.stop();
m_ackTimer.stop();

m_frames = 1U;
m_lost = 0U;

m_n = 0U;

m_bits = 1U;
m_errs = 0U;

if (m_duplex) {
// Modify the header
header.setRepeater(false);
Expand Down Expand Up @@ -186,8 +195,10 @@ void CDStarControl::writeModem(unsigned char *data)
writeQueueData(data);
}

m_ackTimer.start();

if (m_bits == 0U) m_bits = 1U;
LogMessage("D-Star, received RF end of transmission, %.1f seconds, BER: %u%%", float(m_frames) / 50.0F, (m_errs * 100U) / m_bits);
LogMessage("D-Star, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_frames) / 50.0F, float(m_errs * 100U) / float(m_bits));

writeEndOfTransmission();
} else if (m_state == RS_RELAYING_NETWORK_AUDIO) {
Expand Down Expand Up @@ -268,9 +279,18 @@ void CDStarControl::writeModem(unsigned char *data)

m_net = ::memcmp(gateway, m_gateway, DSTAR_LONG_CALLSIGN_LENGTH) == 0;

// Only reset the timeout if the ack is not pending
if (!m_ackTimer.isRunning()) {
m_timeoutTimer.start();
m_bits = 1U;
m_errs = 0U;
}

// Create a dummy start frame to replace the received frame
m_networkWatchdog.stop();
m_timeoutTimer.start();
m_ackTimer.stop();

m_header = *header;

m_frames = 1U;
m_lost = 0U;
Expand Down Expand Up @@ -307,8 +327,8 @@ void CDStarControl::writeModem(unsigned char *data)
delete header;

unsigned int errors = m_fec.regenerateDMR(data + 1U);
m_errs = errors;
m_bits = 48U;
m_errs += errors;
m_bits += 48U;

if (m_net)
writeNetworkData(data, errors, false, false);
Expand Down Expand Up @@ -351,15 +371,8 @@ void CDStarControl::writeEndOfTransmission()
m_display->clearDStar();

m_networkWatchdog.stop();
m_timeoutTimer.stop();
m_packetTimer.stop();

m_frames = 0U;
m_lost = 0U;

m_errs = 0U;
m_bits = 0U;

#if defined(DUMP_DSTAR)
closeFile();
#endif
Expand Down Expand Up @@ -397,8 +410,11 @@ void CDStarControl::writeNetwork()
unsigned char your[DSTAR_LONG_CALLSIGN_LENGTH];
header.getYourCall(your);

m_header = header;

m_timeoutTimer.start();
m_elapsed.start();
m_ackTimer.stop();

m_frames = 0U;
m_lost = 0U;
Expand All @@ -424,6 +440,8 @@ void CDStarControl::writeNetwork()
if (m_state != RS_RELAYING_NETWORK_AUDIO)
return;

m_timeoutTimer.stop();

data[1U] = TAG_EOT;
for (unsigned int i = 0U; i < 3U; i++)
writeQueueData(data + 1U);
Expand All @@ -435,7 +453,7 @@ void CDStarControl::writeNetwork()
// We've received the header and EOT haven't we?
m_frames += 2U;
if (m_bits == 0U) m_bits = 1U;
LogMessage("D-Star, received network end of transmission, %.1f seconds, %u%% packet loss, BER: %u%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
LogMessage("D-Star, received network end of transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));

writeEndOfTransmission();
} else {
Expand Down Expand Up @@ -472,6 +490,13 @@ void CDStarControl::clock(unsigned int ms)
if (m_network != NULL)
writeNetwork();

m_ackTimer.clock(ms);
if (m_ackTimer.isRunning() && m_ackTimer.hasExpired()) {
sendAck();
m_timeoutTimer.stop();
m_ackTimer.stop();
}

m_holdoffTimer.clock(ms);
if (m_holdoffTimer.isRunning() && m_holdoffTimer.hasExpired())
m_holdoffTimer.stop();
Expand All @@ -485,7 +510,8 @@ void CDStarControl::clock(unsigned int ms)
// We're received the header haven't we?
m_frames += 1U;
if (m_bits == 0U) m_bits = 1U;
LogMessage("D-Star, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %u%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, (m_errs * 100U) / m_bits);
LogMessage("D-Star, network watchdog has expired, %.1f seconds, %u%% packet loss, BER: %.1f%%", float(m_frames) / 50.0F, (m_lost * 100U) / m_frames, float(m_errs * 100U) / float(m_bits));
m_timeoutTimer.stop();
writeEndOfTransmission();
#if defined(DUMP_DSTAR)
closeFile();
Expand Down Expand Up @@ -639,24 +665,15 @@ void CDStarControl::insertSilence(unsigned int count)
unsigned char n = (m_n + 1U) % 21U;

for (unsigned int i = 0U; i < count; i++) {
unsigned char data[DSTAR_FRAME_LENGTH_BYTES + 1U];
if (i < 3U)
::memcpy(data + 1U, m_lastFrame + 1U, DSTAR_FRAME_LENGTH_BYTES);
else
::memcpy(data + 1U, DSTAR_NULL_AMBE_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES);

if (n == 0U) {
// Regenerate the sync
::memcpy(data + DSTAR_VOICE_FRAME_LENGTH_BYTES + 1U, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES);
if (i < 3U) {
writeQueueData(m_lastFrame);
} else {
// Dummy slow data values
::memcpy(data + DSTAR_VOICE_FRAME_LENGTH_BYTES + 1U, DSTAR_NULL_SLOW_DATA_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES);
if (n == 0U)
writeQueueData(DSTAR_NULL_FRAME_SYNC_BYTES);
else
writeQueueData(DSTAR_NULL_FRAME_DATA_BYTES);
}

data[0U] = TAG_DATA;

writeQueueData(data);

m_n = n;

m_frames++;
Expand Down Expand Up @@ -699,3 +716,45 @@ unsigned int CDStarControl::matchSync(const unsigned char* data) const

return errors;
}

void CDStarControl::sendAck()
{
unsigned char user[DSTAR_LONG_CALLSIGN_LENGTH];
m_header.getMyCall1(user);

CDStarHeader header;
header.setUnavailable(true);
header.setMyCall1(m_callsign);
header.setYourCall(user);
header.setRPTCall1(m_gateway);
header.setRPTCall2(m_callsign);

unsigned char data[DSTAR_HEADER_LENGTH_BYTES + 1U];
header.get(data + 1U);
data[0U] = TAG_HEADER;

writeQueueHeader(data);

writeQueueData(DSTAR_NULL_FRAME_SYNC_BYTES);

LINK_STATUS status = LS_NONE;
unsigned char reflector[DSTAR_LONG_CALLSIGN_LENGTH];
if (m_network != NULL)
m_network->getStatus(status, reflector);

char text[20U];
if (status == LS_LINKED_DEXTRA || status == LS_LINKED_DPLUS || status == LS_LINKED_DCS || status == LS_LINKED_CCS || status == LS_LINKED_LOOPBACK)
::sprintf(text, "%-8.8s BER: %.1f%% ", reflector, float(m_errs * 100U) / float(m_bits));
else
::sprintf(text, "BER: %.1f%% ", float(m_errs * 100U) / float(m_bits));
m_slowData.setText(text);

::memcpy(data, DSTAR_NULL_FRAME_DATA_BYTES, DSTAR_FRAME_LENGTH_BYTES + 1U);

for (unsigned int i = 0U; i < 19U; i++) {
m_slowData.get(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES);
writeQueueData(data);
}

writeQueueData(DSTAR_END_PATTERN_BYTES);
}
4 changes: 4 additions & 0 deletions DStarControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class CDStarControl {
IDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
CDStarHeader m_header;
RPT_STATE m_state;
bool m_net;
CDStarSlowData m_slowData;
Expand All @@ -59,6 +60,7 @@ class CDStarControl {
CTimer m_holdoffTimer;
CTimer m_timeoutTimer;
CTimer m_packetTimer;
CTimer m_ackTimer;
CStopWatch m_elapsed;
unsigned int m_frames;
unsigned int m_lost;
Expand Down Expand Up @@ -86,6 +88,8 @@ class CDStarControl {

void blankDTMF(unsigned char* data) const;
unsigned int matchSync(const unsigned char* data) const;

void sendAck();
};

#endif
28 changes: 26 additions & 2 deletions DStarDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,21 @@
#if !defined(DStarDefines_H)
#define DStarDefines_H

#include "Defines.h"

const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
const unsigned int DSTAR_FRAME_LENGTH_BYTES = 12U;

const unsigned char DSTAR_END_PATTERN_BYTES[] = { 0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const unsigned char DSTAR_END_PATTERN_BYTES[] = { TAG_EOT, 0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const unsigned int DSTAR_END_PATTERN_LENGTH_BYTES = 6U;

const unsigned char DSTAR_NULL_AMBE_DATA_BYTES[] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8 };

// Note that these are already scrambled, 0x66 0x66 0x66 otherwise
const unsigned char DSTAR_NULL_SLOW_DATA_BYTES[] = { 0x16, 0x29, 0xF5 };

const unsigned char DSTAR_NULL_FRAME_DATA_BYTES[] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xF5 };
const unsigned char DSTAR_NULL_FRAME_SYNC_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16 };
const unsigned char DSTAR_NULL_FRAME_DATA_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xF5 };

const unsigned int DSTAR_VOICE_FRAME_LENGTH_BYTES = 9U;
const unsigned int DSTAR_DATA_FRAME_LENGTH_BYTES = 3U;
Expand All @@ -52,6 +55,12 @@ const unsigned char DSTAR_REPEATER_MASK = 0x40U;
const unsigned char DSTAR_INTERRUPTED_MASK = 0x20U;
const unsigned char DSTAR_CONTROL_SIGNAL_MASK = 0x10U;
const unsigned char DSTAR_URGENT_MASK = 0x08U;
const unsigned char DSTAR_REPEATER_CONTROL = 0x07U;
const unsigned char DSTAR_AUTO_REPLY = 0x06U;
const unsigned char DSTAR_RESEND_REQUESTED = 0x04U;
const unsigned char DSTAR_ACK_FLAG = 0x03U;
const unsigned char DSTAR_NO_RESPONSE = 0x02U;
const unsigned char DSTAR_RELAY_UNAVAILABLE = 0x01U;

const unsigned char DSTAR_SYNC_BYTES[] = {0x55U, 0x2DU, 0x16U};

Expand All @@ -60,4 +69,19 @@ const unsigned char DSTAR_DTMF_SIG[] = { 0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x0

const unsigned int DSTAR_FRAME_TIME = 20U;

enum LINK_STATUS {
LS_NONE,
LS_PENDING_IRCDDB,
LS_LINKING_LOOPBACK,
LS_LINKING_DEXTRA,
LS_LINKING_DPLUS,
LS_LINKING_DCS,
LS_LINKING_CCS,
LS_LINKED_LOOPBACK,
LS_LINKED_DEXTRA,
LS_LINKED_DPLUS,
LS_LINKED_DCS,
LS_LINKED_CCS
};

#endif
Loading

0 comments on commit 2947888

Please sign in to comment.