From d3f6b2d1a5507e0f29349bfa40d99d6f3d3f3b5d Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Tue, 12 Sep 2017 11:05:27 -0400 Subject: [PATCH 01/33] Added Travis support --- .gitignore | 8 ++++++ .travis.yml | 17 ++++++++++++ test/test.ino | 76 +++++++++++++++++++++++++-------------------------- 3 files changed, 63 insertions(+), 38 deletions(-) create mode 100644 .travis.yml diff --git a/.gitignore b/.gitignore index 96374c4..b86373e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,11 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + +# Atom / PlatformIO +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json +lib/readme.txt +platformio.ini diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1340e5d --- /dev/null +++ b/.travis.yml @@ -0,0 +1,17 @@ +language: python +python: + - "2.7" + +sudo: false +cache: + directories: + - "~/.platformio" + +env: + - PLATFORMIO_CI_SRC=test/test.ino + +install: + - pip install -U platformio + +script: + - platformio ci --lib="." --board=megaatmega2560 --board=mayfly diff --git a/test/test.ino b/test/test.ino index ec228aa..31f1922 100644 --- a/test/test.ino +++ b/test/test.ino @@ -85,7 +85,7 @@ void testOne( Stream & ins, Stream & outs, uint8_t c ) uint8_t received = 0; bool gotIt = false; uint32_t start = millis(); - + do { if (ins.available()) { uint8_t received_c = ins.read(); @@ -197,7 +197,7 @@ static void printStats() stopBitCompletions = 0; highBitWaits = 0; #endif - + Serial.println( F("-----------------") ); Serial.flush(); @@ -224,18 +224,18 @@ static void printRC() //--------------------------------------------------------------------- -void setup() { +void setup() { //Initialize serial and wait for port to open: - Serial.begin(9600); + Serial.begin(9600); while (!Serial) ; - Serial3.begin( baudrate ); + Serial1.begin( baudrate ); delay( 10 ); - Serial3.print( 'U' ); - Serial3.flush(); + Serial1.print( 'U' ); + Serial1.flush(); delay( 10 ); - + nss.begin( baudrate ); } // setup @@ -250,13 +250,13 @@ void loop() Serial.println( F("Individual RX test") ); Serial.flush(); - + uint8_t c=0; do { - testOne( nss, Serial3, c ); + testOne( nss, Serial1, c ); c++; } while (c != 0); - testOne( nss, Serial3, c ); + testOne( nss, Serial1, c ); uint32_t start = millis(); while (millis() - start < 100) { if (nss.available()) { @@ -271,16 +271,16 @@ void loop() Serial.println( F("RX test") ); Serial.flush(); - + for (uint8_t times=0; times<1; times++) { do { - Serial3.write( c++ ); + Serial1.write( c++ ); sent++; if (nss.available()) rc[ received++ ] = nss.read(); } while (c != 0); } - Serial3.write( c++ ); + Serial1.write( c++ ); sent++; start = millis(); @@ -303,11 +303,11 @@ void loop() Serial.println( F("TX test") ); Serial.flush(); - + for (uint16_t i=0; i<=256; i++) { nss.write( (uint8_t) (i & 0xFF) ); - if (Serial3.available()) - rc[ received++ ] = Serial3.read(); + if (Serial1.available()) + rc[ received++ ] = Serial1.read(); } start = millis(); @@ -315,12 +315,12 @@ void loop() uint32_t ms; do { ms = millis(); - if (Serial3.available()) { + if (Serial1.available()) { start = ms; - rc[ received++ ] = Serial3.read(); + rc[ received++ ] = Serial1.read(); } } while (ms - start < 100); - + printRC(); printStats(); @@ -329,15 +329,15 @@ void loop() Serial.println( F("RX and TX test") ); Serial.flush(); - + for (uint16_t i=0; i<=256; i++) { - Serial3.write( (uint8_t) i & 0xFF ); + Serial1.write( (uint8_t) i & 0xFF ); if (nss.available()) { c = nss.read(); nss.write( c ); } - if (Serial3.available()) - rc[ received++ ] = Serial3.read(); + if (Serial1.available()) + rc[ received++ ] = Serial1.read(); } start = millis(); @@ -349,12 +349,12 @@ void loop() c = nss.read(); nss.write( c ); } - if (Serial3.available()) { + if (Serial1.available()) { start = ms; - rc[ received++ ] = Serial3.read(); + rc[ received++ ] = Serial1.read(); } } while (ms - start < 100); - + printRC(); printStats(); @@ -363,12 +363,12 @@ void loop() Serial.println( F("TX and RX test") ); Serial.flush(); - + for (uint16_t i=0; i<=256; i++) { nss.write( (uint8_t) i & 0xFF ); - if (Serial3.available()) { - c = Serial3.read(); - Serial3.write( c ); + if (Serial1.available()) { + c = Serial1.read(); + Serial1.write( c ); } while (nss.available()) rc[ received++ ] = nss.read(); @@ -378,17 +378,17 @@ void loop() do { ms = millis(); - if (Serial3.available()) { + if (Serial1.available()) { start = ms; - c = Serial3.read(); - Serial3.write( c ); + c = Serial1.read(); + Serial1.write( c ); } while (nss.available()) { start = ms; rc[ received++ ] = nss.read(); } } while (ms - start < 100); - + printRC(); printStats(); @@ -409,6 +409,6 @@ void loop() baudrate = 9600; else baudrate <<= 1; - nss.setBaudRate( baudrate ); - Serial3.begin( baudrate ); -} + nss.setBaudRate( baudrate ); + Serial1.begin( baudrate ); +} From 804e871e210801d451cbdf622f136894aa6436f2 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Tue, 12 Sep 2017 16:33:40 -0400 Subject: [PATCH 02/33] Added support for 32u4 --- src/NeoSWSerial.cpp | 53 +++++++++++++++++++++++++++++---------------- src/NeoSWSerial.h | 12 +++++----- test/test.ino | 2 +- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index ce8edfe..560d413 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -42,17 +42,23 @@ static const uint8_t BITS_PER_TICK_31250_Q10 = 128; static const uint8_t BITS_PER_TICK_38400_Q10 = 157; // 1s/(38400 bits) * (1 tick)/(4 us) * 2^10 "multiplier" +// Choose the timer to use #if F_CPU == 16000000L - #define TCNTX TCNT0 + #define TCNTX TCNT0 // 8-bit timer w/ PWM, default prescaler has divisor of 64, thus 250kHz #define PCI_FLAG_REGISTER PCIFR + #elif F_CPU == 8000000L #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) - #define TCNTX TCNT1 + defined(__AVR_ATtiny85__) + #define TCNTX TCNT1 // 8-bit timer/counter w/ independent prescaler #define PCI_FLAG_REGISTER GIFR + #elif defined(__AVR_ATmega32U4__) + #define TCNTX TCNT4 // 10-bit high speed timer, usable as 8-bit timer by ignoring high bits + #define PCI_FLAG_REGISTER PCIFR #else - #define TCNTX TCNT2 + // Have to use timer 2 for an 8 MHz system because timer 0 doesn't have the correct prescaler + #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous opperation, and independent prescaler #define PCI_FLAG_REGISTER PCIFR #endif #endif @@ -145,15 +151,24 @@ void NeoSWSerial::listen() *txPort |= txBitMask; // high = idle pinMode(txPin, OUTPUT); + // Set the timer prescaling as necessary - want to be running at 250kHz if (F_CPU == 8000000L) { - // Have to use timer 2 for an 8 MHz system. #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) - TCCR1 = 0x06; // divide by 32 + defined(__AVR_ATtiny85__) + TCCR1 = 0x06; // 0b00000110 - Clock Select bits 12 & 11 on - prescaling source = CK/32 + // timer now running at 8MHz/32 = 250kHz + #elif defined(__AVR_ATmega32U4__) + TCCR4A = 0x00; // "normal" operation - Normal port operation, OC4A & OC4B disconnected + TCCR4B = 0x06; // 0b00000110 - Clock Select bits 42 & 41 on - prescaler set to CK/32 + // timer now running at 8MHz/32 = 250kHz + TCCR4C = 0x00; // "normal" operation - Normal port operation, OC4D0 disconnected + TCCR4D = 0x00; // No fault protection + TCCR4E = 0x00; // No register locks or overrides #else - TCCR2A = 0x00; - TCCR2B = 0x03; // divide by 32 + TCCR2A = 0x00; // "normal" operation - Normal port operation, OC2A & OC2B disconnected + TCCR2B = 0x03; // 0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32 + // timer now running at 8MHz/32 = 250kHz #endif } @@ -164,7 +179,7 @@ void NeoSWSerial::listen() flush(); // Set up timings based on baud rate - + switch (_baudRate) { case 9600: txBitWidth = TICKS_PER_BIT_9600 ; @@ -177,7 +192,7 @@ void NeoSWSerial::listen() bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; rxWindowWidth = 5; break; - } // else use 19200 + } case 38400: if (F_CPU > 12000000L) { txBitWidth = TICKS_PER_BIT_9600 >> 2; @@ -252,7 +267,7 @@ void NeoSWSerial::setBaudRate(uint16_t baudRate) int NeoSWSerial::available() { uint8_t avail = ((rxHead - rxTail + RX_BUFFER_SIZE) % RX_BUFFER_SIZE); - + if (avail == 0) { cli(); if (checkRxTime()) { @@ -305,8 +320,8 @@ void NeoSWSerial::startChar() void NeoSWSerial::rxISR( uint8_t rxPort ) { - uint8_t t0 = TCNTX; // time of data transition (plus ISR latency) - uint8_t d = rxPort & rxBitMask; // read RX data level + uint8_t t0 = TCNTX; // time of data transition (plus ISR latency) + uint8_t d = rxPort & rxBitMask; // read RX data level if (rxState == WAITING_FOR_START_BIT) { @@ -457,13 +472,13 @@ void NeoSWSerial::rxChar( uint8_t c ) #elif defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) + defined(__AVR_ATtiny85__) PCINT_ISR(0, PINB); #elif defined(__AVR_ATtiny24__) | \ defined(__AVR_ATtiny44__) | \ - defined(__AVR_ATtiny84__) + defined(__AVR_ATtiny84__) PCINT_ISR(0, PINA); PCINT_ISR(1, PINB); @@ -535,9 +550,9 @@ size_t NeoSWSerial::write(uint8_t txChar) uint8_t t0 = TCNTX; // start time - // TODO: This would benefit from an early break after + // TODO: This would benefit from an early break after // the last 0 data bit. Then we could wait for the - // remaining 1 data bits and stop bit with interrupts + // remaining 1 data bits and stop bit with interrupts // re-enabled. while (txBit++ < 9) { // repeat for start bit + 8 data bits @@ -551,7 +566,7 @@ size_t NeoSWSerial::write(uint8_t txChar) (width == TICKS_PER_BIT_9600/4) && (txBit & 0x01)) { // The width is 6.5 ticks, so add a tick every other bit - width++; + width++; } // Hold the line for the bit duration diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 1e54499..4a7dd4b 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -24,8 +24,8 @@ // This software serial library is intended as a more-efficient replacement // for SoftwareSerial at baud rates 9600, 19200 and 38400. // -// Any of the pins supported by SoftwareSerial may be used. Pins (0-19) -// on the Uno may be used. Other boards can use any of the pins +// Any of the pins supported by SoftwareSerial may be used. Pins (0-19) +// on the Uno may be used. Other boards can use any of the pins // allowed by digitalPinToPCMSK in pins_arduino.h // // This code uses a pin change interrupt on the selected RX pin. @@ -42,9 +42,9 @@ // Supported baud rates are 9600 (default), 19200 and 38400. // The baud rate is selectable at run time. // -// The size of the RX buffer may be changed by editing the -// accompanying .cpp file. For optimal performance of the interrupt -// service routines, the buffer size should be chosen to be a +// The size of the RX buffer may be changed by editing the +// accompanying .cpp file. For optimal performance of the interrupt +// service routines, the buffer size should be chosen to be a // power of 2 (i.e., 2, 4, 8, 16, 32, 64,...). // // v1.0 Nov 2014 jboyton - Created @@ -75,7 +75,7 @@ class NeoSWSerial : public Stream void begin(uint16_t baudRate=9600); // initialize, set baudrate, listen void listen(); // enable RX interrupts void ignore(); // disable RX interrupts - void setBaudRate(uint16_t baudRate); // 9600 [default], 19200, 38400 + void setBaudRate(uint16_t baudRate); // 9600 [default], 19200, 31250, 38400 virtual int available(); virtual int read(); virtual size_t write(uint8_t txChar); diff --git a/test/test.ino b/test/test.ino index 31f1922..955ff22 100644 --- a/test/test.ino +++ b/test/test.ino @@ -1,6 +1,6 @@ #include -NeoSWSerial nss( 52, 53 ); +NeoSWSerial nss( 10, 11 ); uint16_t baudrate = 9600; uint8_t rc[520]; From b46608ddaf8b96365a7bfa626ec49338264cf266 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Tue, 12 Sep 2017 18:30:52 -0400 Subject: [PATCH 03/33] Added another test for myself --- .../test.ino => tests/DebugTest/DebugTest.ino | 0 tests/RxTest/RxTest.ino | 77 +++++++++++++++++++ 2 files changed, 77 insertions(+) rename test/test.ino => tests/DebugTest/DebugTest.ino (100%) create mode 100644 tests/RxTest/RxTest.ino diff --git a/test/test.ino b/tests/DebugTest/DebugTest.ino similarity index 100% rename from test/test.ino rename to tests/DebugTest/DebugTest.ino diff --git a/tests/RxTest/RxTest.ino b/tests/RxTest/RxTest.ino new file mode 100644 index 0000000..f536ce1 --- /dev/null +++ b/tests/RxTest/RxTest.ino @@ -0,0 +1,77 @@ +#include +#include + +#define BAUD 57600 + +NeoSWSerial nss( 10, 11 ); + +void setup(){ + Serial.begin(57600); + delay(50); + + while (!Serial){}; + Serial.print("Test at "); + Serial.println(BAUD); + + Serial1.begin(BAUD); + delay(50); + + nss.begin(BAUD); + delay(50); + +} + +void loop() { + // char endline = '\n'; + // String readstr = Serial1.readStringUntil(endline); + // if (readstr.length() > 0) + // { + // Serial.print("Serial1 - "); + // Serial.println(readstr); + // } + // else Serial.println("Serial1 - no data"); + // + // String readstr2 = nss.readStringUntil(endline); + // if (readstr2.length() > 0) + // { + // Serial.print(" NSS - "); + // Serial.println(readstr2); + // } + // else Serial.println(" NSS - no data"); + + char readSer, readNSS; + readSer = Serial1.read(); + readNSS = nss.read(); + + if (readSer > 0 and readNSS > 0) + { + Serial.print(readSer); + Serial.print(" ("); + Serial.print(readSer, HEX); + Serial.print(")"); + Serial.print(" - "); + Serial.print(readNSS); + Serial.print(" ("); + Serial.print(readNSS, HEX); + Serial.print(")"); + Serial.println(); + } + else if (readSer > 0) + { + Serial.print(readSer); + Serial.print(" ("); + Serial.print(readSer, HEX); + Serial.print(")"); + Serial.print(" - ? (##)"); + Serial.println(); + } + else if (readNSS > 0) + { + Serial.print("? (##) - "); + Serial.print(readNSS); + Serial.print(" ("); + Serial.print(readNSS, HEX); + Serial.print(")"); + Serial.println(); + } +} From 398c8da7285ba434157df98e643e9f6651c9be72 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Tue, 12 Sep 2017 18:37:21 -0400 Subject: [PATCH 04/33] Removed limits on baud rates for 8MHz boards --- src/NeoSWSerial.cpp | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 560d413..e5a4ca2 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -181,30 +181,26 @@ void NeoSWSerial::listen() // Set up timings based on baud rate switch (_baudRate) { - case 9600: - txBitWidth = TICKS_PER_BIT_9600 ; - bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 2; - rxWindowWidth = 10; - break; - case 31250: - if (F_CPU > 12000000L) { - txBitWidth = TICKS_PER_BIT_31250; - bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; - rxWindowWidth = 5; - break; - } case 38400: - if (F_CPU > 12000000L) { txBitWidth = TICKS_PER_BIT_9600 >> 2; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; rxWindowWidth = 4; break; - } // else use 19200 + case 31250: + txBitWidth = TICKS_PER_BIT_31250; + bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; + rxWindowWidth = 5; + break; case 19200: txBitWidth = TICKS_PER_BIT_9600 >> 1; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 1; rxWindowWidth = 6; break; + case 9600: // default is 9600 + txBitWidth = TICKS_PER_BIT_9600 ; + bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 2; + rxWindowWidth = 10; + break; } // Enable the pin change interrupts @@ -249,8 +245,8 @@ void NeoSWSerial::setBaudRate(uint16_t baudRate) if (( ( baudRate == 9600) || ( baudRate == 19200) || - ((baudRate == 31250) && (F_CPU == 16000000L)) || - ((baudRate == 38400) && (F_CPU == 16000000L)) + ( baudRate == 31250) || + ( baudRate == 38400) ) && (_baudRate != baudRate)) { From bd32958942c68d8ed84624742b52f31356d2e199 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Wed, 13 Sep 2017 14:03:20 -0400 Subject: [PATCH 05/33] Better testing script --- .travis.yml | 2 +- tests/PairedTestNSS/PairedTestNSS.ino | 178 ++++++++++++++++++++++++++ tests/RxTest/RxTest.ino | 98 +++++++------- 3 files changed, 228 insertions(+), 50 deletions(-) create mode 100644 tests/PairedTestNSS/PairedTestNSS.ino diff --git a/.travis.yml b/.travis.yml index 1340e5d..6e873f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ install: - pip install -U platformio script: - - platformio ci --lib="." --board=megaatmega2560 --board=mayfly + - platformio ci --lib="." --board=uno --board=megaatmega2560 --board=mayfly --board=feather32u4 diff --git a/tests/PairedTestNSS/PairedTestNSS.ino b/tests/PairedTestNSS/PairedTestNSS.ino new file mode 100644 index 0000000..6b0b724 --- /dev/null +++ b/tests/PairedTestNSS/PairedTestNSS.ino @@ -0,0 +1,178 @@ +#include +#include + +#define BAUD 9600 +#define HW_STREAM Serial1 + +#if !defined(FIRST_SENDER) + #define FIRST_SENDER true +#endif + +NeoSWSerial nss( 10, 11 ); + +char sentence1[] = "Quick zephyrs blow, vexing daft Jim."; +char sentence2[] = "Sphinx of black quartz, judge my vow."; +char sentence3[] = "The quick brown fox jumps over the lazy dog."; +char alphabet1[] = "abcdefghijklmnopqrstuvwwxyz<>?:{}|~!@#$%^&*()_+"; +char alphabet2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\1234567890`-='"; +char rxBuffer[50]; + +void waitForReady(bool isSending) +{ + bool isStarted = false; + char rxByte[] = "2"; + Serial.println("Wait for ready"); + + if (isSending) + { + while (!isStarted) + { + nss.print("1"); // Continually print out ones + nss.readBytes(rxByte, 1); // Listen for a single returned one + if (rxByte[0] == '1') isStarted = true; + } + } + else + { + // Listening for the "1" to start on neosoftware serial + while (!isStarted) + { + HW_STREAM.readBytes(rxByte, 1); + if (rxByte[0] == '1') isStarted = true; + } + HW_STREAM.print("1"); // Send a single 1 to acknlowlege that it's ready + } +} + + +void sendOrRecieve(char sentence[], bool isSending, Stream *stream, String streamName) +{ + if (isSending) + { + delay(10); + stream->print(sentence); + stream->flush(); + } + else + { + Serial.print("Known: "); + Serial.println(sentence); + long start = millis(); + + while ((stream->available() < strlen(sentence)) and ((millis() - start) < 1000)){} + + if (stream->available()) + { + stream->readBytes(rxBuffer, strlen(sentence)); + Serial.print(streamName); + Serial.print(" Rcvd: "); + Serial.println(rxBuffer); + + Serial.print("Diff: "); + for (uint8_t i = 0; i < strlen(sentence); i++) + { + if (sentence[i] == rxBuffer[i]) Serial.print("-"); + else Serial.print("X"); + } + Serial.println(); + + for (uint8_t i = 0; i < 50; i++) rxBuffer[i] = 0; + } + else Serial.println("No data received"); + } +} + + +void setup() +{ + Serial.begin(57600); + delay(50); + + while (!Serial){}; + Serial.print("Test of NeoSoftwareSerial at "); + Serial.println(BAUD); + + HW_STREAM.begin(BAUD); + delay(50); + + nss.begin(BAUD); + delay(50); + + waitForReady(FIRST_SENDER); + + if (FIRST_SENDER) + { + Serial.println("I am sending data over NSS"); + sendOrRecieve(sentence1, true, &nss, "NSS"); + sendOrRecieve(sentence2, true, &nss, "NSS"); + sendOrRecieve(sentence3, true, &nss, "NSS"); + sendOrRecieve(alphabet1, true, &nss, "NSS"); + sendOrRecieve(alphabet2, true, &nss, "NSS"); + Serial.println(); + + Serial.println("I am listening for data on NSS"); + sendOrRecieve(sentence1, false, &nss, "NSS"); + sendOrRecieve(sentence2, false, &nss, "NSS"); + sendOrRecieve(sentence3, false, &nss, "NSS"); + sendOrRecieve(alphabet1, false, &nss, "NSS"); + sendOrRecieve(alphabet2, false, &nss, "NSS"); + Serial.println(); + + Serial.println("I am listening on Hardware Serial for data from NSS"); + sendOrRecieve(sentence1, false, &HW_STREAM, "HWS"); + sendOrRecieve(sentence2, false, &HW_STREAM, "HWS"); + sendOrRecieve(sentence3, false, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet1, false, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet2, false, &HW_STREAM, "HWS"); + Serial.println(); + + Serial.println("I am sending data to NSS from Hardware Serial"); + sendOrRecieve(sentence1, true, &HW_STREAM, "HWS"); + sendOrRecieve(sentence2, true, &HW_STREAM, "HWS"); + sendOrRecieve(sentence3, true, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet1, true, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet2, true, &HW_STREAM, "HWS"); + Serial.println(); + + Serial.println("Complete!"); + } + + else + { + Serial.println("I am listening on Hardware Serial for data from NSS"); + sendOrRecieve(sentence1, false, &HW_STREAM, "HWS"); + sendOrRecieve(sentence2, false, &HW_STREAM, "HWS"); + sendOrRecieve(sentence3, false, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet1, false, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet2, false, &HW_STREAM, "HWS"); + Serial.println(); + + Serial.println("I am sending data to NSS from Hardware Serial"); + sendOrRecieve(sentence1, true, &HW_STREAM, "HWS"); + sendOrRecieve(sentence2, true, &HW_STREAM, "HWS"); + sendOrRecieve(sentence3, true, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet1, true, &HW_STREAM, "HWS"); + sendOrRecieve(alphabet2, true, &HW_STREAM, "HWS"); + Serial.println(); + + Serial.println("I am sending data over NSS"); + sendOrRecieve(sentence1, true, &nss, "NSS"); + sendOrRecieve(sentence2, true, &nss, "NSS"); + sendOrRecieve(sentence3, true, &nss, "NSS"); + sendOrRecieve(alphabet1, true, &nss, "NSS"); + sendOrRecieve(alphabet2, true, &nss, "NSS"); + Serial.println(); + + Serial.println("I am listening for data on NSS"); + sendOrRecieve(sentence1, false, &nss, "NSS"); + sendOrRecieve(sentence2, false, &nss, "NSS"); + sendOrRecieve(sentence3, false, &nss, "NSS"); + sendOrRecieve(alphabet1, false, &nss, "NSS"); + sendOrRecieve(alphabet2, false, &nss, "NSS"); + Serial.println(); + + Serial.println("Complete!"); + } +} + +void loop(){} diff --git a/tests/RxTest/RxTest.ino b/tests/RxTest/RxTest.ino index f536ce1..8c772dc 100644 --- a/tests/RxTest/RxTest.ino +++ b/tests/RxTest/RxTest.ino @@ -1,7 +1,7 @@ #include #include -#define BAUD 57600 +#define BAUD 38400 NeoSWSerial nss( 10, 11 ); @@ -22,56 +22,56 @@ void setup(){ } void loop() { - // char endline = '\n'; - // String readstr = Serial1.readStringUntil(endline); - // if (readstr.length() > 0) - // { - // Serial.print("Serial1 - "); - // Serial.println(readstr); - // } - // else Serial.println("Serial1 - no data"); - // - // String readstr2 = nss.readStringUntil(endline); - // if (readstr2.length() > 0) - // { - // Serial.print(" NSS - "); - // Serial.println(readstr2); - // } - // else Serial.println(" NSS - no data"); - - char readSer, readNSS; - readSer = Serial1.read(); - readNSS = nss.read(); - - if (readSer > 0 and readNSS > 0) - { - Serial.print(readSer); - Serial.print(" ("); - Serial.print(readSer, HEX); - Serial.print(")"); - Serial.print(" - "); - Serial.print(readNSS); - Serial.print(" ("); - Serial.print(readNSS, HEX); - Serial.print(")"); - Serial.println(); - } - else if (readSer > 0) + char endline = '\n'; + String readstr = Serial1.readStringUntil(endline); + if (readstr.length() > 0) { - Serial.print(readSer); - Serial.print(" ("); - Serial.print(readSer, HEX); - Serial.print(")"); - Serial.print(" - ? (##)"); - Serial.println(); + Serial.print("Serial1 - "); + Serial.println(readstr); } - else if (readNSS > 0) + else Serial.println("Serial1 - no data"); + + String readstr2 = nss.readStringUntil(endline); + if (readstr2.length() > 0) { - Serial.print("? (##) - "); - Serial.print(readNSS); - Serial.print(" ("); - Serial.print(readNSS, HEX); - Serial.print(")"); - Serial.println(); + Serial.print(" NSS - "); + Serial.println(readstr2); } + else Serial.println(" NSS - no data"); + + // char readSer, readNSS; + // readSer = Serial1.read(); + // readNSS = nss.read(); + // + // if (readSer > 0 and readNSS > 0) + // { + // Serial.print(readSer); + // Serial.print(" ("); + // Serial.print(readSer, HEX); + // Serial.print(")"); + // Serial.print(" - "); + // Serial.print(readNSS); + // Serial.print(" ("); + // Serial.print(readNSS, HEX); + // Serial.print(")"); + // Serial.println(); + // } + // else if (readSer > 0) + // { + // Serial.print(readSer); + // Serial.print(" ("); + // Serial.print(readSer, HEX); + // Serial.print(")"); + // Serial.print(" - ? (##)"); + // Serial.println(); + // } + // else if (readNSS > 0) + // { + // Serial.print("? (##) - "); + // Serial.print(readNSS); + // Serial.print(" ("); + // Serial.print(readNSS, HEX); + // Serial.print(")"); + // Serial.println(); + // } } From 19a426678caf9cacb2f9e9502df5e72feb527ee2 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Fri, 18 May 2018 12:57:16 -0400 Subject: [PATCH 06/33] Added peak and unsetting prescalers at ignore Also some of my notes on the Rx ISR --- .gitignore | 8 +++ src/NeoSWSerial.cpp | 150 +++++++++++++++++++++++++++++++------------- src/NeoSWSerial.h | 14 ++--- 3 files changed, 120 insertions(+), 52 deletions(-) diff --git a/.gitignore b/.gitignore index 96374c4..b86373e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,11 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk + +# Atom / PlatformIO +.pioenvs +.piolibdeps +.clang_complete +.gcc-flags.json +lib/readme.txt +platformio.ini diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index ce8edfe..559a93e 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -42,17 +42,20 @@ static const uint8_t BITS_PER_TICK_31250_Q10 = 128; static const uint8_t BITS_PER_TICK_38400_Q10 = 157; // 1s/(38400 bits) * (1 tick)/(4 us) * 2^10 "multiplier" +// Choose the timer to use #if F_CPU == 16000000L - #define TCNTX TCNT0 + #define TCNTX TCNT0 // 8-bit timer w/ PWM, default prescaler has divisor of 64, thus 250kHz #define PCI_FLAG_REGISTER PCIFR + #elif F_CPU == 8000000L #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) - #define TCNTX TCNT1 + defined(__AVR_ATtiny85__) + #define TCNTX TCNT1 // 8-bit timer/counter w/ independent prescaler #define PCI_FLAG_REGISTER GIFR #else - #define TCNTX TCNT2 + // Have to use timer 2 for an 8 MHz system because timer 0 doesn't have the correct prescaler + #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous opperation, and independent prescaler #define PCI_FLAG_REGISTER PCIFR #endif #endif @@ -77,6 +80,11 @@ static uint8_t rxTail; // buffer pointer output static uint8_t rxBitMask, txBitMask; // port bit masks static volatile uint8_t *txPort; // port register +// Timer control registers, so we can un-set changes at end() +uint8_t preNSWS_TCCR1; +uint8_t preNSWS_TCCR2A; +uint8_t preNSWS_TCCR2B; + //#define DEBUG_NEOSWSERIAL #ifdef DEBUG_NEOSWSERIAL @@ -145,15 +153,21 @@ void NeoSWSerial::listen() *txPort |= txBitMask; // high = idle pinMode(txPin, OUTPUT); + // Set the timer prescaling as necessary - want to be running at 250kHz if (F_CPU == 8000000L) { // Have to use timer 2 for an 8 MHz system. #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) - TCCR1 = 0x06; // divide by 32 + defined(__AVR_ATtiny85__) + preNSWS_TCCR1 = TCCR1; + TCCR1 = 0x06; // 0b00000110 - Clock Select bits 12 & 11 on - prescaling source = CK/32 + // timer now running at 8MHz/32 = 250kHz #else - TCCR2A = 0x00; - TCCR2B = 0x03; // divide by 32 + preNSWS_TCCR2A = TCCR2A; + preNSWS_TCCR2B = TCCR2B; + TCCR2A = 0x00; // "normal" operation - Normal port operation, OC2A & OC2B disconnected + TCCR2B = 0x03; // 0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32 + // timer now running at 8MHz/32 = 250kHz #endif } @@ -164,7 +178,7 @@ void NeoSWSerial::listen() flush(); // Set up timings based on baud rate - + switch (_baudRate) { case 9600: txBitWidth = TICKS_PER_BIT_9600 ; @@ -225,6 +239,18 @@ void NeoSWSerial::ignore() SREG = prevSREG; } + if (F_CPU == 8000000L) { + // Un-set the timer pre-scalers + #if defined(__AVR_ATtiny25__) | \ + defined(__AVR_ATtiny45__) | \ + defined(__AVR_ATtiny85__) + TCCR1 = preNSWS_TCCR1; + #else + TCCR2A = preNSWS_TCCR2A; + TCCR2B = preNSWS_TCCR2B; + #endif + } + } // ignore //---------------------------------------------------------------------------- @@ -252,7 +278,7 @@ void NeoSWSerial::setBaudRate(uint16_t baudRate) int NeoSWSerial::available() { uint8_t avail = ((rxHead - rxTail + RX_BUFFER_SIZE) % RX_BUFFER_SIZE); - + if (avail == 0) { cli(); if (checkRxTime()) { @@ -268,13 +294,21 @@ int NeoSWSerial::available() //---------------------------------------------------------------------------- +int NeoSWSerial::peek() +{ + if (rxHead == rxTail) return -1; // Empty buffer? If yes, -1 + return rxBuffer[rxHead]; // Otherwise, read from "head" +} // peek + +//---------------------------------------------------------------------------- + int NeoSWSerial::read() { - if (rxHead == rxTail) return -1; - uint8_t c = rxBuffer[rxTail]; - rxTail = (rxTail + 1) % RX_BUFFER_SIZE; + if (rxHead == rxTail) return -1; // Empty buffer? If yes, -1 + uint8_t c = rxBuffer[rxTail]; // Otherwise, grab char at head + rxTail = (rxTail + 1) % RX_BUFFER_SIZE; // increment head - return c; + return c; // return the char } // read @@ -305,62 +339,88 @@ void NeoSWSerial::startChar() void NeoSWSerial::rxISR( uint8_t rxPort ) { - uint8_t t0 = TCNTX; // time of data transition (plus ISR latency) + uint8_t t0 = TCNTX; // time of data transition (plus ISR latency) uint8_t d = rxPort & rxBitMask; // read RX data level + // Check if we're ready for a start bit, and if this could possibly be it + // Otherwise, just ignore the interrupt and exit if (rxState == WAITING_FOR_START_BIT) { - - // If it looks like a start bit then initialize; - // otherwise ignore the rising edge and exit. - - if (d != 0) return; // it's high so not a start bit, exit + // If it is HIGH it's not a start bit, exit + if (d != 0) return; + // If it is LOW, this should be a start bit + // Thus set the rxStat to 0, create an empty character, and a new mask with a 1 in the lowest place startChar(); - } else { // data bit or stop bit (probably) received + } - DBG_NSS_ARRAY(bitTransitionTimes, bitTransitions, (t0-prev_t0)); + // if the character is incomplete, and this is not a start bit, + // then this change is from a data or stop bit + else { - // Determine how many bit periods have elapsed since the last transition. + DBG_NSS_ARRAY(bitTransitionTimes, bitTransitions, (t0-prev_t0)); + // check how many bit times have passed since the last change + // the rxWindowWidth is just a fudge factor uint16_t rxBits = bitTimes( t0-prev_t0 ); - uint8_t bitsLeft = 9 - rxState; // ignores stop bit + // calculate how many *data* bits should be left + // We know the start bit is past and are ignoring the stop bit + uint8_t bitsLeft = 9 - rxState; + // note that a new character *may* have started if more bits have been + // received than should be left. + // This will also happen if last bit(s) of the character are all 0's. bool nextCharStarted = (rxBits > bitsLeft); if (nextCharStarted) DBG_NSS_ARRAY(rxStartCompletionBits,rxStartCompletions,(10*rxBits + bitsLeft)); - uint8_t bitsThisFrame = nextCharStarted ? bitsLeft : rxBits; + // check how many data bits have been sent in this frame + // If the total number of bits in this frame is more than the number of data + // bits remaining in the character, then the number of data bits is equal + // to the number of bits remaining for the character and partiy. If the total + // number of bits in this frame is less than the number of data bits left + // for the character and parity, then the number of data bits received + // in this frame is equal to the total number of bits received in this frame. + // translation: + // if nextCharStarted then bitsThisFrame = bitsLeft + // else bitsThisFrame = rxBits + uint8_t bitsThisFrame = nextCharStarted ? bitsLeft : rxBits; + // Tick up the rxState by that many bits rxState += bitsThisFrame; - // Set all those bits - + // Set all the bits received between the last change and this change + // If the current state is LOW (and it just became so), then all bits between + // the last change and now must have been HIGH. if (d == 0) { // back fill previous bits with 1's while (bitsThisFrame-- > 0) { - rxValue |= rxMask; - rxMask = rxMask << 1; + rxValue |= rxMask; // Add a 1 to the LSB/right-most place + rxMask = rxMask << 1;; // Shift the 1 in the mask up by one position } - rxMask = rxMask << 1; - } else { // d==1 + rxMask = rxMask << 1; // Shift the 1 in the mask up by one more position + } + // If the current state is HIGH (and it just became so), then this bit is HIGH + // but all bits between the last change and now must have been LOW + else { // d==1 // previous bits were 0's so only this bit is a 1. - rxMask = rxMask << (bitsThisFrame-1); - rxValue |= rxMask; + rxMask = rxMask << (bitsThisFrame-1); // Shift the 1 in the mask up by the number of bits past + rxValue |= rxMask; // Add that shifted one to the character being created } // If 8th bit or stop bit then the character is complete. if (rxState > 7) { - rxChar( rxValue ); + rxChar( rxValue ); // Put the finished character into the buffer + // if this is HIGH, or we haven't exceeded the number of bits in a + // character (but have gotten all the data bits) then this should be a + // stop bit and we can start looking for a new start bit. if ((d == 1) || !nextCharStarted) { - rxState = WAITING_FOR_START_BIT; - // DISABLE STOP BIT TIMER - + rxState = WAITING_FOR_START_BIT; // DISABLE STOP BIT TIMER } else { - // The last char ended with 1's, so this 0 is actually - // the start bit of the next character. - + // If we just switched to LOW, or we've exceeded the total number of + // bits in a character, then the character must have ended with 1's/HIGH, + // and this new 0/LOW is actually the start bit of the next character. startChar(); } } @@ -457,13 +517,13 @@ void NeoSWSerial::rxChar( uint8_t c ) #elif defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ - defined(__AVR_ATtiny85__) + defined(__AVR_ATtiny85__) PCINT_ISR(0, PINB); #elif defined(__AVR_ATtiny24__) | \ defined(__AVR_ATtiny44__) | \ - defined(__AVR_ATtiny84__) + defined(__AVR_ATtiny84__) PCINT_ISR(0, PINA); PCINT_ISR(1, PINB); @@ -535,9 +595,9 @@ size_t NeoSWSerial::write(uint8_t txChar) uint8_t t0 = TCNTX; // start time - // TODO: This would benefit from an early break after + // TODO: This would benefit from an early break after // the last 0 data bit. Then we could wait for the - // remaining 1 data bits and stop bit with interrupts + // remaining 1 data bits and stop bit with interrupts // re-enabled. while (txBit++ < 9) { // repeat for start bit + 8 data bits @@ -551,7 +611,7 @@ size_t NeoSWSerial::write(uint8_t txChar) (width == TICKS_PER_BIT_9600/4) && (txBit & 0x01)) { // The width is 6.5 ticks, so add a tick every other bit - width++; + width++; } // Hold the line for the bit duration diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 1e54499..674aa01 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -24,8 +24,8 @@ // This software serial library is intended as a more-efficient replacement // for SoftwareSerial at baud rates 9600, 19200 and 38400. // -// Any of the pins supported by SoftwareSerial may be used. Pins (0-19) -// on the Uno may be used. Other boards can use any of the pins +// Any of the pins supported by SoftwareSerial may be used. Pins (0-19) +// on the Uno may be used. Other boards can use any of the pins // allowed by digitalPinToPCMSK in pins_arduino.h // // This code uses a pin change interrupt on the selected RX pin. @@ -42,9 +42,9 @@ // Supported baud rates are 9600 (default), 19200 and 38400. // The baud rate is selectable at run time. // -// The size of the RX buffer may be changed by editing the -// accompanying .cpp file. For optimal performance of the interrupt -// service routines, the buffer size should be chosen to be a +// The size of the RX buffer may be changed by editing the +// accompanying .cpp file. For optimal performance of the interrupt +// service routines, the buffer size should be chosen to be a // power of 2 (i.e., 2, 4, 8, 16, 32, 64,...). // // v1.0 Nov 2014 jboyton - Created @@ -75,12 +75,12 @@ class NeoSWSerial : public Stream void begin(uint16_t baudRate=9600); // initialize, set baudrate, listen void listen(); // enable RX interrupts void ignore(); // disable RX interrupts - void setBaudRate(uint16_t baudRate); // 9600 [default], 19200, 38400 + void setBaudRate(uint16_t baudRate); // 9600 [default], 19200, 31250, 38400 virtual int available(); virtual int read(); virtual size_t write(uint8_t txChar); using Stream::write; // make the base class overloads visible - virtual int peek() { return 0; }; + virtual int peek(); virtual void flush() {}; void end() { ignore(); } From cc1f99e79fddec4c403fb85302d3d84520ccdff4 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Fri, 18 May 2018 13:09:25 -0400 Subject: [PATCH 07/33] Interrupts off by default --- src/NeoSWSerial.cpp | 22 +++++++++++++++++----- src/NeoSWSerial.h | 2 +- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 6bfea08..15f4f1d 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -53,14 +53,25 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; defined(__AVR_ATtiny85__) #define TCNTX TCNT1 // 8-bit timer/counter w/ independent prescaler #define PCI_FLAG_REGISTER GIFR + uint8_t preNSWS_TCCR1; + #elif defined(__AVR_ATmega32U4__) #define TCNTX TCNT4 // 10-bit high speed timer, usable as 8-bit timer by ignoring high bits #define PCI_FLAG_REGISTER PCIFR + uint8_t preNSWS_TCCR4A; + uint8_t preNSWS_TCCR4B; + uint8_t preNSWS_TCCR4C; + uint8_t preNSWS_TCCR4D; + uint8_t preNSWS_TCCR4E; + #else // Have to use timer 2 for an 8 MHz system because timer 0 doesn't have the correct prescaler #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous opperation, and independent prescaler #define PCI_FLAG_REGISTER PCIFR + uint8_t preNSWS_TCCR2A; + uint8_t preNSWS_TCCR2B; #endif + #endif static NeoSWSerial *listener = (NeoSWSerial *) NULL; @@ -83,11 +94,6 @@ static uint8_t rxTail; // buffer pointer output static uint8_t rxBitMask, txBitMask; // port bit masks static volatile uint8_t *txPort; // port register -// Timer control registers, so we can un-set changes at end() -uint8_t preNSWS_TCCR1; -uint8_t preNSWS_TCCR2A; -uint8_t preNSWS_TCCR2B; - //#define DEBUG_NEOSWSERIAL #ifdef DEBUG_NEOSWSERIAL @@ -247,6 +253,12 @@ void NeoSWSerial::ignore() defined(__AVR_ATtiny45__) | \ defined(__AVR_ATtiny85__) TCCR1 = preNSWS_TCCR1; + #elif defined(__AVR_ATmega32U4__) + TCCR4A = preNSWS_TCCR4A; + TCCR4B = preNSWS_TCCR4B; + TCCR4C = preNSWS_TCCR4C; + TCCR4D = preNSWS_TCCR4D; + TCCR4E = preNSWS_TCCR4E; #else TCCR2A = preNSWS_TCCR2A; TCCR2B = preNSWS_TCCR2B; diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 674aa01..5872ef0 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -103,7 +103,7 @@ class NeoSWSerial : public Stream public: // visible only so the ISRs can call it... - static void rxISR( uint8_t port_input_register ); + // static void rxISR( uint8_t port_input_register ); //#define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs }; From 8738faf0b2c085f03a9b15549d9390d101c894e1 Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Fri, 18 May 2018 13:14:26 -0400 Subject: [PATCH 08/33] Oops, uncommented the wrong line! --- src/NeoSWSerial.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 5872ef0..b003e58 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -103,8 +103,8 @@ class NeoSWSerial : public Stream public: // visible only so the ISRs can call it... - // static void rxISR( uint8_t port_input_register ); + static void rxISR( uint8_t port_input_register ); - //#define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs + #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs }; #endif From 283da332c4844e76a61fc5fbf50fb01e9622966b Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Mon, 21 May 2018 11:48:54 -0400 Subject: [PATCH 09/33] Fixed some comments --- src/NeoSWSerial.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 15f4f1d..a6220c1 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -53,23 +53,23 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; defined(__AVR_ATtiny85__) #define TCNTX TCNT1 // 8-bit timer/counter w/ independent prescaler #define PCI_FLAG_REGISTER GIFR - uint8_t preNSWS_TCCR1; + static uint8_t preNSWS_TCCR1; #elif defined(__AVR_ATmega32U4__) #define TCNTX TCNT4 // 10-bit high speed timer, usable as 8-bit timer by ignoring high bits #define PCI_FLAG_REGISTER PCIFR - uint8_t preNSWS_TCCR4A; - uint8_t preNSWS_TCCR4B; - uint8_t preNSWS_TCCR4C; - uint8_t preNSWS_TCCR4D; - uint8_t preNSWS_TCCR4E; + static uint8_t preNSWS_TCCR4A; + static uint8_t preNSWS_TCCR4B; + static uint8_t preNSWS_TCCR4C; + static uint8_t preNSWS_TCCR4D; + static uint8_t preNSWS_TCCR4E; #else // Have to use timer 2 for an 8 MHz system because timer 0 doesn't have the correct prescaler - #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous opperation, and independent prescaler + #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous operation, and independent prescaler #define PCI_FLAG_REGISTER PCIFR - uint8_t preNSWS_TCCR2A; - uint8_t preNSWS_TCCR2B; + static uint8_t preNSWS_TCCR2A; + static uint8_t preNSWS_TCCR2B; #endif #endif @@ -311,7 +311,7 @@ int NeoSWSerial::available() int NeoSWSerial::peek() { if (rxHead == rxTail) return -1; // Empty buffer? If yes, -1 - return rxBuffer[rxHead]; // Otherwise, read from "head" + return rxBuffer[rxTail]; // Otherwise, read from "tail" } // peek //---------------------------------------------------------------------------- @@ -319,8 +319,8 @@ int NeoSWSerial::peek() int NeoSWSerial::read() { if (rxHead == rxTail) return -1; // Empty buffer? If yes, -1 - uint8_t c = rxBuffer[rxTail]; // Otherwise, grab char at head - rxTail = (rxTail + 1) % RX_BUFFER_SIZE; // increment head + uint8_t c = rxBuffer[rxTail]; // Otherwise, grab char at tail + rxTail = (rxTail + 1) % RX_BUFFER_SIZE; // increment tail return c; // return the char From 63f17a15148d8eff9b7ab0e584c782df44d4d5fb Mon Sep 17 00:00:00 2001 From: SRGDamia1 Date: Mon, 21 May 2018 11:58:43 -0400 Subject: [PATCH 10/33] Added missed setting of TCCR's --- src/NeoSWSerial.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index a6220c1..1fc7564 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -164,12 +164,19 @@ void NeoSWSerial::listen() // Set the timer prescaling as necessary - want to be running at 250kHz if (F_CPU == 8000000L) { + // Have to use timer 2 for an 8 MHz system. #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ defined(__AVR_ATtiny85__) + preNSWS_TCCR1 = TCCR1; TCCR1 = 0x06; // 0b00000110 - Clock Select bits 12 & 11 on - prescaling source = CK/32 // timer now running at 8MHz/32 = 250kHz #elif defined(__AVR_ATmega32U4__) + preNSWS_TCCR4A = TCCR4A; + preNSWS_TCCR4B = TCCR4B; + preNSWS_TCCR4C = TCCR4C; + preNSWS_TCCR4D = TCCR4D; + preNSWS_TCCR4D = TCCR4E; TCCR4A = 0x00; // "normal" operation - Normal port operation, OC4A & OC4B disconnected TCCR4B = 0x06; // 0b00000110 - Clock Select bits 42 & 41 on - prescaler set to CK/32 // timer now running at 8MHz/32 = 250kHz @@ -177,6 +184,8 @@ void NeoSWSerial::listen() TCCR4D = 0x00; // No fault protection TCCR4E = 0x00; // No register locks or overrides #else + preNSWS_TCCR2A = TCCR2A; + preNSWS_TCCR2B = TCCR2B; TCCR2A = 0x00; // "normal" operation - Normal port operation, OC2A & OC2B disconnected TCCR2B = 0x03; // 0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32 // timer now running at 8MHz/32 = 250kHz From 66f45087fcb2b15d8620a8c9981ab57ff9ad3747 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Tue, 8 Jan 2019 15:51:02 -0500 Subject: [PATCH 11/33] Default take ISR --- src/NeoSWSerial.cpp | 28 ++++++++++++++-------------- src/NeoSWSerial.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 1fc7564..fb0ca71 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -201,26 +201,26 @@ void NeoSWSerial::listen() // Set up timings based on baud rate switch (_baudRate) { - case 38400: - txBitWidth = TICKS_PER_BIT_9600 >> 2; - bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; - rxWindowWidth = 4; - break; + case 9600: // default is 9600 + txBitWidth = TICKS_PER_BIT_9600 ; + bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 2; + rxWindowWidth = 10; + break; case 31250: - txBitWidth = TICKS_PER_BIT_31250; - bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; - rxWindowWidth = 5; - break; + txBitWidth = TICKS_PER_BIT_31250; + bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; + rxWindowWidth = 5; + break; + case 38400: + txBitWidth = TICKS_PER_BIT_9600 >> 2; + bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; + rxWindowWidth = 4; + break; case 19200: txBitWidth = TICKS_PER_BIT_9600 >> 1; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 1; rxWindowWidth = 6; break; - case 9600: // default is 9600 - txBitWidth = TICKS_PER_BIT_9600 ; - bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 2; - rxWindowWidth = 10; - break; } // Enable the pin change interrupts diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index b003e58..514acee 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -105,6 +105,6 @@ class NeoSWSerial : public Stream // visible only so the ISRs can call it... static void rxISR( uint8_t port_input_register ); - #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs + // #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs }; #endif From 2251940710b9b889663cf527a76da653ad50d323 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 12:53:48 -0500 Subject: [PATCH 12/33] Travis on more boards --- .travis.yml | 2 +- src/NeoSWSerial.cpp | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e873f5..7a8c776 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,4 +14,4 @@ install: - pip install -U platformio script: - - platformio ci --lib="." --board=uno --board=megaatmega2560 --board=mayfly --board=feather32u4 + - platformio ci --lib="." --board=uno --board=feather328p --board=megaatmega2560 --board=sparkfun_megapro8MHz --board=leonardo --board=feather32u4 --board=trinket5 --board=gemma --board=attiny25 --board=attiny45 --board=mayfly diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index fb0ca71..5e8caa0 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -45,19 +45,20 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; // Choose the timer to use #if F_CPU == 16000000L #define TCNTX TCNT0 // 8-bit timer w/ PWM, default prescaler has divisor of 64, thus 250kHz - #define PCI_FLAG_REGISTER PCIFR + #define PCI_FLAG_REGISTER PCIFR // Pin change interrupt flag register +// Have to use alternate timer for an 8 MHz system because timer 0 doesn't have the correct prescaler #elif F_CPU == 8000000L #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ defined(__AVR_ATtiny85__) #define TCNTX TCNT1 // 8-bit timer/counter w/ independent prescaler - #define PCI_FLAG_REGISTER GIFR + #define PCI_FLAG_REGISTER GIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR1; #elif defined(__AVR_ATmega32U4__) #define TCNTX TCNT4 // 10-bit high speed timer, usable as 8-bit timer by ignoring high bits - #define PCI_FLAG_REGISTER PCIFR + #define PCI_FLAG_REGISTER PCIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR4A; static uint8_t preNSWS_TCCR4B; static uint8_t preNSWS_TCCR4C; @@ -65,14 +66,13 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; static uint8_t preNSWS_TCCR4E; #else - // Have to use timer 2 for an 8 MHz system because timer 0 doesn't have the correct prescaler #define TCNTX TCNT2 // 8-bit timer w/ PWM, asynchronous operation, and independent prescaler - #define PCI_FLAG_REGISTER PCIFR + #define PCI_FLAG_REGISTER PCIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR2A; static uint8_t preNSWS_TCCR2B; - #endif + #endif // F_CPU == 8000000L -#endif +#endif // F_CPU == 16000000L static NeoSWSerial *listener = (NeoSWSerial *) NULL; From 3cdc90dc78ad5ef48778ea8f7132a58f96ae667f Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:06:41 -0500 Subject: [PATCH 13/33] Move tests --- .travis.yml | 1 + .../DebugTest/DebugTest.ino => test/test.ino | 0 tests/PairedTestNSS/PairedTestNSS.ino | 178 ------------------ tests/RxTest/RxTest.ino | 77 -------- 4 files changed, 1 insertion(+), 255 deletions(-) rename tests/DebugTest/DebugTest.ino => test/test.ino (100%) delete mode 100644 tests/PairedTestNSS/PairedTestNSS.ino delete mode 100644 tests/RxTest/RxTest.ino diff --git a/.travis.yml b/.travis.yml index 7a8c776..0968b3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ python: sudo: false cache: + pip: true directories: - "~/.platformio" diff --git a/tests/DebugTest/DebugTest.ino b/test/test.ino similarity index 100% rename from tests/DebugTest/DebugTest.ino rename to test/test.ino diff --git a/tests/PairedTestNSS/PairedTestNSS.ino b/tests/PairedTestNSS/PairedTestNSS.ino deleted file mode 100644 index 6b0b724..0000000 --- a/tests/PairedTestNSS/PairedTestNSS.ino +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include - -#define BAUD 9600 -#define HW_STREAM Serial1 - -#if !defined(FIRST_SENDER) - #define FIRST_SENDER true -#endif - -NeoSWSerial nss( 10, 11 ); - -char sentence1[] = "Quick zephyrs blow, vexing daft Jim."; -char sentence2[] = "Sphinx of black quartz, judge my vow."; -char sentence3[] = "The quick brown fox jumps over the lazy dog."; -char alphabet1[] = "abcdefghijklmnopqrstuvwwxyz<>?:{}|~!@#$%^&*()_+"; -char alphabet2[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ,./;'[]\1234567890`-='"; -char rxBuffer[50]; - -void waitForReady(bool isSending) -{ - bool isStarted = false; - char rxByte[] = "2"; - Serial.println("Wait for ready"); - - if (isSending) - { - while (!isStarted) - { - nss.print("1"); // Continually print out ones - nss.readBytes(rxByte, 1); // Listen for a single returned one - if (rxByte[0] == '1') isStarted = true; - } - } - else - { - // Listening for the "1" to start on neosoftware serial - while (!isStarted) - { - HW_STREAM.readBytes(rxByte, 1); - if (rxByte[0] == '1') isStarted = true; - } - HW_STREAM.print("1"); // Send a single 1 to acknlowlege that it's ready - } -} - - -void sendOrRecieve(char sentence[], bool isSending, Stream *stream, String streamName) -{ - if (isSending) - { - delay(10); - stream->print(sentence); - stream->flush(); - } - else - { - Serial.print("Known: "); - Serial.println(sentence); - long start = millis(); - - while ((stream->available() < strlen(sentence)) and ((millis() - start) < 1000)){} - - if (stream->available()) - { - stream->readBytes(rxBuffer, strlen(sentence)); - Serial.print(streamName); - Serial.print(" Rcvd: "); - Serial.println(rxBuffer); - - Serial.print("Diff: "); - for (uint8_t i = 0; i < strlen(sentence); i++) - { - if (sentence[i] == rxBuffer[i]) Serial.print("-"); - else Serial.print("X"); - } - Serial.println(); - - for (uint8_t i = 0; i < 50; i++) rxBuffer[i] = 0; - } - else Serial.println("No data received"); - } -} - - -void setup() -{ - Serial.begin(57600); - delay(50); - - while (!Serial){}; - Serial.print("Test of NeoSoftwareSerial at "); - Serial.println(BAUD); - - HW_STREAM.begin(BAUD); - delay(50); - - nss.begin(BAUD); - delay(50); - - waitForReady(FIRST_SENDER); - - if (FIRST_SENDER) - { - Serial.println("I am sending data over NSS"); - sendOrRecieve(sentence1, true, &nss, "NSS"); - sendOrRecieve(sentence2, true, &nss, "NSS"); - sendOrRecieve(sentence3, true, &nss, "NSS"); - sendOrRecieve(alphabet1, true, &nss, "NSS"); - sendOrRecieve(alphabet2, true, &nss, "NSS"); - Serial.println(); - - Serial.println("I am listening for data on NSS"); - sendOrRecieve(sentence1, false, &nss, "NSS"); - sendOrRecieve(sentence2, false, &nss, "NSS"); - sendOrRecieve(sentence3, false, &nss, "NSS"); - sendOrRecieve(alphabet1, false, &nss, "NSS"); - sendOrRecieve(alphabet2, false, &nss, "NSS"); - Serial.println(); - - Serial.println("I am listening on Hardware Serial for data from NSS"); - sendOrRecieve(sentence1, false, &HW_STREAM, "HWS"); - sendOrRecieve(sentence2, false, &HW_STREAM, "HWS"); - sendOrRecieve(sentence3, false, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet1, false, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet2, false, &HW_STREAM, "HWS"); - Serial.println(); - - Serial.println("I am sending data to NSS from Hardware Serial"); - sendOrRecieve(sentence1, true, &HW_STREAM, "HWS"); - sendOrRecieve(sentence2, true, &HW_STREAM, "HWS"); - sendOrRecieve(sentence3, true, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet1, true, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet2, true, &HW_STREAM, "HWS"); - Serial.println(); - - Serial.println("Complete!"); - } - - else - { - Serial.println("I am listening on Hardware Serial for data from NSS"); - sendOrRecieve(sentence1, false, &HW_STREAM, "HWS"); - sendOrRecieve(sentence2, false, &HW_STREAM, "HWS"); - sendOrRecieve(sentence3, false, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet1, false, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet2, false, &HW_STREAM, "HWS"); - Serial.println(); - - Serial.println("I am sending data to NSS from Hardware Serial"); - sendOrRecieve(sentence1, true, &HW_STREAM, "HWS"); - sendOrRecieve(sentence2, true, &HW_STREAM, "HWS"); - sendOrRecieve(sentence3, true, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet1, true, &HW_STREAM, "HWS"); - sendOrRecieve(alphabet2, true, &HW_STREAM, "HWS"); - Serial.println(); - - Serial.println("I am sending data over NSS"); - sendOrRecieve(sentence1, true, &nss, "NSS"); - sendOrRecieve(sentence2, true, &nss, "NSS"); - sendOrRecieve(sentence3, true, &nss, "NSS"); - sendOrRecieve(alphabet1, true, &nss, "NSS"); - sendOrRecieve(alphabet2, true, &nss, "NSS"); - Serial.println(); - - Serial.println("I am listening for data on NSS"); - sendOrRecieve(sentence1, false, &nss, "NSS"); - sendOrRecieve(sentence2, false, &nss, "NSS"); - sendOrRecieve(sentence3, false, &nss, "NSS"); - sendOrRecieve(alphabet1, false, &nss, "NSS"); - sendOrRecieve(alphabet2, false, &nss, "NSS"); - Serial.println(); - - Serial.println("Complete!"); - } -} - -void loop(){} diff --git a/tests/RxTest/RxTest.ino b/tests/RxTest/RxTest.ino deleted file mode 100644 index 8c772dc..0000000 --- a/tests/RxTest/RxTest.ino +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include - -#define BAUD 38400 - -NeoSWSerial nss( 10, 11 ); - -void setup(){ - Serial.begin(57600); - delay(50); - - while (!Serial){}; - Serial.print("Test at "); - Serial.println(BAUD); - - Serial1.begin(BAUD); - delay(50); - - nss.begin(BAUD); - delay(50); - -} - -void loop() { - char endline = '\n'; - String readstr = Serial1.readStringUntil(endline); - if (readstr.length() > 0) - { - Serial.print("Serial1 - "); - Serial.println(readstr); - } - else Serial.println("Serial1 - no data"); - - String readstr2 = nss.readStringUntil(endline); - if (readstr2.length() > 0) - { - Serial.print(" NSS - "); - Serial.println(readstr2); - } - else Serial.println(" NSS - no data"); - - // char readSer, readNSS; - // readSer = Serial1.read(); - // readNSS = nss.read(); - // - // if (readSer > 0 and readNSS > 0) - // { - // Serial.print(readSer); - // Serial.print(" ("); - // Serial.print(readSer, HEX); - // Serial.print(")"); - // Serial.print(" - "); - // Serial.print(readNSS); - // Serial.print(" ("); - // Serial.print(readNSS, HEX); - // Serial.print(")"); - // Serial.println(); - // } - // else if (readSer > 0) - // { - // Serial.print(readSer); - // Serial.print(" ("); - // Serial.print(readSer, HEX); - // Serial.print(")"); - // Serial.print(" - ? (##)"); - // Serial.println(); - // } - // else if (readNSS > 0) - // { - // Serial.print("? (##) - "); - // Serial.print(readNSS); - // Serial.print(" ("); - // Serial.print(readNSS, HEX); - // Serial.print(")"); - // Serial.println(); - // } -} From eaaea5f7d8b205c3a5d5505d65dca2d55654428b Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:17:22 -0500 Subject: [PATCH 14/33] Example to compile against --- .travis.yml | 2 +- examples/passThrough/passThrough.ino | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 examples/passThrough/passThrough.ino diff --git a/.travis.yml b/.travis.yml index 0968b3b..0ad0d96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ cache: - "~/.platformio" env: - - PLATFORMIO_CI_SRC=test/test.ino + - PLATFORMIO_CI_SRC=examples/passThrough install: - pip install -U platformio diff --git a/examples/passThrough/passThrough.ino b/examples/passThrough/passThrough.ino new file mode 100644 index 0000000..31ad03f --- /dev/null +++ b/examples/passThrough/passThrough.ino @@ -0,0 +1,26 @@ +#include +#include + +#define BAUD 38400 + +NeoSWSerial nss( 10, 11 ); + +void setup(){ + Serial.begin(57600); + delay(50); + + while (!Serial){}; + + nss.begin(BAUD); + delay(50); + +} + +void loop() { + while (nss.available()) { + Serial.write(nss.read()); + } + while (Serial.available()) { + nss.write(Serial.read()); + } +} From a2dbb7849bcba06aa188295080c4a7bdac034e45 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:28:48 -0500 Subject: [PATCH 15/33] Fix timer pre-setting assignment --- .travis.yml | 2 +- src/NeoSWSerial.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ad0d96..807aca7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ install: - pip install -U platformio script: - - platformio ci --lib="." --board=uno --board=feather328p --board=megaatmega2560 --board=sparkfun_megapro8MHz --board=leonardo --board=feather32u4 --board=trinket5 --board=gemma --board=attiny25 --board=attiny45 --board=mayfly + - platformio ci --lib="." --board=uno --board=feather328p --board=megaatmega2560 --board=sparkfun_megapro8MHz --board=leonardo --board=feather32u4 --board=trinket5 --board=gemma --board=attiny25 --board=attiny45 --board=mightycore1284 --board=mayfly diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 5e8caa0..633c424 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -163,7 +163,7 @@ void NeoSWSerial::listen() pinMode(txPin, OUTPUT); // Set the timer prescaling as necessary - want to be running at 250kHz - if (F_CPU == 8000000L) { + #if F_CPU == 16000000L // Have to use timer 2 for an 8 MHz system. #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ @@ -190,7 +190,7 @@ void NeoSWSerial::listen() TCCR2B = 0x03; // 0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32 // timer now running at 8MHz/32 = 250kHz #endif - } + #endif volatile uint8_t *pcmsk = digitalPinToPCMSK(rxPin); if (pcmsk) { From 075f1e07a166710e7602ca2721aeabcb55c31985 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:49:08 -0500 Subject: [PATCH 16/33] Oops, wrong speeds --- src/NeoSWSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 633c424..919e263 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -163,7 +163,7 @@ void NeoSWSerial::listen() pinMode(txPin, OUTPUT); // Set the timer prescaling as necessary - want to be running at 250kHz - #if F_CPU == 16000000L + #if F_CPU == 8000000L // Have to use timer 2 for an 8 MHz system. #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ From 7046a6c3eebba3dd6f50cf8161a64eb449b69048 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:53:36 -0500 Subject: [PATCH 17/33] Missed ignore --- src/NeoSWSerial.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 919e263..a7208f6 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -70,9 +70,9 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; #define PCI_FLAG_REGISTER PCIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR2A; static uint8_t preNSWS_TCCR2B; - #endif // F_CPU == 8000000L + #endif -#endif // F_CPU == 16000000L +#endif static NeoSWSerial *listener = (NeoSWSerial *) NULL; @@ -256,7 +256,7 @@ void NeoSWSerial::ignore() SREG = prevSREG; } - if (F_CPU == 8000000L) { + #if F_CPU == 8000000L // Un-set the timer pre-scalers #if defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ @@ -272,7 +272,7 @@ void NeoSWSerial::ignore() TCCR2A = preNSWS_TCCR2A; TCCR2B = preNSWS_TCCR2B; #endif - } + #endif } // ignore From a51d57553ecb1e4ea2b2979904b3d2f63b6a5854 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 13:58:26 -0500 Subject: [PATCH 18/33] Skipping test on ATTINY --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 807aca7..caf501d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,4 @@ install: - pip install -U platformio script: - - platformio ci --lib="." --board=uno --board=feather328p --board=megaatmega2560 --board=sparkfun_megapro8MHz --board=leonardo --board=feather32u4 --board=trinket5 --board=gemma --board=attiny25 --board=attiny45 --board=mightycore1284 --board=mayfly + - platformio ci --lib="." --board=uno --board=feather328p --board=megaatmega2560 --board=sparkfun_megapro8MHz --board=leonardo --board=feather32u4 --board=mightycore1284 --board=mayfly From 67f1a7f2508f474b505507fadfe7b2bb34bbaa5d Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 9 Jan 2019 16:31:45 -0500 Subject: [PATCH 19/33] Removed unwanted comment --- src/NeoSWSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index a7208f6..be8afee 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -433,7 +433,7 @@ void NeoSWSerial::rxISR( uint8_t rxPort ) // If 8th bit or stop bit then the character is complete. if (rxState > 7) { - rxChar( rxValue ); // Put the finished character into the buffer + rxChar( rxValue ); // if this is HIGH, or we haven't exceeded the number of bits in a // character (but have gotten all the data bits) then this should be a From dcbdc48f1ae69f6137901d24d55987eec29703ac Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Fri, 11 Jan 2019 14:54:57 -0500 Subject: [PATCH 20/33] Get tests really working --- src/NeoSWSerial.cpp | 15 +- test/test.ino | 414 --------------------------------- tests/bounce/bounce.ino | 62 +++++ tests/test/test.ino | 501 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 570 insertions(+), 422 deletions(-) delete mode 100644 test/test.ino create mode 100644 tests/bounce/bounce.ino create mode 100644 tests/test/test.ino diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index be8afee..a6339b8 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -207,15 +207,14 @@ void NeoSWSerial::listen() rxWindowWidth = 10; break; case 31250: - txBitWidth = TICKS_PER_BIT_31250; - bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; - rxWindowWidth = 5; - break; + txBitWidth = TICKS_PER_BIT_31250; + bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; + rxWindowWidth = 5; + break; case 38400: - txBitWidth = TICKS_PER_BIT_9600 >> 2; - bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; - rxWindowWidth = 4; - break; + txBitWidth = TICKS_PER_BIT_9600 >> 2; + bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; + rxWindowWidth = 4; case 19200: txBitWidth = TICKS_PER_BIT_9600 >> 1; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 1; diff --git a/test/test.ino b/test/test.ino deleted file mode 100644 index 955ff22..0000000 --- a/test/test.ino +++ /dev/null @@ -1,414 +0,0 @@ -#include - -NeoSWSerial nss( 10, 11 ); - - uint16_t baudrate = 9600; - uint8_t rc[520]; - uint16_t received = 0; - uint16_t sent = 0; - -//--------------------------------------------------------------------- -//#define INTER_CHAR_TIME 50 -#define INTER_CHAR_TIME 0 - -//#define BITDUMP - -#ifdef BITDUMP - extern uint8_t bitTransitionTimes[]; - extern uint8_t bitTransitions; - struct rbd_t { uint8_t loop_bits; uint8_t mul_bits; uint16_t prod; }; - extern rbd_t diffRXbits[]; - extern uint8_t diffRXbitsCount; - - extern uint16_t availCompletions; - extern uint16_t rxStartCompletions; - extern uint8_t rxStartCompletionBits[]; - extern uint16_t checkRxCompletions; - extern uint16_t polledPCI; - extern uint16_t polledPCICompletions; - extern uint16_t stopBitCompletions; - extern uint16_t highBitWaits; -#endif - -//--------------------------------------------------------------------- - -static void dumpBits() -{ -#ifdef BITDUMP - for (uint8_t i=0; i 0) { - Serial.print( F(" (") ); - for (uint8_t i=0;;) { - Serial.print( diffRXbits[i].prod ); - Serial.print( ' ' ); - Serial.print( diffRXbits[i].mul_bits ); - Serial.print( F(" != ") ); - Serial.print( diffRXbits[i].loop_bits ); - i++; - if (i >= diffRXbitsCount) - break; - Serial.print( F(", ") ); - } - Serial.print( ')' ); - diffRXbitsCount = 0; - } -#endif -} // dumpDiffs - -//--------------------------------------------------------------------- - -static uint16_t errors = 0; - -void testOne( Stream & ins, Stream & outs, uint8_t c ) -{ - uint8_t pair[2]; - pair[0] = c; - pair[1] = c+1; - uint8_t len = 1; - outs.write( pair, len ); - if (INTER_CHAR_TIME < 10) - outs.flush(); - - static bool dotPrinted = false; - - uint8_t received = 0; - bool gotIt = false; - uint32_t start = millis(); - - do { - if (ins.available()) { - uint8_t received_c = ins.read(); - - dotPrinted = false; - - gotIt = (received_c == c); - - if (!gotIt || (INTER_CHAR_TIME > 10)) { - Serial.print( F("rx ") ); - if (received_c < 0x10) Serial.print( '0' ); - Serial.print( received_c, HEX ); - - if (!gotIt) { - Serial.print( F(" != tx ") ); - if (c < 0x10) Serial.print( '0' ); - Serial.print( 0xFF & (c), HEX ); - } - - if (received == 0) { - dumpBits(); - dumpDiffs(); - Serial.print( ' ' ); - } - } - - received++; - c++; - } - } while (millis() - start < INTER_CHAR_TIME); - - if (INTER_CHAR_TIME > 10) { - if (!received) { - Serial.print( '.' ); - dumpBits(); - dumpDiffs(); - Serial.println(); - dotPrinted = true; - } else - Serial.println(); - - Serial.flush(); - } - -} // testOne - -//--------------------------------------------------------------------- - -static void testTwo( uint8_t & c, uint8_t & received_c ) -{ - if (nss.available()) { - uint8_t rcActual = nss.read(); - if (rcActual != received_c) { - errors++; - Serial.print( F("rx ") ); - if (received_c < 0x10) Serial.print( '0' ); - Serial.print( 0xFF & rcActual, HEX ); - Serial.print( F(" != tx ") ); - if (received_c < 0x10) Serial.print( '0' ); - Serial.print( 0xFF & (received_c), HEX ); - dumpBits(); - dumpDiffs(); - Serial.println(); - } - received_c++; - } -} // testTwo - -//--------------------------------------------------------------------- - -static void printStats() -{ - if (received != sent) { - Serial.print( received ); - Serial.print( F(" received, ") ); - Serial.print( sent ); - Serial.println( F(" sent") ); - } - - Serial.print( errors ); - Serial.println( F(" errors") ); -#ifdef BITDUMP - Serial.print( rxStartCompletions ); - Serial.print( F(" RX start completions:") ); - for (uint16_t i=0; i < rxStartCompletions; i++) { - Serial.print( ' ' ); - Serial.print( rxStartCompletionBits[i] ); - } - Serial.println(); - - Serial.print( availCompletions ); - Serial.println( F(" available() completions") ); - Serial.print( checkRxCompletions ); - Serial.println( F(" checkRxTime completions") ); - Serial.print( polledPCI ); - Serial.println( F(" polled PCI detected") ); - Serial.print( polledPCICompletions ); - Serial.println( F(" polled PCI completions") ); - Serial.print( stopBitCompletions ); - Serial.println( F(" stop bit completions") ); - Serial.print( highBitWaits ); - Serial.println( F(" high bit waits") ); - - rxStartCompletions = 0; - availCompletions = 0; - checkRxCompletions = 0; - polledPCI = 0; - polledPCICompletions = 0; - stopBitCompletions = 0; - highBitWaits = 0; -#endif - - Serial.println( F("-----------------") ); - Serial.flush(); - - received = 0; - sent = 0; - errors = 0; - -} // printStats - -//--------------------------------------------------------------------- - -static void printRC() -{ - for (uint16_t i=0; i < received; i++) { - uint8_t c = rc[i]; - if (c < 0x10) Serial.print( '0' ); - Serial.print( 0xFF & (c), HEX ); - Serial.print( ' ' ); - if ((i & 0x1F) == 0x1F) - Serial.println(); - } - Serial.println(); -} // printRC - -//--------------------------------------------------------------------- - -void setup() { - //Initialize serial and wait for port to open: - Serial.begin(9600); - while (!Serial) - ; - - Serial1.begin( baudrate ); - delay( 10 ); - Serial1.print( 'U' ); - Serial1.flush(); - delay( 10 ); - - nss.begin( baudrate ); - -} // setup - -//--------------------------------------------------------------------- - -void loop() -{ - Serial.print( F("NeoSWSerial test @ ") ); - Serial.println( baudrate ); - Serial.flush(); - - Serial.println( F("Individual RX test") ); - Serial.flush(); - - uint8_t c=0; - do { - testOne( nss, Serial1, c ); - c++; - } while (c != 0); - testOne( nss, Serial1, c ); - uint32_t start = millis(); - while (millis() - start < 100) { - if (nss.available()) { - nss.read(); - start = millis(); - } - } - - printStats(); - - //===================================== - - Serial.println( F("RX test") ); - Serial.flush(); - - for (uint8_t times=0; times<1; times++) { - do { - Serial1.write( c++ ); - sent++; - if (nss.available()) - rc[ received++ ] = nss.read(); - } while (c != 0); - } - Serial1.write( c++ ); - sent++; - - start = millis(); - while (millis() - start < 100) { - if (nss.available()) { - rc[ received++ ] = nss.read(); - start = millis(); - } - } - - if (received < sent) { - Serial.print( sent-received ); - Serial.println( F(" chars dropped.") ); - } - printRC(); - - printStats(); - - //===================================== - - Serial.println( F("TX test") ); - Serial.flush(); - - for (uint16_t i=0; i<=256; i++) { - nss.write( (uint8_t) (i & 0xFF) ); - if (Serial1.available()) - rc[ received++ ] = Serial1.read(); - } - - start = millis(); - - uint32_t ms; - do { - ms = millis(); - if (Serial1.available()) { - start = ms; - rc[ received++ ] = Serial1.read(); - } - } while (ms - start < 100); - - printRC(); - - printStats(); - - //===================================== - - Serial.println( F("RX and TX test") ); - Serial.flush(); - - for (uint16_t i=0; i<=256; i++) { - Serial1.write( (uint8_t) i & 0xFF ); - if (nss.available()) { - c = nss.read(); - nss.write( c ); - } - if (Serial1.available()) - rc[ received++ ] = Serial1.read(); - } - - start = millis(); - - do { - ms = millis(); - if (nss.available()) { - start = ms; - c = nss.read(); - nss.write( c ); - } - if (Serial1.available()) { - start = ms; - rc[ received++ ] = Serial1.read(); - } - } while (ms - start < 100); - - printRC(); - - printStats(); - - //===================================== - - Serial.println( F("TX and RX test") ); - Serial.flush(); - - for (uint16_t i=0; i<=256; i++) { - nss.write( (uint8_t) i & 0xFF ); - if (Serial1.available()) { - c = Serial1.read(); - Serial1.write( c ); - } - while (nss.available()) - rc[ received++ ] = nss.read(); - } - - start = millis(); - - do { - ms = millis(); - if (Serial1.available()) { - start = ms; - c = Serial1.read(); - Serial1.write( c ); - } - while (nss.available()) { - start = ms; - rc[ received++ ] = nss.read(); - } - } while (ms - start < 100); - - printRC(); - - printStats(); - - //===================================== - - while (!Serial.available()) - ; - - do { - while (Serial.available()) { - Serial.read(); - start = millis(); - } - } while (millis() - start < 20); - - if (baudrate == 38400) - baudrate = 9600; - else - baudrate <<= 1; - nss.setBaudRate( baudrate ); - Serial1.begin( baudrate ); -} diff --git a/tests/bounce/bounce.ino b/tests/bounce/bounce.ino new file mode 100644 index 0000000..1e7b4e9 --- /dev/null +++ b/tests/bounce/bounce.ino @@ -0,0 +1,62 @@ +#include + +uint16_t baudrate = 9600; +HardwareSerial &checkStream1 = Serial1; +HardwareSerial &checkStream2 = Serial2; + +// prints a single character prettily +void printCharHex(uint8_t c) +{ + if (c < 0x10) Serial.print( '0' ); + Serial.print( 0xFF & (c), HEX ); + Serial.print( ' ' ); + if ((c & 0x0F) == 0x0F) + Serial.println(); + if ((c & 0xFF) == 0xFF) + Serial.println(); +} // printChar + +void setup(){ + Serial.begin(115200); + delay(50); + checkStream1.begin(baudrate); + delay(50); + checkStream2.begin(baudrate); + delay(50); + + Serial.print(F("Serial bouncer at ")); + Serial.println(baudrate); + +} + +void loop() { + if (checkStream1.available()) + { + uint8_t c = checkStream1.read(); + printCharHex(c); + checkStream1.write(c); + } + if (checkStream2.available()) + { + uint8_t c = checkStream2.read(); + printCharHex(c); + checkStream2.write(c); + } + + // if given input on serial, repeat everything at the next baud rate + if ( Serial.available() ) { + Serial.println(Serial.readString()); + + if (baudrate == 38400) + baudrate = 31250; + else if (baudrate == 31250) + baudrate = 9600; + else + baudrate <<= 1; + checkStream1.begin( baudrate ); + checkStream2.begin( baudrate ); + + Serial.print(F("Serial bouncer at ")); + Serial.println(baudrate); + } +} diff --git a/tests/test/test.ino b/tests/test/test.ino new file mode 100644 index 0000000..3619c67 --- /dev/null +++ b/tests/test/test.ino @@ -0,0 +1,501 @@ +#include + +NeoSWSerial nss( 10, 11 ); + +// NeoSWSerial nssCheck( 8, 9 ); +// NeoSWSerial &checkSerial = nssCheck; +HardwareSerial &checkSerial = Serial1; + + uint16_t baudrate = 9600; + uint8_t rc[770]; // Received character array + uint8_t sc[770]; // Sent character array - only for error checking + uint16_t received = 0; // # characters received + uint16_t sent = 0; // # characters sent + static uint16_t errors = 0; // # errors + +//--------------------------------------------------------------------- +#define INTER_CHAR_TIME 50 +// #define INTER_CHAR_TIME 0 + +//#define BITDUMP + +#ifdef BITDUMP + #define DEBUG_NEOSWSERIAL + extern uint8_t bitTransitionTimes[]; + extern uint8_t bitTransitions; + struct rbd_t { uint8_t loop_bits; uint8_t mul_bits; uint16_t prod; }; + extern rbd_t diffRXbits[]; + extern uint8_t diffRXbitsCount; + + extern uint16_t availCompletions; + extern uint16_t rxStartCompletions; + extern uint8_t rxStartCompletionBits[]; + extern uint16_t checkRxCompletions; + extern uint16_t polledPCI; + extern uint16_t polledPCICompletions; + extern uint16_t stopBitCompletions; + extern uint16_t highBitWaits; +#endif + +//--------------------------------------------------------------------- + +static void dumpBits() +{ +#ifdef BITDUMP + for (uint8_t i=0; i 0) { + Serial.print( F(" (") ); + for (uint8_t i=0;;) { + Serial.print( diffRXbits[i].prod ); + Serial.print( ' ' ); + Serial.print( diffRXbits[i].mul_bits ); + Serial.print( F(" != ") ); + Serial.print( diffRXbits[i].loop_bits ); + i++; + if (i >= diffRXbitsCount) + break; + Serial.print( F(", ") ); + } + Serial.print( ')' ); + diffRXbitsCount = 0; + } +#endif +} // dumpDiffs + + +void emptyBuffer ( Stream & ins ) { + uint32_t start = millis(); + while (millis() - start < 100) { + if (ins.available()) { + ins.read(); + start = millis(); + } + } +} + +//--------------------------------------------------------------------- + +// prints a single character prettily +void printCharHex(uint8_t c) +{ + if (c < 0x10) Serial.print( '0' ); + Serial.print( 0xFF & (c), HEX ); +} // printChar + +// prints the whole received character array +void printRC() +{ + Serial.println(F("Received: ")); + for (uint16_t i=0; i < received; i++) { + uint8_t c = rc[i]; + printCharHex(c); + Serial.print( ' ' ); + if ((i & 0x1F) == 0x1F) + Serial.println(); + } + Serial.println(); +} // printRC + +// prints the whole sent character array +void printSC() +{ + Serial.println(F("Sent: ")); + for (uint16_t i=0; i < sent; i++) { + uint8_t c = sc[i]; + printCharHex(c); + Serial.print( ' ' ); + if ((i & 0x1F) == 0x1F) + Serial.println(); + } + Serial.println(); +} // printSC + +// Checks for errors in the receive array vs the sc array +void checkRC() +{ + // printSC(); + // printRC(); + for (uint16_t i=0; i < received; i++) { + uint8_t cActual = rc[i]; + uint8_t cExpected = sc[i]; + if (cActual != cExpected) { + errors++; + // Serial.print( F("rx ") ); + // printCharHex(cActual); + // Serial.print( F(" != tx ") ); + // printCharHex(cExpected); + // Serial.println(); + } + } +} // checkRC + +static void printStats() +{ + if (received != sent) { + Serial.print( received ); + Serial.print( F(" received, ") ); + Serial.print( sent ); + Serial.println( F(" sent") ); + } + + Serial.print( errors ); + Serial.println( F(" errors") ); +#ifdef BITDUMP + Serial.print( rxStartCompletions ); + Serial.print( F(" RX start completions:") ); + for (uint16_t i=0; i < rxStartCompletions; i++) { + Serial.print( ' ' ); + Serial.print( rxStartCompletionBits[i] ); + } + Serial.println(); + + Serial.print( availCompletions ); + Serial.println( F(" available() completions") ); + Serial.print( checkRxCompletions ); + Serial.println( F(" checkRxTime completions") ); + Serial.print( polledPCI ); + Serial.println( F(" polled PCI detected") ); + Serial.print( polledPCICompletions ); + Serial.println( F(" polled PCI completions") ); + Serial.print( stopBitCompletions ); + Serial.println( F(" stop bit completions") ); + Serial.print( highBitWaits ); + Serial.println( F(" high bit waits") ); + + // Zero everything after we've printed it + rxStartCompletions = 0; + availCompletions = 0; + checkRxCompletions = 0; + polledPCI = 0; + polledPCICompletions = 0; + stopBitCompletions = 0; + highBitWaits = 0; +#endif + + Serial.println( F("-----------------") ); + Serial.flush(); + + // Zero everything after we've printed it + received = 0; + sent = 0; + errors = 0; + +} // printStats + + +//--------------------------------------------------------------------- + +// In the first round of testing, the sketch waits for the echo of each character. + +// With 2 Arduinos, this tests whether the send process works independently +// from the receive process (the 2nd Arduino echo doesn't begin until the 1st +// Arduino is done sending). +// With 1 Arduino + loopback wires, this tests whether the receive process works +// during the transmit process (each sent bit is simulataneously received). + +// And by incrementing the sent character, all byte values can be tested. + +void testOne( Stream & ins, Stream & outs, uint8_t c ) +{ + + // Write one character out and wait for it to finish + uint8_t pair[2]; + pair[0] = c; + pair[1] = c+1; + uint8_t len = 1; + outs.write( pair, len ); + if (INTER_CHAR_TIME < 10) + outs.flush(); + + uint8_t received = 0; + bool gotIt = false; + uint32_t start = millis(); + + do { + if (ins.available()) { + uint8_t received_c = ins.read(); + + gotIt = (received_c == c); + + if (!gotIt /*|| (INTER_CHAR_TIME > 10*/) { + Serial.print( F("rx ") ); + printCharHex(received_c); + + if (!gotIt) { + Serial.print( F(" != tx ") ); + printCharHex(c); + errors++; + } + + if (received == 0) { + dumpBits(); + dumpDiffs(); + Serial.print( ' ' ); + } + + Serial.println(); + } + + received++; + c++; + } + } while (millis() - start < INTER_CHAR_TIME + 10); // Give a little time for bounce with two units + + /*if (INTER_CHAR_TIME > 10) { + if (!received) { + Serial.print( '.' ); + dumpBits(); + dumpDiffs(); + Serial.println(); + } else + Serial.println(); + + Serial.flush(); + }*/ + +} // testOne + + +// In the second round of testing, the sketch sends the same characters as fast +// as it can (no inter-character wait time). +// NeoSWSerial writes each byte immediately; there is no TX buffer. + +// With 2 Arduinos, the echo from the second Arduino begins coming in after the +// 1st Arduino finishes sending the first byte. Then the 1st Arduino starts +// sending the second byte. + +// With 1 Arduino + loopback wires, the first character arrives at the same time +// it is being sent. + +// This tests the simultaneous sending and receiving parts of NeoSWSerial, +// synchronously (1 Arduino + loopback wires) and asynchronously (2 Arduinos). + +void testTwo( Stream & ins, Stream & outs, uint8_t numRepeats ) +{ + for (uint8_t times=0; times Date: Tue, 15 Jan 2019 14:55:11 -0500 Subject: [PATCH 21/33] Printing speed in test --- src/NeoSWSerial.cpp | 2 +- tests/test/test.ino | 60 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index a6339b8..5b6a2ac 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -186,7 +186,7 @@ void NeoSWSerial::listen() #else preNSWS_TCCR2A = TCCR2A; preNSWS_TCCR2B = TCCR2B; - TCCR2A = 0x00; // "normal" operation - Normal port operation, OC2A & OC2B disconnected + TCCR2A = 0x00; // "normal" operation - Normal port operation, OC2A & OC2B disconnected, normal waveform generation TCCR2B = 0x03; // 0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32 // timer now running at 8MHz/32 = 250kHz #endif diff --git a/tests/test/test.ino b/tests/test/test.ino index 3619c67..025a1dd 100644 --- a/tests/test/test.ino +++ b/tests/test/test.ino @@ -2,9 +2,8 @@ NeoSWSerial nss( 10, 11 ); -// NeoSWSerial nssCheck( 8, 9 ); -// NeoSWSerial &checkSerial = nssCheck; HardwareSerial &checkSerial = Serial1; +// NeoSWSerial &checkSerial = nss; uint16_t baudrate = 9600; uint8_t rc[770]; // Received character array @@ -391,6 +390,43 @@ void setup() { nss.begin( baudrate ); + #if F_CPU == 16000000L + // Use Timer 0 (TCNT0) 8-bit timer w/ PWM, default prescaler has divisor of 64, thus 250kHz + Serial.print("TCCR0A: 0x0"); Serial.println(TCCR0A, HEX); + // ^^ Should be 0x03=0b00000011 - OC0A & OC0B disconnected, Fast PWM + Serial.print("TCCR0B: 0x0"); Serial.println(TCCR0B, HEX); + // ^^ Should be 0x03=0b00000011 - Clock Select bits 01 & 00 on - prescaling source = CK/64, timer at 16MHz/64 = 250kHz + + // Have to use alternate timer for an 8 MHz system because timer 0 doesn't have the correct prescaler + #elif F_CPU == 8000000L + #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) + // Use Timer 1 (TCNT1) 8-bit timer/counter w/ independent prescaler + Serial.print("TCCR1: 0x0"); Serial.println(TCCR1, HEX); + // ^^ Should be 0x06=0b00000110 - Clock Select bits 12 & 11 on - prescaling source = CK/32, timer at 8MHz/32 = 250kHz + + #elif defined(__AVR_ATmega32U4__) + // Use Timer 4 (TCNT4) 10-bit high speed timer, usable as 8-bit timer by ignoring high bits + Serial.print("TCCR4A: 0x0"); Serial.println(TCCR4A, HEX); + // ^^ Should be 0x00 - "normal" operation - Normal port operation, OC4A & OC4B disconnected + Serial.print("TCCR4B: 0x0"); Serial.println(TCCR4B, HEX); + // ^^ Should be 0x06=0b00000110 - Clock Select bits 42 & 41 on - prescaler set to CK/32, timer at 8MHz/32 = 250kHz + Serial.print("TCCR4C: 0x0"); Serial.println(TCCR4C, HEX); + // ^^ Should be 0x00 - "normal" operation - Normal port operation, OC4D0 disconnected + Serial.print("TCCR4D: 0x0"); Serial.println(TCCR4D, HEX); + // ^^ Should be 0x00 - No fault protection + Serial.print("TCCR4E: 0x0"); Serial.println(TCCR4E, HEX); + // ^^ Should be 0x00 - No register locks or overrides + + #else + // Use Timer 2 (TCNT2) 8-bit timer w/ PWM, asynchronous operation, and independent prescaler + Serial.print("TCCR2A: 0x0"); Serial.println(TCCR2A, HEX); + // ^^ Should be 0x00 - "normal" operation - Normal port operation, OC2A & OC2B disconnected + Serial.print("TCCR2B: 0x0"); Serial.println(TCCR2B, HEX); + // ^^ Should be 0x03=0b00000011 - Clock Select bits 21 & 20 on - prescaler set to clkT2S/32, timer at 8MHz/32 = 250kHz + #endif + + #endif + } // setup //--------------------------------------------------------------------- @@ -403,6 +439,10 @@ void loop() Serial.println( F("Individual Character RX test") ); Serial.flush(); + delay(1000); + emptyBuffer(nss); + emptyBuffer(checkSerial); + delay(1000); uint8_t c=0; do { @@ -422,6 +462,10 @@ void loop() Serial.println( F("RX test") ); Serial.flush(); + delay(1000); + emptyBuffer(nss); + emptyBuffer(checkSerial); + delay(1000); // Send out all the characters on a hardware serial port and read them over NSS testTwo(nss, checkSerial, 3); @@ -436,6 +480,10 @@ void loop() Serial.println( F("TX test") ); Serial.flush(); + delay(1000); + emptyBuffer(nss); + emptyBuffer(checkSerial); + delay(1000); // Send out all the characters on NSS and read them over a hardware serial port testTwo(checkSerial, nss, 3); @@ -450,6 +498,10 @@ void loop() Serial.println( F("RX and TX test") ); Serial.flush(); + delay(1000); + emptyBuffer(nss); + emptyBuffer(checkSerial); + delay(1000); // Send out all the characters on a hardware serial port and read them and // immeciately send them back over NSS @@ -465,6 +517,10 @@ void loop() Serial.println( F("TX and RX test") ); Serial.flush(); + delay(1000); + emptyBuffer(nss); + emptyBuffer(checkSerial); + delay(1000); // Send out all the characters on NSS and read them and immeciately send them // back over a hardware serial port From 545404e831a4ae16c5296acaece11365d8bec8d1 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Tue, 15 Jan 2019 14:57:23 -0500 Subject: [PATCH 22/33] Limit speeds for processors at less than 12mhz --- src/NeoSWSerial.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 5b6a2ac..1ee53f3 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -207,14 +207,19 @@ void NeoSWSerial::listen() rxWindowWidth = 10; break; case 31250: + if (F_CPU >= 12000000L) { txBitWidth = TICKS_PER_BIT_31250; bitsPerTick_Q10 = BITS_PER_TICK_31250_Q10; rxWindowWidth = 5; break; + } // else use 19200 case 38400: + if (F_CPU >= 12000000L) { txBitWidth = TICKS_PER_BIT_9600 >> 2; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 ; rxWindowWidth = 4; + break; + } // else use 19200 case 19200: txBitWidth = TICKS_PER_BIT_9600 >> 1; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 1; @@ -282,8 +287,10 @@ void NeoSWSerial::setBaudRate(uint16_t baudRate) if (( ( baudRate == 9600) || ( baudRate == 19200) || - ( baudRate == 31250) || - ( baudRate == 38400) + ( baudRate == 31250 ) || + ( baudRate == 38400 ) + // ((baudRate == 31250) && (F_CPU == 16000000L)) || + // ((baudRate == 38400) && (F_CPU == 16000000L)) ) && (_baudRate != baudRate)) { @@ -570,7 +577,7 @@ void NeoSWSerial::rxChar( uint8_t c ) PCINT_ISR(1, PINJ); PCINT_ISR(2, PINK); - #elif defined(__AVR_ATmega1281__) + #elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1280__ ) PCINT_ISR(0, PINB); // PCINT8 on PE0 not supported. Other 7 are on PJ0..6 From f003e0a78bc602eddaed8883c2118403bb2fca5a Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Tue, 15 Jan 2019 15:05:52 -0500 Subject: [PATCH 23/33] Removed extra comment --- src/NeoSWSerial.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 1ee53f3..83c00f9 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -337,7 +337,7 @@ int NeoSWSerial::read() uint8_t c = rxBuffer[rxTail]; // Otherwise, grab char at tail rxTail = (rxTail + 1) % RX_BUFFER_SIZE; // increment tail - return c; // return the char + return c; } // read From a51c2353419e97714b1b7fe0a63e22d0da3cdd20 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 16 Jan 2019 14:26:33 -0500 Subject: [PATCH 24/33] Small fix to print dropped chars in test --- examples/passThrough/passThrough.ino | 10 +++++--- tests/test/test.ino | 34 ++++++++++++++-------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/examples/passThrough/passThrough.ino b/examples/passThrough/passThrough.ino index 31ad03f..0dc0676 100644 --- a/examples/passThrough/passThrough.ino +++ b/examples/passThrough/passThrough.ino @@ -1,17 +1,21 @@ #include #include -#define BAUD 38400 +uint16_t baudrate = 9600; NeoSWSerial nss( 10, 11 ); void setup(){ - Serial.begin(57600); + Serial.begin(115200); delay(50); while (!Serial){}; - nss.begin(BAUD); + Serial.print( F("NeoSWSerial pass through @ ") ); + Serial.println( baudrate ); + Serial.flush(); + + nss.begin(baudrate); delay(50); } diff --git a/tests/test/test.ino b/tests/test/test.ino index 025a1dd..ce6c6d6 100644 --- a/tests/test/test.ino +++ b/tests/test/test.ino @@ -5,12 +5,13 @@ NeoSWSerial nss( 10, 11 ); HardwareSerial &checkSerial = Serial1; // NeoSWSerial &checkSerial = nss; - uint16_t baudrate = 9600; - uint8_t rc[770]; // Received character array - uint8_t sc[770]; // Sent character array - only for error checking - uint16_t received = 0; // # characters received - uint16_t sent = 0; // # characters sent - static uint16_t errors = 0; // # errors +uint16_t baudrate = 9600; +uint8_t rc[770]; // Received character array +uint8_t sc[770]; // Sent character array - only for error checking +uint16_t received = 0; // # characters received +uint16_t dropped = 0; // # characters received +uint16_t sent = 0; // # characters sent +static uint16_t errors = 0; // # errors //--------------------------------------------------------------------- #define INTER_CHAR_TIME 50 @@ -147,6 +148,11 @@ static void printStats() Serial.print( sent ); Serial.println( F(" sent") ); } + if (received < sent) { + Serial.print( sent-received ); + Serial.println( F(" chars dropped.") ); + } + Serial.print( errors ); Serial.println( F(" errors") ); @@ -214,10 +220,10 @@ void testOne( Stream & ins, Stream & outs, uint8_t c ) pair[1] = c+1; uint8_t len = 1; outs.write( pair, len ); + sent++; if (INTER_CHAR_TIME < 10) outs.flush(); - uint8_t received = 0; bool gotIt = false; uint32_t start = millis(); @@ -301,11 +307,6 @@ void testTwo( Stream & ins, Stream & outs, uint8_t numRepeats ) } // Print results - if (received < sent) { - Serial.print( sent-received ); - Serial.println( F(" chars dropped.") ); - } - checkRC(); printStats(); @@ -364,11 +365,6 @@ void testThree( Stream & ins, Stream & outs, uint8_t numRepeats ) } while (ms - start < 100); // Print results - if (received < sent) { - Serial.print( sent-received ); - Serial.println( F(" chars dropped.") ); - } - checkRC(); printStats(); @@ -443,6 +439,10 @@ void loop() emptyBuffer(nss); emptyBuffer(checkSerial); delay(1000); + + received = 0; + sent = 0; + errors = 0; uint8_t c=0; do { From 27229c46c1584dabbf57bd7dd4b8978790ccef8b Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 16 Jan 2019 14:27:15 -0500 Subject: [PATCH 25/33] Added notes on processors and pin numbers --- src/NeoSWSerial.cpp | 83 +++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 83c00f9..f2ed020 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -56,7 +56,7 @@ static const uint8_t BITS_PER_TICK_38400_Q10 = 157; #define PCI_FLAG_REGISTER GIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR1; - #elif defined(__AVR_ATmega32U4__) + #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) #define TCNTX TCNT4 // 10-bit high speed timer, usable as 8-bit timer by ignoring high bits #define PCI_FLAG_REGISTER PCIFR // Pin change interrupt flag register static uint8_t preNSWS_TCCR4A; @@ -171,7 +171,7 @@ void NeoSWSerial::listen() preNSWS_TCCR1 = TCCR1; TCCR1 = 0x06; // 0b00000110 - Clock Select bits 12 & 11 on - prescaling source = CK/32 // timer now running at 8MHz/32 = 250kHz - #elif defined(__AVR_ATmega32U4__) + #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) preNSWS_TCCR4A = TCCR4A; preNSWS_TCCR4B = TCCR4B; preNSWS_TCCR4C = TCCR4C; @@ -266,7 +266,7 @@ void NeoSWSerial::ignore() defined(__AVR_ATtiny45__) | \ defined(__AVR_ATtiny85__) TCCR1 = preNSWS_TCCR1; - #elif defined(__AVR_ATmega32U4__) + #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) TCCR4A = preNSWS_TCCR4A; TCCR4B = preNSWS_TCCR4B; TCCR4C = preNSWS_TCCR4C; @@ -531,6 +531,8 @@ void NeoSWSerial::rxChar( uint8_t c ) NeoSWSerial::rxISR(pin); \ } } + // Only supported at 16MHz + // ?? Are there any boards that use one of these at 16Mhz? #if defined(__AVR_ATtiny261__) | \ defined(__AVR_ATtiny461__) | \ defined(__AVR_ATtiny861__) @@ -544,57 +546,64 @@ void NeoSWSerial::rxChar( uint8_t c ) } } + // Supported at 8 and 16 MHZ #elif defined(__AVR_ATtiny25__) | \ defined(__AVR_ATtiny45__) | \ defined(__AVR_ATtiny85__) - PCINT_ISR(0, PINB); + PCINT_ISR(0, PINB); // D0-D5 - #elif defined(__AVR_ATtiny24__) | \ - defined(__AVR_ATtiny44__) | \ - defined(__AVR_ATtiny84__) + // Only supported at 16MHz + // ?? Are there any boards that use one of these at 16Mhz? + #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny24A__) || \ + defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny44A__) ||\ + defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny84A__) - PCINT_ISR(0, PINA); - PCINT_ISR(1, PINB); + PCINT_ISR(0, PINA); // D0-D7 + PCINT_ISR(1, PINB); // D10, D9, D8, D11 - #elif defined(__AVR_ATmega328P__) + // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz + #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || \ + defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PA__) || \ + defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) - PCINT_ISR(0, PINB); - PCINT_ISR(1, PINC); - PCINT_ISR(2, PIND); + PCINT_ISR(0, PINB); // D8-D13 + PCINT_ISR(1, PINC); // D14-D19 + PCINT_ISR(2, PIND); // D0-D7 - #elif defined(__AVR_ATmega32U4__) + // Supported at 8MHz and 16MHz + #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) - PCINT_ISR(0, PINB); + PCINT_ISR(0, PINB); // D17 (SS), D15 (SCK), D16 (MOSI), D14 (MISO), D8, D9, D10. D11, + // Only supported at 16MHz #elif defined(__AVR_AT90USB1286__) PCINT_ISR(0, PINB); - #elif defined(__AVR_ATmega2560__) - - PCINT_ISR(0, PINB); - PCINT_ISR(1, PINJ); - PCINT_ISR(2, PINK); - - #elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1280__ ) - - PCINT_ISR(0, PINB); - // PCINT8 on PE0 not supported. Other 7 are on PJ0..6 - PCINT_ISR(1, PINJ); - PCINT_ISR(2, PINK); - - #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) - - PCINT_ISR(0, PINA); - PCINT_ISR(1, PINB); - PCINT_ISR(2, PINC); - PCINT_ISR(3, PIND); - + // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz + #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || \ + defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1280__ ) || \ + defined(__AVR_ATmega640__) + + PCINT_ISR(0, PINB); // D53-D50, D10-D13 + PCINT_ISR(1, PINJ); // D15-D14, D70-D74 (fake) + PCINT_ISR(2, PINK); // D62-D69 + + // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz + #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) \ + defined(__AVR_ATmega1284__) || defined(__AVR_ATmega644__) + + PCINT_ISR(0, PINA); // D24-D31 (most) or D21-D14 (bobuino) + PCINT_ISR(1, PINB); // D0-D7 or D8-D15 (Mayfly/mbilli) or D4-D13 (bobuino) + PCINT_ISR(2, PINC); // D16-D23 (most) or D22-D29 (bobuino) + PCINT_ISR(3, PIND); // D8-D15 or D0-D7 (Mayfly/mbilli) or D0-D3, D30, D8-D9, D31 (bobuino) + + // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz #elif defined(__AVR_ATmega2560RFR2__) - PCINT_ISR(0, PINB); - PCINT_ISR(1, PINE); + PCINT_ISR(0, PINB); // PIN?? + PCINT_ISR(1, PINE); // PIN?? #else #error MCU not supported by NeoSWSerial! From 96cfd101077fb84d414d440989b46c1f6936d3b1 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Wed, 16 Jan 2019 16:11:40 -0500 Subject: [PATCH 26/33] Corrected 2560RFR2 tp 256RFR2, also added notes on compatibility at 8MHz --- README.md | 12 +++++++----- src/NeoSWSerial.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index cafccff..d2d2759 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The class methods are nearly identical to the built-in `SoftwareSerial`, except There are five, nay, **six** advantages over `SoftwareSerial`: -**1)** It uses *much* less CPU time. +**1)** It uses *much* less CPU time. **2)** Simultaneous transmit and receive is fully supported. @@ -28,15 +28,15 @@ There are five, nay, **six** advantages over `SoftwareSerial`: ``` #include NeoSWSerial ss( 4, 3 ); - + volatile uint32_t newlines = 0UL; - + static void handleRxChar( uint8_t c ) { if (c == '\n') newlines++; } - + void setup() { ss.attachInterrupt( handleRxChar ); @@ -68,4 +68,6 @@ void setup() } ``` -This class supports the following MCUs: ATtinyx61, ATtinyx4, ATtinyx5, ATmega328P (Pro, UNO, Nano), ATmega32U4 (Micro, Leonardo), ATmega2560 (Mega), ATmega2560RFR2, ATmega1284P and ATmega1286 +This class supports the following MCUs at 16MHz: ATmega328P (Pro, UNO, Nano), ATmega2560 (Mega), ATmega256RFR2 (Xplained Pro, Altair, Pinoccio), ATmega1284P (MightyCore), ATmega32U4 (Micro, Leonardo), ATtinyx61, ATtinyx4, ATtinyx5 (Trinket), and AT90USB1286 (Teensy++) + +These MCUs are also supported at 8MHz: ATmega328P (Pro, Fio, Feather 328), ATmega2560 (Mega), ATmega256RFR2, ATmega1284P (Mayfly, Mbili), ATmega32U4 (Feather 32U4, Flora), and ATtinyx5 (Trinket, Gemma). To run on 8MHz boards, NeoSWSerial must set another timer prescaler - timer4 on the 32U4, timer1 on the AtTiny, and timer2 on the others. For the vast majority of cases, this will not be a problem. But, if not used carefully, this will cause the tone() function (and possibly others) to behave strangely. It could also cause the [EnviroDIY SDI-12](https://github.com/EnviroDIY/Arduino-SDI-12) library (which was partly modeled on NeoSWSerial) to malfunction. To avoid these problems make sure that you ignore() or end() all instances of NeoSWSerial before using the other functions/libraries. You must then begin() or listen() again to restart NeoSWSerial. diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index f2ed020..e947866 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -598,9 +598,9 @@ void NeoSWSerial::rxChar( uint8_t c ) PCINT_ISR(1, PINB); // D0-D7 or D8-D15 (Mayfly/mbilli) or D4-D13 (bobuino) PCINT_ISR(2, PINC); // D16-D23 (most) or D22-D29 (bobuino) PCINT_ISR(3, PIND); // D8-D15 or D0-D7 (Mayfly/mbilli) or D0-D3, D30, D8-D9, D31 (bobuino) - + // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz - #elif defined(__AVR_ATmega2560RFR2__) + #elif defined(__AVR_ATmega256RFR2__) PCINT_ISR(0, PINB); // PIN?? PCINT_ISR(1, PINE); // PIN?? From bf6653d3e2a5d656c8d471a3bcc417b67cfe95ac Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 29 Aug 2019 15:46:05 -0400 Subject: [PATCH 27/33] Added sign to pin vars, fixed elif --- .gitignore | 1 + src/NeoSWSerial.cpp | 5 +++-- src/NeoSWSerial.h | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index b86373e..89fbcf3 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ Temporary Items .apdisk # Atom / PlatformIO +.pio .pioenvs .piolibdeps .clang_complete diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index e947866..ab1ab0a 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -399,8 +399,9 @@ void NeoSWSerial::rxISR( uint8_t rxPort ) // This will also happen if last bit(s) of the character are all 0's. bool nextCharStarted = (rxBits > bitsLeft); - if (nextCharStarted) + if (nextCharStarted) { DBG_NSS_ARRAY(rxStartCompletionBits,rxStartCompletions,(10*rxBits + bitsLeft)); + } // check how many data bits have been sent in this frame @@ -591,7 +592,7 @@ void NeoSWSerial::rxChar( uint8_t c ) PCINT_ISR(2, PINK); // D62-D69 // Supported at 8MHz and 16MHz; conflicts with "tone" at 8MHz - #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) \ + #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644P__) || \ defined(__AVR_ATmega1284__) || defined(__AVR_ATmega644__) PCINT_ISR(0, PINA); // D24-D31 (most) or D21-D14 (bobuino) diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 514acee..38537cc 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -89,7 +89,7 @@ class NeoSWSerial : public Stream void detachInterrupt() { attachInterrupt( (isr_t) NULL ); }; private: - uint8_t rxPin, txPin; + int8_t rxPin, txPin; volatile uint8_t *rxPort; uint16_t _baudRate; From fff812bd332512e9a935174cd28345a1442fb5bb Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 29 Aug 2019 15:46:33 -0400 Subject: [PATCH 28/33] version bump --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index b908d25..31b1d8a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=NeoSWSerial -version=3.0.5 +version=3.0.6 author=SlashDevin maintainer=SlashDevin sentence=An efficient replacement for SoftwareSerial at baud rates 9600, 19200 and 38400. From e0a9c6ed08d1737badc69a5666cc93ea90b0ffb0 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Thu, 29 Aug 2019 16:14:41 -0400 Subject: [PATCH 29/33] Extra braces --- src/NeoSWSerial.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index ab1ab0a..8f5e99d 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -674,8 +674,9 @@ size_t NeoSWSerial::write(uint8_t txChar) *txPort |= txBitMask; // stop bit is high SREG = prevSREG; // interrupts on for stop bit while ((uint8_t)(TCNTX - t0) < width) { - if (checkRxTime()) + if (checkRxTime()) { DBG_NSS_COUNT(stopBitCompletions); + } } return 1; // 1 character sent From 79d693be1307bc1af276884547ec0c356bf73c73 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Mon, 24 May 2021 12:12:58 -0400 Subject: [PATCH 30/33] Make fallthrough explicity Signed-off-by: Sara Damiano --- .gitignore | 2 ++ src/NeoSWSerial.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 89fbcf3..f57828d 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ Temporary Items .gcc-flags.json lib/readme.txt platformio.ini +.history +.vscode diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 8f5e99d..30c55f4 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -213,6 +213,7 @@ void NeoSWSerial::listen() rxWindowWidth = 5; break; } // else use 19200 + __attribute__ ((fallthrough)); case 38400: if (F_CPU >= 12000000L) { txBitWidth = TICKS_PER_BIT_9600 >> 2; @@ -220,6 +221,7 @@ void NeoSWSerial::listen() rxWindowWidth = 4; break; } // else use 19200 + __attribute__ ((fallthrough)); case 19200: txBitWidth = TICKS_PER_BIT_9600 >> 1; bitsPerTick_Q10 = BITS_PER_TICK_38400_Q10 >> 1; From 5a0daf7096b3851d7b63840b27a6b130580e3e63 Mon Sep 17 00:00:00 2001 From: Sara Damiano Date: Tue, 12 Jul 2022 18:24:48 -0400 Subject: [PATCH 31/33] Make interrupts external by default --- src/NeoSWSerial.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 38537cc..96ec2a6 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -105,6 +105,8 @@ class NeoSWSerial : public Stream // visible only so the ISRs can call it... static void rxISR( uint8_t port_input_register ); - // #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs + #ifndef NEOSWSERIAL_EXTERNAL_PCINT + #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs + #endif }; #endif From 9626916c115c51bb33b1d1b143ecef3975002d5f Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 10 Jan 2023 15:24:39 -0600 Subject: [PATCH 32/33] add support for RS232-type logic levels https://github.com/matthewmarks-bbc/NeoSWSerial/commit/f9faa1b6b29690896db6009f1e1dd190c5c4a98b --- src/NeoSWSerial.cpp | 22 ++++++++++++++++++---- src/NeoSWSerial.h | 5 ++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index 30c55f4..c56cd08 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -93,6 +93,7 @@ static uint8_t rxTail; // buffer pointer output static uint8_t rxBitMask, txBitMask; // port bit masks static volatile uint8_t *txPort; // port register +static bool inv; //invert the signal on the line //#define DEBUG_NEOSWSERIAL #ifdef DEBUG_NEOSWSERIAL @@ -158,8 +159,12 @@ void NeoSWSerial::listen() txBitMask = digitalPinToBitMask( txPin ); txPort = portOutputRegister( digitalPinToPort( txPin ) ); + inv = inverse; if (txPort) - *txPort |= txBitMask; // high = idle + if (inv) + *txPort &= ~txBitMask; // set TX line low + else + *txPort |= txBitMask; // set TX line high pinMode(txPin, OUTPUT); // Set the timer prescaling as necessary - want to be running at 250kHz @@ -371,6 +376,9 @@ void NeoSWSerial::startChar() void NeoSWSerial::rxISR( uint8_t rxPort ) { uint8_t t0 = TCNTX; // time of data transition (plus ISR latency) + if (inv) { + rxPort = ~rxPort; + } uint8_t d = rxPort & rxBitMask; // read RX data level // Check if we're ready for a start bit, and if this could possibly be it @@ -469,6 +477,7 @@ bool NeoSWSerial::checkRxTime() if (rxState != WAITING_FOR_START_BIT) { uint8_t d = *rxPort & rxBitMask; + if (inv) d = ~d; if (d) { // Ended on a 1, see if it has been too long @@ -628,7 +637,7 @@ size_t NeoSWSerial::write(uint8_t txChar) uint8_t width; // ticks for one bit uint8_t txBit = 0; // first bit is start bit - uint8_t b = 0; // start bit is low + bool b = false; // start bit is logic 0 uint8_t PCIbit = bit(digitalPinToPCICRbit(rxPin)); uint8_t prevSREG = SREG; @@ -642,7 +651,7 @@ size_t NeoSWSerial::write(uint8_t txChar) // re-enabled. while (txBit++ < 9) { // repeat for start bit + 8 data bits - if (b) // if bit is set + if (b != inv) // if desired state is high *txPort |= txBitMask; // set TX line high else *txPort &= ~txBitMask; // else set TX line low @@ -673,7 +682,12 @@ size_t NeoSWSerial::write(uint8_t txChar) // Q: would a signed >> pull in a 1? } - *txPort |= txBitMask; // stop bit is high + // stop bit is logic 1 + if (inv) + *txPort &= ~txBitMask; // else set TX line low + else + *txPort |= txBitMask; // set TX line high + SREG = prevSREG; // interrupts on for stop bit while ((uint8_t)(TCNTX - t0) < width) { if (checkRxTime()) { diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index 96ec2a6..bda61cf 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -65,10 +65,11 @@ class NeoSWSerial : public Stream NeoSWSerial & operator =( const NeoSWSerial & ); // Not allowed public: - NeoSWSerial(uint8_t receivePin, uint8_t transmitPin) + NeoSWSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false) { rxPin = receivePin; txPin = transmitPin; + inverse = inverse_logic; _isr = (isr_t) NULL; } @@ -90,6 +91,7 @@ class NeoSWSerial : public Stream private: int8_t rxPin, txPin; + bool inverse; volatile uint8_t *rxPort; uint16_t _baudRate; @@ -104,6 +106,7 @@ class NeoSWSerial : public Stream public: // visible only so the ISRs can call it... static void rxISR( uint8_t port_input_register ); + static bool invert; // invert levels on line #ifndef NEOSWSERIAL_EXTERNAL_PCINT #define NEOSWSERIAL_EXTERNAL_PCINT // uncomment to use your own PCINT ISRs From df6af12687d1bd72e86214077427bf30b95c68ab Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Mon, 13 Feb 2023 11:19:20 -0600 Subject: [PATCH 33/33] NeoSWSerial: avoid undefined behavior when TX disable is requested Correctly avoid setting up transmit path when a txPin of -1 is given. --- src/NeoSWSerial.cpp | 25 ++++++++++++++++--------- src/NeoSWSerial.h | 2 +- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/NeoSWSerial.cpp b/src/NeoSWSerial.cpp index c56cd08..fc8a251 100644 --- a/src/NeoSWSerial.cpp +++ b/src/NeoSWSerial.cpp @@ -153,19 +153,26 @@ void NeoSWSerial::listen() if (listener) listener->ignore(); + inv = inverse; pinMode(rxPin, INPUT); rxBitMask = digitalPinToBitMask( rxPin ); rxPort = portInputRegister( digitalPinToPort( rxPin ) ); - txBitMask = digitalPinToBitMask( txPin ); - txPort = portOutputRegister( digitalPinToPort( txPin ) ); - inv = inverse; - if (txPort) - if (inv) - *txPort &= ~txBitMask; // set TX line low - else - *txPort |= txBitMask; // set TX line high - pinMode(txPin, OUTPUT); + if (txPin >= 0) { + txBitMask = digitalPinToBitMask( txPin ); + txPort = portOutputRegister( digitalPinToPort( txPin ) ); + + if (txPort) { + if (inv) + *txPort &= ~txBitMask; // set TX line low + else + *txPort |= txBitMask; // set TX line high + } + + pinMode(txPin, OUTPUT); + } else { + txPort = 0; + } // Set the timer prescaling as necessary - want to be running at 250kHz #if F_CPU == 8000000L diff --git a/src/NeoSWSerial.h b/src/NeoSWSerial.h index bda61cf..78e9e14 100644 --- a/src/NeoSWSerial.h +++ b/src/NeoSWSerial.h @@ -65,7 +65,7 @@ class NeoSWSerial : public Stream NeoSWSerial & operator =( const NeoSWSerial & ); // Not allowed public: - NeoSWSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false) + NeoSWSerial(int8_t receivePin, int8_t transmitPin, bool inverse_logic = false) { rxPin = receivePin; txPin = transmitPin;