Помнится, еще на старом форуме кто-то из участников разместил функцию для переноса данных из массива цветов на ленту. Для тех, кому не нужны навороты существующих библиотек для ws2812.
Тогда сохранил себе в файл, а сейчас дошли руки попробовать. Исходной темы, увы, поиском нее нашел.
В общем, что-то у меня эта функция выдает странные результаты.
Есть: Arduino Nano прошитая как Uno, колечко из 16 светодиодов.
Хочется: чтобы колечко крутилось по спектру: RYGCBM…
Результат: при использовании NeoPixel (раскомментирована первая строка) все так и происходит, при использовании обсуждаемой функции (закомментирована первая строка) - обновляются лишь чуть более половины светодиодов и порядок цветов отличен от желаемого.
Код (можно выбрать библиотеку NeoPixel или обсуждаемую функцию, рас-/за-комментировав первую строку):
Спойлер
//#define NEOPIXEL
#define NumPixels 16
#define DO_PIN 6
#ifdef NEOPIXEL
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
Adafruit_NeoPixel pix(NumPixels, DO_PIN, NEO_GRB + NEO_KHZ800);
#else
/*
* Copyright (C) 2022, Andrei Egorov - работа с адресными светодиодами
*/
#define NumColors 4
#if DO_PIN > 19
#error !!! DO_PIN must be less than 20 !!!
#endif
#define DOPORT (DO_PIN>=0 && DO_PIN<=7) ? 0x0B : (DO_PIN>=8 && DO_PIN<=13) ? 0x05 : (DO_PIN>=14 && DO_PIN<=19) ? 0x08 : 0
#define DOPIN (DO_PIN>=0 && DO_PIN<=7) ? DO_PIN : (DO_PIN>=8 && DO_PIN<=13) ? DO_PIN - 8 : (DO_PIN>=14 && DO_PIN<=19) ? DO_PIN - 14 : 0
uint8_t pixels[NumPixels][NumColors];
void __attribute__ ((noinline))send_pixels(uint16_t num, uint8_t *ppixels) {
static uint32_t endsend=0;
while ((micros()-endsend)<300);
asm volatile(
"IN __tmp_reg__,%0 \n\t"
"PUSH __tmp_reg__ \n\t"
"CLI \n\t"
"LDI r19,1<<%3 \n\t"
"LDI r18,2 \n\t"
"LD __tmp_reg__,%a1+ \n\t"
"label_1: \n\t"
"BST __tmp_reg__,7 \n\t"
"OUT %2-2,r19 \n\t"
"BRTC label_2 \n\t"
"ROL __tmp_reg__ \n\t"
"LSL r18 \n\t"
"RJMP .+0\n\t"
"RJMP .+0\n\t"
"BRCS label_3 \n\t"
"NOP \n\t"
"OUT %2-2,r19 \n\t"
"RJMP label_1 \n\t"
"label_2: \n\t"
"BST __tmp_reg__,7 \n\t"
"OUT %2-2,r19 \n\t"
"ROL __tmp_reg__ \n\t"
"LSL r18 \n\t"
"RJMP .+0\n\t"
"RJMP .+0\n\t"
"BRCC label_1 \n\t"
"RJMP label_4 \n\t"
"label_3: \n\t"
"OUT %2-2,r19 \n\t"
"RJMP .+0\n\t"
"BST __tmp_reg__,7 \n\t"
"label_4: \n\t"
"OUT %2-2,r19 \n\t"
"BRTC label_5 \n\t"
"RJMP .+0\n\t"
"LDI r18,2 \n\t"
"SBIW %4,1 \n\t"
"BREQ label_6 \n\t"
"LD __tmp_reg__,%a1+ \n\t"
"OUT %2-2,r19 \n\t"
"RJMP label_1 \n\t"
"label_5: \n\t"
"LDI r18,2 \n\t"
"OUT %2-2,r19 \n\t"
"SBIW %4,1 \n\t"
"LD __tmp_reg__,%a1+ \n\t"
"RJMP .+0\n\t"
"BRNE label_1 \n\t"
"RJMP label_7 \n\t"
"label_6: \n\t"
"NOP \n\t"
"OUT %2-2,r19 \n\t"
"label_7: \n\t"
"POP __tmp_reg__ \n\t"
"OUT %0,__tmp_reg__\n\t"
::"I" (_SFR_IO_ADDR(SREG)), "e" (ppixels), "I" (_SFR_IO_ADDR(_SFR_IO8(DOPORT))), "M" (DOPIN), "w" (num):"r18","r19"
);
endsend=micros();
}
#endif
#define tickRange (256*6) // 0-225:R-Y, 256-511:Y-G, 512-767:G-C, 768-1023:C-B, 1024-1279:B-M, 1280-1535:M-R
// Rm G+ B0 R- Gm B0 R0 Gm B+ R0 G- Bm R+ G0 Bm Rm G0 B-
// R ^^^^^^^^^^^\\\\\\\\\\\\\___________________________///////////////^^^^^^^^^^^
// G ///////////^^^^^^^^^^^^^^^^^^^^^^^^^^\\\\\\\\\\\\\\__________________________
// B ________________________/////////////^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\\\\\\\\\\\
#define stepi 4
byte getValue(int pos) { // G: первые 256 нарастает, следующие 512 - максимум, след. 256 убывает, остальные 512 - 0
while(pos < 0) pos += tickRange;
while(pos >= tickRange) pos -= tickRange;
if(pos < 256) return pos;
if(pos < 768) return 255;
if(pos < 1024) return 1023 - pos;
return 0;
}
void setup () {
Serial.begin(115200);
Serial.println("Start");
pinMode(13, OUTPUT);
#ifdef NEOPIXEL
pix.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
#else
asm volatile(
"SBI %0-1,%1 \n\t"
"CBI %0,%1 \n\t"
::"I" (_SFR_IO_ADDR(_SFR_IO8(DOPORT))), "I" (DOPIN)//, "r" (DO)
);
#endif
Serial.print("End Prepare NumPixels: ");
Serial.println(NumPixels);
}
#define angle (tickRange/NumPixels)
void oneStep() {
long t0 = micros();
static int i = 0;
byte j;
i += stepi;
if (i >= tickRange) i -= tickRange;
for(int k = 0; k < NumPixels; k++) {
byte b0 = getValue(i - 512 - k*angle);
byte b1 = getValue(i - k*angle);
byte b2 = getValue(i + 512 - k*angle);
#ifdef NEOPIXEL
pix.setPixelColor(k, pix.Color(b0, b1, b2));
#else
pixels[k][0] = b0;
pixels[k][1] = b1;
pixels[k][2] = b2;
#endif
}
long t1 = micros();
#ifdef NEOPIXEL
pix.show(); // Send the updated pixel colors to the hardware.
#else
send_pixels(NumPixels*NumColors, *pixels);
#endif
long t2 = micros();
static long tt;
if(i == 256) {
Serial.print(t1-t0);
Serial.print('\t');
Serial.print(t2-t1);
Serial.print('\t');
Serial.println(t2-tt);
}
tt = t2;
}
void loop() {
static unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= 5) {
previousMillis = currentMillis;
digitalWrite(13, !digitalRead(13));
oneStep();
}
}