From 4b07afa17e1a901c2eab2c2b99ec1c7ee2fc1d12 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 16 Feb 2017 19:40:20 +0000 Subject: [PATCH 1/6] Handle crashing P25 RS decoder better. --- P25Data.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/P25Data.cpp b/P25Data.cpp index 06d25c6..6f787ce 100644 --- a/P25Data.cpp +++ b/P25Data.cpp @@ -1,5 +1,5 @@ /* -* Copyright (C) 2016 by Jonathan Naylor G4KLX +* Copyright (C) 2016,2017 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 @@ -96,9 +96,14 @@ bool CP25Data::decodeLDU1(const unsigned char* data) CP25Utils::decode(data, raw, 1356U, 1398U); decodeLDUHamming(raw, rs + 15U); - bool ret = m_rs241213.decode(rs); - if (!ret) + try { + bool ret = m_rs241213.decode(rs); + if (!ret) + return false; + } catch (...) { + CUtils::dump(2U, "P25, RS carshed with input data", rs, 18U); return false; + } // Simple validation of the source id unsigned int srcId = (rs[6U] << 16) + (rs[7U] << 8) + rs[8U]; From ac22f0b783cdd3a14ab4831df4ee62602318bd71 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Thu, 16 Feb 2017 19:49:58 +0000 Subject: [PATCH 2/6] Add an optional error reply for D-Star. --- Conf.cpp | 9 +++- Conf.h | 2 + DStarControl.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++----- DStarControl.h | 5 ++- Defines.h | 5 ++- MMDVM.ini | 1 + MMDVMHost.cpp | 4 +- 7 files changed, 119 insertions(+), 15 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index 851dbe7..5bdd518 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -99,6 +99,7 @@ m_dstarEnabled(false), m_dstarModule("C"), m_dstarSelfOnly(false), m_dstarBlackList(), +m_dstarErrorReply(true), m_dmrEnabled(false), m_dmrBeacons(false), m_dmrId(0U), @@ -359,7 +360,8 @@ bool CConf::read() } p = ::strtok(NULL, ",\r\n"); } - } + } else if (::strcmp(key, "ErrorReply") == 0) + m_dstarErrorReply = ::atoi(value) == 1; } else if (section == SECTION_DMR) { if (::strcmp(key, "Enable") == 0) m_dmrEnabled = ::atoi(value) == 1; @@ -779,6 +781,11 @@ std::vector CConf::getDStarBlackList() const return m_dstarBlackList; } +bool CConf::getDStarErrorReply() const +{ + return m_dstarErrorReply; +} + bool CConf::getDMREnabled() const { return m_dmrEnabled; diff --git a/Conf.h b/Conf.h index 8aca5b0..d158130 100644 --- a/Conf.h +++ b/Conf.h @@ -90,6 +90,7 @@ public: std::string getDStarModule() const; bool getDStarSelfOnly() const; std::vector getDStarBlackList() const; + bool getDStarErrorReply() const; // The DMR section bool getDMREnabled() const; @@ -238,6 +239,7 @@ private: std::string m_dstarModule; bool m_dstarSelfOnly; std::vector m_dstarBlackList; + bool m_dstarErrorReply; bool m_dmrEnabled; bool m_dmrBeacons; diff --git a/DStarControl.cpp b/DStarControl.cpp index f8d4e9c..48713c1 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -36,10 +36,11 @@ bool CallsignCompare(const std::string& arg, const unsigned char* my) // #define DUMP_DSTAR -CDStarControl::CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, const std::vector& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : +CDStarControl::CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool errorReply, const std::vector& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : m_callsign(NULL), m_gateway(NULL), m_selfOnly(selfOnly), +m_errorReply(errorReply), m_blackList(blackList), m_network(network), m_display(display), @@ -58,6 +59,7 @@ m_rfTimeoutTimer(1000U, timeout), m_netTimeoutTimer(1000U, timeout), m_packetTimer(1000U, 0U, 300U), m_ackTimer(1000U, 0U, 750U), +m_errTimer(1000U, 0U, 750U), m_interval(), m_elapsed(), m_rfFrames(0U), @@ -126,6 +128,20 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) return false; } + if (type == TAG_LOST && m_rfState == RS_RF_INVALID) { + m_rfState = RS_RF_LISTENING; + + if (m_netState == RS_NET_IDLE) { + if (m_errorReply) + m_errTimer.start(); + + if (m_network != NULL) + m_network->reset(); + } + + return false; + } + if (type == TAG_LOST) { m_rfState = RS_RF_LISTENING; return false; @@ -177,6 +193,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (type == TAG_HEADER) { CDStarHeader header(data + 1U); + m_rfHeader = header; unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH]; header.getMyCall1(my1); @@ -184,7 +201,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) // Is this a transmission destined for a repeater? if (!header.isRepeater()) { LogMessage("D-Star, non repeater RF header received from %8.8s", my1); - m_rfState = RS_RF_REJECTED; + m_rfState = RS_RF_INVALID; return false; } @@ -194,7 +211,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) // Is it for us? if (::memcmp(callsign, m_callsign, DSTAR_LONG_CALLSIGN_LENGTH) != 0) { LogMessage("D-Star, received RF header for wrong repeater (%8.8s) from %8.8s", callsign, my1); - m_rfState = RS_RF_REJECTED; + m_rfState = RS_RF_INVALID; return false; } @@ -225,9 +242,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (!m_rfTimeoutTimer.isRunning()) m_rfTimeoutTimer.start(); - m_rfHeader = header; - m_ackTimer.stop(); + m_errTimer.stop(); m_rfBits = 1U; m_rfErrs = 0U; @@ -271,6 +287,18 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (type == TAG_EOT) { if (m_rfState == RS_RF_REJECTED) { m_rfState = RS_RF_LISTENING; + } else if (m_rfState == RS_RF_INVALID) { + m_rfState = RS_RF_LISTENING; + + if (m_netState == RS_NET_IDLE) { + if (m_errorReply) + m_errTimer.start(); + + if (m_network != NULL) + m_network->reset(); + } + + return false; } else if (m_rfState == RS_RF_AUDIO) { if (m_net) writeNetworkDataRF(DSTAR_END_PATTERN_BYTES, 0U, true); @@ -290,6 +318,8 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) } else if (type == TAG_DATA) { if (m_rfState == RS_RF_REJECTED) { return false; + } else if (m_rfState == RS_RF_INVALID) { + return false; } else if (m_rfState == RS_RF_LISTENING) { // 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) { @@ -340,8 +370,15 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) if (header == NULL) return false; + m_rfHeader = *header; + + unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH]; + header->getMyCall1(my1); + // Is this a transmission destined for a repeater? if (!header->isRepeater()) { + LogMessage("D-Star, non repeater RF header received from %8.8s", my1); + m_rfState = RS_RF_INVALID; delete header; return false; } @@ -351,19 +388,22 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) // Is it for us? if (::memcmp(callsign, m_callsign, DSTAR_LONG_CALLSIGN_LENGTH) != 0) { + LogMessage("D-Star, received RF header for wrong repeater (%8.8s) from %8.8s", callsign, my1); + m_rfState = RS_RF_INVALID; delete header; return false; } - unsigned char my1[DSTAR_LONG_CALLSIGN_LENGTH]; - header->getMyCall1(my1); - if (m_selfOnly && ::memcmp(my1, m_callsign, DSTAR_LONG_CALLSIGN_LENGTH - 1U) != 0) { + LogMessage("D-Star, invalid access attempt from %8.8s", my1); + m_rfState = RS_RF_REJECTED; delete header; return false; } if (!m_selfOnly && std::find_if(m_blackList.begin(), m_blackList.end(), std::bind(CallsignCompare, std::placeholders::_1, my1)) != m_blackList.end()) { + LogMessage("D-Star, invalid access attempt from %8.8s", my1); + m_rfState = RS_RF_REJECTED; delete header; return false; } @@ -385,8 +425,7 @@ bool CDStarControl::writeModem(unsigned char *data, unsigned int len) // Create a dummy start frame to replace the received frame m_ackTimer.stop(); - - m_rfHeader = *header; + m_errTimer.stop(); m_rfBits = 1U; m_rfErrs = 0U; @@ -550,6 +589,7 @@ void CDStarControl::writeNetwork() m_packetTimer.start(); //m_elapsed.start(); // commented out and placed lower down due to delay introduced somewhere below here. m_ackTimer.stop(); + m_errTimer.stop(); m_lastFrameValid = false; @@ -655,6 +695,12 @@ void CDStarControl::clock() m_ackTimer.stop(); } + m_errTimer.clock(ms); + if (m_errTimer.isRunning() && m_errTimer.hasExpired()) { + sendError(); + m_errTimer.stop(); + } + m_rfTimeoutTimer.clock(ms); m_netTimeoutTimer.clock(ms); @@ -1004,3 +1050,45 @@ void CDStarControl::sendAck() writeQueueEOTRF(); } + +void CDStarControl::sendError() +{ + unsigned char user[DSTAR_LONG_CALLSIGN_LENGTH]; + m_rfHeader.getMyCall1(user); + + CDStarHeader header; + header.setUnavailable(true); + header.setMyCall1(m_callsign); + header.setYourCall(user); + header.setRPTCall1(m_callsign); + header.setRPTCall2(m_callsign); + + unsigned char data[DSTAR_HEADER_LENGTH_BYTES + 1U]; + header.get(data + 1U); + data[0U] = TAG_HEADER; + + writeQueueHeaderRF(data); + + writeQueueDataRF(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[40U]; + 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_rfErrs * 100U) / float(m_rfBits)); + else + ::sprintf(text, "BER: %.1f%% ", float(m_rfErrs * 100U) / float(m_rfBits)); + 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); + writeQueueDataRF(data); + } + + writeQueueEOTRF(); +} diff --git a/DStarControl.h b/DStarControl.h index 9eab5e3..84b4f3d 100644 --- a/DStarControl.h +++ b/DStarControl.h @@ -37,7 +37,7 @@ class CDStarControl { public: - CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, const std::vector& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); + CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool errorReply, const std::vector& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); ~CDStarControl(); bool writeModem(unsigned char* data, unsigned int len); @@ -50,6 +50,7 @@ private: unsigned char* m_callsign; unsigned char* m_gateway; bool m_selfOnly; + bool m_errorReply; std::vector m_blackList; CDStarNetwork* m_network; CDisplay* m_display; @@ -68,6 +69,7 @@ private: CTimer m_netTimeoutTimer; CTimer m_packetTimer; CTimer m_ackTimer; + CTimer m_errTimer; CStopWatch m_interval; CStopWatch m_elapsed; unsigned int m_rfFrames; @@ -112,6 +114,7 @@ private: void blankDTMF(unsigned char* data) const; void sendAck(); + void sendError(); }; #endif diff --git a/Defines.h b/Defines.h index 6b81e7a..22baf2d 100644 --- a/Defines.h +++ b/Defines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX + * Copyright (C) 2015,2016,2017 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 @@ -44,7 +44,8 @@ enum RPT_RF_STATE { RS_RF_LATE_ENTRY, RS_RF_AUDIO, RS_RF_DATA, - RS_RF_REJECTED + RS_RF_REJECTED, + RS_RF_INVALID }; enum RPT_NET_STATE { diff --git a/MMDVM.ini b/MMDVM.ini index cacc2ff..4d899a3 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -62,6 +62,7 @@ Port=/dev/ttyACM1 Enable=1 Module=C SelfOnly=0 +ErrorReply=1 [DMR] Enable=1 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 22e9707..d568199 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -329,15 +329,17 @@ int CMMDVMHost::run() std::string module = m_conf.getDStarModule(); bool selfOnly = m_conf.getDStarSelfOnly(); std::vector blackList = m_conf.getDStarBlackList(); + bool errorReply = m_conf.getDStarErrorReply(); LogInfo("D-Star Parameters"); LogInfo(" Module: %s", module.c_str()); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); + LogInfo(" Error Reply: %s", errorReply ? "yes" : "no"); if (blackList.size() > 0U) LogInfo(" Black List: %u", blackList.size()); - dstar = new CDStarControl(m_callsign, module, selfOnly, blackList, m_dstarNetwork, m_display, m_timeout, m_duplex, rssi); + dstar = new CDStarControl(m_callsign, module, selfOnly, errorReply, blackList, m_dstarNetwork, m_display, m_timeout, m_duplex, rssi); } CDMRControl* dmr = NULL; From fc477d9abfbbda6aceb642dd7db90e9c14093c3d Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 20 Feb 2017 21:36:35 +0000 Subject: [PATCH 3/6] Add full frame file dumping. --- Conf.cpp | 8 +++++ Conf.h | 2 ++ MMDVM.ini | 1 + MMDVMHost.cpp | 4 +-- Modem.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++------ Modem.h | 6 ++-- 6 files changed, 97 insertions(+), 14 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index 5bdd518..3b1ef41 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -92,6 +92,7 @@ m_modemYSFTXLevel(50U), m_modemP25TXLevel(50U), m_modemOscOffset(0), m_modemRSSIMappingFile(), +m_modemSamplesDir(), m_modemDebug(false), m_umpEnabled(false), m_umpPort(), @@ -331,6 +332,8 @@ bool CConf::read() m_modemOscOffset = ::atoi(value); else if (::strcmp(key, "RSSIMappingFile") == 0) m_modemRSSIMappingFile = value; + else if (::strcmp(key, "SamplesDir") == 0) + m_modemSamplesDir = value; else if (::strcmp(key, "Debug") == 0) m_modemDebug = ::atoi(value) == 1; } else if (section == SECTION_UMP) { @@ -746,6 +749,11 @@ std::string CConf::getModemRSSIMappingFile () const return m_modemRSSIMappingFile; } +std::string CConf::getModemSamplesDir() const +{ + return m_modemSamplesDir; +} + bool CConf::getModemDebug() const { return m_modemDebug; diff --git a/Conf.h b/Conf.h index d158130..4983643 100644 --- a/Conf.h +++ b/Conf.h @@ -79,6 +79,7 @@ public: unsigned int getModemP25TXLevel() const; int getModemOscOffset() const; std::string getModemRSSIMappingFile() const; + std::string getModemSamplesDir() const; bool getModemDebug() const; // The UMP section @@ -230,6 +231,7 @@ private: unsigned int m_modemP25TXLevel; int m_modemOscOffset; std::string m_modemRSSIMappingFile; + std::string m_modemSamplesDir; bool m_modemDebug; bool m_umpEnabled; diff --git a/MMDVM.ini b/MMDVM.ini index 4d899a3..2d990a8 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -51,6 +51,7 @@ TXLevel=50 # P25TXLevel=50 OscOffset=0 RSSIMappingFile=RSSI.dat +SamplesDir= Debug=0 [UMP] diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index d568199..a648007 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -795,6 +795,7 @@ bool CMMDVMHost::createModem() unsigned int rxFrequency = m_conf.getRxFrequency(); unsigned int txFrequency = m_conf.getTxFrequency(); int oscOffset = m_conf.getModemOscOffset(); + std::string samplesDir = m_conf.getModemSamplesDir(); LogInfo("Modem Parameters"); LogInfo(" Port: %s", port.c_str()); @@ -811,10 +812,9 @@ bool CMMDVMHost::createModem() LogInfo(" P25 TX Level: %u%%", p25TXLevel); LogInfo(" RX Frequency: %uHz", rxFrequency); LogInfo(" TX Frequency: %uHz", txFrequency); - LogInfo(" Osc. Offset: %dppm", oscOffset); - m_modem = new CModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, oscOffset, debug); + m_modem = new CModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, oscOffset, samplesDir, debug); m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled); m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel); m_modem->setRFParams(rxFrequency, txFrequency); diff --git a/Modem.cpp b/Modem.cpp index d4429e0..7c3c631 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #if defined(_WIN32) || defined(_WIN64) #include @@ -71,7 +72,8 @@ const unsigned char MMDVM_NAK = 0x7FU; const unsigned char MMDVM_SERIAL = 0x80U; -const unsigned char MMDVM_SAMPLES = 0xF0U; +const unsigned char MMDVM_SAMPLES = 0xEFU; +const unsigned char MMDVM_SYNC_SAMPLES = 0xF0U; const unsigned char MMDVM_DEBUG1 = 0xF1U; const unsigned char MMDVM_DEBUG2 = 0xF2U; @@ -81,10 +83,10 @@ const unsigned char MMDVM_DEBUG5 = 0xF5U; const unsigned int MAX_RESPONSES = 30U; -const unsigned int BUFFER_LENGTH = 500U; +const unsigned int BUFFER_LENGTH = 2000U; -CModem::CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, int oscOffset, bool debug) : +CModem::CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, int oscOffset, const std::string& samplesDir, bool debug) : m_port(port), m_colorCode(0U), m_duplex(duplex), @@ -100,6 +102,7 @@ m_dmrTXLevel(0U), m_ysfTXLevel(0U), m_p25TXLevel(0U), m_oscOffset(oscOffset), +m_samplesDir(samplesDir), m_debug(debug), m_rxFrequency(0U), m_txFrequency(0U), @@ -474,7 +477,11 @@ void CModem::clock(unsigned int ms) break; case MMDVM_SAMPLES: - printSamples(); + dumpSamples(); + break; + + case MMDVM_SYNC_SAMPLES: + printSyncSamples(); break; default: @@ -1128,6 +1135,22 @@ RESP_TYPE_MMDVM CModem::getResponse() } if (m_offset >= 3U) { + // Use later two byte length field + if (m_length == 0U) { + int ret = m_serial.read(m_buffer + 3U, 2U); + if (ret < 0) { + LogError("Error when reading from the modem"); + m_offset = 0U; + return RTM_ERROR; + } + + if (ret == 0) + return RTM_TIMEOUT; + + m_length = (m_buffer[3U] << 8) | m_buffer[4U]; + m_offset = 5U; + } + while (m_offset < m_length) { int ret = m_serial.read(m_buffer + m_offset, m_length - m_offset); if (ret < 0) { @@ -1277,7 +1300,7 @@ void CModem::printDebug() } } -void CModem::printSamples() +void CModem::printSyncSamples() { const char* mode = NULL; switch (m_buffer[3U]) { @@ -1287,12 +1310,12 @@ void CModem::printSamples() case MODE_DMR: mode = "DMR"; break; - case MODE_YSF: - mode = "YSF"; - break; case MODE_P25: mode = "P25"; break; + case MODE_YSF: + mode = "YSF"; + break; default: mode = "???"; break; @@ -1301,7 +1324,7 @@ void CModem::printSamples() char samples[250U]; samples[0U] = '\0'; - unsigned char n = (m_buffer[1U] - 4U) / 2U; + unsigned char n = (m_length - 4U) / 2U; for (unsigned char i = 0U; i < n; i++) { unsigned char index = i * 2U + 4U; @@ -1311,5 +1334,52 @@ void CModem::printSamples() ::sprintf(samples + ::strlen(samples), " %d", val - 2048); } - LogMessage("Debug: Samples dump: %s:%s", mode, samples); + LogMessage("Debug: Sync Samples dump: %s:%s", mode, samples); +} + +void CModem::dumpSamples() +{ + if (m_samplesDir.empty()) + m_samplesDir = "."; + + time_t now; + ::time(&now); + + struct tm* tm = ::localtime(&now); + + char* mode = NULL; + switch (m_buffer[5U]) { + case MODE_DSTAR: + mode = "DStar"; + break; + case MODE_DMR: + mode = "DMR"; + break; + case MODE_P25: + mode = "P25"; + break; + case MODE_YSF: + mode = "YSF"; + break; + default: + LogWarning("Unknown protocol passed to samples dump - %u", m_buffer[5U]); + return; + } + + char filename[150U]; +#if defined(_WIN32) || defined(_WIN64) + ::sprintf(filename, "%s\\Samples-%s-%04d%02d%02d.dat", m_samplesDir.c_str(), mode, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +#else + ::sprintf(filename, "%s/Samples-%s-%04d%02d%02d.dat", m_samplesDir.c_str(), mode, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); +#endif + + FILE* fp = ::fopen(filename, "a+b"); + if (fp == NULL) { + LogWarning("Unable to open samples file for writing - %s", filename); + return; + } + + ::fwrite(m_buffer + 6U, 1U, m_length, fp); + + ::fclose(fp); } diff --git a/Modem.h b/Modem.h index a4d2afd..dfb602d 100644 --- a/Modem.h +++ b/Modem.h @@ -34,7 +34,7 @@ enum RESP_TYPE_MMDVM { class CModem { public: - CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, int oscOffset, bool debug = false); + CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, int oscOffset, const std::string& samplesDir, bool debug = false); ~CModem(); void setRFParams(unsigned int rxFrequency, unsigned int txFrequency); @@ -102,6 +102,7 @@ private: unsigned int m_ysfTXLevel; unsigned int m_p25TXLevel; int m_oscOffset; + std::string m_samplesDir; bool m_debug; unsigned int m_rxFrequency; unsigned int m_txFrequency; @@ -143,7 +144,8 @@ private: bool setFrequency(); void printDebug(); - void printSamples(); + void printSyncSamples(); + void dumpSamples(); RESP_TYPE_MMDVM getResponse(); }; From f8a946889e9e9214728afa622ab256c4c2ee7255 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Feb 2017 11:16:57 +0000 Subject: [PATCH 4/6] Remove compiler warnings. --- Modem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modem.cpp b/Modem.cpp index 7c3c631..93b8358 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -1347,7 +1347,7 @@ void CModem::dumpSamples() struct tm* tm = ::localtime(&now); - char* mode = NULL; + const char* mode = NULL; switch (m_buffer[5U]) { case MODE_DSTAR: mode = "DStar"; From e5228109d0a9e8cd4ce9d941029ceb6c23f58f62 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Feb 2017 17:47:05 +0000 Subject: [PATCH 5/6] Remove sync sample dumping. --- Modem.cpp | 46 ++-------------------------------------------- Modem.h | 1 - 2 files changed, 2 insertions(+), 45 deletions(-) diff --git a/Modem.cpp b/Modem.cpp index 7c3c631..5565b38 100644 --- a/Modem.cpp +++ b/Modem.cpp @@ -72,8 +72,7 @@ const unsigned char MMDVM_NAK = 0x7FU; const unsigned char MMDVM_SERIAL = 0x80U; -const unsigned char MMDVM_SAMPLES = 0xEFU; -const unsigned char MMDVM_SYNC_SAMPLES = 0xF0U; +const unsigned char MMDVM_SAMPLES = 0xF0U; const unsigned char MMDVM_DEBUG1 = 0xF1U; const unsigned char MMDVM_DEBUG2 = 0xF2U; @@ -480,10 +479,6 @@ void CModem::clock(unsigned int ms) dumpSamples(); break; - case MMDVM_SYNC_SAMPLES: - printSyncSamples(); - break; - default: LogMessage("Unknown message, type: %02X", m_buffer[2U]); CUtils::dump("Buffer dump", m_buffer, m_length); @@ -1300,43 +1295,6 @@ void CModem::printDebug() } } -void CModem::printSyncSamples() -{ - const char* mode = NULL; - switch (m_buffer[3U]) { - case MODE_DSTAR: - mode = "D-Star"; - break; - case MODE_DMR: - mode = "DMR"; - break; - case MODE_P25: - mode = "P25"; - break; - case MODE_YSF: - mode = "YSF"; - break; - default: - mode = "???"; - break; - } - - char samples[250U]; - samples[0U] = '\0'; - - unsigned char n = (m_length - 4U) / 2U; - - for (unsigned char i = 0U; i < n; i++) { - unsigned char index = i * 2U + 4U; - - short val = (m_buffer[index + 0U] << 8) | m_buffer[index + 1U]; - - ::sprintf(samples + ::strlen(samples), " %d", val - 2048); - } - - LogMessage("Debug: Sync Samples dump: %s:%s", mode, samples); -} - void CModem::dumpSamples() { if (m_samplesDir.empty()) @@ -1347,7 +1305,7 @@ void CModem::dumpSamples() struct tm* tm = ::localtime(&now); - char* mode = NULL; + const char* mode = NULL; switch (m_buffer[5U]) { case MODE_DSTAR: mode = "DStar"; diff --git a/Modem.h b/Modem.h index dfb602d..6c31992 100644 --- a/Modem.h +++ b/Modem.h @@ -144,7 +144,6 @@ private: bool setFrequency(); void printDebug(); - void printSyncSamples(); void dumpSamples(); RESP_TYPE_MMDVM getResponse(); From 6b4dceca50b968303324d4bd8212edb5dd3a04f1 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Tue, 21 Feb 2017 17:56:58 +0000 Subject: [PATCH 6/6] Put in a dummy value for the new SamplesDir ini file entry. --- MMDVM.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MMDVM.ini b/MMDVM.ini index 2d990a8..6332db6 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -51,7 +51,7 @@ TXLevel=50 # P25TXLevel=50 OscOffset=0 RSSIMappingFile=RSSI.dat -SamplesDir= +SamplesDir=. Debug=0 [UMP]