/** * 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 * */ /* * Copyright (C) 2022 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. */ #include "Defines.h" #include "dmr/lc/csbk/CSBK_BROADCAST.h" #include "Log.h" #include "Utils.h" using namespace dmr::lc::csbk; using namespace dmr::lc; using namespace dmr; #include #include // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- /// /// Initializes a new instance of the CSBK_BROADCAST class. /// CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(), m_anncType(BCAST_ANNC_SITE_PARMS), m_hibernating(false), m_annWdCh1(false), m_annWdCh2(false), m_backoffNo(1U) { m_CSBKO = CSBKO_BROADCAST; } /// /// Decode a control signalling block. /// /// /// True, if CSBK was decoded, otherwise false. bool CSBK_BROADCAST::decode(const uint8_t* data) { assert(data != NULL); /* stub */ return true; } /// /// Encode a control signalling block. /// /// void CSBK_BROADCAST::encode(uint8_t* data) { assert(data != NULL); ulong64_t csbkValue = 0U; if (!m_Cdef) { csbkValue = m_anncType; // Announcement Type } switch (m_anncType) { case BCAST_ANNC_ANN_WD_TSCC: // Broadcast Parms 1 csbkValue = (csbkValue << 4) + 0U; // Reserved csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1 csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 2 csbkValue = (csbkValue << 1) + ((m_annWdCh1) ? 1U : 0U); // Announce/Withdraw Channel 1 csbkValue = (csbkValue << 1) + ((m_annWdCh2) ? 1U : 0U); // Announce/Withdraw Channel 2 csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity // Broadcast Parms 2 csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1 csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2 break; case BCAST_ANNC_CHAN_FREQ: { uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000; const uint32_t multiple = 100000; // calculate Rx frequency uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)) + calcTxOffset); // generate frequency in mhz uint32_t rxFreqMhz = rxFrequency + multiple / 2; rxFreqMhz -= rxFreqMhz % multiple; rxFreqMhz /= multiple * 10; // generate khz offset uint32_t rxFreqKhz = rxFrequency - (rxFreqMhz * 1000000); // calculate Tx Frequency uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1))); // generate frequency in mhz uint32_t txFreqMhz = txFrequency + multiple / 2; txFreqMhz -= txFreqMhz % multiple; txFreqMhz /= multiple * 10; // generate khz offset uint32_t txFreqKhz = txFrequency - (txFreqMhz * 1000000); csbkValue = 0U; // Cdef Type (always 0 for ANN_WD_TSCC) csbkValue = (csbkValue << 2) + 0U; // Reserved csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel csbkValue = (csbkValue << 10) + (txFreqMhz & 0x7FFU); // Transmit Freq Mhz csbkValue = (csbkValue << 13) + (txFreqKhz & 0x3FFFU); // Transmit Freq Offset Khz csbkValue = (csbkValue << 10) + (rxFreqMhz & 0x7FFU); // Receive Freq Mhz csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz } break; case BCAST_ANNC_SITE_PARMS: // Broadcast Parms 1 csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1) csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity // Broadcast Parms 2 csbkValue = (csbkValue << 1) + 0U; // Roaming TG Subscription/Attach csbkValue = (csbkValue << 1) + ((m_hibernating) ? 1U : 0U); // TSCC Hibernating csbkValue = (csbkValue << 22) + 0U; // Broadcast Parms 2 (Reserved) break; } std::unique_ptr csbk = CSBK::fromValue(csbkValue); CSBK::encode(data, csbk.get()); } // --------------------------------------------------------------------------- // Private Class Members // --------------------------------------------------------------------------- /// /// Internal helper to copy the the class. /// /// void CSBK_BROADCAST::copy(const CSBK_BROADCAST& data) { CSBK::copy(data); m_anncType = data.m_anncType; m_hibernating = data.m_hibernating; m_annWdCh1 = data.m_annWdCh1; m_annWdCh2 = data.m_annWdCh2; }