From f00c1c14f307e9152c1bc1e5c0b07413338f844b Mon Sep 17 00:00:00 2001 From: peteruithoven Date: Mon, 13 Nov 2017 17:18:28 +0100 Subject: [PATCH] [SoftSerial] Half duplex support Squash and rebase of https://github.com/arduino/Arduino/pull/4377 --- .../SoftwareSerial/src/SoftwareSerial.cpp | 19 ++++++++++++++++--- libraries/SoftwareSerial/src/SoftwareSerial.h | 4 +++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 474fe4a..b83fcf3 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -246,13 +246,14 @@ ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect)); // // Constructor // -SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */) : +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */, bool full_duplex /* = true */) : _rx_delay_centering(0), _rx_delay_intrabit(0), _rx_delay_stopbit(0), _tx_delay(0), _buffer_overflow(false), - _inverse_logic(inverse_logic) + _inverse_logic(inverse_logic), + _full_duplex(full_duplex) { setTX(transmitPin); setRX(receivePin); @@ -273,7 +274,11 @@ void SoftwareSerial::setTX(uint8_t tx) // output high. Now, it is input with pullup for a short while, which // is fine. With inverse logic, either order is fine. digitalWrite(tx, _inverse_logic ? LOW : HIGH); - pinMode(tx, OUTPUT); + if(_full_duplex) + pinMode(tx, OUTPUT); + else + pinMode(tx, INPUT); + _transmitPin = tx; _transmitBitMask = digitalPinToBitMask(tx); uint8_t port = digitalPinToPort(tx); _transmitPortRegister = portOutputRegister(port); @@ -418,6 +423,9 @@ size_t SoftwareSerial::write(uint8_t b) setWriteError(); return 0; } + + if(!_full_duplex) + pinMode(_transmitPin, OUTPUT); // By declaring these as local variables, the compiler will put them // in registers _before_ disabling interrupts and entering the @@ -461,6 +469,11 @@ size_t SoftwareSerial::write(uint8_t b) else *reg |= reg_mask; + if(!_full_duplex){ + pinMode(_transmitPin, INPUT); + *reg |= reg_mask; // send 1 + } + SREG = oldSREG; // turn interrupts back on tunedDelay(_tx_delay); diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index b1a37c4..63132cc 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -54,6 +54,7 @@ private: uint8_t _receivePin; uint8_t _receiveBitMask; volatile uint8_t *_receivePortRegister; + uint8_t _transmitPin; uint8_t _transmitBitMask; volatile uint8_t *_transmitPortRegister; volatile uint8_t *_pcint_maskreg; @@ -67,6 +68,7 @@ private: uint16_t _buffer_overflow:1; uint16_t _inverse_logic:1; + uint16_t _full_duplex:1; // static data static uint8_t _receive_buffer[_SS_MAX_RX_BUFF]; @@ -89,7 +91,7 @@ private: public: // public methods - SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false, bool full_duplex = true); ~SoftwareSerial(); void begin(long speed); bool listen();