// SPDX-License-Identifier: GPL-2.0-only /** * Digital Voice Modem - 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 / Modem Host Software * @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * * Copyright (C) 2015-2020 Jonathan Naylor, G4KLX * Copyright (C) 2022-2024 Bryan Biedenkapp, N2PLL * */ #if !defined(__NXDN_CONTROL_H__) #define __NXDN_CONTROL_H__ #include "Defines.h" #include "common/nxdn/NXDNDefines.h" #include "common/nxdn/channel/LICH.h" #include "common/nxdn/lc/RTCH.h" #include "common/nxdn/SiteData.h" #include "common/lookups/RSSIInterpolator.h" #include "common/lookups/IdenTableLookup.h" #include "common/lookups/RadioIdLookup.h" #include "common/lookups/TalkgroupRulesLookup.h" #include "common/lookups/AffiliationLookup.h" #include "common/RingBuffer.h" #include "common/StopWatch.h" #include "common/Timer.h" #include "common/yaml/Yaml.h" #include "nxdn/packet/Voice.h" #include "nxdn/packet/ControlSignaling.h" #include "nxdn/packet/Data.h" #include "network/Network.h" #include "modem/Modem.h" #include #include namespace nxdn { // --------------------------------------------------------------------------- // Class Prototypes // --------------------------------------------------------------------------- namespace packet { class HOST_SW_API Voice; } namespace packet { class HOST_SW_API ControlSignaling; } namespace packet { class HOST_SW_API Data; } // --------------------------------------------------------------------------- // Class Declaration // This class implements core logic for handling NXDN. // --------------------------------------------------------------------------- class HOST_SW_API Control { public: /// Initializes a new instance of the Control class. Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t queueSize, uint32_t timeout, uint32_t tgHang, modem::Modem* modem, network::Network* network, bool duplex, lookups::ChannelLookup* chLookup, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupRulesLookup* tidLookup, lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, bool dumpRCCHData, bool debug, bool verbose); /// Finalizes a instance of the Control class. ~Control(); /// Resets the data states for the RF interface. void reset(); /// Helper to set NXDN configuration options. void setOptions(yaml::Node& conf, bool supervisor, const std::string cwCallsign, lookups::VoiceChData controlChData, uint16_t siteId, uint32_t sysId, uint8_t channelId, uint32_t channelNo, bool printOptions); /// Gets a flag indicating whether the NXDN control channel is running. bool getCCRunning() const { return m_ccRunning; } /// Sets a flag indicating whether the NXDN control channel is running. void setCCRunning(bool ccRunning) { m_ccPrevRunning = m_ccRunning; m_ccRunning = ccRunning; } /// Gets a flag indicating whether the NXDN control channel is running. bool getCCHalted() const { return m_ccHalted; } /// Sets a flag indicating whether the NXDN control channel is halted. void setCCHalted(bool ccHalted) { m_ccHalted = ccHalted; } /// Process a data frame from the RF interface. bool processFrame(uint8_t* data, uint32_t len); /// Get the frame data length for the next frame in the data ring buffer. uint32_t peekFrameLength(); /// Get frame data from data ring buffer. uint32_t getFrame(uint8_t* data); /// Updates the processor. void clock(); /// Updates the adj. site tables and affiliations. void clockSiteData(uint32_t ms); /// Sets a flag indicating whether NXDN has supervisory functions and can send permit TG to voice channels. void setSupervisor(bool supervisor) { m_supervisor = supervisor; } /// Permits a TGID on a non-authoritative host. void permittedTG(uint32_t dstId); /// Grants a TGID on a non-authoritative host. void grantTG(uint32_t srcId, uint32_t dstId, bool grp); /// Releases a granted TG. void releaseGrantTG(uint32_t dstId); /// Touches a granted TG to keep a channel grant alive. void touchGrantTG(uint32_t dstId); /// Gets instance of the AffiliationLookup class. lookups::AffiliationLookup affiliations() { return m_affiliations; } /// Flag indicating whether the processor or is busy or not. bool isBusy() const; /// Flag indicating whether NXDN debug is enabled or not. bool getDebug() const { return m_debug; }; /// Flag indicating whether NXDN verbosity is enabled or not. bool getVerbose() const { return m_verbose; }; /// Helper to change the debug and verbose state. void setDebugVerbose(bool debug, bool verbose); /// Flag indicating whether NXDN RCCH verbosity is enabled or not. bool getRCCHVerbose() const { return m_dumpRCCH; }; /// Helper to change the RCCH verbose state. void setRCCHVerbose(bool verbose); /// Helper to get the last transmitted destination ID. uint32_t getLastDstId() const; /// Helper to get the last transmitted source ID. uint32_t getLastSrcId() const; private: friend class packet::Voice; packet::Voice* m_voice; friend class packet::Data; packet::Data* m_data; friend class packet::ControlSignaling; packet::ControlSignaling* m_control; bool m_authoritative; bool m_supervisor; uint32_t m_ran; uint32_t m_timeout; modem::Modem* m_modem; network::Network* m_network; bool m_duplex; bool m_enableControl; bool m_dedicatedControl; channel::LICH m_rfLastLICH; lc::RTCH m_rfLC; lc::RTCH m_netLC; uint32_t m_permittedDstId; uint8_t m_rfMask; uint8_t m_netMask; lookups::IdenTableLookup* m_idenTable; lookups::RadioIdLookup* m_ridLookup; lookups::TalkgroupRulesLookup* m_tidLookup; lookups::AffiliationLookup m_affiliations; ::lookups::VoiceChData m_controlChData; lookups::IdenTable m_idenEntry; RingBuffer m_txImmQueue; RingBuffer m_txQueue; RPT_RF_STATE m_rfState; uint32_t m_rfLastDstId; uint32_t m_rfLastSrcId; RPT_NET_STATE m_netState; uint32_t m_netLastDstId; uint32_t m_netLastSrcId; bool m_ccRunning; bool m_ccPrevRunning; bool m_ccHalted; Timer m_rfTimeout; Timer m_rfTGHang; Timer m_rfLossWatchdog; Timer m_netTimeout; Timer m_netTGHang; Timer m_networkWatchdog; Timer m_adjSiteUpdate; Timer m_ccPacketInterval; StopWatch m_interval; uint8_t m_frameLossCnt; uint8_t m_frameLossThreshold; uint8_t m_ccFrameCnt; uint8_t m_ccSeq; SiteData m_siteData; lookups::RSSIInterpolator* m_rssiMapper; uint8_t m_rssi; uint8_t m_maxRSSI; uint8_t m_minRSSI; uint32_t m_aveRSSI; uint32_t m_rssiCount; bool m_dumpRCCH; bool m_notifyCC; bool m_verbose; bool m_debug; /// Add data frame to the data ring buffer. void addFrame(const uint8_t* data, bool net = false, bool imm = false); /// Process a data frames from the network. void processNetwork(); /// Helper to process loss of frame stream from modem. void processFrameLoss(); /// Helper to send a REST API request to the CC to release a channel grant at the end of a call. void notifyCC_ReleaseGrant(uint32_t dstId); /// Helper to send a REST API request to the CC to "touch" a channel grant to refresh grant timers. void notifyCC_TouchGrant(uint32_t dstId); /// Helper to write control channel frame data. bool writeRF_ControlData(); /// Helper to write a Tx release packet. void writeRF_Message_Tx_Rel(bool noNetwork); /// Helper to write RF end of frame data. void writeEndRF(); /// Helper to write network end of frame data. void writeEndNet(); }; } // namespace nxdn #endif // __NXDN_CONTROL_H__