/* MY9291 LED Driver Arduino library 0.1.0 Copyright (c) 2016 - 2026 MaiKe Labs Copyright (C) 2017 - Xose Pérez (for the library) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "my9291.h" extern "C" { void os_delay_us(unsigned int); } void my9291::_di_pulse(unsigned int times) { unsigned int i; for (i = 0; i < times; i++) { digitalWrite(_pin_di, HIGH); digitalWrite(_pin_di, LOW); } } void my9291::_dcki_pulse(unsigned int times) { unsigned int i; for (i = 0; i < times; i++) { digitalWrite(_pin_dcki, HIGH); digitalWrite(_pin_dcki, LOW); } } void my9291::_set_cmd(my9291_cmd_t command) { unsigned char i; unsigned char command_data = *(unsigned char *) (&command); _command = command; // ets_intr_lock(); // TStop > 12us. os_delay_us(12); // Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12 // pulse's rising edge convert to command mode. _di_pulse(12); // Delay >12us, begin send CMD data os_delay_us(12); // Send CMD data for (i = 0; i < 4; i++) { // DCK = 0; digitalWrite(_pin_dcki, LOW); if (command_data & 0x80) { // DI = 1; digitalWrite(_pin_di, HIGH); } else { // DI = 0; digitalWrite(_pin_di, LOW); } // DCK = 1; digitalWrite(_pin_dcki, HIGH); command_data = command_data << 1; if (command_data & 0x80) { // DI = 1; digitalWrite(_pin_di, HIGH); } else { // DI = 0; digitalWrite(_pin_di, LOW); } // DCK = 0; digitalWrite(_pin_dcki, LOW); // DI = 0; digitalWrite(_pin_di, LOW); command_data = command_data << 1; } // TStart > 12us. Delay 12 us. os_delay_us(12); // Send 16 DI pulse,at 14 pulse's falling edge store CMD data, and // at 16 pulse's falling edge convert to duty mode. _di_pulse(16); // TStop > 12us. os_delay_us(12); // ets_intr_unlock(); } void my9291::send(unsigned int duty_r, unsigned int duty_g, unsigned int duty_b, unsigned int duty_w) { unsigned char i = 0; unsigned char channel = 0; unsigned char bit_length = 8; unsigned int duty_current = 0; // Definition for RGBW channels unsigned int duty[4] = { duty_r, duty_g, duty_b, duty_w }; switch (_command.bit_width) { case MY9291_CMD_BIT_WIDTH_16: bit_length = 16; break; case MY9291_CMD_BIT_WIDTH_14: bit_length = 14; break; case MY9291_CMD_BIT_WIDTH_12: bit_length = 12; break; case MY9291_CMD_BIT_WIDTH_8: bit_length = 8; break; default: bit_length = 8; break; } // ets_intr_lock(); // TStop > 12us. os_delay_us(12); for (channel = 0; channel < 4; channel++) { //RGBW 4CH // RGBW Channel duty_current = duty[channel]; // Send 8bit/12bit/14bit/16bit Data for (i = 0; i < bit_length / 2; i++) { // DCK = 0; digitalWrite(_pin_dcki, LOW); if (duty_current & (0x01 << (bit_length - 1))) { // DI = 1; digitalWrite(_pin_di, HIGH); } else { // DI = 0; digitalWrite(_pin_di, LOW); } // DCK = 1; digitalWrite(_pin_dcki, HIGH); duty_current = duty_current << 1; if (duty_current & (0x01 << (bit_length - 1))) { // DI = 1; digitalWrite(_pin_di, HIGH); } else { // DI = 0; digitalWrite(_pin_di, LOW); } //DCK = 0; digitalWrite(_pin_dcki, LOW); //DI = 0; digitalWrite(_pin_di, LOW); duty_current = duty_current << 1; } } // TStart > 12us. Ready for send DI pulse. os_delay_us(12); // Send 8 DI pulse. After 8 pulse falling edge, store old data. _di_pulse(8); // TStop > 12us. os_delay_us(12); // ets_intr_unlock(); } my9291::my9291(unsigned char di, unsigned char dcki, my9291_cmd_t command) { _pin_di = di; _pin_dcki = dcki; pinMode(_pin_di, OUTPUT); pinMode(_pin_dcki, OUTPUT); digitalWrite(_pin_di, LOW); digitalWrite(_pin_dcki, LOW); // Clear all duty register _dcki_pulse(64 / 2); _set_cmd(command); }