Skip to content

Commit bcff9d6

Browse files
committed
Bumped version to 3.3.0. - New pattern TWINKLE. New function copyRegion(). Copied and used random8() from FastLED.
1 parent 0bd2f0f commit bcff9d6

16 files changed

+948
-808
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Available as [Arduino library "NeoPatterns"](https://www.arduinolibraries.info/l
5252
- SCANNER_EXTENDED
5353
- STRIPES
5454
- FLASH
55+
- TWINKLE
5556
- PROCESS_SELECTIVE
5657
- HEARTBEAT
5758
- BOUNCING_BALL
@@ -90,6 +91,7 @@ the included **NeoPixel library is an extensions of the Adafruit NeoPixel librar
9091
- convertLinearToGamma5Color(aLinearBrightnessValue) - Returns the gamma corrected color.
9192
- dimColorWithGamma5(aLinearBrightnessValue, aBrightness) - like before but with additional brightness.
9293
- Wheel() - Returns colors from a color wheel starting ar red.
94+
- copyRegion() - Copy a mutiple pixels to another part of the strip. Optional do a reverse copy.
9395
- printConnectionInfo().<br/>
9496
as well as functions for getting pixel info:
9597
- getRedPart(color32_t color).
@@ -221,6 +223,12 @@ It also shows, how to dynamically **determine the length of the attached strip**
221223
<br/>
222224

223225
# Revision History
226+
### Version 3.3.0
227+
- New pattern `TWINKLE`.
228+
- New functions `setCompensatedInterval()` and `copyRegion()`.
229+
- Member variable `Interval` is now signed.
230+
- Copied and used `random8()` from [FastLED](https://github.com/FastLED/FastLED/blob/master/src/lib8tion/random8.h).
231+
224232
### Version 3.2.0
225233
- Added functions `getActualNeopixelLenghtSimple()`, `clearAndShow()`, `setMatrixPixelColorAndShow()` and `testMapping()`.
226234
- Improved `SNOW` pattern.

examples/AllPatternsOnMultiDevices/AllPatternsOnMultiDevices.ino

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* You need to install "Adafruit NeoPixel" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" -> use "neoPixel" as filter string
77
*
8-
* Copyright (C) 2018-2022 Armin Joachimsmeyer
8+
* Copyright (C) 2018-2025 Armin Joachimsmeyer
99
1010
*
1111
* This file is part of NeoPatterns https://github.com/ArminJo/NeoPatterns.

examples/MatrixPatternsTest/AVRUtils.cpp

+22-19
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,28 @@
3737
* Returns actual start of available / free heap
3838
* Usage for print:
3939
Serial.print(F("AvailableHeapStart=0x"));
40-
Serial.println((uint16_t) getAvailableHeapStart(), HEX);
40+
Serial.println((uint16_t) getStartOfAvailableHeap(), HEX);
4141
*/
42-
uint8_t* getAvailableHeapStart(void) {
42+
43+
uint8_t* getStartOfAvailableHeap(void) {
4344
if (__brkval == 0) {
4445
// __brkval is 0 if no malloc() has happened before
4546
// __brkval = __malloc_heap_start;
4647
__brkval = &__heap_start;
4748
}
4849
return (uint8_t*) __brkval;
4950
}
50-
void printAvailableHeapStart(Print *aSerial) {
51+
52+
void printStartOfAvailableHeap(Print *aSerial) {
5153
aSerial->print(F("Heap start="));
52-
aSerial->println((uint16_t) getAvailableHeapStart());
54+
aSerial->println((uint16_t) getStartOfAvailableHeap());
5355
}
5456

5557
/*
5658
* Initialize RAM between current stack and actual heap start (__brkval) with pattern 0x5A
5759
*/
5860
void initStackFreeMeasurement() {
59-
uint8_t *tHeapPtr = getAvailableHeapStart(); // This sets __brkval
61+
uint8_t *tHeapPtr = getStartOfAvailableHeap(); // This sets __brkval
6062

6163
// Fill / paint stack
6264
do {
@@ -79,7 +81,7 @@ int16_t getStackMaxUsedAndUnusedSizes(uint16_t *aStackUnusedSizePointer) {
7981
* Search for first touched value from end of current heap.
8082
*/
8183
uint16_t tStackUnused = 0;
82-
uint8_t *tHeapPtr = getAvailableHeapStart(); // __brkval
84+
uint8_t *tHeapPtr = getStartOfAvailableHeap(); // __brkval
8385
while (*tHeapPtr == HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr <= (uint8_t*) SP) {
8486
tHeapPtr++;
8587
tStackUnused++;
@@ -107,14 +109,14 @@ void printStackMaxUsedAndUnusedSizes(Print *aSerial) {
107109
aSerial->print(F(", unused="));
108110
aSerial->print(tStackUnusedBytes);
109111
aSerial->print(F(" of current total "));
110-
aSerial->println((RAMEND + 1) - (uint16_t) getAvailableHeapStart());
112+
aSerial->println((RAMEND + 1) - (uint16_t) getStartOfAvailableHeap());
111113
}
112114

113115
/*
114116
* Search upwards the first two HEAP_STACK_UNTOUCHED_VALUE values after current begin of heap
115117
*/
116118
uint16_t getHeapMaxUsedSize() {
117-
uint8_t *tHeapPtr = getAvailableHeapStart();
119+
uint8_t *tHeapPtr = getStartOfAvailableHeap();
118120
while (*tHeapPtr != HEAP_STACK_UNTOUCHED_VALUE && *(tHeapPtr + 1) != HEAP_STACK_UNTOUCHED_VALUE && tHeapPtr <= (uint8_t*) SP) {
119121
tHeapPtr++;
120122
}
@@ -150,7 +152,7 @@ bool printStackMaxUsedAndUnusedSizesIfChanged(Print *aSerial) {
150152
* Value computed depends on current stackpointer!
151153
*/
152154
uint16_t getCurrentAvailableStackSize(void) {
153-
uint16_t tAvailableHeapStart = (uint16_t) getAvailableHeapStart(); // __brkval
155+
uint16_t tAvailableHeapStart = (uint16_t) getStartOfAvailableHeap(); // __brkval
154156
if (tAvailableHeapStart >= SP) {
155157
return 0;
156158
}
@@ -183,7 +185,7 @@ uint16_t getTheoreticalMaximumAvailableHeapSize(void) {
183185
if (RAMEND <= __malloc_margin) {
184186
return 0;
185187
}
186-
return RAMEND - __malloc_margin; // (128)
188+
return (RAMEND - RAMSTART) -__malloc_margin; // (128)
187189
}
188190

189191
/*
@@ -194,7 +196,6 @@ void printCurrentAvailableHeapSize(Print *aSerial) {
194196
aSerial->println(getCurrentAvailableHeapSize());
195197
}
196198

197-
198199
/*
199200
* Simple and short implementation, does not work before initStackFreeMeasurement() or first malloc()
200201
* The STACK required for this function is 4 bytes, so available numbers are 4 less than for caller.
@@ -205,7 +206,7 @@ void printCurrentAvailableHeapSizeSimple(Print *aSerial) {
205206
}
206207

207208
// This define is in AVRUtils.h
208-
// #define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN))
209+
//#define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - HEURISTIC_ADDITIONAL_MALLOC_MARGIN - ((uint16_t) __malloc_margin))
209210

210211
void printBaseRAMData(Print *aSerial) {
211212
// __malloc_heap_end seems to be 0
@@ -245,7 +246,7 @@ void printBaseRAMData(Print *aSerial) {
245246

246247
/*
247248
* RAM starts with Data, i.e. variables initialized with values != 0,
248-
* followed by BSS, i.e. uninitalized variables (which are initialized with 0)
249+
* followed by BSS, i.e. uninitialized variables (which are initialized with 0)
249250
* and variables not initialized by using attribute "__attribute__((section(".noinit")))".
250251
* It ends with the heap and the stack.
251252
*
@@ -264,14 +265,14 @@ void printRAMInfo(Print *aSerial) {
264265
aSerial->print((uint16_t) &__heap_start - RAMSTART);
265266

266267
aSerial->print(F(". Heap: used="));
267-
aSerial->print((uint16_t) getAvailableHeapStart() - (uint16_t) &__heap_start);
268+
aSerial->print((uint16_t) getStartOfAvailableHeap() - (uint16_t) &__heap_start);
268269
aSerial->print(F(", max written=")); // if Stack uses total heap, we see the stack size here :-(
269270
aSerial->print(getHeapMaxUsedSize());
270271
aSerial->print(F(", max available="));
271-
aSerial->print(RAMEND - (uint16_t) __malloc_margin);
272+
aSerial->print(RAMEND - (uint16_t) getStartOfAvailableHeap() + 1 - (uint16_t) __malloc_margin);
272273

273274
aSerial->print(F(". Stack: available="));
274-
aSerial->print(SP - (uint16_t) getAvailableHeapStart() + 1);
275+
aSerial->print(SP - (uint16_t) getStartOfAvailableHeap() + 1);
275276
aSerial->print(F(", used="));
276277
aSerial->print(RAMEND - SP);
277278
uint16_t tStackUnusedBytes;
@@ -280,7 +281,7 @@ void printRAMInfo(Print *aSerial) {
280281
aSerial->print(F(", unused="));
281282
aSerial->print(tStackUnusedBytes);
282283
aSerial->print(F(" of current total "));
283-
aSerial->print((RAMEND + 1) - (uint16_t) getAvailableHeapStart()); // getAvailableHeapStart()
284+
aSerial->print((RAMEND + 1) - (uint16_t) getStartOfAvailableHeap()); // getStartOfAvailableHeap()
284285

285286
aSerial->println();
286287
}
@@ -302,7 +303,7 @@ bool isAddressInRAM(void *aAddressToCheck) {
302303
}
303304

304305
bool isAddressBelowAvailableHeapStart(void *aAddressToCheck) {
305-
return (aAddressToCheck < getAvailableHeapStart());
306+
return (aAddressToCheck < getStartOfAvailableHeap());
306307
}
307308

308309
/*
@@ -315,8 +316,10 @@ void testCallocSizesAndPrint(Print *aSerial) {
315316
while (true) {
316317
aSerial->print(F("SP=0x"));
317318
aSerial->print(SP, HEX);
319+
aSerial->print(F(" available="));
320+
aSerial->print(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin)- HEURISTIC_ADDITIONAL_MALLOC_MARGIN);
318321
aSerial->print(F(" max available="));
319-
aSerial->print(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin));
322+
aSerial->print(RAMEND - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin));
320323
uint8_t *tMallocPtr = (uint8_t*) calloc(tMallocSize, 1);
321324

322325
aSerial->print(F(" -> calloc("));

examples/MatrixPatternsTest/AVRUtils.h

+11-4
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ extern void *__flp; //
4444
extern char __heap_start; // = __bss_end, the linker address of heap start
4545
#define DEFAULT_MALLOC_MARGIN 128
4646

47-
//#define HEURISTIC_ADDITIONAL_MALLOC_MARGIN 14 // No malloc() possible if size is lower than (__malloc_margin + HEURISTIC_ADDITIONAL_MALLOC_MARGIN)
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
4852

4953
/*
5054
* storage for millis value to enable compensation for interrupt disable at signal acquisition etc.
@@ -71,15 +75,18 @@ void sleepWithWatchdog(uint8_t aWatchdogPrescaler, bool aAdjustMillis = false);
7175

7276
#include <Print.h>
7377

74-
uint8_t* getAvailableHeapStart();
75-
void printAvailableHeapStart(Print *aSerial);
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);
7682
uint16_t getCurrentAvailableStackSize(void);
7783
void printCurrentAvailableStackSize(Print *aSerial);
7884
uint16_t getCurrentAvailableHeapSize(void);
7985
uint16_t getTheoreticalMaximumAvailableHeapSize(void);
8086
void printCurrentAvailableHeapSize(Print *aSerial);
8187
void printCurrentAvailableHeapSizeSimple(Print *aSerial);
82-
#define PRINT_AVAILABLE_HEAP Serial.print(F("available="));Serial.println(SP - (uint16_t) __brkval + 1 - ((uint16_t) __malloc_margin))
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))
8390

8491
#define HEAP_STACK_UNTOUCHED_VALUE 0x5A
8592
void initStackFreeMeasurement();

examples/MatrixPatternsTest/MatrixPatternsTest.ino

+25-11
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#endif
3838
//#include "HexDump.hpp"
3939

40-
4140
#define INFO
4241

4342
#define DO_NOT_SUPPORT_RGBW // saves up to 428 bytes additional program memory for the AllPatternsOnMultiDevices() example.
@@ -46,6 +45,7 @@
4645

4746
#define ENABLE_MATRIX_PATTERN_FIRE
4847
#define ENABLE_MATRIX_PATTERN_SNOW
48+
#define ENABLE_PATTERN_TWINKLE
4949
#define ENABLE_PATTERNS_FOR_SNAKE_AUTORUN
5050
#include <MatrixSnake.hpp>
5151

@@ -97,8 +97,9 @@ bool delayAndCheckMode(uint16_t aMilliseconds);
9797
#define MODE_SNOW 0
9898
#define MODE_SNAKE 1
9999
#define MODE_FIRE 2
100-
#define MODE_ALL_COLORS 3
101-
#define MODE_MAX 3
100+
#define MODE_TWINKLE 3
101+
#define MODE_ALL_COLORS 4
102+
#define MODE_MAX 4
102103
#define MODE_NO_MODE 255 // in case of error
103104
uint8_t sCurrentMode;
104105
volatile bool sButtonJustPressed = false;
@@ -272,13 +273,20 @@ void loop() {
272273
if (sCurrentMode == MODE_SNOW) {
273274
NeoPixelMatrix.update(tBrightness);
274275
if (!sDemoModeEnabled) {
275-
NeoPixelMatrix.TotalStepCounter = 3; // to enable fast ending, if demo mode is enabled again
276+
// set to constant value to allow endless running
277+
NeoPixelMatrix.TotalStepCounter = 3; // 3 to enable fast ending, if demo mode is enabled again
278+
}
279+
280+
} else if (sCurrentMode == MODE_TWINKLE) {
281+
NeoPixelMatrix.update(tBrightness);
282+
if (!sDemoModeEnabled) {
283+
NeoPixelMatrix.TotalStepCounter = 3; // 3 to enable fast ending, if demo mode is enabled again
276284
}
277285

278286
} else if (sCurrentMode == MODE_SNAKE) {
279287
NeoPixelMatrix.update(tBrightness);
280288
if (!sDemoModeEnabled) {
281-
NeoPixelMatrix.Repetitions = 1; // to enable fast ending, if demo mode is enabled again
289+
NeoPixelMatrix.Repetitions = 1; // 1 to enable fast ending, if demo mode is enabled again
282290
}
283291

284292
} else if (sCurrentMode == MODE_ALL_COLORS) {
@@ -359,13 +367,14 @@ bool startPattern(uint8_t aNewMode) {
359367
if (aNewMode == MODE_SNOW) {
360368
return NeoPixelMatrix.Snow(1000, 20);
361369

370+
} else if (aNewMode == MODE_TWINKLE) {
371+
NeoPixelMatrix.Twinkle(COLOR32_SPECIAL, NeoPixelMatrix.getNumberOfPixels() / 4, 50, 60);
372+
return true;
373+
362374
} else if (aNewMode == MODE_SNAKE) {
363375
return initSnakeAutorun(&NeoPixelMatrix, 200, COLOR32_BLUE, 2);
364376

365377
} else if (aNewMode == MODE_FIRE) {
366-
#if defined(USE_16_X_16_MATRIX)
367-
set__malloc_margin(120); // 2 bytes stack are unused then :-)
368-
#endif
369378
return NeoPixelMatrix.Fire(800, 30);
370379
}
371380
return true;
@@ -406,7 +415,6 @@ void switchMode() {
406415
* Handler for automatically playing all patterns
407416
*/
408417
void DemoModeHandler(NeoPatterns *aLedsPtr) {
409-
(void) aLedsPtr;
410418

411419
Serial.println();
412420
Serial.print(F("Old mode="));
@@ -421,8 +429,12 @@ void DemoModeHandler(NeoPatterns *aLedsPtr) {
421429
* Start new pattern
422430
*/
423431
if (!startPattern(sCurrentMode)) {
424-
Serial.println(F("Not enough heap available"));
425-
sCurrentMode = MODE_NO_MODE;
432+
Serial.print(F("Not enough heap available for new mode "));
433+
printlnMode(sCurrentMode);
434+
#if defined(__AVR__)
435+
printRAMInfo(&Serial);
436+
#endif
437+
DemoModeHandler(aLedsPtr); // Try next pattern
426438
} else {
427439
Serial.print(F("New mode="));
428440
printlnMode(sCurrentMode);
@@ -438,6 +450,8 @@ void printlnMode(uint8_t aMode) {
438450
Serial.println(F("Snow"));
439451
} else if (aMode == MODE_SNAKE) {
440452
Serial.println(F("Snake"));
453+
} else if (aMode == MODE_TWINKLE) {
454+
Serial.println(F("Twinkle"));
441455
} else if (aMode == MODE_FIRE) {
442456
Serial.println(F("Fire"));
443457
} else if (aMode == MODE_ALL_COLORS) {

library.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "NeoPatterns",
3-
"version": "3.2.0",
3+
"version": "3.3.0",
44
"description": "Patterns for NeoPixel strips and matrixes including the patterns of the NeoPattern example by Adafruit.",
55
"keywords": "NeoPixel, adafruit",
66
"homepage": "https://github.com/ArminJo/NeoPatterns",

library.properties

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=NeoPatterns
2-
version=3.2.0
2+
version=3.3.0
33
author=Armin Joachimsmeyer
44
maintainer=Armin Joachimsmeyer <[email protected]>
55
sentence=Patterns for NeoPixel strips and matrixes including the patterns of the NeoPattern example by Adafruit.
6-
paragraph=Patterns from Adafruit are: SCANNER, STRIPES, DELAY, PROCESS_SELECTIVE, FADE_SELECTIVE. The original SCANNER pattern is extended and includes the CYLON as well as the ROCKET or FALLING_STAR pattern. The more versatile STRIPES pattern replaces the old THEATER_CHASE one. NeoPixel-Matrix pattern are: MOVING_PICTURE, MOVE, TICKER, FIRE, SNOW, SNAKE.
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.
77
category=Display
88
url=https://github.com/ArminJo/NeoPatterns
99
architectures=avr,megaavr,esp8266,esp32,stm32,STM32F1

src/ADCUtils.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
#define STR_HELPER(x) #x
3333
#define STR(x) STR_HELPER(x)
3434
#endif
35+
#if !defined(BITS_PER_BYTE)
36+
#define BITS_PER_BYTE 8
37+
#endif
3538

3639
/*
3740
* By replacing this value with the voltage you measured a the AREF pin after a conversion

src/Colors.h

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ typedef uint32_t color32_t;
7676
#define COLOR32_BLACK COLOR32(0,0,0)
7777

7878
#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
7980
#define COLOR32_WHITE_HALF COLOR32(128,128,128) // to reduce power consumption
8081
#define COLOR32_WHITE_QUARTER COLOR32(64,64,64) // to reduce power consumption
8182
#define COLOR32_WHITE_EIGHTH COLOR32(32,32,32) // to reduce power consumption

0 commit comments

Comments
 (0)