diff --git a/DStarControl.cpp b/DStarControl.cpp index e8d7035..8cd57e5 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -23,6 +23,7 @@ #include const unsigned int MAX_SYNC_BIT_ERRORS = 2U; +const unsigned int FAST_DATA_BEEP_GRACE_FRAMES = 6U; bool CallsignCompare(const std::string& arg, const unsigned char* my) { @@ -83,7 +84,15 @@ m_minRSSI(0U), m_aveRSSI(0U), m_rssiCount(0U), m_enabled(true), -m_fp(NULL) +m_fp(NULL), +m_rfVoiceSyncData(NULL), +m_rfVoiceSyncDataLen(0U), +m_netVoiceSyncData(NULL), +m_netVoiceSyncDataLen(0U), +m_rfNextFrameIsFastData(false), +m_netNextFrameIsFastData(false), +m_rfSkipDTMFBlankingFrames(0U), +m_netSkipDTMFBlankingFrames(0U) { assert(display != NULL); assert(rssiMapper != NULL); @@ -92,6 +101,8 @@ m_fp(NULL) m_gateway = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH]; m_lastFrame = new unsigned char[DSTAR_FRAME_LENGTH_BYTES + 1U]; + m_rfVoiceSyncData = new unsigned char[MODEM_DATA_LEN]; + m_netVoiceSyncData = new unsigned char[MODEM_DATA_LEN]; std::string call = callsign; call.resize(DSTAR_LONG_CALLSIGN_LENGTH - 1U, ' '); @@ -116,6 +127,56 @@ CDStarControl::~CDStarControl() delete[] m_callsign; delete[] m_gateway; delete[] m_lastFrame; + delete[] m_rfVoiceSyncData; + delete[] m_netVoiceSyncData; +} + +unsigned int CDStarControl::maybeFixupVoiceFrame( + unsigned char* data, + unsigned int len, + unsigned int offset, + const char* log_prefix, + unsigned char n, + bool blank_dtmf, + unsigned char* voice_sync_data, + unsigned int* voice_sync_data_len, + bool* next_frame_is_fast_data, + unsigned int* skip_dtmf_blanking_frames + ) +{ + unsigned int errors = 0U; + unsigned char mini_header = data[offset + 9U] ^ DSTAR_SCRAMBLER_BYTES[0U]; + unsigned char mini_header_type = mini_header & DSTAR_SLOW_DATA_TYPE_MASK; + + if (n == 0U) { + LogMessage("%s frame %u: FEC regeneration disabled for first frame", log_prefix, n); + } else if ((n % 2U != 0U) && + ((mini_header_type == DSTAR_SLOW_DATA_TYPE_FASTDATA01) || + (mini_header_type == DSTAR_SLOW_DATA_TYPE_FASTDATA16))) { + *next_frame_is_fast_data = true; + if (blank_dtmf) + *skip_dtmf_blanking_frames = FAST_DATA_BEEP_GRACE_FRAMES; + LogMessage("%s frame %u: found fast data", log_prefix, n); + } else if (*next_frame_is_fast_data == true) { + *next_frame_is_fast_data = false; + if (blank_dtmf) + *skip_dtmf_blanking_frames = FAST_DATA_BEEP_GRACE_FRAMES; + LogMessage("%s frame %u: found fast data (cont.)", log_prefix, n); + } else { + errors = m_fec.regenerateDStar(data + offset); + LogMessage("%s frame %u: *** REGENERATING FEC ***", log_prefix, n); + + if (blank_dtmf && (*skip_dtmf_blanking_frames > 0U)) { + (*skip_dtmf_blanking_frames)--; + LogMessage("%s frame %u: *** Not BLANKING DTMF (left to skip: %u) ***", + log_prefix, n, *skip_dtmf_blanking_frames); + } else if (blank_dtmf && (*skip_dtmf_blanking_frames == 0U)) { + LogMessage("%s frame %u: *** BLANKING DTMF ***", log_prefix, n); + blankDTMF(data + offset); + } + } + + return errors; } bool CDStarControl::writeModem(unsigned char *data, unsigned int len) @@ -323,6 +384,9 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_duplex) writeQueueEOTRF(); + m_rfNextFrameIsFastData = false; + m_rfSkipDTMFBlankingFrames = 0U; + unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH]; unsigned char my2[DSTAR_SHORT_CALLSIGN_LENGTH]; unsigned char your[DSTAR_LONG_CALLSIGN_LENGTH]; @@ -353,17 +417,6 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) return false; } else if (m_rfState == RS_RF_AUDIO) { - unsigned int errors = 0U; - if (!m_rfHeader.isDataPacket()) { - errors = m_fec.regenerateDStar(data + 1U); - m_display->writeDStarBER(float(errors) / 0.48F); - LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F); - m_rfErrs += errors; - } - - m_rfBits += 48U; - m_rfFrames++; - // 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_rfN = 0U; @@ -374,13 +427,23 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) m_display->writeDStarRSSI(m_rssi); } + unsigned int errors = 0U; + if (!m_rfHeader.isDataPacket()) { + errors = maybeFixupVoiceFrame(data, len, 1U, "RF", m_rfN, m_duplex, m_rfVoiceSyncData, &m_rfVoiceSyncDataLen, + &m_rfNextFrameIsFastData, &m_rfSkipDTMFBlankingFrames); + m_display->writeDStarBER(float(errors) / 0.48F); + LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F); + m_rfErrs += errors; + } + + m_rfBits += 48U; + m_rfFrames++; + if (m_net) writeNetworkDataRF(data, errors, false); - if (m_duplex) { - blankDTMF(data + 1U); + if (m_duplex) writeQueueDataRF(data); - } m_rfN = (m_rfN + 1U) % 21U; } else if (m_rfState == RS_RF_LATE_ENTRY) { @@ -492,7 +555,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) unsigned int errors = 0U; if (!m_rfHeader.isDataPacket()) { - errors = m_fec.regenerateDStar(data + 1U); + errors = maybeFixupVoiceFrame(data, len, 1U, "RF", m_rfN, m_duplex, m_rfVoiceSyncData, &m_rfVoiceSyncDataLen, + &m_rfNextFrameIsFastData, &m_rfSkipDTMFBlankingFrames); LogDebug("D-Star, audio sequence no. %u, errs: %u/48 (%.1f%%)", m_rfN, errors, float(errors) / 0.48F); m_rfErrs += errors; } @@ -502,10 +566,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (m_net) writeNetworkDataRF(data, errors, false); - if (m_duplex) { - blankDTMF(data + 1U); + if (m_duplex) writeQueueDataRF(data); - } m_rfState = RS_RF_AUDIO; @@ -670,6 +732,9 @@ void CDStarControl::writeNetwork() writeFile(data + 1U, length - 1U); closeFile(); #endif + m_netNextFrameIsFastData = false; + m_netSkipDTMFBlankingFrames = 0U; + unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH]; unsigned char my2[DSTAR_SHORT_CALLSIGN_LENGTH]; unsigned char your[DSTAR_LONG_CALLSIGN_LENGTH]; @@ -690,9 +755,8 @@ void CDStarControl::writeNetwork() unsigned int errors = 0U; if (!m_netHeader.isDataPacket()) - errors = m_fec.regenerateDStar(data + 2U); - - blankDTMF(data + 2U); + errors = maybeFixupVoiceFrame(data, length, 2U, "Net", n, true, m_netVoiceSyncData, &m_netVoiceSyncDataLen, + &m_netNextFrameIsFastData, &m_netSkipDTMFBlankingFrames); data[1U] = TAG_DATA; diff --git a/DStarControl.h b/DStarControl.h index 3d541d1..1378c87 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -98,6 +98,28 @@ private: unsigned int m_rssiCount; bool m_enabled; FILE* m_fp; + unsigned char* m_rfVoiceSyncData; + unsigned int m_rfVoiceSyncDataLen; + unsigned char* m_netVoiceSyncData; + unsigned int m_netVoiceSyncDataLen; + bool m_rfNextFrameIsFastData; + bool m_netNextFrameIsFastData; + unsigned int m_rfSkipDTMFBlankingFrames; + unsigned int m_netSkipDTMFBlankingFrames; + + + unsigned int maybeFixupVoiceFrame( + unsigned char* data, + unsigned int len, + unsigned int offset, + const char* log_prefix, + unsigned char n, + bool blank_dtmf, + unsigned char* voice_sync_data, + unsigned int* voice_sync_data_len, + bool* next_frame_is_fast_data, + unsigned int* skip_dtmf_blanking_frames + ); void writeNetwork(); diff --git a/DStarDefines.h b/DStarDefines.h index 8c28991..46f4c1d 100644 --- a/DStarDefines.h +++ b/DStarDefines.h @@ -42,12 +42,14 @@ const unsigned int DSTAR_DATA_FRAME_LENGTH_BYTES = 3U; const unsigned int DSTAR_LONG_CALLSIGN_LENGTH = 8U; const unsigned int DSTAR_SHORT_CALLSIGN_LENGTH = 4U; -const unsigned char DSTAR_SLOW_DATA_TYPE_MASK = 0xF0U; -const unsigned char DSTAR_SLOW_DATA_TYPE_GPSDATA = 0x30U; -const unsigned char DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U; -const unsigned char DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U; -const unsigned char DSTAR_SLOW_DATA_TYPE_SQUELCH = 0xC0U; -const unsigned char DSTAR_SLOW_DATA_LENGTH_MASK = 0x0FU; +const unsigned char DSTAR_SLOW_DATA_TYPE_MASK = 0xF0U; +const unsigned char DSTAR_SLOW_DATA_TYPE_GPSDATA = 0x30U; +const unsigned char DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U; +const unsigned char DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U; +const unsigned char DSTAR_SLOW_DATA_TYPE_FASTDATA01 = 0x80U; +const unsigned char DSTAR_SLOW_DATA_TYPE_FASTDATA16 = 0x90U; +const unsigned char DSTAR_SLOW_DATA_TYPE_SQUELCH = 0xC0U; +const unsigned char DSTAR_SLOW_DATA_LENGTH_MASK = 0x0FU; // Data Frames are always scrambled using the first three bytes of // DSTAR_SCRAMBLER_BYTES, and Voice Frames are scrambled with all nine diff --git a/Defines.h b/Defines.h index 8c57721..ebd75eb 100644 --- a/Defines.h +++ b/Defines.h @@ -39,6 +39,8 @@ const unsigned char TAG_DATA = 0x01U; const unsigned char TAG_LOST = 0x02U; const unsigned char TAG_EOT = 0x03U; +const unsigned int MODEM_DATA_LEN = 220U; + enum HW_TYPE { HWT_MMDVM, HWT_DVMEGA, diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 333b701..f100634 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -668,7 +668,7 @@ int CMMDVMHost::run() m_ump->setCD(cd); } - unsigned char data[220U]; + unsigned char data[MODEM_DATA_LEN]; unsigned int len; bool ret;