├── extras ├── RunPythonJoystickForInput.cmd ├── RunPythonKeybordForInput.cmd ├── installPythonforScripts.txt ├── WOKWI_MatrixDemo_diagram.json ├── WOKWI_AllPatternOnOneBar_diagram.json ├── Keyboard2Serial.py └── Joystick2Serial.py ├── pictures ├── SnakeGame.jpg ├── Wokwi_MatrixDemo.png ├── Breadboard_complete.jpg └── Wokwi_AllPatternOnOneBar.png ├── Doxygen.cmd ├── ArduinoLint.cmd ├── library.properties ├── library.json ├── .github └── workflows │ ├── PlatformIoPublish.yml │ └── LibraryBuild.yml ├── src ├── LocalDebugLevelEnd.h ├── fonts.hpp ├── DebugLevel.h ├── LocalDebugLevelStart.h ├── LongUnion.h ├── Colors.h ├── MatrixSnake.h ├── MatrixNeoPixel.h ├── MatrixNeoPatterns.h ├── font_4x6.hpp ├── NeoPixel.h └── ADCUtils.h ├── keywords.txt └── examples ├── MatrixPatternsTest ├── HexDump.h ├── AVRUtils.h └── HexDump.hpp ├── OpenLedRace ├── SoftI2CMasterConfig.h ├── LiquidCrystal_I2C.h ├── MPU6050IMUData.h ├── AVRUtils.h ├── LCDBigNumbers.h ├── README.md └── LiquidCrystal_I2C.hpp ├── MatrixSnow ├── MatrixSnow.ino └── AVRUtils.h ├── MatrixDemo └── MatrixDemo.ino ├── MatrixShowAllColors └── MatrixShowAllColors.ino ├── NeoPatternsSimpleDemo └── NeoPatternsSimpleDemo.ino ├── SnowFlakes └── SnowFlakes.ino ├── AllPatternOnOneBar └── AllPatternOnOneBar.ino ├── SnakeSolver └── SnakeSolver.ino ├── SnakeGame └── SnakeGame.ino ├── MultiplePatternsOnOneBar └── MultiplePatternsOnOneBar.ino └── UserPatterns └── UserPattern.ino /extras/RunPythonJoystickForInput.cmd: -------------------------------------------------------------------------------- 1 | py Joystick2Serial.py 2 | pause -------------------------------------------------------------------------------- /extras/RunPythonKeybordForInput.cmd: -------------------------------------------------------------------------------- 1 | py Keyboard2Serial.py 2 | pause -------------------------------------------------------------------------------- /pictures/SnakeGame.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArminJo/NeoPatterns/HEAD/pictures/SnakeGame.jpg -------------------------------------------------------------------------------- /pictures/Wokwi_MatrixDemo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArminJo/NeoPatterns/HEAD/pictures/Wokwi_MatrixDemo.png -------------------------------------------------------------------------------- /pictures/Breadboard_complete.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArminJo/NeoPatterns/HEAD/pictures/Breadboard_complete.jpg -------------------------------------------------------------------------------- /pictures/Wokwi_AllPatternOnOneBar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArminJo/NeoPatterns/HEAD/pictures/Wokwi_AllPatternOnOneBar.png -------------------------------------------------------------------------------- /Doxygen.cmd: -------------------------------------------------------------------------------- 1 | if exist README.md ( 2 | E:\Elektro\doxygen\bin\doxygen.exe 3 | ) else ( 4 | echo "Please change directory to library root" 5 | ) 6 | pause -------------------------------------------------------------------------------- /ArduinoLint.cmd: -------------------------------------------------------------------------------- 1 | if exist keywords.txt ( 2 | E:\Elektro\arduino_common\arduino-lint.exe --library-manager update --compliance strict 3 | ) else ( 4 | echo "Please change directory to library root" 5 | ) 6 | pause -------------------------------------------------------------------------------- /extras/installPythonforScripts.txt: -------------------------------------------------------------------------------- 1 | install latest Python from https://www.python.org/downloads/ 2 | choose "add Python to PATH variable" or similar. 3 | choose "extend PATH length limit" or similar. 4 | 5 | run "pip install pygame" 6 | run "pip install pyserial" 7 | run "pip install pynput" 8 | 9 | edit baudrate and port at line 15ff. of the Keyboard2Serial.py and Joystick2Serial.py code 10 | 11 | run "RunPythonKeybordForInput.cmd" or "RunPythonJoystickForInput.cmd" -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=NeoPatterns 2 | version=3.3.1 3 | author=Armin Joachimsmeyer 4 | maintainer=Armin Joachimsmeyer 5 | sentence=Patterns for NeoPixel strips and matrixes including the patterns of the NeoPattern example by Adafruit. 6 | paragraph=Patterns not from Adafruit are: SCANNER, STRIPES, FLASH, TWINKLE, 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, SNOW, SNAKE. 7 | category=Display 8 | url=https://github.com/ArminJo/NeoPatterns 9 | architectures=avr,megaavr,esp8266,esp32,stm32,STM32F1 10 | depends=Adafruit NeoPixel 11 | -------------------------------------------------------------------------------- /extras/WOKWI_MatrixDemo_diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "ArminJo", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-nano", 8 | "id": "nano", 9 | "top": -7.99, 10 | "left": -501.32, 11 | "rotate": 0, 12 | "hide": false, 13 | "attrs": {} 14 | }, 15 | { 16 | "type": "wokwi-neopixel-matrix", 17 | "id": "neopixels", 18 | "top": 95.32, 19 | "left": -494.66, 20 | "rotate": 180, 21 | "hide": false, 22 | "attrs": { "rows": "8", "cols": "8", "pin": "3" } 23 | } 24 | ], 25 | "connections": [ 26 | [ "nano:GND.1", "neopixels:GND", "black", [ "v0", "*", "v-10" ] ], 27 | [ "nano:5V", "neopixels:VCC", "red", [ "v0", "*", "v-15" ] ], 28 | [ "nano:8", "neopixels:DIN", "green", [ "v0", "*", "v-5" ] ] 29 | ] 30 | } -------------------------------------------------------------------------------- /extras/WOKWI_AllPatternOnOneBar_diagram.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "author": "ArminJo", 4 | "editor": "wokwi", 5 | "parts": [ 6 | { 7 | "type": "wokwi-arduino-nano", 8 | "id": "nano", 9 | "top": 6.67, 10 | "left": -537.99, 11 | "rotate": 0, 12 | "hide": false, 13 | "attrs": {} 14 | }, 15 | { 16 | "type": "wokwi-neopixel-matrix", 17 | "id": "neopixels", 18 | "top": -24.67, 19 | "left": -354.01, 20 | "rotate": 180, 21 | "hide": false, 22 | "attrs": { "rows": "16", "cols": "1", "matrixBrightness": "5" } 23 | } 24 | ], 25 | "connections": [ 26 | [ "nano:GND.1", "neopixels:GND", "black", [ "v0", "*", "v-10" ] ], 27 | [ "nano:5V", "neopixels:VCC", "red", [ "v0", "*", "v-15" ] ], 28 | [ "nano:3", "neopixels:DIN", "green", [ "v0", "*", "v-5" ] ] 29 | ] 30 | } -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NeoPatterns", 3 | "version": "3.3.1", 4 | "description": "Patterns for NeoPixel strips and matrixes including the patterns of the NeoPattern example by Adafruit.", 5 | "keywords": "NeoPixel, adafruit", 6 | "homepage": "https://github.com/ArminJo/NeoPatterns", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/ArminJo/NeoPatterns.git" 10 | }, 11 | "authors": { 12 | "name": "Armin Joachimsmeyer", 13 | "email": "armin.arduino@gmail.com", 14 | "maintainer": true 15 | }, 16 | "license": "GPL-3.0-or-later", 17 | "frameworks": "arduino", 18 | "platforms": ["atmelavr", "atmelmegaavr", "espressif8266", "espressif32", "ststm32"], 19 | "headers": "NeoPatterns.hpp", 20 | "examples": "examples/*/*.ino", 21 | "dependencies": { "Adafruit/Adafruit NeoPixel": "*"}, 22 | "export": {"exclude": [".github", "pictures"]} 23 | } -------------------------------------------------------------------------------- /.github/workflows/PlatformIoPublish.yml: -------------------------------------------------------------------------------- 1 | # PlatformIoPublish.yml 2 | # Github workflow script to publish a release to PlatformIo. 3 | # 4 | # Copyright (C) 2021-2023 Armin Joachimsmeyer 5 | # https://github.com/ArminJo/Github-Actions 6 | # 7 | 8 | # This is the name of the workflow, visible on GitHub UI. 9 | name: PlatformIo publishing 10 | on: 11 | workflow_dispatch: # To run it manually 12 | description: manual PlatformIo publishing 13 | release: # see: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#example-using-multiple-events-with-activity-types-or-configuration 14 | types: 15 | - created 16 | 17 | jobs: 18 | publish: 19 | runs-on: ubuntu-latest 20 | steps: 21 | 22 | - name: Checkout 23 | uses: actions/checkout@master 24 | 25 | - name: Set up Python 26 | uses: actions/setup-python@master 27 | with: 28 | python-version: '3.x' 29 | 30 | - name: Install dependencies 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install platformio 34 | 35 | - name: Build and publish 36 | env: 37 | PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_TOKEN }} 38 | run: | 39 | pio package publish --owner arminjo --non-interactive 40 | # run: | 41 | # pio package pack 42 | # pio package publish --owner arminjo --non-interactive 43 | -------------------------------------------------------------------------------- /src/LocalDebugLevelEnd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LocalDebugLevelEnd.h 3 | * Undefine local macros at the end of an included (.hpp) file 4 | * 5 | * Copyright (C) 2024 Armin Joachimsmeyer 6 | * Email: armin.joachimsmeyer@gmail.com 7 | * 8 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 9 | * 10 | * Arduino-Utils is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18 | * See the GNU General Public INFOse for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | /* 26 | * Undefine local macros at the end of an included (.hpp) file 27 | */ 28 | #if defined(LOCAL_TRACE) 29 | #undef LOCAL_TRACE 30 | #endif 31 | #undef TRACE_PRINT 32 | #undef TRACE_PRINTLN 33 | #if defined(LOCAL_DEBUG) 34 | #undef LOCAL_DEBUG 35 | #endif 36 | #undef DEBUG_PRINT 37 | #undef DEBUG_PRINTLN 38 | #if defined(LOCAL_INFO) 39 | #undef LOCAL_INFO 40 | #endif 41 | #undef INFO_PRINT 42 | #undef INFO_PRINTLN 43 | -------------------------------------------------------------------------------- /extras/Keyboard2Serial.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import serial 3 | import time 4 | from pynput import keyboard 5 | 6 | refresh_rate = 20 7 | baudrate = 115200 8 | port = 6; 9 | 10 | ser = None 11 | 12 | while ser == None: 13 | # if port is chosen 14 | if port: 15 | try: 16 | ser = serial.Serial('COM' + str(port), baudrate, timeout = 1 / refresh_rate) 17 | except: 18 | pass 19 | else: 20 | # try all ports: 21 | for i in range(10): 22 | try: 23 | ser = serial.Serial('COM' + str(i), baudrate) 24 | print("Port = COM" + str(i)) 25 | break 26 | except: 27 | pass 28 | 29 | if ser == None: 30 | print("Waiting for serial device") 31 | time.sleep(1) 32 | 33 | print("Found serial") 34 | print("Terminate with esc") 35 | 36 | def send_serial(button): 37 | ser.write((button.encode())) 38 | 39 | def on_press(key): 40 | if key == keyboard.Key.esc: 41 | ser.close() 42 | sys.exit() 43 | return False # stop listener 44 | try: 45 | k = key.char # single-char keys 46 | except: 47 | k = key.name # other keys 48 | if k in [ 'w', 'a', 's', 'd']: # keys of interest 49 | send_serial(k) 50 | # return False # stop listener; remove this if want more keys 51 | 52 | listener = keyboard.Listener(on_press=on_press) 53 | listener.start() # start to listen on a separate thread 54 | listener.join() # remove if main thread is polling self.keys 55 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map for NeoPatterns 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | NeoPatterns KEYWORD1 10 | NeoPixel KEYWORD1 11 | MatrixNeoPatterns KEYWORD1 12 | MatrixSnake KEYWORD1 13 | 14 | ####################################### 15 | # Methods and Functions (KEYWORD2) 16 | ####################################### 17 | 18 | update KEYWORD2 19 | RainbowCycle KEYWORD2 20 | ColorWipe KEYWORD2 21 | ScannerExtended KEYWORD2 22 | Fade KEYWORD2 23 | Fire KEYWORD2 24 | Cylon KEYWORD2 25 | Delay KEYWORD2 26 | BouncingBall KEYWORD2 27 | Heartbeat KEYWORD2 28 | UserPattern1 KEYWORD2 29 | UserPattern2 KEYWORD2 30 | 31 | printPatternName KEYWORD2 32 | printInfo KEYWORD2 33 | setCallback KEYWORD2 34 | showPatternInitially KEYWORD2 35 | decrementTotalStepCounter KEYWORD2 36 | setNextIndex KEYWORD2 37 | decrementTotalStepCounterAndSetNextIndex KEYWORD2 38 | updateShowAndWaitForPatternToStop KEYWORD2 39 | 40 | initMultipleFallingStars KEYWORD2 41 | allPatternsRandomHandler KEYWORD2 42 | MatrixAndSnakePatternsDemoHandler KEYWORD2 43 | 44 | ProcessSelectiveColor KEYWORD2 45 | FadeSelectiveColor KEYWORD2 46 | MovingPicturePGM KEYWORD2 47 | TickerPGM KEYWORD2 48 | Ticker KEYWORD2 49 | loadPicturePGM KEYWORD2 50 | Wheel KEYWORD2 51 | HeatColor KEYWORD2 52 | Snake KEYWORD2 53 | begin KEYWORD2 54 | 55 | ####################################### 56 | # Constants (LITERAL1) 57 | ####################################### 58 | 59 | DIRECTION_RIGHT LITERAL1 60 | DIRECTION_LEFT LITERAL1 61 | DIRECTION_UP LITERAL1 62 | DIRECTION_DOWN LITERAL1 63 | COLOR32 LITERAL1 64 | 65 | FLAG_SCANNER_EXT_ROCKET LITERAL1 66 | FLAG_SCANNER_EXT_CYLON LITERAL1 67 | FLAG_SCANNER_EXT_VANISH_COMPLETE LITERAL1 68 | FLAG_SCANNER_EXT_START_AT_BOTH_ENDS LITERAL1 69 | FLAG_DO_NOT_CLEAR LITERAL1 -------------------------------------------------------------------------------- /src/fonts.hpp: -------------------------------------------------------------------------------- 1 | #ifndef _FONTS_HPP 2 | #define _FONTS_HPP 3 | 4 | // All font data from Benedikt K. 5 | // http://www.mikrocontroller.net/topic/54860 6 | 7 | //Font selection (select only one font) 8 | //#define FONT_4X6 9 | //#define FONT_5X8 10 | //#define FONT_5X12 11 | //#define FONT_6X8 12 | //#define FONT_6X10 13 | //#define FONT_7X12 14 | //#define FONT_8X8 15 | //#define FONT_8X12 16 | //#define FONT_8X14 17 | //#define FONT_10X16 18 | //#define FONT_12X16 19 | //#define FONT_12X20 20 | //#define FONT_16X26 21 | 22 | //if defined char range 0x20-0x7F otherwise 0x20-0xFF 23 | //#define FONT_END7F 24 | 25 | #define FONT_START (0x20) //first character 26 | 27 | #if defined(FONT_4X6) 28 | #include "font_4x6.hpp" 29 | # define FONT_WIDTH (4) 30 | # define FONT_HEIGHT (6) 31 | #elif defined(FONT_5X8) 32 | #include "font_5x8.hpp" 33 | # define FONT_WIDTH (5) 34 | # define FONT_HEIGHT (8) 35 | #elif defined(FONT_5X12) 36 | #include "font_5x12.hpp" 37 | # define FONT_WIDTH (5) 38 | # define FONT_HEIGHT (12) 39 | #elif defined(FONT_6X8) 40 | #include "font_6x8.hpp" 41 | # define FONT_WIDTH (6) 42 | # define FONT_HEIGHT (8) 43 | #elif defined(FONT_6X10) 44 | #include "font_6x10.hpp" 45 | # define FONT_WIDTH (6) 46 | # define FONT_HEIGHT (10) 47 | #elif defined(FONT_7X12) 48 | #include "font_7x12.hpp" 49 | # define FONT_WIDTH (7) 50 | # define FONT_HEIGHT (12) 51 | #elif defined(FONT_8X8) 52 | #include "font_8x8.hpp" 53 | # define FONT_WIDTH (8) 54 | # define FONT_HEIGHT (8) 55 | #elif defined(FONT_8X12) 56 | #include "font_8x12.hpp" 57 | # define FONT_WIDTH (8) 58 | # define FONT_HEIGHT (12) 59 | #elif defined(FONT_8X14) 60 | #include "font_8x14.hpp" 61 | # define FONT_WIDTH (8) 62 | # define FONT_HEIGHT (14) 63 | #elif defined(FONT_10X16) 64 | #include "font_10x16.hpp" 65 | # define FONT_WIDTH (10) 66 | # define FONT_HEIGHT (16) 67 | #elif defined(FONT_12X16) 68 | #include "font_12x16.hpp" 69 | # define FONT_WIDTH (12) 70 | # define FONT_HEIGHT (16) 71 | #elif defined(FONT_12X20) 72 | #include "font_12x20.hpp" 73 | # define FONT_WIDTH (12) 74 | # define FONT_HEIGHT (20) 75 | #elif defined(FONT_16X26) 76 | #include "font_16x26.hpp" 77 | # define FONT_WIDTH (16) 78 | # define FONT_HEIGHT (26) 79 | #else 80 | # warning No font defined 81 | #endif 82 | 83 | #endif // _FONTS_HPP 84 | -------------------------------------------------------------------------------- /src/DebugLevel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * DebugLevel.h 3 | * Include to propagate debug levels to each other 4 | * 5 | * TRACE // Information you need to understand details of a function or if you hunt a bug. 6 | * DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. 7 | * INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody". 8 | * WARN // Information that the program may encounter problems, like small Heap/Stack area. 9 | * ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. 10 | * 11 | * 12 | * Copyright (C) 2016-2024 Armin Joachimsmeyer 13 | * Email: armin.joachimsmeyer@gmail.com 14 | * 15 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 16 | * 17 | * Arduino-Utils is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU General Public License as published by 19 | * the Free Software Foundation, either version 3 of the License, or 20 | * (at your option) any later version. 21 | * 22 | * This program is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 25 | * See the GNU General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU General Public License 28 | * along with this program. If not, see . 29 | * 30 | */ 31 | 32 | #ifndef _DEBUGLEVEL_H 33 | #define _DEBUGLEVEL_H 34 | 35 | // Propagate different debug level 36 | #if defined(TRACE) // Information you need to understand details of a function or if you hunt a bug. 37 | # if !defined(DEBUG) 38 | #define DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. 39 | # endif 40 | #endif 41 | #if defined(DEBUG) 42 | # if !defined(INFO) 43 | #define INFO // Information you want to see in regular operation to see what the program is doing. E.g. "START ../src/LightToTone.cpp Version 1.2 from Dec 31 2019" or "Now playing Muppets melody". 44 | # endif 45 | #endif 46 | #if defined(INFO) 47 | # if !defined(WARN) 48 | #define WARN // Information that the program may encounter problems, like small Heap/Stack area. 49 | # endif 50 | #endif 51 | #if defined(WARN) 52 | # if !defined(ERROR) 53 | #define ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. 54 | # endif 55 | #endif 56 | 57 | #endif // _DEBUGLEVEL_H 58 | -------------------------------------------------------------------------------- /examples/MatrixPatternsTest/HexDump.h: -------------------------------------------------------------------------------- 1 | /* 2 | * HexDump.h 3 | * 4 | * Copyright (C) 2022 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * Arduino-Utils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | #ifndef _HEX_DUMP_H 24 | #define _HEX_DUMP_H 25 | 26 | #include 27 | #include 28 | 29 | #define _16_BYTES_PER_LINE 16 30 | 31 | #define HEX_DUMP_FORMAT_16_BIT_ABSOLUTE_ADDRESS 0x00 // Print 16 bit absolute address 32 | #define HEX_DUMP_FORMAT_NO_ADDRESS_AT_ALL 0x01 // Bit 0: else print 33 | #define HEX_DUMP_FORMAT_RELATIVE_ADDRESS 0x02 // Bit 1: else absolute address 34 | #define HEX_DUMP_FORMAT_8_BIT_ADDRESS 0x04 // Bit 2: else 16 bit Address 35 | #define HEX_DUMP_FORMAT_ASCII_VALUES 0x08 // default 36 | 37 | void printBufferHex(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints no address and hex bytes without ASCII representation. 38 | void printBufferHexDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints short relative address and hex bytes without ASCII representation. 39 | void printBufferHexAndASCIIDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints short relative address and hex bytes without ASCII representation. 40 | void printMemoryHexNoASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes with ASCII representation. 41 | void printMemoryHexAndASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes with ASCII representation. 42 | void printStackMemory(uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes ending at top of stack / RAM end. 43 | void printStackDump(); // Prints 16 bit address and hex bytes starting at current stackpointer and ending at ending at top of stack / RAM end. 44 | void printMemoryHexDump(uint8_t *aMemory, uint16_t aSizeOfMemoryToPrint, uint8_t aBytesPerLine = _16_BYTES_PER_LINE, 45 | uint8_t aFormatFlags = HEX_DUMP_FORMAT_ASCII_VALUES); 46 | void printBytePaddedHex(uint8_t aHexValueToPrint); 47 | void printWordPaddedHex(uint16_t aHexValueToPrint); 48 | #endif // _HEX_DUMP_H 49 | -------------------------------------------------------------------------------- /extras/Joystick2Serial.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import serial 3 | import time 4 | 5 | import pygame as pg 6 | 7 | pg.init() 8 | screen = pg.display.set_mode((1, 1)) 9 | clock = pg.time.Clock() 10 | 11 | refresh_rate = 20 12 | baudrate = 115200 13 | port = 6; 14 | 15 | 16 | # init joysticks and get joystick 17 | joystick = None 18 | joystick_type = "Controller (XBOX 360 For Windows)" 19 | 20 | pg.joystick.init() 21 | # get joysticks 22 | joysticks = [pg.joystick.Joystick(x) for x in range(pg.joystick.get_count())] 23 | # select xBox controller 24 | print("devices:") 25 | for j in joysticks: 26 | name = j.get_name() 27 | print(name) 28 | if name == joystick_type: 29 | joystick = j 30 | 31 | if joystick == None: 32 | print("could not detect: ", joystick_type, "\n") 33 | else: 34 | joystick.init() 35 | print("Joystick: " + joystick.get_name()) 36 | 37 | ser = None 38 | 39 | while ser == None: 40 | # if port is chosen 41 | if port: 42 | try: 43 | ser = serial.Serial('COM' + str(port), baudrate, timeout = 1 / refresh_rate) 44 | except: 45 | pass 46 | else: 47 | # try all ports: 48 | for i in range(10): 49 | try: 50 | ser = serial.Serial('COM' + str(i), baudrate) 51 | print("Port = COM" + str(i)) 52 | break 53 | except: 54 | pass 55 | 56 | if ser == None: 57 | print("Waiting for serial device") 58 | time.sleep(1) 59 | 60 | print("found serial") 61 | 62 | buttons = { 63 | 0: "A", 64 | 1: "B", 65 | 2: "X", 66 | 3: "Y", 67 | } 68 | 69 | 70 | hat_to_button = { 71 | (1, 0): "B", 72 | (0, 1): "Y", 73 | (-1, 0): "X", 74 | (0, -1): "A" 75 | } 76 | 77 | def my_quit(): 78 | global loop 79 | loop = False 80 | 81 | def send_serial(button): 82 | ser.write((button.encode())) 83 | 84 | def key_up(): 85 | send_serial("w") 86 | 87 | def key_down(): 88 | send_serial("s") 89 | 90 | def key_left(): 91 | send_serial("a") 92 | 93 | def key_right(): 94 | send_serial("d") 95 | 96 | keydown_func = { 97 | pg.K_ESCAPE: my_quit, 98 | pg.K_RIGHT: key_right, 99 | pg.K_LEFT: key_left, 100 | pg.K_UP: key_up, 101 | pg.K_DOWN: key_down, 102 | } 103 | 104 | loop = True 105 | while loop: 106 | clock.tick(refresh_rate) 107 | for e in pg.event.get(): 108 | if e.type == pg.QUIT: 109 | loop = False 110 | elif e.type == pg.KEYDOWN: 111 | try: 112 | keydown_func[e.key]() 113 | except: 114 | sys.stderr.write("No such Key!") 115 | sys.stderr.flush() 116 | elif e.type == pg.JOYBUTTONDOWN: 117 | if e.button in buttons: 118 | send_serial(buttons[e.button]) 119 | elif e.type == pg.JOYHATMOTION: 120 | if e.value in hat_to_button: 121 | send_serial(hat_to_button[e.value]) 122 | 123 | print_str = str(ser.readline().decode().strip()) 124 | 125 | if print_str: 126 | print(print_str) 127 | 128 | pg.quit() 129 | ser.close() 130 | -------------------------------------------------------------------------------- /src/LocalDebugLevelStart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LocalDebugLevelStart.h 3 | * Include to propagate global debug levels to file local ones and to define appropriate print macros. 4 | * To propagate debug levels to each other, use #include "DebugLevel.h". 5 | * !!! If used in included (.hpp) files, #include "LocalDebugLevelEnd.h" must be used at end of file to undefine local macros. 6 | * 7 | * LOCAL_TRACE // Information you need to understand details of a function or if you hunt a bug. 8 | * LOCAL_DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. 9 | * LOCAL_INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody". 10 | * LOCAL_WARN // Information that the program may encounter problems, like small Heap/Stack area. 11 | * LOCAL_ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. 12 | * 13 | * Copyright (C) 2024-2025 Armin Joachimsmeyer 14 | * Email: armin.joachimsmeyer@gmail.com 15 | * 16 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 17 | * 18 | * Arduino-Utils is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU General Public License as published by 20 | * the Free Software Foundation, either version 3 of the License, or 21 | * (at your option) any later version. 22 | * 23 | * This program is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 | * See the GNU General Public INFOse for more details. 27 | * 28 | * You should have received a copy of the GNU General Public License 29 | * along with this program. If not, see . 30 | * 31 | */ 32 | 33 | /* 34 | * Propagate debug level to local ones but at first not to each other, i.e. enabling TRACE does not enable DEBUG and INFO 35 | */ 36 | #if defined(TRACE) 37 | #define LOCAL_TRACE 38 | #endif 39 | 40 | #if defined(DEBUG) 41 | #define LOCAL_DEBUG 42 | #endif 43 | 44 | #if defined(INFO) 45 | #define LOCAL_INFO 46 | #endif 47 | 48 | #if defined(PROPAGATE_DEBUG_LEVELS) 49 | /* 50 | * Propagate levels i.e. enabling TRACE does not enable DEBUG and INFO 51 | */ 52 | # if defined(LOCAL_TRACE) 53 | #define LOCAL_DEBUG 54 | # endif 55 | # if defined(LOCAL_DEBUG) 56 | #define LOCAL_INFO 57 | # endif 58 | #endif // defined(PROPAGATE_DEBUG_LEVELS) 59 | 60 | /* 61 | * Define appropriate print macros 62 | */ 63 | #if defined(LOCAL_TRACE) 64 | #define TRACE_PRINT(...) Serial.print(__VA_ARGS__) 65 | #define TRACE_PRINTLN(...) Serial.println(__VA_ARGS__) 66 | #else 67 | #define TRACE_PRINT(...) void() 68 | #define TRACE_PRINTLN(...) void() 69 | #endif 70 | 71 | #if defined(LOCAL_DEBUG) 72 | #define DEBUG_PRINT(...) Serial.print(__VA_ARGS__) 73 | #define DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) 74 | #else 75 | #define DEBUG_PRINT(...) void() 76 | #define DEBUG_PRINTLN(...) void() 77 | #endif 78 | 79 | #if defined(LOCAL_INFO) 80 | #define INFO_PRINT(...) Serial.print(__VA_ARGS__) 81 | #define INFO_PRINTLN(...) Serial.println(__VA_ARGS__) 82 | #else 83 | #define INFO_PRINT(...) void() 84 | #define INFO_PRINTLN(...) void() 85 | #endif 86 | 87 | -------------------------------------------------------------------------------- /examples/OpenLedRace/SoftI2CMasterConfig.h: -------------------------------------------------------------------------------- 1 | /* Arduino SoftI2C library. 2 | * 3 | * SoftI2CMasterConfig.h 4 | * 5 | * This contains a sample configuration setting for SoftI2CMaster.h 6 | * The existence of this file can trigger the use of SoftI2CMaster by usage of #if __has_include("SoftI2CMasterConfig.h"), 7 | * which saves 2110 bytes program memory and 200 bytes RAM compared with Arduino Wire. 8 | * 9 | * Copyright (C) 2022, Armin Joachimsmeyer 10 | * 11 | * This file is part of SoftI2CMaster https://github.com/felias-fogg/SoftI2CMaster. 12 | * 13 | * This Library is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This Library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with the Arduino I2cMaster Library. If not, see 25 | * . 26 | */ 27 | 28 | /* In order to use the library, you need to define SDA_PIN, SCL_PIN, 29 | * SDA_PORT and SCL_PORT before including this file. Have a look at 30 | * http://www.arduino.cc/en/Reference/PortManipulation for finding out 31 | * which values to use. For example, if you use digital pin 3 (corresponding 32 | * to PD3) for SDA and digital pin 13 (corresponding to PB5) 33 | * for SCL on a standard Arduino, 34 | * you have to use the following definitions: 35 | * #define SDA_PIN 3 36 | * #define SDA_PORT PORTD 37 | * #define SCL_PIN 5 38 | * #define SCL_PORT PORTB 39 | * 40 | * Alternatively, you can define the compile time constant I2C_HARDWARE, 41 | * in which case the TWI hardware is used. In this case you have to use 42 | * the standard SDA/SCL pins (and, of course, the chip needs to support 43 | * this). 44 | * 45 | * You can also define the following constants (see also below): 46 | ' - I2C_PULLUP = 1 meaning that internal pullups should be used 47 | * - I2C_CPUFREQ, when changing CPU clock frequency dynamically 48 | * - I2C_FASTMODE = 1 meaning that the I2C bus allows speeds up to 400 kHz 49 | * - I2C_SLOWMODE = 1 meaning that the I2C bus will allow only up to 25 kHz 50 | * - I2C_NOINTERRUPT = 1 in order to prohibit interrupts while 51 | * communicating (see below). This can be useful if you use the library 52 | * for communicating with SMbus devices, which have timeouts. 53 | * Note, however, that interrupts are disabled from issuing a start condition 54 | * until issuing a stop condition. So use this option with care! 55 | * - I2C_TIMEOUT = 0...10000 msec in order to return from the I2C functions 56 | * in case of a I2C bus lockup (i.e., SCL constantly low). 0 means no timeout. 57 | * - I2C_MAXWAIT = 0...32767 number of retries in i2c_start_wait. 0 means never stop. 58 | */ 59 | #ifndef _SOFT_I2C_MASTER_CONFIG_H 60 | #define _SOFT_I2C_MASTER_CONFIG_H 61 | 62 | //#define SCL_PIN 5 63 | //#define SCL_PORT PORTC 64 | //#define SDA_PIN 4 65 | //#define SDA_PORT PORTC 66 | #define I2C_HARDWARE 1 // use I2C Hardware 67 | #define I2C_PULLUP 1 68 | //#define I2C_TIMEOUT 5000 // costs 350 bytes 69 | #define I2C_FASTMODE 1 70 | 71 | #endif // _SOFT_I2C_MASTER_CONFIG_H 72 | -------------------------------------------------------------------------------- /examples/OpenLedRace/LiquidCrystal_I2C.h: -------------------------------------------------------------------------------- 1 | //YWROBOT 2 | #ifndef LiquidCrystal_I2C_h 3 | #define LiquidCrystal_I2C_h 4 | 5 | #include 6 | #include "Print.h" 7 | #if !defined(USE_SOFT_I2C_MASTER) && !defined(USE_SOFT_WIRE) 8 | #include 9 | #endif 10 | 11 | // commands 12 | #define LCD_CLEARDISPLAY 0x01 13 | #define LCD_RETURNHOME 0x02 14 | #define LCD_ENTRYMODESET 0x04 15 | #define LCD_DISPLAYCONTROL 0x08 16 | #define LCD_CURSORSHIFT 0x10 17 | #define LCD_FUNCTIONSET 0x20 18 | #define LCD_SETCGRAMADDR 0x40 19 | #define LCD_SETDDRAMADDR 0x80 20 | 21 | // flags for display entry mode 22 | #define LCD_ENTRYRIGHT 0x00 23 | #define LCD_ENTRYLEFT 0x02 24 | #define LCD_ENTRYSHIFTINCREMENT 0x01 25 | #define LCD_ENTRYSHIFTDECREMENT 0x00 26 | 27 | // flags for display on/off control 28 | #define LCD_DISPLAYON 0x04 29 | #define LCD_DISPLAYOFF 0x00 30 | #define LCD_CURSORON 0x02 31 | #define LCD_CURSOROFF 0x00 32 | #define LCD_BLINKON 0x01 33 | #define LCD_BLINKOFF 0x00 34 | 35 | // flags for display/cursor shift 36 | #define LCD_DISPLAYMOVE 0x08 37 | #define LCD_CURSORMOVE 0x00 38 | #define LCD_MOVERIGHT 0x04 39 | #define LCD_MOVELEFT 0x00 40 | 41 | // flags for function set 42 | #define LCD_8BITMODE 0x10 43 | #define LCD_4BITMODE 0x00 44 | #define LCD_2LINE 0x08 45 | #define LCD_1LINE 0x00 46 | #define LCD_5x10DOTS 0x04 47 | #define LCD_5x8DOTS 0x00 48 | 49 | // flags for backlight control 50 | #define LCD_BACKLIGHT 0x08 51 | #define LCD_NOBACKLIGHT 0x00 52 | 53 | #define En 0b00000100 // Enable bit 54 | #define Rw 0b00000010 // Read/Write bit 55 | #define Rs 0b00000001 // Register select bit 56 | 57 | class LiquidCrystal_I2C : public Print { 58 | public: 59 | LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows); 60 | void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS ); 61 | void clear(); 62 | void home(); 63 | void noDisplay(); 64 | void display(); 65 | void noBlink(); 66 | void blink(); 67 | void noCursor(); 68 | void cursor(); 69 | void scrollDisplayLeft(); 70 | void scrollDisplayRight(); 71 | void printLeft(); 72 | void printRight(); 73 | void leftToRight(); 74 | void rightToLeft(); 75 | void shiftIncrement(); 76 | void shiftDecrement(); 77 | void noBacklight(); 78 | void backlight(); 79 | void autoscroll(); 80 | void noAutoscroll(); 81 | void createChar(uint8_t, uint8_t[]); 82 | void createChar(uint8_t location, const char *charmap); 83 | // Example: const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000}; 84 | 85 | void setCursor(uint8_t, uint8_t); 86 | size_t write(uint8_t); 87 | void command(uint8_t); 88 | void init(); 89 | void oled_init(); 90 | 91 | ////compatibility API function aliases 92 | void blink_on(); // alias for blink() 93 | void blink_off(); // alias for noBlink() 94 | void cursor_on(); // alias for cursor() 95 | void cursor_off(); // alias for noCursor() 96 | void setBacklight(uint8_t new_val); // alias for backlight() and nobacklight() 97 | void load_custom_character(uint8_t char_num, uint8_t *rows); // alias for createChar() 98 | void printstr(const char[]); 99 | 100 | ////Unsupported API functions (not implemented in this library) 101 | uint8_t status(); 102 | void setContrast(uint8_t new_val); 103 | uint8_t keypad(); 104 | void setDelay(int,int); 105 | void on(); 106 | void off(); 107 | uint8_t init_bargraph(uint8_t graphtype); 108 | void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); 109 | void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end); 110 | 111 | 112 | private: 113 | void init_priv(); 114 | void send(uint8_t, uint8_t); 115 | void write4bits(uint8_t); 116 | void expanderWrite(uint8_t); 117 | void pulseEnable(uint8_t); 118 | uint8_t _Addr; 119 | uint8_t _displayfunction; 120 | uint8_t _displaycontrol; 121 | uint8_t _displaymode; 122 | uint8_t _numlines; 123 | bool _oled; 124 | uint8_t _cols; 125 | uint8_t _rows; 126 | uint8_t _backlightval; 127 | }; 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /examples/OpenLedRace/MPU6050IMUData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MPU6050IMUData.h 3 | * 4 | * Functions for getting IMU data from MPU6050 for car control. 5 | * 6 | * Created on: 19.11.2019 7 | * Copyright (C) 2020 Armin Joachimsmeyer 8 | * armin.joachimsmeyer@gmail.com 9 | * 10 | * This file is part of PWMMotorControl https://github.com/ArminJo/PWMMotorControl. 11 | * 12 | * PWMMotorControl is free software: you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation, either version 3 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 20 | * See the GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program. If not, see . 24 | */ 25 | 26 | #ifndef _MPU6050_IMU_DATA_H 27 | #define _MPU6050_IMU_DATA_H 28 | 29 | #include 30 | #include "MPU6050Defines.h" 31 | #include "LongUnion.h" 32 | 33 | #if defined(USE_ONLY_ACCEL_FLOATING_OFFSET) 34 | #define USE_ACCEL_FLOATING_OFFSET 35 | #endif 36 | 37 | class MPU6050IMUData { 38 | public: 39 | uint8_t I2CAddress; // For USE_SOFT_I2C_MASTER this is the full 8 byte address with LSB == 0 40 | #if !defined(USE_ONLY_ACCEL_FLOATING_OFFSET) 41 | int16_t AcceleratorOffset[NUMBER_OF_ACCEL_VALUES]; // stores the initial offsets for the 3 axes 42 | LongUnion Speed[NUMBER_OF_ACCEL_VALUES]; 43 | bool OffsetsJustHaveChanged; // To be used for print as flag, that printing once has happened 44 | #endif 45 | int16_t Accelerator[NUMBER_OF_ACCEL_VALUES]; // Values compensated with initial offset, +/-2 | 4 g for 16 bit full range 46 | #if defined(USE_ACCEL_FLOATING_OFFSET) 47 | // The low pass value is in the HighWord, the LowWord holds the fraction 48 | LongUnion AcceleratorLowpassSubOneHertz[NUMBER_OF_ACCEL_VALUES]; // stores the low pass (0.6 Hz) values (-> floating offsets) for the 3 axes 49 | uint8_t LowPassShiftValue; // Computed at init dependent of the sample frequency, to have a fixed AcceleratorLowpassSubOneHertz filter value 50 | #endif 51 | 52 | #if !defined(DO_NOT_USE_GYRO) 53 | int16_t GyroscopeOffset[NUMBER_OF_GYRO_VALUES]; 54 | int16_t Gyro[NUMBER_OF_GYRO_VALUES]; 55 | /* 56 | * 1000 samples / second 57 | * => 17 bit LSB per degree at +/-250 dps range 58 | * The upper word has a resolution of 1/2 degree at 1000 samples per second 59 | * The upper word has a resolution of 1 degree at 500 samples per second 60 | */ 61 | LongUnion Rotation[NUMBER_OF_GYRO_VALUES]; 62 | #endif 63 | 64 | int16_t CountOfFifoChunksForOffset = 0; // signed, since it is used in formulas with other signed values 65 | 66 | MPU6050IMUData(); 67 | MPU6050IMUData(uint8_t aI2CAddress); 68 | 69 | /* 70 | * Initialization 71 | */ 72 | void setI2CAddress(uint8_t aI2CAddress); 73 | bool initMPU6050(uint8_t aSampleRateDivider, mpu6050_bandwidth_t aLowPassIndex); 74 | bool initMPU6050AndCalculateAllOffsetsAndWait(uint8_t aSampleRateDivider, mpu6050_bandwidth_t aLowPassType); 75 | void printLP8Offsets(Print *aSerial); 76 | void printAllOffsets(Print *aSerial); 77 | 78 | /* 79 | * Read data with and without FIFO 80 | */ 81 | void initMPU6050Fifo(); 82 | void resetMPU6050Fifo(); 83 | void resetOffset(); 84 | uint8_t readDataFromMPU6050Fifo(); 85 | void readDataFromMPU6050(); 86 | 87 | /* 88 | * Low level functions 89 | */ 90 | void MPU6050WriteByte(uint8_t aRegisterNumber, uint8_t aData); 91 | uint16_t MPU6050ReadWord(uint8_t aRegisterNumber); 92 | uint16_t MPU6050ReadWordSwapped(uint8_t aRegisterNumber); 93 | 94 | /* 95 | * 96 | */ 97 | unsigned int computeAccelerationWithInitialOffset(); 98 | unsigned int computeAccelerationWithFloatingOffset(); 99 | 100 | }; 101 | 102 | bool initWire(); 103 | 104 | #endif // _MPU6050_IMU_DATA_H 105 | -------------------------------------------------------------------------------- /examples/MatrixSnow/MatrixSnow.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixSnow.cpp 3 | * 4 | * For testing the MatrixNeoPatterns Snow pattern on a 16 x 16 or on a 8 x 8 matrix 5 | * 6 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 7 | * 8 | * Copyright (C) 2019-2022 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 12 | * 13 | * NeoPatterns is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | #include 29 | 30 | //#define ENABLE_MATRIX_PATTERN_SNOW // not required since we call SnowUpdate() directly and do not call update(). 31 | //#define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 32 | //#define DO_NOT_SUPPORT_BRIGHTNESS // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 33 | //#define DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS // If activated, disables writing of zero only if brightness or color is zero. Saves up to 144 bytes ... 34 | 35 | //#define DEBUG 36 | #define INFO 37 | #include 38 | 39 | #if defined(__AVR__) 40 | #include "AVRUtils.h" // for printRAMInfo() 41 | #endif 42 | 43 | //#define USE_16_X_16_MATRIX // else 8x8 matrix 44 | 45 | #define PIN_NEOPIXEL_MATRIX 8 46 | #if defined(USE_16_X_16_MATRIX) 47 | #define MATRIX_NUMBER_OF_COLUMNS 16 48 | #define MATRIX_NUMBER_OF_ROWS 16 49 | #define MATRIX_GEOMETRY (NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_ZIGZAG) 50 | #else 51 | #define MATRIX_NUMBER_OF_COLUMNS 8 52 | #define MATRIX_NUMBER_OF_ROWS 8 53 | #define MATRIX_GEOMETRY (NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE) 54 | #endif 55 | /* 56 | * Specify your matrix geometry as 4th parameter. 57 | * ....BOTTOM ....RIGHT specify the position of the zeroth pixel. 58 | * See MatrixNeoPatterns.h for further explanation. 59 | */ 60 | MatrixNeoPatterns NeoPixelMatrix = MatrixNeoPatterns(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX, 61 | MATRIX_GEOMETRY, NEO_GRB + NEO_KHZ800, nullptr); 62 | 63 | void setup() { 64 | pinMode(LED_BUILTIN, OUTPUT); 65 | 66 | Serial.begin(115200); 67 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 68 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 69 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 70 | #endif 71 | // Just to know which program is running on my Arduino 72 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 73 | NeoPixelMatrix.printConnectionInfo(&Serial); 74 | 75 | // This initializes the NeoPixel library and checks if enough memory was available 76 | if (!NeoPixelMatrix.begin(&Serial)) { 77 | // Blink forever 78 | while (true) { 79 | digitalWrite(LED_BUILTIN, HIGH); 80 | delay(500); 81 | digitalWrite(LED_BUILTIN, LOW); 82 | delay(500); 83 | } 84 | } 85 | NeoPixelMatrix.clear(); //clear all 86 | 87 | Serial.println(F("Snow")); 88 | NeoPixelMatrix.Snow(); 89 | 90 | #if defined(__AVR__) 91 | printRAMInfo(&Serial); 92 | #endif 93 | } 94 | 95 | void loop() { 96 | NeoPixelMatrix.SnowUpdate(); 97 | NeoPixelMatrix.show(); 98 | NeoPixelMatrix.TotalStepCounter = 42; // set to any value > 1 99 | delay(20); 100 | } 101 | -------------------------------------------------------------------------------- /examples/MatrixDemo/MatrixDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixDemo.cpp 3 | * 4 | * Simply runs the MatrixAndSnakePatternsDemoHandler for one 8x8 matrix at PIN_NEO_PIXEL_MATRIX. 5 | * 1. Runs ticker "I love Neopixel" from right to left / from bottom to top 6 | * 2. Moves heart in from top / bottom, show 2 heart beats, and move heart out 7 | * 3. Show 2 snake runs / fire. Snake shows up on the odd loops, fire on the even ones 8 | * 9 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 10 | * 11 | * Copyright (C) 2018 Armin Joachimsmeyer 12 | * armin.joachimsmeyer@gmail.com 13 | * 14 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 15 | * 16 | * NeoPatterns is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published by 18 | * the Free Software Foundation, either version 3 of the License, or 19 | * (at your option) any later version. 20 | * 21 | * This program is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 24 | * See the GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with this program. If not, see . 28 | * 29 | */ 30 | 31 | #include 32 | 33 | #define INFO 34 | 35 | #define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 36 | #define DO_NOT_SUPPORT_BRIGHTNESS // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 37 | //#define DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS // If activated, disables writing of zero only if brightness or color is zero. Saves up to 144 bytes ... 38 | 39 | #define ENABLE_PATTERNS_FOR_MATRIX_AND_SNAKE_DEMO_HANDLER 40 | #include 41 | 42 | #if defined(__AVR__) 43 | # if defined(DEBUG) 44 | #include "AvrTracing.hpp" 45 | #include "AVRUtils.h" 46 | # endif 47 | #endif 48 | 49 | #if defined(ESP32) 50 | #define PIN_NEOPIXEL_MATRIX 2 51 | #else 52 | #define PIN_NEOPIXEL_MATRIX 8 53 | #endif 54 | #define MATRIX_NUMBER_OF_COLUMNS 8 55 | #define MATRIX_NUMBER_OF_ROWS 8 56 | 57 | /* 58 | * Specify your matrix geometry as 4th parameter. 59 | * ....BOTTOM ....RIGHT specify the position of the zeroth pixel. 60 | * See MatrixNeoPatterns.h for further explanation. 61 | */ 62 | MatrixSnake NeoPixelMatrix = MatrixSnake(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX, 63 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800, 64 | &MatrixAndSnakePatternsDemoHandler); 65 | 66 | void setup() { 67 | pinMode(LED_BUILTIN, OUTPUT); 68 | 69 | Serial.begin(115200); 70 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 71 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 72 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 73 | #endif 74 | // Just to know which program is running on my Arduino 75 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 76 | NeoPixelMatrix.printConnectionInfo(&Serial); 77 | 78 | // This initializes the NeoPixel library and checks if enough memory was available 79 | if (!NeoPixelMatrix.begin(&Serial)) { 80 | // Blink forever 81 | while (true) { 82 | digitalWrite(LED_BUILTIN, HIGH); 83 | delay(500); 84 | digitalWrite(LED_BUILTIN, LOW); 85 | delay(500); 86 | } 87 | } 88 | 89 | #if defined(__AVR__) 90 | # if defined(DEBUG) 91 | initStackFreeMeasurement(); 92 | initTrace(); 93 | printFreeRam(&Serial); 94 | # endif 95 | #endif 96 | 97 | MatrixAndSnakePatternsDemoHandler(&NeoPixelMatrix); // start pattern 98 | } 99 | 100 | uint8_t sWheelPosition = 0; // hold the color index for the changing ticker colors 101 | 102 | void loop() { 103 | if (NeoPixelMatrix.update()) { 104 | if (NeoPixelMatrix.ActivePattern == MATRIX_PATTERN_TICKER) { 105 | // change color of ticker after each update 106 | NeoPixelMatrix.Color1 = NeoPatterns::Wheel(sWheelPosition); 107 | sWheelPosition += 4; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/LongUnion.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LongUnion.h 3 | * 4 | * Copyright (C) 2020-2022 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * Arduino-Utils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #if !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H) 25 | 26 | #include 27 | 28 | #ifndef _WORD_UNION_H 29 | #define _WORD_UNION_H 30 | /** 31 | * Union to specify parts / manifestations of a 16 bit Word without casts and shifts. 32 | * It also supports the compiler generating small code. 33 | * Usage: WordUnion tWord; 34 | * tWord.UByte.HighByte = 0x12; 35 | */ 36 | union WordUnion { 37 | struct { 38 | uint8_t LowByte; 39 | uint8_t HighByte; 40 | } UByte; 41 | struct { 42 | int8_t LowByte; 43 | int8_t HighByte; 44 | } Byte; 45 | uint8_t UBytes[2]; // UBytes[0] is LowByte 46 | int8_t Bytes[2]; 47 | uint16_t UWord; 48 | int16_t Word; 49 | uint8_t *BytePointer; 50 | }; 51 | #endif // _WORD_UNION_H 52 | 53 | #ifndef _LONG_UNION_H 54 | #define _LONG_UNION_H 55 | /** 56 | * Union to specify parts / manifestations of a 32 bit Long without casts and shifts. 57 | * It also supports the compiler generating small code. 58 | */ 59 | union LongUnion { 60 | struct { 61 | uint8_t LowByte; 62 | uint8_t MidLowByte; 63 | uint8_t MidHighByte; 64 | uint8_t HighByte; 65 | } UByte; 66 | struct { 67 | int8_t LowByte; 68 | int8_t MidLowByte; 69 | int8_t MidHighByte; 70 | int8_t HighByte; 71 | } Byte; 72 | /* Does not work for STM32 73 | struct { 74 | uint8_t LowByte; 75 | uint16_t MidWord; 76 | uint8_t HighByte; 77 | } UByteWord; 78 | */ 79 | struct { 80 | uint16_t LowWord; 81 | uint16_t HighWord; 82 | } UWord; 83 | struct { 84 | int16_t LowWord; 85 | int16_t HighWord; 86 | } Word; 87 | struct { 88 | WordUnion LowWord; 89 | WordUnion HighWord; 90 | } TwoWordUnions; 91 | uint8_t UBytes[4]; // seems to have the same code size as using struct UByte 92 | int8_t Bytes[4]; // Bytes[0] is LowByte 93 | uint16_t UWords[2]; 94 | int16_t Words[2]; 95 | uint32_t ULong; 96 | int32_t Long; 97 | float Float; 98 | }; 99 | #endif // _LONG_UNION_H 100 | 101 | #ifndef _LONG_LONG_UNION_H 102 | #define _LONG_LONG_UNION_H 103 | /** 104 | * Union to specify parts / manifestations of a 64 bit LongLong without casts and shifts. 105 | * It also supports the compiler generating small code. 106 | */ 107 | union LongLongUnion { 108 | struct { 109 | uint16_t LowWord; 110 | uint16_t MidLowWord; 111 | uint16_t MidHighWord; 112 | uint16_t HighWord; 113 | } UWord; 114 | struct { 115 | int16_t LowWord; 116 | int16_t MidLowWord; 117 | int16_t MidHighWord; 118 | int16_t HighWord; 119 | } Word; 120 | struct { 121 | WordUnion LowWord; 122 | WordUnion MidLowWord; 123 | WordUnion MidHighWord; 124 | WordUnion HighWord; 125 | } FourWordUnions; 126 | struct { 127 | uint32_t LowLong; 128 | uint32_t HighLong; 129 | } ULong; 130 | struct { 131 | int32_t LowLong; 132 | int32_t HighLong; 133 | } Long; 134 | struct { 135 | LongUnion LowLong; 136 | LongUnion HighLong; 137 | } TwoLongUnions; 138 | uint8_t UBytes[8]; // seems to have the same code size as using struct UByte 139 | int8_t Bytes[8]; 140 | uint16_t UWords[4]; 141 | int16_t Words[4]; 142 | uint64_t ULongLong; 143 | int64_t LongLong; 144 | #if __DBL_MANT_DIG__== 24 145 | float Floats[2]; // 32 bit double, as for AVR 146 | #else 147 | // 64 bit double 148 | double Double; 149 | #endif 150 | }; 151 | #endif // _LONG_LONG_UNION_H 152 | 153 | #endif // !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H) 154 | -------------------------------------------------------------------------------- /examples/MatrixShowAllColors/MatrixShowAllColors.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixShowAllColors.cpp 3 | * 4 | * This Example uses the drawAllColors() functions to show all colors. 5 | * To dim the colors, storePixelBuffer() / restorePixelBuffer() together with setBrightness() and gamma8() are used. 6 | * 7 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 8 | * 9 | * Copyright (C) 2021-2022 Armin Joachimsmeyer 10 | * armin.joachimsmeyer@gmail.com 11 | * 12 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 13 | * 14 | * NeoPatterns is free software: you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation, either version 3 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 | * See the GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program. If not, see . 26 | * 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | 33 | #define PIN_NEOPIXEL_MATRIX 8 34 | #define MATRIX_NUMBER_OF_COLUMNS 8 35 | #define MATRIX_NUMBER_OF_ROWS 8 36 | 37 | /* 38 | * Specify your matrix geometry as 4th parameter. 39 | * ....BOTTOM ....RIGHT specify the position of the zeroth pixel. 40 | * See MatrixNeoPatterns.h for further explanation. 41 | */ 42 | MatrixNeoPatterns NeoPixelMatrix = MatrixNeoPatterns(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX, 43 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800, nullptr); 44 | 45 | uint8_t *sPixelBuffer; 46 | 47 | void setup() { 48 | pinMode(LED_BUILTIN, OUTPUT); 49 | 50 | Serial.begin(115200); 51 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 52 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 53 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 54 | #endif 55 | // Just to know which program is running on my Arduino 56 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 57 | NeoPixelMatrix.printConnectionInfo(&Serial); 58 | 59 | // bar24.begin(); 60 | // This initializes the NeoPixel library and checks if enough memory was available 61 | if (!NeoPixelMatrix.begin(&Serial)) { 62 | // Blink forever 63 | while (true) { 64 | digitalWrite(LED_BUILTIN, HIGH); 65 | delay(500); 66 | digitalWrite(LED_BUILTIN, LOW); 67 | delay(500); 68 | } 69 | } 70 | 71 | sPixelBuffer = (uint8_t*) malloc(NeoPixelMatrix.getPixelBufferSize()); 72 | } 73 | 74 | void loop() { 75 | 76 | NeoPixelMatrix.drawAllColors(); 77 | delay(4000); 78 | NeoPixelMatrix.storePixelBuffer(sPixelBuffer); 79 | 80 | // dim pattern 81 | for (int i = 0; i < 256; ++i) { 82 | NeoPixelMatrix.restorePixelBuffer(sPixelBuffer); 83 | NeoPixelMatrix.setBrightness(NeoPixelMatrix.gamma8(255 - i)); 84 | NeoPixelMatrix.show(); 85 | delay(10); 86 | } 87 | 88 | // brighten pattern 89 | for (int i = 0; i < 256; ++i) { 90 | // restore pixels 91 | NeoPixelMatrix.restorePixelBuffer(sPixelBuffer); 92 | NeoPixelMatrix.setBrightness(NeoPixelMatrix.gamma8(i)); 93 | NeoPixelMatrix.show(); 94 | delay(10); 95 | } 96 | 97 | delay(2000); 98 | 99 | NeoPixelMatrix.drawAllColors2(); 100 | delay(4000); 101 | 102 | NeoPixelMatrix.storePixelBuffer(sPixelBuffer); 103 | 104 | // dim pattern 105 | for (int i = 0; i < 256; ++i) { 106 | NeoPixelMatrix.restorePixelBuffer(sPixelBuffer); 107 | NeoPixelMatrix.setBrightness(NeoPixelMatrix.gamma8(255 - i)); 108 | NeoPixelMatrix.show(); 109 | delay(10); 110 | } 111 | 112 | // brighten pattern 113 | for (int i = 0; i < 256; ++i) { 114 | // restore pixels 115 | NeoPixelMatrix.restorePixelBuffer(sPixelBuffer); 116 | NeoPixelMatrix.setBrightness(NeoPixelMatrix.gamma8(i)); 117 | NeoPixelMatrix.show(); 118 | delay(10); 119 | } 120 | delay(4000); 121 | } 122 | -------------------------------------------------------------------------------- /examples/NeoPatternsSimpleDemo/NeoPatternsSimpleDemo.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * NeoPatternsSimpleDemo.cpp 3 | * 4 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 5 | * 6 | * Copyright (C) 2018 Armin Joachimsmeyer 7 | * armin.joachimsmeyer@gmail.com 8 | * 9 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 10 | * 11 | * NeoPatterns is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | * See the GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | #include 27 | 28 | #include 29 | 30 | // Which pin on the Arduino is connected to the NeoPixels? 31 | #define PIN_NEOPIXEL_BAR_16 3 32 | 33 | // onComplete callback functions 34 | void TwoPatterns(NeoPatterns *aLedsPtr); 35 | 36 | // The NeoPatterns instances 37 | NeoPatterns bar16 = NeoPatterns(16, PIN_NEOPIXEL_BAR_16, NEO_GRB + NEO_KHZ800, &TwoPatterns); 38 | 39 | void setup() { 40 | Serial.begin(115200); 41 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 42 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 43 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 44 | #endif 45 | // Just to know which program is running on my Arduino 46 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 47 | bar16.printConnectionInfo(&Serial); 48 | 49 | bar16.begin(); // This sets the pin. 50 | 51 | /* 52 | * First pattern ColorWipe 53 | */ 54 | Serial.println("ColorWipe"); 55 | bar16.ColorWipe(COLOR32(0, 0, 4), 50, false, DIRECTION_DOWN); // light Blue 56 | bar16.updateShowAndWaitForPatternToStop(); 57 | delay(500); 58 | 59 | /* 60 | * Second pattern - RainbowCycle 61 | */ 62 | Serial.println("RainbowCycle"); 63 | bar16.RainbowCycle(10); 64 | bar16.updateShowAndWaitForPatternToStop(); 65 | delay(500); 66 | 67 | /* 68 | * Third pattern - rocket 69 | */ 70 | Serial.println("Rocket"); 71 | bar16.ScannerExtended(COLOR32_WHITE_HALF, 7, 20, 0, FLAG_SCANNER_EXT_VANISH_COMPLETE); 72 | bar16.updateShowAndWaitForPatternToStop(); 73 | delay(500); 74 | 75 | /* 76 | * Now trigger the automatic patterns 77 | */ 78 | TwoPatterns(&bar16); 79 | 80 | Serial.println("started"); 81 | randomSeed(1234); 82 | } 83 | 84 | void loop() { 85 | bar16.update(); 86 | delay(10); 87 | } 88 | 89 | /* 90 | * Simple handler for switching between 2 patterns 91 | */ 92 | void TwoPatterns(NeoPatterns *aLedsPtr) { 93 | static int8_t sState = 0; 94 | 95 | uint8_t tDuration = random8(20, 121); 96 | uint8_t tColorWheelIndex1 = random8(); 97 | uint8_t tColorWheelIndex2 = random8(); 98 | 99 | switch (sState) { 100 | case 0: 101 | // Scanner - use random mode and direction 102 | aLedsPtr->ScannerExtended(NeoPatterns::Wheel(tColorWheelIndex1), 4, tDuration, 2, 103 | (tColorWheelIndex2 & FLAG_SCANNER_EXT_CYLON) | (tColorWheelIndex2 & FLAG_SCANNER_EXT_VANISH_COMPLETE) 104 | | (tColorWheelIndex2 & FLAG_SCANNER_EXT_START_AT_BOTH_ENDS), (tColorWheelIndex1 & DIRECTION_DOWN)); 105 | break; 106 | 107 | case 1: 108 | // Stripes - use random direction 109 | aLedsPtr->Stripes(NeoPatterns::Wheel(tColorWheelIndex1), 5, NeoPatterns::Wheel(tColorWheelIndex2), 3, 110 | 2 * aLedsPtr->numPixels(), tDuration, (tColorWheelIndex2 & DIRECTION_DOWN)); 111 | break; 112 | 113 | case 2: 114 | /* 115 | * Non blocking delay implemented as pattern :-) 116 | */ 117 | aLedsPtr->Delay(1000); 118 | sState = -1; // Start from beginning 119 | break; 120 | 121 | default: 122 | Serial.println("ERROR"); 123 | break; 124 | } 125 | 126 | Serial.print(" ActivePattern="); 127 | aLedsPtr->printPatternName(aLedsPtr->ActivePattern, &Serial); 128 | Serial.print("|"); 129 | Serial.print(aLedsPtr->ActivePattern); 130 | Serial.println(); 131 | 132 | sState++; 133 | } 134 | -------------------------------------------------------------------------------- /examples/MatrixSnow/AVRUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AVRUtils.h 3 | * 4 | * Copyright (C) 2016-2024 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * Arduino-Utils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include "Arduino.h" 25 | 26 | #if defined(__AVR__) && defined (SPMCSR) && !(defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) 27 | #ifndef _AVR_UTILS_H 28 | #define _AVR_UTILS_H 29 | 30 | #include 31 | #include 32 | #include 33 | #include "avr/boot.h" 34 | 35 | /* 36 | * The largest address just not allocated so far 37 | * Under Unix, the "break value" was the end of the data 38 | * segment as dynamically requested from the operating system. 39 | * Since we don't have an operating system, just make sure 40 | * that we don't collide with the stack. 41 | */ 42 | extern void *__brkval; // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() 43 | extern void *__flp; // 44 | extern char __heap_start; // = __bss_end, the linker address of heap start 45 | #define DEFAULT_MALLOC_MARGIN 128 46 | 47 | /* 48 | * The stack amount used for call of malloc(), i.e. Stack is lowered by this value before applying __malloc_margin. 49 | * No malloc() possible if size at caller (stack) position is lower than (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN). 50 | */ 51 | #define HEURISTIC_ADDITIONAL_MALLOC_MARGIN 14 52 | 53 | /* 54 | * storage for millis value to enable compensation for interrupt disable at signal acquisition etc. 55 | */ 56 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 57 | # if !defined(_MILLIS_UTILS_H) 58 | #define timer0_millis millis_timer_millis // The ATTinyCore libraries use other variable name in wiring.c - copied from MillisUtils.h 59 | # endif 60 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 61 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 65 62 | # endif 63 | #else 64 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 65 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 0 // default for Uno / Nano etc. 66 | # endif 67 | #endif 68 | 69 | extern volatile unsigned long timer0_millis; 70 | 71 | void initSleep(uint8_t tSleepMode); 72 | void initPeriodicSleepWithWatchdog(uint8_t tSleepMode, uint8_t aWatchdogPrescaler); 73 | uint16_t computeSleepMillis(uint8_t aWatchdogPrescaler); 74 | void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis = false); 75 | 76 | #include 77 | 78 | uint8_t* getAvailableHeapStart() __attribute__ ((deprecated ("Renamed to getStartOfAvailableHeap()"))); 79 | void printAvailableHeapStart(Print *aSerial) __attribute__ ((deprecated ("Renamed to printStartOfAvailableHeap()"))); 80 | uint8_t* getStartOfAvailableHeap(void); 81 | void printStartOfAvailableHeap(Print *aSerial); 82 | uint16_t getCurrentAvailableStackSize(void); 83 | void printCurrentAvailableStackSize(Print *aSerial); 84 | uint16_t getCurrentAvailableHeapSize(void); 85 | uint16_t getTheoreticalMaximumAvailableHeapSize(void); 86 | void printCurrentAvailableHeapSize(Print *aSerial); 87 | void printCurrentAvailableHeapSizeSimple(Print *aSerial); 88 | // print available heap at current program (SP value matters) position 89 | #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((uint16_t) __malloc_margin)) 90 | 91 | #define HEAP_STACK_UNTOUCHED_VALUE 0x5A 92 | void initStackFreeMeasurement(); 93 | 94 | int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer); 95 | void printStackMaxUsedAndUnusedSizes(Print *aSerial); 96 | bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial); 97 | 98 | void printBaseRAMData(Print *aSerial); 99 | void printRAMInfo(Print *aSerial); 100 | 101 | bool isAddressInRAM(void *aAddressToCheck); 102 | bool isAddressBelowAvailableHeapStart(void *aAddressToCheck); 103 | 104 | void set__malloc_margin(uint8_t aNewMallocMargin); 105 | void reset__malloc_margin(); 106 | 107 | void testCallocSizesAndPrint(Print *aSerial); 108 | 109 | #endif // _AVR_UTILS_H 110 | #endif // defined(__AVR__) 111 | -------------------------------------------------------------------------------- /examples/OpenLedRace/AVRUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AVRUtils.h 3 | * 4 | * Copyright (C) 2016-2024 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * Arduino-Utils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include "Arduino.h" 25 | 26 | #if defined(__AVR__) && defined (SPMCSR) && !(defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) 27 | #ifndef _AVR_UTILS_H 28 | #define _AVR_UTILS_H 29 | 30 | #include 31 | #include 32 | #include 33 | #include "avr/boot.h" 34 | 35 | /* 36 | * The largest address just not allocated so far 37 | * Under Unix, the "break value" was the end of the data 38 | * segment as dynamically requested from the operating system. 39 | * Since we don't have an operating system, just make sure 40 | * that we don't collide with the stack. 41 | */ 42 | extern void *__brkval; // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() 43 | extern void *__flp; // 44 | extern char __heap_start; // = __bss_end, the linker address of heap start 45 | #define DEFAULT_MALLOC_MARGIN 128 46 | 47 | /* 48 | * The stack amount used for call of malloc(), i.e. Stack is lowered by this value before applying __malloc_margin. 49 | * No malloc() possible if size at caller (stack) position is lower than (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN). 50 | */ 51 | #define HEURISTIC_ADDITIONAL_MALLOC_MARGIN 14 52 | 53 | /* 54 | * storage for millis value to enable compensation for interrupt disable at signal acquisition etc. 55 | */ 56 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 57 | # if !defined(_MILLIS_UTILS_H) 58 | #define timer0_millis millis_timer_millis // The ATTinyCore libraries use other variable name in wiring.c - copied from MillisUtils.h 59 | # endif 60 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 61 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 65 62 | # endif 63 | #else 64 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 65 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 0 // default for Uno / Nano etc. 66 | # endif 67 | #endif 68 | 69 | extern volatile unsigned long timer0_millis; 70 | 71 | void initSleep(uint8_t tSleepMode); 72 | void initPeriodicSleepWithWatchdog(uint8_t tSleepMode, uint8_t aWatchdogPrescaler); 73 | uint16_t computeSleepMillis(uint8_t aWatchdogPrescaler); 74 | void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis = false); 75 | 76 | #include 77 | 78 | uint8_t* getAvailableHeapStart() __attribute__ ((deprecated ("Renamed to getStartOfAvailableHeap()"))); 79 | void printAvailableHeapStart(Print *aSerial) __attribute__ ((deprecated ("Renamed to printStartOfAvailableHeap()"))); 80 | uint8_t* getStartOfAvailableHeap(void); 81 | void printStartOfAvailableHeap(Print *aSerial); 82 | uint16_t getCurrentAvailableStackSize(void); 83 | void printCurrentAvailableStackSize(Print *aSerial); 84 | uint16_t getCurrentAvailableHeapSize(void); 85 | uint16_t getTheoreticalMaximumAvailableHeapSize(void); 86 | void printCurrentAvailableHeapSize(Print *aSerial); 87 | void printCurrentAvailableHeapSizeSimple(Print *aSerial); 88 | // print available heap at current program (SP value matters) position 89 | #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((uint16_t) __malloc_margin)) 90 | 91 | #define HEAP_STACK_UNTOUCHED_VALUE 0x5A 92 | void initStackFreeMeasurement(); 93 | 94 | int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer); 95 | void printStackMaxUsedAndUnusedSizes(Print *aSerial); 96 | bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial); 97 | 98 | void printBaseRAMData(Print *aSerial); 99 | void printRAMInfo(Print *aSerial); 100 | 101 | bool isAddressInRAM(void *aAddressToCheck); 102 | bool isAddressBelowAvailableHeapStart(void *aAddressToCheck); 103 | 104 | void set__malloc_margin(uint8_t aNewMallocMargin); 105 | void reset__malloc_margin(); 106 | 107 | void testCallocSizesAndPrint(Print *aSerial); 108 | 109 | #endif // _AVR_UTILS_H 110 | #endif // defined(__AVR__) 111 | -------------------------------------------------------------------------------- /examples/MatrixPatternsTest/AVRUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AVRUtils.h 3 | * 4 | * Copyright (C) 2016-2024 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * Arduino-Utils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #include "Arduino.h" 25 | 26 | #if defined(__AVR__) && defined (SPMCSR) && !(defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) 27 | #ifndef _AVR_UTILS_H 28 | #define _AVR_UTILS_H 29 | 30 | #include 31 | #include 32 | #include 33 | #include "avr/boot.h" 34 | 35 | /* 36 | * The largest address just not allocated so far 37 | * Under Unix, the "break value" was the end of the data 38 | * segment as dynamically requested from the operating system. 39 | * Since we don't have an operating system, just make sure 40 | * that we don't collide with the stack. 41 | */ 42 | extern void *__brkval; // The largest address just not allocated so far / start of available / free heap, initialized at first malloc() 43 | extern void *__flp; // 44 | extern char __heap_start; // = __bss_end, the linker address of heap start 45 | #define DEFAULT_MALLOC_MARGIN 128 46 | 47 | /* 48 | * The stack amount used for call of malloc(), i.e. Stack is lowered by this value before applying __malloc_margin. 49 | * No malloc() possible if size at caller (stack) position is lower than (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN). 50 | */ 51 | #define HEURISTIC_ADDITIONAL_MALLOC_MARGIN 14 52 | 53 | /* 54 | * storage for millis value to enable compensation for interrupt disable at signal acquisition etc. 55 | */ 56 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 57 | # if !defined(_MILLIS_UTILS_H) 58 | #define timer0_millis millis_timer_millis // The ATTinyCore libraries use other variable name in wiring.c - copied from MillisUtils.h 59 | # endif 60 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 61 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 65 62 | # endif 63 | #else 64 | # if !defined(DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN) 65 | #define DEFAULT_MILLIS_FOR_WAKEUP_AFTER_POWER_DOWN 0 // default for Uno / Nano etc. 66 | # endif 67 | #endif 68 | 69 | extern volatile unsigned long timer0_millis; 70 | 71 | void initSleep(uint8_t tSleepMode); 72 | void initPeriodicSleepWithWatchdog(uint8_t tSleepMode, uint8_t aWatchdogPrescaler); 73 | uint16_t computeSleepMillis(uint8_t aWatchdogPrescaler); 74 | void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis = false); 75 | 76 | #include 77 | 78 | uint8_t* getAvailableHeapStart() __attribute__ ((deprecated ("Renamed to getStartOfAvailableHeap()"))); 79 | void printAvailableHeapStart(Print *aSerial) __attribute__ ((deprecated ("Renamed to printStartOfAvailableHeap()"))); 80 | uint8_t* getStartOfAvailableHeap(void); 81 | void printStartOfAvailableHeap(Print *aSerial); 82 | uint16_t getCurrentAvailableStackSize(void); 83 | void printCurrentAvailableStackSize(Print *aSerial); 84 | uint16_t getCurrentAvailableHeapSize(void); 85 | uint16_t getTheoreticalMaximumAvailableHeapSize(void); 86 | void printCurrentAvailableHeapSize(Print *aSerial); 87 | void printCurrentAvailableHeapSizeSimple(Print *aSerial); 88 | // print available heap at current program (SP value matters) position 89 | #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((uint16_t) __malloc_margin)) 90 | 91 | #define HEAP_STACK_UNTOUCHED_VALUE 0x5A 92 | void initStackFreeMeasurement(); 93 | 94 | int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer); 95 | void printStackMaxUsedAndUnusedSizes(Print *aSerial); 96 | bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial); 97 | 98 | void printBaseRAMData(Print *aSerial); 99 | void printRAMInfo(Print *aSerial); 100 | 101 | bool isAddressInRAM(void *aAddressToCheck); 102 | bool isAddressBelowAvailableHeapStart(void *aAddressToCheck); 103 | 104 | void set__malloc_margin(uint8_t aNewMallocMargin); 105 | void reset__malloc_margin(); 106 | 107 | void testCallocSizesAndPrint(Print *aSerial); 108 | 109 | #endif // _AVR_UTILS_H 110 | #endif // defined(__AVR__) 111 | -------------------------------------------------------------------------------- /.github/workflows/LibraryBuild.yml: -------------------------------------------------------------------------------- 1 | # LibraryBuild.yml 2 | # Github workflow script to test compile all examples of an Arduino library repository. 3 | # 4 | # Copyright (C) 2020 Armin Joachimsmeyer 5 | # https://github.com/ArminJo/Github-Actions 6 | # 7 | 8 | # This is the name of the workflow, visible on GitHub UI. 9 | name: LibraryBuild 10 | on: 11 | workflow_dispatch: # To run it manually 12 | description: 'manual build check' 13 | push: # see: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request 14 | paths: 15 | - '**.ino' 16 | - '**.cpp' 17 | - '**.hpp' 18 | - '**.h' 19 | - '**LibraryBuild.yml' 20 | pull_request: 21 | 22 | jobs: 23 | build: 24 | name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples 25 | 26 | runs-on: ubuntu-latest # I picked Ubuntu to use shell scripts. 27 | 28 | env: 29 | # Comma separated list without double quotes around the list. 30 | REQUIRED_LIBRARIES: Adafruit NeoPixel,PlayRtttl 31 | 32 | strategy: 33 | matrix: 34 | # The matrix will produce one job for each configuration parameter of type `arduino-boards-fqbn` 35 | # In the Arduino IDE, the fqbn is printed in the first line of the verbose output for compilation as parameter -fqbn=... for the "arduino-builder -dump-prefs" command 36 | # 37 | # Examples: arduino:avr:uno, arduino:avr:leonardo, arduino:avr:nano, arduino:avr:mega 38 | # arduino:sam:arduino_due_x, arduino:samd:arduino_zero_native" 39 | # ATTinyCore:avr:attinyx5:chip=85,clock=1internal, digistump:avr:digispark-tiny, digistump:avr:digispark-pro 40 | # STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 41 | # esp8266:esp8266:huzzah:eesz=4M3M,xtal=80, esp32:esp32:featheresp32:FlashFreq=80 42 | # You may add a suffix behind the fqbn with "|" to specify one board for e.g. different compile options like arduino:avr:uno|trace 43 | ############################################################################################################# 44 | arduino-boards-fqbn: 45 | - arduino:avr:uno 46 | - arduino:avr:uno|All-DO_NOT_SUPPORT_RGBW 47 | - arduino:avr:leonardo 48 | - arduino:avr:mega 49 | - esp8266:esp8266:huzzah:eesz=4M3M,xtal=80 50 | - esp32:esp32:featheresp32:FlashFreq=80 51 | - STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 52 | # - stm32duino:STM32F1:genericSTM32F103C # 2 issues pending for it 53 | 54 | # Specify parameters for each board. 55 | ############################################################################################################# 56 | include: 57 | - arduino-boards-fqbn: arduino:avr:uno|All-DO_NOT_SUPPORT_RGBW 58 | build-properties: 59 | AllPatternsOnMultiDevices: -DALL_PATTERN_ON_ONE_STRIP -DDO_NOT_SUPPORT_RGBW 60 | OpenLedRace: -DUSE_SOFT_I2C_MASTER -DDO_NOT_SUPPORT_RGBW 61 | SnowFlakes: -DTRACE 62 | All: -DDO_NOT_SUPPORT_RGBW 63 | 64 | - arduino-boards-fqbn: arduino:avr:leonardo 65 | sketches-exclude: AllPatternsOnMultiDevices,OpenLedRace # too big 66 | 67 | - arduino-boards-fqbn: esp8266:esp8266:huzzah:eesz=4M3M,xtal=80 68 | platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json 69 | sketches-exclude: OpenLedRace,MatrixPatternsTest,TwoPatternsOnOneStrip # Comma separated list of example names to exclude in build 70 | 71 | - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80 72 | platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json 73 | sketches-exclude: OpenLedRace,MatrixPatternsTest,TwoPatternsOnOneStrip # MatrixPatternsTest,TwoPatternsOnOneStrip because of missing EasyButton library 74 | 75 | - arduino-boards-fqbn: STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 76 | platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json 77 | sketches-exclude: OpenLedRace,MatrixPatternsTest,TwoPatternsOnOneStrip # MatrixPatternsTest,TwoPatternsOnOneStrip because of missing EasyButton library 78 | 79 | # - arduino-boards-fqbn: stm32duino:STM32F1:genericSTM32F103C # Roger Clark version 80 | # platform-url: http://dan.drown.org/stm32duino/package_STM32duino_index.json 81 | # sketches-exclude: OpenLedRace,MatrixPatternsTest,TwoPatternsOnOneStrip # MatrixPatternsTest,TwoPatternsOnOneStrip because of missing EasyButton library 82 | 83 | # Do not cancel all jobs / architectures if one job fails 84 | fail-fast: false 85 | 86 | steps: 87 | - name: Checkout 88 | uses: actions/checkout@master 89 | 90 | - name: Compile all examples using the arduino-test-compile action 91 | uses: ArminJo/arduino-test-compile@master 92 | with: 93 | arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }} 94 | arduino-platform: ${{ matrix.arduino-platform }} 95 | platform-url: ${{ matrix.platform-url }} 96 | required-libraries: ${{ env.REQUIRED_LIBRARIES }} 97 | sketches-exclude: ${{ matrix.sketches-exclude }} 98 | build-properties: ${{ toJson(matrix.build-properties) }} 99 | -------------------------------------------------------------------------------- /examples/SnowFlakes/SnowFlakes.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * SnowFlakes.cpp 3 | * 4 | * First shows fixed snowflake pattern on a 8x8 Matrix and then creates random patterns. 5 | * Inspired by https://learn.adafruit.com/neopixel-matrix-snowflake-sweater 6 | * 7 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 8 | * 9 | * Copyright (C) 2019-2022 Armin Joachimsmeyer 10 | * armin.joachimsmeyer@gmail.com 11 | * 12 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 13 | * 14 | * NeoPatterns is free software: you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation, either version 3 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 | * See the GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program. If not, see . 26 | * 27 | */ 28 | 29 | #include 30 | 31 | //#define TRACE 32 | 33 | #define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 34 | //#define DO_NOT_SUPPORT_BRIGHTNESS // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 35 | //#define DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS // If activated, disables writing of zero only if brightness or color is zero. Saves up to 144 bytes ... 36 | 37 | #include 38 | 39 | #define PIN_NEOPIXEL_MATRIX 8 40 | #define MATRIX_NUMBER_OF_COLUMNS 8 41 | #define MATRIX_NUMBER_OF_ROWS 8 42 | /* 43 | * Specify your matrix geometry as 4th parameter. 44 | * ....BOTTOM ....RIGHT specify the position of the zeroth pixel. 45 | * See MatrixNeoPatterns.h for further explanation. 46 | */ 47 | MatrixNeoPatterns NeoPixelMatrix = MatrixNeoPatterns(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX, 48 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800, nullptr); 49 | 50 | uint8_t *sPixelBuffer; 51 | 52 | #define TEST_DELAY_MILLIS 2000 53 | 54 | void setup() { 55 | pinMode(LED_BUILTIN, OUTPUT); 56 | 57 | Serial.begin(115200); 58 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 59 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 60 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 61 | #endif 62 | // Just to know which program is running on my Arduino 63 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 64 | NeoPixelMatrix.printConnectionInfo(&Serial); 65 | 66 | // bar24.begin(); 67 | // This initializes the NeoPixel library and checks if enough memory was available 68 | if (!NeoPixelMatrix.begin(&Serial)) { 69 | // Blink forever 70 | while (true) { 71 | digitalWrite(LED_BUILTIN, HIGH); 72 | delay(500); 73 | digitalWrite(LED_BUILTIN, LOW); 74 | delay(500); 75 | } 76 | } 77 | 78 | /* 79 | * Fixed pattern. 80 | * The numbers behind the pattern are related to the pattern number in: 81 | * https://learn.adafruit.com/neopixel-matrix-snowflake-sweater/code 82 | */ 83 | Serial.println(F("Displaying 9 fixed patterns")); 84 | NeoPixelMatrix.drawQuarterPatternOdd(0xDA68, COLOR32_WHITE_HALF, COLOR32_BLACK); // Adafruit pattern 5 85 | delay(TEST_DELAY_MILLIS); 86 | NeoPixelMatrix.drawQuarterPatternOdd(0x7AC8, COLOR32_WHITE_HALF, COLOR32_BLACK); // 6 87 | delay(TEST_DELAY_MILLIS); 88 | NeoPixelMatrix.drawQuarterPatternOdd(0x6DA4, COLOR32_WHITE_HALF, COLOR32_BLACK); // 9 89 | delay(TEST_DELAY_MILLIS); 90 | NeoPixelMatrix.drawQuarterPatternOdd(0x8641, COLOR32_WHITE_HALF, COLOR32_BLACK); // 3 91 | delay(TEST_DELAY_MILLIS); 92 | 93 | NeoPixelMatrix.drawQuarterPatternOdd(~0x7AC8, COLOR32_WHITE_HALF, COLOR32_BLACK); // 11 94 | delay(TEST_DELAY_MILLIS); 95 | NeoPixelMatrix.drawQuarterPatternOdd(~0xDA68, COLOR32_WHITE_HALF, COLOR32_BLACK); // own pattern 96 | delay(TEST_DELAY_MILLIS); 97 | 98 | NeoPixelMatrix.drawQuarterPatternOdd(0x936D, COLOR32_WHITE_HALF, COLOR32_BLACK); // 8 99 | delay(TEST_DELAY_MILLIS); 100 | NeoPixelMatrix.drawQuarterPatternOdd(0x79AC, COLOR32_WHITE_HALF, COLOR32_BLACK); // 1 101 | delay(TEST_DELAY_MILLIS); 102 | NeoPixelMatrix.drawQuarterPatternOdd(0x79AD, COLOR32_WHITE_HALF, COLOR32_BLACK); // 1 103 | delay(TEST_DELAY_MILLIS); 104 | delay(4000); 105 | Serial.println(F("Now creating random patterns")); 106 | } 107 | 108 | void loop() { 109 | // show random pattern in random color 110 | uint16_t tPatternValue = random(250, 64000); 111 | uint8_t tColorValue = random(255); 112 | NeoPixelMatrix.drawQuarterPatternOdd(tPatternValue, NeoPixelMatrix.Wheel(tColorValue), COLOR32_BLACK); // 1 113 | Serial.print(F("Pattern value=0x")); 114 | Serial.print(tPatternValue, HEX); 115 | Serial.print(F(" color=")); 116 | Serial.println(tColorValue); 117 | delay(TEST_DELAY_MILLIS); 118 | } 119 | -------------------------------------------------------------------------------- /src/Colors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Colors.h 3 | * 4 | * 5 | * Copyright (C) 2018-2021 Armin Joachimsmeyer 6 | * armin.joachimsmeyer@gmail.com 7 | * 8 | * This file is part of BlueDisplay https://github.com/ArminJo/android-blue-display. 9 | * 10 | * BlueDisplay is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation, either version 3 of the License, or 13 | * (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 18 | * See the GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | #ifndef _COLORS_H 26 | #define _COLORS_H 27 | 28 | #include 29 | 30 | /* 31 | * Basic 16 Bit Colors 32 | * RGB to 16 bit 565 schema - 5 red | 6 green | 5 blue 33 | */ 34 | typedef uint16_t color16_t; 35 | 36 | // If used as background color for char or text, the background will not filled 37 | #define COLOR16_BLUEMASK 0x1F 38 | #define COLOR16_GET_RED(rgb) ((rgb & 0xF800) >> 8) 39 | #define COLOR16_GET_GREEN(rgb) ((rgb & 0x07E0) >> 3) 40 | #define COLOR16_GET_BLUE(rgb) ((rgb & 0x001F) << 3) 41 | #define COLOR16(r,g,b) ((color16_t)(((r&0xF8)<<8)|((g&0xFC)<<3)|((b&0xF8)>>3))) // 5 red | 6 green | 5 blue 42 | 43 | #define COLOR16_WHITE ((color16_t)0xFFFF) 44 | #define COLOR16_ALMOST_WHITE ((color16_t)0xF7DE) // Every color is 1 bit less than maximum value, but we can distinguish it from white 45 | 46 | #define COLOR16_NO_BACKGROUND ((color16_t)COLOR16_WHITE - 1) // No background drawing for text and button (Only-text button) 47 | 48 | #define COLOR16_LIGHT_GREY ((color16_t)0x7BEF) 49 | #define COLOR16_GREY ((color16_t)0x39E7) 50 | #define COLOR16_DARK_GREY ((color16_t)0x18E3) 51 | 52 | #define COLOR16_NO_DELETE ((color16_t)0X0001) // 01 is used as flag (e.g. for not delete old chart) 53 | #define COLOR16_BLACK ((color16_t)0X0000) 54 | #define COLOR16_RED ((color16_t)0xF800) 55 | #define COLOR16_GREEN ((color16_t)0X07E0) 56 | #define COLOR16_BLUE ((color16_t)0x001F) 57 | #define COLOR16_DARK_BLUE ((color16_t)0x0014) 58 | #define COLOR16_YELLOW ((color16_t)0XFFE0) 59 | #define COLOR16_ORANGE ((color16_t)0XFE00) 60 | #define COLOR16_PURPLE ((color16_t)0xF81F) 61 | #define COLOR16_CYAN ((color16_t)0x07FF) 62 | 63 | /* 64 | * 32 Bit Color values 65 | */ 66 | typedef uint32_t color32_t; 67 | 68 | #define COLOR32_GET_WHITE(color) ((color >> 24) & 0xFF) 69 | #define COLOR32_GET_RED(color) ((color >> 16) & 0xFF) 70 | #define COLOR32_GET_GREEN(color) ((color >> 8) & 0xFF) 71 | #define COLOR32_GET_BLUE(color) (color & 0xFF) 72 | // Eases constant color declarations but should only be used for constant colors. Otherwise better use Adafruit_NeoPixel::Color() to save program memory 73 | #define COLOR32(r,g,b) ((color32_t)(((uint32_t)r<<16)|((uint16_t)g<<8)|b)) // return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 74 | #define COLOR32_W(r,g,b,w) ((color32_t)(((uint32_t)w<<24)|((uint32_t)r<<16)|((uint16_t)g<<8)|b)) // return ((uint32_t)w << 24) |(uint32_t)r << 16) | ((uint32_t)g << 8) | b; 75 | 76 | #define COLOR32_BLACK COLOR32(0,0,0) 77 | 78 | #define COLOR32_WHITE COLOR32(255,255,255) 79 | #define COLOR32_SPECIAL (COLOR32(255,255,255) - 1) // To signal special color treatment e.g. use random color 80 | #define COLOR32_WHITE_HALF COLOR32(128,128,128) // to reduce power consumption 81 | #define COLOR32_WHITE_QUARTER COLOR32(64,64,64) // to reduce power consumption 82 | #define COLOR32_WHITE_EIGHTH COLOR32(32,32,32) // to reduce power consumption 83 | #define COLOR32_WHITE_16TH COLOR32(16,16,16) 84 | #define COLOR32_WHITE_32TH COLOR32(8,8,8) 85 | #define COLOR32_WHITE_64TH COLOR32(4,4,4) 86 | #define COLOR32_WHITE_128TH COLOR32(2,2,2) 87 | #define COLOR32_RED COLOR32(255,0,0) 88 | #define COLOR32_RED_HALF COLOR32(128,0,0) 89 | #define COLOR32_RED_QUARTER COLOR32(64,0,0) 90 | #define COLOR32_GREEN COLOR32(0,255,0) 91 | #define COLOR32_GREEN_HALF COLOR32(0,128,0) 92 | #define COLOR32_GREEN_QUARTER COLOR32(0,64,0) 93 | #define COLOR32_BLUE COLOR32(0,0,255) 94 | #define COLOR32_BLUE_HALF COLOR32(0,0,128) 95 | #define COLOR32_BLUE_QUARTER COLOR32(0,0,64) 96 | #define COLOR32_YELLOW COLOR32(255,200,0) // value was visually determined 97 | #define COLOR32_YELLOW_HALF COLOR32(128,100,0) 98 | #define COLOR32_YELLOW_QUARTER COLOR32(64,50,0) 99 | #define COLOR32_ORANGE COLOR32(255,64,0) // value was visually determined 100 | #define COLOR32_ORANGE_HALF COLOR32(128,32,0) 101 | #define COLOR32_ORANGE_QUARTER COLOR32(64,16,0) 102 | #define COLOR32_PURPLE COLOR32(255,0,255) 103 | #define COLOR32_PURPLE_HALF COLOR32(128,0,128) 104 | #define COLOR32_PURPLE_QUARTER COLOR32(64,0,64) 105 | #define COLOR32_CYAN COLOR32(0,255,255) 106 | #define COLOR32_CYAN_HALF COLOR32(0,128,128) 107 | #define COLOR32_CYAN_QUARTER COLOR32(0,64,64) 108 | 109 | // deprecated 110 | #define COLOR32(r,g,b) ((color32_t)(((uint32_t)r<<16)|((uint16_t)g<<8)|b)) // return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b; 111 | #define COLOR_W32(r,g,b,w) ((color32_t)(((uint32_t)w<<24)|((uint32_t)r<<16)|((uint16_t)g<<8)|b)) // return ((uint32_t)w << 24) |(uint32_t)r << 16) | ((uint32_t)g << 8) | b; 112 | #define WHITE(color) ((color >> 24) & 0xFF) 113 | #define RED(color) ((color >> 16) & 0xFF) 114 | #define GREEN(color) ((color >> 8) & 0xFF) 115 | #define BLUE(color) (color & 0xFF) 116 | // end deprecated 117 | 118 | #endif // _COLORS_H 119 | -------------------------------------------------------------------------------- /examples/AllPatternOnOneBar/AllPatternOnOneBar.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * AllPatternOnOneBar.cpp 3 | * 4 | * Shows all NeoPatterns included in the NeoPatterns library randomly on one 16 pixel bar. 5 | * 6 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 7 | * 8 | * Copyright (C) 2018-2022 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 12 | * 13 | * NeoPatterns is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | #include 29 | 30 | #include 31 | 32 | #define INFO // if not defined, no Serial related code should be linked 33 | 34 | // Which pin on the Arduino is connected to the NeoPixels? 35 | #define PIN_NEOPIXEL_BAR_16 3 36 | 37 | // onComplete callback handler for all patterns 38 | void allPatterns(NeoPatterns *aLedsPtr); 39 | 40 | // Construct the NeoPatterns instances 41 | NeoPatterns bar16 = NeoPatterns(16, PIN_NEOPIXEL_BAR_16, NEO_GRB + NEO_KHZ800, &allPatterns); 42 | 43 | void setup() { 44 | pinMode(LED_BUILTIN, OUTPUT); 45 | 46 | #if defined(INFO) 47 | Serial.begin(115200); 48 | 49 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 50 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 51 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 52 | #endif 53 | // Just to know which program is running on my Arduino 54 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 55 | bar16.printConnectionInfo(&Serial); 56 | #endif 57 | 58 | bar16.begin(); // This initializes the NeoPixel library. 59 | bar16.ColorWipe(COLOR32(0, 0, 02), 50, false, DIRECTION_DOWN); // light Blue 60 | 61 | #if defined(INFO) 62 | Serial.println("started"); 63 | #endif 64 | delay(500); 65 | } 66 | 67 | void loop() { 68 | bar16.update(); 69 | delay(10); 70 | } 71 | 72 | /* 73 | * onComplete callback handler for all patterns 74 | */ 75 | void allPatterns(NeoPatterns *aLedsPtr) { 76 | static int8_t sState = 0; 77 | 78 | uint8_t tDuration = random8(40, 81); 79 | uint8_t tColorWheelIndex = random8(); 80 | 81 | #if defined(INFO) 82 | Serial.print("Pin="); 83 | Serial.print(aLedsPtr->getPin()); 84 | Serial.print(" Length="); 85 | Serial.print(aLedsPtr->numPixels()); 86 | Serial.print(" State="); 87 | Serial.print(sState); 88 | #endif 89 | 90 | switch (sState) { 91 | case 0: 92 | // Cylon 93 | aLedsPtr->ScannerExtended(NeoPatterns::Wheel(tColorWheelIndex), 5, tDuration, 2, FLAG_SCANNER_EXT_CYLON); 94 | break; 95 | case 1: 96 | // Heartbeat 97 | aLedsPtr->Heartbeat(NeoPatterns::Wheel(tColorWheelIndex), tDuration / 2, 2); 98 | break; 99 | case 2: 100 | // rocket and falling star - 2 times bouncing 101 | aLedsPtr->ScannerExtended(NeoPatterns::Wheel(tColorWheelIndex), 7, tDuration, 2, 102 | FLAG_SCANNER_EXT_ROCKET | FLAG_SCANNER_EXT_START_AT_BOTH_ENDS, (tDuration & DIRECTION_DOWN)); 103 | break; 104 | case 3: 105 | aLedsPtr->Stripes(NeoPatterns::Wheel(tColorWheelIndex), 5, NeoPatterns::Wheel(tColorWheelIndex + 0x80), 3, 2 * aLedsPtr->numPixels(), 106 | tDuration * 2, (tDuration & DIRECTION_DOWN)); 107 | break; 108 | case 4: 109 | aLedsPtr->RainbowCycle(tDuration / 4, (tDuration & DIRECTION_DOWN)); 110 | break; 111 | case 5: 112 | // old TheaterChase 113 | aLedsPtr->Stripes(NeoPatterns::Wheel(tColorWheelIndex), 1, NeoPatterns::Wheel(tColorWheelIndex + 0x80), 2, 2 * aLedsPtr->numPixels(), 114 | tDuration * 2, (tDuration & DIRECTION_DOWN)); 115 | break; 116 | case 6: 117 | aLedsPtr->Fade(NeoPatterns::Wheel(tColorWheelIndex), NeoPatterns::Wheel(tColorWheelIndex + 0x80), 64, tDuration); 118 | break; 119 | case 7: 120 | aLedsPtr->ColorWipe(NeoPatterns::Wheel(tColorWheelIndex), tDuration); 121 | break; 122 | case 8: 123 | // clear existing color wipe with black 124 | aLedsPtr->ColorWipe(COLOR32_BLACK, tDuration, true, DIRECTION_DOWN); 125 | break; 126 | case 9: 127 | // Multiple falling star 128 | initMultipleFallingStars(aLedsPtr, COLOR32_WHITE_HALF, 7, tDuration / 2, 3, &allPatterns); 129 | break; 130 | case 10: 131 | if ((aLedsPtr->PixelFlags & PIXEL_FLAG_GEOMETRY_CIRCLE) == 0) { 132 | //Fire 133 | aLedsPtr->Fire(tDuration * 2, tDuration / 2); 134 | } else { 135 | // start at both end 136 | aLedsPtr->ScannerExtended(NeoPatterns::Wheel(tColorWheelIndex), 5, tDuration, 0, 137 | FLAG_SCANNER_EXT_START_AT_BOTH_ENDS | FLAG_SCANNER_EXT_VANISH_COMPLETE); 138 | } 139 | 140 | sState = -1; // Start from beginning 141 | break; 142 | default: 143 | #if defined(INFO) 144 | Serial.println("ERROR"); 145 | #endif 146 | break; 147 | } 148 | 149 | #if defined(INFO) 150 | Serial.print(" ActivePattern="); 151 | aLedsPtr->printPatternName(aLedsPtr->ActivePattern, &Serial); 152 | Serial.print("|"); 153 | Serial.print(aLedsPtr->ActivePattern); 154 | Serial.println(); 155 | #endif 156 | 157 | sState++; 158 | } 159 | -------------------------------------------------------------------------------- /examples/OpenLedRace/LCDBigNumbers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * LCDBigNumbers.h 3 | * 4 | * The plain include file without sources. 5 | * 6 | * Arduino library to write big numbers on a 1602 or 2004 LCD. 7 | * 8 | * Copyright (C) 2022-2023 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of LCDBigNumbers https://github.com/ArminJo/LCDBigNumbers. 12 | * 13 | * LCDBigNumbers is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | #ifndef _LCD_BIG_NUMBERS_H 29 | #define _LCD_BIG_NUMBERS_H 30 | 31 | #include 32 | #define ONE_COLUMN_SPACE_CHARACTER '|' // This character is printed as a one column space. Normal spaces are printed as a space with the width of the number. 33 | #define ONE_COLUMN_SPACE_STRING "|" // This string is printed as a one column space. Normal spaces are printed as a space with the width of the number. 34 | 35 | #define ONE_COLUMN_HYPHEN_CHARACTER '_' // This input character is printed as a one column hyphen. Normal hyphen / minus are printed as a hyphen with the width of the number - 1. 36 | #define ONE_COLUMN_HYPHEN_STRING "_" // This input string is printed as a one column hyphen. Normal hyphen / minus are printed as a hyphen with the width of the number - 1. 37 | 38 | #if !defined(USE_PARALLEL_2004_LCD) && !defined(USE_PARALLEL_1602_LCD) && !defined(USE_SERIAL_2004_LCD) && !defined(USE_SERIAL_1602_LCD) 39 | #define USE_PARALLEL_2004_LCD // Use parallel 2004 LCD as default 40 | #endif 41 | 42 | #if defined(USE_PARALLEL_2004_LCD) || defined(USE_PARALLEL_1602_LCD) 43 | #define USE_PARALLEL_LCD 44 | #include 45 | #else 46 | #include "LiquidCrystal_I2C.h" // Use an up to date library version which has the init method 47 | #endif 48 | 49 | #define COLUMN_MASK 0x0C // Number of columns = shifted masked value + 1 50 | #define ROW_MASK 0x03 // Number of rows = masked value + 1 51 | #define VARIANT_MASK 0x30 52 | // Numbers are created by using the above masks 53 | #define BIG_NUMBERS_FONT_1_COLUMN_2_ROWS_VARIANT_1 0x01 54 | #define BIG_NUMBERS_FONT_2_COLUMN_2_ROWS_VARIANT_1 0x05 55 | #define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_1 0x09 56 | #define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_2 0x19 57 | #define BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_3 0x29 58 | #define BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_1 0x06 59 | #define BIG_NUMBERS_FONT_2_COLUMN_3_ROWS_VARIANT_2 0x16 60 | #define BIG_NUMBERS_FONT_3_COLUMN_3_ROWS_VARIANT_1 0x0A 61 | #define BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_1 0x0B 62 | #define BIG_NUMBERS_FONT_3_COLUMN_4_ROWS_VARIANT_2 0x1B 63 | 64 | class LCDBigNumbers : public Print{ 65 | 66 | public: 67 | #if defined(USE_PARALLEL_LCD) 68 | LiquidCrystal *LCD; 69 | #else 70 | LiquidCrystal_I2C *LCD; 71 | #endif 72 | const uint8_t NumberWidth; 73 | const uint8_t NumberHeight; 74 | uint8_t FontVariant; 75 | const uint8_t (*bigNumbersCustomPatterns)[8]; 76 | uint8_t NumberOfCustomPatterns; 77 | const uint8_t *bigNumbersFont; 78 | bool forceGapBetweenNumbers; // The default depends on the font used 79 | uint8_t upperLeftColumnIndex; // Start of the next character 80 | uint8_t maximumColumnIndex; // Maximum of columns to be written. Used to not clear the gap after a number which ends at the last column. ( 44 bytes program space) 81 | uint8_t upperLeftRowIndex; // Start of the next character 82 | 83 | #if defined(USE_PARALLEL_LCD) 84 | LCDBigNumbers(LiquidCrystal *aLCD, const uint8_t aBigNumberFontIdentifier); 85 | #else 86 | LCDBigNumbers(LiquidCrystal_I2C *aLCD, const uint8_t aBigNumberFontIdentifier); 87 | #endif 88 | 89 | //createChar with PROGMEM input 90 | void _createChar(uint8_t location, const uint8_t *charmap); 91 | 92 | void init(const uint8_t aBigNumberFontIdentifier); // Internal function to select the appropriate font arrays 93 | size_t write(); 94 | size_t writeAt(uint8_t aNumber, uint8_t aUpperLeftColumnIndex, uint8_t aUpperLeftRowIndex = 0); 95 | size_t writeBigNumber(uint8_t aNumberOrSpecialCharacter); 96 | void setBigNumberCursor(uint8_t aUpperLeftColumnIndex, uint8_t aUpperLeftRowIndex = 0); 97 | 98 | void begin(); // Creates custom character used for generating big numbers 99 | void enableGapBetweenNumbers(); 100 | void disableGapBetweenNumbers(); 101 | }; 102 | 103 | #if defined(USE_PARALLEL_LCD) 104 | void printSpaces(LiquidCrystal *aLCD, uint_fast8_t aNumberOfSpacesToPrint); 105 | #else 106 | void printSpaces(LiquidCrystal_I2C *aLCD, uint_fast8_t aNumberOfSpacesToPrint); 107 | #endif 108 | 109 | #if defined(USE_PARALLEL_LCD) 110 | void clearLine(LiquidCrystal *aLCD, uint_fast8_t aLineNumber); 111 | #else 112 | void clearLine(LiquidCrystal_I2C *aLCD, uint_fast8_t aLineNumber); 113 | #endif 114 | 115 | /* 116 | * Prints 2 or 4 character Hex value with leading zero 117 | */ 118 | #if defined(USE_PARALLEL_LCD) 119 | size_t printHex(LiquidCrystal *aLCD, uint16_t aHexByteValue); 120 | #else 121 | size_t printHex(LiquidCrystal_I2C *aLCD, uint16_t aHexByteValue); 122 | #endif 123 | 124 | /* 125 | * On my 2004 LCD the custon characters are available under 0 to 7 and mirrored to 8 to 15 126 | * The characters 0x80 to 0x8F are blanks 127 | */ 128 | #if defined(USE_PARALLEL_LCD) 129 | void showSpecialCharacters(LiquidCrystal *aLCD); 130 | #else 131 | void showSpecialCharacters(LiquidCrystal_I2C *aLCD); 132 | #endif 133 | 134 | 135 | #if defined(USE_PARALLEL_LCD) 136 | void showCustomCharacters(LiquidCrystal *aLCD); 137 | #else 138 | void showCustomCharacters(LiquidCrystal_I2C *aLCD); 139 | #endif 140 | 141 | #if defined(USE_PARALLEL_LCD) 142 | void testBigNumbers(LiquidCrystal *aLCD); 143 | #else 144 | void testBigNumbers(LiquidCrystal_I2C *aLCD); 145 | #endif 146 | 147 | #endif // _LCD_BIG_NUMBERS_H 148 | -------------------------------------------------------------------------------- /examples/SnakeSolver/SnakeSolver.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * SnakeSolver.cpp 3 | * 4 | * It runs the snake game using your AI code in the getNextSnakeDirection() function. 5 | * 6 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 7 | * 8 | * Copyright (C) 2018-2022 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 12 | * 13 | * NeoPatterns is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | #include 29 | 30 | #define ENABLE_USER_SNAKE_SOLVER // activates function getNextSnakeDirection() below 31 | 32 | #define ENABLE_PATTERNS_FOR_SNAKE_AUTORUN 33 | #include 34 | 35 | // Delay between two SNAKE moves / Speed of game 36 | #define GAME_REFRESH_INTERVAL 200 37 | 38 | #define PIN_NEOPIXEL_MATRIX_SNAKE 8 39 | #define MATRIX_NUMBER_OF_COLUMNS 8 40 | #define MATRIX_NUMBER_OF_ROWS 8 41 | 42 | #define RIGHT_BUTTON_PIN 2 43 | #define LEFT_BUTTON_PIN 3 44 | /* 45 | * if connected, use up or down button first after reset to enable 4 button direct direction input 46 | */ 47 | #define UP_BUTTON_PIN 4 48 | #define DOWN_BUTTON_PIN 5 49 | 50 | /* 51 | * In this example parameters are set in setup by calling NeoPixelMatrixSnake.init(...) 52 | */ 53 | MatrixSnake NeoPixelMatrixSnake = MatrixSnake(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX_SNAKE, 54 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800); 55 | 56 | /****************************************************************************************************** 57 | * Put your Snake solver code here 58 | * This function is called before every snake move and must return the new direction for the snake. 59 | * 60 | * TopLeft coordinates are 0,0 61 | * BottomRight are e.g 8,8 62 | * 63 | * aSnakeBodyArray[0] is head position of snake 64 | * aSnakeBodyArray[aSnakeLength-1] is tail position of snake 65 | * 66 | * Apple.x, Apple.y is position of the apple 67 | * 68 | * Useful functions are: aSnake->checkDirection(uint8_t aDirectionToCheck) 69 | * computeDirection(position aStartPosition, position aEndPosition) 70 | * computeNewHeadPosition(uint8_t aDirection, position * aSnakeNewHeadPosition) 71 | * 72 | * More functions can be found in MatrixSnake.hpp 73 | * 74 | ******************************************************************************************************/ 75 | #if defined(ENABLE_USER_SNAKE_SOLVER) 76 | uint8_t getNextSnakeDirection(MatrixSnake *aSnake) { 77 | 78 | /* 79 | * Call internal solver 80 | * Comment / deactivate the next line to enable your own code 81 | */ 82 | return aSnake->builtinGetNextSnakeDirection(); 83 | 84 | /* 85 | * Debug output 86 | */ 87 | Serial.print(F("getSnakeDirection CurrentDirection=")); 88 | Serial.print(DirectionToString(aSnake->Direction)); 89 | Serial.print(F(" head=(")); 90 | Serial.print(aSnake->SnakePixelList[0].x); 91 | Serial.print(','); 92 | Serial.print(aSnake->SnakePixelList[0].y); 93 | Serial.println(')'); 94 | 95 | int8_t tDeltaX = aSnake->Apple.x - aSnake->SnakePixelList[0].x; 96 | int8_t tDeltaY = aSnake->Apple.y - aSnake->SnakePixelList[0].y; 97 | 98 | Serial.print(F("DeltaX=")); 99 | Serial.print(tDeltaX); 100 | Serial.print(F(" DeltaY=")); 101 | Serial.println(tDeltaY); 102 | 103 | uint8_t tNewDirection = aSnake->Direction; 104 | 105 | /* 106 | * Simple example, go towards the apple. 107 | */ 108 | 109 | /* 110 | * Avoid going to opposite direction, because this is invalid. 111 | * Eg. if actual direction is UP, we must not change to DOWN. 112 | */ 113 | if (tDeltaX > 0 && aSnake->Direction != DIRECTION_LEFT) { 114 | tNewDirection = DIRECTION_RIGHT; 115 | } else if (tDeltaX < 0 && aSnake->Direction != DIRECTION_RIGHT) { 116 | tNewDirection = DIRECTION_LEFT; 117 | } 118 | if (tDeltaY > 0 && aSnake->Direction != DIRECTION_UP) { 119 | tNewDirection = DIRECTION_DOWN; 120 | } else if (tDeltaY < 0 && aSnake->Direction != DIRECTION_DOWN) { 121 | tNewDirection = DIRECTION_UP; 122 | } 123 | 124 | // check new direction... 125 | if (aSnake->checkDirection(tNewDirection) != 0) { 126 | /* 127 | * check was not successful just check all available directions 128 | */ 129 | for (tNewDirection = 0; tNewDirection < NUMBER_OF_DIRECTIONS; ++tNewDirection) { 130 | if (aSnake->checkDirection(tNewDirection) == 0) { 131 | break; 132 | } 133 | } 134 | } 135 | 136 | // End of dummy example 137 | Serial.print(F("NewDirection=")); 138 | Serial.println(DirectionToString(tNewDirection)); 139 | 140 | return tNewDirection; 141 | } 142 | #endif // ENABLE_USER_SNAKE_SOLVER 143 | 144 | void setup() { 145 | pinMode(LED_BUILTIN, OUTPUT); 146 | 147 | Serial.begin(115200); 148 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 149 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 150 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 151 | #endif 152 | // Just to know which program is running on my Arduino 153 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 154 | NeoPixelMatrixSnake.printConnectionInfo(&Serial); 155 | 156 | // This initializes the Snake and checks if enough memory was available 157 | if (!NeoPixelMatrixSnake.init(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX_SNAKE, 158 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800)) { 159 | Serial.println(F("Not enough memory for Snake matrix")); 160 | // Blink forever as error indicator 161 | while (true) { 162 | digitalWrite(LED_BUILTIN, HIGH); 163 | delay(500); 164 | digitalWrite(LED_BUILTIN, LOW); 165 | delay(500); 166 | } 167 | } 168 | initSnakeAutorun(&NeoPixelMatrixSnake, GAME_REFRESH_INTERVAL, COLOR32_BLUE); 169 | } 170 | 171 | void loop() { 172 | NeoPixelMatrixSnake.update(); 173 | } 174 | 175 | -------------------------------------------------------------------------------- /examples/SnakeGame/SnakeGame.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * SnakeGame.cpp 3 | * 4 | * Simply runs the Snake game. It can be controlled by 2 or 4 buttons or by serial input (WASD). 5 | * The experimental Python script in the extras folder converts key presses and game controller input to appropriate serial output for the game. 6 | * 7 | * After 7 seconds of inactivity it runs the Snake demo with a simple AI. 8 | * The game starts in 2 button mode, i.e. one button for turn left and one for turn right. 9 | * If one of the up or down button is used, 4 button mode is entered automatically. 10 | * 11 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 12 | * 13 | * Copyright (C) 2018-2025 Armin Joachimsmeyer 14 | * armin.joachimsmeyer@gmail.com 15 | * 16 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 17 | * 18 | * NeoPatterns is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU General Public License as published by 20 | * the Free Software Foundation, either version 3 of the License, or 21 | * (at your option) any later version. 22 | * 23 | * This program is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 | * See the GNU General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU General Public License 29 | * along with this program. If not, see . 30 | * 31 | */ 32 | 33 | #include 34 | 35 | //#define DEBUG // implies also setting of INFO 36 | //#define INFO 37 | 38 | #define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 39 | //#define DO_NOT_SUPPORT_BRIGHTNESS // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 40 | //#define DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS // If activated, disables writing of zero only if brightness or color is zero. Saves up to 144 bytes ... 41 | 42 | #define ENABLE_PATTERNS_FOR_SNAKE_AUTORUN 43 | //#define SNAKE_ALLOW_SERIAL_CONTROL // control the snake direction with sending characters a,s,d,f over serial 44 | #include 45 | 46 | // Delay between two SNAKE moves / Speed of game 47 | #define GAME_REFRESH_INTERVAL 400 48 | 49 | // Which pin on the Arduino is connected to the NeoPixels? 50 | #define PIN_NEOPIXEL_MATRIX_SNAKE 8 51 | #define MATRIX_NUMBER_OF_COLUMNS 8 52 | #define MATRIX_NUMBER_OF_ROWS 8 53 | 54 | #define BRIGHTNESS_INPUT_PIN A0 55 | 56 | #define RIGHT_BUTTON_PIN 2 57 | #define LEFT_BUTTON_PIN 3 58 | // If one of the up or down button is used, 4 button mode is entered automatically. 59 | #define UP_BUTTON_PIN 4 60 | #define DOWN_BUTTON_PIN 5 61 | 62 | /* 63 | * Specify your matrix geometry as 4th parameter. 64 | * ....BOTTOM ....RIGHT specify the position of the zeroth pixel. 65 | * See MatrixNeoPatterns.h for further explanation. 66 | */ 67 | MatrixSnake NeoPixelMatrixSnake = MatrixSnake(MATRIX_NUMBER_OF_COLUMNS, MATRIX_NUMBER_OF_ROWS, PIN_NEOPIXEL_MATRIX_SNAKE, 68 | NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_PROGRESSIVE, NEO_GRB + NEO_KHZ800); 69 | 70 | /* 71 | * Helper macro for getting a macro definition as string 72 | */ 73 | #define STR_HELPER(x) #x 74 | #define STR(x) STR_HELPER(x) 75 | 76 | void setup() { 77 | pinMode(LED_BUILTIN, OUTPUT); 78 | 79 | Serial.begin(115200); 80 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 81 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 82 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 83 | #endif 84 | // Just to know which program is running on my Arduino 85 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 86 | Serial.println(); 87 | NeoPixelMatrixSnake.printConnectionInfo(&Serial); 88 | Serial.println( 89 | F( 90 | "Allows 2 button mode, using only right and left button ( pin " STR(RIGHT_BUTTON_PIN) " or " STR(LEFT_BUTTON_PIN) " )")); 91 | Serial.println( 92 | F( 93 | "If up or down button ( pin " STR(UP_BUTTON_PIN) " or " STR(DOWN_BUTTON_PIN) " ) is pressed (later), 4 button mode is entered automatically")); 94 | Serial.println(); 95 | 96 | #if defined(SUPPORT_BRIGHTNESS) 97 | uint8_t tBrightness = NeoPixel::gamma8(analogRead(BRIGHTNESS_INPUT_PIN) >> 2); 98 | randomSeed(tBrightness); // Initialize random value :-) 99 | Serial.println(F("Brightness voltage input is at pin " STR(BRIGHTNESS_INPUT_PIN))); 100 | #else 101 | Serial.println(F("Brightness voltage input at pin " STR(BRIGHTNESS_INPUT_PIN) " is disabled")); 102 | uint8_t tBrightness = 0; // value is ignored :-) 103 | #endif 104 | 105 | // This initializes the NeoPixel library and checks if enough memory was available. true for EnableBrightnessNonZeroMode 106 | if (!NeoPixelMatrixSnake.begin(&Serial, tBrightness, true)) { 107 | Serial.println(F("Not enough memory for Snake matrix")); 108 | // Blink forever as error indicator 109 | while (true) { 110 | digitalWrite(LED_BUILTIN, HIGH); 111 | delay(500); 112 | digitalWrite(LED_BUILTIN, LOW); 113 | delay(500); 114 | } 115 | } 116 | // Prepare for 4 button mode. If up and down button are not connected 117 | NeoPixelMatrixSnake.Snake(GAME_REFRESH_INTERVAL, COLOR32_BLUE, RIGHT_BUTTON_PIN, LEFT_BUTTON_PIN, UP_BUTTON_PIN, 118 | DOWN_BUTTON_PIN); 119 | 120 | } 121 | 122 | void loop() { 123 | static bool sButtonWasPressedOnce = false; 124 | #if defined(SUPPORT_BRIGHTNESS) 125 | static uint8_t sLastBrightness; 126 | #endif 127 | 128 | if (NeoPixelMatrixSnake.Direction != DIRECTION_NONE) { 129 | // Direction is DIRECTION_NONE at start => Direction != NONE indicates a pressed button 130 | sButtonWasPressedOnce = true; 131 | } 132 | 133 | if (!sButtonWasPressedOnce) { 134 | /* 135 | * Just wait for TIME_TO_SWITCH_TO_AUTO_MODE_MILLIS and then start snake autorun mode. 136 | */ 137 | long tMillis = millis(); 138 | if (tMillis > TIME_TO_SWITCH_TO_AUTO_MODE_MILLIS) { 139 | // switch to demo mode after switching delay if snake has not moved 140 | initSnakeAutorun(&NeoPixelMatrixSnake, GAME_REFRESH_INTERVAL / 2, COLOR32_BLUE); 141 | } 142 | } 143 | #if defined(SUPPORT_BRIGHTNESS) 144 | uint8_t tBrightness = NeoPixel::gamma8(analogRead(BRIGHTNESS_INPUT_PIN) >> 2); 145 | if (abs(sLastBrightness - tBrightness) > (tBrightness / 16)) { 146 | sLastBrightness = tBrightness; 147 | Serial.print(F("Brightness=")); 148 | Serial.println(tBrightness); 149 | NeoPixelMatrixSnake.updateOrRedraw(true, tBrightness); 150 | } else { 151 | NeoPixelMatrixSnake.updateOrRedraw(false, tBrightness); 152 | } 153 | #else 154 | NeoPixelMatrixSnake.update(); // calls SnakeInputHandler() 155 | #endif 156 | delay(50); 157 | } 158 | -------------------------------------------------------------------------------- /src/MatrixSnake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixSnake.h 3 | * 4 | * SUMMARY 5 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 6 | * Extension are made to include more patterns and combined patterns and patterns for 8x8 NeoPixel matrix. 7 | * 8 | * Copyright (C) 2018-2025 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 12 | * 13 | * NeoPatterns is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | /* Class inheritance diagram 29 | * ,o--> MatrixNeoPixel \ 30 | * MatrixSnake --> MatrixNeoPatterns < o--> NeoPixel --> Adafruit_NeoPixel 31 | * `o--> NeoPatterns / 32 | */ 33 | 34 | #ifndef _MATRIX_SNAKE_H 35 | #define _MATRIX_SNAKE_H 36 | 37 | #if defined(ENABLE_PATTERNS_FOR_SNAKE_AUTORUN) 38 | #define ENABLE_MATRIX_PATTERN_MOVE // required for SnakeAutorunCompleteHandler() to move the score out. 39 | #endif 40 | 41 | #if defined(ENABLE_PATTERNS_FOR_MATRIX_AND_SNAKE_DEMO_HANDLER) 42 | #define ENABLE_MATRIX_PATTERN_TICKER 43 | #define ENABLE_MATRIX_PATTERN_MOVING_PICTURE 44 | #define ENABLE_PATTERN_PROCESS_SELECTIVE 45 | #define ENABLE_MATRIX_PATTERN_MOVE 46 | #define ENABLE_MATRIX_PATTERN_FIRE 47 | #define ENABLE_MATRIX_PATTERN_SNOW 48 | #define ENABLE_PATTERN_TWINKLE 49 | #endif 50 | 51 | #include "MatrixNeoPatterns.h" 52 | 53 | //#define SNAKE_ALLOW_SERIAL_CONTROL // Accepts snake direction commands over the serial line 54 | 55 | #define SPECIAL_PATTERN_SNAKE (LAST_MATRIX_NEO_PATTERN + 1) 56 | 57 | #define APPLE_COLOR COLOR32_RED 58 | 59 | #define MILLIS_FOR_BUTTON_DEBOUNCING 100 60 | 61 | #define FLAG_SNAKE_USE_4_BUTTONS 0x01 // will be set if PinOfUpButton != 0 and up or down button was at least pressed once 62 | #define FLAG_SNAKE_AUTORUN 0x02 // autorun mode - will be set if no left buttons is defined 63 | #define FLAG_SNAKE_SHOW_LENGTH_SCORE 0x20 // signal number shown -> enables delay 64 | #define FLAG_SNAKE_SHOW_END 0x40 // signal end of snake shown -> enables delay 65 | #define SHOW_END_INTERVAL_MILLIS 3000 66 | #define SHOW_NUMBER_INTERVAL_MILLIS 2000 67 | 68 | #define TIME_TO_SWITCH_TO_AUTO_MODE_MILLIS 7000 69 | //#define TIME_TO_SWITCH_TO_AUTO_MODE_MILLIS 2000 70 | 71 | // stores a 2d position TopLeft coordinates are 0,0 72 | struct position { 73 | uint8_t x; 74 | uint8_t y; 75 | }; 76 | 77 | // stores the initial shape of the snake. SnakeInitialPixels[0] is head of snake 78 | position const SnakeInitialPixels[] = { { 4, 4 }, { 5, 4 }, { 6, 4 }, { 6, 5 } }; 79 | #define INITIAL_DIRECTION_SNAKE DIRECTION_LEFT // The initial direction of the above SnakeInitialPixels 80 | 81 | // extension of NeoPattern Class approximately 85 byte / object 82 | class MatrixSnake: public MatrixNeoPatterns { 83 | public: 84 | MatrixSnake(); 85 | MatrixSnake(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, uint8_t aTypeOfPixel, 86 | void (*aPatternCompletionCallback)(NeoPatterns*)=nullptr); 87 | bool init(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, uint8_t aTypeOfPixel, 88 | void (*aPatternCompletionCallback)(NeoPatterns*)=nullptr); 89 | 90 | bool Snake(uint16_t aIntervalMillis, color32_t aColor, uint8_t aPinOfRightButton = 0, uint8_t aPinOfLeftButton = 0, 91 | uint8_t aPinOfUpButton = 0, uint8_t aPinOfDownButton = 0); 92 | 93 | bool update(); 94 | bool update(uint8_t aBrightness); 95 | bool updateOrRedraw(bool aDoRedrawIfNoUpdate); 96 | bool updateOrRedraw(bool aDoRedrawIfNoUpdate, uint8_t aBrightness); 97 | 98 | void SnakeUpdate(bool aDoUpdate = true); 99 | void SnakeStop(); 100 | void SnakeInputHandler(); 101 | void SnakeEndHandler(); 102 | void showScore(); 103 | 104 | void newApple(); 105 | void drawApple(); 106 | void drawSnake(); 107 | void resetAndClearAndShowSnakeAndNewApple(); 108 | void rotateRight(); 109 | void rotateLeft(); 110 | // 111 | bool isPositionInArea(position aPositionToCheck); 112 | uint16_t getIndexOfPositionInSnake(uint8_t aPositionToCheckX, uint8_t aPositionToCheckY); 113 | uint16_t getIndexOfPositionInSnake(position aPositionToCheck); 114 | uint16_t getIndexOfPositionInSnakeTail(position aPositionToCheck); 115 | uint16_t checkDirection(uint8_t aDirectionToCheck); 116 | // 117 | bool computeNewHeadPosition(uint8_t aActualDirection, position *aSnakeNewHeadPosition); 118 | bool moveSnakeAndCheckApple(position tSnakeNewHeadPosition); 119 | #if defined(LOCAL_TRACE) 120 | void printSnakePosition(position aSnakePosition); 121 | #endif 122 | /* 123 | * internal auto solver functions 124 | */ 125 | uint8_t findNextDir(); 126 | uint8_t runAndCheckIfAppleCanBeReached(); 127 | uint8_t builtinGetNextSnakeDirection(); 128 | 129 | // The pixel positions of the Snake. Only the positions up until snake_length - 1 are displayed 130 | // SnakePixelList[0] is head of snake 131 | position *SnakePixelList; 132 | uint16_t SnakeLength; // current length of snake 133 | 134 | #define AUTOSOLVER_CLOCKWISE_FLAG 0x01 // if set choose directions from 3 to 0 135 | uint8_t SnakeAutoSolverMode; // The mode for findNextDir() 136 | 137 | // the apple the snake chases after 138 | position Apple; 139 | 140 | uint16_t HighScore; 141 | 142 | /* 143 | * Snake input stuff 144 | */ 145 | uint8_t PinOfRightButton; // if not set (==0), snake runs in autorun mode 146 | uint8_t PinOfLeftButton; 147 | uint8_t PinOfUpButton; 148 | uint8_t PinOfDownButton; 149 | uint8_t DirectionOfLastButtonPressed; // for debouncing 150 | uint32_t MillisOfLastButtonChange; // for debouncing in 2 button mode 151 | 152 | private: 153 | }; 154 | 155 | uint8_t computeDirection(position aStartPosition, position aEndPosition); 156 | 157 | extern const char sDefaultTickerText[] PROGMEM; // = "I love Neopixel" 158 | extern const char *sTickerTextPtr; // = sDefaultTickerText; 159 | void setMatrixAndSnakePatternsDemoHandlerTickerText(const __FlashStringHelper *aTextForTicker); 160 | void setMatrixAndSnakePatternsDemoHandlerTickerText(const char *aTextForTicker); 161 | #if defined(ENABLE_MATRIX_PATTERN_TICKER) && defined(ENABLE_MATRIX_PATTERN_MOVING_PICTURE) && defined(ENABLE_PATTERN_PROCESS_SELECTIVE) \ 162 | && defined(ENABLE_MATRIX_PATTERN_MOVE) && defined(ENABLE_MATRIX_PATTERN_FIRE) && defined(ENABLE_MATRIX_PATTERN_SNOW) 163 | void MatrixAndSnakePatternsDemoHandler(NeoPatterns *aLedsPtr); 164 | #endif 165 | 166 | uint8_t getNextSnakeDirection(MatrixSnake *aSnake); 167 | #if defined(ENABLE_MATRIX_PATTERN_MOVE) 168 | bool initSnakeAutorun(MatrixSnake *aLedsPtr, uint16_t aIntervalMillis, color32_t aColor, uint16_t aRepetitions = 1); 169 | void SnakeAutorunCompleteHandler(NeoPatterns *aLedsPtr); 170 | #endif 171 | 172 | #endif // _MATRIX_SNAKE_H 173 | -------------------------------------------------------------------------------- /examples/MultiplePatternsOnOneBar/MultiplePatternsOnOneBar.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * MultiplePatternsOnOneBar.cpp 3 | * 4 | * Runs 3 8-pixel patterns simultaneously on a 24 NeoPixel bar. 5 | * This is done by using one base NeoPixel object and 3 NeoPatterns using the constructor NeoPatterns(NeoPixel *aUnderlyingNeoPixelObject, uint16_t aPixelOffset, ... 6 | * 7 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 8 | * 9 | * Copyright (C) 2018 Armin Joachimsmeyer 10 | * armin.joachimsmeyer@gmail.com 11 | * 12 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 13 | * 14 | * NeoPatterns is free software: you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation, either version 3 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 22 | * See the GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program. If not, see . 26 | * 27 | */ 28 | 29 | #include 30 | 31 | #define ENABLE_PATTERN_COLOR_WIPE 32 | #define ENABLE_PATTERN_SCANNER_EXTENDED 33 | #define ENABLE_PATTERN_STRIPES 34 | #include 35 | //#define DEBUG 36 | 37 | // Which pin on the Arduino is connected to the NeoPixels? 38 | #define PIN_NEOPIXEL 3 39 | 40 | // onComplete callback functions 41 | void MultiPatterns(NeoPatterns *aLedsPtr); 42 | 43 | // construct the NeoPatterns instances 44 | NeoPatterns NeoPixelBar24 = NeoPatterns(24, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800); 45 | /* 46 | * Here we use the constructor NeoPatterns(NeoPixel *aUnderlyingNeoPixelObject, uint16_t aPixelOffset, ... 47 | * false -> do not allow show on partial NeoPixel bar 48 | */ 49 | NeoPatterns LowerNeoPixelBar = NeoPatterns(&NeoPixelBar24, 0, 8, false, &MultiPatterns); 50 | NeoPatterns MiddleNeoPixelBar = NeoPatterns(&NeoPixelBar24, 8, 8, false, &MultiPatterns); 51 | NeoPatterns UpperNeoPixelBar = NeoPatterns(&NeoPixelBar24, 16, 8, false, &MultiPatterns); 52 | 53 | void setup() { 54 | pinMode(LED_BUILTIN, OUTPUT); 55 | 56 | Serial.begin(115200); 57 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 58 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 59 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 60 | #endif 61 | // Just to know which program is running on my Arduino 62 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 63 | NeoPixelBar24.printConnectionInfo(&Serial); 64 | 65 | NeoPixelBar24.begin(); // This sets the output pin. 66 | 67 | /* 68 | * Start the patterns 69 | */ 70 | LowerNeoPixelBar.ColorWipe(COLOR32_GREEN_QUARTER, 80); 71 | MiddleNeoPixelBar.ScannerExtended(COLOR32_BLUE_HALF, 2, 60, 2, FLAG_SCANNER_EXT_ROCKET | FLAG_SCANNER_EXT_START_AT_BOTH_ENDS); 72 | UpperNeoPixelBar.ColorWipe(COLOR32_RED_QUARTER, 80, false, DIRECTION_DOWN); 73 | Serial.println(F("Started")); 74 | } 75 | 76 | void loop() { 77 | /* 78 | * Cannot do this in one if statement, because evaluation will stop after the first true. 79 | */ 80 | bool tMustUpdate = LowerNeoPixelBar.update(); 81 | tMustUpdate |= MiddleNeoPixelBar.update(); 82 | tMustUpdate |= UpperNeoPixelBar.update(); 83 | if (tMustUpdate) { 84 | NeoPixelBar24.show(); 85 | } 86 | delay(10); 87 | } 88 | 89 | /* 90 | * Callback handler for multi pattern 91 | */ 92 | void MultiPatterns(NeoPatterns *aLedsPtr) { 93 | static int8_t sState = 1; // start with delay 94 | 95 | /* 96 | * Wait for the last pattern to end 97 | */ 98 | if (LowerNeoPixelBar.TotalStepCounter != 0 || MiddleNeoPixelBar.TotalStepCounter != 0 99 | || UpperNeoPixelBar.TotalStepCounter != 0) { 100 | aLedsPtr->ActivePattern = PATTERN_NONE; 101 | #if defined(DEBUG) 102 | Serial.print(F("Lower counter=")); 103 | Serial.print(LowerNeoPixelBar.TotalStepCounter); 104 | Serial.print(F(" Middle counter=")); 105 | Serial.print(MiddleNeoPixelBar.TotalStepCounter); 106 | Serial.print(F(" Upper counter=")); 107 | Serial.print(UpperNeoPixelBar.TotalStepCounter); 108 | Serial.println(F(" One pattern is still active")); 109 | #endif 110 | } else { 111 | 112 | uint8_t tInterval = random8(40, 201); 113 | 114 | if ((sState & 1) == 1) { 115 | /* 116 | * Insert a random delay if sState is odd 117 | */ 118 | uint16_t tDelay = random(200, 1000); 119 | aLedsPtr->Delay(tDelay); // to separate each pattern 120 | sState++; 121 | Serial.print(F("Insert delay of ")); 122 | Serial.println(tDelay); 123 | return; 124 | } 125 | 126 | int8_t tState = sState / 2; 127 | uint8_t tColorWheelIndex = random8(); 128 | 129 | switch (tState) { 130 | case 0: 131 | // falling stars 132 | initMultipleFallingStars(&LowerNeoPixelBar, COLOR32_WHITE_HALF, 4, tInterval / 4, 2, &MultiPatterns, DIRECTION_UP); 133 | Serial.println(F("Clear")); 134 | 135 | MiddleNeoPixelBar.clear(); 136 | initMultipleFallingStars(&UpperNeoPixelBar, COLOR32_WHITE_HALF, 4, tInterval / 4, 2, &MultiPatterns); 137 | break; 138 | case 1: 139 | LowerNeoPixelBar.ColorWipe(COLOR32_GREEN_QUARTER, tInterval, false, DIRECTION_DOWN); 140 | MiddleNeoPixelBar.ScannerExtended(COLOR32_BLUE_HALF, 2, tInterval, 5, 141 | FLAG_SCANNER_EXT_CYLON | FLAG_SCANNER_EXT_VANISH_COMPLETE); 142 | UpperNeoPixelBar.ColorWipe(COLOR32_RED_QUARTER, tInterval); 143 | break; 144 | case 2: 145 | LowerNeoPixelBar.ColorWipe(COLOR32_BLACK, tInterval, true); 146 | UpperNeoPixelBar.ColorWipe(COLOR32_BLACK, tInterval, true, DIRECTION_DOWN); 147 | break; 148 | case 3: 149 | LowerNeoPixelBar.Stripes(COLOR32_BLACK, 12, NeoPatterns::Wheel(tColorWheelIndex), 12, tInterval, 48, tColorWheelIndex & DIRECTION_DOWN); 150 | MiddleNeoPixelBar.ScannerExtended(COLOR32_BLUE_HALF, 2, tInterval, 2, 151 | FLAG_SCANNER_EXT_ROCKET | FLAG_SCANNER_EXT_START_AT_BOTH_ENDS); 152 | 153 | UpperNeoPixelBar.Stripes(COLOR32_BLACK, 12, NeoPatterns::Wheel(tColorWheelIndex), 12, tInterval, 48, 154 | OppositeDirection(tColorWheelIndex & DIRECTION_DOWN)); 155 | sState = -2; // Start from beginning 156 | break; 157 | default: 158 | Serial.println("ERROR"); 159 | break; 160 | } 161 | 162 | Serial.print(F("Pin=")); 163 | Serial.print(aLedsPtr->getPin()); 164 | Serial.print(F(" Length=")); 165 | Serial.print(aLedsPtr->numPixels()); 166 | Serial.print(F(" ActivePattern=")); 167 | aLedsPtr->printPatternName(aLedsPtr->ActivePattern, &Serial); 168 | Serial.print('|'); 169 | Serial.print(aLedsPtr->ActivePattern); 170 | Serial.print(F(" Interval=")); 171 | Serial.print(tInterval); 172 | Serial.print(F(" State=")); 173 | Serial.println(tState); 174 | 175 | sState++; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/MatrixNeoPixel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixNeoPixel.h 3 | * 4 | * Implements basic functions for NeoPixel matrix. Tested with 8x8 matrix. 5 | * Origin (0,0) of x and y values is at the top left corner and the positive direction is right and down. 6 | * 7 | * Copyright (C) 2019 Armin Joachimsmeyer 8 | * armin.joachimsmeyer@gmail.com 9 | * 10 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 11 | * 12 | * NeoPatterns is free software: you can redistribute it and/or modify 13 | * it under the terms of the GNU General Public License as published by 14 | * the Free Software Foundation, either version 3 of the License, or 15 | * (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 20 | * See the GNU General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public License 23 | * along with this program. If not, see . 24 | * 25 | */ 26 | 27 | /* 28 | * Class inheritance diagram. We have virtual inheritance, since MatrixNeoPatterns needs only one member set of NeoPixel 29 | * 30 | * MatrixNeoPixelVU \ 31 | * ,o--> MatrixNeoPixel (virtual) \ 32 | * MatrixSnake --> MatrixNeoPatterns < o--> NeoPixel --> Adafruit_NeoPixel 33 | * `o--> NeoPatterns (virtual) / 34 | * 35 | */ 36 | 37 | #ifndef SRC_LIB_NEOPATTERNS_MATRIXNEOPIXEL_H_ 38 | #define SRC_LIB_NEOPATTERNS_MATRIXNEOPIXEL_H_ 39 | 40 | #include "NeoPixel.h" 41 | 42 | /* 43 | * If you have only default geometry (NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE), 44 | * i.e. Pixel 0 is at bottom right of matrix, matrix is row major (horizontal) and same pixel order across each line (no zig-zag), 45 | * then you can save program memory by defining symbol `SUPPORT_ONLY_DEFAULT_GEOMETRY`. 46 | * This saves 560 bytes program memory and 3 bytes RAM. 47 | */ 48 | //#define SUPPORT_ONLY_DEFAULT_GEOMETRY 49 | // 50 | /* 51 | * Defines from Adafruit_NeoMatrix.h 52 | */ 53 | // Matrix layout information is passed in the 'matrixType' parameter for 54 | // each constructor (the parameter immediately following is the LED type 55 | // from NeoPixel.h). 56 | // These define the layout for a single 'unified' matrix (e.g. one made 57 | // from NeoPixel strips, or a single NeoPixel shield), or for the pixels 58 | // within each matrix of a tiled display (e.g. multiple NeoPixel shields). 59 | #define NEO_MATRIX_TOP 0x00 // Pixel 0 is at top of matrix 60 | #define NEO_MATRIX_BOTTOM 0x01 // Pixel 0 is at bottom of matrix 61 | #define NEO_MATRIX_LEFT 0x00 // Pixel 0 is at left of matrix 62 | #define NEO_MATRIX_RIGHT 0x02 // Pixel 0 is at right of matrix 63 | #define NEO_MATRIX_CORNER 0x03 // Bitmask for pixel 0 matrix corner 64 | 65 | #define NEO_MATRIX_ROWS 0x00 // Matrix is row major (horizontal) 66 | #define NEO_MATRIX_COLUMNS 0x04 // Matrix is column major (vertical) 67 | #define NEO_MATRIX_AXIS 0x04 // Bitmask for row/column layout 68 | 69 | #define NEO_MATRIX_PROGRESSIVE 0x00 // Same pixel order across each line 70 | #define NEO_MATRIX_ZIGZAG 0x08 // Pixel order reverses between lines 71 | #define NEO_MATRIX_SEQUENCE 0x08 // Bitmask for pixel line order 72 | 73 | #define NEO_MATRIX_DEFAULT_GEOMETRY (NEO_MATRIX_BOTTOM | NEO_MATRIX_RIGHT | NEO_MATRIX_ROWS | NEO_MATRIX_PROGRESSIVE) 74 | 75 | /* 76 | * For constrain function 77 | */ 78 | #define MAX_SUPPORTED_GRAPHICS_WIDTH 16 // see void loadPicture(const uint16_t *aGraphicsArrayPtr... 79 | #define MAX_SUPPORTED_GRAPHICS_HEIGHT 16 // a guess 80 | 81 | class MatrixNeoPixel: public virtual NeoPixel { 82 | public: 83 | MatrixNeoPixel(); 84 | void init(); 85 | MatrixNeoPixel(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, uint8_t aTypeOfPixel); 86 | bool init(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, uint8_t aTypeOfPixel); 87 | 88 | void printConnectionInfo(Print *aSerial); 89 | 90 | #if !defined(SUPPORT_ONLY_DEFAULT_GEOMETRY) 91 | void setLayoutMappingFunction(uint16_t (*aLayoutMappingFunction)(uint8_t, uint8_t, uint8_t, uint8_t)); 92 | uint16_t LayoutMapping(uint8_t aColumnX, uint8_t aRowY); 93 | #endif 94 | 95 | color32_t getMatrixPixelColor(uint8_t aColumnX, uint8_t aRowY); 96 | void setMatrixPixelColor(uint8_t aColumnX, uint8_t aRowY, color32_t a32BitColor); 97 | void setMatrixPixelColorAndShow(uint8_t aColumnX, uint8_t aRowY, color32_t a32BitColor); 98 | void setMatrixPixelColor(uint8_t aColumnX, uint8_t aRowY, uint8_t aRed, uint8_t aGreen, uint8_t aBlue); 99 | void setMatrixPixelColorAndShow(uint8_t aColumnX, uint8_t aRowY, uint8_t aRed, uint8_t aGreen, uint8_t aBlue); 100 | void addMatrixPixelColor(uint8_t aColumnX, uint8_t aRowY, uint8_t aRed, uint8_t aGreen, uint8_t aBlue); 101 | void addMatrixPixelColor(uint8_t aColumnX, uint8_t aRowY, color32_t aColor); 102 | 103 | void loadPicturePGM(const uint8_t *aGraphicsArrayPtrPGM, int8_t aWidthOfGraphic, uint8_t aHeightOfGraphic, 104 | color32_t aForegroundColor, color32_t aBackgroundColor, int8_t aXOffset, int8_t aYOffset, bool doPadding = false); 105 | 106 | void loadPicture(const uint8_t *aGraphicsArrayPtr, int8_t aWidthOfGraphic, uint8_t aHeightOfGraphic, color32_t aForegroundColor, 107 | color32_t aBackgroundColor, int8_t aXOffset, int8_t aYOffset, bool doPadding = false, bool IsPGMData = false); 108 | 109 | void loadPicture(const uint16_t *aGraphicsArrayPtr, int8_t aWidthOfGraphic, uint8_t aHeightOfGraphic, 110 | color32_t aForegroundColor, color32_t aBackgroundColor, int8_t aXOffset, int8_t aYOffset, bool doPadding = false, 111 | bool IsPGMData = false); 112 | 113 | void drawQuarterPatternOdd(uint16_t aPatternValue, color32_t aForegroundColor, color32_t aBackgroundColor); 114 | void drawQuarterPatternEven(uint16_t aPatternValue, color32_t aForegroundColor, color32_t aBackgroundColor); 115 | 116 | void drawAllColors(); 117 | void drawAllColors2(); 118 | void testMapping(uint16_t aDelayMillis); 119 | 120 | void drawBar(uint8_t aColumnX, uint8_t aBarLength, color32_t aColor, bool aDrawFromBottom = true); 121 | void drawBarFromColorArray(uint8_t aColumnX, uint8_t aBarLength, color32_t *aColorArrayPtr, bool aDrawFromBottom = true); 122 | 123 | // Geometry of Matrix 124 | uint8_t Rows; // Y Direction / size 125 | uint8_t Columns; // X Direction / size 126 | 127 | #if !defined(SUPPORT_ONLY_DEFAULT_GEOMETRY) 128 | // Origin (0,0) of x and y values is at the top left corner and the positive direction is right and down. 129 | uint8_t Geometry; // Flags for geometry 130 | uint16_t (*LayoutMappingFunction)(uint8_t, uint8_t, uint8_t, uint8_t); // Pointer to function, which implements the mapping between X/Y and pixel number 131 | #endif 132 | }; 133 | 134 | #define HEART_WIDTH 8 135 | #define HEART_HEIGHT 8 136 | extern const uint8_t heart8x8[] PROGMEM; 137 | 138 | /* 139 | * Example (fast) custom mapping functions 140 | */ 141 | uint16_t ProgressiveTypeBottomRightMapping(uint8_t aColumnX, uint8_t aRowY, uint8_t aColumnsTotal, uint8_t aRowsTotal); 142 | uint16_t ProgressiveTypeBottomLeftMapping(uint8_t aColumnX, uint8_t aRowY, uint8_t aColumnsTotal, uint8_t aRowsTotal); 143 | uint16_t ZigzagTypeBottomRightMapping(uint8_t aColumnX, uint8_t aRowY, uint8_t aColumnsTotal, uint8_t aRowsTotal); 144 | uint16_t ZigzagTypeBottomLeftMapping(uint8_t aColumnX, uint8_t aRowY, uint8_t aColumnsTotal, uint8_t aRowsTotal); 145 | 146 | #endif /* SRC_LIB_NEOPATTERNS_MATRIXNEOPIXEL_H_ */ 147 | -------------------------------------------------------------------------------- /examples/OpenLedRace/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # [OpenledRace](https://github.com/ArminJo/OpenledRace) 4 | 5 | **Extended version** of the [OpenledRace](https://twitter.com/openledrace) version ["Basic for PCB Rome Edition. 2 Player, without Boxes Track"](https://gitlab.com/open-led-race/olr-arduino). 6 | 7 | [![Open Led Race logo](https://github.com/ArminJo/OpenledRace/blob/master/pictures/OLR-Logo_400x400.png)](https://twitter.com/openledrace) 8 | 9 | [![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0) 10 |     11 | [![Badge Version](https://img.shields.io/github/v/release/ArminJo/OpenledRace?include_prereleases&color=yellow&logo=DocuSign&logoColor=white)](https://github.com/ArminJo/OpenledRace/releases/latest) 12 |     13 | [![Badge Commits since latest](https://img.shields.io/github/commits-since/ArminJo/OpenledRace/latest?color=yellow)](https://github.com/ArminJo/OpenledRace/commits/master) 14 |     15 | [![Badge Build Status](https://github.com/ArminJo/OpenledRace/workflows/TestCompile/badge.svg)](https://github.com/ArminJo/OpenledRace/actions) 16 |     17 | ![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_OpenledRace) 18 |
19 | 20 | Also available as [OpenLedRace example](https://github.com/ArminJo/NeoPatterns/tree/master/examples/OpenLedRace) in the [NeoPatterns library](https://github.com/ArminJo/NeoPatterns). 21 | 22 |
23 | 24 | #### If you find this library useful, please give it a star. 25 | 26 | 🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/ArminJo/OpenLedRace) 27 | 28 |
29 | 30 | #### If you find this program useful, please give it a star. 31 | 32 | # Extensions to standard version 33 | * **Input from MPU6050 Accelerometer**. 34 | * Classes for Car, Bridge, Ramp and Loop with **natural gravity**. 35 | * **Light effects** by NeoPattern library. 36 | * **Tone generation without dropouts** by use of hardware timer output. 37 | * 2004 **LCD** for instructions and leap counter. 38 | * Input feedback by an 8 pixel Neopixel bar. 39 | * Winner melody by PlayRTTTL library. 40 | * Compensation for blocked millis() timer during draw. 41 | * Checks for RAM availability. 42 | * Overlapping of cars is handled by using addPixelColor() for drawing. 43 | * **Development mode**, where Gravity, Friction and Drag can be set by potentiometers. 44 | 45 |
46 | 47 | # Principle of operation 48 | With every button press or every acceleration of the dumbbells you **add a fixed amount of energy to the "car"**.
49 | This energy is used to **increase speed**. 50 | 51 | Formula is: **Speed = sqrt((OldSpeed * OldSpeed) + AdditionalEnergy)** 52 | 53 | On the other hand, **energy is consumed by friction and drag**.
54 | Gravity also increases or decreases the car as in real life. 55 | 56 | Formula is: **NewSpeed = Speed + Gravity + Friction + (Speed * Drag)** 57 | 58 |
59 | 60 | 61 | 62 | # Pictures 63 | | Old version | New version | 64 | | :-: | :-: | 65 | | ![Accelerometer version from MakerFaire 2022](https://github.com/ArminJo/OpenledRace/blob/master/pictures/Overview.jpg) | ![Accelerometer version from MakerFaire 2022](https://github.com/ArminJo/OpenledRace/blob/master/pictures/Details2.jpg) | 66 | | | | 67 | | At the Cologne public library MINTköln-Festival 2025 | At the Cologne public library MINTköln-Festival 2021 | 68 | | ![OpenLedRace at the Cologne public library MINTköln-Festival 2021](https://github.com/ArminJo/OpenledRace/blob/master/pictures/OpenLedRaceAtMintFestival.jpg) | ![OpenLedRace at the Cologne public library MINTköln-Festival 2025](https://github.com/ArminJo/OpenledRace/blob/master/pictures/OpenLedRaceAtMintFestival_2025.jpg) | 69 | 70 |
71 | 72 | # Size 73 | The version using a 5 m IP30 - 60 pixel per meter strip with ramp and loop reqires an area of 145 cm x 80 cm plus 20 cm space for breadboard etc.
74 | The base of the ramp is 83 cm, the height is 23.5 cm. The slope is 45 degree and therefore the top of the ramp is 83 cm - (2 * 23.5 cm) = 36 cm.
75 | The diameter of the loop is 26 cm. 76 | 77 |
78 | 79 | # YouTube Videos 80 | | At the Hannover MakerFaire 2022 | At the Cologne public library MINTköln-Festival 2021 | 81 | | :-: | :-: | 82 | | [![OpenLedRace at the Hannover MakerFaire 2022](https://i.ytimg.com/vi/lYzYpFYJfWI/hqdefault.jpg)](https://www.youtube.com/watch?v=lYzYpFYJfWI) | [![OpenLedRace in action 2021](https://i.ytimg.com/vi/y25rjRkDg0g/hqdefault.jpg)](https://www.youtube.com/watch?v=y25rjRkDg0g) | 83 | | | | 84 | | At the Cologne public library MINTköln-Festival 2025 | | 85 | | [![OpenLedRace in action 2025](https://i.ytimg.com/vi/mGpJGzWwncQ/hqdefault.jpg)](https://www.youtube.com/watch?v=mGpJGzWwncQ) | | 86 | 87 |
88 | 89 | # Arduino plotter output 90 | ![Arduino plotter output](https://github.com/ArminJo/OpenledRace/blob/master/pictures/ArduinoPlotterOutput.png) 91 | 92 | In this output, both accelerators were initially moving, then only the first, and finally the second alone. `AccelLP` is the low-pass value of `Accel`.
93 | In the middle, there is a steep decrease in speed at the same input level. This is because the car has reached the ramp and must now overcome gravity.
94 | At the end, you can see negative speed. This is because the car was on the ramp when the input stopped and gravity moved it backwards down the ramp. 95 | 96 |
97 | 98 | # Compile with the Arduino IDE 99 | Download and extract the repository. In the Arduino IDE open the sketch with File -> Open... and select the OpenledRace folder.
100 | You need to install *Adafruit NeoPixel* library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string.
101 | You also need to install *NeoPatterns* and *PlayRtttl* library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" 102 | 103 | # BOM 104 | ### Required 105 | - Breadboard 106 | - Jumper wire 107 | - Pin header to connect cables to breadboard 108 | - Arduino Nano 109 | - WS2812 strip 5m 60 IP30 - 60 pixel per meter 110 | - 10 kOhm resistor for WS2812 strip data input 111 | - 2 push buttons 16 mm + 2x2 meter flexible 2-wire cable 112 | - 2 Handlebar ends with foam grips to mount the push buttons 113 | - 2004 LCD with serial I2C interface adapter 114 | - Speaker > 32 Ω 115 | - 4.7 µF capacitor for speaker 116 | - Power supply - e.g. a 18650 battery + holder 117 | - "Reset / Start Game" Pushbutton 118 | - 1 kΩ potentiometer for speaker volume control 119 | 120 | ### Optional 121 | - 2 8xWS2812 bars + 2 10kOhm resistors for optical feedback of input strength 122 | - 2 GY-521 MPU6050 accelerometer Breakout boards (+ 2 Blink LEDs) 123 | - 2 Dumbbells, each 1 kg 124 | - 2x2 meter 4-Wire cable (+ 2x2 10 kOhm I2C pullup resistors) to connect the accelerometers 125 | - 3 pieces 4 pole magnetic pogo pin connectors 126 | 127 | 128 | ### For development 129 | - 3 100k potentiometers for setting of Gravity, Friction and Drag. 130 | 131 | Pin layout is defined [here](https://github.com/ArminJo/NeoPatterns/blob/master/examples/OpenLedRace/OpenLedRace.ino#L129) 132 | 133 | | Breadboard overview | Accelerometer connection | 134 | | :-: | :-: | 135 | | ![BreadboardOverview](https://github.com/ArminJo/OpenledRace/blob/master/pictures/BreadboardOverview.jpg) | ![Accelerometer connection](https://github.com/ArminJo/OpenledRace/blob/master/pictures/Accelerometer.jpg) | 136 | | Breadboard top view | Breadboard front view | 137 | | ![Breadboard top view](https://github.com/ArminJo/OpenledRace/blob/master/pictures/BreadboardTop.jpg) | ![Breadboard front view](https://github.com/ArminJo/OpenledRace/blob/master/pictures/BreadboardFront.jpg) | 138 | 139 | 140 | ### Links: 141 | - https://www.hackster.io/gbarbarov/open-led-race-a0331a 142 | - https://twitter.com/openledrace 143 | - https://gitlab.com/open-led-race 144 | - https://openledrace.net/open-software/ 145 | -------------------------------------------------------------------------------- /src/MatrixNeoPatterns.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MatrixNeoPatterns.h 3 | * 4 | * SUMMARY 5 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 6 | * Extension are made to include more patterns and combined patterns and patterns for 8x8 NeoPixel matrix. 7 | * 8 | * Copyright (C) 2018-2022 Armin Joachimsmeyer 9 | * armin.joachimsmeyer@gmail.com 10 | * 11 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 12 | * 13 | * NeoPatterns is free software: you can redistribute it and/or modify 14 | * it under the terms of the GNU General Public License as published by 15 | * the Free Software Foundation, either version 3 of the License, or 16 | * (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 21 | * See the GNU General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public License 24 | * along with this program. If not, see . 25 | * 26 | */ 27 | 28 | /* 29 | * Class inheritance diagram. We have virtual inheritance, since MatrixNeoPatterns needs only one member set of NeoPixel 30 | * 31 | * ,o--> MatrixNeoPixel (virtual) \ 32 | * MatrixSnake --> MatrixNeoPatterns < o--> NeoPixel --> Adafruit_NeoPixel 33 | * `o--> NeoPatterns (virtual) / 34 | */ 35 | 36 | #ifndef _MATRIX_NEOPATTERNS_H 37 | #define _MATRIX_NEOPATTERNS_H 38 | 39 | #include "MatrixNeoPixel.h" 40 | 41 | #if (!(defined(ENABLE_MATRIX_PATTERN_TICKER) || defined(ENABLE_MATRIX_PATTERN_MOVE) || defined(ENABLE_MATRIX_PATTERN_MOVING_PICTURE) \ 42 | || defined(ENABLE_MATRIX_PATTERN_FIRE) || defined(ENABLE_MATRIX_PATTERN_SNOW) \ 43 | || defined(ENABLE_NO_MATRIX_AND_NEO_PATTERN_BY_DEFAULT) )) 44 | #define ENABLE_MATRIX_PATTERN_TICKER 45 | #define ENABLE_MATRIX_PATTERN_MOVE 46 | #define ENABLE_MATRIX_PATTERN_MOVING_PICTURE 47 | #define ENABLE_MATRIX_PATTERN_FIRE 48 | #define ENABLE_MATRIX_PATTERN_SNOW 49 | #else 50 | #define ENABLE_NO_NEO_PATTERN_BY_DEFAULT // must be before #include "NeoPatterns.h" 51 | #endif 52 | 53 | #include "NeoPatterns.h" 54 | 55 | #define MATRIX_PATTERN_TICKER (LAST_NEO_PATTERN + 1) 56 | #define MATRIX_PATTERN_MOVE (LAST_NEO_PATTERN + 2) 57 | #define MATRIX_PATTERN_MOVING_PICTURE (LAST_NEO_PATTERN + 3) 58 | #define MATRIX_PATTERN_FIRE (LAST_NEO_PATTERN + 4) 59 | #define MATRIX_PATTERN_SNOW (LAST_NEO_PATTERN + 5) 60 | #define LAST_MATRIX_NEO_PATTERN MATRIX_PATTERN_SNOW 61 | 62 | #define FLAG_TICKER_DATA_IN_FLASH 0x01 // Flag if DataPtr points to RAM or FLASH. Only evaluated for AVR platform. 63 | 64 | extern const uint8_t fontNumbers4x6[] PROGMEM; // the font for showing numbers 65 | #define NUMBERS_FONT_WIDTH 4 66 | #define NUMBERS_FONT_HEIGHT 6 67 | 68 | #define MATRIX_FIRE_COOLING_PER_8_ROWS 15 // for 8 rows 10 to 25 are sensible with optimum around 15 69 | /* 70 | * The sum SHOULD be 0!!! 71 | * The Matrix which describes the contribution of each surrounding pixel to the next heat value. 72 | */ 73 | #define CONVOLUTION_MATRIX_SIZE 3 74 | //float const convolutionMatrix[CONVOLUTION_MATRIX_SIZE][CONVOLUTION_MATRIX_SIZE] = 75 | // { { 0.05, 0.74, 0.05 }/*weights of values below*/, { 0.05, -1 /*own value*/, 0.05 }, { 0.02, 0.02, 0.02 } /*weights of values above*/}; 76 | //int16_t const convolutionMatrixIntegerTimes256[CONVOLUTION_MATRIX_SIZE][CONVOLUTION_MATRIX_SIZE] = 77 | //{ { 13, 189, 13 }/*weights of values below*/, { 13, -256 /*own value*/, 13 }, { 5, 5, 5 } /*weights of values above*/}; 78 | //int16_t const convolutionMatrixIntegerTimes256[CONVOLUTION_MATRIX_SIZE][CONVOLUTION_MATRIX_SIZE] = 79 | //{ { 13, 90, 13 }/*weights of values below*/, { 6, -128 /*own value*/, 6 },{ 0, 0, 0 } /*weights of values above*/}; 80 | int16_t const convolutionMatrixIntegerTimes256[CONVOLUTION_MATRIX_SIZE][CONVOLUTION_MATRIX_SIZE] = { 81 | { 13, 102, 13 } /*weights of values below*/, { 0, -128 /*own value*/, 0 }, { 0, 0, 0 } /*weights of values above*/}; 82 | 83 | #define SNOW_BOTTOM_LINE_DIM_PRESCALER 20 84 | // Bit-fields save 2 bytes RAM per flake but costs 120 bytes program memory 85 | struct SnowFlakeInfoStruct { 86 | #if defined(SNOW_SUPPORT_MORE_THAN_16_ROWS_AND_COLUMNS) 87 | uint8_t Period; 88 | uint8_t Counter; 89 | uint8_t Row; // starting with 0 / top 90 | uint8_t Column; // starting with 0 / left 91 | #else 92 | uint8_t Period :4; // Lowest nibble. Values from 8 to F. Fast flakes (period = 8 or 9) are in the foreground an therefore brighter; 93 | uint8_t Counter :4; 94 | uint8_t Row :4; // starting with 0 / top 95 | uint8_t Column :4; // Highest Nibble. Starting with 0 / left 96 | #endif 97 | #define MASK_FOR_8X8_MATRIX 0x77FF // only columns / rows from 0 to 7 98 | }; 99 | 100 | // extension of NeoPattern Class approximately 85 byte / object 101 | class MatrixNeoPatterns: public MatrixNeoPixel, public NeoPatterns { 102 | public: 103 | MatrixNeoPatterns(); 104 | void init(); 105 | MatrixNeoPatterns(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, neoPixelType aTypeOfPixel, 106 | void (*aPatternCompletionCallback)(NeoPatterns*)=nullptr); 107 | bool init(uint8_t aColumns, uint8_t aRows, uint8_t aPin, uint8_t aMatrixGeometry, neoPixelType aTypeOfPixel, 108 | void (*aPatternCompletionCallback)(NeoPatterns*)=nullptr); 109 | 110 | void setGeometry(uint8_t aRows, uint8_t aColoums); 111 | 112 | #if defined(ENABLE_MATRIX_PATTERN_TICKER) 113 | void TickerPGM(const char *aStringPtrPGM, color32_t aForegroundColor, color32_t aBackgroundColor, uint16_t aIntervalMillis, 114 | uint8_t aDirection = DIRECTION_LEFT); 115 | void Ticker(__FlashStringHelper *aStringPtrPGM, color32_t aForegroundColor, color32_t aBackgroundColor, 116 | uint16_t aIntervalMillis, uint8_t aDirection = DIRECTION_LEFT); 117 | void Ticker(const char *aStringPtr, color32_t aForegroundColor, color32_t aBackgroundColor, uint16_t aIntervalMillis, 118 | uint8_t aDirection = DIRECTION_LEFT); 119 | void TickerInit(const char *aStringPtr, color32_t aForegroundColor, color32_t aBackgroundColor, uint16_t aIntervalMillis, 120 | uint8_t aDirection = DIRECTION_LEFT, uint8_t aFlags = 0); 121 | bool TickerUpdate(); 122 | #endif 123 | 124 | #if defined(ENABLE_MATRIX_PATTERN_MOVING_PICTURE) 125 | void MovingPicturePGM(const uint8_t *aGraphics8x8Array, color32_t aForegroundColor, color32_t aBackgroundColor, int8_t aXOffset, 126 | int8_t aYOffset, uint16_t aSteps, uint16_t aIntervalMillis, uint8_t aDirection = DIRECTION_UP); 127 | bool MovingPicturePGMUpdate(); 128 | #endif 129 | #if defined(ENABLE_MATRIX_PATTERN_MOVE) 130 | void Move(uint8_t aDirection, uint16_t aNumberOfSteps = 1, uint16_t aIntervalMillis = 70, color32_t aBackgroundColor = 131 | COLOR32_BLACK); 132 | bool MoveUpdate(); 133 | #endif 134 | void moveArrayContent(uint8_t aDirection); 135 | void moveArrayContent(uint8_t aDirection, color32_t aBackgroundColor); 136 | 137 | bool update(); 138 | bool update(uint8_t aBrightness); 139 | 140 | #if defined(ENABLE_MATRIX_PATTERN_SNOW) 141 | bool Snow(uint16_t aNumberOfSteps = 500, uint16_t aIntervalMillis = 20); 142 | bool SnowUpdate(); 143 | void SnowStop(); 144 | 145 | void setRandomFlakeParameters(uint8_t aSnowFlakeIndex); 146 | void drawSnowFlake(uint8_t aSnowFlakeIndex); 147 | struct SnowFlakeInfoStruct *SnowFlakesArray; 148 | #endif 149 | 150 | void showNumberOnMatrix(uint8_t aNumber, color32_t aColor); 151 | 152 | #if defined(ENABLE_MATRIX_PATTERN_FIRE) 153 | bool Fire(uint16_t aNumberOfSteps = 200, uint16_t aIntervalMillis = 30); 154 | bool FireMatrixUpdate(); 155 | void FireMatrixStop(); 156 | void FireMatrixDealloc(); 157 | /* 158 | * Two arrays for double buffering. Used for fire pattern 159 | * They have 1 pixel padding on each side for computation of convolution 160 | * Plus 1 extra bottom row for initial heat values 161 | */ 162 | uint8_t *MatrixNew; 163 | uint8_t *MatrixOld; 164 | #endif 165 | 166 | // for movingPicture and Ticker patterns 167 | const uint8_t *DataPtr; // can hold pointer to PGM or data space string or to PGM space 8x8 graphic array. 168 | int8_t GraphicsYOffset; // Offset of lower edge of graphic 169 | int8_t GraphicsXOffset; // Offset of left edge of graphic 170 | 171 | void setInitHeat(); 172 | }; 173 | 174 | void MatrixPatternsDemo(NeoPatterns *aLedsPtr); 175 | 176 | void myLoadTest(MatrixNeoPatterns *aLedsPtr); 177 | 178 | #endif // _MATRIX_NEOPATTERNS_H 179 | -------------------------------------------------------------------------------- /examples/UserPatterns/UserPattern.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * UserPattern.cpp 3 | * 4 | * User pattern must at least implement the following functions: 5 | * bool UserPattern1Update(NeoPatterns *aNeoPatterns, bool aDoUpdate); 6 | * 7 | * This example contains the definitions of all functions for UserPattern1 and UserPattern2. 8 | * For convenience it also contains a test handler userPatternsHandler(), 9 | * which switches between both patterns using different colors. 10 | * 11 | * You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string 12 | * 13 | * Copyright (C) 2022-2024 Armin Joachimsmeyer 14 | * armin.joachimsmeyer@gmail.com 15 | * 16 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 17 | * 18 | * NeoPatterns is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU General Public License as published by 20 | * the Free Software Foundation, either version 3 of the License, or 21 | * (at your option) any later version. 22 | * 23 | * This program is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 | * See the GNU General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU General Public License 29 | * along with this program. If not, see . 30 | * 31 | */ 32 | 33 | #include 34 | 35 | #define ENABLE_PATTERN_USER_PATTERN1 36 | #define ENABLE_PATTERN_USER_PATTERN2 37 | #define ENABLE_PATTERN_COLOR_WIPE 38 | #define DEBUG 39 | 40 | #include 41 | 42 | #define INFO // if not defined, no Serial related code should be linked 43 | 44 | // Which pin on the Arduino is connected to the NeoPixels? 45 | #define PIN_NEOPIXEL_BAR_16 3 46 | 47 | // onComplete callback handler for all patterns 48 | void userPatternsHandler(NeoPatterns *aLedsPtr); 49 | 50 | NeoPatterns bar16 = NeoPatterns(16, PIN_NEOPIXEL_BAR_16, NEO_GRB + NEO_KHZ800, &userPatternsHandler); 51 | 52 | void setup() { 53 | pinMode(LED_BUILTIN, OUTPUT); 54 | 55 | Serial.begin(115200); 56 | #if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \ 57 | || defined(SERIALUSB_PID) || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) 58 | delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor! 59 | #endif 60 | // Just to know which program is running on my Arduino 61 | Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_NEOPATTERNS)); 62 | bar16.printConnectionInfo(&Serial); 63 | 64 | bar16.begin(); // This initializes the NeoPixel library. 65 | bar16.ColorWipe(COLOR32(0, 0, 02), 50, false, DIRECTION_DOWN); // light Blue 66 | 67 | Serial.println("started"); 68 | 69 | delay(500); 70 | } 71 | 72 | void loop() { 73 | bar16.update(); 74 | delay(10); 75 | } 76 | 77 | /************************************************************************************************************ 78 | * Put your own pattern code here 79 | * Provided are sample implementations 80 | ************************************************************************************************************/ 81 | /* 82 | * Set all pixel to aBackgroundColor and let a pixel of Color1 move through. 83 | * Starts with all pixel aColor1 and also ends with it. 84 | */ 85 | void UserPattern1(NeoPatterns *aNeoPatterns, color32_t aPixelColor, color32_t aBackgroundColor, uint16_t aIntervalMillis, 86 | uint8_t aDirection) { 87 | aNeoPatterns->Interval = aIntervalMillis; 88 | aNeoPatterns->Color1 = aPixelColor; 89 | aNeoPatterns->LongValue1.BackgroundColor = aBackgroundColor; 90 | aNeoPatterns->Direction = aDirection; 91 | aNeoPatterns->TotalStepCounter = aNeoPatterns->numPixels() + 2; // + 2 for the first and last pattern 92 | if (aDirection == DIRECTION_UP) { 93 | aNeoPatterns->Index = -1; 94 | } else { 95 | aNeoPatterns->Index = aNeoPatterns->numPixels(); 96 | } 97 | 98 | aNeoPatterns->setColor(aBackgroundColor); 99 | aNeoPatterns->showPatternInitially(); 100 | // must be after showPatternInitially(), since it requires the old value do detect asynchronous calling 101 | aNeoPatterns->ActivePattern = PATTERN_USER_PATTERN1; 102 | #if defined(TRACE) 103 | aNeoPatterns->printInfo(&Serial, true); 104 | #endif 105 | } 106 | 107 | /* 108 | * @return - true if pattern has ended, false if pattern has NOT ended 109 | */ 110 | bool UserPattern1Update(NeoPatterns *aNeoPatterns, bool aDoUpdate) { 111 | if (aDoUpdate) { 112 | Serial.println("User pattern 1 updated"); 113 | Serial.flush(); 114 | 115 | // decrementTotalStepCounterAndSetNextIndex() calls callback and returns true if pattern ended 116 | if (aNeoPatterns->decrementTotalStepCounterAndSetNextIndex()) { 117 | Serial.println("User pattern 1 ended"); 118 | Serial.flush(); 119 | return true; 120 | } 121 | } 122 | 123 | /* 124 | * Refresh pattern 125 | */ 126 | for (unsigned int i = 0; i < aNeoPatterns->numPixels(); i++) { 127 | if (i == aNeoPatterns->Index) { 128 | aNeoPatterns->setPixelColor(i, aNeoPatterns->Color1); 129 | } else { 130 | aNeoPatterns->setPixelColor(i, aNeoPatterns->LongValue1.BackgroundColor); 131 | } 132 | } 133 | return false; 134 | } 135 | 136 | /* 137 | * Sample implementation 138 | * let a pixel of aColor move up and down 139 | * starts and ends with all pixel cleared 140 | */ 141 | void UserPattern2(NeoPatterns *aNeoPatterns, color32_t aColor, uint16_t aIntervalMillis, uint16_t aRepetitions, 142 | uint8_t aDirection) { 143 | 144 | aNeoPatterns->Interval = aIntervalMillis; 145 | aNeoPatterns->Color1 = aColor; 146 | aNeoPatterns->Direction = aDirection; 147 | // *2 for up and down. (aNeoPatterns->numPixels() - 1) do not use end pixel twice. 148 | // +1 for the initial pattern with end pixel. + 2 for the first and last clear pattern. 149 | aNeoPatterns->TotalStepCounter = ((aRepetitions + 1) * 2 * (aNeoPatterns->numPixels() - 1)) + 1 + 2; 150 | if (aDirection == DIRECTION_UP) { 151 | aNeoPatterns->Index = -1; 152 | } else { 153 | aNeoPatterns->Index = aNeoPatterns->numPixels(); 154 | } 155 | 156 | aNeoPatterns->clear(); 157 | aNeoPatterns->showPatternInitially(); 158 | // must be after showPatternInitially(), since it requires the old value do detect asynchronous calling 159 | aNeoPatterns->ActivePattern = PATTERN_USER_PATTERN2; 160 | #if defined(TRACE) 161 | aNeoPatterns->printInfo(&Serial, true); 162 | #endif 163 | } 164 | 165 | /* 166 | * @param aDoUpdate if true update the pattern by one step, otherwise only refresh it. 167 | * @return - true if pattern has ended, false if pattern has NOT ended 168 | */ 169 | bool UserPattern2Update(NeoPatterns *aNeoPatterns, bool aDoUpdate) { 170 | if (aDoUpdate) { 171 | // clear old pixel 172 | aNeoPatterns->setPixelColor(aNeoPatterns->Index, COLOR32_BLACK); 173 | 174 | if (aNeoPatterns->decrementTotalStepCounterAndSetNextIndex()) { 175 | return true; 176 | } 177 | /* 178 | * Next index 179 | */ 180 | if (aNeoPatterns->Direction == DIRECTION_UP) { 181 | // do not use top pixel twice 182 | if (aNeoPatterns->Index == (aNeoPatterns->numPixels() - 1)) { 183 | aNeoPatterns->Direction = DIRECTION_DOWN; 184 | } 185 | } else { 186 | // do not use bottom pixel twice 187 | if (aNeoPatterns->Index == 0) { 188 | aNeoPatterns->Direction = DIRECTION_UP; 189 | } 190 | } 191 | } 192 | 193 | /* 194 | * Refresh pattern 195 | */ 196 | if (aNeoPatterns->TotalStepCounter != 1) { 197 | // last pattern is clear 198 | aNeoPatterns->setPixelColor(aNeoPatterns->Index, aNeoPatterns->Color1); 199 | } 200 | return false; 201 | } 202 | 203 | /* 204 | * Handler for testing your user patterns 205 | */ 206 | void userPatternsHandler(NeoPatterns *aLedsPtr) { 207 | static int8_t sState = 0; 208 | 209 | uint8_t tDuration = random(20, 120); 210 | uint8_t tColor = random(255); 211 | uint8_t tRepetitions = random(2); 212 | Serial.print("sState="); 213 | Serial.println(sState); 214 | 215 | switch (sState) { 216 | case 0: 217 | Serial.println("Start user pattern 1"); 218 | Serial.flush(); 219 | // tRepetitions & DIRECTION_UP_DOWN_MASK leads to 0 or 2 which is UP and DOWN 220 | // dimColor() reduces color intensity to 50 % 221 | UserPattern1(aLedsPtr, COLOR32_RED_HALF, NeoPatterns::dimColor(NeoPatterns::Wheel(tColor)), tDuration, tRepetitions & DIRECTION_UP_DOWN_MASK); 222 | break; 223 | 224 | case 1: 225 | Serial.println("Start user pattern 2"); 226 | UserPattern2(aLedsPtr, NeoPatterns::Wheel(tColor), tDuration, tRepetitions, DIRECTION_UP); 227 | sState = -1; // Start from beginning 228 | break; 229 | 230 | default: 231 | Serial.println("ERROR"); 232 | break; 233 | } 234 | 235 | sState++; 236 | } 237 | -------------------------------------------------------------------------------- /examples/MatrixPatternsTest/HexDump.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * HexDump.hpp 3 | * Hex memory dump utility functions for Arduino. 4 | * 0x00 and 0xFF are printed as spaces, values above 0x80 are printed as '.'. 5 | * 6 | * Sample output: 7 | * 0x0000: 0xF1 0x81 0x82 0x00 0x08 0x02 0x00 0x27 0xFF 0xFF 0x0E 0xB3 0x81 0xFC 0x9B 0x47 ... .. ' .....G 8 | * 0x0020: 0x00 0x00 0x00 0x00 0x20 0x65 0x00 0x0F 0xBE 0xEB 0x9B 0x98 0x2C 0xF1 0x08 0x2C e .....,.., 9 | * 10 | * Copyright (C) 2022-2024 Armin Joachimsmeyer 11 | * Email: armin.joachimsmeyer@gmail.com 12 | * 13 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 14 | * 15 | * Arduino-Utils is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published by 17 | * the Free Software Foundation, either version 3 of the License, or 18 | * (at your option) any later version. 19 | * 20 | * This program is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 23 | * See the GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with this program. If not, see . 27 | */ 28 | 29 | #ifndef _HEX_DUMP_HPP 30 | #define _HEX_DUMP_HPP 31 | 32 | #include 33 | 34 | // Next lines are a copy of the HexDump.h content 35 | #define _16_BYTES_PER_LINE 16 36 | 37 | #define HEX_DUMP_FORMAT_16_BIT_ABSOLUTE_ADDRESS 0x00 // Print 16 bit absolute address 38 | #define HEX_DUMP_FORMAT_NO_ADDRESS_AT_ALL 0x01 // Bit 0: else print 39 | #define HEX_DUMP_FORMAT_RELATIVE_ADDRESS 0x02 // Bit 1: else absolute address 40 | #define HEX_DUMP_FORMAT_8_BIT_ADDRESS 0x04 // Bit 2: else 16 bit Address 41 | #define HEX_DUMP_FORMAT_ASCII_VALUES 0x08 // default 42 | 43 | void printBufferHex(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints no address and hex bytes without ASCII representation. 44 | void printBufferHexDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints short relative address and hex bytes without ASCII representation. 45 | void printBufferHexAndASCIIDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint); // Prints short relative address and hex bytes without ASCII representation. 46 | void printMemoryHexNoASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes with ASCII representation. 47 | void printMemoryHexAndASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes with ASCII representation. 48 | void printStackMemory(uint16_t aNumberOfBytesToPrint); // Prints 16 bit address and hex bytes ending at top of stack / RAM end. 49 | void printStackDump(); // Prints 16 bit address and hex bytes starting at current stackpointer and ending at ending at top of stack / RAM end. 50 | void printMemoryHexDump(uint8_t *aMemory, uint16_t aSizeOfMemoryToPrint, uint8_t aBytesPerLine = _16_BYTES_PER_LINE, 51 | uint8_t aFormatFlags = HEX_DUMP_FORMAT_ASCII_VALUES); 52 | void printBytePaddedHex(uint8_t aHexValueToPrint); 53 | void printWordPaddedHex(uint16_t aHexValueToPrint); 54 | // End of the copy of the HexDump.h content 55 | 56 | /* 57 | * Prints no address and hex bytes without ASCII representation. 58 | */ 59 | void printBufferHex(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint) { 60 | printMemoryHexDump(aBufferAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, HEX_DUMP_FORMAT_NO_ADDRESS_AT_ALL); 61 | } 62 | /* 63 | * Prints short relative address and hex bytes without ASCII representation. 64 | */ 65 | void printBufferHexDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint) { 66 | printMemoryHexDump(aBufferAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, 67 | HEX_DUMP_FORMAT_8_BIT_ADDRESS | HEX_DUMP_FORMAT_RELATIVE_ADDRESS); 68 | } 69 | /* 70 | * Prints short relative address and hex bytes without ASCII representation. 71 | */ 72 | void printBufferHexAndASCIIDump(uint8_t *aBufferAddress, uint16_t aNumberOfBytesToPrint) { 73 | printMemoryHexDump(aBufferAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, 74 | HEX_DUMP_FORMAT_8_BIT_ADDRESS | HEX_DUMP_FORMAT_RELATIVE_ADDRESS | HEX_DUMP_FORMAT_ASCII_VALUES); 75 | } 76 | 77 | /* 78 | * Prints 16 bit address and hex bytes with ASCII representation. 79 | */ 80 | void printMemoryHexNoASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint) { 81 | printMemoryHexDump(aMemoryAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, HEX_DUMP_FORMAT_16_BIT_ABSOLUTE_ADDRESS); 82 | } 83 | 84 | /* 85 | * Prints 16 bit address and hex bytes starting at current stackpointer and ending at ending at top of stack / RAM end. 86 | */ 87 | void printStackDump() { 88 | Serial.print(F("Caller address=0x")); 89 | uint16_t tCallerAddress = (uint16_t) __builtin_return_address(0); 90 | Serial.print(tCallerAddress, HEX); 91 | Serial.print(F(" | ")); 92 | Serial.println(tCallerAddress << 1, HEX); 93 | printMemoryHexDump((uint8_t*) SP, RAMEND - SP, _16_BYTES_PER_LINE, HEX_DUMP_FORMAT_16_BIT_ABSOLUTE_ADDRESS); 94 | } 95 | 96 | /* 97 | * Prints 16 bit address and hex bytes ending at top of stack / RAM end. 98 | */ 99 | void printStackMemory(uint16_t aNumberOfBytesToPrint) { 100 | Serial.print(F("SP=0x")); 101 | Serial.print((uint16_t) SP, HEX); 102 | Serial.print(F(", caller address=0x")); 103 | uint16_t tCallerAddress = (uint16_t) __builtin_return_address(0); 104 | Serial.print(tCallerAddress, HEX); 105 | Serial.print(F(" | ")); 106 | Serial.println(tCallerAddress << 1, HEX); 107 | 108 | uint8_t *tMemoryAddress = (uint8_t*) ((RAMEND + 1) - aNumberOfBytesToPrint); 109 | printMemoryHexDump(tMemoryAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, HEX_DUMP_FORMAT_16_BIT_ABSOLUTE_ADDRESS); 110 | } 111 | 112 | /* 113 | * Prints 16 bit address and hex bytes with ASCII representation. 114 | * like printMemoryHexDump(aMemoryAddress, aNumberOfBytesToPrint), because of default parameter 115 | */ 116 | void printMemoryHexAndASCIIDump(uint8_t *aMemoryAddress, uint16_t aNumberOfBytesToPrint) { 117 | printMemoryHexDump(aMemoryAddress, aNumberOfBytesToPrint, _16_BYTES_PER_LINE, HEX_DUMP_FORMAT_ASCII_VALUES); 118 | } 119 | 120 | /** 121 | * Prints lines of memory content 122 | * 0x0000: 0xF1 0x81 0x82 0x00 0x08 0x02 0x00 0x27 0xFF 0xFF 0x0E 0xB3 0x81 0xFC 0x9B 0x47 ... .. ' .....G 123 | * @param aNumberOfBytesToPrint Number of lines to print are: (aSizeOfMemoryToPrint/BYTES_PER_LINE) + 1 124 | * @param aBytesPerLine Number of bytes in one line 125 | * @param aFormatFlags See definitions above 126 | */ 127 | void printMemoryHexDump(uint8_t *aMemory, uint16_t aNumberOfBytesToPrint, uint8_t aBytesPerLine, uint8_t aFormatFlags) { 128 | uint16_t tIndex = 0; 129 | Serial.println(); 130 | while (true) { 131 | if (aBytesPerLine > aNumberOfBytesToPrint) { 132 | // last line 133 | aBytesPerLine = aNumberOfBytesToPrint; 134 | } 135 | 136 | if (aBytesPerLine == 0) { 137 | break; 138 | } else { 139 | aNumberOfBytesToPrint -= aBytesPerLine; 140 | if ((aFormatFlags & HEX_DUMP_FORMAT_NO_ADDRESS_AT_ALL) == 0) { 141 | /* 142 | * Print address in different formats 143 | */ 144 | uint16_t tAddress = tIndex; 145 | if ((aFormatFlags & HEX_DUMP_FORMAT_RELATIVE_ADDRESS) == 0) { 146 | tAddress += (uint16_t) aMemory; 147 | } 148 | if ((aFormatFlags & HEX_DUMP_FORMAT_8_BIT_ADDRESS) != 0) { 149 | printBytePaddedHex(tAddress); 150 | } else { 151 | printWordPaddedHex(tAddress); 152 | } 153 | Serial.print(F(": ")); 154 | } 155 | 156 | /* 157 | * print hex bytes 158 | */ 159 | for (uint_fast8_t i = 0; i < aBytesPerLine; i++) { 160 | printBytePaddedHex(aMemory[tIndex + i]); 161 | } 162 | 163 | if ((aFormatFlags & HEX_DUMP_FORMAT_ASCII_VALUES) != 0) { 164 | /* 165 | * print bytes ASCII representation 166 | */ 167 | Serial.print(F(" ")); 168 | for (uint_fast8_t i = 0; i < aBytesPerLine; i++) { 169 | uint8_t tCharacterToPrint = aMemory[tIndex + i]; 170 | // if(isalnum(tIndex+i)){ // requires 40 bytes more program space 171 | if (' ' <= tCharacterToPrint && tCharacterToPrint <= '~') { 172 | Serial.print((char) tCharacterToPrint); 173 | } else if (tCharacterToPrint != 0x00 && tCharacterToPrint != 0xFF) { 174 | // for non printable characters except 0 and FF 175 | Serial.print('.'); 176 | } else { 177 | Serial.print(' '); 178 | } 179 | } 180 | } 181 | Serial.println(); 182 | tIndex += aBytesPerLine; 183 | } 184 | } 185 | } 186 | 187 | /* 188 | * Print with leading space and "0x" and padded with 0 189 | */ 190 | void printBytePaddedHex(uint8_t aHexValueToPrint) { 191 | Serial.print(F(" 0x")); 192 | if (aHexValueToPrint < 0x10) { 193 | Serial.print('0'); 194 | } 195 | Serial.print(aHexValueToPrint, HEX); 196 | } 197 | 198 | void printWordPaddedHex(uint16_t aHexValueToPrint) { 199 | Serial.print(F("0x")); 200 | if (aHexValueToPrint < 0x1000) { 201 | Serial.print('0'); 202 | } 203 | if (aHexValueToPrint < 0x100) { 204 | Serial.print('0'); 205 | } 206 | if (aHexValueToPrint < 0x10) { 207 | Serial.print('0'); 208 | } 209 | Serial.print(aHexValueToPrint, HEX); 210 | } 211 | #endif // _HEX_DUMP_HPP 212 | -------------------------------------------------------------------------------- /src/font_4x6.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if defined(FONT_4X6) 4 | # if defined(__AVR__) 5 | #include 6 | const uint8_t font_PGM[] PROGMEM = 7 | # else 8 | const uint8_t font[] = 9 | # endif 10 | { 11 | 0x00,0x00,0x00,0x00,0x00,0x00, // 0x20 12 | 0x02,0x02,0x02,0x00,0x02,0x00, // 0x21 13 | 0x05,0x05,0x00,0x00,0x00,0x00, // 0x22 14 | 0x05,0x07,0x05,0x07,0x05,0x00, // 0x23 15 | 0x02,0x03,0x06,0x03,0x06,0x02, // 0x24 16 | 0x04,0x01,0x02,0x04,0x01,0x00, // 0x25 17 | 0x02,0x05,0x03,0x05,0x07,0x00, // 0x26 18 | 0x06,0x04,0x00,0x00,0x00,0x00, // 0x27 19 | 0x02,0x04,0x04,0x04,0x02,0x00, // 0x28 20 | 0x04,0x02,0x02,0x02,0x04,0x00, // 0x29 21 | 0x05,0x02,0x07,0x02,0x05,0x00, // 0x2A 22 | 0x00,0x02,0x07,0x02,0x00,0x00, // 0x2B 23 | 0x00,0x00,0x00,0x00,0x06,0x04, // 0x2C 24 | 0x00,0x00,0x07,0x00,0x00,0x00, // 0x2D 25 | 0x00,0x00,0x00,0x00,0x02,0x00, // 0x2E 26 | 0x01,0x01,0x02,0x04,0x04,0x00, // 0x2F 27 | 0x03,0x05,0x05,0x05,0x06,0x00, // 0x30 0 28 | 0x02,0x06,0x02,0x02,0x07,0x00, // 0x31 1 29 | 0x06,0x01,0x02,0x04,0x07,0x00, // 0x32 30 | 0x06,0x01,0x02,0x01,0x06,0x00, // 0x33 31 | 0x01,0x05,0x07,0x01,0x01,0x00, // 0x34 32 | 0x07,0x04,0x06,0x01,0x06,0x00, // 0x35 33 | 0x02,0x04,0x06,0x05,0x02,0x00, // 0x36 34 | 0x07,0x01,0x03,0x02,0x02,0x00, // 0x37 35 | 0x02,0x05,0x02,0x05,0x02,0x00, // 0x38 36 | 0x02,0x05,0x03,0x01,0x02,0x00, // 0x39 9 37 | 0x00,0x00,0x02,0x00,0x02,0x00, // 0x3A 38 | 0x00,0x00,0x02,0x00,0x06,0x04, // 0x3B 39 | 0x01,0x02,0x04,0x02,0x01,0x00, // 0x3C 40 | 0x00,0x00,0x07,0x00,0x07,0x00, // 0x3D 41 | 0x04,0x02,0x01,0x02,0x04,0x00, // 0x3E 42 | 0x06,0x01,0x02,0x00,0x02,0x00, // 0x3F 43 | 0x07,0x05,0x05,0x04,0x07,0x00, // 0x40 44 | 0x02,0x05,0x07,0x05,0x05,0x00, // 0x41 45 | 0x06,0x05,0x06,0x05,0x06,0x00, // 0x42 46 | 0x03,0x04,0x04,0x04,0x03,0x00, // 0x43 47 | 0x06,0x05,0x05,0x05,0x06,0x00, // 0x44 48 | 0x07,0x04,0x06,0x04,0x07,0x00, // 0x45 49 | 0x07,0x04,0x06,0x04,0x04,0x00, // 0x46 50 | 0x03,0x04,0x05,0x05,0x03,0x00, // 0x47 51 | 0x05,0x05,0x07,0x05,0x05,0x00, // 0x48 52 | 0x07,0x02,0x02,0x02,0x07,0x00, // 0x49 I 53 | 0x01,0x01,0x01,0x05,0x02,0x00, // 0x4A 54 | 0x05,0x05,0x06,0x05,0x05,0x00, // 0x4B 55 | 0x04,0x04,0x04,0x04,0x07,0x00, // 0x4C 56 | 0x05,0x07,0x07,0x05,0x05,0x00, // 0x4D 57 | 0x05,0x07,0x07,0x07,0x05,0x00, // 0x4E N 58 | 0x02,0x05,0x05,0x05,0x02,0x00, // 0x4F 59 | 0x06,0x05,0x06,0x04,0x04,0x00, // 0x50 60 | 0x02,0x05,0x05,0x07,0x03,0x00, // 0x51 61 | 0x06,0x05,0x06,0x05,0x05,0x00, // 0x52 62 | 0x03,0x04,0x07,0x01,0x06,0x00, // 0x53 63 | 0x07,0x02,0x02,0x02,0x02,0x00, // 0x54 64 | 0x05,0x05,0x05,0x05,0x07,0x00, // 0x55 65 | 0x05,0x05,0x05,0x05,0x02,0x00, // 0x56 66 | 0x05,0x05,0x07,0x07,0x05,0x00, // 0x57 67 | 0x05,0x05,0x02,0x05,0x05,0x00, // 0x58 68 | 0x05,0x05,0x02,0x02,0x02,0x00, // 0x59 69 | 0x07,0x01,0x02,0x04,0x07,0x00, // 0x5A 70 | 0x06,0x04,0x04,0x04,0x06,0x00, // 0x5B 71 | 0x04,0x04,0x02,0x01,0x01,0x00, // 0x5C 72 | 0x06,0x02,0x02,0x02,0x06,0x00, // 0x5D 73 | 0x02,0x05,0x00,0x00,0x00,0x00, // 0x5E 74 | 0x00,0x00,0x00,0x00,0x00,0x0F, // 0x5F 75 | 0x06,0x02,0x00,0x00,0x00,0x00, // 0x60 76 | 0x00,0x00,0x03,0x05,0x07,0x00, // 0x61 77 | 0x04,0x04,0x06,0x05,0x06,0x00, // 0x62 78 | 0x00,0x00,0x03,0x04,0x03,0x00, // 0x63 79 | 0x01,0x01,0x03,0x05,0x03,0x00, // 0x64 80 | 0x00,0x00,0x07,0x06,0x03,0x00, // 0x65 81 | 0x01,0x02,0x07,0x02,0x02,0x00, // 0x66 82 | 0x00,0x00,0x07,0x05,0x01,0x07, // 0x67 83 | 0x04,0x04,0x06,0x05,0x05,0x00, // 0x68 84 | 0x02,0x00,0x02,0x02,0x02,0x00, // 0x69 85 | 0x02,0x00,0x02,0x02,0x02,0x06, // 0x6A 86 | 0x04,0x04,0x05,0x06,0x05,0x00, // 0x6B 87 | 0x02,0x02,0x02,0x02,0x02,0x00, // 0x6C 88 | 0x00,0x00,0x07,0x07,0x05,0x00, // 0x6D 89 | 0x00,0x00,0x06,0x05,0x05,0x00, // 0x6E 90 | 0x00,0x00,0x02,0x05,0x02,0x00, // 0x6F 91 | 0x00,0x00,0x06,0x05,0x06,0x04, // 0x70 92 | 0x00,0x00,0x03,0x05,0x03,0x01, // 0x71 93 | 0x00,0x00,0x06,0x04,0x04,0x00, // 0x72 94 | 0x00,0x00,0x03,0x02,0x06,0x00, // 0x73 95 | 0x00,0x02,0x07,0x02,0x03,0x00, // 0x74 96 | 0x00,0x00,0x05,0x05,0x07,0x00, // 0x75 97 | 0x00,0x00,0x05,0x05,0x02,0x00, // 0x76 98 | 0x00,0x00,0x05,0x07,0x07,0x00, // 0x77 99 | 0x00,0x00,0x05,0x02,0x05,0x00, // 0x78 100 | 0x00,0x00,0x05,0x05,0x02,0x04, // 0x79 101 | 0x00,0x00,0x06,0x02,0x03,0x00, // 0x7A 102 | 0x03,0x02,0x06,0x02,0x03,0x00, // 0x7B 103 | 0x02,0x02,0x02,0x02,0x02,0x00, // 0x7C 104 | 0x06,0x02,0x03,0x02,0x06,0x00, // 0x7D 105 | 0x05,0x0A,0x00,0x00,0x00,0x00, // 0x7E 106 | 0x00,0x02,0x05,0x07,0x00,0x00, // 0x7F 107 | #if !defined(FONT_END7F) 108 | 0x03,0x04,0x04,0x07,0x02,0x04, // 0x80 109 | 0x05,0x00,0x05,0x05,0x03,0x00, // 0x81 110 | 0x01,0x02,0x07,0x06,0x03,0x00, // 0x82 111 | 0x02,0x05,0x03,0x05,0x07,0x00, // 0x83 112 | 0x05,0x00,0x03,0x05,0x07,0x00, // 0x84 113 | 0x04,0x02,0x03,0x05,0x07,0x00, // 0x85 114 | 0x02,0x00,0x03,0x05,0x07,0x00, // 0x86 115 | 0x00,0x07,0x04,0x07,0x02,0x06, // 0x87 116 | 0x02,0x05,0x07,0x06,0x03,0x00, // 0x88 117 | 0x05,0x00,0x07,0x06,0x03,0x00, // 0x89 118 | 0x04,0x02,0x07,0x06,0x03,0x00, // 0x8A 119 | 0x05,0x00,0x02,0x02,0x02,0x00, // 0x8B 120 | 0x02,0x05,0x00,0x02,0x02,0x00, // 0x8C 121 | 0x04,0x02,0x00,0x02,0x02,0x00, // 0x8D 122 | 0x05,0x02,0x05,0x07,0x05,0x00, // 0x8E 123 | 0x02,0x02,0x05,0x07,0x05,0x00, // 0x8F 124 | 0x01,0x02,0x07,0x06,0x07,0x00, // 0x90 125 | 0x00,0x00,0x03,0x07,0x06,0x00, // 0x91 126 | 0x03,0x06,0x07,0x06,0x07,0x00, // 0x92 127 | 0x02,0x05,0x02,0x05,0x02,0x00, // 0x93 128 | 0x05,0x00,0x02,0x05,0x02,0x00, // 0x94 129 | 0x04,0x02,0x02,0x05,0x02,0x00, // 0x95 130 | 0x02,0x05,0x00,0x05,0x07,0x00, // 0x96 131 | 0x04,0x02,0x05,0x05,0x07,0x00, // 0x97 132 | 0x05,0x00,0x05,0x05,0x02,0x04, // 0x98 133 | 0x05,0x02,0x05,0x05,0x02,0x00, // 0x99 134 | 0x05,0x00,0x05,0x05,0x07,0x00, // 0x9A 135 | 0x02,0x07,0x04,0x07,0x02,0x00, // 0x9B 136 | 0x01,0x02,0x07,0x02,0x07,0x00, // 0x9C 137 | 0x05,0x07,0x02,0x07,0x02,0x00, // 0x9D 138 | 0x00,0x06,0x06,0x05,0x05,0x00, // 0x9E 139 | 0x03,0x02,0x03,0x02,0x06,0x00, // 0x9F 140 | 0x01,0x02,0x03,0x05,0x07,0x00, // 0xA0 141 | 0x01,0x02,0x00,0x02,0x02,0x00, // 0xA1 142 | 0x01,0x02,0x07,0x05,0x07,0x00, // 0xA2 143 | 0x01,0x02,0x00,0x05,0x07,0x00, // 0xA3 144 | 0x07,0x00,0x07,0x05,0x05,0x00, // 0xA4 145 | 0x07,0x00,0x05,0x07,0x05,0x00, // 0xA5 146 | 0x03,0x05,0x07,0x00,0x07,0x00, // 0xA6 147 | 0x02,0x05,0x02,0x00,0x07,0x00, // 0xA7 148 | 0x02,0x00,0x02,0x04,0x03,0x00, // 0xA8 149 | 0x00,0x07,0x04,0x04,0x00,0x00, // 0xA9 150 | 0x00,0x0E,0x02,0x02,0x00,0x00, // 0xAA 151 | 0x04,0x05,0x02,0x05,0x03,0x00, // 0xAB 152 | 0x04,0x05,0x02,0x07,0x01,0x00, // 0xAC 153 | 0x02,0x00,0x02,0x02,0x02,0x00, // 0xAD 154 | 0x00,0x05,0x0A,0x05,0x00,0x00, // 0xAE 155 | 0x00,0x0A,0x05,0x0A,0x00,0x00, // 0xAF 156 | 0x04,0x01,0x04,0x01,0x04,0x01, // 0xB0 157 | 0x05,0x0A,0x05,0x0A,0x05,0x0A, // 0xB1 158 | 0x0B,0x0E,0x0B,0x0E,0x0B,0x0E, // 0xB2 159 | 0x02,0x02,0x02,0x02,0x02,0x02, // 0xB3 160 | 0x02,0x02,0x0E,0x02,0x02,0x02, // 0xB4 161 | 0x02,0x0E,0x02,0x0E,0x02,0x02, // 0xB5 162 | 0x05,0x05,0x0D,0x05,0x05,0x05, // 0xB6 163 | 0x00,0x00,0x0F,0x05,0x05,0x05, // 0xB7 164 | 0x00,0x0E,0x02,0x0E,0x02,0x02, // 0xB8 165 | 0x05,0x0D,0x01,0x0D,0x05,0x05, // 0xB9 166 | 0x05,0x05,0x05,0x05,0x05,0x05, // 0xBA 167 | 0x00,0x0F,0x01,0x0D,0x05,0x05, // 0xBB 168 | 0x05,0x0D,0x01,0x0F,0x00,0x00, // 0xBC 169 | 0x05,0x05,0x0F,0x00,0x00,0x00, // 0xBD 170 | 0x02,0x0E,0x02,0x0E,0x00,0x00, // 0xBE 171 | 0x00,0x00,0x0E,0x02,0x02,0x02, // 0xBF 172 | 0x02,0x02,0x03,0x00,0x00,0x00, // 0xC0 173 | 0x02,0x02,0x0F,0x00,0x00,0x00, // 0xC1 174 | 0x00,0x00,0x0F,0x02,0x02,0x02, // 0xC2 175 | 0x02,0x02,0x03,0x02,0x02,0x02, // 0xC3 176 | 0x00,0x00,0x0F,0x00,0x00,0x00, // 0xC4 177 | 0x02,0x02,0x0F,0x02,0x02,0x02, // 0xC5 178 | 0x02,0x03,0x02,0x03,0x02,0x02, // 0xC6 179 | 0x05,0x05,0x05,0x05,0x05,0x05, // 0xC7 180 | 0x05,0x05,0x04,0x07,0x00,0x00, // 0xC8 181 | 0x00,0x07,0x04,0x05,0x05,0x05, // 0xC9 182 | 0x05,0x0D,0x00,0x0F,0x00,0x00, // 0xCA 183 | 0x00,0x0F,0x00,0x0D,0x05,0x05, // 0xCB 184 | 0x05,0x05,0x04,0x05,0x05,0x05, // 0xCC 185 | 0x00,0x0F,0x00,0x0F,0x00,0x00, // 0xCD 186 | 0x05,0x0D,0x00,0x0D,0x05,0x05, // 0xCE 187 | 0x02,0x0F,0x00,0x0F,0x00,0x00, // 0xCF 188 | 0x05,0x05,0x0F,0x00,0x00,0x00, // 0xD0 189 | 0x00,0x0F,0x00,0x0F,0x02,0x02, // 0xD1 190 | 0x00,0x00,0x0F,0x05,0x05,0x05, // 0xD2 191 | 0x05,0x05,0x07,0x00,0x00,0x00, // 0xD3 192 | 0x02,0x03,0x02,0x03,0x00,0x00, // 0xD4 193 | 0x00,0x03,0x02,0x03,0x02,0x02, // 0xD5 194 | 0x00,0x00,0x07,0x05,0x05,0x05, // 0xD6 195 | 0x05,0x05,0x0D,0x05,0x05,0x05, // 0xD7 196 | 0x02,0x0F,0x00,0x0F,0x02,0x02, // 0xD8 197 | 0x02,0x02,0x0E,0x00,0x00,0x00, // 0xD9 198 | 0x00,0x00,0x03,0x02,0x02,0x02, // 0xDA 199 | 0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // 0xDB 200 | 0x00,0x00,0x00,0x0F,0x0F,0x0F, // 0xDC 201 | 0x0C,0x0C,0x0C,0x0C,0x0C,0x0C, // 0xDD 202 | 0x03,0x03,0x03,0x03,0x03,0x03, // 0xDE 203 | 0x0F,0x0F,0x0F,0x00,0x00,0x00, // 0xDF 204 | 0x00,0x00,0x07,0x06,0x07,0x00, // 0xE0 205 | 0x02,0x05,0x06,0x05,0x06,0x04, // 0xE1 206 | 0x07,0x05,0x04,0x04,0x04,0x00, // 0xE2 207 | 0x07,0x05,0x05,0x05,0x05,0x00, // 0xE3 208 | 0x07,0x04,0x02,0x04,0x07,0x00, // 0xE4 209 | 0x00,0x00,0x03,0x05,0x02,0x00, // 0xE5 210 | 0x00,0x00,0x05,0x05,0x07,0x04, // 0xE6 211 | 0x00,0x01,0x06,0x02,0x02,0x00, // 0xE7 212 | 0x07,0x02,0x05,0x02,0x07,0x00, // 0xE8 213 | 0x02,0x05,0x07,0x05,0x02,0x00, // 0xE9 214 | 0x00,0x02,0x05,0x05,0x05,0x00, // 0xEA 215 | 0x03,0x04,0x02,0x05,0x02,0x00, // 0xEB 216 | 0x00,0x00,0x07,0x05,0x07,0x00, // 0xEC 217 | 0x02,0x07,0x05,0x07,0x02,0x00, // 0xED 218 | 0x03,0x04,0x07,0x04,0x03,0x00, // 0xEE 219 | 0x02,0x05,0x05,0x05,0x05,0x00, // 0xEF 220 | 0x07,0x00,0x07,0x00,0x07,0x00, // 0xF0 221 | 0x02,0x07,0x02,0x00,0x07,0x00, // 0xF1 222 | 0x06,0x01,0x06,0x00,0x07,0x00, // 0xF2 223 | 0x03,0x04,0x03,0x00,0x07,0x00, // 0xF3 224 | 0x00,0x01,0x02,0x02,0x02,0x02, // 0xF4 225 | 0x02,0x02,0x02,0x02,0x04,0x00, // 0xF5 226 | 0x02,0x00,0x07,0x00,0x02,0x00, // 0xF6 227 | 0x00,0x05,0x0A,0x05,0x0A,0x00, // 0xF7 228 | 0x02,0x05,0x02,0x00,0x00,0x00, // 0xF8 229 | 0x00,0x02,0x07,0x02,0x00,0x00, // 0xF9 230 | 0x00,0x00,0x02,0x00,0x00,0x00, // 0xFA 231 | 0x03,0x02,0x02,0x06,0x02,0x00, // 0xFB 232 | 0x07,0x05,0x05,0x00,0x00,0x00, // 0xFC 233 | 0x06,0x02,0x04,0x06,0x00,0x00, // 0xFD 234 | 0x00,0x00,0x06,0x06,0x00,0x00, // 0xFE 235 | 0x00,0x00,0x00,0x00,0x00,0x00 // 0xFF 236 | #endif 237 | }; 238 | #endif 239 | -------------------------------------------------------------------------------- /src/NeoPixel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * NeoPixel.h 3 | * 4 | * Implements extensions to Adafruit_NeoPixel functions 5 | * 6 | * Copyright (C) 2019-2025 Armin Joachimsmeyer 7 | * armin.joachimsmeyer@gmail.com 8 | * 9 | * This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns. 10 | * 11 | * NeoPatterns is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License as published by 13 | * the Free Software Foundation, either version 3 of the License, or 14 | * (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 19 | * See the GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | /* 27 | * Class inheritance diagram. We have virtual inheritance, since MatrixNeoPatterns needs only one member set of NeoPixel 28 | * 29 | * MatrixNeoPixelVU \ 30 | * ,o--> MatrixNeoPixel (virtual) \ 31 | * MatrixSnake --> MatrixNeoPatterns < o--> NeoPixel --> Adafruit_NeoPixel 32 | * `o--> NeoPatterns (virtual) / 33 | * 34 | */ 35 | 36 | #ifndef _NEOPATTERNS_NEOPIXEL_H 37 | #define _NEOPATTERNS_NEOPIXEL_H 38 | 39 | // To support various debug levels set in different sources 40 | #include "DebugLevel.h" 41 | 42 | // This does not work in Arduino IDE for "Generating function prototypes..." 43 | //#if ! __has_include("Adafruit_NeoPixel.h") 44 | //#error This NeoPixel library requires the "Adafruit NeoPixel" library. Please install it via the Arduino library manager. 45 | //#endif 46 | 47 | #include "Adafruit_NeoPixel.h" // Click here to get the library: http://librarymanager/All#Adafruit_NeoPixel 48 | #include "Colors.h" 49 | 50 | //#define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 51 | #if !defined(DO_NOT_SUPPORT_RGBW) 52 | // Support rgbw colors for pattern. 53 | // Deactivate this, if you do NOT need RGBW support and want to save program memory (max 300 bytes). 54 | #define _SUPPORT_RGBW // Introduced to avoid double negations below using #if ! defined(DO_NOT_SUPPORT_RGBW) 55 | #endif 56 | 57 | //#define DO_NOT_SUPPORT_BRIGHTNESS // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example. 58 | #if !defined(DO_NOT_SUPPORT_BRIGHTNESS) 59 | #define SUPPORT_BRIGHTNESS // Introduced to avoid double negations 60 | 61 | //#define DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS // If activated, disables writing of zero only if brightness or color is zero. Saves up to 144 bytes ... 62 | # if !defined(DO_NOT_SUPPORT_NO_ZERO_BRIGHTNESS) 63 | // // Each color is only set to zero, if brightness or input color is zero. Otherwise each color brightness is at least 1 e.g. 0x000100 64 | #define SUPPORT_NO_ZERO_BRIGHTNESS // Introduced to avoid double negations 65 | # endif 66 | #endif 67 | #define MAX_BRIGHTNESS 0xFF 68 | #define MAX_WHEEL_POSITION 0xFF 69 | 70 | #if defined(_SUPPORT_RGBW) 71 | uint8_t getWhitePart(color32_t color); 72 | uint8_t White(color32_t color) __attribute__ ((deprecated ("Renamed to getWhitePart()"))); // deprecated 73 | #endif 74 | uint8_t getRedPart(color32_t color); 75 | uint8_t getGreenPart(color32_t color); 76 | uint8_t getBluePart(color32_t color); 77 | 78 | uint8_t Red(color32_t color) __attribute__ ((deprecated ("Renamed to getRedPart()"))); // deprecated 79 | uint8_t Green(color32_t color) __attribute__ ((deprecated ("Renamed to getGreenPart()"))); // deprecated 80 | uint8_t Blue(color32_t color) __attribute__ ((deprecated ("Renamed to getBluePart()"))); // deprecated 81 | 82 | /* 83 | * SIZE = 6 + 22 from Adafruit_NeoPixel = 28 84 | */ 85 | class NeoPixel: public Adafruit_NeoPixel { 86 | public: 87 | NeoPixel(); 88 | NeoPixel(uint16_t aNumberOfPixels, uint8_t aPin, neoPixelType aTypeOfPixel); 89 | void AdafruitNeoPixelIinit(uint16_t aNumberOfPixels, uint16_t aPin, neoPixelType aTypeOfPixel); 90 | bool init(uint16_t aNumberOfPixels, uint8_t aPin, neoPixelType aTypeOfPixel); 91 | NeoPixel(NeoPixel *aUnderlyingNeoPixelObject, uint16_t aPixelOffset, uint16_t aNumberOfPixels, 92 | bool aEnableShowOfUnderlyingPixel = true); 93 | void init(NeoPixel *aUnderlyingNeoPixelObject, uint16_t aPixelOffset, uint16_t aNumberOfPixels, 94 | bool aEnableShowOfUnderlyingPixel = true); 95 | 96 | void printInfo(Print *aSerial); 97 | void printContent(Print *aSerial); 98 | void printConnectionInfo(Print *aSerial); 99 | void printPin(Print *aSerial); 100 | 101 | #if defined(ADC_UTILS_ARE_INCLUDED) 102 | uint16_t getAndAdjustActualNeopixelLenghtSimple(); 103 | #endif 104 | 105 | // To enable more than one pattern on the same strip 106 | void setPixelBuffer(uint8_t *aNewPixelBufferPointer); 107 | 108 | // To move the start index of a NeoPixel object 109 | void setPixelOffsetForPartialNeoPixel(uint16_t aPixelOffset); 110 | /* 111 | * Extensions to Adafruit_NeoPixel functions 112 | */ 113 | void begin(); 114 | void begin(uint8_t aBrightness, bool aEnableBrightnessNonZeroMode = false); 115 | void show(); 116 | // Version with error message 117 | bool begin(Print *aSerial); 118 | bool begin(Print *aSerial, uint8_t aBrightness, bool aEnableBrightnessNonZeroMode = false); 119 | 120 | void ColorSet(color32_t aColor) __attribute__ ((deprecated ("Renamed to setColor()"))); // deprecated; 121 | void setColor(color32_t aColor); 122 | color32_t getPixelColor(uint16_t aPixelIndex); 123 | uint8_t getBytesPerPixel(); 124 | neoPixelType getType(); 125 | uint16_t getPixelBufferSize(); 126 | uint16_t getNumberOfPixels(); 127 | void storePixelBuffer(uint8_t *aPixelBufferPointerDestination); 128 | void restorePixelBuffer(uint8_t *aPixelBufferPointerSource); 129 | 130 | // Functions to support PixelOffset 131 | void clear(void); 132 | void clearAndShow(void); 133 | void clearPixel(uint16_t aPixelIndex); 134 | void setPixelColor(uint16_t aPixelIndex, uint8_t aRed, uint8_t aGreen, uint8_t aBlue); 135 | #if defined(_SUPPORT_RGBW) 136 | void setPixelColor(uint16_t aPixelIndex, uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint8_t aWhite); 137 | #endif 138 | void setPixelColor(uint16_t aPixelIndex, color32_t aColor); 139 | 140 | void setBrightnessValue(uint8_t aBrightness)__attribute__ ((deprecated ("Renamed to setBrightness()"))); 141 | void setBrightness(uint8_t aBrightness); // Sets the brightness used by Neopixel drawing functions 142 | void setAdafruitBrightnessValue(uint8_t aBrightness); // Convenience function to set the brightness used by the (unused) Adafruit drawing functions 143 | void setBrightnessNonZeroMode(bool aEnableBrightnessNonZeroMode); 144 | 145 | void fillWithRainbow(uint8_t aRainbowWheelStartPos, bool aStartAtTop = false); 146 | void drawBar(uint16_t aBarLength, color32_t aColor, bool aDrawFromBottom = true); 147 | void fillRegion(color32_t aColor, uint16_t aRegionStartIndext, uint16_t aRegionLength); 148 | void copyRegion(uint16_t aSourcePixelIndex, uint16_t aTargetPixelIndex, uint16_t aLength, bool aDoReverseCopy); 149 | void drawBarFromColorArray(uint16_t aBarLength, color32_t *aColorArrayPtr, bool aDrawFromBottom = true); 150 | 151 | void addPixelColor(uint16_t aPixelIndex, uint8_t aRed, uint8_t aGreen, uint8_t aBlue); 152 | void addPixelColor(uint16_t aPixelIndex, color32_t aColor); 153 | // Static functions 154 | static uint32_t dimColor(color32_t aColor); 155 | void dimPixelColor(uint16_t aPixelIndex); 156 | static color32_t Wheel(uint8_t aWheelPos); 157 | static color32_t SevenColors(uint8_t aColorBits); 158 | static color32_t FourColors(uint8_t aColorBits); 159 | static uint8_t gamma5(uint8_t aLinearBrightnessValue); 160 | static uint8_t gamma5WithSpecialZero(uint8_t aLinearBrightnessValue); 161 | static color32_t convertLinearToGamma5Color(color32_t aLinearBrightnessColor); 162 | static color32_t dimColorWithGamma5(color32_t aLinearBrightnessColor, uint8_t aBrightness, bool doSpecialZero = false); 163 | 164 | // deprecated 165 | static uint8_t gamma32(uint8_t aLinearBrightnessValue) __attribute__ ((deprecated ("Renamed to gamma5()."))); 166 | static color32_t dimColorWithGamma32(color32_t aLinearBrightnessColor, uint8_t aBrightness, bool doSpecialZero = false) 167 | __attribute__ ((deprecated ("Renamed to dimColorWithGamma5()."))); 168 | 169 | void TestWS2812Resolution(); 170 | 171 | #if defined(_SUPPORT_RGBW) 172 | uint8_t BytesPerPixel; // can be 3 or 4 173 | #else 174 | #define BytesPerPixel 3 175 | #endif 176 | uint8_t PixelFlags; 177 | uint16_t PixelOffset; // The offset of the pattern on the underlying pixel buffer to enable partial patterns overlays 178 | NeoPixel *UnderlyingNeoPixelObject; // The underlying NeoPixel object for partial patterns overlays, otherwise the object itself 179 | uint8_t Brightness; // NeoPixel effective brightness instead of the Adafruit brightness, which is stored as effective brightness + 1 :-(. 180 | }; 181 | 182 | #define PIXEL_FLAG_IS_PARTIAL_NEOPIXEL 0x01 // enables partial patterns overlays and uses show() of UnderlyingNeoPixelObject 183 | #define PIXEL_FLAG_DISABLE_SHOW_OF_UNDERLYING_PIXEL_OBJECT 0x02 // use negative logic because evaluation is simpler then 184 | /* 185 | * Flag for NeoPattern. This disables the initial asynchronous show() for a new pattern, but enables show() if called by synchronous callback. 186 | * This behavior is required to avoid disturbing other libraries, which cannot handle the time when interrupt is disabled for show() e.g. the Servo library. 187 | * The asynchronous call is detected by checking if the current pattern is not PATTERN_NONE. 188 | */ 189 | #define PIXEL_FLAG_SHOW_ONLY_AT_UPDATE 0x04 190 | #define PIXEL_FLAG_USE_NON_ZERO_BRIGHTNESS 0x08 // Pixel is set to zero, only if brightness or input color is zero, otherwise it is clipped at e.g. 0x000100 191 | // Used for some demo handler 192 | #define PIXEL_FLAG_GEOMETRY_CIRCLE 0x80 // in contrast to bar 193 | 194 | extern const uint8_t GammaTable32[32] PROGMEM; 195 | 196 | // From FastLED random8.h https://github.com/FastLED/FastLED/blob/master/src/lib8tion/random8.h 197 | uint8_t random8(); 198 | uint8_t random8(uint8_t lim); 199 | uint8_t random8(uint8_t min, uint8_t lim); 200 | 201 | #endif /* _NEOPATTERNS_NEOPIXEL_H */ 202 | -------------------------------------------------------------------------------- /src/ADCUtils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ADCUtils.h 3 | * 4 | * Copyright (C) 2016-2022 Armin Joachimsmeyer 5 | * Email: armin.joachimsmeyer@gmail.com 6 | * 7 | * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. 8 | * 9 | * ArduinoUtils is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU General Public License as published by 11 | * the Free Software Foundation, either version 3 of the License, or 12 | * (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 17 | * See the GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | #ifndef _ADC_UTILS_H 25 | #define _ADC_UTILS_H 26 | 27 | #include 28 | 29 | #if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__)) 30 | #define ADC_UTILS_ARE_AVAILABLE 31 | 32 | // External Reference Current is 150 uA for 5 V and 100 uA for 3.5 V 33 | #define READING_FOR_AREF 1024L // Datasheet 24.2: The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB 34 | #define MAX_ADC_VALUE 1023L 35 | 36 | // PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz 37 | #define ADC_PRESCALE2 1 // 26 microseconds per ADC conversion at 1 MHz 38 | #define ADC_PRESCALE4 2 // 52 microseconds per ADC conversion at 1 MHz 39 | // PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 MHz Clock => 9,6 kHz 40 | #define ADC_PRESCALE8 3 // 104 microseconds per ADC conversion at 1 MHz 41 | #define ADC_PRESCALE16 4 // 13/208 microseconds per ADC conversion at 16/1 MHz - degradations in linearity at 16 MHz 42 | #define ADC_PRESCALE32 5 // 26/416 microseconds per ADC conversion at 16/1 MHz - very good linearity at 16 MHz 43 | #define ADC_PRESCALE64 6 // 52 microseconds per ADC conversion at 16 MHz 44 | #define ADC_PRESCALE128 7 // 104 microseconds per ADC conversion at 16 MHz --- Arduino default 45 | 46 | // definitions for 0.1 ms conversion time 47 | #if (F_CPU == 1000000) 48 | #define ADC_PRESCALE ADC_PRESCALE8 49 | #elif (F_CPU == 8000000) 50 | #define ADC_PRESCALE ADC_PRESCALE64 51 | #elif (F_CPU == 16000000) 52 | #define ADC_PRESCALE ADC_PRESCALE128 53 | #endif 54 | 55 | /* 56 | * Reference shift values are complicated for ATtinyX5 since we have the extra register bit REFS2 57 | * in ATTinyCore, this bit is handled programmatical and therefore the defines are different. 58 | * To keep my library small, I use the changed defines. 59 | * After including this file you can not call the ATTinyCore readAnalog functions reliable, if you specify references other than default! 60 | */ 61 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) 62 | // defines are for ADCUtils.cpp, they can be used WITHOUT bit reordering 63 | #undef DEFAULT 64 | #undef EXTERNAL 65 | #undef INTERNAL1V1 66 | #undef INTERNAL 67 | #undef INTERNAL2V56 68 | #undef INTERNAL2V56_EXTCAP 69 | 70 | #define DEFAULT 0 71 | #define EXTERNAL 4 72 | #define INTERNAL1V1 8 73 | #define INTERNAL INTERNAL1V1 74 | #define INTERNAL2V56 9 75 | #define INTERNAL2V56_EXTCAP 13 76 | 77 | #define SHIFT_VALUE_FOR_REFERENCE REFS2 78 | #define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1) | _BV(REFS2)) 79 | #define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3)) 80 | #else // AVR_ATtiny85 81 | 82 | #define SHIFT_VALUE_FOR_REFERENCE REFS0 83 | #define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1)) 84 | #define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3)) 85 | #endif 86 | 87 | // Temperature channel definitions - 1 LSB / 1 degree Celsius 88 | #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) 89 | #define ADC_TEMPERATURE_CHANNEL_MUX 15 90 | #define ADC_1_1_VOLT_CHANNEL_MUX 12 91 | #define ADC_GND_CHANNEL_MUX 13 92 | #define ADC_CHANNEL_MUX_MASK 0x0F 93 | 94 | #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) 95 | #define ADC_ISCR_CHANNEL_MUX 3 96 | #define ADC_TEMPERATURE_CHANNEL_MUX 11 97 | #define ADC_1_1_VOLT_CHANNEL_MUX 12 98 | #define ADC_GND_CHANNEL_MUX 14 99 | #define ADC_VCC_4TH_CHANNEL_MUX 13 100 | #define ADC_CHANNEL_MUX_MASK 0x1F 101 | 102 | #elif defined(__AVR_ATmega328P__) 103 | #define ADC_TEMPERATURE_CHANNEL_MUX 8 104 | #define ADC_1_1_VOLT_CHANNEL_MUX 14 105 | #define ADC_GND_CHANNEL_MUX 15 106 | #define ADC_CHANNEL_MUX_MASK 0x0F 107 | 108 | #elif defined(__AVR_ATmega644P__) 109 | #define ADC_TEMPERATURE_CHANNEL_MUX // not existent 110 | #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E 111 | #define ADC_GND_CHANNEL_MUX 0x1F 112 | #define ADC_CHANNEL_MUX_MASK 0x0F 113 | 114 | #elif defined(__AVR_ATmega32U4__) 115 | #define ADC_TEMPERATURE_CHANNEL_MUX 0x27 116 | #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E 117 | #define ADC_GND_CHANNEL_MUX 0x1F 118 | #define ADC_CHANNEL_MUX_MASK 0x3F 119 | 120 | #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) 121 | #define ADC_1_1_VOLT_CHANNEL_MUX 0x1E 122 | #define ADC_GND_CHANNEL_MUX 0x1F 123 | #define ADC_CHANNEL_MUX_MASK 0x1F 124 | 125 | #define INTERNAL INTERNAL1V1 126 | 127 | #else 128 | #error "No temperature channel definitions specified for this AVR CPU" 129 | #endif 130 | 131 | /* 132 | * Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion) 133 | * 134 | * Default values are suitable for Li-ion batteries. 135 | * We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC. 136 | * But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt. 137 | */ 138 | #if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) 139 | #define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3400 // Do not stress your battery and we require some power for standby 140 | #endif 141 | #if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) 142 | #define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 3000 // Many Li-ions are specified down to 3.0 volt 143 | #endif 144 | 145 | #if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) 146 | #define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 147 | #endif 148 | #if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) 149 | #define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 150 | #endif 151 | #if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT) 152 | #define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5250 // + 5 % operation voltage 153 | #endif 154 | #if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT) 155 | #define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT 5500 // +10 %. Max recommended operation voltage 156 | #endif 157 | #if !defined(VCC_CHECK_PERIOD_MILLIS) 158 | #define VCC_CHECK_PERIOD_MILLIS 10000L // 10 seconds period of VCC checks 159 | #endif 160 | #if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) 161 | #define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP 6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT 162 | #endif 163 | 164 | #if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT) 165 | #define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT 4300 // Assume USB powered above this voltage 166 | #endif 167 | 168 | #if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) 169 | #define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT 4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN. 170 | // In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply 171 | #endif 172 | 173 | extern long sLastVCCCheckMillis; 174 | extern uint8_t sVCCTooLowCounter; 175 | 176 | uint16_t readADCChannel(); 177 | uint16_t readADCChannel(uint8_t aADCChannelNumber); 178 | uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); 179 | uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber); 180 | uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference); 181 | uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference); 182 | uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent); 183 | void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference); 184 | uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); 185 | uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples); 186 | uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples); 187 | uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale, 188 | uint16_t aNumberOfSamples); 189 | uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples); 190 | uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire); 191 | uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay, 192 | uint8_t aAllowedDifference, uint8_t aMaxRetries); 193 | 194 | void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber); 195 | void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber); 196 | uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference); 197 | 198 | /* 199 | * readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage 200 | */ 201 | float getVCCVoltageSimple(void); 202 | void readVCCVoltageSimple(void); 203 | void readVCCVoltageMillivoltSimple(void); 204 | void readVCCVoltage(void); 205 | uint16_t getVCCVoltageMillivolt(void); 206 | void readVCCVoltageMillivolt(void); 207 | uint16_t getVCCVoltageReadingFor1_1VoltReference(void); 208 | uint16_t printVCCVoltageMillivolt(Print *aSerial); 209 | void readAndPrintVCCVoltageMillivolt(Print *aSerial); 210 | 211 | uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement); 212 | uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement); 213 | uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement); 214 | float getCPUTemperatureSimple(void); 215 | float getCPUTemperature(void); 216 | float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated 217 | 218 | bool isVCCUSBPowered(); 219 | bool isVCCUSBPowered(Print *aSerial); 220 | bool isVCCUndervoltageMultipleTimes(); 221 | void resetCounterForVCCUndervoltageMultipleTimes(); 222 | bool isVCCUndervoltage(); 223 | bool isVCCEmergencyUndervoltage(); 224 | bool isVCCOvervoltage(); 225 | bool isVCCOvervoltageSimple(); // Version using readVCCVoltageMillivoltSimple() 226 | bool isVCCTooHighSimple(); // Version not using readVCCVoltageMillivoltSimple() 227 | 228 | #endif // defined(__AVR__) ... 229 | 230 | /* 231 | * Variables and functions defined as dummies to allow for seamless compiling on non AVR platforms 232 | */ 233 | extern float sVCCVoltage; 234 | extern uint16_t sVCCVoltageMillivolt; 235 | 236 | uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent); 237 | 238 | uint16_t getVCCVoltageMillivoltSimple(void); 239 | float getVCCVoltage(void); 240 | float getCPUTemperature(void); 241 | 242 | #endif // _ADC_UTILS_H 243 | -------------------------------------------------------------------------------- /examples/OpenLedRace/LiquidCrystal_I2C.hpp: -------------------------------------------------------------------------------- 1 | // LiquidCrystal_I2C.hpp 2 | // Based on the work by DFRobot 3 | /* 4 | * Extensions made by AJ 2023 5 | * Removed Arduino 0.x support 6 | * Added SoftI2CMaste support, which drastically reduces program size. 7 | * Added OLED stuff 8 | * Added createChar() with PROGMEM input 9 | * Added fast timing 10 | */ 11 | #ifndef _LIQUID_CRYSTAL_I2C_HPP 12 | #define _LIQUID_CRYSTAL_I2C_HPP 13 | 14 | #include "Arduino.h" 15 | 16 | #if defined(__AVR__) && !defined(USE_SOFT_I2C_MASTER) && __has_include("SoftI2CMasterConfig.h") 17 | #define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.hpp" 18 | #endif 19 | 20 | #include "LiquidCrystal_I2C.h" 21 | #include 22 | 23 | inline size_t LiquidCrystal_I2C::write(uint8_t value) { 24 | send(value, Rs); 25 | return 1; 26 | } 27 | 28 | #if defined(USE_SOFT_I2C_MASTER) 29 | //#define USE_SOFT_I2C_MASTER_H_AS_PLAIN_INCLUDE 30 | #include "SoftI2CMasterConfig.h" // Include configuration for sources 31 | #include "SoftI2CMaster.h" // include sources 32 | #elif defined(USE_SOFT_WIRE) 33 | #define USE_SOFTWIRE_H_AS_PLAIN_INCLUDE 34 | #include "SoftWire.h" 35 | #endif 36 | 37 | #if defined(__AVR__) 38 | /* 39 | * The datasheet says: a command need > 37us to settle. Enable pulse must be > 450ns. 40 | * Use no delay for enable pulse after each command, 41 | * because the overhead of this library seems to be using the 37 us and 450 ns. 42 | * At least it works perfectly for all my LCD's connected to Uno, Nano etc. 43 | * and it saves a lot of time in realtime applications using LCD as display, 44 | * like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter 45 | */ 46 | #define USE_FAST_TIMING 47 | #endif 48 | 49 | // When the display powers up, it is configured as follows: 50 | // 51 | // 1. Display clear 52 | // 2. Function set: 53 | // DL = 1; 8-bit interface data 54 | // N = 0; 1-line display 55 | // F = 0; 5x8 dot character font 56 | // 3. Display on/off control: 57 | // D = 0; Display off 58 | // C = 0; Cursor off 59 | // B = 0; Blinking off 60 | // 4. Entry mode set: 61 | // I/D = 1; Increment by 1 62 | // S = 0; No shift 63 | // 64 | // Note, however, that resetting the Arduino doesn't reset the LCD, so we 65 | // can't assume that its in that state when a sketch starts (and the 66 | // LiquidCrystal constructor is called). 67 | 68 | LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows) { 69 | _Addr = lcd_Addr; 70 | _cols = lcd_cols; 71 | _rows = lcd_rows; 72 | _backlightval = LCD_NOBACKLIGHT; 73 | _oled = false; 74 | } 75 | 76 | void LiquidCrystal_I2C::oled_init() { 77 | _oled = true; 78 | init_priv(); 79 | } 80 | 81 | void LiquidCrystal_I2C::init() { 82 | init_priv(); 83 | } 84 | 85 | void LiquidCrystal_I2C::init_priv() { 86 | #if defined(USE_SOFT_I2C_MASTER) 87 | i2c_init(); 88 | #else 89 | Wire.begin(); 90 | #endif 91 | _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS; 92 | begin(_cols, _rows); 93 | } 94 | 95 | void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t lines, uint8_t dotsize) { 96 | if (lines > 1) { 97 | _displayfunction |= LCD_2LINE; 98 | } 99 | _numlines = lines; 100 | 101 | // for some 1 line displays you can select a 10 pixel high font 102 | if ((dotsize != 0) && (lines == 1)) { 103 | _displayfunction |= LCD_5x10DOTS; 104 | } 105 | 106 | // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION! 107 | // according to datasheet, we need at least 40ms after power rises above 2.7V 108 | // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50 109 | delay(50); 110 | 111 | // Now we pull both RS and R/W low to begin commands 112 | expanderWrite(_backlightval); // reset expander and turn backlight off (Bit 8 =1) 113 | delay(1000); 114 | 115 | //put the LCD into 4 bit mode 116 | // this is according to the hitachi HD44780 datasheet 117 | // figure 24, pg 46 118 | 119 | // we start in 8bit mode, try to set 4 bit mode 120 | write4bits(0x03 << 4); 121 | delayMicroseconds(4500); // wait min 4.1ms 122 | 123 | // second try 124 | write4bits(0x03 << 4); 125 | delayMicroseconds(4500); // wait min 4.1ms 126 | 127 | // third go! 128 | write4bits(0x03 << 4); 129 | delayMicroseconds(150); 130 | 131 | // finally, set to 4-bit interface 132 | write4bits(0x02 << 4); 133 | 134 | // set # lines, font size, etc. 135 | command(LCD_FUNCTIONSET | _displayfunction); 136 | 137 | // turn the display on with no cursor or blinking default 138 | _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF; 139 | display(); 140 | 141 | // clear it off 142 | clear(); 143 | 144 | // Initialize to default text direction (for roman languages) 145 | _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT; 146 | 147 | // set the entry mode 148 | command(LCD_ENTRYMODESET | _displaymode); 149 | 150 | home(); 151 | 152 | } 153 | 154 | /********** high level commands, for the user! */ 155 | void LiquidCrystal_I2C::clear() { 156 | command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero 157 | #if defined(USE_FAST_TIMING) 158 | delayMicroseconds(1500); // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK 159 | #else 160 | delayMicroseconds(2000); // this command takes a long time! 161 | #endif 162 | if (_oled) 163 | setCursor(0, 0); 164 | } 165 | 166 | void LiquidCrystal_I2C::home() { 167 | command(LCD_RETURNHOME); // set cursor position to zero 168 | delayMicroseconds(2000); // this command takes a long time! 169 | } 170 | 171 | void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) { 172 | int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 }; 173 | if (row > _numlines) { 174 | row = _numlines - 1; // we count rows starting w/0 175 | } 176 | command(LCD_SETDDRAMADDR | (col + row_offsets[row])); 177 | } 178 | 179 | // Turn the display on/off (quickly) 180 | void LiquidCrystal_I2C::noDisplay() { 181 | _displaycontrol &= ~LCD_DISPLAYON; 182 | command(LCD_DISPLAYCONTROL | _displaycontrol); 183 | } 184 | void LiquidCrystal_I2C::display() { 185 | _displaycontrol |= LCD_DISPLAYON; 186 | command(LCD_DISPLAYCONTROL | _displaycontrol); 187 | } 188 | 189 | // Turns the underline cursor on/off 190 | void LiquidCrystal_I2C::noCursor() { 191 | _displaycontrol &= ~LCD_CURSORON; 192 | command(LCD_DISPLAYCONTROL | _displaycontrol); 193 | } 194 | void LiquidCrystal_I2C::cursor() { 195 | _displaycontrol |= LCD_CURSORON; 196 | command(LCD_DISPLAYCONTROL | _displaycontrol); 197 | } 198 | 199 | // Turn on and off the blinking cursor 200 | void LiquidCrystal_I2C::noBlink() { 201 | _displaycontrol &= ~LCD_BLINKON; 202 | command(LCD_DISPLAYCONTROL | _displaycontrol); 203 | } 204 | void LiquidCrystal_I2C::blink() { 205 | _displaycontrol |= LCD_BLINKON; 206 | command(LCD_DISPLAYCONTROL | _displaycontrol); 207 | } 208 | 209 | // These commands scroll the display without changing the RAM 210 | void LiquidCrystal_I2C::scrollDisplayLeft(void) { 211 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT); 212 | } 213 | void LiquidCrystal_I2C::scrollDisplayRight(void) { 214 | command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT); 215 | } 216 | 217 | // This is for text that flows Left to Right 218 | void LiquidCrystal_I2C::leftToRight(void) { 219 | _displaymode |= LCD_ENTRYLEFT; 220 | command(LCD_ENTRYMODESET | _displaymode); 221 | } 222 | 223 | // This is for text that flows Right to Left 224 | void LiquidCrystal_I2C::rightToLeft(void) { 225 | _displaymode &= ~LCD_ENTRYLEFT; 226 | command(LCD_ENTRYMODESET | _displaymode); 227 | } 228 | 229 | // This will 'right justify' text from the cursor 230 | void LiquidCrystal_I2C::autoscroll(void) { 231 | _displaymode |= LCD_ENTRYSHIFTINCREMENT; 232 | command(LCD_ENTRYMODESET | _displaymode); 233 | } 234 | 235 | // This will 'left justify' text from the cursor 236 | void LiquidCrystal_I2C::noAutoscroll(void) { 237 | _displaymode &= ~LCD_ENTRYSHIFTINCREMENT; 238 | command(LCD_ENTRYMODESET | _displaymode); 239 | } 240 | 241 | // Allows us to fill the first 8 CGRAM locations 242 | // with custom characters 243 | void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) { 244 | location &= 0x7; // we only have 8 locations 0-7 245 | command(LCD_SETCGRAMADDR | (location << 3)); 246 | for (int i = 0; i < 8; i++) { 247 | write(charmap[i]); 248 | } 249 | } 250 | 251 | //createChar with PROGMEM input 252 | void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) { 253 | location &= 0x7; // we only have 8 locations 0-7 254 | command(LCD_SETCGRAMADDR | (location << 3)); 255 | for (int i = 0; i < 8; i++) { 256 | write(pgm_read_byte_near(charmap++)); 257 | } 258 | } 259 | 260 | // Turn the (optional) backlight off/on 261 | void LiquidCrystal_I2C::noBacklight(void) { 262 | _backlightval = LCD_NOBACKLIGHT; 263 | expanderWrite(0); 264 | } 265 | 266 | void LiquidCrystal_I2C::backlight(void) { 267 | _backlightval = LCD_BACKLIGHT; 268 | expanderWrite(0); 269 | } 270 | 271 | /*********** mid level commands, for sending data/cmds */ 272 | 273 | inline void LiquidCrystal_I2C::command(uint8_t value) { 274 | send(value, 0); 275 | } 276 | 277 | /************ low level data pushing commands **********/ 278 | 279 | // write either command or data 280 | void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) { 281 | uint8_t highnib = value & 0xf0; 282 | uint8_t lownib = (value << 4) & 0xf0; 283 | write4bits((highnib) | mode); 284 | write4bits((lownib) | mode); 285 | } 286 | 287 | void LiquidCrystal_I2C::write4bits(uint8_t value) { 288 | expanderWrite(value); 289 | pulseEnable(value); 290 | } 291 | 292 | void LiquidCrystal_I2C::expanderWrite(uint8_t _data) { 293 | #if defined(USE_SOFT_I2C_MASTER) 294 | i2c_write_byte(_Addr << 1, _data | _backlightval); 295 | #else 296 | Wire.beginTransmission(_Addr); 297 | Wire.write((int )(_data) | _backlightval); 298 | Wire.endTransmission(); 299 | #endif 300 | } 301 | 302 | void LiquidCrystal_I2C::pulseEnable(uint8_t _data) { 303 | expanderWrite(_data | En); // En high 304 | #if !defined(USE_FAST_TIMING) 305 | delayMicroseconds(1); // enable pulse must be > 450ns // AJ 20.9.23 not required for my LCD's 306 | #endif 307 | expanderWrite(_data & ~En); // En low 308 | #if !defined(USE_FAST_TIMING) 309 | delayMicroseconds(50); // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's 310 | #endif 311 | } 312 | 313 | // Alias functions 314 | 315 | void LiquidCrystal_I2C::cursor_on() { 316 | cursor(); 317 | } 318 | 319 | void LiquidCrystal_I2C::cursor_off() { 320 | noCursor(); 321 | } 322 | 323 | void LiquidCrystal_I2C::blink_on() { 324 | blink(); 325 | } 326 | 327 | void LiquidCrystal_I2C::blink_off() { 328 | noBlink(); 329 | } 330 | 331 | void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) { 332 | createChar(char_num, rows); 333 | } 334 | 335 | void LiquidCrystal_I2C::setBacklight(uint8_t new_val) { 336 | if (new_val) { 337 | backlight(); // turn backlight on 338 | } else { 339 | noBacklight(); // turn backlight off 340 | } 341 | } 342 | 343 | void LiquidCrystal_I2C::printstr(const char c[]) { 344 | //This function is not identical to the function used for "real" I2C displays 345 | //it's here so the user sketch doesn't have to be changed 346 | print(c); 347 | } 348 | 349 | // unsupported API functions 350 | #pragma GCC diagnostic push 351 | #pragma GCC diagnostic ignored "-Wunused-parameter" 352 | void LiquidCrystal_I2C::off() { 353 | } 354 | void LiquidCrystal_I2C::on() { 355 | } 356 | void LiquidCrystal_I2C::setDelay(int cmdDelay, int charDelay) { 357 | } 358 | uint8_t LiquidCrystal_I2C::status() { 359 | return 0; 360 | } 361 | uint8_t LiquidCrystal_I2C::keypad() { 362 | return 0; 363 | } 364 | uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype) { 365 | return 0; 366 | } 367 | void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end) { 368 | } 369 | void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end) { 370 | } 371 | void LiquidCrystal_I2C::setContrast(uint8_t new_val) { 372 | } 373 | #pragma GCC diagnostic pop 374 | 375 | #endif // _LIQUID_CRYSTAL_I2C_HPP 376 | --------------------------------------------------------------------------------