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_MINOR "01"
#define VERSION_REV "A"
#define VERSION_REV "B"
#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__

@ -17,300 +17,408 @@
#include "common/Defines.h"
// Shorthand macro to dmr::defines -- keeps source code that doesn't use "using" concise
#define DMRDEF dmr::defines
namespace dmr
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
namespace defines
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
const uint32_t DMR_FRAME_LENGTH_BITS = 264U;
const uint32_t DMR_FRAME_LENGTH_BYTES = 33U;
const uint32_t DMR_FRAME_LENGTH_BITS = 264U;
const uint32_t DMR_FRAME_LENGTH_BYTES = 33U;
const uint32_t DMR_SYNC_LENGTH_BITS = 48U;
const uint32_t DMR_SYNC_LENGTH_BYTES = 6U;
const uint32_t DMR_SYNC_LENGTH_BITS = 48U;
const uint32_t DMR_SYNC_LENGTH_BYTES = 6U;
const uint32_t DMR_EMB_LENGTH_BITS = 8U;
const uint32_t DMR_EMB_LENGTH_BYTES = 1U;
const uint32_t DMR_EMB_LENGTH_BITS = 8U;
const uint32_t DMR_EMB_LENGTH_BYTES = 1U;
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_BITS = 8U;
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_BYTES = 4U;
const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BITS = 32U;
const uint32_t DMR_EMBEDDED_SIGNALLING_LENGTH_BYTES = 4U;
const uint32_t DMR_AMBE_LENGTH_BITS = 108U * 2U;
const uint32_t DMR_AMBE_LENGTH_BYTES = 27U;
const uint32_t DMR_AMBE_LENGTH_BITS = 108U * 2U;
const uint32_t DMR_AMBE_LENGTH_BYTES = 27U;
const uint32_t DMR_LC_HEADER_LENGTH_BYTES = 12U;
const uint32_t DMR_CSBK_LENGTH_BYTES = 12U;
const uint32_t DMR_LC_HEADER_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_DATA_SYNC[] = { 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U };
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 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 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_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 DMR_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 SYNC_MASK[] = { 0x0FU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xF0U };
// The PR FILL and Data Sync pattern.
const uint8_t DMR_IDLE_DATA[] = { 0x01U, 0x00U,
0x53U, 0xC2U, 0x5EU, 0xABU, 0xA8U, 0x67U, 0x1DU, 0xC7U, 0x38U, 0x3BU, 0xD9U,
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U };
// A silence frame only
const uint8_t DMR_SILENCE_DATA[] = { 0x01U, 0x00U,
0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU, 0xB9U, 0xE8U,
0x81U, 0x52U, 0x60U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x73U, 0x00U,
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 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 VOICE_LC_HEADER_CRC_MASK[] = { 0x96U, 0x96U, 0x96U };
const uint8_t TERMINATOR_WITH_LC_CRC_MASK[] = { 0x99U, 0x99U, 0x99U };
const uint8_t PI_HEADER_CRC_MASK[] = { 0x69U, 0x69U };
const uint8_t DATA_HEADER_CRC_MASK[] = { 0xCCU, 0xCCU };
const uint8_t CSBK_CRC_MASK[] = { 0xA5U, 0xA5U };
const uint8_t CSBK_MBC_CRC_MASK[] = { 0xAAU, 0xAAU };
const uint16_t TSCC_MAX_CSC_CNT = 511U;
const uint32_t DMR_SLOT_TIME = 60U;
const uint32_t AMBE_PER_SLOT = 3U;
const uint8_t DT_MASK = 0x0FU;
const uint8_t DMR_IDLE_RX = 0x80U;
const uint8_t DMR_SYNC_DATA = 0x40U;
const uint8_t DMR_SYNC_VOICE = 0x20U;
const uint8_t DMR_SLOT1 = 0x00U;
const uint8_t DMR_SLOT2 = 0x80U;
const uint32_t DMR_MAX_PDU_COUNT = 32U;
const uint32_t DMR_MAX_PDU_LENGTH = 512U;
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 uint8_t DMR_ALOHA_VER_151 = 0x00U;
const uint8_t DMR_CHNULL = 0x00U;
const uint16_t DMR_LOGICAL_CH_ABSOLUTE = 0xFFFU;
const uint8_t DEFAULT_NRAND_WAIT = 8U;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 21U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 2U;
const uint32_t MAX_DMR_VOICE_ERRORS = 141U;
const uint32_t DMR_WUID_SUPLI = 0xFFFEC4U;
const uint32_t DMR_WUID_SDMI = 0xFFFEC5U;
const uint32_t DMR_WUID_REGI = 0xFFFEC6U;
const uint32_t DMR_WUID_STUNI = 0xFFFECCU;
const uint32_t DMR_WUID_AUTHI = 0xFFFECDU;
const uint32_t DMR_WUID_KILLI = 0xFFFECFU;
const uint32_t DMR_WUID_TATTSI = 0xFFFED7U;
const uint32_t DMR_WUID_ALL = 0xFFFFFFU;
// PDU Data Formats
const uint8_t DPF_UDT = 0x00U;
const uint8_t DPF_RESPONSE = 0x01U;
const uint8_t DPF_UNCONFIRMED_DATA = 0x02U;
const uint8_t DPF_CONFIRMED_DATA = 0x03U;
const uint8_t DPF_DEFINED_SHORT = 0x0DU;
const uint8_t DPF_DEFINED_RAW = 0x0EU;
const uint8_t DPF_PROPRIETARY = 0x0FU;
// PDU ACK Class
const uint8_t PDU_ACK_CLASS_ACK = 0x00U;
const uint8_t PDU_ACK_CLASS_NACK = 0x01U;
const uint8_t PDU_ACK_CLASS_ACK_RETRY = 0x02U;
// PDU ACK Type(s)
const uint8_t PDU_ACK_TYPE_ACK = 0x01U;
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_UNDELIVERABLE = 0x04U;// Undeliverable
// Feature IDs
const uint8_t FID_ETSI = 0x00U; // ETSI Standard Feature Set
const uint8_t FID_DMRA = 0x10U; //
const uint8_t FID_OCS_DVM = 0x9CU; // FID used for internal signalling; Omaha Communication Systems, LLC ($9C)
// LC Service Options
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t LC_SVC_OPT_PRIVACY = 0x40U;
const uint8_t LC_SVC_OPT_BCAST = 0x08U;
const uint8_t LC_SVC_OPT_OVCM = 0x04U;
// Call Priorities
const uint8_t CALL_PRIORITY_NONE = 0x00U;
const uint8_t CALL_PRIORITY_1 = 0x01U;
const uint8_t CALL_PRIORITY_2 = 0x02U;
const uint8_t CALL_PRIORITY_3 = 0x03U;
// FID_DMRA Extended Function Opcodes
const uint32_t DMR_EXT_FNCT_CHECK = 0x0000U; // Radio Check
const uint32_t DMR_EXT_FNCT_UNINHIBIT = 0x007EU; // Radio Uninhibit
const uint32_t DMR_EXT_FNCT_INHIBIT = 0x007FU; // Radio Inhibit
const uint32_t DMR_EXT_FNCT_CHECK_ACK = 0x0080U; // Radio Check Ack
const uint32_t DMR_EXT_FNCT_UNINHIBIT_ACK = 0x00FEU; // Radio Uninhibit Ack
const uint32_t DMR_EXT_FNCT_INHIBIT_ACK = 0x00FFU; // Radio Inhibit Ack
// 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)"
const uint8_t DT_VOICE_LC_HEADER = 0x01U;
#define DMR_DT_VOICE_LC_HEADER "DMR_DT_VOICE_LC_HEADER (Voice Header with Link Control)"
const uint8_t DT_TERMINATOR_WITH_LC = 0x02U;
#define DMR_DT_TERMINATOR_WITH_LC "DMR_DT_TERMINATOR_WITH_LC (Terminator with Link Control)"
const uint8_t DT_CSBK = 0x03U;
const uint8_t DT_MBC_HEADER = 0x04U;
const uint8_t DT_MBC_DATA = 0x05U;
const uint8_t DT_DATA_HEADER = 0x06U;
#define DMR_DT_DATA_HEADER "DMR_DT_DATA_HEADER (Data Header)"
const uint8_t DT_RATE_12_DATA = 0x07U;
#define DMR_DT_RATE_12_DATA "DMR_DT_RATE_12_DATA (1/2-rate Data)"
const uint8_t DT_RATE_34_DATA = 0x08U;
#define DMR_DT_RATE_34_DATA "DMR_DT_RATE_34_DATA (3/4-rate Data)"
const uint8_t DT_IDLE = 0x09U;
const uint8_t DT_RATE_1_DATA = 0x0AU;
#define DMR_DT_RATE_1_DATA "DMR_DT_RATE_1_DATA (1-rate Data)"
/*
** Internal Data Type(s)
*/
const uint8_t DT_VOICE_SYNC = 0xF0U;
#define DMR_DT_VOICE_SYNC "DMR_DT_VOICE_SYNC (Voice Data with Sync)"
const uint8_t DT_VOICE = 0xF1U;
#define DMR_DT_VOICE "DMR_DT_VOICE (Voice Data)"
// Site Models
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;
// Target Address
const uint8_t TGT_ADRS_SYSCODE = 0x00U;
const uint8_t TGT_ADRS_TGID = 0x01U;
// Short-Link Control Opcode(s)
const uint8_t SLCO_NULL = 0x00U;
const uint8_t SLCO_ACT = 0x01U;
const uint8_t SLCO_TSCC = 0x02U;
const uint8_t SLCO_PAYLOAD = 0x03U;
// Reason Code(s)
const uint8_t TS_ACK_RSN_MSG = 0x60U; // TS - Message Accepted
const uint8_t TS_ACK_RSN_REG = 0x62U; // TS - Registration Accepted
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
const uint8_t TS_DENY_RSN_SYS_UNSUPPORTED_SVC = 0x20U;
const uint8_t TS_DENY_RSN_PERM_USER_REFUSED = 0x21U;
const uint8_t TS_DENY_RSN_TEMP_USER_REFUSED = 0x22U;
const uint8_t TS_DENY_RSN_TRSN_SYS_REFUSED = 0x23U;
const uint8_t TS_DENY_RSN_TGT_NOT_REG = 0x24U;
const uint8_t TS_DENY_RSN_TGT_UNAVAILABLE = 0x25U;
const uint8_t TS_DENY_RSN_SYS_BUSY = 0x27U;
const uint8_t TS_DENY_RSN_SYS_NOT_READY = 0x28U;
const uint8_t TS_DENY_RSN_CALL_CNCL_REFUSED = 0x29U;
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;
const uint8_t TS_DENY_RSN_TGT_GROUP_NOT_VALID = 0x2FU;
const uint8_t TS_QUEUED_RSN_NO_RESOURCE = 0xA0U;
const uint8_t TS_QUEUED_RSN_SYS_BUSY = 0xA1U;
const uint8_t TS_WAIT_RSN = 0xE0U;
const uint8_t MS_DENY_RSN_UNSUPPORTED_SVC = 0x00U;
// Random Access Service Kind
const uint8_t SVC_KIND_IND_VOICE_CALL = 0x00U; // Individual Voice Call
const uint8_t SVC_KIND_GRP_VOICE_CALL = 0x01U; // Group Voice Call
const uint8_t SVC_KIND_IND_DATA_CALL = 0x02U; // Individual Data Call
const uint8_t SVC_KIND_GRP_DATA_CALL = 0x03U; // Group Data Call
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
const uint8_t SVC_KIND_UDT_SHORT_POLL = 0x06U; // UDT Short Data Polling Service
const uint8_t SVC_KIND_STATUS_TRANSPORT = 0x07U; // Status Transport Service
const uint8_t SVC_KIND_CALL_DIVERSION = 0x08U; // Call Diversion Service
const uint8_t SVC_KIND_CALL_ANSWER = 0x09U; // Call Answer Service
const uint8_t SVC_KIND_SUPPLEMENTARY_SVC = 0x0DU; // Supplementary Service
const uint8_t SVC_KIND_REG_SVC = 0x0EU; // Registration Service
const uint8_t SVC_KIND_CANCEL_CALL = 0x0FU; // Cancel Call Service
// Broadcast Announcement 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
const uint8_t BCAST_ANNC_LOCAL_TIME = 0x03U; // Broadcast Local Time
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
// Full-Link Control Opcode(s)
const uint8_t FLCO_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User
const uint8_t FLCO_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User
const uint8_t FLCO_TALKER_ALIAS_HEADER = 0x04U; //
const uint8_t FLCO_TALKER_ALIAS_BLOCK1 = 0x05U; //
const uint8_t FLCO_TALKER_ALIAS_BLOCK2 = 0x06U; //
const uint8_t FLCO_TALKER_ALIAS_BLOCK3 = 0x07U; //
const uint8_t FLCO_GPS_INFO = 0x08U; //
// Control Signalling Block Opcode(s)
const uint8_t CSBKO_NONE = 0x00U; //
const uint8_t CSBKO_UU_V_REQ = 0x04U; // UU VCH REQ - Unit-to-Unit Voice Channel Request
const uint8_t CSBKO_UU_ANS_RSP = 0x05U; // UU ANS RSP - Unit-to-Unit Answer Response
const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK
const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDU for Random Access
const uint8_t CSBKO_AHOY = 0x1CU; // AHOY - Enquiry from TSCC
const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response
const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function
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
const uint8_t CSBKO_PV_GRANT = 0x30U; // PV_GRANT - Private Voice Channel Grant
const uint8_t CSBKO_TV_GRANT = 0x31U; // TV_GRANT - Talkgroup Voice Channel Grant
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
const uint8_t CSBKO_TD_GRANT = 0x34U; // TD_GRANT - Talkgroup Data Channel Grant
const uint8_t CSBKO_BSDWNACT = 0x38U; // BS DWN ACT - BS Outbound Activation
const uint8_t CSBKO_PRECCSBK = 0x3DU; // PRE CSBK - Preamble CSBK
const uint8_t CSBKO_DVM_GIT_HASH = 0x3FU; //
const uint8_t TALKER_ID_NONE = 0x00U;
const uint8_t TALKER_ID_HEADER = 0x01U;
const uint8_t TALKER_ID_BLOCK1 = 0x02U;
const uint8_t TALKER_ID_BLOCK2 = 0x04U;
const uint8_t TALKER_ID_BLOCK3 = 0x08U;
const uint32_t NO_HEADERS_SIMPLEX = 8U;
const uint32_t NO_HEADERS_DUPLEX = 3U;
const uint32_t NO_PREAMBLE_CSBK = 15U;
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 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_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 MS_DATA_SYNC_BYTES[] = { 0x0DU, 0x5DU, 0x7FU, 0x77U, 0xFDU, 0x75U, 0x70U };
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 };
// The PR FILL and Data Sync pattern.
const uint8_t IDLE_DATA[] = { 0x01U, 0x00U,
0x53U, 0xC2U, 0x5EU, 0xABU, 0xA8U, 0x67U, 0x1DU, 0xC7U, 0x38U, 0x3BU, 0xD9U,
0x36U, 0x00U, 0x0DU, 0xFFU, 0x57U, 0xD7U, 0x5DU, 0xF5U, 0xD0U, 0x03U, 0xF6U,
0xE4U, 0x65U, 0x17U, 0x1BU, 0x48U, 0xCAU, 0x6DU, 0x4FU, 0xC6U, 0x10U, 0xB4U };
// A silence frame only
const uint8_t SILENCE_DATA[] = { 0x01U, 0x00U,
0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU, 0xB9U, 0xE8U,
0x81U, 0x52U, 0x60U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U, 0x73U, 0x00U,
0x2AU, 0x6BU, 0xB9U, 0xE8U, 0x81U, 0x52U, 0x61U, 0x73U, 0x00U, 0x2AU, 0x6BU };
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_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 TERMINATOR_WITH_LC_CRC_MASK[] = { 0x99U, 0x99U, 0x99U };
const uint8_t PI_HEADER_CRC_MASK[] = { 0x69U, 0x69U };
const uint8_t DATA_HEADER_CRC_MASK[] = { 0xCCU, 0xCCU };
const uint8_t CSBK_CRC_MASK[] = { 0xA5U, 0xA5U };
const uint8_t CSBK_MBC_CRC_MASK[] = { 0xAAU, 0xAAU };
const uint8_t DT_MASK = 0x0FU;
const uint8_t IDLE_RX = 0x80U;
const uint8_t SYNC_DATA = 0x40U;
const uint8_t SYNC_VOICE = 0x20U;
const uint8_t SLOT1 = 0x00U;
const uint8_t SLOT2 = 0x80U;
const uint32_t MAX_PDU_COUNT = 32U;
const uint32_t MAX_PDU_LENGTH = 512U;
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
/** Thresholds */
const uint16_t TSCC_MAX_CSC_CNT = 511U;
const uint32_t DMR_SLOT_TIME = 60U;
const uint32_t AMBE_PER_SLOT = 3U;
const uint8_t DEFAULT_NRAND_WAIT = 8U;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 21U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 2U;
const uint32_t MAX_DMR_VOICE_ERRORS = 141U;
/** Default Values */
const uint8_t DMR_ALOHA_VER_151 = 0x00U;
const uint8_t DMR_CHNULL = 0x00U;
const uint16_t DMR_LOGICAL_CH_ABSOLUTE = 0xFFFU;
const uint32_t WUID_SUPLI = 0xFFFEC4U; // Supplementary Data Service Working Unit ID
const uint32_t WUID_SDMI = 0xFFFEC5U; // UDT Short Data Service Working Unit ID
const uint32_t WUID_REGI = 0xFFFEC6U; // Registration Working Unit ID
const uint32_t WUID_STUNI = 0xFFFECCU; // MS Stun/Revive Identifier
const uint32_t WUID_AUTHI = 0xFFFECDU; // Authentication Working Unit ID
const uint32_t WUID_KILLI = 0xFFFECFU; // MS Kill Identifier
const uint32_t WUID_TATTSI = 0xFFFED7U; // Talkgroup Subscription/Attachement Service Working Unit ID
const uint32_t WUID_ALLL = 0xFFFFFDU; // All-call Site-wide Working Unit ID
const uint32_t WUID_ALLZ = 0xFFFFFEU; // All-call System-wide Working Unit ID
const uint32_t WUID_ALL = 0xFFFFFFU; // All-call Network-wide Working Unit ID
const uint32_t NO_HEADERS_SIMPLEX = 8U;
const uint32_t NO_HEADERS_DUPLEX = 3U;
const uint32_t NO_PREAMBLE_CSBK = 15U;
/// <summary>
/// Data Packet Format
/// </summary>
namespace DPF {
// Data Packet Format Enumeration
enum E : uint8_t {
UDT = 0x00U, // Unified Data Transport Header
RESPONSE = 0x01U, // Response Data Header
UNCONFIRMED_DATA = 0x02U, // Unconfirmed Data Header
CONFIRMED_DATA = 0x03U, // Confirmed Data Header
DEFINED_SHORT = 0x0DU, // Defined Short Data Header
DEFINED_RAW = 0x0EU, // Defined Raw Data Header
PROPRIETARY = 0x0FU, // Proprietary
};
};
/// <summary>
/// Data Response Class
/// </summary>
namespace PDUResponseClass {
enum : uint8_t {
ACK = 0x00U, // Acknowledge
NACK = 0x01U, // Negative Acknowledge
ACK_RETRY = 0x02U // Acknowlege Retry
};
};
/// <summary>
/// Data Response Type
/// </summary>
namespace PDUResponseType {
enum : uint8_t {
ACK = 0x01U, // Acknowledge
NACK_ILLEGAL = 0x00U, // Illegal Format
NACK_PACKET_CRC = 0x01U, // Packet CRC
NACK_MEMORY_FULL = 0x02U, // Memory Full
NACK_UNDELIVERABLE = 0x04U // Undeliverable
};
};
/** Feature IDs */
const uint8_t FID_ETSI = 0x00U; // ETSI Standard Feature Set
const uint8_t FID_DMRA = 0x10U; // Motorola
const uint8_t FID_DVM_OCS = 0x9CU; // DVM; Omaha Communication Systems, LLC ($9C)
/** LC Service Options */
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t LC_SVC_OPT_PRIVACY = 0x40U;
const uint8_t LC_SVC_OPT_BCAST = 0x08U;
const uint8_t LC_SVC_OPT_OVCM = 0x04U;
/** Call Priorities */
const uint8_t CALL_PRIORITY_NONE = 0x00U;
const uint8_t CALL_PRIORITY_1 = 0x01U;
const uint8_t CALL_PRIORITY_2 = 0x02U;
const uint8_t CALL_PRIORITY_3 = 0x03U;
/// <summary>
/// Short-Link Control Opcode(s)
/// </summary>
namespace SLCO {
// Short-Link Control Opcode Enumeration
enum E : uint8_t {
NONE = 0x00U, // NULL
ACT = 0x01U, //
TSCC = 0x02U, // TSCC
PAYLOAD = 0x03U // Payload
};
}
/// <summary>
/// Full-Link Control Opcode(s)
/// </summary>
namespace FLCO {
// Full-Link Control Opcode Enumeration
enum E : uint8_t {
GROUP = 0x00U, // GRP VCH USER - Group Voice Channel User
PRIVATE = 0x03U, // UU VCH USER - Unit-to-Unit Voice Channel User
TALKER_ALIAS_HEADER = 0x04U, //
TALKER_ALIAS_BLOCK1 = 0x05U, //
TALKER_ALIAS_BLOCK2 = 0x06U, //
TALKER_ALIAS_BLOCK3 = 0x07U, //
GPS_INFO = 0x08U, //
};
}
/// <summary>
/// FID_DMRA Extended Functions.
/// </summary>
namespace ExtendedFunctions {
enum : uint16_t {
CHECK = 0x0000U, // Radio Check
UNINHIBIT = 0x007EU, // Radio Uninhibit
INHIBIT = 0x007FU, // Radio Inhibit
CHECK_ACK = 0x0080U, // Radio Check Ack
UNINHIBIT_ACK = 0x00FEU, // Radio Uninhibit Ack
INHIBIT_ACK = 0x00FFU // Radio Inhibit Ack
};
};
/// <summary>
/// Data Type(s)
/// <summary>
namespace DataType {
// Data Type Enumeration
enum E : uint8_t {
VOICE_PI_HEADER = 0x00U, // Voice with Privacy Indicator Header
VOICE_LC_HEADER = 0x01U, // Voice with Link Control Header
TERMINATOR_WITH_LC = 0x02U, // Terminator with Link Control
CSBK = 0x03U, // CSBK
MBC_HEADER = 0x04U, // Multi-Block Control Header
MBC_DATA = 0x05U, // Multi-Block Control Data
DATA_HEADER = 0x06U, // Data Header
RATE_12_DATA = 0x07U, // 1/2 Rate Data
RATE_34_DATA = 0x08U, // 3/4 Rate Data
IDLE = 0x09U, // Idle
RATE_1_DATA = 0x0AU, // Rate 1 Data
/*
** Internal Data Type(s)
*/
VOICE_SYNC = 0xF0U, // Internal - Voice Sync
VOICE = 0xF1U // Internal - Voice
};
}
#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)"
#define DMR_DT_TERMINATOR_WITH_LC "DMR, TERMINATOR_WITH_LC (Terminator with Link Control)"
#define DMR_DT_DATA_HEADER "DMR, DATA_HEADER (Data Header)"
#define DMR_DT_RATE_12_DATA "DMR, RATE_12_DATA (1/2-rate Data)"
#define DMR_DT_RATE_34_DATA "DMR, RATE_34_DATA (3/4-rate Data)"
#define DMR_DT_RATE_1_DATA "DMR, RATE_1_DATA (1-rate Data)"
#define DMR_DT_VOICE_SYNC "DMR, VOICE_SYNC (Voice Data with Sync)"
#define DMR_DT_VOICE "DMR, VOICE (Voice Data)"
/// <summary>
/// Site Models
/// </summary>
namespace SiteModel {
// Site Model Enumeration
enum E : uint8_t {
TINY = 0x00U, // Tiny
SMALL = 0x01U, // Small
LARGE = 0x02U, // Large
HUGE = 0x03U // Huge
};
}
// Target Address
const uint8_t TGT_ADRS_SYSCODE = 0x00U;
const uint8_t TGT_ADRS_TGID = 0x01U;
/// <summary>
/// Talker ID
/// <summary>
namespace TalkerID {
enum : uint8_t {
NONE = 0x00U, // No Talker ID
HEADER = 0x01U, // Talker ID Header
BLOCK1 = 0x02U, // Talker ID Block 1
BLOCK2 = 0x04U, // Talker ID Block 2
BLOCK3 = 0x08U // Talker ID Block 3
};
}
/// <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
#endif // __DMR_DEFINES_H__

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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__)
@ -26,6 +26,8 @@ namespace dmr
class HOST_SW_API DMRUtils {
public:
/// <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)
{
if (colorCode < 0U) { // clamp to 0
@ -39,36 +41,40 @@ namespace dmr
}
/// <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) {
id--;
}
switch (siteModel)
{
case SITE_MODEL_TINY:
case SiteModel::TINY:
{
if (id > 0x07U) { // clamp to $7
id = 0x07U;
}
}
break;
case SITE_MODEL_SMALL:
case SiteModel::SMALL:
{
if (id > 0x1FU) { // clamp to $1F
id = 0x1FU;
}
}
break;
case SITE_MODEL_LARGE:
case SiteModel::LARGE:
{
if (id > 0x7FU) { // clamp to $7F
id = 0x7FU;
}
}
break;
case SITE_MODEL_HUGE:
case SiteModel::HUGE:
{
if (id > 0x3FFU) { // clamp to $3FF
id = 0x3FFU;
@ -81,31 +87,35 @@ namespace dmr
}
/// <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) {
case SITE_MODEL_TINY:
case SiteModel::TINY:
{
if (id > 0x1FFU) { // clamp to $1FF
id = 0x1FFU;
}
}
break;
case SITE_MODEL_SMALL:
case SiteModel::SMALL:
{
if (id > 0x7FU) { // clamp to $7F
id = 0x7FU;
}
}
break;
case SITE_MODEL_LARGE:
case SiteModel::LARGE:
{
if (id > 0x1FU) { // clamp to $1F
id = 0x1FU;
}
}
break;
case SITE_MODEL_HUGE:
case SiteModel::HUGE:
{
if (id > 0x03U) { // clamp to $3
id = 0x03U;

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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__)
@ -28,7 +28,7 @@ namespace dmr
public:
/// <summary>Initializes a new instance of the SiteData class.</summary>
SiteData() :
m_siteModel(SITE_MODEL_SMALL),
m_siteModel(defines::SiteModel::SMALL),
m_netId(1U),
m_siteId(1U),
m_parId(3U),
@ -43,7 +43,7 @@ namespace dmr
/// <param name="siteId">DMR Site ID.</param>
/// <param name="parId">DMR partition ID.</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_netId(netId),
m_siteId(siteId),
@ -51,9 +51,10 @@ namespace dmr
m_requireReg(requireReq),
m_netActive(false)
{
using namespace dmr::defines;
// siteModel clamping
if (siteModel > SITE_MODEL_HUGE)
siteModel = SITE_MODEL_SMALL;
if (siteModel > SiteModel::HUGE)
siteModel = SiteModel::SMALL;
// netId clamping
m_netId = DMRUtils::netId(netId, siteModel);
@ -80,29 +81,30 @@ namespace dmr
/// <returns></returns>
const uint32_t systemIdentity(bool msb = false)
{
using namespace dmr::defines;
uint32_t value = m_siteModel;
switch (m_siteModel)
{
case SITE_MODEL_TINY:
case SiteModel::TINY:
{
value = (value << 9) + (m_netId & 0x1FFU);
value = (value << 3) + (m_siteId & 0x07U);
}
break;
case SITE_MODEL_SMALL:
case SiteModel::SMALL:
{
value = (value << 7) + (m_netId & 0x7FU);
value = (value << 5) + (m_siteId & 0x1FU);
}
break;
case SITE_MODEL_LARGE:
case SiteModel::LARGE:
{
value = (value << 5) + (m_netId & 0x1FU);
value = (value << 7) + (m_siteId & 0x7FU);
}
break;
case SITE_MODEL_HUGE:
case SiteModel::HUGE:
{
value = (value << 2) + (m_netId & 0x03U);
value = (value << 10) + (m_siteId & 0x3FFU);
@ -138,7 +140,7 @@ namespace dmr
public:
/// <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>
__READONLY_PROPERTY_PLAIN(uint16_t, netId);
/// <summary>DMR site ID.</summary>

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

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

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

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

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

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

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

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

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
#define __DMR_LC__CSBK_H__
#include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/SiteData.h"
#include "common/lookups/IdenTableLookup.h"
#include "common/Utils.h"
@ -95,7 +96,7 @@ namespace dmr
__PROTECTED_PROPERTY(uint8_t, CBF, CBF);
/// <summary>Data type for this CSBK.</summary>
__PROTECTED_PROPERTY(uint8_t, dataType, DataType);
__PROTECTED_PROPERTY(defines::DataType::E, dataType, DataType);
/** Common Service Options */
/// <summary>Flag indicating the emergency bits are set.</summary>

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

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
#define __DMR_LC__FULL_LC_H__
#include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/LC.h"
#include "common/dmr/lc/PrivacyLC.h"
#include "common/edac/BPTC19696.h"
@ -37,9 +38,9 @@ namespace dmr
~FullLC();
/// <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>
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>
std::unique_ptr<PrivacyLC> decodePI(const uint8_t* data);

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

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
#define __DMR_LC__LC_H__
#include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
namespace dmr
{
@ -29,7 +30,7 @@ namespace dmr
class HOST_SW_API LC {
public:
/// <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>
LC(const uint8_t* data);
/// <summary>Initializes a new instance of the LC class.</summary>
@ -49,7 +50,7 @@ namespace dmr
__PROPERTY(bool, PF, PF);
/// <summary>Full-link control opcode.</summary>
__PROPERTY(uint8_t, FLCO, FLCO);
__PROPERTY(defines::FLCO::E, FLCO, FLCO);
/// <summary>Feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -15,8 +15,9 @@
#include "dmr/lc/PrivacyLC.h"
#include "Utils.h"
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
#include <cassert>
@ -38,7 +39,7 @@ PrivacyLC::PrivacyLC(const uint8_t* data) :
{
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_algId = data[0U] & 7; // Algorithm ID
@ -67,7 +68,7 @@ PrivacyLC::PrivacyLC(const bool* bits) :
{
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;
Utils::bitsToByteBE(bits + 0U, temp1);
@ -110,7 +111,7 @@ PrivacyLC::PrivacyLC() :
m_kId(0U),
m_mi(nullptr)
{
m_mi = new uint8_t[DMR_MI_LENGTH_BYTES];
m_mi = new uint8_t[MI_LENGTH_BYTES];
}
/// <summary>

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

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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__)
@ -15,6 +15,7 @@
#include "common/Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/dmr/lc/CSBK.h"
#include "common/dmr/lc/csbk/CSBK_ACK_RSP.h"
#include "common/dmr/lc/csbk/CSBK_ALOHA.h"
@ -55,7 +56,7 @@ namespace dmr
~CSBKFactory();
/// <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:
/// <summary></summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "dmr/lc/csbk/CSBK_ACK_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_ACK_RSP::CSBK_ACK_RSP() : CSBK()
{
m_CSBKO = CSBKO_ACK_RSP;
m_CSBKO = CSBKO::ACK_RSP;
}
/// <summary>
@ -67,7 +68,7 @@ void CSBK_ACK_RSP::encode(uint8_t* data)
ulong64_t csbkValue = 0U;
if (m_reason == TS_ACK_RSN_REG) {
if (m_reason == ReasonCode::TS_ACK_RSN_REG) {
csbkValue = 0U;
} else {
csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type
@ -88,5 +89,5 @@ void CSBK_ACK_RSP::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_ALOHA.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -32,7 +33,7 @@ CSBK_ALOHA::CSBK_ALOHA() : CSBK(),
m_backoffNo(1U),
m_nRandWait(DEFAULT_NRAND_WAIT)
{
m_CSBKO = CSBKO_ALOHA;
m_CSBKO = CSBKO::ALOHA;
}
/// <summary>
@ -82,7 +83,7 @@ void CSBK_ALOHA::encode(uint8_t* data)
/// <returns></returns>
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 "dmr/lc/csbk/CSBK_BROADCAST.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -27,7 +28,7 @@ using namespace dmr;
/// Initializes a new instance of the CSBK_BROADCAST class.
/// </summary>
CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(),
m_anncType(BCAST_ANNC_SITE_PARMS),
m_anncType(BroadcastAnncType::SITE_PARMS),
m_hibernating(false),
m_annWdCh1(false),
m_annWdCh2(false),
@ -35,7 +36,7 @@ CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(),
m_systemId(0U),
m_backoffNo(1U)
{
m_CSBKO = CSBKO_BROADCAST;
m_CSBKO = CSBKO::BROADCAST;
}
/// <summary>
@ -60,7 +61,7 @@ bool CSBK_BROADCAST::decode(const uint8_t* data)
switch (m_anncType)
{
case BCAST_ANNC_ANN_WD_TSCC:
case BroadcastAnncType::ANN_WD_TSCC:
// Broadcast Params 1
m_colorCode = (uint8_t)((csbkValue >> 51) & 0x0FU); // Color Code 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)
{
case BCAST_ANNC_ANN_WD_TSCC:
case BroadcastAnncType::ANN_WD_TSCC:
// Broadcast Params 1
csbkValue = (csbkValue << 4) + 0U; // Reserved
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_logicalCh2 & 0xFFFU); // Logical Channel 2
break;
case BCAST_ANNC_CHAN_FREQ:
case BroadcastAnncType::CHAN_FREQ:
{
uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125);
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
}
break;
case BCAST_ANNC_SITE_PARMS:
case BroadcastAnncType::SITE_PARMS:
// 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()
{
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 BCAST_ANNC_CHAN_FREQ: return std::string("CSBKO_BROADCAST (Announcement PDU), BCAST_ANNC_CHAN_FREQ (Logical Channel/Frequency)");
case BCAST_ANNC_SITE_PARMS: return std::string("CSBKO_BROADCAST (Announcement PDU), BCAST_ANNC_SITE_PARMS (General Site Parameters)");
default: return std::string("CSBKO_BROADCAST (Announcement PDU)");
case BroadcastAnncType::ANN_WD_TSCC: return std::string("CSBKO, BROADCAST (Announcement PDU), BroadcastAnncType::ANN_WD_TSCC (Announce-WD TSCC Channel)");
case BroadcastAnncType::CHAN_FREQ: return std::string("CSBKO, BROADCAST (Announcement PDU), BroadcastAnncType::CHAN_FREQ (Logical Channel/Frequency)");
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)");
}
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "dmr/lc/csbk/CSBK_BSDWNACT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_BSDWNACT::CSBK_BSDWNACT() : CSBK(),
m_bsId(0U)
{
m_CSBKO = CSBKO_BSDWNACT;
m_CSBKO = CSBKO::BSDWNACT;
}
/// <summary>
@ -73,7 +74,7 @@ void CSBK_BSDWNACT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_CALL_ALRT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_CALL_ALRT::CSBK_CALL_ALRT() : CSBK()
{
m_CSBKO = CSBKO_RAND;
m_CSBKO = CSBKO::RAND;
m_FID = FID_DMRA;
}
@ -81,5 +82,5 @@ void CSBK_CALL_ALRT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_EXT_FNCT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -27,9 +28,9 @@ using namespace dmr;
/// Initializes a new instance of the CSBK_EXT_FNCT class.
/// </summary>
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;
}
@ -86,7 +87,7 @@ void CSBK_EXT_FNCT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_MAINT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_MAINT::CSBK_MAINT() : CSBK(),
m_maintKind(0U)
{
m_CSBKO = CSBKO_MAINT;
m_CSBKO = CSBKO::MAINT;
}
/// <summary>
@ -81,7 +82,7 @@ void CSBK_MAINT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_NACK_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_NACK_RSP::CSBK_NACK_RSP() : CSBK(),
m_serviceKind(0U)
{
m_CSBKO = CSBKO_NACK_RSP;
m_CSBKO = CSBKO::NACK_RSP;
}
/// <summary>
@ -86,7 +87,7 @@ void CSBK_NACK_RSP::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_PD_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_PD_GRANT::CSBK_PD_GRANT() : CSBK()
{
m_CSBKO = CSBKO_PD_GRANT;
m_CSBKO = CSBKO::PD_GRANT;
}
/// <summary>
@ -73,5 +74,5 @@ void CSBK_PD_GRANT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_PRECCSBK.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_PRECCSBK::CSBK_PRECCSBK() : CSBK()
{
m_CSBKO = CSBKO_PRECCSBK;
m_CSBKO = CSBKO::PRECCSBK;
}
/// <summary>
@ -75,5 +76,5 @@ void CSBK_PRECCSBK::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_PV_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_PV_GRANT::CSBK_PV_GRANT() : CSBK()
{
m_CSBKO = CSBKO_PV_GRANT;
m_CSBKO = CSBKO::PV_GRANT;
}
/// <summary>
@ -73,5 +74,5 @@ void CSBK_PV_GRANT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_P_CLEAR.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_P_CLEAR::CSBK_P_CLEAR() : CSBK()
{
m_CSBKO = CSBKO_P_CLEAR;
m_CSBKO = CSBKO::P_CLEAR;
}
/// <summary>
@ -72,5 +73,5 @@ void CSBK_P_CLEAR::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_P_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_P_GRANT::CSBK_P_GRANT() : CSBK()
{
m_CSBKO = CSBKO_TV_GRANT;
m_CSBKO = CSBKO::TV_GRANT;
}
/// <summary>
@ -73,5 +74,5 @@ void CSBK_P_GRANT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_RAND.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -31,7 +32,7 @@ CSBK_RAND::CSBK_RAND() : CSBK(),
m_serviceExtra(0U),
m_serviceKind(0U)
{
m_CSBKO = CSBKO_RAND;
m_CSBKO = CSBKO::RAND;
}
/// <summary>
@ -90,20 +91,20 @@ void CSBK_RAND::encode(uint8_t* data)
std::string CSBK_RAND::toString()
{
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 SVC_KIND_GRP_VOICE_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_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 SVC_KIND_GRP_DATA_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_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 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 SVC_KIND_UDT_SHORT_POLL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_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 SVC_KIND_CALL_DIVERSION: return std::string("CSBKO_RAND (Random Access), SVC_KIND_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 SVC_KIND_SUPPLEMENTARY_SVC: return std::string("CSBKO_RAND (Random Access), SVC_KIND_SUPPLEMENTARY_SVC (Supplementary Service)");
case SVC_KIND_REG_SVC: return std::string("CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service)");
case SVC_KIND_CANCEL_CALL: return std::string("CSBKO_RAND (Random Access), SVC_KIND_CANCEL_CALL (Cancel Call Service)");
default: return std::string("CSBKO_RAND (Random Access)");
case ServiceKind::IND_VOICE_CALL: return std::string("CSBKO, RAND (Random Access), IND_VOICE_CALL (Individual Voice Call)");
case ServiceKind::GRP_VOICE_CALL: return std::string("CSBKO, RAND (Random Access), GRP_VOICE_CALL (Group Voice Call)");
case ServiceKind::IND_DATA_CALL: return std::string("CSBKO, RAND (Random Access), IND_DATA_CALL (Individual Data Call)");
case ServiceKind::GRP_DATA_CALL: return std::string("CSBKO, RAND (Random Access), GRP_DATA_CALL (Group 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 ServiceKind::GRP_UDT_DATA_CALL: return std::string("CSBKO, RAND (Random Access), GRP_UDT_DATA_CALL (Group UDT Short Data Call)");
case ServiceKind::UDT_SHORT_POLL: return std::string("CSBKO, RAND (Random Access), UDT_SHORT_POLL (UDT Short Data Polling Service)");
case ServiceKind::STATUS_TRANSPORT: return std::string("CSBKO, RAND (Random Access), STATUS_TRANSPORT (Status Transport Service)");
case ServiceKind::CALL_DIVERSION: return std::string("CSBKO, RAND (Random Access), CALL_DIVERSION (Call Diversion Service)");
case ServiceKind::CALL_ANSWER: return std::string("CSBKO, RAND (Random Access), CALL_ANSWER (Call Answer Service)");
case ServiceKind::SUPPLEMENTARY_SVC: return std::string("CSBKO, RAND (Random Access), SUPPLEMENTARY_SVC (Supplementary Service)");
case ServiceKind::REG_SVC: return std::string("CSBKO, RAND (Random Access), REG_SVC (Registration 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)");
}
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "dmr/lc/csbk/CSBK_RAW.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_RAW::CSBK_RAW() : CSBK(),
m_csbk(nullptr)
{
m_CSBKO = CSBKO_RAND;
m_CSBKO = CSBKO::RAND;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "dmr/lc/csbk/CSBK_TD_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_TD_GRANT::CSBK_TD_GRANT() : CSBK()
{
m_CSBKO = CSBKO_TD_GRANT;
m_CSBKO = CSBKO::TD_GRANT;
}
/// <summary>
@ -73,5 +74,5 @@ void CSBK_TD_GRANT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_TV_GRANT.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -29,7 +30,7 @@ using namespace dmr;
CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK(),
m_lateEntry(false)
{
m_CSBKO = CSBKO_TV_GRANT;
m_CSBKO = CSBKO::TV_GRANT;
}
/// <summary>
@ -74,7 +75,7 @@ void CSBK_TV_GRANT::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_UU_ANS_RSP.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_UU_ANS_RSP::CSBK_UU_ANS_RSP() : CSBK()
{
m_CSBKO = CSBKO_UU_ANS_RSP;
m_CSBKO = CSBKO::UU_ANS_RSP;
}
/// <summary>
@ -72,5 +73,5 @@ void CSBK_UU_ANS_RSP::encode(uint8_t* data)
/// <returns></returns>
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
* @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 "dmr/lc/csbk/CSBK_UU_V_REQ.h"
using namespace dmr::lc::csbk;
using namespace dmr::lc;
using namespace dmr;
using namespace dmr::defines;
using namespace dmr::lc;
using namespace dmr::lc::csbk;
#include <cassert>
@ -28,7 +29,7 @@ using namespace dmr;
/// </summary>
CSBK_UU_V_REQ::CSBK_UU_V_REQ() : CSBK()
{
m_CSBKO = CSBKO_UU_V_REQ;
m_CSBKO = CSBKO::UU_V_REQ;
}
/// <summary>
@ -72,5 +73,5 @@ void CSBK_UU_V_REQ::encode(uint8_t* data)
/// <returns></returns>
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>
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;
}
@ -121,7 +121,7 @@ RadioId RadioIdLookup::find(uint32_t id)
{
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);
}

@ -14,6 +14,7 @@
*/
#include "Defines.h"
#include "common/dmr/DMRDefines.h"
#include "common/p25/P25Defines.h"
#include "common/nxdn/NXDNDefines.h"
#include "common/p25/dfsi/DFSIDefines.h"
#include "common/p25/dfsi/LC.h"
@ -434,6 +435,7 @@ UInt8Array BaseNetwork::readDMR(bool& ret, uint32_t& frameLength)
/// <returns></returns>
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)
return false;
@ -445,17 +447,17 @@ bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence)
if (slotNo == 2U && !m_slot2)
return false;
uint8_t dataType = data.getDataType();
DataType::E dataType = data.getDataType();
uint32_t slotIndex = slotNo - 1U;
bool resetSeq = false;
if (dataType == dmr::DT_VOICE_LC_HEADER) {
if (dataType == DataType::VOICE_LC_HEADER) {
resetSeq = true;
m_dmrStreamId[slotIndex] = createStreamId();
}
if (dataType == dmr::DT_CSBK || dataType == dmr::DT_DATA_HEADER) {
if (dataType == DataType::CSBK || dataType == DataType::DATA_HEADER) {
resetSeq = true;
m_dmrStreamId[slotIndex] = createStreamId();
}
@ -467,7 +469,7 @@ bool BaseNetwork::writeDMR(const dmr::data::Data& data, bool noSequence)
}
uint16_t seq = pktSeq(resetSeq);
if (dataType == dmr::DT_TERMINATOR_WITH_LC) {
if (dataType == DataType::TERMINATOR_WITH_LC) {
seq = RTP_END_OF_CALL_SEQ;
}
@ -531,7 +533,7 @@ UInt8Array BaseNetwork::readP25(bool& ret, uint32_t& frameLength)
/// <param name="data"></param>
/// <param name="frameType"></param>
/// <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)
return false;
@ -724,6 +726,7 @@ UInt8Array BaseNetwork::readNXDN(bool& ret, uint32_t& frameLength)
/// <returns></returns>
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)
return false;
@ -740,8 +743,8 @@ bool BaseNetwork::writeNXDN(const nxdn::lc::RTCH& lc, const uint8_t* data, const
}
uint16_t seq = pktSeq(resetSeq);
if (lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL ||
lc.getMessageType() == nxdn::RTCH_MESSAGE_TYPE_TX_REL_EX) {
if (lc.getMessageType() == MessageType::RTCH_TX_REL ||
lc.getMessageType() == MessageType::RTCH_TX_REL_EX) {
seq = RTP_END_OF_CALL_SEQ;
}
@ -797,6 +800,7 @@ uint16_t BaseNetwork::pktSeq(bool reset)
/// <returns></returns>
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];
::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
uint8_t flco = data.getFLCO();
buffer[15U] |= flco == dmr::FLCO_GROUP ? 0x00U : 0x40U; // Group
FLCO::E flco = data.getFLCO();
buffer[15U] |= flco == FLCO::GROUP ? 0x00U : 0x40U; // Group
uint8_t dataType = data.getDataType();
if (dataType == dmr::DT_VOICE_SYNC) {
if (dataType == DataType::VOICE_SYNC) {
buffer[15U] |= 0x10U;
}
else if (dataType == dmr::DT_VOICE) {
else if (dataType == DataType::VOICE) {
buffer[15U] |= data.getN();
}
else {
@ -858,9 +862,10 @@ UInt8Array BaseNetwork::createDMR_Message(uint32_t& length, const uint32_t strea
/// <param name="control"></param>
/// <param name="lsd"></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,
uint8_t frameType)
void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, p25::defines::DUID::E duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
p25::defines::FrameType::E frameType)
{
using namespace p25::defines;
assert(buffer != nullptr);
// construct P25 message header
@ -889,27 +894,27 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25:
buffer[22U] = duid; // DUID
if (frameType != p25::P25_FT_TERMINATOR) {
if (frameType != FrameType::TERMINATOR) {
buffer[180U] = frameType; // DVM Frame Type
}
// 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
uint32_t kid = control.getKId();
__SET_UINT16B(kid, buffer, 182U); // Key ID
// copy MI data
uint8_t mi[p25::P25_MI_LENGTH_BYTES];
::memset(mi, 0x00U, p25::P25_MI_LENGTH_BYTES);
uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, MI_LENGTH_BYTES);
control.getMI(mi);
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
}
}
@ -925,8 +930,10 @@ void BaseNetwork::createP25_MessageHdr(uint8_t* buffer, uint8_t duid, const p25:
/// <param name="frameType"></param>
/// <returns></returns>
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);
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);
// 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
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);
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);
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);
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);
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);
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);
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);
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);
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);
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;
@ -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,
const uint8_t* data)
{
using namespace p25::defines;
using namespace p25::dfsi::defines;
assert(data != nullptr);
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);
// 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
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);
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);
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);
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);
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);
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);
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);
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);
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);
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;
@ -1084,11 +1093,12 @@ UInt8Array BaseNetwork::createP25_LDU2Message(uint32_t& length, const p25::lc::L
/// <returns></returns>
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];
::memset(buffer, 0x00U, MSG_HDR_SIZE + PACKET_PAD);
// 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[23U] = MSG_HDR_SIZE;
@ -1109,6 +1119,7 @@ UInt8Array BaseNetwork::createP25_TDUMessage(uint32_t& length, const p25::lc::LC
/// <returns></returns>
UInt8Array BaseNetwork::createP25_TSDUMessage(uint32_t& length, const p25::lc::LC& control, const uint8_t* data)
{
using namespace p25::defines;
assert(data != nullptr);
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
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
uint32_t count = MSG_HDR_SIZE;
::memcpy(buffer + 24U, data, p25::P25_TSDU_FRAME_LENGTH_BYTES);
count += p25::P25_TSDU_FRAME_LENGTH_BYTES;
::memcpy(buffer + 24U, data, P25_TSDU_FRAME_LENGTH_BYTES);
count += P25_TSDU_FRAME_LENGTH_BYTES;
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,
const uint8_t currentBlock, const uint8_t* data, const uint32_t len)
{
using namespace p25::defines;
assert(data != nullptr);
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);
buffer[4U] = header.getSAP(); // Service Access Point
if (header.getFormat() == p25::PDU_FMT_CONFIRMED) {
if (header.getFormat() == PDUFormatType::CONFIRMED) {
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[21U] = currentBlock; // Current Block
buffer[22U] = p25::P25_DUID_PDU; // DUID
buffer[22U] = DUID::PDU; // DUID
// pack raw P25 PDU bytes
uint32_t count = MSG_HDR_SIZE;

@ -196,7 +196,7 @@ namespace network
virtual UInt8Array readP25(bool& ret, uint32_t& frameLength);
/// <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,
uint8_t frameType);
p25::defines::FrameType::E frameType);
/// <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);
/// <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);
/// <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,
uint8_t frameType = p25::P25_FT_DATA_UNIT);
void createP25_MessageHdr(uint8_t* buffer, p25::defines::DUID::E duid, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
p25::defines::FrameType::E frameType = p25::defines::FrameType::DATA_UNIT);
/// <summary>Creates an P25 LDU1 frame message.</summary>
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>
UInt8Array createP25_LDU2Message(uint32_t& length, const p25::lc::LC& control, const p25::data::LowSpeedData& lsd,
const uint8_t* data);

