treewide: refactor constant variables into proper enumerations where appropriate (this applies to DMR, P25 and NXDN, and may introduce gremlins);

pull/61/head
Bryan Biedenkapp 2 years ago
parent 41b36a491d
commit cb0500b2e7

@ -90,10 +90,10 @@ typedef unsigned long long ulong64_t;
#define VERSION_MAJOR "04" #define VERSION_MAJOR "04"
#define VERSION_MINOR "01" #define VERSION_MINOR "01"
#define VERSION_REV "A" #define VERSION_REV "B"
#define __NETVER__ "DVM_R" VERSION_MAJOR VERSION_REV VERSION_MINOR #define __NETVER__ "DVM_R" VERSION_MAJOR VERSION_REV VERSION_MINOR
#define __VER__ VERSION_MAJOR "." VERSION_MINOR " (R" VERSION_MAJOR VERSION_REV VERSION_MINOR " " __GIT_VER__ ")" #define __VER__ VERSION_MAJOR "." VERSION_MINOR VERSION_REV " (R" VERSION_MAJOR VERSION_REV VERSION_MINOR " " __GIT_VER__ ")"
#define __BUILD__ __DATE__ " " __TIME__ #define __BUILD__ __DATE__ " " __TIME__

@ -17,300 +17,408 @@
#include "common/Defines.h" #include "common/Defines.h"
// Shorthand macro to dmr::defines -- keeps source code that doesn't use "using" concise
#define DMRDEF dmr::defines
namespace dmr namespace dmr
{ {
// --------------------------------------------------------------------------- namespace defines
// Constants {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint32_t DMR_FRAME_LENGTH_BITS = 264U; const uint32_t DMR_FRAME_LENGTH_BITS = 264U;
const uint32_t DMR_FRAME_LENGTH_BYTES = 33U; const uint32_t DMR_FRAME_LENGTH_BYTES = 33U;
const uint32_t DMR_SYNC_LENGTH_BITS = 48U; const uint32_t DMR_SYNC_LENGTH_BITS = 48U;
const uint32_t DMR_SYNC_LENGTH_BYTES = 6U; const uint32_t DMR_SYNC_LENGTH_BYTES = 6U;
const uint32_t DMR_EMB_LENGTH_BITS = 8U; const uint32_t DMR_EMB_LENGTH_BITS = 8U;
const uint32_t DMR_EMB_LENGTH_BYTES = 1U; const uint32_t DMR_EMB_LENGTH_BYTES = 1U;
const uint32_t DMR_SLOT_TYPE_LENGTH_BITS = 8U; const uint32_t DMR_SLOT_TYPE_LENGTH_BITS = 8U;
const uint32_t DMR_SLOT_TYPE_LENGTH_BYTES = 1U; const uint32_t DMR_SLOT_TYPE_LENGTH_BYTES = 1U;
const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BITS = 32U; const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BITS = 32U;
const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BYTES = 4U; const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BYTES = 4U;
const uint32_t DMR_AMBE_LENGTH_BITS = 108U * 2U; const uint32_t DMR_AMBE_LENGTH_BITS = 108U * 2U;
const uint32_t DMR_AMBE_LENGTH_BYTES = 27U; const uint32_t DMR_AMBE_LENGTH_BYTES = 27U;
const uint32_t DMR_LC_HEADER_LENGTH_BYTES = 12U; const uint32_t DMR_LC_HEADER_LENGTH_BYTES = 12U;
const uint32_t DMR_CSBK_LENGTH_BYTES = 12U; const uint32_t DMR_CSBK_LENGTH_BYTES = 12U;
const uint8_t BS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U }; const uint8_t BS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0x55U, 0xFDU, 0x7DU, 0xF7U, 0x5FU, 0x70U };
const uint8_t BS_SOURCED_DATA_SYNC[] = { 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U }; const uint8_t BS_SOURCED_DATA_SYNC[] = { 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U };
const uint8_t MS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U }; const uint8_t MS_SOURCED_AUDIO_SYNC[] = { 0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U };
const uint8_t MS_SOURCED_DATA_SYNC[] = { 0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U }; const uint8_t MS_SOURCED_DATA_SYNC[] = { 0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U };
const uint8_t DIRECT_SLOT1_AUDIO_SYNC[] = { 0x05U, 0xD5U, 0x77U, 0xF7U, 0x75U, 0x7FU, 0xF0U }; const uint8_t DIRECT_SLOT1_AUDIO_SYNC[] = { 0x05U, 0xD5U, 0x77U, 0xF7U, 0x75U, 0x7FU, 0xF0U };
const uint8_t DIRECT_SLOT1_DATA_SYNC[] = { 0x0FU, 0x7FU, 0xDDU, 0x5DU, 0xDFU, 0xD5U, 0x50U }; const uint8_t DIRECT_SLOT1_DATA_SYNC[] = { 0x0FU, 0x7FU, 0xDDU, 0x5DU, 0xDFU, 0xD5U, 0x50U };
const uint8_t DIRECT_SLOT2_AUDIO_SYNC[] = { 0x07U, 0xDFU, 0xFDU, 0x5FU, 0x55U, 0xD5U, 0xF0U }; const uint8_t DIRECT_SLOT2_AUDIO_SYNC[] = { 0x07U, 0xDFU, 0xFDU, 0x5FU, 0x55U, 0xD5U, 0xF0U };
const uint8_t DIRECT_SLOT2_DATA_SYNC[] = { 0x0DU, 0x75U, 0x57U, 0xF5U, 0xFFU, 0x7FU, 0x50U }; const uint8_t DIRECT_SLOT2_DATA_SYNC[] = { 0x0DU, 0x75U, 0x57U, 0xF5U, 0xFFU, 0x7FU, 0x50U };
const uint8_t DMR_MS_DATA_SYNC_BYTES[] = { 0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U }; const uint8_t MS_DATA_SYNC_BYTES[] = { 0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U };
const uint8_t DMR_MS_VOICE_SYNC_BYTES[] = { 0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U }; const uint8_t MS_VOICE_SYNC_BYTES[] = { 0x07U, 0xF7U, 0xD5U, 0xDDU, 0x57U, 0xDFU, 0xD0U };
const uint8_t SYNC_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U }; const uint8_t SYNC_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U };
// The PR FILL and Data Sync pattern. // The PR FILL and Data Sync pattern.
const uint8_t DMR_IDLE_DATA[] = { 0x01U, 0x00U, const uint8_t IDLE_DATA[] = { 0x01U, 0x00U,
0x53U, 0xC2U, 0x5EU, 0xABU, 0xA8U, 0x67U, 0x1DU, 0xC7U, 0x38U, 0x3BU, 0xD9U, 0x53U, 0xC2U, 0x5EU, 0xABU, 0xA8U, 0x67U, 0x1DU, 0xC7U, 0x38U, 0x3BU, 0xD9U,
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U, 0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U }; 0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U };
// A silence frame only // A silence frame only
const uint8_t DMR_SILENCE_DATA[] = { 0x01U, 0x00U, const uint8_t SILENCE_DATA[] = { 0x01U, 0x00U,
0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU, 0xB9U, 0xE8U, 0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU, 0xB9U, 0xE8U,
0x81U, 0x52U, 0x60U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x73U, 0x00U, 0x81U, 0x52U, 0x60U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x73U, 0x00U,
0x2AU, 0x6BU, 0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU }; 0x2AU, 0x6BU, 0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU };
const uint8_t DMR_NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U }; const uint8_t NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U };
const uint8_t PAYLOAD_LEFT_MASK[] = { 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U }; const uint8_t PAYLOAD_LEFT_MASK[] = { 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U };
const uint8_t PAYLOAD_RIGHT_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU }; const uint8_t PAYLOAD_RIGHT_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU };
const uint8_t VOICE_LC_HEADER_CRC_MASK[] = { 0x96U, 0x96U, 0x96U }; const uint8_t VOICE_LC_HEADER_CRC_MASK[] = { 0x96U, 0x96U, 0x96U };
const uint8_t TERMINATOR_WITH_LC_CRC_MASK[] = { 0x99U, 0x99U, 0x99U }; const uint8_t TERMINATOR_WITH_LC_CRC_MASK[] = { 0x99U, 0x99U, 0x99U };
const uint8_t PI_HEADER_CRC_MASK[] = { 0x69U, 0x69U }; const uint8_t PI_HEADER_CRC_MASK[] = { 0x69U, 0x69U };
const uint8_t DATA_HEADER_CRC_MASK[] = { 0xCCU, 0xCCU }; const uint8_t DATA_HEADER_CRC_MASK[] = { 0xCCU, 0xCCU };
const uint8_t CSBK_CRC_MASK[] = { 0xA5U, 0xA5U }; const uint8_t CSBK_CRC_MASK[] = { 0xA5U, 0xA5U };
const uint8_t CSBK_MBC_CRC_MASK[] = { 0xAAU, 0xAAU }; const uint8_t CSBK_MBC_CRC_MASK[] = { 0xAAU, 0xAAU };
const uint16_t TSCC_MAX_CSC_CNT = 511U; const uint8_t DT_MASK = 0x0FU;
const uint32_t DMR_SLOT_TIME = 60U; const uint8_t IDLE_RX = 0x80U;
const uint32_t AMBE_PER_SLOT = 3U; const uint8_t SYNC_DATA = 0x40U;
const uint8_t SYNC_VOICE = 0x20U;
const uint8_t DT_MASK = 0x0FU;
const uint8_t SLOT1 = 0x00U;
const uint8_t DMR_IDLE_RX = 0x80U; const uint8_t SLOT2 = 0x80U;
const uint8_t DMR_SYNC_DATA = 0x40U;
const uint8_t DMR_SYNC_VOICE = 0x20U; const uint32_t MAX_PDU_COUNT = 32U;
const uint32_t MAX_PDU_LENGTH = 512U;
const uint8_t DMR_SLOT1 = 0x00U;
const uint8_t DMR_SLOT2 = 0x80U; const uint32_t MI_LENGTH_BYTES = 4U; // This was guessed based on OTA data captures -- the message indicator seems to be the same length as a source/destination address
const uint32_t DMR_MAX_PDU_COUNT = 32U; /** Thresholds */
const uint32_t DMR_MAX_PDU_LENGTH = 512U; const uint16_t TSCC_MAX_CSC_CNT = 511U;
const uint32_t DMR_MI_LENGTH_BYTES = 4U; // This was guessed based on OTA data captures -- the message indicator seems to be the same length as a source/destination address const uint32_t DMR_SLOT_TIME = 60U;
const uint32_t AMBE_PER_SLOT = 3U;
const uint8_t DMR_ALOHA_VER_151 = 0x00U;
const uint8_t DMR_CHNULL = 0x00U; const uint8_t DEFAULT_NRAND_WAIT = 8U;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 21U;
const uint16_t DMR_LOGICAL_CH_ABSOLUTE = 0xFFFU; const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 2U;
const uint32_t MAX_DMR_VOICE_ERRORS = 141U;
const uint8_t DEFAULT_NRAND_WAIT = 8U;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 21U; /** Default Values */
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 2U; const uint8_t DMR_ALOHA_VER_151 = 0x00U;
const uint32_t MAX_DMR_VOICE_ERRORS = 141U; const uint8_t DMR_CHNULL = 0x00U;
const uint32_t DMR_WUID_SUPLI = 0xFFFEC4U; const uint16_t DMR_LOGICAL_CH_ABSOLUTE = 0xFFFU;
const uint32_t DMR_WUID_SDMI = 0xFFFEC5U;
const uint32_t DMR_WUID_REGI = 0xFFFEC6U; const uint32_t WUID_SUPLI = 0xFFFEC4U; // Supplementary Data Service Working Unit ID
const uint32_t DMR_WUID_STUNI = 0xFFFECCU; const uint32_t WUID_SDMI = 0xFFFEC5U; // UDT Short Data Service Working Unit ID
const uint32_t DMR_WUID_AUTHI = 0xFFFECDU; const uint32_t WUID_REGI = 0xFFFEC6U; // Registration Working Unit ID
const uint32_t DMR_WUID_KILLI = 0xFFFECFU; const uint32_t WUID_STUNI = 0xFFFECCU; // MS Stun/Revive Identifier
const uint32_t DMR_WUID_TATTSI = 0xFFFED7U; const uint32_t WUID_AUTHI = 0xFFFECDU; // Authentication Working Unit ID
const uint32_t DMR_WUID_ALL = 0xFFFFFFU; const uint32_t WUID_KILLI = 0xFFFECFU; // MS Kill Identifier
const uint32_t WUID_TATTSI = 0xFFFED7U; // Talkgroup Subscription/Attachement Service Working Unit ID
// PDU Data Formats const uint32_t WUID_ALLL = 0xFFFFFDU; // All-call Site-wide Working Unit ID
const uint8_t DPF_UDT = 0x00U; const uint32_t WUID_ALLZ = 0xFFFFFEU; // All-call System-wide Working Unit ID
const uint8_t DPF_RESPONSE = 0x01U; const uint32_t WUID_ALL = 0xFFFFFFU; // All-call Network-wide Working Unit ID
const uint8_t DPF_UNCONFIRMED_DATA = 0x02U;
const uint8_t DPF_CONFIRMED_DATA = 0x03U; const uint32_t NO_HEADERS_SIMPLEX = 8U;
const uint8_t DPF_DEFINED_SHORT = 0x0DU; const uint32_t NO_HEADERS_DUPLEX = 3U;
const uint8_t DPF_DEFINED_RAW = 0x0EU; const uint32_t NO_PREAMBLE_CSBK = 15U;
const uint8_t DPF_PROPRIETARY = 0x0FU;
/// <summary>
// PDU ACK Class /// Data Packet Format
const uint8_t PDU_ACK_CLASS_ACK = 0x00U; /// </summary>
const uint8_t PDU_ACK_CLASS_NACK = 0x01U; namespace DPF {
const uint8_t PDU_ACK_CLASS_ACK_RETRY = 0x02U; // Data Packet Format Enumeration
enum E : uint8_t {
// PDU ACK Type(s) UDT = 0x00U, // Unified Data Transport Header
const uint8_t PDU_ACK_TYPE_ACK = 0x01U; RESPONSE = 0x01U, // Response Data Header
UNCONFIRMED_DATA = 0x02U, // Unconfirmed Data Header
const uint8_t PDU_ACK_TYPE_NACK_ILLEGAL = 0x00U; // Illegal Format CONFIRMED_DATA = 0x03U, // Confirmed Data Header
const uint8_t PDU_ACK_TYPE_NACK_PACKET_CRC = 0x01U; // Packet CRC DEFINED_SHORT = 0x0DU, // Defined Short Data Header
const uint8_t PDU_ACK_TYPE_NACK_MEMORY_FULL = 0x02U; // Memory Full DEFINED_RAW = 0x0EU, // Defined Raw Data Header
const uint8_t PDU_ACK_TYPE_NACK_UNDELIVERABLE = 0x04U;// Undeliverable PROPRIETARY = 0x0FU, // Proprietary
};
// Feature IDs };
const uint8_t FID_ETSI = 0x00U; // ETSI Standard Feature Set
const uint8_t FID_DMRA = 0x10U; // /// <summary>
const uint8_t FID_OCS_DVM = 0x9CU; // FID used for internal signalling; Omaha Communication Systems, LLC ($9C) /// Data Response Class
/// </summary>
// LC Service Options namespace PDUResponseClass {
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U; enum : uint8_t {
const uint8_t LC_SVC_OPT_PRIVACY = 0x40U; ACK = 0x00U, // Acknowledge
const uint8_t LC_SVC_OPT_BCAST = 0x08U; NACK = 0x01U, // Negative Acknowledge
const uint8_t LC_SVC_OPT_OVCM = 0x04U; ACK_RETRY = 0x02U // Acknowlege Retry
};
// Call Priorities };
const uint8_t CALL_PRIORITY_NONE = 0x00U;
const uint8_t CALL_PRIORITY_1 = 0x01U; /// <summary>
const uint8_t CALL_PRIORITY_2 = 0x02U; /// Data Response Type
const uint8_t CALL_PRIORITY_3 = 0x03U; /// </summary>
namespace PDUResponseType {
// FID_DMRA Extended Function Opcodes enum : uint8_t {
const uint32_t DMR_EXT_FNCT_CHECK = 0x0000U; // Radio Check ACK = 0x01U, // Acknowledge
const uint32_t DMR_EXT_FNCT_UNINHIBIT = 0x007EU; // Radio Uninhibit
const uint32_t DMR_EXT_FNCT_INHIBIT = 0x007FU; // Radio Inhibit NACK_ILLEGAL = 0x00U, // Illegal Format
const uint32_t DMR_EXT_FNCT_CHECK_ACK = 0x0080U; // Radio Check Ack NACK_PACKET_CRC = 0x01U, // Packet CRC
const uint32_t DMR_EXT_FNCT_UNINHIBIT_ACK = 0x00FEU; // Radio Uninhibit Ack NACK_MEMORY_FULL = 0x02U, // Memory Full
const uint32_t DMR_EXT_FNCT_INHIBIT_ACK = 0x00FFU; // Radio Inhibit Ack NACK_UNDELIVERABLE = 0x04U // Undeliverable
};
// Data Type(s) };
const uint8_t DT_VOICE_PI_HEADER = 0x00U;
#define DMR_DT_VOICE_PI_HEADER "DMR_DT_VOICE_PI_HEADER (Voice Header with Privacy Indicator)" /** Feature IDs */
const uint8_t DT_VOICE_LC_HEADER = 0x01U; const uint8_t FID_ETSI = 0x00U; // ETSI Standard Feature Set
#define DMR_DT_VOICE_LC_HEADER "DMR_DT_VOICE_LC_HEADER (Voice Header with Link Control)" const uint8_t FID_DMRA = 0x10U; // Motorola
const uint8_t DT_TERMINATOR_WITH_LC = 0x02U; const uint8_t FID_DVM_OCS = 0x9CU; // DVM; Omaha Communication Systems, LLC ($9C)
#define DMR_DT_TERMINATOR_WITH_LC "DMR_DT_TERMINATOR_WITH_LC (Terminator with Link Control)"
const uint8_t DT_CSBK = 0x03U; /** LC Service Options */
const uint8_t DT_MBC_HEADER = 0x04U; const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t DT_MBC_DATA = 0x05U; const uint8_t LC_SVC_OPT_PRIVACY = 0x40U;
const uint8_t DT_DATA_HEADER = 0x06U; const uint8_t LC_SVC_OPT_BCAST = 0x08U;
#define DMR_DT_DATA_HEADER "DMR_DT_DATA_HEADER (Data Header)" const uint8_t LC_SVC_OPT_OVCM = 0x04U;
const uint8_t DT_RATE_12_DATA = 0x07U;
#define DMR_DT_RATE_12_DATA "DMR_DT_RATE_12_DATA (1/2-rate Data)" /** Call Priorities */
const uint8_t DT_RATE_34_DATA = 0x08U; const uint8_t CALL_PRIORITY_NONE = 0x00U;
#define DMR_DT_RATE_34_DATA "DMR_DT_RATE_34_DATA (3/4-rate Data)" const uint8_t CALL_PRIORITY_1 = 0x01U;
const uint8_t DT_IDLE = 0x09U; const uint8_t CALL_PRIORITY_2 = 0x02U;
const uint8_t DT_RATE_1_DATA = 0x0AU; const uint8_t CALL_PRIORITY_3 = 0x03U;
#define DMR_DT_RATE_1_DATA "DMR_DT_RATE_1_DATA (1-rate Data)"
/// <summary>
/* /// Short-Link Control Opcode(s)
** Internal Data Type(s) /// </summary>
*/ namespace SLCO {
const uint8_t DT_VOICE_SYNC = 0xF0U; // Short-Link Control Opcode Enumeration
#define DMR_DT_VOICE_SYNC "DMR_DT_VOICE_SYNC (Voice Data with Sync)" enum E : uint8_t {
const uint8_t DT_VOICE = 0xF1U; NONE = 0x00U, // NULL
#define DMR_DT_VOICE "DMR_DT_VOICE (Voice Data)" ACT = 0x01U, //
TSCC = 0x02U, // TSCC
// Site Models PAYLOAD = 0x03U // Payload
const uint8_t SITE_MODEL_TINY = 0x00U; };
const uint8_t SITE_MODEL_SMALL = 0x01U; }
const uint8_t SITE_MODEL_LARGE = 0x02U;
const uint8_t SITE_MODEL_HUGE = 0x03U; /// <summary>
/// Full-Link Control Opcode(s)
// Target Address /// </summary>
const uint8_t TGT_ADRS_SYSCODE = 0x00U; namespace FLCO {
const uint8_t TGT_ADRS_TGID = 0x01U; // Full-Link Control Opcode Enumeration
enum E : uint8_t {
// Short-Link Control Opcode(s) GROUP = 0x00U, // GRP VCH USER - Group Voice Channel User
const uint8_t SLCO_NULL = 0x00U; PRIVATE = 0x03U, // UU VCH USER - Unit-to-Unit Voice Channel User
const uint8_t SLCO_ACT = 0x01U;
const uint8_t SLCO_TSCC = 0x02U; TALKER_ALIAS_HEADER = 0x04U, //
const uint8_t SLCO_PAYLOAD = 0x03U; TALKER_ALIAS_BLOCK1 = 0x05U, //
TALKER_ALIAS_BLOCK2 = 0x06U, //
// Reason Code(s) TALKER_ALIAS_BLOCK3 = 0x07U, //
const uint8_t TS_ACK_RSN_MSG = 0x60U; // TS - Message Accepted
const uint8_t TS_ACK_RSN_REG = 0x62U; // TS - Registration Accepted GPS_INFO = 0x08U, //
const uint8_t TS_ACK_RSN_AUTH_RESP = 0x64U; // TS - Authentication Challenge Response };
const uint8_t TS_ACK_RSN_REG_SUB_ATTACH = 0x65U; // TS - Registration Response with subscription }
const uint8_t MS_ACK_RSN_MSG = 0x44U; // MS - Message Accepted
const uint8_t MS_ACK_RSN_AUTH_RESP = 0x48U; // MS - Authentication Challenge Response /// <summary>
/// FID_DMRA Extended Functions.
const uint8_t TS_DENY_RSN_SYS_UNSUPPORTED_SVC = 0x20U; /// </summary>
const uint8_t TS_DENY_RSN_PERM_USER_REFUSED = 0x21U; namespace ExtendedFunctions {
const uint8_t TS_DENY_RSN_TEMP_USER_REFUSED = 0x22U; enum : uint16_t {
const uint8_t TS_DENY_RSN_TRSN_SYS_REFUSED = 0x23U; CHECK = 0x0000U, // Radio Check
const uint8_t TS_DENY_RSN_TGT_NOT_REG = 0x24U; UNINHIBIT = 0x007EU, // Radio Uninhibit
const uint8_t TS_DENY_RSN_TGT_UNAVAILABLE = 0x25U; INHIBIT = 0x007FU, // Radio Inhibit
const uint8_t TS_DENY_RSN_SYS_BUSY = 0x27U; CHECK_ACK = 0x0080U, // Radio Check Ack
const uint8_t TS_DENY_RSN_SYS_NOT_READY = 0x28U; UNINHIBIT_ACK = 0x00FEU, // Radio Uninhibit Ack
const uint8_t TS_DENY_RSN_CALL_CNCL_REFUSED = 0x29U; INHIBIT_ACK = 0x00FFU // Radio Inhibit Ack
const uint8_t TS_DENY_RSN_REG_REFUSED = 0x2AU; };
const uint8_t TS_DENY_RSN_REG_DENIED = 0x2BU; };
const uint8_t TS_DENY_RSN_MS_NOT_REG = 0x2DU;
const uint8_t TS_DENY_RSN_TGT_BUSY = 0x2EU; /// <summary>
const uint8_t TS_DENY_RSN_TGT_GROUP_NOT_VALID = 0x2FU; /// Data Type(s)
/// <summary>
const uint8_t TS_QUEUED_RSN_NO_RESOURCE = 0xA0U; namespace DataType {
const uint8_t TS_QUEUED_RSN_SYS_BUSY = 0xA1U; // Data Type Enumeration
enum E : uint8_t {
const uint8_t TS_WAIT_RSN = 0xE0U; VOICE_PI_HEADER = 0x00U, // Voice with Privacy Indicator Header
VOICE_LC_HEADER = 0x01U, // Voice with Link Control Header
const uint8_t MS_DENY_RSN_UNSUPPORTED_SVC = 0x00U;
TERMINATOR_WITH_LC = 0x02U, // Terminator with Link Control
// Random Access Service Kind
const uint8_t SVC_KIND_IND_VOICE_CALL = 0x00U; // Individual Voice Call CSBK = 0x03U, // CSBK
const uint8_t SVC_KIND_GRP_VOICE_CALL = 0x01U; // Group Voice Call
const uint8_t SVC_KIND_IND_DATA_CALL = 0x02U; // Individual Data Call MBC_HEADER = 0x04U, // Multi-Block Control Header
const uint8_t SVC_KIND_GRP_DATA_CALL = 0x03U; // Group Data Call MBC_DATA = 0x05U, // Multi-Block Control Data
const uint8_t SVC_KIND_IND_UDT_DATA_CALL = 0x04U; // Individual UDT Short Data Call
const uint8_t SVC_KIND_GRP_UDT_DATA_CALL = 0x05U; // Group UDT Short Data Call DATA_HEADER = 0x06U, // Data Header
const uint8_t SVC_KIND_UDT_SHORT_POLL = 0x06U; // UDT Short Data Polling Service RATE_12_DATA = 0x07U, // 1/2 Rate Data
const uint8_t SVC_KIND_STATUS_TRANSPORT = 0x07U; // Status Transport Service RATE_34_DATA = 0x08U, // 3/4 Rate Data
const uint8_t SVC_KIND_CALL_DIVERSION = 0x08U; // Call Diversion Service
const uint8_t SVC_KIND_CALL_ANSWER = 0x09U; // Call Answer Service IDLE = 0x09U, // Idle
const uint8_t SVC_KIND_SUPPLEMENTARY_SVC = 0x0DU; // Supplementary Service
const uint8_t SVC_KIND_REG_SVC = 0x0EU; // Registration Service RATE_1_DATA = 0x0AU, // Rate 1 Data
const uint8_t SVC_KIND_CANCEL_CALL = 0x0FU; // Cancel Call Service
/*
// Broadcast Announcement Type(s) ** Internal Data Type(s)
const uint8_t BCAST_ANNC_ANN_WD_TSCC = 0x00U; // Announce-WD TSCC Channel */
const uint8_t BCAST_ANNC_CALL_TIMER_PARMS = 0x01U; // Specify Call Timer Parameters
const uint8_t BCAST_ANNC_VOTE_NOW = 0x02U; // Vote Now Advice VOICE_SYNC = 0xF0U, // Internal - Voice Sync
const uint8_t BCAST_ANNC_LOCAL_TIME = 0x03U; // Broadcast Local Time VOICE = 0xF1U // Internal - Voice
const uint8_t BCAST_ANNC_MASS_REG = 0x04U; // Mass Registration };
const uint8_t BCAST_ANNC_CHAN_FREQ = 0x05U; // Logical Channel/Frequency }
const uint8_t BCAST_ANNC_ADJ_SITE = 0x06U; // Adjacent Site Information
const uint8_t BCAST_ANNC_SITE_PARMS = 0x07U; // General Site Parameters #define DMR_DT_VOICE_PI_HEADER "DMR, VOICE_PI_HEADER (Voice Header with Privacy Indicator)"
#define DMR_DT_VOICE_LC_HEADER "DMR, VOICE_LC_HEADER (Voice Header with Link Control)"
// Full-Link Control Opcode(s) #define DMR_DT_TERMINATOR_WITH_LC "DMR, TERMINATOR_WITH_LC (Terminator with Link Control)"
const uint8_t FLCO_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User #define DMR_DT_DATA_HEADER "DMR, DATA_HEADER (Data Header)"
const uint8_t FLCO_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User #define DMR_DT_RATE_12_DATA "DMR, RATE_12_DATA (1/2-rate Data)"
const uint8_t FLCO_TALKER_ALIAS_HEADER = 0x04U; // #define DMR_DT_RATE_34_DATA "DMR, RATE_34_DATA (3/4-rate Data)"
const uint8_t FLCO_TALKER_ALIAS_BLOCK1 = 0x05U; // #define DMR_DT_RATE_1_DATA "DMR, RATE_1_DATA (1-rate Data)"
const uint8_t FLCO_TALKER_ALIAS_BLOCK2 = 0x06U; //
const uint8_t FLCO_TALKER_ALIAS_BLOCK3 = 0x07U; // #define DMR_DT_VOICE_SYNC "DMR, VOICE_SYNC (Voice Data with Sync)"
const uint8_t FLCO_GPS_INFO = 0x08U; // #define DMR_DT_VOICE "DMR, VOICE (Voice Data)"
// Control Signalling Block Opcode(s) /// <summary>
const uint8_t CSBKO_NONE = 0x00U; // /// Site Models
const uint8_t CSBKO_UU_V_REQ = 0x04U; // UU VCH REQ - Unit-to-Unit Voice Channel Request /// </summary>
const uint8_t CSBKO_UU_ANS_RSP = 0x05U; // UU ANS RSP - Unit-to-Unit Answer Response namespace SiteModel {
const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK // Site Model Enumeration
const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDU for Random Access enum E : uint8_t {
const uint8_t CSBKO_AHOY = 0x1CU; // AHOY - Enquiry from TSCC TINY = 0x00U, // Tiny
const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert SMALL = 0x01U, // Small
const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response LARGE = 0x02U, // Large
const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function HUGE = 0x03U // Huge
const uint8_t CSBKO_NACK_RSP = 0x26U; // NACK RSP - Negative Acknowledgement Response };
const uint8_t CSBKO_BROADCAST = 0x28U; // BCAST - Announcement PDU }
const uint8_t CSBKO_MAINT = 0x2AU; // MAINT - Call Maintainence PDU
const uint8_t CSBKO_P_CLEAR = 0x2EU; // P_CLEAR - Payload Channel Clear // Target Address
const uint8_t CSBKO_PV_GRANT = 0x30U; // PV_GRANT - Private Voice Channel Grant const uint8_t TGT_ADRS_SYSCODE = 0x00U;
const uint8_t CSBKO_TV_GRANT = 0x31U; // TV_GRANT - Talkgroup Voice Channel Grant const uint8_t TGT_ADRS_TGID = 0x01U;
const uint8_t CSBKO_BTV_GRANT = 0x32U; // BTV_GRANT - Broadcast Talkgroup Voice Channel Grant
const uint8_t CSBKO_PD_GRANT = 0x33U; // PD_GRANT - Private Data Channel Grant /// <summary>
const uint8_t CSBKO_TD_GRANT = 0x34U; // TD_GRANT - Talkgroup Data Channel Grant /// Talker ID
const uint8_t CSBKO_BSDWNACT = 0x38U; // BS DWN ACT - BS Outbound Activation /// <summary>
const uint8_t CSBKO_PRECCSBK = 0x3DU; // PRE CSBK - Preamble CSBK namespace TalkerID {
enum : uint8_t {
const uint8_t CSBKO_DVM_GIT_HASH = 0x3FU; // NONE = 0x00U, // No Talker ID
const uint8_t TALKER_ID_NONE = 0x00U; HEADER = 0x01U, // Talker ID Header
const uint8_t TALKER_ID_HEADER = 0x01U;
const uint8_t TALKER_ID_BLOCK1 = 0x02U; BLOCK1 = 0x02U, // Talker ID Block 1
const uint8_t TALKER_ID_BLOCK2 = 0x04U; BLOCK2 = 0x04U, // Talker ID Block 2
const uint8_t TALKER_ID_BLOCK3 = 0x08U; BLOCK3 = 0x08U // Talker ID Block 3
};
const uint32_t NO_HEADERS_SIMPLEX = 8U; }
const uint32_t NO_HEADERS_DUPLEX = 3U;
const uint32_t NO_PREAMBLE_CSBK = 15U; /// <summary>
/// Reason Code(s)
/// <summary>
namespace ReasonCode {
enum : uint8_t {
TS_ACK_RSN_MSG = 0x60U, // TS - Message Accepted
TS_ACK_RSN_REG = 0x62U, // TS - Registration Accepted
TS_ACK_RSN_AUTH_RESP = 0x64U, // TS - Authentication Challenge Response
TS_ACK_RSN_REG_SUB_ATTACH = 0x65U, // TS - Registration Response with subscription
MS_ACK_RSN_MSG = 0x44U, // MS - Message Accepted
MS_ACK_RSN_AUTH_RESP = 0x48U, // MS - Authentication Challenge Response
TS_DENY_RSN_SYS_UNSUPPORTED_SVC = 0x20U,// System Unsupported Service
TS_DENY_RSN_PERM_USER_REFUSED = 0x21U, // User Permenantly Refused
TS_DENY_RSN_TEMP_USER_REFUSED = 0x22U, // User Temporarily Refused
TS_DENY_RSN_TRSN_SYS_REFUSED = 0x23U, // System Refused
TS_DENY_RSN_TGT_NOT_REG = 0x24U, // Target Not Registered
TS_DENY_RSN_TGT_UNAVAILABLE = 0x25U, // Target Unavailable
TS_DENY_RSN_SYS_BUSY = 0x27U, // System Busy
TS_DENY_RSN_SYS_NOT_READY = 0x28U, // System Not Ready
TS_DENY_RSN_CALL_CNCL_REFUSED = 0x29U, // Call Cancel Refused
TS_DENY_RSN_REG_REFUSED = 0x2AU, // Registration Refused
TS_DENY_RSN_REG_DENIED = 0x2BU, // Registration Denied
TS_DENY_RSN_MS_NOT_REG = 0x2DU, // MS Not Registered
TS_DENY_RSN_TGT_BUSY = 0x2EU, // Target Busy
TS_DENY_RSN_TGT_GROUP_NOT_VALID = 0x2FU,// Group Not Valid
TS_QUEUED_RSN_NO_RESOURCE = 0xA0U, // No Resources Available
TS_QUEUED_RSN_SYS_BUSY = 0xA1U, // System Busy
TS_WAIT_RSN = 0xE0U, // Wait
MS_DENY_RSN_UNSUPPORTED_SVC = 0x00U, // Service Unsupported
};
}
/// <summary>
/// Random Access Service Kind
/// </summary>
namespace ServiceKind {
enum : uint8_t {
IND_VOICE_CALL = 0x00U, // Individual Voice Call
GRP_VOICE_CALL = 0x01U, // Group Voice Call
IND_DATA_CALL = 0x02U, // Individual Data Call
GRP_DATA_CALL = 0x03U, // Group Data Call
IND_UDT_DATA_CALL = 0x04U, // Individual UDT Short Data Call
GRP_UDT_DATA_CALL = 0x05U, // Group UDT Short Data Call
UDT_SHORT_POLL = 0x06U, // UDT Short Data Polling Service
STATUS_TRANSPORT = 0x07U, // Status Transport Service
CALL_DIVERSION = 0x08U, // Call Diversion Service
CALL_ANSWER = 0x09U, // Call Answer Service
SUPPLEMENTARY_SVC = 0x0DU, // Supplementary Service
REG_SVC = 0x0EU, // Registration Service
CANCEL_CALL = 0x0FU // Cancel Call Service
};
}
/// <summary>
/// Broadcast Announcement Type(s)
/// </summary>
namespace BroadcastAnncType {
enum : uint8_t {
ANN_WD_TSCC = 0x00U, // Announce-Withdraw TSCC Channel
CALL_TIMER_PARMS = 0x01U, // Specify Call Timer Parameters
VOTE_NOW = 0x02U, // Vote Now Advice
LOCAL_TIME = 0x03U, // Broadcast Local Time
MASS_REG = 0x04U, // Mass Registration
CHAN_FREQ = 0x05U, // Logical Channel/Frequency
ADJ_SITE = 0x06U, // Adjacent Site Information
SITE_PARMS = 0x07U // General Site Parameters
};
}
/// <summary>
/// Control Signalling Block Opcode(s)
/// </summary>
namespace CSBKO {
enum : uint8_t {
// CSBK ISP/OSP Shared Opcode(s)
NONE = 0x00U, //
UU_V_REQ = 0x04U, // UU VCH REQ - Unit-to-Unit Voice Channel Request
UU_ANS_RSP = 0x05U, // UU ANS RSP - Unit-to-Unit Answer Response
CTCSBK = 0x07U, // CT CSBK - Channel Timing CSBK
ALOHA = 0x19U, // ALOHA - Aloha PDU for Random Access
AHOY = 0x1CU, // AHOY - Enquiry from TSCC
RAND = 0x1FU, // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
ACK_RSP = 0x20U, // ACK RSP - Acknowledge Response
EXT_FNCT = 0x24U, // (DMRA) EXT FNCT - Extended Function
NACK_RSP = 0x26U, // NACK RSP - Negative Acknowledgement Response
BROADCAST = 0x28U, // BCAST - Announcement PDU
MAINT = 0x2AU, // MAINT - Call Maintainence PDU
P_CLEAR = 0x2EU, // P_CLEAR - Payload Channel Clear
PV_GRANT = 0x30U, // PV_GRANT - Private Voice Channel Grant
TV_GRANT = 0x31U, // TV_GRANT - Talkgroup Voice Channel Grant
BTV_GRANT = 0x32U, // BTV_GRANT - Broadcast Talkgroup Voice Channel Grant
PD_GRANT = 0x33U, // PD_GRANT - Private Data Channel Grant
TD_GRANT = 0x34U, // TD_GRANT - Talkgroup Data Channel Grant
BSDWNACT = 0x38U, // BS DWN ACT - BS Outbound Activation
PRECCSBK = 0x3DU, // PRE CSBK - Preamble CSBK
// CSBK DVM Outbound Signalling Packet (OSP) Opcode(s)
DVM_GIT_HASH = 0x3FU //
};
}
} // namespace defines
} // namespace dmr } // namespace dmr
#endif // __DMR_DEFINES_H__ #endif // __DMR_DEFINES_H__

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_UTILS_H__) #if !defined(__DMR_UTILS_H__)
@ -26,6 +26,8 @@ namespace dmr
class HOST_SW_API DMRUtils { class HOST_SW_API DMRUtils {
public: public:
/// <summary>Helper to test and clamp a DMR color code.</summary> /// <summary>Helper to test and clamp a DMR color code.</summary>
/// <param name="colorCode">Color Code</param>
/// <returns>Clamped color code.</returns>
static uint32_t colorCode(uint32_t colorCode) static uint32_t colorCode(uint32_t colorCode)
{ {
if (colorCode < 0U) { // clamp to 0 if (colorCode < 0U) { // clamp to 0
@ -39,36 +41,40 @@ namespace dmr
} }
/// <summary>Helper to test and clamp a DMR site ID.</summary> /// <summary>Helper to test and clamp a DMR site ID.</summary>
static uint32_t siteId(uint32_t id, uint8_t siteModel) /// <param name="id">Site ID</param>
/// <param name="siteModel">Site Model</param>
/// <returns>Clamped site ID.</returns>
static uint32_t siteId(uint32_t id, defines::SiteModel::E siteModel)
{ {
using namespace dmr::defines;
if (id > 0U) { if (id > 0U) {
id--; id--;
} }
switch (siteModel) switch (siteModel)
{ {
case SITE_MODEL_TINY: case SiteModel::TINY:
{ {
if (id > 0x07U) { // clamp to $7 if (id > 0x07U) { // clamp to $7
id = 0x07U; id = 0x07U;
} }
} }
break; break;
case SITE_MODEL_SMALL: case SiteModel::SMALL:
{ {
if (id > 0x1FU) { // clamp to $1F if (id > 0x1FU) { // clamp to $1F
id = 0x1FU; id = 0x1FU;
} }
} }
break; break;
case SITE_MODEL_LARGE: case SiteModel::LARGE:
{ {
if (id > 0x7FU) { // clamp to $7F if (id > 0x7FU) { // clamp to $7F
id = 0x7FU; id = 0x7FU;
} }
} }
break; break;
case SITE_MODEL_HUGE: case SiteModel::HUGE:
{ {
if (id > 0x3FFU) { // clamp to $3FF if (id > 0x3FFU) { // clamp to $3FF
id = 0x3FFU; id = 0x3FFU;
@ -81,31 +87,35 @@ namespace dmr
} }
/// <summary>Helper to test and clamp a DMR network ID.</summary> /// <summary>Helper to test and clamp a DMR network ID.</summary>
static uint32_t netId(uint32_t id, uint8_t siteModel) /// <param name="id">Network ID</param>
/// <param name="siteModel">Site Model</param>
/// <returns>Clamped network ID.</returns>
static uint32_t netId(uint32_t id, defines::SiteModel::E siteModel)
{ {
using namespace dmr::defines;
switch (siteModel) { switch (siteModel) {
case SITE_MODEL_TINY: case SiteModel::TINY:
{ {
if (id > 0x1FFU) { // clamp to $1FF if (id > 0x1FFU) { // clamp to $1FF
id = 0x1FFU; id = 0x1FFU;
} }
} }
break; break;
case SITE_MODEL_SMALL: case SiteModel::SMALL:
{ {
if (id > 0x7FU) { // clamp to $7F if (id > 0x7FU) { // clamp to $7F
id = 0x7FU; id = 0x7FU;
} }
} }
break; break;
case SITE_MODEL_LARGE: case SiteModel::LARGE:
{ {
if (id > 0x1FU) { // clamp to $1F if (id > 0x1FU) { // clamp to $1F
id = 0x1FU; id = 0x1FU;
} }
} }
break; break;
case SITE_MODEL_HUGE: case SiteModel::HUGE:
{ {
if (id > 0x03U) { // clamp to $3 if (id > 0x03U) { // clamp to $3
id = 0x03U; id = 0x03U;

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_SITE_DATA_H__) #if !defined(__DMR_SITE_DATA_H__)
@ -28,7 +28,7 @@ namespace dmr
public: public:
/// <summary>Initializes a new instance of the SiteData class.</summary> /// <summary>Initializes a new instance of the SiteData class.</summary>
SiteData() : SiteData() :
m_siteModel(SITE_MODEL_SMALL), m_siteModel(defines::SiteModel::SMALL),
m_netId(1U), m_netId(1U),
m_siteId(1U), m_siteId(1U),
m_parId(3U), m_parId(3U),
@ -43,7 +43,7 @@ namespace dmr
/// <param name="siteId">DMR Site ID.</param> /// <param name="siteId">DMR Site ID.</param>
/// <param name="parId">DMR partition ID.</param> /// <param name="parId">DMR partition ID.</param>
/// <param name="requireReg"></param> /// <param name="requireReg"></param>
SiteData(uint8_t siteModel, uint16_t netId, uint16_t siteId, uint8_t parId, bool requireReq) : SiteData(defines::SiteModel::E siteModel, uint16_t netId, uint16_t siteId, uint8_t parId, bool requireReq) :
m_siteModel(siteModel), m_siteModel(siteModel),
m_netId(netId), m_netId(netId),
m_siteId(siteId), m_siteId(siteId),
@ -51,9 +51,10 @@ namespace dmr
m_requireReg(requireReq), m_requireReg(requireReq),
m_netActive(false) m_netActive(false)
{ {
using namespace dmr::defines;
// siteModel clamping // siteModel clamping
if (siteModel > SITE_MODEL_HUGE) if (siteModel > SiteModel::HUGE)
siteModel = SITE_MODEL_SMALL; siteModel = SiteModel::SMALL;
// netId clamping // netId clamping
m_netId = DMRUtils::netId(netId, siteModel); m_netId = DMRUtils::netId(netId, siteModel);
@ -80,29 +81,30 @@ namespace dmr
/// <returns></returns> /// <returns></returns>
const uint32_t systemIdentity(bool msb = false) const uint32_t systemIdentity(bool msb = false)
{ {
using namespace dmr::defines;
uint32_t value = m_siteModel; uint32_t value = m_siteModel;
switch (m_siteModel) switch (m_siteModel)
{ {
case SITE_MODEL_TINY: case SiteModel::TINY:
{ {
value = (value << 9) + (m_netId & 0x1FFU); value = (value << 9) + (m_netId & 0x1FFU);
value = (value << 3) + (m_siteId & 0x07U); value = (value << 3) + (m_siteId & 0x07U);
} }
break; break;
case SITE_MODEL_SMALL: case SiteModel::SMALL:
{ {
value = (value << 7) + (m_netId & 0x7FU); value = (value << 7) + (m_netId & 0x7FU);
value = (value << 5) + (m_siteId & 0x1FU); value = (value << 5) + (m_siteId & 0x1FU);
} }
break; break;
case SITE_MODEL_LARGE: case SiteModel::LARGE:
{ {
value = (value << 5) + (m_netId & 0x1FU); value = (value << 5) + (m_netId & 0x1FU);
value = (value << 7) + (m_siteId & 0x7FU); value = (value << 7) + (m_siteId & 0x7FU);
} }
break; break;
case SITE_MODEL_HUGE: case SiteModel::HUGE:
{ {
value = (value << 2) + (m_netId & 0x03U); value = (value << 2) + (m_netId & 0x03U);
value = (value << 10) + (m_siteId & 0x3FFU); value = (value << 10) + (m_siteId & 0x3FFU);
@ -138,7 +140,7 @@ namespace dmr
public: public:
/// <summary>DMR site model type.</summary> /// <summary>DMR site model type.</summary>
__READONLY_PROPERTY_PLAIN(uint8_t, siteModel); __READONLY_PROPERTY_PLAIN(defines::SiteModel::E, siteModel);
/// <summary>DMR site network ID.</summary> /// <summary>DMR site network ID.</summary>
__READONLY_PROPERTY_PLAIN(uint16_t, netId); __READONLY_PROPERTY_PLAIN(uint16_t, netId);
/// <summary>DMR site ID.</summary> /// <summary>DMR site ID.</summary>

@ -9,12 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "common/dmr/SlotType.h" #include "common/dmr/SlotType.h"
#include "common/edac/Golay2087.h" #include "common/edac/Golay2087.h"
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
#include <cassert> #include <cassert>
@ -27,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
SlotType::SlotType() : SlotType::SlotType() :
m_colorCode(0U), m_colorCode(0U),
m_dataType(0U) m_dataType(DataType::IDLE)
{ {
/* stub */ /* stub */
} }
@ -45,20 +47,20 @@ void SlotType::decode(const uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
uint8_t DMRSlotType[3U]; uint8_t slotType[3U];
DMRSlotType[0U] = (data[12U] << 2) & 0xFCU; slotType[0U] = (data[12U] << 2) & 0xFCU;
DMRSlotType[0U] |= (data[13U] >> 6) & 0x03U; slotType[0U] |= (data[13U] >> 6) & 0x03U;
DMRSlotType[1U] = (data[13U] << 2) & 0xC0U; slotType[1U] = (data[13U] << 2) & 0xC0U;
DMRSlotType[1U] |= (data[19U] << 2) & 0x3CU; slotType[1U] |= (data[19U] << 2) & 0x3CU;
DMRSlotType[1U] |= (data[20U] >> 6) & 0x03U; slotType[1U] |= (data[20U] >> 6) & 0x03U;
DMRSlotType[2U] = (data[20U] << 2) & 0xF0U; slotType[2U] = (data[20U] << 2) & 0xF0U;
uint8_t code = edac::Golay2087::decode(DMRSlotType); uint8_t code = edac::Golay2087::decode(slotType);
m_colorCode = (code >> 4) & 0x0FU; m_colorCode = (code >> 4) & 0x0FU;
m_dataType = (code >> 0) & 0x0FU; m_dataType = (DataType::E)((code >> 0) & 0x0FU);
} }
/// <summary> /// <summary>
@ -69,16 +71,16 @@ void SlotType::encode(uint8_t* data) const
{ {
assert(data != nullptr); assert(data != nullptr);
uint8_t DMRSlotType[3U]; uint8_t slotType[3U];
DMRSlotType[0U] = (m_colorCode << 4) & 0xF0U; slotType[0U] = (m_colorCode << 4) & 0xF0U;
DMRSlotType[0U] |= (m_dataType << 0) & 0x0FU; slotType[0U] |= (m_dataType << 0) & 0x0FU;
DMRSlotType[1U] = 0x00U; slotType[1U] = 0x00U;
DMRSlotType[2U] = 0x00U; slotType[2U] = 0x00U;
edac::Golay2087::encode(DMRSlotType); edac::Golay2087::encode(slotType);
data[12U] = (data[12U] & 0xC0U) | ((DMRSlotType[0U] >> 2) & 0x3FU); data[12U] = (data[12U] & 0xC0U) | ((slotType[0U] >> 2) & 0x3FU);
data[13U] = (data[13U] & 0x0FU) | ((DMRSlotType[0U] << 6) & 0xC0U) | ((DMRSlotType[1U] >> 2) & 0x30U); data[13U] = (data[13U] & 0x0FU) | ((slotType[0U] << 6) & 0xC0U) | ((slotType[1U] >> 2) & 0x30U);
data[19U] = (data[19U] & 0xF0U) | ((DMRSlotType[1U] >> 2) & 0x0FU); data[19U] = (data[19U] & 0xF0U) | ((slotType[1U] >> 2) & 0x0FU);
data[20U] = (data[20U] & 0x03U) | ((DMRSlotType[1U] << 6) & 0xC0U) | ((DMRSlotType[2U] >> 2) & 0x3CU); data[20U] = (data[20U] & 0x03U) | ((slotType[1U] << 6) & 0xC0U) | ((slotType[2U] >> 2) & 0x3CU);
} }

@ -9,12 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_SLOT_TYPE_H__) #if !defined(__DMR_SLOT_TYPE_H__)
#define __DMR_SLOT_TYPE_H__ #define __DMR_SLOT_TYPE_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
namespace dmr namespace dmr
{ {
@ -40,7 +42,7 @@ namespace dmr
__PROPERTY(uint8_t, colorCode, ColorCode); __PROPERTY(uint8_t, colorCode, ColorCode);
/// <summary>Slot data type.</summary> /// <summary>Slot data type.</summary>
__PROPERTY(uint8_t, dataType, DataType); __PROPERTY(defines::DataType::E, dataType, DataType);
}; };
} // namespace dmr } // namespace dmr

@ -16,6 +16,7 @@
#include "dmr/Sync.h" #include "dmr/Sync.h"
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
#include <cassert> #include <cassert>

@ -9,14 +9,16 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/DMRDefines.h" #include "dmr/DMRDefines.h"
#include "dmr/data/Data.h" #include "dmr/data/Data.h"
using namespace dmr::data;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::data;
#include <cstring> #include <cstring>
#include <cassert> #include <cassert>
@ -52,10 +54,10 @@ Data::Data() :
m_slotNo(1U), m_slotNo(1U),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_flco(FLCO_GROUP), m_flco(FLCO::GROUP),
m_n(0U), m_n(0U),
m_seqNo(0U), m_seqNo(0U),
m_dataType(0U), m_dataType(DataType::IDLE),
m_ber(0U), m_ber(0U),
m_rssi(0U), m_rssi(0U),
m_data(nullptr) m_data(nullptr)

@ -9,12 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_DATA__DATA_H__) #if !defined(__DMR_DATA__DATA_H__)
#define __DMR_DATA__DATA_H__ #define __DMR_DATA__DATA_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
namespace dmr namespace dmr
{ {
@ -52,7 +54,7 @@ namespace dmr
__PROPERTY(uint32_t, dstId, DstId); __PROPERTY(uint32_t, dstId, DstId);
/// <summary>Sets the full-link control opcode.</summary> /// <summary>Sets the full-link control opcode.</summary>
__PROPERTY(uint8_t, flco, FLCO); __PROPERTY(defines::FLCO::E, flco, FLCO);
/// <summary></summary> /// <summary></summary>
__PROPERTY(uint8_t, n, N); __PROPERTY(uint8_t, n, N);
@ -61,7 +63,7 @@ namespace dmr
__PROPERTY(uint8_t, seqNo, SeqNo); __PROPERTY(uint8_t, seqNo, SeqNo);
/// <summary>Embedded data type.</summary> /// <summary>Embedded data type.</summary>
__PROPERTY(uint8_t, dataType, DataType); __PROPERTY(defines::DataType::E, dataType, DataType);
/// <summary>Bit Error Rate.</summary> /// <summary>Bit Error Rate.</summary>
__PROPERTY(uint8_t, ber, BER); __PROPERTY(uint8_t, ber, BER);

@ -10,7 +10,7 @@
* *
* Copyright (C) 2012 Ian Wraith * Copyright (C) 2012 Ian Wraith
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2021,2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2023,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -20,8 +20,9 @@
#include "edac/CRC.h" #include "edac/CRC.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::data;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::data;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -41,7 +42,7 @@ const uint8_t UDTF_NMEA = 0x05U;
/// </summary> /// </summary>
DataHeader::DataHeader() : DataHeader::DataHeader() :
m_GI(false), m_GI(false),
m_DPF(DPF_UDT), m_DPF(DPF::UDT),
m_sap(0U), m_sap(0U),
m_fsn(0U), m_fsn(0U),
m_Ns(0U), m_Ns(0U),
@ -52,8 +53,8 @@ DataHeader::DataHeader() :
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_blocks(0U), m_blocks(0U),
m_rspClass(PDU_ACK_CLASS_NACK), m_rspClass(PDUResponseClass::NACK),
m_rspType(PDU_ACK_TYPE_NACK_ILLEGAL), m_rspType(PDUResponseType::NACK_ILLEGAL),
m_rspStatus(0U), m_rspStatus(0U),
m_srcPort(0U), m_srcPort(0U),
m_dstPort(0U), m_dstPort(0U),
@ -141,15 +142,15 @@ bool DataHeader::decode(const uint8_t* data)
m_GI = (m_data[0U] & 0x80U) == 0x80U; // Group/Individual Flag m_GI = (m_data[0U] & 0x80U) == 0x80U; // Group/Individual Flag
m_A = (m_data[0U] & 0x40U) == 0x40U; m_A = (m_data[0U] & 0x40U) == 0x40U;
m_DPF = m_data[0U] & 0x0FU; // Data Packet Format m_DPF = (DPF::E)(m_data[0U] & 0x0FU); // Data Packet Format
if (m_DPF == DPF_PROPRIETARY) if (m_DPF == DPF::PROPRIETARY)
return true; return true;
m_dstId = m_data[2U] << 16 | m_data[3U] << 8 | m_data[4U]; // Destination ID m_dstId = m_data[2U] << 16 | m_data[3U] << 8 | m_data[4U]; // Destination ID
m_srcId = m_data[5U] << 16 | m_data[6U] << 8 | m_data[7U]; // Source ID m_srcId = m_data[5U] << 16 | m_data[6U] << 8 | m_data[7U]; // Source ID
switch (m_DPF) { switch (m_DPF) {
case DPF_UDT: case DPF::UDT:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Unified Data Transport Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Unified Data Transport Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -162,7 +163,7 @@ bool DataHeader::decode(const uint8_t* data)
m_UDTO = m_data[9U] & 0x3FU; // UDT Opcode m_UDTO = m_data[9U] & 0x3FU; // UDT Opcode
break; break;
case DPF_UNCONFIRMED_DATA: case DPF::UNCONFIRMED_DATA:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Unconfirmed Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Unconfirmed Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -173,7 +174,7 @@ bool DataHeader::decode(const uint8_t* data)
m_fsn = m_data[9U] & 0x0FU; // Fragment Sequence Number m_fsn = m_data[9U] & 0x0FU; // Fragment Sequence Number
break; break;
case DPF_CONFIRMED_DATA: case DPF::CONFIRMED_DATA:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Confirmed Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Confirmed Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -186,7 +187,7 @@ bool DataHeader::decode(const uint8_t* data)
m_fsn = m_data[9U] & 0x0FU; // Fragement Sequence Number m_fsn = m_data[9U] & 0x0FU; // Fragement Sequence Number
break; break;
case DPF_RESPONSE: case DPF::RESPONSE:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Response Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Response Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -197,7 +198,7 @@ bool DataHeader::decode(const uint8_t* data)
m_rspStatus = m_data[9U] & 0x07U; // Response Status m_rspStatus = m_data[9U] & 0x07U; // Response Status
break; break;
case DPF_DEFINED_SHORT: case DPF::DEFINED_SHORT:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Defined Short Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Defined Short Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -209,7 +210,7 @@ bool DataHeader::decode(const uint8_t* data)
m_padCount = m_data[9U]; // Bit Padding m_padCount = m_data[9U]; // Bit Padding
break; break;
case DPF_DEFINED_RAW: case DPF::DEFINED_RAW:
#if DEBUG_DMR_PDU_DATA #if DEBUG_DMR_PDU_DATA
Utils::dump(1U, "DMR, DataHeader::decode(), Raw Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(1U, "DMR, DataHeader::decode(), Raw Data Header", m_data, DMR_LC_HEADER_LENGTH_BYTES);
#endif #endif
@ -238,7 +239,7 @@ void DataHeader::encode(uint8_t* data) const
assert(data != nullptr); assert(data != nullptr);
// perform no processing other then regenerating FEC // perform no processing other then regenerating FEC
if (m_DPF == DPF_PROPRIETARY) { if (m_DPF == DPF::PROPRIETARY) {
m_data[10U] = m_data[11U] = 0x00U; m_data[10U] = m_data[11U] = 0x00U;
// compute CRC-CCITT 16 // compute CRC-CCITT 16
@ -272,7 +273,7 @@ void DataHeader::encode(uint8_t* data) const
m_data[7U] = (m_srcId >> 0) & 0xFFU; m_data[7U] = (m_srcId >> 0) & 0xFFU;
switch (m_DPF) { switch (m_DPF) {
case DPF_UDT: case DPF::UDT:
m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point
(m_dataFormat & 0x0FU); // UDT Format (m_dataFormat & 0x0FU); // UDT Format
m_data[8U] = ((m_padCount & 0x1FU) << 3) + // Pad Nibble m_data[8U] = ((m_padCount & 0x1FU) << 3) + // Pad Nibble
@ -285,7 +286,7 @@ void DataHeader::encode(uint8_t* data) const
#endif #endif
break; break;
case DPF_UNCONFIRMED_DATA: case DPF::UNCONFIRMED_DATA:
m_data[0U] = m_data[0U] + (m_padCount & 0x10U); // Octet Pad Count MSB m_data[0U] = m_data[0U] + (m_padCount & 0x10U); // Octet Pad Count MSB
m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point
(m_padCount & 0x0FU); // Octet Pad Count LSB (m_padCount & 0x0FU); // Octet Pad Count LSB
@ -297,7 +298,7 @@ void DataHeader::encode(uint8_t* data) const
#endif #endif
break; break;
case DPF_CONFIRMED_DATA: case DPF::CONFIRMED_DATA:
m_data[0U] = m_data[0U] + (m_padCount & 0x10U); // Octet Pad Count MSB m_data[0U] = m_data[0U] + (m_padCount & 0x10U); // Octet Pad Count MSB
m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point
(m_padCount & 0x0FU); // Octet Pad Count LSB (m_padCount & 0x0FU); // Octet Pad Count LSB
@ -311,7 +312,7 @@ void DataHeader::encode(uint8_t* data) const
#endif #endif
break; break;
case DPF_RESPONSE: case DPF::RESPONSE:
m_data[1U] = ((m_sap & 0x0FU) << 4); // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4); // Service Access Point
m_data[8U] = m_blocks & 0x7FU; // Blocks To Follow m_data[8U] = m_blocks & 0x7FU; // Blocks To Follow
m_data[9U] = ((m_rspClass & 0x03U) << 6) + // Response Class m_data[9U] = ((m_rspClass & 0x03U) << 6) + // Response Class
@ -322,7 +323,7 @@ void DataHeader::encode(uint8_t* data) const
#endif #endif
break; break;
case DPF_DEFINED_SHORT: case DPF::DEFINED_SHORT:
m_data[0U] = m_data[0U] + (m_blocks & 0x30U); // Blocks To Follow MSB m_data[0U] = m_data[0U] + (m_blocks & 0x30U); // Blocks To Follow MSB
m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point
(m_blocks & 0x0FU); // Blocks To Follow LSB (m_blocks & 0x0FU); // Blocks To Follow LSB
@ -335,7 +336,7 @@ void DataHeader::encode(uint8_t* data) const
#endif #endif
break; break;
case DPF_DEFINED_RAW: case DPF::DEFINED_RAW:
m_data[0U] = m_data[0U] + (m_blocks & 0x30U); // Blocks To Follow MSB m_data[0U] = m_data[0U] + (m_blocks & 0x30U); // Blocks To Follow MSB
m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point m_data[1U] = ((m_sap & 0x0FU) << 4) + // Service Access Point
(m_blocks & 0x0FU); // Blocks To Follow LSB (m_blocks & 0x0FU); // Blocks To Follow LSB
@ -353,7 +354,7 @@ void DataHeader::encode(uint8_t* data) const
break; break;
} }
if (m_DPF == DPF_UDT) { if (m_DPF == DPF::UDT) {
m_data[9U] &= 0xFEU; m_data[9U] &= 0xFEU;
edac::CRC::addCCITT162(m_data, DMR_LC_HEADER_LENGTH_BYTES); edac::CRC::addCCITT162(m_data, DMR_LC_HEADER_LENGTH_BYTES);

@ -45,8 +45,8 @@ namespace dmr
/// <summary>Flag indicating whether the CSBK is group or individual.</summary> /// <summary>Flag indicating whether the CSBK is group or individual.</summary>
__PROPERTY(bool, GI, GI); __PROPERTY(bool, GI, GI);
/// <summary></summary> /// <summary>Data packet format.</summary>
__PROPERTY(uint8_t, DPF, DPF); __PROPERTY(defines::DPF::E, DPF, DPF);
/// <summary>Service access point.</summary> /// <summary>Service access point.</summary>
__PROPERTY(uint8_t, sap, SAP); __PROPERTY(uint8_t, sap, SAP);

@ -9,6 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -18,8 +19,9 @@
#include "edac/CRC.h" #include "edac/CRC.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::data;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::data;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -34,7 +36,7 @@ using namespace dmr;
/// </summary> /// </summary>
EmbeddedData::EmbeddedData() : EmbeddedData::EmbeddedData() :
m_valid(false), m_valid(false),
m_FLCO(FLCO_GROUP), m_FLCO(FLCO::GROUP),
m_state(LCS_NONE), m_state(LCS_NONE),
m_data(nullptr), m_data(nullptr),
m_raw(nullptr) m_raw(nullptr)
@ -195,7 +197,7 @@ std::unique_ptr<lc::LC> EmbeddedData::getLC() const
if (!m_valid) if (!m_valid)
return nullptr; return nullptr;
if (m_FLCO != FLCO_GROUP && m_FLCO != FLCO_PRIVATE) if (m_FLCO != FLCO::GROUP && m_FLCO != FLCO::PRIVATE)
return nullptr; return nullptr;
return std::make_unique<lc::LC>(m_data); return std::make_unique<lc::LC>(m_data);
@ -303,7 +305,7 @@ void EmbeddedData::decodeEmbeddedData()
// extract the FLCO // extract the FLCO
uint8_t flco; uint8_t flco;
Utils::bitsToByteBE(m_data + 0U, flco); Utils::bitsToByteBE(m_data + 0U, flco);
m_FLCO = flco & 0x3FU; m_FLCO = (FLCO::E)(flco & 0x3FU);
} }
/// <summary> /// <summary>

@ -9,12 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkap, N2PLL
* *
*/ */
#if !defined(__DMR_DATA__EMBEDDED_DATA_H__) #if !defined(__DMR_DATA__EMBEDDED_DATA_H__)
#define __DMR_DATA__EMBEDDED_DATA_H__ #define __DMR_DATA__EMBEDDED_DATA_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/LC.h" #include "common/dmr/lc/LC.h"
namespace dmr namespace dmr
@ -64,7 +66,7 @@ namespace dmr
/// <summary>Flag indicating whether or not the embedded data is valid.</summary> /// <summary>Flag indicating whether or not the embedded data is valid.</summary>
__READONLY_PROPERTY_PLAIN(bool, valid); __READONLY_PROPERTY_PLAIN(bool, valid);
/// <summary>Full-link control opcode.</summary> /// <summary>Full-link control opcode.</summary>
__READONLY_PROPERTY(uint8_t, FLCO, FLCO); __READONLY_PROPERTY(defines::FLCO::E, FLCO, FLCO);
private: private:
LC_STATE m_state; LC_STATE m_state;

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2019-2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2019-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -19,8 +19,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
#include <cassert> #include <cassert>
@ -52,14 +53,14 @@ CSBK::CSBK() :
m_colorCode(0U), m_colorCode(0U),
m_lastBlock(true), m_lastBlock(true),
m_Cdef(false), m_Cdef(false),
m_CSBKO(CSBKO_NONE), m_CSBKO(CSBKO::NONE),
m_FID(0x00U), m_FID(0x00U),
m_GI(false), m_GI(false),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_dataContent(false), m_dataContent(false),
m_CBF(0U), m_CBF(0U),
m_dataType(DT_CSBK), m_dataType(DataType::CSBK),
m_emergency(false), m_emergency(false),
m_privacy(false), m_privacy(false),
m_supplementData(false), m_supplementData(false),
@ -93,7 +94,7 @@ CSBK::~CSBK()
/// <returns></returns> /// <returns></returns>
std::string CSBK::toString() std::string CSBK::toString()
{ {
return std::string("CSBKO_UNKWN (Unknown CSBK)"); return std::string("CSBKO, UNKNOWN (Unknown CSBK)");
} }
/// <summary> /// <summary>
@ -123,57 +124,69 @@ bool CSBK::regenerate(uint8_t* data, uint8_t dataType)
// validate the CRC-CCITT 16 // validate the CRC-CCITT 16
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::regenerate(), unhandled dataType = $%02X", dataType);
break;
} }
bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES); bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES);
if (!valid) { if (!valid) {
LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check"); LogError(LOG_DMR, "CSBK::regenerate(), failed CRC CCITT-162 check");
return false; return false;
} }
// restore the checksum // restore the checksum
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::regenerate(), unhandled dataType = $%02X", dataType);
break;
} }
// calculate checksum // calculate checksum
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::regenerate(), unhandled dataType = $%02X", dataType);
break;
} }
edac::CRC::addCCITT162(csbk, 12U); edac::CRC::addCCITT162(csbk, 12U);
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::regenerate(), unhandled dataType = $%02X", dataType);
break;
} }
// encode BPTC (196,96) FEC // encode BPTC (196,96) FEC
@ -251,14 +264,17 @@ bool CSBK::decode(const uint8_t* data, uint8_t* payload)
// validate the CRC-CCITT 16 // validate the CRC-CCITT 16
switch (m_dataType) { switch (m_dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::decode(), unhandled dataType = $%02X", m_dataType);
break;
} }
bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES); bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES);
@ -269,14 +285,17 @@ bool CSBK::decode(const uint8_t* data, uint8_t* payload)
// restore the checksum // restore the checksum
switch (m_dataType) { switch (m_dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::decode(), unhandled dataType = $%02X", m_dataType);
break;
} }
if (m_verbose) { if (m_verbose) {
@ -321,27 +340,33 @@ void CSBK::encode(uint8_t* data, const uint8_t* payload)
} }
switch (m_dataType) { switch (m_dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::encoded(), unhandled dataType = $%02X", m_dataType);
break;
} }
edac::CRC::addCCITT162(csbk, 12U); edac::CRC::addCCITT162(csbk, 12U);
switch (m_dataType) { switch (m_dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBK::encode(), unhandled dataType = $%02X", m_dataType);
break;
} }
if (m_verbose) { if (m_verbose) {

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2019-2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2019-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_LC__CSBK_H__) #if !defined(__DMR_LC__CSBK_H__)
#define __DMR_LC__CSBK_H__ #define __DMR_LC__CSBK_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/SiteData.h" #include "common/dmr/SiteData.h"
#include "common/lookups/IdenTableLookup.h" #include "common/lookups/IdenTableLookup.h"
#include "common/Utils.h" #include "common/Utils.h"
@ -95,7 +96,7 @@ namespace dmr
__PROTECTED_PROPERTY(uint8_t, CBF, CBF); __PROTECTED_PROPERTY(uint8_t, CBF, CBF);
/// <summary>Data type for this CSBK.</summary> /// <summary>Data type for this CSBK.</summary>
__PROTECTED_PROPERTY(uint8_t, dataType, DataType); __PROTECTED_PROPERTY(defines::DataType::E, dataType, DataType);
/** Common Service Options */ /** Common Service Options */
/// <summary>Flag indicating the emergency bits are set.</summary> /// <summary>Flag indicating the emergency bits are set.</summary>

@ -10,7 +10,7 @@
* *
* Copyright (C) 2012 Ian Wraith * Copyright (C) 2012 Ian Wraith
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -20,8 +20,9 @@
#include "edac/CRC.h" #include "edac/CRC.h"
#include "Log.h" #include "Log.h"
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
#include <cassert> #include <cassert>
#include <memory> #include <memory>
@ -50,7 +51,7 @@ FullLC::~FullLC() = default;
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="type"></param> /// <param name="type"></param>
/// <returns></returns> /// <returns></returns>
std::unique_ptr<LC> FullLC::decode(const uint8_t* data, uint8_t type) std::unique_ptr<LC> FullLC::decode(const uint8_t* data, DataType::E type)
{ {
assert(data != nullptr); assert(data != nullptr);
@ -59,13 +60,13 @@ std::unique_ptr<LC> FullLC::decode(const uint8_t* data, uint8_t type)
m_bptc.decode(data, lcData); m_bptc.decode(data, lcData);
switch (type) { switch (type) {
case DT_VOICE_LC_HEADER: case DataType::VOICE_LC_HEADER:
lcData[9U] ^= VOICE_LC_HEADER_CRC_MASK[0U]; lcData[9U] ^= VOICE_LC_HEADER_CRC_MASK[0U];
lcData[10U] ^= VOICE_LC_HEADER_CRC_MASK[1U]; lcData[10U] ^= VOICE_LC_HEADER_CRC_MASK[1U];
lcData[11U] ^= VOICE_LC_HEADER_CRC_MASK[2U]; lcData[11U] ^= VOICE_LC_HEADER_CRC_MASK[2U];
break; break;
case DT_TERMINATOR_WITH_LC: case DataType::TERMINATOR_WITH_LC:
lcData[9U] ^= TERMINATOR_WITH_LC_CRC_MASK[0U]; lcData[9U] ^= TERMINATOR_WITH_LC_CRC_MASK[0U];
lcData[10U] ^= TERMINATOR_WITH_LC_CRC_MASK[1U]; lcData[10U] ^= TERMINATOR_WITH_LC_CRC_MASK[1U];
lcData[11U] ^= TERMINATOR_WITH_LC_CRC_MASK[2U]; lcData[11U] ^= TERMINATOR_WITH_LC_CRC_MASK[2U];
@ -89,7 +90,7 @@ std::unique_ptr<LC> FullLC::decode(const uint8_t* data, uint8_t type)
/// <param name="lc"></param> /// <param name="lc"></param>
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="type"></param> /// <param name="type"></param>
void FullLC::encode(const LC& lc, uint8_t* data, uint8_t type) void FullLC::encode(const LC& lc, uint8_t* data, DataType::E type)
{ {
assert(data != nullptr); assert(data != nullptr);
@ -101,13 +102,13 @@ void FullLC::encode(const LC& lc, uint8_t* data, uint8_t type)
edac::RS129::encode(lcData, 9U, parity); edac::RS129::encode(lcData, 9U, parity);
switch (type) { switch (type) {
case DT_VOICE_LC_HEADER: case DataType::VOICE_LC_HEADER:
lcData[9U] = parity[2U] ^ VOICE_LC_HEADER_CRC_MASK[0U]; lcData[9U] = parity[2U] ^ VOICE_LC_HEADER_CRC_MASK[0U];
lcData[10U] = parity[1U] ^ VOICE_LC_HEADER_CRC_MASK[1U]; lcData[10U] = parity[1U] ^ VOICE_LC_HEADER_CRC_MASK[1U];
lcData[11U] = parity[0U] ^ VOICE_LC_HEADER_CRC_MASK[2U]; lcData[11U] = parity[0U] ^ VOICE_LC_HEADER_CRC_MASK[2U];
break; break;
case DT_TERMINATOR_WITH_LC: case DataType::TERMINATOR_WITH_LC:
lcData[9U] = parity[2U] ^ TERMINATOR_WITH_LC_CRC_MASK[0U]; lcData[9U] = parity[2U] ^ TERMINATOR_WITH_LC_CRC_MASK[0U];
lcData[10U] = parity[1U] ^ TERMINATOR_WITH_LC_CRC_MASK[1U]; lcData[10U] = parity[1U] ^ TERMINATOR_WITH_LC_CRC_MASK[1U];
lcData[11U] = parity[0U] ^ TERMINATOR_WITH_LC_CRC_MASK[2U]; lcData[11U] = parity[0U] ^ TERMINATOR_WITH_LC_CRC_MASK[2U];

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_LC__FULL_LC_H__) #if !defined(__DMR_LC__FULL_LC_H__)
#define __DMR_LC__FULL_LC_H__ #define __DMR_LC__FULL_LC_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/LC.h" #include "common/dmr/lc/LC.h"
#include "common/dmr/lc/PrivacyLC.h" #include "common/dmr/lc/PrivacyLC.h"
#include "common/edac/BPTC19696.h" #include "common/edac/BPTC19696.h"
@ -37,9 +38,9 @@ namespace dmr
~FullLC(); ~FullLC();
/// <summary>Decode DMR full-link control data.</summary> /// <summary>Decode DMR full-link control data.</summary>
std::unique_ptr<LC> decode(const uint8_t* data, uint8_t type); std::unique_ptr<LC> decode(const uint8_t* data, defines::DataType::E type);
/// <summary>Encode DMR full-link control data.</summary> /// <summary>Encode DMR full-link control data.</summary>
void encode(const LC& lc, uint8_t* data, uint8_t type); void encode(const LC& lc, uint8_t* data, defines::DataType::E type);
/// <summary>Decode DMR privacy control data.</summary> /// <summary>Decode DMR privacy control data.</summary>
std::unique_ptr<PrivacyLC> decodePI(const uint8_t* data); std::unique_ptr<PrivacyLC> decodePI(const uint8_t* data);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2020-2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2020-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -17,8 +17,9 @@
#include "dmr/lc/LC.h" #include "dmr/lc/LC.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
#include <cassert> #include <cassert>
@ -32,7 +33,7 @@ using namespace dmr;
/// <param name="flco">Full-link Control Opcode.</param> /// <param name="flco">Full-link Control Opcode.</param>
/// <param name="srcId">Source ID.</param> /// <param name="srcId">Source ID.</param>
/// <param name="dstId">Destination ID.</param> /// <param name="dstId">Destination ID.</param>
LC::LC(uint8_t flco, uint32_t srcId, uint32_t dstId) : LC::LC(FLCO::E flco, uint32_t srcId, uint32_t dstId) :
m_PF(false), m_PF(false),
m_FLCO(flco), m_FLCO(flco),
m_FID(FID_ETSI), m_FID(FID_ETSI),
@ -47,13 +48,14 @@ LC::LC(uint8_t flco, uint32_t srcId, uint32_t dstId) :
{ {
/* stub */ /* stub */
} }
/// <summary> /// <summary>
/// Initializes a new instance of the LC class. /// Initializes a new instance of the LC class.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
LC::LC(const uint8_t* data) : LC::LC(const uint8_t* data) :
m_PF(false), m_PF(false),
m_FLCO(FLCO_GROUP), m_FLCO(FLCO::GROUP),
m_FID(FID_ETSI), m_FID(FID_ETSI),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
@ -69,7 +71,7 @@ LC::LC(const uint8_t* data) :
m_PF = (data[0U] & 0x80U) == 0x80U; m_PF = (data[0U] & 0x80U) == 0x80U;
m_R = (data[0U] & 0x40U) == 0x40U; m_R = (data[0U] & 0x40U) == 0x40U;
m_FLCO = data[0U] & 0x3FU; m_FLCO = (FLCO::E)(data[0U] & 0x3FU);
m_FID = data[1U]; m_FID = data[1U];
@ -82,13 +84,14 @@ LC::LC(const uint8_t* data) :
m_dstId = data[3U] << 16 | data[4U] << 8 | data[5U]; // Destination Address m_dstId = data[3U] << 16 | data[4U] << 8 | data[5U]; // Destination Address
m_srcId = data[6U] << 16 | data[7U] << 8 | data[8U]; // Source Address m_srcId = data[6U] << 16 | data[7U] << 8 | data[8U]; // Source Address
} }
/// <summary> /// <summary>
/// Initializes a new instance of the LC class. /// Initializes a new instance of the LC class.
/// </summary> /// </summary>
/// <param name="bits"></param> /// <param name="bits"></param>
LC::LC(const bool* bits) : LC::LC(const bool* bits) :
m_PF(false), m_PF(false),
m_FLCO(FLCO_GROUP), m_FLCO(FLCO::GROUP),
m_FID(FID_ETSI), m_FID(FID_ETSI),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
@ -106,7 +109,7 @@ LC::LC(const bool* bits) :
uint8_t temp1, temp2, temp3; uint8_t temp1, temp2, temp3;
Utils::bitsToByteBE(bits + 0U, temp1); Utils::bitsToByteBE(bits + 0U, temp1);
m_FLCO = temp1 & 0x3FU; m_FLCO = (FLCO::E)(temp1 & 0x3FU);
Utils::bitsToByteBE(bits + 8U, temp2); Utils::bitsToByteBE(bits + 8U, temp2);
m_FID = temp2; m_FID = temp2;
@ -137,7 +140,7 @@ LC::LC(const bool* bits) :
/// </summary> /// </summary>
LC::LC() : LC::LC() :
m_PF(false), m_PF(false),
m_FLCO(FLCO_GROUP), m_FLCO(FLCO::GROUP),
m_FID(FID_ETSI), m_FID(FID_ETSI),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
@ -164,7 +167,7 @@ void LC::getData(uint8_t* data) const
{ {
assert(data != nullptr); assert(data != nullptr);
data[0U] = (uint8_t)m_FLCO; data[0U] = m_FLCO;
if (m_PF) if (m_PF)
data[0U] |= 0x80U; data[0U] |= 0x80U;

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2020-2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2020-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_LC__LC_H__) #if !defined(__DMR_LC__LC_H__)
#define __DMR_LC__LC_H__ #define __DMR_LC__LC_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
namespace dmr namespace dmr
{ {
@ -29,7 +30,7 @@ namespace dmr
class HOST_SW_API LC { class HOST_SW_API LC {
public: public:
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
LC(uint8_t flco, uint32_t srcId, uint32_t dstId); LC(defines::FLCO::E flco, uint32_t srcId, uint32_t dstId);
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
LC(const uint8_t* data); LC(const uint8_t* data);
/// <summary>Initializes a new instance of the LC class.</summary> /// <summary>Initializes a new instance of the LC class.</summary>
@ -49,7 +50,7 @@ namespace dmr
__PROPERTY(bool, PF, PF); __PROPERTY(bool, PF, PF);
/// <summary>Full-link control opcode.</summary> /// <summary>Full-link control opcode.</summary>
__PROPERTY(uint8_t, FLCO, FLCO); __PROPERTY(defines::FLCO::E, FLCO, FLCO);
/// <summary>Feature ID.</summayr> /// <summary>Feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID); __PROPERTY(uint8_t, FID, FID);

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2021 Bryan Biedenkapp, N2PLL * Copyright (C) 2021,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -15,8 +15,9 @@
#include "dmr/lc/PrivacyLC.h" #include "dmr/lc/PrivacyLC.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
#include <cassert> #include <cassert>
@ -38,7 +39,7 @@ PrivacyLC::PrivacyLC(const uint8_t* data) :
{ {
assert(data != nullptr); assert(data != nullptr);
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
m_group = (data[0U] & 0x20U) == 0x20U; m_group = (data[0U] & 0x20U) == 0x20U;
m_algId = data[0U] & 7; // Algorithm ID m_algId = data[0U] & 7; // Algorithm ID
@ -67,7 +68,7 @@ PrivacyLC::PrivacyLC(const bool* bits) :
{ {
assert(bits != nullptr); assert(bits != nullptr);
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
uint8_t temp1, temp2, temp3; uint8_t temp1, temp2, temp3;
Utils::bitsToByteBE(bits + 0U, temp1); Utils::bitsToByteBE(bits + 0U, temp1);
@ -110,7 +111,7 @@ PrivacyLC::PrivacyLC() :
m_kId(0U), m_kId(0U),
m_mi(nullptr) m_mi(nullptr)
{ {
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
} }
/// <summary> /// <summary>

@ -16,8 +16,8 @@
#include "edac/Hamming.h" #include "edac/Hamming.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::lc;
#include <cassert> #include <cassert>

@ -17,9 +17,10 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -43,7 +44,7 @@ CSBKFactory::~CSBKFactory() = default;
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="dataType"></param> /// <param name="dataType"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns> /// <returns>True, if CSBK was decoded, otherwise false.</returns>
std::unique_ptr<CSBK> CSBKFactory::createCSBK(const uint8_t* data, uint8_t dataType) std::unique_ptr<CSBK> CSBKFactory::createCSBK(const uint8_t* data, DataType::E dataType)
{ {
assert(data != nullptr); assert(data != nullptr);
@ -55,47 +56,53 @@ std::unique_ptr<CSBK> CSBKFactory::createCSBK(const uint8_t* data, uint8_t dataT
// validate the CRC-CCITT 16 // validate the CRC-CCITT 16
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBKFactory::createCSBK(), unhandled dataType = $%02X", dataType);
break;
} }
bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES); bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES);
if (!valid) { if (!valid) {
LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check"); LogError(LOG_DMR, "CSBKFactory::createCSBK(), failed CRC CCITT-162 check");
return nullptr; return nullptr;
} }
// restore the checksum // restore the checksum
switch (dataType) { switch (dataType) {
case DT_CSBK: case DataType::CSBK:
csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[10U] ^= CSBK_CRC_MASK[0U];
csbk[11U] ^= CSBK_CRC_MASK[1U]; csbk[11U] ^= CSBK_CRC_MASK[1U];
break; break;
case DT_MBC_HEADER: case DataType::MBC_HEADER:
csbk[10U] ^= CSBK_MBC_CRC_MASK[0U]; csbk[10U] ^= CSBK_MBC_CRC_MASK[0U];
csbk[11U] ^= CSBK_MBC_CRC_MASK[1U]; csbk[11U] ^= CSBK_MBC_CRC_MASK[1U];
break; break;
default:
LogError(LOG_DMR, "CSBKFactory::createCSBK(), unhandled dataType = $%02X", dataType);
break;
} }
uint8_t CSBKO = csbk[0U] & 0x3FU; // CSBKO uint8_t CSBKO = csbk[0U] & 0x3FU; // CSBKO
uint8_t FID = csbk[1U]; // Feature ID uint8_t FID = csbk[1U]; // Feature ID
switch (CSBKO) { switch (CSBKO) {
case CSBKO_BSDWNACT: case CSBKO::BSDWNACT:
return decode(new CSBK_BSDWNACT(), data); return decode(new CSBK_BSDWNACT(), data);
case CSBKO_UU_V_REQ: case CSBKO::UU_V_REQ:
return decode(new CSBK_UU_V_REQ(), data); return decode(new CSBK_UU_V_REQ(), data);
case CSBKO_UU_ANS_RSP: case CSBKO::UU_ANS_RSP:
return decode(new CSBK_UU_ANS_RSP(), data); return decode(new CSBK_UU_ANS_RSP(), data);
case CSBKO_PRECCSBK: case CSBKO::PRECCSBK:
return decode(new CSBK_PRECCSBK(), data); return decode(new CSBK_PRECCSBK(), data);
case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA case CSBKO::RAND: // CSBKO::CALL_ALRT when FID == FID_DMRA
switch (FID) switch (FID)
{ {
case FID_DMRA: case FID_DMRA:
@ -104,17 +111,17 @@ std::unique_ptr<CSBK> CSBKFactory::createCSBK(const uint8_t* data, uint8_t dataT
default: default:
return decode(new CSBK_RAND(), data); return decode(new CSBK_RAND(), data);
} }
case CSBKO_EXT_FNCT: case CSBKO::EXT_FNCT:
return decode(new CSBK_EXT_FNCT(), data); return decode(new CSBK_EXT_FNCT(), data);
case CSBKO_NACK_RSP: case CSBKO::NACK_RSP:
return decode(new CSBK_NACK_RSP(), data); return decode(new CSBK_NACK_RSP(), data);
/** Tier 3 */ /** Tier 3 */
case CSBKO_ACK_RSP: case CSBKO::ACK_RSP:
return decode(new CSBK_ACK_RSP(), data); return decode(new CSBK_ACK_RSP(), data);
case CSBKO_BROADCAST: case CSBKO::BROADCAST:
return decode(new CSBK_BROADCAST(), data); return decode(new CSBK_BROADCAST(), data);
case CSBKO_MAINT: case CSBKO::MAINT:
return decode(new CSBK_MAINT(), data); return decode(new CSBK_MAINT(), data);
default: default:

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__DMR_LC__CSBK_FACTORY_H__) #if !defined(__DMR_LC__CSBK_FACTORY_H__)
@ -15,6 +15,7 @@
#include "common/Defines.h" #include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/CSBK.h" #include "common/dmr/lc/CSBK.h"
#include "common/dmr/lc/csbk/CSBK_ACK_RSP.h" #include "common/dmr/lc/csbk/CSBK_ACK_RSP.h"
#include "common/dmr/lc/csbk/CSBK_ALOHA.h" #include "common/dmr/lc/csbk/CSBK_ALOHA.h"
@ -55,7 +56,7 @@ namespace dmr
~CSBKFactory(); ~CSBKFactory();
/// <summary>Create an instance of a CSBK.</summary> /// <summary>Create an instance of a CSBK.</summary>
static std::unique_ptr<CSBK> createCSBK(const uint8_t* data, uint8_t dataType); static std::unique_ptr<CSBK> createCSBK(const uint8_t* data, defines::DataType::E dataType);
private: private:
/// <summary></summary> /// <summary></summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_ACK_RSP.h" #include "dmr/lc/csbk/CSBK_ACK_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_ACK_RSP::CSBK_ACK_RSP() : CSBK() CSBK_ACK_RSP::CSBK_ACK_RSP() : CSBK()
{ {
m_CSBKO = CSBKO_ACK_RSP; m_CSBKO = CSBKO::ACK_RSP;
} }
/// <summary> /// <summary>
@ -67,7 +68,7 @@ void CSBK_ACK_RSP::encode(uint8_t* data)
ulong64_t csbkValue = 0U; ulong64_t csbkValue = 0U;
if (m_reason == TS_ACK_RSN_REG) { if (m_reason == ReasonCode::TS_ACK_RSN_REG) {
csbkValue = 0U; csbkValue = 0U;
} else { } else {
csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type
@ -88,5 +89,5 @@ void CSBK_ACK_RSP::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_ACK_RSP::toString() std::string CSBK_ACK_RSP::toString()
{ {
return std::string("CSBKO_ACK_RSP (Acknowledge Response)"); return std::string("CSBKO, ACK_RSP (Acknowledge Response)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_ALOHA.h" #include "dmr/lc/csbk/CSBK_ALOHA.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -32,7 +33,7 @@ CSBK_ALOHA::CSBK_ALOHA() : CSBK(),
m_backoffNo(1U), m_backoffNo(1U),
m_nRandWait(DEFAULT_NRAND_WAIT) m_nRandWait(DEFAULT_NRAND_WAIT)
{ {
m_CSBKO = CSBKO_ALOHA; m_CSBKO = CSBKO::ALOHA;
} }
/// <summary> /// <summary>
@ -82,7 +83,7 @@ void CSBK_ALOHA::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_ALOHA::toString() std::string CSBK_ALOHA::toString()
{ {
return std::string("CSBKO_ALOHA (Aloha PDU)"); return std::string("CSBKO, ALOHA (Aloha PDU)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -13,9 +13,10 @@
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_BROADCAST.h" #include "dmr/lc/csbk/CSBK_BROADCAST.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -27,7 +28,7 @@ using namespace dmr;
/// Initializes a new instance of the CSBK_BROADCAST class. /// Initializes a new instance of the CSBK_BROADCAST class.
/// </summary> /// </summary>
CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(), CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(),
m_anncType(BCAST_ANNC_SITE_PARMS), m_anncType(BroadcastAnncType::SITE_PARMS),
m_hibernating(false), m_hibernating(false),
m_annWdCh1(false), m_annWdCh1(false),
m_annWdCh2(false), m_annWdCh2(false),
@ -35,7 +36,7 @@ CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(),
m_systemId(0U), m_systemId(0U),
m_backoffNo(1U) m_backoffNo(1U)
{ {
m_CSBKO = CSBKO_BROADCAST; m_CSBKO = CSBKO::BROADCAST;
} }
/// <summary> /// <summary>
@ -60,7 +61,7 @@ bool CSBK_BROADCAST::decode(const uint8_t* data)
switch (m_anncType) switch (m_anncType)
{ {
case BCAST_ANNC_ANN_WD_TSCC: case BroadcastAnncType::ANN_WD_TSCC:
// Broadcast Params 1 // Broadcast Params 1
m_colorCode = (uint8_t)((csbkValue >> 51) & 0x0FU); // Color Code 1 m_colorCode = (uint8_t)((csbkValue >> 51) & 0x0FU); // Color Code 1
m_annWdCh1 = ((csbkValue >> 44) & 0x04U) == 0x04U; // Announce/Withdraw Channel 1 m_annWdCh1 = ((csbkValue >> 44) & 0x04U) == 0x04U; // Announce/Withdraw Channel 1
@ -95,7 +96,7 @@ void CSBK_BROADCAST::encode(uint8_t* data)
switch (m_anncType) switch (m_anncType)
{ {
case BCAST_ANNC_ANN_WD_TSCC: case BroadcastAnncType::ANN_WD_TSCC:
// Broadcast Params 1 // Broadcast Params 1
csbkValue = (csbkValue << 4) + 0U; // Reserved csbkValue = (csbkValue << 4) + 0U; // Reserved
csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1 csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1
@ -111,7 +112,7 @@ void CSBK_BROADCAST::encode(uint8_t* data)
csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1 csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1
csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2 csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2
break; break;
case BCAST_ANNC_CHAN_FREQ: case BroadcastAnncType::CHAN_FREQ:
{ {
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000; float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000;
@ -148,7 +149,7 @@ void CSBK_BROADCAST::encode(uint8_t* data)
csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz
} }
break; break;
case BCAST_ANNC_SITE_PARMS: case BroadcastAnncType::SITE_PARMS:
// Broadcast Params 1 // Broadcast Params 1
csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Params 1) csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Params 1)
@ -174,10 +175,10 @@ void CSBK_BROADCAST::encode(uint8_t* data)
std::string CSBK_BROADCAST::toString() std::string CSBK_BROADCAST::toString()
{ {
switch (m_anncType) { switch (m_anncType) {
case BCAST_ANNC_ANN_WD_TSCC: return std::string("CSBKO_BROADCAST (Announcement PDU), BCAST_ANNC_ANN_WD_TSCC (Announce-WD TSCC Channel)"); case BroadcastAnncType::ANN_WD_TSCC: return std::string("CSBKO, BROADCAST (Announcement PDU), BroadcastAnncType::ANN_WD_TSCC (Announce-WD TSCC Channel)");
case BCAST_ANNC_CHAN_FREQ: return std::string("CSBKO_BROADCAST (Announcement PDU), BCAST_ANNC_CHAN_FREQ (Logical Channel/Frequency)"); case BroadcastAnncType::CHAN_FREQ: return std::string("CSBKO, BROADCAST (Announcement PDU), BroadcastAnncType::CHAN_FREQ (Logical Channel/Frequency)");
case BCAST_ANNC_SITE_PARMS: return std::string("CSBKO_BROADCAST (Announcement PDU), BCAST_ANNC_SITE_PARMS (General Site Parameters)"); case BroadcastAnncType::SITE_PARMS: return std::string("CSBKO, BROADCAST (Announcement PDU), BroadcastAnncType::SITE_PARMS (General Site Parameters)");
default: return std::string("CSBKO_BROADCAST (Announcement PDU)"); default: return std::string("CSBKO, BROADCAST (Announcement PDU)");
} }
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_BSDWNACT.h" #include "dmr/lc/csbk/CSBK_BSDWNACT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_BSDWNACT::CSBK_BSDWNACT() : CSBK(), CSBK_BSDWNACT::CSBK_BSDWNACT() : CSBK(),
m_bsId(0U) m_bsId(0U)
{ {
m_CSBKO = CSBKO_BSDWNACT; m_CSBKO = CSBKO::BSDWNACT;
} }
/// <summary> /// <summary>
@ -73,7 +74,7 @@ void CSBK_BSDWNACT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_BSDWNACT::toString() std::string CSBK_BSDWNACT::toString()
{ {
return std::string("CSBKO_BSDWNACT (BS Outbound Activation)"); return std::string("CSBKO, BSDWNACT (BS Outbound Activation)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_CALL_ALRT.h" #include "dmr/lc/csbk/CSBK_CALL_ALRT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_CALL_ALRT::CSBK_CALL_ALRT() : CSBK() CSBK_CALL_ALRT::CSBK_CALL_ALRT() : CSBK()
{ {
m_CSBKO = CSBKO_RAND; m_CSBKO = CSBKO::RAND;
m_FID = FID_DMRA; m_FID = FID_DMRA;
} }
@ -81,5 +82,5 @@ void CSBK_CALL_ALRT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_CALL_ALRT::toString() std::string CSBK_CALL_ALRT::toString()
{ {
return std::string("CSBKO_RAND (Call Alert)"); return std::string("CSBKO, RAND (Call Alert)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_EXT_FNCT.h" #include "dmr/lc/csbk/CSBK_EXT_FNCT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -27,9 +28,9 @@ using namespace dmr;
/// Initializes a new instance of the CSBK_EXT_FNCT class. /// Initializes a new instance of the CSBK_EXT_FNCT class.
/// </summary> /// </summary>
CSBK_EXT_FNCT::CSBK_EXT_FNCT() : CSBK(), CSBK_EXT_FNCT::CSBK_EXT_FNCT() : CSBK(),
m_extendedFunction(DMR_EXT_FNCT_CHECK) m_extendedFunction(ExtendedFunctions::CHECK)
{ {
m_CSBKO = CSBKO_EXT_FNCT; m_CSBKO = CSBKO::EXT_FNCT;
m_FID = FID_DMRA; m_FID = FID_DMRA;
} }
@ -86,7 +87,7 @@ void CSBK_EXT_FNCT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_EXT_FNCT::toString() std::string CSBK_EXT_FNCT::toString()
{ {
return std::string("CSBKO_EXT_FNCT (Extended Function)"); return std::string("CSBKO, EXT_FNCT (Extended Function)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2023,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_MAINT.h" #include "dmr/lc/csbk/CSBK_MAINT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_MAINT::CSBK_MAINT() : CSBK(), CSBK_MAINT::CSBK_MAINT() : CSBK(),
m_maintKind(0U) m_maintKind(0U)
{ {
m_CSBKO = CSBKO_MAINT; m_CSBKO = CSBKO::MAINT;
} }
/// <summary> /// <summary>
@ -81,7 +82,7 @@ void CSBK_MAINT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_MAINT::toString() std::string CSBK_MAINT::toString()
{ {
return std::string("CSBKO_MAINT (Call Maintainence)"); return std::string("CSBKO, MAINT (Call Maintainence)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_NACK_RSP.h" #include "dmr/lc/csbk/CSBK_NACK_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_NACK_RSP::CSBK_NACK_RSP() : CSBK(), CSBK_NACK_RSP::CSBK_NACK_RSP() : CSBK(),
m_serviceKind(0U) m_serviceKind(0U)
{ {
m_CSBKO = CSBKO_NACK_RSP; m_CSBKO = CSBKO::NACK_RSP;
} }
/// <summary> /// <summary>
@ -86,7 +87,7 @@ void CSBK_NACK_RSP::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_NACK_RSP::toString() std::string CSBK_NACK_RSP::toString()
{ {
return std::string("CSBKO_NACK_RSP (Negative Acknowledgement Response)"); return std::string("CSBKO, NACK_RSP (Negative Acknowledgement Response)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_PD_GRANT.h" #include "dmr/lc/csbk/CSBK_PD_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_PD_GRANT::CSBK_PD_GRANT() : CSBK() CSBK_PD_GRANT::CSBK_PD_GRANT() : CSBK()
{ {
m_CSBKO = CSBKO_PD_GRANT; m_CSBKO = CSBKO::PD_GRANT;
} }
/// <summary> /// <summary>
@ -73,5 +74,5 @@ void CSBK_PD_GRANT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_PD_GRANT::toString() std::string CSBK_PD_GRANT::toString()
{ {
return std::string("CSBKO_PD_GRANT (Private Data Channel Grant)"); return std::string("CSBKO, PD_GRANT (Private Data Channel Grant)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_PRECCSBK.h" #include "dmr/lc/csbk/CSBK_PRECCSBK.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_PRECCSBK::CSBK_PRECCSBK() : CSBK() CSBK_PRECCSBK::CSBK_PRECCSBK() : CSBK()
{ {
m_CSBKO = CSBKO_PRECCSBK; m_CSBKO = CSBKO::PRECCSBK;
} }
/// <summary> /// <summary>
@ -75,5 +76,5 @@ void CSBK_PRECCSBK::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_PRECCSBK::toString() std::string CSBK_PRECCSBK::toString()
{ {
return std::string("CSBKO_PRECCSBK (Preamble CSBK)"); return std::string("CSBKO, PRECCSBK (Preamble CSBK)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_PV_GRANT.h" #include "dmr/lc/csbk/CSBK_PV_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_PV_GRANT::CSBK_PV_GRANT() : CSBK() CSBK_PV_GRANT::CSBK_PV_GRANT() : CSBK()
{ {
m_CSBKO = CSBKO_PV_GRANT; m_CSBKO = CSBKO::PV_GRANT;
} }
/// <summary> /// <summary>
@ -73,5 +74,5 @@ void CSBK_PV_GRANT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_PV_GRANT::toString() std::string CSBK_PV_GRANT::toString()
{ {
return std::string("CSBKO_PV_GRANT (Private Voice Channel Grant)"); return std::string("CSBKO, PV_GRANT (Private Voice Channel Grant)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2023,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_P_CLEAR.h" #include "dmr/lc/csbk/CSBK_P_CLEAR.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_P_CLEAR::CSBK_P_CLEAR() : CSBK() CSBK_P_CLEAR::CSBK_P_CLEAR() : CSBK()
{ {
m_CSBKO = CSBKO_P_CLEAR; m_CSBKO = CSBKO::P_CLEAR;
} }
/// <summary> /// <summary>
@ -72,5 +73,5 @@ void CSBK_P_CLEAR::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_P_CLEAR::toString() std::string CSBK_P_CLEAR::toString()
{ {
return std::string("CSBKO_P_CLEAR (Payload Channel Clear)"); return std::string("CSBKO, P_CLEAR (Payload Channel Clear)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2023,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_P_GRANT.h" #include "dmr/lc/csbk/CSBK_P_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_P_GRANT::CSBK_P_GRANT() : CSBK() CSBK_P_GRANT::CSBK_P_GRANT() : CSBK()
{ {
m_CSBKO = CSBKO_TV_GRANT; m_CSBKO = CSBKO::TV_GRANT;
} }
/// <summary> /// <summary>
@ -73,5 +74,5 @@ void CSBK_P_GRANT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_P_GRANT::toString() std::string CSBK_P_GRANT::toString()
{ {
return std::string("CSBK_P_GRANT (Payload Grant)"); return std::string("CSBKO, P_GRANT (Payload Grant)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_RAND.h" #include "dmr/lc/csbk/CSBK_RAND.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -31,7 +32,7 @@ CSBK_RAND::CSBK_RAND() : CSBK(),
m_serviceExtra(0U), m_serviceExtra(0U),
m_serviceKind(0U) m_serviceKind(0U)
{ {
m_CSBKO = CSBKO_RAND; m_CSBKO = CSBKO::RAND;
} }
/// <summary> /// <summary>
@ -90,20 +91,20 @@ void CSBK_RAND::encode(uint8_t* data)
std::string CSBK_RAND::toString() std::string CSBK_RAND::toString()
{ {
switch (m_serviceKind) { switch (m_serviceKind) {
case SVC_KIND_IND_VOICE_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)"); case ServiceKind::IND_VOICE_CALL: return std::string("CSBKO, RAND (Random Access), IND_VOICE_CALL (Individual Voice Call)");
case SVC_KIND_GRP_VOICE_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)"); case ServiceKind::GRP_VOICE_CALL: return std::string("CSBKO, RAND (Random Access), GRP_VOICE_CALL (Group Voice Call)");
case SVC_KIND_IND_DATA_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_IND_DATA_CALL (Individual Data Call)"); case ServiceKind::IND_DATA_CALL: return std::string("CSBKO, RAND (Random Access), IND_DATA_CALL (Individual Data Call)");
case SVC_KIND_GRP_DATA_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_GRP_DATA_CALL (Group Data Call)"); case ServiceKind::GRP_DATA_CALL: return std::string("CSBKO, RAND (Random Access), GRP_DATA_CALL (Group Data Call)");
case SVC_KIND_IND_UDT_DATA_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_IND_UDT_DATA_CALL (Individual UDT Short Data Call)"); case ServiceKind::IND_UDT_DATA_CALL: return std::string("CSBKO, RAND (Random Access), IND_UDT_DATA_CALL (Individual UDT Short Data Call)");
case SVC_KIND_GRP_UDT_DATA_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_GRP_UDT_DATA_CALL (Group UDT Short Data Call)"); case ServiceKind::GRP_UDT_DATA_CALL: return std::string("CSBKO, RAND (Random Access), GRP_UDT_DATA_CALL (Group UDT Short Data Call)");
case SVC_KIND_UDT_SHORT_POLL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_UDT_SHORT_POLL (UDT Short Data Polling Service)"); case ServiceKind::UDT_SHORT_POLL: return std::string("CSBKO, RAND (Random Access), UDT_SHORT_POLL (UDT Short Data Polling Service)");
case SVC_KIND_STATUS_TRANSPORT: return std::string("CSBKO_RAND (Random Access), SVC_KIND_STATUS_TRANSPORT (Status Transport Service)"); case ServiceKind::STATUS_TRANSPORT: return std::string("CSBKO, RAND (Random Access), STATUS_TRANSPORT (Status Transport Service)");
case SVC_KIND_CALL_DIVERSION: return std::string("CSBKO_RAND (Random Access), SVC_KIND_CALL_DIVERSION (Call Diversion Service)"); case ServiceKind::CALL_DIVERSION: return std::string("CSBKO, RAND (Random Access), CALL_DIVERSION (Call Diversion Service)");
case SVC_KIND_CALL_ANSWER: return std::string("CSBKO_RAND (Random Access), SVC_KIND_CALL_ANSWER (Call Answer Service)"); case ServiceKind::CALL_ANSWER: return std::string("CSBKO, RAND (Random Access), CALL_ANSWER (Call Answer Service)");
case SVC_KIND_SUPPLEMENTARY_SVC: return std::string("CSBKO_RAND (Random Access), SVC_KIND_SUPPLEMENTARY_SVC (Supplementary Service)"); case ServiceKind::SUPPLEMENTARY_SVC: return std::string("CSBKO, RAND (Random Access), SUPPLEMENTARY_SVC (Supplementary Service)");
case SVC_KIND_REG_SVC: return std::string("CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service)"); case ServiceKind::REG_SVC: return std::string("CSBKO, RAND (Random Access), REG_SVC (Registration Service)");
case SVC_KIND_CANCEL_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_CANCEL_CALL (Cancel Call Service)"); case ServiceKind::CANCEL_CALL: return std::string("CSBKO, RAND (Random Access), CANCEL_CALL (Cancel Call Service)");
default: return std::string("CSBKO_RAND (Random Access)"); default: return std::string("CSBKO, RAND (Random Access)");
} }
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_RAW.h" #include "dmr/lc/csbk/CSBK_RAW.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_RAW::CSBK_RAW() : CSBK(), CSBK_RAW::CSBK_RAW() : CSBK(),
m_csbk(nullptr) m_csbk(nullptr)
{ {
m_CSBKO = CSBKO_RAND; m_CSBKO = CSBKO::RAND;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_TD_GRANT.h" #include "dmr/lc/csbk/CSBK_TD_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_TD_GRANT::CSBK_TD_GRANT() : CSBK() CSBK_TD_GRANT::CSBK_TD_GRANT() : CSBK()
{ {
m_CSBKO = CSBKO_TD_GRANT; m_CSBKO = CSBKO::TD_GRANT;
} }
/// <summary> /// <summary>
@ -73,5 +74,5 @@ void CSBK_TD_GRANT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_TD_GRANT::toString() std::string CSBK_TD_GRANT::toString()
{ {
return std::string("CSBKO_TD_GRANT (Talkgroup Data Channel Grant)"); return std::string("CSBKO, TD_GRANT (Talkgroup Data Channel Grant)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_TV_GRANT.h" #include "dmr/lc/csbk/CSBK_TV_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK(), CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK(),
m_lateEntry(false) m_lateEntry(false)
{ {
m_CSBKO = CSBKO_TV_GRANT; m_CSBKO = CSBKO::TV_GRANT;
} }
/// <summary> /// <summary>
@ -74,7 +75,7 @@ void CSBK_TV_GRANT::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_TV_GRANT::toString() std::string CSBK_TV_GRANT::toString()
{ {
return std::string("CSBKO_TV_GRANT (Talkgroup Voice Channel Grant)"); return std::string("CSBKO, TV_GRANT (Talkgroup Voice Channel Grant)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_UU_ANS_RSP.h" #include "dmr/lc/csbk/CSBK_UU_ANS_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_UU_ANS_RSP::CSBK_UU_ANS_RSP() : CSBK() CSBK_UU_ANS_RSP::CSBK_UU_ANS_RSP() : CSBK()
{ {
m_CSBKO = CSBKO_UU_ANS_RSP; m_CSBKO = CSBKO::UU_ANS_RSP;
} }
/// <summary> /// <summary>
@ -72,5 +73,5 @@ void CSBK_UU_ANS_RSP::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_UU_ANS_RSP::toString() std::string CSBK_UU_ANS_RSP::toString()
{ {
return std::string("CSBKO_UU_ANS_RSP (Unit-to-Unit Answer Response)"); return std::string("CSBKO, UU_ANS_RSP (Unit-to-Unit Answer Response)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "dmr/lc/csbk/CSBK_UU_V_REQ.h" #include "dmr/lc/csbk/CSBK_UU_V_REQ.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr; using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary> /// </summary>
CSBK_UU_V_REQ::CSBK_UU_V_REQ() : CSBK() CSBK_UU_V_REQ::CSBK_UU_V_REQ() : CSBK()
{ {
m_CSBKO = CSBKO_UU_V_REQ; m_CSBKO = CSBKO::UU_V_REQ;
} }
/// <summary> /// <summary>
@ -72,5 +73,5 @@ void CSBK_UU_V_REQ::encode(uint8_t* data)
/// <returns></returns> /// <returns></returns>
std::string CSBK_UU_V_REQ::toString() std::string CSBK_UU_V_REQ::toString()
{ {
return std::string("CSBKO_UU_V_REQ (Unit-to-Unit Voice Channel Request)"); return std::string("CSBKO, UU_V_REQ (Unit-to-Unit Voice Channel Request)");
} }

@ -74,7 +74,7 @@ void RadioIdLookup::toggleEntry(uint32_t id, bool enabled)
/// <param name="alias">Alias for the radio ID</param> /// <param name="alias">Alias for the radio ID</param>
void RadioIdLookup::addEntry(uint32_t id, bool enabled, const std::string& alias) void RadioIdLookup::addEntry(uint32_t id, bool enabled, const std::string& alias)
{ {
if ((id == p25::P25_WUID_ALL) || (id == p25::P25_WUID_FNE)) { if ((id == p25::defines::WUID_ALL) || (id == p25::defines::WUID_FNE)) {
return; return;
} }
@ -121,7 +121,7 @@ RadioId RadioIdLookup::find(uint32_t id)
{ {
RadioId entry; RadioId entry;
if ((id == p25::P25_WUID_ALL) || (id == p25::P25_WUID_FNE)) { if ((id == p25::defines::WUID_ALL) || (id == p25::defines::WUID_FNE)) {
return RadioId(true, false); return RadioId(true, false);
} }

@ -14,6 +14,7 @@
*/ */
#include "Defines.h" #include "Defines.h"
#include "common/dmr/DMRDefines.h" #include "common/dmr/DMRDefines.h"
#include "common/p25/P25Defines.h"
#include "common/nxdn/NXDNDefines.h" #include "common/nxdn/NXDNDefines.h"
#include "common/p25/dfsi/DFSIDefines.h" #include "common/p25/dfsi/DFSIDefines.h"
#include "common/p25/dfsi/LC.h" #include "common/p25/dfsi/LC.h"
@ -434,6 +435,7 @@ UInt8Array BaseNetwork::readDMR(bool& ret, uint32_t& frameLength)
/// <returns></returns> /// <returns></returns>
bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence) bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence)
{ {
using namespace dmr::defines;
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false; return false;
@ -445,17 +447,17 @@ bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence)
if (slotNo == 2U && !m_slot2) if (slotNo == 2U && !m_slot2)
return false; return false;
uint8_t dataType = data.getDataType(); DataType::E dataType = data.getDataType();
uint32_t slotIndex = slotNo - 1U; uint32_t slotIndex = slotNo - 1U;
bool resetSeq = false; bool resetSeq = false;
if (dataType == dmr::DT_VOICE_LC_HEADER) { if (dataType == DataType::VOICE_LC_HEADER) {
resetSeq = true; resetSeq = true;
m_dmrStreamId[slotIndex] = createStreamId(); m_dmrStreamId[slotIndex] = createStreamId();
} }
if (dataType == dmr::DT_CSBK || dataType == dmr::DT_DATA_HEADER) { if (dataType == DataType::CSBK || dataType == DataType::DATA_HEADER) {
resetSeq = true; resetSeq = true;
m_dmrStreamId[slotIndex] = createStreamId(); m_dmrStreamId[slotIndex] = createStreamId();
} }
@ -467,7 +469,7 @@ bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence)
} }
uint16_t seq = pktSeq(resetSeq); uint16_t seq = pktSeq(resetSeq);
if (dataType == dmr::DT_TERMINATOR_WITH_LC) { if (dataType == DataType::TERMINATOR_WITH_LC) {
seq = RTP_END_OF_CALL_SEQ; seq = RTP_END_OF_CALL_SEQ;
} }
@ -531,7 +533,7 @@ UInt8Array BaseNetwork::readP25(bool& ret, uint32_t& frameLength)
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="frameType"></param> /// <param name="frameType"></param>
/// <returns></returns> /// <returns></returns>
bool BaseNetwork::writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data, uint8_t frameType) bool BaseNetwork::writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data, p25::defines::FrameType::E frameType)
{ {
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false; return false;
@ -724,6 +726,7 @@ UInt8Array BaseNetwork::readNXDN(bool& ret, uint32_t& frameLength)
/// <returns></returns> /// <returns></returns>
bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len, bool noSequence) bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const uint32_t len, bool noSequence)
{ {
using namespace nxdn::defines;
if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING) if (m_status != NET_STAT_RUNNING && m_status != NET_STAT_MST_RUNNING)
return false; return false;
@ -740,8 +743,8 @@ bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const
} }
uint16_t seq = pktSeq(resetSeq); uint16_t seq = pktSeq(resetSeq);
if (lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL || if (lc.getMessageType() == MessageType::RTCH_TX_REL ||
lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL_EX) { lc.getMessageType() == MessageType::RTCH_TX_REL_EX) {
seq = RTP_END_OF_CALL_SEQ; seq = RTP_END_OF_CALL_SEQ;
} }
@ -797,6 +800,7 @@ uint16_t BaseNetwork::pktSeq(bool reset)
/// <returns></returns> /// <returns></returns>
UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t streamId, const dmr::data::Data& data) UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t streamId, const dmr::data::Data& data)
{ {
using namespace dmr::defines;
uint8_t* buffer = new uint8_t[DMR_PACKET_LENGTH + PACKET_PAD]; uint8_t* buffer = new uint8_t[DMR_PACKET_LENGTH + PACKET_PAD];
::memset(buffer, 0x00U, DMR_PACKET_LENGTH + PACKET_PAD); ::memset(buffer, 0x00U, DMR_PACKET_LENGTH + PACKET_PAD);
@ -821,14 +825,14 @@ UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t strea
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U; // Slot Number buffer[15U] = slotNo == 1U ? 0x00U : 0x80U; // Slot Number
uint8_t flco = data.getFLCO(); FLCO::E flco = data.getFLCO();
buffer[15U] |= flco == dmr::FLCO_GROUP ? 0x00U : 0x40U; // Group buffer[15U] |= flco == FLCO::GROUP ? 0x00U : 0x40U; // Group
uint8_t dataType = data.getDataType(); uint8_t dataType = data.getDataType();
if (dataType == dmr::DT_VOICE_SYNC) { if (dataType == DataType::VOICE_SYNC) {
buffer[15U] |= 0x10U; buffer[15U] |= 0x10U;
} }
else if (dataType == dmr::DT_VOICE) { else if (dataType == DataType::VOICE) {
buffer[15U] |= data.getN(); buffer[15U] |= data.getN();
} }
else { else {
@ -858,9 +862,10 @@ UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t strea
/// <param name="control"></param> /// <param name="control"></param>
/// <param name="lsd"></param> /// <param name="lsd"></param>
/// <param name="frameType"></param> /// <param name="frameType"></param>
void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, p25::defines::DUID::E duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
uint8_t frameType) p25::defines::FrameType::E frameType)
{ {
using namespace p25::defines;
assert(buffer != nullptr); assert(buffer != nullptr);
// construct P25 message header // construct P25 message header
@ -889,27 +894,27 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25:
buffer[22U] = duid; // DUID buffer[22U] = duid; // DUID
if (frameType != p25::P25_FT_TERMINATOR) { if (frameType != FrameType::TERMINATOR) {
buffer[180U] = frameType; // DVM Frame Type buffer[180U] = frameType; // DVM Frame Type
} }
// is this the first frame of a call? // is this the first frame of a call?
if (frameType == p25::P25_FT_HDU_VALID) { if (frameType == FrameType::HDU_VALID) {
buffer[181U] = control.getAlgId(); // Algorithm ID buffer[181U] = control.getAlgId(); // Algorithm ID
uint32_t kid = control.getKId(); uint32_t kid = control.getKId();
__SET_UINT16B(kid, buffer, 182U); // Key ID __SET_UINT16B(kid, buffer, 182U); // Key ID
// copy MI data // copy MI data
uint8_t mi[p25::P25_MI_LENGTH_BYTES]; uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, p25::P25_MI_LENGTH_BYTES); ::memset(mi, 0x00U, MI_LENGTH_BYTES);
control.getMI(mi); control.getMI(mi);
if (m_debug) { if (m_debug) {
Utils::dump(1U, "P25 HDU MI written to network", mi, p25::P25_MI_LENGTH_BYTES); Utils::dump(1U, "P25 HDU MI written to network", mi, MI_LENGTH_BYTES);
} }
for (uint8_t i = 0; i < p25::P25_MI_LENGTH_BYTES; i++) { for (uint8_t i = 0; i < MI_LENGTH_BYTES; i++) {
buffer[184U + i] = mi[i]; // Message Indicator buffer[184U + i] = mi[i]; // Message Indicator
} }
} }
@ -925,8 +930,10 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25:
/// <param name="frameType"></param> /// <param name="frameType"></param>
/// <returns></returns> /// <returns></returns>
UInt8Array BaseNetwork::createP25_LDU1Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, UInt8Array BaseNetwork::createP25_LDU1Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
const uint8_t* data, uint8_t frameType) const uint8_t* data, p25::defines::FrameType::E frameType)
{ {
using namespace p25::defines;
using namespace p25::dfsi::defines;
assert(data != nullptr); assert(data != nullptr);
p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd); p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd);
@ -935,56 +942,56 @@ UInt8Array BaseNetwork::createP25_LDU1Message(uint32_t& length, const p25::lc::L
::memset(buffer, 0x00U, P25_LDU1_PACKET_LENGTH + PACKET_PAD); ::memset(buffer, 0x00U, P25_LDU1_PACKET_LENGTH + PACKET_PAD);
// construct P25 message header // construct P25 message header
createP25_MessageHdr(buffer, p25::P25_DUID_LDU1, control, lsd, frameType); createP25_MessageHdr(buffer, DUID::LDU1, control, lsd, frameType);
// pack DFSI data // pack DFSI data
uint32_t count = MSG_HDR_SIZE; uint32_t count = MSG_HDR_SIZE;
uint8_t imbe[p25::P25_RAW_IMBE_LENGTH_BYTES]; uint8_t imbe[RAW_IMBE_LENGTH_BYTES];
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE1); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE1);
m_audio.decode(data, imbe, 0U); m_audio.decode(data, imbe, 0U);
dfsiLC.encodeLDU1(buffer + 24U, imbe); dfsiLC.encodeLDU1(buffer + 24U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE2); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE2);
m_audio.decode(data, imbe, 1U); m_audio.decode(data, imbe, 1U);
dfsiLC.encodeLDU1(buffer + 46U, imbe); dfsiLC.encodeLDU1(buffer + 46U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE3); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE3);
m_audio.decode(data, imbe, 2U); m_audio.decode(data, imbe, 2U);
dfsiLC.encodeLDU1(buffer + 60U, imbe); dfsiLC.encodeLDU1(buffer + 60U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE4); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE4);
m_audio.decode(data, imbe, 3U); m_audio.decode(data, imbe, 3U);
dfsiLC.encodeLDU1(buffer + 77U, imbe); dfsiLC.encodeLDU1(buffer + 77U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE5); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE5);
m_audio.decode(data, imbe, 4U); m_audio.decode(data, imbe, 4U);
dfsiLC.encodeLDU1(buffer + 94U, imbe); dfsiLC.encodeLDU1(buffer + 94U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE6); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE6);
m_audio.decode(data, imbe, 5U); m_audio.decode(data, imbe, 5U);
dfsiLC.encodeLDU1(buffer + 111U, imbe); dfsiLC.encodeLDU1(buffer + 111U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE7); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE7);
m_audio.decode(data, imbe, 6U); m_audio.decode(data, imbe, 6U);
dfsiLC.encodeLDU1(buffer + 128U, imbe); dfsiLC.encodeLDU1(buffer + 128U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE8); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE8);
m_audio.decode(data, imbe, 7U); m_audio.decode(data, imbe, 7U);
dfsiLC.encodeLDU1(buffer + 145U, imbe); dfsiLC.encodeLDU1(buffer + 145U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU1_VOICE9); dfsiLC.setFrameType(DFSIFrameType::LDU1_VOICE9);
m_audio.decode(data, imbe, 8U); m_audio.decode(data, imbe, 8U);
dfsiLC.encodeLDU1(buffer + 162U, imbe); dfsiLC.encodeLDU1(buffer + 162U, imbe);
count += p25::dfsi::P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES; count += DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
buffer[23U] = count; buffer[23U] = count;
@ -1006,6 +1013,8 @@ UInt8Array BaseNetwork::createP25_LDU1Message(uint32_t& length, const p25::lc::L
UInt8Array BaseNetwork::createP25_LDU2Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, UInt8Array BaseNetwork::createP25_LDU2Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
const uint8_t* data) const uint8_t* data)
{ {
using namespace p25::defines;
using namespace p25::dfsi::defines;
assert(data != nullptr); assert(data != nullptr);
p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd); p25::dfsi::LC dfsiLC = p25::dfsi::LC(control, lsd);
@ -1014,56 +1023,56 @@ UInt8Array BaseNetwork::createP25_LDU2Message(uint32_t& length, const p25::lc::L
::memset(buffer, 0x00U, P25_LDU2_PACKET_LENGTH + PACKET_PAD); ::memset(buffer, 0x00U, P25_LDU2_PACKET_LENGTH + PACKET_PAD);
// construct P25 message header // construct P25 message header
createP25_MessageHdr(buffer, p25::P25_DUID_LDU2, control, lsd, p25::P25_FT_DATA_UNIT); createP25_MessageHdr(buffer, DUID::LDU2, control, lsd, FrameType::DATA_UNIT);
// pack DFSI data // pack DFSI data
uint32_t count = MSG_HDR_SIZE; uint32_t count = MSG_HDR_SIZE;
uint8_t imbe[p25::P25_RAW_IMBE_LENGTH_BYTES]; uint8_t imbe[RAW_IMBE_LENGTH_BYTES];
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE10); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE10);
m_audio.decode(data, imbe, 0U); m_audio.decode(data, imbe, 0U);
dfsiLC.encodeLDU2(buffer + 24U, imbe); dfsiLC.encodeLDU2(buffer + 24U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE11); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE11);
m_audio.decode(data, imbe, 1U); m_audio.decode(data, imbe, 1U);
dfsiLC.encodeLDU2(buffer + 46U, imbe); dfsiLC.encodeLDU2(buffer + 46U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE12); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE12);
m_audio.decode(data, imbe, 2U); m_audio.decode(data, imbe, 2U);
dfsiLC.encodeLDU2(buffer + 60U, imbe); dfsiLC.encodeLDU2(buffer + 60U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE13); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE13);
m_audio.decode(data, imbe, 3U); m_audio.decode(data, imbe, 3U);
dfsiLC.encodeLDU2(buffer + 77U, imbe); dfsiLC.encodeLDU2(buffer + 77U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE14); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE14);
m_audio.decode(data, imbe, 4U); m_audio.decode(data, imbe, 4U);
dfsiLC.encodeLDU2(buffer + 94U, imbe); dfsiLC.encodeLDU2(buffer + 94U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE15); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE15);
m_audio.decode(data, imbe, 5U); m_audio.decode(data, imbe, 5U);
dfsiLC.encodeLDU2(buffer + 111U, imbe); dfsiLC.encodeLDU2(buffer + 111U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE16); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE16);
m_audio.decode(data, imbe, 6U); m_audio.decode(data, imbe, 6U);
dfsiLC.encodeLDU2(buffer + 128U, imbe); dfsiLC.encodeLDU2(buffer + 128U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE17); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE17);
m_audio.decode(data, imbe, 7U); m_audio.decode(data, imbe, 7U);
dfsiLC.encodeLDU2(buffer + 145U, imbe); dfsiLC.encodeLDU2(buffer + 145U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES;
dfsiLC.setFrameType(p25::dfsi::P25_DFSI_LDU2_VOICE18); dfsiLC.setFrameType(DFSIFrameType::LDU2_VOICE18);
m_audio.decode(data, imbe, 8U); m_audio.decode(data, imbe, 8U);
dfsiLC.encodeLDU2(buffer + 162U, imbe); dfsiLC.encodeLDU2(buffer + 162U, imbe);
count += p25::dfsi::P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES; count += DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
buffer[23U] = count; buffer[23U] = count;
@ -1084,11 +1093,12 @@ UInt8Array BaseNetwork::createP25_LDU2Message(uint32_t& length, const p25::lc::L
/// <returns></returns> /// <returns></returns>
UInt8Array BaseNetwork::createP25_TDUMessage(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t controlByte) UInt8Array BaseNetwork::createP25_TDUMessage(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t controlByte)
{ {
using namespace p25::defines;
uint8_t* buffer = new uint8_t[MSG_HDR_SIZE + PACKET_PAD]; uint8_t* buffer = new uint8_t[MSG_HDR_SIZE + PACKET_PAD];
::memset(buffer, 0x00U, MSG_HDR_SIZE + PACKET_PAD); ::memset(buffer, 0x00U, MSG_HDR_SIZE + PACKET_PAD);
// construct P25 message header // construct P25 message header
createP25_MessageHdr(buffer, p25::P25_DUID_TDU, control, lsd, p25::P25_FT_TERMINATOR); createP25_MessageHdr(buffer, DUID::TDU, control, lsd, FrameType::TERMINATOR);
buffer[14U] = controlByte; buffer[14U] = controlByte;
buffer[23U] = MSG_HDR_SIZE; buffer[23U] = MSG_HDR_SIZE;
@ -1109,6 +1119,7 @@ UInt8Array BaseNetwork::createP25_TDUMessage(uint32_t& length, const p25::lc::LC
/// <returns></returns> /// <returns></returns>
UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data) UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data)
{ {
using namespace p25::defines;
assert(data != nullptr); assert(data != nullptr);
uint8_t* buffer = new uint8_t[P25_TSDU_PACKET_LENGTH + PACKET_PAD]; uint8_t* buffer = new uint8_t[P25_TSDU_PACKET_LENGTH + PACKET_PAD];
@ -1116,13 +1127,13 @@ UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::L
// construct P25 message header // construct P25 message header
p25::data::LowSpeedData lsd = p25::data::LowSpeedData(); p25::data::LowSpeedData lsd = p25::data::LowSpeedData();
createP25_MessageHdr(buffer, p25::P25_DUID_TSDU, control, lsd, p25::P25_FT_TERMINATOR); createP25_MessageHdr(buffer, DUID::TSDU, control, lsd, FrameType::TERMINATOR);
// pack raw P25 TSDU bytes // pack raw P25 TSDU bytes
uint32_t count = MSG_HDR_SIZE; uint32_t count = MSG_HDR_SIZE;
::memcpy(buffer + 24U, data, p25::P25_TSDU_FRAME_LENGTH_BYTES); ::memcpy(buffer + 24U, data, P25_TSDU_FRAME_LENGTH_BYTES);
count += p25::P25_TSDU_FRAME_LENGTH_BYTES; count += P25_TSDU_FRAME_LENGTH_BYTES;
buffer[23U] = count; buffer[23U] = count;
@ -1145,6 +1156,7 @@ UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::L
UInt8Array BaseNetwork::createP25_PDUMessage(uint32_t& length, const p25::data::DataHeader& header, UInt8Array BaseNetwork::createP25_PDUMessage(uint32_t& length, const p25::data::DataHeader& header,
const uint8_t currentBlock, const uint8_t* data, const uint32_t len) const uint8_t currentBlock, const uint8_t* data, const uint32_t len)
{ {
using namespace p25::defines;
assert(data != nullptr); assert(data != nullptr);
uint8_t* buffer = new uint8_t[DATA_PACKET_LENGTH]; uint8_t* buffer = new uint8_t[DATA_PACKET_LENGTH];
@ -1159,7 +1171,7 @@ UInt8Array BaseNetwork::createP25_PDUMessage(uint32_t& length, const p25::data::
::memcpy(buffer + 0U, TAG_P25_DATA, 4U); ::memcpy(buffer + 0U, TAG_P25_DATA, 4U);
buffer[4U] = header.getSAP(); // Service Access Point buffer[4U] = header.getSAP(); // Service Access Point
if (header.getFormat() == p25::PDU_FMT_CONFIRMED) { if (header.getFormat() == PDUFormatType::CONFIRMED) {
buffer[4U] |= 0x80U; buffer[4U] |= 0x80U;
} }
@ -1170,7 +1182,7 @@ UInt8Array BaseNetwork::createP25_PDUMessage(uint32_t& length, const p25::data::
buffer[20U] = header.getBlocksToFollow(); // Blocks To Follow buffer[20U] = header.getBlocksToFollow(); // Blocks To Follow
buffer[21U] = currentBlock; // Current Block buffer[21U] = currentBlock; // Current Block
buffer[22U] = p25::P25_DUID_PDU; // DUID buffer[22U] = DUID::PDU; // DUID
// pack raw P25 PDU bytes // pack raw P25 PDU bytes
uint32_t count = MSG_HDR_SIZE; uint32_t count = MSG_HDR_SIZE;

@ -196,7 +196,7 @@ namespace network
virtual UInt8Array readP25(bool& ret, uint32_t& frameLength); virtual UInt8Array readP25(bool& ret, uint32_t& frameLength);
/// <summary>Writes P25 LDU1 frame data to the network.</summary> /// <summary>Writes P25 LDU1 frame data to the network.</summary>
virtual bool writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data, virtual bool writeP25LDU1(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data,
uint8_t frameType); p25::defines::FrameType::E frameType);
/// <summary>Writes P25 LDU2 frame data to the network.</summary> /// <summary>Writes P25 LDU2 frame data to the network.</summary>
virtual bool writeP25LDU2(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data); virtual bool writeP25LDU2(const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, const uint8_t* data);
/// <summary>Writes P25 TDU frame data to the network.</summary> /// <summary>Writes P25 TDU frame data to the network.</summary>
@ -269,12 +269,12 @@ namespace network
UInt8Array createDMR_Message(uint32_t& length, const uint32_t streamId, const dmr::data::Data& data); UInt8Array createDMR_Message(uint32_t& length, const uint32_t streamId, const dmr::data::Data& data);
/// <summary>Creates an P25 frame message header.</summary> /// <summary>Creates an P25 frame message header.</summary>
void createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, void createP25_MessageHdr(uint8_t* buffer, p25::defines::DUID::E duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
uint8_t frameType = p25::P25_FT_DATA_UNIT); p25::defines::FrameType::E frameType = p25::defines::FrameType::DATA_UNIT);
/// <summary>Creates an P25 LDU1 frame message.</summary> /// <summary>Creates an P25 LDU1 frame message.</summary>
UInt8Array createP25_LDU1Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, UInt8Array createP25_LDU1Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
const uint8_t* data, uint8_t frameType); const uint8_t* data, p25::defines::FrameType::E frameType);
/// <summary>Creates an P25 LDU2 frame message.</summary> /// <summary>Creates an P25 LDU2 frame message.</summary>
UInt8Array createP25_LDU2Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd, UInt8Array createP25_LDU2Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
const uint8_t* data); const uint8_t* data);

@ -17,250 +17,363 @@
#include "common/Defines.h" #include "common/Defines.h"
// Shorthand macro to nxdn::defines -- keeps source code that doesn't use "using" concise
#define NXDDEF nxdn::defines
namespace nxdn namespace nxdn
{ {
// --------------------------------------------------------------------------- namespace defines
// Constants {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Constants
const uint32_t NXDN_FRAME_LENGTH_BITS = 384U; // ---------------------------------------------------------------------------
const uint32_t NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
const uint32_t NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U; const uint32_t NXDN_FRAME_LENGTH_BITS = 384U;
const uint32_t NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
const uint32_t NXDN_FSW_LENGTH_BITS = 20U; const uint32_t NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
const uint32_t NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const uint32_t NXDN_FSW_LENGTH_BITS = 20U;
const uint8_t NXDN_FSW_BYTES[] = { 0xCDU, 0xF5U, 0x90U }; const uint32_t NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const uint8_t NXDN_FSW_BYTES_MASK[] = { 0xFFU, 0xFFU, 0xF0U };
const uint32_t NXDN_FSW_BYTES_LENGTH = 3U; const uint8_t NXDN_FSW_BYTES[] = { 0xCDU, 0xF5U, 0x90U };
const uint8_t NXDN_FSW_BYTES_MASK[] = { 0xFFU, 0xFFU, 0xF0U };
const uint8_t NXDN_PREAMBLE[] = { 0x57U, 0x75U, 0xFDU }; const uint32_t NXDN_FSW_BYTES_LENGTH = 3U;
const uint32_t NXDN_LICH_LENGTH_BITS = 16U; const uint8_t NXDN_PREAMBLE[] = { 0x57U, 0x75U, 0xFDU };
const uint32_t NXDN_LICH_LENGTH_BYTES = NXDN_LICH_LENGTH_BITS / 8U;
const uint32_t NXDN_LICH_LENGTH_BITS = 16U;
const uint32_t NXDN_SACCH_FEC_LENGTH_BITS = 60U; // Puncture and Interleave Length const uint32_t NXDN_LICH_LENGTH_BYTES = NXDN_LICH_LENGTH_BITS / 8U;
const uint32_t NXDN_SACCH_FEC_LENGTH_BYTES = (NXDN_SACCH_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BITS = 72U; // Convolution Length const uint32_t NXDN_SACCH_FEC_LENGTH_BITS = 60U; // Puncture and Interleave Length
const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BYTES = NXDN_SACCH_FEC_CONV_LENGTH_BITS / 8U; const uint32_t NXDN_SACCH_FEC_LENGTH_BYTES = (NXDN_SACCH_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_SACCH_CRC_LENGTH_BITS = 36U; // Data + CRC-6 + 4-bit NULL const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BITS = 72U; // Convolution Length
const uint32_t NXDN_SACCH_CRC_LENGTH_BYTES = (NXDN_SACCH_CRC_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_SACCH_FEC_CONV_LENGTH_BYTES = NXDN_SACCH_FEC_CONV_LENGTH_BITS / 8U;
const uint32_t NXDN_SACCH_LENGTH_BITS = 26U; const uint32_t NXDN_SACCH_CRC_LENGTH_BITS = 36U; // Data + CRC-6 + 4-bit NULL
const uint32_t NXDN_SACCH_CRC_LENGTH_BYTES = (NXDN_SACCH_CRC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_FACCH1_FEC_LENGTH_BITS = 144U; // Puncture and Interleave Length const uint32_t NXDN_SACCH_LENGTH_BITS = 26U;
const uint32_t NXDN_FACCH1_FEC_LENGTH_BYTES = NXDN_FACCH1_FEC_LENGTH_BITS / 8U;
const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BITS = 192U; // Convolution Length const uint32_t NXDN_FACCH1_FEC_LENGTH_BITS = 144U; // Puncture and Interleave Length
const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BYTES = NXDN_FACCH1_FEC_CONV_LENGTH_BITS / 8U; const uint32_t NXDN_FACCH1_FEC_LENGTH_BYTES = NXDN_FACCH1_FEC_LENGTH_BITS / 8U;
const uint32_t NXDN_FACCH1_CRC_LENGTH_BITS = 96U; // Data + CRC-12 + 4-bit NULL const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BITS = 192U; // Convolution Length
const uint32_t NXDN_FACCH1_CRC_LENGTH_BYTES = NXDN_FACCH1_CRC_LENGTH_BITS / 8U; const uint32_t NXDN_FACCH1_FEC_CONV_LENGTH_BYTES = NXDN_FACCH1_FEC_CONV_LENGTH_BITS / 8U;
const uint32_t NXDN_FACCH1_LENGTH_BITS = 80U; const uint32_t NXDN_FACCH1_CRC_LENGTH_BITS = 96U; // Data + CRC-12 + 4-bit NULL
const uint32_t NXDN_FACCH1_CRC_LENGTH_BYTES = NXDN_FACCH1_CRC_LENGTH_BITS / 8U;
const uint32_t NXDN_UDCH_FEC_LENGTH_BITS = 348U; // Puncture and Interleave Length const uint32_t NXDN_FACCH1_LENGTH_BITS = 80U;
const uint32_t NXDN_UDCH_FEC_LENGTH_BYTES = (NXDN_UDCH_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BITS = 406U; // Convolution Length const uint32_t NXDN_UDCH_FEC_LENGTH_BITS = 348U; // Puncture and Interleave Length
const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BYTES = (NXDN_UDCH_FEC_CONV_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_UDCH_FEC_LENGTH_BYTES = (NXDN_UDCH_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_UDCH_CRC_LENGTH_BITS = 203U; // Data + CRC-15 + 4-bit NULL const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BITS = 406U; // Convolution Length
const uint32_t NXDN_UDCH_CRC_LENGTH_BYTES = (NXDN_UDCH_CRC_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_UDCH_FEC_CONV_LENGTH_BYTES = (NXDN_UDCH_FEC_CONV_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_UDCH_LENGTH_BITS = 184U; const uint32_t NXDN_UDCH_CRC_LENGTH_BITS = 203U; // Data + CRC-15 + 4-bit NULL
const uint32_t NXDN_UDCH_CRC_LENGTH_BYTES = (NXDN_UDCH_CRC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length const uint32_t NXDN_UDCH_LENGTH_BITS = 184U;
const uint32_t NXDN_CAC_FEC_LENGTH_BYTES = (NXDN_CAC_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BITS = 350U; // Convolution Length const uint32_t NXDN_CAC_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length
const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BYTES = (NXDN_CAC_FEC_CONV_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_CAC_FEC_LENGTH_BYTES = (NXDN_CAC_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_CRC_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BITS = 350U; // Convolution Length
const uint32_t NXDN_CAC_CRC_LENGTH_BYTES = (NXDN_CAC_CRC_LENGTH_BITS / 8U) + 1U; const uint32_t NXDN_CAC_FEC_CONV_LENGTH_BYTES = (NXDN_CAC_FEC_CONV_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_LENGTH_BITS = 155U; const uint32_t NXDN_CAC_CRC_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL
const uint32_t NXDN_CAC_E_POST_FIELD_BITS = 24U; const uint32_t NXDN_CAC_CRC_LENGTH_BYTES = (NXDN_CAC_CRC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_LENGTH_BITS = 155U;
const uint32_t NXDN_CAC_IN_FEC_LENGTH_BITS = 252U; // Puncture and Interleave Length const uint32_t NXDN_CAC_E_POST_FIELD_BITS = 24U;
const uint32_t NXDN_CAC_IN_FEC_LENGTH_BYTES = (NXDN_CAC_IN_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS = 312U; // Convolution Length const uint32_t NXDN_CAC_IN_FEC_LENGTH_BITS = 252U; // Puncture and Interleave Length
const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS / 8U; const uint32_t NXDN_CAC_IN_FEC_LENGTH_BYTES = (NXDN_CAC_IN_FEC_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_LONG_CRC_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS = 312U; // Convolution Length
const uint32_t NXDN_CAC_LONG_LENGTH_BITS = 136U; const uint32_t NXDN_CAC_LONG_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS / 8U;
const uint32_t NXDN_CAC_SHORT_CRC_LENGTH_BITS = 126U; // Data + CRC-16 + 4-bit NULL const uint32_t NXDN_CAC_LONG_CRC_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL
const uint32_t NXDN_CAC_SHORT_LENGTH_BITS = 106U; const uint32_t NXDN_CAC_LONG_LENGTH_BITS = 136U;
const uint32_t NXDN_CAC_SHORT_CRC_LENGTH_BITS = 126U; // Data + CRC-16 + 4-bit NULL
const uint32_t NXDN_RTCH_LC_LENGTH_BITS = 176U; const uint32_t NXDN_CAC_SHORT_LENGTH_BITS = 106U;
const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = (NXDN_RTCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RTCH_LC_LENGTH_BITS = 176U;
const uint32_t NXDN_RCCH_LC_LENGTH_BITS = 144U; const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = (NXDN_RTCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RCCH_LC_LENGTH_BYTES = (NXDN_RCCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RCCH_CAC_LC_LONG_LENGTH_BITS = 128U; const uint32_t NXDN_RCCH_LC_LENGTH_BITS = 144U;
const uint32_t NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS = 96U; const uint32_t NXDN_RCCH_LC_LENGTH_BYTES = (NXDN_RCCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RCCH_CAC_LC_LONG_LENGTH_BITS = 128U;
const uint32_t NXDN_FSW_LICH_SACCH_LENGTH_BITS = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS; const uint32_t NXDN_RCCH_CAC_LC_SHORT_LENGTH_BITS = 96U;
const uint32_t NXDN_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
const uint32_t NXDN_FSW_LICH_SACCH_LENGTH_BITS = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_FEC_LENGTH_BITS;
const uint8_t NXDN_LICH_RFCT_RCCH = 0U; const uint32_t NXDN_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
const uint8_t NXDN_LICH_RFCT_RTCH = 1U;
const uint8_t NXDN_LICH_RFCT_RDCH = 2U; const uint8_t SACCH_IDLE[] = { 0x10U, 0x00U, 0x00U };
const uint8_t NXDN_LICH_RFCT_RTCH_C = 3U;
const uint8_t NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U };
const uint8_t NXDN_LICH_CAC_OUTBOUND = 0U;
const uint8_t NXDN_LICH_CAC_INBOUND_LONG = 1U; const uint8_t CALLSIGN_LENGTH_BYTES = 8U;
const uint8_t NXDN_LICH_CAC_INBOUND_SHORT = 3U;
const uint32_t MI_LENGTH_BYTES = 8U;
const uint8_t NXDN_LICH_USC_SACCH_NS = 0U; const uint32_t PCKT_INFO_LENGTH_BYTES = 3U;
const uint8_t NXDN_LICH_USC_UDCH = 1U;
const uint8_t NXDN_LICH_USC_SACCH_SS = 2U; /** Thresholds */
const uint8_t NXDN_LICH_USC_SACCH_SS_IDLE = 3U; const uint32_t DEFAULT_SILENCE_THRESHOLD = 14U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 4U;
const uint8_t NXDN_LICH_DATA_NORMAL = 0U; const uint32_t MAX_NXDN_VOICE_ERRORS = 144U;
const uint8_t NXDN_LICH_DATA_IDLE = 1U; const uint32_t MAX_NXDN_VOICE_ERRORS_STEAL = 94U;
const uint8_t NXDN_LICH_DATA_COMMON = 2U;
/// <summary>
const uint8_t NXDN_LICH_STEAL_NONE = 3U; /// Link Information Channel - RF Channel Type
const uint8_t NXDN_LICH_STEAL_FACCH1_2 = 2U; /// </summary>
const uint8_t NXDN_LICH_STEAL_FACCH1_1 = 1U; namespace RFChannelType {
const uint8_t NXDN_LICH_STEAL_FACCH = 0U; // RF Channel Type Enumeration
enum E : uint8_t {
const uint8_t NXDN_SR_RCCH_SINGLE = 0x00U; RCCH = 0U, // Control Channel
const uint8_t NXDN_SR_RCCH_DUAL = 0x01U; RTCH = 1U, // Traffic Channel
const uint8_t NXDN_SR_RCCH_HEAD_SINGLE = 0x02U; RDCH = 2U, // Data Channel
const uint8_t NXDN_SR_RCCH_HEAD_DUAL = 0x03U; RTCH_C = 3U // Composite Control/Traffic Channel
};
const uint8_t NXDN_SR_SINGLE = 0U; }
const uint8_t NXDN_SR_4_4 = 0U;
const uint8_t NXDN_SR_3_4 = 1U; /// <summary>
const uint8_t NXDN_SR_2_4 = 2U; /// Link Information Channel - Functional Channel Type
const uint8_t NXDN_SR_1_4 = 3U; /// </summary>
namespace FuncChannelType {
const uint8_t SACCH_IDLE[] = { 0x10U, 0x00U, 0x00U }; // Functional Channel Type Enumeration
enum E : uint8_t {
const uint32_t DEFAULT_SILENCE_THRESHOLD = 14U; // Common Access Channel
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 4U; CAC_OUTBOUND = 0U, // Common Access Channel - Outbound
const uint32_t MAX_NXDN_VOICE_ERRORS = 144U; CAC_INBOUND_LONG = 1U, // Common Access Channel - Inbound Long
const uint32_t MAX_NXDN_VOICE_ERRORS_STEAL = 94U; CAC_INBOUND_SHORT = 3U, // Common Access Channel - Inbound Short
const uint8_t NXDN_NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U }; // Slow Associated Control Channel / User Data Channel
USC_SACCH_NS = 0U, //
const uint8_t NXDN_CALLSIGN_LENGTH_BYTES = 8U; USC_UDCH = 1U, //
USC_SACCH_SS = 2U, //
const uint32_t NXDN_MI_LENGTH_BYTES = 8U; USC_SACCH_SS_IDLE = 3U //
const uint32_t NXDN_PCKT_INFO_LENGTH_BYTES = 3U; };
}
const uint8_t NXDN_CIPHER_TYPE_NONE = 0x00U;
/// <summary>
const uint8_t DATA_RSP_CLASS_ACK = 0x00U; /// Link Information Channel - Channel Options
const uint8_t DATA_RSP_CLASS_ACK_S = 0x01U; /// </summary>
const uint8_t DATA_RSP_CLASS_NACK = 0x03U; namespace ChOption {
// Channel Option(s) Enumeration
const uint8_t NXDN_LOC_CAT_GLOBAL = 0x00U; enum E : uint8_t {
const uint8_t NXDN_LOC_CAT_LOCAL = 0x01U; DATA_NORMAL = 0U, //
const uint8_t NXDN_LOC_CAT_REGIONAL = 0x02U; DATA_IDLE = 1U, //
DATA_COMMON = 2U, //
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_NETWORK = 0x51U;
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_TEMP = 0x52U; STEAL_NONE = 3U, //
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_QUEUED = 0x53U; STEAL_FACCH1_2 = 2U, //
const uint8_t NXDN_CAUSE_SVC_UNAVAILABLE = 0x06U; STEAL_FACCH1_1 = 1U, //
const uint8_t NXDN_CAUSE_PROC_ERROR = 0x70U; STEAL_FACCH = 0U //
const uint8_t NXDN_CAUSE_PROC_ERROR_UNDEF = 0x71U; };
}
const uint8_t NXDN_CAUSE_MM_REG_ACCEPTED = 0x01U;
const uint8_t NXDN_CAUSE_MM_LOC_ACPT_GRP_FAIL = 0x04U; /// <summary>
const uint8_t NXDN_CAUSE_MM_LOC_ACPT_GRP_REFUSE = 0x04U; /// Common Access Channel - Structure
const uint8_t NXDN_CAUSE_MM_REG_FAILED = 0x06U; /// </summary>
const uint8_t NXDN_CAUSE_MM_REG_REFUSED = 0x08U; namespace ChStructure {
// Channel Structure Enumeration
const uint8_t NXDN_CAUSE_VD_ACCEPTED = 0x10U; enum E : uint8_t {
const uint8_t NXDN_CAUSE_VD_GRP_NOT_PERM = 0x11U; SR_RCCH_SINGLE = 0x00U, //
const uint8_t NXDN_CAUSE_VD_REQ_UNIT_NOT_PERM = 0x12U; SR_RCCH_DUAL = 0x01U, //
const uint8_t NXDN_CAUSE_VD_TGT_UNIT_NOT_PERM = 0x13U; SR_RCCH_HEAD_SINGLE = 0x02U, //
const uint8_t NXDN_CAUSE_VD_REQ_UNIT_NOT_REG = 0x1CU; SR_RCCH_HEAD_DUAL = 0x03U, //
const uint8_t NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL = 0x30U;
const uint8_t NXDN_CAUSE_VD_QUE_TGT_UNIT_BUSY = 0x38U; SR_SINGLE = 0U, //
const uint8_t NXDN_CAUSE_VD_QUE_GRP_BUSY = 0x39U; SR_4_4 = 0U, //
SR_3_4 = 1U, //
const uint8_t NXDN_CAUSE_SS_ACK_R = 0x01U; SR_2_4 = 2U, //
const uint8_t NXDN_CAUSE_SS_ACK_S = 0x02U; SR_1_4 = 3U //
const uint8_t NXDN_CAUSE_SS_NACK = 0x08U; };
const uint8_t NXDN_CAUSE_SS_ACCEPTED = 0x10U; }
const uint8_t NXDN_CAUSE_SS_GRP_NOT_PERM = 0x11U;
const uint8_t NXDN_CAUSE_SS_REQ_UNIT_NOT_PERM = 0x12U; /** Encryption Algorithms */
const uint8_t NXDN_CAUSE_SS_TGT_UNIT_NOT_PERM = 0x13U; const uint8_t CIPHER_TYPE_NONE = 0x00U; // Unencrypted
const uint8_t NXDN_CAUSE_SS_REQ_UNIT_NOT_REG = 0x1CU;
/// <summary>
const uint8_t NXDN_CAUSE_DREQ_USER = 0x10U; /// Location Category
const uint8_t NXDN_CAUSE_DREQ_OTHER = 0x1FU; /// <summary>
namespace LocationCategory {
const uint8_t NXDN_CAUSE_DISC_USER = 0x10U; // Location Category Enumeration
const uint8_t NXDN_CAUSE_DISC_OTHER = 0x1FU; enum E : uint8_t {
GLOBAL = 0x00U, // Global
const uint8_t NXDN_SIF1_DATA_CALL_SVC = 0x01U; LOCAL = 0x01U, // Local
const uint8_t NXDN_SIF1_VOICE_CALL_SVC = 0x02U; REGIONAL = 0x02U // Regional
const uint8_t NXDN_SIF1_COMPOSITE_CONTROL = 0x04U; };
const uint8_t NXDN_SIF1_AUTH_SVC = 0x08U; }
const uint8_t NXDN_SIF1_GRP_REG_SVC = 0x10U;
const uint8_t NXDN_SIF1_LOC_REG_SVC = 0x20U; /// <summary>
const uint8_t NXDN_SIF1_MULTI_SYSTEM_SVC = 0x40U; /// Data Response Class
const uint8_t NXDN_SIF1_MULTI_SITE_SVC = 0x80U; /// <summary>
namespace PDUResponseClass {
const uint8_t NXDN_SIF2_IP_NETWORK = 0x10U; enum : uint8_t
const uint8_t NXDN_SIF2_PSTN_NETWORK = 0x20U; {
const uint8_t NXDN_SIF2_STATUS_CALL_REM_CTRL = 0x40U; ACK = 0x00U, // Acknowledge
const uint8_t NXDN_SIF2_SHORT_DATA_CALL_SVC = 0x80U; ACK_S = 0x01U, //
NACK = 0x03U // Negative Acknowledge
const uint8_t NXDN_CH_ACCESS_STEP_SYS_DEFINED = 0x00U; };
const uint8_t NXDN_CH_ACCESS_STEP_1DOT25K = 0x02U; }
const uint8_t NXDN_CH_ACCESS_STEP_3DOT125K = 0x03U;
/// <summary>
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_100 = 0x01U; /// Causes
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_330 = 0x02U; /// <summary>
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_400 = 0x03U; namespace CauseResponse {
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_750 = 0x04U; enum : uint8_t {
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_SYS_DEFINED = 0x07U; RSRC_NOT_AVAIL_NETWORK = 0x51U, // Network Resource Not Available
RSRC_NOT_AVAIL_TEMP = 0x52U, // Resource Temporarily Not Available
// Common Message Types RSRC_NOT_AVAIL_QUEUED = 0x53U, // Resource Queued Not Available
const uint8_t MESSAGE_TYPE_IDLE = 0x10U; // IDLE - Idle SVC_UNAVAILABLE = 0x06U, // Service Unavailable
const uint8_t MESSAGE_TYPE_DISC = 0x11U; // DISC - Disconnect PROC_ERROR = 0x70U, //
const uint8_t MESSAGE_TYPE_DST_ID_INFO = 0x17U; // DST_ID_INFO - Digital Station ID PROC_ERROR_UNDEF = 0x71U, //
const uint8_t MESSAGE_TYPE_SRV_INFO = 0x19U; // SRV_INFO - Service Information
const uint8_t MESSAGE_TYPE_CCH_INFO = 0x1AU; // CCH_INFO - Control Channel Information MM_REG_ACCEPTED = 0x01U, // Registration Accepted
const uint8_t MESSAGE_TYPE_ADJ_SITE_INFO = 0x1BU; // ADJ_SITE_INFO - Adjacent Site Information MM_LOC_ACPT_GRP_FAIL = 0x04U, // Location Accepted / Group Failed
MM_LOC_ACPT_GRP_REFUSE = 0x04U, // Location Accepted / Group Refused
// Traffic Channel Message Types MM_REG_FAILED = 0x06U, // Registration Failed
const uint8_t RTCH_MESSAGE_TYPE_VCALL = 0x01U; // VCALL - Voice Call MM_REG_REFUSED = 0x08U, // Registration Refused
#define NXDN_RTCH_MSG_TYPE_VCALL "VCALL (Voice Call)"
#define NXDN_RTCH_MSG_TYPE_VCALL_RESP "VCALL_RESP (Voice Call Response)" VD_ACCEPTED = 0x10U, //
const uint8_t RTCH_MESSAGE_TYPE_VCALL_IV = 0x03U; // VCALL_IV - Voice Call Initialization Vector VD_GRP_NOT_PERM = 0x11U, //
const uint8_t RTCH_MESSAGE_TYPE_TX_REL_EX = 0x07U; // TX_REL_EX - Transmission Release Extension VD_REQ_UNIT_NOT_PERM = 0x12U, //
const uint8_t RTCH_MESSAGE_TYPE_TX_REL = 0x08U; // TX_REL - Transmission Release VD_TGT_UNIT_NOT_PERM = 0x13U, //
#define NXDN_RTCH_MSG_TYPE_TX_REL "TX_REL (Transmission Release)" VD_REQ_UNIT_NOT_REG = 0x1CU, //
const uint8_t RTCH_MESSAGE_TYPE_DCALL_HDR = 0x09U; // DCALL - Data Call (Header) VD_QUE_CHN_RESOURCE_NOT_AVAIL = 0x30U, //
#define NXDN_RTCH_MSG_TYPE_DCALL_HDR "DCALL (Data Call Header)" VD_QUE_TGT_UNIT_BUSY = 0x38U, //
const uint8_t RTCH_MESSAGE_TYPE_DCALL_DATA = 0x0BU; // DCALL - Data Call (User Data Format) VD_QUE_GRP_BUSY = 0x39U, //
const uint8_t RTCH_MESSAGE_TYPE_DCALL_ACK = 0x0CU; // DCALL_ACK - Data Call Acknowledge
const uint8_t RTCH_MESSAGE_TYPE_HEAD_DLY = 0x0FU; // HEAD_DLY - Header Delay SS_ACK_R = 0x01U, //
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR = 0x38U; // SDCALL_REQ - Short Data Call Request (Header) SS_ACK_S = 0x02U, //
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_REQ_DATA = 0x39U; // SDCALL_REQ - Short Data Call Request (User Data Format) SS_NACK = 0x08U, //
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_IV = 0x3AU; // SDCALL_IV - Short Data Call Initialization Vector SS_ACCEPTED = 0x10U, //
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_RESP = 0x3BU; // SDCALL_RESP - Short Data Call Response SS_GRP_NOT_PERM = 0x11U, //
SS_REQ_UNIT_NOT_PERM = 0x12U, //
// Control Channel Message Types SS_TGT_UNIT_NOT_PERM = 0x13U, //
const uint8_t RCCH_MESSAGE_TYPE_VCALL_CONN = 0x03U; // VCALL_CONN - Voice Call Connection Request (ISP) / Voice Call Connection Response (OSP) SS_REQ_UNIT_NOT_REG = 0x1CU, //
const uint8_t RCCH_MESSAGE_TYPE_VCALL_ASSGN = 0x04U; // VCALL_ASSGN - Voice Call Assignment
const uint8_t RCCH_MESSAGE_TYPE_DCALL_ASSGN = 0x14U; // DCALL_ASSGN - Data Call Assignment DREQ_USER = 0x10U, //
const uint8_t RCCH_MESSAGE_TYPE_SITE_INFO = 0x18U; // SITE_INFO - Site Information DREQ_OTHER = 0x1FU, //
const uint8_t RCCH_MESSAGE_TYPE_REG = 0x20U; // REG - Registration Request (ISP) / Registration Response (OSP)
const uint8_t RCCH_MESSAGE_TYPE_REG_C = 0x22U; // REG_C - Registration Clear Request (ISP) / Registration Clear Response (OSP) DISC_USER = 0x10U, //
const uint8_t RCCH_MESSAGE_TYPE_REG_COMM = 0x23U; // REG_COMM - Registration Command DISC_OTHER = 0x1FU //
const uint8_t RCCH_MESSAGE_TYPE_GRP_REG = 0x24U; // GRP_REG - Group Registration Request (ISP) / Group Registration Response (OSP) };
const uint8_t RCCH_MESSAGE_TYPE_PROP_FORM = 0x3FU; // PROP_FORM - Proprietary Form }
// Call Types /// <summary>
const uint8_t CALL_TYPE_BROADCAST = 0x00U; /// Site Information 1 (SIF1)
const uint8_t CALL_TYPE_CONFERENCE = 0x01U; /// <summary>
const uint8_t CALL_TYPE_UNSPECIFIED = 0x02U; namespace SiteInformation1 {
const uint8_t CALL_TYPE_INDIVIDUAL = 0x04U; enum : uint8_t {
const uint8_t CALL_TYPE_INTERCONNECT = 0x06U; DATA_CALL_SVC = 0x01U, // Data Call Service
const uint8_t CALL_TYPE_SPEED_DIAL = 0x07U; VOICE_CALL_SVC = 0x02U, // Voice Call Service
COMPOSITE_CONTROL = 0x04U, // Composite Control Channel
// Transmission Mode AUTH_SVC = 0x08U, // Authentication Service
const uint8_t TRANSMISSION_MODE_4800 = 0x00U; GRP_REG_SVC = 0x10U, // Group Registration Service
const uint8_t TRANSMISSION_MODE_9600 = 0x02U; LOC_REG_SVC = 0x20U, // Location Registration Service
const uint8_t TRANSMISSION_MODE_9600_EFR = 0x03U; // should never be used on data calls MULTI_SYSTEM_SVC = 0x40U, // Multi-System Service
MULTI_SITE_SVC = 0x80U // Multi-Site Service
};
}
/// <summary>
/// Site Information 2 (SIF2)
/// <summary>
namespace SiteInformation2 {
enum : uint8_t {
IP_NETWORK = 0x10U, // IP Networked
PSTN_NETWORK = 0x20U, // PSTN Networked
STATUS_CALL_REM_CTRL = 0x40U, //
SHORT_DATA_CALL_SVC = 0x80U //
};
}
/// <summary>
/// Channel Access - Step
/// <summary>
namespace ChAccessStep {
// Channel Access Step Enumeration
enum E : uint8_t {
SYS_DEFINED = 0x00U, // System Defined
ONEDOT25K = 0x02U, //
THREEDOT125K = 0x03U //
};
}
/// <summary>
/// Channel Access - Base
/// <summary>
namespace ChAccessBase {
// Channel Access Base Enumeration
enum E : uint8_t {
FREQ_100 = 0x01U, //
FREQ_330 = 0x02U, //
FREQ_400 = 0x03U, //
FREQ_750 = 0x04U, //
FREQ_SYS_DEFINED = 0x07U //
};
}
/// <summary>
/// Call Types
/// <summary>
namespace CallType {
enum : uint8_t {
BROADCAST = 0x00U, // Broadcast
CONFERENCE = 0x01U, // Conference
UNSPECIFIED = 0x02U, // Unspecified
INDIVIDUAL = 0x04U, // Individual
INTERCONNECT = 0x06U, // Interconnect
SPEED_DIAL = 0x07U // Speed Dial
};
}
/// <summary>
/// Transmission Mode
/// <summary>
namespace TransmissionMode {
enum : uint8_t {
MODE_4800 = 0x00U, // 4800-baud
MODE_9600 = 0x02U, // 9600-baud
MODE_9600_EFR = 0x03U // 9600-baud; should never be used on data calls
};
}
/// <summary>
/// Message Types
/// <summary>
namespace MessageType {
enum : uint8_t {
// Common Message Types
IDLE = 0x10U, // IDLE - Idle
DISC = 0x11U, // DISC - Disconnect
DST_ID_INFO = 0x17U, // DST_ID_INFO - Digital Station ID
SRV_INFO = 0x19U, // SRV_INFO - Service Information
CCH_INFO = 0x1AU, // CCH_INFO - Control Channel Information
ADJ_SITE_INFO = 0x1BU, // ADJ_SITE_INFO - Adjacent Site Information
// Traffic Channel Message Types
RTCH_VCALL = 0x01U, // VCALL - Voice Call
RTCH_VCALL_IV = 0x03U, // VCALL_IV - Voice Call Initialization Vector
RTCH_TX_REL_EX = 0x07U, // TX_REL_EX - Transmission Release Extension
RTCH_TX_REL = 0x08U, // TX_REL - Transmission Release
RTCH_DCALL_HDR = 0x09U, // DCALL - Data Call (Header)
RTCH_DCALL_DATA = 0x0BU, // DCALL - Data Call (User Data Format)
RTCH_DCALL_ACK = 0x0CU, // DCALL_ACK - Data Call Acknowledge
RTCH_HEAD_DLY = 0x0FU, // HEAD_DLY - Header Delay
RTCH_SDCALL_REQ_HDR = 0x38U, // SDCALL_REQ - Short Data Call Request (Header)
RTCH_SDCALL_REQ_DATA = 0x39U, // SDCALL_REQ - Short Data Call Request (User Data Format)
RTCH_SDCALL_IV = 0x3AU, // SDCALL_IV - Short Data Call Initialization Vector
RTCH_SDCALL_RESP = 0x3BU, // SDCALL_RESP - Short Data Call Response
// Control Channel Message Types
RCCH_VCALL_CONN = 0x03U, // VCALL_CONN - Voice Call Connection Request (ISP) / Voice Call Connection Response (OSP)
RCCH_VCALL_ASSGN = 0x04U, // VCALL_ASSGN - Voice Call Assignment
RCCH_DCALL_ASSGN = 0x14U, // DCALL_ASSGN - Data Call Assignment
RCCH_SITE_INFO = 0x18U, // SITE_INFO - Site Information
RCCH_REG = 0x20U, // REG - Registration Request (ISP) / Registration Response (OSP)
RCCH_REG_C = 0x22U, // REG_C - Registration Clear Request (ISP) / Registration Clear Response (OSP)
RCCH_REG_COMM = 0x23U, // REG_COMM - Registration Command
RCCH_GRP_REG = 0x24U, // GRP_REG - Group Registration Request (ISP) / Group Registration Response (OSP)
RCCH_PROP_FORM = 0x3FU // PROP_FORM - Proprietary Form
};
}
#define NXDN_RTCH_MSG_TYPE_VCALL "VCALL (Voice Call)"
#define NXDN_RTCH_MSG_TYPE_VCALL_RESP "VCALL_RESP (Voice Call Response)"
#define NXDN_RTCH_MSG_TYPE_TX_REL "TX_REL (Transmission Release)"
#define NXDN_RTCH_MSG_TYPE_DCALL_HDR "DCALL (Data Call Header)"
} // namespace defines
} // namespace nxdn } // namespace nxdn
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2020 Jonathan Naylor, G4KLX * Copyright (C) 2020 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -18,6 +18,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
#include <cassert> #include <cassert>

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__NXDN_SITE_DATA_H__) #if !defined(__NXDN_SITE_DATA_H__)
@ -30,7 +30,7 @@ namespace nxdn
m_locId(1U), m_locId(1U),
m_channelId(1U), m_channelId(1U),
m_channelNo(1U), m_channelNo(1U),
m_serviceClass(NXDN_SIF1_VOICE_CALL_SVC | NXDN_SIF1_DATA_CALL_SVC), m_serviceClass(defines::SiteInformation1::VOICE_CALL_SVC | defines::SiteInformation1::DATA_CALL_SVC),
m_isAdjSite(false), m_isAdjSite(false),
m_callsign("CHANGEME"), m_callsign("CHANGEME"),
m_requireReg(false), m_requireReg(false),
@ -48,7 +48,7 @@ namespace nxdn
m_locId(locId), m_locId(locId),
m_channelId(channelId), m_channelId(channelId),
m_channelNo(channelNo), m_channelNo(channelNo),
m_serviceClass(NXDN_SIF1_VOICE_CALL_SVC | NXDN_SIF1_DATA_CALL_SVC), m_serviceClass(defines::SiteInformation1::VOICE_CALL_SVC | defines::SiteInformation1::DATA_CALL_SVC),
m_isAdjSite(false), m_isAdjSite(false),
m_callsign("CHANGEME"), m_callsign("CHANGEME"),
m_requireReg(requireReq), m_requireReg(requireReq),

@ -9,6 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2020 Jonathan Naylor, G4KLX * Copyright (C) 2020 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -16,6 +17,7 @@
#include "nxdn/Sync.h" #include "nxdn/Sync.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
#include <cassert> #include <cassert>

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/channel/CAC.h" #include "nxdn/channel/CAC.h"
@ -18,6 +18,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel; using namespace nxdn::channel;
#include <cassert> #include <cassert>
@ -101,7 +102,7 @@ const uint32_t PUNCTURE_LIST_OUT[] = {
/// </summary> /// </summary>
CAC::CAC() : CAC::CAC() :
m_ran(0U), m_ran(0U),
m_structure(NXDN_SR_RCCH_SINGLE), m_structure(ChStructure::SR_RCCH_SINGLE),
m_idleBusy(true), m_idleBusy(true),
m_txContinuous(false), m_txContinuous(false),
m_receive(true), m_receive(true),
@ -118,7 +119,7 @@ CAC::CAC() :
/// <param name="data"></param> /// <param name="data"></param>
CAC::CAC(const CAC& data) : CAC::CAC(const CAC& data) :
m_ran(0U), m_ran(0U),
m_structure(NXDN_SR_RCCH_SINGLE), m_structure(ChStructure::SR_RCCH_SINGLE),
m_idleBusy(true), m_idleBusy(true),
m_txContinuous(false), m_txContinuous(false),
m_receive(true), m_receive(true),
@ -147,7 +148,7 @@ CAC& CAC::operator=(const CAC& data)
::memcpy(m_data, data.m_data, NXDN_CAC_CRC_LENGTH_BYTES); ::memcpy(m_data, data.m_data, NXDN_CAC_CRC_LENGTH_BYTES);
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
m_idleBusy = data.m_idleBusy; m_idleBusy = data.m_idleBusy;
m_txContinuous = data.m_txContinuous; m_txContinuous = data.m_txContinuous;
@ -217,7 +218,7 @@ bool CAC::decode(const uint8_t* data)
::memset(crc, 0x00U, 2U); ::memset(crc, 0x00U, 2U);
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
uint32_t offset = NXDN_CAC_SHORT_CRC_LENGTH_BITS - 20U; uint32_t offset = NXDN_CAC_SHORT_CRC_LENGTH_BITS - 20U;
for (uint32_t i = 0U; i < 16U; i++, offset++) { for (uint32_t i = 0U; i < 16U; i++, offset++) {
@ -362,7 +363,7 @@ void CAC::copy(const CAC& data)
::memcpy(m_data, data.m_data, NXDN_CAC_CRC_LENGTH_BYTES); ::memcpy(m_data, data.m_data, NXDN_CAC_CRC_LENGTH_BYTES);
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
m_idleBusy = data.m_idleBusy; m_idleBusy = data.m_idleBusy;
m_txContinuous = data.m_txContinuous; m_txContinuous = data.m_txContinuous;

@ -7,13 +7,14 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__NXDN_CHANNEL__CAC_H__) #if !defined(__NXDN_CHANNEL__CAC_H__)
#define __NXDN_CHANNEL__CAC_H__ #define __NXDN_CHANNEL__CAC_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/nxdn/NXDNDefines.h"
namespace nxdn namespace nxdn
{ {
@ -51,7 +52,7 @@ namespace nxdn
/// <summary>Radio Access Number</summary> /// <summary>Radio Access Number</summary>
__PROPERTY(uint8_t, ran, RAN); __PROPERTY(uint8_t, ran, RAN);
/// <summary></summary> /// <summary></summary>
__PROPERTY(uint8_t, structure, Structure); __PROPERTY(defines::ChStructure::E, structure, Structure);
/** Collision Control Field */ /** Collision Control Field */
/// <summary>Idle/Busy.</summary> /// <summary>Idle/Busy.</summary>

@ -19,6 +19,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel; using namespace nxdn::channel;
#include <cassert> #include <cassert>

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/NXDNDefines.h" #include "nxdn/NXDNDefines.h"
@ -18,6 +18,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel; using namespace nxdn::channel;
#include <cassert> #include <cassert>
@ -31,9 +32,9 @@ using namespace nxdn::channel;
/// Initializes a new instance of the LICH class. /// Initializes a new instance of the LICH class.
/// </summary> /// </summary>
LICH::LICH() : LICH::LICH() :
m_rfct(NXDN_LICH_RFCT_RCCH), m_rfct(RFChannelType::RCCH),
m_fct(NXDN_LICH_USC_SACCH_NS), m_fct(FuncChannelType::USC_SACCH_NS),
m_option(0U), m_option(ChOption::DATA_NORMAL),
m_outbound(true), m_outbound(true),
m_lich(0U) m_lich(0U)
{ {
@ -45,9 +46,9 @@ LICH::LICH() :
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
LICH::LICH(const LICH& data) : LICH::LICH(const LICH& data) :
m_rfct(NXDN_LICH_RFCT_RCCH), m_rfct(RFChannelType::RCCH),
m_fct(NXDN_LICH_USC_SACCH_NS), m_fct(FuncChannelType::USC_SACCH_NS),
m_option(0U), m_option(ChOption::DATA_NORMAL),
m_outbound(true), m_outbound(true),
m_lich(0U) m_lich(0U)
{ {
@ -108,9 +109,9 @@ bool LICH::decode(const uint8_t* data)
bool newParity = getParity(); bool newParity = getParity();
bool origParity = (m_lich & 0x01U) == 0x01U; bool origParity = (m_lich & 0x01U) == 0x01U;
m_rfct = (m_lich >> 6) & 0x03U; m_rfct = (RFChannelType::E)((m_lich >> 6) & 0x03U);
m_fct = (m_lich >> 4) & 0x03U; m_fct = (FuncChannelType::E)((m_lich >> 4) & 0x03U);
m_option = (m_lich >> 2) & 0x03U; m_option = (ChOption::E)((m_lich >> 2) & 0x03U);
m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U; m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U;
return origParity == newParity; return origParity == newParity;
@ -175,9 +176,9 @@ void LICH::copy(const LICH& data)
{ {
m_lich = data.m_lich; m_lich = data.m_lich;
m_rfct = (m_lich >> 6) & 0x03U; m_rfct = (RFChannelType::E)((m_lich >> 6) & 0x03U);
m_fct = (m_lich >> 4) & 0x03U; m_fct = (FuncChannelType::E)((m_lich >> 4) & 0x03U);
m_option = (m_lich >> 2) & 0x03U; m_option = (ChOption::E)((m_lich >> 2) & 0x03U);
m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U; m_outbound = ((m_lich >> 1) & 0x01U) == 0x01U;
} }

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__NXDN_CHANNEL__LICH_H__) #if !defined(__NXDN_CHANNEL__LICH_H__)
#define __NXDN_CHANNEL__LICH_H__ #define __NXDN_CHANNEL__LICH_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/nxdn/NXDNDefines.h"
namespace nxdn namespace nxdn
{ {
@ -46,11 +47,11 @@ namespace nxdn
public: public:
/** Common Data */ /** Common Data */
/// <summary>RF Channel Type</summary> /// <summary>RF Channel Type</summary>
__PROPERTY(uint8_t, rfct, RFCT); __PROPERTY(defines::RFChannelType::E, rfct, RFCT);
/// <summary>Functional Channel Type</summary> /// <summary>Functional Channel Type</summary>
__PROPERTY(uint8_t, fct, FCT); __PROPERTY(defines::FuncChannelType::E, fct, FCT);
/// <summary>Channel Options</summary> /// <summary>Channel Options</summary>
__PROPERTY(uint8_t, option, Option); __PROPERTY(defines::ChOption::E, option, Option);
/// <summary>Flag indicating outbound traffic direction</summary> /// <summary>Flag indicating outbound traffic direction</summary>
__PROPERTY(bool, outbound, Outbound); __PROPERTY(bool, outbound, Outbound);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/channel/SACCH.h" #include "nxdn/channel/SACCH.h"
@ -20,6 +20,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel; using namespace nxdn::channel;
#include <cassert> #include <cassert>
@ -48,7 +49,7 @@ const uint32_t PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 5
/// </summary> /// </summary>
SACCH::SACCH() : SACCH::SACCH() :
m_ran(0U), m_ran(0U),
m_structure(NXDN_SR_SINGLE), m_structure(ChStructure::SR_SINGLE),
m_data(nullptr) m_data(nullptr)
{ {
m_data = new uint8_t[NXDN_SACCH_CRC_LENGTH_BYTES]; m_data = new uint8_t[NXDN_SACCH_CRC_LENGTH_BYTES];
@ -61,7 +62,7 @@ SACCH::SACCH() :
/// <param name="data"></param> /// <param name="data"></param>
SACCH::SACCH(const SACCH& data) : SACCH::SACCH(const SACCH& data) :
m_ran(0U), m_ran(0U),
m_structure(NXDN_SR_SINGLE), m_structure(ChStructure::SR_SINGLE),
m_data(nullptr) m_data(nullptr)
{ {
copy(data); copy(data);
@ -86,7 +87,7 @@ SACCH& SACCH::operator=(const SACCH& data)
::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES); ::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES);
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
} }
return *this; return *this;
@ -163,7 +164,7 @@ bool SACCH::decode(const uint8_t* data)
} }
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
return true; return true;
} }
@ -274,5 +275,5 @@ void SACCH::copy(const SACCH& data)
::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES); ::memcpy(m_data, data.m_data, NXDN_SACCH_CRC_LENGTH_BYTES);
m_ran = m_data[0U] & 0x3FU; m_ran = m_data[0U] & 0x3FU;
m_structure = (m_data[0U] >> 6) & 0x03U; m_structure = (ChStructure::E)((m_data[0U] >> 6) & 0x03U);
} }

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__NXDN_CHANNEL__SACCH_H__) #if !defined(__NXDN_CHANNEL__SACCH_H__)
#define __NXDN_CHANNEL__SACCH_H__ #define __NXDN_CHANNEL__SACCH_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/nxdn/NXDNDefines.h"
namespace nxdn namespace nxdn
{ {
@ -53,7 +54,7 @@ namespace nxdn
/// <summary>Radio Access Number</summary> /// <summary>Radio Access Number</summary>
__PROPERTY(uint8_t, ran, RAN); __PROPERTY(uint8_t, ran, RAN);
/// <summary></summary> /// <summary></summary>
__PROPERTY(uint8_t, structure, Structure); __PROPERTY(defines::ChStructure::E, structure, Structure);
private: private:
uint8_t* m_data; uint8_t* m_data;

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/channel/UDCH.h" #include "nxdn/channel/UDCH.h"
@ -20,6 +20,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel; using namespace nxdn::channel;
#include <cassert> #include <cassert>

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -15,8 +15,9 @@
#include "nxdn/lc/PacketInformation.h" #include "nxdn/lc/PacketInformation.h"
#include "Log.h" #include "Log.h"
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -36,7 +37,7 @@ PacketInformation::PacketInformation() :
m_start(true), m_start(true),
m_circular(false), m_circular(false),
m_fragmentCount(0U), m_fragmentCount(0U),
m_rspClass(DATA_RSP_CLASS_ACK), m_rspClass(PDUResponseClass::ACK),
m_rspType(1U), m_rspType(1U),
m_rspErrorBlock(0U) m_rspErrorBlock(0U)
{ {
@ -60,7 +61,7 @@ bool PacketInformation::decode(const uint8_t messageType, const uint8_t* data)
switch (messageType) switch (messageType)
{ {
case RTCH_MESSAGE_TYPE_DCALL_HDR: case MessageType::RTCH_DCALL_HDR:
m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery
m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry
m_blockCount = (data[0U] & 0x0FU); // Block Count m_blockCount = (data[0U] & 0x0FU); // Block Count
@ -71,12 +72,12 @@ bool PacketInformation::decode(const uint8_t messageType, const uint8_t* data)
m_fragmentCount = ((data[1U] & 0x01U) << 8) + data[2U]; // Fragment Count m_fragmentCount = ((data[1U] & 0x01U) << 8) + data[2U]; // Fragment Count
break; break;
case RTCH_MESSAGE_TYPE_DCALL_ACK: case MessageType::RTCH_DCALL_ACK:
m_rspClass = (data[0U] >> 4) & 0x03U; // Response Class m_rspClass = (data[0U] >> 4) & 0x03U; // Response Class
m_rspType = (data[0U] >> 1) & 0x07U; // Response Type m_rspType = (data[0U] >> 1) & 0x07U; // Response Type
m_fragmentCount = ((data[0U] & 0x01U) << 8) + data[1U]; // Fragment Count m_fragmentCount = ((data[0U] & 0x01U) << 8) + data[1U]; // Fragment Count
break; break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR: case MessageType::RTCH_SDCALL_REQ_HDR:
m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery
m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry
m_blockCount = (data[0U] & 0x0FU); // Block Count m_blockCount = (data[0U] & 0x0FU); // Block Count
@ -104,9 +105,9 @@ void PacketInformation::encode(const uint8_t messageType, uint8_t* data)
switch (messageType) switch (messageType)
{ {
case RTCH_MESSAGE_TYPE_DCALL_HDR: case MessageType::RTCH_DCALL_HDR:
{ {
::memset(data, 0x00U, NXDN_PCKT_INFO_LENGTH_BYTES); ::memset(data, 0x00U, PCKT_INFO_LENGTH_BYTES);
data[0U] = (m_delivery ? 0x80U : 0x00U) + // Delivery data[0U] = (m_delivery ? 0x80U : 0x00U) + // Delivery
(m_selectiveRetry ? 0x20U : 0x00U) + // Selective Retry (m_selectiveRetry ? 0x20U : 0x00U) + // Selective Retry
@ -121,7 +122,7 @@ void PacketInformation::encode(const uint8_t messageType, uint8_t* data)
data[2U] = m_fragmentCount & 0xFFU; // Fragment Count - bit 0 - 7 data[2U] = m_fragmentCount & 0xFFU; // Fragment Count - bit 0 - 7
} }
break; break;
case RTCH_MESSAGE_TYPE_DCALL_ACK: case MessageType::RTCH_DCALL_ACK:
{ {
data[0U] = (m_rspClass & 0x03U << 4) + // Response Class data[0U] = (m_rspClass & 0x03U << 4) + // Response Class
(m_rspType & 0x07U << 1); // Response Type (m_rspType & 0x07U << 1); // Response Type
@ -131,8 +132,8 @@ void PacketInformation::encode(const uint8_t messageType, uint8_t* data)
data[1U] = m_fragmentCount & 0xFFU; // Fragment Count - bit 0 - 7 data[1U] = m_fragmentCount & 0xFFU; // Fragment Count - bit 0 - 7
} }
break; break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR: case MessageType::RTCH_SDCALL_REQ_HDR:
::memset(data, 0x00U, NXDN_PCKT_INFO_LENGTH_BYTES); ::memset(data, 0x00U, PCKT_INFO_LENGTH_BYTES);
data[0U] = (m_delivery ? 0x80U : 0x00U) + // Delivery data[0U] = (m_delivery ? 0x80U : 0x00U) + // Delivery
(m_selectiveRetry ? 0x20U : 0x00U) + // Selective Retry (m_selectiveRetry ? 0x20U : 0x00U) + // Selective Retry
@ -163,7 +164,7 @@ void PacketInformation::reset()
m_fragmentCount = 0U; m_fragmentCount = 0U;
m_rspClass = DATA_RSP_CLASS_ACK; m_rspClass = PDUResponseClass::ACK;
m_rspType = 0U; m_rspType = 0U;
m_rspErrorBlock = 0U; m_rspErrorBlock = 0U;
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,204 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/NXDNDefines.h" #include "nxdn/NXDNDefines.h"
@ -15,6 +15,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc; using namespace nxdn::lc;
#include <cassert> #include <cassert>
@ -26,7 +27,7 @@ using namespace nxdn::lc;
bool RCCH::m_verbose = false; bool RCCH::m_verbose = false;
uint8_t *RCCH::m_siteCallsign = nullptr; uint8_t* RCCH::m_siteCallsign = nullptr;
SiteData RCCH::m_siteData = SiteData(); SiteData RCCH::m_siteData = SiteData();
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -46,26 +47,26 @@ RCCH::RCCH(const RCCH& data) : RCCH()
/// Initializes a new instance of the RCCH class. /// Initializes a new instance of the RCCH class.
/// </summary> /// </summary>
RCCH::RCCH() : RCCH::RCCH() :
m_messageType(MESSAGE_TYPE_IDLE), m_messageType(MessageType::IDLE),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_locId(0U), m_locId(0U),
m_regOption(0U), m_regOption(0U),
m_version(0U), m_version(0U),
m_causeRsp(NXDN_CAUSE_MM_REG_ACCEPTED), m_causeRsp(CauseResponse::MM_REG_ACCEPTED),
m_grpVchNo(0U), m_grpVchNo(0U),
m_callType(CALL_TYPE_UNSPECIFIED), m_callType(CallType::UNSPECIFIED),
m_emergency(false), m_emergency(false),
m_encrypted(false), m_encrypted(false),
m_priority(false), m_priority(false),
m_group(true), m_group(true),
m_duplex(false), m_duplex(false),
m_transmissionMode(TRANSMISSION_MODE_4800), m_transmissionMode(TransmissionMode::MODE_4800),
m_siteIdenEntry() m_siteIdenEntry()
{ {
if (m_siteCallsign == nullptr) { if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES]; m_siteCallsign = new uint8_t[CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x00U, CALLSIGN_LENGTH_BYTES);
} }
} }
@ -94,16 +95,16 @@ std::string RCCH::toString(bool isp)
void RCCH::setCallsign(std::string callsign) void RCCH::setCallsign(std::string callsign)
{ {
if (m_siteCallsign == nullptr) { if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES]; m_siteCallsign = new uint8_t[CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x00U, CALLSIGN_LENGTH_BYTES);
} }
uint32_t idLength = callsign.length(); uint32_t idLength = callsign.length();
if (idLength > 0) { if (idLength > 0) {
::memset(m_siteCallsign, 0x20U, NXDN_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x20U, CALLSIGN_LENGTH_BYTES);
if (idLength > NXDN_CALLSIGN_LENGTH_BYTES) if (idLength > CALLSIGN_LENGTH_BYTES)
idLength = NXDN_CALLSIGN_LENGTH_BYTES; idLength = CALLSIGN_LENGTH_BYTES;
for (uint32_t i = 0; i < idLength; i++) for (uint32_t i = 0; i < idLength; i++)
m_siteCallsign[i] = callsign[i]; m_siteCallsign[i] = callsign[i];
} }

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Jonathan Naylor, G4KLX * Copyright (C) 2018 Jonathan Naylor, G4KLX
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "nxdn/NXDNDefines.h" #include "nxdn/NXDNDefines.h"
@ -18,6 +18,7 @@
#include "Utils.h" #include "Utils.h"
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc; using namespace nxdn::lc;
#include <cassert> #include <cassert>
@ -37,8 +38,8 @@ bool RTCH::m_verbose = false;
/// Initializes a new instance of the RTCH class. /// Initializes a new instance of the RTCH class.
/// </summary> /// </summary>
RTCH::RTCH() : RTCH::RTCH() :
m_messageType(MESSAGE_TYPE_IDLE), m_messageType(MessageType::IDLE),
m_callType(CALL_TYPE_UNSPECIFIED), m_callType(CallType::UNSPECIFIED),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_emergency(false), m_emergency(false),
@ -46,18 +47,18 @@ RTCH::RTCH() :
m_priority(false), m_priority(false),
m_group(true), m_group(true),
m_duplex(false), m_duplex(false),
m_transmissionMode(TRANSMISSION_MODE_4800), m_transmissionMode(TransmissionMode::MODE_4800),
m_packetInfo(), m_packetInfo(),
m_rsp(), m_rsp(),
m_dataFrameNumber(0U), m_dataFrameNumber(0U),
m_dataBlockNumber(0U), m_dataBlockNumber(0U),
m_delayCount(0U), m_delayCount(0U),
m_algId(NXDN_CIPHER_TYPE_NONE), m_algId(CIPHER_TYPE_NONE),
m_kId(0U), m_kId(0U),
m_causeRsp(NXDN_CAUSE_VD_ACCEPTED) m_causeRsp(CauseResponse::VD_ACCEPTED)
{ {
m_mi = new uint8_t[NXDN_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, NXDN_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
} }
/// <summary> /// <summary>
@ -65,8 +66,8 @@ RTCH::RTCH() :
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
RTCH::RTCH(const RTCH& data) : RTCH::RTCH(const RTCH& data) :
m_messageType(MESSAGE_TYPE_IDLE), m_messageType(MessageType::IDLE),
m_callType(CALL_TYPE_UNSPECIFIED), m_callType(CallType::UNSPECIFIED),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_emergency(false), m_emergency(false),
@ -74,15 +75,15 @@ RTCH::RTCH(const RTCH& data) :
m_priority(false), m_priority(false),
m_group(true), m_group(true),
m_duplex(false), m_duplex(false),
m_transmissionMode(TRANSMISSION_MODE_4800), m_transmissionMode(TransmissionMode::MODE_4800),
m_packetInfo(), m_packetInfo(),
m_rsp(), m_rsp(),
m_dataFrameNumber(0U), m_dataFrameNumber(0U),
m_dataBlockNumber(0U), m_dataBlockNumber(0U),
m_delayCount(0U), m_delayCount(0U),
m_algId(NXDN_CIPHER_TYPE_NONE), m_algId(CIPHER_TYPE_NONE),
m_kId(0U), m_kId(0U),
m_causeRsp(NXDN_CAUSE_VD_ACCEPTED) m_causeRsp(CauseResponse::VD_ACCEPTED)
{ {
copy(data); copy(data);
} }
@ -163,8 +164,8 @@ void RTCH::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// </summary> /// </summary>
void RTCH::reset() void RTCH::reset()
{ {
m_messageType = MESSAGE_TYPE_IDLE; m_messageType = MessageType::IDLE;
m_callType = CALL_TYPE_UNSPECIFIED; m_callType = CallType::UNSPECIFIED;
m_srcId = 0U; m_srcId = 0U;
m_dstId = 0U; m_dstId = 0U;
@ -174,7 +175,7 @@ void RTCH::reset()
m_priority = false; m_priority = false;
m_group = true; m_group = true;
m_duplex = false; m_duplex = false;
m_transmissionMode = TRANSMISSION_MODE_4800; m_transmissionMode = TransmissionMode::MODE_4800;
m_packetInfo = PacketInformation(); m_packetInfo = PacketInformation();
m_rsp = PacketInformation(); m_rsp = PacketInformation();
@ -183,13 +184,13 @@ void RTCH::reset()
m_delayCount = 0U; m_delayCount = 0U;
m_algId = NXDN_CIPHER_TYPE_NONE; m_algId = CIPHER_TYPE_NONE;
m_kId = 0U; m_kId = 0U;
m_causeRsp = NXDN_CAUSE_VD_ACCEPTED; m_causeRsp = CauseResponse::VD_ACCEPTED;
} }
/// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Private Class Members // Private Class Members
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -206,7 +207,7 @@ bool RTCH::decodeLC(const uint8_t* data)
// message type opcodes // message type opcodes
switch (m_messageType) { switch (m_messageType) {
case RTCH_MESSAGE_TYPE_VCALL: case MessageType::RTCH_VCALL:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -217,22 +218,22 @@ bool RTCH::decodeLC(const uint8_t* data)
m_algId = (data[7U] >> 6) & 0x03U; // Cipher Type m_algId = (data[7U] >> 6) & 0x03U; // Cipher Type
m_kId = (data[7U] & 0x3FU); // Key ID m_kId = (data[7U] & 0x3FU); // Key ID
break; break;
case RTCH_MESSAGE_TYPE_VCALL_IV: case MessageType::RTCH_VCALL_IV:
case RTCH_MESSAGE_TYPE_SDCALL_IV: case MessageType::RTCH_SDCALL_IV:
if (m_algId != NXDN_CIPHER_TYPE_NONE && m_kId > 0U) { if (m_algId != CIPHER_TYPE_NONE && m_kId > 0U) {
m_mi = new uint8_t[NXDN_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, NXDN_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
::memcpy(m_mi, data + 1U, NXDN_MI_LENGTH_BYTES); // Message Indicator ::memcpy(m_mi, data + 1U, MI_LENGTH_BYTES); // Message Indicator
} }
break; break;
case RTCH_MESSAGE_TYPE_TX_REL: case MessageType::RTCH_TX_REL:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
m_srcId = (uint16_t)((data[3U] << 8) | data[4U]) & 0xFFFFU; // Source Radio Address m_srcId = (uint16_t)((data[3U] << 8) | data[4U]) & 0xFFFFU; // Source Radio Address
m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address
break; break;
case RTCH_MESSAGE_TYPE_DCALL_HDR: case MessageType::RTCH_DCALL_HDR:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -246,17 +247,17 @@ bool RTCH::decodeLC(const uint8_t* data)
m_packetInfo = PacketInformation(); m_packetInfo = PacketInformation();
m_packetInfo.decode(m_messageType, data + 8U); // Packet Information m_packetInfo.decode(m_messageType, data + 8U); // Packet Information
if (m_algId != NXDN_CIPHER_TYPE_NONE && m_kId > 0U) { if (m_algId != CIPHER_TYPE_NONE && m_kId > 0U) {
::memset(m_mi, 0x00U, NXDN_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
::memcpy(m_mi, data + 11U, NXDN_MI_LENGTH_BYTES); // Message Indicator ::memcpy(m_mi, data + 11U, MI_LENGTH_BYTES); // Message Indicator
} }
break; break;
case RTCH_MESSAGE_TYPE_DCALL_DATA: case MessageType::RTCH_DCALL_DATA:
case RTCH_MESSAGE_TYPE_SDCALL_REQ_DATA: case MessageType::RTCH_SDCALL_REQ_DATA:
m_dataFrameNumber = (data[1U] >> 4) & 0x0FU; // Frame Number m_dataFrameNumber = (data[1U] >> 4) & 0x0FU; // Frame Number
m_dataBlockNumber = (data[1U] & 0x0FU); // Block Number m_dataBlockNumber = (data[1U] & 0x0FU); // Block Number
break; break;
case RTCH_MESSAGE_TYPE_DCALL_ACK: case MessageType::RTCH_DCALL_ACK:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -268,7 +269,7 @@ bool RTCH::decodeLC(const uint8_t* data)
m_rsp = PacketInformation(); m_rsp = PacketInformation();
m_rsp.decode(m_messageType, data + 7U); // Response m_rsp.decode(m_messageType, data + 7U); // Response
break; break;
case RTCH_MESSAGE_TYPE_HEAD_DLY: case MessageType::RTCH_HEAD_DLY:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -276,9 +277,9 @@ bool RTCH::decodeLC(const uint8_t* data)
m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address m_dstId = (uint16_t)((data[5U] << 8) | data[6U]) & 0xFFFFU; // Target Radio Address
m_delayCount = (uint16_t)((data[7U] << 8) | data[8U]) & 0xFFFFU; // Delay Count m_delayCount = (uint16_t)((data[7U] << 8) | data[8U]) & 0xFFFFU; // Delay Count
break; break;
case MESSAGE_TYPE_IDLE: case MessageType::IDLE:
break; break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR: case MessageType::RTCH_SDCALL_REQ_HDR:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -292,7 +293,7 @@ bool RTCH::decodeLC(const uint8_t* data)
m_packetInfo = PacketInformation(); m_packetInfo = PacketInformation();
m_packetInfo.decode(m_messageType, data + 8U); // Packet Information m_packetInfo.decode(m_messageType, data + 8U); // Packet Information
break; break;
case RTCH_MESSAGE_TYPE_SDCALL_RESP: case MessageType::RTCH_SDCALL_RESP:
m_callType = (data[2U] >> 5) & 0x07U; // Call Type m_callType = (data[2U] >> 5) & 0x07U; // Call Type
m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (data[1U] & 0x80U) == 0x80U; // Emergency Flag
m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag m_priority = (data[1U] & 0x20U) == 0x20U; // Priority Flag
@ -322,7 +323,7 @@ void RTCH::encodeLC(uint8_t* data)
// message type opcodes // message type opcodes
switch (m_messageType) { switch (m_messageType) {
case RTCH_MESSAGE_TYPE_VCALL: case MessageType::RTCH_VCALL:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = ((m_callType & 0x07U) << 5) + // Call Type data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
@ -337,12 +338,12 @@ void RTCH::encodeLC(uint8_t* data)
data[7U] = ((m_algId & 0x03U) << 6) + // Cipher Type data[7U] = ((m_algId & 0x03U) << 6) + // Cipher Type
(m_kId & 0x3FU); // Key ID (m_kId & 0x3FU); // Key ID
break; break;
case RTCH_MESSAGE_TYPE_VCALL_IV: case MessageType::RTCH_VCALL_IV:
if (m_algId != NXDN_CIPHER_TYPE_NONE && m_kId > 0U) { if (m_algId != CIPHER_TYPE_NONE && m_kId > 0U) {
::memcpy(data + 1U, m_mi, NXDN_MI_LENGTH_BYTES); // Message Indicator ::memcpy(data + 1U, m_mi, MI_LENGTH_BYTES); // Message Indicator
} }
break; break;
case RTCH_MESSAGE_TYPE_TX_REL: case MessageType::RTCH_TX_REL:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = (m_callType & 0x07U) << 5; // Call Type data[2U] = (m_callType & 0x07U) << 5; // Call Type
@ -352,7 +353,7 @@ void RTCH::encodeLC(uint8_t* data)
data[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address data[5U] = (m_dstId >> 8U) & 0xFFU; // Target Radio Address
data[6U] = (m_dstId >> 0U) & 0xFFU; // ... data[6U] = (m_dstId >> 0U) & 0xFFU; // ...
break; break;
case RTCH_MESSAGE_TYPE_DCALL_HDR: case MessageType::RTCH_DCALL_HDR:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = ((m_callType & 0x07U) << 5) + // Call Type data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
@ -369,16 +370,16 @@ void RTCH::encodeLC(uint8_t* data)
m_packetInfo.encode(m_messageType, data + 8U); // Packet Information m_packetInfo.encode(m_messageType, data + 8U); // Packet Information
if (m_algId != NXDN_CIPHER_TYPE_NONE && m_kId > 0U) { if (m_algId != CIPHER_TYPE_NONE && m_kId > 0U) {
::memcpy(data + 11U, m_mi, NXDN_MI_LENGTH_BYTES); // Message Indicator ::memcpy(data + 11U, m_mi, MI_LENGTH_BYTES); // Message Indicator
} }
break; break;
case RTCH_MESSAGE_TYPE_DCALL_DATA: case MessageType::RTCH_DCALL_DATA:
case RTCH_MESSAGE_TYPE_SDCALL_REQ_DATA: case MessageType::RTCH_SDCALL_REQ_DATA:
data[1U] = (m_dataFrameNumber & 0x0FU << 4) + // Frame Number data[1U] = (m_dataFrameNumber & 0x0FU << 4) + // Frame Number
(m_dataBlockNumber & 0x0FU); // Block Number (m_dataBlockNumber & 0x0FU); // Block Number
break; break;
case RTCH_MESSAGE_TYPE_DCALL_ACK: case MessageType::RTCH_DCALL_ACK:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = ((m_callType & 0x07U) << 5) + // Call Type data[2U] = ((m_callType & 0x07U) << 5) + // Call Type
@ -392,7 +393,7 @@ void RTCH::encodeLC(uint8_t* data)
m_rsp.encode(m_messageType, data + 7U); // Response m_rsp.encode(m_messageType, data + 7U); // Response
break; break;
case RTCH_MESSAGE_TYPE_HEAD_DLY: case MessageType::RTCH_HEAD_DLY:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = (m_callType & 0x07U) << 5; // Call Type data[2U] = (m_callType & 0x07U) << 5; // Call Type
@ -405,9 +406,9 @@ void RTCH::encodeLC(uint8_t* data)
data[7U] = (m_delayCount >> 8U) & 0xFFU; // Delay Count data[7U] = (m_delayCount >> 8U) & 0xFFU; // Delay Count
data[8U] = (m_delayCount >> 0U) & 0xFFU; // ... data[8U] = (m_delayCount >> 0U) & 0xFFU; // ...
break; break;
case MESSAGE_TYPE_IDLE: case MessageType::IDLE:
break; break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR: case MessageType::RTCH_SDCALL_REQ_HDR:
data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag data[1U] = (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
(m_priority ? 0x20U : 0x00U); // Priority Flag (m_priority ? 0x20U : 0x00U); // Priority Flag
data[2U] = ((m_callType & 0x07U) << 5) + // Call Type data[2U] = ((m_callType & 0x07U) << 5) + // Call Type

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_DCALL_HDR::MESSAGE_TYPE_DCALL_HDR() : RCCH() MESSAGE_TYPE_DCALL_HDR::MESSAGE_TYPE_DCALL_HDR() : RCCH()
{ {
m_messageType = RTCH_MESSAGE_TYPE_DCALL_HDR; m_messageType = MessageType::RTCH_DCALL_HDR;
} }
/// <summary> /// <summary>
@ -93,5 +94,5 @@ void MESSAGE_TYPE_DCALL_HDR::encode(uint8_t* data, uint32_t length, uint32_t off
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_DCALL_HDR::toString(bool isp) std::string MESSAGE_TYPE_DCALL_HDR::toString(bool isp)
{ {
return std::string("RTCH_MESSAGE_TYPE_DCALL_HDR (Data Call Header)"); return std::string("RTCH_DCALL_HDR (Data Call Header)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_DST_ID_INFO::MESSAGE_TYPE_DST_ID_INFO() : RCCH() MESSAGE_TYPE_DST_ID_INFO::MESSAGE_TYPE_DST_ID_INFO() : RCCH()
{ {
m_messageType = nxdn::MESSAGE_TYPE_DST_ID_INFO; m_messageType = MessageType::DST_ID_INFO;
} }
/// <summary> /// <summary>
@ -60,9 +61,9 @@ void MESSAGE_TYPE_DST_ID_INFO::encode(uint8_t* data, uint32_t length, uint32_t o
uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U]; uint8_t rcch[NXDN_RCCH_LC_LENGTH_BYTES + 4U];
::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U); ::memset(rcch, 0x00U, NXDN_RCCH_LC_LENGTH_BYTES + 4U);
rcch[1U] = 0xC0U + NXDN_CALLSIGN_LENGTH_BYTES; // Station ID Option - Start / End / Character Count rcch[1U] = 0xC0U + CALLSIGN_LENGTH_BYTES; // Station ID Option - Start / End / Character Count
rcch[2U] = (m_siteCallsign[0]); // Character 0 rcch[2U] = (m_siteCallsign[0]); // Character 0
for (uint8_t i = 1; i < NXDN_CALLSIGN_LENGTH_BYTES; i++) { for (uint8_t i = 1; i < CALLSIGN_LENGTH_BYTES; i++) {
rcch[i + 2U] = m_siteCallsign[i]; // Character 1 - 7 rcch[i + 2U] = m_siteCallsign[i]; // Character 1 - 7
} }
@ -76,5 +77,5 @@ void MESSAGE_TYPE_DST_ID_INFO::encode(uint8_t* data, uint32_t length, uint32_t o
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_DST_ID_INFO::toString(bool isp) std::string MESSAGE_TYPE_DST_ID_INFO::toString(bool isp)
{ {
return std::string("MESSAGE_TYPE_DST_ID_INFO (Digital Station ID)"); return std::string("DST_ID_INFO (Digital Station ID)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_GRP_REG::MESSAGE_TYPE_GRP_REG() : RCCH() MESSAGE_TYPE_GRP_REG::MESSAGE_TYPE_GRP_REG() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_GRP_REG; m_messageType = MessageType::RCCH_GRP_REG;
} }
/// <summary> /// <summary>
@ -82,6 +83,6 @@ void MESSAGE_TYPE_GRP_REG::encode(uint8_t* data, uint32_t length, uint32_t offse
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_GRP_REG::toString(bool isp) std::string MESSAGE_TYPE_GRP_REG::toString(bool isp)
{ {
if (isp) return std::string("RCCH_MESSAGE_TYPE_GRP_REG (Group Registration Request)"); return (isp) ? std::string("RCCH_GRP_REG (Group Registration Request)") :
else return std::string("RCCH_MESSAGE_TYPE_GRP_REG (Group Registration Response)"); std::string("RCCH_GRP_REG (Group Registration Response)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_IDLE::MESSAGE_TYPE_IDLE() : RCCH() MESSAGE_TYPE_IDLE::MESSAGE_TYPE_IDLE() : RCCH()
{ {
m_messageType = nxdn::MESSAGE_TYPE_IDLE; m_messageType = MessageType::IDLE;
} }
/// <summary> /// <summary>
@ -70,5 +71,5 @@ void MESSAGE_TYPE_IDLE::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_IDLE::toString(bool isp) std::string MESSAGE_TYPE_IDLE::toString(bool isp)
{ {
return std::string("MESSAGE_TYPE_IDLE (Idle)"); return std::string("IDLE (Idle)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_REG.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_REG.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_REG::MESSAGE_TYPE_REG() : RCCH() MESSAGE_TYPE_REG::MESSAGE_TYPE_REG() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_REG; m_messageType = MessageType::RCCH_REG;
} }
/// <summary> /// <summary>
@ -85,6 +86,6 @@ void MESSAGE_TYPE_REG::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_REG::toString(bool isp) std::string MESSAGE_TYPE_REG::toString(bool isp)
{ {
if (isp) return std::string("RCCH_MESSAGE_TYPE_REG (Registration Request)"); return (isp) ? std::string("RCCH_REG (Registration Request)") :
else return std::string("RCCH_MESSAGE_TYPE_REG (Registration Response)"); std::string("RCCH_REG (Registration Response)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_REG_C::MESSAGE_TYPE_REG_C() : RCCH() MESSAGE_TYPE_REG_C::MESSAGE_TYPE_REG_C() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_REG_C; m_messageType = MessageType::RCCH_REG_C;
} }
/// <summary> /// <summary>
@ -80,6 +81,6 @@ void MESSAGE_TYPE_REG_C::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_REG_C::toString(bool isp) std::string MESSAGE_TYPE_REG_C::toString(bool isp)
{ {
if (isp) return std::string("RCCH_MESSAGE_TYPE_REG_C (Registration Clear Request)"); return (isp) ? std::string("RCCH_REG_C (Registration Clear Request)") :
else return std::string("RCCH_MESSAGE_TYPE_REG_C (Registration Clear Response)"); std::string("RCCH_REG_C (Registration Clear Response)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_REG_COMM::MESSAGE_TYPE_REG_COMM() : RCCH() MESSAGE_TYPE_REG_COMM::MESSAGE_TYPE_REG_COMM() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_REG_COMM; m_messageType = MessageType::RCCH_REG_COMM;
} }
/// <summary> /// <summary>
@ -75,5 +76,5 @@ void MESSAGE_TYPE_REG_COMM::encode(uint8_t* data, uint32_t length, uint32_t offs
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_REG_COMM::toString(bool isp) std::string MESSAGE_TYPE_REG_COMM::toString(bool isp)
{ {
return std::string("RCCH_MESSAGE_TYPE_REG_COMM (Registration Command)"); return std::string("RCCH_REG_COMM (Registration Command)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -33,7 +34,7 @@ MESSAGE_TYPE_SITE_INFO::MESSAGE_TYPE_SITE_INFO() : RCCH(),
m_ccchMultiCnt(2U), m_ccchMultiCnt(2U),
m_rcchIterateCnt(2U) m_rcchIterateCnt(2U)
{ {
m_messageType = RCCH_MESSAGE_TYPE_SITE_INFO; m_messageType = MessageType::RCCH_SITE_INFO;
} }
/// <summary> /// <summary>
@ -76,7 +77,7 @@ void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t off
((m_rcchIterateCnt & 0x0FU) << 0); // ... - Number of Iteration ((m_rcchIterateCnt & 0x0FU) << 0); // ... - Number of Iteration
rcch[6U] = m_siteData.serviceClass(); // Service Information rcch[6U] = m_siteData.serviceClass(); // Service Information
rcch[7U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ... rcch[7U] = (m_siteData.netActive() ? SiteInformation2::IP_NETWORK : 0x00U); // ...
// bryanb: this is currently fixed -- maybe dynamic in the future // bryanb: this is currently fixed -- maybe dynamic in the future
rcch[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction rcch[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction
@ -84,7 +85,7 @@ void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t off
rcch[10U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO rcch[10U] = (!m_siteData.netActive() ? 0x01U : 0x00U); // ... - No group ratio restriction / No delay time extension / ISO
// bryanb: this is currently fixed -- maybe dynamic in the future // bryanb: this is currently fixed -- maybe dynamic in the future
rcch[11U] = NXDN_CH_ACCESS_BASE_FREQ_SYS_DEFINED << 2; // Channel Access Information - Channel Version / Sys Defined Step / Sys Defined Base Freq rcch[11U] = ChAccessBase::FREQ_SYS_DEFINED << 2; // Channel Access Information - Channel Version / Sys Defined Step / Sys Defined Base Freq
rcch[14U] = 1U; // Version rcch[14U] = 1U; // Version
@ -102,7 +103,7 @@ void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t off
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_SITE_INFO::toString(bool isp) std::string MESSAGE_TYPE_SITE_INFO::toString(bool isp)
{ {
return std::string("RCCH_MESSAGE_TYPE_SITE_INFO (Site Information)"); return std::string("RCCH_SITE_INFO (Site Information)");
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_SRV_INFO::MESSAGE_TYPE_SRV_INFO() : RCCH() MESSAGE_TYPE_SRV_INFO::MESSAGE_TYPE_SRV_INFO() : RCCH()
{ {
m_messageType = nxdn::MESSAGE_TYPE_SRV_INFO; m_messageType = MessageType::SRV_INFO;
} }
/// <summary> /// <summary>
@ -64,7 +65,7 @@ void MESSAGE_TYPE_SRV_INFO::encode(uint8_t* data, uint32_t length, uint32_t offs
rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ... rcch[2U] = (m_siteData.locId() >> 8) & 0xFFU; // ...
rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ... rcch[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
rcch[4U] = m_siteData.serviceClass(); // Service Information rcch[4U] = m_siteData.serviceClass(); // Service Information
rcch[5U] = (m_siteData.netActive() ? NXDN_SIF2_IP_NETWORK : 0x00U); // ... rcch[5U] = (m_siteData.netActive() ? SiteInformation2::IP_NETWORK : 0x00U); // ...
// bryanb: this is currently fixed -- maybe dynamic in the future // bryanb: this is currently fixed -- maybe dynamic in the future
rcch[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction rcch[8U] = 0U; // Restriction Information - No access restriction / No cycle restriction
@ -81,5 +82,5 @@ void MESSAGE_TYPE_SRV_INFO::encode(uint8_t* data, uint32_t length, uint32_t offs
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_SRV_INFO::toString(bool isp) std::string MESSAGE_TYPE_SRV_INFO::toString(bool isp)
{ {
return std::string("MESSAGE_TYPE_SRV_INFO (Service Information)"); return std::string("SRV_INFO (Service Information)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_VCALL_ASSGN::MESSAGE_TYPE_VCALL_ASSGN() : RCCH() MESSAGE_TYPE_VCALL_ASSGN::MESSAGE_TYPE_VCALL_ASSGN() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_VCALL_ASSGN; m_messageType = MessageType::RCCH_VCALL_ASSGN;
} }
/// <summary> /// <summary>
@ -87,5 +88,5 @@ void MESSAGE_TYPE_VCALL_ASSGN::encode(uint8_t* data, uint32_t length, uint32_t o
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_VCALL_ASSGN::toString(bool isp) std::string MESSAGE_TYPE_VCALL_ASSGN::toString(bool isp)
{ {
return std::string("RCCH_MESSAGE_TYPE_VCALL_ASSGN (Voice Call Assignment)"); return std::string("RCCH_VCALL_ASSGN (Voice Call Assignment)");
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h" #include "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary> /// </summary>
MESSAGE_TYPE_VCALL_CONN::MESSAGE_TYPE_VCALL_CONN() : RCCH() MESSAGE_TYPE_VCALL_CONN::MESSAGE_TYPE_VCALL_CONN() : RCCH()
{ {
m_messageType = RCCH_MESSAGE_TYPE_VCALL_CONN; m_messageType = MessageType::RCCH_VCALL_CONN;
} }
/// <summary> /// <summary>
@ -93,6 +94,6 @@ void MESSAGE_TYPE_VCALL_CONN::encode(uint8_t* data, uint32_t length, uint32_t of
/// <returns></returns> /// <returns></returns>
std::string MESSAGE_TYPE_VCALL_CONN::toString(bool isp) std::string MESSAGE_TYPE_VCALL_CONN::toString(bool isp)
{ {
if (isp) return std::string("RCCH_MESSAGE_TYPE_VCALL_CONN (Voice Call Connection Request)"); return (isp) ? std::string("RCCH_VCALL_CONN (Voice Call Connection Request)") :
else return std::string("RCCH_MESSAGE_TYPE_VCALL_CONN (Voice Call Connection Response)"); std::string("RCCH_VCALL_CONN (Voice Call Connection Response)");
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -15,9 +15,10 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn; using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert> #include <cassert>
@ -58,18 +59,18 @@ std::unique_ptr<RCCH> RCCHFactory::createRCCH(const uint8_t* data, uint32_t leng
// message type opcodes // message type opcodes
switch (messageType) { switch (messageType) {
case RTCH_MESSAGE_TYPE_VCALL: case MessageType::RTCH_VCALL:
case RCCH_MESSAGE_TYPE_VCALL_CONN: case MessageType::RCCH_VCALL_CONN:
return decode(new MESSAGE_TYPE_VCALL_CONN(), data, length, offset); return decode(new MESSAGE_TYPE_VCALL_CONN(), data, length, offset);
case RTCH_MESSAGE_TYPE_DCALL_HDR: case MessageType::RTCH_DCALL_HDR:
return decode(new MESSAGE_TYPE_DCALL_HDR(), data, length, offset); return decode(new MESSAGE_TYPE_DCALL_HDR(), data, length, offset);
case nxdn::MESSAGE_TYPE_IDLE: case MessageType::IDLE:
return decode(new MESSAGE_TYPE_IDLE(), data, length, offset); return decode(new MESSAGE_TYPE_IDLE(), data, length, offset);
case RCCH_MESSAGE_TYPE_REG: case MessageType::RCCH_REG:
return decode(new MESSAGE_TYPE_REG(), data, length, offset); return decode(new MESSAGE_TYPE_REG(), data, length, offset);
case RCCH_MESSAGE_TYPE_REG_C: case MessageType::RCCH_REG_C:
return decode(new MESSAGE_TYPE_REG_C(), data, length, offset); return decode(new MESSAGE_TYPE_REG_C(), data, length, offset);
case RCCH_MESSAGE_TYPE_GRP_REG: case MessageType::RCCH_GRP_REG:
return decode(new MESSAGE_TYPE_GRP_REG(), data, length, offset); return decode(new MESSAGE_TYPE_GRP_REG(), data, length, offset);
default: default:
LogError(LOG_NXDN, "RCCH::decodeRCCH(), unknown RCCH value, messageType = $%02X", messageType); LogError(LOG_NXDN, "RCCH::decodeRCCH(), unknown RCCH value, messageType = $%02X", messageType);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2016 Jonathan Naylor, G4KLX * Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017,2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -20,6 +20,7 @@
#include "edac/BCH.h" #include "edac/BCH.h"
using namespace p25; using namespace p25;
using namespace p25::defines;
#include <cassert> #include <cassert>
@ -38,7 +39,7 @@ const uint32_t MAX_NID_ERRS = 7U;//5U;
/// </summary> /// </summary>
/// <param name="nac">P25 Network Access Code.</param> /// <param name="nac">P25 Network Access Code.</param>
NID::NID(uint32_t nac) : NID::NID(uint32_t nac) :
m_duid(0U), m_duid(DUID::HDU),
m_nac(nac), m_nac(nac),
m_rxTx(nullptr), m_rxTx(nullptr),
m_tx(nullptr), m_tx(nullptr),
@ -78,51 +79,51 @@ bool NID::decode(const uint8_t* data)
P25Utils::decode(data, nid, 48U, 114U); P25Utils::decode(data, nid, 48U, 114U);
// handle digital "squelch" NAC // handle digital "squelch" NAC
if ((m_nac == P25_NAC_DIGITAL_SQ) || (m_nac == P25_NAC_REUSE_RX_NAC)) { if ((m_nac == NAC_DIGITAL_SQ) || (m_nac == NAC_REUSE_RX_NAC)) {
uint32_t nac = ((nid[0U] << 4) + (nid[1U] >> 4)) & 0xFFFU; uint32_t nac = ((nid[0U] << 4) + (nid[1U] >> 4)) & 0xFFFU;
cleanupArrays(); cleanupArrays();
createRxTxNID(nac); // bryanb: I hate this and it'll be slow createRxTxNID(nac); // bryanb: I hate this and it'll be slow
} }
uint32_t errs = P25Utils::compare(nid, m_rxTx[P25_DUID_LDU1], P25_NID_LENGTH_BYTES); uint32_t errs = P25Utils::compare(nid, m_rxTx[DUID::LDU1], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_LDU1; m_duid = DUID::LDU1;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_LDU2], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::LDU2], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_LDU2; m_duid = DUID::LDU2;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_PDU], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::PDU], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_PDU; m_duid = DUID::PDU;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_TSDU], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::TSDU], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_TSDU; m_duid = DUID::TSDU;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_HDU], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::HDU], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_HDU; m_duid = DUID::HDU;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_TDULC], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::TDULC], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_TDULC; m_duid = DUID::TDULC;
return true; return true;
} }
errs = P25Utils::compare(nid, m_rxTx[P25_DUID_TDU], P25_NID_LENGTH_BYTES); errs = P25Utils::compare(nid, m_rxTx[DUID::TDU], P25_NID_LENGTH_BYTES);
if (errs < MAX_NID_ERRS) { if (errs < MAX_NID_ERRS) {
m_duid = P25_DUID_TDU; m_duid = DUID::TDU;
return true; return true;
} }
@ -134,19 +135,19 @@ bool NID::decode(const uint8_t* data)
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="duid"></param> /// <param name="duid"></param>
void NID::encode(uint8_t* data, uint8_t duid) void NID::encode(uint8_t* data, defines::DUID::E duid)
{ {
assert(data != nullptr); assert(data != nullptr);
if (m_splitNac) { if (m_splitNac) {
switch (duid) { switch (duid) {
case P25_DUID_HDU: case DUID::HDU:
case P25_DUID_TDU: case DUID::TDU:
case P25_DUID_LDU1: case DUID::LDU1:
case P25_DUID_PDU: case DUID::PDU:
case P25_DUID_TSDU: case DUID::TSDU:
case P25_DUID_LDU2: case DUID::LDU2:
case P25_DUID_TDULC: case DUID::TDULC:
P25Utils::encode(m_tx[duid], data, 48U, 114U); P25Utils::encode(m_tx[duid], data, 48U, 114U);
break; break;
default: default:
@ -155,19 +156,19 @@ void NID::encode(uint8_t* data, uint8_t duid)
} }
else { else {
// handle digital "squelch" NAC // handle digital "squelch" NAC
if (m_nac == P25_NAC_DIGITAL_SQ) { if (m_nac == NAC_DIGITAL_SQ) {
cleanupArrays(); cleanupArrays();
createRxTxNID(P25_DEFAULT_NAC); createRxTxNID(DEFAULT_NAC);
} }
switch (duid) { switch (duid) {
case P25_DUID_HDU: case DUID::HDU:
case P25_DUID_TDU: case DUID::TDU:
case P25_DUID_LDU1: case DUID::LDU1:
case P25_DUID_PDU: case DUID::PDU:
case P25_DUID_TSDU: case DUID::TSDU:
case P25_DUID_LDU2: case DUID::LDU2:
case P25_DUID_TDULC: case DUID::TDULC:
P25Utils::encode(m_rxTx[duid], data, 48U, 114U); P25Utils::encode(m_rxTx[duid], data, 48U, 114U);
break; break;
default: default:
@ -219,54 +220,54 @@ void NID::createRxTxNID(uint32_t nac)
{ {
edac::BCH bch; edac::BCH bch;
m_rxTx[P25_DUID_HDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_HDU][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::HDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_HDU][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::HDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_HDU][1U] |= P25_DUID_HDU; m_rxTx[DUID::HDU][1U] |= DUID::HDU;
bch.encode(m_rxTx[P25_DUID_HDU]); bch.encode(m_rxTx[DUID::HDU]);
m_rxTx[P25_DUID_HDU][7U] &= 0xFEU; // Clear the parity bit m_rxTx[DUID::HDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_TDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TDU][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::TDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TDU][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::TDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TDU][1U] |= P25_DUID_TDU; m_rxTx[DUID::TDU][1U] |= DUID::TDU;
bch.encode(m_rxTx[P25_DUID_TDU]); bch.encode(m_rxTx[DUID::TDU]);
m_rxTx[P25_DUID_TDU][7U] &= 0xFEU; // Clear the parity bit m_rxTx[DUID::TDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_LDU1] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_LDU1][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::LDU1][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_LDU1][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::LDU1][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_LDU1][1U] |= P25_DUID_LDU1; m_rxTx[DUID::LDU1][1U] |= DUID::LDU1;
bch.encode(m_rxTx[P25_DUID_LDU1]); bch.encode(m_rxTx[DUID::LDU1]);
m_rxTx[P25_DUID_LDU1][7U] |= 0x01U; // Set the parity bit m_rxTx[DUID::LDU1][7U] |= 0x01U; // Set the parity bit
m_rxTx[P25_DUID_PDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_PDU][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::PDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_PDU][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::PDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_PDU][1U] |= P25_DUID_PDU; m_rxTx[DUID::PDU][1U] |= DUID::PDU;
bch.encode(m_rxTx[P25_DUID_PDU]); bch.encode(m_rxTx[DUID::PDU]);
m_rxTx[P25_DUID_PDU][7U] &= 0xFEU; // Clear the parity bit m_rxTx[DUID::PDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_TSDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TSDU][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::TSDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TSDU][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::TSDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TSDU][1U] |= P25_DUID_TSDU; m_rxTx[DUID::TSDU][1U] |= DUID::TSDU;
bch.encode(m_rxTx[P25_DUID_TSDU]); bch.encode(m_rxTx[DUID::TSDU]);
m_rxTx[P25_DUID_TSDU][7U] &= 0xFEU; // Clear the parity bit m_rxTx[DUID::TSDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_LDU2] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_LDU2][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::LDU2][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_LDU2][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::LDU2][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_LDU2][1U] |= P25_DUID_LDU2; m_rxTx[DUID::LDU2][1U] |= DUID::LDU2;
bch.encode(m_rxTx[P25_DUID_LDU2]); bch.encode(m_rxTx[DUID::LDU2]);
m_rxTx[P25_DUID_LDU2][7U] |= 0x01U; // Set the parity bit m_rxTx[DUID::LDU2][7U] |= 0x01U; // Set the parity bit
m_rxTx[P25_DUID_TDULC] = new uint8_t[P25_NID_LENGTH_BYTES]; m_rxTx[DUID::TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TDULC][0U] = (nac >> 4) & 0xFFU; m_rxTx[DUID::TDULC][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TDULC][1U] = (nac << 4) & 0xF0U; m_rxTx[DUID::TDULC][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TDULC][1U] |= P25_DUID_TDULC; m_rxTx[DUID::TDULC][1U] |= DUID::TDULC;
bch.encode(m_rxTx[P25_DUID_TDULC]); bch.encode(m_rxTx[DUID::TDULC]);
m_rxTx[P25_DUID_TDULC][7U] &= 0xFEU; // Clear the parity bit m_rxTx[DUID::TDULC][7U] &= 0xFEU; // Clear the parity bit
} }
/// <summary> /// <summary>
@ -277,52 +278,52 @@ void NID::createTxNID(uint32_t nac)
{ {
edac::BCH bch; edac::BCH bch;
m_tx[P25_DUID_HDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_HDU][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::HDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_HDU][1U] = (nac << 4) & 0xF0U; m_tx[DUID::HDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_HDU][1U] |= P25_DUID_HDU; m_tx[DUID::HDU][1U] |= DUID::HDU;
bch.encode(m_tx[P25_DUID_HDU]); bch.encode(m_tx[DUID::HDU]);
m_tx[P25_DUID_HDU][7U] &= 0xFEU; // Clear the parity bit m_tx[DUID::HDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_TDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TDU][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::TDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TDU][1U] = (nac << 4) & 0xF0U; m_tx[DUID::TDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TDU][1U] |= P25_DUID_TDU; m_tx[DUID::TDU][1U] |= DUID::TDU;
bch.encode(m_tx[P25_DUID_TDU]); bch.encode(m_tx[DUID::TDU]);
m_tx[P25_DUID_TDU][7U] &= 0xFEU; // Clear the parity bit m_tx[DUID::TDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_LDU1] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_LDU1][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::LDU1][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_LDU1][1U] = (nac << 4) & 0xF0U; m_tx[DUID::LDU1][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_LDU1][1U] |= P25_DUID_LDU1; m_tx[DUID::LDU1][1U] |= DUID::LDU1;
bch.encode(m_tx[P25_DUID_LDU1]); bch.encode(m_tx[DUID::LDU1]);
m_tx[P25_DUID_LDU1][7U] |= 0x01U; // Set the parity bit m_tx[DUID::LDU1][7U] |= 0x01U; // Set the parity bit
m_tx[P25_DUID_PDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_PDU][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::PDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_PDU][1U] = (nac << 4) & 0xF0U; m_tx[DUID::PDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_PDU][1U] |= P25_DUID_PDU; m_tx[DUID::PDU][1U] |= DUID::PDU;
bch.encode(m_tx[P25_DUID_PDU]); bch.encode(m_tx[DUID::PDU]);
m_tx[P25_DUID_PDU][7U] &= 0xFEU; // Clear the parity bit m_tx[DUID::PDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_TSDU] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TSDU][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::TSDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TSDU][1U] = (nac << 4) & 0xF0U; m_tx[DUID::TSDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TSDU][1U] |= P25_DUID_TSDU; m_tx[DUID::TSDU][1U] |= DUID::TSDU;
bch.encode(m_tx[P25_DUID_TSDU]); bch.encode(m_tx[DUID::TSDU]);
m_tx[P25_DUID_TSDU][7U] &= 0xFEU; // Clear the parity bit m_tx[DUID::TSDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_LDU2] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_LDU2][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::LDU2][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_LDU2][1U] = (nac << 4) & 0xF0U; m_tx[DUID::LDU2][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_LDU2][1U] |= P25_DUID_LDU2; m_tx[DUID::LDU2][1U] |= DUID::LDU2;
bch.encode(m_tx[P25_DUID_LDU2]); bch.encode(m_tx[DUID::LDU2]);
m_tx[P25_DUID_LDU2][7U] |= 0x01U; // Set the parity bit m_tx[DUID::LDU2][7U] |= 0x01U; // Set the parity bit
m_tx[P25_DUID_TDULC] = new uint8_t[P25_NID_LENGTH_BYTES]; m_tx[DUID::TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TDULC][0U] = (nac >> 4) & 0xFFU; m_tx[DUID::TDULC][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TDULC][1U] = (nac << 4) & 0xF0U; m_tx[DUID::TDULC][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TDULC][1U] |= P25_DUID_TDULC; m_tx[DUID::TDULC][1U] |= DUID::TDULC;
bch.encode(m_tx[P25_DUID_TDULC]); bch.encode(m_tx[DUID::TDULC]);
m_tx[P25_DUID_TDULC][7U] &= 0xFEU; // Clear the parity bit m_tx[DUID::TDULC][7U] &= 0xFEU; // Clear the parity bit
} }

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2016 Jonathan Naylor, G4KLX * Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017,2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__P25_NID_H__) #if !defined(__P25_NID_H__)
#define __P25_NID_H__ #define __P25_NID_H__
#include "common/Defines.h" #include "common/Defines.h"
#include "common/p25/P25Defines.h"
namespace p25 namespace p25
{ {
@ -34,14 +35,14 @@ namespace p25
/// <summary>Decodes P25 network identifier data.</summary> /// <summary>Decodes P25 network identifier data.</summary>
bool decode(const uint8_t* data); bool decode(const uint8_t* data);
/// <summary>Encodes P25 network identifier data.</summary> /// <summary>Encodes P25 network identifier data.</summary>
void encode(uint8_t* data, uint8_t duid); void encode(uint8_t* data, defines::DUID::E duid);
/// <summary>Helper to configure a separate Tx NAC.</summary> /// <summary>Helper to configure a separate Tx NAC.</summary>
void setTxNAC(uint32_t nac); void setTxNAC(uint32_t nac);
public: public:
/// <summary>Data unit ID.</summary> /// <summary>Data unit ID.</summary>
__READONLY_PROPERTY(uint8_t, duid, DUID); __READONLY_PROPERTY(defines::DUID::E, duid, DUID);
private: private:
uint32_t m_nac; uint32_t m_nac;

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2016 Jonathan Naylor, G4KLX * Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__P25_DEFINES_H__) #if !defined(__P25_DEFINES_H__)
@ -17,371 +17,497 @@
#include "common/Defines.h" #include "common/Defines.h"
// Shorthand macro to p25::defines -- keeps source code that doesn't use "using" concise
#define P25DEF p25::defines
namespace p25 namespace p25
{ {
// --------------------------------------------------------------------------- namespace defines
// Constants {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint32_t P25_HDU_FRAME_LENGTH_BYTES = 99U; const uint32_t P25_HDU_FRAME_LENGTH_BYTES = 99U;
const uint32_t P25_HDU_FRAME_LENGTH_BITS = P25_HDU_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_HDU_FRAME_LENGTH_BITS = P25_HDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TDU_FRAME_LENGTH_BYTES = 18U; const uint32_t P25_TDU_FRAME_LENGTH_BYTES = 18U;
const uint32_t P25_TDU_FRAME_LENGTH_BITS = P25_TDU_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_TDU_FRAME_LENGTH_BITS = P25_TDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_LDU_FRAME_LENGTH_BYTES = 216U; const uint32_t P25_LDU_FRAME_LENGTH_BYTES = 216U;
const uint32_t P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_LDU_FRAME_LENGTH_BITS = P25_LDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TSDU_FRAME_LENGTH_BYTES = 45U; const uint32_t P25_TSDU_FRAME_LENGTH_BYTES = 45U;
const uint32_t P25_TSDU_FRAME_LENGTH_BITS = P25_TSDU_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_TSDU_FRAME_LENGTH_BITS = P25_TSDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TSDU_DOUBLE_FRAME_LENGTH_BYTES = 72U; const uint32_t P25_TSDU_DOUBLE_FRAME_LENGTH_BYTES = 72U;
const uint32_t P25_TSDU_DOUBLE_FRAME_LENGTH_BITS = P25_TSDU_DOUBLE_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_TSDU_DOUBLE_FRAME_LENGTH_BITS = P25_TSDU_DOUBLE_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES = 90U; const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES = 90U;
const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BITS = P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_TSDU_TRIPLE_FRAME_LENGTH_BITS = P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_PDU_FRAME_LENGTH_BYTES = 512U; const uint32_t P25_PDU_FRAME_LENGTH_BYTES = 512U;
const uint32_t P25_PDU_FRAME_LENGTH_BITS = P25_PDU_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_PDU_FRAME_LENGTH_BITS = P25_PDU_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_TDULC_FRAME_LENGTH_BYTES = 54U; const uint32_t P25_TDULC_FRAME_LENGTH_BYTES = 54U;
const uint32_t P25_TDULC_FRAME_LENGTH_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U; const uint32_t P25_TDULC_FRAME_LENGTH_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U;
const uint32_t P25_NID_LENGTH_BYTES = 8U; const uint32_t P25_NID_LENGTH_BYTES = 8U;
const uint32_t P25_NID_LENGTH_BITS = P25_NID_LENGTH_BYTES * 8U; const uint32_t P25_NID_LENGTH_BITS = P25_NID_LENGTH_BYTES * 8U;
const uint8_t P25_SYNC_BYTES[] = { 0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU }; const uint8_t P25_SYNC_BYTES[] = { 0x55U, 0x75U, 0xF5U, 0xFFU, 0x77U, 0xFFU };
const uint32_t P25_SYNC_LENGTH_BYTES = 6U; const uint32_t P25_SYNC_LENGTH_BYTES = 6U;
const uint32_t P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U; const uint32_t P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U;
const uint8_t P25_START_SYNC = 0x5FU; const uint8_t P25_START_SYNC = 0x5FU;
const uint32_t P25_PREAMBLE_LENGTH_BYTES = P25_SYNC_LENGTH_BYTES + P25_NID_LENGTH_BYTES; const uint32_t P25_PREAMBLE_LENGTH_BYTES = P25_SYNC_LENGTH_BYTES + P25_NID_LENGTH_BYTES;
const uint32_t P25_PREAMBLE_LENGTH_BITS = P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS; const uint32_t P25_PREAMBLE_LENGTH_BITS = P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS;
const uint32_t P25_LDU_FRAME_TIME = 180U; const uint32_t P25_LDU_FRAME_TIME = 180U;
const uint32_t P25_HDU_LENGTH_BYTES = 81U; const uint32_t P25_HDU_LENGTH_BYTES = 81U;
const uint32_t P25_LDU_LC_FEC_LENGTH_BYTES = 18U; const uint32_t P25_LDU_LC_FEC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U; const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U;
const uint32_t P25_TDULC_LENGTH_BYTES = 18U; const uint32_t P25_TDULC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_PAYLOAD_LENGTH_BYTES = 8U; const uint32_t P25_TDULC_PAYLOAD_LENGTH_BYTES = 8U;
const uint32_t P25_TSBK_FEC_LENGTH_BYTES = 25U; const uint32_t P25_TSBK_FEC_LENGTH_BYTES = 25U;
const uint32_t P25_TSBK_FEC_LENGTH_BITS = P25_TSBK_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits const uint32_t P25_TSBK_FEC_LENGTH_BITS = P25_TSBK_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits
const uint32_t P25_TSBK_LENGTH_BYTES = 12U; const uint32_t P25_TSBK_LENGTH_BYTES = 12U;
const uint32_t P25_MAX_PDU_BLOCKS = 42U; const uint32_t P25_MAX_PDU_BLOCKS = 42U;
const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U; const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U;
const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U; const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U;
const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U; const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U;
const uint32_t P25_PDU_UNCONFIRMED_LENGTH_BYTES = 12U; const uint32_t P25_PDU_UNCONFIRMED_LENGTH_BYTES = 12U;
const uint32_t P25_PDU_FEC_LENGTH_BYTES = 25U; const uint32_t P25_PDU_FEC_LENGTH_BYTES = 25U;
const uint32_t P25_PDU_FEC_LENGTH_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits const uint32_t P25_PDU_FEC_LENGTH_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits
const uint32_t P25_MI_LENGTH_BYTES = 9U; const uint32_t MI_LENGTH_BYTES = 9U;
const uint32_t P25_RAW_IMBE_LENGTH_BYTES = 11U; const uint32_t RAW_IMBE_LENGTH_BYTES = 11U;
const uint32_t P25_SS0_START = 70U; const uint32_t P25_SS0_START = 70U;
const uint32_t P25_SS1_START = 71U; const uint32_t P25_SS1_START = 71U;
const uint32_t P25_SS_INCREMENT = 72U; const uint32_t P25_SS_INCREMENT = 72U;
const uint8_t P25_NULL_IMBE[] = { 0x04U, 0x0CU, 0xFDU, 0x7BU, 0xFBU, 0x7DU, 0xF2U, 0x7BU, 0x3DU, 0x9EU, 0x45U }; const uint8_t NULL_IMBE[] = { 0x04U, 0x0CU, 0xFDU, 0x7BU, 0xFBU, 0x7DU, 0xF2U, 0x7BU, 0x3DU, 0x9EU, 0x45U };
const uint8_t P25_ENCRYPTED_NULL_IMBE[] = { 0xFCU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U }; const uint8_t ENCRYPTED_NULL_IMBE[] = { 0xFCU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U };
const uint8_t P25_MFG_STANDARD = 0x00U; const uint8_t MOT_CALLSIGN_LENGTH_BYTES = 8U;
const uint8_t P25_MFG_STANDARD_ALT = 0x01U;
const uint8_t AUTH_RES_LENGTH_BYTES = 4U;
const uint8_t P25_MFG_MOT = 0x90U; const uint8_t AUTH_RAND_SEED_LENGTH_BYTES = 10U;
const uint8_t P25_MFG_DVM_OCS = 0x9CU; // P25 MFId used for internal signalling; Omaha Communication Systems, LLC ($9C) const uint8_t AUTH_RAND_CHLNG_LENGTH_BYTES = 5U;
const uint8_t AUTH_KEY_LENGTH_BYTES = 16U;
const uint8_t P25_MOT_CALLSIGN_LENGTH_BYTES = 8U;
/** Thresholds */
const uint8_t P25_AUTH_RES_LENGTH_BYTES = 4U; const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U;
const uint8_t P25_AUTH_RAND_SEED_LENGTH_BYTES = 10U; const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 6U;
const uint8_t P25_AUTH_RAND_CHLNG_LENGTH_BYTES = 5U; const uint32_t MAX_P25_VOICE_ERRORS = 1233U;
const uint8_t P25_AUTH_KEY_LENGTH_BYTES = 16U;
/** Manufacturer IDs */
const uint8_t P25_ALGO_UNENCRYPT = 0x80U; const uint8_t MFG_STANDARD = 0x00U; // Standard MFId
const uint8_t MFG_STANDARD_ALT = 0x01U; // Alternate Standard MFId
const uint8_t P25_IDEN_UP_VU_BW_625K = 0x04U;
const uint8_t P25_IDEN_UP_VU_BW_125K = 0x05U; const uint8_t MFG_MOT = 0x90U; // Motorola
const uint8_t MFG_DVM_OCS = 0x9CU; // DVM; Omaha Communication Systems, LLC ($9C)
const uint8_t P25_SVC_CLS_INVALID = 0x00U;
const uint8_t P25_SVC_CLS_COMPOSITE = 0x01U; /** Encryption Algorithms */
const uint8_t P25_SVC_CLS_VOICE = 0x10U; const uint8_t ALGO_UNENCRYPT = 0x80U; // Unencrypted
const uint8_t P25_SVC_CLS_DATA = 0x20U;
const uint8_t P25_SVC_CLS_REG = 0x40U; /** IDEN Table Bandwidth Sizes */
const uint8_t P25_SVC_CLS_AUTH = 0x80U; const uint8_t IDEN_UP_VU_BW_625K = 0x04U;
const uint8_t IDEN_UP_VU_BW_125K = 0x05U;
const uint32_t P25_SYS_SRV_NET_ACTIVE = 0x0200000U;
const uint32_t P25_SYS_SRV_GROUP_VOICE = 0x0080000U; /// <summary>
const uint32_t P25_SYS_SRV_IND_VOICE = 0x0040000U; /// Station Service Classes
const uint32_t P25_SYS_SRV_PSTN_UNIT_VOICE = 0x0020000U; /// </summary>
const uint32_t P25_SYS_SRV_UNIT_PSTN_VOICE = 0x0010000U; namespace ServiceClass {
const uint32_t P25_SYS_SRV_GROUP_DATA = 0x0004000U; enum : uint8_t {
const uint32_t P25_SYS_SRV_IND_DATA = 0x0002000U; INVALID = 0x00U, // Invalid Service Class
const uint32_t P25_SYS_SRV_UNIT_REG = 0x0000800U; COMPOSITE = 0x01U, // Composite Control Channel
const uint32_t P25_SYS_SRV_GROUP_AFF = 0x0000400U; VOICE = 0x10U, // Voice
const uint32_t P25_SYS_SRV_GROUP_AFF_Q = 0x0000200U; DATA = 0x20U, // Data
const uint32_t P25_SYS_SRV_USER_STS = 0x0000040U; REG = 0x40U, // Registration
const uint32_t P25_SYS_SRV_USER_MSG = 0x0000020U; AUTH = 0x80U // Authentication
const uint32_t P25_SYS_SRV_UNIT_STS = 0x0000010U; };
const uint32_t P25_SYS_SRV_USER_STS_Q = 0x0000008U; }
const uint32_t P25_SYS_SRV_UNIT_STS_Q = 0x0000004U;
const uint32_t P25_SYS_SRV_CALL_ALRT = 0x0000002U; /// <summary>
const uint32_t P25_SYS_SRV_EMERGENCY = 0x0000001U; /// System Service Types
/// </summary>
const uint32_t P25_SYS_SRV_DEFAULT = P25_SYS_SRV_EMERGENCY | P25_SYS_SRV_CALL_ALRT | P25_SYS_SRV_USER_MSG | namespace SystemService {
P25_SYS_SRV_UNIT_STS_Q | P25_SYS_SRV_USER_STS_Q | P25_SYS_SRV_UNIT_STS | P25_SYS_SRV_USER_STS | enum : uint32_t {
P25_SYS_SRV_IND_DATA | P25_SYS_SRV_IND_VOICE | P25_SYS_SRV_GROUP_DATA | P25_SYS_SRV_GROUP_VOICE; NET_ACTIVE = 0x0200000U, // Network Active
const uint32_t P25_SYS_SRV_TRUNK = P25_SYS_SRV_DEFAULT | P25_SYS_SRV_GROUP_AFF | P25_SYS_SRV_UNIT_REG | P25_SYS_SRV_GROUP_AFF_Q; GROUP_VOICE = 0x0080000U, // Group Voice
IND_VOICE = 0x0040000U, // Individual Voice
const uint8_t P25_CFVA_CONV = 0x08U; PSTN_UNIT_VOICE = 0x0020000U, // PSTN Unit Voice
const uint8_t P25_CFVA_FAILURE = 0x04U; UNIT_PSTN_VOICE = 0x0010000U, // Unit PSTN Voice
const uint8_t P25_CFVA_VALID = 0x02U; GROUP_DATA = 0x0004000U, // Group Data
const uint8_t P25_CFVA_NETWORK = 0x01U; IND_DATA = 0x0002000U, // Individual Data
UNIT_REG = 0x0000800U, // Unit Registration
const uint8_t P25_RSP_ACCEPT = 0x00U; GROUP_AFF = 0x0000400U, // Group Affiliation
const uint8_t P25_RSP_FAIL = 0x01U; GROUP_AFF_Q = 0x0000200U, // Group Affiliation Query
const uint8_t P25_RSP_DENY = 0x02U; USER_STS = 0x0000040U, // User Status
const uint8_t P25_RSP_REFUSED = 0x03U; USER_MSG = 0x0000020U, // User Message
UNIT_STS = 0x0000010U, // Unit Status
const uint8_t P25_ANS_RSP_PROCEED = 0x20U; USER_STS_Q = 0x0000008U, // User Status Query
const uint8_t P25_ANS_RSP_DENY = 0x21U; UNIT_STS_Q = 0x0000004U, // Unit Status Query
const uint8_t P25_ANS_RSP_WAIT = 0x22U; CALL_ALRT = 0x0000002U, // Call Alert
EMERGENCY = 0x0000001U // Emergency
const uint8_t P25_CAN_SRV_NONE = 0x00U; };
const uint8_t P25_CAN_SRV_TERM_QUE = 0x10U; }
const uint8_t P25_CAN_SRV_TERM_RSRC_ASSIGN = 0x20U;
const uint32_t SYS_SRV_DEFAULT = SystemService::EMERGENCY | SystemService::CALL_ALRT | SystemService::USER_MSG |
const uint32_t P25_DENY_RSN_REQ_UNIT_NOT_VALID = 0x10U; SystemService::UNIT_STS_Q | SystemService::USER_STS_Q | SystemService::UNIT_STS | SystemService::USER_STS |
const uint32_t P25_DENY_RSN_REQ_UNIT_NOT_AUTH = 0x11U; SystemService::IND_DATA | SystemService::IND_VOICE | SystemService::GROUP_DATA | SystemService::GROUP_VOICE;
const uint32_t SYS_SRV_TRUNK = SYS_SRV_DEFAULT | SystemService::GROUP_AFF | SystemService::UNIT_REG | SystemService::GROUP_AFF_Q;
const uint32_t P25_DENY_RSN_TGT_UNIT_NOT_VALID = 0x20U;
const uint32_t P25_DENY_RSN_TGT_UNIT_NOT_AUTH = 0x21U; /// <summary>
const uint32_t P25_DENY_RSN_SU_FAILED_AUTH = 0x22U; ///
const uint32_t P25_DENY_RSN_TGT_UNIT_REFUSED = 0x2FU; /// </summary>
namespace CFVA {
const uint32_t P25_DENY_RSN_TGT_GROUP_NOT_VALID = 0x30U; enum : uint8_t {
const uint32_t P25_DENY_RSN_TGT_GROUP_NOT_AUTH = 0x31U; CONV = 0x08U, // Conventional
FAILURE = 0x04U, // Failure
const uint32_t P25_DENY_RSN_NO_NET_RSRC_AVAIL = 0x53U; VALID = 0x02U, // Valid
const uint32_t P25_DENY_RSN_NO_RF_RSRC_AVAIL = 0x54U; NETWORK = 0x01U // Networked
const uint32_t P25_DENY_RSN_SVC_IN_USE = 0x55U; };
}
const uint32_t P25_DENY_RSN_SITE_ACCESS_DENIAL = 0x60U;
/// <summary>
const uint32_t P25_DENY_RSN_PTT_COLLIDE = 0x67U; /// Response Codes
const uint32_t P25_DENY_RSN_PTT_BONK = 0x77U; /// </summary>
namespace ResponseCode {
const uint32_t P25_DENY_RSN_SYS_UNSUPPORTED_SVC = 0xFFU; enum : uint8_t {
// General Codes
const uint32_t P25_QUE_RSN_REQ_ACTIVE_SERVICE = 0x10U; ACCEPT = 0x00U, // Accept
const uint32_t P25_QUE_RSN_TGT_ACTIVE_SERVICE = 0x20U; FAIL = 0x01U, // Fail
DENY = 0x02U, // Deny
const uint32_t P25_QUE_RSN_TGT_UNIT_QUEUED = 0x2FU; REFUSED = 0x03U, // Refused
const uint32_t P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL = 0x40U; // Answer Codes
ANS_PROCEED = 0x20U, // Proceed
const uint32_t P25_EXT_FNCT_CHECK = 0x0000U; // Radio Check ANS_DENY = 0x21U, // Deny
const uint32_t P25_EXT_FNCT_UNINHIBIT = 0x007EU; // Radio Uninhibit ANS_WAIT = 0x22U // Wait
const uint32_t P25_EXT_FNCT_INHIBIT = 0x007FU; // Radio Inhibit };
const uint32_t P25_EXT_FNCT_CHECK_ACK = 0x0080U; // Radio Check Ack }
const uint32_t P25_EXT_FNCT_UNINHIBIT_ACK = 0x00FEU; // Radio Uninhibit Ack
const uint32_t P25_EXT_FNCT_INHIBIT_ACK = 0x00FFU; // Radio Inhibit Ack /// <summary>
/// Cancel Service Codes
const uint32_t P25_WACN_STD_DEFAULT = 0xBB800U; /// </summary>
namespace CancelService {
const uint32_t P25_SID_STD_DEFAULT = 0x001U; enum : uint8_t {
NONE = 0x00U, // None
const uint32_t P25_NAC_DIGITAL_SQ = 0xF7EU; TERM_QUE = 0x10U, // Terminate Queued
const uint32_t P25_NAC_REUSE_RX_NAC = 0xF7FU; TERM_RSRC_ASSIGN = 0x20U // Terminate Resource Assigned
const uint32_t P25_DEFAULT_NAC = 0x293U; };
}
const uint32_t P25_WUID_FNE = 0xFFFFFCU;
const uint32_t P25_WUID_REG = 0xFFFFFEU; /// <summary>
const uint32_t P25_WUID_ALL = 0xFFFFFFU; /// Reason Codes
/// </summary>
const uint32_t P25_TGID_ALL = 0xFFFFU; namespace ReasonCode {
enum : uint8_t {
const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U; // Denial Codes
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 6U; DENY_REQ_UNIT_NOT_VALID = 0x10U, // Requesting Unit Not Valid
const uint32_t MAX_P25_VOICE_ERRORS = 1233U; DENY_REQ_UNIT_NOT_AUTH = 0x11U, // Requesting Unit Not Authenticated
const uint8_t P25_FT_HDU_VALID = 0x01U; DENY_TGT_UNIT_NOT_VALID = 0x20U, // Target Unit Not Vaild
const uint8_t P25_FT_HDU_LATE_ENTRY = 0x02U; DENY_TGT_UNIT_NOT_AUTH = 0x21U, // Target Unit Not Authenticated
const uint8_t P25_FT_TERMINATOR = 0x03U; DENY_SU_FAILED_AUTH = 0x22U, // Subscriber Failed Authentication
const uint8_t P25_FT_DATA_UNIT = 0x00U; DENY_TGT_UNIT_REFUSED = 0x2FU, // Target Unit Refused
// PDU Format Type(s) DENY_TGT_GROUP_NOT_VALID = 0x30U, // Target Group Not Valid
const uint8_t PDU_FMT_RSP = 0x03U; DENY_TGT_GROUP_NOT_AUTH = 0x31U, // Target Group Not Authenticated
const uint8_t PDU_FMT_UNCONFIRMED = 0x15U;
const uint8_t PDU_FMT_CONFIRMED = 0x16U; DENY_NO_NET_RSRC_AVAIL = 0x53U, // No Network Resources Available
const uint8_t PDU_FMT_AMBT = 0x17U; DENY_NO_RF_RSRC_AVAIL = 0x54U, // No RF Resources Available
DENY_SVC_IN_USE = 0x55U, // Service In Use
// PDU SAP
const uint8_t PDU_SAP_USER_DATA = 0x00U; DENY_SITE_ACCESS_DENIAL = 0x60U, // Site Access Denial
const uint8_t PDU_SAP_ENC_USER_DATA = 0x01U;
DENY_PTT_COLLIDE = 0x67U, // Push-to-Talk Collision
const uint8_t PDU_SAP_PACKET_DATA = 0x04U; DENY_PTT_BONK = 0x77U, // Push-to-Talk Denial/Bonk
const uint8_t PDU_SAP_ARP = 0x05U; DENY_SYS_UNSUPPORTED_SVC = 0xFFU, // Service Unsupported
const uint8_t PDU_SAP_SNDCP_CTRL_DATA = 0x06U; // Queue Codes
QUE_REQ_ACTIVE_SERVICE = 0x10U, // Requested Service Active
const uint8_t PDU_SAP_EXT_ADDR = 0x1FU; QUE_TGT_ACTIVE_SERVICE = 0x20U, // Target Service Active
const uint8_t PDU_SAP_REG = 0x20U; QUE_TGT_UNIT_QUEUED = 0x2FU, // Target Unit Queued
const uint8_t PDU_SAP_UNENC_KMM = 0x28U; QUE_CHN_RESOURCE_NOT_AVAIL = 0x40U // Channel Resource Not Available
const uint8_t PDU_SAP_ENC_KMM = 0x29U; };
}
const uint8_t PDU_SAP_TRUNK_CTRL = 0x3DU;
/// <summary>
// PDU ACK Class /// Extended Functions
const uint8_t PDU_ACK_CLASS_ACK = 0x00U; /// </summary>
const uint8_t PDU_ACK_CLASS_NACK = 0x01U; namespace ExtendedFunctions {
const uint8_t PDU_ACK_CLASS_ACK_RETRY = 0x02U; enum : uint16_t {
CHECK = 0x0000U, // Radio Check
// PDU ACK Type(s) UNINHIBIT = 0x007EU, // Radio Uninhibit
const uint8_t PDU_ACK_TYPE_RETRY = 0x00U; INHIBIT = 0x007FU, // Radio Inhibit
CHECK_ACK = 0x0080U, // Radio Check Ack
const uint8_t PDU_ACK_TYPE_ACK = 0x01U; UNINHIBIT_ACK = 0x00FEU, // Radio Uninhibit Ack
INHIBIT_ACK = 0x00FFU // Radio Inhibit Ack
const uint8_t PDU_ACK_TYPE_NACK_ILLEGAL = 0x00U; // Illegal Format };
const uint8_t PDU_ACK_TYPE_NACK_PACKET_CRC = 0x01U; // Packet CRC }
const uint8_t PDU_ACK_TYPE_NACK_MEMORY_FULL = 0x02U; // Memory Full
const uint8_t PDU_ACK_TYPE_NACK_SEQ = 0x03U; // Out of logical sequence FSN /** Default Values */
const uint8_t PDU_ACK_TYPE_NACK_UNDELIVERABLE = 0x04U;// Undeliverable const uint32_t NAC_DIGITAL_SQ = 0xF7EU; // Digital Squelch NAC
const uint8_t PDU_ACK_TYPE_NACK_OUT_OF_SEQ = 0x05U; // Out of sequence, N(S) != V(R) or V(R) + 1 const uint32_t NAC_REUSE_RX_NAC = 0xF7FU; // Reuse RX NAC
const uint8_t PDU_ACK_TYPE_NACK_INVL_USER = 0x06U; // Invalid User disallowed by the system const uint32_t DEFAULT_NAC = 0x293U; // Default NAC
// PDU Registration Type(s) const uint32_t WACN_STD_DEFAULT = 0xBB800U; // Default WACN
const uint8_t PDU_REG_TYPE_REQ_CNCT = 0x00U; const uint32_t SID_STD_DEFAULT = 0x001U; // Default System ID
const uint8_t PDU_REG_TYPE_REQ_DISCNCT = 0x01U;
const uint8_t PDU_REG_TYPE_RSP_ACCPT = 0x04U; const uint32_t WUID_FNE = 0xFFFFFCU; // FNE Working Unit ID
const uint8_t PDU_REG_TYPE_RSP_DENY = 0x05U; const uint32_t WUID_REG = 0xFFFFFEU; // Registration Working Unit ID
const uint32_t WUID_ALL = 0xFFFFFFU; // All-call Working Unit ID
// PDU SNDCP Type(s)
const uint8_t PDU_TYPE_SNDCP_ACT_TDS_CTX_ACCPT = 0x00U; const uint32_t TGID_ALL = 0xFFFFU; // All-call Talkgroup ID
const uint8_t PDU_TYPE_SNDCP_DEACT_TDS_CTX_ACCPT = 0x01U;
const uint8_t PDU_TYPE_SNDCP_DEACT_TDS_CTX_REQ = 0x02U; /// <summary>
const uint8_t PDU_TYPE_SNDCP_ACT_TDS_CTX_REJECT = 0x03U; /// DVM Network Frame Types
const uint8_t PDU_TYPE_SNDCP_RF_UNCONFIRMED = 0x04U; /// </summary>
const uint8_t PDU_TYPE_SNDCP_RF_CONFIRMED = 0x05U; namespace FrameType {
// DVM Network Frame Types Enumeration
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U; enum E : uint8_t {
const uint8_t LC_SVC_OPT_ENCRYPTION = 0x40U; HDU_VALID = 0x01U, // HDU Valid
HDU_LATE_ENTRY = 0x02U, // HDU Late Entry
// LDUx/TDULC Link Control Opcode(s) TERMINATOR = 0x03U, // TDU/TDULC Terminator
const uint8_t LC_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User DATA_UNIT = 0x00U // Standard Data Unit
const uint8_t LC_GROUP_UPDT = 0x02U; // GRP VCH UPDT - Group Voice Channel Update };
const uint8_t LC_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User }
const uint8_t LC_UU_ANS_REQ = 0x05U; // UU ANS REQ - Unit to Unit Answer Request /// <summary>
const uint8_t LC_TEL_INT_VCH_USER = 0x06U; // TEL INT VCH USER - Telephone Interconnect Voice Channel User / MOT GPS DATA - Motorola In-Band GPS Data /// Data Format Type
const uint8_t LC_TEL_INT_ANS_RQST = 0x07U; // TEL INT ANS RQST - Telephone Interconnect Answer Request /// </summary>
const uint8_t LC_EXPLICIT_SOURCE_ID = 0x09U; // EXPLICIT SOURCE ID - Explicit Source ID namespace PDUFormatType {
const uint8_t LC_CALL_TERM = 0x0FU; // CALL TERM - Call Termination or Cancellation enum : uint8_t {
const uint8_t LC_IDEN_UP = 0x18U; // IDEN UP - Channel Identifier Update RSP = 0x03U, // Response
const uint8_t LC_SYS_SRV_BCAST = 0x20U; // SYS SRV BCAST - System Service Broadcast UNCONFIRMED = 0x15U, // Unconfirmed PDU
const uint8_t LC_ADJ_STS_BCAST = 0x22U; // ADJ STS BCAST - Adjacent Site Status Broadcast CONFIRMED = 0x16U, // Confirmed PDU
const uint8_t LC_RFSS_STS_BCAST = 0x23U; // RFSS STS BCAST - RFSS Status Broadcast AMBT = 0x17U // Alternate Multi Block Trunking
const uint8_t LC_NET_STS_BCAST = 0x24U; // NET STS BCAST - Network Status Broadcast };
const uint8_t LC_CONV_FALLBACK = 0x2AU; // CONV FALLBACK - Conventional Fallback }
// LDUx/TDULC Motorola Link Control Opcode(s) /// <summary>
const uint8_t LC_FAILSOFT = 0x02U; // FAILSOFT - Failsoft /// Service Access Point
/// </summary>
// TSBK ISP/OSP Shared Opcode(s) namespace PDUSAP {
const uint8_t TSBK_IOSP_GRP_VCH = 0x00U; // GRP VCH REQ - Group Voice Channel Request (ISP), GRP VCH GRANT - Group Voice Channel Grant (OSP) enum : uint8_t {
const uint8_t TSBK_IOSP_UU_VCH = 0x04U; // UU VCH REQ - Unit-to-Unit Voice Channel Request (ISP), UU VCH GRANT - Unit-to-Unit Voice Channel Grant (OSP) USER_DATA = 0x00U, // User Data
const uint8_t TSBK_IOSP_UU_ANS = 0x05U; // UU ANS RSP - Unit-to-Unit Answer Response (ISP), UU ANS REQ - Unit-to-Unit Answer Request (OSP) ENC_USER_DATA = 0x01U, // Encrypted User Data
const uint8_t TSBK_IOSP_TELE_INT_DIAL = 0x08U; // TELE INT DIAL REQ - Telephone Interconnect Request - Explicit (ISP), TELE INT DIAL GRANT - Telephone Interconnect Grant (OSP)
const uint8_t TSBK_IOSP_TELE_INT_ANS = 0x0AU; // TELE INT ANS RSP - Telephone Interconnect Answer Response (ISP), TELE INT ANS REQ - Telephone Interconnect Answer Request (OSP) PACKET_DATA = 0x04U, // Packet Data
const uint8_t TSBK_IOSP_STS_UPDT = 0x18U; // STS UPDT REQ - Status Update Request (ISP), STS UPDT - Status Update (OSP)
const uint8_t TSBK_IOSP_STS_Q = 0x1AU; // STS Q REQ - Status Query Request (ISP), STS Q - Status Query (OSP) ARP = 0x05U, // ARP
const uint8_t TSBK_IOSP_MSG_UPDT = 0x1CU; // MSG UPDT REQ - Message Update Request (ISP), MSG UPDT - Message Update (OSP)
const uint8_t TSBK_IOSP_RAD_MON = 0x1DU; // RAD MON REQ - Radio Unit Monitor Request (ISP), RAD MON CMD - Radio Monitor Command (OSP) SNDCP_CTRL_DATA = 0x06U, // SNDCP Control Data
const uint8_t TSBK_IOSP_RAD_MON_ENH = 0x1EU; // RAD MON ENH REQ - Radio Unit Monitor Enhanced Request (ISP), RAD MON ENH CMD - Radio Unit Monitor Enhanced Command (OSP)
const uint8_t TSBK_IOSP_CALL_ALRT = 0x1FU; // CALL ALRT REQ - Call Alert Request (ISP), CALL ALRT - Call Alert (OSP) EXT_ADDR = 0x1FU, // Extended Addressing
const uint8_t TSBK_IOSP_ACK_RSP = 0x20U; // ACK RSP U - Acknowledge Response - Unit (ISP), ACK RSP FNE - Acknowledge Response - FNE (OSP)
const uint8_t TSBK_IOSP_EXT_FNCT = 0x24U; // EXT FNCT RSP - Extended Function Response (ISP), EXT FNCT CMD - Extended Function Command (OSP) REG = 0x20U, // Registration
const uint8_t TSBK_IOSP_GRP_AFF = 0x28U; // GRP AFF REQ - Group Affiliation Request (ISP), GRP AFF RSP - Group Affiliation Response (OSP)
const uint8_t TSBK_IOSP_U_REG = 0x2CU; // U REG REQ - Unit Registration Request (ISP), U REG RSP - Unit Registration Response (OSP) UNENC_KMM = 0x28U, // Unencrypted KMM
ENC_KMM = 0x29U, // Encrypted KMM
// TSBK Inbound Signalling Packet (ISP) Opcode(s)
const uint8_t TSBK_ISP_TELE_INT_PSTN_REQ = 0x09U; // TELE INT PSTN REQ - Telephone Interconnect Request - Implicit TRUNK_CTRL = 0x3DU // Trunking Control
const uint8_t TSBK_ISP_SNDCP_CH_REQ = 0x12U; // SNDCP CH REQ - SNDCP Data Channel Request };
const uint8_t TSBK_ISP_STS_Q_RSP = 0x19U; // STS Q RSP - Status Query Response }
const uint8_t TSBK_ISP_STS_Q_REQ = 0x1CU; // STS Q REQ - Status Query Request
const uint8_t TSBK_ISP_CAN_SRV_REQ = 0x23U; // CAN SRV REQ - Cancel Service Request /// <summary>
const uint8_t TSBK_ISP_EMERG_ALRM_REQ = 0x27U; // EMERG ALRM REQ - Emergency Alarm Request /// Acknowledgement Class
const uint8_t TSBK_ISP_GRP_AFF_Q_RSP = 0x29U; // GRP AFF Q RSP - Group Affiliation Query Response /// </summary>
const uint8_t TSBK_ISP_U_DEREG_REQ = 0x2BU; // U DE REG REQ - Unit De-Registration Request namespace PDUAckClass {
const uint8_t TSBK_ISP_LOC_REG_REQ = 0x2DU; // LOC REG REQ - Location Registration Request enum : uint8_t {
const uint8_t TSBK_ISP_AUTH_RESP = 0x38U; // AUTH RESP - Authentication Response ACK = 0x00U, // Acknowledge
const uint8_t TSBK_ISP_AUTH_RESP_M = 0x39U; // AUTH RESP M - Authentication Response Mutual NACK = 0x01U, // Negative Acknowledge
const uint8_t TSBK_ISP_AUTH_FNE_RST = 0x3AU; // AUTH FNE RST - Authentication FNE Result ACK_RETRY = 0x02U // Acknowledge Retry
const uint8_t TSBK_ISP_AUTH_SU_DMD = 0x3BU; // AUTH SU DMD - Authentication SU Demand };
}
// TSBK Outbound Signalling Packet (OSP) Opcode(s)
const uint8_t TSBK_OSP_GRP_VCH_GRANT_UPD = 0x02U; // GRP VCH GRANT UPD - Group Voice Channel Grant Update /// <summary>
const uint8_t TSBK_OSP_UU_VCH_GRANT_UPD = 0x06U; // UU VCH GRANT UPD - Unit-to-Unit Voice Channel Grant Update /// Acknowledgement Type
const uint8_t TSBK_OSP_SNDCP_CH_GNT = 0x14U; // SNDCP CH GNT - SNDCP Data Channel Grant /// </summary>
const uint8_t TSBK_OSP_SNDCP_CH_ANN = 0x16U; // SNDCP CH ANN - SNDCP Data Channel Announcement namespace PDUAckType {
const uint8_t TSBK_OSP_STS_Q = 0x1AU; // STS Q - Status Query enum : uint8_t {
const uint8_t TSBK_OSP_DENY_RSP = 0x27U; // DENY RSP - Deny Response RETRY = 0x00U, // Retry
const uint8_t TSBK_OSP_SCCB_EXP = 0x29U; // SCCB - Secondary Control Channel Broadcast - Explicit
const uint8_t TSBK_OSP_GRP_AFF_Q = 0x2AU; // GRP AFF Q - Group Affiliation Query ACK = 0x01U, // Acknowledge
const uint8_t TSBK_OSP_LOC_REG_RSP = 0x2BU; // LOC REG RSP - Location Registration Response
const uint8_t TSBK_OSP_U_REG_CMD = 0x2DU; // U REG CMD - Unit Registration Command NACK_ILLEGAL = 0x00U, // Illegal Format
const uint8_t TSBK_OSP_U_DEREG_ACK = 0x2FU; // U DE REG ACK - Unit De-Registration Acknowledge NACK_PACKET_CRC = 0x01U, // Packet CRC
const uint8_t TSBK_OSP_SYNC_BCAST = 0x30U; // SYNC BCAST - Synchronization Broadcast NACK_MEMORY_FULL = 0x02U, // Memory Full
const uint8_t TSBK_OSP_AUTH_DMD = 0x31U; // AUTH DMD - Authentication Demand NACK_SEQ = 0x03U, // Out of logical sequence FSN
const uint8_t TSBK_OSP_AUTH_FNE_RESP = 0x32U; // AUTH FNE RESP - Authentication FNE Response NACK_UNDELIVERABLE = 0x04U, // Undeliverable
const uint8_t TSBK_OSP_QUE_RSP = 0x33U; // QUE RSP - Queued Response NACK_OUT_OF_SEQ = 0x05U, // Out of sequence, N(S) != V(R) or V(R) + 1
const uint8_t TSBK_OSP_IDEN_UP_VU = 0x34U; // IDEN UP VU - Channel Identifier Update for VHF/UHF Bands NACK_INVL_USER = 0x06U // Invalid User disallowed by the system
const uint8_t TSBK_OSP_TIME_DATE_ANN = 0x35U; // TIME DATE ANN - Time and Date Announcement };
const uint8_t TSBK_OSP_SYS_SRV_BCAST = 0x38U; // SYS SRV BCAST - System Service Broadcast }
const uint8_t TSBK_OSP_SCCB = 0x39U; // SCCB - Secondary Control Channel Broadcast
const uint8_t TSBK_OSP_RFSS_STS_BCAST = 0x3AU; // RFSS STS BCAST - RFSS Status Broadcast /// <summary>
const uint8_t TSBK_OSP_NET_STS_BCAST = 0x3BU; // NET STS BCAST - Network Status Broadcast /// Registration Type
const uint8_t TSBK_OSP_ADJ_STS_BCAST = 0x3CU; // ADJ STS BCAST - Adjacent Site Status Broadcast /// </summary>
const uint8_t TSBK_OSP_IDEN_UP = 0x3DU; // IDEN UP - Channel Identifier Update namespace PDURegType {
enum : uint8_t {
// TSBK Motorola Outbound Signalling Packet (OSP) Opcode(s) CNCT = 0x00U, // Connect
const uint8_t TSBK_OSP_MOT_GRG_ADD = 0x00U; // MOT GRG ADD - Motorola / Group Regroup Add (Patch Supergroup) DISCNCT = 0x01U, // Disconnect
const uint8_t TSBK_OSP_MOT_GRG_DEL = 0x01U; // MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup) ACCPT = 0x04U, // Accept
const uint8_t TSBK_OSP_MOT_GRG_VCH_GRANT = 0x02U; // MOT GRG GROUP VCH GRANT / Group Regroup Voice Channel Grant DENY = 0x05U // Deny
const uint8_t TSBK_OSP_MOT_GRG_VCH_UPD = 0x03U; // MOT GRG GROUP VCH GRANT UPD / Group Regroup Voice Channel Grant Update };
const uint8_t TSBK_OSP_MOT_CC_BSI = 0x0BU; // MOT CC BSI - Motorola / Control Channel Base Station Identifier }
const uint8_t TSBK_OSP_MOT_PSH_CCH = 0x0EU; // MOT PSH CCH - Motorola / Planned Control Channel Shutdown
/// <summary>
// TSBK DVM Outbound Signalling Packet (OSP) Opcode(s) /// SNDCP Type
const uint8_t TSBK_OSP_DVM_GIT_HASH = 0x3FU; // /// </summary>
namespace PDUSNDCPType {
// Data Unit ID(s) enum : uint8_t {
const uint8_t P25_DUID_HDU = 0x00U; // Header Data Unit ACT_TDS_CTX_ACCPT = 0x00U, // Activate Context Accept
#define P25_HDU_STR "P25_DUID_HDU (Header Data Unit)" DEACT_TDS_CTX_ACCPT = 0x01U, // Deactivate Context Accept
const uint8_t P25_DUID_TDU = 0x03U; // Simple Terminator Data Unit DEACT_TDS_CTX_REQ = 0x02U, // Deactivate Context Request
#define P25_TDU_STR "P25_DUID_TDU (Simple Terminator Data Unit)" ACT_TDS_CTX_REJECT = 0x03U, // Activate Context Reject
const uint8_t P25_DUID_LDU1 = 0x05U; // Logical Link Data Unit 1 RF_UNCONFIRMED = 0x04U, // RF Unconfirmed
#define P25_LDU1_STR "P25_DUID_LDU1 (Logical Link Data Unit 1)" RF_CONFIRMED = 0x05U // RF Confirmed
const uint8_t P25_DUID_VSELP1 = 0x06U; // Motorola VSELP 1 };
#define P25_VSELP1_STR "P25_DUID_VSELP1 (VSELP Data Unit 1)" }
const uint8_t P25_DUID_TSDU = 0x07U; // Trunking System Data Unit
#define P25_TSDU_STR "P25_DUID_TSDU (Trunking System Data Unit)" const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t P25_DUID_VSELP2 = 0x09U; // Motorola VSELP 2 const uint8_t LC_SVC_OPT_ENCRYPTION = 0x40U;
#define P25_VSELP2_STR "P25_DUID_VSELP2 (VSELP Data Unit 2)"
const uint8_t P25_DUID_LDU2 = 0x0AU; // Logical Link Data Unit 2 /// <summary>
#define P25_LDU2_STR "P25_DUID_LDU2 (Logical Link Data Unit 2)" /// LDUx/TDULC Link Control Opcode(s)
const uint8_t P25_DUID_PDU = 0x0CU; // Packet Data Unit /// </summary>
#define P25_PDU_STR "P25_DUID_PDU (Packet Data Unit)" namespace LCO {
const uint8_t P25_DUID_TDULC = 0x0FU; // Terminator Data Unit with Link Control enum : uint8_t {
#define P25_TDULC_STR "P25_DUID_TDULC (Terminator Data Unit with Link Control)" GROUP = 0x00U, // GRP VCH USER - Group Voice Channel User
GROUP_UPDT = 0x02U, // GRP VCH UPDT - Group Voice Channel Update
PRIVATE = 0x03U, // UU VCH USER - Unit-to-Unit Voice Channel User
UU_ANS_REQ = 0x05U, // UU ANS REQ - Unit to Unit Answer Request
TEL_INT_VCH_USER = 0x06U, // TEL INT VCH USER - Telephone Interconnect Voice Channel User / MOT GPS DATA - Motorola In-Band GPS Data
TEL_INT_ANS_RQST = 0x07U, // TEL INT ANS RQST - Telephone Interconnect Answer Request
EXPLICIT_SOURCE_ID = 0x09U, // EXPLICIT SOURCE ID - Explicit Source ID
CALL_TERM = 0x0FU, // CALL TERM - Call Termination or Cancellation
IDEN_UP = 0x18U, // IDEN UP - Channel Identifier Update
SYS_SRV_BCAST = 0x20U, // SYS SRV BCAST - System Service Broadcast
ADJ_STS_BCAST = 0x22U, // ADJ STS BCAST - Adjacent Site Status Broadcast
RFSS_STS_BCAST = 0x23U, // RFSS STS BCAST - RFSS Status Broadcast
NET_STS_BCAST = 0x24U, // NET STS BCAST - Network Status Broadcast
CONV_FALLBACK = 0x2AU, // CONV FALLBACK - Conventional Fallback
// LDUx/TDULC Motorola Link Control Opcode(s)
FAILSOFT = 0x02U // FAILSOFT - Failsoft
};
}
/// <summary>
/// TSBK Control Opcode(s)
/// </summary>
namespace TSBKO {
enum : uint8_t {
// TSBK ISP/OSP Shared Opcode(s)
IOSP_GRP_VCH = 0x00U, // GRP VCH REQ - Group Voice Channel Request (ISP), GRP VCH GRANT - Group Voice Channel Grant (OSP)
IOSP_UU_VCH = 0x04U, // UU VCH REQ - Unit-to-Unit Voice Channel Request (ISP), UU VCH GRANT - Unit-to-Unit Voice Channel Grant (OSP)
IOSP_UU_ANS = 0x05U, // UU ANS RSP - Unit-to-Unit Answer Response (ISP), UU ANS REQ - Unit-to-Unit Answer Request (OSP)
IOSP_TELE_INT_DIAL = 0x08U, // TELE INT DIAL REQ - Telephone Interconnect Request - Explicit (ISP), TELE INT DIAL GRANT - Telephone Interconnect Grant (OSP)
IOSP_TELE_INT_ANS = 0x0AU, // TELE INT ANS RSP - Telephone Interconnect Answer Response (ISP), TELE INT ANS REQ - Telephone Interconnect Answer Request (OSP)
IOSP_STS_UPDT = 0x18U, // STS UPDT REQ - Status Update Request (ISP), STS UPDT - Status Update (OSP)
IOSP_STS_Q = 0x1AU, // STS Q REQ - Status Query Request (ISP), STS Q - Status Query (OSP)
IOSP_MSG_UPDT = 0x1CU, // MSG UPDT REQ - Message Update Request (ISP), MSG UPDT - Message Update (OSP)
IOSP_RAD_MON = 0x1DU, // RAD MON REQ - Radio Unit Monitor Request (ISP), RAD MON CMD - Radio Monitor Command (OSP)
IOSP_RAD_MON_ENH = 0x1EU, // RAD MON ENH REQ - Radio Unit Monitor Enhanced Request (ISP), RAD MON ENH CMD - Radio Unit Monitor Enhanced Command (OSP)
IOSP_CALL_ALRT = 0x1FU, // CALL ALRT REQ - Call Alert Request (ISP), CALL ALRT - Call Alert (OSP)
IOSP_ACK_RSP = 0x20U, // ACK RSP U - Acknowledge Response - Unit (ISP), ACK RSP FNE - Acknowledge Response - FNE (OSP)
IOSP_EXT_FNCT = 0x24U, // EXT FNCT RSP - Extended Function Response (ISP), EXT FNCT CMD - Extended Function Command (OSP)
IOSP_GRP_AFF = 0x28U, // GRP AFF REQ - Group Affiliation Request (ISP), GRP AFF RSP - Group Affiliation Response (OSP)
IOSP_U_REG = 0x2CU, // U REG REQ - Unit Registration Request (ISP), U REG RSP - Unit Registration Response (OSP)
// TSBK Inbound Signalling Packet (ISP) Opcode(s)
ISP_TELE_INT_PSTN_REQ = 0x09U, // TELE INT PSTN REQ - Telephone Interconnect Request - Implicit
ISP_SNDCP_CH_REQ = 0x12U, // SNDCP CH REQ - SNDCP Data Channel Request
ISP_STS_Q_RSP = 0x19U, // STS Q RSP - Status Query Response
ISP_STS_Q_REQ = 0x1CU, // STS Q REQ - Status Query Request
ISP_CAN_SRV_REQ = 0x23U, // CAN SRV REQ - Cancel Service Request
ISP_EMERG_ALRM_REQ = 0x27U, // EMERG ALRM REQ - Emergency Alarm Request
ISP_GRP_AFF_Q_RSP = 0x29U, // GRP AFF Q RSP - Group Affiliation Query Response
ISP_U_DEREG_REQ = 0x2BU, // U DE REG REQ - Unit De-Registration Request
ISP_LOC_REG_REQ = 0x2DU, // LOC REG REQ - Location Registration Request
ISP_AUTH_RESP = 0x38U, // AUTH RESP - Authentication Response
ISP_AUTH_RESP_M = 0x39U, // AUTH RESP M - Authentication Response Mutual
ISP_AUTH_FNE_RST = 0x3AU, // AUTH FNE RST - Authentication FNE Result
ISP_AUTH_SU_DMD = 0x3BU, // AUTH SU DMD - Authentication SU Demand
// TSBK Outbound Signalling Packet (OSP) Opcode(s)
OSP_GRP_VCH_GRANT_UPD = 0x02U, // GRP VCH GRANT UPD - Group Voice Channel Grant Update
OSP_UU_VCH_GRANT_UPD = 0x06U, // UU VCH GRANT UPD - Unit-to-Unit Voice Channel Grant Update
OSP_SNDCP_CH_GNT = 0x14U, // SNDCP CH GNT - SNDCP Data Channel Grant
OSP_SNDCP_CH_ANN = 0x16U, // SNDCP CH ANN - SNDCP Data Channel Announcement
OSP_STS_Q = 0x1AU, // STS Q - Status Query
OSP_DENY_RSP = 0x27U, // DENY RSP - Deny Response
OSP_SCCB_EXP = 0x29U, // SCCB - Secondary Control Channel Broadcast - Explicit
OSP_GRP_AFF_Q = 0x2AU, // GRP AFF Q - Group Affiliation Query
OSP_LOC_REG_RSP = 0x2BU, // LOC REG RSP - Location Registration Response
OSP_U_REG_CMD = 0x2DU, // U REG CMD - Unit Registration Command
OSP_U_DEREG_ACK = 0x2FU, // U DE REG ACK - Unit De-Registration Acknowledge
OSP_SYNC_BCAST = 0x30U, // SYNC BCAST - Synchronization Broadcast
OSP_AUTH_DMD = 0x31U, // AUTH DMD - Authentication Demand
OSP_AUTH_FNE_RESP = 0x32U, // AUTH FNE RESP - Authentication FNE Response
OSP_QUE_RSP = 0x33U, // QUE RSP - Queued Response
OSP_IDEN_UP_VU = 0x34U, // IDEN UP VU - Channel Identifier Update for VHF/UHF Bands
OSP_TIME_DATE_ANN = 0x35U, // TIME DATE ANN - Time and Date Announcement
OSP_SYS_SRV_BCAST = 0x38U, // SYS SRV BCAST - System Service Broadcast
OSP_SCCB = 0x39U, // SCCB - Secondary Control Channel Broadcast
OSP_RFSS_STS_BCAST = 0x3AU, // RFSS STS BCAST - RFSS Status Broadcast
OSP_NET_STS_BCAST = 0x3BU, // NET STS BCAST - Network Status Broadcast
OSP_ADJ_STS_BCAST = 0x3CU, // ADJ STS BCAST - Adjacent Site Status Broadcast
OSP_IDEN_UP = 0x3DU, // IDEN UP - Channel Identifier Update
// TSBK Motorola Outbound Signalling Packet (OSP) Opcode(s)
OSP_MOT_GRG_ADD = 0x00U, // MOT GRG ADD - Motorola / Group Regroup Add (Patch Supergroup)
OSP_MOT_GRG_DEL = 0x01U, // MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup)
OSP_MOT_GRG_VCH_GRANT = 0x02U, // MOT GRG GROUP VCH GRANT / Group Regroup Voice Channel Grant
OSP_MOT_GRG_VCH_UPD = 0x03U, // MOT GRG GROUP VCH GRANT UPD / Group Regroup Voice Channel Grant Update
OSP_MOT_CC_BSI = 0x0BU, // MOT CC BSI - Motorola / Control Channel Base Station Identifier
OSP_MOT_PSH_CCH = 0x0EU, // MOT PSH CCH - Motorola / Planned Control Channel Shutdown
// TSBK DVM Outbound Signalling Packet (OSP) Opcode(s)
OSP_DVM_GIT_HASH = 0x3FU, //
};
}
/// <summary>
/// Data Unit ID(s)
/// </summary>
namespace DUID {
// Data Unit ID Enumeration
enum E : uint8_t {
HDU = 0x00U, // Header Data Unit
TDU = 0x03U, // Simple Terminator Data Unit
LDU1 = 0x05U, // Logical Link Data Unit 1
VSELP1 = 0x06U, // Motorola VSELP 1
TSDU = 0x07U, // Trunking System Data Unit
VSELP2 = 0x09U, // Motorola VSELP 2
LDU2 = 0x0AU, // Logical Link Data Unit 2
PDU = 0x0CU, // Packet Data Unit
TDULC = 0x0FU // Terminator Data Unit with Link Control
};
}
#define P25_HDU_STR "P25, HDU (Header Data Unit)"
#define P25_TDU_STR "P25, TDU (Simple Terminator Data Unit)"
#define P25_LDU1_STR "P25, LDU1 (Logical Link Data Unit 1)"
#define P25_VSELP1_STR "P25, VSELP1 (VSELP Data Unit 1)"
#define P25_TSDU_STR "P25, TSDU (Trunking System Data Unit)"
#define P25_VSELP2_STR "P25, VSELP2 (VSELP Data Unit 2)"
#define P25_LDU2_STR "P25, LDU2 (Logical Link Data Unit 2)"
#define P25_PDU_STR "P25, PDU (Packet Data Unit)"
#define P25_TDULC_STR "P25, TDULC (Terminator Data Unit with Link Control)"
} // namespace defines
} // namespace p25 } // namespace p25
#endif // __P25_DEFINES_H__ #endif // __P25_DEFINES_H__

@ -17,6 +17,7 @@
#include "Utils.h" #include "Utils.h"
using namespace p25; using namespace p25;
using namespace p25::defines;
#include <cassert> #include <cassert>

@ -28,6 +28,8 @@ namespace p25
class HOST_SW_API P25Utils { class HOST_SW_API P25Utils {
public: public:
/// <summary>Helper to test and clamp a P25 NAC.</summary> /// <summary>Helper to test and clamp a P25 NAC.</summary>
/// <param name="nac">Network Access Code</param>
/// <returns>Clamped network access code.</returns>
static uint32_t nac(uint32_t nac) static uint32_t nac(uint32_t nac)
{ {
if (nac < 0U) { // clamp to $000 if (nac < 0U) { // clamp to $000
@ -41,6 +43,8 @@ namespace p25
} }
/// <summary>Helper to test and clamp a P25 site ID.</summary> /// <summary>Helper to test and clamp a P25 site ID.</summary>
/// <param name="id">Site ID</param>
/// <returns>Clamped site ID.</returns>
static uint8_t siteId(uint8_t id) static uint8_t siteId(uint8_t id)
{ {
if (id == 0U) { // clamp to 1 if (id == 0U) { // clamp to 1
@ -54,6 +58,8 @@ namespace p25
} }
/// <summary>Helper to test and clamp a P25 network ID.</summary> /// <summary>Helper to test and clamp a P25 network ID.</summary>
/// <param name="id">Network ID</param>
/// <returns>Clamped network ID.</returns>
static uint32_t netId(uint32_t id) static uint32_t netId(uint32_t id)
{ {
if (id == 0U) { // clamp to 1 if (id == 0U) { // clamp to 1
@ -67,6 +73,8 @@ namespace p25
} }
/// <summary>Helper to test and clamp a P25 system ID.</summary> /// <summary>Helper to test and clamp a P25 system ID.</summary>
/// <param name="id">System ID</param>
/// <returns>Clamped system ID.</returns>
static uint32_t sysId(uint32_t id) static uint32_t sysId(uint32_t id)
{ {
if (id == 0U) { // clamp to 1 if (id == 0U) { // clamp to 1
@ -80,6 +88,8 @@ namespace p25
} }
/// <summary>Helper to test and clamp a P25 RFSS ID.</summary> /// <summary>Helper to test and clamp a P25 RFSS ID.</summary>
/// <param name="id">RFSS ID</param>
/// <returns>Clamped RFSS ID.</returns>
static uint8_t rfssId(uint8_t id) static uint8_t rfssId(uint8_t id)
{ {
if (id == 0U) { // clamp to 1 if (id == 0U) { // clamp to 1

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018 Bryan Biedenkapp, N2PLL * Copyright (C) 2018,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__P25_SITE_DATA_H__) #if !defined(__P25_SITE_DATA_H__)
@ -31,13 +31,13 @@ namespace p25
/// <summary>Initializes a new instance of the SiteData class.</summary> /// <summary>Initializes a new instance of the SiteData class.</summary>
SiteData() : SiteData() :
m_lra(0U), m_lra(0U),
m_netId(P25_WACN_STD_DEFAULT), m_netId(defines::WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT), m_sysId(defines::SID_STD_DEFAULT),
m_rfssId(1U), m_rfssId(1U),
m_siteId(1U), m_siteId(1U),
m_channelId(1U), m_channelId(1U),
m_channelNo(1U), m_channelNo(1U),
m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), m_serviceClass(defines::ServiceClass::VOICE | defines::ServiceClass::DATA),
m_isAdjSite(false), m_isAdjSite(false),
m_callsign("CHANGEME"), m_callsign("CHANGEME"),
m_chCnt(0U), m_chCnt(0U),
@ -58,13 +58,13 @@ namespace p25
/// <param name="lto">Local time offset.</param> /// <param name="lto">Local time offset.</param>
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, int8_t lto) : 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, int8_t lto) :
m_lra(0U), m_lra(0U),
m_netId(P25_WACN_STD_DEFAULT), m_netId(defines::WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT), m_sysId(defines::SID_STD_DEFAULT),
m_rfssId(1U), m_rfssId(1U),
m_siteId(1U), m_siteId(1U),
m_channelId(1U), m_channelId(1U),
m_channelNo(1U), m_channelNo(1U),
m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), m_serviceClass(defines::ServiceClass::VOICE | defines::ServiceClass::DATA),
m_isAdjSite(false), m_isAdjSite(false),
m_callsign("CHANGEME"), m_callsign("CHANGEME"),
m_chCnt(0U), m_chCnt(0U),
@ -110,7 +110,7 @@ namespace p25
std::random_device rd; std::random_device rd;
std::mt19937 mt(rd()); std::mt19937 mt(rd());
std::uniform_int_distribution<uint32_t> dist(0x01, P25_WACN_STD_DEFAULT); std::uniform_int_distribution<uint32_t> dist(0x01, defines::WACN_STD_DEFAULT);
m_netId = dist(mt); m_netId = dist(mt);
// netId clamping // netId clamping

@ -9,6 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016 Jonathan Naylor, G4KLX
* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -16,6 +17,7 @@
#include "p25/Sync.h" #include "p25/Sync.h"
using namespace p25; using namespace p25;
using namespace p25::defines;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018,2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2018,2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -17,8 +17,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::data;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::data;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -36,7 +37,7 @@ DataBlock::DataBlock() :
m_llId(0U), m_llId(0U),
m_sap(0U), m_sap(0U),
m_trellis(), m_trellis(),
m_fmt(PDU_FMT_CONFIRMED), m_fmt(PDUFormatType::CONFIRMED),
m_headerSap(0U), m_headerSap(0U),
m_data(nullptr) m_data(nullptr)
{ {
@ -73,7 +74,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
m_lastBlock = false; m_lastBlock = false;
m_llId = 0U; m_llId = 0U;
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDUFormatType::CONFIRMED) {
// decode 3/4 rate Trellis // decode 3/4 rate Trellis
try { try {
bool valid = m_trellis.decode34(data, buffer); bool valid = m_trellis.decode34(data, buffer);
@ -92,7 +93,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
::memset(m_data, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); ::memset(m_data, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
// if this is extended addressing and the first block decode the SAP and LLId // if this is extended addressing and the first block decode the SAP and LLId
if (m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U) { if (m_headerSap == PDUSAP::EXT_ADDR && m_serialNo == 0U) {
m_sap = buffer[5U] & 0x3FU; // Service Access Point m_sap = buffer[5U] & 0x3FU; // Service Access Point
m_llId = (buffer[2U] << 16) + (buffer[3U] << 8) + buffer[4U]; // Logical Link ID m_llId = (buffer[2U] << 16) + (buffer[3U] << 8) + buffer[4U]; // Logical Link ID
@ -118,11 +119,11 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
// compute CRC-9 for the packet // compute CRC-9 for the packet
uint16_t calculated = edac::CRC::createCRC9(crcBuffer, 135U); uint16_t calculated = edac::CRC::createCRC9(crcBuffer, 135U);
if ((crc ^ calculated) != 0) { if ((crc ^ calculated) != 0) {
LogWarning(LOG_P25, "P25_DUID_PDU, fmt = $%02X, invalid crc = $%04X != $%04X (computed)", m_fmt, crc, calculated); LogWarning(LOG_P25, "PDU, fmt = $%02X, invalid crc = $%04X != $%04X (computed)", m_fmt, crc, calculated);
} }
#if DEBUG_P25_PDU_DATA #if DEBUG_P25_PDU_DATA
LogDebug(LOG_P25, "P25_DUID_PDU, fmt = $%02X, crc = $%04X, calculated = $%04X", m_fmt, crc, calculated); LogDebug(LOG_P25, "PDU, fmt = $%02X, crc = $%04X, calculated = $%04X", m_fmt, crc, calculated);
Utils::dump(1U, "P25, DataBlock::decode(), Confirmed PDU Block Data", m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); Utils::dump(1U, "P25, DataBlock::decode(), Confirmed PDU Block Data", m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
#endif #endif
} }
@ -131,7 +132,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
return false; return false;
} }
} }
else if ((m_fmt == PDU_FMT_UNCONFIRMED) || (m_fmt == PDU_FMT_RSP) || (m_fmt == PDU_FMT_AMBT)) { else if ((m_fmt == PDUFormatType::UNCONFIRMED) || (m_fmt == PDUFormatType::RSP) || (m_fmt == PDUFormatType::AMBT)) {
// decode 1/2 rate Trellis // decode 1/2 rate Trellis
try { try {
bool valid = m_trellis.decode12(data, buffer); bool valid = m_trellis.decode12(data, buffer);
@ -154,7 +155,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
} }
} }
else { else {
LogError(LOG_P25, "unknown FMT value in P25_DUID_PDU, fmt = $%02X", m_fmt); LogError(LOG_P25, "unknown FMT value in PDU, fmt = $%02X", m_fmt);
} }
return true; return true;
@ -169,14 +170,14 @@ void DataBlock::encode(uint8_t* data)
assert(data != nullptr); assert(data != nullptr);
assert(m_data != nullptr); assert(m_data != nullptr);
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDUFormatType::CONFIRMED) {
uint8_t buffer[P25_PDU_CONFIRMED_LENGTH_BYTES]; uint8_t buffer[P25_PDU_CONFIRMED_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES); ::memset(buffer, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
buffer[0U] = ((m_serialNo << 1) & 0xFEU); // Confirmed Data Serial No. buffer[0U] = ((m_serialNo << 1) & 0xFEU); // Confirmed Data Serial No.
// if this is extended addressing and the first block decode the SAP and LLId // if this is extended addressing and the first block decode the SAP and LLId
if (m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U) { if (m_headerSap == PDUSAP::EXT_ADDR && m_serialNo == 0U) {
buffer[5U] = m_sap & 0x3FU; // Service Access Point buffer[5U] = m_sap & 0x3FU; // Service Access Point
buffer[2U] = (m_llId >> 16) & 0xFFU; // Logical Link ID buffer[2U] = (m_llId >> 16) & 0xFFU; // Logical Link ID
@ -212,7 +213,7 @@ void DataBlock::encode(uint8_t* data)
m_trellis.encode34(buffer, data); m_trellis.encode34(buffer, data);
} }
else if (m_fmt == PDU_FMT_UNCONFIRMED || m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) { else if (m_fmt == PDUFormatType::UNCONFIRMED || m_fmt == PDUFormatType::RSP || m_fmt == PDUFormatType::AMBT) {
uint8_t buffer[P25_PDU_UNCONFIRMED_LENGTH_BYTES]; uint8_t buffer[P25_PDU_UNCONFIRMED_LENGTH_BYTES];
::memset(buffer, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memset(buffer, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
@ -225,7 +226,7 @@ void DataBlock::encode(uint8_t* data)
m_trellis.encode12(buffer, data); m_trellis.encode12(buffer, data);
} }
else { else {
LogError(LOG_P25, "unknown FMT value in P25_DUID_PDU, fmt = $%02X", m_fmt); LogError(LOG_P25, "unknown FMT value in PDU, fmt = $%02X", m_fmt);
return; return;
} }
} }
@ -266,14 +267,14 @@ void DataBlock::setData(const uint8_t* buffer)
assert(buffer != nullptr); assert(buffer != nullptr);
assert(m_data != nullptr); assert(m_data != nullptr);
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDUFormatType::CONFIRMED) {
::memcpy(m_data, buffer, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); ::memcpy(m_data, buffer, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
} }
else if (m_fmt == PDU_FMT_UNCONFIRMED || m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) { else if (m_fmt == PDUFormatType::UNCONFIRMED || m_fmt == PDUFormatType::RSP || m_fmt == PDUFormatType::AMBT) {
::memcpy(m_data, buffer, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(m_data, buffer, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
} }
else { else {
LogError(LOG_P25, "unknown FMT value in P25_DUID_PDU, fmt = $%02X", m_fmt); LogError(LOG_P25, "unknown FMT value in PDU, fmt = $%02X", m_fmt);
} }
} }
@ -286,16 +287,16 @@ uint32_t DataBlock::getData(uint8_t* buffer) const
assert(buffer != nullptr); assert(buffer != nullptr);
assert(m_data != nullptr); assert(m_data != nullptr);
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDUFormatType::CONFIRMED) {
::memcpy(buffer, m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); ::memcpy(buffer, m_data, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES; return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES;
} }
else if (m_fmt == PDU_FMT_UNCONFIRMED || m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) { else if (m_fmt == PDUFormatType::UNCONFIRMED || m_fmt == PDUFormatType::RSP || m_fmt == PDUFormatType::AMBT) {
::memcpy(buffer, m_data, P25_PDU_UNCONFIRMED_LENGTH_BYTES); ::memcpy(buffer, m_data, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
return P25_PDU_UNCONFIRMED_LENGTH_BYTES; return P25_PDU_UNCONFIRMED_LENGTH_BYTES;
} }
else { else {
LogError(LOG_P25, "unknown FMT value in P25_DUID_PDU, fmt = $%02X", m_fmt); LogError(LOG_P25, "unknown FMT value in PDU, fmt = $%02X", m_fmt);
return 0U; return 0U;
} }
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2018,2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2018,2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -17,8 +17,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::data;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::data;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -43,9 +44,9 @@ bool DataHeader::m_warnCRC = false;
DataHeader::DataHeader() : DataHeader::DataHeader() :
m_ackNeeded(false), m_ackNeeded(false),
m_outbound(false), m_outbound(false),
m_fmt(PDU_FMT_CONFIRMED), m_fmt(PDUFormatType::CONFIRMED),
m_sap(0U), m_sap(0U),
m_mfId(P25_MFG_STANDARD), m_mfId(MFG_STANDARD),
m_llId(0U), m_llId(0U),
m_blocksToFollow(0U), m_blocksToFollow(0U),
m_padLength(0U), m_padLength(0U),
@ -56,8 +57,8 @@ DataHeader::DataHeader() :
m_lastFragment(true), m_lastFragment(true),
m_headerOffset(0U), m_headerOffset(0U),
m_srcLlId(0U), m_srcLlId(0U),
m_rspClass(PDU_ACK_CLASS_NACK), m_rspClass(PDUAckClass::NACK),
m_rspType(PDU_ACK_TYPE_NACK_ILLEGAL), m_rspType(PDUAckType::NACK_ILLEGAL),
m_rspStatus(0U), m_rspStatus(0U),
m_ambtOpcode(0U), m_ambtOpcode(0U),
m_ambtField8(0U), m_ambtField8(0U),
@ -136,12 +137,12 @@ bool DataHeader::decode(const uint8_t* data, bool noTrellis)
m_blocksToFollow = m_data[6U] & 0x7FU; // Block Frames to Follow m_blocksToFollow = m_data[6U] & 0x7FU; // Block Frames to Follow
m_padLength = m_data[7U] & 0x1FU; // Pad Byte Count m_padLength = m_data[7U] & 0x1FU; // Pad Byte Count
if (m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) { if (m_fmt == PDUFormatType::RSP || m_fmt == PDUFormatType::AMBT) {
m_padLength = 0U; m_padLength = 0U;
} }
switch (m_fmt) { switch (m_fmt) {
case PDU_FMT_CONFIRMED: case PDUFormatType::CONFIRMED:
m_S = (m_data[8U] & 0x80U) == 0x80U; // Re-synchronize Flag m_S = (m_data[8U] & 0x80U) == 0x80U; // Re-synchronize Flag
m_Ns = (m_data[8U] >> 4) & 0x07U; // Packet Sequence No. m_Ns = (m_data[8U] >> 4) & 0x07U; // Packet Sequence No.
@ -150,9 +151,9 @@ bool DataHeader::decode(const uint8_t* data, bool noTrellis)
m_headerOffset = m_data[9U] & 0x3FU; // Data Header Offset m_headerOffset = m_data[9U] & 0x3FU; // Data Header Offset
break; break;
case PDU_FMT_RSP: case PDUFormatType::RSP:
m_ackNeeded = false; m_ackNeeded = false;
m_sap = PDU_SAP_USER_DATA; m_sap = PDUSAP::USER_DATA;
m_rspClass = (m_data[1U] >> 6) & 0x03U; // Response Class m_rspClass = (m_data[1U] >> 6) & 0x03U; // Response Class
m_rspType = (m_data[1U] >> 3) & 0x07U; // Response Type m_rspType = (m_data[1U] >> 3) & 0x07U; // Response Type
m_rspStatus = m_data[1U] & 0x07U; // Response Status m_rspStatus = m_data[1U] & 0x07U; // Response Status
@ -160,12 +161,12 @@ bool DataHeader::decode(const uint8_t* data, bool noTrellis)
m_srcLlId = (m_data[7U] << 16) + (m_data[8U] << 8) + m_data[9U]; // Source Logical Link ID m_srcLlId = (m_data[7U] << 16) + (m_data[8U] << 8) + m_data[9U]; // Source Logical Link ID
} }
break; break;
case PDU_FMT_AMBT: case PDUFormatType::AMBT:
m_ambtOpcode = m_data[7U] & 0x3FU; // AMBT Opcode m_ambtOpcode = m_data[7U] & 0x3FU; // AMBT Opcode
m_ambtField8 = m_data[8U]; // AMBT Field 8 m_ambtField8 = m_data[8U]; // AMBT Field 8
m_ambtField9 = m_data[9U]; // AMBT Field 9 m_ambtField9 = m_data[9U]; // AMBT Field 9
// fall-thru // fall-thru
case PDU_FMT_UNCONFIRMED: case PDUFormatType::UNCONFIRMED:
default: default:
m_ackNeeded = false; m_ackNeeded = false;
m_S = false; m_S = false;
@ -190,12 +191,12 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
uint8_t header[P25_PDU_HEADER_LENGTH_BYTES]; uint8_t header[P25_PDU_HEADER_LENGTH_BYTES];
::memset(header, 0x00U, P25_PDU_HEADER_LENGTH_BYTES); ::memset(header, 0x00U, P25_PDU_HEADER_LENGTH_BYTES);
if (m_fmt == PDU_FMT_UNCONFIRMED || m_fmt == PDU_FMT_RSP) { if (m_fmt == PDUFormatType::UNCONFIRMED || m_fmt == PDUFormatType::RSP) {
m_ackNeeded = false; m_ackNeeded = false;
} }
if (m_fmt == PDU_FMT_CONFIRMED && !m_ackNeeded) { if (m_fmt == PDUFormatType::CONFIRMED && !m_ackNeeded) {
LogWarning(LOG_P25, "DataHeader::encode(), invalid values for PDU_FMT_CONFIRMED, ackNeeded = %u", m_ackNeeded); LogWarning(LOG_P25, "DataHeader::encode(), invalid values for confirmed PDU, ackNeeded = %u", m_ackNeeded);
m_ackNeeded = true; // force set this to true m_ackNeeded = true; // force set this to true
} }
@ -216,7 +217,7 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
(m_blocksToFollow & 0x7FU); // Blocks Frames to Follow (m_blocksToFollow & 0x7FU); // Blocks Frames to Follow
switch (m_fmt) { switch (m_fmt) {
case PDU_FMT_CONFIRMED: case PDUFormatType::CONFIRMED:
header[7U] = (m_padLength & 0x1FU); // Pad Byte Count header[7U] = (m_padLength & 0x1FU); // Pad Byte Count
header[8U] = (m_S ? 0x80U : 0x00U) + // Re-synchronize Flag header[8U] = (m_S ? 0x80U : 0x00U) + // Re-synchronize Flag
((m_Ns & 0x07U) << 4) + // Packet Sequence No. ((m_Ns & 0x07U) << 4) + // Packet Sequence No.
@ -225,7 +226,7 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
header[9U] = m_headerOffset & 0x3FU; // Data Header Offset header[9U] = m_headerOffset & 0x3FU; // Data Header Offset
break; break;
case PDU_FMT_RSP: case PDUFormatType::RSP:
header[1U] = ((m_rspClass & 0x03U) << 6) + // Response Class header[1U] = ((m_rspClass & 0x03U) << 6) + // Response Class
((m_rspType & 0x07U) << 3) + // Response Type ((m_rspType & 0x07U) << 3) + // Response Type
((m_rspStatus & 0x07U)); // Response Status ((m_rspStatus & 0x07U)); // Response Status
@ -235,12 +236,12 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
header[9U] = (m_srcLlId >> 0) & 0xFFU; header[9U] = (m_srcLlId >> 0) & 0xFFU;
} }
break; break;
case PDU_FMT_AMBT: case PDUFormatType::AMBT:
header[7U] = (m_ambtOpcode & 0x3FU); // AMBT Opcode header[7U] = (m_ambtOpcode & 0x3FU); // AMBT Opcode
header[8U] = m_ambtField8; // AMBT Field 8 header[8U] = m_ambtField8; // AMBT Field 8
header[9U] = m_ambtField9; // AMBT Field 9 header[9U] = m_ambtField9; // AMBT Field 9
break; break;
case PDU_FMT_UNCONFIRMED: case PDUFormatType::UNCONFIRMED:
default: default:
header[7U] = (m_padLength & 0x1FU); // Pad Byte Count header[7U] = (m_padLength & 0x1FU); // Pad Byte Count
header[8U] = 0x00U; header[8U] = 0x00U;
@ -271,10 +272,10 @@ void DataHeader::reset()
m_ackNeeded = false; m_ackNeeded = false;
m_outbound = false; m_outbound = false;
m_fmt = PDU_FMT_CONFIRMED; m_fmt = PDUFormatType::CONFIRMED;
m_sap = PDU_SAP_USER_DATA; m_sap = PDUSAP::USER_DATA;
m_mfId = P25_MFG_STANDARD; m_mfId = MFG_STANDARD;
m_llId = 0U; m_llId = 0U;
m_F = true; m_F = true;
@ -290,8 +291,8 @@ void DataHeader::reset()
m_headerOffset = 0U; m_headerOffset = 0U;
m_srcLlId = 0U; m_srcLlId = 0U;
m_rspClass = PDU_ACK_CLASS_NACK; m_rspClass = PDUAckClass::NACK;
m_rspType = PDU_ACK_TYPE_NACK_ILLEGAL; m_rspType = PDUAckType::NACK_ILLEGAL;
m_rspStatus = 0U; m_rspStatus = 0U;
m_ambtOpcode = 0U; m_ambtOpcode = 0U;
@ -307,7 +308,7 @@ void DataHeader::reset()
/// <returns></returns> /// <returns></returns>
uint32_t DataHeader::getPacketLength() const uint32_t DataHeader::getPacketLength() const
{ {
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDUFormatType::CONFIRMED) {
return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * m_blocksToFollow - 4 - m_padLength; return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES * m_blocksToFollow - 4 - m_padLength;
} }
else { else {
@ -336,7 +337,7 @@ uint32_t DataHeader::getData(uint8_t* buffer) const
uint32_t DataHeader::calculatePadLength(uint8_t fmt, uint32_t packetLength) uint32_t DataHeader::calculatePadLength(uint8_t fmt, uint32_t packetLength)
{ {
uint32_t len = packetLength + 4; uint32_t len = packetLength + 4;
if (fmt == PDU_FMT_CONFIRMED) { if (fmt == PDUFormatType::CONFIRMED) {
return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES - (len % P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); return P25_PDU_CONFIRMED_DATA_LENGTH_BYTES - (len % P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
} }
else { else {

@ -16,8 +16,8 @@
#include "p25/data/LowSpeedData.h" #include "p25/data/LowSpeedData.h"
#include "p25/P25Utils.h" #include "p25/P25Utils.h"
using namespace p25::data;
using namespace p25; using namespace p25;
using namespace p25::data;
#include <cassert> #include <cassert>

@ -10,93 +10,105 @@
* Copyright (C) 2022-2024 Bryan Biedenkapp, N2PLL * Copyright (C) 2022-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#if !defined(__P25_DFSI_DEFINES_H__) #if !defined(__DFSI_DEFINES_H__)
#define __P25_DFSI_DEFINES_H__ #define __DFSI_DEFINES_H__
#include "common/Defines.h" #include "common/Defines.h"
// Frame Type String(s) // Frame Type String(s)
#define P25_DFSI_SS_STR "P25_DFSI_START_STOP (Start/Stop)" #define P25_DFSI_SS_STR "P25, DFSI_START_STOP (Start/Stop)"
#define P25_DFSI_VHDR1_STR "P25_DFSI_VHDR1 (Voice Header 1)" #define P25_DFSI_VHDR1_STR "P25, DFSI_VHDR1 (Voice Header 1)"
#define P25_DFSI_VHDR2_STR "P25_DFSI_VHDR2 (Voice Header 2)" #define P25_DFSI_VHDR2_STR "P25, DFSI_VHDR2 (Voice Header 2)"
#define P25_DFSI_LDU1_STR "P25_DFSI_LDU1 (Logical Link Data Unit 1)" #define P25_DFSI_LDU1_STR "P25, DFSI_LDU1 (Logical Link Data Unit 1)"
#define P25_DFSI_LDU2_STR "P25_DFSI_LDU2 (Logical Link Data Unit 2)" #define P25_DFSI_LDU2_STR "P25, DFSI_LDU2 (Logical Link Data Unit 2)"
#define P25_DFSI_TSBK_STR "P25_DFSI_TSBK (Trunking System Block)" #define P25_DFSI_TSBK_STR "P25, DFSI_TSBK (Trunking System Block)"
// Shorthand macro to p25::dfsi::defines -- keeps source code that doesn't use "using" concise
#define P25DFSIDEF p25::dfsi::defines
namespace p25 namespace p25
{ {
namespace dfsi namespace dfsi
{ {
// --------------------------------------------------------------------------- namespace defines
// Constants {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Constants
const uint8_t P25_DFSI_STATUS_NO_ERROR = 0x00; // // ---------------------------------------------------------------------------
const uint8_t P25_DFSI_STATUS_ERASE = 0x02; //
const uint8_t DFSI_STATUS_NO_ERROR = 0x00U; //
const uint8_t P25_DFSI_RT_ENABLED = 0x02; // const uint8_t DFSI_STATUS_ERASE = 0x02U; //
const uint8_t P25_DFSI_RT_DISABLED = 0x04; //
const uint8_t DFSI_RT_ENABLED = 0x02U; //
const uint8_t P25_DFSI_START_FLAG = 0x0C; // const uint8_t DFSI_RT_DISABLED = 0x04U; //
const uint8_t P25_DFSI_STOP_FLAG = 0x25; //
const uint8_t DFSI_START_FLAG = 0x0CU; //
const uint8_t P25_DFSI_TYPE_DATA_PAYLOAD = 0x06; // const uint8_t DFSI_STOP_FLAG = 0x25U; //
const uint8_t P25_DFSI_TYPE_VOICE = 0x0B; //
const uint8_t DFSI_TYPE_DATA_PAYLOAD = 0x06U; //
const uint8_t P25_DFSI_DEF_ICW_SOURCE = 0x00; // Infrastructure Source - Default Source const uint8_t DFSI_TYPE_VOICE = 0x0BU; //
const uint8_t P25_DFSI_DEF_SOURCE = 0x00; //
const uint8_t DFSI_DEF_ICW_SOURCE = 0x00U; // Infrastructure Source - Default Source
const uint8_t P25_DFSI_MOT_START_STOP = 0x00; // Motorola Start/Stop Frame const uint8_t DFSI_DEF_SOURCE = 0x00U; //
const uint32_t P25_DFSI_VHDR_RAW_LEN = 36U; const uint32_t DFSI_VHDR_RAW_LEN = 36U;
const uint32_t P25_DFSI_VHDR_LEN = 27U; const uint32_t DFSI_VHDR_LEN = 27U;
const uint32_t P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES = 22U; const uint32_t DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES = 22U;
const uint32_t P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES = 14U; const uint32_t DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES = 14U;
const uint32_t P25_DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES = 16U; const uint32_t DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES = 16U;
const uint32_t P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES = 22U; const uint32_t DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES = 22U;
const uint32_t P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES = 14U; const uint32_t DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES = 14U;
const uint32_t P25_DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES = 17U; const uint32_t DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES = 17U;
const uint32_t P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES = 16U; const uint32_t DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES = 16U;
// Frame Type(s) /// <summary>
const uint8_t P25_DFSI_MOT_VHDR_1 = 0x60; // Motorola Voice Header 1 /// Frame Type
const uint8_t P25_DFSI_MOT_VHDR_2 = 0x61; // Motorola Voice Header 2 /// </summary>
namespace DFSIFrameType {
const uint8_t P25_DFSI_LDU1_VOICE1 = 0x62U; // IMBE LDU1 - Voice 1 // DFSI Frame Type
const uint8_t P25_DFSI_LDU1_VOICE2 = 0x63U; // IMBE LDU1 - Voice 2 enum E : uint8_t {
const uint8_t P25_DFSI_LDU1_VOICE3 = 0x64U; // IMBE LDU1 - Voice 3 + Link Control MOT_START_STOP = 0x00U, // Motorola Start/Stop
const uint8_t P25_DFSI_LDU1_VOICE4 = 0x65U; // IMBE LDU1 - Voice 4 + Link Control
const uint8_t P25_DFSI_LDU1_VOICE5 = 0x66U; // IMBE LDU1 - Voice 5 + Link Control MOT_VHDR_1 = 0x60U, // Motorola Voice Header 1
const uint8_t P25_DFSI_LDU1_VOICE6 = 0x67U; // IMBE LDU1 - Voice 6 + Link Control MOT_VHDR_2 = 0x61U, // Motorola Voice Header 2
const uint8_t P25_DFSI_LDU1_VOICE7 = 0x68U; // IMBE LDU1 - Voice 7 + Link Control
const uint8_t P25_DFSI_LDU1_VOICE8 = 0x69U; // IMBE LDU1 - Voice 8 + Link Control LDU1_VOICE1 = 0x62U, // IMBE LDU1 - Voice 1
const uint8_t P25_DFSI_LDU1_VOICE9 = 0x6AU; // IMBE LDU1 - Voice 9 + Low Speed Data LDU1_VOICE2 = 0x63U, // IMBE LDU1 - Voice 2
LDU1_VOICE3 = 0x64U, // IMBE LDU1 - Voice 3 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE10 = 0x6BU; // IMBE LDU2 - Voice 10 LDU1_VOICE4 = 0x65U, // IMBE LDU1 - Voice 4 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE11 = 0x6CU; // IMBE LDU2 - Voice 11 LDU1_VOICE5 = 0x66U, // IMBE LDU1 - Voice 5 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE12 = 0x6DU; // IMBE LDU2 - Voice 12 + Encryption Sync LDU1_VOICE6 = 0x67U, // IMBE LDU1 - Voice 6 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE13 = 0x6EU; // IMBE LDU2 - Voice 13 + Encryption Sync LDU1_VOICE7 = 0x68U, // IMBE LDU1 - Voice 7 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE14 = 0x6FU; // IMBE LDU2 - Voice 14 + Encryption Sync LDU1_VOICE8 = 0x69U, // IMBE LDU1 - Voice 8 + Link Control
const uint8_t P25_DFSI_LDU2_VOICE15 = 0x70U; // IMBE LDU2 - Voice 15 + Encryption Sync LDU1_VOICE9 = 0x6AU, // IMBE LDU1 - Voice 9 + Low Speed Data
const uint8_t P25_DFSI_LDU2_VOICE16 = 0x71U; // IMBE LDU2 - Voice 16 + Encryption Sync
const uint8_t P25_DFSI_LDU2_VOICE17 = 0x72U; // IMBE LDU2 - Voice 17 + Encryption Sync LDU2_VOICE10 = 0x6BU, // IMBE LDU2 - Voice 10
const uint8_t P25_DFSI_LDU2_VOICE18 = 0x73U; // IMBE LDU2 - Voice 18 + Low Speed Data LDU2_VOICE11 = 0x6CU, // IMBE LDU2 - Voice 11
LDU2_VOICE12 = 0x6DU, // IMBE LDU2 - Voice 12 + Encryption Sync
const uint8_t P25_DFSI_TSBK = 0xA1U; // TSBK LDU2_VOICE13 = 0x6EU, // IMBE LDU2 - Voice 13 + Encryption Sync
LDU2_VOICE14 = 0x6FU, // IMBE LDU2 - Voice 14 + Encryption Sync
LDU2_VOICE15 = 0x70U, // IMBE LDU2 - Voice 15 + Encryption Sync
LDU2_VOICE16 = 0x71U, // IMBE LDU2 - Voice 16 + Encryption Sync
LDU2_VOICE17 = 0x72U, // IMBE LDU2 - Voice 17 + Encryption Sync
LDU2_VOICE18 = 0x73U, // IMBE LDU2 - Voice 18 + Low Speed Data
TSBK = 0xA1U // TSBK
};
}
} // namespace defines
} // namespace dfsi } // namespace dfsi
} // namespace p25 } // namespace p25
#endif // __P25_DFSI_DEFINES_H__ #endif // __DFSI_DEFINES_H__

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -17,8 +17,10 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::dfsi;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::dfsi;
using namespace p25::dfsi::defines;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -37,8 +39,8 @@ LC::LC() :
m_rs(), m_rs(),
m_mi(nullptr) m_mi(nullptr)
{ {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
m_control = new lc::LC(); m_control = new lc::LC();
m_lsd = new data::LowSpeedData(); m_lsd = new data::LowSpeedData();
@ -118,7 +120,7 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU1_VOICE1: case DFSIFrameType::LDU1_VOICE1:
{ {
if (m_control != nullptr) { if (m_control != nullptr) {
delete m_control; delete m_control;
@ -130,15 +132,15 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
} }
m_rssi = data[6U]; // RSSI m_rssi = data[6U]; // RSSI
::memcpy(imbe, data + 10U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 10U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE2: case DFSIFrameType::LDU1_VOICE2:
{ {
::memcpy(imbe, data + 1U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 1U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE3: case DFSIFrameType::LDU1_VOICE3:
{ {
m_control->setLCO(data[1U]); // LCO m_control->setLCO(data[1U]); // LCO
m_control->setMFId(data[2U]); // MFId m_control->setMFId(data[2U]); // MFId
@ -146,48 +148,48 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
m_control->setEmergency((serviceOptions & 0x80U) == 0x80U); m_control->setEmergency((serviceOptions & 0x80U) == 0x80U);
m_control->setEncrypted((serviceOptions & 0x40U) == 0x40U); m_control->setEncrypted((serviceOptions & 0x40U) == 0x40U);
m_control->setPriority((serviceOptions & 0x07U)); m_control->setPriority((serviceOptions & 0x07U));
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE4: case DFSIFrameType::LDU1_VOICE4:
{ {
uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0); uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
m_control->setDstId(dstId); // Talkgroup Address m_control->setDstId(dstId); // Talkgroup Address
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE5: case DFSIFrameType::LDU1_VOICE5:
{ {
uint32_t srcId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0); uint32_t srcId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
m_control->setSrcId(srcId); // Source Address m_control->setSrcId(srcId); // Source Address
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE6: case DFSIFrameType::LDU1_VOICE6:
{ {
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE7: case DFSIFrameType::LDU1_VOICE7:
{ {
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE8: case DFSIFrameType::LDU1_VOICE8:
{ {
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE9: case DFSIFrameType::LDU1_VOICE9:
{ {
m_lsd->setLSD1(data[1U]); // LSD MSB m_lsd->setLSD1(data[1U]); // LSD MSB
m_lsd->setLSD2(data[2U]); // LSD LSB m_lsd->setLSD2(data[2U]); // LSD LSB
::memcpy(imbe, data + 4U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 4U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
default: default:
{ {
LogError(LOG_P25, "LC::decodeLDU1(), invalid frametype, frameType = $%02X", m_frameType); LogError(LOG_P25, "LC::decodeLDU1(), invalid frame type, frameType = $%02X", m_frameType);
return false; return false;
} }
break; break;
@ -213,39 +215,39 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
(m_control->getPriority() & 0x07U); (m_control->getPriority() & 0x07U);
// determine the LDU1 DFSI frame length, its variable // determine the LDU1 DFSI frame length, its variable
uint32_t frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; uint32_t frameLength = DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU1_VOICE1: case DFSIFrameType::LDU1_VOICE1:
frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE2: case DFSIFrameType::LDU1_VOICE2:
frameLength = P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE3: case DFSIFrameType::LDU1_VOICE3:
frameLength = P25_DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE4: case DFSIFrameType::LDU1_VOICE4:
frameLength = P25_DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE5: case DFSIFrameType::LDU1_VOICE5:
frameLength = P25_DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE6: case DFSIFrameType::LDU1_VOICE6:
frameLength = P25_DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE7: case DFSIFrameType::LDU1_VOICE7:
frameLength = P25_DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE8: case DFSIFrameType::LDU1_VOICE8:
frameLength = P25_DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE9: case DFSIFrameType::LDU1_VOICE9:
frameLength = P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
break; break;
default: default:
{ {
LogError(LOG_P25, "LC::encodeLDU1(), invalid frametype, frameType = $%02X", m_frameType); LogError(LOG_P25, "LC::encodeLDU1(), invalid frame type, frameType = $%02X", m_frameType);
return; return;
} }
break; break;
@ -276,72 +278,72 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU1_VOICE2: case DFSIFrameType::LDU1_VOICE2:
{ {
::memcpy(dfsiFrame + 1U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 1U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE3: case DFSIFrameType::LDU1_VOICE3:
{ {
dfsiFrame[1U] = rs[0U]; // LCO dfsiFrame[1U] = rs[0U]; // LCO
dfsiFrame[2U] = rs[1U]; // MFId dfsiFrame[2U] = rs[1U]; // MFId
dfsiFrame[3U] = rs[2U]; // Service Options dfsiFrame[3U] = rs[2U]; // Service Options
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE4: case DFSIFrameType::LDU1_VOICE4:
{ {
dfsiFrame[1U] = rs[3U]; // Target Address dfsiFrame[1U] = rs[3U]; // Target Address
dfsiFrame[2U] = rs[4U]; dfsiFrame[2U] = rs[4U];
dfsiFrame[3U] = rs[5U]; dfsiFrame[3U] = rs[5U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE5: case DFSIFrameType::LDU1_VOICE5:
{ {
dfsiFrame[1U] = rs[6U]; // Source Address dfsiFrame[1U] = rs[6U]; // Source Address
dfsiFrame[2U] = rs[7U]; dfsiFrame[2U] = rs[7U];
dfsiFrame[3U] = rs[8U]; dfsiFrame[3U] = rs[8U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE6: case DFSIFrameType::LDU1_VOICE6:
{ {
dfsiFrame[1U] = rs[9U]; // RS (24,12,13) dfsiFrame[1U] = rs[9U]; // RS (24,12,13)
dfsiFrame[2U] = rs[10U]; // RS (24,12,13) dfsiFrame[2U] = rs[10U]; // RS (24,12,13)
dfsiFrame[3U] = rs[11U]; // RS (24,12,13) dfsiFrame[3U] = rs[11U]; // RS (24,12,13)
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE7: case DFSIFrameType::LDU1_VOICE7:
{ {
dfsiFrame[1U] = rs[12U]; // RS (24,12,13) dfsiFrame[1U] = rs[12U]; // RS (24,12,13)
dfsiFrame[2U] = rs[13U]; // RS (24,12,13) dfsiFrame[2U] = rs[13U]; // RS (24,12,13)
dfsiFrame[3U] = rs[14U]; // RS (24,12,13) dfsiFrame[3U] = rs[14U]; // RS (24,12,13)
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE8: case DFSIFrameType::LDU1_VOICE8:
{ {
dfsiFrame[1U] = rs[15U]; // RS (24,12,13) dfsiFrame[1U] = rs[15U]; // RS (24,12,13)
dfsiFrame[2U] = rs[16U]; // RS (24,12,13) dfsiFrame[2U] = rs[16U]; // RS (24,12,13)
dfsiFrame[3U] = rs[17U]; // RS (24,12,13) dfsiFrame[3U] = rs[17U]; // RS (24,12,13)
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE9: case DFSIFrameType::LDU1_VOICE9:
{ {
dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB
dfsiFrame[2U] = m_lsd->getLSD2(); // LSD LSB dfsiFrame[2U] = m_lsd->getLSD2(); // LSD LSB
::memcpy(dfsiFrame + 4U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 4U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU1_VOICE1: case DFSIFrameType::LDU1_VOICE1:
default: default:
{ {
dfsiFrame[6U] = m_rssi; // RSSI dfsiFrame[6U] = m_rssi; // RSSI
::memcpy(dfsiFrame + 10U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 10U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
} }
@ -371,76 +373,76 @@ bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe)
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU2_VOICE10: case DFSIFrameType::LDU2_VOICE10:
{ {
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
if (m_lsd != nullptr) { if (m_lsd != nullptr) {
delete m_lsd; delete m_lsd;
} }
m_lsd = new data::LowSpeedData(); m_lsd = new data::LowSpeedData();
m_rssi = data[6U]; // RSSI m_rssi = data[6U]; // RSSI
::memcpy(imbe, data + 10U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 10U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE11: case DFSIFrameType::LDU2_VOICE11:
{ {
::memcpy(imbe, data + 1U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 1U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE12: case DFSIFrameType::LDU2_VOICE12:
{ {
m_mi[0U] = data[1U]; // Message Indicator m_mi[0U] = data[1U]; // Message Indicator
m_mi[1U] = data[2U]; m_mi[1U] = data[2U];
m_mi[2U] = data[3U]; m_mi[2U] = data[3U];
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE13: case DFSIFrameType::LDU2_VOICE13:
{ {
m_mi[3U] = data[1U]; // Message Indicator m_mi[3U] = data[1U]; // Message Indicator
m_mi[4U] = data[2U]; m_mi[4U] = data[2U];
m_mi[5U] = data[3U]; m_mi[5U] = data[3U];
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE14: case DFSIFrameType::LDU2_VOICE14:
{ {
m_mi[6U] = data[1U]; // Message Indicator m_mi[6U] = data[1U]; // Message Indicator
m_mi[7U] = data[2U]; m_mi[7U] = data[2U];
m_mi[8U] = data[3U]; m_mi[8U] = data[3U];
m_control->setMI(m_mi); m_control->setMI(m_mi);
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE15: case DFSIFrameType::LDU2_VOICE15:
{ {
m_control->setAlgId(data[1U]); // Algorithm ID m_control->setAlgId(data[1U]); // Algorithm ID
uint32_t kid = (data[2U] << 8) | (data[3U] << 0); // Key ID uint32_t kid = (data[2U] << 8) | (data[3U] << 0); // Key ID
m_control->setKId(kid); m_control->setKId(kid);
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE16: case DFSIFrameType::LDU2_VOICE16:
{ {
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE17: case DFSIFrameType::LDU2_VOICE17:
{ {
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE18: case DFSIFrameType::LDU2_VOICE18:
{ {
m_lsd->setLSD1(data[1U]); // LSD MSB m_lsd->setLSD1(data[1U]); // LSD MSB
m_lsd->setLSD2(data[2U]); // LSD LSB m_lsd->setLSD2(data[2U]); // LSD LSB
::memcpy(imbe, data + 4U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(imbe, data + 4U, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
default: default:
{ {
LogError(LOG_P25, "LC::decodeLDU2(), invalid frametype, frameType = $%02X", m_frameType); LogError(LOG_P25, "LC::decodeLDU2(), invalid frame type, frameType = $%02X", m_frameType);
return false; return false;
} }
break; break;
@ -461,44 +463,44 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
assert(m_control != nullptr); assert(m_control != nullptr);
// generate MI data // generate MI data
uint8_t mi[P25_MI_LENGTH_BYTES]; uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(mi, 0x00U, MI_LENGTH_BYTES);
m_control->getMI(mi); m_control->getMI(mi);
// determine the LDU2 DFSI frame length, its variable // determine the LDU2 DFSI frame length, its variable
uint32_t frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; uint32_t frameLength = DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU2_VOICE10: case DFSIFrameType::LDU2_VOICE10:
frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE11: case DFSIFrameType::LDU2_VOICE11:
frameLength = P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE12: case DFSIFrameType::LDU2_VOICE12:
frameLength = P25_DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE13: case DFSIFrameType::LDU2_VOICE13:
frameLength = P25_DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE14: case DFSIFrameType::LDU2_VOICE14:
frameLength = P25_DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE15: case DFSIFrameType::LDU2_VOICE15:
frameLength = P25_DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE16: case DFSIFrameType::LDU2_VOICE16:
frameLength = P25_DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE17: case DFSIFrameType::LDU2_VOICE17:
frameLength = P25_DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE18: case DFSIFrameType::LDU2_VOICE18:
frameLength = P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES; frameLength = DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
break; break;
default: default:
{ {
LogError(LOG_P25, "LC::encodeLDU2(), invalid frametype, frameType = $%02X", m_frameType); LogError(LOG_P25, "LC::encodeLDU2(), invalid frame type, frameType = $%02X", m_frameType);
return; return;
} }
break; break;
@ -507,7 +509,7 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
uint8_t rs[P25_LDU_LC_FEC_LENGTH_BYTES]; uint8_t rs[P25_LDU_LC_FEC_LENGTH_BYTES];
::memset(rs, 0x00U, P25_LDU_LC_FEC_LENGTH_BYTES); ::memset(rs, 0x00U, P25_LDU_LC_FEC_LENGTH_BYTES);
for (uint32_t i = 0; i < P25_MI_LENGTH_BYTES; i++) for (uint32_t i = 0; i < MI_LENGTH_BYTES; i++)
rs[i] = mi[i]; // Message Indicator rs[i] = mi[i]; // Message Indicator
rs[9U] = m_control->getAlgId(); // Algorithm ID rs[9U] = m_control->getAlgId(); // Algorithm ID
@ -524,72 +526,72 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU2_VOICE11: case DFSIFrameType::LDU2_VOICE11:
{ {
::memcpy(dfsiFrame + 1U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 1U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE12: case DFSIFrameType::LDU2_VOICE12:
{ {
dfsiFrame[1U] = rs[0U]; // Message Indicator dfsiFrame[1U] = rs[0U]; // Message Indicator
dfsiFrame[2U] = rs[1U]; dfsiFrame[2U] = rs[1U];
dfsiFrame[3U] = rs[2U]; dfsiFrame[3U] = rs[2U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE13: case DFSIFrameType::LDU2_VOICE13:
{ {
dfsiFrame[1U] = rs[3U]; // Message Indicator dfsiFrame[1U] = rs[3U]; // Message Indicator
dfsiFrame[2U] = rs[4U]; dfsiFrame[2U] = rs[4U];
dfsiFrame[3U] = rs[5U]; dfsiFrame[3U] = rs[5U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE14: case DFSIFrameType::LDU2_VOICE14:
{ {
dfsiFrame[1U] = rs[6U]; // Message Indicator dfsiFrame[1U] = rs[6U]; // Message Indicator
dfsiFrame[2U] = rs[7U]; dfsiFrame[2U] = rs[7U];
dfsiFrame[3U] = rs[8U]; dfsiFrame[3U] = rs[8U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE15: case DFSIFrameType::LDU2_VOICE15:
{ {
dfsiFrame[1U] = rs[9U]; // Algorithm ID dfsiFrame[1U] = rs[9U]; // Algorithm ID
dfsiFrame[2U] = rs[10U]; // Key ID dfsiFrame[2U] = rs[10U]; // Key ID
dfsiFrame[3U] = rs[11U]; dfsiFrame[3U] = rs[11U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE16: case DFSIFrameType::LDU2_VOICE16:
{ {
dfsiFrame[1U] = rs[12U]; // RS (24,16,9) dfsiFrame[1U] = rs[12U]; // RS (24,16,9)
dfsiFrame[2U] = rs[13U]; // RS (24,16,9) dfsiFrame[2U] = rs[13U]; // RS (24,16,9)
dfsiFrame[3U] = rs[14U]; // RS (24,16,9) dfsiFrame[3U] = rs[14U]; // RS (24,16,9)
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE17: case DFSIFrameType::LDU2_VOICE17:
{ {
dfsiFrame[1U] = rs[15U]; // RS (24,16,9) dfsiFrame[1U] = rs[15U]; // RS (24,16,9)
dfsiFrame[2U] = rs[16U]; // RS (24,16,9) dfsiFrame[2U] = rs[16U]; // RS (24,16,9)
dfsiFrame[3U] = rs[17U]; // RS (24,16,9) dfsiFrame[3U] = rs[17U]; // RS (24,16,9)
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE18: case DFSIFrameType::LDU2_VOICE18:
{ {
dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB
dfsiFrame[2U] = m_lsd->getLSD2(); // LSD LSB dfsiFrame[2U] = m_lsd->getLSD2(); // LSD LSB
::memcpy(dfsiFrame + 4U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 4U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
case P25_DFSI_LDU2_VOICE10: case DFSIFrameType::LDU2_VOICE10:
default: default:
{ {
dfsiFrame[6U] = m_rssi; // RSSI dfsiFrame[6U] = m_rssi; // RSSI
::memcpy(dfsiFrame + 10U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE ::memcpy(dfsiFrame + 10U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
} }
break; break;
} }
@ -621,8 +623,8 @@ void LC::copy(const LC& data)
delete[] m_mi; delete[] m_mi;
uint8_t* mi = new uint8_t[P25_MI_LENGTH_BYTES]; uint8_t* mi = new uint8_t[MI_LENGTH_BYTES];
::memcpy(mi, data.m_mi, P25_MI_LENGTH_BYTES); ::memcpy(mi, data.m_mi, MI_LENGTH_BYTES);
m_mi = mi; m_mi = mi;
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -17,8 +17,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cassert> #include <cassert>
@ -101,7 +102,7 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo
assert(blocks != nullptr); assert(blocks != nullptr);
assert(pduUserData != nullptr); assert(pduUserData != nullptr);
if (dataHeader.getFormat() != PDU_FMT_AMBT) { if (dataHeader.getFormat() != PDUFormatType::AMBT) {
LogError(LOG_P25, "AMBT::decode(), PDU is not a AMBT PDU"); LogError(LOG_P25, "AMBT::decode(), PDU is not a AMBT PDU");
return false; return false;
} }
@ -150,11 +151,11 @@ void AMBT::encode(data::DataHeader& dataHeader, uint8_t* pduUserData)
{ {
assert(pduUserData != nullptr); assert(pduUserData != nullptr);
dataHeader.setFormat(PDU_FMT_AMBT); dataHeader.setFormat(PDUFormatType::AMBT);
dataHeader.setMFId(m_mfId); // Mfg Id. dataHeader.setMFId(m_mfId); // Mfg Id.
dataHeader.setAckNeeded(false); dataHeader.setAckNeeded(false);
dataHeader.setOutbound(true); dataHeader.setOutbound(true);
dataHeader.setSAP(PDU_SAP_TRUNK_CTRL); dataHeader.setSAP(PDUSAP::TRUNK_CTRL);
dataHeader.setLLId(m_srcId); dataHeader.setLLId(m_srcId);
dataHeader.setFullMessage(true); dataHeader.setFullMessage(true);

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2016,2017 Jonathan Naylor, G4KLX * Copyright (C) 2016,2017 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -21,8 +21,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
@ -41,24 +42,23 @@ SiteData LC::m_siteData = SiteData();
/// <summary> /// <summary>
/// Initializes a new instance of the LC class. /// Initializes a new instance of the LC class.
/// </summary> /// </summary>
/// <param name="siteData"></param>
LC::LC() : LC::LC() :
m_protect(false), m_protect(false),
m_lco(LC_GROUP), m_lco(LCO::GROUP),
m_mfId(P25_MFG_STANDARD), m_mfId(MFG_STANDARD),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_grpVchNo(0U), m_grpVchNo(0U),
m_grpVchNoB(0U), m_grpVchNoB(0U),
m_dstIdB(0U), m_dstIdB(0U),
m_explicitId(false), m_explicitId(false),
m_netId(P25_WACN_STD_DEFAULT), m_netId(WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT), m_sysId(SID_STD_DEFAULT),
m_emergency(false), m_emergency(false),
m_encrypted(false), m_encrypted(false),
m_priority(4U), m_priority(4U),
m_group(true), m_group(true),
m_algId(P25_ALGO_UNENCRYPT), m_algId(ALGO_UNENCRYPT),
m_kId(0U), m_kId(0U),
m_rs(), m_rs(),
m_encryptOverride(false), m_encryptOverride(false),
@ -67,8 +67,8 @@ LC::LC() :
m_rsValue(0U), m_rsValue(0U),
m_mi(nullptr) m_mi(nullptr)
{ {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
} }
/// <summary> /// <summary>
@ -145,10 +145,10 @@ bool LC::decodeHDU(const uint8_t* data)
m_mfId = rs[9U]; // Mfg Id. m_mfId = rs[9U]; // Mfg Id.
m_algId = rs[10U]; // Algorithm ID m_algId = rs[10U]; // Algorithm ID
if (m_algId != P25_ALGO_UNENCRYPT) { if (m_algId != ALGO_UNENCRYPT) {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
::memcpy(m_mi, rs, P25_MI_LENGTH_BYTES); // Message Indicator ::memcpy(m_mi, rs, MI_LENGTH_BYTES); // Message Indicator
m_kId = (rs[11U] << 8) + rs[12U]; // Key ID m_kId = (rs[11U] << 8) + rs[12U]; // Key ID
if (!m_encrypted) { if (!m_encrypted) {
@ -157,8 +157,8 @@ bool LC::decodeHDU(const uint8_t* data)
} }
} }
else { else {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
m_kId = 0x0000U; m_kId = 0x0000U;
if (m_encrypted) { if (m_encrypted) {
@ -191,7 +191,7 @@ void LC::encodeHDU(uint8_t* data)
uint8_t rs[P25_HDU_LENGTH_BYTES]; uint8_t rs[P25_HDU_LENGTH_BYTES];
::memset(rs, 0x00U, P25_HDU_LENGTH_BYTES); ::memset(rs, 0x00U, P25_HDU_LENGTH_BYTES);
for (uint32_t i = 0; i < P25_MI_LENGTH_BYTES; i++) for (uint32_t i = 0; i < MI_LENGTH_BYTES; i++)
rs[i] = m_mi[i]; // Message Indicator rs[i] = m_mi[i]; // Message Indicator
rs[9U] = m_mfId; // Mfg Id. rs[9U] = m_mfId; // Mfg Id.
@ -383,10 +383,10 @@ bool LC::decodeLDU2(const uint8_t* data)
#endif #endif
m_algId = rs[9U]; // Algorithm ID m_algId = rs[9U]; // Algorithm ID
if (m_algId != P25_ALGO_UNENCRYPT) { if (m_algId != ALGO_UNENCRYPT) {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
::memcpy(m_mi, rs, P25_MI_LENGTH_BYTES); // Message Indicator ::memcpy(m_mi, rs, MI_LENGTH_BYTES); // Message Indicator
m_kId = (rs[10U] << 8) + rs[11U]; // Key ID m_kId = (rs[10U] << 8) + rs[11U]; // Key ID
if (!m_encrypted) { if (!m_encrypted) {
@ -395,8 +395,8 @@ bool LC::decodeLDU2(const uint8_t* data)
} }
} }
else { else {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
m_kId = 0x0000U; m_kId = 0x0000U;
if (m_encrypted) { if (m_encrypted) {
@ -420,7 +420,7 @@ void LC::encodeLDU2(uint8_t* data)
uint8_t rs[P25_LDU_LC_FEC_LENGTH_BYTES]; uint8_t rs[P25_LDU_LC_FEC_LENGTH_BYTES];
::memset(rs, 0x00U, P25_LDU_LC_FEC_LENGTH_BYTES); ::memset(rs, 0x00U, P25_LDU_LC_FEC_LENGTH_BYTES);
for (uint32_t i = 0; i < P25_MI_LENGTH_BYTES; i++) for (uint32_t i = 0; i < MI_LENGTH_BYTES; i++)
rs[i] = m_mi[i]; // Message Indicator rs[i] = m_mi[i]; // Message Indicator
rs[9U] = m_algId; // Algorithm ID rs[9U] = m_algId; // Algorithm ID
@ -470,7 +470,7 @@ void LC::setMI(const uint8_t* mi)
{ {
assert(mi != nullptr); assert(mi != nullptr);
::memcpy(m_mi, mi, P25_MI_LENGTH_BYTES); ::memcpy(m_mi, mi, MI_LENGTH_BYTES);
} }
/// <summary>Gets the encryption message indicator.</summary> /// <summary>Gets the encryption message indicator.</summary>
@ -479,7 +479,7 @@ void LC::getMI(uint8_t* mi) const
{ {
assert(mi != nullptr); assert(mi != nullptr);
::memcpy(mi, m_mi, P25_MI_LENGTH_BYTES); ::memcpy(mi, m_mi, MI_LENGTH_BYTES);
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -519,11 +519,11 @@ void LC::copy(const LC& data)
m_rsValue = data.m_rsValue; m_rsValue = data.m_rsValue;
m_algId = data.m_algId; m_algId = data.m_algId;
if (m_algId != P25_ALGO_UNENCRYPT) { if (m_algId != ALGO_UNENCRYPT) {
delete[] m_mi; delete[] m_mi;
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memcpy(m_mi, data.m_mi, P25_MI_LENGTH_BYTES); ::memcpy(m_mi, data.m_mi, MI_LENGTH_BYTES);
m_kId = data.m_kId; m_kId = data.m_kId;
if (!m_encrypted) { if (!m_encrypted) {
@ -534,8 +534,8 @@ void LC::copy(const LC& data)
else { else {
delete[] m_mi; delete[] m_mi;
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); ::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
m_kId = 0x0000U; m_kId = 0x0000U;
if (m_encrypted) { if (m_encrypted) {
@ -572,14 +572,14 @@ bool LC::decodeLC(const uint8_t* rs)
m_mfId = rs[1U]; // Mfg Id. m_mfId = rs[1U]; // Mfg Id.
// non-standard P25 vendor opcodes (these are just detected for passthru) // non-standard P25 vendor opcodes (these are just detected for passthru)
if ((m_mfId != P25_MFG_STANDARD) && (m_mfId != P25_MFG_STANDARD_ALT)) { if ((m_mfId != MFG_STANDARD) && (m_mfId != MFG_STANDARD_ALT)) {
m_rsValue = rsValue; m_rsValue = rsValue;
return true; return true;
} }
// standard P25 reference opcodes // standard P25 reference opcodes
switch (m_lco) { switch (m_lco) {
case LC_GROUP: case LCO::GROUP:
m_mfId = rs[1U]; // Mfg Id. m_mfId = rs[1U]; // Mfg Id.
m_group = true; m_group = true;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
@ -591,7 +591,7 @@ bool LC::decodeLC(const uint8_t* rs)
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
break; break;
case LC_PRIVATE: case LCO::PRIVATE:
m_mfId = rs[1U]; // Mfg Id. m_mfId = rs[1U]; // Mfg Id.
m_group = false; m_group = false;
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
@ -602,7 +602,7 @@ bool LC::decodeLC(const uint8_t* rs)
m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
break; break;
case LC_TEL_INT_VCH_USER: case LCO::TEL_INT_VCH_USER:
m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag
if (!m_encryptOverride) { if (!m_encryptOverride) {
m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag
@ -613,7 +613,7 @@ bool LC::decodeLC(const uint8_t* rs)
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address
} }
break; break;
case LC_EXPLICIT_SOURCE_ID: case LCO::EXPLICIT_SOURCE_ID:
m_netId = (uint32_t)((rsValue >> 36) & 0xFFFFFU); // Network ID m_netId = (uint32_t)((rsValue >> 36) & 0xFFFFFU); // Network ID
m_sysId = (uint32_t)((rsValue >> 24) & 0xFFFU); // System ID m_sysId = (uint32_t)((rsValue >> 24) & 0xFFFU); // System ID
m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address
@ -642,7 +642,7 @@ void LC::encodeLC(uint8_t* rs)
// standard P25 reference opcodes // standard P25 reference opcodes
switch (m_lco) { switch (m_lco) {
case LC_GROUP: case LCO::GROUP:
rsValue = m_mfId; rsValue = m_mfId;
rsValue = (rsValue << 8) + rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
@ -651,7 +651,7 @@ void LC::encodeLC(uint8_t* rs)
rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
break; break;
case LC_GROUP_UPDT: case LCO::GROUP_UPDT:
rs[0U] |= 0x40U; // Implicit Operation rs[0U] |= 0x40U; // Implicit Operation
rsValue = m_siteData.channelId(); // Group A - Channel ID rsValue = m_siteData.channelId(); // Group A - Channel ID
rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number
@ -660,7 +660,7 @@ void LC::encodeLC(uint8_t* rs)
rsValue = (rsValue << 12) + m_grpVchNoB; // Group B - Channel Number rsValue = (rsValue << 12) + m_grpVchNoB; // Group B - Channel Number
rsValue = (rsValue << 16) + m_dstIdB; // Group B - Talkgroup Address rsValue = (rsValue << 16) + m_dstIdB; // Group B - Talkgroup Address
break; break;
case LC_PRIVATE: case LCO::PRIVATE:
rsValue = m_mfId; rsValue = m_mfId;
rsValue = (rsValue << 8) + rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
@ -669,7 +669,7 @@ void LC::encodeLC(uint8_t* rs)
rsValue = (rsValue << 24) + m_dstId; // Target Radio Address rsValue = (rsValue << 24) + m_dstId; // Target Radio Address
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
break; break;
case LC_TEL_INT_VCH_USER: case LCO::TEL_INT_VCH_USER:
rs[0U] |= 0x40U; // Implicit Operation rs[0U] |= 0x40U; // Implicit Operation
rsValue = (rsValue << 8) + rsValue = (rsValue << 8) +
(m_emergency ? 0x80U : 0x00U) + // Emergency Flag (m_emergency ? 0x80U : 0x00U) + // Emergency Flag
@ -678,12 +678,12 @@ void LC::encodeLC(uint8_t* rs)
rsValue = (rsValue << 16) + m_callTimer; // Call Timer rsValue = (rsValue << 16) + m_callTimer; // Call Timer
rsValue = (rsValue << 24) + m_srcId; // Source/Target Radio Address rsValue = (rsValue << 24) + m_srcId; // Source/Target Radio Address
break; break;
case LC_EXPLICIT_SOURCE_ID: case LCO::EXPLICIT_SOURCE_ID:
rsValue = m_netId; // Network ID rsValue = m_netId; // Network ID
rsValue = (rsValue << 12) + (m_sysId & 0xFFFU); // System ID rsValue = (rsValue << 12) + (m_sysId & 0xFFFU); // System ID
rsValue = (rsValue << 24) + m_srcId; // Source Radio Address rsValue = (rsValue << 24) + m_srcId; // Source Radio Address
break; break;
case LC_RFSS_STS_BCAST: case LCO::RFSS_STS_BCAST:
rs[0U] |= 0x40U; // Implicit Operation rs[0U] |= 0x40U; // Implicit Operation
rsValue = m_siteData.lra(); // Location Registration Area rsValue = m_siteData.lra(); // Location Registration Area
rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID
@ -699,7 +699,7 @@ void LC::encodeLC(uint8_t* rs)
} }
// non-standard P25 vendor opcodes (these are just detected for passthru) // non-standard P25 vendor opcodes (these are just detected for passthru)
if ((m_mfId != P25_MFG_STANDARD) && (m_mfId != P25_MFG_STANDARD_ALT)) { if ((m_mfId != MFG_STANDARD) && (m_mfId != MFG_STANDARD_ALT)) {
rsValue = 0U; rsValue = 0U;
rsValue = m_rsValue; rsValue = m_rsValue;
} }

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -18,8 +18,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@ -74,8 +75,8 @@ TDULC::TDULC(LC* lc) : TDULC()
/// </summary> /// </summary>
TDULC::TDULC() : TDULC::TDULC() :
m_protect(false), m_protect(false),
m_lco(LC_GROUP), m_lco(LCO::GROUP),
m_mfId(P25_MFG_STANDARD), m_mfId(MFG_STANDARD),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_grpVchNo(0U), m_grpVchNo(0U),

@ -7,7 +7,7 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2017-2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2017-2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
@ -18,8 +18,9 @@
#include "Log.h" #include "Log.h"
#include "Utils.h" #include "Utils.h"
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cassert> #include <cassert>
@ -76,17 +77,17 @@ TSBK::TSBK(LC* lc) : TSBK()
/// <remarks>This should never be used.</remarks> /// <remarks>This should never be used.</remarks>
TSBK::TSBK() : TSBK::TSBK() :
m_protect(false), m_protect(false),
m_lco(LC_GROUP), m_lco(TSBKO::IOSP_GRP_VCH),
m_mfId(P25_MFG_STANDARD), m_mfId(MFG_STANDARD),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_lastBlock(false), m_lastBlock(false),
m_aivFlag(true), m_aivFlag(true),
m_extendedAddrFlag(false), m_extendedAddrFlag(false),
m_service(0U), m_service(0U),
m_response(P25_RSP_ACCEPT), m_response(ResponseCode::ACCEPT),
m_netId(P25_WACN_STD_DEFAULT), m_netId(WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT), m_sysId(SID_STD_DEFAULT),
m_grpVchId(0U), m_grpVchId(0U),
m_grpVchNo(0U), m_grpVchNo(0U),
m_emergency(false), m_emergency(false),
@ -99,8 +100,8 @@ TSBK::TSBK() :
m_raw(nullptr) m_raw(nullptr)
{ {
if (m_siteCallsign == nullptr) { if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES]; m_siteCallsign = new uint8_t[MOT_CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x00U, MOT_CALLSIGN_LENGTH_BYTES);
} }
#if FORCE_TSBK_CRC_WARN #if FORCE_TSBK_CRC_WARN
@ -124,7 +125,7 @@ TSBK::~TSBK()
/// <returns></returns> /// <returns></returns>
std::string TSBK::toString(bool isp) std::string TSBK::toString(bool isp)
{ {
return std::string("TSBK_IOSP_UNKWN (Unknown TSBK)"); return std::string("TSBKO, UNKNOWN (Unknown TSBK)");
} }
/// <summary> /// <summary>
@ -144,16 +145,16 @@ uint8_t* TSBK::getDecodedRaw() const
void TSBK::setCallsign(std::string callsign) void TSBK::setCallsign(std::string callsign)
{ {
if (m_siteCallsign == nullptr) { if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES]; m_siteCallsign = new uint8_t[MOT_CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x00U, MOT_CALLSIGN_LENGTH_BYTES);
} }
uint32_t idLength = callsign.length(); uint32_t idLength = callsign.length();
if (idLength > 0) { if (idLength > 0) {
::memset(m_siteCallsign, 0x20U, P25_MOT_CALLSIGN_LENGTH_BYTES); ::memset(m_siteCallsign, 0x20U, MOT_CALLSIGN_LENGTH_BYTES);
if (idLength > P25_MOT_CALLSIGN_LENGTH_BYTES) if (idLength > MOT_CALLSIGN_LENGTH_BYTES)
idLength = P25_MOT_CALLSIGN_LENGTH_BYTES; idLength = MOT_CALLSIGN_LENGTH_BYTES;
for (uint32_t i = 0; i < idLength; i++) for (uint32_t i = 0; i < idLength; i++)
m_siteCallsign[i] = callsign[i]; m_siteCallsign[i] = callsign[i];
} }

@ -7,16 +7,17 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_ADJ_STS_BCAST.h" #include "p25/lc/tdulc/LC_ADJ_STS_BCAST.h"
#include "Log.h" #include "Log.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,15 +29,15 @@ using namespace p25;
/// Initializes a new instance of the LC_ADJ_STS_BCAST class. /// Initializes a new instance of the LC_ADJ_STS_BCAST class.
/// </summary> /// </summary>
LC_ADJ_STS_BCAST::LC_ADJ_STS_BCAST() : TDULC(), LC_ADJ_STS_BCAST::LC_ADJ_STS_BCAST() : TDULC(),
m_adjCFVA(P25_CFVA_FAILURE), m_adjCFVA(CFVA::FAILURE),
m_adjSysId(0U), m_adjSysId(0U),
m_adjRfssId(0U), m_adjRfssId(0U),
m_adjSiteId(0U), m_adjSiteId(0U),
m_adjChannelId(0U), m_adjChannelId(0U),
m_adjChannelNo(0U), m_adjChannelNo(0U),
m_adjServiceClass(P25_SVC_CLS_INVALID) m_adjServiceClass(ServiceClass::INVALID)
{ {
m_lco = p25::LC_ADJ_STS_BCAST; m_lco = LCO::ADJ_STS_BCAST;
} }
/// <summary> /// <summary>
@ -79,7 +80,7 @@ void LC_ADJ_STS_BCAST::encode(uint8_t* data)
rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class
} }
else { else {
LogError(LOG_P25, "LC_ADJ_STS_BCAST::encodeLC(), invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X", LogError(LOG_P25, "LC_ADJ_STS_BCAST::encodeLC(), invalid values for LC_ADJ_STS_BCAST, adjSiteRFSSId = $%02X, adjSiteId = $%02X, adjSiteChannel = $%02X",
m_adjRfssId, m_adjSiteId, m_adjChannelNo); m_adjRfssId, m_adjSiteId, m_adjChannelNo);
return; // blatantly ignore creating this TSBK return; // blatantly ignore creating this TSBK
} }

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_CALL_TERM.h" #include "p25/lc/tdulc/LC_CALL_TERM.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_CALL_TERM::LC_CALL_TERM() : TDULC() LC_CALL_TERM::LC_CALL_TERM() : TDULC()
{ {
m_lco = p25::LC_CALL_TERM; m_lco = LCO::CALL_TERM;
} }
/// <summary> /// <summary>
@ -58,7 +59,7 @@ void LC_CALL_TERM::encode(uint8_t* data)
m_implicit = true; m_implicit = true;
rsValue = 0U; rsValue = 0U;
rsValue = (rsValue << 24) + P25_WUID_FNE; // System Radio Address rsValue = (rsValue << 24) + WUID_FNE; // System Radio Address
std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue); std::unique_ptr<uint8_t[]> rs = TDULC::fromValue(rsValue);
TDULC::encode(data, rs.get()); TDULC::encode(data, rs.get());

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_CONV_FALLBACK.h" #include "p25/lc/tdulc/LC_CONV_FALLBACK.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_CONV_FALLBACK::LC_CONV_FALLBACK() : TDULC() LC_CONV_FALLBACK::LC_CONV_FALLBACK() : TDULC()
{ {
m_lco = p25::LC_CONV_FALLBACK; m_lco = LCO::CONV_FALLBACK;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2023 Bryan Biedenkapp, N2PLL * Copyright (C) 2023,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_FAILSOFT.h" #include "p25/lc/tdulc/LC_FAILSOFT.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,8 +29,8 @@ using namespace p25;
/// </summary> /// </summary>
LC_FAILSOFT::LC_FAILSOFT() : TDULC() LC_FAILSOFT::LC_FAILSOFT() : TDULC()
{ {
m_lco = p25::LC_FAILSOFT; m_lco = LCO::FAILSOFT;
m_mfId = p25::P25_MFG_MOT; m_mfId = MFG_MOT;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_GROUP.h" #include "p25/lc/tdulc/LC_GROUP.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_GROUP::LC_GROUP() : TDULC() LC_GROUP::LC_GROUP() : TDULC()
{ {
m_lco = p25::LC_GROUP; m_lco = LCO::GROUP;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_GROUP_UPDT.h" #include "p25/lc/tdulc/LC_GROUP_UPDT.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_GROUP_UPDT::LC_GROUP_UPDT() : TDULC() LC_GROUP_UPDT::LC_GROUP_UPDT() : TDULC()
{ {
m_lco = p25::LC_GROUP_UPDT; m_lco = LCO::GROUP_UPDT;
} }
/// <summary> /// <summary>

@ -7,16 +7,17 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_IDEN_UP.h" #include "p25/lc/tdulc/LC_IDEN_UP.h"
#include "Log.h" #include "Log.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
@ -30,7 +31,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_IDEN_UP::LC_IDEN_UP() : TDULC() LC_IDEN_UP::LC_IDEN_UP() : TDULC()
{ {
m_lco = p25::LC_IDEN_UP; m_lco = LCO::IDEN_UP;
} }
/// <summary> /// <summary>
@ -70,7 +71,7 @@ void LC_IDEN_UP::encode(uint8_t* data)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ... uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5); uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5);
uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K; uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? IDEN_UP_VU_BW_125K : IDEN_UP_VU_BW_625K;
rsValue = m_siteIdenEntry.channelId(); // Channel ID rsValue = m_siteIdenEntry.channelId(); // Channel ID
rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_NET_STS_BCAST.h" #include "p25/lc/tdulc/LC_NET_STS_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_NET_STS_BCAST::LC_NET_STS_BCAST() : TDULC() LC_NET_STS_BCAST::LC_NET_STS_BCAST() : TDULC()
{ {
m_lco = p25::LC_NET_STS_BCAST; m_lco = LCO::NET_STS_BCAST;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_PRIVATE.h" #include "p25/lc/tdulc/LC_PRIVATE.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_PRIVATE::LC_PRIVATE() : TDULC() LC_PRIVATE::LC_PRIVATE() : TDULC()
{ {
m_lco = p25::LC_PRIVATE; m_lco = LCO::PRIVATE;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_RFSS_STS_BCAST.h" #include "p25/lc/tdulc/LC_RFSS_STS_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_RFSS_STS_BCAST::LC_RFSS_STS_BCAST() : TDULC() LC_RFSS_STS_BCAST::LC_RFSS_STS_BCAST() : TDULC()
{ {
m_lco = p25::LC_RFSS_STS_BCAST; m_lco = LCO::RFSS_STS_BCAST;
} }
/// <summary> /// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_SYS_SRV_BCAST.h" #include "p25/lc/tdulc/LC_SYS_SRV_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_SYS_SRV_BCAST::LC_SYS_SRV_BCAST() : TDULC() LC_SYS_SRV_BCAST::LC_SYS_SRV_BCAST() : TDULC()
{ {
m_lco = p25::LC_SYS_SRV_BCAST; m_lco = LCO::SYS_SRV_BCAST;
} }
/// <summary> /// <summary>
@ -53,7 +54,7 @@ void LC_SYS_SRV_BCAST::encode(uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; const uint32_t services = (m_siteData.netActive()) ? SystemService::NET_ACTIVE : 0U | SYS_SRV_DEFAULT;
ulong64_t rsValue = 0U; ulong64_t rsValue = 0U;

@ -7,15 +7,16 @@
* @package DVM / Common Library * @package DVM / Common Library
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) * @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
* *
* Copyright (C) 2022 Bryan Biedenkapp, N2PLL * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL
* *
*/ */
#include "Defines.h" #include "Defines.h"
#include "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h" #include "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25; using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert> #include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary> /// </summary>
LC_TEL_INT_VCH_USER::LC_TEL_INT_VCH_USER() : TDULC() LC_TEL_INT_VCH_USER::LC_TEL_INT_VCH_USER() : TDULC()
{ {
m_lco = p25::LC_TEL_INT_VCH_USER; m_lco = LCO::TEL_INT_VCH_USER;
} }
/// <summary> /// <summary>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save

Powered by TurnKey Linux.