diff --git a/DVMHost.vcxproj b/DVMHost.vcxproj
index 5b709d4b..2f218a70 100644
--- a/DVMHost.vcxproj
+++ b/DVMHost.vcxproj
@@ -163,6 +163,7 @@
+
diff --git a/DVMHost.vcxproj.filters b/DVMHost.vcxproj.filters
index e413b15e..b5ff3973 100644
--- a/DVMHost.vcxproj.filters
+++ b/DVMHost.vcxproj.filters
@@ -362,6 +362,9 @@
Header Files\host\setup
+
+ Header Files\dmr
+
diff --git a/Defines.h b/Defines.h
index 04f45862..3578db84 100644
--- a/Defines.h
+++ b/Defines.h
@@ -178,6 +178,12 @@ inline std::string __INT_STR(const int& value) {
return ss.str();
}
+inline std::string __INT_HEX_STR(const int& value) {
+ std::stringstream ss;
+ ss << std::hex << value;
+ return ss.str();
+}
+
inline std::string __FLOAT_STR(const float& value) {
std::stringstream ss;
ss << value;
diff --git a/dmr/DMRUtils.h b/dmr/DMRUtils.h
new file mode 100644
index 00000000..d8493c3e
--- /dev/null
+++ b/dmr/DMRUtils.h
@@ -0,0 +1,143 @@
+/**
+* Digital Voice Modem - Host Software
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / Host Software
+*
+*/
+//
+// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost)
+// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+//
+/*
+* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
+*
+* 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(__DMR_UTILS_H__)
+#define __DMR_UTILS_H__
+
+#include "Defines.h"
+#include "dmr/DMRDefines.h"
+
+namespace dmr
+{
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // This class implements various helper functions for validating DMR data.
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API DMRUtils {
+ public:
+ /// Helper to test and clamp a DMR color code.
+ static uint32_t colorCode(uint32_t colorCode)
+ {
+ if (colorCode < 0U) { // clamp to 0
+ colorCode = 0U;
+ }
+ if (colorCode > 15U) { // clamp to 15
+ colorCode = 15U;
+ }
+
+ return colorCode;
+ }
+
+ /// Helper to test and clamp a DMR site ID.
+ static uint32_t siteId(uint32_t id, uint8_t siteModel)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+
+ switch (siteModel)
+ {
+ case SITE_MODEL_TINY:
+ {
+ if (id > 0x07U) { // clamp to $7
+ id = 0x07U;
+ }
+ }
+ break;
+ case SITE_MODEL_SMALL:
+ {
+ if (id > 0x1FU) { // clamp to $1F
+ id = 0x1FU;
+ }
+ }
+ break;
+ case SITE_MODEL_LARGE:
+ {
+ if (id > 0xFFU) { // clamp to $FF
+ id = 0xFFU;
+ }
+ }
+ break;
+ case SITE_MODEL_HUGE:
+ {
+ if (id > 0x7FFU) { // clamp to $7FF
+ id = 0x7FFU;
+ }
+ }
+ break;
+ }
+
+ return id;
+ }
+
+ /// Helper to test and clamp a DMR network ID.
+ static uint32_t netId(uint32_t id, uint8_t siteModel)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+
+ switch (siteModel) {
+ case SITE_MODEL_TINY:
+ {
+ if (id > 0x1FFU) { // clamp to $1FF
+ id = 0x1FFU;
+ }
+ }
+ break;
+ case SITE_MODEL_SMALL:
+ {
+ if (id > 0x7FU) { // clamp to $7F
+ id = 0x7FU;
+ }
+ }
+ break;
+ case SITE_MODEL_LARGE:
+ {
+ if (id > 0x1FU) { // clamp to $1F
+ id = 0x1FU;
+ }
+ }
+ break;
+ case SITE_MODEL_HUGE:
+ {
+ if (id > 0x03U) { // clamp to $3
+ id = 0x03U;
+ }
+ }
+ break;
+ }
+
+ return id;
+ }
+ };
+} // namespace dmr
+
+#endif // __DMR_UTILS_H__
diff --git a/dmr/SiteData.h b/dmr/SiteData.h
index 3c637a74..704842d6 100644
--- a/dmr/SiteData.h
+++ b/dmr/SiteData.h
@@ -32,6 +32,7 @@
#include "Defines.h"
#include "dmr/DMRDefines.h"
+#include "dmr/DMRUtils.h"
namespace dmr
{
@@ -72,71 +73,10 @@ namespace dmr
siteModel = SITE_MODEL_SMALL;
// netId clamping
- if (netId == 0U) // clamp to 1
- netId = 1U;
-
- switch (siteModel) {
- case SITE_MODEL_TINY:
- {
- if (netId > 0x1FFU) // clamp to $1FF
- netId = 0x1FFU;
- }
- break;
- case SITE_MODEL_SMALL:
- {
- if (netId > 0x7FU) // clamp to $7F
- netId = 0x7FU;
- }
- break;
- case SITE_MODEL_LARGE:
- {
- if (netId > 0x1FU) // clamp to $1F
- netId = 0x1FU;
- }
- break;
- case SITE_MODEL_HUGE:
- {
- if (netId > 0x03U) // clamp to $3
- netId = 0x03U;
- }
- break;
- }
-
- m_netId = netId;
+ m_netId = DMRUtils::netId(netId, siteModel);
// siteId clamping
- if (siteId == 0U) // clamp to 1
- siteId = 1U;
-
- switch (siteModel)
- {
- case SITE_MODEL_TINY:
- {
- if (siteId > 0x07U) // clamp to $7
- siteId = 0x07U;
- }
- break;
- case SITE_MODEL_SMALL:
- {
- if (siteId > 0x1FU) // clamp to $1F
- siteId = 0x1FU;
- }
- break;
- case SITE_MODEL_LARGE:
- {
- if (siteId > 0xFFU) // clamp to $FF
- siteId = 0xFFU;
- }
- break;
- case SITE_MODEL_HUGE:
- {
- if (siteId > 0x7FFU) // clamp to $7FF
- siteId = 0x7FFU;
- }
- break;
- }
-
- m_siteId = siteId;
+ m_siteId = DMRUtils::siteId(siteId, siteModel);
// parId clamping
if (parId == 0U)
diff --git a/host/Host.cpp b/host/Host.cpp
index a3afdfeb..67f0831c 100644
--- a/host/Host.cpp
+++ b/host/Host.cpp
@@ -31,7 +31,9 @@
*/
#include "Defines.h"
#include "dmr/Control.h"
+#include "dmr/DMRUtils.h"
#include "p25/Control.h"
+#include "p25/P25Utils.h"
#include "modem/port/ModemNullPort.h"
#include "modem/port/UARTPort.h"
#include "modem/port/UDPPort.h"
@@ -1410,59 +1412,26 @@ bool Host::readParams()
strVoiceChNo.erase(strVoiceChNo.find_last_of(","));
m_siteId = (uint8_t)::strtoul(rfssConfig["siteId"].as("1").c_str(), NULL, 16);
- if (m_siteId == 0U) { // clamp to 1
- m_siteId = 1U;
- }
- if (m_siteId > 0xFEU) { // clamp to $FE
- m_siteId = 0xFEU;
- }
+ m_siteId = p25::P25Utils::siteId(m_siteId);
m_dmrColorCode = rfssConfig["colorCode"].as(2U);
- if (m_dmrColorCode < 0U) { // clamp to 0
- m_dmrColorCode = 0U;
- }
- if (m_dmrColorCode > 15U) { // clamp to 15
- m_dmrColorCode = 15U;
- }
+ m_dmrColorCode = dmr::DMRUtils::colorCode(m_dmrColorCode);
m_dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as("1").c_str(), NULL, 16);
- if (m_dmrNetId == 0U) { // clamp to 1
- m_dmrNetId = 1U;
- }
- if (m_dmrNetId > 0x1FFU) { // clamp to $1FF
- m_dmrNetId = 0x1FFU;
- }
+ m_dmrNetId = dmr::DMRUtils::netId(m_dmrNetId, dmr::SITE_MODEL_TINY);
m_p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as("293").c_str(), NULL, 16);
- if (m_p25NAC < 0U) { // clamp to $000
- m_p25NAC = 0U;
- }
- if (m_p25NAC > 0xF7DU) { // clamp to $F7D
- m_p25NAC = 0xF7DU;
- }
+ m_p25NAC = p25::P25Utils::nac(m_p25NAC);
m_p25PatchSuperGroup = (uint32_t)::strtoul(rfssConfig["pSuperGroup"].as("FFFF").c_str(), NULL, 16);
m_p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as("BB800").c_str(), NULL, 16);
- if (m_p25NetId == 0U) { // clamp to 1
- m_p25NetId = 1U;
- }
- if (m_p25NetId > 0xFFFFEU) { // clamp to $FFFFE
- m_p25NetId = 0xFFFFEU;
- }
+ m_p25NetId = p25::P25Utils::netId(m_p25NetId);
+
m_p25SysId = (uint32_t)::strtoul(rfssConfig["sysId"].as("001").c_str(), NULL, 16);
- if (m_p25SysId == 0U) { // clamp to 1
- m_p25SysId = 1U;
- }
- if (m_p25SysId > 0xFFEU) { // clamp to $FFE
- m_p25SysId = 0xFFEU;
- }
+ m_p25SysId = p25::P25Utils::sysId(m_p25SysId);
+
m_p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as("1").c_str(), NULL, 16);
- if (m_p25RfssId == 0U) { // clamp to 1
- m_p25RfssId = 1U;
- }
- if (m_p25RfssId > 0xFEU) { // clamp to $FE
- m_p25RfssId = 0xFEU;
- }
+ m_p25RfssId = p25::P25Utils::rfssId(m_p25RfssId);
LogInfo("System Config Parameters");
LogInfo(" RX Frequency: %uHz", m_rxFrequency);
@@ -1625,8 +1594,8 @@ bool Host::createModem()
}
// apply the frequency tuning offsets
- int adjustedRx = m_rxFrequency + rxTuning;
- int adjustedTx = m_txFrequency + txTuning;
+ uint32_t rxActualFreq = m_rxFrequency + rxTuning;
+ uint32_t txActualFreq = m_txFrequency + txTuning;
LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no");
LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
@@ -1640,8 +1609,8 @@ bool Host::createModem()
LogInfo(" TX DC Offset: %d", txDCOffset);
LogInfo(" RX Tuning Offset: %dhz", rxTuning);
LogInfo(" TX Tuning Offset: %dhz", txTuning);
- LogInfo(" RX Effective Frequency: %dhz", adjustedRx);
- LogInfo(" TX Effective Frequency: %dhz", adjustedTx);
+ LogInfo(" RX Effective Frequency: %uhz", rxActualFreq);
+ LogInfo(" TX Effective Frequency: %uhz", txActualFreq);
LogInfo(" RF Power Level: %u", rfPower);
LogInfo(" RX Level: %.1f%%", rxLevel);
LogInfo(" CW Id TX Level: %.1f%%", cwIdTXLevel);
@@ -1659,7 +1628,7 @@ bool Host::createModem()
m_modem->setLevels(rxLevel, cwIdTXLevel, dmrTXLevel, p25TXLevel);
m_modem->setSymbolAdjust(dmrSymLevel3Adj, dmrSymLevel1Adj, p25SymLevel3Adj, p25SymLevel1Adj);
m_modem->setDCOffsetParams(txDCOffset, rxDCOffset);
- m_modem->setRFParams(adjustedRx, adjustedTx, rfPower);
+ m_modem->setRFParams(rxActualFreq, txActualFreq, rfPower);
m_modem->setDMRColorCode(m_dmrColorCode);
m_modem->setP25NAC(m_p25NAC);
diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp
index d14d82d3..f682254f 100644
--- a/host/calibrate/HostCal.cpp
+++ b/host/calibrate/HostCal.cpp
@@ -152,8 +152,12 @@ HostCal::HostCal(const std::string& confFile) :
m_debug(false),
m_mode(STATE_DMR_CAL),
m_modeStr(DMR_CAL_STR),
+ m_rxTuning(0),
+ m_txTuning(0),
m_rxFrequency(0U),
+ m_rxAdjustedFreq(0U),
m_txFrequency(0U),
+ m_txAdjustedFreq(0U),
m_channelId(0U),
m_channelNo(0U),
m_idenTable(NULL),
@@ -269,6 +273,18 @@ int HostCal::run()
yaml::Node modemConf = systemConf["modem"];
+ m_rxTuning = modemConf["rxTuning"].as(0);
+ m_txTuning = modemConf["txTuning"].as(0);
+
+ // apply the frequency tuning offsets
+ m_rxAdjustedFreq = m_rxFrequency + m_rxTuning;
+ m_txAdjustedFreq = m_txFrequency + m_txTuning;
+
+ LogInfo(" RX Tuning Offset: %dhz", m_rxTuning);
+ LogInfo(" TX Tuning Offset: %dhz", m_txTuning);
+ LogInfo(" RX Effective Frequency: %uhz", m_rxAdjustedFreq);
+ LogInfo(" TX Effective Frequency: %uhz", m_txAdjustedFreq);
+
yaml::Node modemProtocol = modemConf["protocol"];
std::string portType = modemProtocol["type"].as("null");
@@ -443,6 +459,105 @@ int HostCal::run()
setTXDCOffset(1);
break;
+ case 'N':
+ {
+ char value[5] = { '\0' };
+ ::fprintf(stdout, "> FDMA Preambles [%u] ? ", m_fdmaPreamble);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 5, 0);
+ if (value[0] != '\0') {
+ // bryanb: appease the compiler...
+ uint32_t fdmaPreamble = m_fdmaPreamble;
+ sscanf(value, "%u", &fdmaPreamble);
+
+ m_fdmaPreamble = (uint8_t)fdmaPreamble;
+
+ writeConfig();
+ }
+ }
+ break;
+
+ case 'W':
+ {
+ char value[5] = { '\0' };
+ ::fprintf(stdout, "> DMR Rx Delay [%u] ? ", m_dmrRxDelay);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 5, 0);
+ if (value[0] != '\0') {
+ // bryanb: appease the compiler...
+ uint32_t dmrRxDelay = m_dmrRxDelay;
+ sscanf(value, "%u", &dmrRxDelay);
+
+ m_dmrRxDelay = (uint8_t)dmrRxDelay;
+
+ writeConfig();
+ }
+ }
+ break;
+
+ case 'w':
+ {
+ char value[5] = { '\0' };
+ ::fprintf(stdout, "> P25 Correlation Count [%u] ? ", m_p25CorrCount);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 5, 0);
+ if (value[0] != '\0') {
+ // bryanb: appease the compiler...
+ uint32_t p25CorrCount = m_p25CorrCount;
+ sscanf(value, "%u", &p25CorrCount);
+
+ m_p25CorrCount = (uint8_t)p25CorrCount;
+
+ writeConfig();
+ }
+ }
+ break;
+
+ case 'F':
+ {
+ char value[10] = { '\0' };
+ ::fprintf(stdout, "> Rx Frequency Offset [%dHz] (Hz) ? ", m_rxTuning);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 10, 0);
+ if (value[0] != '\0') {
+ int rxTuning = m_rxTuning;
+ sscanf(value, "%d", &rxTuning);
+
+ m_rxTuning = rxTuning;
+ m_rxAdjustedFreq = m_rxFrequency + m_rxTuning;
+
+ writeRFParams();
+ }
+
+ printStatus();
+ }
+ break;
+
+ case 'f':
+ {
+ char value[10] = { '\0' };
+ ::fprintf(stdout, "> Tx Frequency Offset [%dHz] (Hz) ? ", m_txTuning);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 10, 0);
+ if (value[0] != '\0') {
+ int txTuning = m_txTuning;
+ sscanf(value, "%d", &txTuning);
+
+ m_txTuning = txTuning;
+ m_txAdjustedFreq = m_txFrequency + m_txTuning;
+
+ writeRFParams();
+ }
+
+ printStatus();
+ }
+ break;
+
/** Engineering Commands */
case '-':
setDMRSymLevel3Adj(-1);
@@ -860,6 +975,11 @@ void HostCal::displayHelp()
LogMessage(LOG_CAL, " T/t Increase/Decrease transmit level");
LogMessage(LOG_CAL, " C/c Increase/Decrease RX DC offset level");
LogMessage(LOG_CAL, " O/o Increase/Decrease TX DC offset level");
+ LogMessage(LOG_CAL, " N Set FDMA Preambles");
+ LogMessage(LOG_CAL, " W Set DMR Rx Delay");
+ LogMessage(LOG_CAL, " w Set P25 Correlation Count");
+ LogMessage(LOG_CAL, " F Set Rx Frequency Adjustment (affects hotspots only!)");
+ LogMessage(LOG_CAL, " f Set Tx Frequency Adjustment (affects hotspots only!)");
LogMessage(LOG_CAL, "Mode Commands:");
LogMessage(LOG_CAL, " Z %s", DMR_CAL_STR);
LogMessage(LOG_CAL, " z %s", P25_CAL_STR);
@@ -1601,6 +1721,7 @@ bool HostCal::writeConfig(uint8_t modeOverride)
m_fdmaPreamble = MAX_FDMA_PREAMBLE;
}
+ m_conf["system"]["modem"]["fdmaPreamble"] = __INT_STR(m_fdmaPreamble);
buffer[5U] = m_fdmaPreamble;
buffer[6U] = modeOverride;
@@ -1613,6 +1734,7 @@ bool HostCal::writeConfig(uint8_t modeOverride)
buffer[9U] = 1U;
+ m_conf["system"]["modem"]["dmrRxDelay"] = __INT_STR(m_dmrRxDelay);
buffer[10U] = m_dmrRxDelay;
uint32_t nac = 0xF7EU;
@@ -1627,6 +1749,7 @@ bool HostCal::writeConfig(uint8_t modeOverride)
m_conf["system"]["modem"]["rxDCOffset"] = __INT_STR(m_rxDCOffset);
buffer[17U] = (uint8_t)(m_rxDCOffset + 128);
+ m_conf["system"]["modem"]["p25CorrCount"] = __INT_STR(m_p25CorrCount);
buffer[14U] = (uint8_t)m_p25CorrCount;
int ret = m_modem->write(buffer, 17U);
@@ -1653,15 +1776,15 @@ bool HostCal::writeRFParams()
buffer[3U] = 0x00U;
- buffer[4U] = (m_rxFrequency >> 0) & 0xFFU;
- buffer[5U] = (m_rxFrequency >> 8) & 0xFFU;
- buffer[6U] = (m_rxFrequency >> 16) & 0xFFU;
- buffer[7U] = (m_rxFrequency >> 24) & 0xFFU;
+ buffer[4U] = (m_rxAdjustedFreq >> 0) & 0xFFU;
+ buffer[5U] = (m_rxAdjustedFreq >> 8) & 0xFFU;
+ buffer[6U] = (m_rxAdjustedFreq >> 16) & 0xFFU;
+ buffer[7U] = (m_rxAdjustedFreq >> 24) & 0xFFU;
- buffer[8U] = (m_txFrequency >> 0) & 0xFFU;
- buffer[9U] = (m_txFrequency >> 8) & 0xFFU;
- buffer[10U] = (m_txFrequency >> 16) & 0xFFU;
- buffer[11U] = (m_txFrequency >> 24) & 0xFFU;
+ buffer[8U] = (m_txAdjustedFreq >> 0) & 0xFFU;
+ buffer[9U] = (m_txAdjustedFreq >> 8) & 0xFFU;
+ buffer[10U] = (m_txAdjustedFreq >> 16) & 0xFFU;
+ buffer[11U] = (m_txAdjustedFreq >> 24) & 0xFFU;
buffer[12U] = (unsigned char)(100 * 2.55F + 0.5F); // cal sets power fixed to 100
@@ -1766,15 +1889,30 @@ void HostCal::timerStop()
///
void HostCal::printStatus()
{
- LogMessage(LOG_CAL, " - PTT Invert: %s, RX Invert: %s, TX Invert: %s, DC Blocker: %s",
- m_pttInvert ? "yes" : "no", m_rxInvert ? "yes" : "no", m_txInvert ? "yes" : "no", m_dcBlocker ? "yes" : "no");
- LogMessage(LOG_CAL, " - RX Level: %.1f%%, TX Level: %.1f%%, TX DC Offset: %d, RX DC Offset: %d",
- m_rxLevel, m_txLevel, m_txDCOffset, m_rxDCOffset);
- LogMessage(LOG_CAL, " - DMR Symbol +/- 3 Level Adj.: %d, DMR Symbol +/- 1 Level Adj.: %d, P25 Symbol +/- 3 Level Adj.: %d, P25 Symbol +/- 1 Level Adj.: %d",
- m_dmrSymLevel3Adj, m_dmrSymLevel1Adj, m_p25SymLevel3Adj, m_p25SymLevel1Adj);
- LogMessage(LOG_CAL, " - FDMA Preambles: %u (%.1fms), DMR Rx Delay: %u (%.1fms), P25 Corr. Count: %u (%.1fms)", m_fdmaPreamble, float(m_fdmaPreamble) * 0.2083F, m_dmrRxDelay, float(m_dmrRxDelay) * 0.0416666F,
- m_p25CorrCount, float(m_p25CorrCount) * 0.667F);
- LogMessage(LOG_CAL, " - Rx Freq: %uHz, Tx Freq: %uHz, Operating Mode: %s", m_rxFrequency, m_txFrequency, m_modeStr.c_str());
+ yaml::Node systemConf = m_conf["system"];
+ {
+ yaml::Node modemConfig = m_conf["system"]["modem"];
+ std::string type = modemConfig["protocol"]["type"].as();
+
+ yaml::Node uartConfig = modemConfig["protocol"]["uart"];
+ std::string modemPort = uartConfig["port"].as();
+ uint32_t portSpeed = uartConfig["speed"].as(115200U);
+
+ LogMessage(LOG_CAL, " - Operating Mode: %s, Port Type: %s, Modem Port: %s, Port Speed: %u", m_modeStr.c_str(), type.c_str(), modemPort.c_str(), portSpeed);
+ }
+
+ {
+ LogMessage(LOG_CAL, " - PTT Invert: %s, RX Invert: %s, TX Invert: %s, DC Blocker: %s",
+ m_pttInvert ? "yes" : "no", m_rxInvert ? "yes" : "no", m_txInvert ? "yes" : "no", m_dcBlocker ? "yes" : "no");
+ LogMessage(LOG_CAL, " - RX Level: %.1f%%, TX Level: %.1f%%, TX DC Offset: %d, RX DC Offset: %d",
+ m_rxLevel, m_txLevel, m_txDCOffset, m_rxDCOffset);
+ LogMessage(LOG_CAL, " - DMR Symbol +/- 3 Level Adj.: %d, DMR Symbol +/- 1 Level Adj.: %d, P25 Symbol +/- 3 Level Adj.: %d, P25 Symbol +/- 1 Level Adj.: %d",
+ m_dmrSymLevel3Adj, m_dmrSymLevel1Adj, m_p25SymLevel3Adj, m_p25SymLevel1Adj);
+ LogMessage(LOG_CAL, " - FDMA Preambles: %u (%.1fms), DMR Rx Delay: %u (%.1fms), P25 Corr. Count: %u (%.1fms)", m_fdmaPreamble, float(m_fdmaPreamble) * 0.2083F, m_dmrRxDelay, float(m_dmrRxDelay) * 0.0416666F,
+ m_p25CorrCount, float(m_p25CorrCount) * 0.667F);
+ LogMessage(LOG_CAL, " - Rx Freq: %uHz, Tx Freq: %uHz, Rx Offset: %dHz, Tx Offset: %dHz", m_rxFrequency, m_txFrequency, m_rxTuning, m_txTuning);
+ LogMessage(LOG_CAL, " - Rx Effective Freq: %uHz, Tx Effective Freq: %uHz", m_rxAdjustedFreq, m_txAdjustedFreq);
+ }
uint8_t buffer[50U];
diff --git a/host/calibrate/HostCal.h b/host/calibrate/HostCal.h
index 8b84c765..2d57b2c5 100644
--- a/host/calibrate/HostCal.h
+++ b/host/calibrate/HostCal.h
@@ -99,8 +99,13 @@ private:
uint8_t m_mode;
std::string m_modeStr;
+ int m_rxTuning;
+ int m_txTuning;
+
uint32_t m_rxFrequency;
+ uint32_t m_rxAdjustedFreq;
uint32_t m_txFrequency;
+ uint32_t m_txAdjustedFreq;
uint8_t m_channelId;
uint32_t m_channelNo;
diff --git a/host/setup/HostSetup.cpp b/host/setup/HostSetup.cpp
index 1a53852b..f0fc451e 100644
--- a/host/setup/HostSetup.cpp
+++ b/host/setup/HostSetup.cpp
@@ -27,6 +27,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include "dmr/DMRUtils.h"
+#include "p25/P25Utils.h"
#include "host/setup/HostSetup.h"
#include "HostMain.h"
#include "Log.h"
@@ -92,6 +94,7 @@ int HostSetup::run()
::LogInfo(">> Modem Setup");
yaml::Node systemConf = m_conf["system"];
+ yaml::Node modemConfig = systemConf["modem"];
m_duplex = systemConf["duplex"].as(true);
// try to load bandplan identity table
@@ -111,20 +114,7 @@ int HostSetup::run()
m_idenTable = new IdenTableLookup(idenLookupFile, idenReloadTime);
m_idenTable->read();
- LogInfo("General Parameters");
-
- std::string identity = systemConf["identity"].as();
- ::LogInfo(" Identity: %s", identity.c_str());
-
yaml::Node cwId = systemConf["cwId"];
- bool cwEnabled = cwId["enable"].as(false);
- uint32_t cwTime = cwId["time"].as(10U);
- std::string callsign = cwId["callsign"].as();
-
- LogInfo("CW Id Parameters");
- LogInfo(" Enabled: %s", cwEnabled ? "enabled" : "disabled");
- LogInfo(" Time: %u mins", cwTime);
- LogInfo(" Callsign: %s", callsign.c_str());
yaml::Node rfssConfig = systemConf["config"];
m_channelId = (uint8_t)rfssConfig["channelId"].as(0U);
@@ -150,12 +140,6 @@ int HostSetup::run()
return false;
}
- LogInfo("System Config Parameters");
- LogInfo(" RX Frequency: %uHz", m_rxFrequency);
- LogInfo(" TX Frequency: %uHz", m_txFrequency);
- LogInfo(" Base Frequency: %uHz", entry.baseFrequency());
- LogInfo(" TX Offset: %fMHz", entry.txOffsetMhz());
-
// open terminal console
ret = m_console.open();
if (!ret) {
@@ -172,37 +156,75 @@ int HostSetup::run()
switch (c) {
/** Setup Commands */
+ case 'M':
+ {
+ modemConfig = m_conf["system"]["modem"];
+ m_conf["system"]["modem"]["protocol"]["type"] = std::string("uart"); // configuring modem, always sets type to UART
+
+ yaml::Node uartConfig = modemConfig["protocol"]["uart"];
+
+ std::string modemPort = uartConfig["port"].as("/dev/ttyUSB0");
+ uint32_t portSpeed = uartConfig["speed"].as(115200);
+
+ char value[21] = { '\0' };
+ ::fprintf(stdout, "> Modem UART Port [%s] ? ", modemPort.c_str());
+ ::fflush(stdout);
+
+ m_console.getLine(value, 21, 0);
+ if (value[0] != '\0') {
+ modemPort = std::string(value);
+ m_conf["system"]["modem"]["protocol"]["uart"]["port"] = modemPort;
+ }
+
+ ::fprintf(stdout, "> Port Speed [%u] ? ", portSpeed);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 7, 0);
+ if (value[0] != '\0') {
+ sscanf(value, "%u", &portSpeed);
+ m_conf["system"]["modem"]["protocol"]["uart"]["speed"] = __INT_STR(portSpeed);
+ }
+
+ printStatus();
+ }
+ break;
+
case 'I':
{
+ std::string identity = m_conf["system"]["identity"].as();
+
char value[9] = { '\0' };
- ::fprintf(stdout, "> Identity ? ");
+ ::fprintf(stdout, "> Identity [%s] ? ", identity.c_str());
::fflush(stdout);
m_console.getLine(value, 9, 0);
- std::string identity = std::string(value);
+ identity = std::string(value);
if (identity.length() > 0) {
m_conf["system"]["identity"] = identity;
}
- writeConfig();
+ printStatus();
}
break;
case 'C':
{
+ cwId = m_conf["system"]["cwId"];
bool enabled = cwId["enable"].as(false);
+ uint32_t cwTime = cwId["time"].as(10U);
+ std::string callsign = cwId["callsign"].as();
char value[9] = { '\0' };
- ::fprintf(stdout, "> Callsign ? ");
+ ::fprintf(stdout, "> Callsign [%s] ? ", callsign.c_str());
::fflush(stdout);
m_console.getLine(value, 9, 0);
- std::string callsign = std::string(value);
+ callsign = std::string(value);
if (callsign.length() > 0) {
m_conf["system"]["cwId"]["callsign"] = callsign;
}
- ::fprintf(stdout, "> CW Enabled (Y/N) ? ");
+ ::fprintf(stdout, "> CW Enabled [%u] (Y/N) ? ", enabled);
::fflush(stdout);
m_console.getLine(value, 2, 0);
@@ -212,7 +234,7 @@ int HostSetup::run()
m_conf["system"]["cwId"]["enable"] = __BOOL_STR(enabled);
- ::fprintf(stdout, "> CW Interval (minutes) ? ");
+ ::fprintf(stdout, "> CW Interval [%u] (minutes) ? ", cwTime);
::fflush(stdout);
m_console.getLine(value, 4, 0);
@@ -222,98 +244,224 @@ int HostSetup::run()
m_conf["system"]["cwId"]["time"] = __INT_STR(time);
}
- writeConfig();
+ printStatus();
+ }
+ break;
+
+ case 'N':
+ {
+ rfssConfig = m_conf["system"]["config"];
+ uint32_t siteId = (uint8_t)::strtoul(rfssConfig["siteId"].as("1").c_str(), NULL, 16);
+ uint32_t dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as("1").c_str(), NULL, 16);
+ uint32_t p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as("BB800").c_str(), NULL, 16);
+ uint32_t p25SysId = (uint32_t)::strtoul(rfssConfig["sysId"].as("001").c_str(), NULL, 16);
+ uint32_t p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as("1").c_str(), NULL, 16);
+
+ char value[6] = { '\0' };
+ ::fprintf(stdout, "> Site ID [$%02X] ? ", siteId);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 3, 0);
+ if (value[0] != '\0') {
+ siteId = (uint32_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ siteId = p25::P25Utils::siteId(siteId);
+
+ m_conf["system"]["config"]["siteId"] = __INT_HEX_STR(siteId);
+ }
+
+ ::fprintf(stdout, "> DMR Network ID [$%05X] ? ", dmrNetId);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 6, 0);
+ if (value[0] != '\0') {
+ dmrNetId = (uint32_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ dmrNetId = dmr::DMRUtils::netId(dmrNetId, dmr::SITE_MODEL_TINY);
+
+ m_conf["system"]["config"]["dmrNetId"] = __INT_HEX_STR(dmrNetId);
+ }
+
+ ::fprintf(stdout, "> P25 Network ID [$%05X] ? ", p25NetId);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 6, 0);
+ if (value[0] != '\0') {
+ p25NetId = (uint32_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ p25NetId = p25::P25Utils::netId(p25NetId);
+
+ m_conf["system"]["config"]["netId"] = __INT_HEX_STR(p25NetId);
+ }
+
+ ::fprintf(stdout, "> P25 System ID [$%03X] ? ", p25SysId);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 4, 0);
+ if (value[0] != '\0') {
+ p25SysId = (uint32_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ p25SysId = p25::P25Utils::sysId(p25SysId);
+
+ m_conf["system"]["config"]["sysId"] = __INT_HEX_STR(p25SysId);
+ }
+
+ ::fprintf(stdout, "> P25 RFSS ID [$%02X] ? ", p25RfssId);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 3, 0);
+ if (value[0] != '\0') {
+ p25RfssId = (uint8_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ p25RfssId = p25::P25Utils::rfssId(p25RfssId);
+
+ m_conf["system"]["config"]["rfssId"] = __INT_HEX_STR(p25RfssId);
+ }
+
+ printStatus();
+ }
+ break;
+
+ case 'a':
+ {
+ rfssConfig = m_conf["system"]["config"];
+ uint32_t dmrColorCode = rfssConfig["colorCode"].as(2U);
+ uint32_t p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as("293").c_str(), NULL, 16);
+
+ char value[6] = { '\0' };
+ ::fprintf(stdout, "> DMR Color Code [%u] ? ", dmrColorCode);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 2, 0);
+ if (value[0] != '\0') {
+ sscanf(value, "%u", &dmrColorCode);
+ dmrColorCode = dmr::DMRUtils::colorCode(dmrColorCode);
+
+ m_conf["system"]["config"]["colorCode"] = __INT_STR(dmrColorCode);
+ }
+
+ ::fprintf(stdout, "> P25 NAC [$%03X] ? ", p25NAC);
+ ::fflush(stdout);
+
+ m_console.getLine(value, 4, 0);
+ if (value[0] != '\0') {
+ p25NAC = (uint32_t)::strtoul(std::string(value).c_str(), NULL, 16);
+ p25NAC = p25::P25Utils::nac(p25NAC);
+
+ m_conf["system"]["config"]["nac"] = __INT_HEX_STR(p25NAC);
+ }
+
+ printStatus();
}
break;
case 'i':
{
+ rfssConfig = m_conf["system"]["config"];
+ m_channelId = (uint8_t)rfssConfig["channelId"].as(0U);
+
char value[3] = { '\0' };
- ::fprintf(stdout, "> Channel ID ? ");
+ ::fprintf(stdout, "> Channel ID [%u] ? ", m_channelId);
::fflush(stdout);
m_console.getLine(value, 3, 0);
+ if (value[0] != '\0') {
+ uint8_t prevChannelId = m_channelId;
- uint8_t prevChannelId = m_channelId;
+ // bryanb: appease the compiler...
+ uint32_t channelId = m_channelId;
+ sscanf(value, "%u", &channelId);
- // bryanb: appease the compiler...
- uint32_t channelId = m_channelId;
- sscanf(value, "%u", &channelId);
+ m_channelId = (uint8_t)channelId;
- m_channelId = (uint8_t)channelId;
+ IdenTable entry = m_idenTable->find(m_channelId);
+ if (entry.baseFrequency() == 0U) {
+ ::LogError(LOG_SETUP, "Channel Id %u has an invalid base frequency.", m_channelId);
+ m_channelId = prevChannelId;
+ }
- IdenTable entry = m_idenTable->find(m_channelId);
- if (entry.baseFrequency() == 0U) {
- ::LogError(LOG_SETUP, "Channel Id %u has an invalid base frequency.", m_channelId);
- m_channelId = prevChannelId;
+ m_conf["system"]["config"]["channelId"] = __INT_STR(m_channelId);
}
- writeConfig();
+ printStatus();
}
break;
case 'c':
{
+ rfssConfig = m_conf["system"]["config"];
+ m_channelNo = (uint32_t)::strtoul(rfssConfig["channelNo"].as("1").c_str(), NULL, 16);
+
char value[5] = { '\0' };
- ::fprintf(stdout, "> Channel No ? ");
+ ::fprintf(stdout, "> Channel No [%u] ? ", m_channelNo);
::fflush(stdout);
m_console.getLine(value, 5, 0);
+ if (value[0] != '\0') {
+ uint8_t prevChannelNo = m_channelNo;
+ sscanf(value, "%u", &m_channelNo);
- uint8_t prevChannelNo = m_channelNo;
- sscanf(value, "%u", &m_channelNo);
+ if (m_channelNo < 0 || m_channelNo > 4096) {
+ ::LogError(LOG_SETUP, "Channel No %u is invalid.", m_channelNo);
+ m_channelNo = prevChannelNo;
+ }
- if (m_channelNo < 0 || m_channelNo > 4096) {
- ::LogError(LOG_SETUP, "Channel No %u is invalid.", m_channelNo);
- m_channelNo = prevChannelNo;
+ m_conf["system"]["config"]["channelNo"] = __INT_HEX_STR(m_channelNo);
}
- writeConfig();
+ printStatus();
}
break;
case 'f':
{
+ rfssConfig = m_conf["system"]["config"];
+ m_channelNo = (uint32_t)::strtoul(rfssConfig["channelNo"].as("1").c_str(), NULL, 16);
+
char value[10] = { '\0' };
- ::fprintf(stdout, "> Tx Frequency (Hz) ? ");
+ ::fprintf(stdout, "> Tx Frequency [%uHz] (Hz) ? ", m_txFrequency);
::fflush(stdout);
m_console.getLine(value, 10, 0);
-
- uint32_t txFrequency = m_txFrequency;
- sscanf(value, "%u", &txFrequency);
-
- IdenTable entry = m_idenTable->find(m_channelId);
- if (txFrequency < entry.baseFrequency()) {
- ::LogError(LOG_SETUP, "Tx Frequency %uHz is out of band range for base frequency %uHz. Tx Frequency must be greater then base frequency!", txFrequency, entry.baseFrequency());
- break;
- }
-
- if (txFrequency > entry.baseFrequency() + 25500000) {
- ::LogError(LOG_SETUP, "Tx Frequency %uHz is out of band range for base frequency %uHz. Tx Frequency must be no more then 25.5 Mhz higher then base frequency!", txFrequency, entry.baseFrequency());
- break;
+ if (value[0] != '\0') {
+ uint32_t txFrequency = m_txFrequency;
+ sscanf(value, "%u", &txFrequency);
+
+ IdenTable entry = m_idenTable->find(m_channelId);
+ if (txFrequency < entry.baseFrequency()) {
+ ::LogError(LOG_SETUP, "Tx Frequency %uHz is out of band range for base frequency %uHz. Tx Frequency must be greater then base frequency!", txFrequency, entry.baseFrequency());
+ break;
+ }
+
+ if (txFrequency > entry.baseFrequency() + 25500000) {
+ ::LogError(LOG_SETUP, "Tx Frequency %uHz is out of band range for base frequency %uHz. Tx Frequency must be no more then 25.5 Mhz higher then base frequency!", txFrequency, entry.baseFrequency());
+ break;
+ }
+
+ uint32_t prevTxFrequency = m_txFrequency;
+ m_txFrequency = txFrequency;
+ uint32_t prevRxFrequency = m_rxFrequency;
+ m_rxFrequency = m_txFrequency + (uint32_t)(entry.txOffsetMhz() * 1000000);
+
+ float spaceHz = entry.chSpaceKhz() * 1000;
+
+ uint32_t rootFreq = m_txFrequency - entry.baseFrequency();
+ uint8_t prevChannelNo = m_channelNo;
+ m_channelNo = (uint32_t)(rootFreq / spaceHz);
+
+ if (m_channelNo < 0 || m_channelNo > 4096) {
+ ::LogError(LOG_SETUP, "Channel No %u is invalid.", m_channelNo);
+ m_channelNo = prevChannelNo;
+ m_txFrequency = prevTxFrequency;
+ m_rxFrequency = prevRxFrequency;
+ break;
+ }
}
- uint32_t prevTxFrequency = m_txFrequency;
- m_txFrequency = txFrequency;
- uint32_t prevRxFrequency = m_rxFrequency;
- m_rxFrequency = m_txFrequency + (uint32_t)(entry.txOffsetMhz() * 1000000);
-
- float spaceHz = entry.chSpaceKhz() * 1000;
-
- uint32_t rootFreq = m_txFrequency - entry.baseFrequency();
- uint8_t prevChannelNo = m_channelNo;
- m_channelNo = (uint32_t)(rootFreq / spaceHz);
-
- if (m_channelNo < 0 || m_channelNo > 4096) {
- ::LogError(LOG_SETUP, "Channel No %u is invalid.", m_channelNo);
- m_channelNo = prevChannelNo;
- m_txFrequency = prevTxFrequency;
- m_rxFrequency = prevRxFrequency;
- break;
- }
+ printStatus();
+ }
+ break;
- writeConfig();
+ case '!':
+ {
+ modemConfig = m_conf["system"]["modem"];
+ m_conf["system"]["modem"]["protocol"]["type"] = std::string("null"); // configuring modem, always sets type to UART
+ printStatus();
}
break;
@@ -369,11 +517,15 @@ void HostSetup::displayHelp()
LogMessage(LOG_SETUP, " ` Display current settings");
LogMessage(LOG_SETUP, " V Display version of host");
LogMessage(LOG_SETUP, " H/h Display help");
+ LogMessage(LOG_SETUP, " ! Set \"null\" modem (disables modem communication)");
LogMessage(LOG_SETUP, " S/s Save settings to configuration file");
LogMessage(LOG_SETUP, " Q/q Quit");
LogMessage(LOG_SETUP, "Setup Commands:");
+ LogMessage(LOG_SETUP, " M Set modem port and speed");
LogMessage(LOG_SETUP, " I Set identity (logical name)");
LogMessage(LOG_SETUP, " C Set callsign and CW configuration");
+ LogMessage(LOG_SETUP, " N Set site and network configuration");
+ LogMessage(LOG_SETUP, " a Set NAC and Color Code");
LogMessage(LOG_SETUP, " i Set logical channel ID");
LogMessage(LOG_SETUP, " c Set logical channel number (by channel number)");
LogMessage(LOG_SETUP, " f Set logical channel number (by Tx frequency)");
@@ -419,19 +571,6 @@ bool HostSetup::calculateRxTxFreq()
return true;
}
-///
-/// Write configuration file.
-///
-/// True, if configuration is written, otherwise false.
-bool HostSetup::writeConfig()
-{
- m_conf["system"]["config"]["channelId"] = __INT_STR(m_channelId);
- m_conf["system"]["config"]["channelNo"] = __INT_STR(m_channelNo);
-
- printStatus();
- return true;
-}
-
///
/// Helper to sleep the thread.
///
@@ -451,20 +590,33 @@ void HostSetup::sleep(uint32_t ms)
void HostSetup::printStatus()
{
yaml::Node systemConf = m_conf["system"];
- std::string identity = systemConf["identity"].as();
+ {
+ yaml::Node modemConfig = m_conf["system"]["modem"];
+ std::string type = modemConfig["protocol"]["type"].as();
- IdenTable entry = m_idenTable->find(m_channelId);
- if (entry.baseFrequency() == 0U) {
- ::LogError(LOG_HOST, "Channel Id %u has an invalid base frequency.", m_channelId);
+ yaml::Node uartConfig = modemConfig["protocol"]["uart"];
+ std::string modemPort = uartConfig["port"].as();
+ uint32_t portSpeed = uartConfig["speed"].as(115200U);
+
+ LogMessage(LOG_SETUP, " - Port Type: %s, Modem Port: %s, Port Speed: %u", type.c_str(), modemPort.c_str(), portSpeed);
}
- calculateRxTxFreq();
+ {
+ std::string identity = systemConf["identity"].as();
+
+ IdenTable entry = m_idenTable->find(m_channelId);
+ if (entry.baseFrequency() == 0U) {
+ ::LogError(LOG_HOST, "Channel Id %u has an invalid base frequency.", m_channelId);
+ }
+
+ calculateRxTxFreq();
+
+ LogMessage(LOG_SETUP, " - Identity: %s", identity.c_str());
+ LogMessage(LOG_SETUP, " - Channel Id: %u, Channel No: %u", m_channelId, m_channelNo);
+ LogMessage(LOG_SETUP, " - Base Freq: %uHz, TX Offset: %fMHz, Bandwidth: %fKHz, Channel Spacing: %fKHz", entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz());
+ LogMessage(LOG_SETUP, " - Rx Freq: %uHz, Tx Freq: %uHz", m_rxFrequency, m_txFrequency);
+ }
- LogMessage(LOG_SETUP, " - Identity: %s", identity.c_str());
- LogMessage(LOG_SETUP, " - Channel ID: %u, Channel No: %u", m_channelId, m_channelNo);
- LogMessage(LOG_SETUP, " - Base Freq: %uHz, TX Offset: %fMHz, Bandwidth: %fKHz, Channel Spacing: %fKHz", entry.baseFrequency(), entry.txOffsetMhz(), entry.chBandwidthKhz(), entry.chSpaceKhz());
- LogMessage(LOG_SETUP, " - Rx Freq: %uHz, Tx Freq: %uHz", m_rxFrequency, m_txFrequency);
-
{
yaml::Node cwId = systemConf["cwId"];
bool enabled = cwId["enable"].as(false);
@@ -473,4 +625,23 @@ void HostSetup::printStatus()
LogMessage(LOG_SETUP, " - Callsign: %s, CW Interval: %u mins, CW Enabled: %u", callsign.c_str(), cwTime, enabled);
}
+
+ {
+ yaml::Node rfssConfig = systemConf["config"];
+ uint32_t dmrColorCode = rfssConfig["colorCode"].as(2U);
+ uint32_t p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as("293").c_str(), NULL, 16);
+
+ LogMessage(LOG_SETUP, " - DMR Color Code: %u, P25 NAC: $%03X", dmrColorCode, p25NAC);
+ }
+
+ {
+ yaml::Node rfssConfig = systemConf["config"];
+ uint32_t siteId = (uint8_t)::strtoul(rfssConfig["siteId"].as("1").c_str(), NULL, 16);
+ uint32_t dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as("1").c_str(), NULL, 16);
+ uint32_t p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as("BB800").c_str(), NULL, 16);
+ uint32_t p25SysId = (uint32_t)::strtoul(rfssConfig["sysId"].as("001").c_str(), NULL, 16);
+ uint32_t p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as("1").c_str(), NULL, 16);
+
+ LogMessage(LOG_SETUP, " - Site Id: $%02X, DMR Network Id: $%05X, P25 Network Id: $%05X, P25 System Id: $%03X, P25 RFSS Id: $%02X", siteId, dmrNetId, p25NetId, p25SysId, p25RfssId);
+ }
}
diff --git a/host/setup/HostSetup.h b/host/setup/HostSetup.h
index d20f57af..943a97d5 100644
--- a/host/setup/HostSetup.h
+++ b/host/setup/HostSetup.h
@@ -74,8 +74,6 @@ private:
/// Helper to calculate the Rx/Tx frequencies.
bool calculateRxTxFreq();
- /// Write configuration file.
- bool writeConfig();
/// Helper to sleep the thread.
void sleep(uint32_t ms);
diff --git a/p25/P25Utils.h b/p25/P25Utils.h
index e127c03d..d93a1319 100644
--- a/p25/P25Utils.h
+++ b/p25/P25Utils.h
@@ -12,6 +12,7 @@
//
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
+* Copyright (C) 2021 by Bryan Biedenkapp N2PLL
*
* 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
@@ -36,12 +37,77 @@ namespace p25
{
// ---------------------------------------------------------------------------
// Class Declaration
- // This class implements various helper functions for interleaving P25
- // data.
+ // This class implements various helper functions for validating and
+ // for interleaving P25 data.
// ---------------------------------------------------------------------------
class HOST_SW_API P25Utils {
public:
+ /// Helper to test and clamp a P25 NAC.
+ static uint32_t nac(uint32_t nac)
+ {
+ if (nac < 0U) { // clamp to $000
+ nac = 0U;
+ }
+ if (nac > 0xF7DU) { // clamp to $F7D
+ nac = 0xF7DU;
+ }
+
+ return nac;
+ }
+
+ /// Helper to test and clamp a P25 site ID.
+ static uint8_t siteId(uint8_t id)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+ if (id > 0xFEU) { // clamp to $FE
+ id = 0xFEU;
+ }
+
+ return id;
+ }
+
+ /// Helper to test and clamp a P25 network ID.
+ static uint32_t netId(uint32_t id)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+ if (id > 0xFFFFEU) { // clamp to $FFFFE
+ id = 0xFFFFEU;
+ }
+
+ return id;
+ }
+
+ /// Helper to test and clamp a P25 system ID.
+ static uint32_t sysId(uint32_t id)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+ if (id > 0xFFEU) { // clamp to $FFE
+ id = 0xFFEU;
+ }
+
+ return id;
+ }
+
+ /// Helper to test and clamp a P25 RFSS ID.
+ static uint8_t rfssId(uint8_t id)
+ {
+ if (id == 0U) { // clamp to 1
+ id = 1U;
+ }
+ if (id > 0xFEU) { // clamp to $FE
+ id = 0xFEU;
+ }
+
+ return id;
+ }
+
/// Decode bit interleaving.
static uint32_t decode(const uint8_t* in, uint8_t* out, uint32_t start, uint32_t stop);
/// Encode bit interleaving.
diff --git a/p25/SiteData.h b/p25/SiteData.h
index 3d9d413b..16d8102e 100644
--- a/p25/SiteData.h
+++ b/p25/SiteData.h
@@ -32,6 +32,7 @@
#include "Defines.h"
#include "p25/P25Defines.h"
+#include "p25/P25Utils.h"
namespace p25
{
@@ -87,38 +88,28 @@ namespace p25
lra = 0xFFU;
// netId clamping
- if (netId == 0U) // clamp to 1
- netId = 1U;
- if (netId > 0xFFFFEU) // clamp to $FFFFE
- netId = 0xFFFFEU;
+ netId = P25Utils::netId(netId);
// sysId clamping
- if (sysId == 0U) // clamp to 1
- sysId = 1U;
- if (sysId > 0xFFEU) // clamp to $FFE
- sysId = 0xFFEU;
+ sysId = P25Utils::sysId(sysId);
// rfssId clamping
- if (rfssId == 0U) // clamp to 1
- rfssId = 1U;
- if (rfssId > 0xFEU) // clamp to $FE
- rfssId = 0xFEU;
+ rfssId = P25Utils::rfssId(rfssId);
// siteId clamping
- if (siteId == 0U) // clamp to 1
- siteId = 1U;
- if (siteId > 0xFEU) // clamp to $FE
- siteId = 0xFEU;
+ siteId = P25Utils::siteId(siteId);
// channel id clamping
if (channelId > 15U)
channelId = 15U;
// channel number clamping
- if (channelNo == 0U) // clamp to 1
- channelNo = 1U;
- if (channelNo > 4095U) // clamp to 4096
- channelNo = 4095U;
+ if (m_channelNo == 0U) { // clamp to 1
+ m_channelNo = 1U;
+ }
+ if (m_channelNo > 4095U) { // clamp to 4095
+ m_channelNo = 4095U;
+ }
m_lra = lra;
@@ -165,32 +156,25 @@ namespace p25
void setAdjSite(uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, uint8_t serviceClass)
{
// sysId clamping
- if (sysId == 0U) // clamp to 1
- sysId = 1U;
- if (sysId > 0xFFEU) // clamp to $FFE
- sysId = 0xFFEU;
+ sysId = P25Utils::sysId(sysId);
// rfssId clamping
- if (rfssId == 0U) // clamp to 1
- rfssId = 1U;
- if (rfssId > 0xFEU) // clamp to $FE
- rfssId = 0xFEU;
+ rfssId = P25Utils::rfssId(rfssId);
// siteId clamping
- if (siteId == 0U) // clamp to 1
- siteId = 1U;
- if (siteId > 0xFEU) // clamp to $FE
- siteId = 0xFEU;
+ siteId = P25Utils::siteId(siteId);
// channel id clamping
if (channelId > 15U)
channelId = 15U;
// channel number clamping
- if (channelNo == 0U) // clamp to 1
- channelNo = 1U;
- if (channelNo > 4095U) // clamp to 4096
- channelNo = 4095U;
+ if (m_channelNo == 0U) { // clamp to 1
+ m_channelNo = 1U;
+ }
+ if (m_channelNo > 4095U) { // clamp to 4095
+ m_channelNo = 4095U;
+ }
m_lra = 0U;