Skip to content

Commit

Permalink
Add support for single wire
Browse files Browse the repository at this point in the history
  • Loading branch information
dominikberse committed Jun 15, 2022
1 parent bc792a9 commit 5482bf9
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
35 changes: 31 additions & 4 deletions libraries/SoftwareSerial/src/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ bool SoftwareSerial::listen()
{
if (active_object)
active_object->stopListening();
if (_singleWirePin)
setupRXPin(_singleWirePin);

_buffer_overflow = false;
_receive_buffer_head = _receive_buffer_tail = 0;
Expand All @@ -111,6 +113,8 @@ bool SoftwareSerial::stopListening()
if (active_object == this)
{
setRxIntMsk(false);
if (_singleWirePin)
setupTXPin(_singleWirePin);
active_object = NULL;
return true;
}
Expand Down Expand Up @@ -246,7 +250,8 @@ 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 */) :
_singleWirePin(receivePin == transmitPin ? receivePin : 0),
_rx_delay_centering(0),
_rx_delay_intrabit(0),
_rx_delay_stopbit(0),
Expand All @@ -256,6 +261,9 @@ SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inv
{
setTX(transmitPin);
setRX(receivePin);

if (_singleWirePin)
setupTXPin(_singleWirePin);
}

//
Expand All @@ -266,24 +274,38 @@ SoftwareSerial::~SoftwareSerial()
end();
}

void SoftwareSerial::setTX(uint8_t tx)
void SoftwareSerial::setupTXPin(uint8_t tx)
{
// First write, then set output. If we do this the other way around,
// the pin would be output low for a short while before switching to
// 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);
}

void SoftwareSerial::setTX(uint8_t tx)
{
if(!_singleWirePin)
setupTXPin(tx);

_transmitBitMask = digitalPinToBitMask(tx);
uint8_t port = digitalPinToPort(tx);
_transmitPortRegister = portOutputRegister(port);
}

void SoftwareSerial::setRX(uint8_t rx)
void SoftwareSerial::setupRXPin(uint8_t rx)
{
pinMode(rx, INPUT);
if (!_inverse_logic)
digitalWrite(rx, HIGH); // pullup for normal logic!
}

void SoftwareSerial::setRX(uint8_t rx)
{
if(!_singleWirePin)
setupRXPin(rx);

_receivePin = rx;
_receiveBitMask = digitalPinToBitMask(rx);
uint8_t port = digitalPinToPort(rx);
Expand Down Expand Up @@ -371,7 +393,9 @@ void SoftwareSerial::begin(long speed)
pinMode(_DEBUG_PIN2, OUTPUT);
#endif

listen();
// Single-wire will be in TX mode by default
if (!_singleWirePin)
listen();
}

void SoftwareSerial::setRxIntMsk(bool enable)
Expand Down Expand Up @@ -414,6 +438,9 @@ int SoftwareSerial::available()

size_t SoftwareSerial::write(uint8_t b)
{
if (_singleWirePin && isListening())
return 0;

if (_tx_delay == 0) {
setWriteError();
return 0;
Expand Down
3 changes: 3 additions & 0 deletions libraries/SoftwareSerial/src/SoftwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ class SoftwareSerial : public Stream
{
private:
// per object data
uint8_t _singleWirePin;
uint8_t _receivePin;
uint8_t _receiveBitMask;
volatile uint8_t *_receivePortRegister;
Expand Down Expand Up @@ -79,6 +80,8 @@ class SoftwareSerial : public Stream
uint8_t rx_pin_read();
void setTX(uint8_t transmitPin);
void setRX(uint8_t receivePin);
void setupTXPin(uint8_t transmitPin);
void setupRXPin(uint8_t receivePin);
inline void setRxIntMsk(bool enable) __attribute__((__always_inline__));

// Return num - sub, or 1 if the result would be < 1
Expand Down

0 comments on commit 5482bf9

Please sign in to comment.