1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 04:34:43 +04:00

Start working on combining rgb_backlight and original_backlight.

This commit is contained in:
Dmitry422
2025-02-28 23:14:18 +07:00
parent edd42d34c6
commit 3c7d9e63fb
7 changed files with 571 additions and 17 deletions

View File

@@ -9,6 +9,7 @@
#include "notification.h" #include "notification.h"
#include "notification_messages.h" #include "notification_messages.h"
#include "notification_app.h" #include "notification_app.h"
#include "applications/settings/notification_settings/rgb_backlight.h"
#define TAG "NotificationSrv" #define TAG "NotificationSrv"
@@ -616,6 +617,7 @@ int32_t notification_srv(void* p) {
break; break;
case SaveSettingsMessage: case SaveSettingsMessage:
notification_save_settings(app); notification_save_settings(app);
rgb_backlight_save_settings();
break; break;
case LoadSettingsMessage: case LoadSettingsMessage:
notification_load_settings(app); notification_load_settings(app);

View File

@@ -3,6 +3,7 @@
#include <gui/modules/variable_item_list.h> #include <gui/modules/variable_item_list.h>
#include <gui/view_dispatcher.h> #include <gui/view_dispatcher.h>
#include <lib/toolbox/value_index.h> #include <lib/toolbox/value_index.h>
#include <applications/settings/notification_settings/rgb_backlight.h>
#define MAX_NOTIFICATION_SETTINGS 4 #define MAX_NOTIFICATION_SETTINGS 4
@@ -13,6 +14,8 @@ typedef struct {
VariableItemList* variable_item_list; VariableItemList* variable_item_list;
} NotificationAppSettings; } NotificationAppSettings;
static VariableItem* temp_item;
static const NotificationSequence sequence_note_c = { static const NotificationSequence sequence_note_c = {
&message_note_c5, &message_note_c5,
&message_delay_100, &message_delay_100,
@@ -168,6 +171,59 @@ static void vibro_changed(VariableItem* item) {
notification_message(app->notification, &sequence_single_vibro); notification_message(app->notification, &sequence_single_vibro);
} }
// Set RGB backlight color
static void color_changed(VariableItem* item) {
NotificationAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
rgb_backlight_set_color(index);
variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
notification_message(app->notification, &sequence_display_backlight_on);
}
// TODO: refactor and fix this
static void color_set_custom_red(VariableItem* item) {
NotificationAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
rgb_backlight_set_custom_color(index, 0);
char valtext[4] = {};
snprintf(valtext, sizeof(valtext), "%d", index);
variable_item_set_current_value_text(item, valtext);
rgb_backlight_set_color(13);
rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
// Set to custom color explicitly
variable_item_set_current_value_index(temp_item, 13);
variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
notification_message(app->notification, &sequence_display_backlight_on);
}
static void color_set_custom_green(VariableItem* item) {
NotificationAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
rgb_backlight_set_custom_color(index, 1);
char valtext[4] = {};
snprintf(valtext, sizeof(valtext), "%d", index);
variable_item_set_current_value_text(item, valtext);
rgb_backlight_set_color(13);
rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
// Set to custom color explicitly
variable_item_set_current_value_index(temp_item, 13);
variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
notification_message(app->notification, &sequence_display_backlight_on);
}
static void color_set_custom_blue(VariableItem* item) {
NotificationAppSettings* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
rgb_backlight_set_custom_color(index, 2);
char valtext[4] = {};
snprintf(valtext, sizeof(valtext), "%d", index);
variable_item_set_current_value_text(item, valtext);
rgb_backlight_set_color(13);
rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
// Set to custom color explicitly
variable_item_set_current_value_index(temp_item, 13);
variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
notification_message(app->notification, &sequence_display_backlight_on);
}
static uint32_t notification_app_settings_exit(void* context) { static uint32_t notification_app_settings_exit(void* context) {
UNUSED(context); UNUSED(context);
return VIEW_NONE; return VIEW_NONE;
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings(void) {
variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, contrast_text[value_index]); variable_item_set_current_value_text(item, contrast_text[value_index]);
// RGB Colors
item = variable_item_list_add( item = variable_item_list_add(
app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app); app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
value_index = rgb_backlight_get_settings()->display_color_index;
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, rgb_backlight_get_color_text(value_index));
temp_item = item;
// Custom Color - REFACTOR THIS
item = variable_item_list_add(
app->variable_item_list, "Custom Red", 255, color_set_custom_red, app);
value_index = rgb_backlight_get_settings()->custom_r;
variable_item_set_current_value_index(item, value_index);
char valtext[4] = {};
snprintf(valtext, sizeof(valtext), "%d", value_index);
variable_item_set_current_value_text(item, valtext);
item = variable_item_list_add(
app->variable_item_list, "Custom Green", 255, color_set_custom_green, app);
value_index = rgb_backlight_get_settings()->custom_g;
variable_item_set_current_value_index(item, value_index);
snprintf(valtext, sizeof(valtext), "%d", value_index);
variable_item_set_current_value_text(item, valtext);
item = variable_item_list_add(
app->variable_item_list, "Custom Blue", 255, color_set_custom_blue, app);
value_index = rgb_backlight_get_settings()->custom_b;
variable_item_set_current_value_index(item, value_index);
snprintf(valtext, sizeof(valtext), "%d", value_index);
variable_item_set_current_value_text(item, valtext);
// End of RGB
item = variable_item_list_add(
app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
value_index = value_index_float( value_index = value_index_float(
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT); app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_index(item, value_index);

View File

@@ -0,0 +1,217 @@
/*
RGB backlight FlipperZero driver
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
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 <https://www.gnu.org/licenses/>.
*/
#include "rgb_backlight.h"
#include <furi_hal.h>
#include <storage/storage.h>
#define RGB_BACKLIGHT_SETTINGS_VERSION 6
#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
#define TAG "RGB Backlight"
static RGBBacklightSettings rgb_settings = {
.version = RGB_BACKLIGHT_SETTINGS_VERSION,
.display_color_index = 0,
.custom_r = 254,
.custom_g = 254,
.custom_b = 254,
.settings_is_loaded = false};
static const RGBBacklightColor colors[] = {
{"Orange", 255, 60, 0},
{"Yellow", 255, 144, 0},
{"Spring", 167, 255, 0},
{"Lime", 0, 255, 0},
{"Aqua", 0, 255, 127},
{"Cyan", 0, 210, 210},
{"Azure", 0, 127, 255},
{"Blue", 0, 0, 255},
{"Purple", 127, 0, 255},
{"Magenta", 210, 0, 210},
{"Pink", 255, 0, 127},
{"Red", 255, 0, 0},
{"White", 254, 210, 200},
{"Custom", 0, 0, 0},
};
uint8_t rgb_backlight_get_color_count(void) {
return COLOR_COUNT;
}
const char* rgb_backlight_get_color_text(uint8_t index) {
return colors[index].name;
}
void rgb_backlight_load_settings(void) {
// Do not load settings if we are in other boot modes than normal
if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
rgb_settings.settings_is_loaded = true;
return;
}
// Wait for all required services to start and create their records
uint8_t timeout = 0;
while(!furi_record_exists(RECORD_STORAGE)) {
timeout++;
if(timeout > 150) {
rgb_settings.settings_is_loaded = true;
return;
}
furi_delay_ms(5);
}
RGBBacklightSettings settings;
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
const size_t settings_size = sizeof(RGBBacklightSettings);
FURI_LOG_D(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
bool fs_result =
storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
if(fs_result) {
uint16_t bytes_count = storage_file_read(file, &settings, settings_size);
if(bytes_count != settings_size) {
fs_result = false;
}
}
if(fs_result) {
FURI_LOG_D(TAG, "load success");
if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
FURI_LOG_E(
TAG,
"version(%d != %d) mismatch",
settings.version,
RGB_BACKLIGHT_SETTINGS_VERSION);
} else {
memcpy(&rgb_settings, &settings, settings_size);
}
} else {
FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file));
}
storage_file_close(file);
storage_file_free(file);
furi_record_close(RECORD_STORAGE);
rgb_settings.settings_is_loaded = true;
}
void rgb_backlight_save_settings(void) {
RGBBacklightSettings settings;
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
const size_t settings_size = sizeof(RGBBacklightSettings);
FURI_LOG_D(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
memcpy(&settings, &rgb_settings, settings_size);
bool fs_result =
storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS);
if(fs_result) {
uint16_t bytes_count = storage_file_write(file, &settings, settings_size);
if(bytes_count != settings_size) {
fs_result = false;
}
}
if(fs_result) {
FURI_LOG_D(TAG, "save success");
} else {
FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
}
storage_file_close(file);
storage_file_free(file);
furi_record_close(RECORD_STORAGE);
}
RGBBacklightSettings* rgb_backlight_get_settings(void) {
if(!rgb_settings.settings_is_loaded) {
rgb_backlight_load_settings();
}
return &rgb_settings;
}
void rgb_backlight_set_color(uint8_t color_index) {
if(color_index > (rgb_backlight_get_color_count() - 1)) color_index = 0;
rgb_settings.display_color_index = color_index;
}
void rgb_backlight_set_custom_color(uint8_t color, uint8_t index) {
if(index > 2) return;
if(index == 0) {
rgb_settings.custom_r = color;
} else if(index == 1) {
rgb_settings.custom_g = color;
} else if(index == 2) {
rgb_settings.custom_b = color;
}
}
void rgb_backlight_update(uint8_t brightness, bool bypass) {
if(!rgb_settings.settings_is_loaded) {
rgb_backlight_load_settings();
}
if(!bypass) {
static uint8_t last_color_index = 255;
static uint8_t last_brightness = 123;
if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index) {
return;
}
last_brightness = brightness;
last_color_index = rgb_settings.display_color_index;
}
for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
if(rgb_settings.display_color_index == 13) {
uint8_t r = rgb_settings.custom_r * (brightness / 255.0f);
uint8_t g = rgb_settings.custom_g * (brightness / 255.0f);
uint8_t b = rgb_settings.custom_b * (brightness / 255.0f);
SK6805_set_led_color(i, r, g, b);
} else {
if((colors[rgb_settings.display_color_index].red == 0) &&
(colors[rgb_settings.display_color_index].green == 0) &&
(colors[rgb_settings.display_color_index].blue == 0)) {
uint8_t r = colors[0].red * (brightness / 255.0f);
uint8_t g = colors[0].green * (brightness / 255.0f);
uint8_t b = colors[0].blue * (brightness / 255.0f);
SK6805_set_led_color(i, r, g, b);
} else {
uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
SK6805_set_led_color(i, r, g, b);
}
}
}
SK6805_update();
}

