Merge branch 'master' into devel

pull/32/head
Andy CA6JAU 8 years ago
commit 4ac0f51887

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
* *
* Some of the code is based on work of Guus Van Dooren PE1PLM: * Some of the code is based on work of Guus Van Dooren PE1PLM:
@ -33,7 +33,7 @@
volatile bool totx_request = false; volatile bool totx_request = false;
volatile bool torx_request = false; volatile bool torx_request = false;
volatile bool even = true; volatile bool even = true;
static uint32_t last_clk = 2; static uint32_t last_clk = 2U;
volatile uint32_t AD7021_control_word; volatile uint32_t AD7021_control_word;
@ -100,7 +100,7 @@ void Send_AD7021_control2(bool doSle)
uint16_t CIO::readRSSI() uint16_t CIO::readRSSI()
{ {
uint32_t AD7021_RB; uint32_t AD7021_RB;
uint16_t RB_word = 0; uint16_t RB_word = 0U;
int AD7021_counter; int AD7021_counter;
uint8_t RB_code, gain_code, gain_corr; uint8_t RB_code, gain_code, gain_corr;
@ -145,22 +145,22 @@ uint16_t CIO::readRSSI()
switch(gain_code) { switch(gain_code) {
case 0b1010: case 0b1010:
gain_corr = 0; gain_corr = 0U;
break; break;
case 0b0110: case 0b0110:
gain_corr = 24; gain_corr = 24U;
break; break;
case 0b0101: case 0b0101:
gain_corr = 38; gain_corr = 38U;
break; break;
case 0b0100: case 0b0100:
gain_corr = 58; gain_corr = 58U;
break; break;
case 0b0000: case 0b0000:
gain_corr = 86; gain_corr = 86U;
break; break;
default: default:
gain_corr = 0; gain_corr = 0U;
break; break;
} }
@ -173,12 +173,12 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
{ {
float divider; float divider;
uint32_t ADF7021_REG2 = 0; uint32_t ADF7021_REG2 = 0U;
uint32_t ADF7021_REG3 = 0; uint32_t ADF7021_REG3 = 0U;
uint32_t ADF7021_REG4 = 0; uint32_t ADF7021_REG4 = 0U;
uint32_t ADF7021_REG10 = 0; uint32_t ADF7021_REG10 = 0U;
uint32_t ADF7021_REG13 = 0; uint32_t ADF7021_REG13 = 0U;
uint32_t AFC_OFFSET = 0; int32_t AFC_OFFSET = 0;
if(modemState != STATE_CWID) if(modemState != STATE_CWID)
m_modemState_prev = modemState; m_modemState_prev = modemState;
@ -232,6 +232,9 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
case STATE_P25: case STATE_P25:
AFC_OFFSET = AFC_OFFSET_P25; AFC_OFFSET = AFC_OFFSET_P25;
break; break;
case STATE_NXDN:
AFC_OFFSET = AFC_OFFSET_NXDN;
break;
default: default:
break; break;
} }
@ -409,6 +412,33 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset)
#endif #endif
break; break;
case STATE_NXDN:
// Dev: +1 symb 350 Hz, symb rate = 2400
ADF7021_REG3 = ADF7021_REG3_NXDN;
ADF7021_REG10 = ADF7021_REG10_NXDN;
// K=32
ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4
ADF7021_REG4 |= (uint32_t) 0b011 << 4; // mode, 4FSK
ADF7021_REG4 |= (uint32_t) 0b0 << 7;
ADF7021_REG4 |= (uint32_t) 0b11 << 8;
ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_NXDN << 10; // Disc BW
ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_NXDN << 20; // Post dem BW
ADF7021_REG4 |= (uint32_t) 0b00 << 30; // IF filter (12.5 kHz)
ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13
ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_NXDN << 4; // slicer threshold
ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5)
ADF7021_REG2 |= (uint32_t) (ADF7021_DEV_NXDN / div2) << 19; // deviation
#if defined(ADF7021_DISABLE_RC_4FSK)
ADF7021_REG2 |= (uint32_t) 0b011 << 4; // modulation (4FSK)
#else
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
#endif
break;
default: default:
break; break;
} }
@ -495,11 +525,11 @@ if(m_duplex && (modemState != STATE_CWID))
#if defined(DUPLEX) #if defined(DUPLEX)
void CIO::ifConf2(MMDVM_STATE modemState) void CIO::ifConf2(MMDVM_STATE modemState)
{ {
uint32_t ADF7021_REG2 = 0; uint32_t ADF7021_REG2 = 0U;
uint32_t ADF7021_REG3 = 0; uint32_t ADF7021_REG3 = 0U;
uint32_t ADF7021_REG4 = 0; uint32_t ADF7021_REG4 = 0U;
uint32_t ADF7021_REG10 = 0; uint32_t ADF7021_REG10 = 0U;
uint32_t ADF7021_REG13 = 0; uint32_t ADF7021_REG13 = 0U;
switch (modemState) { switch (modemState) {
case STATE_DSTAR: case STATE_DSTAR:
@ -594,6 +624,29 @@ void CIO::ifConf2(MMDVM_STATE modemState)
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK) ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
break; break;
case STATE_NXDN:
// Dev: +1 symb 350 Hz, symb rate = 2400
ADF7021_REG3 = ADF7021_REG3_NXDN;
ADF7021_REG10 = ADF7021_REG10_NXDN;
// K=32
ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4
ADF7021_REG4 |= (uint32_t) 0b011 << 4; // mode, 4FSK
ADF7021_REG4 |= (uint32_t) 0b0 << 7;
ADF7021_REG4 |= (uint32_t) 0b11 << 8;
ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_NXDN << 10; // Disc BW
ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_NXDN << 20; // Post dem BW
ADF7021_REG4 |= (uint32_t) 0b00 << 30; // IF filter (12.5 kHz)
ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13
ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_NXDN << 4; // slicer threshold
ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5)
ADF7021_REG2 |= (uint32_t) (ADF7021_DEV_NXDN / div2) << 19; // deviation
ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK)
break;
default: default:
break; break;
} }
@ -664,7 +717,7 @@ void CIO::ifConf2(MMDVM_STATE modemState)
void CIO::interrupt() void CIO::interrupt()
{ {
uint8_t bit = 0; uint8_t bit = 0U;
if (!m_started) if (!m_started)
return; return;
@ -687,7 +740,7 @@ void CIO::interrupt()
} }
// we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock // we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock
if (m_tx && clk == 0) { if (m_tx && clk == 0U) {
m_txBuffer.get(bit, m_control); m_txBuffer.get(bit, m_control);
even = !even; even = !even;
@ -729,19 +782,19 @@ void CIO::interrupt()
} }
// we sample the RX bit at rising TXD clock edge, so TXD must be 1 and we are not in tx mode // we sample the RX bit at rising TXD clock edge, so TXD must be 1 and we are not in tx mode
if (!m_tx && clk == 1 && !m_duplex) { if (!m_tx && clk == 1U && !m_duplex) {
if(RXD_pin()) if(RXD_pin())
bit = 1; bit = 1U;
else else
bit = 0; bit = 0U;
m_rxBuffer.put(bit, m_control); m_rxBuffer.put(bit, m_control);
} }
if (torx_request == true && even == ADF7021_EVEN_BIT && m_tx && clk == 0) { if (torx_request == true && even == ADF7021_EVEN_BIT && m_tx && clk == 0U) {
// that is absolutely crucial in 4FSK, see datasheet: // that is absolutely crucial in 4FSK, see datasheet:
// enable sle after 1/4 tBit == 26uS when sending MSB (even == false) and clock is low // enable sle after 1/4 tBit == 26uS when sending MSB (even == false) and clock is low
delay_us(26); delay_us(26U);
// SLE Pulse, should be moved out of here into class method // SLE Pulse, should be moved out of here into class method
SLE_pin(HIGH); SLE_pin(HIGH);
@ -764,22 +817,22 @@ void CIO::interrupt()
m_modeTimerCnt++; m_modeTimerCnt++;
if(m_scanPauseCnt >= SCAN_PAUSE) if(m_scanPauseCnt >= SCAN_PAUSE)
m_scanPauseCnt = 0; m_scanPauseCnt = 0U;
if(m_scanPauseCnt != 0) if(m_scanPauseCnt != 0U)
m_scanPauseCnt++; m_scanPauseCnt++;
} }
#if defined(DUPLEX) #if defined(DUPLEX)
void CIO::interrupt2() void CIO::interrupt2()
{ {
uint8_t bit = 0; uint8_t bit = 0U;
if(m_duplex) { if(m_duplex) {
if(RXD2_pin()) if(RXD2_pin())
bit = 1; bit = 1U;
else else
bit = 0; bit = 0U;
m_rxBuffer.put(bit, m_control); m_rxBuffer.put(bit, m_control);
} }
@ -865,6 +918,11 @@ uint16_t CIO::devP25()
return (uint16_t)((ADF7021_PFD * ADF7021_DEV_P25) / (f_div * 65536)); return (uint16_t)((ADF7021_PFD * ADF7021_DEV_P25) / (f_div * 65536));
} }
uint16_t CIO::devNXDN()
{
return (uint16_t)((ADF7021_PFD * ADF7021_DEV_NXDN) / (f_div * 65536));
}
void CIO::printConf() void CIO::printConf()
{ {
DEBUG1("MMDVM_HS FW configuration:"); DEBUG1("MMDVM_HS FW configuration:");
@ -876,6 +934,7 @@ void CIO::printConf()
DEBUG2("YSF_H +1 sym dev (Hz):", devYSF_H()); DEBUG2("YSF_H +1 sym dev (Hz):", devYSF_H());
DEBUG2("YSF_L +1 sym dev (Hz):", devYSF_L()); DEBUG2("YSF_L +1 sym dev (Hz):", devYSF_L());
DEBUG2("P25 +1 sym dev (Hz):", devP25()); DEBUG2("P25 +1 sym dev (Hz):", devP25());
DEBUG2("NXDN +1 sym dev (Hz):", devNXDN());
} }
#endif #endif

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2016 by Jim McLaughlin KI6ZUM * Copyright (C) 2016 by Jim McLaughlin KI6ZUM
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
* *
* Some of the code is based on work of Guus Van Dooren PE1PLM: * Some of the code is based on work of Guus Van Dooren PE1PLM:
@ -66,6 +66,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
// DEMOD_CLK = 2.4576 MHz (DSTAR) // DEMOD_CLK = 2.4576 MHz (DSTAR)
// DEMOD_CLK = 4.9152 MHz (DMR, YSF_L, P25) // DEMOD_CLK = 4.9152 MHz (DMR, YSF_L, P25)
// DEMOD_CLK = 7.3728 MHz (YSF_H) // DEMOD_CLK = 7.3728 MHz (YSF_H)
// DEMOD CLK = 3.6864 MHz (NXDN)
#define ADF7021_PFD 3686400.0 #define ADF7021_PFD 3686400.0
// PLL (REG 01) // PLL (REG 01)
@ -84,6 +85,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#else #else
#define ADF7021_DEV_P25 22U #define ADF7021_DEV_P25 22U
#endif #endif
#define ADF7021_DEV_NXDN 13U
// TX/RX CLOCK register (REG 03) // TX/RX CLOCK register (REG 03)
#define ADF7021_REG3_DSTAR 0x2A4C4193 #define ADF7021_REG3_DSTAR 0x2A4C4193
@ -92,11 +94,13 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG3_YSF_L 0x2A4C04D3 #define ADF7021_REG3_YSF_L 0x2A4C04D3
#define ADF7021_REG3_YSF_H 0x2A4C0493 #define ADF7021_REG3_YSF_H 0x2A4C0493
#define ADF7021_REG3_P25 0x2A4C04D3 #define ADF7021_REG3_P25 0x2A4C04D3
#define ADF7021_REG3_NXDN 0x2A4C04D3
#else #else
#define ADF7021_REG3_DMR 0x2A4C80D3 #define ADF7021_REG3_DMR 0x2A4C80D3
#define ADF7021_REG3_YSF_L 0x2A4C80D3 #define ADF7021_REG3_YSF_L 0x2A4C80D3
#define ADF7021_REG3_YSF_H 0x2A4CC093 #define ADF7021_REG3_YSF_H 0x2A4CC093
#define ADF7021_REG3_P25 0x2A4C80D3 #define ADF7021_REG3_P25 0x2A4C80D3
#define ADF7021_REG3_NXDN 0x2A4CC113
#endif #endif
// Discriminator bandwith, demodulator (REG 04) // Discriminator bandwith, demodulator (REG 04)
@ -106,12 +110,14 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_DISC_BW_YSF_L 393U // K=32 #define ADF7021_DISC_BW_YSF_L 393U // K=32
#define ADF7021_DISC_BW_YSF_H 516U // K=28 #define ADF7021_DISC_BW_YSF_H 516U // K=28
#define ADF7021_DISC_BW_P25 394U // K=32 #define ADF7021_DISC_BW_P25 394U // K=32
#define ADF7021_DISC_BW_NXDN 295U // K=32
// Post demodulator bandwith (REG 04) // Post demodulator bandwith (REG 04)
#define ADF7021_POST_BW_DSTAR 10U #define ADF7021_POST_BW_DSTAR 10U
#define ADF7021_POST_BW_DMR 150U #define ADF7021_POST_BW_DMR 150U
#define ADF7021_POST_BW_YSF 20U #define ADF7021_POST_BW_YSF 20U
#define ADF7021_POST_BW_P25 6U #define ADF7021_POST_BW_P25 6U
#define ADF7021_POST_BW_NXDN 7U
// IF filter (REG 05) // IF filter (REG 05)
#define ADF7021_REG5 0x000024F5 #define ADF7021_REG5 0x000024F5
@ -126,22 +132,27 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG10_DMR 0x01FE473A #define ADF7021_REG10_DMR 0x01FE473A
#define ADF7021_REG10_YSF 0x01FE473A #define ADF7021_REG10_YSF 0x01FE473A
#define ADF7021_REG10_P25 0x01FE473A #define ADF7021_REG10_P25 0x01FE473A
#define ADF7021_REG10_NXDN 0x01FE473A
#if defined(ADF7021_AFC_POS) #if defined(ADF7021_AFC_POS)
#define AFC_OFFSET_DMR -250 #define AFC_OFFSET_DMR -250
#define AFC_OFFSET_YSF -250 #define AFC_OFFSET_YSF -250
#define AFC_OFFSET_P25 -250 #define AFC_OFFSET_P25 -250
#define AFC_OFFSET_NXDN -250
#else #else
#define AFC_OFFSET_DMR 250 #define AFC_OFFSET_DMR 250
#define AFC_OFFSET_YSF 250 #define AFC_OFFSET_YSF 250
#define AFC_OFFSET_P25 250 #define AFC_OFFSET_P25 250
#define AFC_OFFSET_NXDN 250
#endif #endif
#else #else
#define ADF7021_REG10_DMR 0x049E472A #define ADF7021_REG10_DMR 0x049E472A
#define ADF7021_REG10_YSF 0x049E472A #define ADF7021_REG10_YSF 0x049E472A
#define ADF7021_REG10_P25 0x049E472A #define ADF7021_REG10_P25 0x049E472A
#define ADF7021_REG10_NXDN 0x049E472A
#define AFC_OFFSET_DMR 0 #define AFC_OFFSET_DMR 0
#define AFC_OFFSET_YSF 0 #define AFC_OFFSET_YSF 0
#define AFC_OFFSET_P25 0 #define AFC_OFFSET_P25 0
#define AFC_OFFSET_NXDN 0
#endif #endif
/****** Support for 12.2880 MHz TCXO ******/ /****** Support for 12.2880 MHz TCXO ******/
@ -150,6 +161,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
// R = 2 // R = 2
// DEMOD_CLK = 2.4576 MHz (DSTAR) // DEMOD_CLK = 2.4576 MHz (DSTAR)
// DEMOD_CLK = 6.1440 MHz (DMR, YSF_H, YSF_L, P25) // DEMOD_CLK = 6.1440 MHz (DMR, YSF_H, YSF_L, P25)
// DEMOD_CLK = 3.0720 MHz (NXDN)
#define ADF7021_PFD 6144000.0 #define ADF7021_PFD 6144000.0
// PLL (REG 01) // PLL (REG 01)
@ -168,6 +180,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#else #else
#define ADF7021_DEV_P25 13U #define ADF7021_DEV_P25 13U
#endif #endif
#define ADF7021_DEV_NXDN 8U
// TX/RX CLOCK register (REG 03) // TX/RX CLOCK register (REG 03)
#define ADF7021_REG3_DSTAR 0x29EC4153 #define ADF7021_REG3_DSTAR 0x29EC4153
@ -176,11 +189,13 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG3_YSF_L 0x29EC0493 #define ADF7021_REG3_YSF_L 0x29EC0493
#define ADF7021_REG3_YSF_H 0x29EC0493 #define ADF7021_REG3_YSF_H 0x29EC0493
#define ADF7021_REG3_P25 0x29EC0493 #define ADF7021_REG3_P25 0x29EC0493
#define ADF7021_REG3_NXDN 0x29EC0493
#else #else
#define ADF7021_REG3_DMR 0x29ECA093 #define ADF7021_REG3_DMR 0x29ECA093
#define ADF7021_REG3_YSF_L 0x29ECA093 #define ADF7021_REG3_YSF_L 0x29ECA093
#define ADF7021_REG3_YSF_H 0x29ECA093 #define ADF7021_REG3_YSF_H 0x29ECA093
#define ADF7021_REG3_P25 0x29ECA093 #define ADF7021_REG3_P25 0x29ECA093
#define ADF7021_REG3_NXDN 0x29ECA113
#endif #endif
// Discriminator bandwith, demodulator (REG 04) // Discriminator bandwith, demodulator (REG 04)
@ -190,12 +205,14 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_DISC_BW_YSF_L 491U // K=32 #define ADF7021_DISC_BW_YSF_L 491U // K=32
#define ADF7021_DISC_BW_YSF_H 430U // K=28 #define ADF7021_DISC_BW_YSF_H 430U // K=28
#define ADF7021_DISC_BW_P25 493U // K=32 #define ADF7021_DISC_BW_P25 493U // K=32
#define ADF7021_DISC_BW_NXDN 246U // K=32
// Post demodulator bandwith (REG 04) // Post demodulator bandwith (REG 04)
#define ADF7021_POST_BW_DSTAR 10U #define ADF7021_POST_BW_DSTAR 10U
#define ADF7021_POST_BW_DMR 150U #define ADF7021_POST_BW_DMR 150U
#define ADF7021_POST_BW_YSF 20U #define ADF7021_POST_BW_YSF 20U
#define ADF7021_POST_BW_P25 6U #define ADF7021_POST_BW_P25 6U
#define ADF7021_POST_BW_NXDN 8U
// IF filter (REG 05) // IF filter (REG 05)
#define ADF7021_REG5 0x00001ED5 #define ADF7021_REG5 0x00001ED5
@ -210,22 +227,27 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_REG10_DMR 0x01FE557A #define ADF7021_REG10_DMR 0x01FE557A
#define ADF7021_REG10_YSF 0x01FE557A #define ADF7021_REG10_YSF 0x01FE557A
#define ADF7021_REG10_P25 0x01FE557A #define ADF7021_REG10_P25 0x01FE557A
#define ADF7021_REG10_NXDN 0x01FE557A
#if defined(ADF7021_AFC_POS) #if defined(ADF7021_AFC_POS)
#define AFC_OFFSET_DMR -250 #define AFC_OFFSET_DMR -250
#define AFC_OFFSET_YSF -250 #define AFC_OFFSET_YSF -250
#define AFC_OFFSET_P25 -250 #define AFC_OFFSET_P25 -250
#define AFC_OFFSET_NXDN -250
#else #else
#define AFC_OFFSET_DMR 250 #define AFC_OFFSET_DMR 250
#define AFC_OFFSET_YSF 250 #define AFC_OFFSET_YSF 250
#define AFC_OFFSET_P25 250 #define AFC_OFFSET_P25 250
#define AFC_OFFSET_NXDN 250
#endif #endif
#else #else
#define ADF7021_REG10_DMR 0x049E556A #define ADF7021_REG10_DMR 0x049E556A
#define ADF7021_REG10_YSF 0x049E556A #define ADF7021_REG10_YSF 0x049E556A
#define ADF7021_REG10_P25 0x049E556A #define ADF7021_REG10_P25 0x049E556A
#define ADF7021_REG10_NXDN 0x049E556A
#define AFC_OFFSET_DMR 0 #define AFC_OFFSET_DMR 0
#define AFC_OFFSET_YSF 0 #define AFC_OFFSET_YSF 0
#define AFC_OFFSET_P25 0 #define AFC_OFFSET_P25 0
#define AFC_OFFSET_NXDN 0
#endif #endif
#endif #endif
@ -238,6 +260,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_SLICER_TH_YSF_L 35U #define ADF7021_SLICER_TH_YSF_L 35U
#define ADF7021_SLICER_TH_YSF_H 69U #define ADF7021_SLICER_TH_YSF_H 69U
#define ADF7021_SLICER_TH_P25 43U #define ADF7021_SLICER_TH_P25 43U
#define ADF7021_SLICER_TH_NXDN 26U
#else #else
@ -246,6 +269,7 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf
#define ADF7021_SLICER_TH_YSF_L 38U #define ADF7021_SLICER_TH_YSF_L 38U
#define ADF7021_SLICER_TH_YSF_H 75U #define ADF7021_SLICER_TH_YSF_H 75U
#define ADF7021_SLICER_TH_P25 47U #define ADF7021_SLICER_TH_P25 47U
#define ADF7021_SLICER_TH_NXDN 26U
#endif #endif

