fix incorrect handling of channel number as decimal in setup; enhance setup to make it more comprehensive (essentially all "system" configuration parameters can be modified in setup mode); add support to calibration to set the FDMA preambles, P25 correlation count, DMR Rx Delay as well as setting the Rx and Tx frequency offsets;

pull/12/head
Bryan Biedenkapp 4 years ago
parent 43f8f6e8ae
commit 08dd49d51f

@ -163,6 +163,7 @@
<ClInclude Include="dmr\Control.h" />
<ClInclude Include="dmr\DataPacket.h" />
<ClInclude Include="dmr\DMRDefines.h" />
<ClInclude Include="dmr\DMRUtils.h" />
<ClInclude Include="dmr\lc\PrivacyLC.h" />
<ClInclude Include="dmr\SiteData.h" />
<ClInclude Include="dmr\Slot.h" />

@ -362,6 +362,9 @@
<ClInclude Include="host\setup\HostSetup.h">
<Filter>Header Files\host\setup</Filter>
</ClInclude>
<ClInclude Include="dmr\DMRUtils.h">
<Filter>Header Files\dmr</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Log.cpp">

@ -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;

@ -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:
/// <summary>Helper to test and clamp a DMR color code.</summary>
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;
}
/// <summary>Helper to test and clamp a DMR site ID.</summary>
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;
}
/// <summary>Helper to test and clamp a DMR network ID.</summary>
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__

@ -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)

@ -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<std::string>("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<uint32_t>(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<std::string>("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<std::string>("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<std::string>("FFFF").c_str(), NULL, 16);
m_p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as<std::string>("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<std::string>("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<std::string>("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);

@ -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<int>(0);
m_txTuning = modemConf["txTuning"].as<int>(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<std::string>("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()
/// </summary>
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<std::string>();
yaml::Node uartConfig = modemConfig["protocol"]["uart"];
std::string modemPort = uartConfig["port"].as<std::string>();
uint32_t portSpeed = uartConfig["speed"].as<uint32_t>(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];

@ -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;

@ -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<bool>(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<std::string>();
::LogInfo(" Identity: %s", identity.c_str());
yaml::Node cwId = systemConf["cwId"];
bool cwEnabled = cwId["enable"].as<bool>(false);
uint32_t cwTime = cwId["time"].as<uint32_t>(10U);
std::string callsign = cwId["callsign"].as<std::string>();
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<uint32_t>(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<std::string>("/dev/ttyUSB0");
uint32_t portSpeed = uartConfig["speed"].as<uint32_t>(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<std::string>();
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<bool>(false);
uint32_t cwTime = cwId["time"].as<uint32_t>(10U);
std::string callsign = cwId["callsign"].as<std::string>();
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<std::string>("1").c_str(), NULL, 16);
uint32_t dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as<std::string>("1").c_str(), NULL, 16);
uint32_t p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as<std::string>("BB800").c_str(), NULL, 16);
uint32_t p25SysId = (uint32_t)::strtoul(rfssConfig["sysId"].as<std::string>("001").c_str(), NULL, 16);
uint32_t p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as<std::string>("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<uint32_t>(2U);
uint32_t p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as<std::string>("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<uint32_t>(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<std::string>("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<std::string>("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;
}
/// <summary>
/// Write configuration file.
/// </summary>
/// <returns>True, if configuration is written, otherwise false.</returns>
bool HostSetup::writeConfig()
{
m_conf["system"]["config"]["channelId"] = __INT_STR(m_channelId);
m_conf["system"]["config"]["channelNo"] = __INT_STR(m_channelNo);
printStatus();
return true;
}
/// <summary>
/// Helper to sleep the thread.
/// </summary>
@ -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<std::string>();
{
yaml::Node modemConfig = m_conf["system"]["modem"];
std::string type = modemConfig["protocol"]["type"].as<std::string>();
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<std::string>();
uint32_t portSpeed = uartConfig["speed"].as<uint32_t>(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<std::string>();
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<bool>(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<uint32_t>(2U);
uint32_t p25NAC = (uint32_t)::strtoul(rfssConfig["nac"].as<std::string>("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<std::string>("1").c_str(), NULL, 16);
uint32_t dmrNetId = (uint32_t)::strtoul(rfssConfig["dmrNetId"].as<std::string>("1").c_str(), NULL, 16);
uint32_t p25NetId = (uint32_t)::strtoul(rfssConfig["netId"].as<std::string>("BB800").c_str(), NULL, 16);
uint32_t p25SysId = (uint32_t)::strtoul(rfssConfig["sysId"].as<std::string>("001").c_str(), NULL, 16);
uint32_t p25RfssId = (uint8_t)::strtoul(rfssConfig["rfssId"].as<std::string>("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);
}
}

@ -74,8 +74,6 @@ private:
/// <summary>Helper to calculate the Rx/Tx frequencies.</summary>
bool calculateRxTxFreq();
/// <summary>Write configuration file.</summary>
bool writeConfig();
/// <summary>Helper to sleep the thread.</summary>
void sleep(uint32_t ms);

@ -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:
/// <summary>Helper to test and clamp a P25 NAC.</summary>
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;
}
/// <summary>Helper to test and clamp a P25 site ID.</summary>
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;
}
/// <summary>Helper to test and clamp a P25 network ID.</summary>
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;
}
/// <summary>Helper to test and clamp a P25 system ID.</summary>
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;
}
/// <summary>Helper to test and clamp a P25 RFSS ID.</summary>
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;
}
/// <summary>Decode bit interleaving.</summary>
static uint32_t decode(const uint8_t* in, uint8_t* out, uint32_t start, uint32_t stop);
/// <summary>Encode bit interleaving.</summary>

@ -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;

Loading…
Cancel
Save

Powered by TurnKey Linux.