Add the status ack to D-Star.
This commit is contained in:
parent
279a709793
commit
2947888cad
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
|
125
DStarControl.cpp
125
DStarControl.cpp
|
@ -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(),
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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++;
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ private:
|
|||
IDisplay* m_display;
|
||||
bool m_duplex;
|
||||
CRingBuffer<unsigned char> m_queue;
|
||||
CDStarHeader m_header;
|
||||
RPT_STATE m_state;
|
||||
bool m_net;
|
||||
CDStarSlowData m_slowData;
|
||||
|
@ -59,6 +60,7 @@ private:
|
|||
CTimer m_holdoffTimer;
|
||||
CTimer m_timeoutTimer;
|
||||
CTimer m_packetTimer;
|
||||
CTimer m_ackTimer;
|
||||
CStopWatch m_elapsed;
|
||||
unsigned int m_frames;
|
||||
unsigned int m_lost;
|
||||
|
@ -86,6 +88,8 @@ private:
|
|||
|
||||
void blankDTMF(unsigned char* data) const;
|
||||
unsigned int matchSync(const unsigned char* data) const;
|
||||
|
||||
void sendAck();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,10 +19,12 @@
|
|||
#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 };
|
||||
|
@ -30,7 +32,8 @@ const unsigned char DSTAR_NULL_AMBE_DATA_BYTES[] = { 0x9E, 0x8D, 0x32, 0x88, 0x2
|
|||
// 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;
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -34,11 +34,31 @@ m_header(NULL)
|
|||
::memcpy(m_header, header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
CDStarHeader::CDStarHeader() :
|
||||
m_header(NULL)
|
||||
{
|
||||
m_header = new unsigned char[DSTAR_HEADER_LENGTH_BYTES];
|
||||
|
||||
::memset(m_header, ' ', DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
m_header[0U] = 0x00U;
|
||||
m_header[1U] = 0x00U;
|
||||
m_header[2U] = 0x00U;
|
||||
}
|
||||
|
||||
CDStarHeader::~CDStarHeader()
|
||||
{
|
||||
delete[] m_header;
|
||||
}
|
||||
|
||||
CDStarHeader& CDStarHeader::operator=(const CDStarHeader& header)
|
||||
{
|
||||
if (&header != this)
|
||||
::memcpy(m_header, header.m_header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CDStarHeader::isRepeater() const
|
||||
{
|
||||
return (m_header[0U] & DSTAR_REPEATER_MASK) == DSTAR_REPEATER_MASK;
|
||||
|
@ -52,6 +72,14 @@ void CDStarHeader::setRepeater(bool on)
|
|||
m_header[0U] &= ~DSTAR_REPEATER_MASK;
|
||||
}
|
||||
|
||||
void CDStarHeader::setUnavailable(bool on)
|
||||
{
|
||||
if (on)
|
||||
m_header[0U] |= DSTAR_RELAY_UNAVAILABLE;
|
||||
else
|
||||
m_header[0U] &= ~DSTAR_RELAY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
void CDStarHeader::getMyCall1(unsigned char* call1) const
|
||||
{
|
||||
::memcpy(call1, m_header + 27U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
|
@ -62,6 +90,16 @@ void CDStarHeader::getMyCall2(unsigned char* call2) const
|
|||
::memcpy(call2, m_header + 35U, DSTAR_SHORT_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setMyCall1(const unsigned char* call1)
|
||||
{
|
||||
::memcpy(m_header + 27U, call1, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setMyCall2(const unsigned char* call2)
|
||||
{
|
||||
::memcpy(m_header + 35U, call2, DSTAR_SHORT_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::getRPTCall1(unsigned char* call1) const
|
||||
{
|
||||
::memcpy(call1, m_header + 11U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
|
@ -87,6 +125,11 @@ void CDStarHeader::getYourCall(unsigned char* call) const
|
|||
::memcpy(call, m_header + 19U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setYourCall(const unsigned char* call)
|
||||
{
|
||||
::memcpy(m_header + 19U, call, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::get(unsigned char* header) const
|
||||
{
|
||||
assert(header != NULL);
|
||||
|
|
|
@ -22,14 +22,20 @@
|
|||
class CDStarHeader {
|
||||
public:
|
||||
CDStarHeader(const unsigned char* header);
|
||||
CDStarHeader();
|
||||
~CDStarHeader();
|
||||
|
||||
bool isRepeater() const;
|
||||
void setRepeater(bool on);
|
||||
|
||||
void setUnavailable(bool on);
|
||||
|
||||
void getMyCall1(unsigned char* call1) const;
|
||||
void getMyCall2(unsigned char* call2) const;
|
||||
|
||||
void setMyCall1(const unsigned char* call1);
|
||||
void setMyCall2(const unsigned char* call2);
|
||||
|
||||
void getRPTCall1(unsigned char* call1) const;
|
||||
void getRPTCall2(unsigned char* call2) const;
|
||||
|
||||
|
@ -37,9 +43,12 @@ public:
|
|||
void setRPTCall2(const unsigned char* call2);
|
||||
|
||||
void getYourCall(unsigned char* call) const;
|
||||
void setYourCall(const unsigned char* call);
|
||||
|
||||
void get(unsigned char* header) const;
|
||||
|
||||
CDStarHeader& operator=(const CDStarHeader& header);
|
||||
|
||||
private:
|
||||
unsigned char* m_header;
|
||||
};
|
||||
|
|
|
@ -40,16 +40,21 @@ m_outId(0U),
|
|||
m_outSeq(0U),
|
||||
m_inId(0U),
|
||||
m_buffer(1000U),
|
||||
m_pollTimer(1000U, 60U)
|
||||
m_pollTimer(1000U, 60U),
|
||||
m_linkStatus(LS_NONE),
|
||||
m_linkReflector(NULL)
|
||||
{
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
|
||||
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
|
||||
|
||||
CStopWatch stopWatch;
|
||||
::srand(stopWatch.start());
|
||||
}
|
||||
|
||||
CDStarNetwork::~CDStarNetwork()
|
||||
{
|
||||
delete[] m_linkReflector;
|
||||
}
|
||||
|
||||
bool CDStarNetwork::open()
|
||||
|
@ -200,6 +205,10 @@ void CDStarNetwork::clock(unsigned int ms)
|
|||
|
||||
switch (buffer[4]) {
|
||||
case 0x00U: // NETWORK_TEXT;
|
||||
m_linkStatus = LINK_STATUS(buffer[25U]);
|
||||
::memcpy(m_linkReflector, buffer + 26U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
return;
|
||||
|
||||
case 0x01U: // NETWORK_TEMPTEXT;
|
||||
case 0x04U: // NETWORK_STATUS1..5
|
||||
case 0x24U: // NETWORK_DD_DATA
|
||||
|
@ -296,3 +305,12 @@ void CDStarNetwork::enable(bool enabled)
|
|||
{
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void CDStarNetwork::getStatus(LINK_STATUS& status, unsigned char* reflector)
|
||||
{
|
||||
assert(reflector != NULL);
|
||||
|
||||
status = m_linkStatus;
|
||||
|
||||
::memcpy(reflector, m_linkReflector, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
bool writeHeader(const unsigned char* header, unsigned int length, bool busy);
|
||||
bool writeData(const unsigned char* data, unsigned int length, unsigned int errors, bool end, bool busy);
|
||||
|
||||
void getStatus(LINK_STATUS& status, unsigned char* reflector);
|
||||
|
||||
unsigned int read(unsigned char* data, unsigned int length);
|
||||
|
||||
void reset();
|
||||
|
@ -48,17 +50,19 @@ public:
|
|||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
std::string m_version;
|
||||
bool m_debug;
|
||||
bool m_enabled;
|
||||
uint16_t m_outId;
|
||||
uint8_t m_outSeq;
|
||||
uint16_t m_inId;
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
std::string m_version;
|
||||
bool m_debug;
|
||||
bool m_enabled;
|
||||
uint16_t m_outId;
|
||||
uint8_t m_outSeq;
|
||||
uint16_t m_inId;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
CTimer m_pollTimer;
|
||||
CTimer m_pollTimer;
|
||||
LINK_STATUS m_linkStatus;
|
||||
unsigned char* m_linkReflector;
|
||||
|
||||
bool writePoll(const char* text);
|
||||
};
|
||||
|
|
|
@ -28,16 +28,20 @@ CDStarSlowData::CDStarSlowData() :
|
|||
m_header(NULL),
|
||||
m_ptr(0U),
|
||||
m_buffer(NULL),
|
||||
m_text(NULL),
|
||||
m_textPtr(0U),
|
||||
m_state(SDD_FIRST)
|
||||
{
|
||||
m_header = new unsigned char[50U]; // DSTAR_HEADER_LENGTH_BYTES
|
||||
m_buffer = new unsigned char[DSTAR_DATA_FRAME_LENGTH_BYTES * 2U];
|
||||
m_text = new unsigned char[24U];
|
||||
}
|
||||
|
||||
CDStarSlowData::~CDStarSlowData()
|
||||
{
|
||||
delete[] m_header;
|
||||
delete[] m_buffer;
|
||||
delete[] m_text;
|
||||
}
|
||||
|
||||
CDStarHeader* CDStarSlowData::add(const unsigned char* data)
|
||||
|
@ -106,3 +110,53 @@ void CDStarSlowData::reset()
|
|||
m_ptr = 0U;
|
||||
m_state = SDD_FIRST;
|
||||
}
|
||||
|
||||
void CDStarSlowData::setText(const char* text)
|
||||
{
|
||||
assert(text != NULL);
|
||||
|
||||
m_text[0U] = DSTAR_SLOW_DATA_TYPE_TEXT | 0U;
|
||||
m_text[1U] = text[0U];
|
||||
m_text[2U] = text[1U];
|
||||
m_text[3U] = text[2U];
|
||||
m_text[4U] = text[3U];
|
||||
m_text[5U] = text[4U];
|
||||
|
||||
m_text[6U] = DSTAR_SLOW_DATA_TYPE_TEXT | 1U;
|
||||
m_text[7U] = text[5U];
|
||||
m_text[8U] = text[6U];
|
||||
m_text[9U] = text[7U];
|
||||
m_text[10U] = text[8U];
|
||||
m_text[11U] = text[9U];
|
||||
|
||||
m_text[12U] = DSTAR_SLOW_DATA_TYPE_TEXT | 2U;
|
||||
m_text[13U] = text[10U];
|
||||
m_text[14U] = text[11U];
|
||||
m_text[15U] = text[12U];
|
||||
m_text[16U] = text[13U];
|
||||
m_text[17U] = text[14U];
|
||||
|
||||
m_text[18U] = DSTAR_SLOW_DATA_TYPE_TEXT | 3U;
|
||||
m_text[19U] = text[15U];
|
||||
m_text[20U] = text[16U];
|
||||
m_text[21U] = text[17U];
|
||||
m_text[22U] = text[18U];
|
||||
m_text[23U] = text[19U];
|
||||
|
||||
m_textPtr = 0U;
|
||||
}
|
||||
|
||||
void CDStarSlowData::get(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_textPtr < 24U) {
|
||||
data[0U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
data[1U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
data[2U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
} else {
|
||||
data[0U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
data[1U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
data[2U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,10 +31,15 @@ public:
|
|||
void start();
|
||||
void reset();
|
||||
|
||||
void setText(const char* text);
|
||||
void get(unsigned char* data);
|
||||
|
||||
private:
|
||||
unsigned char* m_header;
|
||||
unsigned int m_ptr;
|
||||
unsigned char* m_buffer;
|
||||
unsigned char* m_text;
|
||||
unsigned int m_textPtr;
|
||||
|
||||
enum SDD_STATE {
|
||||
SDD_FIRST,
|
||||
|
|
Loading…
Reference in New Issue