diff --git a/.gitmodules b/.gitmodules index e2611c4..8ed74ce 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "assets/flipperzero-protobuf"] + path = assets/flipperzero-protobuf + url = https://github.com/Next-Flip/flipperzero-protobuf.git [submodule "lib/pico_dvi"] path = lib/pico_dvi url = https://github.com/Wren6991/PicoDVI.git @@ -10,6 +13,3 @@ [submodule "lib/nanopb"] path = lib/nanopb url = https://github.com/nanopb/nanopb.git -[submodule "assets/flipperzero-protobuf"] - path = assets/flipperzero-protobuf - url = https://github.com/flipperdevices/flipperzero-protobuf.git diff --git a/app/frame.c b/app/frame.c index 524cc89..0244e4c 100644 --- a/app/frame.c +++ b/app/frame.c @@ -13,9 +13,6 @@ static struct dvi_inst dvi0; static uint16_t framebuf[FRAME_WIDTH * 2]; -#define COLOR_BG 0xFC00 -#define COLOR_FG 0x0000 - #define COLOR_RED 0xF800 #define COLOR_GREEN 0x07E0 #define COLOR_BLUE 0x001F @@ -165,3 +162,11 @@ void frame_set_color(uint16_t bg, uint16_t fg) { color_bg = bg; color_fg = fg; } + +void frame_set_background(uint16_t bg) { + color_bg = bg; +} + +void frame_set_foreground(uint16_t fg) { + color_fg = fg; +} diff --git a/app/frame.h b/app/frame.h index bdb85d9..c40c0ea 100644 --- a/app/frame.h +++ b/app/frame.h @@ -1,6 +1,9 @@ #pragma once #include +#define COLOR_BG 0xFC00 +#define COLOR_FG 0x0000 + typedef struct { const uint8_t data[1024]; } frame_t; @@ -20,4 +23,6 @@ typedef enum { void frame_parse_data(uint8_t orientation, const frame_t* frame, uint32_t timeout_ms); -void frame_set_color(uint16_t bg, uint16_t fg); \ No newline at end of file +void frame_set_color(uint16_t bg, uint16_t fg); +void frame_set_background(uint16_t bg); +void frame_set_foreground(uint16_t fg); diff --git a/app/rgb.c b/app/rgb.c index 55be915..7ee1c09 100644 --- a/app/rgb.c +++ b/app/rgb.c @@ -1,10 +1,20 @@ #include "rgb.h" -#include -#include -#include "frame.h" +State bg_state = { + .thread = NULL, + .current_color_index = 0, + .totalSteps = 20, + .currentStep = 0, + .set_color = &frame_set_background, +}; -static TaskHandle_t rgb_handle; +State fg_state = { + .thread = NULL, + .current_color_index = 0, + .totalSteps = 20, + .currentStep = 0, + .set_color = &frame_set_foreground, +}; // Define rainbow colors in RGB565 format static const uint16_t rainbow_colors[] = { @@ -18,10 +28,6 @@ static const uint16_t rainbow_colors[] = { }; static const size_t rainbow_colors_count = sizeof(rainbow_colors) / sizeof(rainbow_colors[0]); -static size_t current_color_index = 0; -static uint16_t color_background; -static const uint8_t totalSteps = 20; // Total steps for smooth transition -static uint8_t currentStep = 0; // Current step in the transition // Function to linearly interpolate between two colors in RGB565 format uint16_t @@ -44,19 +50,19 @@ uint16_t } // Modified function to cycle through the rainbow colors for the background with smooth transitions -void cycle_rainbow_background_colors_smooth() { - uint16_t currentColor = rainbow_colors[current_color_index]; - uint16_t nextColor = rainbow_colors[(current_color_index + 1) % rainbow_colors_count]; +void cycle_rainbow_background_colors_smooth(State* s) { + uint16_t currentColor = rainbow_colors[s->current_color_index]; + uint16_t nextColor = rainbow_colors[(s->current_color_index + 1) % rainbow_colors_count]; uint16_t interpolatedColor = - interpolate_color(currentColor, nextColor, currentStep, totalSteps); - frame_set_color(interpolatedColor, color_background); // Update the background color - - currentStep++; - if(currentStep >= totalSteps) { - currentStep = 0; - current_color_index = - (current_color_index + 1) % rainbow_colors_count; // Move to the next color + interpolate_color(currentColor, nextColor, s->currentStep, s->totalSteps); + s->set_color(interpolatedColor); + + s->currentStep++; + if(s->currentStep >= s->totalSteps) { + s->currentStep = 0; + s->current_color_index = + (s->current_color_index + 1) % rainbow_colors_count; // Move to the next color } } @@ -64,26 +70,26 @@ void RainbowBackgroundColorCyclerTask(void* pvParameters) { const TickType_t xDelay = 50 / portTICK_PERIOD_MS; // Adjust delay for smoother transitions while(1) { - cycle_rainbow_background_colors_smooth(); + cycle_rainbow_background_colors_smooth(pvParameters); vTaskDelay(xDelay); } } -void start_rainbow_mode() { - if(rgb_handle) { - vTaskResume(rgb_handle); +uint16_t rgb888_to_rgb565(RgbColor rgb) { + return (((uint16_t)rgb.r & 0xF8) << 8) + (((uint16_t)rgb.g & 0xFC) << 3) + + ((rgb.b & 0xF8) >> 3); +} + +void start_rainbow_mode(State* s) { + if(s->thread) { + vTaskResume(s->thread); return; } xTaskCreate( - RainbowBackgroundColorCyclerTask, - "RainbowBackgroundColorCycler", - 256, - NULL, - 1, - &rgb_handle); + RainbowBackgroundColorCyclerTask, "RainbowBackgroundColorCycler", 256, s, 1, &s->thread); } -void stop_rainbow_mode() { - if(rgb_handle == NULL) return; - vTaskSuspend(rgb_handle); +void stop_rainbow_mode(State* s) { + if(s->thread == NULL) return; + vTaskSuspend(s->thread); } diff --git a/app/rgb.h b/app/rgb.h index c66a89e..1d60271 100644 --- a/app/rgb.h +++ b/app/rgb.h @@ -1,13 +1,49 @@ #pragma once +#include +#include +#include + +#include "frame.h" + +typedef union __attribute__((packed)) { + struct { + uint8_t r; + uint8_t g; + uint8_t b; + }; + uint32_t value : 24; +} RgbColor; typedef enum { - VgmColorModeDefault, - VgmColorModeCustom, - VgmColorModeRainbow, - VgmColorModeRgbBacklight, - VgmColorModeCount, -} VgmColorMode; + ScreenColorModeDefault, + ScreenColorModeCustom, + ScreenColorModeRainbow, + _ScreenColorModeRgbBacklight, // FW will replace this with backlight mode + ScreenColorModeCount, +} ScreenColorMode; + +typedef union __attribute__((packed)) { + struct { + ScreenColorMode mode; + RgbColor rgb; + }; + uint32_t value; +} ScreenFrameColor; + +typedef struct { + TaskHandle_t thread; + size_t current_color_index; + uint8_t totalSteps; + uint8_t currentStep; + void (*set_color)(uint16_t color); +} State; + +extern State bg_state; + +extern State fg_state; + +uint16_t rgb888_to_rgb565(RgbColor rgb); -void start_rainbow_mode(); +void start_rainbow_mode(State* s); -void stop_rainbow_mode(); +void stop_rainbow_mode(State* s); diff --git a/app/uart.c b/app/uart.c index 9889ca8..d0b1ebe 100644 --- a/app/uart.c +++ b/app/uart.c @@ -269,11 +269,6 @@ static inline bool expansion_is_screen_frame_rpc_response(const PB_Main* message message->which_content == PB_Main_gui_screen_frame_tag; } -static inline bool expansion_is_system_device_info_rpc_response(const PB_Main* message) { - return message->command_status == PB_CommandStatus_OK && - message->which_content == PB_Main_system_device_info_response_tag; -} - // Main states static bool expansion_wait_ready() { @@ -368,84 +363,6 @@ static bool expansion_start_virtual_display() { return success; } -static bool expansion_get_rgb_info() { - bool success = false; - - rpc_message.command_id = expansion_get_next_command_id(); - rpc_message.command_status = PB_CommandStatus_OK; - rpc_message.which_content = PB_Main_system_device_info_request_tag; - - VgmColorMode color_mode = VgmColorModeDefault; - - uint32_t led_rgb_0 = 0; - uint32_t led_rgb_1 = 0; - uint32_t led_rgb_2 = 0; - - uint16_t vgm_bg = 0xFC00; - uint16_t vgm_fg = 0x0000; - - do { - if(!expansion_send_rpc_message(&rpc_message)) break; - PB_System_DeviceInfoResponse* response = &rpc_message.content.system_device_info_response; - do { - if(!expansion_receive_rpc_message(&rpc_message)) break; - if(!expansion_is_system_device_info_rpc_response(&rpc_message)) break; - - if(strcmp(response->key, "hardware_vgm_color_mode") == 0) - color_mode = (VgmColorMode)strtol(response->value, NULL, 10); - - if(strcmp(response->key, "hardware_screen_rgb_led0") == 0) - led_rgb_0 = strtol(response->value, NULL, 16); - if(strcmp(response->key, "hardware_screen_rgb_led1") == 0) - led_rgb_1 = strtol(response->value, NULL, 16); - if(strcmp(response->key, "hardware_screen_rgb_led2") == 0) - led_rgb_2 = strtol(response->value, NULL, 16); - - if(strcmp(response->key, "hardware_vgm_color_fg") == 0) - vgm_fg = strtol(response->value, NULL, 16); - if(strcmp(response->key, "hardware_vgm_color_bg") == 0) - vgm_bg = strtol(response->value, NULL, 16); - - } while(rpc_message.has_next); - - if(rpc_message.has_next) break; - - switch(color_mode) { - case VgmColorModeDefault: - vgm_bg = 0xFC00; - vgm_fg = 0x0000; - stop_rainbow_mode(); - break; - case VgmColorModeRainbow: - start_rainbow_mode(); - break; - case VgmColorModeRgbBacklight: - vgm_bg = (uint16_t)((led_rgb_2 & 0xF80000) >> 8) + - (uint16_t)((led_rgb_2 & 0x00FC00) >> 5) + - (uint16_t)((led_rgb_2 & 0x0000F8) >> 3); - vgm_bg = (uint16_t)((led_rgb_1 & 0xF80000) >> 8) + - (uint16_t)((led_rgb_1 & 0x00FC00) >> 5) + - (uint16_t)((led_rgb_1 & 0x0000F8) >> 3); - vgm_bg = (uint16_t)((led_rgb_0 & 0xF80000) >> 8) + - (uint16_t)((led_rgb_0 & 0x00FC00) >> 5) + - (uint16_t)((led_rgb_0 & 0x0000F8) >> 3); - vgm_fg = 0x0000; - stop_rainbow_mode(); - break; - default: - stop_rainbow_mode(); - break; - } - - frame_set_color(vgm_bg, vgm_fg); - - success = true; - } while(false); - - pb_release(&PB_Main_msg, &rpc_message); - return success; -} - static bool expansion_wait_input() { bool success = false; @@ -515,6 +432,24 @@ static void expansion_process_screen_streaming() { const PB_Gui_ScreenOrientation orientation = rpc_message.content.gui_screen_frame.orientation; const pb_byte_t* data = rpc_message.content.gui_screen_frame.data->bytes; + const ScreenFrameColor bg = {.value = rpc_message.content.gui_screen_frame.bg_color}; + const ScreenFrameColor fg = {.value = rpc_message.content.gui_screen_frame.fg_color}; + + if(bg.mode == ScreenColorModeRainbow) { + start_rainbow_mode(&bg_state); + } else { + stop_rainbow_mode(&bg_state); + frame_set_background( + bg.mode == ScreenColorModeCustom ? rgb888_to_rgb565(bg.rgb) : COLOR_BG); + } + + if(fg.mode == ScreenColorModeRainbow) { + start_rainbow_mode(&fg_state); + } else { + stop_rainbow_mode(&fg_state); + frame_set_foreground( + fg.mode == ScreenColorModeCustom ? rgb888_to_rgb565(fg.rgb) : COLOR_FG); + } frame_parse_data( orientation, (const frame_t*)data, pdMS_TO_TICKS(EXPANSION_MODULE_TIMEOUT_MS)); @@ -577,9 +512,6 @@ static void uart_task(void* unused_arg) { // start rpc if(!expansion_start_rpc()) continue; - // get rgb info - if(!expansion_get_rgb_info()) continue; - // leds: activate active state led_state_active(); diff --git a/assets/flipperzero-protobuf b/assets/flipperzero-protobuf index 1956b83..fae8e0e 160000 --- a/assets/flipperzero-protobuf +++ b/assets/flipperzero-protobuf @@ -1 +1 @@ -Subproject commit 1956b83bba99313ee8d8386e5d35d0549341ca26 +Subproject commit fae8e0e9b95895f10e97679fac779066794f197c