mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-07-29 02:08:10 -07:00
Merge branch 'dev' into xtruan/eurocorp_menu
This commit is contained in:
@@ -19,9 +19,10 @@
|
||||
#include "SK6805.h"
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "SK6805"
|
||||
|
||||
/* Настройки */
|
||||
#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||
#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||
#define SK6805_LED_PIN &led_pin // LED connection port
|
||||
|
||||
#ifdef FURI_DEBUG
|
||||
#define DEBUG_PIN &gpio_ext_pa7
|
||||
@@ -53,17 +54,18 @@ void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b) {
|
||||
led_buffer[led_index][0] = g;
|
||||
led_buffer[led_index][1] = r;
|
||||
led_buffer[led_index][2] = b;
|
||||
FURI_LOG_T(TAG, "led: %d, r: %d, g: %d, b: %d", led_index, r, g, b);
|
||||
}
|
||||
|
||||
void SK6805_update(void) {
|
||||
SK6805_init();
|
||||
furi_kernel_lock();
|
||||
uint32_t end;
|
||||
/* Последовательная отправка цветов светодиодов */
|
||||
// Sequential sending LEDs
|
||||
for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
||||
//Последовательная отправка цветов светодиода
|
||||
// Sequential sending colors
|
||||
for(uint8_t color = 0; color < 3; color++) {
|
||||
//Последовательная отправка битов цвета
|
||||
// Sequentially sending color bits
|
||||
uint8_t i = 0b10000000;
|
||||
while(i != 0) {
|
||||
if(led_buffer[lednumber][color] & (i)) {
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||
|
||||
/**
|
||||
* @brief Инициализация линии управления подсветкой
|
||||
*/
|
||||
@@ -48,4 +50,4 @@ void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||
*/
|
||||
void SK6805_update(void);
|
||||
|
||||
#endif /* SK6805_H_ */
|
||||
#endif /* SK6805_H_ */
|
||||
|
||||
+209
-121
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
RGB backlight FlipperZero driver
|
||||
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
Heavily modified by Willy-JL and Z3bro
|
||||
|
||||
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
|
||||
@@ -19,156 +20,243 @@
|
||||
#include "rgb_backlight.h"
|
||||
#include <furi_hal.h>
|
||||
#include <storage/storage.h>
|
||||
#include <toolbox/saved_struct.h>
|
||||
|
||||
#define RGB_BACKLIGHT_SETTINGS_VERSION 5
|
||||
#define RGB_BACKLIGHT_SETTINGS_MAGIC 0x15
|
||||
#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||
#define RGB_BACKLIGHT_SETTINGS_PATH CFG_PATH("rgb_backlight.settings")
|
||||
|
||||
#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||
|
||||
#define TAG "RGB Backlight"
|
||||
|
||||
static RGBBacklightSettings rgb_settings = {
|
||||
.version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||
.display_color_index = 0,
|
||||
.settings_is_loaded = false};
|
||||
|
||||
static const RGBBacklightColor colors[] = {
|
||||
{"Orange", 255, 69, 0},
|
||||
{"Red", 255, 0, 0},
|
||||
{"Maroon", 128, 0, 0},
|
||||
{"Yellow", 255, 255, 0},
|
||||
{"Olive", 128, 128, 0},
|
||||
{"Lime", 0, 255, 0},
|
||||
{"Green", 0, 128, 0},
|
||||
{"Aqua", 0, 255, 127},
|
||||
{"Cyan", 0, 210, 210},
|
||||
{"Azure", 0, 127, 255},
|
||||
{"Teal", 0, 128, 128},
|
||||
{"Blue", 0, 0, 255},
|
||||
{"Navy", 0, 0, 128},
|
||||
{"Purple", 128, 0, 128},
|
||||
{"Fuchsia", 255, 0, 255},
|
||||
{"Pink", 173, 31, 173},
|
||||
{"Brown", 165, 42, 42},
|
||||
{"White", 255, 192, 203},
|
||||
static struct {
|
||||
RgbColor colors[SK6805_LED_COUNT];
|
||||
RGBBacklightRainbowMode rainbow_mode;
|
||||
uint8_t rainbow_speed;
|
||||
uint32_t rainbow_interval;
|
||||
uint32_t rainbow_saturation;
|
||||
} rgb_settings = {
|
||||
.colors =
|
||||
{
|
||||
{255, 69, 0},
|
||||
{255, 69, 0},
|
||||
{255, 69, 0},
|
||||
},
|
||||
.rainbow_mode = RGBBacklightRainbowModeOff,
|
||||
.rainbow_speed = 5,
|
||||
.rainbow_interval = 250,
|
||||
.rainbow_saturation = 255,
|
||||
};
|
||||
|
||||
uint8_t rgb_backlight_get_color_count(void) {
|
||||
return COLOR_COUNT;
|
||||
static struct {
|
||||
bool settings_loaded;
|
||||
bool enabled;
|
||||
bool last_rainbow;
|
||||
uint8_t last_brightness;
|
||||
RgbColor last_colors[SK6805_LED_COUNT];
|
||||
FuriTimer* rainbow_timer;
|
||||
HsvColor rainbow_hsv;
|
||||
} rgb_state = {
|
||||
.settings_loaded = false,
|
||||
.enabled = false,
|
||||
.last_rainbow = true,
|
||||
.last_brightness = 0,
|
||||
.last_colors =
|
||||
{
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
{0, 0, 0},
|
||||
},
|
||||
.rainbow_timer = NULL,
|
||||
.rainbow_hsv = {0, 255, 255},
|
||||
};
|
||||
|
||||
static void rainbow_timer(void* ctx) {
|
||||
UNUSED(ctx);
|
||||
rgb_backlight_update(rgb_state.last_brightness, true);
|
||||
}
|
||||
|
||||
const char* rgb_backlight_get_color_text(uint8_t index) {
|
||||
return colors[index].name;
|
||||
void rgb_backlight_reconfigure(bool enabled) {
|
||||
if(enabled && !rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_state.enabled = enabled;
|
||||
|
||||
if(rgb_state.enabled && rgb_settings.rainbow_mode != RGBBacklightRainbowModeOff) {
|
||||
if(rgb_state.rainbow_timer == NULL) {
|
||||
rgb_state.rainbow_timer = furi_timer_alloc(rainbow_timer, FuriTimerTypePeriodic, NULL);
|
||||
} else {
|
||||
furi_timer_stop(rgb_state.rainbow_timer);
|
||||
}
|
||||
furi_timer_start(rgb_state.rainbow_timer, rgb_settings.rainbow_interval);
|
||||
} else if(rgb_state.rainbow_timer != NULL) {
|
||||
furi_timer_stop(rgb_state.rainbow_timer);
|
||||
furi_timer_free(rgb_state.rainbow_timer);
|
||||
rgb_state.rainbow_timer = NULL;
|
||||
}
|
||||
rgb_state.rainbow_hsv.s = rgb_settings.rainbow_saturation;
|
||||
|
||||
rgb_backlight_update(rgb_state.last_brightness, false);
|
||||
}
|
||||
|
||||
void rgb_backlight_load_settings(void) {
|
||||
//Не загружать данные из внутренней памяти при загрузке в режиме DFU
|
||||
if(!furi_hal_is_normal_boot()) {
|
||||
rgb_settings.settings_is_loaded = true;
|
||||
// Do not load data from internal memory when booting in DFU mode
|
||||
if(!furi_hal_is_normal_boot() || rgb_state.settings_loaded) {
|
||||
rgb_state.settings_loaded = true;
|
||||
return;
|
||||
}
|
||||
|
||||
RGBBacklightSettings settings;
|
||||
File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||
saved_struct_load(
|
||||
RGB_BACKLIGHT_SETTINGS_PATH,
|
||||
&rgb_settings,
|
||||
sizeof(rgb_settings),
|
||||
RGB_BACKLIGHT_SETTINGS_MAGIC,
|
||||
RGB_BACKLIGHT_SETTINGS_VERSION);
|
||||
|
||||
FURI_LOG_I(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_I(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;
|
||||
rgb_state.settings_loaded = true;
|
||||
rgb_backlight_reconfigure(rgb_state.enabled);
|
||||
}
|
||||
|
||||
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);
|
||||
saved_struct_save(
|
||||
RGB_BACKLIGHT_SETTINGS_PATH,
|
||||
&rgb_settings,
|
||||
sizeof(rgb_settings),
|
||||
RGB_BACKLIGHT_SETTINGS_MAGIC,
|
||||
RGB_BACKLIGHT_SETTINGS_VERSION);
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||
void rgb_backlight_set_color(uint8_t index, RgbColor color) {
|
||||
if(index >= COUNT_OF(rgb_settings.colors)) return;
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_settings.colors[index] = color;
|
||||
rgb_backlight_reconfigure(rgb_state.enabled);
|
||||
}
|
||||
|
||||
memcpy(&settings, &rgb_settings, settings_size);
|
||||
RgbColor rgb_backlight_get_color(uint8_t index) {
|
||||
if(index >= COUNT_OF(rgb_settings.colors)) return (RgbColor){0, 0, 0};
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
return rgb_settings.colors[index];
|
||||
}
|
||||
|
||||
bool fs_result =
|
||||
storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
void rgb_backlight_set_rainbow_mode(RGBBacklightRainbowMode rainbow_mode) {
|
||||
if(rainbow_mode >= RGBBacklightRainbowModeCount) return;
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_settings.rainbow_mode = rainbow_mode;
|
||||
rgb_backlight_reconfigure(rgb_state.enabled);
|
||||
}
|
||||
|
||||
if(fs_result) {
|
||||
uint16_t bytes_count = storage_file_write(file, &settings, settings_size);
|
||||
RGBBacklightRainbowMode rgb_backlight_get_rainbow_mode() {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
return rgb_settings.rainbow_mode;
|
||||
}
|
||||
|
||||
if(bytes_count != settings_size) {
|
||||
fs_result = false;
|
||||
void rgb_backlight_set_rainbow_speed(uint8_t rainbow_speed) {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_settings.rainbow_speed = rainbow_speed;
|
||||
}
|
||||
|
||||
uint8_t rgb_backlight_get_rainbow_speed() {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
return rgb_settings.rainbow_speed;
|
||||
}
|
||||
|
||||
void rgb_backlight_set_rainbow_interval(uint32_t rainbow_interval) {
|
||||
if(rainbow_interval < 100) return;
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_settings.rainbow_interval = rainbow_interval;
|
||||
rgb_backlight_reconfigure(rgb_state.enabled);
|
||||
}
|
||||
|
||||
uint32_t rgb_backlight_get_rainbow_interval() {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
return rgb_settings.rainbow_interval;
|
||||
}
|
||||
|
||||
void rgb_backlight_set_rainbow_saturation(uint8_t rainbow_saturation) {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
rgb_settings.rainbow_saturation = rainbow_saturation;
|
||||
rgb_backlight_reconfigure(rgb_state.enabled);
|
||||
}
|
||||
|
||||
uint8_t rgb_backlight_get_rainbow_saturation() {
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
return rgb_settings.rainbow_saturation;
|
||||
}
|
||||
|
||||
void rgb_backlight_update(uint8_t brightness, bool tick) {
|
||||
if(!rgb_state.enabled) return;
|
||||
if(!rgb_state.settings_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
|
||||
switch(rgb_settings.rainbow_mode) {
|
||||
case RGBBacklightRainbowModeOff: {
|
||||
if(!rgb_state.last_rainbow && rgb_state.last_brightness == brightness &&
|
||||
memcmp(rgb_state.last_colors, rgb_settings.colors, sizeof(rgb_settings.colors)) == 0) {
|
||||
return;
|
||||
}
|
||||
rgb_state.last_rainbow = false;
|
||||
memcpy(rgb_state.last_colors, rgb_settings.colors, sizeof(rgb_settings.colors));
|
||||
|
||||
float bright = brightness / 255.0f;
|
||||
for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||
SK6805_set_led_color(
|
||||
i,
|
||||
rgb_settings.colors[i].r * bright,
|
||||
rgb_settings.colors[i].g * bright,
|
||||
rgb_settings.colors[i].b * bright);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(fs_result) {
|
||||
FURI_LOG_I(TAG, "save success");
|
||||
} else {
|
||||
FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||
case RGBBacklightRainbowModeWave:
|
||||
case RGBBacklightRainbowModeSolid: {
|
||||
rgb_state.last_rainbow = true;
|
||||
|
||||
if(tick && brightness) {
|
||||
rgb_state.rainbow_hsv.h += rgb_settings.rainbow_speed;
|
||||
} else {
|
||||
if(rgb_state.last_brightness == brightness && rgb_state.last_rainbow) {
|
||||
return;
|
||||
}
|
||||
rgb_state.rainbow_hsv.v = brightness;
|
||||
}
|
||||
|
||||
HsvColor hsv = rgb_state.rainbow_hsv;
|
||||
RgbColor rgb = hsv2rgb(hsv);
|
||||
|
||||
for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||
if(i && rgb_settings.rainbow_mode == RGBBacklightRainbowModeWave) {
|
||||
hsv.h += (50 * i);
|
||||
rgb = hsv2rgb(hsv);
|
||||
}
|
||||
SK6805_set_led_color(i, rgb.r, rgb.g, rgb.b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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_update(uint8_t brightness) {
|
||||
if(!rgb_settings.settings_is_loaded) {
|
||||
rgb_backlight_load_settings();
|
||||
}
|
||||
|
||||
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)
|
||||
default:
|
||||
return;
|
||||
|
||||
last_brightness = brightness;
|
||||
last_color_index = rgb_settings.display_color_index;
|
||||
|
||||
for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||
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);
|
||||
}
|
||||
|
||||
rgb_state.last_brightness = brightness;
|
||||
SK6805_update();
|
||||
}
|
||||
|
||||
+53
-32
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
RGB backlight FlipperZero driver
|
||||
Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
Heavily modified by Willy-JL and Z3bro
|
||||
|
||||
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
|
||||
@@ -18,69 +19,89 @@
|
||||
|
||||
#include <furi.h>
|
||||
#include "SK6805.h"
|
||||
#include <toolbox/colors.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} RGBBacklightColor;
|
||||
|
||||
typedef struct {
|
||||
uint8_t version;
|
||||
uint8_t display_color_index;
|
||||
bool settings_is_loaded;
|
||||
} RGBBacklightSettings;
|
||||
typedef enum {
|
||||
RGBBacklightRainbowModeOff,
|
||||
RGBBacklightRainbowModeWave,
|
||||
RGBBacklightRainbowModeSolid,
|
||||
RGBBacklightRainbowModeCount,
|
||||
} RGBBacklightRainbowMode;
|
||||
|
||||
/**
|
||||
* @brief Получить текущие настройки RGB-подсветки
|
||||
* @brief Reconfigure rgb backlight with new settings
|
||||
*
|
||||
* @return Указатель на структуру настроек
|
||||
* @param enabled Whether the rgb backlight is enabled
|
||||
*/
|
||||
RGBBacklightSettings* rgb_backlight_get_settings(void);
|
||||
void rgb_backlight_reconfigure(bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Загрузить настройки подсветки с SD-карты
|
||||
* @brief Load backlight settings from SD card
|
||||
*/
|
||||
void rgb_backlight_load_settings(void);
|
||||
void rgb_backlight_load_settings();
|
||||
|
||||
/**
|
||||
* @brief Сохранить текущие настройки RGB-подсветки
|
||||
* @brief Save Current RGB Lighting Settings
|
||||
*/
|
||||
void rgb_backlight_save_settings(void);
|
||||
void rgb_backlight_save_settings();
|
||||
|
||||
/**
|
||||
* @brief Применить текущие настройки RGB-подсветки
|
||||
* @brief Change the color of the backlight
|
||||
*
|
||||
* @param brightness Яркость свечения (0-255)
|
||||
* @param index What led to set the color to (0 - SK6805_LED_COUNT-1)
|
||||
* @param color RGB color to use
|
||||
*/
|
||||
void rgb_backlight_update(uint8_t brightness);
|
||||
void rgb_backlight_set_color(uint8_t index, RgbColor color);
|
||||
|
||||
RgbColor rgb_backlight_get_color(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Установить цвет RGB-подсветки
|
||||
* @brief Change rainbow mode
|
||||
*
|
||||
* @param color_index Индекс цвета (0 - rgb_backlight_get_color_count())
|
||||
* @param rainbow_mode What mode to use (0 - RGBBacklightRainbowModeCount)
|
||||
*/
|
||||
void rgb_backlight_set_color(uint8_t color_index);
|
||||
void rgb_backlight_set_rainbow_mode(RGBBacklightRainbowMode rainbow_mode);
|
||||
|
||||
RGBBacklightRainbowMode rgb_backlight_get_rainbow_mode();
|
||||
|
||||
/**
|
||||
* @brief Получить количество доступных цветов
|
||||
* @brief Change rainbow speed
|
||||
*
|
||||
* @return Число доступных вариантов цвета
|
||||
* @param rainbow_speed What speed to use (0 - 255)
|
||||
*/
|
||||
uint8_t rgb_backlight_get_color_count(void);
|
||||
void rgb_backlight_set_rainbow_speed(uint8_t rainbow_speed);
|
||||
|
||||
uint8_t rgb_backlight_get_rainbow_speed();
|
||||
|
||||
/**
|
||||
* @brief Получить текстовое название цвета
|
||||
* @brief Change rainbow interval
|
||||
*
|
||||
* @param index Индекс из доступных вариантов цвета
|
||||
* @return Указатель на строку с названием цвета
|
||||
* @param rainbow_interval What interval to use
|
||||
*/
|
||||
const char* rgb_backlight_get_color_text(uint8_t index);
|
||||
void rgb_backlight_set_rainbow_interval(uint32_t rainbow_interval);
|
||||
|
||||
uint32_t rgb_backlight_get_rainbow_interval();
|
||||
|
||||
/**
|
||||
* @brief Change rainbow saturation
|
||||
*
|
||||
* @param rainbow_saturation What saturation to use (0 - 255)
|
||||
*/
|
||||
void rgb_backlight_set_rainbow_saturation(uint8_t rainbow_saturation);
|
||||
|
||||
uint8_t rgb_backlight_get_rainbow_saturation();
|
||||
|
||||
/**
|
||||
* @brief Apply current RGB lighting settings
|
||||
*
|
||||
* @param brightness Backlight intensity (0-255)
|
||||
* @param tick Whether this update was a tick (for rainbow)
|
||||
*/
|
||||
void rgb_backlight_update(uint8_t brightness, bool tick);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// https://stackoverflow.com/a/14733008
|
||||
|
||||
#include "colors.h"
|
||||
|
||||
inline int rgbcmp(const RgbColor* a, const RgbColor* b) {
|
||||
return memcmp(a, b, sizeof(RgbColor));
|
||||
}
|
||||
|
||||
inline int hsvcmp(const HsvColor* a, const HsvColor* b) {
|
||||
return memcmp(a, b, sizeof(HsvColor));
|
||||
}
|
||||
|
||||
RgbColor hsv2rgb(HsvColor hsv) {
|
||||
RgbColor rgb;
|
||||
uint8_t region, remainder, p, q, t;
|
||||
|
||||
if(hsv.s == 0) {
|
||||
rgb.r = hsv.v;
|
||||
rgb.g = hsv.v;
|
||||
rgb.b = hsv.v;
|
||||
return rgb;
|
||||
}
|
||||
|
||||
region = hsv.h / 43;
|
||||
remainder = (hsv.h - (region * 43)) * 6;
|
||||
|
||||
p = (hsv.v * (255 - hsv.s)) >> 8;
|
||||
q = (hsv.v * (255 - ((hsv.s * remainder) >> 8))) >> 8;
|
||||
t = (hsv.v * (255 - ((hsv.s * (255 - remainder)) >> 8))) >> 8;
|
||||
|
||||
switch(region) {
|
||||
case 0:
|
||||
rgb.r = hsv.v;
|
||||
rgb.g = t;
|
||||
rgb.b = p;
|
||||
break;
|
||||
case 1:
|
||||
rgb.r = q;
|
||||
rgb.g = hsv.v;
|
||||
rgb.b = p;
|
||||
break;
|
||||
case 2:
|
||||
rgb.r = p;
|
||||
rgb.g = hsv.v;
|
||||
rgb.b = t;
|
||||
break;
|
||||
case 3:
|
||||
rgb.r = p;
|
||||
rgb.g = q;
|
||||
rgb.b = hsv.v;
|
||||
break;
|
||||
case 4:
|
||||
rgb.r = t;
|
||||
rgb.g = p;
|
||||
rgb.b = hsv.v;
|
||||
break;
|
||||
default:
|
||||
rgb.r = hsv.v;
|
||||
rgb.g = p;
|
||||
rgb.b = q;
|
||||
break;
|
||||
}
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
HsvColor rgb2hsv(RgbColor rgb) {
|
||||
HsvColor hsv;
|
||||
uint8_t rgbMin, rgbMax;
|
||||
|
||||
rgbMin = rgb.r < rgb.g ? (rgb.r < rgb.b ? rgb.r : rgb.b) : (rgb.g < rgb.b ? rgb.g : rgb.b);
|
||||
rgbMax = rgb.r > rgb.g ? (rgb.r > rgb.b ? rgb.r : rgb.b) : (rgb.g > rgb.b ? rgb.g : rgb.b);
|
||||
|
||||
hsv.v = rgbMax;
|
||||
if(hsv.v == 0) {
|
||||
hsv.h = 0;
|
||||
hsv.s = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
hsv.s = 255 * ((long)rgbMax - (long)rgbMin) / hsv.v;
|
||||
if(hsv.s == 0) {
|
||||
hsv.h = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
if(rgbMax == rgb.r)
|
||||
hsv.h = 0 + 43 * (rgb.g - rgb.b) / (rgbMax - rgbMin);
|
||||
else if(rgbMax == rgb.g)
|
||||
hsv.h = 85 + 43 * (rgb.b - rgb.r) / (rgbMax - rgbMin);
|
||||
else
|
||||
hsv.h = 171 + 43 * (rgb.r - rgb.g) / (rgbMax - rgbMin);
|
||||
|
||||
return hsv;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct RgbColor {
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
} RgbColor;
|
||||
|
||||
typedef struct HsvColor {
|
||||
uint8_t h;
|
||||
uint8_t s;
|
||||
uint8_t v;
|
||||
} HsvColor;
|
||||
|
||||
int rgbcmp(const RgbColor* a, const RgbColor* b);
|
||||
|
||||
int hsvcmp(const HsvColor* a, const HsvColor* b);
|
||||
|
||||
RgbColor hsv2rgb(HsvColor hsv);
|
||||
|
||||
HsvColor rgb2hsv(RgbColor rgb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "xtreme.h"
|
||||
#include <furi_hal.h>
|
||||
#include <rgb_backlight.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#define TAG "XtremeSettings"
|
||||
@@ -194,6 +195,8 @@ void XTREME_SETTINGS_LOAD() {
|
||||
}
|
||||
flipper_format_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
rgb_backlight_reconfigure(x->rgb_backlight);
|
||||
}
|
||||
|
||||
void XTREME_SETTINGS_SAVE() {
|
||||
|
||||
Reference in New Issue
Block a user