Add the status ack to D-Star.

This commit is contained in:
Jonathan Naylor 2016-02-01 20:49:52 +00:00
parent 279a709793
commit 2947888cad
10 changed files with 270 additions and 50 deletions

View File

@ -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();

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
};

View File

@ -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);
}

View File

@ -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);
};

View File

@ -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];
}
}

View File

@ -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,