View File

@@ -0,0 +1,91 @@
/*
RGB backlight FlipperZero driver
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
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 <https://www.gnu.org/licenses/>.
*/
#include <furi.h>
#include "SK6805.h"
typedef struct {
char* name;
uint8_t red;
uint8_t green;
uint8_t blue;
} RGBBacklightColor;
typedef struct {
uint8_t version;
uint8_t display_color_index;
uint8_t custom_r;
uint8_t custom_g;
uint8_t custom_b;
bool settings_is_loaded;
} RGBBacklightSettings;
/**
* @brief Получить текущие настройки RGB-подсветки
*
* @return Указатель на структуру настроек
*/
RGBBacklightSettings* rgb_backlight_get_settings(void);
/**
* @brief Загрузить настройки подсветки с SD-карты
*/
void rgb_backlight_load_settings(void);
/**
* @brief Сохранить текущие настройки RGB-подсветки
*/
void rgb_backlight_save_settings(void);
/**
* @brief Применить текущие настройки RGB-подсветки
*
* @param brightness Яркость свечения (0-255)
* @param bypass Применить настройки принудительно
*/
void rgb_backlight_update(uint8_t brightness, bool bypass);
/**
* @brief Установить цвет RGB-подсветки
*
* @param color_index Индекс цвета (0 - rgb_backlight_get_color_count())
*/
void rgb_backlight_set_color(uint8_t color_index);
/**
* @brief Set custom color values by index - 0=R 1=G 2=B
*
* @param color - color value (0-255)
* @param index - color index (0-2) 0=R 1=G 2=B
*/
void rgb_backlight_set_custom_color(uint8_t color, uint8_t index);
/**
* @brief Получить количество доступных цветов
*
* @return Число доступных вариантов цвета
*/
uint8_t rgb_backlight_get_color_count(void);
/**
* @brief Получить текстовое название цвета
*
* @param index Индекс из доступных вариантов цвета
* @return Указатель на строку с названием цвета
*/
const char* rgb_backlight_get_color_text(uint8_t index);

