add appropriate support for DMR TSCC to repeat the channel grant following appropriate channel grant; add support to affiliation tables to log what source ID a destination ID is granted to;

pull/24/head 2023-03-25
Bryan Biedenkapp 3 years ago
parent 4ec99becfe
commit 7e2e002b10

@ -159,6 +159,7 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz
m_tsccPayloadDstId(0U),
m_tsccPayloadGroup(false),
m_tsccPayloadVoice(true),
m_lastLateEntry(0U),
m_verbose(verbose),
m_debug(debug)
{
@ -438,7 +439,7 @@ void Slot::clock()
if (m_ccPacketInterval.isRunning() && m_ccPacketInterval.hasExpired()) {
if (m_ccRunning) {
if (m_ccSeq == 3U) {
if (m_ccSeq == 4U) {
m_ccSeq = 0U;
}
@ -975,9 +976,9 @@ void Slot::writeRF_ControlData(uint16_t frameCnt, uint8_t n)
return;
}
// loop to generate 3 control sequences
// loop to generate 4 control sequences
if (frameCnt == 511U) {
seqCnt = 3U;
seqCnt = 4U;
}
// should we insert the Git Hash burst?
@ -999,6 +1000,37 @@ void Slot::writeRF_ControlData(uint16_t frameCnt, uint8_t n)
switch (n)
{
case 3:
{
std::unordered_map<uint32_t, uint32_t> grants = m_affiliations->grantTable();
if (grants.size() > 0) {
uint32_t j = 0U;
if (m_lastLateEntry > grants.size()) {
m_lastLateEntry = 0U;
}
for (auto entry : grants) {
if (j == m_lastLateEntry) {
uint32_t dstId = entry.first;
uint32_t srcId = m_affiliations->getGrantedSrcId(dstId);
if (m_debug) {
LogDebug(LOG_DMR, "writeRF_ControlData, frameCnt = %u, seq = %u, late entry, dstId = %u, srcId = %u", frameCnt, n, dstId, srcId);
}
m_control->writeRF_CSBK_Grant_LateEntry(dstId, srcId);
m_lastLateEntry = j++;
break;
}
j++;
}
}
else {
m_control->writeRF_TSCC_Bcast_Sys_Parm();
}
}
break;
case 2:
m_control->writeRF_TSCC_Bcast_Ann_Wd(m_channelNo, true);
break;

@ -196,6 +196,8 @@ namespace dmr
bool m_tsccPayloadGroup;
bool m_tsccPayloadVoice;
uint32_t m_lastLateEntry;
bool m_controlPermitTG;
bool m_verbose;

@ -42,7 +42,8 @@ using namespace dmr;
/// <summary>
/// Initializes a new instance of the CSBK_TV_GRANT class.
/// </summary>
CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK()
CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK(),
m_lateEntry(false)
{
m_CSBKO = CSBKO_TV_GRANT;
}
@ -73,7 +74,7 @@ void CSBK_TV_GRANT::encode(uint8_t* data)
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1
csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number
csbkValue = (csbkValue << 1) + 0U; // Late Entry
csbkValue = (csbkValue << 1) + ((m_lateEntry) ? 1U : 0U);; // Late Entry
csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency
csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset
csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID
@ -82,3 +83,18 @@ void CSBK_TV_GRANT::encode(uint8_t* data)
std::unique_ptr<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
void CSBK_TV_GRANT::copy(const CSBK_TV_GRANT& data)
{
CSBK::copy(data);
m_lateEntry = data.m_lateEntry;
}

@ -49,6 +49,12 @@ namespace dmr
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Flag indicating whether the grant is a late entry.</summary>
__PROPERTY(bool, lateEntry, LateEntry);
__COPY(CSBK_TV_GRANT);
};
} // namespace csbk
} // namespace lc

@ -62,9 +62,10 @@ DMRAffiliationLookup::~DMRAffiliationLookup()
/// Helper to grant a channel.
/// </summary>
/// <param name="dstId"></param>
/// <param name="srcId"></param>
/// <param name="grantTimeout"></param>
/// <returns></returns>
bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t grantTimeout)
bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout)
{
uint32_t chNo = m_rfChTable.at(0);
uint8_t slot = getAvailableSlotForChannel(chNo);
@ -73,17 +74,18 @@ bool DMRAffiliationLookup::grantCh(uint32_t dstId, uint32_t grantTimeout)
return false;
}
return grantChSlot(dstId, slot, grantTimeout);
return grantChSlot(dstId, srcId, slot, grantTimeout);
}
/// <summary>
/// Helper to grant a channel and slot.
/// </summary>
/// <param name="dstId"></param>
/// <param name="srcId"></param>
/// <param name="slot"></param>
/// <param name="grantTimeout"></param>
/// <returns></returns>
bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint8_t slot, uint32_t grantTimeout)
bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout)
{
if (dstId == 0U) {
return false;
@ -104,6 +106,7 @@ bool DMRAffiliationLookup::grantChSlot(uint32_t dstId, uint8_t slot, uint32_t gr
}
m_grantChTable[dstId] = chNo;
m_grantSrcIdTable[dstId] = srcId;
m_grantChSlotTable[dstId] = std::make_tuple(chNo, slot);
m_rfGrantChCnt++;
@ -161,7 +164,8 @@ bool DMRAffiliationLookup::releaseGrant(uint32_t dstId, bool releaseAll)
m_releaseGrant(chNo, dstId, slot);
}
m_grantChTable[dstId] = 0U;
m_grantChTable.erase(dstId);
m_grantSrcIdTable.erase(dstId);
m_grantChSlotTable.erase(dstId);
auto it = std::find(m_rfChTable.begin(), m_rfChTable.end(), chNo);

@ -50,9 +50,9 @@ namespace dmr
virtual ~DMRAffiliationLookup();
/// <summary>Helper to grant a channel.</summary>
virtual bool grantCh(uint32_t dstId, uint32_t grantTimeout);
virtual bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout);
/// <summary>Helper to grant a channel and slot.</summary>
bool grantChSlot(uint32_t dstId, uint8_t slot, uint32_t grantTimeout);
bool grantChSlot(uint32_t dstId, uint32_t srcId, uint8_t slot, uint32_t grantTimeout);
/// <summary>Helper to release the channel grant for the destination ID.</summary>
virtual bool releaseGrant(uint32_t dstId, bool releaseAll);
/// <summary>Helper to determine if the channel number is busy.</summary>