@ -17,250 +17,363 @@
#include "common/Defines.h"
// Shorthand macro to nxdn::defines -- keeps source code that doesn't use "using" concise
#define NXDDEF nxdn::defines
namespace nxdn
{
// ---------------------------------------------------------------------------
// 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_FSW_LENGTH_BITS = 20U;
const uint32_t NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const uint8_t NXDN_FSW_BYTES[] = { 0xCDU, 0xF5U, 0x90U };
const uint8_t NXDN_FSW_BYTES_MASK[] = { 0xFFU, 0xFFU, 0xF0U };
const uint32_t NXDN_FSW_BYTES_LENGTH = 3U;
const uint8_t NXDN_PREAMBLE[] = { 0x57U, 0x75U, 0xFDU };
const uint32_t NXDN_LICH_LENGTH_BITS = 16U;
const uint32_t NXDN_LICH_LENGTH_BYTES = NXDN_LICH_LENGTH_BITS / 8U;
const uint32_t NXDN_SACCH_FEC_LENGTH_BITS = 60U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = NXDN_SACCH_FEC_CONV_LENGTH_BITS / 8U;
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_SACCH_LENGTH_BITS = 26U;
const uint32_t NXDN_FACCH1_FEC_LENGTH_BITS = 144U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = NXDN_FACCH1_FEC_CONV_LENGTH_BITS / 8U;
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_FACCH1_LENGTH_BITS = 80U;
const uint32_t NXDN_UDCH_FEC_LENGTH_BITS = 348U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = (NXDN_UDCH_FEC_CONV_LENGTH_BITS / 8U) + 1U;
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_UDCH_LENGTH_BITS = 184U;
const uint32_t NXDN_CAC_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = (NXDN_CAC_FEC_CONV_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_CRC_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL
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_E_POST_FIELD_BITS = 24U;
const uint32_t NXDN_CAC_IN_FEC_LENGTH_BITS = 252U; // Puncture and Interleave Length
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_LONG_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS / 8U;
const uint32_t NXDN_CAC_LONG_CRC_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL
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_CAC_SHORT_LENGTH_BITS = 106U;
const uint32_t NXDN_RTCH_LC_LENGTH_BITS = 176U;
const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = (NXDN_RTCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RCCH_LC_LENGTH_BITS = 144U;
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_CAC_LC_SHORT_LENGTH_BITS = 96U;
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_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
const uint8_t NXDN_LICH_RFCT_RCCH = 0U;
const uint8_t NXDN_LICH_RFCT_RTCH = 1U;
const uint8_t NXDN_LICH_RFCT_RDCH = 2U;
const uint8_t NXDN_LICH_RFCT_RTCH_C = 3U;
const uint8_t NXDN_LICH_CAC_OUTBOUND = 0U;
const uint8_t NXDN_LICH_CAC_INBOUND_LONG = 1U;
const uint8_t NXDN_LICH_CAC_INBOUND_SHORT = 3U;
const uint8_t NXDN_LICH_USC_SACCH_NS = 0U;
const uint8_t NXDN_LICH_USC_UDCH = 1U;
const uint8_t NXDN_LICH_USC_SACCH_SS = 2U;
const uint8_t NXDN_LICH_USC_SACCH_SS_IDLE = 3U;
const uint8_t NXDN_LICH_DATA_NORMAL = 0U;
const uint8_t NXDN_LICH_DATA_IDLE = 1U;
const uint8_t NXDN_LICH_DATA_COMMON = 2U;
const uint8_t NXDN_LICH_STEAL_NONE = 3U;
const uint8_t NXDN_LICH_STEAL_FACCH1_2 = 2U;
const uint8_t NXDN_LICH_STEAL_FACCH1_1 = 1U;
const uint8_t NXDN_LICH_STEAL_FACCH = 0U;
const uint8_t NXDN_SR_RCCH_SINGLE = 0x00U;
const uint8_t NXDN_SR_RCCH_DUAL = 0x01U;
const uint8_t NXDN_SR_RCCH_HEAD_SINGLE = 0x02U;
const uint8_t NXDN_SR_RCCH_HEAD_DUAL = 0x03U;
const uint8_t NXDN_SR_SINGLE = 0U;
const uint8_t NXDN_SR_4_4 = 0U;
const uint8_t NXDN_SR_3_4 = 1U;
const uint8_t NXDN_SR_2_4 = 2U;
const uint8_t NXDN_SR_1_4 = 3U;
const uint8_t SACCH_IDLE[] = { 0x10U, 0x00U, 0x00U };
const uint32_t DEFAULT_SILENCE_THRESHOLD = 14U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 4U;
const uint32_t MAX_NXDN_VOICE_ERRORS = 144U;
const uint32_t MAX_NXDN_VOICE_ERRORS_STEAL = 94U;
const uint8_t NXDN_NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U };
const uint8_t NXDN_CALLSIGN_LENGTH_BYTES = 8U;
const uint32_t NXDN_MI_LENGTH_BYTES = 8U;
const uint32_t NXDN_PCKT_INFO_LENGTH_BYTES = 3U;
const uint8_t NXDN_CIPHER_TYPE_NONE = 0x00U;
const uint8_t DATA_RSP_CLASS_ACK = 0x00U;
const uint8_t DATA_RSP_CLASS_ACK_S = 0x01U;
const uint8_t DATA_RSP_CLASS_NACK = 0x03U;
const uint8_t NXDN_LOC_CAT_GLOBAL = 0x00U;
const uint8_t NXDN_LOC_CAT_LOCAL = 0x01U;
const uint8_t NXDN_LOC_CAT_REGIONAL = 0x02U;
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_NETWORK = 0x51U;
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_TEMP = 0x52U;
const uint8_t NXDN_CAUSE_RSRC_NOT_AVAIL_QUEUED = 0x53U;
const uint8_t NXDN_CAUSE_SVC_UNAVAILABLE = 0x06U;
const uint8_t NXDN_CAUSE_PROC_ERROR = 0x70U;
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;
const uint8_t NXDN_CAUSE_MM_LOC_ACPT_GRP_REFUSE = 0x04U;
const uint8_t NXDN_CAUSE_MM_REG_FAILED = 0x06U;
const uint8_t NXDN_CAUSE_MM_REG_REFUSED = 0x08U;
const uint8_t NXDN_CAUSE_VD_ACCEPTED = 0x10U;
const uint8_t NXDN_CAUSE_VD_GRP_NOT_PERM = 0x11U;
const uint8_t NXDN_CAUSE_VD_REQ_UNIT_NOT_PERM = 0x12U;
const uint8_t NXDN_CAUSE_VD_TGT_UNIT_NOT_PERM = 0x13U;
const uint8_t NXDN_CAUSE_VD_REQ_UNIT_NOT_REG = 0x1CU;
const uint8_t NXDN_CAUSE_VD_QUE_CHN_RESOURCE_NOT_AVAIL = 0x30U;
const uint8_t NXDN_CAUSE_VD_QUE_TGT_UNIT_BUSY = 0x38U;
const uint8_t NXDN_CAUSE_VD_QUE_GRP_BUSY = 0x39U;
const uint8_t NXDN_CAUSE_SS_ACK_R = 0x01U;
const uint8_t NXDN_CAUSE_SS_ACK_S = 0x02U;
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;
const uint8_t NXDN_CAUSE_SS_TGT_UNIT_NOT_PERM = 0x13U;
const uint8_t NXDN_CAUSE_SS_REQ_UNIT_NOT_REG = 0x1CU;
const uint8_t NXDN_CAUSE_DREQ_USER = 0x10U;
const uint8_t NXDN_CAUSE_DREQ_OTHER = 0x1FU;
const uint8_t NXDN_CAUSE_DISC_USER = 0x10U;
const uint8_t NXDN_CAUSE_DISC_OTHER = 0x1FU;
const uint8_t NXDN_SIF1_DATA_CALL_SVC = 0x01U;
const uint8_t NXDN_SIF1_VOICE_CALL_SVC = 0x02U;
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;
const uint8_t NXDN_SIF1_MULTI_SYSTEM_SVC = 0x40U;
const uint8_t NXDN_SIF1_MULTI_SITE_SVC = 0x80U;
const uint8_t NXDN_SIF2_IP_NETWORK = 0x10U;
const uint8_t NXDN_SIF2_PSTN_NETWORK = 0x20U;
const uint8_t NXDN_SIF2_STATUS_CALL_REM_CTRL = 0x40U;
const uint8_t NXDN_SIF2_SHORT_DATA_CALL_SVC = 0x80U;
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;
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_100 = 0x01U;
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_330 = 0x02U;
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_400 = 0x03U;
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_750 = 0x04U;
const uint8_t NXDN_CH_ACCESS_BASE_FREQ_SYS_DEFINED = 0x07U;
// Common Message Types
const uint8_t MESSAGE_TYPE_IDLE = 0x10U; // IDLE - Idle
const uint8_t MESSAGE_TYPE_DISC = 0x11U; // DISC - Disconnect
const uint8_t MESSAGE_TYPE_DST_ID_INFO = 0x17U; // DST_ID_INFO - Digital Station ID
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
const uint8_t MESSAGE_TYPE_ADJ_SITE_INFO = 0x1BU; // ADJ_SITE_INFO - Adjacent Site Information
// Traffic Channel Message Types
const uint8_t RTCH_MESSAGE_TYPE_VCALL = 0x01U; // VCALL - Voice Call
#define NXDN_RTCH_MSG_TYPE_VCALL "VCALL (Voice Call)"
#define NXDN_RTCH_MSG_TYPE_VCALL_RESP "VCALL_RESP (Voice Call Response)"
const uint8_t RTCH_MESSAGE_TYPE_VCALL_IV = 0x03U; // VCALL_IV - Voice Call Initialization Vector
const uint8_t RTCH_MESSAGE_TYPE_TX_REL_EX = 0x07U; // TX_REL_EX - Transmission Release Extension
const uint8_t RTCH_MESSAGE_TYPE_TX_REL = 0x08U; // TX_REL - Transmission Release
#define NXDN_RTCH_MSG_TYPE_TX_REL "TX_REL (Transmission Release)"
const uint8_t RTCH_MESSAGE_TYPE_DCALL_HDR = 0x09U; // DCALL - Data Call (Header)
#define NXDN_RTCH_MSG_TYPE_DCALL_HDR "DCALL (Data Call Header)"
const uint8_t RTCH_MESSAGE_TYPE_DCALL_DATA = 0x0BU; // DCALL - Data Call (User Data Format)
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
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR = 0x38U; // SDCALL_REQ - Short Data Call Request (Header)
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_REQ_DATA = 0x39U; // SDCALL_REQ - Short Data Call Request (User Data Format)
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_IV = 0x3AU; // SDCALL_IV - Short Data Call Initialization Vector
const uint8_t RTCH_MESSAGE_TYPE_SDCALL_RESP = 0x3BU; // SDCALL_RESP - Short Data Call Response
// Control Channel Message Types
const uint8_t RCCH_MESSAGE_TYPE_VCALL_CONN = 0x03U; // VCALL_CONN - Voice Call Connection Request (ISP) / Voice Call Connection Response (OSP)
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
const uint8_t RCCH_MESSAGE_TYPE_SITE_INFO = 0x18U; // SITE_INFO - Site Information
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)
const uint8_t RCCH_MESSAGE_TYPE_REG_COMM = 0x23U; // REG_COMM - Registration Command
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
const uint8_t CALL_TYPE_BROADCAST = 0x00U;
const uint8_t CALL_TYPE_CONFERENCE = 0x01U;
const uint8_t CALL_TYPE_UNSPECIFIED = 0x02U;
const uint8_t CALL_TYPE_INDIVIDUAL = 0x04U;
const uint8_t CALL_TYPE_INTERCONNECT = 0x06U;
const uint8_t CALL_TYPE_SPEED_DIAL = 0x07U;
// Transmission Mode
const uint8_t TRANSMISSION_MODE_4800 = 0x00U;
const uint8_t TRANSMISSION_MODE_9600 = 0x02U;
const uint8_t TRANSMISSION_MODE_9600_EFR = 0x03U; // should never be used on data calls
namespace defines
{
// ---------------------------------------------------------------------------
// 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_FSW_LENGTH_BITS = 20U;
const uint32_t NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const uint8_t NXDN_FSW_BYTES[] = { 0xCDU, 0xF5U, 0x90U };
const uint8_t NXDN_FSW_BYTES_MASK[] = { 0xFFU, 0xFFU, 0xF0U };
const uint32_t NXDN_FSW_BYTES_LENGTH = 3U;
const uint8_t NXDN_PREAMBLE[] = { 0x57U, 0x75U, 0xFDU };
const uint32_t NXDN_LICH_LENGTH_BITS = 16U;
const uint32_t NXDN_LICH_LENGTH_BYTES = NXDN_LICH_LENGTH_BITS / 8U;
const uint32_t NXDN_SACCH_FEC_LENGTH_BITS = 60U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = NXDN_SACCH_FEC_CONV_LENGTH_BITS / 8U;
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_SACCH_LENGTH_BITS = 26U;
const uint32_t NXDN_FACCH1_FEC_LENGTH_BITS = 144U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = NXDN_FACCH1_FEC_CONV_LENGTH_BITS / 8U;
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_FACCH1_LENGTH_BITS = 80U;
const uint32_t NXDN_UDCH_FEC_LENGTH_BITS = 348U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = (NXDN_UDCH_FEC_CONV_LENGTH_BITS / 8U) + 1U;
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_UDCH_LENGTH_BITS = 184U;
const uint32_t NXDN_CAC_FEC_LENGTH_BITS = 300U; // Puncture and Interleave Length
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_CONV_LENGTH_BYTES = (NXDN_CAC_FEC_CONV_LENGTH_BITS / 8U) + 1U;
const uint32_t NXDN_CAC_CRC_LENGTH_BITS = 175U; // Data + CRC-16 + 4-bit NULL
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_E_POST_FIELD_BITS = 24U;
const uint32_t NXDN_CAC_IN_FEC_LENGTH_BITS = 252U; // Puncture and Interleave Length
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_LONG_FEC_CONV_LENGTH_BYTES = NXDN_CAC_LONG_FEC_CONV_LENGTH_BITS / 8U;
const uint32_t NXDN_CAC_LONG_CRC_LENGTH_BITS = 156U; // Data + CRC-16 + 4-bit NULL
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_CAC_SHORT_LENGTH_BITS = 106U;
const uint32_t NXDN_RTCH_LC_LENGTH_BITS = 176U;
const uint32_t NXDN_RTCH_LC_LENGTH_BYTES = (NXDN_RTCH_LC_LENGTH_BITS / 8U);
const uint32_t NXDN_RCCH_LC_LENGTH_BITS = 144U;
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_CAC_LC_SHORT_LENGTH_BITS = 96U;
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_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
const uint8_t SACCH_IDLE[] = { 0x10U, 0x00U, 0x00U };
const uint8_t NULL_AMBE[] = { 0xB1U, 0xA8U, 0x22U, 0x25U, 0x6BU, 0xD1U, 0x6CU, 0xCFU, 0x67U };
const uint8_t CALLSIGN_LENGTH_BYTES = 8U;
const uint32_t MI_LENGTH_BYTES = 8U;
const uint32_t PCKT_INFO_LENGTH_BYTES = 3U;
/** Thresholds */
const uint32_t DEFAULT_SILENCE_THRESHOLD = 14U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 4U;
const uint32_t MAX_NXDN_VOICE_ERRORS = 144U;
const uint32_t MAX_NXDN_VOICE_ERRORS_STEAL = 94U;
/// <summary>
/// Link Information Channel - RF Channel Type
/// </summary>
namespace RFChannelType {
// RF Channel Type Enumeration
enum E : uint8_t {
RCCH = 0U, // Control Channel
RTCH = 1U, // Traffic Channel
RDCH = 2U, // Data Channel
RTCH_C = 3U // Composite Control/Traffic Channel
};
}
/// <summary>
/// Link Information Channel - Functional Channel Type
/// </summary>
namespace FuncChannelType {
// Functional Channel Type Enumeration
enum E : uint8_t {
// Common Access Channel
CAC_OUTBOUND = 0U, // Common Access Channel - Outbound
CAC_INBOUND_LONG = 1U, // Common Access Channel - Inbound Long
CAC_INBOUND_SHORT = 3U, // Common Access Channel - Inbound Short
// Slow Associated Control Channel / User Data Channel
USC_SACCH_NS = 0U, //
USC_UDCH = 1U, //
USC_SACCH_SS = 2U, //
USC_SACCH_SS_IDLE = 3U //
};
}
/// <summary>
/// Link Information Channel - Channel Options
/// </summary>
namespace ChOption {
// Channel Option(s) Enumeration
enum E : uint8_t {
DATA_NORMAL = 0U, //
DATA_IDLE = 1U, //
DATA_COMMON = 2U, //
STEAL_NONE = 3U, //
STEAL_FACCH1_2 = 2U, //
STEAL_FACCH1_1 = 1U, //
STEAL_FACCH = 0U //
};
}
/// <summary>
/// Common Access Channel - Structure
/// </summary>
namespace ChStructure {
// Channel Structure Enumeration
enum E : uint8_t {
SR_RCCH_SINGLE = 0x00U, //
SR_RCCH_DUAL = 0x01U, //
SR_RCCH_HEAD_SINGLE = 0x02U, //
SR_RCCH_HEAD_DUAL = 0x03U, //
SR_SINGLE = 0U, //
SR_4_4 = 0U, //
SR_3_4 = 1U, //
SR_2_4 = 2U, //
SR_1_4 = 3U //
};
}
/** Encryption Algorithms */
const uint8_t CIPHER_TYPE_NONE = 0x00U; // Unencrypted
/// <summary>
/// Location Category
/// <summary>
namespace LocationCategory {
// Location Category Enumeration
enum E : uint8_t {
GLOBAL = 0x00U, // Global
LOCAL = 0x01U, // Local
REGIONAL = 0x02U // Regional
};
}
/// <summary>
/// Data Response Class
/// <summary>
namespace PDUResponseClass {
enum : uint8_t
{
ACK = 0x00U, // Acknowledge
ACK_S = 0x01U, //
NACK = 0x03U // Negative Acknowledge
};
}
/// <summary>
/// Causes
/// <summary>
namespace CauseResponse {
enum : uint8_t {
RSRC_NOT_AVAIL_NETWORK = 0x51U, // Network Resource Not Available
RSRC_NOT_AVAIL_TEMP = 0x52U, // Resource Temporarily Not Available
RSRC_NOT_AVAIL_QUEUED = 0x53U, // Resource Queued Not Available
SVC_UNAVAILABLE = 0x06U, // Service Unavailable
PROC_ERROR = 0x70U, //
PROC_ERROR_UNDEF = 0x71U, //
MM_REG_ACCEPTED = 0x01U, // Registration Accepted
MM_LOC_ACPT_GRP_FAIL = 0x04U, // Location Accepted / Group Failed
MM_LOC_ACPT_GRP_REFUSE = 0x04U, // Location Accepted / Group Refused
MM_REG_FAILED = 0x06U, // Registration Failed
MM_REG_REFUSED = 0x08U, // Registration Refused
VD_ACCEPTED = 0x10U, //
VD_GRP_NOT_PERM = 0x11U, //
VD_REQ_UNIT_NOT_PERM = 0x12U, //
VD_TGT_UNIT_NOT_PERM = 0x13U, //
VD_REQ_UNIT_NOT_REG = 0x1CU, //
VD_QUE_CHN_RESOURCE_NOT_AVAIL = 0x30U, //
VD_QUE_TGT_UNIT_BUSY = 0x38U, //
VD_QUE_GRP_BUSY = 0x39U, //
SS_ACK_R = 0x01U, //
SS_ACK_S = 0x02U, //
SS_NACK = 0x08U, //
SS_ACCEPTED = 0x10U, //
SS_GRP_NOT_PERM = 0x11U, //
SS_REQ_UNIT_NOT_PERM = 0x12U, //
SS_TGT_UNIT_NOT_PERM = 0x13U, //
SS_REQ_UNIT_NOT_REG = 0x1CU, //
DREQ_USER = 0x10U, //
DREQ_OTHER = 0x1FU, //
DISC_USER = 0x10U, //
DISC_OTHER = 0x1FU //
};
}
/// <summary>
/// Site Information 1 (SIF1)
/// <summary>
namespace SiteInformation1 {
enum : uint8_t {
DATA_CALL_SVC = 0x01U, // Data Call Service
VOICE_CALL_SVC = 0x02U, // Voice Call Service
COMPOSITE_CONTROL = 0x04U, // Composite Control Channel
AUTH_SVC = 0x08U, // Authentication Service
GRP_REG_SVC = 0x10U, // Group Registration Service
LOC_REG_SVC = 0x20U, // Location Registration Service
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
// ---------------------------------------------------------------------------

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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__)
@ -30,7 +30,7 @@ namespace nxdn
m_locId(1U),
m_channelId(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_callsign("CHANGEME"),
m_requireReg(false),
@ -48,7 +48,7 @@ namespace nxdn
m_locId(locId),
m_channelId(channelId),
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_callsign("CHANGEME"),
m_requireReg(requireReq),

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -18,6 +18,7 @@
#include "Utils.h"
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::channel;
#include <cassert>
@ -101,7 +102,7 @@ const uint32_t PUNCTURE_LIST_OUT[] = {
/// </summary>
CAC::CAC() :
m_ran(0U),
m_structure(NXDN_SR_RCCH_SINGLE),
m_structure(ChStructure::SR_RCCH_SINGLE),
m_idleBusy(true),
m_txContinuous(false),
m_receive(true),
@ -118,7 +119,7 @@ CAC::CAC() :
/// <param name="data"></param>
CAC::CAC(const CAC& data) :
m_ran(0U),
m_structure(NXDN_SR_RCCH_SINGLE),
m_structure(ChStructure::SR_RCCH_SINGLE),
m_idleBusy(true),
m_txContinuous(false),
m_receive(true),
@ -147,7 +148,7 @@ CAC& CAC::operator=(const CAC& data)
::memcpy(m_data, data.m_data, NXDN_CAC_CRC_LENGTH_BYTES);
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_txContinuous = data.m_txContinuous;
@ -217,7 +218,7 @@ bool CAC::decode(const uint8_t* data)
::memset(crc, 0x00U, 2U);
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;
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);
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_txContinuous = data.m_txContinuous;

@ -7,13 +7,14 @@
* @package DVM / Common Library
* @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__)
#define __NXDN_CHANNEL__CAC_H__
#include "common/Defines.h"
#include "common/nxdn/NXDNDefines.h"
namespace nxdn
{
@ -51,7 +52,7 @@ namespace nxdn
/// <summary>Radio Access Number</summary>
__PROPERTY(uint8_t, ran, RAN);
/// <summary></summary>
__PROPERTY(uint8_t, structure, Structure);
__PROPERTY(defines::ChStructure::E, structure, Structure);
/** Collision Control Field */
/// <summary>Idle/Busy.</summary>

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

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

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
#define __NXDN_CHANNEL__LICH_H__
#include "common/Defines.h"
#include "common/nxdn/NXDNDefines.h"
namespace nxdn
{
@ -46,11 +47,11 @@ namespace nxdn
public:
/** Common Data */
/// <summary>RF Channel Type</summary>
__PROPERTY(uint8_t, rfct, RFCT);
__PROPERTY(defines::RFChannelType::E, rfct, RFCT);
/// <summary>Functional Channel Type</summary>
__PROPERTY(uint8_t, fct, FCT);
__PROPERTY(defines::FuncChannelType::E, fct, FCT);
/// <summary>Channel Options</summary>
__PROPERTY(uint8_t, option, Option);
__PROPERTY(defines::ChOption::E, option, Option);
/// <summary>Flag indicating outbound traffic direction</summary>
__PROPERTY(bool, outbound, Outbound);

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

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -15,8 +15,9 @@
#include "nxdn/lc/PacketInformation.h"
#include "Log.h"
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
#include <cassert>
#include <cstring>
@ -36,7 +37,7 @@ PacketInformation::PacketInformation() :
m_start(true),
m_circular(false),
m_fragmentCount(0U),
m_rspClass(DATA_RSP_CLASS_ACK),
m_rspClass(PDUResponseClass::ACK),
m_rspType(1U),
m_rspErrorBlock(0U)
{
@ -60,7 +61,7 @@ bool PacketInformation::decode(const uint8_t messageType, const uint8_t* data)
switch (messageType)
{
case RTCH_MESSAGE_TYPE_DCALL_HDR:
case MessageType::RTCH_DCALL_HDR:
m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery
m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry
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
break;
case RTCH_MESSAGE_TYPE_DCALL_ACK:
case MessageType::RTCH_DCALL_ACK:
m_rspClass = (data[0U] >> 4) & 0x03U; // Response Class
m_rspType = (data[0U] >> 1) & 0x07U; // Response Type
m_fragmentCount = ((data[0U] & 0x01U) << 8) + data[1U]; // Fragment Count
break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR:
case MessageType::RTCH_SDCALL_REQ_HDR:
m_delivery = (data[0U] & 0x80U) == 0x80U; // Delivery
m_selectiveRetry = (data[0U] & 0x20U) == 0x20U; // Selective Retry
m_blockCount = (data[0U] & 0x0FU); // Block Count
@ -104,9 +105,9 @@ void PacketInformation::encode(const uint8_t messageType, uint8_t* data)
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
(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
}
break;
case RTCH_MESSAGE_TYPE_DCALL_ACK:
case MessageType::RTCH_DCALL_ACK:
{
data[0U] = (m_rspClass & 0x03U << 4) + // Response Class
(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
}
break;
case RTCH_MESSAGE_TYPE_SDCALL_REQ_HDR:
::memset(data, 0x00U, NXDN_PCKT_INFO_LENGTH_BYTES);
case MessageType::RTCH_SDCALL_REQ_HDR:
::memset(data, 0x00U, PCKT_INFO_LENGTH_BYTES);
data[0U] = (m_delivery ? 0x80U : 0x00U) + // Delivery
(m_selectiveRetry ? 0x20U : 0x00U) + // Selective Retry
@ -163,7 +164,7 @@ void PacketInformation::reset()
m_fragmentCount = 0U;
m_rspClass = DATA_RSP_CLASS_ACK;
m_rspClass = PDUResponseClass::ACK;
m_rspType = 0U;
m_rspErrorBlock = 0U;
}

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -15,6 +15,7 @@
#include "Utils.h"
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
#include <cassert>
@ -26,7 +27,7 @@ using namespace nxdn::lc;
bool RCCH::m_verbose = false;
uint8_t *RCCH::m_siteCallsign = nullptr;
uint8_t* RCCH::m_siteCallsign = nullptr;
SiteData RCCH::m_siteData = SiteData();
// ---------------------------------------------------------------------------
@ -46,26 +47,26 @@ RCCH::RCCH(const RCCH& data) : RCCH()
/// Initializes a new instance of the RCCH class.
/// </summary>
RCCH::RCCH() :
m_messageType(MESSAGE_TYPE_IDLE),
m_messageType(MessageType::IDLE),
m_srcId(0U),
m_dstId(0U),
m_locId(0U),
m_regOption(0U),
m_version(0U),
m_causeRsp(NXDN_CAUSE_MM_REG_ACCEPTED),
m_causeRsp(CauseResponse::MM_REG_ACCEPTED),
m_grpVchNo(0U),
m_callType(CALL_TYPE_UNSPECIFIED),
m_callType(CallType::UNSPECIFIED),
m_emergency(false),
m_encrypted(false),
m_priority(false),
m_group(true),
m_duplex(false),
m_transmissionMode(TRANSMISSION_MODE_4800),
m_transmissionMode(TransmissionMode::MODE_4800),
m_siteIdenEntry()
{
if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES);
m_siteCallsign = new uint8_t[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)
{
if (m_siteCallsign == nullptr) {
m_siteCallsign = new uint8_t[NXDN_CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, NXDN_CALLSIGN_LENGTH_BYTES);
m_siteCallsign = new uint8_t[CALLSIGN_LENGTH_BYTES];
::memset(m_siteCallsign, 0x00U, CALLSIGN_LENGTH_BYTES);
}
uint32_t idLength = callsign.length();
if (idLength > 0) {
::memset(m_siteCallsign, 0x20U, NXDN_CALLSIGN_LENGTH_BYTES);
::memset(m_siteCallsign, 0x20U, CALLSIGN_LENGTH_BYTES);
if (idLength > NXDN_CALLSIGN_LENGTH_BYTES)
idLength = NXDN_CALLSIGN_LENGTH_BYTES;
if (idLength > CALLSIGN_LENGTH_BYTES)
idLength = CALLSIGN_LENGTH_BYTES;
for (uint32_t i = 0; i < idLength; i++)
m_siteCallsign[i] = callsign[i];
}

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

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_DCALL_HDR.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_DCALL_HDR::MESSAGE_TYPE_DCALL_HDR() : RCCH()
{
m_messageType = RTCH_MESSAGE_TYPE_DCALL_HDR;
m_messageType = MessageType::RTCH_DCALL_HDR;
}
/// <summary>
@ -93,5 +94,5 @@ void MESSAGE_TYPE_DCALL_HDR::encode(uint8_t* data, uint32_t length, uint32_t off
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_DST_ID_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
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>
@ -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];
::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
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
}
@ -76,5 +77,5 @@ void MESSAGE_TYPE_DST_ID_INFO::encode(uint8_t* data, uint32_t length, uint32_t o
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_GRP_REG.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_GRP_REG::MESSAGE_TYPE_GRP_REG() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_GRP_REG;
m_messageType = MessageType::RCCH_GRP_REG;
}
/// <summary>
@ -82,6 +83,6 @@ void MESSAGE_TYPE_GRP_REG::encode(uint8_t* data, uint32_t length, uint32_t offse
/// <returns></returns>
std::string MESSAGE_TYPE_GRP_REG::toString(bool isp)
{
if (isp) return std::string("RCCH_MESSAGE_TYPE_GRP_REG (Group Registration Request)");
else return std::string("RCCH_MESSAGE_TYPE_GRP_REG (Group Registration Response)");
return (isp) ? std::string("RCCH_GRP_REG (Group Registration Request)") :
std::string("RCCH_GRP_REG (Group Registration Response)");
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_IDLE.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_IDLE::MESSAGE_TYPE_IDLE() : RCCH()
{
m_messageType = nxdn::MESSAGE_TYPE_IDLE;
m_messageType = MessageType::IDLE;
}
/// <summary>
@ -70,5 +71,5 @@ void MESSAGE_TYPE_IDLE::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_REG.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_REG::MESSAGE_TYPE_REG() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_REG;
m_messageType = MessageType::RCCH_REG;
}
/// <summary>
@ -85,6 +86,6 @@ void MESSAGE_TYPE_REG::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns>
std::string MESSAGE_TYPE_REG::toString(bool isp)
{
if (isp) return std::string("RCCH_MESSAGE_TYPE_REG (Registration Request)");
else return std::string("RCCH_MESSAGE_TYPE_REG (Registration Response)");
return (isp) ? std::string("RCCH_REG (Registration Request)") :
std::string("RCCH_REG (Registration Response)");
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_REG_C.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_REG_C::MESSAGE_TYPE_REG_C() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_REG_C;
m_messageType = MessageType::RCCH_REG_C;
}
/// <summary>
@ -80,6 +81,6 @@ void MESSAGE_TYPE_REG_C::encode(uint8_t* data, uint32_t length, uint32_t offset)
/// <returns></returns>
std::string MESSAGE_TYPE_REG_C::toString(bool isp)
{
if (isp) return std::string("RCCH_MESSAGE_TYPE_REG_C (Registration Clear Request)");
else return std::string("RCCH_MESSAGE_TYPE_REG_C (Registration Clear Response)");
return (isp) ? std::string("RCCH_REG_C (Registration Clear Request)") :
std::string("RCCH_REG_C (Registration Clear Response)");
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_REG_COMM.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_REG_COMM::MESSAGE_TYPE_REG_COMM() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_REG_COMM;
m_messageType = MessageType::RCCH_REG_COMM;
}
/// <summary>
@ -75,5 +76,5 @@ void MESSAGE_TYPE_REG_COMM::encode(uint8_t* data, uint32_t length, uint32_t offs
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_SITE_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -33,7 +34,7 @@ MESSAGE_TYPE_SITE_INFO::MESSAGE_TYPE_SITE_INFO() : RCCH(),
m_ccchMultiCnt(2U),
m_rcchIterateCnt(2U)
{
m_messageType = RCCH_MESSAGE_TYPE_SITE_INFO;
m_messageType = MessageType::RCCH_SITE_INFO;
}
/// <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
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
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
// 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
@ -102,7 +103,7 @@ void MESSAGE_TYPE_SITE_INFO::encode(uint8_t* data, uint32_t length, uint32_t off
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_SRV_INFO.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_SRV_INFO::MESSAGE_TYPE_SRV_INFO() : RCCH()
{
m_messageType = nxdn::MESSAGE_TYPE_SRV_INFO;
m_messageType = MessageType::SRV_INFO;
}
/// <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[3U] = (m_siteData.locId() >> 0) & 0xFFU; // ...
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
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>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_ASSGN.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_VCALL_ASSGN::MESSAGE_TYPE_VCALL_ASSGN() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_VCALL_ASSGN;
m_messageType = MessageType::RCCH_VCALL_ASSGN;
}
/// <summary>
@ -87,5 +88,5 @@ void MESSAGE_TYPE_VCALL_ASSGN::encode(uint8_t* data, uint32_t length, uint32_t o
/// <returns></returns>
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
* @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 "nxdn/lc/rcch/MESSAGE_TYPE_VCALL_CONN.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -28,7 +29,7 @@ using namespace nxdn;
/// </summary>
MESSAGE_TYPE_VCALL_CONN::MESSAGE_TYPE_VCALL_CONN() : RCCH()
{
m_messageType = RCCH_MESSAGE_TYPE_VCALL_CONN;
m_messageType = MessageType::RCCH_VCALL_CONN;
}
/// <summary>
@ -93,6 +94,6 @@ void MESSAGE_TYPE_VCALL_CONN::encode(uint8_t* data, uint32_t length, uint32_t of
/// <returns></returns>
std::string MESSAGE_TYPE_VCALL_CONN::toString(bool isp)
{
if (isp) return std::string("RCCH_MESSAGE_TYPE_VCALL_CONN (Voice Call Connection Request)");
else return std::string("RCCH_MESSAGE_TYPE_VCALL_CONN (Voice Call Connection Response)");
return (isp) ? std::string("RCCH_VCALL_CONN (Voice Call Connection Request)") :
std::string("RCCH_VCALL_CONN (Voice Call Connection Response)");
}

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -15,9 +15,10 @@
#include "Log.h"
#include "Utils.h"
using namespace nxdn::lc::rcch;
using namespace nxdn::lc;
using namespace nxdn;
using namespace nxdn::defines;
using namespace nxdn::lc;
using namespace nxdn::lc::rcch;
#include <cassert>
@ -58,18 +59,18 @@ std::unique_ptr<RCCH> RCCHFactory::createRCCH(const uint8_t* data, uint32_t leng
// message type opcodes
switch (messageType) {
case RTCH_MESSAGE_TYPE_VCALL:
case RCCH_MESSAGE_TYPE_VCALL_CONN:
case MessageType::RTCH_VCALL:
case MessageType::RCCH_VCALL_CONN:
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);
case nxdn::MESSAGE_TYPE_IDLE:
case MessageType::IDLE:
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);
case RCCH_MESSAGE_TYPE_REG_C:
case MessageType::RCCH_REG_C:
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);
default:
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)
*
* Copyright (C) 2016 Jonathan Naylor, G4KLX
* Copyright (C) 2017,2022 Bryan Biedenkapp, N2PLL
* Copyright (C) 2017,2022,2024 Bryan Biedenkapp, N2PLL
*
*/
#include "Defines.h"
@ -20,6 +20,7 @@
#include "edac/BCH.h"
using namespace p25;
using namespace p25::defines;
#include <cassert>
@ -38,7 +39,7 @@ const uint32_t MAX_NID_ERRS = 7U;//5U;
/// </summary>
/// <param name="nac">P25 Network Access Code.</param>
NID::NID(uint32_t nac) :
m_duid(0U),
m_duid(DUID::HDU),
m_nac(nac),
m_rxTx(nullptr),
m_tx(nullptr),
@ -78,51 +79,51 @@ bool NID::decode(const uint8_t* data)
P25Utils::decode(data, nid, 48U, 114U);
// 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;
cleanupArrays();
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) {
m_duid = P25_DUID_LDU1;
m_duid = DUID::LDU1;
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) {
m_duid = P25_DUID_LDU2;
m_duid = DUID::LDU2;
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) {
m_duid = P25_DUID_PDU;
m_duid = DUID::PDU;
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) {
m_duid = P25_DUID_TSDU;
m_duid = DUID::TSDU;
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) {
m_duid = P25_DUID_HDU;
m_duid = DUID::HDU;
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) {
m_duid = P25_DUID_TDULC;
m_duid = DUID::TDULC;
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) {
m_duid = P25_DUID_TDU;
m_duid = DUID::TDU;
return true;
}
@ -134,19 +135,19 @@ bool NID::decode(const uint8_t* data)
/// </summary>
/// <param name="data"></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);
if (m_splitNac) {
switch (duid) {
case P25_DUID_HDU:
case P25_DUID_TDU:
case P25_DUID_LDU1:
case P25_DUID_PDU:
case P25_DUID_TSDU:
case P25_DUID_LDU2:
case P25_DUID_TDULC:
case DUID::HDU:
case DUID::TDU:
case DUID::LDU1:
case DUID::PDU:
case DUID::TSDU:
case DUID::LDU2:
case DUID::TDULC:
P25Utils::encode(m_tx[duid], data, 48U, 114U);
break;
default:
@ -155,19 +156,19 @@ void NID::encode(uint8_t* data, uint8_t duid)
}
else {
// handle digital "squelch" NAC
if (m_nac == P25_NAC_DIGITAL_SQ) {
if (m_nac == NAC_DIGITAL_SQ) {
cleanupArrays();
createRxTxNID(P25_DEFAULT_NAC);
createRxTxNID(DEFAULT_NAC);
}
switch (duid) {
case P25_DUID_HDU:
case P25_DUID_TDU:
case P25_DUID_LDU1:
case P25_DUID_PDU:
case P25_DUID_TSDU:
case P25_DUID_LDU2:
case P25_DUID_TDULC:
case DUID::HDU:
case DUID::TDU:
case DUID::LDU1:
case DUID::PDU:
case DUID::TSDU:
case DUID::LDU2:
case DUID::TDULC:
P25Utils::encode(m_rxTx[duid], data, 48U, 114U);
break;
default:
@ -219,54 +220,54 @@ void NID::createRxTxNID(uint32_t nac)
{
edac::BCH bch;
m_rxTx[P25_DUID_HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_HDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_HDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_HDU][1U] |= P25_DUID_HDU;
bch.encode(m_rxTx[P25_DUID_HDU]);
m_rxTx[P25_DUID_HDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TDU][1U] |= P25_DUID_TDU;
bch.encode(m_rxTx[P25_DUID_TDU]);
m_rxTx[P25_DUID_TDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_LDU1][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_LDU1][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_LDU1][1U] |= P25_DUID_LDU1;
bch.encode(m_rxTx[P25_DUID_LDU1]);
m_rxTx[P25_DUID_LDU1][7U] |= 0x01U; // Set the parity bit
m_rxTx[P25_DUID_PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_PDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_PDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_PDU][1U] |= P25_DUID_PDU;
bch.encode(m_rxTx[P25_DUID_PDU]);
m_rxTx[P25_DUID_PDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TSDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TSDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TSDU][1U] |= P25_DUID_TSDU;
bch.encode(m_rxTx[P25_DUID_TSDU]);
m_rxTx[P25_DUID_TSDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[P25_DUID_LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_LDU2][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_LDU2][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_LDU2][1U] |= P25_DUID_LDU2;
bch.encode(m_rxTx[P25_DUID_LDU2]);
m_rxTx[P25_DUID_LDU2][7U] |= 0x01U; // Set the parity bit
m_rxTx[P25_DUID_TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[P25_DUID_TDULC][0U] = (nac >> 4) & 0xFFU;
m_rxTx[P25_DUID_TDULC][1U] = (nac << 4) & 0xF0U;
m_rxTx[P25_DUID_TDULC][1U] |= P25_DUID_TDULC;
bch.encode(m_rxTx[P25_DUID_TDULC]);
m_rxTx[P25_DUID_TDULC][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[DUID::HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::HDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::HDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::HDU][1U] |= DUID::HDU;
bch.encode(m_rxTx[DUID::HDU]);
m_rxTx[DUID::HDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[DUID::TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::TDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::TDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::TDU][1U] |= DUID::TDU;
bch.encode(m_rxTx[DUID::TDU]);
m_rxTx[DUID::TDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[DUID::LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::LDU1][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::LDU1][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::LDU1][1U] |= DUID::LDU1;
bch.encode(m_rxTx[DUID::LDU1]);
m_rxTx[DUID::LDU1][7U] |= 0x01U; // Set the parity bit
m_rxTx[DUID::PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::PDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::PDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::PDU][1U] |= DUID::PDU;
bch.encode(m_rxTx[DUID::PDU]);
m_rxTx[DUID::PDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[DUID::TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::TSDU][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::TSDU][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::TSDU][1U] |= DUID::TSDU;
bch.encode(m_rxTx[DUID::TSDU]);
m_rxTx[DUID::TSDU][7U] &= 0xFEU; // Clear the parity bit
m_rxTx[DUID::LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::LDU2][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::LDU2][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::LDU2][1U] |= DUID::LDU2;
bch.encode(m_rxTx[DUID::LDU2]);
m_rxTx[DUID::LDU2][7U] |= 0x01U; // Set the parity bit
m_rxTx[DUID::TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_rxTx[DUID::TDULC][0U] = (nac >> 4) & 0xFFU;
m_rxTx[DUID::TDULC][1U] = (nac << 4) & 0xF0U;
m_rxTx[DUID::TDULC][1U] |= DUID::TDULC;
bch.encode(m_rxTx[DUID::TDULC]);
m_rxTx[DUID::TDULC][7U] &= 0xFEU; // Clear the parity bit
}
/// <summary>
@ -277,52 +278,52 @@ void NID::createTxNID(uint32_t nac)
{
edac::BCH bch;
m_tx[P25_DUID_HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_HDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_HDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_HDU][1U] |= P25_DUID_HDU;
bch.encode(m_tx[P25_DUID_HDU]);
m_tx[P25_DUID_HDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TDU][1U] |= P25_DUID_TDU;
bch.encode(m_tx[P25_DUID_TDU]);
m_tx[P25_DUID_TDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_LDU1][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_LDU1][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_LDU1][1U] |= P25_DUID_LDU1;
bch.encode(m_tx[P25_DUID_LDU1]);
m_tx[P25_DUID_LDU1][7U] |= 0x01U; // Set the parity bit
m_tx[P25_DUID_PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_PDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_PDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_PDU][1U] |= P25_DUID_PDU;
bch.encode(m_tx[P25_DUID_PDU]);
m_tx[P25_DUID_PDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TSDU][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TSDU][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TSDU][1U] |= P25_DUID_TSDU;
bch.encode(m_tx[P25_DUID_TSDU]);
m_tx[P25_DUID_TSDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[P25_DUID_LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_LDU2][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_LDU2][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_LDU2][1U] |= P25_DUID_LDU2;
bch.encode(m_tx[P25_DUID_LDU2]);
m_tx[P25_DUID_LDU2][7U] |= 0x01U; // Set the parity bit
m_tx[P25_DUID_TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[P25_DUID_TDULC][0U] = (nac >> 4) & 0xFFU;
m_tx[P25_DUID_TDULC][1U] = (nac << 4) & 0xF0U;
m_tx[P25_DUID_TDULC][1U] |= P25_DUID_TDULC;
bch.encode(m_tx[P25_DUID_TDULC]);
m_tx[P25_DUID_TDULC][7U] &= 0xFEU; // Clear the parity bit
m_tx[DUID::HDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::HDU][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::HDU][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::HDU][1U] |= DUID::HDU;
bch.encode(m_tx[DUID::HDU]);
m_tx[DUID::HDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[DUID::TDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::TDU][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::TDU][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::TDU][1U] |= DUID::TDU;
bch.encode(m_tx[DUID::TDU]);
m_tx[DUID::TDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[DUID::LDU1] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::LDU1][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::LDU1][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::LDU1][1U] |= DUID::LDU1;
bch.encode(m_tx[DUID::LDU1]);
m_tx[DUID::LDU1][7U] |= 0x01U; // Set the parity bit
m_tx[DUID::PDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::PDU][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::PDU][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::PDU][1U] |= DUID::PDU;
bch.encode(m_tx[DUID::PDU]);
m_tx[DUID::PDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[DUID::TSDU] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::TSDU][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::TSDU][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::TSDU][1U] |= DUID::TSDU;
bch.encode(m_tx[DUID::TSDU]);
m_tx[DUID::TSDU][7U] &= 0xFEU; // Clear the parity bit
m_tx[DUID::LDU2] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::LDU2][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::LDU2][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::LDU2][1U] |= DUID::LDU2;
bch.encode(m_tx[DUID::LDU2]);
m_tx[DUID::LDU2][7U] |= 0x01U; // Set the parity bit
m_tx[DUID::TDULC] = new uint8_t[P25_NID_LENGTH_BYTES];
m_tx[DUID::TDULC][0U] = (nac >> 4) & 0xFFU;
m_tx[DUID::TDULC][1U] = (nac << 4) & 0xF0U;
m_tx[DUID::TDULC][1U] |= DUID::TDULC;
bch.encode(m_tx[DUID::TDULC]);
m_tx[DUID::TDULC][7U] &= 0xFEU; // Clear the parity bit
}

@ -9,13 +9,14 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
#define __P25_NID_H__
#include "common/Defines.h"
#include "common/p25/P25Defines.h"
namespace p25
{
@ -34,14 +35,14 @@ namespace p25
/// <summary>Decodes P25 network identifier data.</summary>
bool decode(const uint8_t* data);
/// <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>
void setTxNAC(uint32_t nac);
public:
/// <summary>Data unit ID.</summary>
__READONLY_PROPERTY(uint8_t, duid, DUID);
__READONLY_PROPERTY(defines::DUID::E, duid, DUID);
private:
uint32_t m_nac;

@ -9,7 +9,7 @@
* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
*
* 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__)
@ -17,371 +17,497 @@
#include "common/Defines.h"
// Shorthand macro to p25::defines -- keeps source code that doesn't use "using" concise
#define P25DEF p25::defines
namespace p25
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
namespace defines
{
// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------
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_BYTES = 99U;
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_BITS = P25_TDU_FRAME_LENGTH_BYTES * 8U;
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_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_BYTES = 216U;
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_BITS = P25_TSDU_FRAME_LENGTH_BYTES * 8U;
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_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_BYTES = 72U;
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_BITS = P25_TSDU_TRIPLE_FRAME_LENGTH_BYTES * 8U;
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_TDULC_FRAME_LENGTH_BYTES = 54U;
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_BITS = P25_NID_LENGTH_BYTES * 8U;
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_BITS = P25_SYNC_LENGTH_BYTES * 8U;
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_BITS = P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS;
const uint32_t P25_LDU_FRAME_TIME = 180U;
const uint32_t P25_HDU_LENGTH_BYTES = 81U;
const uint32_t P25_LDU_LC_FEC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U;
const uint32_t P25_TDULC_LENGTH_BYTES = 18U;
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_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_MAX_PDU_BLOCKS = 42U;
const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U;
const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U;
const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U;
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_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits
const uint32_t P25_MI_LENGTH_BYTES = 9U;
const uint32_t P25_RAW_IMBE_LENGTH_BYTES = 11U;
const uint32_t P25_SS0_START = 70U;
const uint32_t P25_SS1_START = 71U;
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 P25_ENCRYPTED_NULL_IMBE[] = { 0xFCU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U };
const uint8_t P25_MFG_STANDARD = 0x00U;
const uint8_t P25_MFG_STANDARD_ALT = 0x01U;
const uint8_t P25_MFG_MOT = 0x90U;
const uint8_t P25_MFG_DVM_OCS = 0x9CU; // P25 MFId used for internal signalling; Omaha Communication Systems, LLC ($9C)
const uint8_t P25_MOT_CALLSIGN_LENGTH_BYTES = 8U;
const uint8_t P25_AUTH_RES_LENGTH_BYTES = 4U;
const uint8_t P25_AUTH_RAND_SEED_LENGTH_BYTES = 10U;
const uint8_t P25_AUTH_RAND_CHLNG_LENGTH_BYTES = 5U;
const uint8_t P25_AUTH_KEY_LENGTH_BYTES = 16U;
const uint8_t P25_ALGO_UNENCRYPT = 0x80U;
const uint8_t P25_IDEN_UP_VU_BW_625K = 0x04U;
const uint8_t P25_IDEN_UP_VU_BW_125K = 0x05U;
const uint8_t P25_SVC_CLS_INVALID = 0x00U;
const uint8_t P25_SVC_CLS_COMPOSITE = 0x01U;
const uint8_t P25_SVC_CLS_VOICE = 0x10U;
const uint8_t P25_SVC_CLS_DATA = 0x20U;
const uint8_t P25_SVC_CLS_REG = 0x40U;
const uint8_t P25_SVC_CLS_AUTH = 0x80U;
const uint32_t P25_SYS_SRV_NET_ACTIVE = 0x0200000U;
const uint32_t P25_SYS_SRV_GROUP_VOICE = 0x0080000U;
const uint32_t P25_SYS_SRV_IND_VOICE = 0x0040000U;
const uint32_t P25_SYS_SRV_PSTN_UNIT_VOICE = 0x0020000U;
const uint32_t P25_SYS_SRV_UNIT_PSTN_VOICE = 0x0010000U;
const uint32_t P25_SYS_SRV_GROUP_DATA = 0x0004000U;
const uint32_t P25_SYS_SRV_IND_DATA = 0x0002000U;
const uint32_t P25_SYS_SRV_UNIT_REG = 0x0000800U;
const uint32_t P25_SYS_SRV_GROUP_AFF = 0x0000400U;
const uint32_t P25_SYS_SRV_GROUP_AFF_Q = 0x0000200U;
const uint32_t P25_SYS_SRV_USER_STS = 0x0000040U;
const uint32_t P25_SYS_SRV_USER_MSG = 0x0000020U;
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;
const uint32_t P25_SYS_SRV_EMERGENCY = 0x0000001U;
const uint32_t P25_SYS_SRV_DEFAULT = P25_SYS_SRV_EMERGENCY | P25_SYS_SRV_CALL_ALRT | P25_SYS_SRV_USER_MSG |
P25_SYS_SRV_UNIT_STS_Q | P25_SYS_SRV_USER_STS_Q | P25_SYS_SRV_UNIT_STS | P25_SYS_SRV_USER_STS |
P25_SYS_SRV_IND_DATA | P25_SYS_SRV_IND_VOICE | P25_SYS_SRV_GROUP_DATA | P25_SYS_SRV_GROUP_VOICE;
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;
const uint8_t P25_CFVA_CONV = 0x08U;
const uint8_t P25_CFVA_FAILURE = 0x04U;
const uint8_t P25_CFVA_VALID = 0x02U;
const uint8_t P25_CFVA_NETWORK = 0x01U;
const uint8_t P25_RSP_ACCEPT = 0x00U;
const uint8_t P25_RSP_FAIL = 0x01U;
const uint8_t P25_RSP_DENY = 0x02U;
const uint8_t P25_RSP_REFUSED = 0x03U;
const uint8_t P25_ANS_RSP_PROCEED = 0x20U;
const uint8_t P25_ANS_RSP_DENY = 0x21U;
const uint8_t P25_ANS_RSP_WAIT = 0x22U;
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 P25_DENY_RSN_REQ_UNIT_NOT_VALID = 0x10U;
const uint32_t P25_DENY_RSN_REQ_UNIT_NOT_AUTH = 0x11U;
const uint32_t P25_DENY_RSN_TGT_UNIT_NOT_VALID = 0x20U;
const uint32_t P25_DENY_RSN_TGT_UNIT_NOT_AUTH = 0x21U;
const uint32_t P25_DENY_RSN_SU_FAILED_AUTH = 0x22U;
const uint32_t P25_DENY_RSN_TGT_UNIT_REFUSED = 0x2FU;
const uint32_t P25_DENY_RSN_TGT_GROUP_NOT_VALID = 0x30U;
const uint32_t P25_DENY_RSN_TGT_GROUP_NOT_AUTH = 0x31U;
const uint32_t P25_DENY_RSN_NO_NET_RSRC_AVAIL = 0x53U;
const uint32_t P25_DENY_RSN_NO_RF_RSRC_AVAIL = 0x54U;
const uint32_t P25_DENY_RSN_SVC_IN_USE = 0x55U;
const uint32_t P25_DENY_RSN_SITE_ACCESS_DENIAL = 0x60U;
const uint32_t P25_DENY_RSN_PTT_COLLIDE = 0x67U;
const uint32_t P25_DENY_RSN_PTT_BONK = 0x77U;
const uint32_t P25_DENY_RSN_SYS_UNSUPPORTED_SVC = 0xFFU;
const uint32_t P25_QUE_RSN_REQ_ACTIVE_SERVICE = 0x10U;
const uint32_t P25_QUE_RSN_TGT_ACTIVE_SERVICE = 0x20U;
const uint32_t P25_QUE_RSN_TGT_UNIT_QUEUED = 0x2FU;
const uint32_t P25_QUE_RSN_CHN_RESOURCE_NOT_AVAIL = 0x40U;
const uint32_t P25_EXT_FNCT_CHECK = 0x0000U; // Radio Check
const uint32_t P25_EXT_FNCT_UNINHIBIT = 0x007EU; // Radio Uninhibit
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
const uint32_t P25_WACN_STD_DEFAULT = 0xBB800U;
const uint32_t P25_SID_STD_DEFAULT = 0x001U;
const uint32_t P25_NAC_DIGITAL_SQ = 0xF7EU;
const uint32_t P25_NAC_REUSE_RX_NAC = 0xF7FU;
const uint32_t P25_DEFAULT_NAC = 0x293U;
const uint32_t P25_WUID_FNE = 0xFFFFFCU;
const uint32_t P25_WUID_REG = 0xFFFFFEU;
const uint32_t P25_WUID_ALL = 0xFFFFFFU;
const uint32_t P25_TGID_ALL = 0xFFFFU;
const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 6U;
const uint32_t MAX_P25_VOICE_ERRORS = 1233U;
const uint8_t P25_FT_HDU_VALID = 0x01U;
const uint8_t P25_FT_HDU_LATE_ENTRY = 0x02U;
const uint8_t P25_FT_TERMINATOR = 0x03U;
const uint8_t P25_FT_DATA_UNIT = 0x00U;
// PDU Format Type(s)
const uint8_t PDU_FMT_RSP = 0x03U;
const uint8_t PDU_FMT_UNCONFIRMED = 0x15U;
const uint8_t PDU_FMT_CONFIRMED = 0x16U;
const uint8_t PDU_FMT_AMBT = 0x17U;
// PDU SAP
const uint8_t PDU_SAP_USER_DATA = 0x00U;
const uint8_t PDU_SAP_ENC_USER_DATA = 0x01U;
const uint8_t PDU_SAP_PACKET_DATA = 0x04U;
const uint8_t PDU_SAP_ARP = 0x05U;
const uint8_t PDU_SAP_SNDCP_CTRL_DATA = 0x06U;
const uint8_t PDU_SAP_EXT_ADDR = 0x1FU;
const uint8_t PDU_SAP_REG = 0x20U;
const uint8_t PDU_SAP_UNENC_KMM = 0x28U;
const uint8_t PDU_SAP_ENC_KMM = 0x29U;
const uint8_t PDU_SAP_TRUNK_CTRL = 0x3DU;
// PDU ACK Class
const uint8_t PDU_ACK_CLASS_ACK = 0x00U;
const uint8_t PDU_ACK_CLASS_NACK = 0x01U;
const uint8_t PDU_ACK_CLASS_ACK_RETRY = 0x02U;
// PDU ACK Type(s)
const uint8_t PDU_ACK_TYPE_RETRY = 0x00U;
const uint8_t PDU_ACK_TYPE_ACK = 0x01U;
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
const uint8_t PDU_ACK_TYPE_NACK_UNDELIVERABLE = 0x04U;// Undeliverable
const uint8_t PDU_ACK_TYPE_NACK_OUT_OF_SEQ = 0x05U; // Out of sequence, N(S) != V(R) or V(R) + 1
const uint8_t PDU_ACK_TYPE_NACK_INVL_USER = 0x06U; // Invalid User disallowed by the system
// PDU Registration Type(s)
const uint8_t PDU_REG_TYPE_REQ_CNCT = 0x00U;
const uint8_t PDU_REG_TYPE_REQ_DISCNCT = 0x01U;
const uint8_t PDU_REG_TYPE_RSP_ACCPT = 0x04U;
const uint8_t PDU_REG_TYPE_RSP_DENY = 0x05U;
// PDU SNDCP Type(s)
const uint8_t PDU_TYPE_SNDCP_ACT_TDS_CTX_ACCPT = 0x00U;
const uint8_t PDU_TYPE_SNDCP_DEACT_TDS_CTX_ACCPT = 0x01U;
const uint8_t PDU_TYPE_SNDCP_DEACT_TDS_CTX_REQ = 0x02U;
const uint8_t PDU_TYPE_SNDCP_ACT_TDS_CTX_REJECT = 0x03U;
const uint8_t PDU_TYPE_SNDCP_RF_UNCONFIRMED = 0x04U;
const uint8_t PDU_TYPE_SNDCP_RF_CONFIRMED = 0x05U;
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t LC_SVC_OPT_ENCRYPTION = 0x40U;
// LDUx/TDULC Link Control Opcode(s)
const uint8_t LC_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User
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
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
const uint8_t LC_TEL_INT_ANS_RQST = 0x07U; // TEL INT ANS RQST - Telephone Interconnect Answer Request
const uint8_t LC_EXPLICIT_SOURCE_ID = 0x09U; // EXPLICIT SOURCE ID - Explicit Source ID
const uint8_t LC_CALL_TERM = 0x0FU; // CALL TERM - Call Termination or Cancellation
const uint8_t LC_IDEN_UP = 0x18U; // IDEN UP - Channel Identifier Update
const uint8_t LC_SYS_SRV_BCAST = 0x20U; // SYS SRV BCAST - System Service Broadcast
const uint8_t LC_ADJ_STS_BCAST = 0x22U; // ADJ STS BCAST - Adjacent Site Status Broadcast
const uint8_t LC_RFSS_STS_BCAST = 0x23U; // RFSS STS BCAST - RFSS Status Broadcast
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)
const uint8_t LC_FAILSOFT = 0x02U; // FAILSOFT - Failsoft
// TSBK ISP/OSP Shared Opcode(s)
const uint8_t TSBK_IOSP_GRP_VCH = 0x00U; // GRP VCH REQ - Group Voice Channel Request (ISP), GRP VCH GRANT - Group Voice Channel Grant (OSP)
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)
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)
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)
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)
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)
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)
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)
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)
// 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
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
const uint8_t TSBK_ISP_EMERG_ALRM_REQ = 0x27U; // EMERG ALRM REQ - Emergency Alarm Request
const uint8_t TSBK_ISP_GRP_AFF_Q_RSP = 0x29U; // GRP AFF Q RSP - Group Affiliation Query Response
const uint8_t TSBK_ISP_U_DEREG_REQ = 0x2BU; // U DE REG REQ - Unit De-Registration Request
const uint8_t TSBK_ISP_LOC_REG_REQ = 0x2DU; // LOC REG REQ - Location Registration Request
const uint8_t TSBK_ISP_AUTH_RESP = 0x38U; // AUTH RESP - Authentication Response
const uint8_t TSBK_ISP_AUTH_RESP_M = 0x39U; // AUTH RESP M - Authentication Response Mutual
const uint8_t TSBK_ISP_AUTH_FNE_RST = 0x3AU; // AUTH FNE RST - Authentication FNE Result
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
const uint8_t TSBK_OSP_UU_VCH_GRANT_UPD = 0x06U; // UU VCH GRANT UPD - Unit-to-Unit Voice Channel Grant Update
const uint8_t TSBK_OSP_SNDCP_CH_GNT = 0x14U; // SNDCP CH GNT - SNDCP Data Channel Grant
const uint8_t TSBK_OSP_SNDCP_CH_ANN = 0x16U; // SNDCP CH ANN - SNDCP Data Channel Announcement
const uint8_t TSBK_OSP_STS_Q = 0x1AU; // STS Q - Status Query
const uint8_t TSBK_OSP_DENY_RSP = 0x27U; // DENY RSP - Deny Response
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
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
const uint8_t TSBK_OSP_U_DEREG_ACK = 0x2FU; // U DE REG ACK - Unit De-Registration Acknowledge
const uint8_t TSBK_OSP_SYNC_BCAST = 0x30U; // SYNC BCAST - Synchronization Broadcast
const uint8_t TSBK_OSP_AUTH_DMD = 0x31U; // AUTH DMD - Authentication Demand
const uint8_t TSBK_OSP_AUTH_FNE_RESP = 0x32U; // AUTH FNE RESP - Authentication FNE Response
const uint8_t TSBK_OSP_QUE_RSP = 0x33U; // QUE RSP - Queued Response
const uint8_t TSBK_OSP_IDEN_UP_VU = 0x34U; // IDEN UP VU - Channel Identifier Update for VHF/UHF Bands
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
const uint8_t TSBK_OSP_NET_STS_BCAST = 0x3BU; // NET STS BCAST - Network Status Broadcast
const uint8_t TSBK_OSP_ADJ_STS_BCAST = 0x3CU; // ADJ STS BCAST - Adjacent Site Status Broadcast
const uint8_t TSBK_OSP_IDEN_UP = 0x3DU; // IDEN UP - Channel Identifier Update
// TSBK Motorola Outbound Signalling Packet (OSP) Opcode(s)
const uint8_t TSBK_OSP_MOT_GRG_ADD = 0x00U; // MOT GRG ADD - Motorola / Group Regroup Add (Patch Supergroup)
const uint8_t TSBK_OSP_MOT_GRG_DEL = 0x01U; // MOT GRG DEL - Motorola / Group Regroup Delete (Unpatch Supergroup)
const uint8_t TSBK_OSP_MOT_GRG_VCH_GRANT = 0x02U; // MOT GRG GROUP VCH GRANT / Group Regroup Voice Channel Grant
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
// TSBK DVM Outbound Signalling Packet (OSP) Opcode(s)
const uint8_t TSBK_OSP_DVM_GIT_HASH = 0x3FU; //
// Data Unit ID(s)
const uint8_t P25_DUID_HDU = 0x00U; // Header Data Unit
#define P25_HDU_STR "P25_DUID_HDU (Header Data Unit)"
const uint8_t P25_DUID_TDU = 0x03U; // Simple Terminator Data Unit
#define P25_TDU_STR "P25_DUID_TDU (Simple Terminator Data Unit)"
const uint8_t P25_DUID_LDU1 = 0x05U; // Logical Link Data Unit 1
#define P25_LDU1_STR "P25_DUID_LDU1 (Logical Link Data Unit 1)"
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 P25_DUID_VSELP2 = 0x09U; // Motorola VSELP 2
#define P25_VSELP2_STR "P25_DUID_VSELP2 (VSELP Data Unit 2)"
const uint8_t P25_DUID_LDU2 = 0x0AU; // Logical Link Data Unit 2
#define P25_LDU2_STR "P25_DUID_LDU2 (Logical Link Data Unit 2)"
const uint8_t P25_DUID_PDU = 0x0CU; // Packet Data Unit
#define P25_PDU_STR "P25_DUID_PDU (Packet Data Unit)"
const uint8_t P25_DUID_TDULC = 0x0FU; // Terminator Data Unit with Link Control
#define P25_TDULC_STR "P25_DUID_TDULC (Terminator Data Unit with Link Control)"
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_PDU_FRAME_LENGTH_BYTES = 512U;
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_BITS = P25_TDULC_FRAME_LENGTH_BYTES * 8U;
const uint32_t 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 uint32_t P25_SYNC_LENGTH_BYTES = 6U;
const uint32_t P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U;
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_BITS = P25_SYNC_LENGTH_BITS + P25_NID_LENGTH_BITS;
const uint32_t P25_LDU_FRAME_TIME = 180U;
const uint32_t P25_HDU_LENGTH_BYTES = 81U;
const uint32_t P25_LDU_LC_FEC_LENGTH_BYTES = 18U;
const uint32_t P25_TDULC_FEC_LENGTH_BYTES = 36U;
const uint32_t P25_TDULC_LENGTH_BYTES = 18U;
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_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_MAX_PDU_BLOCKS = 42U;
const uint32_t P25_PDU_HEADER_LENGTH_BYTES = 12U;
const uint32_t P25_PDU_CONFIRMED_LENGTH_BYTES = 18U;
const uint32_t P25_PDU_CONFIRMED_DATA_LENGTH_BYTES = 16U;
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_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits
const uint32_t MI_LENGTH_BYTES = 9U;
const uint32_t RAW_IMBE_LENGTH_BYTES = 11U;
const uint32_t P25_SS0_START = 70U;
const uint32_t P25_SS1_START = 71U;
const uint32_t P25_SS_INCREMENT = 72U;
const uint8_t NULL_IMBE[] = { 0x04U, 0x0CU, 0xFDU, 0x7BU, 0xFBU, 0x7DU, 0xF2U, 0x7BU, 0x3DU, 0x9EU, 0x45U };
const uint8_t ENCRYPTED_NULL_IMBE[] = { 0xFCU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U };
const uint8_t MOT_CALLSIGN_LENGTH_BYTES = 8U;
const uint8_t AUTH_RES_LENGTH_BYTES = 4U;
const uint8_t AUTH_RAND_SEED_LENGTH_BYTES = 10U;
const uint8_t AUTH_RAND_CHLNG_LENGTH_BYTES = 5U;
const uint8_t AUTH_KEY_LENGTH_BYTES = 16U;
/** Thresholds */
const uint32_t DEFAULT_SILENCE_THRESHOLD = 124U;
const uint32_t DEFAULT_FRAME_LOSS_THRESHOLD = 6U;
const uint32_t MAX_P25_VOICE_ERRORS = 1233U;
/** Manufacturer IDs */
const uint8_t MFG_STANDARD = 0x00U; // Standard MFId
const uint8_t MFG_STANDARD_ALT = 0x01U; // Alternate Standard MFId
const uint8_t MFG_MOT = 0x90U; // Motorola
const uint8_t MFG_DVM_OCS = 0x9CU; // DVM; Omaha Communication Systems, LLC ($9C)
/** Encryption Algorithms */
const uint8_t ALGO_UNENCRYPT = 0x80U; // Unencrypted
/** IDEN Table Bandwidth Sizes */
const uint8_t IDEN_UP_VU_BW_625K = 0x04U;
const uint8_t IDEN_UP_VU_BW_125K = 0x05U;
/// <summary>
/// Station Service Classes
/// </summary>
namespace ServiceClass {
enum : uint8_t {
INVALID = 0x00U, // Invalid Service Class
COMPOSITE = 0x01U, // Composite Control Channel
VOICE = 0x10U, // Voice
DATA = 0x20U, // Data
REG = 0x40U, // Registration
AUTH = 0x80U // Authentication
};
}
/// <summary>
/// System Service Types
/// </summary>
namespace SystemService {
enum : uint32_t {
NET_ACTIVE = 0x0200000U, // Network Active
GROUP_VOICE = 0x0080000U, // Group Voice
IND_VOICE = 0x0040000U, // Individual Voice
PSTN_UNIT_VOICE = 0x0020000U, // PSTN Unit Voice
UNIT_PSTN_VOICE = 0x0010000U, // Unit PSTN Voice
GROUP_DATA = 0x0004000U, // Group Data
IND_DATA = 0x0002000U, // Individual Data
UNIT_REG = 0x0000800U, // Unit Registration
GROUP_AFF = 0x0000400U, // Group Affiliation
GROUP_AFF_Q = 0x0000200U, // Group Affiliation Query
USER_STS = 0x0000040U, // User Status
USER_MSG = 0x0000020U, // User Message
UNIT_STS = 0x0000010U, // Unit Status
USER_STS_Q = 0x0000008U, // User Status Query
UNIT_STS_Q = 0x0000004U, // Unit Status Query
CALL_ALRT = 0x0000002U, // Call Alert
EMERGENCY = 0x0000001U // Emergency
};
}
const uint32_t SYS_SRV_DEFAULT = SystemService::EMERGENCY | SystemService::CALL_ALRT | SystemService::USER_MSG |
SystemService::UNIT_STS_Q | SystemService::USER_STS_Q | SystemService::UNIT_STS | SystemService::USER_STS |
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;
/// <summary>
///
/// </summary>
namespace CFVA {
enum : uint8_t {
CONV = 0x08U, // Conventional
FAILURE = 0x04U, // Failure
VALID = 0x02U, // Valid
NETWORK = 0x01U // Networked
};
}
/// <summary>
/// Response Codes
/// </summary>
namespace ResponseCode {
enum : uint8_t {
// General Codes
ACCEPT = 0x00U, // Accept
FAIL = 0x01U, // Fail
DENY = 0x02U, // Deny
REFUSED = 0x03U, // Refused
// Answer Codes
ANS_PROCEED = 0x20U, // Proceed
ANS_DENY = 0x21U, // Deny
ANS_WAIT = 0x22U // Wait
};
}
/// <summary>
/// Cancel Service Codes
/// </summary>
namespace CancelService {
enum : uint8_t {
NONE = 0x00U, // None
TERM_QUE = 0x10U, // Terminate Queued
TERM_RSRC_ASSIGN = 0x20U // Terminate Resource Assigned
};
}
/// <summary>
/// Reason Codes
/// </summary>
namespace ReasonCode {
enum : uint8_t {
// Denial Codes
DENY_REQ_UNIT_NOT_VALID = 0x10U, // Requesting Unit Not Valid
DENY_REQ_UNIT_NOT_AUTH = 0x11U, // Requesting Unit Not Authenticated
DENY_TGT_UNIT_NOT_VALID = 0x20U, // Target Unit Not Vaild
DENY_TGT_UNIT_NOT_AUTH = 0x21U, // Target Unit Not Authenticated
DENY_SU_FAILED_AUTH = 0x22U, // Subscriber Failed Authentication
DENY_TGT_UNIT_REFUSED = 0x2FU, // Target Unit Refused
DENY_TGT_GROUP_NOT_VALID = 0x30U, // Target Group Not Valid
DENY_TGT_GROUP_NOT_AUTH = 0x31U, // Target Group Not Authenticated
DENY_NO_NET_RSRC_AVAIL = 0x53U, // No Network Resources Available
DENY_NO_RF_RSRC_AVAIL = 0x54U, // No RF Resources Available
DENY_SVC_IN_USE = 0x55U, // Service In Use
DENY_SITE_ACCESS_DENIAL = 0x60U, // Site Access Denial
DENY_PTT_COLLIDE = 0x67U, // Push-to-Talk Collision
DENY_PTT_BONK = 0x77U, // Push-to-Talk Denial/Bonk
DENY_SYS_UNSUPPORTED_SVC = 0xFFU, // Service Unsupported
// Queue Codes
QUE_REQ_ACTIVE_SERVICE = 0x10U, // Requested Service Active
QUE_TGT_ACTIVE_SERVICE = 0x20U, // Target Service Active
QUE_TGT_UNIT_QUEUED = 0x2FU, // Target Unit Queued
QUE_CHN_RESOURCE_NOT_AVAIL = 0x40U // Channel Resource Not Available
};
}
/// <summary>
/// Extended Functions
/// </summary>
namespace ExtendedFunctions {
enum : uint16_t {
CHECK = 0x0000U, // Radio Check
UNINHIBIT = 0x007EU, // Radio Uninhibit
INHIBIT = 0x007FU, // Radio Inhibit
CHECK_ACK = 0x0080U, // Radio Check Ack
UNINHIBIT_ACK = 0x00FEU, // Radio Uninhibit Ack
INHIBIT_ACK = 0x00FFU // Radio Inhibit Ack
};
}
/** Default Values */
const uint32_t NAC_DIGITAL_SQ = 0xF7EU; // Digital Squelch NAC
const uint32_t NAC_REUSE_RX_NAC = 0xF7FU; // Reuse RX NAC
const uint32_t DEFAULT_NAC = 0x293U; // Default NAC
const uint32_t WACN_STD_DEFAULT = 0xBB800U; // Default WACN
const uint32_t SID_STD_DEFAULT = 0x001U; // Default System ID
const uint32_t WUID_FNE = 0xFFFFFCU; // FNE Working Unit ID
const uint32_t WUID_REG = 0xFFFFFEU; // Registration Working Unit ID
const uint32_t WUID_ALL = 0xFFFFFFU; // All-call Working Unit ID
const uint32_t TGID_ALL = 0xFFFFU; // All-call Talkgroup ID
/// <summary>
/// DVM Network Frame Types
/// </summary>
namespace FrameType {
// DVM Network Frame Types Enumeration
enum E : uint8_t {
HDU_VALID = 0x01U, // HDU Valid
HDU_LATE_ENTRY = 0x02U, // HDU Late Entry
TERMINATOR = 0x03U, // TDU/TDULC Terminator
DATA_UNIT = 0x00U // Standard Data Unit
};
}
/// <summary>
/// Data Format Type
/// </summary>
namespace PDUFormatType {
enum : uint8_t {
RSP = 0x03U, // Response
UNCONFIRMED = 0x15U, // Unconfirmed PDU
CONFIRMED = 0x16U, // Confirmed PDU
AMBT = 0x17U // Alternate Multi Block Trunking
};
}
/// <summary>
/// Service Access Point
/// </summary>
namespace PDUSAP {
enum : uint8_t {
USER_DATA = 0x00U, // User Data
ENC_USER_DATA = 0x01U, // Encrypted User Data
PACKET_DATA = 0x04U, // Packet Data
ARP = 0x05U, // ARP
SNDCP_CTRL_DATA = 0x06U, // SNDCP Control Data
EXT_ADDR = 0x1FU, // Extended Addressing
REG = 0x20U, // Registration
UNENC_KMM = 0x28U, // Unencrypted KMM
ENC_KMM = 0x29U, // Encrypted KMM
TRUNK_CTRL = 0x3DU // Trunking Control
};
}
/// <summary>
/// Acknowledgement Class
/// </summary>
namespace PDUAckClass {
enum : uint8_t {
ACK = 0x00U, // Acknowledge
NACK = 0x01U, // Negative Acknowledge
ACK_RETRY = 0x02U // Acknowledge Retry
};
}
/// <summary>
/// Acknowledgement Type
/// </summary>
namespace PDUAckType {
enum : uint8_t {
RETRY = 0x00U, // Retry
ACK = 0x01U, // Acknowledge
NACK_ILLEGAL = 0x00U, // Illegal Format
NACK_PACKET_CRC = 0x01U, // Packet CRC
NACK_MEMORY_FULL = 0x02U, // Memory Full
NACK_SEQ = 0x03U, // Out of logical sequence FSN
NACK_UNDELIVERABLE = 0x04U, // Undeliverable
NACK_OUT_OF_SEQ = 0x05U, // Out of sequence, N(S) != V(R) or V(R) + 1
NACK_INVL_USER = 0x06U // Invalid User disallowed by the system
};
}
/// <summary>
/// Registration Type
/// </summary>
namespace PDURegType {
enum : uint8_t {
CNCT = 0x00U, // Connect
DISCNCT = 0x01U, // Disconnect
ACCPT = 0x04U, // Accept
DENY = 0x05U // Deny
};
}
/// <summary>
/// SNDCP Type
/// </summary>
namespace PDUSNDCPType {
enum : uint8_t {
ACT_TDS_CTX_ACCPT = 0x00U, // Activate Context Accept
DEACT_TDS_CTX_ACCPT = 0x01U, // Deactivate Context Accept
DEACT_TDS_CTX_REQ = 0x02U, // Deactivate Context Request
ACT_TDS_CTX_REJECT = 0x03U, // Activate Context Reject
RF_UNCONFIRMED = 0x04U, // RF Unconfirmed
RF_CONFIRMED = 0x05U // RF Confirmed
};
}
const uint8_t LC_SVC_OPT_EMERGENCY = 0x80U;
const uint8_t LC_SVC_OPT_ENCRYPTION = 0x40U;
/// <summary>
/// LDUx/TDULC Link Control Opcode(s)
/// </summary>
namespace LCO {
enum : uint8_t {
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
#endif // __P25_DEFINES_H__

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

@ -28,6 +28,8 @@ namespace p25
class HOST_SW_API P25Utils {
public:
/// <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)
{
if (nac < 0U) { // clamp to $000
@ -41,6 +43,8 @@ namespace p25
}
/// <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)
{
if (id == 0U) { // clamp to 1
@ -54,6 +58,8 @@ namespace p25
}
/// <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)
{
if (id == 0U) { // clamp to 1
@ -67,6 +73,8 @@ namespace p25
}
/// <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)
{
if (id == 0U) { // clamp to 1
@ -80,6 +88,8 @@ namespace p25
}
/// <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)
{
if (id == 0U) { // clamp to 1

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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__)
@ -31,13 +31,13 @@ namespace p25
/// <summary>Initializes a new instance of the SiteData class.</summary>
SiteData() :
m_lra(0U),
m_netId(P25_WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT),
m_netId(defines::WACN_STD_DEFAULT),
m_sysId(defines::SID_STD_DEFAULT),
m_rfssId(1U),
m_siteId(1U),
m_channelId(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_callsign("CHANGEME"),
m_chCnt(0U),
@ -58,13 +58,13 @@ namespace p25
/// <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) :
m_lra(0U),
m_netId(P25_WACN_STD_DEFAULT),
m_sysId(P25_SID_STD_DEFAULT),
m_netId(defines::WACN_STD_DEFAULT),
m_sysId(defines::SID_STD_DEFAULT),
m_rfssId(1U),
m_siteId(1U),
m_channelId(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_callsign("CHANGEME"),
m_chCnt(0U),
@ -110,7 +110,7 @@ namespace p25
std::random_device 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);
// netId clamping

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -17,8 +17,9 @@
#include "Log.h"
#include "Utils.h"
using namespace p25::data;
using namespace p25;
using namespace p25::defines;
using namespace p25::data;
#include <cassert>
#include <cstring>
@ -36,7 +37,7 @@ DataBlock::DataBlock() :
m_llId(0U),
m_sap(0U),
m_trellis(),
m_fmt(PDU_FMT_CONFIRMED),
m_fmt(PDUFormatType::CONFIRMED),
m_headerSap(0U),
m_data(nullptr)
{
@ -73,7 +74,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
m_lastBlock = false;
m_llId = 0U;
if (m_fmt == PDU_FMT_CONFIRMED) {
if (m_fmt == PDUFormatType::CONFIRMED) {
// decode 3/4 rate Trellis
try {
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);
// 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_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
uint16_t calculated = edac::CRC::createCRC9(crcBuffer, 135U);
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
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);
#endif
}
@ -131,7 +132,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
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
try {
bool valid = m_trellis.decode12(data, buffer);
@ -154,7 +155,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
}
}
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;
@ -169,14 +170,14 @@ void DataBlock::encode(uint8_t* data)
assert(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];
::memset(buffer, 0x00U, P25_PDU_CONFIRMED_LENGTH_BYTES);
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 (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[2U] = (m_llId >> 16) & 0xFFU; // Logical Link ID
@ -212,7 +213,7 @@ void DataBlock::encode(uint8_t* 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];
::memset(buffer, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES);
@ -225,7 +226,7 @@ void DataBlock::encode(uint8_t* data)
m_trellis.encode12(buffer, data);
}
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;
}
}
@ -266,14 +267,14 @@ void DataBlock::setData(const uint8_t* buffer)
assert(buffer != 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);
}
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);
}
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(m_data != nullptr);
if (m_fmt == PDU_FMT_CONFIRMED) {
if (m_fmt == PDUFormatType::CONFIRMED) {
::memcpy(buffer, m_data, 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);
return P25_PDU_UNCONFIRMED_LENGTH_BYTES;
}
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;
}
}

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -17,8 +17,9 @@
#include "Log.h"
#include "Utils.h"
using namespace p25::data;
using namespace p25;
using namespace p25::defines;
using namespace p25::data;
#include <cassert>
#include <cstring>
@ -43,9 +44,9 @@ bool DataHeader::m_warnCRC = false;
DataHeader::DataHeader() :
m_ackNeeded(false),
m_outbound(false),
m_fmt(PDU_FMT_CONFIRMED),
m_fmt(PDUFormatType::CONFIRMED),
m_sap(0U),
m_mfId(P25_MFG_STANDARD),
m_mfId(MFG_STANDARD),
m_llId(0U),
m_blocksToFollow(0U),
m_padLength(0U),
@ -56,8 +57,8 @@ DataHeader::DataHeader() :
m_lastFragment(true),
m_headerOffset(0U),
m_srcLlId(0U),
m_rspClass(PDU_ACK_CLASS_NACK),
m_rspType(PDU_ACK_TYPE_NACK_ILLEGAL),
m_rspClass(PDUAckClass::NACK),
m_rspType(PDUAckType::NACK_ILLEGAL),
m_rspStatus(0U),
m_ambtOpcode(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_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;
}
switch (m_fmt) {
case PDU_FMT_CONFIRMED:
case PDUFormatType::CONFIRMED:
m_S = (m_data[8U] & 0x80U) == 0x80U; // Re-synchronize Flag
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
break;
case PDU_FMT_RSP:
case PDUFormatType::RSP:
m_ackNeeded = false;
m_sap = PDU_SAP_USER_DATA;
m_sap = PDUSAP::USER_DATA;
m_rspClass = (m_data[1U] >> 6) & 0x03U; // Response Class
m_rspType = (m_data[1U] >> 3) & 0x07U; // Response Type
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
}
break;
case PDU_FMT_AMBT:
case PDUFormatType::AMBT:
m_ambtOpcode = m_data[7U] & 0x3FU; // AMBT Opcode
m_ambtField8 = m_data[8U]; // AMBT Field 8
m_ambtField9 = m_data[9U]; // AMBT Field 9
// fall-thru
case PDU_FMT_UNCONFIRMED:
case PDUFormatType::UNCONFIRMED:
default:
m_ackNeeded = false;
m_S = false;
@ -190,12 +191,12 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
uint8_t header[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;
}
if (m_fmt == PDU_FMT_CONFIRMED && !m_ackNeeded) {
LogWarning(LOG_P25, "DataHeader::encode(), invalid values for PDU_FMT_CONFIRMED, ackNeeded = %u", m_ackNeeded);
if (m_fmt == PDUFormatType::CONFIRMED && !m_ackNeeded) {
LogWarning(LOG_P25, "DataHeader::encode(), invalid values for confirmed PDU, ackNeeded = %u", m_ackNeeded);
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
switch (m_fmt) {
case PDU_FMT_CONFIRMED:
case PDUFormatType::CONFIRMED:
header[7U] = (m_padLength & 0x1FU); // Pad Byte Count
header[8U] = (m_S ? 0x80U : 0x00U) + // Re-synchronize Flag
((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
break;
case PDU_FMT_RSP:
case PDUFormatType::RSP:
header[1U] = ((m_rspClass & 0x03U) << 6) + // Response Class
((m_rspType & 0x07U) << 3) + // Response Type
((m_rspStatus & 0x07U)); // Response Status
@ -235,12 +236,12 @@ void DataHeader::encode(uint8_t* data, bool noTrellis)
header[9U] = (m_srcLlId >> 0) & 0xFFU;
}
break;
case PDU_FMT_AMBT:
case PDUFormatType::AMBT:
header[7U] = (m_ambtOpcode & 0x3FU); // AMBT Opcode
header[8U] = m_ambtField8; // AMBT Field 8
header[9U] = m_ambtField9; // AMBT Field 9
break;
case PDU_FMT_UNCONFIRMED:
case PDUFormatType::UNCONFIRMED:
default:
header[7U] = (m_padLength & 0x1FU); // Pad Byte Count
header[8U] = 0x00U;
@ -271,10 +272,10 @@ void DataHeader::reset()
m_ackNeeded = false;
m_outbound = false;
m_fmt = PDU_FMT_CONFIRMED;
m_fmt = PDUFormatType::CONFIRMED;
m_sap = PDU_SAP_USER_DATA;
m_mfId = P25_MFG_STANDARD;
m_sap = PDUSAP::USER_DATA;
m_mfId = MFG_STANDARD;
m_llId = 0U;
m_F = true;
@ -290,8 +291,8 @@ void DataHeader::reset()
m_headerOffset = 0U;
m_srcLlId = 0U;
m_rspClass = PDU_ACK_CLASS_NACK;
m_rspType = PDU_ACK_TYPE_NACK_ILLEGAL;
m_rspClass = PDUAckClass::NACK;
m_rspType = PDUAckType::NACK_ILLEGAL;
m_rspStatus = 0U;
m_ambtOpcode = 0U;
@ -307,7 +308,7 @@ void DataHeader::reset()
/// <returns></returns>
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;
}
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 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);
}
else {

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

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -17,8 +17,10 @@
#include "Log.h"
#include "Utils.h"
using namespace p25::dfsi;
using namespace p25;
using namespace p25::defines;
using namespace p25::dfsi;
using namespace p25::dfsi::defines;
#include <cassert>
#include <cstring>
@ -37,8 +39,8 @@ LC::LC() :
m_rs(),
m_mi(nullptr)
{
m_mi = new uint8_t[P25_MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES);
m_mi = new uint8_t[MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, MI_LENGTH_BYTES);
m_control = new lc::LC();
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
switch (m_frameType)
{
case P25_DFSI_LDU1_VOICE1:
case DFSIFrameType::LDU1_VOICE1:
{
if (m_control != nullptr) {
delete m_control;
@ -130,15 +132,15 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
}
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;
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;
case P25_DFSI_LDU1_VOICE3:
case DFSIFrameType::LDU1_VOICE3:
{
m_control->setLCO(data[1U]); // LCO
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->setEncrypted((serviceOptions & 0x40U) == 0x40U);
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;
case P25_DFSI_LDU1_VOICE4:
case DFSIFrameType::LDU1_VOICE4:
{
uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
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;
case P25_DFSI_LDU1_VOICE5:
case DFSIFrameType::LDU1_VOICE5:
{
uint32_t srcId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
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;
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;
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;
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;
case P25_DFSI_LDU1_VOICE9:
case DFSIFrameType::LDU1_VOICE9:
{
m_lsd->setLSD1(data[1U]); // LSD MSB
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;
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;
}
break;
@ -213,39 +215,39 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
(m_control->getPriority() & 0x07U);
// 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)
{
case P25_DFSI_LDU1_VOICE1:
frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE1:
frameLength = DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE2:
frameLength = P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE2:
frameLength = DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE3:
frameLength = P25_DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE3:
frameLength = DFSI_LDU1_VOICE3_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE4:
frameLength = P25_DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE4:
frameLength = DFSI_LDU1_VOICE4_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE5:
frameLength = P25_DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE5:
frameLength = DFSI_LDU1_VOICE5_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE6:
frameLength = P25_DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE6:
frameLength = DFSI_LDU1_VOICE6_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE7:
frameLength = P25_DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE7:
frameLength = DFSI_LDU1_VOICE7_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE8:
frameLength = P25_DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE8:
frameLength = DFSI_LDU1_VOICE8_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE9:
frameLength = P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU1_VOICE9:
frameLength = DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
break;
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;
}
break;
@ -276,72 +278,72 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
// different frame types mean different things
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;
case P25_DFSI_LDU1_VOICE3:
case DFSIFrameType::LDU1_VOICE3:
{
dfsiFrame[1U] = rs[0U]; // LCO
dfsiFrame[2U] = rs[1U]; // MFId
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;
case P25_DFSI_LDU1_VOICE4:
case DFSIFrameType::LDU1_VOICE4:
{
dfsiFrame[1U] = rs[3U]; // Target Address
dfsiFrame[2U] = rs[4U];
dfsiFrame[3U] = rs[5U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE5:
case DFSIFrameType::LDU1_VOICE5:
{
dfsiFrame[1U] = rs[6U]; // Source Address
dfsiFrame[2U] = rs[7U];
dfsiFrame[3U] = rs[8U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE6:
case DFSIFrameType::LDU1_VOICE6:
{
dfsiFrame[1U] = rs[9U]; // RS (24,12,13)
dfsiFrame[2U] = rs[10U]; // 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;
case P25_DFSI_LDU1_VOICE7:
case DFSIFrameType::LDU1_VOICE7:
{
dfsiFrame[1U] = rs[12U]; // RS (24,12,13)
dfsiFrame[2U] = rs[13U]; // 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;
case P25_DFSI_LDU1_VOICE8:
case DFSIFrameType::LDU1_VOICE8:
{
dfsiFrame[1U] = rs[15U]; // RS (24,12,13)
dfsiFrame[2U] = rs[16U]; // 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;
case P25_DFSI_LDU1_VOICE9:
case DFSIFrameType::LDU1_VOICE9:
{
dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB
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;
case P25_DFSI_LDU1_VOICE1:
case DFSIFrameType::LDU1_VOICE1:
default:
{
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;
}
@ -371,76 +373,76 @@ bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe)
// different frame types mean different things
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) {
delete m_lsd;
}
m_lsd = new data::LowSpeedData();
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;
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;
case P25_DFSI_LDU2_VOICE12:
case DFSIFrameType::LDU2_VOICE12:
{
m_mi[0U] = data[1U]; // Message Indicator
m_mi[1U] = data[2U];
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;
case P25_DFSI_LDU2_VOICE13:
case DFSIFrameType::LDU2_VOICE13:
{
m_mi[3U] = data[1U]; // Message Indicator
m_mi[4U] = data[2U];
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;
case P25_DFSI_LDU2_VOICE14:
case DFSIFrameType::LDU2_VOICE14:
{
m_mi[6U] = data[1U]; // Message Indicator
m_mi[7U] = data[2U];
m_mi[8U] = data[3U];
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;
case P25_DFSI_LDU2_VOICE15:
case DFSIFrameType::LDU2_VOICE15:
{
m_control->setAlgId(data[1U]); // Algorithm ID
uint32_t kid = (data[2U] << 8) | (data[3U] << 0); // Key ID
m_control->setKId(kid);
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(imbe, data + 5U, RAW_IMBE_LENGTH_BYTES); // IMBE
}
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;
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;
case P25_DFSI_LDU2_VOICE18:
case DFSIFrameType::LDU2_VOICE18:
{
m_lsd->setLSD1(data[1U]); // LSD MSB
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;
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;
}
break;
@ -461,44 +463,44 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
assert(m_control != nullptr);
// generate MI data
uint8_t mi[P25_MI_LENGTH_BYTES];
::memset(mi, 0x00U, P25_MI_LENGTH_BYTES);
uint8_t mi[MI_LENGTH_BYTES];
::memset(mi, 0x00U, MI_LENGTH_BYTES);
m_control->getMI(mi);
// 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)
{
case P25_DFSI_LDU2_VOICE10:
frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE10:
frameLength = DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE11:
frameLength = P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE11:
frameLength = DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE12:
frameLength = P25_DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE12:
frameLength = DFSI_LDU2_VOICE12_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE13:
frameLength = P25_DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE13:
frameLength = DFSI_LDU2_VOICE13_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE14:
frameLength = P25_DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE14:
frameLength = DFSI_LDU2_VOICE14_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE15:
frameLength = P25_DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE15:
frameLength = DFSI_LDU2_VOICE15_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE16:
frameLength = P25_DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE16:
frameLength = DFSI_LDU2_VOICE16_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE17:
frameLength = P25_DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE17:
frameLength = DFSI_LDU2_VOICE17_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE18:
frameLength = P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
case DFSIFrameType::LDU2_VOICE18:
frameLength = DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
break;
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;
}
break;
@ -507,7 +509,7 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
uint8_t rs[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[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
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;
case P25_DFSI_LDU2_VOICE12:
case DFSIFrameType::LDU2_VOICE12:
{
dfsiFrame[1U] = rs[0U]; // Message Indicator
dfsiFrame[2U] = rs[1U];
dfsiFrame[3U] = rs[2U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE13:
case DFSIFrameType::LDU2_VOICE13:
{
dfsiFrame[1U] = rs[3U]; // Message Indicator
dfsiFrame[2U] = rs[4U];
dfsiFrame[3U] = rs[5U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE14:
case DFSIFrameType::LDU2_VOICE14:
{
dfsiFrame[1U] = rs[6U]; // Message Indicator
dfsiFrame[2U] = rs[7U];
dfsiFrame[3U] = rs[8U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE15:
case DFSIFrameType::LDU2_VOICE15:
{
dfsiFrame[1U] = rs[9U]; // Algorithm ID
dfsiFrame[2U] = rs[10U]; // Key ID
dfsiFrame[3U] = rs[11U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
::memcpy(dfsiFrame + 5U, imbe, RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE16:
case DFSIFrameType::LDU2_VOICE16:
{
dfsiFrame[1U] = rs[12U]; // RS (24,16,9)
dfsiFrame[2U] = rs[13U]; // 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;
case P25_DFSI_LDU2_VOICE17:
case DFSIFrameType::LDU2_VOICE17:
{
dfsiFrame[1U] = rs[15U]; // RS (24,16,9)
dfsiFrame[2U] = rs[16U]; // 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;
case P25_DFSI_LDU2_VOICE18:
case DFSIFrameType::LDU2_VOICE18:
{
dfsiFrame[1U] = m_lsd->getLSD1(); // LSD MSB
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;
case P25_DFSI_LDU2_VOICE10:
case DFSIFrameType::LDU2_VOICE10:
default:
{
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;
}
@ -621,8 +623,8 @@ void LC::copy(const LC& data)
delete[] m_mi;
uint8_t* mi = new uint8_t[P25_MI_LENGTH_BYTES];
::memcpy(mi, data.m_mi, P25_MI_LENGTH_BYTES);
uint8_t* mi = new uint8_t[MI_LENGTH_BYTES];
::memcpy(mi, data.m_mi, MI_LENGTH_BYTES);
m_mi = mi;
}

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -17,8 +17,9 @@
#include "Log.h"
#include "Utils.h"
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cassert>
@ -101,7 +102,7 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo
assert(blocks != 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");
return false;
}
@ -150,11 +151,11 @@ void AMBT::encode(data::DataHeader& dataHeader, uint8_t* pduUserData)
{
assert(pduUserData != nullptr);
dataHeader.setFormat(PDU_FMT_AMBT);
dataHeader.setFormat(PDUFormatType::AMBT);
dataHeader.setMFId(m_mfId); // Mfg Id.
dataHeader.setAckNeeded(false);
dataHeader.setOutbound(true);
dataHeader.setSAP(PDU_SAP_TRUNK_CTRL);
dataHeader.setSAP(PDUSAP::TRUNK_CTRL);
dataHeader.setLLId(m_srcId);
dataHeader.setFullMessage(true);

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

@ -7,7 +7,7 @@
* @package DVM / Common Library
* @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"
@ -18,8 +18,9 @@
#include "Log.h"
#include "Utils.h"
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
#include <cassert>
#include <cstring>
@ -74,8 +75,8 @@ TDULC::TDULC(LC* lc) : TDULC()
/// </summary>
TDULC::TDULC() :
m_protect(false),
m_lco(LC_GROUP),
m_mfId(P25_MFG_STANDARD),
m_lco(LCO::GROUP),
m_mfId(MFG_STANDARD),
m_srcId(0U),
m_dstId(0U),
m_grpVchNo(0U),

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

@ -7,16 +7,17 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_ADJ_STS_BCAST.h"
#include "Log.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,15 +29,15 @@ using namespace p25;
/// Initializes a new instance of the LC_ADJ_STS_BCAST class.
/// </summary>
LC_ADJ_STS_BCAST::LC_ADJ_STS_BCAST() : TDULC(),
m_adjCFVA(P25_CFVA_FAILURE),
m_adjCFVA(CFVA::FAILURE),
m_adjSysId(0U),
m_adjRfssId(0U),
m_adjSiteId(0U),
m_adjChannelId(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>
@ -79,7 +80,7 @@ void LC_ADJ_STS_BCAST::encode(uint8_t* data)
rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class
}
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);
return; // blatantly ignore creating this TSBK
}

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_CALL_TERM.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_CALL_TERM::LC_CALL_TERM() : TDULC()
{
m_lco = p25::LC_CALL_TERM;
m_lco = LCO::CALL_TERM;
}
/// <summary>
@ -58,7 +59,7 @@ void LC_CALL_TERM::encode(uint8_t* data)
m_implicit = true;
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);
TDULC::encode(data, rs.get());

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_CONV_FALLBACK.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_CONV_FALLBACK::LC_CONV_FALLBACK() : TDULC()
{
m_lco = p25::LC_CONV_FALLBACK;
m_lco = LCO::CONV_FALLBACK;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_FAILSOFT.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,8 +29,8 @@ using namespace p25;
/// </summary>
LC_FAILSOFT::LC_FAILSOFT() : TDULC()
{
m_lco = p25::LC_FAILSOFT;
m_mfId = p25::P25_MFG_MOT;
m_lco = LCO::FAILSOFT;
m_mfId = MFG_MOT;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_GROUP.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_GROUP::LC_GROUP() : TDULC()
{
m_lco = p25::LC_GROUP;
m_lco = LCO::GROUP;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_GROUP_UPDT.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_GROUP_UPDT::LC_GROUP_UPDT() : TDULC()
{
m_lco = p25::LC_GROUP_UPDT;
m_lco = LCO::GROUP_UPDT;
}
/// <summary>

@ -7,16 +7,17 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_IDEN_UP.h"
#include "Log.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
#include <cmath>
@ -30,7 +31,7 @@ using namespace p25;
/// </summary>
LC_IDEN_UP::LC_IDEN_UP() : TDULC()
{
m_lco = p25::LC_IDEN_UP;
m_lco = LCO::IDEN_UP;
}
/// <summary>
@ -70,7 +71,7 @@ void LC_IDEN_UP::encode(uint8_t* data)
uCalcTxOffset |= 0x2000U; // this sets a positive offset ...
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 = (rsValue << 4) + chanBw; // Channel Bandwidth

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_NET_STS_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_NET_STS_BCAST::LC_NET_STS_BCAST() : TDULC()
{
m_lco = p25::LC_NET_STS_BCAST;
m_lco = LCO::NET_STS_BCAST;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_PRIVATE.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_PRIVATE::LC_PRIVATE() : TDULC()
{
m_lco = p25::LC_PRIVATE;
m_lco = LCO::PRIVATE;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_RFSS_STS_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_RFSS_STS_BCAST::LC_RFSS_STS_BCAST() : TDULC()
{
m_lco = p25::LC_RFSS_STS_BCAST;
m_lco = LCO::RFSS_STS_BCAST;
}
/// <summary>

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_SYS_SRV_BCAST.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
LC_SYS_SRV_BCAST::LC_SYS_SRV_BCAST() : TDULC()
{
m_lco = p25::LC_SYS_SRV_BCAST;
m_lco = LCO::SYS_SRV_BCAST;
}
/// <summary>
@ -53,7 +54,7 @@ void LC_SYS_SRV_BCAST::encode(uint8_t* data)
{
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;

@ -7,15 +7,16 @@
* @package DVM / Common Library
* @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 "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h"
using namespace p25::lc::tdulc;
using namespace p25::lc;
using namespace p25;
using namespace p25::defines;
using namespace p25::lc;
using namespace p25::lc::tdulc;
#include <cassert>
@ -28,7 +29,7 @@ using namespace p25;
/// </summary>
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>

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

Loading…
Cancel
Save

Powered by TurnKey Linux.