103
lib/drivers/SK6805.c Normal file
View File

@@ -0,0 +1,103 @@
/*
SK6805 FlipperZero driver
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
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 <https://www.gnu.org/licenses/>.
*/
#include "SK6805.h"
#include <furi_hal.h>
/* Настройки */
#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
#ifdef FURI_DEBUG
#define DEBUG_PIN &gpio_ext_pa7
#define DEBUG_INIT() \
furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
#else
#define DEBUG_INIT()
#define DEBUG_SET_HIGH()
#define DEBUG_SET_LOW()
#endif
static const GpioPin led_pin = {.port = GPIOA, .pin = LL_GPIO_PIN_8};
static uint8_t led_buffer[SK6805_LED_COUNT][3];
void SK6805_init(void) {
DEBUG_INIT();
furi_hal_gpio_write(SK6805_LED_PIN, false);
furi_hal_gpio_init(SK6805_LED_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
}
uint8_t SK6805_get_led_count(void) {
return (const uint8_t)SK6805_LED_COUNT;
}
void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b) {
furi_check(led_index < SK6805_LED_COUNT);
led_buffer[led_index][0] = g;
led_buffer[led_index][1] = r;
led_buffer[led_index][2] = b;
}
void SK6805_update(void) {
SK6805_init();
FURI_CRITICAL_ENTER();
furi_delay_us(150);
uint32_t end;
/* Последовательная отправка цветов светодиодов */
for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
//Последовательная отправка цветов светодиода
for(uint8_t color = 0; color < 3; color++) {
//Последовательная отправка битов цвета
uint8_t i = 0b10000000;
while(i != 0) {
if(led_buffer[lednumber][color] & (i)) {
furi_hal_gpio_write(SK6805_LED_PIN, true);
DEBUG_SET_HIGH();
end = DWT->CYCCNT + 30;
//T1H 600 us (615 us)
while(DWT->CYCCNT < end) {
}
furi_hal_gpio_write(SK6805_LED_PIN, false);
DEBUG_SET_LOW();
end = DWT->CYCCNT + 26;
//T1L 600 us (587 us)
while(DWT->CYCCNT < end) {
}
} else {
furi_hal_gpio_write(SK6805_LED_PIN, true);
DEBUG_SET_HIGH();
end = DWT->CYCCNT + 11;
//T0H 300 ns (312 ns)
while(DWT->CYCCNT < end) {
}
furi_hal_gpio_write(SK6805_LED_PIN, false);
DEBUG_SET_LOW();
end = DWT->CYCCNT + 43;
//T0L 900 ns (890 ns)
while(DWT->CYCCNT < end) {
}
}
i >>= 1;
}
}
}
furi_delay_us(150);
FURI_CRITICAL_EXIT();
}

