- Added initial version of Hierarchical Menu

- Beautified the Message Box a bit
This commit is contained in:
2025-09-19 15:21:15 +02:00
parent 097a50f073
commit c8f14373d3
36 changed files with 2998 additions and 1973 deletions

View File

@@ -82,6 +82,8 @@ add_executable(Firmware
Display_Default_Configurations.c
Display_Message_Box_Icons.c
Display_Render_Complex.c
Display_Render_Simple.c
Display_Color.c
Display_Font.c
Display_Image.c
@@ -93,6 +95,7 @@ add_executable(Firmware
Display.c
Screen_Variables.c
Hierarchical_Menu.c
${IMAGE_SOURCES}
${FONT_SOURCES}
@@ -134,3 +137,7 @@ target_link_libraries(Firmware
pico_add_extra_outputs(Firmware)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -t $<TARGET_FILE:${PROJECT_NAME}> > ${CMAKE_CURRENT_BINARY_DIR}/symbols_full.txt
COMMENT "Extracting all symbols to symbols_full.txt"
)

View File

@@ -92,7 +92,7 @@ typedef uint8_t Value_t;
typedef union
{
uint Data;
uint32_t Data;
struct Command_s
{
uint8_t Command;
@@ -105,13 +105,17 @@ typedef union
{
struct
{
uint8_t Gap;
uint8_t B;
uint8_t R;
uint8_t R;
uint8_t G;
uint8_t B;
uint8_t A; // Alpha channel (unused, for 32-bit alignment)
// uint8_t Gap;
// uint8_t B;
// uint8_t R;
// uint8_t G;
};
uint8_t Array[4];
uint Pixel;
uint32_t Pixel;
} __packed LED_Data_t;
typedef struct {
@@ -141,7 +145,7 @@ typedef struct
{
uint8_t Enabled;
LED_Data_t Color;
uint Timeout;
uint32_t Timeout;
uint8_t Reset_Condition;
uint8_t Fade_Speed;
} __packed Pause_Light_Configuration_s;
@@ -158,8 +162,8 @@ typedef struct
{
Duration_t Duration_Min_s;
Duration_t Duration_Max_s;
int Hue_Angle_Start_Color;
uint Color_Change;
int32_t Hue_Angle_Start_Color;
uint32_t Color_Change;
uint8_t Fade_Speed;
} __packed Jam_Light_Configuration_s;

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,18 @@
// ============================================================================================
// Datatypes
typedef struct {
Screen_Transition_Direction Direction_Out;
Screen_Transition_Direction Direction_In;
Coordinates Offset;
Easing Type;
uint32_t Frame_Duration;
uint32_t Step;
int16_t Position_In;
int16_t Position_Out;
} Screen_Transition_Settings_t;
// ============================================================================================

View File

@@ -8,22 +8,87 @@
// ============================================================================================
// Defines
#define MODERN_PRIMARY_DARK DISPLAY_COLOR_FROM_RGB888(28, 28, 30) // Dark charcoal
#define MODERN_PRIMARY_LIGHT DISPLAY_COLOR_FROM_RGB888(242, 242, 247) // Light gray
#define MODERN_ACCENT_BLUE DISPLAY_COLOR_FROM_RGB888(0, 122, 255) // System blue
#define MODERN_ACCENT_GREEN DISPLAY_COLOR_FROM_RGB888(48, 209, 88) // System green
#define MODERN_ACCENT_ORANGE DISPLAY_COLOR_FROM_RGB888(255, 149, 0) // System orange
#define MODERN_ACCENT_RED DISPLAY_COLOR_FROM_RGB888(255, 69, 58) // System red
#define MODERN_SHADOW DISPLAY_COLOR_FROM_RGB888(0, 0, 0) // True black shadow
#define MODERN_GLASS_OVERLAY DISPLAY_COLOR_FROM_RGB888(255, 255, 255) // White overlay for glass effect
// ============================================================================================
// Variables
extern const unsigned char _Font_Victor_Mono_Bold_8x19[];
extern const unsigned char _Font_Victor_Mono_Regular_6x11[];
extern const unsigned char _Font_Victor_Mono_Regular_7x13[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_7x15[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_11x17[];
extern const unsigned char _Font_DejaVu_Sans_Mono_6x12[];
extern const unsigned char _Font_DejaVu_Sans_Mono_7x15[];
extern const unsigned char _Font_DejaVu_Sans_Mono_10x17[];
const Message_Box_Style _Message_Box_Style_Regular = {
.Font = _Font_DejaVu_Sans_Mono_10x17,
.Background_Color = MODERN_PRIMARY_DARK,
.Border_Color = DISPLAY_COLOR_FROM_RGB888(58, 58, 60),
.Text_Color = MODERN_PRIMARY_LIGHT,
.Accent_Color = MODERN_ACCENT_BLUE,
.Border_Radius = 15,
.Border_Thickness = 1,
.Padding[PADDING_LEFT] = 20,
.Padding[PADDING_TOP] = 20,
.Padding[PADDING_RIGHT] = 20,
.Padding[PADDING_BOTTOM] = 25
};
Configuration_Menu_Select _Configuration_Default_Select_Menu = {
.X_Offset = 60,
.X_Indent = -4,
.Font = { _Font_Victor_Mono_Bold_8x19, _Font_Victor_Mono_Regular_7x13, _Font_Victor_Mono_Regular_6x11 },
.Font = { _Font_DejaVu_Sans_Mono_Bold_7x15, _Font_DejaVu_Sans_Mono_7x15, _Font_DejaVu_Sans_Mono_6x12 },
.Color = { DISPLAY_COLOR_WHITE, DISPLAY_COLOR_LIGHTGREY, DISPLAY_COLOR_DARKGREY }
};
Configuration_Menu_Hierarchical _Configuration_Menu_Hierarchical_Default = {
// Fonts
.Title_Font = _Font_DejaVu_Sans_Mono_Bold_11x17,
.Item_Font = _Font_DejaVu_Sans_Mono_7x15,
.Back_Font = _Font_DejaVu_Sans_Mono_6x12,
// Colors
.Title_Color = DISPLAY_COLOR_WHITE,
.Item_Selected_Color = DISPLAY_COLOR_CYAN,
.Item_Normal_Color = DISPLAY_COLOR_LIGHTGREY,
.Item_Back_Color = DISPLAY_COLOR_YELLOW,
.Background_Color = DISPLAY_COLOR_BLACK,
.Border_Color = DISPLAY_COLOR_DARKGREY,
.Indicator_Color = DISPLAY_COLOR_BLUE,
// Layout
.Title_Y_Offset = 25,
.Menu_Start_Y = 60,
.Item_Height = 20,
.Item_Spacing = 4,
.Item_Alignment = CENTER,
.Side_Padding = 30,
.Visible_Items = 6,
// Animation
.Animation_Speed = 8,
.Transition_Frames = 12,
// Visual indicators
.Show_Scroll_Indicators = true,
.Show_Item_Icons = false,
.Show_Sub_Menu_Indicators = true,
.Show_Selection_Box = true,
.Selection_Box_Padding = 4
};
// Configuration_Menu_Icon_Row
Configuration_Select_YesNo _Configuration_Default_Select_YesNo = {
@@ -34,7 +99,7 @@ Configuration_Select_YesNo _Configuration_Default_Select_YesNo = {
.Value_Font = _Font_DejaVu_Sans_Mono_10x17,
.Value_Center_X_Offset = 20,
.Value_Y_Center = DISPLAY_Y_CENTER+20,
.Animation_Speed = 6
.Animation_Speed = 20
};
Configuration_Select_List _Configuration_Default_Select_List = {
@@ -45,7 +110,7 @@ Configuration_Select_List _Configuration_Default_Select_List = {
};
Configuration_Select_Value _Configuration_Default_Select_Value = {
.Title_Font = _Font_Victor_Mono_Bold_8x19,
.Title_Font = _Font_DejaVu_Sans_Mono_Bold_7x15,
.Title_Color = DISPLAY_COLOR_WHITE,
.Title_Y_Center = DISPLAY_Y_CENTER-50,
@@ -84,7 +149,7 @@ Configuration_Select_RGB _Configuration_Default_Select_RGB = {
.Show_Previous_Markers = true,
// Text display settings - clear hierarchy
.Component_Label_Font = _Font_Victor_Mono_Bold_8x19, // Bold for component labels (RED/GREEN/BLUE)
.Component_Label_Font = _Font_DejaVu_Sans_Mono_Bold_7x15, // Bold for component labels (RED/GREEN/BLUE)
.Value_Font = _Font_DejaVu_Sans_Mono_10x17, // Large readable font for values
.Text_Color = DISPLAY_COLOR_WHITE, // High contrast white text
.Text_Y_Offset = 100, // 100px from bottom edge
@@ -124,8 +189,8 @@ Configuration_Select_RGB _Configuration_Compact_Select_RGB = {
.Show_Previous_Markers = true,
// Smaller fonts for compact layout
.Component_Label_Font = _Font_Victor_Mono_Regular_6x11, // Smaller label font
.Value_Font = _Font_Victor_Mono_Bold_8x19, // Medium value font
.Component_Label_Font = _Font_DejaVu_Sans_Mono_6x12, // Smaller label font
.Value_Font = _Font_DejaVu_Sans_Mono_Bold_7x15, // Medium value font
.Text_Color = DISPLAY_COLOR_LIGHTGREY,
.Text_Y_Offset = 25,
@@ -165,7 +230,7 @@ Configuration_Select_RGB _Configuration_High_Contrast_Select_RGB = {
// Large, clear fonts
.Component_Label_Font = _Font_DejaVu_Sans_Mono_10x17, // Larger labels
.Value_Font = _Font_Victor_Mono_Bold_8x19, // Bold values
.Value_Font = _Font_DejaVu_Sans_Mono_Bold_7x15, // Bold values
.Text_Color = DISPLAY_COLOR_WHITE,
.Text_Y_Offset = 35,

View File

@@ -17,19 +17,29 @@
#define SCREEN_TRANSITION_DEFAULT_EASING INOUT_SINE
#define SCREEN_TRANSITION_DEFAULT_FRAMES 15
#define MESSAGE_BOX_DEFAULT_TICKS 40
// ============================================================================================
// Datatypes
extern const Message_Box_Style _Message_Box_Style_Regular;
extern Configuration_Menu_Select _Configuration_Default_Select_Menu;
extern Configuration_Menu_Hierarchical _Configuration_Menu_Hierarchical_Default;
extern Configuration_Menu_Hierarchical _Configuration_Menu_Hierarchical_Modern;
extern Configuration_Select_YesNo _Configuration_Default_Select_YesNo;
extern Configuration_Select_List _Configuration_Default_Select_List;
extern Configuration_Select_Value _Configuration_Default_Select_Value;
extern Configuration_Select_RGB _Configuration_Default_Select_RGB;
extern Configuration_Select_RGB _Configuration_Compact_Select_RGB;
extern Configuration_Select_RGB _Configuration_High_Contrast_Select_RGB;
extern Configuration_Entry_Indicator _Configuration_Default_Entry_Indicator_Arc;
extern Configuration_Entry_Indicator _Configuration_Default_Entry_Indicator_Dot;
// ============================================================================================
// Function Declarations

View File

@@ -10,6 +10,8 @@
#include "Display_Objects.h"
#include "Display_Message_Box_Icons.h"
#include "Hierarchical_Menu.h"
#include <string.h>
#include <math.h>
@@ -93,6 +95,7 @@ void Display_Objects_Clear(void)
{
Object_Value_Bar_Arc *VA;
Object_Menu_Ring *MR;
Object_Menu_Hierarchical* MH;
Object_Canvas *C;
for (uint i = 0; i < _Objects.Size; i++)
@@ -155,6 +158,13 @@ void Display_Objects_Clear(void)
}
free(MR);
break;
case MENU_HIERARCHICAL:
MH = (Object_Menu_Hierarchical*)(O->Data);
if (MH->Transition_Animation != NULL) {
free(MH->Transition_Animation);
}
free(MH);
break;
case SELECT_YESNO:
free((Object_Select_YesNo*)(O->Data));
break;
@@ -612,16 +622,15 @@ Object_ID Display_Objects_Add_Canvas(Anchor_Point anchor_point, Coordinates_Type
return Display_Objects_Add(CANVAS, anchor_point, coordinates_type, x, y, selectable, (void *)Canvas, style_id, animation_id);
}
Object_ID Display_Objects_Add_Message_Box(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, char* text, Font_ID font, Object_Message_Box_Icon icon, Display_Color color, Style_ID style_id)
Object_ID Display_Objects_Add_Message_Box(Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, char* text, Object_Message_Box_Icon icon, const Message_Box_Style* style)
{
Object_Message_Box *Message_Box = malloc(sizeof(Object_Message_Box));
Message_Box->Length = sprintf(Message_Box->Text, "%s", text);
Message_Box->Font = Display_Objects_Font_From_ID(font);
Message_Box->Color = color;
Message_Box->Icon = icon;
Message_Box->Style = style;
Message_Box->Show_Ticks_Left = 0;
return Display_Objects_Add(MESSAGE_BOX, anchor_point, coordinates_type, x, y, NOT_SELECTABLE, (void *)Message_Box, style_id, NO_ANIMATION);
return Display_Objects_Add(MESSAGE_BOX, anchor_point, coordinates_type, x, y, NOT_SELECTABLE, (void *)Message_Box, NO_STYLE, NO_ANIMATION);
}
Object_ID Display_Objects_Add_Menu_Select(char* menu_titles, uint32_t menu_entry_count, uint32_t title_char_length, uint32_t* selected_entry, Configuration_Menu_Select* config)
@@ -700,6 +709,37 @@ Object_ID Display_Objects_Add_Menu_Ring(Menu_Ring_Item_Config* items, uint32_t i
return Display_Objects_Add(MENU_RING, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, SELECTABLE, (void *)Menu_Ring, NO_STYLE, NO_ANIMATION);
}
Object_ID Display_Objects_Add_Menu_Hierarchical(const Menu_List** current_list, int32_t* selected_item, int32_t* scroll_offset, Configuration_Menu_Hierarchical* config)
{
Object_Menu_Hierarchical* Menu_Hierarchical = malloc(sizeof(Object_Menu_Hierarchical));
Menu_Hierarchical->Current_List = current_list;
Menu_Hierarchical->Selected_Item = selected_item;
Menu_Hierarchical->Scroll_Offset = scroll_offset;
Menu_Hierarchical->Config = config;
Menu_Hierarchical->Animation_Counter = 0;
Menu_Hierarchical->Transition_Progress = 0.0f;
Menu_Hierarchical->Last_Selected_Item = *selected_item;
Menu_Hierarchical->Last_Current_List = *current_list;
Menu_Hierarchical->Last_Selected_Item_Value = *selected_item;
Menu_Hierarchical->Last_Scroll_Offset_Value = *scroll_offset;
Menu_Hierarchical->Transition_Animation = malloc(sizeof(Menu_Hierarchical_Transition_Animation));
Menu_Hierarchical->Transition_Animation->State = MENU_HIERARCHICAL_TRANSITION_STATE_IDLE;
Menu_Hierarchical->Transition_Animation->Direction = MENU_TRANSITION_ENTER_SUBMENU;
Menu_Hierarchical->Transition_Animation->Transition_Counter = 0;
Menu_Hierarchical->Transition_Animation->Total_Transition_Frames = MENU_HIERARCHICAL_TRANSITION_FRAMES;
Menu_Hierarchical->Transition_Animation->Previous_List = NULL;
Menu_Hierarchical->Transition_Animation->Target_List = NULL;
Menu_Hierarchical->Transition_Animation->Current_Menu_X_Offset = 0;
Menu_Hierarchical->Transition_Animation->Target_Menu_X_Offset = 0;
Menu_Hierarchical->Transition_Animation_Active = false;
return Display_Objects_Add(MENU_HIERARCHICAL, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Menu_Hierarchical, NO_STYLE, NO_ANIMATION);
}
Object_ID Display_Objects_Add_Select_YesNo(char* title, uint32_t title_length, bool* value, Configuration_Select_YesNo* config)
{
Object_Select_YesNo* Select_YesNo = malloc(sizeof(Object_Select_YesNo));
@@ -737,7 +777,7 @@ Object_ID Display_Objects_Add_Select_Value(char* title, uint32_t title_length, i
return Display_Objects_Add(SELECT_VALUE, LEFT_TOP, BOTH_IN_PIXEL, 0, 0, NOT_SELECTABLE, (void *)Select_Value, NO_STYLE, NO_ANIMATION);
}
Object_ID Display_Objects_Add_Select_RGB(RGB_Color* color_value, uint8_t* current_component, Configuration_Select_RGB* config)
Object_ID Display_Objects_Add_Select_RGB(LED_Data_t* color_value, uint8_t* current_component, Configuration_Select_RGB* config)
{
if (color_value == NULL || config == NULL) {
return -1; // Invalid parameters
@@ -1397,27 +1437,31 @@ Dimension Display_Objects_Get_Content_Size(Display_Object *object)
break;
case MESSAGE_BOX:
Display_Font_Set_Font(((Object_Message_Box *)Data)->Font->Font);
Dimension.Height = Display_Font_Get_Font_Height() + MESSAGE_BOX_TEXT_BAR_DISTANCE + MESSAGE_BOX_BAR_HEIGHT;
Dimension.Width = Display_Font_Width_String((((Object_Message_Box *)Data)->Text), ((Object_Message_Box *)Data)->Length, ((Object_Message_Box *)Data)->Font->Character_Spacing);
if((((Object_Message_Box *)Data)->Icon) != MESSAGE_BOX_ICON_NONE) {
Dimension.Width += MESSAGE_BOX_TEXT_ICON_DISTANCE + Display_Message_Box_Icons_Get_Icon_Width(((Object_Message_Box *)Data)->Icon);
Object_Message_Box* MB = (Object_Message_Box *)Data;
const Message_Box_Style* Style = MB->Style;
if(Style == NULL) {
return Dimension;
}
if(Display_Message_Box_Icons_Get_Icon_Height(((Object_Message_Box *)Data)->Icon) > Display_Font_Get_Font_Height()) {
Dimension.Height = Display_Message_Box_Icons_Get_Icon_Height(((Object_Message_Box *)Data)->Icon) + MESSAGE_BOX_TEXT_BAR_DISTANCE + MESSAGE_BOX_BAR_HEIGHT;
}
Display_Font_Set_Font(Style->Font);
Dimension.Height = Display_Font_Get_Font_Height() + 2 * Style->Border_Thickness + Style->Padding[PADDING_TOP] + Style->Padding[PADDING_BOTTOM];
Dimension.Width = Display_Font_Width_String(MB->Text, MB->Length, DISPLAY_DEFAULT_CHAR_SPACING) + 2 * Style->Border_Thickness + Style->Padding[PADDING_LEFT] + Style->Padding[PADDING_RIGHT];
if(MB->Icon != MESSAGE_BOX_ICON_NONE) {
Dimension.Width += (MESSAGE_BOX_TEXT_ICON_DISTANCE + Display_Message_Box_Icons_Get_Icon_Width(MB->Icon));
}
break;
case MENU_SELECT:
case MENU_ICON_ROW:
case MENU_RING:
case MENU_HIERARCHICAL:
case SELECT_YESNO:
case SELECT_LIST:
case SELECT_VALUE:
case SELECT_RGB:
Dimension.Height = 0;
Dimension.Width = 0;
break;
default:

View File

@@ -18,6 +18,8 @@
#include "Display_Config.h"
#include "Display_Objects_Datatypes.h"
#include "Command_Definition.h"
// ============================================================================================
// Defines
@@ -77,14 +79,15 @@ Object_ID Display_Objects_Add_Arc_Frame ( Coordinates_Type coordinates_
Object_ID Dispaly_Objects_Add_Line_XY ( Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, int16_t x2, int16_t y2, uint16_t thickness , Style_ID style_id, Animation_ID animation_id);
Object_ID Dispaly_Objects_Add_Line_Rad ( Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint16_t radius_start, uint16_t radius_end, uint16_t thickness, int16_t angle , Style_ID style_id, Animation_ID animation_id);
Object_ID Display_Objects_Add_Canvas (Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, bool selectable, Display_Color color, uint width, uint height , Style_ID style_id, Animation_ID animation_id);
Object_ID Display_Objects_Add_Message_Box (Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, char* text, Font_ID font, Object_Message_Box_Icon icon, Display_Color color , Style_ID style_id);
Object_ID Display_Objects_Add_Message_Box (Anchor_Point anchor_point, Coordinates_Type coordinates_type, int16_t x, int16_t y, char* text, Object_Message_Box_Icon icon, const Message_Box_Style* style);
Object_ID Display_Objects_Add_Menu_Select (char* menu_titles, uint32_t menu_entry_count, uint32_t title_char_length, uint32_t* selected_entry, Configuration_Menu_Select* config);
Object_ID Display_Objects_Add_Menu_Icon_Row (Icon_Row_Item* items, uint32_t item_count, uint32_t* selected_item, Configuration_Menu_Icon_Row* config);
Object_ID Display_Objects_Add_Menu_Ring (Menu_Ring_Item_Config* items, uint32_t item_count, uint32_t* selected_item, Configuration_Menu_Ring* config);
Object_ID Display_Objects_Add_Menu_Hierarchical (const Menu_List** current_list, int32_t* selected_item, int32_t* scroll_offset, Configuration_Menu_Hierarchical* config);
Object_ID Display_Objects_Add_Select_YesNo (char* title, uint32_t title_length, bool* value, Configuration_Select_YesNo* config);
Object_ID Display_Objects_Add_Select_List (char* list_titles, uint32_t list_entry_count, uint32_t list_char_length, uint32_t* selected_entry, Configuration_Select_List* config);
Object_ID Display_Objects_Add_Select_Value (char* title, uint32_t title_length, int32_t* value, int32_t max, int32_t min, char* format, Configuration_Select_Value* config);
Object_ID Display_Objects_Add_Select_RGB (RGB_Color* color_value, uint8_t* current_component, Configuration_Select_RGB* config);
Object_ID Display_Objects_Add_Select_RGB (LED_Data_t* color_value, uint8_t* current_component, Configuration_Select_RGB* config);
Object_ID Display_Objects_Add_Entry_Indicator (uint32_t entry_count, int32_t* entry_value, Configuration_Entry_Indicator* config);

View File

@@ -11,6 +11,7 @@
// ============================================================================================
// Includes
#include "Display_Config.h"
#include "Command_Definition.h"
// ============================================================================================
@@ -41,10 +42,23 @@
#define MENU_RING_APPEAR_ITEM_POP_SPEED 4 // Frames for each item to appear
#define MENU_RING_APPEAR_ITEM_DELAY 1 // Frames between each item appearance
// Animation timing constants Menu Hierarchical
#define MENU_HIERARCHICAL_TRANSITION_FRAMES 20 // Frames for slide transition
#define MENU_HIERARCHICAL_SLIDE_DISTANCE DISPLAY_WIDTH // Pixels to slide (full screen width)
// ============================================================================================
// Variables / Datatypes
/*******************************************************************
Forwward Declarations
*******************************************************************/
typedef struct Menu_Item_S Menu_Item;
typedef struct Menu_List_S Menu_List;
typedef struct Hierarchical_Menu_S Hierarchical_Menu;
/*******************************************************************
Generic Types
*******************************************************************/
@@ -61,7 +75,7 @@ typedef union
uint32_t Pixel;
} __packed RGB_Color;
typedef enum {
typedef enum {
FLOAT,
INTEGER,
TEXT,
@@ -77,6 +91,7 @@ typedef enum {
MENU_SELECT,
MENU_ICON_ROW,
MENU_RING,
MENU_HIERARCHICAL,
SELECT_YESNO,
SELECT_LIST,
SELECT_VALUE,
@@ -300,11 +315,13 @@ typedef struct {
uint16_t* Data;
} Object_Canvas;
/*******************************************************************
MESSAGE_BOX Configuration and Object Structure
*******************************************************************/
typedef enum {
MESSAGE_BOX_TEXT_BAR_DISTANCE = 2,
MESSAGE_BOX_BAR_HEIGHT = 3,
MESSAGE_BOX_TEXT_ICON_DISTANCE = 2
MESSAGE_BOX_TEXT_ICON_DISTANCE = 10
} Object_Message_Box_Properties;
typedef enum {
@@ -322,22 +339,37 @@ typedef enum {
} Object_Message_Box_Icon;
typedef struct {
char Text[64];
uint8_t Length;
Font* Font;
Display_Color Color;
const unsigned char* Font;
Display_Color Background_Color;
Display_Color Border_Color;
Display_Color Text_Color;
Display_Color Accent_Color;
Display_Color Shadow_Color;
uint8_t Border_Radius;
uint8_t Border_Thickness;
uint32_t Padding[4];
} Message_Box_Style;
typedef struct {
char Text[64];
int Length;
Object_Message_Box_Icon Icon;
const Message_Box_Style* Style;
uint32_t Show_Ticks_Max;
uint32_t Show_Ticks_Left;
} Object_Message_Box;
typedef struct {
int16_t X_Offset;
int16_t X_Indent;
const unsigned char *Font[3];
const unsigned char* Font[3];
Display_Color Color[3];
} Configuration_Menu_Select;
@@ -376,6 +408,9 @@ typedef struct {
} Object_Menu_Icon_Row;
/*******************************************************************
MENU_RING Configuration and Object Structure
*******************************************************************/
// Animation data structure
typedef struct {
Menu_Ring_Appear_State State;
@@ -458,6 +493,101 @@ typedef struct {
} Object_Menu_Ring;
/*******************************************************************
MENU_HIERARCHICAL Configuration and Object Structure
*******************************************************************/
// Animation states for hierarchical menu transitions
typedef enum {
MENU_HIERARCHICAL_TRANSITION_STATE_IDLE, // No transition running
MENU_HIERARCHICAL_TRANSITION_STATE_SLIDE_OUT, // Current menu sliding out
MENU_HIERARCHICAL_TRANSITION_STATE_SLIDE_IN, // New menu sliding in
MENU_HIERARCHICAL_TRANSITION_STATE_COMPLETE // Transition finished
} Menu_Hierarchical_Transition_State;
// Direction of menu transition
typedef enum {
MENU_TRANSITION_ENTER_SUBMENU, // Moving deeper into menu hierarchy
MENU_TRANSITION_EXIT_SUBMENU // Moving back up in hierarchy
} Menu_Transition_Direction;
// Transition animation structure
typedef struct {
Menu_Hierarchical_Transition_State State;
Menu_Transition_Direction Direction;
// Animation progress
uint16_t Transition_Counter;
uint16_t Total_Transition_Frames;
// Menu states
const Menu_List* Previous_List; // Menu being transitioned from
const Menu_List* Target_List; // Menu being transitioned to
int32_t Previous_Selected_Item;
int32_t Target_Selected_Item;
int32_t Previous_Scroll_Offset;
int32_t Target_Scroll_Offset;
// Visual offsets for slide animation
int16_t Current_Menu_X_Offset; // Current menu position
int16_t Target_Menu_X_Offset; // Target menu position
} Menu_Hierarchical_Transition_Animation;
typedef struct {
// Fonts
const unsigned char *Title_Font;
const unsigned char *Item_Font;
const unsigned char *Back_Font;
// Colors
Display_Color Title_Color;
Display_Color Item_Selected_Color;
Display_Color Item_Normal_Color;
Display_Color Item_Back_Color;
Display_Color Background_Color;
Display_Color Border_Color;
Display_Color Indicator_Color;
// Layout
int16_t Title_Y_Offset;
int16_t Menu_Start_Y;
int16_t Item_Height;
int16_t Item_Spacing;
uint8_t Item_Alignment;
int16_t Side_Padding;
int16_t Visible_Items;
// Animation
uint16_t Animation_Speed;
uint16_t Transition_Frames;
// Visual indicators
bool Show_Scroll_Indicators;
bool Show_Item_Icons;
bool Show_Sub_Menu_Indicators;
bool Show_Selection_Box;
uint16_t Selection_Box_Padding;
} Configuration_Menu_Hierarchical;
typedef struct {
const Menu_List** Current_List;
int32_t* Selected_Item;
int32_t* Scroll_Offset;
Configuration_Menu_Hierarchical* Config;
// Internal state
uint32_t Animation_Counter;
float Transition_Progress;
int32_t Last_Selected_Item;
const Menu_List* Last_Current_List; // Previous frame's current list
int32_t Last_Selected_Item_Value; // Previous frame's selected item
int32_t Last_Scroll_Offset_Value; // Previous frame's scroll offset
Menu_Hierarchical_Transition_Animation* Transition_Animation;
bool Transition_Animation_Active;
} Object_Menu_Hierarchical;
typedef struct {
const unsigned char *Title_Font;
Display_Color Title_Color;
@@ -566,7 +696,7 @@ typedef struct {
typedef struct {
// RGB value pointer
RGB_Color* Color_Value; // Pointer to RGB color structure
LED_Data_t* Color_Value; // Pointer to RGB color structure
// Current state
uint8_t *Current_Component; // Active component: 0=Red, 1=Green, 2=Blue

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,46 @@
/*
* File: Display_Render_Complex.h
* Created: Created: Saturday September 2025 09:22:17
* Author: Chris
*/
#ifndef DISPLAY_RENDER_COMPLEX_H
#define DISPLAY_RENDER_COMPLEX_H
// ============================================================================================
// Includes
#include <math.h>
#include <string.h>
#include "Display_Shapes.h"
#include "Display_Objects.h"
// ============================================================================================
// Defines
// ============================================================================================
// Datatypes
// ============================================================================================
// Function Declarations
void Display_Render_Complex_Value_Bar_Rect (Coordinates* coordinates, Object_Value_Bar_Rect* value_bar);
void Display_Render_Complex_Value_Bar_Arc (Coordinates* coordinates, Object_Value_Bar_Arc* value_bar);
void Display_Render_Complex_Graph (Coordinates* coordinates, Object_Graph* graph);
void Display_Render_Complex_Button (Coordinates* coordinates, Object_Button* button);
void Display_Render_Complex_Canvas (Coordinates* coordinates, Object_Canvas* canvas);
void Display_Render_Complex_Message_Box (Coordinates* coordinates, Object_Message_Box* message_box, int16_t width, int16_t height);
void Display_Render_Complex_Menu_Select (Coordinates* coordinates, char* menu_titles, uint32_t menu_entry_count, uint32_t title_char_length, uint32_t selected_entry, Configuration_Menu_Select* config);
void Display_Render_Complex_Menu_Icon_Row_Set (uint32_t initially_selected_item, uint32_t icon_space_width);
void Display_Render_Complex_Menu_Icon_Row (Coordinates* coordinates, Icon_Row_Item* items, uint32_t item_count, uint32_t selected_item, Configuration_Menu_Icon_Row* config);
void Display_Render_Complex_Menu_Ring (Coordinates* coordinates, Object_Menu_Ring* ring_menu);
void Display_Render_Complex_Menu_Hierarchical (Coordinates* coordinates, Object_Menu_Hierarchical* menu_hierarchical);
void Display_Render_Complex_Select_YesNo (Coordinates* coordinates, char* title, uint32_t title_length, bool value, Configuration_Select_YesNo* config);
void Display_Render_Complex_Select_List (Coordinates* coordinates, char* list_titles, uint32_t list_entry_count, uint32_t list_char_length, uint32_t selected_entry, Configuration_Select_List* config);
void Display_Render_Complex_Select_Value (Coordinates* coordinates, char* title, uint32_t title_length, int32_t value, int32_t max, int32_t min, char* format, Configuration_Select_Value* config);
void Display_Render_Complex_Select_RGB (Coordinates* coordinates, Object_Select_RGB* rgb_selector);
void Display_Render_Complex_Entry_Indicator (Coordinates* coordinates, uint32_t entry_count, int32_t entry_value, Configuration_Entry_Indicator* config);
#endif // DISPLAY_RENDER_COMPLEX_H

View File

@@ -0,0 +1,152 @@
/*
* File: Display_Render_Simple.c
*
* Created: Created: Saturday September 2025 09:22:12
* Author: Chris
*/
#include "Display_Render_Simple.h"
// ============================================================================================
// Includes
#include "Display_Font.h"
#include "Display_Color.h"
#include "Display_Image.h"
// ============================================================================================
// Variables
static Screen_Transition_Settings_t* _Transition_Settings;
// ============================================================================================
// Function Declarations
/*******************************************************************
Functions
*******************************************************************/
void Display_Render_Simple_Init(Screen_Transition_Settings_t* transition_settings)
{
_Transition_Settings = transition_settings;
}
void Display_Render_Simple_Float(Coordinates* coordinates_object, Object_Float* float_data)
{
char String[64];
uint32_t String_Char_Count;
Display_Font_Set_Font(float_data->Font->Font);
String_Char_Count = sprintf(String, float_data->Format, *(float_data->Value));
Display_Font_Print_String(coordinates_object->X, coordinates_object->Y, String, String_Char_Count, float_data->Font->Character_Spacing, float_data->Color);
}
void Display_Render_Simple_Integer(Coordinates* coordinates_object, Object_Integer* integer_data)
{
char String[64];
uint32_t String_Char_Count;
Display_Font_Set_Font(integer_data->Font->Font);
String_Char_Count = sprintf(String, integer_data->Format, *(integer_data->Value));
Display_Font_Print_String(coordinates_object->X, coordinates_object->Y, String, String_Char_Count, integer_data->Font->Character_Spacing, integer_data->Color);
}
void Display_Render_Simple_Text(Coordinates* coordinates_object, Object_Text* text_data)
{
char String[64];
uint32_t String_Char_Count;
Display_Font_Set_Font(text_data->Font->Font);
sprintf(String, "%s", text_data->Text);
String_Char_Count = text_data->Length;
Display_Font_Print_String(coordinates_object->X, coordinates_object->Y, String, String_Char_Count, text_data->Font->Character_Spacing, text_data->Color);
}
void Display_Render_Simple_Image(Coordinates* coordinates_object, Object_Image_Color* image)
{
if(image->Rotation_Angle == 0) {
Display_Image_Draw_Color_Alpha(coordinates_object->X, coordinates_object->Y, image->Image, image->Alpha);
}
else {
Display_Image_Draw_Color_Rotated_Alpha(coordinates_object->X, coordinates_object->Y, image->Image, image->Rotation_Angle, image->Alpha);
}
}
void Display_Render_Simple_Bool(Coordinates* coordinates_object, Object_Bool* bool_data)
{
char String[64];
uint32_t String_Char_Count;
Display_Color Color;
Display_Font_Set_Font(bool_data->Font->Font);
if(*bool_data->Value == true)
{
sprintf(String, "%s", bool_data->Text_True);
String_Char_Count = bool_data->Length_True;
Color = bool_data->Color_True;
}
else
{
sprintf(String, "%s", bool_data->Text_False);
String_Char_Count = bool_data->Length_False;
Color = bool_data->Color_False;
}
Display_Font_Print_String(coordinates_object->X, coordinates_object->Y, String, String_Char_Count, bool_data->Font->Character_Spacing, Color);
}
void Display_Render_Simple_Shape(Coordinates* coordinates_object, Object_Shape* shape)
{
int16_t X1, X2, Y1, Y2;
switch (shape->Type)
{
case RECTANGLE_FILLED:
Display_Shapes_Draw_Rect_Filled(coordinates_object->X, coordinates_object->Y, shape->Dimension.Width, shape->Dimension.Height, shape->Color);
break;
case RECTANGLE_FRAME:
Display_Shapes_Draw_Rect_Frame(coordinates_object->X, coordinates_object->Y, shape->Dimension.Width, shape->Dimension.Height, shape->Thickness, shape->Color);
break;
case ROUNDED_RECTANGLE_FILLED:
Display_Shapes_Draw_Round_Rect_Filled(coordinates_object->X, coordinates_object->Y, shape->Dimension.Width, shape->Dimension.Height, shape->Radius_Start, shape->Color);
break;
case ROUNDED_RECTANGLE_FRAME:
Display_Shapes_Draw_Round_Rect_Frame(coordinates_object->X, coordinates_object->Y, shape->Dimension.Width, shape->Dimension.Height, shape->Radius_Start, shape->Thickness, shape->Color);
break;
case CIRCLE_FILLED:
Display_Shapes_Draw_Circle_Filled(coordinates_object->X, coordinates_object->Y, shape->Radius_Start, shape->Color);
break;
case CIRCLE_FRAME:
Display_Shapes_Draw_Circle_Frame(coordinates_object->X, coordinates_object->Y, shape->Radius_Start, shape->Thickness, shape->Color);
break;
case ARC:
Display_Shapes_Draw_Arc_Frame(coordinates_object->X, coordinates_object->Y, shape->Radius_Start, shape->Thickness, shape->Angle_Start, shape->Angle_End, shape->Draw_Steps, shape->Color);
break;
case LINE_XY:
X2 = shape->Angle_Start - _Transition_Settings->Offset.X; // Angle Start contains X2
Y2 = shape->Angle_End - _Transition_Settings->Offset.Y; // Angle End contains Y2
Display_Shapes_Draw_Line_XY(coordinates_object->X, coordinates_object->Y, X1, Y2, shape->Thickness, shape->Color);
break;
case LINE_RAD:
Display_Shapes_Draw_Line_Rad(coordinates_object->X, coordinates_object->Y, shape->Angle_Start, shape->Radius_Start, shape->Radius_End, shape->Thickness, shape->Color);
break;
}
}
/*******************************************************************
Internal Functions
*******************************************************************/

View File

@@ -0,0 +1,39 @@
/*
* File: Display_Render_Simple.h
* Created: Created: Saturday September 2025 09:22:07
* Author: Chris
*/
#ifndef DISPLAY_RENDER_SIMPLE_H
#define DISPLAY_RENDER_SIMPLE_H
// ============================================================================================
// Includes
#include <math.h>
#include <string.h>
#include "Display.h"
#include "Display_Shapes.h"
#include "Display_Objects.h"
// ============================================================================================
// Defines
// ============================================================================================
// Datatypes
// ============================================================================================
// Function Declarations
void Display_Render_Simple_Init(Screen_Transition_Settings_t* transition_settings);
void Display_Render_Simple_Float(Coordinates* coordinates_object, Object_Float* float_data);
void Display_Render_Simple_Integer(Coordinates* coordinates_object, Object_Integer* integer_data);
void Display_Render_Simple_Text(Coordinates* coordinates_object, Object_Text* text_data);
void Display_Render_Simple_Image(Coordinates* coordinates_object, Object_Image_Color* image);
void Display_Render_Simple_Bool(Coordinates* coordinates_object, Object_Bool* bool_data);
void Display_Render_Simple_Shape(Coordinates* coordinates_object, Object_Shape* shape);
#endif // DISPLAY_RENDER_SIMPLE_H

View File

@@ -45,11 +45,6 @@ static dma_channel_config _DMA_Config_Drawing;
void Display_Shapes_Draw_Rounded_Rect_Frame_1 (int16_t x, int16_t y, uint16_t width, uint16_t height, uint16_t radius, Display_Color color);
void Display_Shapes_Draw_Circle_Frame_1 (int16_t center_x, int16_t center_y, uint16_t radius, Display_Color color);
void Display_Shapes_Draw_Circle_Helper(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color);
void Display_Shapes_Draw_Circle_Helper_Improved(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color);
void Display_Shapes_Draw_Circle_Helper_Single_Pixel(int16_t x0, int16_t y0, uint16_t radius, uint8_t cornername, Display_Color color);
void Display_Shapes_Draw_Circle_Helper_Filled(int16_t x0, int16_t y0, uint16_t radius, uint8_t corners, int16_t delta, Display_Color color);
/*******************************************************************
Functions
@@ -84,7 +79,8 @@ void Display_Shapes_Fill_Screen(Display_Color color)
void Display_Shapes_Draw_Pixel_Safe(int16_t x, int16_t y, Display_Color color)
{
if(x >= 0 && x < DISPLAY_WIDTH && y >= 0 && y < DISPLAY_HEIGHT)
// Cast to uint16_t purpose to reduce the amount of comparisions required
if((uint16_t)x < DISPLAY_WIDTH && (uint16_t)y < DISPLAY_HEIGHT)
{
(*_Current_Buffer)->Dim_2[y][x] = color;
}
@@ -722,189 +718,4 @@ void Display_Shapes_Draw_Circle_Frame_1(int16_t center_x, int16_t center_y, uint
Last_X = Data[i];
}
}
/**************************************************************************/
/*!
@brief Quarter-circle drawer, used to do circles and roundrects
@param x0 Center-point x coordinate
@param y0 Center-point y coordinate
@param r Radius of circle
@param cornername Mask bit #1 or bit #2 to indicate which quarters of the circle we're doing
@param color 16-bit 5-6-5 Color to draw with
*/
/**************************************************************************/
void Display_Shapes_Draw_Circle_Helper(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color)
{
int16_t f = 1 - radius;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * radius;
int16_t x = 0;
int16_t y = radius;
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & CORNER_BOTTOM_RIGHT)
{
Display_Shapes_Draw_Circle_Filled(x0 + x, y0 + y, thickness >> 1, color);
Display_Shapes_Draw_Circle_Filled(x0 + y, y0 + x, thickness >> 1, color);
}
if (cornername & CORNER_TOP_RIGHT)
{
Display_Shapes_Draw_Circle_Filled(x0 + x, y0 - y, thickness >> 1, color);
Display_Shapes_Draw_Circle_Filled(x0 + y, y0 - x, thickness >> 1, color);
}
if (cornername & CORNER_BOTTOM_LEFT)
{
Display_Shapes_Draw_Circle_Filled(x0 - x, y0 + y, thickness >> 1, color);
Display_Shapes_Draw_Circle_Filled(x0 - y, y0 + x, thickness >> 1, color);
}
if (cornername & CORNER_TOP_LEFT)
{
Display_Shapes_Draw_Circle_Filled(x0 - x, y0 - y, thickness >> 1, color);
Display_Shapes_Draw_Circle_Filled(x0 - y, y0 - x, thickness >> 1, color);
}
}
}
void Display_Shapes_Draw_Circle_Helper_Improved(int16_t x0, int16_t y0, uint16_t radius, uint16_t thickness, uint8_t cornername, Display_Color color)
{
if (radius == 0) return;
// For thickness of 1, use single pixel drawing
if (thickness == 1) {
Display_Shapes_Draw_Circle_Helper_Single_Pixel(x0, y0, radius, cornername, color);
return;
}
// For thicker lines, draw multiple concentric quarter-circles
// This ensures consistent thickness with the straight edges
for (uint16_t t = 0; t < thickness; t++) {
uint16_t current_radius = radius - t;
if (current_radius == 0) break;
Display_Shapes_Draw_Circle_Helper_Single_Pixel(x0, y0, current_radius, cornername, color);
}
}
void Display_Shapes_Draw_Circle_Helper_Single_Pixel(int16_t x0, int16_t y0, uint16_t radius, uint8_t cornername, Display_Color color)
{
if (radius == 0) return;
// Use Bresenham's circle algorithm for single pixel drawing
int16_t f = 1 - radius;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * radius;
int16_t x = 0;
int16_t y = radius;
while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
// Draw quarter-circle segments based on corner mask - single pixels only
if (cornername & CORNER_TOP_LEFT) {
Display_Shapes_Draw_Pixel_Safe(x0 - x, y0 - y, color);
Display_Shapes_Draw_Pixel_Safe(x0 - y, y0 - x, color);
}
if (cornername & CORNER_TOP_RIGHT) {
Display_Shapes_Draw_Pixel_Safe(0 + x, y0 - y, color);
Display_Shapes_Draw_Pixel_Safe(x0 + y, y0 - x, color);
}
if (cornername & CORNER_BOTTOM_RIGHT) {
Display_Shapes_Draw_Pixel_Safe(x0 + x, y0 + y, color);
Display_Shapes_Draw_Pixel_Safe(x0 + y, y0 + x, color);
}
if (cornername & CORNER_BOTTOM_LEFT) {
Display_Shapes_Draw_Pixel_Safe(x0 - x, y0 + y, color);
Display_Shapes_Draw_Pixel_Safe(x0 - y, y0 + x, color);
}
}
}
/**************************************************************************/
/*!
@brief Quarter-circle drawer with fill, used for circles and roundrects
@param x0 Center-point x coordinate
@param y0 Center-point y coordinate
@param r Radius of circle
@param corners Mask bits indicating which quarters we're doing
@param delta Offset from center-point, used for round-rects
@param color 16-bit 5-6-5 Color to fill with
*/
/**************************************************************************/
void Display_Shapes_Draw_Circle_Helper_Filled(int16_t x0, int16_t y0, uint16_t radius, uint8_t corners, int16_t delta, Display_Color color)
{
int16_t f = 1 - radius;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * radius;
int16_t x = 0;
int16_t y = radius;
int16_t px = x;
int16_t py = y;
delta++; // Avoid some +1's in the loop
while (x < y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
// These checks avoid double-drawing certain lines, important
// for the SSD1306 library which has an INVERT drawing mode.
if (x < (y + 1))
{
if (corners & CORNER_TOP_LEFT) {
Display_Shapes_Draw_VLine(x0 + x, y0 - y, 2 * y + delta, 1, color);
// writeFastVLine(x0 + x, y0 - y, 2 * y + delta, color);
}
if (corners & CORNER_TOP_RIGHT) {
Display_Shapes_Draw_VLine(x0 - x, y0 - y, 2 * y + delta, 1, color);
// writeFastVLine(x0 - x, y0 - y, 2 * y + delta, color);
}
}
if (y != py)
{
if (corners & CORNER_TOP_LEFT) {
Display_Shapes_Draw_VLine(x0 + py, y0 - px, 2 * px + delta, 1, color);
// writeFastVLine(x0 + py, y0 - px, 2 * px + delta, color);
}
if (corners & CORNER_TOP_RIGHT) {
Display_Shapes_Draw_VLine(x0 - py, y0 - px, 2 * px + delta, 1, color);
// writeFastVLine(x0 - py, y0 - px, 2 * px + delta, color);
}
py = y;
}
px = x;
}
}

View File

@@ -43,5 +43,4 @@ void Display_Shapes_Draw_Glow_Circle (int16_t center_x, int16_t center_y,
Coordinates Display_Shapes_Polar_To_XY (int16_t origin_x, int16_t origin_y, float angle, uint16_t radius);
#endif /* DISPLAY_SHAPES_H_ */

View File

@@ -165,7 +165,9 @@ void EEPROM_Check_Content_Valid()
_EEPROM_Content.Channel_MIDI_Configuration[LED_Channel_1].Skip_Note_Off_Event = 1;
}
// Pause Light Enabled no need, as bool is compared with equal to 0
if(_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Enabled > 1) {
_EEPROM_Content.Pause_Light_Configuration[LED_Channel_1].Enabled = 1;
}
// Pause Light Color no need, as full range of UINT8 is valid

View File

@@ -0,0 +1,123 @@
/*
* File: Hierarchical_Menu.c
*
* Created: Created: Sunday September 2025 07:47:28
* Author: Chris
*/
#include "Hierarchical_Menu.h"
// ============================================================================================
// Includes
#include "Screens.h"
#include "EEPROM_M24C64.h"
// ============================================================================================
// Forward Declaration
static const Menu_Item _Menu_Items_MIDI_Config[];
static const Menu_Item _Menu_Items_MIDI_Notes[];
static const Menu_Item _Menu_Items_MIDI_Pause[];
static const Menu_Item _Menu_Items_MIDI[];
static const Menu_List _Menu_List_MIDI_Config;
static const Menu_List _Menu_List_MIDI_Notes;
static const Menu_List _Menu_List_MIDI_Pause;
static const Menu_List _Menu_List_MIDI;
const Hierarchical_Menu _Hierarchical_Menu_MIDI;
// ============================================================================================
// Variables
static const Menu_Item _Menu_Items_MIDI_Config[] = {
{ "MIDI Channel" , NULL, false, &_Menu_List_MIDI_Config, NONE, "", NULL },
{ "Select Octave" , NULL, false, &_Menu_List_MIDI_Config, NONE, "", NULL },
{ "Skip Note Off" , NULL, false, &_Menu_List_MIDI_Config, BOOL, "Skip Note Off", (void*)(&_EEPROM_Content.Channel_MIDI_Configuration[0].Skip_Note_Off_Event) },
{ "Back" , NULL, true , &_Menu_List_MIDI_Config, NONE, "", NULL }
};
static const Menu_List _Menu_List_MIDI_Config = {
.Title = "MIDI Config",
.Items = _Menu_Items_MIDI_Config,
.Item_Count = sizeof(_Menu_Items_MIDI_Config) / sizeof(Menu_Item),
.Parent = &_Menu_Items_MIDI[0],
.Root = &_Hierarchical_Menu_MIDI
};
static const Menu_Item _Menu_Items_MIDI_Notes[] = {
{ "Red" , NULL, false, &_Menu_List_MIDI_Notes, NONE, "", NULL },
{ "Green" , NULL, false, &_Menu_List_MIDI_Notes, NONE, "", NULL },
{ "Blue" , NULL, false, &_Menu_List_MIDI_Notes, NONE, "", NULL },
{ "Default Notes" , NULL, false, &_Menu_List_MIDI_Notes, NONE, "", NULL },
{ "Back" , NULL, true , &_Menu_List_MIDI_Notes, NONE, "", NULL }
};
static const Menu_List _Menu_List_MIDI_Notes = {
.Title = "Color Notes",
.Items = _Menu_Items_MIDI_Notes,
.Item_Count = sizeof(_Menu_Items_MIDI_Notes) / sizeof(Menu_Item),
.Parent = &_Menu_Items_MIDI[1],
.Root = &_Hierarchical_Menu_MIDI
};
static const Menu_Item _Menu_Items_MIDI_Pause[] = {
{ "Enable" , NULL, false, &_Menu_List_MIDI_Pause, BOOL, "Enable Pause Light", (void*)(&_EEPROM_Content.Pause_Light_Configuration[0].Enabled) },
{ "Color" , NULL, false, &_Menu_List_MIDI_Pause, RGB , "Pause Light Color", (void*)(&_EEPROM_Content.Pause_Light_Configuration[0].Color) },
{ "Fade Speed" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Timeout" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Reset" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 1" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 2" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 3" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 4" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 5" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Item 6" , NULL, false, &_Menu_List_MIDI_Pause, NONE, "", NULL },
{ "Back" , NULL, true , &_Menu_List_MIDI_Pause, NONE, "", NULL }
};
static const Menu_List _Menu_List_MIDI_Pause = {
.Title = "Pause Light",
.Items = _Menu_Items_MIDI_Pause,
.Item_Count = sizeof(_Menu_Items_MIDI_Pause) / sizeof(Menu_Item),
.Parent = &_Menu_Items_MIDI[2],
.Root = &_Hierarchical_Menu_MIDI
};
static const Menu_Item _Menu_Items_MIDI[] = {
{ "MIDI Config" , &_Menu_List_MIDI_Config , false, &_Menu_List_MIDI },
{ "Color Notes" , &_Menu_List_MIDI_Notes , false, &_Menu_List_MIDI },
{ "Pause Light" , &_Menu_List_MIDI_Pause , false, &_Menu_List_MIDI },
{ "Back" , NULL , true , &_Menu_List_MIDI }
};
static const Menu_List _Menu_List_MIDI = {
.Title = "MIDI",
.Items = _Menu_Items_MIDI,
.Item_Count = sizeof(_Menu_Items_MIDI) / sizeof(Menu_Item),
.Parent = NULL,
.Root = &_Hierarchical_Menu_MIDI
};
const Hierarchical_Menu _Hierarchical_Menu_MIDI = {
.List = &_Menu_List_MIDI,
.Parent_Function = &Screen_Setup_Settings,
.Parent_Selected_Setting = 0
};
// ============================================================================================
// Function Declarations
/*******************************************************************
Functions
*******************************************************************/
/*******************************************************************
Internal Functions
*******************************************************************/

View File

@@ -0,0 +1,70 @@
/*
* File: Hierarchical_Menu.h
* Created: Created: Sunday September 2025 07:47:35
* Author: Chris
*/
#ifndef HIERARCHICAL_MENU_H
#define HIERARCHICAL_MENU_H
// ============================================================================================
// Includes
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "Display.h"
#include "Display_Objects.h"
#include "Display_Objects_Datatypes.h"
// ============================================================================================
// Defines
// ============================================================================================
// Forward declarations
typedef struct Menu_Item_S Menu_Item;
typedef struct Menu_List_S Menu_List;
typedef struct Hierarchical_Menu_S Hierarchical_Menu;
// ============================================================================================
// Datatypes
typedef enum {
NONE,
BOOL,
RGB
} Variable_Type;
typedef struct Menu_Item_S {
const char* Text;
const Menu_List* List;
const bool Is_Back;
const Menu_List* Containing_List;
const Variable_Type Type;
const char* Variable_Title;
const void* Variable;
} Menu_Item;
typedef struct Menu_List_S {
const char* Title;
const Menu_Item* Items;
const uint32_t Item_Count;
const Menu_Item* Parent;
const Hierarchical_Menu* Root;
} Menu_List;
typedef struct Hierarchical_Menu_S {
const Menu_List* List;
const void (*Parent_Function)(Screen_Transition_Direction, Screen_Transition_Direction, Easing, uint32_t, int32_t);
const int32_t Parent_Selected_Setting;
} Hierarchical_Menu;
// ============================================================================================
// Variables
#endif // HIERARCHICAL_MENU_H

View File

@@ -13,6 +13,7 @@
// ============================================================================================
// Variables
void (*_Screen_Last)(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
void (*_Screen_Tick)(void);
void (*_Screen_Click)(uint button_return_value);
void (*_Screen_Touch_Event)(int16_t x, int16_t y);

View File

@@ -15,6 +15,8 @@
#include <stdbool.h>
#include "Easings.h"
#include "Hierarchical_Menu.h"
#include "Command_Definition.h"
#include "Display_Objects_Datatypes.h"
@@ -24,6 +26,7 @@
// ============================================================================================
// Variables (do not edit)
extern void (*_Screen_Last)(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
extern void (*_Screen_Tick)(void);
extern void (*_Screen_Click)(uint button_return_value);
extern void (*_Screen_Touch_Event)(int16_t x, int16_t y);
@@ -45,14 +48,12 @@ extern void Screen_Setup_Graph(Screen_Transition_Direction direction_out, Screen
extern void Screen_Setup_Settings(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
extern void Screen_Setup_Settings_MIDI(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
extern void Screen_Setup_Settings_MIDI_Config(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
extern void Screen_Setup_Settings_Hierarchical_Menu(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, const Hierarchical_Menu* menu, const Menu_List* list, int32_t selected_item);
extern void Screen_Setup_Settings_About(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
extern void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, void (*return_function)(Screen_Transition_Direction, Screen_Transition_Direction, Easing, uint32_t, int32_t), int32_t return_value);
extern void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, RGB_Color* rgb_color);
extern void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item);
extern void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, LED_Data_t* rgb_color, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item);
#endif /* SCREENS_H_ */

View File

@@ -37,6 +37,7 @@ static float _Current_BusVoltage_V;
// Function Declarations
void Screen_Setup_Graph(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -53,7 +54,19 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
*******************************************************************/
void Screen_Setup_Graph(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
Screen_Init(direction_out, direction_in, type, frame_duration);
for(int i=0;i<GRAPH_DATA_WDITH;i++) {
_Data_BusVoltage[i] = 0;
_Data_BusVoltage_Threshold_Overvoltage[i] = THRESHOLD_OVERVOLTAGE_mV;
_Data_BusVoltage_Threshold_Undervoltage[i] = THRESHOLD_UNDERVOLTAGE_mV;
}
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Last = Screen_Init;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -64,21 +77,12 @@ void Screen_Setup_Graph(Screen_Transition_Direction direction_out, Screen_Transi
_Screen_On_Object_Deselect = Screen_On_Object_Deselect;
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
for(int i=0;i<GRAPH_DATA_WDITH;i++) {
_Data_BusVoltage[i] = 0;
_Data_BusVoltage_Threshold_Overvoltage[i] = THRESHOLD_OVERVOLTAGE_mV;
_Data_BusVoltage_Threshold_Undervoltage[i] = THRESHOLD_UNDERVOLTAGE_mV;
}
Font_ID Font_10_1 = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_10x17, 1);
Font_ID Font_10_1 = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_10x17, 1);
Display_Objects_Add_Graph(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, false, _Data_BusVoltage, GRAPH_DATA_WDITH, 32000, 0, DISPLAY_COLOR_WHITE, 200, NO_STYLE, NO_ANIMATION);
Display_Objects_Add_Graph(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, false, _Data_BusVoltage_Threshold_Overvoltage, GRAPH_DATA_WDITH, 32000, 0, DISPLAY_COLOR_RED, 200, NO_STYLE, NO_ANIMATION);

View File

@@ -41,9 +41,6 @@
// ============================================================================================
// Variables
extern const unsigned char _Font_Victor_Mono_Bold_8x19[];
extern const unsigned char _Font_Victor_Mono_Regular_6x11[];
extern const unsigned char _Font_Victor_Mono_Regular_7x13[];
extern const unsigned char _Font_DejaVu_Sans_Mono_10x17[];
extern const unsigned char _Font_DejaVu_Sans_Mono_6x12[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_Oblique_10x19[];

View File

@@ -56,18 +56,29 @@ static int16_t _X_Data_Info = 10+25;
static int16_t _X_Data_Timestamp = 10+89;
static int16_t _X_Data_Timestamp_Text = 10+25;
static int16_t _Y_Offest_Scroll;
static int32_t _Y_Offest_Scroll;
static int16_t _Y_Offset_1st_Entry = 20;
static int16_t _Y_Offset_Rows = 10;
static int16_t _Y_Between_Entries = 38;
static int16_t _Y_Scroll_Speed = 10;
// Default configuration
static const Encoder_Acceleration_Config _MIDI_Log_Acceleration_Config = {
.Base_Step = 10,
.Base_Threshold = 5, // Requires more steps to trigger
.Level_Step = 3, // Bigger jumps between levels
.Max_Level = 3, // Fewer levels
.Timeout_ms = 100, // Longer timeout
.Multipliers = {1, 2, 3, 5, 7, 10, 13, 16, 20, 25}
};
// ============================================================================================
// Function Declarations
void Screen_Setup_MIDI_Log(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Action_CW (Object_ID object_id);
@@ -89,7 +100,15 @@ bool Check_Entry_Is_Command(uint entry_id);
*******************************************************************/
void Screen_Setup_MIDI_Log(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
Screen_Init(direction_out, direction_in, type, frame_duration);
_Y_Offest_Scroll = 0;
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Last = Screen_Init;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Action_CW = Screen_Action_CW;
_Screen_Action_CCW = Screen_Action_CCW;
@@ -101,6 +120,10 @@ void Screen_Setup_MIDI_Log(Screen_Transition_Direction direction_out, Screen_Tra
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
Font_ID Font_10_0 = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_6x12, 0);
Font_ID Font_10_1 = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_6x12, 1);
@@ -110,12 +133,6 @@ void Screen_Setup_MIDI_Log(Screen_Transition_Direction direction_out, Screen_Tra
Style_ID Style_Header = Display_Objects_Add_Style(DISPLAY_COLOR_LIGHTGREY, DISPLAY_COLOR_BLACK, 0, 2, PADDING_1(2), STYLE_WIDTH_HEIGHT_RATIO_AUTO);
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
_Y_Offest_Scroll = 0;
_Object_Text_Top = Display_Objects_Add_Text(CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, 0, NOT_SELECTABLE, "Received MIDI Data", Font_10_0, DISPLAY_COLOR_BLACK, Style_Header, NO_ANIMATION);
for(int16_t i=0;i<RECEIVED_MIDI_HISTORY_BUFFER_SIZE;i++)
@@ -141,6 +158,10 @@ void Screen_Setup_MIDI_Log(Screen_Transition_Direction direction_out, Screen_Tra
Update_Object_Coordinates();
Display_Select_Object();
UI_Control_Acceleration_Reset();
UI_Control_Acceleration_Init_Custom(&_MIDI_Log_Acceleration_Config);
UI_Control_Acceleration_Set_Enabled(true);
}
void Screen_Tick(void)
@@ -155,13 +176,15 @@ void Screen_Click(uint button_return_value)
void Screen_Action_CW(Object_ID object_id)
{
_Y_Offest_Scroll -= _Y_Scroll_Speed;
// _Y_Offest_Scroll -= _Y_Scroll_Speed;
UI_Control_Selector_Dec(&_Y_Offest_Scroll, INT16_MIN, INT16_MAX, false);
Update_Object_Coordinates();
}
void Screen_Action_CCW(Object_ID object_id)
{
_Y_Offest_Scroll += _Y_Scroll_Speed;
// _Y_Offest_Scroll += _Y_Scroll_Speed;
UI_Control_Selector_Inc(&_Y_Offest_Scroll, INT16_MIN, INT16_MAX, false);
Update_Object_Coordinates();
}
@@ -182,7 +205,10 @@ void Screen_On_Object_Select(Object_ID object_id)
void Screen_On_Object_Deselect(Object_ID object_id)
{
Screen_Setup_Menu_Main(TRANSITION_RIGHT, TRANSITION_RIGHT, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, false, 0);
UI_Control_Init(); // Reset to default configuration
UI_Control_Acceleration_Set_Enabled(false);
Screen_Setup_Menu_Main(TRANSITION_RIGHT, TRANSITION_RIGHT, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, false, 0);
}
/*******************************************************************
@@ -190,22 +216,22 @@ void Screen_On_Object_Deselect(Object_ID object_id)
*******************************************************************/
void Update_Object_Coordinates(void)
{
Display_Objects_Update_Coordinates(_Object_Text_Top, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, _Y_Offest_Scroll);
Display_Objects_Update_Coordinates(_Object_Text_Top, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, (int16_t)_Y_Offest_Scroll);
for(uint i=0;i<RECEIVED_MIDI_HISTORY_BUFFER_SIZE;i++)
{
Object_History_Entry_s *E = &Objects_History[i];
Display_Objects_Update_Coordinates(E->Object_Number , LEFT_TOP, BOTH_IN_PIXEL, _X_Number , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Data_Hex , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Hex , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Data_Dec , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Dec , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Type_Info , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Info , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries + 1 * _Y_Offset_Rows);
Display_Objects_Update_Coordinates(E->Object_Timestamp , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Timestamp , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries + 2 * _Y_Offset_Rows);
Display_Objects_Update_Coordinates(E->Object_Timestamp_Text , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Timestamp_Text , _Y_Offset_1st_Entry + _Y_Offest_Scroll + i*_Y_Between_Entries + 2 * _Y_Offset_Rows);
Display_Objects_Update_Coordinates(E->Object_Number , LEFT_TOP, BOTH_IN_PIXEL, _X_Number , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Data_Hex , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Hex , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Data_Dec , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Dec , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries);
Display_Objects_Update_Coordinates(E->Object_Type_Info , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Info , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries + 1 * _Y_Offset_Rows);
Display_Objects_Update_Coordinates(E->Object_Timestamp , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Timestamp , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries + 2 * _Y_Offset_Rows);
Display_Objects_Update_Coordinates(E->Object_Timestamp_Text , LEFT_TOP, BOTH_IN_PIXEL, _X_Data_Timestamp_Text , _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + i*_Y_Between_Entries + 2 * _Y_Offset_Rows);
}
Display_Objects_Update_Coordinates(_Object_Text_Bottom, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, _Y_Offset_1st_Entry + _Y_Offest_Scroll + RECEIVED_MIDI_HISTORY_BUFFER_SIZE*_Y_Between_Entries);
Display_Objects_Update_Coordinates(_Object_Text_Return, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, _Y_Offset_1st_Entry + _Y_Offest_Scroll + RECEIVED_MIDI_HISTORY_BUFFER_SIZE*_Y_Between_Entries + _Y_Offset_1st_Entry);
Display_Objects_Update_Coordinates(_Object_Text_Bottom, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + RECEIVED_MIDI_HISTORY_BUFFER_SIZE*_Y_Between_Entries);
Display_Objects_Update_Coordinates(_Object_Text_Return, CENTER_TOP, X_IN_PERCENT_Y_IN_PIXEL, 50, _Y_Offset_1st_Entry + (int16_t)_Y_Offest_Scroll + RECEIVED_MIDI_HISTORY_BUFFER_SIZE*_Y_Between_Entries + _Y_Offset_1st_Entry);
}
void Update_Object_Values(void)

View File

@@ -80,11 +80,14 @@ static Configuration_Menu_Ring _Ring_Menu_Config = {
.Enable_Appear_Animation = false
};
static bool _Do_Menu_Animation;
// ============================================================================================
// Function Declarations
void Screen_Setup_Menu_Main(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, bool do_menu_animation, uint32_t selected_entry);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -102,7 +105,21 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
*******************************************************************/
void Screen_Setup_Menu_Main(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, bool do_menu_animation, uint32_t selected_entry)
{
_Screen_Tick = Screen_Tick;
_Do_Menu_Animation = do_menu_animation;
Screen_Init(direction_out, direction_in, type, frame_duration);
// Initialize values
_Ring_Menu_Selected = 0;
if(selected_entry < ENTRY_COUNT) {
_Ring_Menu_Selected = selected_entry;
}
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Last = Screen_Init;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -116,26 +133,20 @@ void Screen_Setup_Menu_Main(Screen_Transition_Direction direction_out, Screen_Tr
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
_Object_Ring_Menu = Display_Objects_Add_Menu_Ring(_Ring_Menu_Items, ENTRY_COUNT, &_Ring_Menu_Selected, &_Ring_Menu_Config);
_Object_Ring_Menu = Display_Objects_Add_Menu_Ring(_Ring_Menu_Items, ENTRY_COUNT, &_Ring_Menu_Selected, &_Ring_Menu_Config);
if(do_menu_animation) {
if(_Do_Menu_Animation) {
Display_Objects_Menu_Ring_Start_Appear_Animation(_Object_Ring_Menu);
}
Display_Select_First_Object();
Display_Select_Object();
_Do_Menu_Animation = false;
// Initialize values
_Ring_Menu_Selected = 0;
if(selected_entry < ENTRY_COUNT) {
_Ring_Menu_Selected = selected_entry;
}
Display_Select_First_Object();
Display_Select_Object();
}
void Screen_Tick(void)

View File

@@ -27,6 +27,7 @@
// Function Declarations
void Screen_Setup_Mode(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -43,7 +44,13 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
*******************************************************************/
void Screen_Setup_Mode(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
Screen_Init(direction_out, direction_in, type, frame_duration);
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Last = Screen_Init;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -60,8 +67,7 @@ void Screen_Setup_Mode(Screen_Transition_Direction direction_out, Screen_Transit
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
Display_Objects_Add_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_RED, 80, 80, 1, NO_STYLE, NO_ANIMATION);
Display_Objects_Add_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_RED, 80, 80, 1, NO_STYLE, NO_ANIMATION);
// Display_Objects_Add_Rounded_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_GREEN, 80, 80, 10, 4, NO_STYLE, NO_ANIMATION);
// Display_Objects_Add_Rounded_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_GREEN, 100, 100, 15, 1, NO_STYLE, NO_ANIMATION);
// Display_Objects_Add_Rounded_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_GREEN, 80, 80, 5, 1, NO_STYLE, NO_ANIMATION);

View File

@@ -9,10 +9,11 @@
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Display_Default_Configurations.h"
#include "../Hierarchical_Menu.h"
#include "../Display.h"
#include "../Display_Objects.h"
#include "../Display_Default_Configurations.h"
// ============================================================================================
@@ -21,16 +22,25 @@
// ============================================================================================
// Variables
static void (*_Return_Function)(Screen_Transition_Direction, Screen_Transition_Direction, Easing, uint32_t, int32_t);
static int32_t _Return_Value;
static Object_ID _Object_Message_Box;
static const Hierarchical_Menu* _Return_Menu = NULL;
static const Menu_List* _Return_List = NULL;
static int32_t _Return_Selected_Item;
static char* _Title;
static uint32_t _Title_Length;
static uint8_t* _Value;
static bool _Bool_Value;
static bool _Bool_Value;
static bool _Decision_Made;
static uint32_t _Counter;
// ============================================================================================
// Function Declarations
void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, void (*return_function)(Screen_Transition_Direction, Screen_Transition_Direction, Easing, uint32_t, int32_t), int32_t return_value);
void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -45,9 +55,26 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
/*******************************************************************
Functions
*******************************************************************/
void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, void (*return_function)(Screen_Transition_Direction, Screen_Transition_Direction, Easing, uint32_t, int32_t), int32_t return_value)
void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, uint8_t *value, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item)
{
_Screen_Tick = Screen_Tick;
_Title = title;
_Title_Length = title_length;
_Value = value;
_Bool_Value = (*_Value) > 0;
Screen_Init(direction_out, direction_in, type, frame_duration);
_Return_Menu = return_menu;
_Return_List = return_list;
_Return_Selected_Item = return_selected_item;
_Decision_Made = false;
_Counter = 0;
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -61,23 +88,24 @@ void Screen_Setup_Select_Bool(Screen_Transition_Direction direction_out, Screen_
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
_Return_Function = return_function;
_Return_Value = return_value;
_Value = value;
_Bool_Value = (*_Value) > 0;
Display_Objects_Add_Select_YesNo(title, title_length, &_Bool_Value, &_Configuration_Default_Select_YesNo);
Display_Objects_Add_Select_YesNo(_Title, _Title_Length, &_Bool_Value, &_Configuration_Default_Select_YesNo);
_Object_Message_Box = Display_Objects_Add_Message_Box(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, "Saved", MESSAGE_BOX_ICON_CIRCLE_CHECKMARK, &_Message_Box_Style_Regular);
Display_Select_Object();
}
void Screen_Tick(void)
{
if(_Decision_Made) {
_Counter++;
}
if(_Counter == MESSAGE_BOX_DEFAULT_TICKS) {
Screen_Setup_Settings_Hierarchical_Menu(TRANSITION_DOWN, TRANSITION_RIGHT, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, _Return_Menu, _Return_List, _Return_Selected_Item);
}
}
void Screen_Click(uint button_return_value)
@@ -92,7 +120,11 @@ void Screen_Touch_Event(int16_t x, int16_t y)
void Screen_Action_CW(Object_ID object_id)
{
(*_Value) ^= 0x01;
if(_Decision_Made) {
return;
}
(*_Value) ^= 0x01;
_Bool_Value = (*_Value) > 0;
}
@@ -119,7 +151,10 @@ void Screen_On_Object_Select(Object_ID object_id)
void Screen_On_Object_Deselect(Object_ID object_id)
{
_Return_Function(TRANSITION_DOWN, TRANSITION_DOWN, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, _Return_Value);
if(!_Decision_Made) {
Display_Objects_Show_Message_Box(_Object_Message_Box, MESSAGE_BOX_DEFAULT_TICKS);
_Decision_Made = true;
}
}

View File

@@ -9,6 +9,7 @@
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Command_Definition.h"
#include "../Display.h"
#include "../Display_Objects.h"
@@ -17,17 +18,28 @@
// ============================================================================================
// Variables
static Object_ID _RGB_Selector_Object;
static RGB_Color* _RGB_Color;
static Object_ID _Object_Message_Box;
static const Hierarchical_Menu* _Return_Menu = NULL;
static const Menu_List* _Return_List = NULL;
static int32_t _Return_Selected_Item;
static char* _Title;
static uint32_t _Title_Length;
static LED_Data_t* _RGB_Color;
static uint8_t _Current_Component;
static uint8_t* _Color;
static bool _Decision_Made;
static uint32_t _Counter;
// ============================================================================================
// Function Declarations
void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, RGB_Color* rgb_color);
void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, LED_Data_t* rgb_color, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -42,9 +54,26 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
/*******************************************************************
Functions
*******************************************************************/
void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, RGB_Color* rgb_color)
void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, char* title, uint32_t title_length, LED_Data_t* rgb_color, const Hierarchical_Menu* return_menu, const Menu_List* return_list, int32_t return_selected_item)
{
_Screen_Tick = Screen_Tick;
_Current_Component = 0;
_RGB_Color = rgb_color;
_Color = &(rgb_color->Array[_Current_Component]);
Screen_Init(direction_out, direction_in, type, frame_duration);
_Return_Menu = return_menu;
_Return_List = return_list;
_Return_Selected_Item = return_selected_item;
_Decision_Made = false;
_Counter = 0;
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -55,25 +84,14 @@ void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_T
_Screen_On_Object_Deselect = Screen_On_Object_Deselect;
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
_Current_Component = 0;
_RGB_Color = rgb_color;
_Color = &(rgb_color->Array[_Current_Component]);
// Create the RGB selector object
_RGB_Selector_Object = Display_Objects_Add_Select_RGB(
_RGB_Color, // Pointer to color to modify
&_Current_Component, // Indicater for active RGB Base Color
&_Configuration_Default_Select_RGB // Use configuration
);
Display_Objects_Add_Select_RGB(_RGB_Color, &_Current_Component, &_Configuration_Default_Select_RGB);
_Object_Message_Box = Display_Objects_Add_Message_Box(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, "Saved", MESSAGE_BOX_ICON_CIRCLE_CHECKMARK, &_Message_Box_Style_Regular);
Display_Select_Object();
@@ -83,7 +101,13 @@ void Screen_Setup_Select_RGB(Screen_Transition_Direction direction_out, Screen_T
void Screen_Tick(void)
{
if(_Decision_Made) {
_Counter++;
}
if(_Counter == MESSAGE_BOX_DEFAULT_TICKS) {
Screen_Setup_Settings_Hierarchical_Menu(TRANSITION_DOWN, TRANSITION_RIGHT, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, _Return_Menu, _Return_List, _Return_Selected_Item);
}
}
void Screen_Click(uint button_return_value)
@@ -98,6 +122,10 @@ void Screen_Touch_Event(int16_t x, int16_t y)
void Screen_Action_CW(Object_ID object_id)
{
if(_Decision_Made) {
return;
}
int32_t Color = *_Color;
UI_Control_Selector_Inc(&Color, 0, UINT8_MAX, false);
*_Color = (uint8_t)Color;
@@ -105,6 +133,10 @@ void Screen_Action_CW(Object_ID object_id)
void Screen_Action_CCW(Object_ID object_id)
{
if(_Decision_Made) {
return;
}
int32_t Color = *_Color;
UI_Control_Selector_Dec(&Color, 0, UINT8_MAX, false);
*_Color = (uint8_t)Color;
@@ -136,7 +168,10 @@ void Screen_On_Object_Deselect(Object_ID object_id)
return;
}
// Screen_Setup_Menu_Main(TRANSITION_DOWN, TRANSITION_DOWN, INOUT_SINE, 15, false, 1);
if(!_Decision_Made) {
Display_Objects_Show_Message_Box(_Object_Message_Box, MESSAGE_BOX_DEFAULT_TICKS);
_Decision_Made = true;
}
}

View File

@@ -9,10 +9,10 @@
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Display_Default_Configurations.h"
#include "../Display.h"
#include "../Display_Objects.h"
#include "../Display_Default_Configurations.h"
// ============================================================================================
@@ -58,11 +58,14 @@ static Configuration_Menu_Icon_Row _Configuration_Menu_Icon_Row = {
static int32_t _Selected_Item;
extern const Hierarchical_Menu _Hierarchical_Menu_MIDI;
// ============================================================================================
// Function Declarations
void Screen_Setup_Settings(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
@@ -80,7 +83,15 @@ static void Screen_On_Object_Deselect (Object_ID object_id);
*******************************************************************/
void Screen_Setup_Settings(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item)
{
_Screen_Tick = Screen_Tick;
Screen_Init(direction_out, direction_in, type, frame_duration);
_Selected_Item = selected_item;
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Last = Screen_Init;
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
@@ -94,9 +105,7 @@ void Screen_Setup_Settings(Screen_Transition_Direction direction_out, Screen_Tra
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
@@ -107,11 +116,8 @@ void Screen_Setup_Settings(Screen_Transition_Direction direction_out, Screen_Tra
Display_Objects_Add_Text(CENTER_MIDDLE, X_IN_PERCENT_Y_IN_PIXEL, 50, 45, NOT_SELECTABLE, "Settings", Font_Title, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
Display_Objects_Add_Rectangle_Filled(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_FROM_RGB888(32, 32, 32), DISPLAY_WIDTH, 85, NO_STYLE, NO_ANIMATION);
_Object_Menu = Display_Objects_Add_Menu_Icon_Row(_Icon_Row_Items, MENU_ENTRY_COUNT, &_Selected_Item, &_Configuration_Menu_Icon_Row);
// Display_Objects_Add_Rounded_Rectangle_Frame(CENTER_MIDDLE, BOTH_IN_PERCENT, 50, 50, NOT_SELECTABLE, DISPLAY_COLOR_FROM_RGB888(255, 223, 0), 70, 70, 21, 4, NO_STYLE, NO_ANIMATION);
_Selected_Item = selected_item;
Display_Select_First_Object();
Display_Select_First_Object();
Display_Select_Object();
}
@@ -159,7 +165,8 @@ void Screen_On_Object_Deselect(Object_ID object_id)
{
switch (_Selected_Item)
{
case 0: Screen_Setup_Settings_MIDI(TRANSITION_UP, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, 0); break;
// case 0: Screen_Setup_Settings_MIDI(TRANSITION_UP, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, 0); break;
case 0: Screen_Setup_Settings_Hierarchical_Menu(TRANSITION_UP, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, &_Hierarchical_Menu_MIDI, _Hierarchical_Menu_MIDI.List, 0); break;
case 1: break;
case 2: break;
case 3: break;

View File

@@ -0,0 +1,258 @@
/*
* File: Screen_Settings_Hierarchical_Menu.c
*
* Created: Created: Sunday September 2025 19:19:34
* Author: Chris
*/
// ============================================================================================
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Hierarchical_Menu.h"
#include "../Command_Definition.h"
#include "../Display.h"
#include "../Display_Objects.h"
#include "../Display_Default_Configurations.h"
#include <string.h>
// ============================================================================================
// Defines
// ============================================================================================
// Variables
extern const unsigned char _Font_DejaVu_Sans_Mono_6x12[];
extern const unsigned char _Font_DejaVu_Sans_Mono_7x15[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_7x15[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_15x26[];
static const Hierarchical_Menu* _Menu = NULL;
static const Menu_List* _Current_List = NULL;
static int32_t _Selected_Item;
static int32_t _Scroll_Offset;
static int32_t _Visible_Items;
// ============================================================================================
// Function Declarations
void Screen_Setup_Settings_Hierarchical_Menu(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, const Hierarchical_Menu* menu, const Menu_List* list, int32_t selected_item);
static void Screen_Init (Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
static void Screen_Action_CW (Object_ID object_id);
static void Screen_Action_CCW (Object_ID object_id);
static void Screen_On_Object_Focused (Object_ID object_id);
static void Screen_On_Object_Defocused (Object_ID object_id);
static void Screen_On_Object_Select (Object_ID object_id);
static void Screen_On_Object_Deselect (Object_ID object_id);
static void Navigate_To_List(const Menu_List* new_list);
static void Handle_Back_Navigation(void);
static void Calculate_Scroll_Offset(void);
static void Handle_Item_Selection(void);
/*******************************************************************
Functions
*******************************************************************/
void Screen_Setup_Settings_Hierarchical_Menu(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, const Hierarchical_Menu* menu, const Menu_List* list, int32_t selected_item)
{
_Menu = menu;
_Current_List = list;
_Selected_Item = selected_item;
Screen_Init(direction_out, direction_in, type, frame_duration);
_Scroll_Offset = 0;
_Visible_Items = _Configuration_Menu_Hierarchical_Default.Visible_Items;
}
void Screen_Init(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration)
{
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
_Screen_Action_CCW = Screen_Action_CCW;
_Screen_On_Objects_Focused = Screen_On_Object_Focused;
_Screen_On_Objects_Defocused = Screen_On_Object_Defocused;
_Screen_On_Object_Select = Screen_On_Object_Select;
_Screen_On_Object_Deselect = Screen_On_Object_Deselect;
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
Display_Objects_Add_Menu_Hierarchical(&_Current_List, &_Selected_Item, &_Scroll_Offset, &_Configuration_Menu_Hierarchical_Default);
Calculate_Scroll_Offset();
Display_Select_Object();
}
void Screen_Tick(void)
{
}
void Screen_Click(uint button_return_value)
{
}
void Screen_Touch_Event(int16_t x, int16_t y)
{
}
void Screen_Action_CW(Object_ID object_id)
{
// Move selection down (the renderer will automatically show the change)
UI_Control_Selector_Inc(&_Selected_Item, 0, (int32_t)_Current_List->Item_Count - 1, false);
Calculate_Scroll_Offset();
}
void Screen_Action_CCW(Object_ID object_id)
{
// Move selection up (the renderer will automatically show the change)
UI_Control_Selector_Dec(&_Selected_Item, 0, (int32_t)_Current_List->Item_Count - 1, false);
Calculate_Scroll_Offset();
}
void Screen_On_Object_Focused(Object_ID object_id)
{
}
void Screen_On_Object_Defocused(Object_ID object_id)
{
}
void Screen_On_Object_Select(Object_ID object_id)
{
}
void Screen_On_Object_Deselect(Object_ID object_id)
{
Handle_Item_Selection();
}
/*******************************************************************
Internal Functions
*******************************************************************/
void Navigate_To_List(const Menu_List* new_list)
{
if (new_list == NULL) {
return;
}
// Update menu state
_Current_List = new_list;
_Selected_Item = 0;
_Scroll_Offset = 0;
Calculate_Scroll_Offset();
Display_Select_Object();
}
void Handle_Back_Navigation(void)
{
if (_Current_List->Parent != NULL)
{
// Navigate to parent list
const Menu_List* Parent_List = _Current_List->Parent->Containing_List;
// Find the index of the item that led to current list
_Selected_Item = 0;
for (uint32_t i = 0; i < Parent_List->Item_Count; i++)
{
if (Parent_List->Items[i].List == _Current_List) {
_Selected_Item = i;
break;
}
}
_Current_List = Parent_List;
Calculate_Scroll_Offset();
Display_Select_Object();
}
else if (_Menu->Parent_Function != NULL)
{
// Exit to parent screen
_Menu->Parent_Function(TRANSITION_DOWN, TRANSITION_DOWN, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, _Menu->Parent_Selected_Setting);
}
}
void Calculate_Scroll_Offset(void)
{
// Auto-scroll to keep selected item visible
if (_Selected_Item < _Scroll_Offset) {
_Scroll_Offset = 0;
}
else {
_Scroll_Offset = _Selected_Item - _Visible_Items + 1;
}
// Ensure scroll offset is within bounds
int32_t Max_Scroll = (int32_t)_Current_List->Item_Count - _Visible_Items;
if (Max_Scroll < 0) {
Max_Scroll = 0;
}
if (_Scroll_Offset > Max_Scroll) {
_Scroll_Offset = Max_Scroll;
}
if (_Scroll_Offset < 0) {
_Scroll_Offset = 0;
}
}
void Handle_Item_Selection(void)
{
if (_Selected_Item < 0 || _Selected_Item >= (int32_t)_Current_List->Item_Count) {
return;
}
const Menu_Item* Selected_Item = &_Current_List->Items[_Selected_Item];
if (Selected_Item->Is_Back) {
Handle_Back_Navigation();
return;
}
if (Selected_Item->List != NULL) {
Navigate_To_List(Selected_Item->List);
return;
}
switch(Selected_Item->Type)
{
case BOOL:
Screen_Setup_Select_Bool(TRANSITION_LEFT, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, (char*)Selected_Item->Variable_Title, strlen(Selected_Item->Variable_Title), (uint8_t*)Selected_Item->Variable, _Menu, Selected_Item->Containing_List, _Selected_Item);
break;
case RGB:
Screen_Setup_Select_RGB(TRANSITION_LEFT, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, (char*)Selected_Item->Variable_Title, strlen(Selected_Item->Variable_Title), (LED_Data_t*)Selected_Item->Variable, _Menu, Selected_Item->Containing_List, _Selected_Item);
break;
case NONE:
default:
break;
}
}

View File

@@ -1,144 +0,0 @@
/*
* File: Screen_Settings_MIDI.c
*
* Created: Created: Thursday August 2025 14:24:40
* Author: Chris
*/
// ============================================================================================
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Display_Default_Configurations.h"
#include "../Display.h"
#include "../Display_Objects.h"
// ============================================================================================
// Defines
#define MENU_ENTRY_COUNT 4
#define MENU_CHAR_LENGTH 11
// ============================================================================================
// Variables
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_15x26[];
static int32_t _Selected_Item;
static char _Menu_Titles[MENU_ENTRY_COUNT][MENU_CHAR_LENGTH] = {
{ "MIDI Config" },
{ "Color Notes" },
{ "Pause Light" },
{ "Back " }
};
// ============================================================================================
// Function Declarations
void Screen_Setup_Settings_MIDI(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
static void Screen_Action_CW (Object_ID object_id);
static void Screen_Action_CCW (Object_ID object_id);
static void Screen_On_Object_Focused (Object_ID object_id);
static void Screen_On_Object_Defocused (Object_ID object_id);
static void Screen_On_Object_Select (Object_ID object_id);
static void Screen_On_Object_Deselect (Object_ID object_id);
/*******************************************************************
Functions
*******************************************************************/
void Screen_Setup_Settings_MIDI(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item)
{
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
_Screen_Action_CCW = Screen_Action_CCW;
_Screen_On_Objects_Focused = Screen_On_Object_Focused;
_Screen_On_Objects_Defocused = Screen_On_Object_Defocused;
_Screen_On_Object_Select = Screen_On_Object_Select;
_Screen_On_Object_Deselect = Screen_On_Object_Deselect;
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
Font_ID Font_Title = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_Bold_15x26, 0);
Display_Objects_Add_Text(CENTER_MIDDLE, X_IN_PERCENT_Y_IN_PIXEL, 50, 45, NOT_SELECTABLE, "MIDI", Font_Title, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
Display_Objects_Add_Select_List((char*)_Menu_Titles, MENU_ENTRY_COUNT, MENU_CHAR_LENGTH, &_Selected_Item, &_Configuration_Default_Select_List);
_Selected_Item = selected_item;
Display_Select_First_Object();
Display_Select_Object();
}
void Screen_Tick(void)
{
}
void Screen_Click(uint button_return_value)
{
}
void Screen_Touch_Event(int16_t x, int16_t y)
{
}
void Screen_Action_CW(Object_ID object_id)
{
UI_Control_Selector_Inc(&_Selected_Item, 0, MENU_ENTRY_COUNT-1, false);
}
void Screen_Action_CCW(Object_ID object_id)
{
UI_Control_Selector_Dec(&_Selected_Item, 0, MENU_ENTRY_COUNT-1, false);
}
void Screen_On_Object_Focused(Object_ID object_id)
{
}
void Screen_On_Object_Defocused(Object_ID object_id)
{
}
void Screen_On_Object_Select(Object_ID object_id)
{
}
void Screen_On_Object_Deselect(Object_ID object_id)
{
switch (_Selected_Item)
{
case 0: Screen_Setup_Settings_MIDI_Config(TRANSITION_UP, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, 0); break;
case 1: break;
case 2: break;
case 3: Screen_Setup_Settings(TRANSITION_DOWN, TRANSITION_DOWN, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, 0); break;
}
Display_Select_Object();
}
/*******************************************************************
Internal Functions
*******************************************************************/

View File

@@ -1,147 +0,0 @@
/*
* File: Screen_Settings_MIDI_Config.c
*
* Created: Created: Thursday August 2025 15:53:58
* Author: Chris
*/
// ============================================================================================
// Includes
#include "../Screens.h"
#include "../UI_Control.h"
#include "../Display_Default_Configurations.h"
#include "../Display.h"
#include "../Display_Objects.h"
#include "../EEPROM_M24C64.h"
// ============================================================================================
// Defines
#define MENU_ENTRY_COUNT 4
#define MENU_CHAR_LENGTH 13
// ============================================================================================
// Variables
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_11x17[];
extern const unsigned char _Font_DejaVu_Sans_Mono_Bold_15x26[];
static int32_t _Selected_Item;
static char _Menu_Titles[MENU_ENTRY_COUNT][MENU_CHAR_LENGTH] = {
{ "MIDI Channel " },
{ "Select Octave" },
{ "Skip Note Off" },
{ "Back " }
};
// ============================================================================================
// Function Declarations
void Screen_Setup_Settings_MIDI_Config(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item);
static void Screen_Tick (void);
static void Screen_Click (uint button_return_value);
static void Screen_Touch_Event (int16_t x, int16_t y);
static void Screen_Action_CW (Object_ID object_id);
static void Screen_Action_CCW (Object_ID object_id);
static void Screen_On_Object_Focused (Object_ID object_id);
static void Screen_On_Object_Defocused (Object_ID object_id);
static void Screen_On_Object_Select (Object_ID object_id);
static void Screen_On_Object_Deselect (Object_ID object_id);
/*******************************************************************
Functions
*******************************************************************/
void Screen_Setup_Settings_MIDI_Config(Screen_Transition_Direction direction_out, Screen_Transition_Direction direction_in, Easing type, uint32_t frame_duration, int32_t selected_item)
{
_Screen_Tick = Screen_Tick;
_Screen_Click = Screen_Click;
_Screen_Touch_Event = Screen_Touch_Event;
_Screen_Action_CW = Screen_Action_CW;
_Screen_Action_CCW = Screen_Action_CCW;
_Screen_On_Objects_Focused = Screen_On_Object_Focused;
_Screen_On_Objects_Defocused = Screen_On_Object_Defocused;
_Screen_On_Object_Select = Screen_On_Object_Select;
_Screen_On_Object_Deselect = Screen_On_Object_Deselect;
Display_Objects_Clear();
Display_Screen_Transition_Start(direction_out, direction_in, type, frame_duration);
//////////////////////////////
// Add Display Objects here //
//////////////////////////////
Font_ID Font_Title = Display_Objects_Add_Font(_Font_DejaVu_Sans_Mono_Bold_11x17, 0);
Display_Objects_Add_Text(CENTER_MIDDLE, X_IN_PERCENT_Y_IN_PIXEL, 50, 45, NOT_SELECTABLE, "MIDI Config", Font_Title, DISPLAY_COLOR_LIGHTGREY, NO_STYLE, NO_ANIMATION);
Display_Objects_Add_Select_List((char*)_Menu_Titles, MENU_ENTRY_COUNT, MENU_CHAR_LENGTH, &_Selected_Item, &_Configuration_Default_Select_List);
_Selected_Item = selected_item;
Display_Select_First_Object();
Display_Select_Object();
}
void Screen_Tick(void)
{
}
void Screen_Click(uint button_return_value)
{
}
void Screen_Touch_Event(int16_t x, int16_t y)
{
}
void Screen_Action_CW(Object_ID object_id)
{
UI_Control_Selector_Inc(&_Selected_Item, 0, MENU_ENTRY_COUNT-1, false);
}
void Screen_Action_CCW(Object_ID object_id)
{
UI_Control_Selector_Dec(&_Selected_Item, 0, MENU_ENTRY_COUNT-1, false);
}
void Screen_On_Object_Focused(Object_ID object_id)
{
}
void Screen_On_Object_Defocused(Object_ID object_id)
{
}
void Screen_On_Object_Select(Object_ID object_id)
{
}
void Screen_On_Object_Deselect(Object_ID object_id)
{
switch (_Selected_Item)
{
case 0: break;
case 1: break;
case 2: Screen_Setup_Select_Bool(TRANSITION_UP, TRANSITION_UP, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, "Skip Note Off?", 14, (uint8_t*)&_EEPROM_Content.Channel_MIDI_Configuration->Skip_Note_Off_Event, Screen_Setup_Settings_MIDI_Config, 2); break;
case 3: Screen_Setup_Settings_MIDI(TRANSITION_DOWN, TRANSITION_DOWN, SCREEN_TRANSITION_DEFAULT_EASING, SCREEN_TRANSITION_DEFAULT_FRAMES, 0); break;
}
Display_Select_Object();
}
/*******************************************************************
Internal Functions
*******************************************************************/

View File

@@ -15,14 +15,33 @@
// ============================================================================================
// Defines
#define SELECTOR_INC(__SELECTOR__, __MIN__, __MAX__, __CIRCLE__) if((*__SELECTOR__) < __MAX__) { (*__SELECTOR__)++; } else if(__CIRCLE__) { (*__SELECTOR__) = __MIN__; break; } else { break; }
#define SELECTOR_DEC(__SELECTOR__, __MIN__, __MAX__, __CIRCLE__) if((*__SELECTOR__) > __MIN__) { (*__SELECTOR__)--; } else if(__CIRCLE__) { (*__SELECTOR__) = __MAX__; break; } else { break; }
#define SELECTOR_INC(__SELECTOR__, __STEP__, __MIN__, __MAX__, __CIRCLE__) if((*__SELECTOR__) <= (__MAX__ - __STEP__)) { (*__SELECTOR__)+=__STEP__; } else if(__CIRCLE__) { (*__SELECTOR__) = __MIN__; break; } else { break; }
#define SELECTOR_DEC(__SELECTOR__, __STEP__, __MIN__, __MAX__, __CIRCLE__) if((*__SELECTOR__) >= (__MIN__ + __STEP__)) { (*__SELECTOR__)-=__STEP__; } else if(__CIRCLE__) { (*__SELECTOR__) = __MAX__; break; } else { break; }
// ============================================================================================
// Datatypes
typedef struct {
// Configuration
const Encoder_Acceleration_Config* config;
// State tracking
uint8_t Speed_Counter; // Current speed counter
uint8_t Acceleration_Level; // Current acceleration level (0 = no accel)
uint32_t Last_Activity_Time; // Last encoder activity timestamp (ms)
// Statistics (for debugging)
uint32_t Total_Steps; // Total encoder steps processed
uint32_t Accelerated_Steps; // Steps that used acceleration
} Encoder_Acceleration_Instance;
// ============================================================================================
// Variables
// Default configuration
static const Encoder_Acceleration_Config _Default_Acceleration_Config = {
.Base_Step = 1,
.Base_Threshold = 5, // Requires more steps to trigger
.Level_Step = 3, // Bigger jumps between levels
.Max_Level = 3, // Fewer levels
@@ -30,6 +49,7 @@ static const Encoder_Acceleration_Config _Default_Acceleration_Config = {
.Multipliers = {1, 2, 3, 5, 7, 10, 13, 16, 20, 25}
};
static Encoder_Acceleration_Instance _Acceleration_Instance;
static bool _Acceleration_Initialized = false;
static bool _Acceleration_Enabled = false;
@@ -65,9 +85,9 @@ void UI_Control_Selector_Inc(int32_t* selector, int32_t minimum, int32_t maximum
{
// if(_EEPROM_Content.Device_Configuration.Reverse_List_Scrolling == 0) {
if(true) {
SELECTOR_INC(selector, minimum, maximum, circle_around);
SELECTOR_INC(selector, _Acceleration_Instance.config->Base_Step, minimum, maximum, circle_around);
} else {
SELECTOR_DEC(selector, minimum, maximum, circle_around);
SELECTOR_DEC(selector, _Acceleration_Instance.config->Base_Step, minimum, maximum, circle_around);
}
}
}
@@ -88,9 +108,9 @@ void UI_Control_Selector_Dec(int32_t* selector, int32_t minimum, int32_t maximum
{
// if(_EEPROM_Content.Device_Configuration.Reverse_List_Scrolling == 0) {
if(true) {
SELECTOR_DEC(selector, minimum, maximum, circle_around);
SELECTOR_DEC(selector, _Acceleration_Instance.config->Base_Step, minimum, maximum, circle_around);
} else {
SELECTOR_INC(selector, minimum, maximum, circle_around);
SELECTOR_INC(selector, _Acceleration_Instance.config->Base_Step, minimum, maximum, circle_around);
}
}
}

View File

@@ -23,27 +23,14 @@
// ============================================================================================
// Datatypes
typedef struct {
uint8_t Base_Threshold; // Steps needed to trigger level 1 acceleration
uint8_t Level_Step; // Additional steps per acceleration level
uint8_t Max_Level; // Maximum acceleration level (1-10)
uint16_t Timeout_ms; // Inactivity timeout to reset acceleration (ms)
uint8_t Multipliers[10]; // Multiplier for each acceleration level
uint8_t Base_Step; // Basic Step width, without any multiplier
uint8_t Base_Threshold; // Steps needed to trigger level 1 acceleration
uint8_t Level_Step; // Additional steps per acceleration level
uint8_t Max_Level; // Maximum acceleration level (1-10)
uint16_t Timeout_ms; // Inactivity timeout to reset acceleration (ms)
uint8_t Multipliers[10]; // Multiplier for each acceleration level
} Encoder_Acceleration_Config;
typedef struct {
// Configuration
const Encoder_Acceleration_Config* config;
// State tracking
uint8_t Speed_Counter; // Current speed counter
uint8_t Acceleration_Level; // Current acceleration level (0 = no accel)
uint32_t Last_Activity_Time; // Last encoder activity timestamp (ms)
// Statistics (for debugging)
uint32_t Total_Steps; // Total encoder steps processed
uint32_t Accelerated_Steps; // Steps that used acceleration
} Encoder_Acceleration_Instance;
// ============================================================================================
// Function Declarations

View File

@@ -1 +1 @@
223
422

View File

@@ -0,0 +1 @@
# Auto-generated symbol addresses

View File

@@ -8,6 +8,7 @@
// ============================================================================================
// Includes
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
@@ -105,7 +106,7 @@ int main(void)
// EEPROM =================================================
EEPROM_Init();
// INA 260 =============================================
// INA 260 =================================================
INA260_Init();
// Core 1 =================================================
@@ -204,6 +205,7 @@ int main(void)
void Check_For_Serial_Input(void)
{
int Analog_Data = -1;
int i;
while(USB_Serial_Available())
{