diff --git a/cores/nRF5/Arduino.h b/cores/nRF5/Arduino.h index 39fbc0fe..bef516fb 100644 --- a/cores/nRF5/Arduino.h +++ b/cores/nRF5/Arduino.h @@ -29,11 +29,11 @@ extern "C"{ #define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) ) #define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) ) -void yield( void ) ; +void yield( void ); /* sketch */ -void setup( void ) ; -void loop( void ) ; +void setup( void ); +void loop( void ); #include "WVariant.h" @@ -92,12 +92,12 @@ void loop( void ) ; #define bit(b) (1UL << (b)) -#define digitalPinToPort(P) ( &(NRF_GPIO[P]) ) +#define digitalPinToPort(P) ( NRF_GPIO ) // NRF_P0 = P0.00 - P0.31, NRF_P1 = P1.00 - P1.15 (e.g. nRF52840) #define digitalPinToBitMask(P) ( 1 << g_ADigitalPinMap[P] ) //#define analogInPinToBit(P) ( ) -#define portOutputRegister(port) ( &(port->OUTSET) ) +#define portOutputRegister(port) ( &(port->OUT) ) #define portInputRegister(port) ( &(port->IN) ) -#define portModeRegister(port) ( &(port->DIRSET) ) +#define portModeRegister(port) ( &(port->DIR) ) #define digitalPinHasPWM(P) ( true ) /* diff --git a/cores/nRF5/WInterrupts.c b/cores/nRF5/WInterrupts.c index 59cc3cb4..5a9b8d1d 100644 --- a/cores/nRF5/WInterrupts.c +++ b/cores/nRF5/WInterrupts.c @@ -30,19 +30,16 @@ #define NUMBER_OF_GPIO_TE 4 #endif -static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE]; -static int8_t channelMap[NUMBER_OF_GPIO_TE]; +static voidFuncPtr callbacksInt[NUMBER_OF_GPIO_TE] = { NULL }; +static int8_t channelMap[NUMBER_OF_GPIO_TE] = { -1 }; static int enabled = 0; /* Configure I/O interrupt sources */ static void __initialize() { - memset(callbacksInt, 0, sizeof(callbacksInt)); - memset(channelMap, -1, sizeof(channelMap)); - NVIC_DisableIRQ(GPIOTE_IRQn); NVIC_ClearPendingIRQ(GPIOTE_IRQn); - NVIC_SetPriority(GPIOTE_IRQn, 1); + NVIC_SetPriority(GPIOTE_IRQn, 3); // Same priority as Uart NVIC_EnableIRQ(GPIOTE_IRQn); } @@ -50,22 +47,29 @@ static void __initialize() * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. * Replaces any previous function that was attached to the interrupt. */ -void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) +int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) { - if (!enabled) { - __initialize(); - enabled = 1; - } + uint32_t polarity; + uint8_t ch; - if (pin >= PINS_COUNT) { - return; + if (pin >= PINS_COUNT) + { + return -1; } pin = g_ADigitalPinMap[pin]; - uint32_t polarity; + switch (mode) + { + //gpiote channel does not support LOW and HIGH mode. These are mantained for compatibility + case LOW: + polarity = GPIOTE_CONFIG_POLARITY_HiToLo; //same as FALLING + break; + + case HIGH: + polarity = GPIOTE_CONFIG_POLARITY_LoToHi; //same as RISING + break; - switch (mode) { case CHANGE: polarity = GPIOTE_CONFIG_POLARITY_Toggle; break; @@ -79,11 +83,13 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) break; default: - return; + return -1; } - for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) { - if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin) { + for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) + { + if (channelMap[ch] == -1 || (uint32_t)channelMap[ch] == pin) + { channelMap[ch] = pin; callbacksInt[ch] = callback; @@ -98,6 +104,16 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode) break; } } + + // enable the interrupt after the first one is configured + if (!enabled) + { + __initialize(); + enabled = 1; + } + + // return the interrupt mask + return (1 << ch); } /* @@ -127,21 +143,31 @@ void detachInterrupt(uint32_t pin) void GPIOTE_IRQHandler() { - uint32_t event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]); - - for (int ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) { - if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch))) { - if (channelMap[ch] != -1 && callbacksInt[ch]) { - callbacksInt[ch](); - } - - *(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0; -#if __CORTEX_M == 0x04 - volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event)); - (void)dummy; -#endif + uint32_t event; + uint8_t ch; + + for (ch = 0; ch < NUMBER_OF_GPIO_TE; ch++) + { + event = offsetof(NRF_GPIOTE_Type, EVENTS_IN[ch]); + if ((*(uint32_t *)((uint32_t)NRF_GPIOTE + event) == 0x1UL) && (NRF_GPIOTE->INTENSET & (1 << ch))) + { + break; } - - event = (uint32_t)((uint32_t)event + 4); } + + // clear event + *(uint32_t *)((uint32_t)NRF_GPIOTE + event) = 0; + #if __CORTEX_M == 0x04 + volatile uint32_t dummy = *((volatile uint32_t *)((uint32_t)NRF_GPIOTE + event)); + (void)dummy; + #endif + + // disable the interrupt + NRF_GPIOTE->INTENCLR = (1 << ch); + + // initiate the callback + callbacksInt[ch](); + + // enable the interrupt + NRF_GPIOTE->INTENSET = (1 << ch); } diff --git a/cores/nRF5/WInterrupts.h b/cores/nRF5/WInterrupts.h index 5d2b24a0..61613f1e 100644 --- a/cores/nRF5/WInterrupts.h +++ b/cores/nRF5/WInterrupts.h @@ -40,7 +40,7 @@ typedef void (*voidFuncPtr)(void); * \brief Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. * Replaces any previous function that was attached to the interrupt. */ -void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); +int attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); /* * \brief Turns off the given interrupt. diff --git a/libraries/SoftwareSerial/LICENSE b/libraries/SoftwareSerial/LICENSE new file mode 100644 index 00000000..7574f55d --- /dev/null +++ b/libraries/SoftwareSerial/LICENSE @@ -0,0 +1,16 @@ +Copyright (c) 2016 Arduino. All rights reserved. +Copyright (c) 2017 Mark Cooke All right reserved. + +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 \ No newline at end of file diff --git a/libraries/SoftwareSerial/README.md b/libraries/SoftwareSerial/README.md new file mode 100644 index 00000000..00c34d81 --- /dev/null +++ b/libraries/SoftwareSerial/README.md @@ -0,0 +1,28 @@ +### SoftwareSerial + +This library is based off SoftwareSerial from @arduino-org's arduino-core-nrf52 release [1.0.1](https://github.com/arduino-org/arduino-core-nrf52/releases/tag/1.0.1) + +#### Modifications +* merged SoftwareSerial.cpp into SoftwareSerial.h to allow ```_SS_MAX_RX_BUFF``` to be user-defined +* added ```_SS_TX_ONLY``` user define to allow this to be used as a transmit only library (no interrupts used) + +### License + +``` +Copyright (c) 2016 Arduino. All rights reserved. +Copyright (c) 2017 Mark Cooke All right reserved. + +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 +``` \ No newline at end of file diff --git a/libraries/SoftwareSerial/SoftwareSerial.h b/libraries/SoftwareSerial/SoftwareSerial.h new file mode 100644 index 00000000..0642890c --- /dev/null +++ b/libraries/SoftwareSerial/SoftwareSerial.h @@ -0,0 +1,472 @@ +/* + SoftwareSerial.h - library for Nordic nRF5 devices + + Copyright (c) 2016 Arduino. All rights reserved. + Copyright (c) 2017 Mark Cooke All right reserved. + + 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 + */ + +#ifndef SoftwareSerial_h +#define SoftwareSerial_h + +#include +#include +#include +#include +#include + +/****************************************************************************** +* Definitions +******************************************************************************/ + +#ifndef _SS_MAX_RX_BUFF +#define _SS_MAX_RX_BUFF 64 // RX buffer size +#endif + +#ifndef _SS_TX_ONLY +#define _SS_TX_ONLY 0 +#endif + +class SoftwareSerial : public Stream +{ + private: + // transmit data + uint8_t _transmitPin; + uint32_t _transmitBitMask; + volatile uint32_t* _transmitPortRegister; + + // Expressed as micro seconds + uint16_t _tx_delay_us; + +#if (_SS_TX_ONLY == 0) + // receive data + uint8_t _receivePin; + uint32_t _receiveBitMask; + volatile uint32_t* _receivePortRegister; + + volatile uint32_t _intMask; + + // Expressed as micro seconds + uint16_t _rx_delay_centering_us; + uint16_t _rx_delay_intrabit_us; + uint16_t _rx_delay_stopbit_us; + + uint16_t _buffer_overflow : 1; + + // static data + uint8_t _receive_buffer[_SS_MAX_RX_BUFF] = {0}; + volatile uint8_t _receive_buffer_tail; + volatile uint8_t _receive_buffer_head; + + static SoftwareSerial* active_object; +#endif + + uint16_t _inverse_logic : 1; + + // private methods + inline void recv() __attribute__((__always_inline__)); + uint32_t rx_pin_read(); + void tx_pin_write(uint8_t pin_state) __attribute__((__always_inline__)); + void setTX(uint8_t transmitPin); + void setRX(uint8_t receivePin); + void setRxIntMsk(bool enable) __attribute__((__always_inline__)); + + public: + // public methods + SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false); + ~SoftwareSerial(); + void begin(long speed); + bool listen(); + void end(); + bool isListening() + { +#if (_SS_TX_ONLY == 0) + return this == active_object; +#else + return 0; +#endif + } + bool stopListening(); + bool overflow() + { +#if (_SS_TX_ONLY == 0) + bool ret = _buffer_overflow; + if (ret) _buffer_overflow = false; + return ret; +#else + return 0; +#endif + } + int peek(); + + virtual size_t write(uint8_t byte); + virtual int read(); + virtual int available(); + virtual void flush(); + operator bool() { return true; } + + using Print::write; + + // public only for easy access by interrupt handlers + static inline void handle_interrupt() __attribute__((__always_inline__)); +}; + +#if (_SS_TX_ONLY == 0) +SoftwareSerial* SoftwareSerial::active_object = NULL; +#endif + +SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, + bool inverse_logic /* = false */) + : +#if (_SS_TX_ONLY == 0) + _rx_delay_centering_us(0), + _rx_delay_intrabit_us(0), + _rx_delay_stopbit_us(0), + _buffer_overflow(false), + _intMask(0), + _receive_buffer_tail(0), + _receive_buffer_head(0), +#endif + _tx_delay_us(0), + _inverse_logic(inverse_logic) +{ +#if (_SS_TX_ONLY == 0) + _receivePin = receivePin; +#endif + _transmitPin = transmitPin; + + //_half_duplex = (_receivePin == _transmitPin) ? !_SS_TX_ONLY : 0; +} + +SoftwareSerial::~SoftwareSerial() { end(); } + +void SoftwareSerial::begin(long speed) +{ + setTX(_transmitPin); +#if (_SS_TX_ONLY == 0) + setRX(_receivePin); +#endif + + // Precalculate the various delays + // Calculate the distance between bit in micro seconds + uint32_t bit_delay = (float(1) / speed) * 1000000; + + _tx_delay_us = bit_delay; +#if (_SS_TX_ONLY == 0) + // Wait 1/2 bit - 2 micro seconds (time for interrupt to be served) + _rx_delay_centering_us = (bit_delay / 2) - 2; + // Wait 1 bit - 2 micro seconds (time in each loop iteration) + _rx_delay_intrabit_us = bit_delay - 1; // 2 + // Wait 1 bit (the stop one) + _rx_delay_stopbit_us = bit_delay; +#endif + delayMicroseconds(_tx_delay_us); + + listen(); +} + +bool SoftwareSerial::listen() +{ +#if (_SS_TX_ONLY == 0) + if (!_rx_delay_stopbit_us) return false; + + if (active_object != this) + { + if (active_object) active_object->stopListening(); + + _buffer_overflow = false; + _receive_buffer_head = _receive_buffer_tail = 0; + active_object = this; + + if (_inverse_logic) + { + // Start bit high + _intMask = attachInterrupt(_receivePin, handle_interrupt, RISING); + } + else + { + // Start bit low + _intMask = attachInterrupt(_receivePin, handle_interrupt, FALLING); + } + return true; + } +#endif + return false; +} + +bool SoftwareSerial::stopListening() +{ +#if (_SS_TX_ONLY == 0) + if (active_object == this) + { + detachInterrupt(_receivePin); + active_object = NULL; + return true; + } +#endif + return false; +} + +void SoftwareSerial::end() { stopListening(); } + +int SoftwareSerial::read() +{ +#if (_SS_TX_ONLY == 1) + this->println(F("read() is invalid - _SS_TX_ONLY is defined.")); +#else + if (isListening() == 0) + { + return -1; + } + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) + { + return -1; + } + + // Read from "head" + uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte + _receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF; + return d; +#endif +} + +int SoftwareSerial::available() +{ +#if (_SS_TX_ONLY == 0) + if (isListening() == 0) + return 0; + else + return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF; +#else + return 0; +#endif +} + +size_t SoftwareSerial::write(uint8_t b) +{ + if (_tx_delay_us == 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 uint32_t* reg = _transmitPortRegister; + uint32_t reg_mask = _transmitBitMask; + uint32_t inv_mask = ~_transmitBitMask; + bool inv = _inverse_logic; + uint16_t delay = _tx_delay_us; + + if (inv) b = ~b; + +// turn off interrupts for a clean txmit +#if (_SS_TX_ONLY == 0) + NRF_GPIOTE->INTENCLR = _intMask; +#endif + + // Write the start bit + if (inv) + *reg |= reg_mask; + else + *reg &= inv_mask; + + delayMicroseconds(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 + + delayMicroseconds(delay); + b >>= 1; + } + + // restore pin to natural state + if (inv) + *reg &= inv_mask; + else + *reg |= reg_mask; + +// turn interrupts back on +#if (_SS_TX_ONLY == 0) + NRF_GPIOTE->INTENSET = _intMask; +#endif + + delayMicroseconds(delay); + + return 1; +} + +void SoftwareSerial::flush() +{ +#if (_SS_TX_ONLY == 0) + if (isListening() == 0) return; + + NRF_GPIOTE->INTENCLR = _intMask; + + _receive_buffer_head = _receive_buffer_tail = 0; + + NRF_GPIOTE->INTENSET = _intMask; +#endif +} + +int SoftwareSerial::peek() +{ +#if (_SS_TX_ONLY == 1) + return -1; +#else + if (isListening() == 0) return -1; + + // Empty buffer? + if (_receive_buffer_head == _receive_buffer_tail) return -1; + + // Read from "head" + return _receive_buffer[_receive_buffer_head]; +#endif +} + +// private methods + +inline void SoftwareSerial::recv() +{ +#if (_SS_TX_ONLY == 0) + 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()) + { + NRF_GPIOTE->INTENCLR = _intMask; + + // Wait approximately 1/2 of a bit width to "center" the sample + delayMicroseconds(_rx_delay_centering_us); + + // Read each of the 8 bits + for (int8_t i = 8; i > 0; --i) + { + delayMicroseconds(_rx_delay_intrabit_us); + // nRF52 needs another delay less than 1 uSec to be better synchronized + // with the highest baud rates + __ASM volatile( + " NOP\n\t" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n"); + + d >>= 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 + { + _buffer_overflow = true; + } + + // skip the stop bit + delayMicroseconds(_rx_delay_stopbit_us); + + NRF_GPIOTE->INTENSET = _intMask; + } +#endif +} + +uint32_t SoftwareSerial::rx_pin_read() +{ +#if (_SS_TX_ONLY == 0) + return *_receivePortRegister & digitalPinToBitMask(_receivePin); +#else + return 0; +#endif +} + +/* static */ +inline void SoftwareSerial::handle_interrupt() +{ +#if (_SS_TX_ONLY == 0) + if (active_object != NULL) + { + active_object->recv(); + } +#endif +} + +void SoftwareSerial::setTX(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. + _transmitPin = tx; + + digitalWrite(_transmitPin, _inverse_logic ? LOW : HIGH); + pinMode(_transmitPin, OUTPUT); + + _transmitBitMask = digitalPinToBitMask(_transmitPin); + NRF_GPIO_Type* port = digitalPinToPort(_transmitPin); + _transmitPortRegister = portOutputRegister(port); +} + +void SoftwareSerial::setRX(uint8_t rx) +{ +#if (_SS_TX_ONLY == 0) + _receivePin = rx; + + digitalWrite(_receivePin, _inverse_logic ? LOW : HIGH); + pinMode(_receivePin, INPUT); + + _receiveBitMask = digitalPinToBitMask(_receivePin); + NRF_GPIO_Type* port = digitalPinToPort(_receivePin); + _receivePortRegister = portInputRegister(port); +#endif +} + +#endif \ No newline at end of file diff --git a/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino b/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino new file mode 100644 index 00000000..4e179b7f --- /dev/null +++ b/libraries/SoftwareSerial/examples/SoftwareSerialExample/SoftwareSerialExample.ino @@ -0,0 +1,38 @@ +/* + Software serial multiple serial test + + Receives from the hardware serial, sends to software serial. + Receives from software serial, sends to hardware serial. + + The circuit: + * RX is digital pin 9 (connect to TX of other device) + * TX is digital pin 10 (connect to RX of other device) + + This example code is in the public domain. + + */ + +#include + +SoftwareSerial mySerial(9, 10); // RX, TX + + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(9600); + Serial.println("Goodnight moon!"); + + // set the data rate for the SoftwareSerial port + mySerial.begin(9600); + mySerial.println("Hello, world?"); +} + +void loop() // run over and over// +{ + if (mySerial.available()) + Serial.write(mySerial.read()); + + if (Serial.available()) + mySerial.write(Serial.read()); +} diff --git a/libraries/SoftwareSerial/examples/TransmitOnly/TransmitOnly.ino b/libraries/SoftwareSerial/examples/TransmitOnly/TransmitOnly.ino new file mode 100644 index 00000000..1c6d6740 --- /dev/null +++ b/libraries/SoftwareSerial/examples/TransmitOnly/TransmitOnly.ino @@ -0,0 +1,37 @@ +/* + SoftwareSerial TX Only test + + If your application is transmit only then setting + #define _SS_TX_ONLY 1 + Will stop the library allocating a GPIO interrupt and save 1432 bytes of memory + */ +#define _SS_TX_ONLY 1 // Transmit only (Rx pin is unused/unassigned, but still needs a number) +#define _SS_MAX_RX_BUFF 128 // Increase the Rx buffer to 128 bytes (default is 64 bytes) +#include + +SoftwareSerial SoftSerial(2, 3); // RX, TX + +uint32_t t; +bool hb_state = false; // heartbeat + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + SoftSerial.begin(9600); + SoftSerial.println(__FILE__); + SoftSerial.println(__TIME__); + t = millis(); +} + +void loop() +{ + if (millis() - t > 1000) + { + t = millis(); + digitalWrite(LED_BUILTIN, hb_state); + hb_state = !hb_state; + SoftSerial.print("."); + } + + yield(); +} diff --git a/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino new file mode 100644 index 00000000..47d58091 --- /dev/null +++ b/libraries/SoftwareSerial/examples/TwoPortReceive/TwoPortReceive.ino @@ -0,0 +1,71 @@ +/* + Software serial multple serial test + + Receives from the two software serial ports, + sends to the hardware serial port. + + In order to listen on a software port, you call port.listen(). + When using two software serial ports, you have to switch ports + by listen()ing on each one in turn. Pick a logical time to switch + ports, like the end of an expected transmission, or when the + buffer is empty. This example switches ports when there is nothing + more to read from a port + + The circuit: + Two devices which communicate serially are needed. + * First serial device's TX attached to digital pin 9, RX to pin 11 + * Second serial device's TX attached to digital pin 8, RX to pin 10 + + This example code is in the public domain. + + */ + +#include +// software serial #1: TX = digital pin 11, RX = digital pin 9 +SoftwareSerial portOne(9, 11); + +// software serial #2: TX = digital pin 10, RX = digital pin 8 +SoftwareSerial portTwo(8, 10); + +void setup() +{ + // Open serial communications and wait for port to open: + Serial.begin(115200); + + // Start each software serial port + portOne.begin(9600); + portTwo.begin(9600); +} + +void loop() +{ + // By default, the last intialized port is listening. + // when you want to listen on a port, explicitly select it: + portOne.listen(); + + Serial.println("Data from port one:"); + // while there is data coming in, read it + // and send to the hardware serial port: + while (portOne.available() > 0) { + char inByte = portOne.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(""); + + // Now listen on the second port + portTwo.listen(); + // while there is data coming in, read it + // and send to the hardware serial port: + + Serial.println("Data from port two:"); + while (portTwo.available() > 0) { + char inByte = portTwo.read(); + Serial.write(inByte); + } + + // blank line to separate data from the two ports: + Serial.println(); +} + diff --git a/libraries/SoftwareSerial/keywords.txt b/libraries/SoftwareSerial/keywords.txt new file mode 100644 index 00000000..e27a0cf4 --- /dev/null +++ b/libraries/SoftwareSerial/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map for SoftwareSerial +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SoftwareSerial KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +end KEYWORD2 +read KEYWORD2 +write KEYWORD2 +available KEYWORD2 +isListening KEYWORD2 +overflow KEYWORD2 +flush KEYWORD2 +listen KEYWORD2 +peek KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + +_SS_MAX_RX_BUFF LITERAL1 +_SS_TX_ONLY LITERAL1 \ No newline at end of file diff --git a/libraries/SoftwareSerial/library.properties b/libraries/SoftwareSerial/library.properties new file mode 100644 index 00000000..cb9b22bc --- /dev/null +++ b/libraries/SoftwareSerial/library.properties @@ -0,0 +1,9 @@ +name=SoftwareSerial +version=1.1.0 +author=Arduino, Mark Cooke +maintainer=Mark Cooke (https://github/micooke) +sentence=Enables serial communication on digital pins. +paragraph=The SoftwareSerial library has been developed to allow serial communication on any digital pin of the board, using software to replicate the functionality of the hardware UART. It is possible to have multiple software serial ports with speeds up to 115200 bps. +category=Communication +url=http://arduino.cc/en/Reference/SoftwareSerial +architectures=nrf52,nRF5