diff --git a/ADF7021.cpp b/ADF7021.cpp index 078ab7d..e1a32ea 100644 --- a/ADF7021.cpp +++ b/ADF7021.cpp @@ -38,6 +38,9 @@ volatile uint32_t AD7021_control_word; uint32_t ADF7021_RX_REG0; uint32_t ADF7021_TX_REG0; +uint32_t ADF7021_REG1; +uint32_t div2; +uint8_t m_control; static void Send_AD7021_control_shift() { @@ -74,6 +77,24 @@ void Send_AD7021_control(bool doSle) } } +#if defined(DUPLEX) +static void Send_AD7021_control_sle2Pulse() +{ + io.SLE2_pin(HIGH); + io.dlybit(); + io.SLE2_pin(LOW); +} + +void Send_AD7021_control2(bool doSle) +{ + Send_AD7021_control_shift(); + + if (doSle) { + Send_AD7021_control_sle2Pulse(); + } +} +#endif + #if defined(SEND_RSSI_DATA) uint16_t CIO::readRSSI() { @@ -152,9 +173,7 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset) float divider; uint8_t N_divider; uint16_t F_divider; - uint32_t div2; - uint32_t ADF7021_REG1 = 0; uint32_t ADF7021_REG2 = 0; uint32_t ADF7021_REG3 = 0; uint32_t ADF7021_REG4 = 0; @@ -420,12 +439,182 @@ void CIO::ifConf(MMDVM_STATE modemState, bool reset) AD7021_control_word = 0x000E000F; #endif Send_AD7021_control(); + +#if defined(DUPLEX) +if(m_duplex) + ifConf2(modemState); +#endif +} + +#if defined(DUPLEX) +void CIO::ifConf2(MMDVM_STATE modemState) +{ + uint32_t ADF7021_REG2 = 0; + uint32_t ADF7021_REG3 = 0; + uint32_t ADF7021_REG4 = 0; + uint32_t ADF7021_REG10 = 0; + uint32_t ADF7021_REG13 = 0; + + switch (modemState) { + case STATE_DSTAR: + // Dev: 1200 Hz, symb rate = 4800 + + ADF7021_REG3 = ADF7021_REG3_DSTAR; + ADF7021_REG10 = ADF7021_REG10_DSTAR; + + // K=32 + ADF7021_REG4 = (uint32_t) 0b0100 << 0; // register 4 + ADF7021_REG4 |= (uint32_t) 0b001 << 4; // mode, GMSK + ADF7021_REG4 |= (uint32_t) 0b1 << 7; + ADF7021_REG4 |= (uint32_t) 0b10 << 8; + ADF7021_REG4 |= (uint32_t) ADF7021_DISC_BW_DSTAR << 10; // Disc BW + ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_DSTAR << 20; // Post dem BW + ADF7021_REG4 |= (uint32_t) 0b10 << 30; // IF filter + + ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13 + ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_DSTAR << 4; // slicer threshold + + ADF7021_REG2 = (uint32_t) 0b00 << 28; // clock normal + ADF7021_REG2 |= (uint32_t) (ADF7021_DEV_DSTAR / div2)<< 19; // deviation + ADF7021_REG2 |= (uint32_t) 0b001 << 4; // modulation (GMSK) + break; + + case STATE_DMR: + // Dev: +1 symb 648 Hz, symb rate = 4800 + + ADF7021_REG3 = ADF7021_REG3_DMR; + ADF7021_REG10 = ADF7021_REG10_DMR; + + // 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_DMR << 10; // Disc BW + ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_DMR << 20; // Post dem BW + ADF7021_REG4 |= (uint32_t) 0b10 << 30; // IF filter + + ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13 + ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_DMR << 4; // slicer threshold + + ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5) + ADF7021_REG2 |= (uint32_t) (ADF7021_DEV_DMR / div2) << 19; // deviation + ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK) + break; + + case STATE_YSF: + // Dev: +1 symb 900 Hz, symb rate = 4800 + + ADF7021_REG3 = (m_LoDevYSF ? ADF7021_REG3_YSF_L : ADF7021_REG3_YSF_H); + ADF7021_REG10 = ADF7021_REG10_YSF; + + // K=28 + 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) (m_LoDevYSF ? ADF7021_DISC_BW_YSF_L : ADF7021_DISC_BW_YSF_H) << 10; // Disc BW + ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_YSF << 20; // Post dem BW + ADF7021_REG4 |= (uint32_t) 0b10 << 30; // IF filter + + ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13 + ADF7021_REG13 |= (uint32_t) (m_LoDevYSF ? ADF7021_SLICER_TH_YSF_L : ADF7021_SLICER_TH_YSF_H) << 4; // slicer threshold + + ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5) + ADF7021_REG2 |= (uint32_t) ((m_LoDevYSF ? ADF7021_DEV_YSF_L : ADF7021_DEV_YSF_H) / div2) << 19; // deviation + ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK) + break; + + case STATE_P25: + // Dev: +1 symb 600 Hz, symb rate = 4800 + + ADF7021_REG3 = ADF7021_REG3_P25; + ADF7021_REG10 = ADF7021_REG10_P25; + + // 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_P25 << 10; // Disc BW + ADF7021_REG4 |= (uint32_t) ADF7021_POST_BW_P25 << 20; // Post dem BW + ADF7021_REG4 |= (uint32_t) 0b10 << 30; // IF filter + + ADF7021_REG13 = (uint32_t) 0b1101 << 0; // register 13 + ADF7021_REG13 |= (uint32_t) ADF7021_SLICER_TH_P25 << 4; // slicer threshold + + ADF7021_REG2 = (uint32_t) 0b10 << 28; // invert data (and RC alpha = 0.5) + ADF7021_REG2 |= (uint32_t) (ADF7021_DEV_P25 / div2) << 19; // deviation + ADF7021_REG2 |= (uint32_t) 0b111 << 4; // modulation (RC 4FSK) + break; + + default: + break; + } + + // VCO/OSCILLATOR (1) + AD7021_control_word = ADF7021_REG1; + Send_AD7021_control2(); + + // TX/RX CLOCK (3) + AD7021_control_word = ADF7021_REG3; + Send_AD7021_control2(); + + // DEMOD (4) + AD7021_control_word = ADF7021_REG4; + Send_AD7021_control2(); + + // IF FILTER (5) + AD7021_control_word = ADF7021_REG5; + Send_AD7021_control2(); + + // Delay for coarse IF filter calibration + delay_ifcal_coarse(); + + // Frequency RX (0) and set to RX only + AD7021_control_word = ADF7021_RX_REG0; + Send_AD7021_control2(); + + // MODULATION (2) + ADF7021_REG2 |= (uint32_t) 0b0010; // register 2 + ADF7021_REG2 |= (uint32_t) m_power << 13; // power level + ADF7021_REG2 |= (uint32_t) 0b110001 << 7; // PA + AD7021_control_word = ADF7021_REG2; + Send_AD7021_control2(); + + // TEST DAC (14) + AD7021_control_word = 0x0000000E; + Send_AD7021_control2(); + + // AGC (auto, defaults) (9) + AD7021_control_word = 0x000231E9; + Send_AD7021_control2(); + + // AFC (10) + AD7021_control_word = ADF7021_REG10; + Send_AD7021_control2(); + + // SYNC WORD DET (11) + AD7021_control_word = 0x0000003B; + Send_AD7021_control2(); + + // SWD/THRESHOLD (12) + AD7021_control_word = 0x0000010C; + Send_AD7021_control2(); + + // 3FSK/4FSK DEMOD (13) + AD7021_control_word = ADF7021_REG13; + Send_AD7021_control2(); + + // TEST MODE (disabled) (15) + AD7021_control_word = 0x000E000F; + Send_AD7021_control2(); } +#endif void CIO::interrupt() { uint8_t bit = 0; - uint8_t control = MARK_NONE; if (!m_started) return; @@ -450,7 +639,7 @@ void CIO::interrupt() // we set the TX bit at TXD low, sampling of ADF7021 happens at rising clock if (m_tx && clk == 0) { - m_txBuffer.get(bit, control); + m_txBuffer.get(bit, m_control); even = !even; // use this for tracking issues @@ -493,13 +682,13 @@ 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 - if (!m_tx && clk == 1) { + if (!m_tx && clk == 1 && !m_duplex) { if(RXD_pin()) bit = 1; else bit = 0; - m_rxBuffer.put(bit, control); + m_rxBuffer.put(bit, m_control); } if (torx_request == true && even == false && m_tx && clk == 0) { @@ -534,6 +723,22 @@ void CIO::interrupt() m_scanPauseCnt++; } +#if defined(DUPLEX) +void CIO::interrupt2() +{ + uint8_t bit = 0; + + if(m_duplex) { + if(RXD2_pin()) + bit = 1; + else + bit = 0; + + m_rxBuffer.put(bit, m_control); + } +} +#endif + //====================================================================================================================== void CIO::setTX() { diff --git a/ADF7021.h b/ADF7021.h index 8992ddc..4eb9e25 100644 --- a/ADF7021.h +++ b/ADF7021.h @@ -227,6 +227,9 @@ www.analog.com/media/en/technical-documentation/data-sheets/ADF7021.pdf #define bitRead(value, bit) (((value) >> (bit)) & 0x01) void Send_AD7021_control(bool doSle = true); +#if defined(DUPLEX) +void Send_AD7021_control2(bool doSle = true); +#endif #endif diff --git a/Config.h b/Config.h index b409bf4..b4b658c 100644 --- a/Config.h +++ b/Config.h @@ -34,7 +34,7 @@ // #define ADF7021_N_VER // Enable duplex mode with dual ADF7021 -// #define DUPLEX +#define DUPLEX // Bidirectional Data pin (Enable Standard TX/RX Data Interface of ADF7021): #define BIDIR_DATA_PIN diff --git a/DMRIdleRX.cpp b/DMRIdleRX.cpp index d87ee75..9bcfbd3 100644 --- a/DMRIdleRX.cpp +++ b/DMRIdleRX.cpp @@ -67,19 +67,19 @@ void CDMRIdleRX::databit(bool bit) } if (m_dataPtr == m_endPtr) { - uint16_t ptr = m_endPtr + 2; + uint16_t ptr = m_endPtr + 1; if (ptr >= DMR_FRAME_LENGTH_BITS) ptr -= DMR_FRAME_LENGTH_BITS; uint8_t frame[DMR_FRAME_LENGTH_BYTES + 1U]; - bitsToBytes(ptr, DMR_FRAME_LENGTH_BITS, frame + 1U); + bitsToBytes(ptr, DMR_FRAME_LENGTH_BYTES, frame + 1U); uint8_t colorCode; uint8_t dataType; CDMRSlotType slotType; slotType.decode(frame + 1U, colorCode, dataType); - + if (colorCode == m_colorCode && dataType == DT_CSBK) { frame[0U] = CONTROL_IDLE | CONTROL_DATA | DT_CSBK; serial.writeDMRData(false, frame, DMR_FRAME_LENGTH_BYTES + 1U); diff --git a/DMRRX.cpp b/DMRRX.cpp index 1b1aa47..2cf2fc8 100644 --- a/DMRRX.cpp +++ b/DMRRX.cpp @@ -44,11 +44,11 @@ void CDMRRX::databit(bool bit, const uint8_t control) break; default: break; - - dcd1 = m_slot1RX.databit(bit); - dcd2 = m_slot2RX.databit(bit); } + dcd1 = m_slot1RX.databit(bit); + dcd2 = m_slot2RX.databit(bit); + io.setDecode(dcd1 || dcd2); } diff --git a/DMRSlotRX.cpp b/DMRSlotRX.cpp index 965bf39..ae3c9fa 100644 --- a/DMRSlotRX.cpp +++ b/DMRSlotRX.cpp @@ -17,19 +17,19 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define WANT_DEBUG - #include "Config.h" #if defined(DUPLEX) +#define WANT_DEBUG + #include "Globals.h" #include "DMRSlotRX.h" #include "DMRSlotType.h" #include "Utils.h" -const uint16_t SCAN_START = 400U; -const uint16_t SCAN_END = 490U; +const uint16_t SCAN_START = 170U; +const uint16_t SCAN_END = 190U; const uint8_t MAX_SYNC_BYTES_ERRS = 1U; @@ -64,6 +64,7 @@ void CDMRSlotRX::start() { m_dataPtr = 0U; m_delayPtr = 0U; + m_patternBuffer = 0U; m_control = CONTROL_NONE; } @@ -86,7 +87,7 @@ bool CDMRSlotRX::databit(bool bit) return m_state != DMRRXS_NONE; // Ensure that the buffer doesn't overflow - if (m_dataPtr > m_endPtr || m_dataPtr >= 900U) + if (m_dataPtr > m_endPtr || m_dataPtr >= 400U) return m_state != DMRRXS_NONE; m_buffer[m_dataPtr] = bit; @@ -94,12 +95,11 @@ bool CDMRSlotRX::databit(bool bit) m_patternBuffer <<= 1; if (bit) m_patternBuffer |= 0x01U; - + if (m_state == DMRRXS_NONE) { if (m_dataPtr >= SCAN_START && m_dataPtr <= SCAN_END) correlateSync(true); } else { - uint16_t min = m_syncPtr - 1U; uint16_t max = m_syncPtr + 1U; if (m_dataPtr >= min && m_dataPtr <= max) @@ -217,7 +217,7 @@ void CDMRSlotRX::correlateSync(bool first) m_syncPtr = m_dataPtr; m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U; - DEBUG4("SYNC MS Data found pos/start/end:", m_dataPtr, m_startPtr, m_endPtr); + DEBUG4("SYNC corr MS Data found pos/start/end:", m_dataPtr, m_startPtr, m_endPtr); } else if (countBits64((m_patternBuffer & DMR_SYNC_BITS_MASK) ^ DMR_MS_VOICE_SYNC_BITS) <= MAX_SYNC_BYTES_ERRS) { @@ -225,7 +225,7 @@ void CDMRSlotRX::correlateSync(bool first) m_syncPtr = m_dataPtr; m_startPtr = m_dataPtr - DMR_SLOT_TYPE_LENGTH_BITS / 2U - DMR_INFO_LENGTH_BITS / 2U - DMR_SYNC_LENGTH_BITS + 1; m_endPtr = m_dataPtr + DMR_SLOT_TYPE_LENGTH_BITS / 2U + DMR_INFO_LENGTH_BITS / 2U; - DEBUG4("SYNC MS Voice found pos/start/end: ", m_dataPtr, m_startPtr, m_endPtr); + DEBUG4("SYNC corr MS Voice found pos/start/end: ", m_dataPtr, m_startPtr, m_endPtr); } } diff --git a/DMRSlotRX.h b/DMRSlotRX.h index 145d6d9..98138de 100644 --- a/DMRSlotRX.h +++ b/DMRSlotRX.h @@ -48,7 +48,7 @@ public: private: bool m_slot; uint64_t m_patternBuffer; - uint8_t m_buffer[900U]; + uint8_t m_buffer[400U]; uint16_t m_dataPtr; uint16_t m_syncPtr; uint16_t m_startPtr; diff --git a/DMRTX.cpp b/DMRTX.cpp index 061385d..4247330 100644 --- a/DMRTX.cpp +++ b/DMRTX.cpp @@ -18,7 +18,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -// #define WANT_DEBUG +//#define WANT_DEBUG #include "Config.h" @@ -220,6 +220,7 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) { uint8_t bit; uint8_t mask = 0x80U; + uint8_t control_tmp; for (uint8_t i = 0U; i < 8U; i++, c <<= 1) { if ((c & mask) == mask) @@ -227,10 +228,13 @@ void CDMRTX::writeByte(uint8_t c, uint8_t control) else bit = 0U; - if( i != 3U) - control = MARK_NONE; + control_tmp = MARK_NONE; + + if( i == 0U) + control_tmp = control; - io.write(&bit, 1, &control); + io.write(&bit, 1, &control_tmp); + } } diff --git a/IO.cpp b/IO.cpp index e46dd03..4df4119 100644 --- a/IO.cpp +++ b/IO.cpp @@ -124,7 +124,17 @@ void CIO::process() dstarRX.databit(bit); break; case STATE_DMR: +#if defined(DUPLEX) + if (m_duplex) { + if (m_tx) + dmrRX.databit(bit, control); + else + dmrIdleRX.databit(bit); + } else + dmrDMORX.databit(bit); +#else dmrDMORX.databit(bit); +#endif break; case STATE_YSF: ysfRX.databit(bit); diff --git a/IO.h b/IO.h index b97b95b..4ff62d8 100644 --- a/IO.h +++ b/IO.h @@ -20,6 +20,7 @@ #if !defined(CIO_H) #define CIO_H +#include "Config.h" #include "Globals.h" #include "BitRB.h" @@ -53,6 +54,10 @@ public: void SDATA_pin(bool on); bool SREAD_pin(void); void SLE_pin(bool on); +#if defined(DUPLEX) + void SLE2_pin(bool on); + bool RXD2_pin(void); +#endif void CE_pin(bool on); bool RXD_pin(void); bool CLK_pin(void); @@ -71,6 +76,9 @@ public: void P25_pin(bool on); void COS_pin(bool on); void interrupt(void); +#if defined(DUPLEX) + void interrupt2(void); +#endif void resetWatchdog(void); #if defined(BIDIR_DATA_PIN) @@ -92,6 +100,9 @@ public: void setTX(void); void setRX(bool doSle = true); void ifConf(MMDVM_STATE modemState, bool reset); +#if defined(DUPLEX) + void ifConf2(MMDVM_STATE modemState); +#endif void start(void); void startInt(void); diff --git a/IOArduino.cpp b/IOArduino.cpp index d99b959..deb5de9 100644 --- a/IOArduino.cpp +++ b/IOArduino.cpp @@ -52,9 +52,12 @@ #define PIN_SREAD PB6 #define PIN_SDATA PB7 #define PIN_SLE PB8 +#define PIN_SLE2 PA6 #define PIN_CE PC14 #define PIN_RXD PB4 +#define PIN_RXD2 PA4 #define PIN_TXD PB3 +#define PIN_TXD2 PA5 #define PIN_CLKOUT PA15 #define PIN_LED PC13 #define PIN_DEB PB9 @@ -71,9 +74,12 @@ #define PIN_SREAD PB7 #define PIN_SDATA PB6 #define PIN_SLE PB8 +#define PIN_SLE2 PA6 #define PIN_CE PC14 #define PIN_RXD PB4 +#define PIN_RXD2 PA4 #define PIN_TXD PB3 +#define PIN_TXD2 PA5 #define PIN_CLKOUT PA15 #define PIN_LED PC13 #define PIN_DEB PB9 @@ -116,6 +122,14 @@ extern "C" { } } +#if defined(DUPLEX) +extern "C" { + void EXT_IRQHandler2(void) { + io.interrupt2(); + } +} +#endif + void CIO::delay_ifcal_coarse() { delayMicroseconds(300); } @@ -152,6 +166,12 @@ void CIO::Init() pinMode(PIN_PTT_LED, OUTPUT); pinMode(PIN_COS_LED, OUTPUT); +#if defined(DUPLEX) + pinMode(PIN_SLE2, OUTPUT); + pinMode(PIN_RXD2, INPUT); + pinMode(PIN_TXD2, INPUT); +#endif + #if defined(BIDIR_DATA_PIN) pinMode(PIN_TXD, INPUT); #else @@ -180,6 +200,10 @@ void CIO::startInt() #endif #endif + +#if defined(DUPLEX) + attachInterrupt(PIN_TXD2, EXT_IRQHandler2, RISING); +#endif } #if defined(BIDIR_DATA_PIN) @@ -213,6 +237,18 @@ void CIO::SLE_pin(bool on) digitalWrite(PIN_SLE, on ? HIGH : LOW); } +#if defined(DUPLEX) +void CIO::SLE2_pin(bool on) +{ + digitalWrite(PIN_SLE2, on ? HIGH : LOW); +} + +bool CIO::RXD2_pin() +{ + return digitalRead(PIN_RXD2) == HIGH; +} +#endif + void CIO::CE_pin(bool on) { digitalWrite(PIN_CE, on ? HIGH : LOW); diff --git a/IOSTM.cpp b/IOSTM.cpp index 7abfb33..deed958 100644 --- a/IOSTM.cpp +++ b/IOSTM.cpp @@ -96,6 +96,9 @@ #define PIN_SLE GPIO_Pin_8 #define PORT_SLE GPIOB +#define PIN_SLE2 GPIO_Pin_6 +#define PORT_SLE2 GPIOA + #define PIN_CE GPIO_Pin_14 #define PORT_CE GPIOC @@ -153,12 +156,18 @@ #define PIN_SLE GPIO_Pin_8 #define PORT_SLE GPIOB +#define PIN_SLE2 GPIO_Pin_6 +#define PORT_SLE2 GPIOA + #define PIN_CE GPIO_Pin_14 #define PORT_CE GPIOC #define PIN_RXD GPIO_Pin_4 #define PORT_RXD GPIOB +#define PIN_RXD2 GPIO_Pin_4 +#define PORT_RXD2 GPIOA + // TXD used in SPI Data mode of ADF7021 // TXD is TxRxCLK of ADF7021, standard TX/RX data interface #define PIN_TXD GPIO_Pin_3 @@ -166,6 +175,12 @@ #define PIN_TXD_INT GPIO_PinSource3 #define PORT_TXD_INT GPIO_PortSourceGPIOB +// TXD2 is TxRxCLK of the second ADF7021, standard TX/RX data interface +#define PIN_TXD2 GPIO_Pin_5 +#define PORT_TXD2 GPIOA +#define PIN_TXD2_INT GPIO_PinSource5 +#define PORT_TXD2_INT GPIO_PortSourceGPIOA + // CLKOUT used in SPI Data mode of ADF7021 #define PIN_CLKOUT GPIO_Pin_15 #define PORT_CLKOUT GPIOA @@ -237,6 +252,15 @@ extern "C" { } #endif +#if defined(DUPLEX) + void EXTI9_5_IRQHandler(void) { + if(EXTI_GetITStatus(EXTI_Line5)!=RESET) { + io.interrupt2(); + EXTI_ClearITPendingBit(EXTI_Line5); + } + } +#endif + #endif } @@ -256,7 +280,8 @@ void CIO::Init() NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); EXTI_InitTypeDef EXTI_InitStructure; - + EXTI_InitTypeDef EXTI_InitStructure2; + GPIO_InitTypeDef GPIO_InitStruct; GPIO_StructInit(&GPIO_InitStruct); @@ -297,6 +322,20 @@ void CIO::Init() GPIO_InitStruct.GPIO_Pin = PIN_SLE; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(PORT_SLE, &GPIO_InitStruct); + +#if defined(DUPLEX) + // Pin SLE2 + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Pin = PIN_SLE2; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_Init(PORT_SLE2, &GPIO_InitStruct); + + // Pin RXD2 + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStruct.GPIO_Pin = PIN_RXD2; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(PORT_RXD2, &GPIO_InitStruct); +#endif // Pin CE GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; @@ -320,6 +359,9 @@ void CIO::Init() GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; #endif GPIO_Init(PORT_TXD, &GPIO_InitStruct); +#if defined(DUPLEX) + GPIO_Init(PORT_TXD2, &GPIO_InitStruct); +#endif // Pin TXRX_CLK #if !defined(BIDIR_DATA_PIN) @@ -405,17 +447,32 @@ void CIO::Init() EXTI_InitStructure.EXTI_Line = EXTI_Line15; #endif +#if defined(DUPLEX) + // Connect EXTI5 Line + GPIO_EXTILineConfig(PORT_TXD2_INT, PIN_TXD2_INT); + // Configure EXT5 line + EXTI_InitStructure2.EXTI_Line = EXTI_Line5; +#endif + #endif EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); + +#if defined(DUPLEX) + EXTI_InitStructure2.EXTI_Mode = EXTI_Mode_Interrupt; + EXTI_InitStructure2.EXTI_Trigger = EXTI_Trigger_Rising; + EXTI_InitStructure2.EXTI_LineCmd = ENABLE; + EXTI_Init(&EXTI_InitStructure2); +#endif } void CIO::startInt() { NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitTypeDef NVIC_InitStructure2; #if defined(PI_HAT_7021_REV_02) @@ -431,12 +488,23 @@ void CIO::startInt() NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; #endif +#if defined(DUPLEX) + NVIC_InitStructure2.NVIC_IRQChannel = EXTI9_5_IRQn; +#endif + #endif NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 15; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); + +#if defined(DUPLEX) + NVIC_InitStructure2.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure2.NVIC_IRQChannelSubPriority = 15; + NVIC_InitStructure2.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure2); +#endif } #if defined(BIDIR_DATA_PIN) @@ -477,6 +545,18 @@ void CIO::SLE_pin(bool on) GPIO_WriteBit(PORT_SLE, PIN_SLE, on ? Bit_SET : Bit_RESET); } +#if defined(DUPLEX) +void CIO::SLE2_pin(bool on) +{ + GPIO_WriteBit(PORT_SLE2, PIN_SLE2, on ? Bit_SET : Bit_RESET); +} + +bool CIO::RXD2_pin() +{ + return GPIO_ReadInputDataBit(PORT_RXD2, PIN_RXD2) == Bit_SET; +} +#endif + void CIO::CE_pin(bool on) { GPIO_WriteBit(PORT_CE, PIN_CE, on ? Bit_SET : Bit_RESET); diff --git a/SerialPort.cpp b/SerialPort.cpp index e9331e9..664af32 100644 --- a/SerialPort.cpp +++ b/SerialPort.cpp @@ -231,7 +231,9 @@ uint8_t CSerialPort::setConfig(const uint8_t* data, uint8_t length) if (colorCode > 15U) return 4U; +#if defined(DUPLEX) uint8_t dmrDelay = data[7U]; +#endif m_modemState = modemState;