diff --git a/MusicRing.ino b/MusicRing.ino index c16d68a..1f01b6e 100644 --- a/MusicRing.ino +++ b/MusicRing.ino @@ -1,87 +1,27 @@ #include //#include +#include "modules/LED_Ring.h" #include "implement/Display__Adafruit_SSD1306.h" #include "misc/bitmaps.h" -Display_Adafruit_SSD1306 screen(128, 32, Display::Ori_HORIZONTAL); +LED_Ring_PINOUT pinout { 5, 6, 7, 8, 9 }; -#define pin_Data 5 // yellow -#define pin_CLK_inside 6 // orange -#define pin_CLK_outside 7 // red - -#define pin_RESET 8 // green -#define pin_OutputEnable 9 // purple - -#define LED_count 32 - - -void shift(uint16_t, bool = true); - -volatile uint8_t position = 1; // позиция сдвига -volatile uint16_t frec = 42; // частота MusicRing -volatile uint16_t t_period_takts = F_CPU / 8 / LED_count / frec; +LED_Ring ring(32, pinout); +Display_Adafruit_SSD1306 screen(128, 32, Display::Ori_HORIZONTAL); void setup() { - Serial.begin(115200); - pinMode(pin_Data, OUTPUT); - pinMode(pin_CLK_inside, OUTPUT); - pinMode(pin_CLK_outside, OUTPUT); - pinMode(pin_RESET, OUTPUT); - pinMode(pin_OutputEnable, OUTPUT); - + ring.begin(); screen.begin(); - + screen.adafruit->drawBitmap(0, 0, DashyFox_logo, 128, 32, WHITE); screen.adafruit->display(); - digitalWrite(pin_RESET, HIGH); - - reset(); - - - for (size_t j = 0; j < 1; j++) { - for (size_t i = 1; i <= LED_count * 2; i++) { - digitalWrite(pin_Data, i <= LED_count ? HIGH : LOW); - shift(1); - delay(11); - } - } - - delay(100); - - for (size_t i = 0; i < 3; i++) { - uint8_t del = 42; - digitalWrite(pin_Data, HIGH); - shift(LED_count); - delay(del * 1.5); - reset(); - delay(del); - } - - // инициализация Timer1 - cli(); // отключить глобальные прерывания - TCCR1A = 0; // установить регистры в 0 - TCCR1B = 0; - - OCR1A = t_period_takts; // установка регистра совпадения - TCCR1B |= (1 << WGM12); // включение в CTC режим - - // Установка битов CS на коэффициент деления 8 - TCCR1B |= 0b00000010; - - TIMSK1 |= (1 << OCIE1A); // включение прерываний по совпадению - sei(); // включить глобальные прерывания } -ISR(TIMER1_COMPA_vect) { - if (position >= LED_count) { - point_ini(1); - position = 1; - } else shift(1); -} +ISR(TIMER1_COMPA_vect) { ring.isr(); } void loop() { @@ -96,34 +36,4 @@ void loop() { f = !f; } -} - -void point_ini(uint8_t width) { - - reset(); - - digitalWrite(pin_Data, HIGH); - shift(width); - digitalWrite(pin_Data, LOW); - -} - -void shift(uint16_t count, bool isVisible = true) { - for (size_t i = 0; i < count; i++) { - - digitalWrite(pin_CLK_inside, HIGH); - if (isVisible) digitalWrite(pin_CLK_outside, HIGH); - - digitalWrite(pin_CLK_inside, LOW); - digitalWrite(pin_CLK_outside, LOW); - - position++; - } -}; - -void reset() { - digitalWrite(pin_RESET, LOW); - digitalWrite(pin_RESET, HIGH); - digitalWrite(pin_CLK_outside, HIGH); - digitalWrite(pin_CLK_outside, LOW); } \ No newline at end of file diff --git a/modules/Display.h b/modules/Display.h index e82bfdc..f334b82 100644 --- a/modules/Display.h +++ b/modules/Display.h @@ -15,6 +15,15 @@ public: Ori_VERTICAL_FLIP = 270, }; + template + struct Picture { + uint16_t sizeX = X; + uint16_t sizeY = Y; + uint8_t bitMap[(X * Y) / 8 + ((X * Y) / 8) ? 1 : 0]; + uint8_t overMap[(X * Y) / 8 + ((X * Y) / 8) ? 1 : 0]; + }; + + protected: struct ScreenParam { uint16_t width, height, orientation; @@ -32,4 +41,12 @@ public: virtual void writePixel() {}; + void drawBbitmap(int16_t x, int16_t y, const uint8_t bitmap [], + int16_t w, int16_t h) { + + Picture<128, 32> logo; + } + + + }; diff --git a/modules/LED_Ring.h b/modules/LED_Ring.h index 2b6c63e..36bbc1a 100644 --- a/modules/LED_Ring.h +++ b/modules/LED_Ring.h @@ -2,16 +2,138 @@ #include struct LED_Ring_PINOUT { - uint8_t Data, CLK_inside, CLK_outside, RESET, OutputEnable; + uint8_t + Data, + CLK_inside, + CLK_outside, + RESET, + OutputEnable; }; class LED_Ring { -public: +private: LED_Ring_PINOUT pinOut; uint16_t ledCount; uint16_t updateFrec; - LED_Ring(uint16_t _ledCount, LED_Ring_PINOUT _pinOut) : ledCount(_ledCount), pinOut(_pinOut) {}; + 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() { + + 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); + } + + /////////////////////////////////////////////////////////////////////////////////////// + + 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) { //TODO: Сделать возможность выбора таймеров + period = F_CPU / 8 / ledCount / _frec; + // инициализация Timer1 + cli(); // отключить глобальные прерывания + TCCR1A = 0; // установить регистры в 0 + TCCR1B = 0; + + OCR1A = period; // установка регистра совпадения + TCCR1B |= (1 << WGM12); // включение в CTC режим + + // Установка битов CS на коэффициент деления 8 + TCCR1B |= 0b00000010; + + TIMSK1 |= (1 << OCIE1A); // включение прерываний по совпадению + sei(); // включить глобальные прерывания + } + + void setFrec(uint8_t frec) { + period = F_CPU / 8 / ledCount / frec; + cli(); + OCR1A = period; // установка регистра совпадения + sei(); + } + void setPeriod(uint8_t per) { + period = per; + cli(); + OCR1A = period; // установка регистра совпадения + sei(); + } + + ///////////////////////////////////////////////////////////////// };