diff --git a/configs/dfsi-config.example.yml b/configs/dfsi-config.example.yml
index c2a286e5..9c8aa3f7 100644
--- a/configs/dfsi-config.example.yml
+++ b/configs/dfsi-config.example.yml
@@ -60,8 +60,11 @@ dfsi:
remoteRtpPort: 27500
serial:
+ # Modem port type.
+ portType: "uart" # Valid values are "null", and "uart"
# Serial configuration for serial DFSI
port: "/dev/ttyACM0"
+ #
baudrate: 115200
# RT/RT flag enabled (0x02) or disabled (0x04)
rtrt: false
diff --git a/src/dfsi/Dfsi.cpp b/src/dfsi/Dfsi.cpp
index 5936a1fc..64846bc1 100644
--- a/src/dfsi/Dfsi.cpp
+++ b/src/dfsi/Dfsi.cpp
@@ -225,49 +225,11 @@ int Dfsi::run()
UInt8Array p25Buffer = m_network->readP25(netReadRet, length);
if (netReadRet) {
- uint8_t duid = p25Buffer[22U];
- uint8_t MFId = p25Buffer[15U];
-
- uint8_t lco = p25Buffer[4U];
-
- uint32_t srcId = __GET_UINT16(p25Buffer, 5U);
- uint32_t dstId = __GET_UINT16(p25Buffer, 8U);
-
- if (!g_hideMessages)
- LogMessage(LOG_NET, "P25, duid = $%02X, lco = $%02X, MFId = $%02X, srcId = %u, dstId = %u, len = %u", duid, lco, MFId, srcId, dstId, length);
-
// Send the data to the serial handler if serial is up
if (m_serial != nullptr)
m_serial->processP25FromNet(std::move(p25Buffer), length);
}
- // We keep DMR & NXDN in so nothing breaks, even though DFSI doesn't do DMR or NXDN
- UInt8Array dmrBuffer = m_network->readDMR(netReadRet, length);
- if (netReadRet) {
- uint8_t seqNo = dmrBuffer[4U];
-
- uint32_t srcId = __GET_UINT16(dmrBuffer, 5U);
- uint32_t dstId = __GET_UINT16(dmrBuffer, 8U);
-
- uint8_t flco = (dmrBuffer[15U] & 0x40U) == 0x40U ? dmr::FLCO_PRIVATE : dmr::FLCO_GROUP;
-
- uint32_t slotNo = (dmrBuffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
-
- if (!g_hideMessages)
- LogMessage(LOG_NET, "DMR, slotNo = %u, seqNo = %u, flco = $%02X, srcId = %u, dstId = %u, len = %u", slotNo, seqNo, flco, srcId, dstId, length);
- }
-
- UInt8Array nxdnBuffer = m_network->readNXDN(netReadRet, length);
- if (netReadRet) {
- uint8_t messageType = nxdnBuffer[4U];
-
- uint32_t srcId = __GET_UINT16(nxdnBuffer, 5U);
- uint32_t dstId = __GET_UINT16(nxdnBuffer, 8U);
-
- if (!g_hideMessages)
- LogMessage(LOG_NET, "NXDN, messageType = $%02X, srcId = %u, dstId = %u, len = %u", messageType, srcId, dstId, length);
- }
-
// ------------------------------------------------------
// -- Network TX Clocking --
// ------------------------------------------------------
@@ -414,11 +376,18 @@ bool Dfsi::createPeerNetwork()
return true;
}
+///
+/// Initializes serial V24 network.
+///
+///
+///
+///
bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout)
{
// Read serial config
yaml::Node dfsi_conf = m_conf["dfsi"];
yaml::Node serial_conf = dfsi_conf["serial"];
+ std::string portType = serial_conf["portType"].as("null");
std::string port = serial_conf["port"].as();
uint32_t baudrate = serial_conf["baudrate"].as();
bool rtrt = serial_conf["rtrt"].as();
@@ -428,6 +397,7 @@ bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout)
bool serial_trace = serial_conf["trace"].as();
LogInfo("Serial Parameters");
+ LogInfo(" Port Type: %s", portType.c_str());
LogInfo(" Port: %s", port.c_str());
LogInfo(" Baudrate: %u", baudrate);
LogInfo(" RT/RT: %s", rtrt ? "Enabled" : "Disabled");
@@ -437,7 +407,7 @@ bool Dfsi::createSerialNetwork(uint32_t p25BufferSize, uint16_t callTimeout)
LogInfo(" Trace: %s", serial_trace ? "Enabled" : "Disabled");
// Create serial service
- m_serial = new SerialService(port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, callTimeout, serial_debug, serial_trace);
+ m_serial = new SerialService(portType, port, baudrate, rtrt, diu, jitter, m_network, p25BufferSize, p25BufferSize, callTimeout, serial_debug, serial_trace);
// Open serial
bool ret = m_serial->open();
diff --git a/src/dfsi/DfsiMain.cpp b/src/dfsi/DfsiMain.cpp
index 4a963d75..3fdcc15e 100644
--- a/src/dfsi/DfsiMain.cpp
+++ b/src/dfsi/DfsiMain.cpp
@@ -152,9 +152,6 @@ int checkArgs(int argc, char* argv[])
else if (IS("--syslog")) {
g_useSyslog = true;
}
- else if (IS("-s")) {
- g_hideMessages = true;
- }
else if (IS("-c")) {
if (argc-- <= 0)
usage("error: %s", "must specify the configuration file to use");
diff --git a/src/dfsi/DfsiMain.h b/src/dfsi/DfsiMain.h
index 60e2a8b1..83ad38bd 100644
--- a/src/dfsi/DfsiMain.h
+++ b/src/dfsi/DfsiMain.h
@@ -29,7 +29,6 @@ extern std::string g_lockFile;
extern bool g_foreground;
extern bool g_killed;
-extern bool g_hideMessages;
extern std::string g_masterAddress;
extern uint16_t g_masterPort;
diff --git a/src/dfsi/frames/BlockHeader.cpp b/src/dfsi/frames/BlockHeader.cpp
new file mode 100644
index 00000000..47a557b8
--- /dev/null
+++ b/src/dfsi/frames/BlockHeader.cpp
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+
+#include "frames/BlockHeader.h"
+#include "common/p25/dfsi/DFSIDefines.h"
+#include "common/Utils.h"
+#include "common/Log.h"
+
+#include
+#include
+
+using namespace p25;
+using namespace dfsi;
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a instance of the BlockHeader class.
+///
+BlockHeader::BlockHeader() :
+ m_payloadType(false),
+ m_blockLength(UNDEFINED)
+{
+ /* stub */
+}
+
+///
+/// Initializes a instance of the BlockHeader class.
+///
+///
+///
+BlockHeader::BlockHeader(uint8_t* data, bool verbose) :
+ m_payloadType(false),
+ m_blockLength(UNDEFINED)
+{
+ decode(data, verbose);
+}
+
+///
+/// Decode a block header frame.
+///
+///
+///
+///
+bool BlockHeader::decode(const uint8_t* data, bool verbose)
+{
+ assert(data != nullptr);
+
+ uint64_t value = 0U;
+
+ // combine bytes into ulong (8 byte) value
+ value = data[0U];
+ value = (value << 8) + data[1U];
+ value = (value << 8) + data[2U];
+ value = (value << 8) + data[3U];
+
+ m_payloadType = (data[0U] & 0x80U) == 0x80U; // Payload Type
+ m_blockType = (BlockType)(data[0U] & 0x7FU); // Block Type
+
+ if (verbose) {
+ m_timestampOffset = (uint32_t)((value >> 10) & 0x3FFU); // Timestamp Offset
+ m_blockLength = (uint32_t)(value & 0x3FFU); // Block Length
+ }
+
+ return true;
+}
+
+///
+/// Encode a block header frame.
+///
+///
+///
+void BlockHeader::encode(uint8_t* data, bool verbose)
+{
+ assert(data != nullptr);
+
+ if (!verbose) {
+ data[0U] = (uint8_t)((m_payloadType ? 0x80U : 0x00U) + // Payload Type
+ ((uint8_t)m_blockType & 0x7FU)); // Block Type
+ }
+ else {
+ uint64_t value = 0;
+
+ value = (uint8_t)((m_payloadType ? 0x80U : 0x00U) + // Payload Type
+ ((uint8_t)m_blockType & 0x7FU)); // Block Type
+ value = (value << 24) + (m_timestampOffset & 0x3FFU); // Timestamp Offset
+ value = (value << 10) + (m_blockLength & 0x3FFU); // Block Length
+
+ // split ulong (8 byte) value into bytes
+ data[0U] = (uint8_t)((value >> 24) & 0xFFU);
+ data[1U] = (uint8_t)((value >> 16) & 0xFFU);
+ data[2U] = (uint8_t)((value >> 8) & 0xFFU);
+ data[3U] = (uint8_t)((value >> 0) & 0xFFU);
+ }
+}
diff --git a/src/dfsi/frames/BlockHeader.h b/src/dfsi/frames/BlockHeader.h
new file mode 100644
index 00000000..cdab1824
--- /dev/null
+++ b/src/dfsi/frames/BlockHeader.h
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+#if !defined(__BLOCK_HEADER_H__)
+#define __BLOCK_HEADER_H__
+
+#include "Defines.h"
+#include "common/Defines.h"
+#include "common/Log.h"
+#include "common/Utils.h"
+#include "frames/FrameDefines.h"
+
+namespace p25
+{
+ namespace dfsi
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements a DFSI block header packet.
+ //
+ // Compact Form
+ // Byte 0
+ // Bit 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+
+ // |E| BT |
+ // +-+-+-+-+-+-+-+-+
+ //
+ // Verbose Form
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // |E| BT | TSO | BL |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API BlockHeader {
+ public:
+ static const uint8_t LENGTH = 1;
+ static const uint8_t VERBOSE_LENGTH = 4;
+
+ /// Initializes a copy instance of the BlockHeader class.
+ BlockHeader();
+ /// Initializes a copy instance of the BlockHeader class.
+ BlockHeader(uint8_t* data, bool verbose = false);
+
+ /// Decode a block header frame.
+ bool decode(const uint8_t* data, bool verbose = false);
+ /// Encode a block header frame.
+ void encode(uint8_t *data, bool verbose = false);
+
+ public:
+ /// Payload type.
+ /// This simple boolean marks this header as either IANA standard, or profile specific.
+ __PROPERTY(bool, payloadType, PayloadType);
+ /// Block type.
+ __PROPERTY(BlockType, blockType, BlockType);
+ /// Timestamp Offset.
+ __PROPERTY(uint16_t, timestampOffset, TimestampOffset);
+ /// Block length.
+ __PROPERTY(uint16_t, blockLength, BlockLength);
+ };
+ } // namespace dfsi
+} // namespace p25
+
+#endif // __BLOCK_HEADER_H__
\ No newline at end of file
diff --git a/src/dfsi/frames/ControlOctet.cpp b/src/dfsi/frames/ControlOctet.cpp
new file mode 100644
index 00000000..b93fcc78
--- /dev/null
+++ b/src/dfsi/frames/ControlOctet.cpp
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+
+#include "frames/ControlOctet.h"
+#include "common/p25/dfsi/DFSIDefines.h"
+#include "common/Utils.h"
+#include "common/Log.h"
+
+#include
+#include
+
+using namespace p25;
+using namespace dfsi;
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a instance of the ControlOctet class.
+///
+ControlOctet::ControlOctet() :
+ m_signal(false),
+ m_compact(true),
+ m_blockHeaderCnt(0U)
+{
+ /* stub */
+}
+
+///
+/// Initializes a instance of the ControlOctet class.
+///
+///
+ControlOctet::ControlOctet(uint8_t* data) :
+ m_signal(false),
+ m_compact(true),
+ m_blockHeaderCnt(0U)
+{
+ decode(data);
+}
+
+///
+/// Decode a control octet frame.
+///
+///
+///
+bool ControlOctet::decode(const uint8_t* data)
+{
+ assert(data != nullptr);
+
+ m_signal = (data[0U] & 0x07U) == 0x07U; // Signal Flag
+ m_compact = (data[0U] & 0x06U) == 0x06U; // Compact Flag
+ m_blockHeaderCnt = (uint8_t)(data[0U] & 0x3FU); // Block Header Count
+
+ return true;
+}
+
+///
+/// Encode a control octet frame.
+///
+///
+void ControlOctet::encode(uint8_t* data)
+{
+ assert(data != nullptr);
+
+ data[0U] = (uint8_t)((m_signal ? 0x07U : 0x00U) + // Signal Flag
+ (m_compact ? 0x06U : 0x00U) + // Control Flag
+ (m_blockHeaderCnt & 0x3F));
+}
diff --git a/src/dfsi/frames/ControlOctet.h b/src/dfsi/frames/ControlOctet.h
new file mode 100644
index 00000000..524a9623
--- /dev/null
+++ b/src/dfsi/frames/ControlOctet.h
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+#if !defined(__CONTROL_OCTET_H__)
+#define __CONTROL_OCTET_H__
+
+#include "Defines.h"
+#include "common/Defines.h"
+#include "common/Log.h"
+#include "common/Utils.h"
+#include "frames/FrameDefines.h"
+
+namespace p25
+{
+ namespace dfsi
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements a DFSI control octet packet.
+ //
+ // Byte 0
+ // Bit 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+
+ // |S|C| BHC |
+ // +-+-+-+-+-+-+-+-+
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API ControlOctet {
+ public:
+ static const uint8_t LENGTH = 1;
+
+ /// Initializes a copy instance of the ControlOctet class.
+ ControlOctet();
+ /// Initializes a copy instance of the ControlOctet class.
+ ControlOctet(uint8_t* data);
+
+ /// Decode a control octet frame.
+ bool decode(const uint8_t* data);
+ /// Encode a control octet frame.
+ void encode(uint8_t* data);
+
+ public:
+ ///
+ __PROPERTY(bool, signal, Signal);
+ /// Indicates a compact (1) or verbose (0) block header.
+ __PROPERTY(bool, compact, Compact);
+ /// Number of block headers following this control octet.
+ __PROPERTY(uint8_t, blockHeaderCnt, BlockHeaderCnt);
+ };
+ } // namespace dfsi
+} // namespace p25
+
+#endif // __CONTROL_OCTET_H__
\ No newline at end of file
diff --git a/src/dfsi/frames/FrameDefines.h b/src/dfsi/frames/FrameDefines.h
index be9d94f9..f9e56a40 100644
--- a/src/dfsi/frames/FrameDefines.h
+++ b/src/dfsi/frames/FrameDefines.h
@@ -25,6 +25,21 @@ namespace p25
// Constants
// ---------------------------------------------------------------------------
+ ///
+ /// DFSI Block Types
+ ///
+ enum BlockType {
+ FULL_RATE_VOICE = 0,
+
+ VOICE_HEADER_P1 = 6,
+ VOICE_HEADER_P2 = 7,
+
+ START_OF_STREAM = 9,
+ END_OF_STREAM = 10,
+
+ UNDEFINED = 127
+ };
+
///
///
///
diff --git a/src/dfsi/frames/Frames.h b/src/dfsi/frames/Frames.h
index bfca6372..33a98d1a 100644
--- a/src/dfsi/frames/Frames.h
+++ b/src/dfsi/frames/Frames.h
@@ -17,8 +17,13 @@
#include "Defines.h"
+// TIA
#include "frames/StartOfStream.h"
+#include "frames/ControlOctet.h"
+#include "frames/BlockHeader.h"
+#include "frames/FullRateVoice.h"
+// "The" Manufacturer
#include "frames/MotFullRateVoice.h"
#include "frames/MotStartOfStream.h"
#include "frames/MotStartVoiceFrame.h"
diff --git a/src/dfsi/frames/FullRateVoice.cpp b/src/dfsi/frames/FullRateVoice.cpp
new file mode 100644
index 00000000..ef3d53c0
--- /dev/null
+++ b/src/dfsi/frames/FullRateVoice.cpp
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+
+#include "frames/FullRateVoice.h"
+#include "common/p25/dfsi/DFSIDefines.h"
+#include "common/Utils.h"
+#include "common/Log.h"
+
+#include
+#include
+
+using namespace p25;
+using namespace dfsi;
+
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a instance of the FullRateVoice class.
+///
+FullRateVoice::FullRateVoice() :
+ imbeData(nullptr),
+ additionalData(nullptr),
+ m_frameType(P25_DFSI_LDU1_VOICE1),
+ m_totalErrors(0U),
+ m_muteFrame(false),
+ m_lostFrame(false),
+ m_superframeCnt(0U),
+ m_busy(0U)
+{
+ imbeData = new uint8_t[IMBE_BUF_LEN];
+ ::memset(imbeData, 0x00U, IMBE_BUF_LEN);
+}
+
+///
+/// Initializes a instance of the FullRateVoice class.
+///
+///
+FullRateVoice::FullRateVoice(uint8_t* data) :
+ imbeData(nullptr),
+ additionalData(nullptr),
+ m_frameType(P25_DFSI_LDU1_VOICE1),
+ m_totalErrors(0U),
+ m_muteFrame(false),
+ m_lostFrame(false),
+ m_superframeCnt(0U),
+ m_busy(0U)
+{
+ decode(data);
+}
+
+///
+/// Finalizes a instance of the FullRateVoice class.
+///
+FullRateVoice::~FullRateVoice()
+{
+ if (imbeData != nullptr)
+ delete[] imbeData;
+ if (additionalData != nullptr)
+ delete[] additionalData;
+}
+
+///
+/// Decode a full rate voice frame.
+///
+///
+///
+bool FullRateVoice::decode(const uint8_t* data)
+{
+ assert(data != nullptr);
+
+ if (imbeData != nullptr)
+ delete imbeData;
+ imbeData = new uint8_t[IMBE_BUF_LEN];
+ ::memset(imbeData, 0x00U, IMBE_BUF_LEN);
+
+ m_frameType = data[0U]; // Frame Type
+ ::memcpy(imbeData, data + 1U, IMBE_BUF_LEN); // IMBE
+
+ m_totalErrors = (uint8_t)((data[12U] >> 5) & 0x07U); // Total Errors
+ m_muteFrame = (data[12U] & 0x02U) == 0x02U; // Mute Frame Flag
+ m_lostFrame = (data[12U] & 0x01U) == 0x01U; // Lost Frame Flag
+ m_superframeCnt = (uint8_t)((data[13U] >> 2) & 0x03U); // Superframe Counter
+ m_busy = (uint8_t)(data[13U] & 0x03U);
+
+ if (isVoice3thru8() || isVoice12thru17() || isVoice9or10()) {
+ if (additionalData != nullptr)
+ delete additionalData;
+ additionalData = new uint8_t[ADDITIONAL_LENGTH];
+ ::memset(additionalData, 0x00U, ADDITIONAL_LENGTH);
+
+ if (isVoice9or10()) {
+ // CAI 9 and 10 are 3 bytes of additional data not 4
+ ::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH - 1U);
+ } else {
+ ::memcpy(additionalData, data + 14U, ADDITIONAL_LENGTH);
+ }
+ } else {
+ if (additionalData != nullptr)
+ delete additionalData;
+ additionalData = nullptr;
+ }
+
+ return true;
+}
+
+///
+/// Encode a full rate voice frame.
+///
+///
+void FullRateVoice::encode(uint8_t* data)
+{
+ assert(data != nullptr);
+ assert(imbeData != nullptr);
+
+ data[0U] = m_frameType; // Frame Type
+ ::memcpy(data + 1U, imbeData, IMBE_BUF_LEN); // IMBE
+
+ data[12U] = (uint8_t)(((m_totalErrors & 0x07U) << 5) + // Total Errors
+ (m_muteFrame ? 0x02U : 0x00U) + // Mute Frame Flag
+ (m_lostFrame ? 0x01U : 0x00U)); // Lost Frame Flag
+ data[13U] = (uint8_t)(((m_superframeCnt & 0x03U) << 2) + // Superframe Count
+ (m_busy & 0x03U)); // Busy Status
+
+ if ((isVoice3thru8() || isVoice12thru17() || isVoice9or10()) &&
+ additionalData != nullptr) {
+ if (isVoice9or10()) {
+ // CAI 9 and 10 are 3 bytes of additional data not 4
+ ::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH - 1U);
+ } else {
+ ::memcpy(data + 14U, additionalData, ADDITIONAL_LENGTH);
+ }
+ }
+}
+
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
+///
+///
+///
+///
+bool FullRateVoice::isVoice3thru8()
+{
+ if ( (m_frameType == P25_DFSI_LDU1_VOICE3) || (m_frameType == P25_DFSI_LDU1_VOICE4) || (m_frameType == P25_DFSI_LDU1_VOICE5) ||
+ (m_frameType == P25_DFSI_LDU1_VOICE6) || (m_frameType == P25_DFSI_LDU1_VOICE7) || (m_frameType == P25_DFSI_LDU1_VOICE8) ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+///
+///
+///
+///
+bool FullRateVoice::isVoice12thru17()
+{
+ if ( (m_frameType == P25_DFSI_LDU2_VOICE12) || (m_frameType == P25_DFSI_LDU2_VOICE13) || (m_frameType == P25_DFSI_LDU2_VOICE14) ||
+ (m_frameType == P25_DFSI_LDU2_VOICE15) || (m_frameType == P25_DFSI_LDU2_VOICE16) || (m_frameType == P25_DFSI_LDU2_VOICE17) ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+///
+///
+///
+///
+bool FullRateVoice::isVoice9or10()
+{
+ if ( (m_frameType == P25_DFSI_LDU1_VOICE9) || (m_frameType == P25_DFSI_LDU2_VOICE10) ) {
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/src/dfsi/frames/FullRateVoice.h b/src/dfsi/frames/FullRateVoice.h
new file mode 100644
index 00000000..e662851d
--- /dev/null
+++ b/src/dfsi/frames/FullRateVoice.h
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/**
+* Digital Voice Modem - DFSI Peer Application
+* GPLv2 Open Source. Use is subject to license terms.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* @package DVM / DFSI Peer Application
+* @derivedfrom MMDVMHost (https://github.com/g4klx/MMDVMHost)
+* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0)
+*
+* Copyright (C) 2024 Bryan Biedenkapp, N2PLL
+*
+*/
+#if !defined(__FULL_RATE_VOICE_H__)
+#define __FULL_RATE_VOICE_H__
+
+#include "Defines.h"
+#include "common/Defines.h"
+#include "common/Log.h"
+#include "common/Utils.h"
+#include "frames/FrameDefines.h"
+
+namespace p25
+{
+ namespace dfsi
+ {
+ // ---------------------------------------------------------------------------
+ // Class Declaration
+ // Implements a P25 full rate voice packet.
+ //
+ // CAI Frames 1, 2, 10 and 11.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | U0(b11-0) | U1(b11-0) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U2(b10-0) | U3(b11-0) | U4(b10-3) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B |
+ // | | | | |4| | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 3 - 8.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | U0(b11-0) | U1(b11-0) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U2(b10-0) | U3(b11-0) | U4(b10-3) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | LC0,4,8 | LC1,5,9 | LC2, |
+ // | | | | |4| | | | | | 6,10 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | | LC3,7,11 |R| Status |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 12 - 17.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | U0(b11-0) | U1(b11-0) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U2(b10-0) | U3(b11-0) | U4(b10-3) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | ES0,4,8 | ES1,5,9 | ES2, |
+ // | | | | |4| | | | | | 6,10 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | | ES3,7,11 |R| Status |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 9 and 10.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | U0(b11-0) | U1(b11-0) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U2(b10-0) | U3(b11-0) | U4(b10-3) |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | U4 | U5(b10-0) | U6(b10-0) | U7(b6-0) |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | LSD0,2 | LSD1,3 |
+ // | | | | |4| | | | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Rsvd |Si |Sj |
+ // +=+=+=+=+=+=+=+=+
+ //
+ // Because the TIA.102-BAHA spec represents the "message vectors" as
+ // 16-bit units (U0 - U7) this makes understanding the layout of the
+ // buffer ... difficult for the 8-bit aligned minded. The following is
+ // the layout with 8-bit aligned IMBE blocks instead of message vectors:
+ //
+ // CAI Frames 1, 2, 10 and 11.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | IMBE 1 | IMBE 2 | IMBE 3 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B |
+ // | | | | |4| | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 3 - 8.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | IMBE 1 | IMBE 2 | IMBE 3 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | Link Ctrl | Link Ctrl |
+ // | | | | |4| | | | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Link Ctrl |R| Status |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 12 - 17.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | IMBE 1 | IMBE 2 | IMBE 3 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | Enc Sync | Enc Sync |
+ // | | | | |4| | | | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Enc Sync |R| Status |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ //
+ // CAI Frames 9 and 10.
+ //
+ // Byte 0 1 2 3
+ // Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | FT | IMBE 1 | IMBE 2 | IMBE 3 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 4 | IMBE 5 | IMBE 6 | IMBE 7 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ // | IMBE 8 | IMBE 9 | IMBE 10 | IMBE 11 |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Et | Er |M|L|E| E1 |SF | B | LSD0,2 | LSD1,3 |
+ // | | | | |4| | | | | |
+ // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+ // | Rsvd |Si |Sj |
+ // +=+=+=+=+=+=+=+=+
+ // ---------------------------------------------------------------------------
+
+ class HOST_SW_API FullRateVoice {
+ public:
+ static const uint8_t LENGTH = 18;
+ static const uint8_t ADDITIONAL_LENGTH = 4;
+ static const uint8_t IMBE_BUF_LEN = 11;
+
+ /// Initializes a copy instance of the FullRateVoice class.
+ FullRateVoice();
+ /// Initializes a copy instance of the FullRateVoice class.
+ FullRateVoice(uint8_t* data);
+ /// Finalizes a instance of the FullRateVoice class.
+ ~FullRateVoice();
+
+ /// Decode a full rate voice frame.
+ bool decode(const uint8_t* data);
+ /// Encode a full rate voice frame.
+ void encode(uint8_t* data);
+
+ public:
+ uint8_t* imbeData; // ?? - this should probably be private with getters/setters
+ uint8_t* additionalData; // ?? - this should probably be private with getters/setters
+
+ /// Frame Type.
+ __PROPERTY(uint8_t, frameType, FrameType);
+ /// Total errors detected in the frame.
+ __PROPERTY(uint8_t, totalErrors, TotalErrors);
+ /// Flag indicating the frame should be muted.
+ __PROPERTY(bool, muteFrame, MuteFrame);
+ /// Flag indicating the frame was lost.
+ __PROPERTY(bool, lostFrame, LostFrame);
+ /// Superframe Counter.
+ __PROPERTY(uint8_t, superframeCnt, SuperframeCnt);
+ /// Busy Status.
+ __PROPERTY(uint8_t, busy, Busy);
+
+ private:
+ ///
+ bool isVoice3thru8();
+ ///
+ bool isVoice12thru17();
+ ///
+ bool isVoice9or10();
+ };
+ } // namespace dfsi
+} // namespace p25
+
+#endif // __FULL_RATE_VOICE_H__
\ No newline at end of file
diff --git a/src/dfsi/frames/MotFullRateVoice.cpp b/src/dfsi/frames/MotFullRateVoice.cpp
index a1e14da6..4671c546 100644
--- a/src/dfsi/frames/MotFullRateVoice.cpp
+++ b/src/dfsi/frames/MotFullRateVoice.cpp
@@ -179,7 +179,7 @@ void MotFullRateVoice::encode(uint8_t* data, bool shortened)
}
// ---------------------------------------------------------------------------
-// Protected Class Members
+// Private Class Members
// ---------------------------------------------------------------------------
///
diff --git a/src/dfsi/frames/MotFullRateVoice.h b/src/dfsi/frames/MotFullRateVoice.h
index 2d7bc928..68b9dbd3 100644
--- a/src/dfsi/frames/MotFullRateVoice.h
+++ b/src/dfsi/frames/MotFullRateVoice.h
@@ -46,7 +46,6 @@ namespace p25
class HOST_SW_API MotFullRateVoice {
public:
- // Frame information
static const uint8_t LENGTH = 17;
static const uint8_t SHORTENED_LENGTH = 13;
static const uint8_t ADDITIONAL_LENGTH = 4;
@@ -70,7 +69,7 @@ namespace p25
uint8_t* imbeData; // ?? - this should probably be private with getters/setters
uint8_t* additionalData; // ?? - this should probably be private with getters/setters
- ///
+ /// Frame Type.
__PROPERTY(uint8_t, frameType, FrameType);
///
__PROPERTY(uint8_t, source, Source);
diff --git a/src/dfsi/frames/MotStartOfStream.cpp b/src/dfsi/frames/MotStartOfStream.cpp
index aa992d74..8971f076 100644
--- a/src/dfsi/frames/MotStartOfStream.cpp
+++ b/src/dfsi/frames/MotStartOfStream.cpp
@@ -44,7 +44,11 @@ MotStartOfStream::MotStartOfStream() :
/// Initializes a instance of the MotStartOfStream class.
///
///
-MotStartOfStream::MotStartOfStream(uint8_t* data)
+MotStartOfStream::MotStartOfStream(uint8_t* data) :
+ m_marker(FIXED_MARKER),
+ m_rt(DISABLED),
+ m_startStop(START),
+ m_streamType(VOICE)
{
decode(data);
}
diff --git a/src/dfsi/frames/MotStartVoiceFrame.cpp b/src/dfsi/frames/MotStartVoiceFrame.cpp
index 66482883..7f641687 100644
--- a/src/dfsi/frames/MotStartVoiceFrame.cpp
+++ b/src/dfsi/frames/MotStartVoiceFrame.cpp
@@ -48,12 +48,15 @@ MotStartVoiceFrame::MotStartVoiceFrame() :
/// Initializes a instance of the MotStartVoiceFrame class.
///
///
-MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data)
+MotStartVoiceFrame::MotStartVoiceFrame(uint8_t* data) :
+ startOfStream(nullptr),
+ fullRateVoice(nullptr),
+ m_icw(ICW_DIU),
+ m_rssi(0U),
+ m_rssiValidity(INVALID),
+ m_nRssi(0U),
+ m_adjMM(0U)
{
- // set our pointers to null since we don't initialize them anywhere else
- startOfStream = nullptr;
- fullRateVoice = nullptr;
- // decode
decode(data);
}
diff --git a/src/dfsi/frames/MotVoiceHeader1.cpp b/src/dfsi/frames/MotVoiceHeader1.cpp
index e8315b6b..261011d3 100644
--- a/src/dfsi/frames/MotVoiceHeader1.cpp
+++ b/src/dfsi/frames/MotVoiceHeader1.cpp
@@ -49,12 +49,14 @@ MotVoiceHeader1::MotVoiceHeader1() :
/// Initializes a instance of the MotVoiceHeader1 class.
///
///
-MotVoiceHeader1::MotVoiceHeader1(uint8_t* data)
+MotVoiceHeader1::MotVoiceHeader1(uint8_t* data) :
+ header(nullptr),
+ startOfStream(nullptr),
+ m_icw(ICW_DIU),
+ m_rssi(0U),
+ m_rssiValidity(INVALID),
+ m_nRssi(0U)
{
- // set our pointers to null since we haven't initialized them yet
- startOfStream = nullptr;
- header = nullptr;
- // decode
decode(data);
}
diff --git a/src/dfsi/frames/MotVoiceHeader2.cpp b/src/dfsi/frames/MotVoiceHeader2.cpp
index fed1e1fc..5dafc009 100644
--- a/src/dfsi/frames/MotVoiceHeader2.cpp
+++ b/src/dfsi/frames/MotVoiceHeader2.cpp
@@ -43,11 +43,10 @@ MotVoiceHeader2::MotVoiceHeader2() :
/// Initializes a instance of the MotVoiceHeader2 class.
///
///
-MotVoiceHeader2::MotVoiceHeader2(uint8_t* data)
+MotVoiceHeader2::MotVoiceHeader2(uint8_t* data) :
+ header(nullptr),
+ m_source(SOURCE_QUANTAR)
{
- // set pointer to null since it hasn't been initialized yet
- header = nullptr;
- // decode
decode(data);
}
diff --git a/src/dfsi/frames/StartOfStream.cpp b/src/dfsi/frames/StartOfStream.cpp
index b339f5cb..14bc98fd 100644
--- a/src/dfsi/frames/StartOfStream.cpp
+++ b/src/dfsi/frames/StartOfStream.cpp
@@ -57,8 +57,8 @@ bool StartOfStream::decode(const uint8_t* data)
{
assert(data != nullptr);
- m_nid = __GET_UINT16(data, 0U); // Network Identifier
- m_errorCount = (data[2U] & 0x0FU); // Error Count
+ m_nid = __GET_UINT16(data, 0U); // Network Identifier
+ m_errorCount = (data[2U] & 0x0FU); // Error Count
return true;
}
@@ -71,6 +71,6 @@ void StartOfStream::encode(uint8_t* data)
{
assert(data != nullptr);
- __SET_UINT16(m_nid, data, 0U); // Network Identifier
- data[2U] = m_errorCount & 0x0FU; // Error Count
+ __SET_UINT16(m_nid, data, 0U); // Network Identifier
+ data[2U] = m_errorCount & 0x0FU; // Error Count
}
diff --git a/src/dfsi/frames/StartOfStream.h b/src/dfsi/frames/StartOfStream.h
index 002af9c5..6a41bc63 100644
--- a/src/dfsi/frames/StartOfStream.h
+++ b/src/dfsi/frames/StartOfStream.h
@@ -27,7 +27,6 @@ namespace p25
// ---------------------------------------------------------------------------
// Class Declaration
// Implements a P25 DFSI start of stream packet.
- //
//
// Byte 0 1 2
// Bit 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
@@ -51,9 +50,9 @@ namespace p25
void encode(uint8_t* data);
public:
- ///
+ /// Network Identifier.
__PROPERTY(uint16_t, nid, NID);
- ///
+ /// Error count.
__PROPERTY(uint8_t, errorCount, ErrorCount);
};
} // namespace dfsi
diff --git a/src/dfsi/network/SerialService.cpp b/src/dfsi/network/SerialService.cpp
index a41b711a..2f5fc9d0 100644
--- a/src/dfsi/network/SerialService.cpp
+++ b/src/dfsi/network/SerialService.cpp
@@ -23,7 +23,27 @@ using namespace modem;
using namespace p25;
using namespace dfsi;
-SerialService::SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace) :
+// ---------------------------------------------------------------------------
+// Public Class Members
+// ---------------------------------------------------------------------------
+
+///
+/// Initializes a new instance of the SerialService class.
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+///
+SerialService::SerialService(std::string& portType, const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network,
+ uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace) :
m_portName(portName),
m_baudrate(baudrate),
m_rtrt(rtrt),
@@ -62,7 +82,13 @@ SerialService::SerialService(const std::string& portName, uint32_t baudrate, boo
// Setup serial
port::SERIAL_SPEED serialSpeed = port::SERIAL_115200;
- m_port = new port::UARTPort(portName, serialSpeed, false);
+ std::transform(portType.begin(), portType.end(), portType.begin(), ::tolower);
+ if (portType == NULL_PORT) {
+ m_port = new port::ModemNullPort();
+ }
+ else {
+ m_port = new port::UARTPort(portName, serialSpeed, false);
+ }
m_lastIMBE = new uint8_t[11U];
::memcpy(m_lastIMBE, P25_NULL_IMBE, 11U);
@@ -70,6 +96,9 @@ SerialService::SerialService(const std::string& portName, uint32_t baudrate, boo
m_msgBuffer = new uint8_t[BUFFER_LENGTH];
}
+///
+/// Finalizes a instance of the SerialService class.
+///
SerialService::~SerialService()
{
if (m_port != nullptr) {
@@ -86,6 +115,10 @@ SerialService::~SerialService()
delete m_rxVoiceCallData;
}
+///
+/// Updates the timer by the passed number of milliseconds.
+///
+///
void SerialService::clock(uint32_t ms)
{
// Get now
@@ -193,6 +226,10 @@ void SerialService::clock(uint32_t ms)
}
}
+///
+/// Opens connection to the serial interface.
+///
+/// True, if connection is established, otherwise false.
bool SerialService::open()
{
LogInfoEx(LOG_SERIAL, "Opening port %s at %u baud", m_portName.c_str(), m_baudrate);
@@ -209,6 +246,9 @@ bool SerialService::open()
return true;
}
+///
+/// Closes connection to the serial interface.
+///
void SerialService::close()
{
LogInfoEx(LOG_SERIAL, "Closing port");
@@ -916,6 +956,10 @@ void SerialService::processP25ToNet()
}
}
+// ---------------------------------------------------------------------------
+// Private Class Members
+// ---------------------------------------------------------------------------
+
/// Read a data message from the serial port
/// This is borrowed from the Modem::getResponse() function
/// Response type
diff --git a/src/dfsi/network/SerialService.h b/src/dfsi/network/SerialService.h
index 1cb9e6df..86881fc5 100644
--- a/src/dfsi/network/SerialService.h
+++ b/src/dfsi/network/SerialService.h
@@ -33,6 +33,7 @@
#include "host/modem/Modem.h"
#include "host/modem/port/IModemPort.h"
#include "host/modem/port/UARTPort.h"
+#include "host/modem/port/ModemNullPort.h"
// System Includes
#include
@@ -48,7 +49,6 @@ using namespace dfsi;
namespace network
{
-
// DFSI serial tx flags used to determine proper jitter handling of data in ringbuffer
enum SERIAL_TX_TYPE {
NONIMBE,
@@ -56,20 +56,24 @@ namespace network
};
// ---------------------------------------------------------------------------
- // Class Declaration
+ // Class Declaration
// Serial V24 service
// ---------------------------------------------------------------------------
class HOST_SW_API SerialService {
public:
- SerialService(const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace);
-
+ /// Initializes an instance of the SerialService class.
+ SerialService(std::string& portType, const std::string& portName, uint32_t baudrate, bool rtrt, bool diu, uint16_t jitter, DfsiPeerNetwork* network, uint32_t p25TxQueueSize, uint32_t p25RxQueueSize, uint16_t callTimeout, bool debug, bool trace);
+ /// Finalizes an instance of the SerialService class.
~SerialService();
+ /// Updates the serial interface by the passed number of milliseconds.
void clock(uint32_t ms);
+ /// Opens connection to the serial interface.
bool open();
+ /// Closes connection to the serial interface.
void close();
// Handle P25 data from network to V24
@@ -156,10 +160,6 @@ namespace network
void printDebug(const uint8_t* buffer, uint16_t length);
};
-
- // Defines for Mot DFSI
-
-
} // namespace network
#endif // __SERIAL_SERVICE_H__
\ No newline at end of file