@ -618,6 +618,7 @@ Status LEDs:
COS_LED PB15 COS_LED PB15
PTT_LED PB14 PTT_LED PB14
NXDN_LED PA8
P25_LED PB0 P25_LED PB0
YSF_LED PB1 YSF_LED PB1
DMR_LED PB13 DMR_LED PB13
@ -657,6 +658,7 @@ Status LEDs:
COS_LED 10 COS_LED 10
PTT_LED 9 PTT_LED 9
NXDN_LED 18
P25_LED 17 P25_LED 17
YSF_LED 16 YSF_LED 16
DMR_LED 15 DMR_LED 15
@ -698,6 +700,7 @@ Status LEDs:
COS_LED 15 COS_LED 15
PTT_LED 14 PTT_LED 14
NXDN_LED 20
P25_LED 19 P25_LED 19
YSF_LED 18 YSF_LED 18
DMR_LED 17 DMR_LED 17

@ -39,6 +39,7 @@ enum MMDVM_STATE {
STATE_DMR = 2, STATE_DMR = 2,
STATE_YSF = 3, STATE_YSF = 3,
STATE_P25 = 4, STATE_P25 = 4,
STATE_NXDN = 5,
// Dummy states start at 90 // Dummy states start at 90
STATE_CWID = 97 STATE_CWID = 97
@ -68,6 +69,8 @@ const uint8_t MARK_NONE = 0x00U;
#include "YSFTX.h" #include "YSFTX.h"
#include "P25RX.h" #include "P25RX.h"
#include "P25TX.h" #include "P25TX.h"
#include "NXDNRX.h"
#include "NXDNTX.h"
#include "CWIdTX.h" #include "CWIdTX.h"
#include "Debug.h" #include "Debug.h"
#include "Utils.h" #include "Utils.h"
@ -87,6 +90,7 @@ extern bool m_dstarEnable;
extern bool m_dmrEnable; extern bool m_dmrEnable;
extern bool m_ysfEnable; extern bool m_ysfEnable;
extern bool m_p25Enable; extern bool m_p25Enable;
extern bool m_nxdnEnable;
extern bool m_duplex; extern bool m_duplex;
@ -116,6 +120,9 @@ extern CYSFTX ysfTX;
extern CP25RX p25RX; extern CP25RX p25RX;
extern CP25TX p25TX; extern CP25TX p25TX;
extern CNXDNRX nxdnRX;
extern CNXDNTX nxdnTX;
extern CCWIdTX cwIdTX; extern CCWIdTX cwIdTX;
#endif #endif

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -47,6 +47,7 @@ m_watchdog(0U)
DMR_pin(LOW); DMR_pin(LOW);
YSF_pin(LOW); YSF_pin(LOW);
P25_pin(LOW); P25_pin(LOW);
NXDN_pin(LOW);
COS_pin(LOW); COS_pin(LOW);
DEB_pin(LOW); DEB_pin(LOW);
@ -60,18 +61,18 @@ m_watchdog(0U)
selfTest(); selfTest();
m_modeTimerCnt = 0; m_modeTimerCnt = 0U;
} }
void CIO::selfTest() void CIO::selfTest()
{ {
bool ledValue = false; bool ledValue = false;
uint32_t ledCount = 0; uint32_t ledCount = 0U;
uint32_t blinks = 0; uint32_t blinks = 0U;
while(true) { while(true) {
ledCount++; ledCount++;
delay_us(1000); delay_us(1000U);
if(ledCount >= 125U) { if(ledCount >= 125U) {
ledCount = 0U; ledCount = 0U;
@ -83,11 +84,12 @@ void CIO::selfTest()
DMR_pin(ledValue); DMR_pin(ledValue);
YSF_pin(ledValue); YSF_pin(ledValue);
P25_pin(ledValue); P25_pin(ledValue);
NXDN_pin(ledValue);
COS_pin(ledValue); COS_pin(ledValue);
blinks++; blinks++;
if(blinks > 5) if(blinks > 5U)
break; break;
} }
} }
@ -104,7 +106,7 @@ void CIO::process()
if (m_started) { if (m_started) {
// Two seconds timeout // Two seconds timeout
if (m_watchdog >= 19200U) { if (m_watchdog >= 19200U) {
if (m_modemState == STATE_DSTAR || m_modemState == STATE_DMR || m_modemState == STATE_YSF || m_modemState == STATE_P25) { 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; m_modemState = STATE_IDLE;
setMode(m_modemState); setMode(m_modemState);
} }
@ -139,18 +141,20 @@ void CIO::process()
if(m_modemState_prev == STATE_DSTAR) if(m_modemState_prev == STATE_DSTAR)
scantime = SCAN_TIME; scantime = SCAN_TIME;
else if(m_modemState_prev == STATE_DMR) else if(m_modemState_prev == STATE_DMR)
scantime = SCAN_TIME*2; scantime = SCAN_TIME * 2U;
else if(m_modemState_prev == STATE_YSF) else if(m_modemState_prev == STATE_YSF)
scantime = SCAN_TIME; scantime = SCAN_TIME;
else if(m_modemState_prev == STATE_P25) else if(m_modemState_prev == STATE_P25)
scantime = SCAN_TIME; scantime = SCAN_TIME;
else if(m_modemState_prev == STATE_NXDN)
scantime = SCAN_TIME;
else else
scantime = SCAN_TIME; scantime = SCAN_TIME;
if(m_modeTimerCnt >= scantime) { if(m_modeTimerCnt >= scantime) {
m_modeTimerCnt = 0; m_modeTimerCnt = 0U;
if( (m_modemState == STATE_IDLE) && (m_scanPauseCnt == 0) && m_scanEnable && !m_cwid_state) { if( (m_modemState == STATE_IDLE) && (m_scanPauseCnt == 0U) && m_scanEnable && !m_cwid_state) {
m_scanPos = (m_scanPos + 1) % m_TotalModes; m_scanPos = (m_scanPos + 1U) % m_TotalModes;
#if !defined(QUIET_MODE_LEDS) #if !defined(QUIET_MODE_LEDS)
setMode(m_Modes[m_scanPos]); setMode(m_Modes[m_scanPos]);
#endif #endif
@ -184,6 +188,9 @@ void CIO::process()
case STATE_P25: case STATE_P25:
p25RX.databit(bit); p25RX.databit(bit);
break; break;
case STATE_NXDN:
nxdnRX.databit(bit);
break;
default: default:
break; break;
} }
@ -193,7 +200,7 @@ void CIO::process()
void CIO::start() void CIO::start()
{ {
m_TotalModes = 0; m_TotalModes = 0U;
if(m_dstarEnable) { if(m_dstarEnable) {
m_Modes[m_TotalModes] = STATE_DSTAR; m_Modes[m_TotalModes] = STATE_DSTAR;
@ -211,9 +218,13 @@ void CIO::start()
m_Modes[m_TotalModes] = STATE_P25; m_Modes[m_TotalModes] = STATE_P25;
m_TotalModes++; m_TotalModes++;
} }
if(m_nxdnEnable) {
m_Modes[m_TotalModes] = STATE_NXDN;
m_TotalModes++;
}
#if defined(ENABLE_SCAN_MODE) #if defined(ENABLE_SCAN_MODE)
if(m_TotalModes > 1) if(m_TotalModes > 1U)
m_scanEnable = true; m_scanEnable = true;
else { else {
m_scanEnable = false; m_scanEnable = false;
@ -291,12 +302,13 @@ void CIO::setMode(MMDVM_STATE modemState)
DMR_pin(modemState == STATE_DMR); DMR_pin(modemState == STATE_DMR);
YSF_pin(modemState == STATE_YSF); YSF_pin(modemState == STATE_YSF);
P25_pin(modemState == STATE_P25); P25_pin(modemState == STATE_P25);
NXDN_pin(modemState == STATE_NXDN);
} }
void CIO::setDecode(bool dcd) void CIO::setDecode(bool dcd)
{ {
if (dcd != m_dcd) { if (dcd != m_dcd) {
m_scanPauseCnt = 1; m_scanPauseCnt = 1U;
COS_pin(dcd ? true : false); COS_pin(dcd ? true : false);
} }

@ -1,6 +1,6 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* Copyright (C) 2017 by Danilo DB4PLE * Copyright (C) 2017 by Danilo DB4PLE
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
@ -75,6 +75,7 @@ public:
void DMR_pin(bool on); void DMR_pin(bool on);
void YSF_pin(bool on); void YSF_pin(bool on);
void P25_pin(bool on); void P25_pin(bool on);
void NXDN_pin(bool on);
void COS_pin(bool on); void COS_pin(bool on);
void interrupt(void); void interrupt(void);
#if defined(DUPLEX) #if defined(DUPLEX)
@ -126,6 +127,7 @@ public:
uint16_t devYSF_H(void); uint16_t devYSF_H(void);
uint16_t devYSF_L(void); uint16_t devYSF_L(void);
uint16_t devP25(void); uint16_t devP25(void);
uint16_t devNXDN(void);
void printConf(); void printConf();
private: private:
@ -143,7 +145,7 @@ private:
uint32_t m_scanPauseCnt; uint32_t m_scanPauseCnt;
uint8_t m_scanPos; uint8_t m_scanPos;
uint8_t m_TotalModes; uint8_t m_TotalModes;
MMDVM_STATE m_Modes[4]; MMDVM_STATE m_Modes[5];
bool m_ledValue; bool m_ledValue;
volatile uint32_t m_watchdog; volatile uint32_t m_watchdog;

@ -47,6 +47,7 @@
#define PIN_DMR_LED PB13 #define PIN_DMR_LED PB13
#define PIN_YSF_LED PB1 #define PIN_YSF_LED PB1
#define PIN_P25_LED PB0 #define PIN_P25_LED PB0
#define PIN_NXDN_LED PA8
#define PIN_PTT_LED PB14 #define PIN_PTT_LED PB14
#define PIN_COS_LED PB15 #define PIN_COS_LED PB15
@ -69,6 +70,7 @@
#define PIN_DMR_LED PB13 #define PIN_DMR_LED PB13
#define PIN_YSF_LED PB1 #define PIN_YSF_LED PB1
#define PIN_P25_LED PB0 #define PIN_P25_LED PB0
#define PIN_NXDN_LED PA8
#define PIN_PTT_LED PB14 #define PIN_PTT_LED PB14
#define PIN_COS_LED PB15 #define PIN_COS_LED PB15
@ -93,6 +95,7 @@
#define PIN_DMR_LED 17 #define PIN_DMR_LED 17
#define PIN_YSF_LED 18 #define PIN_YSF_LED 18
#define PIN_P25_LED 19 #define PIN_P25_LED 19
#define PIN_NXDN_LED 20
#define PIN_PTT_LED 14 #define PIN_PTT_LED 14
#define PIN_COS_LED 15 #define PIN_COS_LED 15
@ -113,6 +116,7 @@
#define PIN_DMR_LED 15 #define PIN_DMR_LED 15
#define PIN_YSF_LED 16 #define PIN_YSF_LED 16
#define PIN_P25_LED 17 #define PIN_P25_LED 17
#define PIN_NXDN_LED 18
#define PIN_PTT_LED 9 #define PIN_PTT_LED 9
#define PIN_COS_LED 10 #define PIN_COS_LED 10
@ -163,6 +167,7 @@ void CIO::Init()
pinMode(PIN_DMR_LED, OUTPUT); pinMode(PIN_DMR_LED, OUTPUT);
pinMode(PIN_YSF_LED, OUTPUT); pinMode(PIN_YSF_LED, OUTPUT);
pinMode(PIN_P25_LED, OUTPUT); pinMode(PIN_P25_LED, OUTPUT);
pinMode(PIN_NXDN_LED, OUTPUT);
pinMode(PIN_PTT_LED, OUTPUT); pinMode(PIN_PTT_LED, OUTPUT);
pinMode(PIN_COS_LED, OUTPUT); pinMode(PIN_COS_LED, OUTPUT);
@ -306,6 +311,11 @@ void CIO::P25_pin(bool on)
digitalWrite(PIN_P25_LED, on ? HIGH : LOW); digitalWrite(PIN_P25_LED, on ? HIGH : LOW);
} }
void CIO::NXDN_pin(bool on)
{
digitalWrite(PIN_NXDN_LED, on ? HIGH : LOW);
}
void CIO::PTT_pin(bool on) void CIO::PTT_pin(bool on)
{ {
digitalWrite(PIN_PTT_LED, on ? HIGH : LOW); digitalWrite(PIN_PTT_LED, on ? HIGH : LOW);

@ -80,6 +80,9 @@
#define PIN_P25_LED GPIO_Pin_12 #define PIN_P25_LED GPIO_Pin_12
#define PORT_P25_LED GPIOA #define PORT_P25_LED GPIOA
#define PIN_NXDN_LED GPIO_Pin_8
#define PORT_NXDN_LED GPIOA
#define PIN_PTT_LED GPIO_Pin_12 #define PIN_PTT_LED GPIO_Pin_12
#define PORT_PTT_LED GPIOB #define PORT_PTT_LED GPIOB
@ -140,6 +143,9 @@
#define PIN_P25_LED GPIO_Pin_0 #define PIN_P25_LED GPIO_Pin_0
#define PORT_P25_LED GPIOB #define PORT_P25_LED GPIOB
#define PIN_NXDN_LED GPIO_Pin_8
#define PORT_NXDN_LED GPIOA
#define PIN_PTT_LED GPIO_Pin_14 #define PIN_PTT_LED GPIO_Pin_14
#define PORT_PTT_LED GPIOB #define PORT_PTT_LED GPIOB
@ -209,6 +215,9 @@
#define PIN_P25_LED GPIO_Pin_0 #define PIN_P25_LED GPIO_Pin_0
#define PORT_P25_LED GPIOB #define PORT_P25_LED GPIOB
#define PIN_NXDN_LED GPIO_Pin_8
#define PORT_NXDN_LED GPIOA
#define PIN_PTT_LED GPIO_Pin_14 #define PIN_PTT_LED GPIO_Pin_14
#define PORT_PTT_LED GPIOB #define PORT_PTT_LED GPIOB
@ -413,6 +422,12 @@ void CIO::Init()
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PORT_P25_LED, &GPIO_InitStruct); GPIO_Init(PORT_P25_LED, &GPIO_InitStruct);
// NXDN LED
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = PIN_NXDN_LED;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(PORT_NXDN_LED, &GPIO_InitStruct);
// PTT LED // PTT LED
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Pin = PIN_PTT_LED; GPIO_InitStruct.GPIO_Pin = PIN_PTT_LED;
@ -627,6 +642,11 @@ void CIO::P25_pin(bool on)
GPIO_WriteBit(PORT_P25_LED, PIN_P25_LED, on ? Bit_SET : Bit_RESET); GPIO_WriteBit(PORT_P25_LED, PIN_P25_LED, on ? Bit_SET : Bit_RESET);
} }
void CIO::NXDN_pin(bool on)
{
GPIO_WriteBit(PORT_NXDN_LED, PIN_NXDN_LED, on ? Bit_SET : Bit_RESET);
}
void CIO::PTT_pin(bool on) void CIO::PTT_pin(bool on)
{ {
GPIO_WriteBit(PORT_PTT_LED, PIN_PTT_LED, on ? Bit_SET : Bit_RESET); GPIO_WriteBit(PORT_PTT_LED, PIN_PTT_LED, on ? Bit_SET : Bit_RESET);

@ -38,6 +38,7 @@ bool m_dstarEnable = true;
bool m_dmrEnable = true; bool m_dmrEnable = true;
bool m_ysfEnable = true; bool m_ysfEnable = true;
bool m_p25Enable = true; bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_duplex = false; bool m_duplex = false;
@ -64,6 +65,9 @@ CYSFTX ysfTX;
CP25RX p25RX; CP25RX p25RX;
CP25TX p25TX; CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CCWIdTX cwIdTX; CCWIdTX cwIdTX;
CSerialPort serial; CSerialPort serial;
@ -101,6 +105,9 @@ void loop()
if (m_p25Enable && m_modemState == STATE_P25) if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process(); p25TX.process();
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
if (m_modemState == STATE_IDLE) if (m_modemState == STATE_IDLE)
cwIdTX.process(); cwIdTX.process();
} }

@ -34,6 +34,7 @@ bool m_dstarEnable = true;
bool m_dmrEnable = true; bool m_dmrEnable = true;
bool m_ysfEnable = true; bool m_ysfEnable = true;
bool m_p25Enable = true; bool m_p25Enable = true;
bool m_nxdnEnable = true;
bool m_duplex = false; bool m_duplex = false;
@ -60,6 +61,9 @@ CYSFTX ysfTX;
CP25RX p25RX; CP25RX p25RX;
CP25TX p25TX; CP25TX p25TX;
CNXDNRX nxdnRX;
CNXDNTX nxdnTX;
CCWIdTX cwIdTX; CCWIdTX cwIdTX;
CSerialPort serial; CSerialPort serial;
@ -96,6 +100,9 @@ void loop()
if (m_p25Enable && m_modemState == STATE_P25) if (m_p25Enable && m_modemState == STATE_P25)
p25TX.process(); p25TX.process();
if (m_nxdnEnable && m_modemState == STATE_NXDN)
nxdnTX.process();
if (m_modemState == STATE_IDLE) if (m_modemState == STATE_IDLE)
cwIdTX.process(); cwIdTX.process();
} }

@ -0,0 +1,50 @@
/*
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
*
* 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(NXDNDEFINES_H)
#define NXDNDEFINES_H
const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 10U; // At 24 kHz sample rate
const unsigned int NXDN_FRAME_LENGTH_BITS = 384U;
const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
const unsigned int NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
const unsigned int NXDN_FRAME_LENGTH_SAMPLES = NXDN_FRAME_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
const unsigned int NXDN_FSW_LENGTH_BITS = 20U;
const unsigned int NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
const unsigned int NXDN_FSW_LENGTH_SAMPLES = NXDN_FSW_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
const uint8_t NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U};
const uint8_t NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U};
const uint8_t NXDN_FSW_BYTES_LENGTH = 3U;
const uint32_t NXDN_FSW_BITS = 0x000CDF59U;
const uint32_t NXDN_FSW_BITS_MASK = 0x000FFFFFU;
// C D F 5 9
// 11 00 11 01 11 11 01 01 10 01
// -3 +1 -3 +3 -3 -3 +3 +3 -1 +3
const int8_t NXDN_FSW_SYMBOLS_VALUES[] = {-3, +1, -3, +3, -3, -3, +3, +3, -1, +3};
const uint16_t NXDN_FSW_SYMBOLS = 0x014DU;
const uint16_t NXDN_FSW_SYMBOLS_MASK = 0x03FFU;
#endif

@ -0,0 +1,139 @@
/*
* Copyright (C) 2009-2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,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 "NXDNRX.h"
#include "Utils.h"
const uint8_t MAX_FSW_BIT_START_ERRS = 0U;
const uint8_t MAX_FSW_BIT_RUN_ERRS = 3U;
const unsigned int MAX_FSW_FRAMES = 5U + 1U;
const uint8_t BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
CNXDNRX::CNXDNRX() :
m_prev(false),
m_state(NXDNRXS_NONE),
m_bitBuffer(0x00U),
m_outBuffer(),
m_buffer(NULL),
m_bufferPtr(0U),
m_lostCount(0U)
{
m_buffer = m_outBuffer + 1U;
}
void CNXDNRX::reset()
{
m_prev = false;
m_state = NXDNRXS_NONE;
m_bitBuffer = 0x00U;
m_bufferPtr = 0U;
m_lostCount = 0U;
}
void CNXDNRX::databit(bool bit)
{
if (m_state == NXDNRXS_NONE)
processNone(bit);
else
processData(bit);
}
void CNXDNRX::processNone(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
// Fuzzy matching of the data sync bit sequence
if (countBits64((m_bitBuffer & NXDN_FSW_BITS_MASK) ^ NXDN_FSW_BITS) <= MAX_FSW_BIT_START_ERRS) {
DEBUG1("NXDNRX: sync found in None");
for (uint8_t i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++)
m_buffer[i] = NXDN_FSW_BYTES[i];
m_lostCount = MAX_FSW_FRAMES;
m_bufferPtr = NXDN_FSW_LENGTH_BITS;
m_state = NXDNRXS_DATA;
io.setDecode(true);
}
}
void CNXDNRX::processData(bool bit)
{
m_bitBuffer <<= 1;
if (bit)
m_bitBuffer |= 0x01U;
WRITE_BIT1(m_buffer, m_bufferPtr, bit);
m_bufferPtr++;
// Only search for a sync in the right place +-2 symbols
if (m_bufferPtr >= (NXDN_FSW_LENGTH_BITS - 2U) && m_bufferPtr <= (NXDN_FSW_LENGTH_BITS + 2U)) {
// Fuzzy matching of the data sync bit sequence
if (countBits64((m_bitBuffer & NXDN_FSW_BITS_MASK) ^ NXDN_FSW_BITS) <= MAX_FSW_BIT_RUN_ERRS) {
DEBUG2("NXDNRX: found sync in Data, pos", m_bufferPtr - NXDN_FSW_LENGTH_BITS);
m_lostCount = MAX_FSW_FRAMES;
m_bufferPtr = NXDN_FSW_LENGTH_BITS;
}
}
// Send a data frame to the host if the required number of bits have been received
if (m_bufferPtr == NXDN_FRAME_LENGTH_BITS) {
// We've not seen a data sync for too long, signal RXLOST and change to RX_NONE
m_lostCount--;
if (m_lostCount == 0U) {
DEBUG1("NXDNRX: sync timed out, lost lock");
io.setDecode(false);
serial.writeNXDNLost();
m_state = NXDNRXS_NONE;
} else {
m_outBuffer[0U] = m_lostCount == (MAX_FSW_FRAMES - 1U) ? 0x01U : 0x00U;
writeRSSIData(m_outBuffer);
// Start the next frame
::memset(m_outBuffer, 0x00U, NXDN_FRAME_LENGTH_BYTES + 3U);
m_bufferPtr = 0U;
}
}
}
void CNXDNRX::writeRSSIData(uint8_t* data)
{
#if defined(SEND_RSSI_DATA)
uint16_t rssi = io.readRSSI();
data[49U] = (rssi >> 8) & 0xFFU;
data[50U] = (rssi >> 0) & 0xFFU;
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 3U);
#else
serial.writeNXDNData(data, NXDN_FRAME_LENGTH_BYTES + 1U);
#endif
}

@ -0,0 +1,54 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,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(NXDNRX_H)
#define NXDNRX_H
#include "NXDNDefines.h"
enum NXDNRX_STATE {
NXDNRXS_NONE,
NXDNRXS_DATA
};
class CNXDNRX {
public:
CNXDNRX();
void databit(bool bit);
void reset();
private:
bool m_prev;
NXDNRX_STATE m_state;
uint64_t m_bitBuffer;
uint8_t m_outBuffer[NXDN_FRAME_LENGTH_BYTES + 3U];
uint8_t* m_buffer;
uint16_t m_bufferPtr;
uint16_t m_lostCount;
void processNone(bool bit);
void processData(bool bit);
void writeRSSIData(uint8_t* data);
};
#endif

@ -0,0 +1,134 @@
/*
* Copyright (C) 2009-2016,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,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 "NXDNTX.h"
#include "NXDNDefines.h"
const uint8_t NXDN_PREAMBLE[] = {0x57U, 0x75U, 0xFDU};
const uint8_t NXDN_SYNC = 0x5FU;
CNXDNTX::CNXDNTX() :
m_buffer(1500U),
m_poBuffer(),
m_poLen(0U),
m_poPtr(0U),
m_txDelay(240U), // 200ms
m_count(0U),
m_delay(false),
m_preamble(false)
{
}
void CNXDNTX::process()
{
if (m_buffer.getData() == 0U && m_poLen == 0U)
return;
if (m_poLen == 0U) {
if (!m_tx) {
m_delay = true;
m_preamble = false;
m_count = 0U;
m_poLen = m_txDelay;
} else {
m_delay = false;
m_preamble = false;
for (uint8_t i = 0U; i < NXDN_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) {
writeByte(NXDN_SYNC);
m_poPtr++;
} else if (m_preamble) {
writeByte(NXDN_PREAMBLE[m_poPtr++]);
}
else
writeByte(m_poBuffer[m_poPtr++]);
space -= 8U;
if (m_poPtr >= m_poLen) {
if (m_delay) {
m_preamble = true;
m_delay = false;
m_poPtr = 0U;
m_poLen = 3U;
} else {
m_poPtr = 0U;
m_poLen = 0U;
m_preamble = false;
m_delay = false;
return;
}
}
}
}
}
uint8_t CNXDNTX::writeData(const uint8_t* data, uint8_t length)
{
if (length != (NXDN_FRAME_LENGTH_BYTES + 1U))
return 4U;
uint16_t space = m_buffer.getSpace();
if (space < NXDN_FRAME_LENGTH_BYTES)
return 5U;
for (uint8_t i = 0U; i < NXDN_FRAME_LENGTH_BYTES; i++)
m_buffer.put(data[i + 1U]);
return 0U;
}
void CNXDNTX::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 CNXDNTX::setTXDelay(uint8_t delay)
{
m_txDelay = 300U + uint16_t(delay) * 6U; // 500ms + tx delay
}
uint16_t CNXDNTX::getSpace() const
{
return m_buffer.getSpace() / NXDN_FRAME_LENGTH_BYTES;
}

@ -0,0 +1,51 @@
/*
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,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(NXDNTX_H)
#define NXDNTX_H
#include "SerialRB.h"
class CNXDNTX {
public:
CNXDNTX();
uint8_t writeData(const uint8_t* data, uint8_t length);
void process();
void setTXDelay(uint8_t delay);
uint16_t getSpace() const;
private:
CSerialRB m_buffer;
uint8_t m_poBuffer[60U];
uint16_t m_poLen;
uint16_t m_poPtr;
uint16_t m_txDelay;
uint32_t m_count;
bool m_delay;
bool m_preamble;
void writeByte(uint8_t c);
};
#endif

@ -1,6 +1,6 @@
# Introduction # Introduction
This is the source code of ZUMspot/MMDVM_HS, personal hotspot (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 and P25 digital modes. This is the source code of ZUMspot/MMDVM_HS, personal hotspot (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 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). 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).
@ -8,7 +8,7 @@ This software is licenced under the GPL v2 and is intended for amateur and educa
# Features # Features
- Supported modes: D-Star, DMR, Yaesu Fusion and P25 Phase 1 - Supported modes: D-Star, DMR, Yaesu Fusion, P25 Phase 1 and NXDN
- Automatic mode detection (scanning) - 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) and [DMRGateway](https://github.com/g4klx/DMRGateway) - 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) and [DMRGateway](https://github.com/g4klx/DMRGateway)
- Bands: 144, 220, 430 and 900 MHz (VHF requires external inductor) - Bands: 144, 220, 430 and 900 MHz (VHF requires external inductor)
@ -31,7 +31,7 @@ VHF (144-148 MHz) support for ZUMSpot is added by an external 18 nH inductor bet
Dual ADF7021 for full duplex operation (#define DUPLEX in Config.h) will work only with a big RX/TX frequency separation (5 MHz or more in UHF band for example) and proper antenna filtering. At the moment #define LIBRE_KIT_ADF7021 (Config.h) with STM32F103 platform is supported. Please see [BUILD.md](BUILD.md) for pinout details. Dual ADF7021 for full duplex operation (#define DUPLEX in Config.h) will work only with a big RX/TX frequency separation (5 MHz or more in UHF band for example) and proper antenna filtering. At the moment #define LIBRE_KIT_ADF7021 (Config.h) with STM32F103 platform is supported. Please see [BUILD.md](BUILD.md) for pinout details.
If you can't decode any 4FSK modulation (DMR, YSF and P25) with your ZUMspot, the common solution is to adjust RX frequency offset (RXOffset) in your MMDVM.ini file. Please try with steps of +-100 Hz until you get low BER. If you don't have test equipment, the only procedure is trial and error. In some cases TXOffset adjustment is also required for proper radio decoding. If you have test equipment, enable TEST_TX feature (see "Hidden functions" in [BUILD.md](BUILD.md) document). If you can't decode any 4FSK modulation (DMR, YSF, P25 or NXDN) with your ZUMspot, the common solution is to adjust RX frequency offset (RXOffset) in your MMDVM.ini file. Please try with steps of +-100 Hz until you get low BER. If you don't have test equipment, the only procedure is trial and error. In some cases TXOffset adjustment is also required for proper radio decoding. If you have test equipment, enable TEST_TX feature (see "Hidden functions" in [BUILD.md](BUILD.md) document).
# Quick start # Quick start

@ -1,7 +1,7 @@
/* /*
* Copyright (C) 2013,2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2013,2015,2016,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Colin Durbridge G4EML * Copyright (C) 2016 by Colin Durbridge G4EML
* Copyright (C) 2016,2017 by Andy Uribe CA6JAU * Copyright (C) 2016,2017,2018 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -55,6 +55,9 @@ const uint8_t MMDVM_P25_HDR = 0x30U;
const uint8_t MMDVM_P25_LDU = 0x31U; const uint8_t MMDVM_P25_LDU = 0x31U;
const uint8_t MMDVM_P25_LOST = 0x32U; 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_ACK = 0x70U; const uint8_t MMDVM_ACK = 0x70U;
const uint8_t MMDVM_NAK = 0x7FU; const uint8_t MMDVM_NAK = 0x7FU;
@ -121,6 +124,8 @@ void CSerialPort::getStatus()
reply[3U] |= 0x04U; reply[3U] |= 0x04U;
if (m_p25Enable) if (m_p25Enable)
reply[3U] |= 0x08U; reply[3U] |= 0x08U;
if (m_nxdnEnable)
reply[3U] |= 0x10U;
reply[4U] = uint8_t(m_modemState); reply[4U] = uint8_t(m_modemState);
@ -165,6 +170,11 @@ void CSerialPort::getStatus()
else else
reply[10U] = 0U; reply[10U] = 0U;
if (m_nxdnEnable)
reply[11U] = nxdnTX.getSpace();
else
reply[11U] = 0U;
writeInt(1U, reply, 11); writeInt(1U, reply, 11);
} }
@ -201,6 +211,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
bool dmrEnable = (data[1U] & 0x02U) == 0x02U; bool dmrEnable = (data[1U] & 0x02U) == 0x02U;
bool ysfEnable = (data[1U] & 0x04U) == 0x04U; bool ysfEnable = (data[1U] & 0x04U) == 0x04U;
bool p25Enable = (data[1U] & 0x08U) == 0x08U; bool p25Enable = (data[1U] & 0x08U) == 0x08U;
bool nxdnEnable = (data[1U] & 0x10U) == 0x10U;
uint8_t txDelay = data[2U]; uint8_t txDelay = data[2U];
if (txDelay > 50U) if (txDelay > 50U)
@ -208,7 +219,7 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
MMDVM_STATE modemState = MMDVM_STATE(data[3U]); MMDVM_STATE modemState = MMDVM_STATE(data[3U]);
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25) if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN)
return 4U; return 4U;
if (modemState == STATE_DSTAR && !dstarEnable) if (modemState == STATE_DSTAR && !dstarEnable)
return 4U; return 4U;
@ -218,6 +229,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
return 4U; return 4U;
if (modemState == STATE_P25 && !p25Enable) if (modemState == STATE_P25 && !p25Enable)
return 4U; return 4U;
if (modemState == STATE_NXDN && !nxdnEnable)
return 4U;
uint8_t colorCode = data[6U]; uint8_t colorCode = data[6U];
if (colorCode > 15U) if (colorCode > 15U)
@ -235,12 +248,14 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
m_dmrEnable = dmrEnable; m_dmrEnable = dmrEnable;
m_ysfEnable = ysfEnable; m_ysfEnable = ysfEnable;
m_p25Enable = p25Enable; m_p25Enable = p25Enable;
m_nxdnEnable = nxdnEnable;
m_duplex = !simplex; m_duplex = !simplex;
dstarTX.setTXDelay(txDelay); dstarTX.setTXDelay(txDelay);
ysfTX.setTXDelay(txDelay); ysfTX.setTXDelay(txDelay);
p25TX.setTXDelay(txDelay); p25TX.setTXDelay(txDelay);
nxdnTX.setTXDelay(txDelay);
dmrDMOTX.setTXDelay(txDelay); dmrDMOTX.setTXDelay(txDelay);
#if defined(DUPLEX) #if defined(DUPLEX)
@ -262,6 +277,8 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length)
io.ifConf(STATE_YSF, true); io.ifConf(STATE_YSF, true);
else if(m_p25Enable) else if(m_p25Enable)
io.ifConf(STATE_P25, true); io.ifConf(STATE_P25, true);
else if(m_nxdnEnable)
io.ifConf(STATE_NXDN, true);
io.start(); io.start();
io.printConf(); io.printConf();
@ -279,7 +296,7 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
if (modemState == m_modemState) if (modemState == m_modemState)
return 0U; return 0U;
if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25) if (modemState != STATE_IDLE && modemState != STATE_DSTAR && modemState != STATE_DMR && modemState != STATE_YSF && modemState != STATE_P25 && modemState != STATE_NXDN)
return 4U; return 4U;
if (modemState == STATE_DSTAR && !m_dstarEnable) if (modemState == STATE_DSTAR && !m_dstarEnable)
return 4U; return 4U;
@ -289,6 +306,8 @@ uint8_t CSerialPort::setMode(const uint8_t* data, uint8_t length)
return 4U; return 4U;
if (modemState == STATE_P25 && !m_p25Enable) if (modemState == STATE_P25 && !m_p25Enable)
return 4U; return 4U;
if (modemState == STATE_NXDN && !m_nxdnEnable)
return 4U;
setMode(modemState); setMode(modemState);
@ -309,17 +328,17 @@ uint8_t CSerialPort::setFreq(const uint8_t* data, uint8_t length)
// New MMDVMHost, set power from MMDVM.ini // New MMDVMHost, set power from MMDVM.ini
if (length == 10U) if (length == 10U)
rf_power = data[9]; rf_power = data[9U];
freq_rx = data[1] * 1; freq_rx = data[1U] * 1U;
freq_rx += data[2] * 256; freq_rx += data[2U] * 256U;
freq_rx += data[3] * 65536; freq_rx += data[3U] * 65536U;
freq_rx += data[4] * 16777216; freq_rx += data[4U] * 16777216U;
freq_tx = data[5] * 1; freq_tx = data[5U] * 1U;
freq_tx += data[6] * 256; freq_tx += data[6U] * 256U;
freq_tx += data[7] * 65536; freq_tx += data[7U] * 65536U;
freq_tx += data[8] * 16777216; freq_tx += data[8U] * 16777216U;
return io.setFreq(freq_rx, freq_tx, rf_power); return io.setFreq(freq_rx, freq_tx, rf_power);
} }
@ -332,6 +351,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dstarRX.reset(); dstarRX.reset();
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_DSTAR: case STATE_DSTAR:
@ -343,6 +363,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dmrDMORX.reset(); dmrDMORX.reset();
ysfRX.reset(); ysfRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_YSF: case STATE_YSF:
@ -354,6 +375,7 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dmrDMORX.reset(); dmrDMORX.reset();
dstarRX.reset(); dstarRX.reset();
p25RX.reset(); p25RX.reset();
nxdnRX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
case STATE_P25: case STATE_P25:
@ -365,6 +387,19 @@ void CSerialPort::setMode(MMDVM_STATE modemState)
dmrDMORX.reset(); dmrDMORX.reset();
dstarRX.reset(); dstarRX.reset();
ysfRX.reset(); ysfRX.reset();
nxdnRX.reset();
cwIdTX.reset();
break;
case STATE_NXDN:
DEBUG1("Mode set to NXDN");
#if defined(DUPLEX)
dmrIdleRX.reset();
dmrRX.reset();
#endif
dmrDMORX.reset();
dstarRX.reset();
ysfRX.reset();
p25RX.reset();
cwIdTX.reset(); cwIdTX.reset();
break; break;
default: default:
@ -639,6 +674,20 @@ void CSerialPort::process()
} }
break; break;
case MMDVM_NXDN_DATA:
if (m_nxdnEnable) {
if (m_modemState == STATE_IDLE || m_modemState == STATE_NXDN)
err = nxdnTX.writeData(m_buffer + 3U, m_len - 3U);
}
if (err == 0U) {
if (m_modemState == STATE_IDLE)
setMode(STATE_NXDN);
} else {
DEBUG2("Received invalid NXDN data", err);
sendNAK(err);
}
break;
#if defined(SERIAL_REPEATER) || defined(SERIAL_REPEATER_USART1) #if defined(SERIAL_REPEATER) || defined(SERIAL_REPEATER_USART1)
case MMDVM_SERIAL: case MMDVM_SERIAL:
writeInt(3U, m_buffer + 3U, m_len - 3U); writeInt(3U, m_buffer + 3U, m_len - 3U);
@ -891,6 +940,46 @@ void CSerialPort::writeP25Lost()
writeInt(1U, reply, 3); writeInt(1U, reply, 3);
} }
void CSerialPort::writeNXDNData(const uint8_t* data, uint8_t length)
{
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
return;
if (!m_nxdnEnable)
return;
uint8_t reply[130U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 0U;
reply[2U] = MMDVM_NXDN_DATA;
uint8_t count = 3U;
for (uint8_t i = 0U; i < length; i++, count++)
reply[count] = data[i];
reply[1U] = count;
writeInt(1U, reply, count);
}
void CSerialPort::writeNXDNLost()
{
if (m_modemState != STATE_NXDN && m_modemState != STATE_IDLE)
return;
if (!m_nxdnEnable)
return;
uint8_t reply[3U];
reply[0U] = MMDVM_FRAME_START;
reply[1U] = 3U;
reply[2U] = MMDVM_NXDN_LOST;
writeInt(1U, reply, 3);
}
void CSerialPort::writeDebug(const char* text) void CSerialPort::writeDebug(const char* text)
{ {
if (!m_debug) if (!m_debug)

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
* Copyright (C) 2018 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -44,6 +45,9 @@ public:
void writeP25Ldu(const uint8_t* data, uint8_t length); void writeP25Ldu(const uint8_t* data, uint8_t length);
void writeP25Lost(); void writeP25Lost();
void writeNXDNData(const uint8_t* data, uint8_t length);
void writeNXDNLost();
void writeDebug(const char* text); void writeDebug(const char* text);
void writeDebug(const char* text, int16_t n1); void writeDebug(const char* text, int16_t n1);
void writeDebugI(const char* text, int32_t n1); void writeDebugI(const char* text, int32_t n1);

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2015 by Jonathan Naylor G4KLX * Copyright (C) 2015 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

@ -1,5 +1,6 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2017 by Andy Uribe CA6JAU
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by

@ -23,9 +23,9 @@
#include "ADF7021.h" #include "ADF7021.h"
#define VER_MAJOR "1" #define VER_MAJOR "1"
#define VER_MINOR "1" #define VER_MINOR "2"
#define VER_REV "3" #define VER_REV "0"
#define VERSION_DATE "20180127" #define VERSION_DATE "20180213"
#if defined(ZUMSPOT_ADF7021) #if defined(ZUMSPOT_ADF7021)
#define BOARD_INFO "ZUMspot" #define BOARD_INFO "ZUMspot"

Loading…
Cancel
Save

Powered by TurnKey Linux.