diff --git a/p25/Control.cpp b/p25/Control.cpp index 7410f948..2f3120f9 100644 --- a/p25/Control.cpp +++ b/p25/Control.cpp @@ -181,7 +181,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s m_tduPreambleCount = p25Protocol["tduPreambleCount"].as(8U); m_trunk->m_patchSuperGroup = pSuperGroup; - m_trunk->setSiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo); m_inhibitIllegal = p25Protocol["inhibitIllegal"].as(false); m_legacyGroupGrnt = p25Protocol["legacyGroupGrnt"].as(true); @@ -218,6 +217,8 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s m_disableNetworkHDU = p25Protocol["disableNetworkHDU"].as(false); + m_trunk->setSiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo); + std::vector availCh = voiceChNo; m_trunk->m_voiceChCnt = (uint8_t)availCh.size(); m_trunk->setSiteChCnt((uint8_t)availCh.size()); diff --git a/p25/SiteData.h b/p25/SiteData.h index 154d7e8e..10ad1307 100644 --- a/p25/SiteData.h +++ b/p25/SiteData.h @@ -51,6 +51,7 @@ namespace p25 m_siteId(1U), m_channelId(1U), m_channelNo(1U), + m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), m_isAdjSite(false) { /* stub */ @@ -63,7 +64,8 @@ namespace p25 /// P25 Location Resource Area. /// Channel ID. /// Channel Number. - SiteData(uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t lra, uint8_t channelId, uint32_t channelNo) : + /// Service class. + SiteData(uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t lra, uint8_t channelId, uint32_t channelNo, uint8_t serviceClass) : m_lra(0U), m_netId(P25_WACN_STD_DEFAULT), m_sysId(P25_SID_STD_DEFAULT), @@ -71,6 +73,7 @@ namespace p25 m_siteId(1U), m_channelId(1U), m_channelNo(1U), + m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), m_isAdjSite(false) { // lra clamping @@ -121,6 +124,8 @@ namespace p25 m_channelId = channelId; m_channelNo = channelNo; + + m_serviceClass = serviceClass; } /// Helper to set adjacent site data. @@ -129,7 +134,8 @@ namespace p25 /// P25 Site ID. /// Channel ID. /// Channel Number. - void setAdjSite(uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo) + /// Service class. + 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 @@ -170,6 +176,8 @@ namespace p25 m_channelId = channelId; m_channelNo = channelNo; + m_serviceClass = serviceClass; + m_isAdjSite = true; } @@ -190,6 +198,8 @@ namespace p25 m_channelId = data.m_channelId; m_channelNo = data.m_channelNo; + m_serviceClass = data.m_serviceClass; + m_isAdjSite = data.m_isAdjSite; } @@ -211,6 +221,8 @@ namespace p25 __READONLY_PROPERTY_PLAIN(uint8_t, channelId, channelId); /// Channel number. __READONLY_PROPERTY_PLAIN(uint32_t, channelNo, channelNo); + /// Channel number. + __READONLY_PROPERTY_PLAIN(uint8_t, serviceClass, serviceClass); /// Flag indicating whether this site data is for an adjacent site. __READONLY_PROPERTY_PLAIN(bool, isAdjSite, isAdjSite); }; diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index 5698c8cc..07b5979f 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -151,7 +151,8 @@ const uint32_t GRANT_TIMER_TIMEOUT = 15U; void TrunkPacket::setSiteData(uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t lra, uint8_t channelId, uint32_t channelNo) { - m_siteData = SiteData(netId, sysId, rfssId, siteId, lra, channelId, channelNo); + uint8_t serviceClass = m_rfTSBK.getServiceClass(); + m_siteData = SiteData(netId, sysId, rfssId, siteId, lra, channelId, channelNo, serviceClass); m_rfTSBK.setSiteData(m_siteData); m_rfTDULC.setSiteData(m_siteData); @@ -692,12 +693,12 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d } if (m_verbose) { - LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u", - m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo()); + LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", + m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass()); } site.setAdjSite(m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), - m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo()); + m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass()); m_adjSiteTable[site.siteId()] = site; m_adjSiteUpdateCnt[site.siteId()] = ADJ_SITE_UPDATE_CNT; @@ -715,12 +716,12 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d } if (m_verbose) { - LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_SCCB_EXP (Secondary Control Channel Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u", - m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo()); + LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_SCCB_EXP (Secondary Control Channel Broadcast), sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", + m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass()); } site.setAdjSite(m_netTSBK.getAdjSiteSysId(), m_netTSBK.getAdjSiteRFSSId(), - m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo()); + m_netTSBK.getAdjSiteId(), m_netTSBK.getAdjSiteChnId(), m_netTSBK.getAdjSiteChnNo(), m_netTSBK.getAdjSiteSvcClass()); m_sccbTable[site.rfssId()] = site; m_sccbUpdateCnt[site.rfssId()] = ADJ_SITE_UPDATE_CNT; @@ -863,19 +864,27 @@ void TrunkPacket::writeAdjSSNetwork() m_netTSBK.reset(); if (m_network != NULL) { + uint8_t serviceClass = m_rfTSBK.getServiceClass(); + if (m_verbose) { - LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), network announce, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u", - m_siteData.sysId(), m_siteData.rfssId(), m_siteData.siteId(), m_siteData.channelId(), m_siteData.channelNo()); + LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), network announce, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", + m_siteData.sysId(), m_siteData.rfssId(), m_siteData.siteId(), m_siteData.channelId(), m_siteData.channelNo(), serviceClass); + } + + uint8_t cfva = P25_CFVA_VALID; + if (m_p25->m_control && m_p25->m_voiceOnControl) { + cfva |= P25_CFVA_CONV; } // transmit adjacent site broadcast m_rfTSBK.setLCO(TSBK_OSP_ADJ_STS_BCAST); - m_rfTSBK.setAdjSiteCFVA(P25_CFVA_CONV | P25_CFVA_VALID); + m_rfTSBK.setAdjSiteCFVA(cfva); m_rfTSBK.setAdjSiteSysId(m_siteData.sysId()); m_rfTSBK.setAdjSiteRFSSId(m_siteData.rfssId()); m_rfTSBK.setAdjSiteId(m_siteData.siteId()); m_rfTSBK.setAdjSiteChnId(m_siteData.channelId()); m_rfTSBK.setAdjSiteChnNo(m_siteData.channelNo()); + m_rfTSBK.setAdjSiteSvcClass(serviceClass); RF_TO_WRITE_NET(); } @@ -1124,8 +1133,8 @@ void TrunkPacket::clock(uint32_t ms) if (updateCnt == 0U) { SiteData siteData = m_adjSiteTable[siteId]; - LogWarning(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), no data [FAILED], sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u", - siteData.sysId(), siteData.rfssId(), siteData.siteId(), siteData.channelId(), siteData.channelNo()); + LogWarning(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), no data [FAILED], sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", + siteData.sysId(), siteData.rfssId(), siteData.siteId(), siteData.channelId(), siteData.channelNo(), siteData.serviceClass()); } m_adjSiteUpdateCnt[siteId] = updateCnt; @@ -1142,8 +1151,8 @@ void TrunkPacket::clock(uint32_t ms) if (updateCnt == 0U) { SiteData siteData = m_sccbTable[rfssId]; - LogWarning(LOG_NET, P25_TSDU_STR ", TSBK_OSP_SCCB (Secondary Control Channel Broadcast), no data [FAILED], sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u", - siteData.sysId(), siteData.rfssId(), siteData.siteId(), siteData.channelId(), siteData.channelNo()); + LogWarning(LOG_NET, P25_TSDU_STR ", TSBK_OSP_SCCB (Secondary Control Channel Broadcast), no data [FAILED], sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", + siteData.sysId(), siteData.rfssId(), siteData.siteId(), siteData.channelId(), siteData.channelNo(), siteData.serviceClass()); } m_sccbUpdateCnt[rfssId] = updateCnt; @@ -1854,6 +1863,7 @@ void TrunkPacket::queueRF_TSBK_Ctrl_MBF(uint8_t lco) m_rfTSBK.setAdjSiteId(site.siteId()); m_rfTSBK.setAdjSiteChnId(site.channelId()); m_rfTSBK.setAdjSiteChnNo(site.channelNo()); + m_rfTSBK.setAdjSiteSvcClass(site.serviceClass()); m_mbfAdjSSCnt++; break; diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 3775015d..1807b712 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -283,7 +283,8 @@ bool TSBK::decode(const uint8_t* data) m_adjRfssId = (uint8_t)((tsbkValue >> 32) & 0xFFU); // Site RFSS ID m_adjSiteId = (uint8_t)((tsbkValue >> 24) & 0xFFU); // Site ID m_adjChannelId = (uint8_t)((tsbkValue >> 20) & 0xFU); // Site Channel ID - m_adjChannelNo = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // Site Channel ID + m_adjChannelNo = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // Site Channel Number + m_adjServiceClass = (uint8_t)(tsbkValue & 0xFFU); // Site Service Class break; default: LogError(LOG_P25, "unknown TSBK LCO value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); @@ -558,11 +559,11 @@ void TSBK::encode(uint8_t * data, bool singleBlock) tsbkValue = (tsbkValue << 8) + m_adjSiteId; // Site ID tsbkValue = (tsbkValue << 4) + m_adjChannelId; // Channel ID tsbkValue = (tsbkValue << 12) + m_adjChannelNo; // Channel Number - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_adjServiceClass; // System Service Class } else { - LogError(LOG_P25, "invalid values for OSP_ADJ_STS_BCAST, adjRfssId = $%02X, adjSiteId = $%02X, adjChannelId = %u, adjChannelNo = $%02X", - m_adjRfssId, m_adjSiteId, m_adjChannelId, m_adjChannelNo); + LogError(LOG_P25, "invalid values for OSP_ADJ_STS_BCAST, adjRfssId = $%02X, adjSiteId = $%02X, adjChannelId = %u, adjChannelNo = $%02X, adjSvcClass = $%02X", + m_adjRfssId, m_adjSiteId, m_adjChannelId, m_adjChannelNo, m_adjServiceClass); return; // blatently ignore creating this TSBK } } @@ -785,11 +786,12 @@ void TSBK::reset() m_extendedFunction = P25_EXT_FNCT_CHECK; - m_adjCFVA = P25_CFVA_CONV | P25_CFVA_FAILURE; + m_adjCFVA = P25_CFVA_FAILURE; m_adjRfssId = 0U; m_adjSiteId = 0U; m_adjChannelId = 0U; m_adjChannelNo = 0U; + m_adjServiceClass = P25_SVC_CLS_INVALID; /* TSBK Patch Group data */ m_patchSuperGroupId = 0U; diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h index 54b748b2..86920cf8 100644 --- a/p25/lc/TSBK.h +++ b/p25/lc/TSBK.h @@ -148,6 +148,8 @@ namespace p25 __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId); /// Adjacent site channel number. __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo); + /// Adjacent site channel number. + __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass); /** SCCB Data */ /// SCCB channel ID 1.