Skip to content

a simpler, shorter and faster write() implementation for SofftwareSerial #1933

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: ide-1.5.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 21 additions & 33 deletions hardware/arduino/avr/libraries/SoftwareSerial/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,13 @@ void SoftwareSerial::recv()
#endif
}

void SoftwareSerial::tx_pin_write(uint8_t pin_state)
void SoftwareSerial::tx_pin_low()
{
*_transmitPortRegister &= ~_transmitBitMask;
}

void SoftwareSerial::tx_pin_high()
{
if (pin_state == LOW)
*_transmitPortRegister &= ~_transmitBitMask;
else
*_transmitPortRegister |= _transmitBitMask;
}

Expand Down Expand Up @@ -445,47 +447,33 @@ int SoftwareSerial::available()

size_t SoftwareSerial::write(uint8_t b)
{
if (_tx_delay == 0) {
if (_tx_delay == 0) { //is this check really necessary ?
setWriteError();
return 0;
}

typedef void(SoftwareSerial::*mem_func)();
mem_func tx_high_ = _inverse_logic ? &SoftwareSerial::tx_pin_low : &SoftwareSerial::tx_pin_high;
mem_func tx_low_ = _inverse_logic ? &SoftwareSerial::tx_pin_high : &SoftwareSerial::tx_pin_low;

#define tx_low() (this->*tx_low_)() //just to make it more readable
#define tx_high() (this->*tx_high_)() //just to make it more readable

uint8_t oldSREG = SREG;
cli(); // turn off interrupts for a clean txmit


// Write the start bit
tx_pin_write(_inverse_logic ? HIGH : LOW);
tx_low();
tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);

// Write each of the 8 bits
if (_inverse_logic)
{
for (byte mask = 0x01; mask; mask <<= 1)
{
if (b & mask) // choose bit
tx_pin_write(LOW); // send 1
else
tx_pin_write(HIGH); // send 0

tunedDelay(_tx_delay);
}

tx_pin_write(LOW); // restore pin to natural state
for (byte mask = 0x01; mask; mask <<= 1) {
(b & mask) ? tx_high() : tx_low();
tunedDelay(_tx_delay);
}
else
{
for (byte mask = 0x01; mask; mask <<= 1)
{
if (b & mask) // choose bit
tx_pin_write(HIGH); // send 1
else
tx_pin_write(LOW); // send 0

tunedDelay(_tx_delay);
}

tx_pin_write(HIGH); // restore pin to natural state
}
tx_high(); // restore pin to natural state


SREG = oldSREG; // turn interrupts back on
tunedDelay(_tx_delay);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ class SoftwareSerial : public Stream
// private methods
void recv();
uint8_t rx_pin_read();
void tx_pin_write(uint8_t pin_state);
void tx_pin_high();
void tx_pin_low();
void setTX(uint8_t transmitPin);
void setRX(uint8_t receivePin);

Expand Down