Skip to content

Option for SOFTWARESERIAL_UNUSED to allow TX or RX only configs #3053

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 2 commits into
base: master
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
27 changes: 27 additions & 0 deletions hardware/arduino/avr/libraries/SoftwareSerial/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
= SoftwareSerial Library for Arduino (formerly NewSoftSerial) =

The SoftwareSerial library has been developed to allow serial communication (TX and/or RX) on other digital pins of the Arduino and other Atmel chips, using software to replicate the functionality (hence the name "SoftwareSerial"). It is possible to have multiple software serial ports with speeds up to 115200 bps. A parameter enables inverted signaling for devices which require that protocol.

For more information about this library please visit us at
http://www.arduino.cc/en/Reference/SoftwareSerial

== Written by ==

Mikal Hart; with improvements from: ladyada, Paul Stoffregen, Garrett Mace, Brett Hagman and Scott Brynen.

== License ==

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

54 changes: 31 additions & 23 deletions hardware/arduino/avr/libraries/SoftwareSerial/SoftwareSerial.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
/*
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
SoftwareSerial.cpp (formerly NewSoftSerial.cpp) -
Multi-instance software serial library for Arduino/Wiring
-- Interrupt-driven receive and other improvements by ladyada
(http://ladyada.net)
-- Tuning, circular buffer, derivation from class Print/Stream,
multi-instance support, porting to 8MHz processors,
various optimizations, PROGMEM delay tables, inverse logic and
various optimizations, PROGMEM delay tables, inverse logic and
direct port writing by Mikal Hart (http://www.arduiniana.org)
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
-- Transmit or Receive Only by Scott Brynen (http://github.com/sbrynen)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Expand All @@ -35,6 +36,7 @@ The latest version of this library can always be found at
#define _DEBUG 0
#define _DEBUG_PIN1 11
#define _DEBUG_PIN2 13

//
// Includes
//
Expand All @@ -48,7 +50,7 @@ The latest version of this library can always be found at
// Statics
//
SoftwareSerial *SoftwareSerial::active_object = 0;
char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
char SoftwareSerial::_receive_buffer[_SS_MAX_RX_BUFF];
volatile uint8_t SoftwareSerial::_receive_buffer_tail = 0;
volatile uint8_t SoftwareSerial::_receive_buffer_head = 0;

Expand Down Expand Up @@ -76,15 +78,15 @@ inline void DebugPulse(uint8_t pin, uint8_t count)
//

/* static */
inline void SoftwareSerial::tunedDelay(uint16_t delay) {
inline void SoftwareSerial::tunedDelay(uint16_t delay) {
_delay_loop_2(delay);
}

// This function sets the current object as the "listening"
// one and returns true if it replaces another
bool SoftwareSerial::listen()
{
if (!_rx_delay_stopbit)
if ((_receivePin == SOFTWARESERIAL_UNUSED) || !_rx_delay_stopbit)
return false;

if (active_object != this)
Expand All @@ -106,7 +108,7 @@ bool SoftwareSerial::listen()
// Stop listening. Returns true if we were actually listening.
bool SoftwareSerial::stopListening()
{
if (active_object == this)
if ((_receivePin != SOFTWARESERIAL_UNUSED) && (active_object == this))
{
setRxIntMsk(false);
active_object = NULL;
Expand Down Expand Up @@ -252,6 +254,7 @@ SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inv
_buffer_overflow(false),
_inverse_logic(inverse_logic)
{
// passing SOFTWARESERIAL_UNUSED for either the TX or RX pin makes the object RX or TX only
setTX(transmitPin);
setRX(receivePin);
}
Expand All @@ -270,22 +273,27 @@ void SoftwareSerial::setTX(uint8_t tx)
// the pin would be output low for a short while before switching to
// output hihg. 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);
_transmitBitMask = digitalPinToBitMask(tx);
uint8_t port = digitalPinToPort(tx);
_transmitPortRegister = portOutputRegister(port);
_transmitPin = tx;
if (tx != SOFTWARESERIAL_UNUSED) {
digitalWrite(tx, _inverse_logic ? LOW : HIGH);
pinMode(tx, OUTPUT);
_transmitBitMask = digitalPinToBitMask(tx);
uint8_t port = digitalPinToPort(tx);
_transmitPortRegister = portOutputRegister(port);
}
}

void SoftwareSerial::setRX(uint8_t rx)
{
pinMode(rx, INPUT);
if (!_inverse_logic)
digitalWrite(rx, HIGH); // pullup for normal logic!
_receivePin = rx;
_receiveBitMask = digitalPinToBitMask(rx);
uint8_t port = digitalPinToPort(rx);
_receivePortRegister = portInputRegister(port);
if (rx != SOFTWARESERIAL_UNUSED) {
pinMode(rx, INPUT);
if (!_inverse_logic)
digitalWrite(rx, HIGH); // pullup for normal logic!
_receiveBitMask = digitalPinToBitMask(rx);
uint8_t port = digitalPinToPort(rx);
_receivePortRegister = portInputRegister(port);
}
}

uint16_t SoftwareSerial::subtract_cap(uint16_t num, uint16_t sub) {
Expand Down Expand Up @@ -314,7 +322,7 @@ void SoftwareSerial::begin(long speed)
_tx_delay = subtract_cap(bit_delay, 15 / 4);

// Only setup rx when we have a valid PCINT for this pin
if (digitalPinToPCICR(_receivePin)) {
if ((_receivePin != SOFTWARESERIAL_UNUSED) && digitalPinToPCICR(_receivePin)) {
#if GCC_VERSION > 40800
// Timings counted from gcc 4.8.2 output. This works up to 115200 on
// 16Mhz and 57600 on 8Mhz.
Expand Down Expand Up @@ -374,10 +382,10 @@ void SoftwareSerial::begin(long speed)

void SoftwareSerial::setRxIntMsk(bool enable)
{
if (enable)
*_pcint_maskreg |= _pcint_maskvalue;
else
*_pcint_maskreg &= ~_pcint_maskvalue;
if (enable)
*_pcint_maskreg |= _pcint_maskvalue;
else
*_pcint_maskreg &= ~_pcint_maskvalue;
}

void SoftwareSerial::end()
Expand Down Expand Up @@ -412,7 +420,7 @@ int SoftwareSerial::available()

size_t SoftwareSerial::write(uint8_t b)
{
if (_tx_delay == 0) {
if ((_transmitPin == SOFTWARESERIAL_UNUSED) || (_tx_delay == 0)) {
setWriteError();
return 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Multi-instance software serial library for Arduino/Wiring
-- Pin change interrupt macros by Paul Stoffregen (http://www.pjrc.com)
-- 20MHz processor support by Garrett Mace (http://www.macetech.com)
-- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
-- Transmit or Receive Only by Scott Brynen (http://github.com/sbrynen)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -39,7 +40,9 @@ The latest version of this library can always be found at
* Definitions
******************************************************************************/

#define _SS_MAX_RX_BUFF 64 // RX buffer size
#define _SS_MAX_RX_BUFF 64 // RX buffer size
#define SOFTWARESERIAL_UNUSED -1 // flag for unused TX or RX pins

#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
Expand All @@ -51,6 +54,7 @@ class SoftwareSerial : public Stream
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;
Expand Down Expand Up @@ -92,7 +96,7 @@ class SoftwareSerial : public Stream
void begin(long speed);
bool listen();
void end();
bool isListening() { return this == active_object; }
bool isListening() { return (_receivePin != SOFTWARESERIAL_UNUSED) && (this == active_object); }
bool stopListening();
bool overflow() { bool ret = _buffer_overflow; if (ret) _buffer_overflow = false; return ret; }
int peek();
Expand Down