mirror of
https://github.com/g4klx/MMDVMHost.git
synced 2026-04-21 06:13:49 +00:00
DMR trunking patches
This commit is contained in:
parent
b5b119fa8e
commit
4ff3bbf766
16 changed files with 696 additions and 55 deletions
341
DMRSlot.cpp
341
DMRSlot.cpp
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021,2023,2025 Jonathan Naylor, G4KLX
|
||||
* Copyright (C) 2026 Adrian Musceac, YO8RZZ
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,7 +21,6 @@
|
|||
#include "BPTC19696.h"
|
||||
#include "DMRSlot.h"
|
||||
#include "DMRCSBK.h"
|
||||
#include "DMREMB.h"
|
||||
#include "Utils.h"
|
||||
#include "Sync.h"
|
||||
#include "CRC.h"
|
||||
|
|
@ -71,6 +71,14 @@ const unsigned int NO_HEADERS_SIMPLEX = 8U;
|
|||
const unsigned int NO_HEADERS_DUPLEX = 3U;
|
||||
const unsigned int NO_PREAMBLE_CSBK = 15U;
|
||||
|
||||
|
||||
const unsigned int RC_CEASE_TRANSMIT[5] = {0x07, 0x0D, 0x04, 0xF1, 0xF0};
|
||||
const unsigned int RC_REQUEST_CEASE_TRANSMIT[5] = {0x02, 0x7B, 0x4E, 0x48, 0x70 };
|
||||
const unsigned int RC_MAX_POWER[5] = {0x01, 0xC3, 0xDD, 0x3C, 0x10 };
|
||||
const unsigned int RC_MIN_POWER[5] = {0x04, 0xB5, 0x97, 0x85, 0x90 };
|
||||
const unsigned int RC_POWER_INCREASE[5] = {0x04, 0x5B, 0xA7, 0x58, 0xA0 };
|
||||
const unsigned int RC_POWER_DECREASE[5] = {0x01, 0x2D, 0xED, 0xE1, 0x20 };
|
||||
|
||||
const unsigned int RSSI_COUNT = 3U; // 3 * 360ms = 1080ms
|
||||
const unsigned int BER_COUNT = 18U * 141U; // 18 * 60ms = 1080ms
|
||||
|
||||
|
|
@ -124,7 +132,8 @@ m_rssiAccum(0),
|
|||
m_rssiCount(0U),
|
||||
m_bitErrsAccum(0U),
|
||||
m_bitsCount(0U),
|
||||
m_enabled(true)
|
||||
m_enabled(true),
|
||||
m_reverseChannelCommand(0)
|
||||
{
|
||||
m_lastFrame = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
|
|
@ -227,6 +236,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (dataType == DT_VOICE_LC_HEADER) {
|
||||
if (m_rfState == RPT_RF_STATE::AUDIO)
|
||||
return true;
|
||||
m_reverseChannelCommand = DMRCommand::RCNoCommand;
|
||||
|
||||
CDMRFullLC fullLC;
|
||||
CDMRLC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER);
|
||||
|
|
@ -363,7 +373,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
} else if (dataType == DT_TERMINATOR_WITH_LC) {
|
||||
if (m_rfState != RPT_RF_STATE::AUDIO)
|
||||
return false;
|
||||
|
||||
m_reverseChannelCommand = DMRCommand::RCNoCommand;
|
||||
// Regenerate the LC data
|
||||
CDMRFullLC fullLC;
|
||||
fullLC.encode(*m_rfLC, data + 2U, DT_TERMINATOR_WITH_LC);
|
||||
|
|
@ -381,7 +391,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
for (unsigned int i = 0U; i <= m_hangCount; i++)
|
||||
writeQueueRF(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -485,10 +495,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
return false;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if ((m_ovcm == DMR_OVCM::TX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
if(!m_modem->getDMRTrunking())
|
||||
{
|
||||
if ((m_ovcm == DMR_OVCM::TX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
}
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
|
|
@ -524,7 +537,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
if (m_duplex)
|
||||
if (m_duplex && !m_modem->getDMRTrunking())
|
||||
writeQueueRF(data);
|
||||
|
||||
writeNetworkRF(data, DT_CSBK, gi ? FLCO::GROUP : FLCO::USER_USER, srcId, dstId);
|
||||
|
|
@ -563,7 +576,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
writeJSONRF("csbk", "Call Emergency", srcId, src, gi, dstId);
|
||||
break;
|
||||
default:
|
||||
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
LogMessage("DMR Slot %u, received unhandled CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -848,7 +861,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
emb.setLCSS(lcss);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
|
||||
createReverseChannel(data, emb);
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
|
||||
|
|
@ -1051,7 +1064,7 @@ void CDMRSlot::writeEndRF(bool writeEnd)
|
|||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
for (unsigned int i = 0U; i <= m_hangCount; i++)
|
||||
writeQueueRF(data);
|
||||
}
|
||||
}
|
||||
|
|
@ -1099,7 +1112,7 @@ void CDMRSlot::writeEndNet(bool writeEnd)
|
|||
data[1U] = 0x00U;
|
||||
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
for (unsigned int i = 0U; i <= m_hangCount; i++)
|
||||
writeQueueNet(data);
|
||||
} else {
|
||||
for (unsigned int i = 0U; i < 3U; i++)
|
||||
|
|
@ -1129,7 +1142,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
if ((m_rfState != RPT_RF_STATE::LISTENING) && (m_netState == RPT_NET_STATE::IDLE))
|
||||
if ((m_rfState != RPT_RF_STATE::LISTENING) && (m_netState == RPT_NET_STATE::IDLE) && !m_modem->getDMRTrunking())
|
||||
return;
|
||||
|
||||
m_networkWatchdog.start();
|
||||
|
|
@ -1335,7 +1348,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
data[1U] = 0x00U;
|
||||
|
||||
if (m_duplex) {
|
||||
for (unsigned int i = 0U; i < m_hangCount; i++)
|
||||
for (unsigned int i = 0U; i <= m_hangCount; i++)
|
||||
writeQueueNet(data);
|
||||
} else {
|
||||
for (unsigned int i = 0U; i < 3U; i++)
|
||||
|
|
@ -1686,10 +1699,13 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
return;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
if(!m_modem->getDMRTrunking())
|
||||
{
|
||||
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
}
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
|
|
@ -1770,6 +1786,216 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
break;
|
||||
}
|
||||
|
||||
// If data preamble, signal its existence
|
||||
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent())
|
||||
setShortLC(m_slotNo, dstId, gi ? FLCO::GROUP : FLCO::USER_USER, ACTIVITY_TYPE::DATA);
|
||||
} else if (dataType == DT_MBC_HEADER) {
|
||||
CDMRCSBK csbk;
|
||||
csbk.setDataType(DT_MBC_HEADER);
|
||||
bool valid = csbk.put(data + 2U);
|
||||
if (!valid) {
|
||||
LogMessage("DMR Slot %u, unable to decode the network CSBK", m_slotNo);
|
||||
return;
|
||||
}
|
||||
|
||||
CSBKO csbko = csbk.getCSBKO();
|
||||
if (csbko == CSBKO::BSDWNACT)
|
||||
return;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if(!m_modem->getDMRTrunking())
|
||||
{
|
||||
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
}
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
unsigned int dstId = csbk.getDstId();
|
||||
|
||||
// Regenerate the CSBK data
|
||||
csbk.get(data + 2U);
|
||||
|
||||
// Regenerate the Slot Type
|
||||
CDMRSlotType slotType;
|
||||
slotType.setDataType(DT_MBC_HEADER);
|
||||
slotType.putData(data + 2U);
|
||||
slotType.setColorCode(m_colorCode);
|
||||
slotType.getData(data + 2U);
|
||||
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent()) {
|
||||
unsigned int cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U;
|
||||
for (unsigned int i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) {
|
||||
// Change blocks to follow
|
||||
csbk.setCBF(cbf);
|
||||
|
||||
// Regenerate the CSBK data
|
||||
csbk.get(data + 2U);
|
||||
|
||||
// Regenerate the Slot Type
|
||||
CDMRSlotType slotType;
|
||||
slotType.putData(data + 2U);
|
||||
slotType.setColorCode(m_colorCode);
|
||||
slotType.getData(data + 2U);
|
||||
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
writeQueueNet(data);
|
||||
}
|
||||
} else
|
||||
writeQueueNet(data);
|
||||
|
||||
std::string src = m_lookup->find(srcId);
|
||||
std::string dst = m_lookup->find(dstId);
|
||||
|
||||
switch (csbko) {
|
||||
case CSBKO::UUVREQ:
|
||||
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::UUANSRSP:
|
||||
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "Unit to Unit Voice Service Answer Response", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::NACKRSP:
|
||||
LogMessage("DMR Slot %u, received network Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "UNegative Acknowledgment Response", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::PRECCSBK:
|
||||
LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Preamble", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::CALL_ALERT:
|
||||
LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Call Alert", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::CALL_ALERT_ACK:
|
||||
LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Call Alert Ack", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::RADIO_CHECK:
|
||||
LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Radio Check", srcId, src, gi, dstId);
|
||||
break;
|
||||
default:
|
||||
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
break;
|
||||
}
|
||||
|
||||
// If data preamble, signal its existence
|
||||
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent())
|
||||
setShortLC(m_slotNo, dstId, gi ? FLCO::GROUP : FLCO::USER_USER, ACTIVITY_TYPE::DATA);
|
||||
} else if (dataType == DT_MBC_CONTINUATION) {
|
||||
CDMRCSBK csbk;
|
||||
csbk.setDataType(DT_MBC_CONTINUATION);
|
||||
bool valid = csbk.put(data + 2U);
|
||||
if (!valid) {
|
||||
LogMessage("DMR Slot %u, unable to decode the network CSBK", m_slotNo);
|
||||
return;
|
||||
}
|
||||
|
||||
CSBKO csbko = csbk.getCSBKO();
|
||||
if (csbko == CSBKO::BSDWNACT)
|
||||
return;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if(!m_modem->getDMRTrunking())
|
||||
{
|
||||
if ((m_ovcm == DMR_OVCM::RX_ON) || (m_ovcm == DMR_OVCM::ON))
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM::FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
}
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
unsigned int dstId = csbk.getDstId();
|
||||
|
||||
// Regenerate the CSBK data
|
||||
csbk.get(data + 2U);
|
||||
|
||||
// Regenerate the Slot Type
|
||||
CDMRSlotType slotType;
|
||||
slotType.setDataType(DT_MBC_CONTINUATION);
|
||||
slotType.putData(data + 2U);
|
||||
slotType.setColorCode(m_colorCode);
|
||||
slotType.getData(data + 2U);
|
||||
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent()) {
|
||||
unsigned int cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U;
|
||||
for (unsigned int i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) {
|
||||
// Change blocks to follow
|
||||
csbk.setCBF(cbf);
|
||||
|
||||
// Regenerate the CSBK data
|
||||
csbk.get(data + 2U);
|
||||
|
||||
// Regenerate the Slot Type
|
||||
CDMRSlotType slotType;
|
||||
slotType.putData(data + 2U);
|
||||
slotType.setColorCode(m_colorCode);
|
||||
slotType.getData(data + 2U);
|
||||
|
||||
// Convert the Data Sync to be from the BS or MS as needed
|
||||
CSync::addDMRDataSync(data + 2U, m_duplex);
|
||||
|
||||
writeQueueNet(data);
|
||||
}
|
||||
} else
|
||||
writeQueueNet(data);
|
||||
|
||||
std::string src = m_lookup->find(srcId);
|
||||
std::string dst = m_lookup->find(dstId);
|
||||
|
||||
switch (csbko) {
|
||||
case CSBKO::UUVREQ:
|
||||
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Request CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "Unit to Unit Voice Service Request", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::UUANSRSP:
|
||||
LogMessage("DMR Slot %u, received network Unit to Unit Voice Service Answer Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "Unit to Unit Voice Service Answer Response", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::NACKRSP:
|
||||
LogMessage("DMR Slot %u, received network Negative Acknowledgment Response CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
writeJSONNet("csbk", "UNegative Acknowledgment Response", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::PRECCSBK:
|
||||
LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Preamble", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::CALL_ALERT:
|
||||
LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Call Alert", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::CALL_ALERT_ACK:
|
||||
LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Call Alert Ack", srcId, src, gi, dstId);
|
||||
break;
|
||||
case CSBKO::RADIO_CHECK:
|
||||
LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
writeJSONNet("csbk", "Radio Check", srcId, src, gi, dstId);
|
||||
break;
|
||||
default:
|
||||
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
break;
|
||||
}
|
||||
|
||||
// If data preamble, signal its existence
|
||||
if ((csbko == CSBKO::PRECCSBK) && csbk.getDataContent())
|
||||
setShortLC(m_slotNo, dstId, gi ? FLCO::GROUP : FLCO::USER_USER, ACTIVITY_TYPE::DATA);
|
||||
|
|
@ -2136,7 +2362,7 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, ACTIV
|
|||
CDMRShortLC shortLC;
|
||||
shortLC.encode(lc, sLC);
|
||||
|
||||
m_modem->writeDMRShortLC(sLC);
|
||||
m_modem->writeDMRShortLC(sLC, false);
|
||||
}
|
||||
|
||||
bool CDMRSlot::insertSilence(const unsigned char* data, unsigned char seqNo)
|
||||
|
|
@ -2295,6 +2521,81 @@ void CDMRSlot::enable(bool enabled)
|
|||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void CDMRSlot::setReverseChannelCommand(unsigned int rc_command) {
|
||||
m_reverseChannelCommand = rc_command;
|
||||
}
|
||||
|
||||
void CDMRSlot::createReverseChannel(unsigned char *data, CDMREMB &emb) {
|
||||
if(m_rfN == 5U) {
|
||||
if (m_reverseChannelCommand == DMRCommand::RCCeaseTransmission) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_CEASE_TRANSMIT[0U] & 0x0FU);
|
||||
data[17U] = RC_CEASE_TRANSMIT[1U];
|
||||
data[18U] = RC_CEASE_TRANSMIT[2U];
|
||||
data[19U] = RC_CEASE_TRANSMIT[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_CEASE_TRANSMIT[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
else if (m_reverseChannelCommand == DMRCommand::RCRequestCeaseTransmission) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_REQUEST_CEASE_TRANSMIT[0U] & 0x0FU);
|
||||
data[17U] = RC_REQUEST_CEASE_TRANSMIT[1U];
|
||||
data[18U] = RC_REQUEST_CEASE_TRANSMIT[2U];
|
||||
data[19U] = RC_REQUEST_CEASE_TRANSMIT[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_REQUEST_CEASE_TRANSMIT[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
else if (m_reverseChannelCommand == DMRCommand::RCMaximumPower) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_MAX_POWER[0U] & 0x0FU);
|
||||
data[17U] = RC_MAX_POWER[1U];
|
||||
data[18U] = RC_MAX_POWER[2U];
|
||||
data[19U] = RC_MAX_POWER[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_MAX_POWER[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
else if (m_reverseChannelCommand == DMRCommand::RCMinimumPower) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_MIN_POWER[0U] & 0x0FU);
|
||||
data[17U] = RC_MIN_POWER[1U];
|
||||
data[18U] = RC_MIN_POWER[2U];
|
||||
data[19U] = RC_MIN_POWER[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_MIN_POWER[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
else if (m_reverseChannelCommand == DMRCommand::RCPowerIncreaseOneStep) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_POWER_INCREASE[0U] & 0x0FU);
|
||||
data[17U] = RC_POWER_INCREASE[1U];
|
||||
data[18U] = RC_POWER_INCREASE[2U];
|
||||
data[19U] = RC_POWER_INCREASE[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_POWER_INCREASE[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
else if (m_reverseChannelCommand == DMRCommand::RCPowerDecreaseOneStep) {
|
||||
data[16U] = (data[16U] & 0xF0U) | (RC_POWER_DECREASE[0U] & 0x0FU);
|
||||
data[17U] = RC_POWER_DECREASE[1U];
|
||||
data[18U] = RC_POWER_DECREASE[2U];
|
||||
data[19U] = RC_POWER_DECREASE[3U];
|
||||
data[20U] = (data[20U] & 0x0FU) | (RC_POWER_DECREASE[4U] & 0xF0U);
|
||||
emb.setColorCode(m_colorCode);
|
||||
emb.setLCSS(0);
|
||||
emb.setPI(true);
|
||||
emb.getData(data + 2U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CDMRSlot::writeJSONRSSI()
|
||||
{
|
||||
if (m_rssi == 0U)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue