diff --git a/app/rgb.c b/app/rgb.c new file mode 100644 index 0000000..55be915 --- /dev/null +++ b/app/rgb.c @@ -0,0 +1,89 @@ +#include "rgb.h" +#include +#include + +#include "frame.h" + +static TaskHandle_t rgb_handle; + +// Define rainbow colors in RGB565 format +static const uint16_t rainbow_colors[] = { + 0xF800, // Red + 0xFC00, // Orange + 0xFFE0, // Yellow + 0x07E0, // Green + 0x001F, // Blue + 0x781F, // Indigo + 0xF81F // Violet +}; + +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 + interpolate_color(uint16_t colorStart, uint16_t colorEnd, uint8_t step, uint8_t maxSteps) { + if(step >= maxSteps) return colorEnd; + + int rStart = (colorStart >> 11) & 0x1F; + int gStart = (colorStart >> 5) & 0x3F; + int bStart = colorStart & 0x1F; + + int rEnd = (colorEnd >> 11) & 0x1F; + int gEnd = (colorEnd >> 5) & 0x3F; + int bEnd = colorEnd & 0x1F; + + int r = rStart + ((rEnd - rStart) * step / maxSteps); + int g = gStart + ((gEnd - gStart) * step / maxSteps); + int b = bStart + ((bEnd - bStart) * step / maxSteps); + + return (uint16_t)((r << 11) | (g << 5) | b); +} + +// 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]; + + 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 + } +} + +void RainbowBackgroundColorCyclerTask(void* pvParameters) { + const TickType_t xDelay = 50 / portTICK_PERIOD_MS; // Adjust delay for smoother transitions + + while(1) { + cycle_rainbow_background_colors_smooth(); + vTaskDelay(xDelay); + } +} + +void start_rainbow_mode() { + if(rgb_handle) { + vTaskResume(rgb_handle); + return; + } + xTaskCreate( + RainbowBackgroundColorCyclerTask, + "RainbowBackgroundColorCycler", + 256, + NULL, + 1, + &rgb_handle); +} + +void stop_rainbow_mode() { + if(rgb_handle == NULL) return; + vTaskSuspend(rgb_handle); +} diff --git a/app/rgb.h b/app/rgb.h new file mode 100644 index 0000000..c66a89e --- /dev/null +++ b/app/rgb.h @@ -0,0 +1,13 @@ +#pragma once + +typedef enum { + VgmColorModeDefault, + VgmColorModeCustom, + VgmColorModeRainbow, + VgmColorModeRgbBacklight, + VgmColorModeCount, +} VgmColorMode; + +void start_rainbow_mode(); + +void stop_rainbow_mode(); diff --git a/app/uart.c b/app/uart.c index bcbd031..9889ca8 100644 --- a/app/uart.c +++ b/app/uart.c @@ -16,6 +16,7 @@ #include "led_state.h" #include "bitmaps.h" #include "expansion_protocol.h" +#include "rgb.h" #define UART_ID uart0 #define UART_IRQ UART0_IRQ @@ -374,7 +375,7 @@ static bool expansion_get_rgb_info() { rpc_message.command_status = PB_CommandStatus_OK; rpc_message.which_content = PB_Main_system_device_info_request_tag; - uint8_t color_mode = 0; + VgmColorMode color_mode = VgmColorModeDefault; uint32_t led_rgb_0 = 0; uint32_t led_rgb_1 = 0; @@ -391,14 +392,14 @@ static bool expansion_get_rgb_info() { if(!expansion_is_system_device_info_rpc_response(&rpc_message)) break; if(strcmp(response->key, "hardware_vgm_color_mode") == 0) - color_mode = strtol(response->value, NULL, 10); + color_mode = (VgmColorMode)strtol(response->value, NULL, 10); if(strcmp(response->key, "hardware_screen_rgb_led0") == 0) - led_rgb_0 = (uint32_t)strtol(response->value, NULL, 16); + led_rgb_0 = strtol(response->value, NULL, 16); if(strcmp(response->key, "hardware_screen_rgb_led1") == 0) - led_rgb_1 = (uint32_t)strtol(response->value, NULL, 16); + led_rgb_1 = strtol(response->value, NULL, 16); if(strcmp(response->key, "hardware_screen_rgb_led2") == 0) - led_rgb_2 = (uint32_t)strtol(response->value, NULL, 16); + led_rgb_2 = strtol(response->value, NULL, 16); if(strcmp(response->key, "hardware_vgm_color_fg") == 0) vgm_fg = strtol(response->value, NULL, 16); @@ -410,11 +411,15 @@ static bool expansion_get_rgb_info() { if(rpc_message.has_next) break; switch(color_mode) { - case 0: + case VgmColorModeDefault: vgm_bg = 0xFC00; vgm_fg = 0x0000; + stop_rainbow_mode(); break; - case 2: + 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); @@ -425,8 +430,10 @@ static bool expansion_get_rgb_info() { (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; }