Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

187 lines
4.3 KiB

/*
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 <http://www.gnu.org/licenses/>.
*/
#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);
}