MusicRing/modules/LED_Ring.h
2024-08-26 00:11:00 +03:00

153 lines
4.3 KiB
C++

#pragma once
#include <Arduino.h>
struct LED_Ring_PINOUT {
uint8_t
Data, // yellow
CLK_inside, // red
CLK_outside, // orange
RESET, // green
OutputEnable; // pur
};
class LED_Ring {
private:
HardwareTimer *MyTim = nullptr;
LED_Ring_PINOUT pinOut;
uint16_t ledCount;
uint16_t updateFrec;
volatile uint16_t position = 1; // позиция сдвига
volatile uint16_t frec = 42; // частота MusicRing
volatile uint16_t period; // период в тактах
public:
LED_Ring(uint16_t _ledCount, LED_Ring_PINOUT _pinOut) : ledCount(_ledCount), pinOut(_pinOut) {
period = F_CPU / 8 / ledCount / frec; //TODO: Динамически подстраивать разрешающую способность в зависимости от мк
pinMode(pinOut.CLK_inside, OUTPUT);
pinMode(pinOut.CLK_outside, OUTPUT);
pinMode(pinOut.Data, OUTPUT);
pinMode(pinOut.OutputEnable, OUTPUT);
pinMode(pinOut.RESET, OUTPUT);
digitalWrite(pinOut.RESET, HIGH);
};
void begin(void(*func)(void)) {
reset();
for (size_t j = 0; j < 1; j++) {
for (size_t i = 1; i <= ledCount * 2; i++) {
digitalWrite(pinOut.Data, i <= ledCount ? HIGH : LOW);
shift(1);
delay(11);
}
}
delay(100);
for (size_t i = 0; i < 3; i++) {
uint8_t del = 42;
digitalWrite(pinOut.Data, HIGH);
shift(ledCount);
delay(del * 1.5);
reset();
delay(del);
}
timerIni(frec, func);
}
///////////////////////////////////////////////////////////////////////////////////////
void point_ini(uint8_t width) {
reset();
digitalWrite(pinOut.Data, HIGH);
shift(width);
digitalWrite(pinOut.Data, LOW);
}
void shift(uint16_t count, bool isVisible = true) {
for (size_t i = 0; i < count; i++) {
digitalWrite(pinOut.CLK_inside, HIGH);
if (isVisible) digitalWrite(pinOut.CLK_outside, HIGH);
digitalWrite(pinOut.CLK_inside, LOW);
digitalWrite(pinOut.CLK_outside, LOW);
position++;
}
};
void reset() {
digitalWrite(pinOut.RESET, LOW);
digitalWrite(pinOut.RESET, HIGH);
digitalWrite(pinOut.CLK_outside, HIGH);
digitalWrite(pinOut.CLK_outside, LOW);
}
//////////////////////////////////////////////////////////////////////////////
void isr() {
if (position > ledCount) {
point_ini(1);
position = 1;
} else shift(1);
}
//////////////////////////////////////////////////////////////////////////////
void timerIni(uint16_t _frec, void(*func)(void)) {
// Определяем таймер, например, используем TIM2
MyTim = new HardwareTimer(TIM2);
// Рассчитываем период
uint32_t prescaler = 8; // Делитель
period = (SystemCoreClock / (prescaler * _frec)) - 1;
// Останавливаем таймер перед настройкой
MyTim->pause();
// Настраиваем предделитель (делитель частоты)
MyTim->setPrescaleFactor(prescaler);
// Настраиваем таймер в режиме CTC (count-to-clear)
MyTim->setOverflow(period);
MyTim->attachInterrupt(func);
MyTim->resume();
}
void setFrec(uint16_t frec) {
uint32_t prescaler = 8; // Делитель
period = (SystemCoreClock / (prescaler * frec)) - 1;
// Останавливаем таймер перед изменением периода
MyTim->pause();
MyTim->setOverflow(period);
MyTim->refresh(); // Обновление настроек таймера
MyTim->resume();
}
void setPeriod(uint32_t per) {
period = per;
// Останавливаем таймер перед изменением периода
MyTim->pause();
MyTim->setOverflow(period);
MyTim->refresh(); // Обновление настроек таймера
MyTim->resume();
}
/////////////////////////////////////////////////////////////////
};