51
lib/drivers/SK6805.h Normal file
View File

@@ -0,0 +1,51 @@
/*
SK6805 FlipperZero driver
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
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 <https://www.gnu.org/licenses/>.
*/
#ifndef SK6805_H_
#define SK6805_H_
#include <furi.h>
/**
* @brief Инициализация линии управления подсветкой
*/
void SK6805_init(void);
/**
* @brief Получить количество светодиодов в подсветке
*
* @return Количество светодиодов
*/
uint8_t SK6805_get_led_count(void);
/**
* @brief Установить цвет свечения светодиода
*
* @param led_index номер светодиода (от 0 до SK6805_get_led_count())
* @param r значение красного (0-255)
* @param g значение зелёного (0-255)
* @param b значение синего (0-255)
*/
void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
/**
* @brief Обновление состояния подсветки дисплея
*/
void SK6805_update(void);
#endif /* SK6805_H_ */

View File

@@ -3,6 +3,7 @@
#include <furi_hal_light.h> #include <furi_hal_light.h>
#include <lp5562.h> #include <lp5562.h>
#include <stdint.h> #include <stdint.h>
#include <applications/settings/notification_settings/rgb_backlight.h>
#define LED_CURRENT_RED (50u) #define LED_CURRENT_RED (50u)
#define LED_CURRENT_GREEN (50u) #define LED_CURRENT_GREEN (50u)
@@ -45,6 +46,7 @@ void furi_hal_light_set(Light light, uint8_t value) {
uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite); uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
lp5562_execute_ramp( lp5562_execute_ramp(
&furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100); &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
rgb_backlight_update(value, false);
} }
furi_hal_i2c_release(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power);
} }