From 4f602992240361c0d3ae23284cc6e4202e8a7231 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 7 Aug 2019 21:17:26 -0600 Subject: [PATCH 01/20] Add external hook for CPU freq. --- cores/arduino/ard_sup/ap3_clock_sources.h | 3 +++ cores/arduino/ard_sup/clock/ap3_clock_sources.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/cores/arduino/ard_sup/ap3_clock_sources.h b/cores/arduino/ard_sup/ap3_clock_sources.h index f9d5a68e..2cfd2ac8 100644 --- a/cores/arduino/ard_sup/ap3_clock_sources.h +++ b/cores/arduino/ard_sup/ap3_clock_sources.h @@ -26,5 +26,8 @@ SOFTWARE. bool enableBurstMode(); bool disableBurstMode(); +uint32_t getCpuFreqMHz(); + +uint32_t cpuFreq = 48000000; //At POR core is 48MHz #endif //_AP3_GPIO_H_ \ No newline at end of file diff --git a/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp b/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp index 497ca328..64736f67 100644 --- a/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp +++ b/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp @@ -17,6 +17,7 @@ bool enableBurstMode(void) { return (false); } + cpuFreq = 96000000; return (true); } @@ -36,5 +37,12 @@ bool disableBurstMode(void) { return (false); } + cpuFreq = 48000000; return (true); } + +//Returns the current core speed +uint32_t getCpuFreqMHz(void) +{ + return(cpuFreq); +} \ No newline at end of file From c21d0d9d1aa1df2f16de89ff7d98f40524589db1 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 15:46:55 -0600 Subject: [PATCH 02/20] Basic skeleton working --- cores/arduino/ard_sup/ap3_clock_sources.h | 2 - .../ard_sup/clock/ap3_clock_sources.cpp | 4 +- cores/arduino/ard_sup/gpio/ap3_gpio.cpp | 6 +- .../examples/Apollo_EEPROM/Apollo_EEPROM.ino | 167 ++++++++++ libraries/SoftwareSerial/keywords.txt | 23 ++ libraries/SoftwareSerial/library.properties | 9 + .../SoftwareSerial/src/SoftwareSerial.cpp | 299 ++++++++++++++++++ libraries/SoftwareSerial/src/SoftwareSerial.h | 94 ++++++ 8 files changed, 600 insertions(+), 4 deletions(-) create mode 100644 libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino create mode 100644 libraries/SoftwareSerial/keywords.txt create mode 100644 libraries/SoftwareSerial/library.properties create mode 100644 libraries/SoftwareSerial/src/SoftwareSerial.cpp create mode 100644 libraries/SoftwareSerial/src/SoftwareSerial.h diff --git a/cores/arduino/ard_sup/ap3_clock_sources.h b/cores/arduino/ard_sup/ap3_clock_sources.h index 2cfd2ac8..b2327755 100644 --- a/cores/arduino/ard_sup/ap3_clock_sources.h +++ b/cores/arduino/ard_sup/ap3_clock_sources.h @@ -28,6 +28,4 @@ bool enableBurstMode(); bool disableBurstMode(); uint32_t getCpuFreqMHz(); -uint32_t cpuFreq = 48000000; //At POR core is 48MHz - #endif //_AP3_GPIO_H_ \ No newline at end of file diff --git a/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp b/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp index 64736f67..cb0578af 100644 --- a/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp +++ b/cores/arduino/ard_sup/clock/ap3_clock_sources.cpp @@ -1,5 +1,7 @@ #include "ap3_clock_sources.h" +uint32_t cpuFreq = 48000000; //At POR core is 48MHz + //Turns main processor from 48MHz to 96MHz //Returns false if burst mode failed to enable bool enableBurstMode(void) @@ -44,5 +46,5 @@ bool disableBurstMode(void) //Returns the current core speed uint32_t getCpuFreqMHz(void) { - return(cpuFreq); + return (cpuFreq); } \ No newline at end of file diff --git a/cores/arduino/ard_sup/gpio/ap3_gpio.cpp b/cores/arduino/ard_sup/gpio/ap3_gpio.cpp index df8d2b4a..3829b280 100644 --- a/cores/arduino/ard_sup/gpio/ap3_gpio.cpp +++ b/cores/arduino/ard_sup/gpio/ap3_gpio.cpp @@ -133,6 +133,10 @@ extern "C" void am_gpio_isr(void) uint64_t gpio_int_mask = 0x00; am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); + if (gpio_int_mask & softwareserial_pin_mask) + { + } + for (uint8_t indi = 0; indi < gpio_num_isr; indi++) { if (gpio_isr_entries[indi].callback != NULL) @@ -305,7 +309,7 @@ uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir) uint32_t ui32GPCfgClearMask; uint32_t ui32GPCfgShft; - ui32GPCfgShft = ((ui32Pin & 0x7) << 2); + ui32GPCfgShft = ((ui32Pin & 0x7) << 2); ui32GPCfgAddr = AM_REGADDR(GPIO, CFGA) + ((ui32Pin >> 1) & ~0x3); diff --git a/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino b/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino new file mode 100644 index 00000000..a1418ed4 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino @@ -0,0 +1,167 @@ +/* + Reading and writing test of the EEPROM functions on the Artemis + By: Nathan Seidle + SparkFun Electronics + Date: June 24th, 2019 + This example code is in the public domain. + + SparkFun labored with love to create this code. Feel like supporting open source hardware? + Buy a board from SparkFun! https://www.sparkfun.com/products/15376 + + Page erase takes 15ms + Write byte takes 30ms - This is much longer than Arduino that takes 3.3ms + Float write across two words takes 30ms + Update (no write) takes 1ms +*/ + +#include + +void setup() +{ + Serial.begin(9600); + Serial.println("EEPROM Examples"); + + randomSeed(analogRead(A0)); + + long startTime; + long endTime; + uint16_t randomLocation; + + //Test erase time + startTime = millis(); + EEPROM.erase(); + endTime = millis(); + Serial.printf("Time to erase all EEPROM: %dms\n", endTime - startTime); + + //Byte sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.println(""); + Serial.println("8 bit tests"); + byte myValue1 = 200; + byte myValue2 = 23; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + startTime = millis(); + EEPROM.write(randomLocation, myValue1); //(location, data) + endTime = millis(); + EEPROM.put(randomLocation + 1, myValue2); + + Serial.printf("Write byte time: %dms\n", endTime - startTime); + + byte response1 = EEPROM.read(randomLocation); + byte response2 = EEPROM.read(randomLocation + 1); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue1, response1); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 1, myValue2, response2); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("16 bit tests"); + + //int16_t and uint16_t sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + uint16_t myValue3 = 3411; + int16_t myValue4 = -366; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + EEPROM.put(randomLocation, myValue3); + EEPROM.put(randomLocation + 2, myValue4); + + uint16_t response3; + int16_t response4; + EEPROM.get(randomLocation, response3); + EEPROM.get(randomLocation + 2, response4); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue3, response3); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 2, myValue4, response4); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("32 bit tests"); + + //int and unsigned int (32) sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.printf("Size of int: %d\n", sizeof(int)); + int myValue5 = -245000; + unsigned int myValue6 = 400123; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + EEPROM.put(randomLocation, myValue5); + EEPROM.put(randomLocation + 4, myValue6); + + int response5; + unsigned int response6; + EEPROM.get(randomLocation, response5); + EEPROM.get(randomLocation + 4, response6); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue5, response5); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue6, response6); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //int32_t and uint32_t sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + int32_t myValue7 = -341002; + uint32_t myValue8 = 241544; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + EEPROM.update(randomLocation, myValue7); + EEPROM.update(randomLocation + 4, myValue8); + + int32_t response7; + uint32_t response8; + EEPROM.get(randomLocation, response7); + EEPROM.get(randomLocation + 4, response8); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue7, response7); + Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue8, response8); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + //float (32) sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.printf("Size of float: %d\n", sizeof(float)); + float myValue9 = -7.35; + float myValue10 = 5.22; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + EEPROM.update(randomLocation, myValue9); + EEPROM.update(randomLocation + 4, myValue10); + + float response9; + float response10; + EEPROM.get(randomLocation, response9); + EEPROM.get(randomLocation + 4, response10); + Serial.printf("Location %d should be %f: %f\n\r", randomLocation, myValue9, response9); + Serial.printf("Location %d should be %f: %f\n\r", randomLocation + 4, myValue10, response10); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(""); + Serial.println("64 bit tests"); + + //double (64) sequential test + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + Serial.printf("Size of double: %d\n", sizeof(double)); + double myValue11 = -290.3485723409857; + double myValue12 = 384.95734987; + randomLocation = random(0, FLASH_EEPROM_SIZE); + + EEPROM.update(randomLocation, myValue11); + EEPROM.update(randomLocation + 8, myValue12); + + double response11; + double response12; + EEPROM.get(randomLocation, response11); + EEPROM.get(randomLocation + 8, response12); + Serial.printf("Location %d should be %lf: %lf\n", randomLocation, myValue11, response11); + Serial.printf("Location %d should be %lf: %lf\n", randomLocation + 8, myValue12, response12); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + + Serial.println(); + Serial.print("Flash Contents:"); + for (uint16_t x = 0; x < 8 * 4; x += 4) + { + if (x % 32 == 0) + Serial.println(); + Serial.printf("0x%08X ", *(uint32_t *)(FLASH_EEPROM_START + x)); + } + Serial.println(); +} + +void loop() +{ +} \ No newline at end of file diff --git a/libraries/SoftwareSerial/keywords.txt b/libraries/SoftwareSerial/keywords.txt new file mode 100644 index 00000000..7987e9b3 --- /dev/null +++ b/libraries/SoftwareSerial/keywords.txt @@ -0,0 +1,23 @@ +####################################### +# Syntax Coloring Map +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +EEPROM KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +read KEYWORD2 +write KEYWORD2 +get KEYWORD2 +put KEYWORD2 +update KEYWORD2 +erase KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/SoftwareSerial/library.properties b/libraries/SoftwareSerial/library.properties new file mode 100644 index 00000000..3559ba4d --- /dev/null +++ b/libraries/SoftwareSerial/library.properties @@ -0,0 +1,9 @@ +name=EEPROM +version=1.0 +author=SparkFun Electronics +maintainer=SparkFun Electronics +sentence=Flash based Pseudo EEPROM for Artemis +paragraph=Enables the writing of variables to a protected section of flash. These bytes will not be overwritten when new sketches are loaded and are useful when needing to record settings like calibration data or GPS waypoints that should not change between sketch updates. +category=Communication +url=http://www.arduino.cc/en/Reference/EEPROM +architectures=apollo3 diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp new file mode 100644 index 00000000..0532f539 --- /dev/null +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -0,0 +1,299 @@ +/* + This is a library written for the SparkFun Artemis + + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support open source hardware. Buy a board! + https://www.sparkfun.com/products/15332 + https://www.sparkfun.com/products/15376 + https://www.sparkfun.com/products/15411 + https://www.sparkfun.com/products/15412 + + Written by Nathan Seidle @ SparkFun Electronics, August 12th, 2019 + + https://github.com/sparkfun/SparkFun_Apollo3 + + SoftwareSerial support for the Artemis + Any pin can be used for software serial receive or transmit + at 300 to 115200bps and anywhere inbetween. + Limitations: + Uses Timer/Compare module H. This will remove PWM capabilities + on some pins. + Parity is supported but not checked during RX. + + Development environment specifics: + Arduino IDE 1.8.x + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "SoftwareSerial.h" +#include "Arduino.h" + +//Constructor +SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin) +{ + _rxPin = rxPin; + _txPin = txPin; + + _txPad = ap3_gpio_pin2pad(_txPin); + _rxPad = ap3_gpio_pin2pad(_rxPin); +} + +void SoftwareSerial::begin(uint32_t baudRate) +{ + begin(baudRate, SERIAL_8N1); +} + +void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) +{ + pinMode(_txPin, OUTPUT); + pinMode(_rxPin, INPUT_PULLUP); + + am_hal_gpio_output_set(_txPad); + + // Enable C/T H=7 + am_hal_stimer_int_enable(AM_HAL_STIMER_INT_COMPAREH); + + // Don't change from 3MHz system timer, but enable H timer + am_hal_stimer_config(AM_HAL_STIMER_CFG_CLEAR | AM_HAL_STIMER_CFG_FREEZE); + am_hal_stimer_config(AM_HAL_STIMER_HFRC_3MHZ | AM_HAL_STIMER_CFG_COMPARE_H_ENABLE); + + //Set variables data bits, stop bits and parity based on config + softwareserialSetConfig(SSconfig); + + sysTicksPerBit = (TIMER_FREQ / baudRate) * 0.98; //Short the number of sysTicks a small amount because we are doing a mod operation + + sysTicksPerByte = (TIMER_FREQ / baudRate) * (_dataBits + _parityBits + _stopBits); + + //During RX, if leftover systicks is more than a fraction of a bit, we will call it a bit + //This is needed during 115200 when cmpr ISR extends into the start bit of the following byte + sysTicksPartialBit = sysTicksPerBit / 4; + + //Clear pin change interrupt + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(_rxPad)); + + //Clear compare interrupt + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); + + attachInterrupt(digitalPinToInterrupt(_rxPin), rxBit, CHANGE); + //attachInterruptArg(digitalPinToInterrupt(_rxPin), rxBit, (void *)this, CHANGE); +} + +ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) +{ + ap3_err_t retval = AP3_OK; + switch (SSconfig) + { + case SERIAL_5N1: + _dataBits = 5; + _parity = 0; + _stopBits = 1; + break; + case SERIAL_6N1: + _dataBits = 6; + _parity = 0; + _stopBits = 1; + break; + case SERIAL_7N1: + _dataBits = 7; + _parity = 0; + _stopBits = 1; + break; + case SERIAL_8N1: + _dataBits = 8; + _parity = 0; + _stopBits = 1; + break; + case SERIAL_5N2: + _dataBits = 5; + _parity = 0; + _stopBits = 2; + break; + case SERIAL_6N2: + _dataBits = 6; + _parity = 0; + _stopBits = 2; + break; + case SERIAL_7N2: + _dataBits = 7; + _parity = 0; + _stopBits = 2; + break; + case SERIAL_8N2: + _dataBits = 8; + _parity = 0; + _stopBits = 2; + break; + case SERIAL_5E1: + _dataBits = 5; + _parity = 2; + _stopBits = 1; + break; + case SERIAL_6E1: + _dataBits = 6; + _parity = 2; + _stopBits = 1; + break; + case SERIAL_7E1: + _dataBits = 7; + _parity = 2; + _stopBits = 1; + break; + case SERIAL_8E1: + _dataBits = 8; + _parity = 2; + _stopBits = 1; + break; + case SERIAL_5E2: + _dataBits = 5; + _parity = 2; + _stopBits = 2; + break; + case SERIAL_6E2: + _dataBits = 6; + _parity = 2; + _stopBits = 2; + break; + case SERIAL_7E2: + _dataBits = 7; + _parity = 2; + _stopBits = 2; + break; + case SERIAL_8E2: + _dataBits = 8; + _parity = 2; + _stopBits = 2; + break; + case SERIAL_5O1: + _dataBits = 5; + _parity = 1; + _stopBits = 1; + break; + case SERIAL_6O1: + _dataBits = 6; + _parity = 1; + _stopBits = 1; + break; + case SERIAL_7O1: + _dataBits = 7; + _parity = 1; + _stopBits = 1; + break; + case SERIAL_8O1: + _dataBits = 8; + _parity = 1; + _stopBits = 1; + break; + case SERIAL_5O2: + _dataBits = 5; + _parity = 1; + _stopBits = 2; + break; + case SERIAL_6O2: + _dataBits = 6; + _parity = 1; + _stopBits = 2; + break; + case SERIAL_7O2: + _dataBits = 7; + _parity = 1; + _stopBits = 2; + break; + case SERIAL_8O2: + _dataBits = 8; + _parity = 1; + _stopBits = 2; + break; + default: + retval = AP3_INVALID_ARG; + break; + } + + _parityBits = 0; + if (_parity) + _parityBits = 1; + + return retval; +} + +//ISR that is called each bit transition on RX pin +void SoftwareSerial::rxBit(void) +{ + uint32_t bitTime = CTIMER->STTMR; //Capture current system time + +#ifdef DEBUG + am_hal_gpio_output_set(triggerPad); +#endif + + if (lastBitTime == 0) + { + bitCounter = 0; + lastBitTime = bitTime; + bitType = false; + + //Setup cmpr7 interrupt to handle overall timeout + //am_hal_stimer_compare_delta_set(7, sysTicksPerByte); + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = sysTicksPerByte; //Direct reg write to decrease execution time + + // Enable the timer interrupt in the NVIC. + NVIC_EnableIRQ(STIMER_CMPR7_IRQn); + } + else + { + //Calculate the number of bits that have occured since last PCI + //Then add those bits of the current bitType (either 1 or 0) to + //the byte + uint8_t numberOfBits = (bitTime - lastBitTime) / sysTicksPerBit; + + if (bitCounter == 0) + { + //Catch any partial bits + //For very high bauds (115200) the final interrupt spills over into the + //start bit of the next byte. This catches the partial systicks and correctly + //identifies the start bit as such. + uint16_t partialBits = (bitTime - lastBitTime) % sysTicksPerBit; + if (partialBits > sysTicksPartialBit) + { +#ifdef DEBUG + Serial.println("Partial!"); +#endif + numberOfBits++; + } + + //Exclude start bit from byte shift + bitCounter++; + numberOfBits--; + } + + if (_parity) + { + if (numberOfBits + bitCounter > _dataBits + _parityBits) + { +#ifdef DEBUG + Serial.println("Exclude"); +#endif + numberOfBits--; //Exclude parity bit from byte shift + } + } + + for (uint8_t y = 0; y < numberOfBits; y++) //Number of bits in this chunk of time + { + incomingByte >>= 1; + if (bitType == true) + incomingByte |= 0x80; + } + bitCounter += numberOfBits; + bitType = !bitType; //Next bit will be inverse of this bit + lastBitTime = bitTime; //Remember this bit time as the starting time for the next PCI + } + +#ifdef DEBUG + am_hal_gpio_output_clear(triggerPad); +#endif +} diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h new file mode 100644 index 00000000..08dd450d --- /dev/null +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -0,0 +1,94 @@ +/* + This is a library written for the SparkFun Artemis + + SparkFun sells these at its website: www.sparkfun.com + Do you like this library? Help support open source hardware. Buy a board! + https://www.sparkfun.com/products/15332 + https://www.sparkfun.com/products/15376 + https://www.sparkfun.com/products/15411 + https://www.sparkfun.com/products/15412 + + Written by Nathan Seidle @ SparkFun Electronics, August 12th, 2019 + + https://github.com/sparkfun/SparkFun_Apollo3 + + SoftwareSerial support for the Artemis + Any pin can be used for software serial receive or transmit + at 300 to 115200bps and anywhere inbetween. + Limitations: + Uses Timer/Compare module H. This will remove PWM capabilities + on some pins. + Parity is supported but not checked during RX. + + Development environment specifics: + Arduino IDE 1.8.x + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _SoftwareSerial_H +#define _SoftwareSerial_H +#include "Arduino.h" + +#define AP3_SS_BUFFER_SIZE 128 //Limit to 8 bits + +#define TIMER_FREQ 3000000L + +class SoftwareSerial +{ +public: + SoftwareSerial(uint8_t rxPin, uint8_t txPin); + + void begin(uint32_t baudRate); + void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); + + ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); + + void rxBit(void); + +private: + void startRXListening(void); + + uint8_t txBuffer[AP3_SS_BUFFER_SIZE]; + uint16_t txBufferHead = 0; + volatile uint16_t txBufferTail = 0; + volatile bool txInUse = false; + volatile uint8_t outgoingByte = 0; + + volatile uint8_t rxBuffer[AP3_SS_BUFFER_SIZE]; + volatile uint8_t rxBufferHead = 0; + uint8_t rxBufferTail = 0; + volatile bool rxInUse = false; + volatile uint8_t incomingByte = 0; + + uint8_t _rxPin; + uint8_t _txPin; + + ap3_gpio_pad_t _txPad; + ap3_gpio_pad_t _rxPad; + + uint8_t _dataBits = 0; //5, 6, 7, or 8 + uint8_t _parity = 0; //Type of parity (0, 1, 2) + uint8_t _stopBits = 0; + + //For RX + uint8_t _parityBits = 0; //Number of parity bits (0 or 1) + uint16_t sysTicksPerBit = 0; + uint32_t sysTicksPerByte = 0; + uint16_t sysTicksPartialBit = 0; + volatile uint8_t numberOfBits[10]; + volatile uint8_t bitCounter; + volatile uint32_t lastBitTime = 0; + volatile bool bitType = false; + + //For TX + uint8_t _parityForByte = 0; //Calculated per byte +}; + +#endif From 1d58ae1497ca23d3e9b7239a12b31c825ef6aeac Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 15:48:48 -0600 Subject: [PATCH 03/20] Update example 1 --- .../examples/Apollo_EEPROM/Apollo_EEPROM.ino | 167 ------------------ .../Apollo_SoftwareSerial_Example1.ino | 49 +++++ 2 files changed, 49 insertions(+), 167 deletions(-) delete mode 100644 libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino create mode 100644 libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino diff --git a/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino b/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino deleted file mode 100644 index a1418ed4..00000000 --- a/libraries/SoftwareSerial/examples/Apollo_EEPROM/Apollo_EEPROM.ino +++ /dev/null @@ -1,167 +0,0 @@ -/* - Reading and writing test of the EEPROM functions on the Artemis - By: Nathan Seidle - SparkFun Electronics - Date: June 24th, 2019 - This example code is in the public domain. - - SparkFun labored with love to create this code. Feel like supporting open source hardware? - Buy a board from SparkFun! https://www.sparkfun.com/products/15376 - - Page erase takes 15ms - Write byte takes 30ms - This is much longer than Arduino that takes 3.3ms - Float write across two words takes 30ms - Update (no write) takes 1ms -*/ - -#include - -void setup() -{ - Serial.begin(9600); - Serial.println("EEPROM Examples"); - - randomSeed(analogRead(A0)); - - long startTime; - long endTime; - uint16_t randomLocation; - - //Test erase time - startTime = millis(); - EEPROM.erase(); - endTime = millis(); - Serial.printf("Time to erase all EEPROM: %dms\n", endTime - startTime); - - //Byte sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.println(""); - Serial.println("8 bit tests"); - byte myValue1 = 200; - byte myValue2 = 23; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - startTime = millis(); - EEPROM.write(randomLocation, myValue1); //(location, data) - endTime = millis(); - EEPROM.put(randomLocation + 1, myValue2); - - Serial.printf("Write byte time: %dms\n", endTime - startTime); - - byte response1 = EEPROM.read(randomLocation); - byte response2 = EEPROM.read(randomLocation + 1); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue1, response1); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 1, myValue2, response2); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("16 bit tests"); - - //int16_t and uint16_t sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - uint16_t myValue3 = 3411; - int16_t myValue4 = -366; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - EEPROM.put(randomLocation, myValue3); - EEPROM.put(randomLocation + 2, myValue4); - - uint16_t response3; - int16_t response4; - EEPROM.get(randomLocation, response3); - EEPROM.get(randomLocation + 2, response4); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue3, response3); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 2, myValue4, response4); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("32 bit tests"); - - //int and unsigned int (32) sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.printf("Size of int: %d\n", sizeof(int)); - int myValue5 = -245000; - unsigned int myValue6 = 400123; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - EEPROM.put(randomLocation, myValue5); - EEPROM.put(randomLocation + 4, myValue6); - - int response5; - unsigned int response6; - EEPROM.get(randomLocation, response5); - EEPROM.get(randomLocation + 4, response6); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue5, response5); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue6, response6); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //int32_t and uint32_t sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - int32_t myValue7 = -341002; - uint32_t myValue8 = 241544; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - EEPROM.update(randomLocation, myValue7); - EEPROM.update(randomLocation + 4, myValue8); - - int32_t response7; - uint32_t response8; - EEPROM.get(randomLocation, response7); - EEPROM.get(randomLocation + 4, response8); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation, myValue7, response7); - Serial.printf("Location %d should be %d: %d\n\r", randomLocation + 4, myValue8, response8); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - //float (32) sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.printf("Size of float: %d\n", sizeof(float)); - float myValue9 = -7.35; - float myValue10 = 5.22; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - EEPROM.update(randomLocation, myValue9); - EEPROM.update(randomLocation + 4, myValue10); - - float response9; - float response10; - EEPROM.get(randomLocation, response9); - EEPROM.get(randomLocation + 4, response10); - Serial.printf("Location %d should be %f: %f\n\r", randomLocation, myValue9, response9); - Serial.printf("Location %d should be %f: %f\n\r", randomLocation + 4, myValue10, response10); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(""); - Serial.println("64 bit tests"); - - //double (64) sequential test - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - Serial.printf("Size of double: %d\n", sizeof(double)); - double myValue11 = -290.3485723409857; - double myValue12 = 384.95734987; - randomLocation = random(0, FLASH_EEPROM_SIZE); - - EEPROM.update(randomLocation, myValue11); - EEPROM.update(randomLocation + 8, myValue12); - - double response11; - double response12; - EEPROM.get(randomLocation, response11); - EEPROM.get(randomLocation + 8, response12); - Serial.printf("Location %d should be %lf: %lf\n", randomLocation, myValue11, response11); - Serial.printf("Location %d should be %lf: %lf\n", randomLocation + 8, myValue12, response12); - //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - Serial.println(); - Serial.print("Flash Contents:"); - for (uint16_t x = 0; x < 8 * 4; x += 4) - { - if (x % 32 == 0) - Serial.println(); - Serial.printf("0x%08X ", *(uint32_t *)(FLASH_EEPROM_START + x)); - } - Serial.println(); -} - -void loop() -{ -} \ No newline at end of file diff --git a/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino b/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino new file mode 100644 index 00000000..9316f559 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino @@ -0,0 +1,49 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to receive characters at 9600bps. Any pin can be used for + reception. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 9600 + Open Terminal window (TeraTerm) at 9600 + Press a button in terminal window, you should see it in Arduino monitor +*/ + + +//#define DEBUG +#define LED 13 + +#include +SoftwareSerial mySerial(7, 8); //RX, TX + +void setup() { + Serial.begin(9600); + Serial.println("Software Serial Example"); + + //enableBurstMode(); //Go to 96MHz + + mySerial.begin(9600); //SERIAL_8N1); +} + +void loop() { + digitalWrite(LED, HIGH); + //delay(100); + digitalWrite(LED, LOW); + //delay(100); + + delay(1); + + +} From f3b8bc45c9b7eba7913f92e1a321b2d2666fb42c Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Mon, 12 Aug 2019 16:29:35 -0600 Subject: [PATCH 04/20] Add ISR for software serial --- cores/arduino/ard_sup/gpio/ap3_gpio.cpp | 4 -- .../SoftwareSerial/src/SoftwareSerial.cpp | 55 ++++++++++++++++++- libraries/SoftwareSerial/src/SoftwareSerial.h | 5 ++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/cores/arduino/ard_sup/gpio/ap3_gpio.cpp b/cores/arduino/ard_sup/gpio/ap3_gpio.cpp index 3829b280..0dcc9c43 100644 --- a/cores/arduino/ard_sup/gpio/ap3_gpio.cpp +++ b/cores/arduino/ard_sup/gpio/ap3_gpio.cpp @@ -133,10 +133,6 @@ extern "C" void am_gpio_isr(void) uint64_t gpio_int_mask = 0x00; am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); - if (gpio_int_mask & softwareserial_pin_mask) - { - } - for (uint8_t indi = 0; indi < gpio_num_isr; indi++) { if (gpio_isr_entries[indi].callback != NULL) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 0532f539..0cc0cc6b 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -35,14 +35,66 @@ #include "SoftwareSerial.h" #include "Arduino.h" +// Global Table of SoftwareSerial Pointers +SoftwareSerial* gpSoftwareSerialObjs[AP3_GPIO_MAX_PADS]; +uint8_t gSoftwareSerialNumObjs = 0; + + +// Software Serial ISR (To attach to pin change interrupts) +void _software_serial_isr( void ){ + uint64_t gpio_int_mask = 0x00; + am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); + SoftwareSerial* obj = NULL; + for(uint8_t indi = 0; indi < gSoftwareSerialNumObjs; indi++){ + obj = gpSoftwareSerialObjs[indi]; + if(obj == NULL){ + break; // there should not be any null pointers in the global object table + } + if(obj->_rxPadBitMask & gpio_int_mask){ + obj->rxBit(); + } + } +} + + //Constructor SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin) { + if( gSoftwareSerialNumObjs >= AP3_GPIO_MAX_PADS ){ + return; // Error -- no instances left to create + } + _rxPin = rxPin; _txPin = txPin; _txPad = ap3_gpio_pin2pad(_txPin); _rxPad = ap3_gpio_pin2pad(_rxPin); + + _rxPadBitMask = ( 0x01 << _rxPad ); + + // Add to the global array + _indexNumber = gSoftwareSerialNumObjs; + gpSoftwareSerialObjs[_indexNumber] = this; + gSoftwareSerialNumObjs++; +} + +// Destructor +SoftwareSerial::~SoftwareSerial() +{ + if( gSoftwareSerialNumObjs < 1 ){ + return; // error -- no instances left to destroy + } + + // Remove from global pointer list by filtering others down: + uint8_t index = _indexNumber; + do{ + gpSoftwareSerialObjs[index] = NULL; + if( index < (gSoftwareSerialNumObjs-1) ){ + gpSoftwareSerialObjs[index] = gpSoftwareSerialObjs[index+1]; + } + index++; + }while( index < gSoftwareSerialNumObjs ); + gSoftwareSerialNumObjs--; } void SoftwareSerial::begin(uint32_t baudRate) @@ -81,8 +133,7 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) //Clear compare interrupt am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - attachInterrupt(digitalPinToInterrupt(_rxPin), rxBit, CHANGE); - //attachInterruptArg(digitalPinToInterrupt(_rxPin), rxBit, (void *)this, CHANGE); + attachInterrupt(digitalPinToInterrupt(_rxPin), _software_serial_isr, CHANGE); } ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 08dd450d..673c686d 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -44,6 +44,7 @@ class SoftwareSerial { public: SoftwareSerial(uint8_t rxPin, uint8_t txPin); + ~SoftwareSerial(); void begin(uint32_t baudRate); void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); @@ -52,6 +53,8 @@ class SoftwareSerial void rxBit(void); + uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad + private: void startRXListening(void); @@ -70,6 +73,8 @@ class SoftwareSerial uint8_t _rxPin; uint8_t _txPin; + uint8_t _indexNumber; // The index number at which the pointer to this instance is stored in the global object table. + ap3_gpio_pad_t _txPad; ap3_gpio_pad_t _rxPad; From b9cb3b18507014b90cb282ff14484e750c4bf9ef Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 17:02:22 -0600 Subject: [PATCH 05/20] Adding compare ISR --- .../SoftwareSerial/src/SoftwareSerial.cpp | 125 +++++++++++++++--- libraries/SoftwareSerial/src/SoftwareSerial.h | 15 ++- 2 files changed, 118 insertions(+), 22 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 0cc0cc6b..f07f52be 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -36,31 +36,34 @@ #include "Arduino.h" // Global Table of SoftwareSerial Pointers -SoftwareSerial* gpSoftwareSerialObjs[AP3_GPIO_MAX_PADS]; +SoftwareSerial *gpSoftwareSerialObjs[AP3_GPIO_MAX_PADS]; uint8_t gSoftwareSerialNumObjs = 0; - // Software Serial ISR (To attach to pin change interrupts) -void _software_serial_isr( void ){ +void _software_serial_isr(void) +{ uint64_t gpio_int_mask = 0x00; am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); - SoftwareSerial* obj = NULL; - for(uint8_t indi = 0; indi < gSoftwareSerialNumObjs; indi++){ + SoftwareSerial *obj = NULL; + for (uint8_t indi = 0; indi < gSoftwareSerialNumObjs; indi++) + { obj = gpSoftwareSerialObjs[indi]; - if(obj == NULL){ + if (obj == NULL) + { break; // there should not be any null pointers in the global object table } - if(obj->_rxPadBitMask & gpio_int_mask){ + if (obj->_rxPadBitMask & gpio_int_mask) + { obj->rxBit(); } } } - //Constructor -SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin) +SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic) { - if( gSoftwareSerialNumObjs >= AP3_GPIO_MAX_PADS ){ + if (gSoftwareSerialNumObjs >= AP3_GPIO_MAX_PADS) + { return; // Error -- no instances left to create } @@ -70,7 +73,9 @@ SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin) _txPad = ap3_gpio_pin2pad(_txPin); _rxPad = ap3_gpio_pin2pad(_rxPin); - _rxPadBitMask = ( 0x01 << _rxPad ); + _invertLogic = invertLogic; + + _rxPadBitMask = (0x01 << _rxPad); // Add to the global array _indexNumber = gSoftwareSerialNumObjs; @@ -81,19 +86,22 @@ SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin) // Destructor SoftwareSerial::~SoftwareSerial() { - if( gSoftwareSerialNumObjs < 1 ){ + if (gSoftwareSerialNumObjs < 1) + { return; // error -- no instances left to destroy } // Remove from global pointer list by filtering others down: uint8_t index = _indexNumber; - do{ + do + { gpSoftwareSerialObjs[index] = NULL; - if( index < (gSoftwareSerialNumObjs-1) ){ - gpSoftwareSerialObjs[index] = gpSoftwareSerialObjs[index+1]; + if (index < (gSoftwareSerialNumObjs - 1)) + { + gpSoftwareSerialObjs[index] = gpSoftwareSerialObjs[index + 1]; } index++; - }while( index < gSoftwareSerialNumObjs ); + } while (index < gSoftwareSerialNumObjs); gSoftwareSerialNumObjs--; } @@ -348,3 +356,88 @@ void SoftwareSerial::rxBit(void) am_hal_gpio_output_clear(triggerPad); #endif } + +void SoftwareSerial::endOfByte() +{ + //Finish out bytes that are less than 8 bits +#ifdef DEBUG + Serial.printf("bitCounter: %d\n", bitCounter); + Serial.printf("incoming: 0x%02X\n", incomingByte); +#endif + bitCounter--; //Remove start bit from count + + //Edge case where we need to do an additional byte shift because we had data bits followed by a parity bit of same value + if (_parity) + { + bitCounter = bitCounter - _parityBits; //Remove parity bit from count + if (bitType == true) + bitCounter++; + } + +#ifdef DEBUG + Serial.printf("bitCounter: %d\n", bitCounter); +#endif + + while (bitCounter < 8) + { + incomingByte >>= 1; + if (bitType == true) + if (bitCounter < _dataBits) + { +#ifdef DEBUG + Serial.println("Add bit"); +#endif + incomingByte |= 0x80; + } + bitCounter++; + } + + //TODO - Check parity bit if parity is enabled + + if (_invertLogic) + incomingByte = ~incomingByte; + + //See if we are going to overflow buffer + uint8_t nextSpot = (rxBufferHead + 1) % AP3_SS_BUFFER_SIZE; + if (nextSpot != rxBufferTail) + { + //Add this byte to the buffer + rxBuffer[nextSpot] = incomingByte; + rxBufferHead = nextSpot; + } + else + { +#ifdef DEBUG + am_hal_gpio_output_set(triggerPad); + am_hal_gpio_output_clear(triggerPad); +#endif + _rxBufferOverflow = true; + } + + lastBitTime = 0; //Reset for next byte + + rxInUse = false; + + // Disable the timer interrupt in the NVIC. + NVIC_DisableIRQ(STIMER_CMPR7_IRQn); +} + +//Called at the completion of bytes +extern "C" void am_stimer_cmpr7_isr(void) +{ +#ifdef DEBUG + am_hal_gpio_output_set(triggerPad); +#endif + + uint32_t ui32Status = am_hal_stimer_int_status_get(false); + if (ui32Status & AM_HAL_STIMER_INT_COMPAREH) + { + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); + + //this->endOfByte(); + } + +#ifdef DEBUG + am_hal_gpio_output_clear(triggerPad); +#endif +} \ No newline at end of file diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 673c686d..8934da11 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -43,7 +43,7 @@ class SoftwareSerial { public: - SoftwareSerial(uint8_t rxPin, uint8_t txPin); + SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic = false); ~SoftwareSerial(); void begin(uint32_t baudRate); @@ -52,8 +52,9 @@ class SoftwareSerial ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); void rxBit(void); + void endOfByte(void); - uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad + uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad private: void startRXListening(void); @@ -67,13 +68,12 @@ class SoftwareSerial volatile uint8_t rxBuffer[AP3_SS_BUFFER_SIZE]; volatile uint8_t rxBufferHead = 0; uint8_t rxBufferTail = 0; - volatile bool rxInUse = false; volatile uint8_t incomingByte = 0; uint8_t _rxPin; uint8_t _txPin; - uint8_t _indexNumber; // The index number at which the pointer to this instance is stored in the global object table. + uint8_t _indexNumber; // The index number at which the pointer to this instance is stored in the global object table. ap3_gpio_pad_t _txPad; ap3_gpio_pad_t _rxPad; @@ -81,16 +81,19 @@ class SoftwareSerial uint8_t _dataBits = 0; //5, 6, 7, or 8 uint8_t _parity = 0; //Type of parity (0, 1, 2) uint8_t _stopBits = 0; + uint8_t _parityBits = 0; //Number of parity bits (0 or 1) + bool _invertLogic; //For RX - uint8_t _parityBits = 0; //Number of parity bits (0 or 1) uint16_t sysTicksPerBit = 0; uint32_t sysTicksPerByte = 0; uint16_t sysTicksPartialBit = 0; volatile uint8_t numberOfBits[10]; - volatile uint8_t bitCounter; volatile uint32_t lastBitTime = 0; + volatile uint8_t bitCounter; volatile bool bitType = false; + volatile bool rxInUse = false; + bool _rxBufferOverflow = false; //For TX uint8_t _parityForByte = 0; //Calculated per byte From 8845b27783b28f86369beacb6f0ed38da7c89279 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 17:06:25 -0600 Subject: [PATCH 06/20] Add invertlogic support --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index f07f52be..7108a555 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -113,9 +113,11 @@ void SoftwareSerial::begin(uint32_t baudRate) void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) { pinMode(_txPin, OUTPUT); - pinMode(_rxPin, INPUT_PULLUP); + digitalWrite(_txPin, _invertLogic ? LOW : HIGH); - am_hal_gpio_output_set(_txPad); + pinMode(_rxPin, INPUT); + if (_invertLogic == false) + pinMode(_rxPin, INPUT_PULLUP); //Enable external pullup if using normal logic // Enable C/T H=7 am_hal_stimer_int_enable(AM_HAL_STIMER_INT_COMPAREH); From 67151fc882deecfd4ae208e7b94739b82a1a363a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 17:10:36 -0600 Subject: [PATCH 07/20] Create instance handle to call correct cmpr7 ISR --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 7108a555..64482445 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -39,6 +39,8 @@ SoftwareSerial *gpSoftwareSerialObjs[AP3_GPIO_MAX_PADS]; uint8_t gSoftwareSerialNumObjs = 0; +SoftwareSerial *ap3_serial_handle = 0; + // Software Serial ISR (To attach to pin change interrupts) void _software_serial_isr(void) { @@ -143,6 +145,9 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) //Clear compare interrupt am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); + // Register the class into the local list + ap3_serial_handle = this; + attachInterrupt(digitalPinToInterrupt(_rxPin), _software_serial_isr, CHANGE); } @@ -436,7 +441,7 @@ extern "C" void am_stimer_cmpr7_isr(void) { am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - //this->endOfByte(); + ap3_serial_handle->endOfByte(); } #ifdef DEBUG From a5897b23c2bc8491c38618e41162d2ba04cc6173 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 20:41:31 -0600 Subject: [PATCH 08/20] Rough in of interrupt pointer. Add available() and read() and debug. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 40 +++++++++++++++---- libraries/SoftwareSerial/src/SoftwareSerial.h | 4 +- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 64482445..38fcacf6 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -41,8 +41,16 @@ uint8_t gSoftwareSerialNumObjs = 0; SoftwareSerial *ap3_serial_handle = 0; +//Uncomment to enable debug pulses and Serial.prints +#define DEBUG + +#ifdef DEBUG +#define SS_DEBUG_PIN 8 +ap3_gpio_pad_t debugPad = ap3_gpio_pin2pad(SS_DEBUG_PIN); +#endif + // Software Serial ISR (To attach to pin change interrupts) -void _software_serial_isr(void) +/*void _software_serial_isr(void) { uint64_t gpio_int_mask = 0x00; am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); @@ -59,6 +67,10 @@ void _software_serial_isr(void) obj->rxBit(); } } +}*/ +inline void _software_serial_isr(void) +{ + ap3_serial_handle->rxBit(); } //Constructor @@ -151,6 +163,20 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) attachInterrupt(digitalPinToInterrupt(_rxPin), _software_serial_isr, CHANGE); } +int SoftwareSerial::available() +{ + return (rxBufferHead + AP3_SS_BUFFER_SIZE - rxBufferTail) % AP3_SS_BUFFER_SIZE; +} + +uint8_t SoftwareSerial::read() +{ + if (available() == 0) return (-1); + + rxBufferTail++; + rxBufferTail %= AP3_SS_BUFFER_SIZE; + return (rxBuffer[rxBufferTail]); +} + ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) { ap3_err_t retval = AP3_OK; @@ -294,7 +320,7 @@ void SoftwareSerial::rxBit(void) uint32_t bitTime = CTIMER->STTMR; //Capture current system time #ifdef DEBUG - am_hal_gpio_output_set(triggerPad); + am_hal_gpio_output_set(debugPad); #endif if (lastBitTime == 0) @@ -360,7 +386,7 @@ void SoftwareSerial::rxBit(void) } #ifdef DEBUG - am_hal_gpio_output_clear(triggerPad); + am_hal_gpio_output_clear(debugPad); #endif } @@ -415,8 +441,8 @@ void SoftwareSerial::endOfByte() else { #ifdef DEBUG - am_hal_gpio_output_set(triggerPad); - am_hal_gpio_output_clear(triggerPad); + am_hal_gpio_output_set(debugPad); + am_hal_gpio_output_clear(debugPad); #endif _rxBufferOverflow = true; } @@ -433,7 +459,7 @@ void SoftwareSerial::endOfByte() extern "C" void am_stimer_cmpr7_isr(void) { #ifdef DEBUG - am_hal_gpio_output_set(triggerPad); + am_hal_gpio_output_set(debugPad); #endif uint32_t ui32Status = am_hal_stimer_int_status_get(false); @@ -445,6 +471,6 @@ extern "C" void am_stimer_cmpr7_isr(void) } #ifdef DEBUG - am_hal_gpio_output_clear(triggerPad); + am_hal_gpio_output_clear(debugPad); #endif } \ No newline at end of file diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 8934da11..ce95ad8c 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -50,11 +50,13 @@ class SoftwareSerial void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); + int available(); + uint8_t read(); void rxBit(void); void endOfByte(void); - uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad + uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad private: void startRXListening(void); From 15571ad72bbc9f5890474b280313d8c4a96b49dd Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Mon, 12 Aug 2019 21:12:05 -0600 Subject: [PATCH 09/20] Add peek and overflow --- .../SoftwareSerial/src/SoftwareSerial.cpp | 26 +++++++++++++++++-- libraries/SoftwareSerial/src/SoftwareSerial.h | 5 +++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 38fcacf6..65c2875c 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -42,7 +42,7 @@ uint8_t gSoftwareSerialNumObjs = 0; SoftwareSerial *ap3_serial_handle = 0; //Uncomment to enable debug pulses and Serial.prints -#define DEBUG +//#define DEBUG #ifdef DEBUG #define SS_DEBUG_PIN 8 @@ -168,7 +168,7 @@ int SoftwareSerial::available() return (rxBufferHead + AP3_SS_BUFFER_SIZE - rxBufferTail) % AP3_SS_BUFFER_SIZE; } -uint8_t SoftwareSerial::read() +int SoftwareSerial::read() { if (available() == 0) return (-1); @@ -177,6 +177,28 @@ uint8_t SoftwareSerial::read() return (rxBuffer[rxBufferTail]); } +int SoftwareSerial::peek() +{ + if (available() == 0) return (-1); + + uint8_t tempTail = rxBufferTail + 1; + tempTail %= AP3_SS_BUFFER_SIZE; + return (rxBuffer[tempTail]); +} + +//Returns true if overflow flag is set +//Clears flag when called +bool SoftwareSerial::overflow() +{ + if (_rxBufferOverflow) + { + _rxBufferOverflow = false; + return (true); + } + return (false); + +} + ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) { ap3_err_t retval = AP3_OK; diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index ce95ad8c..87d8791e 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -51,7 +51,10 @@ class SoftwareSerial ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); int available(); - uint8_t read(); + int read(); + int peek(); + bool overflow(); + void rxBit(void); void endOfByte(void); From c83d88ab340372577adc1861b12f8f0c4164ead1 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Tue, 13 Aug 2019 09:17:14 -0600 Subject: [PATCH 10/20] Use 'attachInterruptArg()' for RX interrupts with 'this' argument This allows us to dispose of the ugly global table of pointers to software serial objects. Instead those pointers are all handled in the GPIO core. We will need to make sure to detach the interrupt (and thereby remove reference to the software serial object) when the object is destroyed. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 65 ++----------------- libraries/SoftwareSerial/src/SoftwareSerial.h | 2 - 2 files changed, 7 insertions(+), 60 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 65c2875c..8ac1c42b 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -35,10 +35,6 @@ #include "SoftwareSerial.h" #include "Arduino.h" -// Global Table of SoftwareSerial Pointers -SoftwareSerial *gpSoftwareSerialObjs[AP3_GPIO_MAX_PADS]; -uint8_t gSoftwareSerialNumObjs = 0; - SoftwareSerial *ap3_serial_handle = 0; //Uncomment to enable debug pulses and Serial.prints @@ -49,38 +45,15 @@ SoftwareSerial *ap3_serial_handle = 0; ap3_gpio_pad_t debugPad = ap3_gpio_pin2pad(SS_DEBUG_PIN); #endif -// Software Serial ISR (To attach to pin change interrupts) -/*void _software_serial_isr(void) -{ - uint64_t gpio_int_mask = 0x00; - am_hal_gpio_interrupt_status_get(true, &gpio_int_mask); - SoftwareSerial *obj = NULL; - for (uint8_t indi = 0; indi < gSoftwareSerialNumObjs; indi++) - { - obj = gpSoftwareSerialObjs[indi]; - if (obj == NULL) - { - break; // there should not be any null pointers in the global object table - } - if (obj->_rxPadBitMask & gpio_int_mask) - { - obj->rxBit(); - } - } -}*/ -inline void _software_serial_isr(void) +inline void _software_serial_isr(void* arg) { - ap3_serial_handle->rxBit(); + SoftwareSerial* handle = (SoftwareSerial*)arg; + handle->rxBit(); } //Constructor SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic) { - if (gSoftwareSerialNumObjs >= AP3_GPIO_MAX_PADS) - { - return; // Error -- no instances left to create - } - _rxPin = rxPin; _txPin = txPin; @@ -88,35 +61,13 @@ SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic) _rxPad = ap3_gpio_pin2pad(_rxPin); _invertLogic = invertLogic; - - _rxPadBitMask = (0x01 << _rxPad); - - // Add to the global array - _indexNumber = gSoftwareSerialNumObjs; - gpSoftwareSerialObjs[_indexNumber] = this; - gSoftwareSerialNumObjs++; } // Destructor SoftwareSerial::~SoftwareSerial() { - if (gSoftwareSerialNumObjs < 1) - { - return; // error -- no instances left to destroy - } - - // Remove from global pointer list by filtering others down: - uint8_t index = _indexNumber; - do - { - gpSoftwareSerialObjs[index] = NULL; - if (index < (gSoftwareSerialNumObjs - 1)) - { - gpSoftwareSerialObjs[index] = gpSoftwareSerialObjs[index + 1]; - } - index++; - } while (index < gSoftwareSerialNumObjs); - gSoftwareSerialNumObjs--; + // Todo: call an "end" function that will detach the interrupt before removing the object + // (otherwise rx interrupts will try to access an invalid object) } void SoftwareSerial::begin(uint32_t baudRate) @@ -157,10 +108,8 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) //Clear compare interrupt am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - // Register the class into the local list - ap3_serial_handle = this; - - attachInterrupt(digitalPinToInterrupt(_rxPin), _software_serial_isr, CHANGE); + // Attach argument interrupt with 'this' as argument + attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void*)this, CHANGE); } int SoftwareSerial::available() diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 87d8791e..46130321 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -59,8 +59,6 @@ class SoftwareSerial void rxBit(void); void endOfByte(void); - uint64_t _rxPadBitMask; // The AM HAL style pad bit mask associated with the RX pad - private: void startRXListening(void); From 82920c0e6df0872ab407ddd3f644b597a5eb5115 Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Tue, 13 Aug 2019 09:20:20 -0600 Subject: [PATCH 11/20] Temporary support cor cmpr7 isr This makes it so that only one software serial object can work at any give time, right? How can we handle multiple objects at once? --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 8ac1c42b..b84ae91e 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -110,6 +110,9 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) // Attach argument interrupt with 'this' as argument attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void*)this, CHANGE); + + // temporary: + ap3_serial_handle = this; // right now this is needed for the cmpr7 isr. } int SoftwareSerial::available() From 274dde67c13848a6403abc0f21f2ca8698d9658c Mon Sep 17 00:00:00 2001 From: Owen L - SFE Date: Tue, 13 Aug 2019 09:24:25 -0600 Subject: [PATCH 12/20] Add end() method --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 8 ++++++-- libraries/SoftwareSerial/src/SoftwareSerial.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index b84ae91e..73e30f60 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -66,8 +66,7 @@ SoftwareSerial::SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic) // Destructor SoftwareSerial::~SoftwareSerial() { - // Todo: call an "end" function that will detach the interrupt before removing the object - // (otherwise rx interrupts will try to access an invalid object) + end(); // End detaches the interrupt which removes the reference to this object that is stored in the GPIO core } void SoftwareSerial::begin(uint32_t baudRate) @@ -115,6 +114,11 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) ap3_serial_handle = this; // right now this is needed for the cmpr7 isr. } +void SoftwareSerial::end(void){ + detachInterrupt(_rxPin); + // todo: anything else? +} + int SoftwareSerial::available() { return (rxBufferHead + AP3_SS_BUFFER_SIZE - rxBufferTail) % AP3_SS_BUFFER_SIZE; diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 46130321..dc13477e 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -48,6 +48,7 @@ class SoftwareSerial void begin(uint32_t baudRate); void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); + void end(void); ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); int available(); From e444b9a3c4409355a7245e464ab1006228487c4a Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 13 Aug 2019 16:43:44 -0600 Subject: [PATCH 13/20] Adding listen functions. Working for multiple instances. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 61 ++++++++++++++----- libraries/SoftwareSerial/src/SoftwareSerial.h | 5 +- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 73e30f60..dd7f57c8 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -35,19 +35,19 @@ #include "SoftwareSerial.h" #include "Arduino.h" -SoftwareSerial *ap3_serial_handle = 0; +SoftwareSerial *ap3_active_softwareserial_handle = 0; //Uncomment to enable debug pulses and Serial.prints -//#define DEBUG +#define DEBUG #ifdef DEBUG -#define SS_DEBUG_PIN 8 +#define SS_DEBUG_PIN 9 ap3_gpio_pad_t debugPad = ap3_gpio_pin2pad(SS_DEBUG_PIN); #endif -inline void _software_serial_isr(void* arg) +inline void _software_serial_isr(void *arg) { - SoftwareSerial* handle = (SoftwareSerial*)arg; + SoftwareSerial *handle = (SoftwareSerial *)arg; handle->rxBit(); } @@ -74,6 +74,34 @@ void SoftwareSerial::begin(uint32_t baudRate) begin(baudRate, SERIAL_8N1); } +void SoftwareSerial::listen() +{ + if (ap3_active_softwareserial_handle != NULL) + ap3_active_softwareserial_handle->stopListening(); //temp + + //change handle to point to new PCI + ap3_active_softwareserial_handle = this; + + lastBitTime = 0; //Reset for next byte + + attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void *)this, CHANGE); +} + +void SoftwareSerial::stopListening() +{ + // Disable the timer interrupt in the NVIC. + NVIC_DisableIRQ(STIMER_CMPR7_IRQn); + + detachInterrupt(_rxPin); + + ap3_active_softwareserial_handle == NULL; +} + +bool SoftwareSerial::isListening() +{ + return (this == ap3_active_softwareserial_handle); +} + void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) { pinMode(_txPin, OUTPUT); @@ -83,6 +111,10 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) if (_invertLogic == false) pinMode(_rxPin, INPUT_PULLUP); //Enable external pullup if using normal logic +#ifdef DEBUG + pinMode(SS_DEBUG_PIN, OUTPUT); +#endif + // Enable C/T H=7 am_hal_stimer_int_enable(AM_HAL_STIMER_INT_COMPAREH); @@ -107,14 +139,12 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) //Clear compare interrupt am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - // Attach argument interrupt with 'this' as argument - attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void*)this, CHANGE); - - // temporary: - ap3_serial_handle = this; // right now this is needed for the cmpr7 isr. + //Begin PCI + listen(); } -void SoftwareSerial::end(void){ +void SoftwareSerial::end(void) +{ detachInterrupt(_rxPin); // todo: anything else? } @@ -126,7 +156,8 @@ int SoftwareSerial::available() int SoftwareSerial::read() { - if (available() == 0) return (-1); + if (available() == 0) + return (-1); rxBufferTail++; rxBufferTail %= AP3_SS_BUFFER_SIZE; @@ -135,7 +166,8 @@ int SoftwareSerial::read() int SoftwareSerial::peek() { - if (available() == 0) return (-1); + if (available() == 0) + return (-1); uint8_t tempTail = rxBufferTail + 1; tempTail %= AP3_SS_BUFFER_SIZE; @@ -152,7 +184,6 @@ bool SoftwareSerial::overflow() return (true); } return (false); - } ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) @@ -445,7 +476,7 @@ extern "C" void am_stimer_cmpr7_isr(void) { am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - ap3_serial_handle->endOfByte(); + ap3_active_softwareserial_handle->endOfByte(); } #ifdef DEBUG diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index dc13477e..2a9844ce 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -46,6 +46,10 @@ class SoftwareSerial SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic = false); ~SoftwareSerial(); + void listen(); + void stopListening(); + bool isListening(); + void begin(uint32_t baudRate); void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); void end(void); @@ -56,7 +60,6 @@ class SoftwareSerial int peek(); bool overflow(); - void rxBit(void); void endOfByte(void); From 293bed92c93f68164dfc8215604a67508757c9b0 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Tue, 13 Aug 2019 17:04:57 -0600 Subject: [PATCH 14/20] Update comments --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index dd7f57c8..384994ff 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -38,7 +38,7 @@ SoftwareSerial *ap3_active_softwareserial_handle = 0; //Uncomment to enable debug pulses and Serial.prints -#define DEBUG +//#define DEBUG #ifdef DEBUG #define SS_DEBUG_PIN 9 @@ -77,13 +77,14 @@ void SoftwareSerial::begin(uint32_t baudRate) void SoftwareSerial::listen() { if (ap3_active_softwareserial_handle != NULL) - ap3_active_softwareserial_handle->stopListening(); //temp + ap3_active_softwareserial_handle->stopListening(); //Gracefully shut down previous instance - //change handle to point to new PCI + //Point to new instance's cmpr7 ISR ap3_active_softwareserial_handle = this; lastBitTime = 0; //Reset for next byte + //Attach this instance RX pin to PCI attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void *)this, CHANGE); } From ee9f2a3657b1758968e83479abe71f5f647dda90 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 14 Aug 2019 15:12:25 -0600 Subject: [PATCH 15/20] Adding in TX portion. Works well at 115200. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 224 ++++++++++++++++-- libraries/SoftwareSerial/src/SoftwareSerial.h | 21 +- 2 files changed, 222 insertions(+), 23 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 384994ff..98557cfa 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -38,7 +38,7 @@ SoftwareSerial *ap3_active_softwareserial_handle = 0; //Uncomment to enable debug pulses and Serial.prints -//#define DEBUG +#define DEBUG #ifdef DEBUG #define SS_DEBUG_PIN 9 @@ -105,14 +105,15 @@ bool SoftwareSerial::isListening() void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) { - pinMode(_txPin, OUTPUT); digitalWrite(_txPin, _invertLogic ? LOW : HIGH); + pinMode(_txPin, OUTPUT); pinMode(_rxPin, INPUT); if (_invertLogic == false) pinMode(_rxPin, INPUT_PULLUP); //Enable external pullup if using normal logic #ifdef DEBUG + am_hal_gpio_output_clear(debugPad); pinMode(SS_DEBUG_PIN, OUTPUT); #endif @@ -126,13 +127,18 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) //Set variables data bits, stop bits and parity based on config softwareserialSetConfig(SSconfig); - sysTicksPerBit = (TIMER_FREQ / baudRate) * 0.98; //Short the number of sysTicks a small amount because we are doing a mod operation + rxSysTicksPerBit = (TIMER_FREQ / baudRate) * 0.98; //Shorten the number of sysTicks a small amount because we are doing a mod operation + txSysTicksPerBit = (TIMER_FREQ / baudRate) - 6; //Shorten the txSysTicksPerBit by the number of ticks needed to run the txHandler ISR - sysTicksPerByte = (TIMER_FREQ / baudRate) * (_dataBits + _parityBits + _stopBits); + rxSysTicksPerByte = (TIMER_FREQ / baudRate) * (_dataBits + _parityBits + _stopBits); //During RX, if leftover systicks is more than a fraction of a bit, we will call it a bit //This is needed during 115200 when cmpr ISR extends into the start bit of the following byte - sysTicksPartialBit = sysTicksPerBit / 4; + rxSysTicksPartialBit = rxSysTicksPerBit / 4; + + txSysTicksPerStopBit = txSysTicksPerBit * _stopBits; + + Serial.printf("sysTicksPerBit: %d\n", txSysTicksPerBit); //Clear pin change interrupt am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(_rxPad)); @@ -179,14 +185,99 @@ int SoftwareSerial::peek() //Clears flag when called bool SoftwareSerial::overflow() { - if (_rxBufferOverflow) + if (_rxBufferOverflow || _txBufferOverflow) { _rxBufferOverflow = false; + _txBufferOverflow = false; return (true); } return (false); } +void SoftwareSerial::write(uint8_t toSend) +{ + //See if we are going to overflow buffer + uint8_t nextSpot = (txBufferHead + 1) % AP3_SS_BUFFER_SIZE; + if (nextSpot != txBufferTail) + { + //Add this byte into the circular buffer + txBuffer[nextSpot] = toSend; + txBufferHead = nextSpot; + } + else + { + _txBufferOverflow = true; + } + + //See if hardware is available + if (txInUse == false) + { + txInUse = true; + + //Start sending this byte immediately + txBufferTail = (txBufferTail + 1) % AP3_SS_BUFFER_SIZE; + outgoingByte = txBuffer[txBufferTail]; + + //Calc parity + calcParityBit(); + + beginTX(); + } +} + +//Starts the transmission of the next available byte from the buffer +void SoftwareSerial::beginTX() +{ + bitCounter = 0; + + am_hal_gpio_output_set(debugPad); + + //Initiate start bit + if (_invertLogic == false) + { + am_hal_gpio_output_clear(_txPad); //Normal logic, low is start bit + } + else + { + am_hal_gpio_output_set(_txPad); + } + + //Setup ISR to trigger when we are in middle of start bit + //am_hal_stimer_compare_delta_set(7, txSsysTicksPerBit); + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerBit; //Direct reg write to decrease execution time + + // Enable the timer interrupt in the NVIC. + NVIC_EnableIRQ(STIMER_CMPR7_IRQn); + + am_hal_gpio_output_clear(debugPad); +} + +//Assumes the global variables have been set: _parity, _dataBits, outgoingByte +//Sets global variable _parityBit +void SoftwareSerial::calcParityBit() +{ + if (_parity == 0) + return; //No parity + + uint8_t ones = 0; + for (uint8_t x = 0; x < _dataBits; x++) + { + if (outgoingByte & (0x01 << x)) + { + ones++; + } + } + + if (_parity == 1) //Odd + { + _parityForByte = !(ones % 2); + } + else //Even + { + _parityForByte = (ones % 2); + } +} + ap3_err_t SoftwareSerial::softwareserialSetConfig(HardwareSerial_Config_e SSconfig) { ap3_err_t retval = AP3_OK; @@ -338,10 +429,11 @@ void SoftwareSerial::rxBit(void) bitCounter = 0; lastBitTime = bitTime; bitType = false; + rxInUse = true; //Indicate we are now in process of receiving a byte //Setup cmpr7 interrupt to handle overall timeout - //am_hal_stimer_compare_delta_set(7, sysTicksPerByte); - AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = sysTicksPerByte; //Direct reg write to decrease execution time + //am_hal_stimer_compare_delta_set(7, rxSysTicksPerByte); + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = rxSysTicksPerByte; //Direct reg write to decrease execution time // Enable the timer interrupt in the NVIC. NVIC_EnableIRQ(STIMER_CMPR7_IRQn); @@ -349,9 +441,7 @@ void SoftwareSerial::rxBit(void) else { //Calculate the number of bits that have occured since last PCI - //Then add those bits of the current bitType (either 1 or 0) to - //the byte - uint8_t numberOfBits = (bitTime - lastBitTime) / sysTicksPerBit; + uint8_t numberOfBits = (bitTime - lastBitTime) / rxSysTicksPerBit; if (bitCounter == 0) { @@ -359,8 +449,8 @@ void SoftwareSerial::rxBit(void) //For very high bauds (115200) the final interrupt spills over into the //start bit of the next byte. This catches the partial systicks and correctly //identifies the start bit as such. - uint16_t partialBits = (bitTime - lastBitTime) % sysTicksPerBit; - if (partialBits > sysTicksPartialBit) + uint16_t partialBits = (bitTime - lastBitTime) % rxSysTicksPerBit; + if (partialBits > rxSysTicksPartialBit) { #ifdef DEBUG Serial.println("Partial!"); @@ -384,7 +474,7 @@ void SoftwareSerial::rxBit(void) } } - for (uint8_t y = 0; y < numberOfBits; y++) //Number of bits in this chunk of time + for (uint8_t y = 0; y < numberOfBits; y++) //Add bits of the current bitType (either 1 or 0) to our byte { incomingByte >>= 1; if (bitType == true) @@ -400,7 +490,7 @@ void SoftwareSerial::rxBit(void) #endif } -void SoftwareSerial::endOfByte() +void SoftwareSerial::rxEndOfByte() { //Finish out bytes that are less than 8 bits #ifdef DEBUG @@ -459,12 +549,105 @@ void SoftwareSerial::endOfByte() lastBitTime = 0; //Reset for next byte - rxInUse = false; + rxInUse = false; //Release so that we can TX if needed // Disable the timer interrupt in the NVIC. NVIC_DisableIRQ(STIMER_CMPR7_IRQn); } +//Called from cmprX ISR +//Sends out a bit with each cmprX ISR trigger +void SoftwareSerial::txHandler() +{ + if (bitCounter < _dataBits) //Data bits 0 to 7 + { + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerBit; //Direct reg write to decrease execution time + if (outgoingByte & 0x01) + { + am_hal_gpio_output_set(_txPad); + } + else + { + am_hal_gpio_output_clear(_txPad); + } + outgoingByte >>= 1; + bitCounter++; + } + else if (bitCounter == _dataBits) //Send parity bit or stop bit(s) + { + if (_parity) + { + //Send parity bit + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerBit; //Direct reg write to decrease execution time + if (_parityForByte) + { + am_hal_gpio_output_set(_txPad); + } + else + { + am_hal_gpio_output_clear(_txPad); + } + } + else + { + //Send stop bit + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerStopBit; //Direct reg write to decrease execution time + am_hal_gpio_output_set(_txPad); + } + bitCounter++; + } + else if (bitCounter == (_dataBits + 1)) //Send stop bit or begin next byte + { + if (_parity) + { + //Send stop bit + AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerStopBit; //Direct reg write to decrease execution time + am_hal_gpio_output_set(_txPad); + bitCounter++; + } + else + { + //Start next byte + if (txBufferTail == txBufferHead) + { + // Disable the timer interrupt in the NVIC. + NVIC_DisableIRQ(STIMER_CMPR7_IRQn); + + //All done! + txInUse = false; + } + else + { + //Send next byte in buffer + txBufferTail = (txBufferTail + 1) % AP3_SS_BUFFER_SIZE; + outgoingByte = txBuffer[txBufferTail]; + calcParityBit(); + beginTX(); + } + } + } + else if (bitCounter == (_dataBits + 2)) //Begin next byte + { + //Start next byte + if (txBufferTail == txBufferHead) + { + // Disable the timer interrupt in the NVIC. + NVIC_DisableIRQ(STIMER_CMPR7_IRQn); + + //All done! + txInUse = false; + } + else + { + //Send next byte in buffer + txBufferTail = (txBufferTail + 1) % AP3_SS_BUFFER_SIZE; + outgoingByte = txBuffer[txBufferTail]; + calcParityBit(); + beginTX(); + } + } +} + //Called at the completion of bytes extern "C" void am_stimer_cmpr7_isr(void) { @@ -477,7 +660,14 @@ extern "C" void am_stimer_cmpr7_isr(void) { am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - ap3_active_softwareserial_handle->endOfByte(); + if (ap3_active_softwareserial_handle->rxInUse == true) + { + ap3_active_softwareserial_handle->rxEndOfByte(); + } + else if (ap3_active_softwareserial_handle->txInUse == true) + { + ap3_active_softwareserial_handle->txHandler(); + } } #ifdef DEBUG diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 2a9844ce..bd332512 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -61,7 +61,15 @@ class SoftwareSerial bool overflow(); void rxBit(void); - void endOfByte(void); + void rxEndOfByte(void); + + void write(uint8_t toSend); + void beginTX(); + void calcParityBit(); + void txHandler(void); + + volatile bool rxInUse = false; + volatile bool txInUse = false; private: void startRXListening(void); @@ -69,7 +77,6 @@ class SoftwareSerial uint8_t txBuffer[AP3_SS_BUFFER_SIZE]; uint16_t txBufferHead = 0; volatile uint16_t txBufferTail = 0; - volatile bool txInUse = false; volatile uint8_t outgoingByte = 0; volatile uint8_t rxBuffer[AP3_SS_BUFFER_SIZE]; @@ -92,18 +99,20 @@ class SoftwareSerial bool _invertLogic; //For RX - uint16_t sysTicksPerBit = 0; - uint32_t sysTicksPerByte = 0; - uint16_t sysTicksPartialBit = 0; + uint16_t rxSysTicksPerBit = 0; + uint32_t rxSysTicksPerByte = 0; + uint16_t rxSysTicksPartialBit = 0; volatile uint8_t numberOfBits[10]; volatile uint32_t lastBitTime = 0; volatile uint8_t bitCounter; volatile bool bitType = false; - volatile bool rxInUse = false; bool _rxBufferOverflow = false; //For TX + uint16_t txSysTicksPerBit = 0; + uint16_t txSysTicksPerStopBit = 0; uint8_t _parityForByte = 0; //Calculated per byte + bool _txBufferOverflow = false; }; #endif From 739837384ed0c0c11e9404a203d42603afdb4d91 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Wed, 14 Aug 2019 15:15:57 -0600 Subject: [PATCH 16/20] Adding write functions for global print usage --- .../SoftwareSerial/src/SoftwareSerial.cpp | 21 ++++++++++++++++--- libraries/SoftwareSerial/src/SoftwareSerial.h | 8 +++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 98557cfa..066c8996 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -138,8 +138,6 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) txSysTicksPerStopBit = txSysTicksPerBit * _stopBits; - Serial.printf("sysTicksPerBit: %d\n", txSysTicksPerBit); - //Clear pin change interrupt am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(_rxPad)); @@ -194,7 +192,8 @@ bool SoftwareSerial::overflow() return (false); } -void SoftwareSerial::write(uint8_t toSend) +//Required for print +size_t SoftwareSerial::write(uint8_t toSend) { //See if we are going to overflow buffer uint8_t nextSpot = (txBufferHead + 1) % AP3_SS_BUFFER_SIZE; @@ -225,6 +224,22 @@ void SoftwareSerial::write(uint8_t toSend) } } +size_t SoftwareSerial::write(const uint8_t *buffer, size_t size) +{ + for (uint16_t x = 0; x < size; x++) + { + write(buffer[x]); + } + return (size); +} + +size_t SoftwareSerial::write(const char *str) +{ + if (str == NULL) + return 0; + return write((const uint8_t *)str, strlen(str)); +} + //Starts the transmission of the next available byte from the buffer void SoftwareSerial::beginTX() { diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index bd332512..a2635c54 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -40,7 +40,7 @@ #define TIMER_FREQ 3000000L -class SoftwareSerial +class SoftwareSerial : public Print { public: SoftwareSerial(uint8_t rxPin, uint8_t txPin, bool invertLogic = false); @@ -63,7 +63,11 @@ class SoftwareSerial void rxBit(void); void rxEndOfByte(void); - void write(uint8_t toSend); + virtual size_t write(uint8_t toSend); + + virtual size_t write(const uint8_t *buffer, size_t size); + virtual size_t write(const char *str); + void beginTX(); void calcParityBit(); void txHandler(void); From bce65f22413790ea77ef5b28d488e91a23d16fe2 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 15 Aug 2019 11:40:53 -0600 Subject: [PATCH 17/20] Clear interrupts in listen(). Set TX to prio over RX. Begin RX when TX is complete. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 48 ++++++++++++------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 066c8996..a7c02b24 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -38,7 +38,7 @@ SoftwareSerial *ap3_active_softwareserial_handle = 0; //Uncomment to enable debug pulses and Serial.prints -#define DEBUG +//#define DEBUG #ifdef DEBUG #define SS_DEBUG_PIN 9 @@ -84,6 +84,12 @@ void SoftwareSerial::listen() lastBitTime = 0; //Reset for next byte + //Clear pin change interrupt + am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(_rxPad)); + + //Clear compare interrupt + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); + //Attach this instance RX pin to PCI attachInterruptArg(digitalPinToInterrupt(_rxPin), _software_serial_isr, (void *)this, CHANGE); } @@ -138,12 +144,6 @@ void SoftwareSerial::begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig) txSysTicksPerStopBit = txSysTicksPerBit * _stopBits; - //Clear pin change interrupt - am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(_rxPad)); - - //Clear compare interrupt - am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); - //Begin PCI listen(); } @@ -195,6 +195,14 @@ bool SoftwareSerial::overflow() //Required for print size_t SoftwareSerial::write(uint8_t toSend) { + //As soon as user wants to send something, turn off RX interrupts + if (txInUse == false) + { + detachInterrupt(_rxPin); + + rxInUse = false; + } + //See if we are going to overflow buffer uint8_t nextSpot = (txBufferHead + 1) % AP3_SS_BUFFER_SIZE; if (nextSpot != txBufferTail) @@ -222,6 +230,7 @@ size_t SoftwareSerial::write(uint8_t toSend) beginTX(); } + return (1); } size_t SoftwareSerial::write(const uint8_t *buffer, size_t size) @@ -245,8 +254,6 @@ void SoftwareSerial::beginTX() { bitCounter = 0; - am_hal_gpio_output_set(debugPad); - //Initiate start bit if (_invertLogic == false) { @@ -257,14 +264,15 @@ void SoftwareSerial::beginTX() am_hal_gpio_output_set(_txPad); } + //Clear compare interrupt + am_hal_stimer_int_clear(AM_HAL_STIMER_INT_COMPAREH); + //Setup ISR to trigger when we are in middle of start bit //am_hal_stimer_compare_delta_set(7, txSsysTicksPerBit); AM_REGVAL(AM_REG_STIMER_COMPARE(0, 7)) = txSysTicksPerBit; //Direct reg write to decrease execution time // Enable the timer interrupt in the NVIC. NVIC_EnableIRQ(STIMER_CMPR7_IRQn); - - am_hal_gpio_output_clear(debugPad); } //Assumes the global variables have been set: _parity, _dataBits, outgoingByte @@ -468,7 +476,7 @@ void SoftwareSerial::rxBit(void) if (partialBits > rxSysTicksPartialBit) { #ifdef DEBUG - Serial.println("Partial!"); +// Serial.println("Partial!"); #endif numberOfBits++; } @@ -483,7 +491,7 @@ void SoftwareSerial::rxBit(void) if (numberOfBits + bitCounter > _dataBits + _parityBits) { #ifdef DEBUG - Serial.println("Exclude"); +// Serial.println("Exclude"); #endif numberOfBits--; //Exclude parity bit from byte shift } @@ -509,8 +517,8 @@ void SoftwareSerial::rxEndOfByte() { //Finish out bytes that are less than 8 bits #ifdef DEBUG - Serial.printf("bitCounter: %d\n", bitCounter); - Serial.printf("incoming: 0x%02X\n", incomingByte); +// Serial.printf("bitCounter: %d\n", bitCounter); +// Serial.printf("incoming: 0x%02X\n", incomingByte); #endif bitCounter--; //Remove start bit from count @@ -523,7 +531,7 @@ void SoftwareSerial::rxEndOfByte() } #ifdef DEBUG - Serial.printf("bitCounter: %d\n", bitCounter); +// Serial.printf("bitCounter: %d\n", bitCounter); #endif while (bitCounter < 8) @@ -533,7 +541,7 @@ void SoftwareSerial::rxEndOfByte() if (bitCounter < _dataBits) { #ifdef DEBUG - Serial.println("Add bit"); +// Serial.println("Add bit"); #endif incomingByte |= 0x80; } @@ -630,6 +638,9 @@ void SoftwareSerial::txHandler() //All done! txInUse = false; + + //Reattach PCI so we can hear rx bits coming in + listen(); } else { @@ -651,6 +662,9 @@ void SoftwareSerial::txHandler() //All done! txInUse = false; + + //Reattach PCI so we can hear rx bits coming in + listen(); } else { From 93cf5b8647e1304e53c41e8988cc0fe735cbe181 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 15 Aug 2019 12:42:11 -0600 Subject: [PATCH 18/20] Adding flush() and notes on limitations. --- .../SoftwareSerial/src/SoftwareSerial.cpp | 24 ++++++++++++++++--- libraries/SoftwareSerial/src/SoftwareSerial.h | 1 + 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index a7c02b24..67addee1 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -15,10 +15,17 @@ SoftwareSerial support for the Artemis Any pin can be used for software serial receive or transmit at 300 to 115200bps and anywhere inbetween. - Limitations: - Uses Timer/Compare module H. This will remove PWM capabilities + Limitations (similar to Arduino core SoftwareSerial): + * RX on one pin at a time. + * No TX and RX at the same time. + * TX gets priority. So if Artemis is receiving a string of characters + and you do a Serial.print() the print will begin immediately and any additional + RX characters will be lost. + * Uses Timer/Compare module H (aka 7). This will remove PWM capabilities on some pins. - Parity is supported but not checked during RX. + * Parity is supported during TX but not checked during RX. + * Enabling multiple ports causes 115200 RX to fail (because there is additional instance switching overhead) + Development environment specifics: Arduino IDE 1.8.x @@ -76,6 +83,9 @@ void SoftwareSerial::begin(uint32_t baudRate) void SoftwareSerial::listen() { + // Disable the timer interrupt in the NVIC. + NVIC_DisableIRQ(STIMER_CMPR7_IRQn); + if (ap3_active_softwareserial_handle != NULL) ap3_active_softwareserial_handle->stopListening(); //Gracefully shut down previous instance @@ -179,6 +189,14 @@ int SoftwareSerial::peek() return (rxBuffer[tempTail]); } +//Wait for TX buffer to get sent +void SoftwareSerial::flush() +{ + while (txInUse) + { + } +} + //Returns true if overflow flag is set //Clears flag when called bool SoftwareSerial::overflow() diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index a2635c54..ed4ef3d9 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -58,6 +58,7 @@ class SoftwareSerial : public Print int available(); int read(); int peek(); + void flush(); bool overflow(); void rxBit(void); From 527f9aaa4f2347e527b5bfb4d6a5dbe54df05be2 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 15 Aug 2019 12:54:00 -0600 Subject: [PATCH 19/20] Add examples. Update keywords. Tiddy up comments. --- .../Apollo_SoftwareSerial_Example1.ino | 49 --------------- .../examples/Example1_TX/Example1_TX.ino | 47 +++++++++++++++ .../Example2_RXandTX/Example2_RXandTX.ino | 56 +++++++++++++++++ .../Example3_FastTXandRX.ino | 53 ++++++++++++++++ .../Example4_Multiport/Example4_Multiport.ino | 60 +++++++++++++++++++ .../Example5_BurstMode/Example5_BurstMode.ino | 53 ++++++++++++++++ .../Example6_AdvancedConfig.ino | 51 ++++++++++++++++ libraries/SoftwareSerial/keywords.txt | 17 ++++-- libraries/SoftwareSerial/library.properties | 8 +-- .../SoftwareSerial/src/SoftwareSerial.cpp | 6 +- libraries/SoftwareSerial/src/SoftwareSerial.h | 36 +++++------ 11 files changed, 355 insertions(+), 81 deletions(-) delete mode 100644 libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino create mode 100644 libraries/SoftwareSerial/examples/Example1_TX/Example1_TX.ino create mode 100644 libraries/SoftwareSerial/examples/Example2_RXandTX/Example2_RXandTX.ino create mode 100644 libraries/SoftwareSerial/examples/Example3_FastTXandRX/Example3_FastTXandRX.ino create mode 100644 libraries/SoftwareSerial/examples/Example4_Multiport/Example4_Multiport.ino create mode 100644 libraries/SoftwareSerial/examples/Example5_BurstMode/Example5_BurstMode.ino create mode 100644 libraries/SoftwareSerial/examples/Example6_AdvancedConfig/Example6_AdvancedConfig.ino diff --git a/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino b/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino deleted file mode 100644 index 9316f559..00000000 --- a/libraries/SoftwareSerial/examples/Apollo_SoftwareSerial_Example1/Apollo_SoftwareSerial_Example1.ino +++ /dev/null @@ -1,49 +0,0 @@ -/* - Author: Nathan Seidle - SparkFun Electronics - Created: June 19 2019 - License: MIT. See SparkFun Arduino Apollo3 Project for more information - - Feel like supporting open source hardware? Buy a board from SparkFun! - https://www.sparkfun.com/artemis - - This example shows how to receive characters at 9600bps. Any pin can be used for - reception. - - Hardware Connections: - Attach a USB to serial converter (https://www.sparkfun.com/products/15096) - Connect - GND on SerialBasic <-> GND on Artemis - TXO on SerialBasic <-> Pin 7 on Artemis - Load this code - Open Arduino serial monitor at 9600 - Open Terminal window (TeraTerm) at 9600 - Press a button in terminal window, you should see it in Arduino monitor -*/ - - -//#define DEBUG -#define LED 13 - -#include -SoftwareSerial mySerial(7, 8); //RX, TX - -void setup() { - Serial.begin(9600); - Serial.println("Software Serial Example"); - - //enableBurstMode(); //Go to 96MHz - - mySerial.begin(9600); //SERIAL_8N1); -} - -void loop() { - digitalWrite(LED, HIGH); - //delay(100); - digitalWrite(LED, LOW); - //delay(100); - - delay(1); - - -} diff --git a/libraries/SoftwareSerial/examples/Example1_TX/Example1_TX.ino b/libraries/SoftwareSerial/examples/Example1_TX/Example1_TX.ino new file mode 100644 index 00000000..8afed793 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example1_TX/Example1_TX.ino @@ -0,0 +1,47 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to send characters at 9600bps. Any pin can be used for + TX or RX. + + Note: In this SoftwareSerial library you cannot TX and RX at the same time. + TX gets priority. So if Artemis is receiving a string of characters + and you do a Serial.print() the print will begin immediately and any additional + RX characters will be lost. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + Load this code + Open Arduino serial monitor at 57600 + Open Terminal window (TeraTerm) at 9600 +*/ + +#include +SoftwareSerial mySerial(7, 8); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + Serial.begin(57600); + Serial.println("Software Serial Example"); + + mySerial.begin(9600); +} + +void loop() { + + mySerial.print("Hello world: "); + mySerial.println(counter++); + + delay(20); //Small delay because it takes time to send chars at 9600bps +} diff --git a/libraries/SoftwareSerial/examples/Example2_RXandTX/Example2_RXandTX.ino b/libraries/SoftwareSerial/examples/Example2_RXandTX/Example2_RXandTX.ino new file mode 100644 index 00000000..cb0efc9a --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example2_RXandTX/Example2_RXandTX.ino @@ -0,0 +1,56 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to send characters at 9600bps. Any pin can be used for + TX or RX. + + Note: In this SoftwareSerial library you cannot TX and RX at the same time. + TX gets priority. So if Artemis is receiving a string of characters + and you do a Serial.print() the print will begin immediately and any additional + RX characters will be lost. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 57600 + Open Terminal window (TeraTerm) at 9600 + Press a button in terminal window, you should see it in Arduino monitor +*/ + +#include +SoftwareSerial mySerial(7, 8); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + //and more time checking mySerial.available() + Serial.begin(57600); + Serial.println("Software Serial Example"); + + mySerial.begin(9600); +} + +void loop() { + + mySerial.print("Hi: "); + mySerial.println(counter++); + + while (mySerial.available()) + { + byte incoming = mySerial.read(); + Serial.write(incoming); + } + + delay(100); //Small delay between prints so that we can detect incoming chars if any +} diff --git a/libraries/SoftwareSerial/examples/Example3_FastTXandRX/Example3_FastTXandRX.ino b/libraries/SoftwareSerial/examples/Example3_FastTXandRX/Example3_FastTXandRX.ino new file mode 100644 index 00000000..22547d61 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example3_FastTXandRX/Example3_FastTXandRX.ino @@ -0,0 +1,53 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to send characters at 57600bps. It's counter intuitive + but by printing faster and receiving faster we can do more with interrupt + based software serial. + Any pin can be used for TX or RX. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 115200 + Open Terminal window (TeraTerm) at 57600 + Press a button in terminal window, you should see it in Arduino monitor +*/ + +#include +SoftwareSerial mySerial(7, 8); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + //and more time checking mySerial.available() + Serial.begin(115200); + Serial.println("Software Serial Example"); + + mySerial.begin(57600); +} + +void loop() { + + mySerial.print("Hi: "); + mySerial.println(counter++); + + while (mySerial.available()) + { + byte incoming = mySerial.read(); + Serial.write(incoming); + } + + delay(25); //Small delay between prints so that we can detect incoming chars if any +} diff --git a/libraries/SoftwareSerial/examples/Example4_Multiport/Example4_Multiport.ino b/libraries/SoftwareSerial/examples/Example4_Multiport/Example4_Multiport.ino new file mode 100644 index 00000000..e3794e4e --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example4_Multiport/Example4_Multiport.ino @@ -0,0 +1,60 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to enable multiple software serial ports at 57600bps. + You can only receive on one pin at a time. Use .listen() to switch between + RX pins. + + Note: When multiple ports are enabled receiving at 115200bps is no longer + possible. This is because the receive interrupt has additional overhead + and cannot run fast enough to correctly capture bits in time. TX at 115200 + is still supported. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 115200 + Open Terminal window (TeraTerm) at 57600 + Press a button in terminal window, you should see it in Arduino monitor +*/ + +#include +SoftwareSerial mySerialA(7, 8); //RX, TX - Any pins can be used +SoftwareSerial mySerialB(2, 3); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + Serial.begin(115200); + Serial.println("Software Serial Example"); + + mySerialA.begin(57600); + mySerialB.begin(9600); + + //We are now using mySerialB because it was the last one to begin. Use .listen() to change ports. +} + +void loop() { + mySerialA.listen(); + mySerialA.print("I'm A: "); + mySerialA.println(counter); + mySerialA.flush(); //Wait for TX buffer to get sent out + + mySerialB.listen(); + mySerialB.print("I'm B: "); + mySerialB.println(counter); + mySerialB.flush(); + + counter++; +} diff --git a/libraries/SoftwareSerial/examples/Example5_BurstMode/Example5_BurstMode.ino b/libraries/SoftwareSerial/examples/Example5_BurstMode/Example5_BurstMode.ino new file mode 100644 index 00000000..680dc3a9 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example5_BurstMode/Example5_BurstMode.ino @@ -0,0 +1,53 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to enable burst mode. Although Artemis is running at + 96MHz, software serial operates the same way. + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 57600 + Open Terminal window (TeraTerm) at 57600 + Press a button in terminal window, you should see it in Arduino monitor +*/ + +#include +SoftwareSerial mySerial(7, 8); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + //and more time checking mySerial.available() + Serial.begin(57600); + Serial.println("Software Serial Example"); + + enableBurstMode(); //Go to 96MHz + + mySerial.begin(57600); +} + +void loop() { + + mySerial.print("Hi: "); + mySerial.println(counter++); + + while (mySerial.available()) + { + byte incoming = mySerial.read(); + Serial.write(incoming); + } + + delay(100); //Small delay between prints so that we can detect incoming chars if any +} diff --git a/libraries/SoftwareSerial/examples/Example6_AdvancedConfig/Example6_AdvancedConfig.ino b/libraries/SoftwareSerial/examples/Example6_AdvancedConfig/Example6_AdvancedConfig.ino new file mode 100644 index 00000000..5ba07439 --- /dev/null +++ b/libraries/SoftwareSerial/examples/Example6_AdvancedConfig/Example6_AdvancedConfig.ino @@ -0,0 +1,51 @@ +/* + Author: Nathan Seidle + SparkFun Electronics + Created: June 19 2019 + License: MIT. See SparkFun Arduino Apollo3 Project for more information + + Feel like supporting open source hardware? Buy a board from SparkFun! + https://www.sparkfun.com/artemis + + This example shows how to use different data, parity, and stop bits. + See Arduino reference for all settings: https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/ + + Hardware Connections: + Attach a USB to serial converter (https://www.sparkfun.com/products/15096) + Connect + GND on SerialBasic <-> GND on Artemis + RXO on SerialBasic <-> Pin 8 on Artemis + TXO on SerialBasic <-> Pin 7 on Artemis + Load this code + Open Arduino serial monitor at 57600 + Open Terminal window (TeraTerm) at 9600 with special settings *8 bits, even parity, 2 stop!* + Press a button in terminal window, you should see it in Arduino monitor +*/ + +#include +SoftwareSerial mySerial(7, 8); //RX, TX - Any pins can be used + +int counter = 0; + +void setup() { + //We set the serial monitor speed high so that we spend less time printing the output + //and more time checking mySerial.available() + Serial.begin(57600); + Serial.println("Software Serial Example"); + + mySerial.begin(57600, SERIAL_8E2); //Use 8 data bits, even parity, and 2 stop bits +} + +void loop() { + + mySerial.print("Hi: "); + mySerial.println(counter++); + + while (mySerial.available()) + { + byte incoming = mySerial.read(); + Serial.write(incoming); + } + + delay(100); //Small delay between prints so that we can detect incoming chars if any +} diff --git a/libraries/SoftwareSerial/keywords.txt b/libraries/SoftwareSerial/keywords.txt index 7987e9b3..f9004bdf 100644 --- a/libraries/SoftwareSerial/keywords.txt +++ b/libraries/SoftwareSerial/keywords.txt @@ -6,17 +6,24 @@ # Datatypes (KEYWORD1) ####################################### -EEPROM KEYWORD1 +SoftwareSerial KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### +begin KEYWORD2 +end KEYWORD2 read KEYWORD2 write KEYWORD2 -get KEYWORD2 -put KEYWORD2 -update KEYWORD2 -erase KEYWORD2 + +available KEYWORD2 +flush KEYWORD2 +peek KEYWORD2 +overflow KEYWORD2 + +listen KEYWORD2 +stopListening KEYWORD2 +isListening KEYWORD2 ####################################### # Constants (LITERAL1) diff --git a/libraries/SoftwareSerial/library.properties b/libraries/SoftwareSerial/library.properties index 3559ba4d..5da4f55a 100644 --- a/libraries/SoftwareSerial/library.properties +++ b/libraries/SoftwareSerial/library.properties @@ -1,9 +1,9 @@ -name=EEPROM +name=SoftwareSerial version=1.0 author=SparkFun Electronics maintainer=SparkFun Electronics -sentence=Flash based Pseudo EEPROM for Artemis -paragraph=Enables the writing of variables to a protected section of flash. These bytes will not be overwritten when new sketches are loaded and are useful when needing to record settings like calibration data or GPS waypoints that should not change between sketch updates. +sentence=Interrupt based software serial for Artemis +paragraph=Enables sending and receiving at 300 to 115200 bits per second on any pins. Multiple SoftwareSerial ports are supported. category=Communication -url=http://www.arduino.cc/en/Reference/EEPROM +url=http://www.arduino.cc/en/Reference/SoftwareSerial architectures=apollo3 diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 67addee1..11bbb1ff 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -3,10 +3,7 @@ SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support open source hardware. Buy a board! - https://www.sparkfun.com/products/15332 - https://www.sparkfun.com/products/15376 - https://www.sparkfun.com/products/15411 - https://www.sparkfun.com/products/15412 + https://www.sparkfun.com/artemis Written by Nathan Seidle @ SparkFun Electronics, August 12th, 2019 @@ -26,7 +23,6 @@ * Parity is supported during TX but not checked during RX. * Enabling multiple ports causes 115200 RX to fail (because there is additional instance switching overhead) - Development environment specifics: Arduino IDE 1.8.x diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index ed4ef3d9..791b33f8 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -3,11 +3,8 @@ SparkFun sells these at its website: www.sparkfun.com Do you like this library? Help support open source hardware. Buy a board! - https://www.sparkfun.com/products/15332 - https://www.sparkfun.com/products/15376 - https://www.sparkfun.com/products/15411 - https://www.sparkfun.com/products/15412 - + https://www.sparkfun.com/artemis + Written by Nathan Seidle @ SparkFun Electronics, August 12th, 2019 https://github.com/sparkfun/SparkFun_Apollo3 @@ -15,11 +12,17 @@ SoftwareSerial support for the Artemis Any pin can be used for software serial receive or transmit at 300 to 115200bps and anywhere inbetween. - Limitations: - Uses Timer/Compare module H. This will remove PWM capabilities + Limitations (similar to Arduino core SoftwareSerial): + * RX on one pin at a time. + * No TX and RX at the same time. + * TX gets priority. So if Artemis is receiving a string of characters + and you do a Serial.print() the print will begin immediately and any additional + RX characters will be lost. + * Uses Timer/Compare module H (aka 7). This will remove PWM capabilities on some pins. - Parity is supported but not checked during RX. - + * Parity is supported during TX but not checked during RX. + * Enabling multiple ports causes 115200 RX to fail (because there is additional instance switching overhead) + Development environment specifics: Arduino IDE 1.8.x @@ -54,30 +57,28 @@ class SoftwareSerial : public Print void begin(uint32_t baudRate, HardwareSerial_Config_e SSconfig); void end(void); - ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); int available(); int read(); int peek(); void flush(); bool overflow(); - void rxBit(void); - void rxEndOfByte(void); - virtual size_t write(uint8_t toSend); - virtual size_t write(const uint8_t *buffer, size_t size); virtual size_t write(const char *str); - void beginTX(); - void calcParityBit(); void txHandler(void); + void rxBit(void); + void rxEndOfByte(void); + volatile bool rxInUse = false; volatile bool txInUse = false; private: + ap3_err_t softwareserialSetConfig(HardwareSerial_Config_e SSconfig); void startRXListening(void); + void beginTX(); uint8_t txBuffer[AP3_SS_BUFFER_SIZE]; uint16_t txBufferHead = 0; @@ -92,8 +93,6 @@ class SoftwareSerial : public Print uint8_t _rxPin; uint8_t _txPin; - uint8_t _indexNumber; // The index number at which the pointer to this instance is stored in the global object table. - ap3_gpio_pad_t _txPad; ap3_gpio_pad_t _rxPad; @@ -114,6 +113,7 @@ class SoftwareSerial : public Print bool _rxBufferOverflow = false; //For TX + void calcParityBit(); uint16_t txSysTicksPerBit = 0; uint16_t txSysTicksPerStopBit = 0; uint8_t _parityForByte = 0; //Calculated per byte From caf4700aebed139a66db33365e10844bd4bec8b3 Mon Sep 17 00:00:00 2001 From: Nathan Seidle Date: Thu, 15 Aug 2019 13:18:06 -0600 Subject: [PATCH 20/20] Add note that pad 11 will loose PWM capabilities. --- libraries/SoftwareSerial/src/SoftwareSerial.cpp | 2 +- libraries/SoftwareSerial/src/SoftwareSerial.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.cpp b/libraries/SoftwareSerial/src/SoftwareSerial.cpp index 11bbb1ff..442ee49c 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.cpp +++ b/libraries/SoftwareSerial/src/SoftwareSerial.cpp @@ -19,7 +19,7 @@ and you do a Serial.print() the print will begin immediately and any additional RX characters will be lost. * Uses Timer/Compare module H (aka 7). This will remove PWM capabilities - on some pins. + on pad 11. * Parity is supported during TX but not checked during RX. * Enabling multiple ports causes 115200 RX to fail (because there is additional instance switching overhead) diff --git a/libraries/SoftwareSerial/src/SoftwareSerial.h b/libraries/SoftwareSerial/src/SoftwareSerial.h index 791b33f8..6d3b6f4d 100644 --- a/libraries/SoftwareSerial/src/SoftwareSerial.h +++ b/libraries/SoftwareSerial/src/SoftwareSerial.h @@ -19,7 +19,7 @@ and you do a Serial.print() the print will begin immediately and any additional RX characters will be lost. * Uses Timer/Compare module H (aka 7). This will remove PWM capabilities - on some pins. + on pad 11. * Parity is supported during TX but not checked during RX. * Enabling multiple ports causes 115200 RX to fail (because there is additional instance switching overhead)