#include "FastLED.h"
#include <NecDecoder.h>
#define LED_PIN 13 // пин управления лентой
#define LED_NUM 60 // количество светодиодов в ленте
#define REL_SPEED 25 // период смены кадра
#define IR_TO 14 // максимальный кадр протокола NEC (преамбула (9+4,5)мс)
#define IR_0 0x98 // команды пульта
#define IR_1 0xA2
#define IR_2 0x62
#define IR_3 0xE2
#define IR_4 0x22
#define IR_5 0x02
#define IR_6 0xC2
#define IR_7 0xE0
#define IR_8 0xA8
#define IR_9 0x90
#define IR_STAR 0x68
#define IR_HASH 0xB0
#define IR_OK 0x38
#define IR_UP 0x18
#define IR_LEFT 0x10
#define IR_RIGHT 0x5A
#define IR_DOWN 0x4A
#define RB_ON 0x80 // радуга включена
#define S1_DONE 0x40 // массив светодиодов сдвинут
#define S2_DONE 0x20 // массив светодиодов заполнен
#define IR_CHK 0x02 // флаг таймера таймаута
#define IR_TICK 0x01 // флаг запрета отображения
CRGB leds[LED_NUM]; // массив светодиодной ленты
NecDecoder ir; // класс ИК-управления
byte counter; // кадр анимации
volatile byte flags = 0; // биты флагов
uint16_t time_rel; // время кадра
uint16_t time_ir; // таймаут ИР-управления
void setup() {
//Serial.begin(9600);
pinMode(LED_PIN, OUTPUT);
attachInterrupt(0, irIsr, FALLING);
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, LED_NUM);
FastLED.setBrightness(50);
FastLED.clear();
FastLED.showColor(CRGB(0, 0, 0));//сброс ленты(выключение)
FastLED.show();
}
void irIsr() {
ir.tick(); // обработка импульса
flags |= IR_TICK; // запрет отображения
flags &= ~IR_CHK; // отменяем таймаут
}
void loop() {
if (ir.available()) {
// снятие запрета отображения
flags &= ~(IR_CHK | IR_TICK);
switch (ir.readCommand()) {
case IR_1:
flags &= ~(RB_ON | S1_DONE | S2_DONE); // выключаем радугу
FastLED.showColor(CRGB(255, 0, 0)); // включаем статичный красный свет на всей ленте
break;
case IR_2:
flags &= ~(RB_ON | S1_DONE | S2_DONE); // выключаем радугу
FastLED.showColor(CRGB(0, 255, 0)); // включаем статичный зеленый свет на всей ленте
break;
case IR_STAR:
flags |= RB_ON; // включаем радугу
time_rel = (uint16_t)millis(); // включаем таймер кадра
counter = 0;
}
} else if (flags & RB_ON) { // радуга
if ((flags & IR_TICK) && ((flags & IR_CHK) == 0)) {
// обнаружили IR-передачу
time_ir = (uint16_t)millis(); // включаем таймер таймаута
flags |= IR_CHK; // поднимаем флаг таймаута
}
if (flags & S2_DONE) { // кадр готов
if ((flags & IR_CHK) && ((uint16_t)millis() - time_ir >= IR_TO)) {
// если сработал таймаут
flags &= ~(IR_CHK | IR_TICK); // отменяем запрет отображения, сбрасываем таймаут
}
if ((uint16_t)millis() - time_rel >= REL_SPEED) { // кадр завершился
if ((flags & IR_TICK) == 0) { // отображение разрешено
FastLED.show(); // отображаем
counter += 2; // переход на следующий кадр (через 2 для оптимизации)
flags &= ~(S1_DONE | S2_DONE); // для подготовки следующего кадра
}
time_rel += REL_SPEED;
}
} else if (flags & S1_DONE) { // расчёт последнего светодиода
leds[LED_NUM-1] = CHSV(counter + (LED_NUM - 1) * 2, 255, 255);
flags |= S2_DONE; // кадр подготовлен
} else { // смещение картинки в сторону первого светодиода
memmove(leds, (leds+1), sizeof(CRGB)*(LED_NUM-1));
flags |= S1_DONE; // смещение произведено
}
}
}