Skip to content

CurieSoftwareSerial Improvements #101

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

Closed
wants to merge 1 commit into from
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -42,21 +42,17 @@ char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;


//
// Globals
//
uint8_t rxPin;
uint16_t bitDelay;
uint16_t rxIntraBitDelay;
int rxCenteringDelay;
int initRxIntraBitDelay;
int firstIntraBitDelay;
int initRxCenteringDelay;
bool firstStartBit = true;
bool bufferOverflow = true;
bool invertedLogic = false;
bool isSOCGpio = false;
static uint8_t _rxPin;
static uint16_t bitDelay;
static uint16_t rxIntraBitDelay;
static int rxCenteringDelay;
static int initRxIntraBitDelay;
static int firstIntraBitDelay;
static int initRxCenteringDelay;
static bool firstStartBit = true;
static bool bufferOverflow = true;
static bool invertedLogic = false;
static bool isSOCGpio = false;

//
// Debugging
Expand Down Expand Up @@ -94,14 +90,21 @@ bool SoftwareSerial::listen()
bufferOverflow = false;
_receive_buffer_head = _receive_buffer_tail = 0;
active_object = this;
rxPin = _receivePin;
_rxPin = _receivePin;
rxIntraBitDelay = _rx_delay_intrabit;
rxCenteringDelay = _rx_delay_centering;
initRxIntraBitDelay = _rx_delay_init_intrabit;
firstIntraBitDelay = _rx_delay_first_intrabit;
initRxCenteringDelay = _rx_delay_init_centering;
invertedLogic = _inverse_logic;
isSOCGpio = _isSOCGpio;
if(invertedLogic)
{
attachInterrupt(rxPin, recv, HIGH);
attachInterrupt(_rxPin, recv, HIGH);
}
else
{
attachInterrupt(rxPin, recv, LOW);
attachInterrupt(_rxPin, recv, LOW);
}

