mirror of
https://github.com/juribeparada/MMDVM_HS.git
synced 2025-12-06 07:12:08 +01:00
Merge pocsag branch to master
This commit is contained in:
commit
34ef6fd0cf
53
ADF7021.cpp
53
ADF7021.cpp
|
|
@ -48,6 +48,7 @@ uint16_t m_dmrDev;
|
|||
uint16_t m_ysfDev;
|
||||
uint16_t m_p25Dev;
|
||||
uint16_t m_nxdnDev;
|
||||
uint16_t m_pocsagDev;
|
||||
|
||||
static void Send_AD7021_control_shift()
|
||||
{
|
||||
|
|
@ -186,9 +187,19 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
|
|||
uint32_t ADF7021_REG13 = 0U;
|
||||
int32_t AFC_OFFSET = 0;
|
||||
|
||||
if(modemState != STATE_CWID)
|
||||
uint32_t frequency_tx_tmp, frequency_rx_tmp;
|
||||
|
||||
if (modemState != STATE_CWID && modemState != STATE_POCSAG)
|
||||
m_modemState_prev = modemState;
|
||||
|
||||
// Change frequency for POCSAG mode, store a backup of DV frequencies
|
||||
if (modemState == STATE_POCSAG) {
|
||||
frequency_tx_tmp = m_frequency_tx;
|
||||
frequency_rx_tmp = m_frequency_rx;
|
||||
m_frequency_tx = m_pocsag_freq_tx;
|
||||
m_frequency_rx = m_pocsag_freq_tx;
|
||||
}
|
||||
|
||||
// Toggle CE pin for ADF7021 reset
|
||||
if(reset) {
|
||||
CE_pin(LOW);
|
||||
|
|
@ -226,6 +237,7 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
|
|||
|
||||
switch (modemState) {
|
||||
case STATE_DSTAR:
|
||||
case STATE_POCSAG:
|
||||
AFC_OFFSET = 0;
|
||||
break;
|
||||
case STATE_DMR:
|
||||
|
|
@ -314,6 +326,28 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
|
|||
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
|
||||
break;
|
||||
|
||||
case STATE_POCSAG:
|
||||
// Dev: 4500 Hz, symb rate = 1200
|
||||
|
||||
ADF7021_REG3 = ADF7021_REG3_POCSAG;
|
||||
ADF7021_REG10 = ADF7021_REG10_POCSAG;
|
||||
|
||||
ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4
|
||||
ADF7021_REG4 |= (uint32_t) 0b000 << 4; // 2FSK linear demodulator
|
||||
ADF7021_REG4 |= (uint32_t) 0b1 << 7;
|
||||
ADF7021_REG4 |= (uint32_t) 0b10 << 8;
|
||||
ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_POCSAG << 10; // Disc BW
|
||||
ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_POCSAG << 20; // Post dem BW
|
||||
ADF7021_REG4 |= (uint32_t) 0b10 << 30; // IF filter (25 kHz)
|
||||
|
||||
// Register 13 not used with 2FSK
|
||||
ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13
|
||||
|
||||
ADF7021_REG2 = (uint32_t) 0b10 << 28; // inverted data, clock normal
|
||||
ADF7021_REG2 |= (uint32_t) (m_pocsagDev / div2) << 19; // deviation
|
||||
ADF7021_REG2 |= (uint32_t) 0b000 << 4; // modulation (2FSK)
|
||||
break;
|
||||
|
||||
case STATE_DSTAR:
|
||||
// Dev: 1200 Hz, symb rate = 4800
|
||||
|
||||
|
|
@ -522,8 +556,14 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
|
|||
#endif
|
||||
Send_AD7021_control();
|
||||
|
||||
// Restore normal DV frequencies
|
||||
if (modemState == STATE_POCSAG) {
|
||||
m_frequency_tx = frequency_tx_tmp;
|
||||
m_frequency_rx = frequency_rx_tmp;
|
||||
}
|
||||
|
||||
#if defined(DUPLEX)
|
||||
if(m_duplex && (modemState != STATE_CWID))
|
||||
if(m_duplex && (modemState != STATE_CWID && modemState != STATE_POCSAG))
|
||||
ifConf2(modemState);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -888,7 +928,7 @@ void CIO::setPower(uint8_t power)
|
|||
m_power = power >> 2;
|
||||
}
|
||||
|
||||
void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, bool ysfLoDev)
|
||||
void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, bool ysfLoDev)
|
||||
{
|
||||
m_dstarDev = uint16_t((ADF7021_DEV_DSTAR * uint16_t(dstarTXLevel)) / 128U);
|
||||
m_dmrDev = uint16_t((ADF7021_DEV_DMR * uint16_t(dmrTXLevel)) / 128U);
|
||||
|
|
@ -900,6 +940,7 @@ void CIO::setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXL
|
|||
|
||||
m_p25Dev = uint16_t((ADF7021_DEV_P25 * uint16_t(p25TXLevel)) / 128U);
|
||||
m_nxdnDev = uint16_t((ADF7021_DEV_NXDN * uint16_t(nxdnTXLevel)) / 128U);
|
||||
m_pocsagDev = uint16_t((ADF7021_DEV_POCSAG * uint16_t(pocsagTXLevel)) / 128U);
|
||||
}
|
||||
|
||||
void CIO::updateCal()
|
||||
|
|
@ -1011,6 +1052,11 @@ uint16_t CIO::devNXDN()
|
|||
return (uint16_t)((ADF7021_PFD * m_nxdnDev) / (f_div * 65536));
|
||||
}
|
||||
|
||||
uint16_t CIO::devPOCSAG()
|
||||
{
|
||||
return (uint16_t)((ADF7021_PFD * m_pocsagDev) / (f_div * 65536));
|
||||
}
|
||||
|
||||
void CIO::printConf()
|
||||
{
|
||||
DEBUG1("MMDVM_HS FW configuration:");
|
||||
|
|
@ -1022,6 +1068,7 @@ void CIO::printConf()
|
|||
DEBUG2("YSF +1 sym dev (Hz):", devYSF());
|
||||
DEBUG2("P25 +1 sym dev (Hz):", devP25());
|
||||
DEBUG2("NXDN +1 sym dev (Hz):", devNXDN());
|
||||
DEBUG2("POCSAG dev (Hz):", devPOCSAG());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
12
ADF7021.h
12
ADF7021.h
|
|
@ -67,6 +67,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
// DEMOD_CLK = 4.9152 MHz (DMR, YSF_L, P25)
|
||||
// DEMOD_CLK = 7.3728 MHz (YSF_H)
|
||||
// DEMOD CLK = 3.6864 MHz (NXDN)
|
||||
// DEMOD_CLK = 7.3728 MHz (POCSAG)
|
||||
#define ADF7021_PFD 3686400.0
|
||||
|
||||
// PLL (REG 01)
|
||||
|
|
@ -86,6 +87,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_DEV_P25 22U
|
||||
#endif
|
||||
#define ADF7021_DEV_NXDN 13U
|
||||
#define ADF7021_DEV_POCSAG 160U
|
||||
|
||||
// TX/RX CLOCK register (REG 03)
|
||||
#define ADF7021_REG3_DSTAR 0x2A4C4193
|
||||
|
|
@ -102,6 +104,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_REG3_P25 0x2A4C80D3
|
||||
#define ADF7021_REG3_NXDN 0x2A4CC113
|
||||
#endif
|
||||
#define ADF7021_REG3_POCSAG 0x2A4F0093
|
||||
|
||||
// Discriminator bandwith, demodulator (REG 04)
|
||||
// Bug in ADI evaluation software, use datasheet formula (4FSK)
|
||||
|
|
@ -111,6 +114,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_DISC_BW_YSF_H 516U // K=28
|
||||
#define ADF7021_DISC_BW_P25 394U // K=32
|
||||
#define ADF7021_DISC_BW_NXDN 295U // K=32
|
||||
#define ADF7021_DISC_BW_POCSAG 406U // K=22
|
||||
|
||||
// Post demodulator bandwith (REG 04)
|
||||
#define ADF7021_POST_BW_DSTAR 10U
|
||||
|
|
@ -118,6 +122,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_POST_BW_YSF 20U
|
||||
#define ADF7021_POST_BW_P25 6U
|
||||
#define ADF7021_POST_BW_NXDN 7U
|
||||
#define ADF7021_POST_BW_POCSAG 1U
|
||||
|
||||
// IF filter (REG 05)
|
||||
#define ADF7021_REG5 0x000024F5
|
||||
|
|
@ -127,6 +132,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
|
||||
// AFC configuration (REG 10)
|
||||
#define ADF7021_REG10_DSTAR 0x0C96473A
|
||||
#define ADF7021_REG10_POCSAG 0x1496473A
|
||||
|
||||
#if defined(ADF7021_ENABLE_4FSK_AFC)
|
||||
#define ADF7021_REG10_DMR 0x01FE473A
|
||||
|
|
@ -162,6 +168,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
// DEMOD_CLK = 2.4576 MHz (DSTAR)
|
||||
// DEMOD_CLK = 6.1440 MHz (DMR, YSF_H, YSF_L, P25)
|
||||
// DEMOD_CLK = 3.0720 MHz (NXDN)
|
||||
// DEMOD_CLK = 6.1440 MHz (POCSAG)
|
||||
#define ADF7021_PFD 6144000.0
|
||||
|
||||
// PLL (REG 01)
|
||||
|
|
@ -181,6 +188,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_DEV_P25 13U
|
||||
#endif
|
||||
#define ADF7021_DEV_NXDN 8U
|
||||
#define ADF7021_DEV_POCSAG 96U
|
||||
|
||||
// TX/RX CLOCK register (REG 03)
|
||||
#define ADF7021_REG3_DSTAR 0x29EC4153
|
||||
|
|
@ -197,6 +205,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_REG3_P25 0x29ECA093
|
||||
#define ADF7021_REG3_NXDN 0x29ECA113
|
||||
#endif
|
||||
#define ADF7021_REG3_POCSAG 0x29EE8093
|
||||
|
||||
// Discriminator bandwith, demodulator (REG 04)
|
||||
// Bug in ADI evaluation software, use datasheet formula (4FSK)
|
||||
|
|
@ -206,6 +215,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_DISC_BW_YSF_H 430U // K=28
|
||||
#define ADF7021_DISC_BW_P25 493U // K=32
|
||||
#define ADF7021_DISC_BW_NXDN 246U // K=32
|
||||
#define ADF7021_DISC_BW_POCSAG 338U // K=22
|
||||
|
||||
// Post demodulator bandwith (REG 04)
|
||||
#define ADF7021_POST_BW_DSTAR 10U
|
||||
|
|
@ -213,6 +223,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
#define ADF7021_POST_BW_YSF 20U
|
||||
#define ADF7021_POST_BW_P25 6U
|
||||
#define ADF7021_POST_BW_NXDN 8U
|
||||
#define ADF7021_POST_BW_POCSAG 1U
|
||||
|
||||
// IF filter (REG 05)
|
||||
#define ADF7021_REG5 0x00001ED5
|
||||
|
|
@ -222,6 +233,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
|
|||
|
||||
// AFC (REG 10)
|
||||
#define ADF7021_REG10_DSTAR 0x0C96557A
|
||||
#define ADF7021_REG10_POCSAG 0x1496557A
|
||||
|
||||
#if defined(ADF7021_ENABLE_4FSK_AFC)
|
||||
#define ADF7021_REG10_DMR 0x01FE557A
|
||||
|
|
|
|||
8
Config.h
8
Config.h
|
|
@ -37,7 +37,7 @@
|
|||
#define ENABLE_ADF7021
|
||||
|
||||
// Enable full duplex support with dual ADF7021 (valid for homebrew hotspots only):
|
||||
// #define DUPLEX
|
||||
#define DUPLEX
|
||||
|
||||
// TCXO of the ADF7021
|
||||
// For 14.7456 MHz:
|
||||
|
|
@ -70,6 +70,12 @@
|
|||
// Constant Service LED once repeater is running
|
||||
// #define CONSTANT_SRV_LED
|
||||
|
||||
// Use the YSF and P25 LEDs for NXDN
|
||||
// #define USE_ALTERNATE_NXDN_LEDS
|
||||
|
||||
// Use the D-Star and DMR LEDs for POCSAG
|
||||
// #define USE_ALTERNATE_POCSAG_LEDS
|
||||
|
||||
// Enable modem debug messages
|
||||
// #define ENABLE_DEBUG
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ m_poBuffer(),
|
|||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(240U), // 200ms
|
||||
m_count(0U),
|
||||
m_delay(false),
|
||||
m_cal(false)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ private:
|
|||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
bool m_cal;
|
||||
|
||||
|
|
|
|||
|
|
@ -186,9 +186,8 @@ m_poBuffer(),
|
|||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(60U), // 100ms
|
||||
m_count(0U)
|
||||
m_delay(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CDStarTX::process()
|
||||
|
|
@ -201,7 +200,6 @@ void CDStarTX::process()
|
|||
if (type == DSTAR_HEADER && m_poLen == 0U) {
|
||||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_count = 0U;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
m_delay = false;
|
||||
|
|
@ -228,8 +226,6 @@ void CDStarTX::process()
|
|||
|
||||
if (type == DSTAR_DATA && m_poLen == 0U) {
|
||||
m_delay = false;
|
||||
if (!m_tx)
|
||||
m_count = 0U;
|
||||
|
||||
// Pop the type byte off
|
||||
m_buffer.get();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ private:
|
|||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay; // In bytes
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
|
||||
void txHeader(const uint8_t* in, uint8_t* out) const;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ enum MMDVM_STATE {
|
|||
STATE_YSF = 3,
|
||||
STATE_P25 = 4,
|
||||
STATE_NXDN = 5,
|
||||
STATE_POCSAG = 6,
|
||||
|
||||
// Dummy states start at 90
|
||||
STATE_DMRDMO1K = 92,
|
||||
|
|
@ -75,6 +76,7 @@ const uint8_t MARK_NONE = 0x00U;
|
|||
#include "P25TX.h"
|
||||
#include "NXDNRX.h"
|
||||
#include "NXDNTX.h"
|
||||
#include "POCSAGTX.h"
|
||||
#include "CWIdTX.h"
|
||||
#include "CalRSSI.h"
|
||||
#include "CalDMR.h"
|
||||
|
|
@ -89,6 +91,8 @@ extern MMDVM_STATE m_calState;
|
|||
extern MMDVM_STATE m_modemState_prev;
|
||||
|
||||
extern bool m_cwid_state;
|
||||
extern bool m_pocsag_state;
|
||||
|
||||
extern uint8_t m_cwIdTXLevel;
|
||||
|
||||
extern uint32_t m_modeTimerCnt;
|
||||
|
|
@ -98,6 +102,7 @@ extern bool m_dmrEnable;
|
|||
extern bool m_ysfEnable;
|
||||
extern bool m_p25Enable;
|
||||
extern bool m_nxdnEnable;
|
||||
extern bool m_pocsagEnable;
|
||||
|
||||
extern bool m_duplex;
|
||||
|
||||
|
|
@ -130,6 +135,8 @@ extern CP25TX p25TX;
|
|||
extern CNXDNRX nxdnRX;
|
||||
extern CNXDNTX nxdnTX;
|
||||
|
||||
extern CPOCSAGTX pocsagTX;
|
||||
|
||||
extern CCalDMR calDMR;
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
|
|
|
|||
28
IO.cpp
28
IO.cpp
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
uint32_t m_frequency_rx;
|
||||
uint32_t m_frequency_tx;
|
||||
uint32_t m_pocsag_freq_tx;
|
||||
uint8_t m_power;
|
||||
|
||||
CIO::CIO():
|
||||
|
|
@ -48,6 +49,7 @@ m_watchdog(0U)
|
|||
YSF_pin(LOW);
|
||||
P25_pin(LOW);
|
||||
NXDN_pin(LOW);
|
||||
POCSAG_pin(LOW);
|
||||
COS_pin(LOW);
|
||||
DEB_pin(LOW);
|
||||
|
||||
|
|
@ -85,6 +87,7 @@ void CIO::selfTest()
|
|||
YSF_pin(ledValue);
|
||||
P25_pin(ledValue);
|
||||
NXDN_pin(ledValue);
|
||||
POCSAG_pin(ledValue);
|
||||
COS_pin(ledValue);
|
||||
|
||||
blinks++;
|
||||
|
|
@ -106,7 +109,7 @@ void CIO::process()
|
|||
if (m_started) {
|
||||
// Two seconds timeout
|
||||
if (m_watchdog >= 19200U) {
|
||||
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN) {
|
||||
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25 || m_modemState == STATE_NXDN) {
|
||||
m_modemState = STATE_IDLE;
|
||||
setMode(m_modemState);
|
||||
}
|
||||
|
|
@ -137,7 +140,14 @@ void CIO::process()
|
|||
if(m_cwid_state) { // check for CW ID end of transmission
|
||||
m_cwid_state = false;
|
||||
// Restoring previous mode
|
||||
io.ifConf(m_modemState_prev, true);
|
||||
if (m_TotalModes)
|
||||
io.ifConf(m_modemState_prev, true);
|
||||
}
|
||||
if(m_pocsag_state) { // check for POCSAG end of transmission
|
||||
m_pocsag_state = false;
|
||||
// Restoring previous mode
|
||||
if (m_TotalModes)
|
||||
io.ifConf(m_modemState_prev, true);
|
||||
}
|
||||
setRX(false);
|
||||
}
|
||||
|
|
@ -157,7 +167,7 @@ void CIO::process()
|
|||
|
||||
if(m_modeTimerCnt >= scantime) {
|
||||
m_modeTimerCnt = 0U;
|
||||
if( (m_modemState == STATE_IDLE) && (m_scanPauseCnt == 0U) && m_scanEnable && !m_cwid_state) {
|
||||
if( (m_modemState == STATE_IDLE) && (m_scanPauseCnt == 0U) && m_scanEnable && !m_cwid_state && !m_pocsag_state) {
|
||||
m_scanPos = (m_scanPos + 1U) % m_TotalModes;
|
||||
#if !defined(QUIET_MODE_LEDS)
|
||||
setMode(m_Modes[m_scanPos]);
|
||||
|
|
@ -281,7 +291,7 @@ bool CIO::hasRXOverflow()
|
|||
return m_rxBuffer.hasOverflowed();
|
||||
}
|
||||
|
||||
uint8_t CIO::setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_power)
|
||||
uint8_t CIO::setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_power, uint32_t pocsag_freq_tx)
|
||||
{
|
||||
// Configure power level
|
||||
setPower(rf_power);
|
||||
|
|
@ -293,9 +303,16 @@ uint8_t CIO::setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_po
|
|||
((frequency_rx >= UHF2_MIN)&&(frequency_rx < UHF2_MAX)) || ((frequency_tx >= UHF2_MIN)&&(frequency_tx < UHF2_MAX)) ) )
|
||||
return 4U;
|
||||
|
||||
if( !( ((pocsag_freq_tx >= VHF1_MIN)&&(pocsag_freq_tx < VHF1_MAX)) || \
|
||||
((pocsag_freq_tx >= UHF1_MIN)&&(pocsag_freq_tx < UHF1_MAX)) || \
|
||||
((pocsag_freq_tx >= VHF2_MIN)&&(pocsag_freq_tx < VHF2_MAX)) || \
|
||||
((pocsag_freq_tx >= UHF2_MIN)&&(pocsag_freq_tx < UHF2_MAX)) ) )
|
||||
return 4U;
|
||||
|
||||
// Configure frequency
|
||||
m_frequency_rx = frequency_rx;
|
||||
m_frequency_tx = frequency_tx;
|
||||
m_pocsag_freq_tx = pocsag_freq_tx;
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
|
@ -306,7 +323,8 @@ void CIO::setMode(MMDVM_STATE modemState)
|
|||
DMR_pin(modemState == STATE_DMR);
|
||||
YSF_pin(modemState == STATE_YSF);
|
||||
P25_pin(modemState == STATE_P25);
|
||||
NXDN_pin(modemState == STATE_NXDN);
|
||||
NXDN_pin(modemState == STATE_NXDN);
|
||||
POCSAG_pin(modemState == STATE_POCSAG);
|
||||
}
|
||||
|
||||
void CIO::setDecode(bool dcd)
|
||||
|
|
|
|||
7
IO.h
7
IO.h
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
extern uint32_t m_frequency_rx;
|
||||
extern uint32_t m_frequency_tx;
|
||||
extern uint32_t m_pocsag_freq_tx;
|
||||
extern uint8_t m_power;
|
||||
|
||||
class CIO {
|
||||
|
|
@ -76,6 +77,7 @@ public:
|
|||
void YSF_pin(bool on);
|
||||
void P25_pin(bool on);
|
||||
void NXDN_pin(bool on);
|
||||
void POCSAG_pin(bool on);
|
||||
void COS_pin(bool on);
|
||||
void interrupt(void);
|
||||
#if defined(DUPLEX)
|
||||
|
|
@ -92,7 +94,7 @@ public:
|
|||
void process(void);
|
||||
bool hasTXOverflow(void);
|
||||
bool hasRXOverflow(void);
|
||||
uint8_t setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_power);
|
||||
uint8_t setFreq(uint32_t frequency_rx, uint32_t frequency_tx, uint8_t rf_power, uint32_t pocsag_freq_tx);
|
||||
void setPower(uint8_t power);
|
||||
void setMode(MMDVM_STATE modemState);
|
||||
void setDecode(bool dcd);
|
||||
|
|
@ -110,7 +112,7 @@ public:
|
|||
#endif
|
||||
void start(void);
|
||||
void startInt(void);
|
||||
void setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, bool ysfLoDev);
|
||||
void setDeviations(uint8_t dstarTXLevel, uint8_t dmrTXLevel, uint8_t ysfTXLevel, uint8_t p25TXLevel, uint8_t nxdnTXLevel, uint8_t pocsagTXLevel, bool ysfLoDev);
|
||||
void updateCal(void);
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
|
|
@ -131,6 +133,7 @@ public:
|
|||
uint16_t devYSF(void);
|
||||
uint16_t devP25(void);
|
||||
uint16_t devNXDN(void);
|
||||
uint16_t devPOCSAG(void);
|
||||
void printConf();
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,21 @@ void CIO::P25_pin(bool on)
|
|||
|
||||
void CIO::NXDN_pin(bool on)
|
||||
{
|
||||
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
digitalWrite(PIN_YSF_LED, on ? HIGH : LOW);
|
||||
digitalWrite(PIN_P25_LED, on ? HIGH : LOW);
|
||||
#else
|
||||
digitalWrite(PIN_NXDN_LED, on ? HIGH : LOW);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::POCSAG_pin(bool on)
|
||||
{
|
||||
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
digitalWrite(PIN_DSTAR_LED, on ? HIGH : LOW);
|
||||
digitalWrite(PIN_DMR_LED, on ? HIGH : LOW);
|
||||
#endif
|
||||
// TODO: add a separate LED pin for POCSAG mode
|
||||
}
|
||||
|
||||
void CIO::PTT_pin(bool on)
|
||||
|
|
|
|||
14
IOSTM.cpp
14
IOSTM.cpp
|
|
@ -644,7 +644,21 @@ void CIO::P25_pin(bool on)
|
|||
|
||||
void CIO::NXDN_pin(bool on)
|
||||
{
|
||||
#if defined(USE_ALTERNATE_NXDN_LEDS)
|
||||
GPIO_WriteBit(PORT_YSF_LED, PIN_YSF_LED, on ? Bit_SET : Bit_RESET);
|
||||
GPIO_WriteBit(PORT_P25_LED, PIN_P25_LED, on ? Bit_SET : Bit_RESET);
|
||||
#else
|
||||
GPIO_WriteBit(PORT_NXDN_LED, PIN_NXDN_LED, on ? Bit_SET : Bit_RESET);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CIO::POCSAG_pin(bool on)
|
||||
{
|
||||
#if defined(USE_ALTERNATE_POCSAG_LEDS)
|
||||
GPIO_WriteBit(PORT_DSTAR_LED, PIN_DSTAR_LED, on ? Bit_SET : Bit_RESET);
|
||||
GPIO_WriteBit(PORT_DMR_LED, PIN_DMR_LED, on ? Bit_SET : Bit_RESET);
|
||||
#endif
|
||||
// TODO: add a separate LED pin for POCSAG mode
|
||||
}
|
||||
|
||||
void CIO::PTT_pin(bool on)
|
||||
|
|
|
|||
18
MMDVM_HS.cpp
18
MMDVM_HS.cpp
|
|
@ -31,15 +31,18 @@ MMDVM_STATE m_calState = STATE_IDLE;
|
|||
MMDVM_STATE m_modemState_prev = STATE_IDLE;
|
||||
|
||||
bool m_cwid_state = false;
|
||||
bool m_pocsag_state = false;
|
||||
|
||||
uint8_t m_cwIdTXLevel = 30;
|
||||
|
||||
uint32_t m_modeTimerCnt;
|
||||
|
||||
bool m_dstarEnable = true;
|
||||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
bool m_dstarEnable = true;
|
||||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
bool m_pocsagEnable = true;
|
||||
|
||||
bool m_duplex = false;
|
||||
|
||||
|
|
@ -69,6 +72,8 @@ CP25TX p25TX;
|
|||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CPOCSAGTX pocsagTX;
|
||||
|
||||
CCalDMR calDMR;
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
|
|
@ -115,6 +120,9 @@ void loop()
|
|||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
|
||||
if (m_pocsagEnable && m_modemState == STATE_POCSAG)
|
||||
pocsagTX.process();
|
||||
|
||||
if (m_calState == STATE_DMRCAL || m_calState == STATE_DMRDMO1K)
|
||||
calDMR.process();
|
||||
|
||||
|
|
|
|||
18
MMDVM_HS.ino
18
MMDVM_HS.ino
|
|
@ -27,15 +27,18 @@ MMDVM_STATE m_calState = STATE_IDLE;
|
|||
MMDVM_STATE m_modemState_prev = STATE_IDLE;
|
||||
|
||||
bool m_cwid_state = false;
|
||||
bool m_pocsag_state = false;
|
||||
|
||||
uint8_t m_cwIdTXLevel = 30;
|
||||
|
||||
uint32_t m_modeTimerCnt;
|
||||
|
||||
bool m_dstarEnable = true;
|
||||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
bool m_dstarEnable = true;
|
||||
bool m_dmrEnable = true;
|
||||
bool m_ysfEnable = true;
|
||||
bool m_p25Enable = true;
|
||||
bool m_nxdnEnable = true;
|
||||
bool m_pocsagEnable = true;
|
||||
|
||||
bool m_duplex = false;
|
||||
|
||||
|
|
@ -65,6 +68,8 @@ CP25TX p25TX;
|
|||
CNXDNRX nxdnRX;
|
||||
CNXDNTX nxdnTX;
|
||||
|
||||
CPOCSAGTX pocsagTX;
|
||||
|
||||
CCalDMR calDMR;
|
||||
|
||||
#if defined(SEND_RSSI_DATA)
|
||||
|
|
@ -110,6 +115,9 @@ void loop()
|
|||
if (m_nxdnEnable && m_modemState == STATE_NXDN)
|
||||
nxdnTX.process();
|
||||
|
||||
if (m_pocsagEnable && m_modemState == STATE_POCSAG)
|
||||
pocsagTX.process();
|
||||
|
||||
if (m_calState == STATE_DMRCAL || m_calState == STATE_DMRDMO1K)
|
||||
calDMR.process();
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ m_poBuffer(),
|
|||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(240U), // 200ms
|
||||
m_count(0U),
|
||||
m_delay(false),
|
||||
m_preamble(false)
|
||||
{
|
||||
|
|
@ -47,7 +46,6 @@ void CNXDNTX::process()
|
|||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_preamble = false;
|
||||
m_count = 0U;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
m_delay = false;
|
||||
|
|
|
|||
1
NXDNTX.h
1
NXDNTX.h
|
|
@ -40,7 +40,6 @@ private:
|
|||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
bool m_preamble;
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ m_poBuffer(),
|
|||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(240U), // 200ms
|
||||
m_count(0U)
|
||||
m_delay(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -43,7 +43,6 @@ void CP25TX::process()
|
|||
if (m_poLen == 0U) {
|
||||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_count = 0U;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
uint8_t length = m_buffer.get();
|
||||
|
|
|
|||
1
P25TX.h
1
P25TX.h
|
|
@ -40,7 +40,6 @@ private:
|
|||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
|
||||
void writeByte(uint8_t c);
|
||||
|
|
|
|||
27
POCSAGDefines.h
Normal file
27
POCSAGDefines.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(POCSAGDEFINES_H)
|
||||
#define POCSAGDEFINES_H
|
||||
|
||||
const uint16_t POCSAG_PREAMBLE_LENGTH_BYTES = 18U * sizeof(uint32_t);
|
||||
const uint16_t POCSAG_FRAME_LENGTH_BYTES = 17U * sizeof(uint32_t);
|
||||
const uint8_t POCSAG_SYNC = 0xAAU;
|
||||
|
||||
#endif
|
||||
117
POCSAGTX.cpp
Normal file
117
POCSAGTX.cpp
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
#include "Globals.h"
|
||||
#include "POCSAGTX.h"
|
||||
#include "POCSAGDefines.h"
|
||||
|
||||
CPOCSAGTX::CPOCSAGTX() :
|
||||
m_buffer(1000U),
|
||||
m_poBuffer(),
|
||||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(POCSAG_PREAMBLE_LENGTH_BYTES),
|
||||
m_delay(false)
|
||||
{
|
||||
}
|
||||
|
||||
void CPOCSAGTX::process()
|
||||
{
|
||||
if (m_buffer.getData() == 0U && m_poLen == 0U)
|
||||
return;
|
||||
|
||||
if (m_poLen == 0U) {
|
||||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
m_delay = false;
|
||||
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++)
|
||||
m_poBuffer[m_poLen++] = m_buffer.get();
|
||||
}
|
||||
|
||||
m_poPtr = 0U;
|
||||
}
|
||||
|
||||
if (m_poLen > 0U) {
|
||||
uint16_t space = io.getSpace();
|
||||
|
||||
while (space > 8U) {
|
||||
if (m_delay) {
|
||||
m_poPtr++;
|
||||
writeByte(POCSAG_SYNC);
|
||||
}
|
||||
else
|
||||
writeByte(m_poBuffer[m_poPtr++]);
|
||||
|
||||
space -= 8U;
|
||||
|
||||
if (m_poPtr >= m_poLen) {
|
||||
m_poPtr = 0U;
|
||||
m_poLen = 0U;
|
||||
m_delay = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CPOCSAGTX::writeData(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
if (length != POCSAG_FRAME_LENGTH_BYTES)
|
||||
return 4U;
|
||||
|
||||
uint16_t space = m_buffer.getSpace();
|
||||
if (space < POCSAG_FRAME_LENGTH_BYTES)
|
||||
return 5U;
|
||||
|
||||
for (uint8_t i = 0U; i < POCSAG_FRAME_LENGTH_BYTES; i++)
|
||||
m_buffer.put(data[i]);
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
void CPOCSAGTX::writeByte(uint8_t c)
|
||||
{
|
||||
uint8_t bit;
|
||||
uint8_t mask = 0x80U;
|
||||
|
||||
for (uint8_t i = 0U; i < 8U; i++, c <<= 1) {
|
||||
if ((c & mask) == mask)
|
||||
bit = 1U;
|
||||
else
|
||||
bit = 0U;
|
||||
|
||||
io.write(&bit, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void CPOCSAGTX::setTXDelay(uint8_t delay)
|
||||
{
|
||||
m_txDelay = POCSAG_PREAMBLE_LENGTH_BYTES + (delay * 3U) / 2U;
|
||||
|
||||
if (m_txDelay > 150U)
|
||||
m_txDelay = 150U;
|
||||
}
|
||||
|
||||
uint8_t CPOCSAGTX::getSpace() const
|
||||
{
|
||||
return m_buffer.getSpace() / POCSAG_FRAME_LENGTH_BYTES;
|
||||
}
|
||||
46
POCSAGTX.h
Normal file
46
POCSAGTX.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Andy Uribe CA6JAU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(POCSAGTX_H)
|
||||
#define POCSAGTX_H
|
||||
|
||||
class CPOCSAGTX {
|
||||
public:
|
||||
CPOCSAGTX();
|
||||
|
||||
uint8_t writeData(const uint8_t* data, uint8_t length);
|
||||
|
||||
void setTXDelay(uint8_t delay);
|
||||
|
||||
uint8_t getSpace() const;
|
||||
|
||||
void process();
|
||||
|
||||
private:
|
||||
CSerialRB m_buffer;
|
||||
uint8_t m_poBuffer[200U];
|
||||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
bool m_delay;
|
||||
|
||||
void writeByte(uint8_t c);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# Introduction
|
||||
|
||||
This is the source code of ZUMspot/MMDVM_HS firmware for personal hotspots (ADF7021 version of the MMDVM firmware), based on Jonathan G4KLX's [MMDVM](https://github.com/g4klx/MMDVM) software. This firmware supports D-Star, DMR, System Fusion, P25 and NXDN digital modes.
|
||||
This is the source code of ZUMspot/MMDVM_HS firmware for personal hotspots (ADF7021 version of the MMDVM firmware), based on Jonathan G4KLX's [MMDVM](https://github.com/g4klx/MMDVM) software. This firmware supports D-Star, DMR, System Fusion, P25 and NXDN digital voice modes and POCSAG 1200 pager protocol.
|
||||
|
||||
This software is intended to be run on STM32F103 microcontroller. Also, Arduino with 3.3 V I/O (Arduino Due and Zero) and Teensy (3.1, 3.2, 3.5 or 3.6) are supported. You can build this code using Arduino IDE with Roger Clark's [STM32duino](https://github.com/rogerclarkmelbourne/Arduino_STM32/tree/ZUMspot) package, or using command line tools with ARM GCC tools. The preferred method under Windows is using STM32duino, and under Linux or macOS (command line) is using [STM32F10X_Lib](https://github.com/juribeparada/STM32F10X_Lib).
|
||||
|
||||
|
|
@ -11,8 +11,10 @@ This software is licenced under the GPL v2 and is intended for amateur and educa
|
|||
# Features
|
||||
|
||||
- Supported modes: D-Star, DMR, Yaesu Fusion, P25 Phase 1 and NXDN
|
||||
- Other modes: POCSAG 1200
|
||||
- Automatic mode detection (scanning)
|
||||
- G4KLX software suite: [MMDVMHost](https://github.com/g4klx/MMDVMHost), [ircDDBGateway](https://github.com/dl5di/OpenDV), [YSFGateway](https://github.com/g4klx/YSFClients), [P25Gateway](https://github.com/g4klx/P25Clients), [DMRGateway](https://github.com/g4klx/DMRGateway), [NXDNGateway](https://github.com/g4klx/NXDNClients) and [MMDVMCal](https://github.com/g4klx/MMDVMCal)
|
||||
- G4KLX software suite: [MMDVMHost](https://github.com/g4klx/MMDVMHost), [ircDDBGateway](https://github.com/g4klx/ircDDBGateway), [YSFGateway](https://github.com/g4klx/YSFClients), [P25Gateway](https://github.com/g4klx/P25Clients), [DMRGateway](https://github.com/g4klx/DMRGateway), [NXDNGateway](https://github.com/g4klx/NXDNClients),
|
||||
[DAPNETGateway](https://github.com/g4klx/DAPNETGateway) and [MMDVMCal](https://github.com/g4klx/MMDVMCal)
|
||||
- Bands: 144, 220, 430 and 900 MHz (VHF requires external inductor)
|
||||
- Status LEDs (PTT, COR and digital modes)
|
||||
- Serial repeater port for Nextion displays
|
||||
|
|
|
|||
138
SerialPort.cpp
138
SerialPort.cpp
|
|
@ -59,6 +59,8 @@ const uint8_t MMDVM_P25_LOST = 0x32U;
|
|||
const uint8_t MMDVM_NXDN_DATA = 0x40U;
|
||||
const uint8_t MMDVM_NXDN_LOST = 0x41U;
|
||||
|
||||
const uint8_t MMDVM_POCSAG_DATA = 0x50U;
|
||||
|
||||
const uint8_t MMDVM_ACK = 0x70U;
|
||||
const uint8_t MMDVM_NAK = 0x7FU;
|
||||
|
||||
|
|
@ -114,7 +116,7 @@ void CSerialPort::getStatus()
|
|||
|
||||
// Send all sorts of interesting internal values
|
||||
reply[0U] = MMDVM_FRAME_START;
|
||||
reply[1U] = 12U;
|
||||
reply[1U] = 13U;
|
||||
reply[2U] = MMDVM_GET_STATUS;
|
||||
|
||||
reply[3U] = 0x00U;
|
||||
|
|
@ -128,6 +130,8 @@ void CSerialPort::getStatus()
|
|||
reply[3U] |= 0x08U;
|
||||
if (m_nxdnEnable)
|
||||
reply[3U] |= 0x10U;
|
||||
if (m_pocsagEnable)
|
||||
reply[3U] |= 0x20U;
|
||||
|
||||
reply[4U] = uint8_t(m_modemState);
|
||||
|
||||
|
|
@ -177,7 +181,12 @@ void CSerialPort::getStatus()
|
|||
else
|
||||
reply[11U] = 0U;
|
||||
|
||||
writeInt(1U, reply, 12);
|
||||
if (m_pocsagEnable)
|
||||
reply[12U] = pocsagTX.getSpace();
|
||||
else
|
||||
reply[12U] = 0U;
|
||||
|
||||
writeInt(1U, reply, 13);
|
||||
}
|
||||
|
||||
void CSerialPort::getVersion()
|
||||
|
|
@ -209,11 +218,12 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
|
||||
m_debug = (data[0U] & 0x10U) == 0x10U;
|
||||
|
||||
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
|
||||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
bool dstarEnable = (data[1U] & 0x01U) == 0x01U;
|
||||
bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
|
||||
bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
|
||||
bool p25Enable = (data[1U] & 0x08U) == 0x08U;
|
||||
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
|
||||
bool pocsagEnable = (data[1U] & 0x20U) == 0x20U;
|
||||
|
||||
uint8_t txDelay = data[2U];
|
||||
if (txDelay > 50U)
|
||||
|
|
@ -221,7 +231,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
|
||||
MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
|
||||
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !dstarEnable)
|
||||
return 4U;
|
||||
|
|
@ -233,6 +243,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
return 4U;
|
||||
if (modemState == STATE_NXDN && !nxdnEnable)
|
||||
return 4U;
|
||||
if (modemState == STATE_POCSAG && !pocsagEnable)
|
||||
return 4U;
|
||||
|
||||
uint8_t colorCode = data[6U];
|
||||
if (colorCode > 15U)
|
||||
|
|
@ -244,22 +256,27 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
|
||||
m_cwIdTXLevel = data[5U]>>2;
|
||||
|
||||
uint8_t dstarTXLevel = data[9U];
|
||||
uint8_t dmrTXLevel = data[10U];
|
||||
uint8_t ysfTXLevel = data[11U];
|
||||
uint8_t p25TXLevel = data[12U];
|
||||
uint8_t nxdnTXLevel = 128U;
|
||||
uint8_t dstarTXLevel = data[9U];
|
||||
uint8_t dmrTXLevel = data[10U];
|
||||
uint8_t ysfTXLevel = data[11U];
|
||||
uint8_t p25TXLevel = data[12U];
|
||||
uint8_t nxdnTXLevel = 128U;
|
||||
uint8_t pocsagTXLevel = 128U;
|
||||
|
||||
if (length >= 16U)
|
||||
nxdnTXLevel = data[15U];
|
||||
|
||||
io.setDeviations(dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, ysfLoDev);
|
||||
if (length >= 18U)
|
||||
pocsagTXLevel = data[17U];
|
||||
|
||||
m_dstarEnable = dstarEnable;
|
||||
m_dmrEnable = dmrEnable;
|
||||
m_ysfEnable = ysfEnable;
|
||||
m_p25Enable = p25Enable;
|
||||
m_nxdnEnable = nxdnEnable;
|
||||
io.setDeviations(dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, ysfLoDev);
|
||||
|
||||
m_dstarEnable = dstarEnable;
|
||||
m_dmrEnable = dmrEnable;
|
||||
m_ysfEnable = ysfEnable;
|
||||
m_p25Enable = p25Enable;
|
||||
m_nxdnEnable = nxdnEnable;
|
||||
m_pocsagEnable = pocsagEnable;
|
||||
|
||||
if (modemState == STATE_DMRCAL || modemState == STATE_DMRDMO1K || modemState == STATE_RSSICAL) {
|
||||
m_dmrEnable = true;
|
||||
|
|
@ -288,6 +305,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
ysfTX.setTXDelay(txDelay);
|
||||
p25TX.setTXDelay(txDelay);
|
||||
nxdnTX.setTXDelay(txDelay);
|
||||
pocsagTX.setTXDelay(txDelay);
|
||||
dmrDMOTX.setTXDelay(txDelay);
|
||||
|
||||
#if defined(DUPLEX)
|
||||
|
|
@ -312,6 +330,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
|
|||
io.ifConf(STATE_P25, true);
|
||||
else if(m_nxdnEnable)
|
||||
io.ifConf(STATE_NXDN, true);
|
||||
else if(m_pocsagEnable)
|
||||
io.ifConf(STATE_POCSAG, true);
|
||||
}
|
||||
|
||||
io.start();
|
||||
|
|
@ -336,7 +356,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||
if (modemState == m_modemState)
|
||||
return 0U;
|
||||
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL)
|
||||
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN && modemState != STATE_POCSAG && modemState != STATE_DSTARCAL && modemState != STATE_DMRCAL && modemState != STATE_DMRDMO1K && modemState != STATE_RSSICAL)
|
||||
return 4U;
|
||||
if (modemState == STATE_DSTAR && !m_dstarEnable)
|
||||
return 4U;
|
||||
|
|
@ -348,6 +368,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||
return 4U;
|
||||
if (modemState == STATE_NXDN && !m_nxdnEnable)
|
||||
return 4U;
|
||||
if (modemState == STATE_POCSAG && !m_pocsagEnable)
|
||||
return 4U;
|
||||
|
||||
if (modemState == STATE_DMRCAL || modemState == STATE_DMRDMO1K || modemState == STATE_RSSICAL) {
|
||||
m_dmrEnable = true;
|
||||
|
|
@ -368,31 +390,41 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
|
|||
|
||||
uint8_t CSerialPort::setFreq(const uint8_t* data, uint8_t length)
|
||||
{
|
||||
uint32_t freq_rx, freq_tx;
|
||||
uint8_t rf_power;
|
||||
uint32_t freq_rx, freq_tx, pocsag_freq_tx;
|
||||
uint8_t rf_power;
|
||||
|
||||
if (length < 9U)
|
||||
return 4U;
|
||||
if (length < 9U)
|
||||
return 4U;
|
||||
|
||||
// Old MMDVMHost, set full power
|
||||
if (length == 9U)
|
||||
rf_power = 255U;
|
||||
// Very old MMDVMHost, set full power
|
||||
if (length == 9U)
|
||||
rf_power = 255U;
|
||||
|
||||
// New MMDVMHost, set power from MMDVM.ini
|
||||
if (length == 10U)
|
||||
rf_power = data[9U];
|
||||
// Current MMDVMHost, set power from MMDVM.ini
|
||||
if (length >= 10U)
|
||||
rf_power = data[9U];
|
||||
|
||||
freq_rx = data[1U] * 1U;
|
||||
freq_rx += data[2U] * 256U;
|
||||
freq_rx += data[3U] * 65536U;
|
||||
freq_rx += data[4U] * 16777216U;
|
||||
freq_rx = data[1U] << 0;
|
||||
freq_rx |= data[2U] << 8;
|
||||
freq_rx |= data[3U] << 16;
|
||||
freq_rx |= data[4U] << 24;
|
||||
|
||||
freq_tx = data[5U] * 1U;
|
||||
freq_tx += data[6U] * 256U;
|
||||
freq_tx += data[7U] * 65536U;
|
||||
freq_tx += data[8U] * 16777216U;
|
||||
freq_tx = data[5U] << 0;
|
||||
freq_tx |= data[6U] << 8;
|
||||
freq_tx |= data[7U] << 16;
|
||||
freq_tx |= data[8U] << 24;
|
||||
|
||||
return io.setFreq(freq_rx, freq_tx, rf_power);
|
||||
// New MMDVMHost, set POCSAG TX frequency
|
||||
if (length >= 14U) {
|
||||
pocsag_freq_tx = data[10U] << 0;
|
||||
pocsag_freq_tx |= data[11U] << 8;
|
||||
pocsag_freq_tx |= data[12U] << 16;
|
||||
pocsag_freq_tx |= data[13U] << 24;
|
||||
}
|
||||
else
|
||||
pocsag_freq_tx = freq_tx;
|
||||
|
||||
return io.setFreq(freq_rx, freq_tx, rf_power, pocsag_freq_tx);
|
||||
}
|
||||
|
||||
void CSerialPort::setMode(MMDVM_STATE modemState)
|
||||
|
|
@ -454,6 +486,19 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
|
|||
p25RX.reset();
|
||||
cwIdTX.reset();
|
||||
break;
|
||||
case STATE_POCSAG:
|
||||
DEBUG1("Mode set to POCSAG");
|
||||
#if defined(DUPLEX)
|
||||
dmrIdleRX.reset();
|
||||
dmrRX.reset();
|
||||
#endif
|
||||
dmrDMORX.reset();
|
||||
dstarRX.reset();
|
||||
ysfRX.reset();
|
||||
p25RX.reset();
|
||||
nxdnRX.reset();
|
||||
cwIdTX.reset();
|
||||
break;
|
||||
default:
|
||||
DEBUG1("Mode set to Idle");
|
||||
// STATE_IDLE
|
||||
|
|
@ -751,6 +796,21 @@ void CSerialPort::process()
|
|||
}
|
||||
break;
|
||||
|
||||
case MMDVM_POCSAG_DATA:
|
||||
if (m_pocsagEnable) {
|
||||
if (m_modemState == STATE_IDLE || m_modemState == STATE_POCSAG)
|
||||
m_pocsag_state = true;
|
||||
err = pocsagTX.writeData(m_buffer + 3U, m_len - 3U);
|
||||
}
|
||||
if (err == 0U) {
|
||||
if (m_modemState == STATE_IDLE)
|
||||
setMode(STATE_POCSAG);
|
||||
} else {
|
||||
DEBUG2("Received invalid POCSAG data", err);
|
||||
sendNAK(err);
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(SERIAL_REPEATER) || defined(SERIAL_REPEATER_USART1)
|
||||
case MMDVM_SERIAL:
|
||||
writeInt(3U, m_buffer + 3U, m_len - 3U);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ m_poBuffer(),
|
|||
m_poLen(0U),
|
||||
m_poPtr(0U),
|
||||
m_txDelay(240U), // 200ms
|
||||
m_count(0U)
|
||||
m_delay(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +44,6 @@ void CYSFTX::process()
|
|||
if (m_poLen == 0U) {
|
||||
if (!m_tx) {
|
||||
m_delay = true;
|
||||
m_count = 0U;
|
||||
m_poLen = m_txDelay;
|
||||
} else {
|
||||
m_delay = false;
|
||||
|
|
|
|||
1
YSFTX.h
1
YSFTX.h
|
|
@ -40,7 +40,6 @@ private:
|
|||
uint16_t m_poLen;
|
||||
uint16_t m_poPtr;
|
||||
uint16_t m_txDelay;
|
||||
uint32_t m_count;
|
||||
bool m_delay;
|
||||
|
||||
void writeByte(uint8_t c);
|
||||
|
|
|
|||
Loading…
Reference in a new issue