From 191c72f7882f7e2dce4b25e0777cd006e16adc74 Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 24 Sep 2020 23:11:22 +0200 Subject: [PATCH] version 2.2.1 --- .github/workflows/LibraryBuild.yml | 10 +- README.md | 5 +- .../AllPatternOnOneStrip.ino | 5 +- .../AllPatternsOnMultiDevices/ADCUtils.cpp | 2 +- examples/AllPatternsOnMultiDevices/ADCUtils.h | 13 +- .../AllPatternsOnMultiDevices.ino | 5 +- examples/MatrixDemo/MatrixDemo.ino | 5 +- .../MatrixShowAllColors.ino | 5 +- .../MultiplePatternsOnOneBar.ino | 5 +- .../NeoPatternsSimpleDemo.ino | 5 +- examples/OpenLedRace/OpenLedRace.ino | 4 +- examples/OpenLedRace/PlayRtttl.h | 10 +- examples/SnakeAutorun/SnakeAutorun.ino | 5 +- examples/SnakeGame/SnakeGame.ino | 5 +- examples/SnowFlakes/SnowFlakes.ino | 5 +- .../EasyButtonAtInt01.cpp.h | 82 +++++++----- .../TwoPatternsOnOneStrip/EasyButtonAtInt01.h | 117 ++++++++++++++---- .../TwoPatternsOnOneStrip.ino | 7 +- library.json | 2 +- library.properties | 4 +- src/NeoPatterns.h | 2 +- 21 files changed, 183 insertions(+), 120 deletions(-) diff --git a/.github/workflows/LibraryBuild.yml b/.github/workflows/LibraryBuild.yml index 80f234d..eb6bfa4 100644 --- a/.github/workflows/LibraryBuild.yml +++ b/.github/workflows/LibraryBuild.yml @@ -43,17 +43,17 @@ jobs: ############################################################################################################# include: - arduino-boards-fqbn: arduino:avr:uno|All-DO_NOT_SUPPORT_RGBW - examples-build-properties: + build-properties: All: -DDO_NOT_SUPPORT_RGBW - arduino-boards-fqbn: esp8266:esp8266:huzzah:eesz=4M3M,xtal=80 platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json - examples-exclude: OpenLedRace,TwoPatternsOnOneStrip # Comma separated list of (unique substrings of) example names to exclude in build + sketches-exclude: OpenLedRace,TwoPatternsOnOneStrip # Comma separated list of (unique substrings of) example names to exclude in build - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 platform-url: https://dl.espressif.com/dl/package_esp32_index.json - examples-exclude: OpenLedRace,TwoPatternsOnOneStrip # TwoPatternsOnOneStrip because of missing EasyButton library + sketches-exclude: OpenLedRace,TwoPatternsOnOneStrip # TwoPatternsOnOneStrip because of missing EasyButton library # Do not cancel all jobs / architectures if one job fails fail-fast: false @@ -69,8 +69,8 @@ jobs: ENV_ARDUINO_BOARD_FQBN: ${{ matrix.arduino-boards-fqbn }} ENV_PLATFORM_URL: ${{ matrix.platform-url }} ENV_REQUIRED_LIBRARIES: ${{ env.REQUIRED_LIBRARIES }} - ENV_EXAMPLES_EXCLUDE: ${{ matrix.examples-exclude }} - ENV_EXAMPLES_BUILD_PROPERTIES: ${{ toJson(matrix.examples-build-properties) }} + ENV_EXAMPLES_EXCLUDE: ${{ matrix.sketches-exclude }} + ENV_EXAMPLES_BUILD_PROPERTIES: ${{ toJson(matrix.build-properties) }} run: | wget --quiet https://raw.githubusercontent.com/ArminJo/arduino-test-compile/master/arduino-test-compile.sh chmod +x arduino-test-compile.sh diff --git a/README.md b/README.md index c32743b..f8601dc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # [NeoPatterns](https://github.com/ArminJo/NeoPatterns) for NeoPixel strips and Snake game for NeoPixel matrix. Available as Arduino library "NeoPatterns" -### [Version 2.2.0](https://github.com/ArminJo/NeoPatterns/releases) +### [Version 2.2.1](https://github.com/ArminJo/NeoPatterns/releases) [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Installation instructions](https://www.ardu-badge.com/badge/NeoPatterns.svg?)](https://www.ardu-badge.com/NeoPatterns) @@ -89,6 +89,9 @@ NeoPatterns on breadboard ![NeoPatterns on breadboard](https://github.com/ArminJo/NeoPatterns/blob/master/extras/Breadboard_complete.jpg) # Revision History +### Version 2.2.1 +- Removed blocking wait for ATmega32U4 Serial in examples. + ### Version 2.2.0 - Added support for RGBW patterns. Requires additional 200 bytes for the AllPatternsOnMultiDevices example. Commenting out `#define SUPPORT_RGBW` or defining `DO_NOT_SUPPORT_RGBW` saves 400 bytes FLASH for the AllPatternsOnMultiDevices example. - Use type `Print *` instead of `Stream *`. diff --git a/examples/AllPatternOnOneStrip/AllPatternOnOneStrip.ino b/examples/AllPatternOnOneStrip/AllPatternOnOneStrip.ino index 7e3b666..905d05f 100644 --- a/examples/AllPatternOnOneStrip/AllPatternOnOneStrip.ino +++ b/examples/AllPatternOnOneStrip/AllPatternOnOneStrip.ino @@ -59,10 +59,7 @@ void setup() { #ifdef INFO Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/AllPatternsOnMultiDevices/ADCUtils.cpp b/examples/AllPatternsOnMultiDevices/ADCUtils.cpp index 88ddead..fde8b14 100644 --- a/examples/AllPatternsOnMultiDevices/ADCUtils.cpp +++ b/examples/AllPatternsOnMultiDevices/ADCUtils.cpp @@ -22,7 +22,7 @@ * along with this program. If not, see . */ -#if defined(__AVR__) +#if defined(__AVR__) && (! defined(__AVR_ATmega4809__)) #include "ADCUtils.h" // Union to speed up the combination of low and high bytes to a word diff --git a/examples/AllPatternsOnMultiDevices/ADCUtils.h b/examples/AllPatternsOnMultiDevices/ADCUtils.h index 1ed3fef..0664614 100644 --- a/examples/AllPatternsOnMultiDevices/ADCUtils.h +++ b/examples/AllPatternsOnMultiDevices/ADCUtils.h @@ -24,13 +24,13 @@ #ifndef SRC_ADCUTILS_H_ #define SRC_ADCUTILS_H_ -#if defined(__AVR__) +#if defined(__AVR__) && (! defined(__AVR_ATmega4809__)) #include -// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 Mhz Clock => 19,2 kHz +// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz #define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz #define ADC_PRESCALE4 2 // 52 microseconds per ADC conversion at 1 MHz -// PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 Mhz Clock => 9,6 kHz +// PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 MHz Clock => 9,6 kHz #define ADC_PRESCALE8 3 // 104 microseconds per ADC conversion at 1 MHz #define ADC_PRESCALE16 4 // 208 microseconds per ADC conversion at 1 MHz #define ADC_PRESCALE32 5 // 416 microseconds per ADC conversion at 1 MHz @@ -53,15 +53,14 @@ * After including this file you can not call the ATTinyCore readAnalog functions reliable, if you specify references other than default! */ #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) -// defines are from Arduino.h, the can be used without bit reordering -#ifdef ATTINY_CORE +// defines are for ADCUtils.cpp, they can be used WITHOUT bit reordering #undef DEFAULT #undef EXTERNAL #undef INTERNAL1V1 #undef INTERNAL #undef INTERNAL2V56 #undef INTERNAL2V56_EXTCAP -#endif + #define DEFAULT 0 #define EXTERNAL 4 #define INTERNAL1V1 8 @@ -71,7 +70,7 @@ #define SHIFT_VALUE_FOR_REFERENCE REFS2 #define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1) | _BV(REFS2)) -#else +#else // AVR_ATtiny85 #define SHIFT_VALUE_FOR_REFERENCE REFS0 #define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1)) #endif diff --git a/examples/AllPatternsOnMultiDevices/AllPatternsOnMultiDevices.ino b/examples/AllPatternsOnMultiDevices/AllPatternsOnMultiDevices.ino index 25cda1c..464b49d 100644 --- a/examples/AllPatternsOnMultiDevices/AllPatternsOnMultiDevices.ino +++ b/examples/AllPatternsOnMultiDevices/AllPatternsOnMultiDevices.ino @@ -87,10 +87,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/MatrixDemo/MatrixDemo.ino b/examples/MatrixDemo/MatrixDemo.ino index 93cd61c..9bde689 100644 --- a/examples/MatrixDemo/MatrixDemo.ino +++ b/examples/MatrixDemo/MatrixDemo.ino @@ -48,10 +48,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/MatrixShowAllColors/MatrixShowAllColors.ino b/examples/MatrixShowAllColors/MatrixShowAllColors.ino index bf135cb..b5a7002 100644 --- a/examples/MatrixShowAllColors/MatrixShowAllColors.ino +++ b/examples/MatrixShowAllColors/MatrixShowAllColors.ino @@ -48,10 +48,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/MultiplePatternsOnOneBar/MultiplePatternsOnOneBar.ino b/examples/MultiplePatternsOnOneBar/MultiplePatternsOnOneBar.ino index fa4998d..bbb4856 100644 --- a/examples/MultiplePatternsOnOneBar/MultiplePatternsOnOneBar.ino +++ b/examples/MultiplePatternsOnOneBar/MultiplePatternsOnOneBar.ino @@ -48,10 +48,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/NeoPatternsSimpleDemo/NeoPatternsSimpleDemo.ino b/examples/NeoPatternsSimpleDemo/NeoPatternsSimpleDemo.ino index 895c3ed..ffa593c 100644 --- a/examples/NeoPatternsSimpleDemo/NeoPatternsSimpleDemo.ino +++ b/examples/NeoPatternsSimpleDemo/NeoPatternsSimpleDemo.ino @@ -40,10 +40,7 @@ NeoPatterns bar16 = NeoPatterns(16, PIN_NEOPIXEL_BAR_16, NEO_GRB + NEO_KHZ800, & void setup() { Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/OpenLedRace/OpenLedRace.ino b/examples/OpenLedRace/OpenLedRace.ino index a6b669f..399abba 100644 --- a/examples/OpenLedRace/OpenLedRace.ino +++ b/examples/OpenLedRace/OpenLedRace.ino @@ -690,8 +690,8 @@ void setup() { #endif Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) + delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__)); diff --git a/examples/OpenLedRace/PlayRtttl.h b/examples/OpenLedRace/PlayRtttl.h index 0eaf636..b61e514 100644 --- a/examples/OpenLedRace/PlayRtttl.h +++ b/examples/OpenLedRace/PlayRtttl.h @@ -41,11 +41,14 @@ #endif #include "pitches.h" -#define VERSION_PLAY_RTTTL "1.4.0" +#define VERSION_PLAY_RTTTL "1.4.1" #define VERSION_PLAY_RTTTL_MAJOR 1 #define VERSION_PLAY_RTTTL_MINOR 4 /* + * Version 1.4.1 - 9/2020 + * - Removed blocking wait for ATmega32U4 Serial in examples. + * * Version 1.4.0 - 1/2020 * - Supporting direct tone output at pin 11 for ATmega328. Can be used with interrupt blocking libraries for NeoPixel etc. * - Use Print * instead of Stream *. @@ -75,9 +78,8 @@ * - new setNumberOfLoops() and setDefaultStyle() functions. */ -//#define USE_NON_STANDARD_SERIAL_FOR_DEBUG // if activated you must -you are able to- set your own serial class for debugging purposes by setSerialForPlayRtttlDebug() - -#if ! defined(USE_NO_RTX_EXTENSIONS) // if defined it suppresses the next 2 defines / useful for ATtinies to shrink code +#if ! defined(USE_NO_RTX_EXTENSIONS) // if defined it suppresses the next 2 defines / useful for ATtinies to shrink code up to 182 bytes +// Even without `SUPPORT_RTX_EXTENSIONS` the default style is natural (Tone length = note length - 1/16) #define SUPPORT_RTX_EXTENSIONS // needs additional 200 bytes FLASH - support loop and style #define SUPPORT_RTX_FORMAT // needs additional 100 bytes FLASH - can read RTX formatted definitions #endif diff --git a/examples/SnakeAutorun/SnakeAutorun.ino b/examples/SnakeAutorun/SnakeAutorun.ino index f7f6606..3256ef4 100644 --- a/examples/SnakeAutorun/SnakeAutorun.ino +++ b/examples/SnakeAutorun/SnakeAutorun.ino @@ -140,10 +140,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/SnakeGame/SnakeGame.ino b/examples/SnakeGame/SnakeGame.ino index e989cf0..7b3f6c7 100644 --- a/examples/SnakeGame/SnakeGame.ino +++ b/examples/SnakeGame/SnakeGame.ino @@ -61,10 +61,7 @@ void setup() { pinMode(TWO_BUTTON_MODE_SELECT_PIN, INPUT_PULLUP); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/SnowFlakes/SnowFlakes.ino b/examples/SnowFlakes/SnowFlakes.ino index b4dba0e..fa7eec2 100644 --- a/examples/SnowFlakes/SnowFlakes.ino +++ b/examples/SnowFlakes/SnowFlakes.ino @@ -50,10 +50,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.cpp.h b/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.cpp.h index 094823c..e81f480 100644 --- a/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.cpp.h +++ b/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.cpp.h @@ -34,6 +34,7 @@ * along with this program. If not, see . */ +#if defined(__AVR__) #include #include "EasyButtonAtInt01.h" @@ -63,15 +64,17 @@ EasyButton * EasyButton::sPointerToButton0ForISR; EasyButton * EasyButton::sPointerToButton1ForISR; #endif +// @formatter:off // the eclipse formatter has problems with // comments in undefined code blocks + /* - * Constructor deterministic if only one button was enabled - * If two buttons are enabled it is taken as the 1. button at INT0 + * These constructors are deterministic if only one button is enabled + * If two buttons are enabled they can be taken for the 1. button at INT0 */ EasyButton::EasyButton() { -#if defined(USE_BUTTON_1) && not defined(USE_BUTTON_0) - init(false); // 2. button +#if defined(USE_BUTTON_0) + init(true); // 1. button #else - init(true); // 1. button + init(false); // 2. button #endif } /* @@ -79,16 +82,33 @@ EasyButton::EasyButton() { */ EasyButton::EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState)) { ButtonPressCallback = aButtonPressCallback; -#if defined(USE_BUTTON_1) && not defined(USE_BUTTON_0) - init(false); // 2. button +#if defined(USE_BUTTON_0) + init(true); // 1. button #else - init(true); // 1. button + init(false); // 2. button #endif } +#if ! defined(NO_BUTTON_RELEASE_CALLBACK) +EasyButton::EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState), + void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis)) { + ButtonPressCallback = aButtonPressCallback; + ButtonReleaseCallback = aButtonReleaseCallback; +# if defined(USE_BUTTON_0) + init(true); // 1. button +# else + init(false); // 2. button +# endif +} +#endif // NO_BUTTON_RELEASE_CALLBACK + +/* + * These constructors use the first (bool) parameter to decide which button to take. + */ #if defined(USE_BUTTON_0) && defined(USE_BUTTON_1) EasyButton::EasyButton(bool aIsButtonAtINT0) #else +// Constructor with unused attribute to avoid warnings EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused))) #endif { @@ -104,6 +124,7 @@ EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused))) #if defined(USE_BUTTON_0) && defined(USE_BUTTON_1) EasyButton::EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState)) #else +// Constructor with unused attribute to avoid warnings EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aButtonPressCallback)(bool aButtonToggleState)) #endif { @@ -122,6 +143,7 @@ EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aBut EasyButton::EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState), void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis)) # else +// Constructor with unused attribute to avoid warnings EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aButtonPressCallback)(bool aButtonToggleState), void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis)) # endif @@ -252,15 +274,15 @@ void EasyButton::init(bool aIsButtonAtINT0) { /* * ATmega328 (Uno, Nano ) etc. Enable pin change interrupt for port PD0 to PD7 (Arduino pin 0 to 7) */ - PCICR |= 1 << PCIE2; - PCMSK2 = digitalPinToBitMask(INT1_PIN); + PCICR |= 1 << PCIE2; + PCMSK2 = digitalPinToBitMask(INT1_PIN); # else # if defined(USE_ATTACH_INTERRUPT) - attachInterrupt(digitalPinToInterrupt(INT1_PIN), &handleINT1Interrupt, CHANGE); + attachInterrupt(digitalPinToInterrupt(INT1_PIN), &handleINT1Interrupt, CHANGE); # else - EICRA |= (1 << ISC10); // interrupt on any logical change - EIFR |= 1 << INTF1; // clear interrupt bit - EIMSK |= 1 << INT1; // enable interrupt on next change + EICRA |= (1 << ISC10); // interrupt on any logical change + EIFR |= 1 << INTF1; // clear interrupt bit + EIMSK |= 1 << INT1; // enable interrupt on next change # endif //USE_ATTACH_INTERRUPT # endif // ! defined(ISC10) } @@ -275,35 +297,37 @@ void EasyButton::init(bool aIsButtonAtINT0) { bool EasyButton::readButtonState() { #if defined(USE_BUTTON_0) && not defined(USE_BUTTON_1) # if defined(BUTTON_IS_ACTIVE_HIGH) - return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); + return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); # else - return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); + return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); # endif #elif defined(USE_BUTTON_1) && not defined(USE_BUTTON_0) # if defined(BUTTON_IS_ACTIVE_HIGH) - return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); + return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); # else - return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); + return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); # endif #elif defined(USE_BUTTON_0) && defined(USE_BUTTON_1) # if defined(BUTTON_IS_ACTIVE_HIGH) - if (isButtonAtINT0) { - return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); - } else { - return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); - } + if (isButtonAtINT0) { + return (INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); + } else { + return (INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); + } # else - if (isButtonAtINT0) { - return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); - } else { - return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); - } + if (isButtonAtINT0) { + return !(INT0_IN_PORT & _BV(INT0_BIT)); // = digitalReadFast(2); + } else { + return !(INT1_IN_PORT & _BV(INT1_BIT)); // = digitalReadFast(3); + } # endif #endif } +// @formatter:on // the eclipse formatter has problems with // comments in undefined code blocks + /* * Returns stored state if in debouncing period otherwise current state of button */ @@ -652,3 +676,5 @@ ISR(INT1_vect) } # endif #endif // not defined(USE_ATTACH_INTERRUPT) + +#endif // defined(__AVR__) diff --git a/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.h b/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.h index 7db8cf3..7b94141 100644 --- a/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.h +++ b/examples/TwoPatternsOnOneStrip/EasyButtonAtInt01.h @@ -34,11 +34,15 @@ #ifndef EASY_BUTTON_AT_INT01_H_ #define EASY_BUTTON_AT_INT01_H_ -#define VERSION_EASY_BUTTON "3.0.0" +#define VERSION_EASY_BUTTON "3.1.0" #define VERSION_EASY_BUTTON_MAJOR 3 -#define VERSION_EASY_BUTTON_MINOR 0 +#define VERSION_EASY_BUTTON_MINOR 1 /* + * Version 3.1.0 - 6/2020 + * - 2 sets of constructors, one for only one button used and one for the second button if two buttons used. + * - Map pin numbers for Digispark pro boards, for use with with digispark library. + * * Version 3.0.0 - 5/2020 * - Added button release handler and adapted examples. * - Revoke change for "only one true result per press for checkForLongPressBlocking()". It is superseded by button release handler. @@ -57,6 +61,7 @@ * - Renamed to EasyButtonAtInt01.cpp.h */ +#if defined(__AVR__) #include /* @@ -101,7 +106,7 @@ #endif /* - * Comment this out to save 2 bytes RAM and ? bytes FLASH + * Comment this out to save 2 bytes RAM and 64 bytes FLASH */ //#define NO_BUTTON_RELEASE_CALLBACK // @@ -162,35 +167,68 @@ #define INT0_IN_PORT (PINB) #define INT0_OUT_PORT (PORTB) -# if ! defined(INT1_PIN) +# if defined(USE_BUTTON_1) +# if ! defined(INT1_PIN) #define INT1_PIN 3 -# elif (INT1_PIN != 2) && (INT1_PIN > 5) +# elif (INT1_PIN != 2) && (INT1_PIN > 5) #error "INT1_PIN (for PCINT0 interrupt) can only be 0,1,3,4,5" -# endif +# endif #define INT1_DDR_PORT (DDRB) #define INT1_IN_PORT (PINB) #define INT1_OUT_PORT (PORTB) +# endif // defined(USE_BUTTON_1) #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) -# if defined(ARDUINO_AVR_DIGISPARKPRO) -/// Strange enumeration of pins on Digispark board and core library -#define INT0_PIN 3 // PB6 / INT0 is connected to USB+ on DigisparkPro boards and labeled with 3 (D3) -# else -#define INT0_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards -# endif +// from here we use only ATtinyCore / PAx / PBx numbers, since on Digispark board and core library there is used a strange enumeration of pins +#define INT0_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards and labeled with 3 (D3) #define INT0_DDR_PORT (DDRB) #define INT0_IN_PORT (PINB) #define INT0_OUT_PORT (PORTB) -# if ! defined(INT1_PIN) -#define INT1_PIN 3 -# elif (INT1_PIN != 3) && (INT1_PIN > 7) -#error "INT1_PIN (for PCINT0 interrupt) can only be 0 to 2 or 4 to 7" -# endif +# if defined(USE_BUTTON_1) +# if ! defined(INT1_PIN) +#define INT1_PIN 3 // PA3 labeled 9 on DigisparkPro boards +# endif // ! defined(INT1_PIN) + +// Check for pin range and map digispark to PA pin number +# if defined(ARDUINO_AVR_DIGISPARKPRO) +# if INT1_PIN == 5 +#undef INT1_PIN +#define INT1_PIN 7 // PA7 +# elif INT1_PIN == 6 +#undef INT1_PIN +#define INT1_PIN 0 // PA0 +# elif INT1_PIN == 7 +#undef INT1_PIN +#define INT1_PIN 1 // PA1 +# elif INT1_PIN == 8 +#undef INT1_PIN +#define INT1_PIN 2 // PA2 +# elif INT1_PIN == 9 +#undef INT1_PIN +#define INT1_PIN 3 // PA3 +# elif INT1_PIN == 10 +#undef INT1_PIN +#define INT1_PIN 4 // PA4 +# elif INT1_PIN == 11 +#undef INT1_PIN +#define INT1_PIN 5 // PA5 +# elif INT1_PIN == 12 +#undef INT1_PIN +#define INT1_PIN 6 // PA6 +# else +#error "INT1_PIN (for PCINT0 interrupt) can only be 5 to 12" +# endif +# else // defined(ARDUINO_AVR_DIGISPARKPRO) +# if (INT1_PIN > 7) +#error "INT1_PIN (for PCINT0 interrupt) can only be 0 to 7" +# endif +# endif // defined(ARDUINO_AVR_DIGISPARKPRO) #define INT1_DDR_PORT (DDRA) #define INT1_IN_PORT (PINA) #define INT1_OUT_PORT (PORTA) +# endif // defined(USE_BUTTON_1) #else // other AVR MCUs @@ -199,17 +237,21 @@ #define INT0_IN_PORT (PIND) #define INT0_OUT_PORT (PORTD) -# if ! defined(INT1_PIN) +# if defined(USE_BUTTON_1) +# if ! defined(INT1_PIN) #define INT1_PIN 3 -# elif (INT1_PIN > 7) +# elif (INT1_PIN > 7) #error "INT1_PIN (for PCINT2 interrupt) can only be Arduino pins 0 to 7 (PD0 to PD7)" -# endif +# endif #define INT1_DDR_PORT (DDRD) #define INT1_IN_PORT (PIND) #define INT1_OUT_PORT (PORTD) -#endif +# endif // defined(USE_BUTTON_1) +#endif // defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) +#if defined(USE_BUTTON_1) #define INT1_BIT INT1_PIN +#endif #if defined(USE_BUTTON_1) && ((! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3)) \ && ! defined(INTENTIONALLY_USE_PCI0_FOR_BUTTON1) && !(defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) @@ -228,16 +270,26 @@ #define INT0_BIT INT0_PIN #endif +#define BUTTON_AT_INT0 ((bool)true) +#define BUTTON_AT_INT1_OR_PCINT ((bool)false) + class EasyButton { public: /* - * Constructor deterministic if only one button was enabled - * If two buttons are enabled it is taken as the 1. button at INT0 + * These constructors are deterministic if only one button is enabled + * If two buttons are enabled they can be taken for the 1. button at INT0 */ EasyButton(); EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState)); +#if ! defined(NO_BUTTON_RELEASE_CALLBACK) + EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState), + void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis)); +#endif + /* + * These constructors use the first (bool) parameter to decide which button to take. + */ EasyButton(bool aIsButtonAtINT0); EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState)); #if ! defined(NO_BUTTON_RELEASE_CALLBACK) @@ -266,8 +318,8 @@ class EasyButton { void handleINT01Interrupts(); // internal use only bool LastBounceWasChangeToInactive; // Internal state, reflects actual reading with spikes and bouncing. Negative logic: true / active means button pin is LOW - volatile bool ButtonStateIsActive; // Negative logic: true / active means button pin is LOW. If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false) :-( - volatile bool ButtonToggleState; // Toggle is on press, not on release - initial value is false + volatile bool ButtonStateIsActive; // Negative logic: true / active means button pin is LOW. If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false) :-( + volatile bool ButtonToggleState; // Toggle is on press, not on release - initial value is false /* * Flag to enable action only once. Only set to true by library. Can be checked and set to false my main program to enable only one action per button press @@ -280,9 +332,19 @@ class EasyButton { * To cover this case you can call updateButtonState() from an outside loop which updates the button state in this case. */ volatile uint16_t ButtonPressDurationMillis; - volatile unsigned long ButtonLastChangeMillis; // For debouncing - volatile unsigned long ButtonReleaseMillis; // for double press recognition + /* + * Milliseconds of last button change, going active or inactive. + * If bouncing occurs the time is not updated with the time of the bouncing. + * So ButtonPressDurationMillis is the complete time and not the time after the last bounce. + */ + volatile unsigned long ButtonLastChangeMillis; + + /* + * If last button change is going inactive, it contains the same value as ButtonLastChangeMillis + * It is required for double press recognition, which is done when button is active and ButtonLastChangeMillis has just changed. + */ + volatile unsigned long ButtonReleaseMillis; #if defined(ANALYZE_MAX_BOUNCING_PERIOD) volatile unsigned int MaxBouncingPeriodMillis = 0; // Maximum bouncing period. Time between first level change and last bouncing level change during BUTTON_DEBOUNCING_MILLIS @@ -317,6 +379,7 @@ void __attribute__ ((weak)) handleINT0Interrupt(); void __attribute__ ((weak)) handleINT1Interrupt(); #endif +#endif // defined(__AVR__) #endif /* EASY_BUTTON_AT_INT01_H_ */ #pragma once diff --git a/examples/TwoPatternsOnOneStrip/TwoPatternsOnOneStrip.ino b/examples/TwoPatternsOnOneStrip/TwoPatternsOnOneStrip.ino index da67bb8..b8674dc 100644 --- a/examples/TwoPatternsOnOneStrip/TwoPatternsOnOneStrip.ino +++ b/examples/TwoPatternsOnOneStrip/TwoPatternsOnOneStrip.ino @@ -42,7 +42,7 @@ #define VERSION_EXAMPLE "2.0" -EasyButton Button0AtPin3(false); +EasyButton Button0AtPin3; #define PIN_TIMING_DEBUG_BUTTON 6 #define PIN_DELAY_POTI A0 @@ -83,10 +83,7 @@ void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); -#if defined(__AVR_ATmega32U4__) - while (!Serial); //delay for Leonardo, but this loops forever for Maple Serial -#endif -#if defined(SERIAL_USB) +#if defined(__AVR_ATmega32U4__) || defined(SERIAL_USB) || defined(SERIAL_PORT_USBVIRTUAL) delay(2000); // To be able to connect Serial monitor after reset and before first printout #endif // Just to know which program is running on my Arduino diff --git a/library.json b/library.json index 3b4408a..134d7d8 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/ArminJo/NeoPatterns" }, - "version": "2.2.0", + "version": "2.2.1", "exclude": "pictures", "authors": { "name": "Armin Joachimsmeyer", diff --git a/library.properties b/library.properties index b13e892..b964bbc 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=NeoPatterns -version=2.2.0 +version=2.2.1 author=Armin Joachimsmeyer maintainer=Armin Joachimsmeyer sentence=Patterns for NeoPixel strips and matrixes including the patterns of the NeoPattern example by Adafruit.
-paragraph=Patterns from Adafruit are:
  • SCANNER
  • STRIPES
  • DELAY
  • PROCESS_SELECTIVE
  • FADE_SELECTIVE
