diff --git a/tasmota/i18n.h b/tasmota/i18n.h index b0b0cd666..a2e9e16b0 100644 --- a/tasmota/i18n.h +++ b/tasmota/i18n.h @@ -587,6 +587,11 @@ // Commands xsns_02_analog.ino #define D_CMND_ADCPARAM "AdcParam" +// Commands led pwm settings +#define D_CMND_SETLEDPWMOFF "LedPwmOff" +#define D_CMND_SETLEDPWMON "LedPwmOn" +#define D_CMND_SETLEDPWMMODE "LedPwmMode" + // xsns_70_veml6075.ino #define D_JSON_UVA_INTENSITY "UvaIntensity" #define D_JSON_UVB_INTENSITY "UvbItensity" diff --git a/tasmota/settings.h b/tasmota/settings.h index edd3de523..e8bae5182 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -569,8 +569,11 @@ struct { uint16_t windmeter_pulse_debounce; // F3A int16_t windmeter_speed_factor; // F3C uint8_t windmeter_tele_pchange; // F3E - - uint8_t free_f3f[121]; // F3F - Decrement if adding new Setting variables just above and below + uint8_t ledpwm_mask; // F3F + uint8_t ledpwm_on; // F40 + uint8_t ledpwm_off; // F41 + + uint8_t free_f42[118]; // F42 - Decrement if adding new Setting variables just above and below // Only 32 bit boundary variables below uint16_t pulse_counter_debounce_low; // FB8 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index 5214add7a..8d771a109 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -1055,6 +1055,11 @@ void SettingsDefaultSet2(void) Settings.flag2 = flag2; Settings.flag3 = flag3; Settings.flag4 = flag4; + + // Led PWM + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 255; + Settings.ledpwm_mask = 0; } /********************************************************************************************/ @@ -1411,6 +1416,13 @@ void SettingsDelta(void) if (Settings.rules[1][0] == 0) { Settings.rules[1][1] = 0; } if (Settings.rules[2][0] == 0) { Settings.rules[2][1] = 0; } } + + // ledpwm + if (Settings.version < 0x08030001) { + Settings.ledpwm_off = 0; + Settings.ledpwm_on = 255; + Settings.ledpwm_mask = 0; + } if (Settings.version < 0x08030002) { SettingsUpdateText(SET_DEVICENAME, SettingsText(SET_FRIENDLYNAME1)); @@ -1419,4 +1431,5 @@ void SettingsDelta(void) Settings.version = VERSION; SettingsSave(1); } + } diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f262b5fcb..f52fb7ea5 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -27,7 +27,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_DEVICENAME "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" - D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" + D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM "|" D_CMND_SETLEDPWMON "|" D_CMND_SETLEDPWMOFF "|" D_CMND_SETLEDPWMMODE "|" #ifdef USE_I2C D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|" #endif @@ -50,7 +50,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = { &CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndDevicename, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset, &CmndHumOffset, - &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, + &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndSetLedPwmOn, &CmndSetLedPwmOff, &CmndSetLedPwmMode, #ifdef USE_I2C &CmndI2cScan, CmndI2cDriver, #endif @@ -1890,3 +1890,57 @@ void CmndDriver(void) { XdrvCall(FUNC_COMMAND_DRIVER); } + +void CmndSetLedPwmOff(void) +{ + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { + Settings.ledpwm_off = 0; + } else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_off = 255; + } else { + Settings.ledpwm_off = XdrvMailbox.payload; + } + UpdateLedPowerAll(); + } + ResponseCmndNumber(Settings.ledpwm_off); +} + +void CmndSetLedPwmOn(void) +{ + if (XdrvMailbox.data_len > 0) { + if (XdrvMailbox.payload < 0) { + Settings.ledpwm_on = 0; + } else if (XdrvMailbox.payload > 255) { + Settings.ledpwm_on = 255; + } else { + Settings.ledpwm_on = XdrvMailbox.payload; + } + UpdateLedPowerAll(); + } + ResponseCmndNumber(Settings.ledpwm_on); +} + +void CmndSetLedPwmMode(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_LEDS)) { + if (!PinUsed(GPIO_LEDLNK)) { XdrvMailbox.index = 1; } + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { + uint32_t mask = 1 << (XdrvMailbox.index -1); // Led to configure + switch (XdrvMailbox.payload) { + case 0: // digital + Settings.ledpwm_mask &= (0xFF ^ mask); + break; + case 1: // pwm + Settings.ledpwm_mask |= mask; + break; + case 2: // toggle + Settings.ledpwm_mask ^= mask; + break; + } + UpdateLedPowerAll(); + } + bool state = bitRead(Settings.ledpwm_mask, XdrvMailbox.index -1); + ResponseCmndIdxChar(GetStateText(state)); + } +} diff --git a/tasmota/support_tasmota.ino b/tasmota/support_tasmota.ino index 90df92a37..374cb6884 100644 --- a/tasmota/support_tasmota.ino +++ b/tasmota/support_tasmota.ino @@ -336,6 +336,13 @@ void SetPowerOnState(void) blink_powersave = power; } +void UpdateLedPowerAll() +{ + for (uint32_t i = 0; i < leds_present; i++) { + SetLedPowerIdx(i, bitRead(led_power, i)); + } +} + void SetLedPowerIdx(uint32_t led, uint32_t state) { if (!PinUsed(GPIO_LEDLNK) && (0 == led)) { // Legacy - LED1 is link led only if LED2 is present @@ -351,7 +358,17 @@ void SetLedPowerIdx(uint32_t led, uint32_t state) } else { led_power &= (0xFF ^ mask); } - DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + uint16_t pwm = 0; + if (bitRead(Settings.ledpwm_mask, led)) { + #ifdef USE_LIGHT + pwm = changeUIntScale(ledGamma10(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 1023, 0, Settings.pwm_range); // gamma corrected + #else //USE_LIGHT + pwm = changeUIntScale((uint16_t)(state ? Settings.ledpwm_on : Settings.ledpwm_off), 0, 255, 0, Settings.pwm_range); // linear + #endif //USE_LIGHT + analogWrite(Pin(GPIO_LED1, led), bitRead(led_inverted, led) ? Settings.pwm_range - pwm : pwm); + } else { + DigitalWrite(GPIO_LED1, led, bitRead(led_inverted, led) ? !state : state); + } } #ifdef USE_BUZZER if (led == 0) { @@ -386,10 +403,8 @@ void SetLedLink(uint32_t state) uint32_t led_pin = Pin(GPIO_LEDLNK); uint32_t led_inv = ledlnk_inverted; if (99 == led_pin) { // Legacy - LED1 is status - led_pin = Pin(GPIO_LED1); - led_inv = bitRead(led_inverted, 0); - } - if (led_pin < 99) { + SetLedPowerIdx(0, state); + } else if (led_pin < 99) { if (state) { state = 1; } digitalWrite(led_pin, (led_inv) ? !state : state); } diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index ecf1127ec..92e3169b2 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -1,4 +1,4 @@ -/* + /* tasmota.ino - Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware Copyright (C) 2020 Theo Arends