@ -821,7 +821,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_
}
}
else {
if (m_tscc->m_affiliations->grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT)) {
chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId);
//m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt());
@ -1056,7 +1056,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u
}
}
else {
if (m_tscc->m_affiliations->grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
if (m_tscc->m_affiliations->grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT)) {
chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
slot = m_tscc->m_affiliations->getGrantedSlot(dstId);
@ -1219,6 +1219,29 @@ void ControlSignaling::writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOpt
writeRF_CSBK(csbk.get());
}
/// <summary>
/// Helper to write a grant packet.
/// </summary>
/// <param name="dstId"></param>
/// <param name="srcId"></param>
void ControlSignaling::writeRF_CSBK_Grant_LateEntry(uint32_t dstId, uint32_t srcId)
{
Slot *m_tscc = m_slot->m_dmr->getTSCCSlot();
uint32_t chNo = m_tscc->m_affiliations->getGrantedCh(dstId);
uint8_t slot = m_tscc->m_affiliations->getGrantedSlot(dstId);
std::unique_ptr<CSBK_TV_GRANT> csbk = new_unique(CSBK_TV_GRANT);
csbk->setLogicalCh1(chNo);
csbk->setSlotNo(slot - 1U);
csbk->setSrcId(srcId);
csbk->setDstId(dstId);
writeRF_CSBK(csbk.get());
}
/// <summary>
/// Helper to write a TSCC Aloha broadcast packet on the RF interface.
/// </summary>

@ -101,6 +101,9 @@ namespace dmr
/// <summary>Helper to write a unit registration response packet.</summary>
void writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOptions);
/// <summary>Helper to write a TSCC late entry channel grant packet on the RF interface.</summary>
void writeRF_CSBK_Grant_LateEntry(uint32_t dstId, uint32_t srcId);
/// <summary>Helper to write a TSCC Aloha broadcast packet on the RF interface.</summary>
void writeRF_TSCC_Aloha();
/// <summary>Helper to write a TSCC Ann-Wd broadcast packet on the RF interface.</summary>

