diff --git a/Version.h b/Version.h index 4d2faa4..28b79b8 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20200809"; +const char* VERSION = "20200924"; #endif diff --git a/YSFControl.cpp b/YSFControl.cpp index 408b819..ac16e55 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -321,9 +321,16 @@ bool CYSFControl::processVWData(bool valid, unsigned char *data) unsigned char fn = fich.getFN(); unsigned char ft = fich.getFT(); - if (fn != 0U || ft != 1U) { - // The first packet after the header is odd, don't try and regenerate it - unsigned int errors = m_rfPayload.processVoiceFRModeAudio(data + 2U); + if (fn == 0U && ft == 1U) { + // The first packet after the header is odd + m_rfPayload.processVoiceFRModeData(data + 2U); + unsigned int errors = m_rfPayload.processVoiceFRModeAudio2(data + 2U); + m_rfErrs += errors; + m_rfBits += 288U; + m_display->writeFusionBER(float(errors) / 2.88F); + LogDebug("YSF, V Mode 3, seq %u, AMBE FEC %u/288 (%.1f%%)", m_rfFrames % 128, errors, float(errors) / 2.88F); + } else { + unsigned int errors = m_rfPayload.processVoiceFRModeAudio5(data + 2U); m_rfErrs += errors; m_rfBits += 720U; m_display->writeFusionBER(float(errors) / 7.2F); @@ -991,9 +998,14 @@ void CYSFControl::writeNetwork() break; case YSF_DT_VOICE_FR_MODE: - if (fn != 0U || ft != 1U) { - // The first packet after the header is odd, don't try and regenerate it - unsigned int errors = m_netPayload.processVoiceFRModeAudio(data + 35U); + if (fn == 0U && ft == 1U) { + // The first packet after the header is odd + m_netPayload.processVoiceFRModeData(data + 35U); + unsigned int errors = m_netPayload.processVoiceFRModeAudio2(data + 35U); + m_netErrs += errors; + m_netBits += 288U; + } else { + unsigned int errors = m_netPayload.processVoiceFRModeAudio5(data + 35U); m_netErrs += errors; m_netBits += 720U; } diff --git a/YSFPayload.cpp b/YSFPayload.cpp index 41e4d17..31126a3 100644 --- a/YSFPayload.cpp +++ b/YSFPayload.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016,2017 Jonathan Naylor, G4KLX +* Copyright (C) 2016,2017,2020 Jonathan Naylor, G4KLX * Copyright (C) 2016 Mathias Weyland, HB9FRV * * This program is free software; you can redistribute it and/or modify @@ -799,7 +799,21 @@ bool CYSFPayload::processDataFRModeData(unsigned char* data, unsigned char fn, b return ret1 && (fn == 0U); } -unsigned int CYSFPayload::processVoiceFRModeAudio(unsigned char* data) +unsigned int CYSFPayload::processVoiceFRModeAudio2(unsigned char* data) +{ + assert(data != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + // Regenerate the IMBE FEC + unsigned int errors = 0U; + errors += m_fec.regenerateIMBE(data + 54U); + errors += m_fec.regenerateIMBE(data + 72U); + + return errors; +} + +unsigned int CYSFPayload::processVoiceFRModeAudio5(unsigned char* data) { assert(data != NULL); @@ -816,6 +830,62 @@ unsigned int CYSFPayload::processVoiceFRModeAudio(unsigned char* data) return errors; } +bool CYSFPayload::processVoiceFRModeData(unsigned char* data) +{ + assert(data != NULL); + + data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; + + unsigned char dch[45U]; + ::memcpy(dch, data, 45U); + + CYSFConvolution conv; + conv.start(); + + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U; + + n++; + uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U; + + conv.decode(s0, s1); + } + + unsigned char output[23U]; + conv.chainback(output, 176U); + + bool ret = CCRC::checkCCITT162(output, 22U); + if (ret) { + CCRC::addCCITT162(output, 22U); + output[22U] = 0x00U; + + unsigned char convolved[45U]; + conv.encode(output, convolved, 180U); + + unsigned char bytes[45U]; + unsigned int j = 0U; + for (unsigned int i = 0U; i < 180U; i++) { + unsigned int n = INTERLEAVE_TABLE_9_20[i]; + + bool s0 = READ_BIT1(convolved, j) != 0U; + j++; + + bool s1 = READ_BIT1(convolved, j) != 0U; + j++; + + WRITE_BIT1(bytes, n, s0); + + n++; + WRITE_BIT1(bytes, n, s1); + } + + ::memcpy(data, bytes, 45U); + } + + return ret; +} + void CYSFPayload::writeHeader(unsigned char* data, const unsigned char* csd1, const unsigned char* csd2) { assert(data != NULL); diff --git a/YSFPayload.h b/YSFPayload.h index 1baac99..ab9e6ca 100644 --- a/YSFPayload.h +++ b/YSFPayload.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2017,2020 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,7 +38,10 @@ public: bool processDataFRModeData(unsigned char* bytes, unsigned char fn, bool gateway = false); - unsigned int processVoiceFRModeAudio(unsigned char* bytes); + bool processVoiceFRModeData(unsigned char* bytes); + + unsigned int processVoiceFRModeAudio2(unsigned char* bytes); + unsigned int processVoiceFRModeAudio5(unsigned char* bytes); void writeHeader(unsigned char* data, const unsigned char* csd1, const unsigned char* csd2);