You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
400 lines
12 KiB
400 lines
12 KiB
// SPDX-License-Identifier: GPL-2.0-only
|
|
/*
|
|
* Digital Voice Modem - Hotspot Firmware
|
|
* GPLv2 Open Source. Use is subject to license terms.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* Copyright (C) 2015,2016,2018,2020,2021 Jonathan Naylor, G4KLX
|
|
* Copyright (C) 2018 Andy Uribe, CA6JAU
|
|
* Copyright (C) 2018,2021-2024 Bryan Biedenkapp, N2PLL
|
|
*
|
|
*/
|
|
/**
|
|
* @file SerialPort.h
|
|
* @ingroup hotspot_fw
|
|
* @file SerialPort.cpp
|
|
* @ingroup hotspot_fw
|
|
* @file SerialSTM.cpp
|
|
* @ingroup hotspot_fw
|
|
*/
|
|
#if !defined(__SERIAL_PORT_H__)
|
|
#define __SERIAL_PORT_H__
|
|
|
|
#include "Defines.h"
|
|
#include "Globals.h"
|
|
#include "SerialBuffer.h"
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Constants
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @addtogroup modem
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @brief Modem operation states.
|
|
*/
|
|
enum DVM_STATE {
|
|
STATE_IDLE = 0U, //! Idle
|
|
// DMR
|
|
STATE_DMR = 1U, //! DMR
|
|
// Project 25
|
|
STATE_P25 = 2U, //! Project 25
|
|
// NXDN
|
|
STATE_NXDN = 3U, //! NXDN
|
|
|
|
// CW
|
|
STATE_CW = 10U, //! Continuous Wave
|
|
|
|
// Calibration States
|
|
STATE_INT_CAL = 90U, //!
|
|
|
|
STATE_P25_CAL_1K = 92U, //! Project 25 Calibration 1K
|
|
|
|
STATE_DMR_DMO_CAL_1K = 93U, //! DMR DMO Calibration 1K
|
|
STATE_DMR_CAL_1K = 94U, //! DMR Calibration 1K
|
|
STATE_DMR_LF_CAL = 95U, //! DMR Low Frequency Calibration
|
|
|
|
STATE_RSSI_CAL = 96U, //! RSSI Calibration
|
|
|
|
STATE_P25_CAL = 97U, //! Project 25 Calibration
|
|
STATE_DMR_CAL = 98U, //! DMR Calibration
|
|
STATE_NXDN_CAL = 99U //! NXDN Calibration
|
|
};
|
|
|
|
/**
|
|
* @brief Modem commands.
|
|
*/
|
|
enum DVM_COMMANDS {
|
|
CMD_GET_VERSION = 0x00U, //! Get Modem Version
|
|
CMD_GET_STATUS = 0x01U, //! Get Modem Status
|
|
CMD_SET_CONFIG = 0x02U, //! Set Modem Configuration
|
|
CMD_SET_MODE = 0x03U, //! Set Modem Mode
|
|
|
|
CMD_SET_SYMLVLADJ = 0x04U, //! Set Symbol Level Adjustments
|
|
CMD_SET_RXLEVEL = 0x05U, //! Set Rx Level
|
|
CMD_SET_RFPARAMS = 0x06U, //! (Hotspot) Set RF Parameters
|
|
|
|
CMD_CAL_DATA = 0x08U, //! Calibration Data
|
|
CMD_RSSI_DATA = 0x09U, //! RSSI Data
|
|
|
|
CMD_SEND_CWID = 0x0AU, //! Send Continous Wave ID (Morse)
|
|
|
|
CMD_SET_BUFFERS = 0x0FU, //! Set FIFO Buffer Lengths
|
|
|
|
CMD_DMR_DATA1 = 0x18U, //! DMR Data Slot 1
|
|
CMD_DMR_LOST1 = 0x19U, //! DMR Data Lost Slot 1
|
|
CMD_DMR_DATA2 = 0x1AU, //! DMR Data Slot 2
|
|
CMD_DMR_LOST2 = 0x1BU, //! DMR Data Lost Slot 2
|
|
CMD_DMR_SHORTLC = 0x1CU, //! DMR Short Link Control
|
|
CMD_DMR_START = 0x1DU, //! DMR Start Transmit
|
|
CMD_DMR_ABORT = 0x1EU, //! DMR Abort
|
|
CMD_DMR_CACH_AT_CTRL = 0x1FU, //! DMR Set CACH AT Control
|
|
CMD_DMR_CLEAR1 = 0x20U, //! DMR Clear Slot 1 Buffer
|
|
CMD_DMR_CLEAR2 = 0x21U, //! DMR Clear Slot 2 Buffer
|
|
|
|
CMD_P25_DATA = 0x31U, //! Project 25 Data
|
|
CMD_P25_LOST = 0x32U, //! Project 25 Data Lost
|
|
CMD_P25_CLEAR = 0x33U, //! Project 25 Clear Buffer
|
|
|
|
CMD_NXDN_DATA = 0x41U, //! NXDN Data
|
|
CMD_NXDN_LOST = 0x42U, //! NXDN Data Lost
|
|
CMD_NXDN_CLEAR = 0x43U, //! NXDN Clear Buffer
|
|
|
|
CMD_ACK = 0x70U, //! Command ACK
|
|
CMD_NAK = 0x7FU, //! Command NACK
|
|
|
|
CMD_FLSH_READ = 0xE0U, //! Read Flash Partition
|
|
CMD_FLSH_WRITE = 0xE1U, //! Write Flash Partition
|
|
|
|
CMD_RESET_MCU = 0xEAU, //! Soft Reboot MCU
|
|
|
|
CMD_DEBUG1 = 0xF1U, //!
|
|
CMD_DEBUG2 = 0xF2U, //!
|
|
CMD_DEBUG3 = 0xF3U, //!
|
|
CMD_DEBUG4 = 0xF4U, //!
|
|
CMD_DEBUG5 = 0xF5U, //!
|
|
CMD_DEBUG_DUMP = 0xFAU, //!
|
|
};
|
|
|
|
/**
|
|
* @brief Modem response reason codes.
|
|
*/
|
|
enum CMD_REASON_CODE {
|
|
RSN_OK = 0U, //! OK
|
|
RSN_NAK = 1U, //! Negative Acknowledge
|
|
|
|
RSN_ILLEGAL_LENGTH = 2U, //! Illegal Length
|
|
RSN_INVALID_REQUEST = 4U, //! Invalid Request
|
|
RSN_RINGBUFF_FULL = 8U, //! Ring Buffer Full
|
|
|
|
RSN_INVALID_FDMA_PREAMBLE = 10U, //! Invalid FDMA Preamble Length
|
|
RSN_INVALID_MODE = 11U, //! Invalid Mode
|
|
|
|
RSN_INVALID_DMR_CC = 12U, //! Invalid DMR CC
|
|
RSN_INVALID_DMR_SLOT = 13U, //! Invalid DMR Slot
|
|
RSN_INVALID_DMR_START = 14U, //! Invaild DMR Start Transmit
|
|
RSN_INVALID_DMR_RX_DELAY = 15U, //! Invalid DMR Rx Delay
|
|
|
|
RSN_INVALID_P25_CORR_COUNT = 16U, //! Invalid P25 Correlation Count
|
|
|
|
RSN_NO_INTERNAL_FLASH = 20U, //! No Internal Flash
|
|
RSN_FAILED_ERASE_FLASH = 21U, //! Failed to erase flash partition
|
|
RSN_FAILED_WRITE_FLASH = 22U, //! Failed to write flash partition
|
|
RSN_FLASH_WRITE_TOO_BIG = 23U, //! Data to large for flash partition
|
|
|
|
RSN_HS_NO_DUAL_MODE = 32U, //! (Hotspot) No Dual Mode Operation
|
|
|
|
RSN_DMR_DISABLED = 63U, //! DMR Disabled
|
|
RSN_P25_DISABLED = 64U, //! Project 25 Disabled
|
|
RSN_NXDN_DISABLED = 65U //! NXDN Disabled
|
|
};
|
|
|
|
const uint8_t DVM_SHORT_FRAME_START = 0xFEU;
|
|
const uint8_t DVM_LONG_FRAME_START = 0xFDU;
|
|
|
|
#define SERIAL_FB_LEN 518U
|
|
#define SERIAL_SPEED 115200
|
|
/** @} */
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Class Declaration
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @brief Implements the RS232 serial bus to communicate with the HOST S/W.
|
|
* @ingroup hotspot_fw
|
|
*/
|
|
class DSP_FW_API SerialPort {
|
|
public:
|
|
/**
|
|
* @brief Initializes a new instance of the SerialPort class.
|
|
*/
|
|
SerialPort();
|
|
|
|
/**
|
|
* @brief Starts serial port communications.
|
|
*/
|
|
void start();
|
|
|
|
/**
|
|
* @brief Process data from serial port.
|
|
*/
|
|
void process();
|
|
|
|
/**
|
|
* @brief Helper to check if the modem is in a calibration state.
|
|
* @param state
|
|
* @returns bool
|
|
*/
|
|
bool isCalState(DVM_STATE state);
|
|
/**
|
|
* @brief Helper to determine digital mode if the modem is in a calibration state.
|
|
* @param state
|
|
* @returns DVM_STATE
|
|
*/
|
|
DVM_STATE calRelativeState(DVM_STATE state);
|
|
|
|
/**
|
|
* @brief Write DMR frame data to serial port.
|
|
* @param slot DMR slot number.
|
|
* @param[in] data Data to write.
|
|
* @param length Length of data to write.
|
|
*/
|
|
void writeDMRData(bool slot, const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Write lost DMR frame data to serial port.
|
|
* @param slot DMR slot number.
|
|
*/
|
|
void writeDMRLost(bool slot);
|
|
|
|
/**
|
|
* @brief Write P25 frame data to serial port.
|
|
* @param[in] data Data to write.
|
|
* @param length Length of data to write.
|
|
*/
|
|
void writeP25Data(const uint8_t* data, uint16_t length);
|
|
/**
|
|
* @brief Write lost P25 frame data to serial port.
|
|
*/
|
|
void writeP25Lost();
|
|
|
|
/**
|
|
* @brief Write NXDN frame data to serial port.
|
|
* @param[in] data Data to write.
|
|
* @param length Length of data to write.
|
|
*/
|
|
void writeNXDNData(const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Write lost NXDN frame data to serial port.
|
|
*/
|
|
void writeNXDNLost();
|
|
|
|
/**
|
|
* @brief Write calibration frame data to serial port.
|
|
* @param[in] data Data to write.
|
|
* @param length Length of data to write.
|
|
*/
|
|
void writeCalData(const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Write RSSI frame data to serial port.
|
|
* @param[in] data Data to write.
|
|
* @param length Length of data to write.
|
|
*/
|
|
void writeRSSIData(const uint8_t* data, uint8_t length);
|
|
|
|
/**
|
|
* @brief
|
|
* @param[in] text
|
|
*/
|
|
void writeDebug(const char* text);
|
|
/**
|
|
* @brief
|
|
* @param[in] text
|
|
* @param n1
|
|
*/
|
|
void writeDebug(const char* text, int16_t n1);
|
|
/**
|
|
* @brief
|
|
* @param[in] text
|
|
* @param n1
|
|
* @param n2
|
|
*/
|
|
void writeDebug(const char* text, int16_t n1, int16_t n2);
|
|
/**
|
|
* @brief
|
|
* @param[in] text
|
|
* @param n1
|
|
* @param n2
|
|
* @param n3
|
|
*/
|
|
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3);
|
|
/**
|
|
* @brief
|
|
* @param[in] text
|
|
* @param n1
|
|
* @param n2
|
|
* @param n3
|
|
* @param n4
|
|
*/
|
|
void writeDebug(const char* text, int16_t n1, int16_t n2, int16_t n3, int16_t n4);
|
|
/**
|
|
* @brief
|
|
* @param[in] data
|
|
* @param length
|
|
*/
|
|
void writeDump(const uint8_t* data, uint16_t length);
|
|
|
|
private:
|
|
uint8_t m_buffer[SERIAL_FB_LEN];
|
|
uint16_t m_ptr;
|
|
uint16_t m_len;
|
|
bool m_dblFrame;
|
|
|
|
bool m_debug;
|
|
|
|
/**
|
|
* @brief Write acknowlegement.
|
|
*/
|
|
void sendACK();
|
|
/**
|
|
* @brief Write negative acknowlegement.
|
|
* @param err
|
|
*/
|
|
void sendNAK(uint8_t err);
|
|
/**
|
|
* @brief Write modem DSP status.
|
|
*/
|
|
void getStatus();
|
|
/**
|
|
* @brief Write modem DSP version.
|
|
*/
|
|
void getVersion();
|
|
/**
|
|
* @brief Helper to validate the passed modem state is valid.
|
|
* @param state
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t modemStateCheck(DVM_STATE state);
|
|
/**
|
|
* @brief Set modem DSP configuration from serial port data.
|
|
* @param[in] data Buffer containing configuration frame.
|
|
* @param length Length of buffer.
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t setConfig(const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Set modem DSP mode from serial port data.
|
|
* @param[in] data Buffer containing mode frame.
|
|
* @param length Length of buffer.
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t setMode(const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Sets the modem state.
|
|
* @param modemState
|
|
*/
|
|
void setMode(DVM_STATE modemState);
|
|
/**
|
|
* @brief Sets the RF parameters.
|
|
* @param[in] data Buffer containing RF parameters frame.
|
|
* @param length Length of buffer.
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t setRFParams(const uint8_t* data, uint8_t length);
|
|
/**
|
|
* @brief Sets the protocol ring buffer sizes.
|
|
* @param[in] data Buffer containing set buffers frame.
|
|
* @param length Length of buffer.
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t setBuffers(const uint8_t* data, uint8_t length);
|
|
|
|
/**
|
|
* @brief Reads data from the modem flash parititon.
|
|
*/
|
|
void flashRead();
|
|
/**
|
|
* @brief Writes data to the modem flash partition.
|
|
* @param[in] data Buffer containing data to write to flash partition.
|
|
* @param length Length of buffer.
|
|
* @returns uint8_t Reason code.
|
|
*/
|
|
uint8_t flashWrite(const uint8_t* data, uint8_t length);
|
|
|
|
// Hardware specific routines
|
|
/**
|
|
* @brief
|
|
* @param n
|
|
* @param speed
|
|
*/
|
|
void beginInt(uint8_t n, int speed);
|
|
/**
|
|
* @brief
|
|
* @param n
|
|
*/
|
|
int availableInt(uint8_t n);
|
|
/**
|
|
* @brief
|
|
* @param n
|
|
*/
|
|
int availableForWriteInt(uint8_t n);
|
|
/**
|
|
* @brief
|
|
* @param n
|
|
*/
|
|
uint8_t readInt(uint8_t n);
|
|
/**
|
|
* @brief
|
|
* @param n
|
|
* @param[in] data
|
|
* @param length
|
|
* @param flush
|
|
*/
|
|
void writeInt(uint8_t n, const uint8_t* data, uint16_t length, bool flush = false);
|
|
};
|
|
|
|
#endif // __SERIAL_PORT_H__
|