@ -49,6 +49,7 @@ AffiliationLookup::AffiliationLookup(const char* name, bool verbose) :
m_unitRegTable(),
m_grpAffTable(),
m_grantChTable(),
m_grantSrcIdTable(),
m_grantTimers(),
m_name(name),
m_verbose(verbose)
@ -59,6 +60,7 @@ AffiliationLookup::AffiliationLookup(const char* name, bool verbose) :
m_grpAffTable.clear();
m_grantChTable.clear();
m_grantSrcIdTable.clear();
m_grantTimers.clear();
}
@ -238,9 +240,10 @@ std::vector<uint32_t> AffiliationLookup::clearGroupAff(uint32_t dstId, bool rele
/// Helper to grant a channel.
/// </summary>
/// <param name="dstId"></param>
/// <param name="srcId"></param>
/// <param name="grantTimeout"></param>
/// <returns></returns>
bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t grantTimeout)
bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout)
{
if (dstId == 0U) {
return false;
@ -255,14 +258,15 @@ bool AffiliationLookup::grantCh(uint32_t dstId, uint32_t grantTimeout)
m_rfChTable.erase(it);
m_grantChTable[dstId] = chNo;
m_grantSrcIdTable[dstId] = srcId;
m_rfGrantChCnt++;
m_grantTimers[dstId] = Timer(1000U, grantTimeout);
m_grantTimers[dstId].start();
if (m_verbose) {
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, dstId = %u",
m_name, chNo, dstId);
LogMessage(LOG_HOST, "%s, granting channel, chNo = %u, dstId = %u, srcId = %u",
m_name, chNo, dstId, srcId);
}
return true;
@ -321,7 +325,8 @@ bool AffiliationLookup::releaseGrant(uint32_t dstId, bool releaseAll)
m_name, chNo, dstId);
}
m_grantChTable[dstId] = 0U;
m_grantChTable.erase(dstId);
m_grantSrcIdTable.erase(dstId);
m_rfChTable.push_back(chNo);
if (m_rfGrantChCnt > 0U) {
@ -402,6 +407,24 @@ uint32_t AffiliationLookup::getGrantedCh(uint32_t dstId)
return 0U;
}
/// <summary>
/// Helper to get the source ID granted for the given destination ID.
/// </summary>
/// <param name="dstId"></param>
/// <returns></returns>
uint32_t AffiliationLookup::getGrantedSrcId(uint32_t dstId)
{
if (dstId == 0U) {
return 0U;
}
if (isGranted(dstId)) {
return m_grantSrcIdTable[dstId];
}
return 0U;
}
/// <summary>
/// Helper to get RF channel data.
/// </summary>

@ -137,7 +137,7 @@ namespace lookups
/// <summary>Gets the grant table.</summary>
std::unordered_map<uint32_t, uint32_t> grantTable() const { return m_grantChTable; }
/// <summary>Helper to grant a channel.</summary>
virtual bool grantCh(uint32_t dstId, uint32_t grantTimeout);
virtual bool grantCh(uint32_t dstId, uint32_t srcId, uint32_t grantTimeout);
/// <summary>Helper to start the destination ID grant timer.</summary>
virtual void touchGrant(uint32_t dstId);
/// <summary>Helper to release the channel grant for the destination ID.</summary>
@ -148,6 +148,8 @@ namespace lookups
virtual bool isGranted(uint32_t dstId) const;
/// <summary>Helper to get the channel granted for the given destination ID.</summary>
virtual uint32_t getGrantedCh(uint32_t dstId);
/// <summary>Helper to get the source ID granted for the given destination ID.</summary>
virtual uint32_t getGrantedSrcId(uint32_t srcId);
/// <summary>Helper to set RF channel data.</summary>
void setRFChData(const std::unordered_map<uint32_t, VoiceChData> chData) { m_rfChDataTable = chData; }
@ -177,6 +179,7 @@ namespace lookups
std::unordered_map<uint32_t, uint32_t> m_grpAffTable;
std::unordered_map<uint32_t, uint32_t> m_grantChTable;
std::unordered_map<uint32_t, uint32_t> m_grantSrcIdTable;
std::unordered_map<uint32_t, Timer> m_grantTimers;
const char *m_name;

@ -488,7 +488,7 @@ bool Trunk::writeRF_Message_Grant(uint32_t srcId, uint32_t dstId, uint8_t servic
}
}
else {
if (m_nxdn->m_affiliations.grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
if (m_nxdn->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT)) {
chNo = m_nxdn->m_affiliations.getGrantedCh(dstId);
}
}

@ -2216,7 +2216,7 @@ bool Trunk::writeRF_TSDU_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOp
}
}
else {
if (m_p25->m_affiliations.grantCh(dstId, GRANT_TIMER_TIMEOUT)) {
if (m_p25->m_affiliations.grantCh(dstId, srcId, GRANT_TIMER_TIMEOUT)) {
chNo = m_p25->m_affiliations.getGrantedCh(dstId);
m_p25->m_siteData.setChCnt(m_p25->m_affiliations.getRFChCnt() + m_p25->m_affiliations.getGrantedRFChCnt());
}
@ -2360,7 +2360,7 @@ bool Trunk::writeRF_TSDU_SNDCP_Grant(uint32_t srcId, uint32_t dstId, bool skip,
return false;
}
else {
if (m_p25->m_affiliations.grantCh(srcId, GRANT_TIMER_TIMEOUT)) {
if (m_p25->m_affiliations.grantCh(srcId, srcId, GRANT_TIMER_TIMEOUT)) {
uint32_t chNo = m_p25->m_affiliations.getGrantedCh(srcId);
osp->setGrpVchNo(chNo);
osp->setDataChnNo(chNo);

Loading…
Cancel
Save

Powered by TurnKey Linux.