return true;
Expand All @@ -116,7 +119,7 @@ bool SoftwareSerial::stopListening()
if (active_object == this)
{
active_object = NULL;
detachInterrupt(rxPin);
detachInterrupt(_rxPin);
return true;
}
return false;
Expand All @@ -131,7 +134,7 @@ void SoftwareSerial::recv()
uint8_t d = 0;
// If RX line is high, then we don't see any start bit
// so interrupt is probably not for us
if (invertedLogic ? digitalRead(rxPin) : !digitalRead(rxPin))
if (invertedLogic ? digitalRead(_rxPin) : !digitalRead(_rxPin))
{
// The very first start bit the sketch receives takes about 5us longer
if(firstStartBit && !isSOCGpio)
Expand Down Expand Up @@ -162,7 +165,7 @@ void SoftwareSerial::recv()
delayTicks(rxIntraBitDelay);
}
d >>= 1;
if (digitalRead(rxPin))
if (digitalRead(_rxPin))
d |= 0x80;
firstStartBit = false;
}
Expand All @@ -187,15 +190,15 @@ void SoftwareSerial::recv()
uint8_t loopTimeout = 8;
if(invertedLogic)
{
while(digitalRead(rxPin) && (loopTimeout >0))
while(digitalRead(_rxPin) && (loopTimeout >0))
{
delayTicks(bitDelay >> 4);
loopTimeout--;
}
}
else
{
while(!digitalRead(rxPin) && (loopTimeout >0))
while(!digitalRead(_rxPin) && (loopTimeout >0))
{
delayTicks(bitDelay >> 4);
loopTimeout--;
Expand All @@ -208,21 +211,9 @@ void SoftwareSerial::recv()

uint32_t SoftwareSerial::rx_pin_read()
{
return digitalRead(rxPin);
return digitalRead(_rxPin);
}

//
// Interrupt handling
//

/* static */
inline void SoftwareSerial::handle_interrupt()
{
if (active_object)
{
active_object->recv();
}
}

//
// Constructor
Expand All @@ -235,7 +226,7 @@ SoftwareSerial::SoftwareSerial(uint32_t receivePin, uint32_t transmitPin, bool i
_buffer_overflow(false),
_inverse_logic(inverse_logic)
{
invertedLogic = inverse_logic;
_inverse_logic = inverse_logic;
setTX(transmitPin);
_transmitPin = transmitPin;
setRX(receivePin);
Expand Down Expand Up @@ -283,37 +274,37 @@ void SoftwareSerial::begin(long speed)
{
_rx_delay_centering = _rx_delay_intrabit = _rx_delay_stopbit = _tx_delay = 0;
//pre-calculate delays
bitDelay = (F_CPU/speed);
PinDescription *p = &g_APinDescription[rxPin];
_bit_delay = (F_CPU/speed);
PinDescription *p = &g_APinDescription[_rxPin];
if (p->ulGPIOType == SOC_GPIO)
{
isSOCGpio = true;
_isSOCGpio = true;
}
//toggling a pin takes about 62 ticks
_tx_delay = bitDelay - 62;
_tx_delay = _bit_delay - 62;
//reading a pin takes about 70 ticks
rxIntraBitDelay = bitDelay - 70;
_rx_delay_intrabit = _bit_delay - 70;
//it takes about 272 ticks from when the start bit is received to when the ISR is called
rxCenteringDelay = (bitDelay / 2 - 272 - 55);
if(rxCenteringDelay < 0)
_rx_delay_centering = (_bit_delay / 2 - 272 - 55);
if(_rx_delay_centering < 0)
{
firstIntraBitDelay = rxIntraBitDelay + rxCenteringDelay;
if(firstIntraBitDelay < 0)
firstIntraBitDelay = 0;
rxCenteringDelay = 0;
_rx_delay_first_intrabit = _rx_delay_intrabit + _rx_delay_centering;
if(_rx_delay_first_intrabit < 0)
_rx_delay_first_intrabit = 0;
_rx_delay_centering = 0;
}
else
{
firstIntraBitDelay = rxIntraBitDelay;
_rx_delay_first_intrabit = _rx_delay_intrabit;
}
//the first time the ISR is called is about 150 ticks longer
initRxCenteringDelay = rxCenteringDelay - 150;
if(initRxCenteringDelay < 0)
_rx_delay_init_centering = _rx_delay_centering - 150;
if(_rx_delay_init_centering < 0)
{
initRxIntraBitDelay = rxIntraBitDelay + initRxCenteringDelay;
if(initRxIntraBitDelay < 0)
initRxIntraBitDelay = 0;
initRxCenteringDelay = 0;
_rx_delay_init_intrabit = _rx_delay_intrabit + _rx_delay_init_centering;
if(_rx_delay_init_intrabit < 0)
_rx_delay_init_intrabit = 0;
_rx_delay_init_centering = 0;
}

#if _DEBUG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ class SoftwareSerial : public Stream
// per object data
uint32_t _receivePin;
uint32_t _transmitPin;
uint32_t _receiveBitMask;
volatile uint32_t *_receivePortRegister;
uint32_t _transmitBitMask;
volatile uint32_t *_pcint_maskreg;
uint32_t _pcint_maskvalue;
uint32_t _isSOCGpio;

// delays
uint32_t _rx_delay_centering;
uint32_t _rx_delay_intrabit;
uint32_t _rx_delay_stopbit;
uint32_t _tx_delay;
int _bit_delay;
int _rx_delay_centering;
int _rx_delay_init_centering;
int _rx_delay_init_intrabit;
int _rx_delay_first_intrabit;
int _rx_delay_intrabit;
int _rx_delay_stopbit;
int _tx_delay;

uint32_t _buffer_overflow:1;
uint32_t _inverse_logic:1;
bool _inverse_logic = false;

// static data
static char _receive_buffer[_SS_MAX_RX_BUFF];
Expand Down Expand Up @@ -94,8 +94,6 @@ class SoftwareSerial : public Stream

using Print::write;

// public only for easy access by interrupt handlers
static inline void handle_interrupt() __attribute__((__always_inline__));
};

// Arduino 0012 workaround
Expand Down