Skip to content

Commit

Permalink
RGB mode over custom RPC (#2)
Browse files Browse the repository at this point in the history
* first poc for rgb over rpc

* get VgmMode over rpc

* foreground and background can be rainbow now

* Update protobuf

* Remove unused function

* Naming and sync from fw pr

* Fix warnings

* More unused stuff

* Fallback to default when not custom color (eg OFW RPC)

---------

Co-authored-by: Willy-JL <[email protected]>
  • Loading branch information
HaxSam and Willy-JL authored Jun 2, 2024
1 parent 3f25703 commit f484ac5
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 134 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
11 changes: 8 additions & 3 deletions app/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
7 changes: 6 additions & 1 deletion app/frame.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#pragma once
#include <stdint.h>

#define COLOR_BG 0xFC00
#define COLOR_FG 0x0000

typedef struct {
const uint8_t data[1024];
} frame_t;
Expand All @@ -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);
void frame_set_color(uint16_t bg, uint16_t fg);
void frame_set_background(uint16_t bg);
void frame_set_foreground(uint16_t fg);
70 changes: 38 additions & 32 deletions app/rgb.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
#include "rgb.h"
#include <FreeRTOS.h>
#include <task.h>

#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[] = {
Expand All @@ -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
Expand All @@ -44,46 +50,46 @@ 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
}
}

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);
}
52 changes: 44 additions & 8 deletions app/rgb.h
Original file line number Diff line number Diff line change
@@ -1,13 +1,49 @@
#pragma once
#include <pico/stdlib.h>
#include <FreeRTOS.h>
#include <task.h>

#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);
104 changes: 18 additions & 86 deletions app/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion assets/flipperzero-protobuf

0 comments on commit f484ac5

Please sign in to comment.