mirror of
https://github.com/g4klx/MMDVMHost
synced 2025-12-21 23:45:49 +08:00
Add new processing for D-Star Fast Data which doesn't clobber normal
D-Star audio.
This commit is contained in:
210
DStarControl.cpp
210
DStarControl.cpp
@@ -129,7 +129,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
|
||||
unsigned char type = data[0U];
|
||||
|
||||
if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) {
|
||||
if (type == TAG_LOST && ((m_rfState == RS_RF_AUDIO) || (m_rfState == RS_RF_DATA))) {
|
||||
unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH];
|
||||
unsigned char my2[DSTAR_SHORT_CALLSIGN_LENGTH];
|
||||
unsigned char your[DSTAR_LONG_CALLSIGN_LENGTH];
|
||||
@@ -320,7 +320,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (m_rfState == RS_RF_AUDIO) {
|
||||
} else if ((m_rfState == RS_RF_AUDIO) || (m_rfState == RS_RF_DATA)) {
|
||||
if (m_net)
|
||||
writeNetworkDataRF(DSTAR_END_PATTERN_BYTES, 0U, true);
|
||||
|
||||
@@ -354,37 +354,75 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
// The sync is regenerated by the modem so can do exact match
|
||||
if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) {
|
||||
m_rfSlowData.start();
|
||||
m_rfN = 0U;
|
||||
m_rfState = RS_RF_LATE_ENTRY;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_rfState == RS_RF_AUDIO) {
|
||||
if ((m_rfState == RS_RF_AUDIO) || (m_rfState == RS_RF_DATA)) {
|
||||
// The sync is regenerated by the modem so can do exact match
|
||||
if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) {
|
||||
m_rfSlowData.start();
|
||||
m_rfN = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
// Regenerate the sync and send the RSSI data to the display
|
||||
if (m_rfN == 0U) {
|
||||
CSync::addDStarSync(data + 1U);
|
||||
m_display->writeDStarRSSI(m_rssi);
|
||||
}
|
||||
if (m_rfState == RS_RF_AUDIO) {
|
||||
m_rfSlowData.peakSlowData(data + 1U, m_rfN);
|
||||
unsigned char type = m_rfSlowData.getType();
|
||||
|
||||
unsigned int errors = 0U;
|
||||
if (!m_rfHeader.isDataPacket()) {
|
||||
errors = m_fec.regenerateDStar(data + 1U);
|
||||
m_display->writeDStarBER(float(errors) / 0.48F);
|
||||
m_rfErrs += errors;
|
||||
if (type == DSTAR_SLOW_DATA_TYPE_FASTDATA_BEGIN) {
|
||||
LogMessage("D-Star, starting fast data mode");
|
||||
m_rfState = RS_RF_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_rfState == RS_RF_DATA) {
|
||||
LogDebug("D-Star, fast data sequence no. %u", m_rfN);
|
||||
|
||||
m_rfBits += 48U;
|
||||
m_rfFrames++;
|
||||
|
||||
if (m_net)
|
||||
writeNetworkDataRF(data, 0U, false);
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueDataRF(data);
|
||||
|
||||
m_rfSlowData.peakSlowData(data + 1U, m_rfN);
|
||||
bool complete = m_rfSlowData.isComplete();
|
||||
|
||||
if (complete) {
|
||||
unsigned char type = m_rfSlowData.getType();
|
||||
if (type == DSTAR_SLOW_DATA_TYPE_FASTDATA_END) {
|
||||
LogMessage("D-Star, leaving fast data mode");
|
||||
m_rfState = RS_RF_AUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
m_rfN = (m_rfN + 1U) % 21U;
|
||||
} else if (m_rfState == RS_RF_AUDIO) {
|
||||
// Send the RSSI data to the display
|
||||
if (m_rfN == 0U)
|
||||
m_display->writeDStarRSSI(m_rssi);
|
||||
|
||||
unsigned int errors = 0U;
|
||||
if (::memcmp(data + 1U, DSTAR_NULL_AMBE_DATA_BYTES_SCRAMBLED, DSTAR_VOICE_FRAME_LENGTH_BYTES) == 0) {
|
||||
LogDebug("D-Star, audio sequence no. %u, null audio", m_rfN);
|
||||
} else {
|
||||
errors = m_fec.regenerateDStar(data + 1U);
|
||||
LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F);
|
||||
m_display->writeDStarBER(float(errors) / 0.48F);
|
||||
}
|
||||
|
||||
m_rfErrs += errors;
|
||||
m_rfBits += 48U;
|
||||
m_rfFrames++;
|
||||
|
||||
if (m_rfN != 0U) {
|
||||
const unsigned char* text = m_rfSlowData.addText(data + 1U);
|
||||
const unsigned char* text = m_rfSlowData.addText(data + 1U, m_rfN);
|
||||
if (text != NULL)
|
||||
LogMessage("D-Star, RF slow data text = \"%s\"", text);
|
||||
}
|
||||
@@ -398,15 +436,20 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
m_rfN = (m_rfN + 1U) % 21U;
|
||||
} else if (m_rfState == RS_RF_LATE_ENTRY) {
|
||||
}
|
||||
|
||||
if (m_rfState == RS_RF_LATE_ENTRY) {
|
||||
// The sync is regenerated by the modem so can do exact match
|
||||
if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) {
|
||||
m_rfSlowData.reset();
|
||||
m_rfN = 0U;
|
||||
return false;
|
||||
} else {
|
||||
CDStarHeader* header = m_rfSlowData.addHeader(data + 1U);
|
||||
if (header == NULL)
|
||||
CDStarHeader* header = m_rfSlowData.addHeader(data + 1U, m_rfN);
|
||||
if (header == NULL) {
|
||||
m_rfN = (m_rfN + 1U) % 21U;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rfHeader = *header;
|
||||
delete header;
|
||||
@@ -503,12 +546,14 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
unsigned int errors = 0U;
|
||||
if (!m_rfHeader.isDataPacket()) {
|
||||
if (::memcmp(data + 1U, DSTAR_NULL_AMBE_DATA_BYTES_SCRAMBLED, DSTAR_VOICE_FRAME_LENGTH_BYTES) == 0) {
|
||||
LogDebug("D-Star, audio sequence no. %u, null audio", m_rfN);
|
||||
} else {
|
||||
errors = m_fec.regenerateDStar(data + 1U);
|
||||
LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F);
|
||||
m_rfErrs += errors;
|
||||
}
|
||||
|
||||
m_rfErrs += errors;
|
||||
m_rfBits += 48U;
|
||||
|
||||
if (m_net)
|
||||
@@ -521,8 +566,6 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
|
||||
m_rfState = RS_RF_AUDIO;
|
||||
|
||||
m_rfN = (m_rfN + 1U) % 21U;
|
||||
|
||||
if (m_netState == RS_NET_IDLE) {
|
||||
m_display->writeDStar((char*)my1, (char*)my2, (char*)your, "R", " ");
|
||||
m_display->writeDStarRSSI(m_rssi);
|
||||
@@ -530,6 +573,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len)
|
||||
}
|
||||
|
||||
LogMessage("D-Star, received RF late entry from %8.8s/%4.4s to %8.8s", my1, my2, your);
|
||||
|
||||
m_rfN = (m_rfN + 1U) % 21U;
|
||||
}
|
||||
} else {
|
||||
CUtils::dump("D-Star, unknown data from modem", data, DSTAR_FRAME_LENGTH_BYTES + 1U);
|
||||
@@ -601,7 +646,7 @@ void CDStarControl::writeNetwork()
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
if (m_rfState == RS_RF_AUDIO && m_netState == RS_NET_IDLE)
|
||||
if (((m_rfState == RS_RF_AUDIO) || (m_rfState == RS_RF_DATA)) && (m_netState == RS_NET_IDLE))
|
||||
return;
|
||||
|
||||
m_networkWatchdog.start();
|
||||
@@ -666,12 +711,9 @@ void CDStarControl::writeNetwork()
|
||||
LogMessage("D-Star, received network header from %8.8s/%4.4s to %8.8s", my1, my2, your);
|
||||
}
|
||||
|
||||
// Something just above here introduces a large delay forcing erroneous(?) insertion of silence packets.
|
||||
// Starting the elapsed timer here instead of the commented out position above solves that.
|
||||
m_elapsed.start();
|
||||
|
||||
} else if (type == TAG_EOT) {
|
||||
if (m_netState != RS_NET_AUDIO)
|
||||
if ((m_netState != RS_NET_AUDIO) && (m_netState != RS_NET_DATA))
|
||||
return;
|
||||
|
||||
writeQueueEOTNet();
|
||||
@@ -695,48 +737,96 @@ void CDStarControl::writeNetwork()
|
||||
|
||||
writeEndNet();
|
||||
} else if (type == TAG_DATA) {
|
||||
if (m_netState != RS_NET_AUDIO)
|
||||
return;
|
||||
if ((m_netState == RS_NET_AUDIO) || (m_netState == RS_NET_DATA)) {
|
||||
unsigned char n = data[1U];
|
||||
|
||||
unsigned int errors = 0U;
|
||||
unsigned char n = data[1U];
|
||||
// The sync is regenerated by the modem so can do exact match
|
||||
if (::memcmp(data + 1U + DSTAR_VOICE_FRAME_LENGTH_BYTES, DSTAR_SYNC_BYTES, DSTAR_DATA_FRAME_LENGTH_BYTES) == 0) {
|
||||
m_netSlowData.start();
|
||||
} else {
|
||||
m_netSlowData.peakSlowData(data + 1U, n);
|
||||
|
||||
if (!m_netHeader.isDataPacket())
|
||||
errors = m_fec.regenerateDStar(data + 2U);
|
||||
|
||||
blankDTMF(data + 2U);
|
||||
|
||||
data[1U] = TAG_DATA;
|
||||
|
||||
// Insert silence and reject if in the past
|
||||
bool ret = insertSilence(data + 1U, n);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
m_netErrs += errors;
|
||||
m_netBits += 48U;
|
||||
|
||||
m_netN = n;
|
||||
|
||||
// Regenerate the sync
|
||||
if (n == 0U) {
|
||||
CSync::addDStarSync(data + 2U);
|
||||
m_netSlowData.start();
|
||||
if (m_netState == RS_NET_AUDIO) {
|
||||
unsigned char type = m_netSlowData.getType();
|
||||
if (type == DSTAR_SLOW_DATA_TYPE_FASTDATA_BEGIN) {
|
||||
LogMessage("D-Star, starting fast data mode");
|
||||
m_netState = RS_NET_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n != 0U) {
|
||||
const unsigned char* text = m_netSlowData.addText(data + 2U);
|
||||
if (text != NULL)
|
||||
LogMessage("D-Star, network slow data text = \"%s\"", text);
|
||||
}
|
||||
if (m_netState == RS_NET_AUDIO) {
|
||||
unsigned char n = data[1U];
|
||||
|
||||
m_packetTimer.start();
|
||||
m_netFrames++;
|
||||
unsigned int errors = 0U;
|
||||
if (::memcmp(data + 2U, DSTAR_NULL_AMBE_DATA_BYTES_SCRAMBLED, DSTAR_VOICE_FRAME_LENGTH_BYTES) != 0) {
|
||||
errors = m_fec.regenerateDStar(data + 2U);
|
||||
blankDTMF(data + 2U);
|
||||
}
|
||||
|
||||
data[1U] = TAG_DATA;
|
||||
|
||||
// Insert silence and reject if in the past
|
||||
bool ret = insertSilence(data + 1U, n);
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
m_netErrs += errors;
|
||||
m_netBits += 48U;
|
||||
|
||||
m_netN = n;
|
||||
|
||||
// Regenerate the sync
|
||||
if (m_netN == 0U) {
|
||||
CSync::addDStarSync(data + 2U);
|
||||
m_netSlowData.start();
|
||||
} else {
|
||||
const unsigned char* text = m_netSlowData.addText(data + 2U, m_netN);
|
||||
if (text != NULL)
|
||||
LogMessage("D-Star, network slow data text = \"%s\"", text);
|
||||
}
|
||||
|
||||
m_packetTimer.start();
|
||||
m_netFrames++;
|
||||
|
||||
#if defined(DUMP_DSTAR)
|
||||
writeFile(data + 1U, length - 1U);
|
||||
writeFile(data + 1U, length - 1U);
|
||||
#endif
|
||||
writeQueueDataNet(data + 1U);
|
||||
writeQueueDataNet(data + 1U);
|
||||
}
|
||||
|
||||
if (m_netState == RS_NET_DATA) {
|
||||
m_netN = data[1U];
|
||||
|
||||
data[1U] = TAG_DATA;
|
||||
|
||||
m_netBits += 48U;
|
||||
|
||||
// Regenerate the sync
|
||||
if (m_netN == 0U) {
|
||||
CSync::addDStarSync(data + 2U);
|
||||
m_netSlowData.start();
|
||||
} else {
|
||||
m_netSlowData.peakSlowData(data + 2U, m_netN);
|
||||
bool complete = m_netSlowData.isComplete();
|
||||
if (complete) {
|
||||
unsigned char type = m_netSlowData.getType();
|
||||
if (type == DSTAR_SLOW_DATA_TYPE_FASTDATA_END) {
|
||||
LogMessage("D-Star, leaving fast data mode");
|
||||
m_netState = RS_NET_AUDIO;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_packetTimer.start();
|
||||
m_netFrames++;
|
||||
|
||||
#if defined(DUMP_DSTAR)
|
||||
writeFile(data + 1U, length - 1U);
|
||||
#endif
|
||||
writeQueueDataNet(data + 1U);
|
||||
}
|
||||
} else {
|
||||
CUtils::dump("D-Star, unknown data from network", data, DSTAR_FRAME_LENGTH_BYTES + 1U);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user