Hy, I need to modify software serial library for 8E1.
I had found an old post on this forum, from back when IDE version was 1.0.5
I had followed instructions to replace void recv() and write() with this:
// The receive routine called by the interrupt handler
//
void SoftwareSerial8e1::recv()
{
#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Preserve the registers that the compiler misses
// (courtesy of Arduino forum user *etracer*)
asm volatile(
"push r18 \n\t"
"push r19 \n\t"
"push r20 \n\t"
"push r21 \n\t"
"push r22 \n\t"
"push r23 \n\t"
"push r26 \n\t"
"push r27 \n\t"
::);
#endif
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 (_inverse_logic ? rx_pin_read() : !rx_pin_read())
{
// Wait approximately 1/2 of a bit width to "center" the sample
tunedDelay(_rx_delay_centering);
DebugPulse(_DEBUG_PIN2, 1);
// Read each of the 8 bits
for (uint8_t i=0x1; i; i <<= 1)
{
tunedDelay(_rx_delay_intrabit);
DebugPulse(_DEBUG_PIN2, 1);
uint8_t noti = ~i;
if (rx_pin_read())
d |= i;
else // else clause added to ensure function timing is ~balanced
d &= noti;
}
// skip the parity bit
tunedDelay(_rx_delay_stopbit);
DebugPulse(_DEBUG_PIN2, 1);
// skip the stop bit
tunedDelay(_rx_delay_stopbit);
DebugPulse(_DEBUG_PIN2, 1);
if (_inverse_logic)
d = ~d;
// if buffer full, set the overflow flag and return
if ((_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF != _receive_buffer_head)
{
// save new data in buffer: tail points to where byte goes
_receive_buffer[_receive_buffer_tail] = d; // save new byte
_receive_buffer_tail = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
}
else
{
#if _DEBUG // for scope: pulse pin as overflow indictator
DebugPulse(_DEBUG_PIN1, 1);
#endif
_buffer_overflow = true;
}
}
#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Restore the registers that the compiler misses
asm volatile(
"pop r27 \n\t"
"pop r26 \n\t"
"pop r23 \n\t"
"pop r22 \n\t"
"pop r21 \n\t"
"pop r20 \n\t"
"pop r19 \n\t"
"pop r18 \n\t"
::);
#endif
}
size_t SoftwareSerial8e1::write(uint8_t b)
{
if (_tx_delay == 0) {
setWriteError();
return 0;
}
uint8_t oldSREG = SREG;
cli(); // turn off interrupts for a clean txmit
// Write the start bit
tx_pin_write(_inverse_logic ? HIGH : LOW);
tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
uint8_t p = 0;
uint8_t t;
for (t = 0x80; t; t >>= 1)
if (b & t) p++;
// 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);
}
// parity
if (!(p & 0x01))
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
}
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);
}
// parity
if (!(p & 0x01))
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
}
SREG = oldSREG; // turn interrupts back on
tunedDelay(_tx_delay);
return 1;
}
It was obvious to remove 8E1 from void SoftwareSerial8e1::recv() and void SoftwareSerial8e1::write().
Now compiler gives these errors:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp: In member function 'virtual size_t SoftwareSerial::write(uint8_t)':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp:424:3: error: 'tx_pin_write' was not declared in this scope
tx_pin_write(_inverse_logic ? HIGH : LOW);
^~~~~~~~~~~~
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp:424:3: note: suggested alternative: 'rx_pin_read'
tx_pin_write(_inverse_logic ? HIGH : LOW);
^~~~~~~~~~~~
rx_pin_read
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp:425:26: error: 'XMIT_START_ADJUSTMENT' was not declared in this scope
tunedDelay(_tx_delay + XMIT_START_ADJUSTMENT);
^~~~~~~~~~~~~~~~~~~~~
exit status 1
Error compiling for board Arduino Nano.
Some things had changed in new version obviously, but I cannot find instructions for new version...
As I wrote the code for the 1.0.5 version I almost urged to post an updated version (qucik hack, untested code):
// The receive routine called by the interrupt handler
//
void SoftwareSerial8e1::recv()
{
#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Preserve the registers that the compiler misses
// (courtesy of Arduino forum user *etracer*)
asm volatile(
"push r18 \n\t"
"push r19 \n\t"
"push r20 \n\t"
"push r21 \n\t"
"push r22 \n\t"
"push r23 \n\t"
"push r26 \n\t"
"push r27 \n\t"
::);
#endif
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 (_inverse_logic ? rx_pin_read() : !rx_pin_read())
{
// Disable further interrupts during reception, this prevents
// triggering another interrupt directly after we return, which can
// cause problems at higher baudrates.
setRxIntMsk(false);
// Wait approximately 1/2 of a bit width to "center" the sample
tunedDelay(_rx_delay_centering);
DebugPulse(_DEBUG_PIN2, 1);
// Read each of the 8 bits
for (uint8_t i=8; i > 0; --i)
{
tunedDelay(_rx_delay_intrabit);
d >>= 1;
DebugPulse(_DEBUG_PIN2, 1);
if (rx_pin_read())
d |= 0x80;
}
if (_inverse_logic)
d = ~d;
// if buffer full, set the overflow flag and return
uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
if (next != _receive_buffer_head)
{
// save new data in buffer: tail points to where byte goes
_receive_buffer[_receive_buffer_tail] = d; // save new byte
_receive_buffer_tail = next;
}
else
{
DebugPulse(_DEBUG_PIN1, 1);
_buffer_overflow = true;
}
// skip the parity bit
tunedDelay(_rx_delay_stopbit);
DebugPulse(_DEBUG_PIN2, 1);
// skip the stop bit
tunedDelay(_rx_delay_stopbit);
DebugPulse(_DEBUG_PIN2, 1);
// Re-enable interrupts when we're sure to be inside the stop bit
setRxIntMsk(true);
}
}
#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Restore the registers that the compiler misses
asm volatile(
"pop r27 \n\t"
"pop r26 \n\t"
"pop r23 \n\t"
"pop r22 \n\t"
"pop r21 \n\t"
"pop r20 \n\t"
"pop r19 \n\t"
"pop r18 \n\t"
::);
#endif
}
size_t SoftwareSerial::write(uint8_t b)
{
if (_tx_delay == 0) {
setWriteError();
return 0;
}
// By declaring these as local variables, the compiler will put them
// in registers _before_ disabling interrupts and entering the
// critical timing sections below, which makes it a lot easier to
// verify the cycle timings
volatile uint8_t *reg = _transmitPortRegister;
uint8_t reg_mask = _transmitBitMask;
uint8_t inv_mask = ~_transmitBitMask;
uint8_t oldSREG = SREG;
bool inv = _inverse_logic;
uint16_t delay = _tx_delay;
// calculate the parity bit
uint8_t p = 0;
uint8_t t;
for (t = 0x80; t; t >>= 1)
if (b & t) p++;
if (inv)
b = ~b;
cli(); // turn off interrupts for a clean txmit
// Write the start bit
if (inv)
*reg |= reg_mask;
else
*reg &= inv_mask;
tunedDelay(delay);
// Write each of the 8 bits
for (uint8_t i = 8; i > 0; --i)
{
if (b & 1) // choose bit
*reg |= reg_mask; // send 1
else
*reg &= inv_mask; // send 0
tunedDelay(delay);
b >>= 1;
}
// parity
if (!(p & 0x01) && !inv)
*reg |= reg_mask; // send 1
else
*reg &= inv_mask; // send 0
tunedDelay(_tx_delay);
// restore pin to natural state
if (inv)
*reg &= inv_mask;
else
*reg |= reg_mask;
SREG = oldSREG; // turn interrupts back on
tunedDelay(_tx_delay);
return 1;
}
Please keep in mind that this isn't a complete implementation of parity support as the parity bit is simply ignored during reception.
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp:211:1: error: expected declaration before '}' token
}
^
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src\SoftwareSerial.cpp:44:0:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\libraries\SoftwareSerial\src/SoftwareSerial.h:82:15: warning: inline function 'void SoftwareSerial::setRxIntMsk(bool)' used but never defined
inline void setRxIntMsk(bool enable) attribute((always_inline));
^~~~~~~~~~~
exit status 1
Error compiling for board Arduino Nano.
cpp:211 from first error would be at the end of recv()
// skip the stop bit
tunedDelay(_rx_delay_stopbit);
DebugPulse(_DEBUG_PIN2, 1);
// Re-enable interrupts when we're sure to be inside the stop bit
setRxIntMsk(true);
}
}
Removed the very last } above.
It compiles now, will test tomorrow in my car as I need to read ibus (BMW) and report.