mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-31 14:37:49 +00:00
Redesign light driver phase 1
Redesign light driver phase 1
This commit is contained in:
parent
2bfa172324
commit
019dc76740
@ -315,9 +315,16 @@
|
|||||||
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
||||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||||
//#define ROTARY_V1 // Add support for MI Desk Lamp
|
//#define ROTARY_V1 // Add support for MI Desk Lamp
|
||||||
#define USE_SM2135 // Add support for SM2135 RGBCW led control (+0k6 code)
|
|
||||||
//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code)
|
//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code)
|
||||||
|
|
||||||
|
// -- Optional light modules ----------------------
|
||||||
|
#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by //
|
||||||
|
// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow
|
||||||
|
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106)
|
||||||
|
#define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW)
|
||||||
|
#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code)
|
||||||
|
#define USE_SM2135 // Add support for SM2135 RGBCW led control as used in Action LSC (+0k6 code)
|
||||||
|
|
||||||
// -- Counter input -------------------------------
|
// -- Counter input -------------------------------
|
||||||
#define USE_COUNTER // Enable inputs as counter (+0k8 code)
|
#define USE_COUNTER // Enable inputs as counter (+0k8 code)
|
||||||
|
|
||||||
@ -513,11 +520,6 @@
|
|||||||
|
|
||||||
// ------------------------------------------------
|
// ------------------------------------------------
|
||||||
|
|
||||||
#define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+5k code, +1k mem, 232 iram) - Disable by //
|
|
||||||
// #define USE_WS2812_DMA // DMA supports only GPIO03 (= Serial RXD) (+1k mem). When USE_WS2812_DMA is enabled expect Exceptions on Pow
|
|
||||||
#define USE_WS2812_HARDWARE NEO_HW_WS2812 // Hardware type (NEO_HW_WS2812, NEO_HW_WS2812X, NEO_HW_WS2813, NEO_HW_SK6812, NEO_HW_LC8812, NEO_HW_APA106)
|
|
||||||
#define USE_WS2812_CTYPE NEO_GRB // Color type (NEO_RGB, NEO_GRB, NEO_BRG, NEO_RBG, NEO_RGBW, NEO_GRBW)
|
|
||||||
|
|
||||||
#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0))
|
#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0))
|
||||||
|
|
||||||
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
|
#define USE_SR04 // Add support for HC-SR04 ultrasonic devices (+1k code)
|
||||||
@ -536,8 +538,6 @@
|
|||||||
// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code)
|
// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code)
|
||||||
// #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code)
|
// #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 weather stations using 868MHz RF sensor receiver (+1k7 code)
|
||||||
|
|
||||||
#define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code)
|
|
||||||
|
|
||||||
//#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code)
|
//#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code)
|
||||||
//#define USE_A4988_Stepper // Add support for A4988 stepper-motor-driver-circuit (+10k5 code)
|
//#define USE_A4988_Stepper // Add support for A4988 stepper-motor-driver-circuit (+10k5 code)
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ uint8_t led_power = 0; // LED power state
|
|||||||
uint8_t ledlnk_inverted = 0; // Link LED inverted flag (1 = (0 = On, 1 = Off))
|
uint8_t ledlnk_inverted = 0; // Link LED inverted flag (1 = (0 = On, 1 = Off))
|
||||||
uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted)
|
uint8_t pwm_inverted = 0; // PWM inverted flag (1 = inverted)
|
||||||
uint8_t energy_flg = 0; // Energy monitor configured
|
uint8_t energy_flg = 0; // Energy monitor configured
|
||||||
|
uint8_t light_flg = 0; // Light module configured
|
||||||
uint8_t light_type = 0; // Light types
|
uint8_t light_type = 0; // Light types
|
||||||
uint8_t serial_in_byte; // Received byte
|
uint8_t serial_in_byte; // Received byte
|
||||||
uint8_t ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter
|
uint8_t ota_retry_counter = OTA_ATTEMPTS; // OTA retry counter
|
||||||
@ -1391,14 +1392,6 @@ void GpioInit(void)
|
|||||||
devices_present = 1;
|
devices_present = 1;
|
||||||
|
|
||||||
light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0
|
light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0
|
||||||
#ifdef USE_LIGHT
|
|
||||||
if (Settings.flag.pwm_control) {
|
|
||||||
for (uint32_t i = 0; i < MAX_PWMS; i++) {
|
|
||||||
if (pin[GPIO_PWM1 +i] < 99) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // USE_LIGHT
|
|
||||||
|
|
||||||
if (XdrvCall(FUNC_MODULE_INIT)) {
|
if (XdrvCall(FUNC_MODULE_INIT)) {
|
||||||
// Serviced
|
// Serviced
|
||||||
}
|
}
|
||||||
@ -1420,30 +1413,24 @@ void GpioInit(void)
|
|||||||
devices_present = 0;
|
devices_present = 0;
|
||||||
baudrate = 19200;
|
baudrate = 19200;
|
||||||
}
|
}
|
||||||
#ifdef USE_LIGHT
|
|
||||||
else if (SONOFF_BN == my_module_type) { // PWM Single color led (White)
|
if (!light_type) {
|
||||||
light_type = LT_PWM1;
|
devices_present = 0;
|
||||||
|
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
|
||||||
|
if (pin[GPIO_PWM1 +i] < 99) {
|
||||||
|
pwm_present = true;
|
||||||
|
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
||||||
|
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (SONOFF_LED == my_module_type) { // PWM Dual color led (White warm and cold)
|
for (uint32_t i = 0; i < MAX_RELAYS; i++) {
|
||||||
light_type = LT_PWM2;
|
if (pin[GPIO_REL1 +i] < 99) {
|
||||||
}
|
pinMode(pin[GPIO_REL1 +i], OUTPUT);
|
||||||
else if (AILIGHT == my_module_type) { // RGBW led
|
devices_present++;
|
||||||
light_type = LT_RGBW;
|
if (EXS_RELAY == my_module_type) {
|
||||||
}
|
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0);
|
||||||
else if (SONOFF_B1 == my_module_type) { // RGBWC led
|
if (i &1) { devices_present--; }
|
||||||
light_type = LT_RGBWC;
|
|
||||||
}
|
|
||||||
#endif // USE_LIGHT
|
|
||||||
else {
|
|
||||||
if (!light_type) { devices_present = 0; }
|
|
||||||
for (uint32_t i = 0; i < MAX_RELAYS; i++) {
|
|
||||||
if (pin[GPIO_REL1 +i] < 99) {
|
|
||||||
pinMode(pin[GPIO_REL1 +i], OUTPUT);
|
|
||||||
devices_present++;
|
|
||||||
if (EXS_RELAY == my_module_type) {
|
|
||||||
digitalWrite(pin[GPIO_REL1 +i], bitRead(rel_inverted, i) ? 1 : 0);
|
|
||||||
if (i &1) { devices_present--; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1475,37 +1462,6 @@ void GpioInit(void)
|
|||||||
RotaryInit();
|
RotaryInit();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIGHT
|
|
||||||
#ifdef USE_WS2812
|
|
||||||
if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led
|
|
||||||
devices_present++;
|
|
||||||
light_type = LT_WS2812;
|
|
||||||
}
|
|
||||||
#endif // USE_WS2812
|
|
||||||
#ifdef USE_SM16716
|
|
||||||
if (SM16716_ModuleSelected()) {
|
|
||||||
light_type += 3;
|
|
||||||
light_type |= LT_SM16716;
|
|
||||||
}
|
|
||||||
#endif // USE_SM16716
|
|
||||||
|
|
||||||
// post-process for lights
|
|
||||||
if (Settings.flag3.pwm_multi_channels) {
|
|
||||||
uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7);
|
|
||||||
if (0 == pwm_channels) { pwm_channels = 1; }
|
|
||||||
devices_present += pwm_channels - 1; // add the pwm channels controls at the end
|
|
||||||
}
|
|
||||||
#endif // USE_LIGHT
|
|
||||||
if (!light_type) {
|
|
||||||
for (uint32_t i = 0; i < MAX_PWMS; i++) { // Basic PWM control only
|
|
||||||
if (pin[GPIO_PWM1 +i] < 99) {
|
|
||||||
pwm_present = true;
|
|
||||||
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
|
||||||
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - Settings.pwm_value[i] : Settings.pwm_value[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SetLedPower(Settings.ledstate &8);
|
SetLedPower(Settings.ledstate &8);
|
||||||
SetLedLink(Settings.ledstate &8);
|
SetLedLink(Settings.ledstate &8);
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ struct LIGHT {
|
|||||||
uint8_t wakeup_active = 0;
|
uint8_t wakeup_active = 0;
|
||||||
uint8_t wakeup_dimmer = 0;
|
uint8_t wakeup_dimmer = 0;
|
||||||
uint8_t fixed_color_index = 1;
|
uint8_t fixed_color_index = 1;
|
||||||
|
uint8_t pwm_offset = 0; // Offset in color buffer
|
||||||
|
|
||||||
bool update = true;
|
bool update = true;
|
||||||
bool pwm_multi_channels = false; // SetOption68, treat each PWM channel as an independant dimmer
|
bool pwm_multi_channels = false; // SetOption68, treat each PWM channel as an independant dimmer
|
||||||
@ -1269,102 +1270,66 @@ void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t dut
|
|||||||
os_delay_us(12); // TStop > 12us.
|
os_delay_us(12); // TStop > 12us.
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SM16716
|
|
||||||
/*********************************************************************************************\
|
|
||||||
* SM16716 - Controlling RGB over a synchronous serial line
|
|
||||||
* Copyright (C) 2019 Gabor Simon
|
|
||||||
*
|
|
||||||
* Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27
|
|
||||||
*
|
|
||||||
\*********************************************************************************************/
|
|
||||||
|
|
||||||
#define D_LOG_SM16716 "SM16716: "
|
|
||||||
|
|
||||||
uint8_t sm16716_pin_clk = 100;
|
|
||||||
uint8_t sm16716_pin_dat = 100;
|
|
||||||
uint8_t sm16716_pin_sel = 100;
|
|
||||||
uint8_t sm16716_enabled = 0;
|
|
||||||
|
|
||||||
void SM16716_SendBit(uint8_t v)
|
|
||||||
{
|
|
||||||
/* NOTE:
|
|
||||||
* According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the
|
|
||||||
* clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate,
|
|
||||||
* so no additional delays are needed yet. */
|
|
||||||
|
|
||||||
digitalWrite(sm16716_pin_dat, (v != 0) ? HIGH : LOW);
|
|
||||||
//delayMicroseconds(1);
|
|
||||||
digitalWrite(sm16716_pin_clk, HIGH);
|
|
||||||
//delayMicroseconds(1);
|
|
||||||
digitalWrite(sm16716_pin_clk, LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM16716_SendByte(uint8_t v)
|
|
||||||
{
|
|
||||||
uint8_t mask;
|
|
||||||
|
|
||||||
for (mask = 0x80; mask; mask >>= 1) {
|
|
||||||
SM16716_SendBit(v & mask);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b)
|
|
||||||
{
|
|
||||||
if (sm16716_pin_sel < 99) {
|
|
||||||
uint8_t sm16716_should_enable = (duty_r | duty_g | duty_b);
|
|
||||||
if (!sm16716_enabled && sm16716_should_enable) {
|
|
||||||
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on"));
|
|
||||||
sm16716_enabled = 1;
|
|
||||||
digitalWrite(sm16716_pin_sel, HIGH);
|
|
||||||
// in testing I found it takes a minimum of ~380us to wake up the chip
|
|
||||||
// tested on a Merkury RGBW with an SM726EB
|
|
||||||
delayMicroseconds(1000);
|
|
||||||
SM16716_Init();
|
|
||||||
}
|
|
||||||
else if (sm16716_enabled && !sm16716_should_enable) {
|
|
||||||
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off"));
|
|
||||||
sm16716_enabled = 0;
|
|
||||||
digitalWrite(sm16716_pin_sel, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b);
|
|
||||||
|
|
||||||
// send start bit
|
|
||||||
SM16716_SendBit(1);
|
|
||||||
SM16716_SendByte(duty_r);
|
|
||||||
SM16716_SendByte(duty_g);
|
|
||||||
SM16716_SendByte(duty_b);
|
|
||||||
|
|
||||||
// send a 'do it' pulse
|
|
||||||
// (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and
|
|
||||||
// passes on the rest, right until the one starting with 0)
|
|
||||||
//SM16716_Init();
|
|
||||||
SM16716_SendBit(0);
|
|
||||||
SM16716_SendByte(0);
|
|
||||||
SM16716_SendByte(0);
|
|
||||||
SM16716_SendByte(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SM16716_ModuleSelected(void)
|
|
||||||
{
|
|
||||||
sm16716_pin_clk = pin[GPIO_SM16716_CLK];
|
|
||||||
sm16716_pin_dat = pin[GPIO_SM16716_DAT];
|
|
||||||
sm16716_pin_sel = pin[GPIO_SM16716_SEL];
|
|
||||||
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), sm16716_pin_clk, sm16716_pin_dat);
|
|
||||||
return (sm16716_pin_clk < 99) && (sm16716_pin_dat < 99);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SM16716_Init(void)
|
|
||||||
{
|
|
||||||
for (uint32_t t_init = 0; t_init < 50; ++t_init) {
|
|
||||||
SM16716_SendBit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // ifdef USE_SM16716
|
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
void LightPwmOffset(uint32_t offset)
|
||||||
|
{
|
||||||
|
Light.pwm_offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LightModuleInit(void)
|
||||||
|
{
|
||||||
|
light_type = LT_BASIC; // Use basic PWM control if SetOption15 = 0
|
||||||
|
|
||||||
|
if (Settings.flag.pwm_control) {
|
||||||
|
for (uint32_t i = 0; i < MAX_PWMS; i++) {
|
||||||
|
if (pin[GPIO_PWM1 +i] < 99) { light_type++; } // Use Dimmer/Color control for all PWM as SetOption15 = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
light_flg = 0;
|
||||||
|
if (XlgtCall(FUNC_MODULE_INIT)) {
|
||||||
|
// serviced
|
||||||
|
}
|
||||||
|
else if (SONOFF_BN == my_module_type) { // PWM Single color led (White)
|
||||||
|
light_type = LT_PWM1;
|
||||||
|
}
|
||||||
|
else if (SONOFF_LED == my_module_type) { // PWM Dual color led (White warm and cold)
|
||||||
|
if (!my_module.io[4]) { // Fix Sonoff Led instabilities
|
||||||
|
pinMode(4, OUTPUT); // Stop floating outputs
|
||||||
|
digitalWrite(4, LOW);
|
||||||
|
}
|
||||||
|
if (!my_module.io[5]) {
|
||||||
|
pinMode(5, OUTPUT); // Stop floating outputs
|
||||||
|
digitalWrite(5, LOW);
|
||||||
|
}
|
||||||
|
if (!my_module.io[14]) {
|
||||||
|
pinMode(14, OUTPUT); // Stop floating outputs
|
||||||
|
digitalWrite(14, LOW);
|
||||||
|
}
|
||||||
|
light_type = LT_PWM2;
|
||||||
|
}
|
||||||
|
else if (AILIGHT == my_module_type) { // RGBW led
|
||||||
|
light_type = LT_RGBW;
|
||||||
|
}
|
||||||
|
else if (SONOFF_B1 == my_module_type) { // RGBWC led
|
||||||
|
light_type = LT_RGBWC;
|
||||||
|
}
|
||||||
|
#ifdef USE_WS2812
|
||||||
|
if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led
|
||||||
|
light_type = LT_WS2812;
|
||||||
|
}
|
||||||
|
#endif // USE_WS2812
|
||||||
|
// post-process for lights
|
||||||
|
if (Settings.flag3.pwm_multi_channels) {
|
||||||
|
uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7);
|
||||||
|
if (0 == pwm_channels) { pwm_channels = 1; }
|
||||||
|
devices_present += pwm_channels - 1; // add the pwm channels controls at the end
|
||||||
|
}
|
||||||
|
|
||||||
|
return (light_type > 0);
|
||||||
|
}
|
||||||
|
|
||||||
void LightInit(void)
|
void LightInit(void)
|
||||||
{
|
{
|
||||||
uint8_t max_scheme = LS_MAX -1;
|
uint8_t max_scheme = LS_MAX -1;
|
||||||
@ -1402,20 +1367,6 @@ void LightInit(void)
|
|||||||
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (SONOFF_LED == my_module_type) { // Fix Sonoff Led instabilities
|
|
||||||
if (!my_module.io[4]) {
|
|
||||||
pinMode(4, OUTPUT); // Stop floating outputs
|
|
||||||
digitalWrite(4, LOW);
|
|
||||||
}
|
|
||||||
if (!my_module.io[5]) {
|
|
||||||
pinMode(5, OUTPUT); // Stop floating outputs
|
|
||||||
digitalWrite(5, LOW);
|
|
||||||
}
|
|
||||||
if (!my_module.io[14]) {
|
|
||||||
pinMode(14, OUTPUT); // Stop floating outputs
|
|
||||||
digitalWrite(14, LOW);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pin[GPIO_ARIRFRCV] < 99) {
|
if (pin[GPIO_ARIRFRCV] < 99) {
|
||||||
if (pin[GPIO_ARIRFSEL] < 99) {
|
if (pin[GPIO_ARIRFSEL] < 99) {
|
||||||
pinMode(pin[GPIO_ARIRFSEL], OUTPUT);
|
pinMode(pin[GPIO_ARIRFSEL], OUTPUT);
|
||||||
@ -1429,32 +1380,6 @@ void LightInit(void)
|
|||||||
max_scheme = LS_MAX + WS2812_SCHEMES;
|
max_scheme = LS_MAX + WS2812_SCHEMES;
|
||||||
}
|
}
|
||||||
#endif // USE_WS2812 ************************************************************************
|
#endif // USE_WS2812 ************************************************************************
|
||||||
#ifdef USE_SM16716
|
|
||||||
else if (LT_SM16716 == light_type - Light.subtype) {
|
|
||||||
// init PWM
|
|
||||||
for (uint32_t i = 0; i < Light.subtype; i++) {
|
|
||||||
Settings.pwm_value[i] = 0; // Disable direct PWM control
|
|
||||||
if (pin[GPIO_PWM1 +i] < 99) {
|
|
||||||
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// init sm16716
|
|
||||||
pinMode(sm16716_pin_clk, OUTPUT);
|
|
||||||
digitalWrite(sm16716_pin_clk, LOW);
|
|
||||||
|
|
||||||
pinMode(sm16716_pin_dat, OUTPUT);
|
|
||||||
digitalWrite(sm16716_pin_dat, LOW);
|
|
||||||
|
|
||||||
if (sm16716_pin_sel < 99) {
|
|
||||||
pinMode(sm16716_pin_sel, OUTPUT);
|
|
||||||
digitalWrite(sm16716_pin_sel, LOW);
|
|
||||||
// no need to call SM16716_Init here, it will be called after sel goes HIGH
|
|
||||||
} else {
|
|
||||||
// no sel pin means you have an 'always on' chip, so init right away
|
|
||||||
SM16716_Init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif // ifdef USE_SM16716
|
|
||||||
else {
|
else {
|
||||||
light_pdi_pin = pin[GPIO_DI];
|
light_pdi_pin = pin[GPIO_DI];
|
||||||
light_pdcki_pin = pin[GPIO_DCKI];
|
light_pdcki_pin = pin[GPIO_DCKI];
|
||||||
@ -2001,10 +1926,10 @@ void LightAnimate(void)
|
|||||||
|
|
||||||
// now apply the actual PWM values, adjusted and remapped 10-bits range
|
// now apply the actual PWM values, adjusted and remapped 10-bits range
|
||||||
if (light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix...
|
if (light_type < LT_PWM6) { // only for direct PWM lights, not for Tuya, Armtronix...
|
||||||
for (uint32_t i = 0; i < Light.subtype; i++) {
|
for (uint32_t i = 0; i < (Light.subtype - Light.pwm_offset); i++) {
|
||||||
if (pin[GPIO_PWM1 +i] < 99) {
|
if (pin[GPIO_PWM1 +i] < 99) {
|
||||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col_10bits[i], i+1, cur_col[i]);
|
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col_10bits[i], i+1, cur_col[i]);
|
||||||
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]);
|
analogWrite(pin[GPIO_PWM1 +i], bitRead(pwm_inverted, i) ? Settings.pwm_range - cur_col_10bits[(i + Light.pwm_offset)] : cur_col_10bits[(i + Light.pwm_offset)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2018,7 +1943,10 @@ void LightAnimate(void)
|
|||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "R%d G%d B%d, C%d W%d"),
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_DEBUG "R%d G%d B%d, C%d W%d"),
|
||||||
cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
||||||
|
|
||||||
if (XdrvCall(FUNC_SET_CHANNELS)) {
|
if (XlgtCall(FUNC_SET_CHANNELS)) {
|
||||||
|
// Serviced
|
||||||
|
}
|
||||||
|
else if (XdrvCall(FUNC_SET_CHANNELS)) {
|
||||||
// Serviced
|
// Serviced
|
||||||
}
|
}
|
||||||
#ifdef USE_WS2812 // ************************************************************************
|
#ifdef USE_WS2812 // ************************************************************************
|
||||||
@ -2026,19 +1954,6 @@ void LightAnimate(void)
|
|||||||
Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]);
|
Ws2812SetColor(0, cur_col[0], cur_col[1], cur_col[2], cur_col[3]);
|
||||||
}
|
}
|
||||||
#endif // USE_ES2812 ************************************************************************
|
#endif // USE_ES2812 ************************************************************************
|
||||||
#ifdef USE_SM16716
|
|
||||||
else if (LT_SM16716 == light_type - Light.subtype) {
|
|
||||||
// handle any PWM pins, skipping the first 3 values for sm16716
|
|
||||||
for (uint32_t i = 3; i < Light.subtype; i++) {
|
|
||||||
if (pin[GPIO_PWM1 +i-3] < 99) {
|
|
||||||
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col[i], i+1, curcol);
|
|
||||||
analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// handle sm16716 update
|
|
||||||
SM16716_Update(cur_col[0], cur_col[1], cur_col[2]);
|
|
||||||
}
|
|
||||||
#endif // ifdef USE_SM16716
|
|
||||||
else if (light_type > LT_WS2812) {
|
else if (light_type > LT_WS2812) {
|
||||||
//AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Cur_Col %d,%d,%d,%d,%d"), cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
//AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION "Cur_Col %d,%d,%d,%d,%d"), cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
||||||
LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
||||||
@ -2588,11 +2503,11 @@ bool Xdrv04(uint8_t function)
|
|||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (light_type) {
|
if (FUNC_MODULE_INIT == function) {
|
||||||
|
return LightModuleInit();
|
||||||
|
}
|
||||||
|
else if (light_type) {
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case FUNC_PRE_INIT:
|
|
||||||
LightInit();
|
|
||||||
break;
|
|
||||||
case FUNC_EVERY_50_MSECOND:
|
case FUNC_EVERY_50_MSECOND:
|
||||||
LightAnimate();
|
LightAnimate();
|
||||||
#ifdef USE_ARILUX_RF
|
#ifdef USE_ARILUX_RF
|
||||||
@ -2610,6 +2525,9 @@ bool Xdrv04(uint8_t function)
|
|||||||
case FUNC_COMMAND:
|
case FUNC_COMMAND:
|
||||||
result = DecodeCommand(kLightCommands, LightCommand);
|
result = DecodeCommand(kLightCommands, LightCommand);
|
||||||
break;
|
break;
|
||||||
|
case FUNC_PRE_INIT:
|
||||||
|
LightInit();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
200
sonoff/xlgt_03_sm16716.ino
Normal file
200
sonoff/xlgt_03_sm16716.ino
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
xlgt_03_sm16716.ino - sm16716 three channel led support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2019 Theo Arends
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_LIGHT
|
||||||
|
#ifdef USE_SM16716
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* SM16716 - Controlling RGB over a synchronous serial line
|
||||||
|
* Copyright (C) 2019 Gabor Simon
|
||||||
|
*
|
||||||
|
* Source: https://community.home-assistant.io/t/cheap-uk-wifi-bulbs-with-tasmota-teardown-help-tywe3s/40508/27
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
#define XLGT_03 3
|
||||||
|
|
||||||
|
#define D_LOG_SM16716 "SM16716: "
|
||||||
|
|
||||||
|
struct SM16716 {
|
||||||
|
uint8_t pin_clk = 0;
|
||||||
|
uint8_t pin_dat = 0;
|
||||||
|
uint8_t pin_sel = 0;
|
||||||
|
bool enabled = false;
|
||||||
|
} Sm16716;
|
||||||
|
|
||||||
|
void SM16716_SendBit(uint8_t v)
|
||||||
|
{
|
||||||
|
/* NOTE:
|
||||||
|
* According to the spec sheet, max freq is 30 MHz, that is 16.6 ns per high/low half of the
|
||||||
|
* clk square wave. That is less than the overhead of 'digitalWrite' at this clock rate,
|
||||||
|
* so no additional delays are needed yet. */
|
||||||
|
|
||||||
|
digitalWrite(Sm16716.pin_dat, (v != 0) ? HIGH : LOW);
|
||||||
|
//delayMicroseconds(1);
|
||||||
|
digitalWrite(Sm16716.pin_clk, HIGH);
|
||||||
|
//delayMicroseconds(1);
|
||||||
|
digitalWrite(Sm16716.pin_clk, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SM16716_SendByte(uint8_t v)
|
||||||
|
{
|
||||||
|
uint8_t mask;
|
||||||
|
|
||||||
|
for (mask = 0x80; mask; mask >>= 1) {
|
||||||
|
SM16716_SendBit(v & mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SM16716_Update(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b)
|
||||||
|
{
|
||||||
|
if (Sm16716.pin_sel < 99) {
|
||||||
|
bool should_enable = (duty_r | duty_g | duty_b);
|
||||||
|
if (!Sm16716.enabled && should_enable) {
|
||||||
|
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color on"));
|
||||||
|
Sm16716.enabled = true;
|
||||||
|
digitalWrite(Sm16716.pin_sel, HIGH);
|
||||||
|
// in testing I found it takes a minimum of ~380us to wake up the chip
|
||||||
|
// tested on a Merkury RGBW with an SM726EB
|
||||||
|
delayMicroseconds(1000);
|
||||||
|
SM16716_Init();
|
||||||
|
}
|
||||||
|
else if (Sm16716.enabled && !should_enable) {
|
||||||
|
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "turning color off"));
|
||||||
|
Sm16716.enabled = false;
|
||||||
|
digitalWrite(Sm16716.pin_sel, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "Update; rgb=%02x%02x%02x"), duty_r, duty_g, duty_b);
|
||||||
|
|
||||||
|
// send start bit
|
||||||
|
SM16716_SendBit(1);
|
||||||
|
SM16716_SendByte(duty_r);
|
||||||
|
SM16716_SendByte(duty_g);
|
||||||
|
SM16716_SendByte(duty_b);
|
||||||
|
|
||||||
|
// send a 'do it' pulse
|
||||||
|
// (if multiple chips are chained, each one processes the 1st '1rgb' 25-bit block and
|
||||||
|
// passes on the rest, right until the one starting with 0)
|
||||||
|
//SM16716_Init();
|
||||||
|
SM16716_SendBit(0);
|
||||||
|
SM16716_SendByte(0);
|
||||||
|
SM16716_SendByte(0);
|
||||||
|
SM16716_SendByte(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool SM16716_ModuleSelected(void)
|
||||||
|
{
|
||||||
|
Sm16716.pin_clk = pin[GPIO_SM16716_CLK];
|
||||||
|
Sm16716.pin_dat = pin[GPIO_SM16716_DAT];
|
||||||
|
Sm16716.pin_sel = pin[GPIO_SM16716_SEL];
|
||||||
|
DEBUG_DRIVER_LOG(PSTR(D_LOG_SM16716 "ModuleSelected; clk_pin=%d, dat_pin=%d)"), Sm16716.pin_clk, Sm16716.pin_dat);
|
||||||
|
return (Sm16716.pin_clk < 99) && (Sm16716.pin_dat < 99);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
void SM16716_Init(void)
|
||||||
|
{
|
||||||
|
for (uint32_t t_init = 0; t_init < 50; ++t_init) {
|
||||||
|
SM16716_SendBit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
bool Sm16716SetChannels(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// handle any PWM pins, skipping the first 3 values for sm16716
|
||||||
|
for (uint32_t i = 3; i < Light.subtype; i++) {
|
||||||
|
if (pin[GPIO_PWM1 +i-3] < 99) {
|
||||||
|
//AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION "Cur_Col%d 10 bits %d, Pwm%d %d"), i, cur_col[i], i+1, curcol);
|
||||||
|
analogWrite(pin[GPIO_PWM1 +i-3], bitRead(pwm_inverted, i-3) ? Settings.pwm_range - cur_col_10bits[i] : cur_col_10bits[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// handle sm16716 update
|
||||||
|
uint8_t *cur_col = (uint8_t*)XdrvMailbox.data;
|
||||||
|
|
||||||
|
SM16716_Update(cur_col[0], cur_col[1], cur_col[2]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sm16716ModuleSelected(void)
|
||||||
|
{
|
||||||
|
if ((pin[GPIO_SM16716_CLK] < 99) && (pin[GPIO_SM16716_DAT] < 99)) {
|
||||||
|
Sm16716.pin_clk = pin[GPIO_SM16716_CLK];
|
||||||
|
Sm16716.pin_dat = pin[GPIO_SM16716_DAT];
|
||||||
|
Sm16716.pin_sel = pin[GPIO_SM16716_SEL];
|
||||||
|
|
||||||
|
/*
|
||||||
|
// init PWM
|
||||||
|
for (uint32_t i = 0; i < Light.subtype; i++) {
|
||||||
|
Settings.pwm_value[i] = 0; // Disable direct PWM control
|
||||||
|
if (pin[GPIO_PWM1 +i] < 99) {
|
||||||
|
pinMode(pin[GPIO_PWM1 +i], OUTPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// init sm16716
|
||||||
|
pinMode(Sm16716.pin_clk, OUTPUT);
|
||||||
|
digitalWrite(Sm16716.pin_clk, LOW);
|
||||||
|
|
||||||
|
pinMode(Sm16716.pin_dat, OUTPUT);
|
||||||
|
digitalWrite(Sm16716.pin_dat, LOW);
|
||||||
|
|
||||||
|
if (Sm16716.pin_sel < 99) {
|
||||||
|
pinMode(Sm16716.pin_sel, OUTPUT);
|
||||||
|
digitalWrite(Sm16716.pin_sel, LOW);
|
||||||
|
// no need to call SM16716_Init here, it will be called after sel goes HIGH
|
||||||
|
} else {
|
||||||
|
// no sel pin means you have an 'always on' chip, so init right away
|
||||||
|
SM16716_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
LightPwmOffset(LST_RGB); // Handle any PWM pins, skipping the first 3 color values for sm16716
|
||||||
|
light_type += LST_RGB; // Add RGB to be controlled by sm16716
|
||||||
|
light_flg = XLGT_03;
|
||||||
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM16716 Found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************************************\
|
||||||
|
* Interface
|
||||||
|
\*********************************************************************************************/
|
||||||
|
|
||||||
|
bool Xlgt03(uint8_t function)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
switch (function) {
|
||||||
|
case FUNC_SET_CHANNELS:
|
||||||
|
result = Sm16716SetChannels();
|
||||||
|
break;
|
||||||
|
case FUNC_MODULE_INIT:
|
||||||
|
Sm16716ModuleSelected();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_SM16716
|
||||||
|
#endif // USE_LIGHT
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
xdrv_26_sm2135.ino - sm2135 five channel led support for Sonoff-Tasmota
|
xlgt_04_sm2135.ino - sm2135 five channel led support for Sonoff-Tasmota
|
||||||
|
|
||||||
Copyright (C) 2019 Theo Arends
|
Copyright (C) 2019 Theo Arends
|
||||||
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
* {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18}
|
* {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,181,0,180,0,0],"FLAG":0,"BASE":18}
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
#define XDRV_26 26
|
#define XLGT_04 4
|
||||||
|
|
||||||
#define SM2135_ADDR_MC 0xC0 // Max current register
|
#define SM2135_ADDR_MC 0xC0 // Max current register
|
||||||
#define SM2135_ADDR_CH 0xC1 // RGB or CW channel select register
|
#define SM2135_ADDR_CH 0xC1 // RGB or CW channel select register
|
||||||
@ -56,7 +56,6 @@ const uint8_t SM2135_CURRENT = (SM2135_20MA << 4) | SM2135_10MA;
|
|||||||
struct SM2135 {
|
struct SM2135 {
|
||||||
uint8_t clk = 0;
|
uint8_t clk = 0;
|
||||||
uint8_t data = 0;
|
uint8_t data = 0;
|
||||||
bool found = true;
|
|
||||||
} Sm2135;
|
} Sm2135;
|
||||||
|
|
||||||
uint8_t Sm2135Write(uint8_t data)
|
uint8_t Sm2135Write(uint8_t data)
|
||||||
@ -87,19 +86,21 @@ void Sm2135Send(uint8_t *buffer, uint8_t size)
|
|||||||
digitalWrite(Sm2135.data, HIGH);
|
digitalWrite(Sm2135.data, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
|
||||||
bool Sm2135SetChannels(void)
|
bool Sm2135SetChannels(void)
|
||||||
{
|
{
|
||||||
char *buffer = XdrvMailbox.data;
|
uint8_t *cur_col = (uint8_t*)XdrvMailbox.data;
|
||||||
uint8_t data[8];
|
uint8_t data[6];
|
||||||
|
|
||||||
if (('\0' == buffer[0]) && ('\0' == buffer[1]) && ('\0' == buffer[2])) {
|
if ((0 == cur_col[0]) && (0 == cur_col[1]) && (0 == cur_col[2])) {
|
||||||
// No color so must be Cold/Warm
|
// No color so must be Cold/Warm
|
||||||
/*
|
/*
|
||||||
if ((buffer[3] + buffer[4]) >= (1 * 256)) {
|
if ((cur_col[3] + cur_col[4]) >= (1 * 256)) {
|
||||||
// Scale down to 255 total to fix max power usage of 9W (=40mA)
|
// Scale down to 255 total to fix max power usage of 9W (=40mA)
|
||||||
|
|
||||||
// buffer[3] >>= 1; // Divide by 2
|
// cur_col[3] >>= 1; // Divide by 2
|
||||||
// buffer[4] >>= 1; // Divide by 2
|
// cur_col[4] >>= 1; // Divide by 2
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
data[0] = SM2135_ADDR_MC;
|
data[0] = SM2135_ADDR_MC;
|
||||||
@ -108,13 +109,13 @@ bool Sm2135SetChannels(void)
|
|||||||
Sm2135Send(data, 3);
|
Sm2135Send(data, 3);
|
||||||
delay(1);
|
delay(1);
|
||||||
data[0] = SM2135_ADDR_C;
|
data[0] = SM2135_ADDR_C;
|
||||||
data[1] = buffer[4]; // Warm
|
data[1] = cur_col[4]; // Warm
|
||||||
data[2] = buffer[3]; // Cold
|
data[2] = cur_col[3]; // Cold
|
||||||
Sm2135Send(data, 3);
|
Sm2135Send(data, 3);
|
||||||
} else {
|
} else {
|
||||||
// Color
|
// Color
|
||||||
/*
|
/*
|
||||||
if ((buffer[0] + buffer[1] + buffer[2]) >= (3 * 256)) {
|
if ((cur_col[0] + cur_col[1] + cur_col[2]) >= (3 * 256)) {
|
||||||
// Scale down to 765 total to fix max power usage of 9W
|
// Scale down to 765 total to fix max power usage of 9W
|
||||||
// Currently not needed with setting 3 x 15mA = 45mA = 11W = 765
|
// Currently not needed with setting 3 x 15mA = 45mA = 11W = 765
|
||||||
}
|
}
|
||||||
@ -122,16 +123,16 @@ bool Sm2135SetChannels(void)
|
|||||||
data[0] = SM2135_ADDR_MC;
|
data[0] = SM2135_ADDR_MC;
|
||||||
data[1] = SM2135_CURRENT;
|
data[1] = SM2135_CURRENT;
|
||||||
data[2] = SM2135_RGB;
|
data[2] = SM2135_RGB;
|
||||||
data[3] = buffer[1]; // Green
|
data[3] = cur_col[1]; // Green
|
||||||
data[4] = buffer[0]; // Red
|
data[4] = cur_col[0]; // Red
|
||||||
data[5] = buffer[2]; // Blue
|
data[5] = cur_col[2]; // Blue
|
||||||
Sm2135Send(data, 6);
|
Sm2135Send(data, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sm2135ModuleSelected(void)
|
void Sm2135ModuleSelected(void)
|
||||||
{
|
{
|
||||||
if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) {
|
if ((pin[GPIO_SM2135_CLK] < 99) && (pin[GPIO_SM2135_DAT] < 99)) {
|
||||||
Sm2135.clk = pin[GPIO_SM2135_CLK];
|
Sm2135.clk = pin[GPIO_SM2135_CLK];
|
||||||
@ -143,30 +144,26 @@ bool Sm2135ModuleSelected(void)
|
|||||||
digitalWrite(Sm2135.clk, HIGH);
|
digitalWrite(Sm2135.clk, HIGH);
|
||||||
|
|
||||||
light_type = LT_RGBWC;
|
light_type = LT_RGBWC;
|
||||||
|
light_flg = XLGT_04;
|
||||||
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found"));
|
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DBG: SM2135 Found"));
|
||||||
} else {
|
|
||||||
Sm2135.found = false;
|
|
||||||
}
|
}
|
||||||
return Sm2135.found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
\*********************************************************************************************/
|
\*********************************************************************************************/
|
||||||
|
|
||||||
bool Xdrv26(uint8_t function)
|
bool Xlgt04(uint8_t function)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (Sm2135.found) {
|
switch (function) {
|
||||||
switch (function) {
|
case FUNC_SET_CHANNELS:
|
||||||
case FUNC_SET_CHANNELS:
|
result = Sm2135SetChannels();
|
||||||
result = Sm2135SetChannels();
|
break;
|
||||||
break;
|
case FUNC_MODULE_INIT:
|
||||||
case FUNC_MODULE_INIT:
|
Sm2135ModuleSelected();
|
||||||
result = Sm2135ModuleSelected();
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
114
sonoff/xlgt_interface.ino
Normal file
114
sonoff/xlgt_interface.ino
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
xlgt_interface.ino - Light driver interface support for Sonoff-Tasmota
|
||||||
|
|
||||||
|
Copyright (C) 2019 Theo Arends
|
||||||
|
|
||||||
|
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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_LIGHT
|
||||||
|
|
||||||
|
#ifdef XFUNC_PTR_IN_ROM
|
||||||
|
bool (* const xlgt_func_ptr[])(uint8_t) PROGMEM = { // Light driver Function Pointers
|
||||||
|
#else
|
||||||
|
bool (* const xlgt_func_ptr[])(uint8_t) = { // Light driver Function Pointers
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_01
|
||||||
|
&Xlgt01,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_02
|
||||||
|
&Xlgt02,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_03
|
||||||
|
&Xlgt03,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_04
|
||||||
|
&Xlgt04,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_05
|
||||||
|
&Xlgt05,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_06
|
||||||
|
&Xlgt06,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_07
|
||||||
|
&Xlgt07,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_08
|
||||||
|
&Xlgt08,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_09
|
||||||
|
&Xlgt09,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_10
|
||||||
|
&Xlgt10,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_11
|
||||||
|
&Xlgt11,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_12
|
||||||
|
&Xlgt12,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_13
|
||||||
|
&Xlgt13,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_14
|
||||||
|
&Xlgt14,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_15
|
||||||
|
&Xlgt15,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef XLGT_16
|
||||||
|
&Xlgt16
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint8_t xlgt_present = sizeof(xlgt_func_ptr) / sizeof(xlgt_func_ptr[0]); // Number of drivers found
|
||||||
|
|
||||||
|
uint8_t xlgt_active = 0;
|
||||||
|
|
||||||
|
bool XlgtCall(uint8_t function)
|
||||||
|
{
|
||||||
|
if (FUNC_MODULE_INIT == function) {
|
||||||
|
for (uint32_t x = 0; x < xlgt_present; x++) {
|
||||||
|
xlgt_func_ptr[x](function);
|
||||||
|
if (light_flg) {
|
||||||
|
xlgt_active = x;
|
||||||
|
return true; // Stop further driver investigation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (light_flg) {
|
||||||
|
return xlgt_func_ptr[xlgt_active](function);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_LIGHT
|
Loading…
x
Reference in New Issue
Block a user