2019-10-06 17:05:17 +01:00
|
|
|
/*
|
2019-10-27 10:13:24 +00:00
|
|
|
xlgt_02_my92x1.ino - led support for Tasmota
|
2019-10-06 17:05:17 +01:00
|
|
|
|
2021-01-01 12:44:04 +00:00
|
|
|
Copyright (C) 2021 Theo Arends
|
2019-10-06 17:05:17 +01:00
|
|
|
|
|
|
|
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_MY92X1
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Sonoff B1 and AiLight inspired by OpenLight https://github.com/icamgo/noduino-sdk
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
|
|
|
#define XLGT_02 2
|
|
|
|
|
|
|
|
struct MY92X1 {
|
2021-02-14 12:06:19 +00:00
|
|
|
int8_t pdi_pin = 0;
|
|
|
|
int8_t pdcki_pin = 0;
|
2019-10-07 10:51:08 +01:00
|
|
|
uint8_t model = 0;
|
2019-10-06 17:05:17 +01:00
|
|
|
} My92x1;
|
|
|
|
|
2024-05-15 15:45:42 +01:00
|
|
|
#ifdef ESP32
|
2023-08-21 16:10:06 +01:00
|
|
|
#include "rom/ets_sys.h"
|
|
|
|
#ifndef os_delay_us
|
|
|
|
#define os_delay_us ets_delay_us
|
|
|
|
#endif //os_delay_us
|
2024-05-15 15:45:42 +01:00
|
|
|
#else // ESP8266
|
2019-10-06 17:05:17 +01:00
|
|
|
extern "C" {
|
|
|
|
void os_delay_us(unsigned int);
|
|
|
|
}
|
2024-05-15 15:45:42 +01:00
|
|
|
#endif // ESP8266
|
2019-10-06 17:05:17 +01:00
|
|
|
|
|
|
|
void LightDiPulse(uint8_t times)
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < times; i++) {
|
|
|
|
digitalWrite(My92x1.pdi_pin, HIGH);
|
|
|
|
digitalWrite(My92x1.pdi_pin, LOW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightDckiPulse(uint8_t times)
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < times; i++) {
|
|
|
|
digitalWrite(My92x1.pdcki_pin, HIGH);
|
|
|
|
digitalWrite(My92x1.pdcki_pin, LOW);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightMy92x1Write(uint8_t data)
|
|
|
|
{
|
|
|
|
for (uint32_t i = 0; i < 4; i++) { // Send 8bit Data
|
|
|
|
digitalWrite(My92x1.pdcki_pin, LOW);
|
|
|
|
digitalWrite(My92x1.pdi_pin, (data & 0x80));
|
|
|
|
digitalWrite(My92x1.pdcki_pin, HIGH);
|
|
|
|
data = data << 1;
|
|
|
|
digitalWrite(My92x1.pdi_pin, (data & 0x80));
|
|
|
|
digitalWrite(My92x1.pdcki_pin, LOW);
|
|
|
|
digitalWrite(My92x1.pdi_pin, LOW);
|
|
|
|
data = data << 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightMy92x1Init(void)
|
|
|
|
{
|
2019-10-07 10:51:08 +01:00
|
|
|
uint8_t chips[3] = { 1, 2, 2 };
|
2019-10-06 17:05:17 +01:00
|
|
|
|
2019-10-07 10:51:08 +01:00
|
|
|
LightDckiPulse(chips[My92x1.model] * 32); // Clear all duty register
|
2019-10-06 17:05:17 +01:00
|
|
|
os_delay_us(12); // TStop > 12us.
|
|
|
|
// Send 12 DI pulse, after 6 pulse's falling edge store duty data, and 12
|
|
|
|
// pulse's rising edge convert to command mode.
|
|
|
|
LightDiPulse(12);
|
|
|
|
os_delay_us(12); // Delay >12us, begin send CMD data
|
2019-10-07 10:51:08 +01:00
|
|
|
for (uint32_t n = 0; n < chips[My92x1.model]; n++) { // Send CMD data
|
2019-10-06 17:05:17 +01:00
|
|
|
LightMy92x1Write(0x18); // ONE_SHOT_DISABLE, REACTION_FAST, BIT_WIDTH_8, FREQUENCY_DIVIDE_1, SCATTER_APDM
|
|
|
|
}
|
|
|
|
os_delay_us(12); // TStart > 12us. Delay 12 us.
|
|
|
|
// Send 16 DI pulse, at 14 pulse's falling edge store CMD data, and
|
|
|
|
// at 16 pulse's falling edge convert to duty mode.
|
|
|
|
LightDiPulse(16);
|
|
|
|
os_delay_us(12); // TStop > 12us.
|
|
|
|
}
|
|
|
|
|
|
|
|
void LightMy92x1Duty(uint8_t duty_r, uint8_t duty_g, uint8_t duty_b, uint8_t duty_w, uint8_t duty_c)
|
|
|
|
{
|
2019-10-07 10:51:08 +01:00
|
|
|
uint8_t channels[3] = { 4, 6, 6 };
|
2019-10-06 17:05:17 +01:00
|
|
|
|
2019-10-07 10:51:08 +01:00
|
|
|
uint8_t duty[3][6] = {{ duty_r, duty_g, duty_b, duty_w, 0, 0 }, // Definition for RGBW channels
|
|
|
|
{ duty_w, duty_c, 0, duty_g, duty_r, duty_b }, // Definition for RGBWC channels
|
|
|
|
{ duty_r, duty_g, duty_b, duty_w, duty_w, duty_w }}; // Definition for RGBWWW channels as used in Lohas which uses up to 3 CW channels
|
2019-10-06 17:05:17 +01:00
|
|
|
|
|
|
|
os_delay_us(12); // TStop > 12us.
|
2019-10-07 10:51:08 +01:00
|
|
|
for (uint32_t channel = 0; channel < channels[My92x1.model]; channel++) {
|
|
|
|
LightMy92x1Write(duty[My92x1.model][channel]); // Send 8bit Data
|
2019-10-06 17:05:17 +01:00
|
|
|
}
|
|
|
|
os_delay_us(12); // TStart > 12us. Ready for send DI pulse.
|
|
|
|
LightDiPulse(8); // Send 8 DI pulse. After 8 pulse falling edge, store old data.
|
|
|
|
os_delay_us(12); // TStop > 12us.
|
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************************************/
|
|
|
|
|
|
|
|
bool My92x1SetChannels(void)
|
|
|
|
{
|
|
|
|
uint8_t *cur_col = (uint8_t*)XdrvMailbox.data;
|
|
|
|
|
|
|
|
LightMy92x1Duty(cur_col[0], cur_col[1], cur_col[2], cur_col[3], cur_col[4]);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void My92x1ModuleSelected(void)
|
|
|
|
{
|
2020-04-27 11:54:07 +01:00
|
|
|
if (PinUsed(GPIO_DCKI) && PinUsed(GPIO_DI)) {
|
2020-04-27 10:54:23 +01:00
|
|
|
My92x1.pdi_pin = Pin(GPIO_DI);
|
|
|
|
My92x1.pdcki_pin = Pin(GPIO_DCKI);
|
2019-10-06 17:05:17 +01:00
|
|
|
|
|
|
|
pinMode(My92x1.pdi_pin, OUTPUT);
|
|
|
|
pinMode(My92x1.pdcki_pin, OUTPUT);
|
|
|
|
digitalWrite(My92x1.pdi_pin, LOW);
|
|
|
|
digitalWrite(My92x1.pdcki_pin, LOW);
|
|
|
|
|
2019-10-07 10:51:08 +01:00
|
|
|
My92x1.model = 2;
|
2021-12-19 15:57:57 +00:00
|
|
|
TasmotaGlobal.light_type = LT_RGBW; // RGBW (2 chips) as used in Lohas
|
|
|
|
#ifdef ESP8266
|
2020-10-30 11:29:48 +00:00
|
|
|
if (AILIGHT == TasmotaGlobal.module_type) { // RGBW (1 chip) as used in Ailight
|
2019-10-07 10:51:08 +01:00
|
|
|
My92x1.model = 0;
|
2020-10-30 11:29:48 +00:00
|
|
|
// TasmotaGlobal.light_type = LT_RGBW;
|
2019-10-06 17:05:17 +01:00
|
|
|
}
|
2020-10-30 11:29:48 +00:00
|
|
|
else if (SONOFF_B1 == TasmotaGlobal.module_type) { // RGBWC (2 chips) as used in Sonoff B1
|
2019-10-07 10:51:08 +01:00
|
|
|
My92x1.model = 1;
|
2020-10-30 11:29:48 +00:00
|
|
|
TasmotaGlobal.light_type = LT_RGBWC;
|
2019-10-06 17:05:17 +01:00
|
|
|
}
|
2021-12-19 15:57:57 +00:00
|
|
|
#endif // ESP8266
|
2019-10-07 10:56:20 +01:00
|
|
|
|
|
|
|
LightMy92x1Init();
|
|
|
|
|
2020-10-30 11:29:48 +00:00
|
|
|
TasmotaGlobal.light_driver = XLGT_02;
|
2021-01-23 16:10:06 +00:00
|
|
|
AddLog(LOG_LEVEL_DEBUG, PSTR("DBG: MY29x1 Found"));
|
2019-10-06 17:05:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*********************************************************************************************\
|
|
|
|
* Interface
|
|
|
|
\*********************************************************************************************/
|
|
|
|
|
2022-11-11 09:44:56 +00:00
|
|
|
bool Xlgt02(uint32_t function)
|
2019-10-06 17:05:17 +01:00
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
switch (function) {
|
|
|
|
case FUNC_SET_CHANNELS:
|
|
|
|
result = My92x1SetChannels();
|
|
|
|
break;
|
|
|
|
case FUNC_MODULE_INIT:
|
|
|
|
My92x1ModuleSelected();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // USE_MY92X1
|
|
|
|
#endif // USE_LIGHT
|