The original SCANNER pattern is extended and includes the CYLON as well as the ROCKET or FALLING_STAR pattern. The more versatile STRIPES pattern replaces the old THEATER_CHASE one.

NeoPixel-Matrix pattern are:
  • MOVING_PICTURE
  • MOVE
  • TICKER
  • FIRE
  • SNAKE

The SNAKE pattern is an implementation of the Snake game and can be played with 2 or 4 buttons attached to the Arduino.
The SnakeAutorun example will start your own code provided in the function getNextSnakeDirection() to solve the Snake game.
Includes an OpenLedRace example for 2 players.

The extras folder contains sample breadboard pictures as well as a Python script, which enables Snake to be played by PC keyboard or game controller.
YouTube demos are available under https://github.com/ArminJo/NeoPatterns.

To test your own pattern, just add your pattern code to the functions UserPattern\[1,2]() and UserPattern\[1,2]Update() in AllPatternOnOneStrip.cpp to see the patterns. Enable TEST_USER_PATTERNS on line 41 to activate them.
+paragraph=Patterns from Adafruit are:
  • SCANNER
  • STRIPES
  • DELAY
  • PROCESS_SELECTIVE
  • FADE_SELECTIVE
The original SCANNER pattern is extended and includes the CYLON as well as the ROCKET or FALLING_STAR pattern. The more versatile STRIPES pattern replaces the old THEATER_CHASE one.

NeoPixel-Matrix pattern are:
  • MOVING_PICTURE
  • MOVE
  • TICKER
  • FIRE
  • SNAKE
The SNAKE pattern is an implementation of the Snake game and can be played with 2 or 4 buttons attached to the Arduino.
The SnakeAutorun example will start your own code to solve the Snake game provided in the function getNextSnakeDirection().

YouTube demos are available under https://github.com/ArminJo/NeoPatterns.

Includes an OpenLedRace example for 2 players.

New: Removed blocking wait for ATmega32U4 Serial in examples.
category=Display url=https://github.com/ArminJo/NeoPatterns architectures=avr,megaAVR,esp8266,esp32,STM32 diff --git a/src/NeoPatterns.h b/src/NeoPatterns.h index 48de6b9..7ed56f7 100644 --- a/src/NeoPatterns.h +++ b/src/NeoPatterns.h @@ -48,7 +48,7 @@ #define PROGMEM #endif -#define VERSION_NEOPATTERNS "2.2.0" +#define VERSION_NEOPATTERNS "2.2.1" #define VERSION_NEOPATTERNS_MAJOR 2 #define VERSION_NEOPATTERNS_MINOR 2