diff --git a/Conf.cpp b/Conf.cpp index 580bd98..3ad2eba 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -129,7 +129,7 @@ m_dstarBlackList(), m_dstarWhiteList(), m_dstarAckReply(true), m_dstarAckTime(750U), -m_dstarAckMessage(false), +m_dstarAckMessage(DSTAR_ACK_BER), m_dstarErrorReply(true), m_dstarRemoteGateway(false), m_dstarModeHang(10U), @@ -583,8 +583,11 @@ bool CConf::read() m_dstarAckReply = ::atoi(value) == 1; else if (::strcmp(key, "AckTime") == 0) m_dstarAckTime = (unsigned int)::atoi(value); - else if (::strcmp(key, "AckMessage") == 0) - m_dstarAckMessage = ::atoi(value) == 1; + else if (::strcmp(key, "AckMessage") == 0) { + m_dstarAckMessage = (DSTAR_ACK_MESSAGE)::atoi(value); + if (m_dstarAckMessage != DSTAR_ACK_BER && m_dstarAckMessage != DSTAR_ACK_RSSI && m_dstarAckMessage != DSTAR_ACK_SMETER) + m_dstarAckMessage = DSTAR_ACK_BER; + } else if (::strcmp(key, "ErrorReply") == 0) m_dstarErrorReply = ::atoi(value) == 1; else if (::strcmp(key, "RemoteGateway") == 0) @@ -1326,7 +1329,7 @@ unsigned int CConf::getDStarAckTime() const return m_dstarAckTime; } -bool CConf::getDStarAckMessage() const +DSTAR_ACK_MESSAGE CConf::getDStarAckMessage() const { return m_dstarAckMessage; } diff --git a/Conf.h b/Conf.h index 5e5a7d3..0fc4650 100644 --- a/Conf.h +++ b/Conf.h @@ -116,7 +116,7 @@ public: std::vector getDStarWhiteList() const; bool getDStarAckReply() const; unsigned int getDStarAckTime() const; - bool getDStarAckMessage() const; + DSTAR_ACK_MESSAGE getDStarAckMessage() const; bool getDStarErrorReply() const; bool getDStarRemoteGateway() const; unsigned int getDStarModeHang() const; @@ -391,7 +391,7 @@ private: std::vector m_dstarWhiteList; bool m_dstarAckReply; unsigned int m_dstarAckTime; - bool m_dstarAckMessage; + DSTAR_ACK_MESSAGE m_dstarAckMessage; bool m_dstarErrorReply; bool m_dstarRemoteGateway; unsigned int m_dstarModeHang; diff --git a/DStarControl.cpp b/DStarControl.cpp index 7a436e5..1c418bd 100644 --- a/DStarControl.cpp +++ b/DStarControl.cpp @@ -15,6 +15,7 @@ #include "Utils.h" #include "Sync.h" #include "Log.h" +#include "SMeter.h" #include #include @@ -37,7 +38,7 @@ 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, bool ackReply, unsigned int ackTime, bool ackMessage, bool errorReply, const std::vector& blackList, const std::vector& whiteList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper) : +CDStarControl::CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, DSTAR_ACK_MESSAGE ackMessage, bool errorReply, const std::vector& blackList, const std::vector& whiteList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper) : m_callsign(NULL), m_gateway(NULL), m_selfOnly(selfOnly), @@ -1182,12 +1183,28 @@ void CDStarControl::sendAck() m_network->getStatus(status, reflector); char text[40U]; - if (m_ackMessage && m_rssi != 0) { - 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 -%udBm ", reflector, m_aveRSSI / m_rssiCount); + if (m_ackMessage == DSTAR_ACK_RSSI && m_rssi != 0) { + if (status == LS_LINKED_DEXTRA || status == LS_LINKED_DPLUS || status == LS_LINKED_DCS || status == LS_LINKED_CCS || status == LS_LINKED_LOOPBACK) { + CUtils::removeChar(reflector, ' ');//remove space from reflector so all nicely fits onto 20 chars in case rssi < 99dBm + ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + } else ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); } + else if (m_ackMessage == DSTAR_ACK_SMETER && m_rssi != 0) { + unsigned int signal, plus; + char signalText[10U]; + CSMeter::getSignal(m_aveRSSI / m_rssiCount, signal, plus); + if (plus != 0U) + ::sprintf(signalText, "S%u+%02u", signal, plus); + else + ::sprintf(signalText, "S%u", signal); + + 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 %.1f%% %s ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), signalText); + else + ::sprintf(text, "BER:%.1f%% %s ", float(m_rfErrs * 100U) / float(m_rfBits), signalText); + } else { 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)); @@ -1232,12 +1249,28 @@ void CDStarControl::sendError() m_network->getStatus(status, reflector); char text[40U]; - if (m_ackMessage && m_rssi != 0) { - 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 -%udBm ", reflector, m_aveRSSI / m_rssiCount); + if (m_ackMessage == DSTAR_ACK_RSSI && m_rssi != 0) { + if (status == LS_LINKED_DEXTRA || status == LS_LINKED_DPLUS || status == LS_LINKED_DCS || status == LS_LINKED_CCS || status == LS_LINKED_LOOPBACK) { + CUtils::removeChar(reflector, ' ');//remove space from reflector so all nicely fits onto 20 chars in case rssi < 99dBm + ::sprintf(text, "%-8.8s %.1f%% -%udBm ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); + } else ::sprintf(text, "BER:%.1f%% -%udBm ", float(m_rfErrs * 100U) / float(m_rfBits), m_aveRSSI / m_rssiCount); } + else if (m_ackMessage == DSTAR_ACK_SMETER && m_rssi != 0) { + unsigned int signal, plus; + char signalText[10U]; + CSMeter::getSignal(m_aveRSSI / m_rssiCount, signal, plus); + if (plus != 0U) + ::sprintf(signalText, "S%u+%02u", signal, plus); + else + ::sprintf(signalText, "S%u", signal); + + 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 %.1f%% %s ", reflector, float(m_rfErrs * 100U) / float(m_rfBits), signalText); + else + ::sprintf(text, "BER:%.1f%% %s ", float(m_rfErrs * 100U) / float(m_rfBits), signalText); + } else { 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)); diff --git a/DStarControl.h b/DStarControl.h index 1378c87..e37f3d0 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, bool ackReply, unsigned int ackTime, bool ackMessage, bool errorReply, const std::vector& blackList, const std::vector& whiteList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper); + CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, DSTAR_ACK_MESSAGE ackMessage, bool errorReply, const std::vector& blackList, const std::vector& whiteList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper); ~CDStarControl(); bool writeModem(unsigned char* data, unsigned int len); @@ -55,7 +55,7 @@ private: unsigned char* m_gateway; bool m_selfOnly; bool m_ackReply; - bool m_ackMessage; + DSTAR_ACK_MESSAGE m_ackMessage; bool m_errorReply; bool m_remoteGateway; std::vector m_blackList; diff --git a/Defines.h b/Defines.h index f254758..16622c7 100644 --- a/Defines.h +++ b/Defines.h @@ -85,4 +85,10 @@ enum DMR_OVCM_TYPES { DMR_OVCM_FORCE_OFF }; +enum DSTAR_ACK_MESSAGE { + DSTAR_ACK_BER, + DSTAR_ACK_RSSI, + DSTAR_ACK_SMETER +}; + #endif diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 2161f17..e1cf512 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -423,7 +423,7 @@ int CMMDVMHost::run() std::vector whiteList = m_conf.getDStarWhiteList(); bool ackReply = m_conf.getDStarAckReply(); unsigned int ackTime = m_conf.getDStarAckTime(); - bool ackMessage = m_conf.getDStarAckMessage(); + DSTAR_ACK_MESSAGE ackMessage = m_conf.getDStarAckMessage(); bool errorReply = m_conf.getDStarErrorReply(); bool remoteGateway = m_conf.getDStarRemoteGateway(); m_dstarRFModeHang = m_conf.getDStarModeHang(); @@ -432,7 +432,7 @@ int CMMDVMHost::run() LogInfo(" Module: %s", module.c_str()); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); LogInfo(" Ack Reply: %s", ackReply ? "yes" : "no"); - LogInfo(" Ack message: %s", ackMessage ? "RSSI" : "BER"); + LogInfo(" Ack message: %s", ackMessage == DSTAR_ACK_RSSI? "RSSI" : (ackMessage == DSTAR_ACK_SMETER ? "SMETER" : "BER")); LogInfo(" Ack Time: %ums", ackTime); LogInfo(" Error Reply: %s", errorReply ? "yes" : "no"); LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no"); diff --git a/Makefile b/Makefile index 8dc7dfb..44906ee 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ OBJECTS = \ MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \ - RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi b/Makefile.Pi index aa7e3f4..b92ab0b 100644 --- a/Makefile.Pi +++ b/Makefile.Pi @@ -13,7 +13,7 @@ OBJECTS = \ MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \ - RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \ YSFFICH.o YSFNetwork.o YSFPayload.o diff --git a/Makefile.Pi.HD44780 b/Makefile.Pi.HD44780 index 08458ca..3ebe193 100644 --- a/Makefile.Pi.HD44780 +++ b/Makefile.Pi.HD44780 @@ -13,7 +13,7 @@ OBJECTS = \ MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \ - RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.OLED b/Makefile.Pi.OLED index a58842b..0eceedf 100644 --- a/Makefile.Pi.OLED +++ b/Makefile.Pi.OLED @@ -17,7 +17,7 @@ OBJECTS = \ MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \ - RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/Makefile.Pi.PCF8574 b/Makefile.Pi.PCF8574 index f9bfc81..ad21a23 100644 --- a/Makefile.Pi.PCF8574 +++ b/Makefile.Pi.PCF8574 @@ -14,7 +14,7 @@ OBJECTS = \ MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o \ NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o \ P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \ - RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ + RSSIInterpolator.o SerialController.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \ UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o all: MMDVMHost RemoteCommand diff --git a/SMeter.cpp b/SMeter.cpp new file mode 100644 index 0000000..0376c0b --- /dev/null +++ b/SMeter.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "SMeter.h" + +#define RSSI_S1 141U +#define RSSI_S9 93U + +void CSMeter::getSignal(unsigned int rssi, unsigned int & signal, unsigned int & plus) +{ + if (rssi > RSSI_S1) { + signal = 0; + plus = rssi - RSSI_S1; + } + else if (rssi > RSSI_S9 && rssi <= RSSI_S1) { + signal = ((RSSI_S1 - rssi) / 6U) + 1U; + plus = (RSSI_S1 - rssi) % 6U; + } + else { + signal = 9U; + plus = RSSI_S9 - rssi; + } +} \ No newline at end of file diff --git a/SMeter.h b/SMeter.h new file mode 100644 index 0000000..5792cd5 --- /dev/null +++ b/SMeter.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015-2021 by Jonathan Naylor G4KLX + * Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if !defined(SMETER_H) +#define SMETER_H + +#include +#include + +class CSMeter +{ +public: + static void getSignal(unsigned int rssi, unsigned int & signal, unsigned int & plus); +}; + +#endif \ No newline at end of file diff --git a/Utils.cpp b/Utils.cpp index 49ded13..1c0c06c 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -144,3 +144,17 @@ void CUtils::bitsToByteLE(const bool* bits, unsigned char& byte) byte |= bits[6U] ? 0x40U : 0x00U; byte |= bits[7U] ? 0x80U : 0x00U; } + +void CUtils::removeChar(unsigned char * haystack, char needdle) +{ + unsigned int i = 0; + unsigned int j = 0; + + while (haystack[i] != '\0') { + if (haystack[i] != needdle) + haystack[j++] = haystack[i]; + i++; + } + + haystack[j] = '\0'; +} \ No newline at end of file diff --git a/Utils.h b/Utils.h index ade28c0..8f6abf3 100644 --- a/Utils.h +++ b/Utils.h @@ -30,6 +30,8 @@ public: static void bitsToByteBE(const bool* bits, unsigned char& byte); static void bitsToByteLE(const bool* bits, unsigned char& byte); + static void removeChar(unsigned char * haystack, char needdle); + private: };