basic menu working
This commit is contained in:
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
.pytest_cache/
|
||||
__pycache__/
|
||||
|
||||
# esp-idf built binaries
|
||||
build/
|
||||
build_*_*/
|
||||
#sdkconfig
|
||||
|
||||
# idf-ci build run output
|
||||
build_summary_*.xml
|
||||
app_info_*.txt
|
||||
size_info_*.txt
|
||||
|
||||
# pytest-embedded log folder
|
||||
pytest_embedded_log/
|
||||
|
||||
# idf-component-manager output
|
||||
dependencies.lock
|
||||
|
||||
.devcontainer
|
||||
|
||||
managed_components
|
||||
components
|
||||
23
.vscode/c_cpp_properties.json
vendored
Normal file
23
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "ESP-IDF",
|
||||
"compilerPath": "${config:idf.toolsPathWin}\\tools\\xtensa-esp-elf\\esp-13.2.0_20240530\\xtensa-esp-elf\\bin\\xtensa-esp32-elf-gcc.exe",
|
||||
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
|
||||
"includePath": [
|
||||
"${config:idf.espIdfPath}/components/**",
|
||||
"${config:idf.espIdfPathWin}/components/**",
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"browse": {
|
||||
"path": [
|
||||
"${config:idf.espIdfPath}/components",
|
||||
"${config:idf.espIdfPathWin}/components",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"limitSymbolsToIncludedHeaders": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "gdbtarget",
|
||||
"request": "attach",
|
||||
"name": "Eclipse CDT GDB Adapter"
|
||||
},
|
||||
{
|
||||
"type": "espidf",
|
||||
"name": "Launch",
|
||||
"request": "launch"
|
||||
}
|
||||
]
|
||||
}
|
||||
41
.vscode/settings.json
vendored
Normal file
41
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"C_Cpp.intelliSenseEngine": "default",
|
||||
"idf.espIdfPathWin": "C:\\Users\\brent.RPX\\esp\\v5.3.1\\esp-idf",
|
||||
"idf.openOcdConfigs": [
|
||||
"board/esp32-wrover-kit-3.3v.cfg"
|
||||
],
|
||||
"idf.portWin": "COM4",
|
||||
"idf.toolsPathWin": "C:\\Users\\brent.RPX\\.espressif\\tools",
|
||||
"idf.flashType": "UART",
|
||||
"files.associations": {
|
||||
"esp_system.h": "c",
|
||||
"task.h": "c",
|
||||
"bt_app_core.h": "c",
|
||||
"math.h": "c",
|
||||
"esp_log.h": "c",
|
||||
"freertos.h": "c",
|
||||
"queue.h": "c",
|
||||
"unistd.h": "c",
|
||||
"inttypes.h": "c",
|
||||
"esp_idf_version.h": "c",
|
||||
"timers.h": "c",
|
||||
"lvgl.h": "c",
|
||||
"esp_timer.h": "c",
|
||||
"esp_bt_device.h": "c",
|
||||
"esp_lvgl_port.h": "c",
|
||||
"lv_global.h": "c",
|
||||
"stdio.h": "c",
|
||||
"compare": "c",
|
||||
"cstdint": "c",
|
||||
"spi_master.h": "c",
|
||||
"bitset": "c",
|
||||
"format": "c",
|
||||
"system.h": "c",
|
||||
"esp_lcd_panel_ops.h": "c",
|
||||
"semphr.h": "c",
|
||||
"lv_spinbox.h": "c",
|
||||
"lv_slider.h": "c",
|
||||
"lv_menu.h": "c"
|
||||
},
|
||||
"git.ignoreLimitWarning": true
|
||||
}
|
||||
455
main/gui.c
455
main/gui.c
@@ -25,6 +25,9 @@
|
||||
|
||||
static const char *TAG = "gui";
|
||||
|
||||
#define UNLOCK() lvgl_port_unlock()
|
||||
#define LOCK() lvgl_port_lock(0)
|
||||
|
||||
// LCD Pin Configuration
|
||||
#define LCD_PIXEL_CLOCK_HZ (5 * 1000 * 1000)
|
||||
#define LCD_SPI_HOST SPI2_HOST
|
||||
@@ -48,8 +51,17 @@ static lv_obj_t *imu_label = NULL; // Label for IMU data
|
||||
|
||||
static lv_style_t style_mono8;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int selected;
|
||||
int count;
|
||||
lv_obj_t *obj;
|
||||
} menu_context_t;
|
||||
|
||||
static void gui_task(void);
|
||||
static void createBubble(lv_obj_t * scr);
|
||||
static void build_scrollable_menu(void);
|
||||
static void currentFocusIndex(menu_context_t *ctx);
|
||||
|
||||
#define MAX_ITEMS 10
|
||||
#define VISIBLE_ITEMS 3
|
||||
@@ -65,72 +77,19 @@ static lv_obj_t *list;
|
||||
static lv_obj_t *buttons[MAX_ITEMS];
|
||||
static int selected_index = 0;
|
||||
static lv_obj_t *_bubble = NULL;
|
||||
static lv_obj_t * _menu = NULL;
|
||||
static lv_obj_t *_currentPage = NULL;
|
||||
|
||||
static GuiMode_t _mode = GUI_BUBBLE;
|
||||
|
||||
/* 1. Prepare a default (unfocused) style */
|
||||
static lv_style_t _styleUnfocusedBtn;
|
||||
|
||||
|
||||
/* 2. Prepare a focus style */
|
||||
static lv_style_t _styleFocusedBtn;
|
||||
|
||||
// Update highlight based on selected_index
|
||||
void update_highlight() {
|
||||
|
||||
lvgl_port_lock(0);
|
||||
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||
if (buttons[i]) {
|
||||
lv_obj_remove_state(buttons[i], LV_STATE_FOCUSED);
|
||||
}
|
||||
}
|
||||
//if (buttons[selected_index])
|
||||
{
|
||||
lv_obj_add_state(buttons[selected_index], LV_STATE_FOCUSED);
|
||||
lv_obj_scroll_to_view(buttons[selected_index], LV_ANIM_ON);
|
||||
}
|
||||
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
// Called when the GPIO button is pressed
|
||||
void scroll_down() {
|
||||
if (selected_index < MAX_ITEMS - 1) {
|
||||
selected_index++;
|
||||
update_highlight();
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_up() {
|
||||
if (selected_index > 0) {
|
||||
selected_index--;
|
||||
update_highlight();
|
||||
}
|
||||
}
|
||||
|
||||
static void create_menu(lv_obj_t *parent)
|
||||
{
|
||||
lvgl_port_lock(0);
|
||||
|
||||
list = lv_list_create(parent);
|
||||
lv_obj_set_size(list, 160, 80);
|
||||
lv_obj_center(list);
|
||||
lv_obj_set_style_pad_row(list, 2, 0);
|
||||
lv_obj_set_scroll_dir(list, LV_DIR_VER);
|
||||
lv_obj_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_AUTO);
|
||||
|
||||
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||
buttons[i] = lv_list_add_btn(list, NULL, menu_items[i]);
|
||||
}
|
||||
|
||||
// Apply style to show selection highlight
|
||||
static lv_style_t style_focus;
|
||||
lv_style_init(&style_focus);
|
||||
lv_style_set_bg_color(&style_focus, lv_palette_main(LV_PALETTE_RED));
|
||||
lv_style_set_bg_opa(&style_focus, LV_OPA_COVER);
|
||||
lv_style_set_text_color(&style_focus, lv_color_white());
|
||||
|
||||
for (int i = 0; i < MAX_ITEMS; i++) {
|
||||
lv_obj_add_style(buttons[i], &style_focus, LV_STATE_FOCUSED);
|
||||
}
|
||||
|
||||
update_highlight();
|
||||
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
static menu_context_t _menuContext;
|
||||
|
||||
static bool notify_lvgl_flush_ready(void *user_ctx) {
|
||||
if (disp) {
|
||||
@@ -146,40 +105,13 @@ static void create_lvgl_demo(void)
|
||||
lvgl_port_lock(0);
|
||||
// Create a screen with black background
|
||||
lv_obj_t *scr = lv_scr_act();
|
||||
//lv_obj_set_style_bg_color(scr, lv_color_black(), LV_PART_MAIN);
|
||||
//lv_obj_set_style_bg_color(scr, lv_palette_main(LV_PALETTE_RED), LV_PART_MAIN);
|
||||
|
||||
//lv_style_init(&style_mono8);
|
||||
//lv_style_set_text_font(&style_mono8, &lv_font_unscii_8);
|
||||
|
||||
//create_menu(scr);
|
||||
createBubble(scr);
|
||||
build_scrollable_menu();
|
||||
|
||||
lvgl_port_unlock();
|
||||
|
||||
#if 0
|
||||
// Create a label for IMU data
|
||||
imu_label = lv_label_create(scr);
|
||||
lv_obj_set_style_text_font(imu_label, &lv_font_montserrat_20, LV_PART_MAIN);
|
||||
lv_obj_set_style_text_color(imu_label, lv_color_white(), LV_PART_MAIN);
|
||||
lv_obj_align(imu_label, LV_ALIGN_CENTER, 0, 0);
|
||||
lv_label_set_text(imu_label, "SOUNDSHOT!");
|
||||
|
||||
// // Create a button
|
||||
// lv_obj_t *btn = lv_btn_create(scr);
|
||||
// lv_obj_align(btn, LV_ALIGN_CENTER, 0, 0);
|
||||
// lv_obj_set_size(btn, 70, 30);
|
||||
|
||||
// // Add label to button
|
||||
// label = lv_label_create(btn);
|
||||
// lv_label_set_text(label, "Button");
|
||||
// lv_obj_center(label);
|
||||
|
||||
// // Create a slider
|
||||
// lv_obj_t *slider = lv_slider_create(scr);
|
||||
// lv_obj_align(slider, LV_ALIGN_BOTTOM_MID, 0, -20);
|
||||
// lv_obj_set_width(slider, 70);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void lcd_init(void)
|
||||
@@ -206,7 +138,6 @@ static void lcd_init(void)
|
||||
.lcd_param_bits = LCD_PARAM_BITS,
|
||||
.spi_mode = 3,
|
||||
.trans_queue_depth = 10,
|
||||
//.on_color_trans_done = notify_lvgl_flush_ready,
|
||||
.user_ctx = NULL,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)LCD_SPI_HOST, &io_config, &io_handle));
|
||||
@@ -313,8 +244,6 @@ void gui_start(void)
|
||||
|
||||
xTaskCreate(gui_task, "gui_task", 4096, NULL, 5, NULL);
|
||||
|
||||
system_notifyAll(EM_EVENT_NEW_DATA);
|
||||
|
||||
}
|
||||
|
||||
static uint32_t waitForKeyPress(void)
|
||||
@@ -341,6 +270,299 @@ static void handleMainMenu(void)
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
|
||||
// ───── MENU CONFIG ─────
|
||||
#define ROW_H 20 // height of each row
|
||||
static const char * items[] = { // your menu entries
|
||||
"VMode Crossmade",
|
||||
"Second Choice",
|
||||
"Another Option",
|
||||
"Yet Another",
|
||||
"Yet Another",
|
||||
"Last One"
|
||||
};
|
||||
#define ITEM_COUNT (sizeof(items)/sizeof(items[0]))
|
||||
|
||||
// ───── STATE & HELPERS ─────
|
||||
static lv_obj_t * btn_array[ITEM_COUNT];
|
||||
static int selected_idx = 0;
|
||||
|
||||
// Called whenever a button is “activated” (Enter/Click)
|
||||
static void btn_click_cb(lv_event_t * e) {
|
||||
lv_obj_t * btn = lv_event_get_target(e);
|
||||
const char * txt = lv_label_get_text(lv_obj_get_child(btn, 0));
|
||||
ESP_LOGI(TAG, "Activated: %s\n", txt);
|
||||
}
|
||||
|
||||
// Repaint all rows so only btn_array[selected_idx] is highlighted
|
||||
static void refresh_highlight(void) {
|
||||
|
||||
return;
|
||||
lvgl_port_lock(0);
|
||||
|
||||
int index = 0;
|
||||
|
||||
lv_obj_t *page = _currentPage;
|
||||
|
||||
lv_obj_t * child = NULL;
|
||||
lv_obj_t * next = lv_obj_get_child(page, index);
|
||||
lv_obj_t * selected = NULL;
|
||||
while(next) {
|
||||
child = next;
|
||||
|
||||
ESP_LOGI(TAG, "Child: %p", child);
|
||||
|
||||
|
||||
if (lv_obj_has_flag(child, LV_OBJ_FLAG_USER_1))
|
||||
{
|
||||
lv_obj_set_style_bg_color(child, lv_color_hex(0xFF8800), 0);
|
||||
lv_obj_set_style_text_color(lv_obj_get_child(child,0),
|
||||
lv_color_white(), 0);
|
||||
|
||||
selected = child;
|
||||
ESP_LOGI(TAG, "Selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_obj_set_style_bg_color(child, lv_color_white(), 0);
|
||||
lv_obj_set_style_text_color(lv_obj_get_child(child,0),
|
||||
lv_color_black(), 0);
|
||||
}
|
||||
|
||||
index++;
|
||||
next = lv_obj_get_child(page, index);
|
||||
}
|
||||
|
||||
// for(int i = 0; i < ITEM_COUNT; i++) {
|
||||
// if(i == selected_idx) {
|
||||
// lv_obj_set_style_bg_color(btn_array[i], lv_color_hex(0xFF8800), 0);
|
||||
// lv_obj_set_style_text_color(lv_obj_get_child(btn_array[i],0),
|
||||
// lv_color_white(), 0);
|
||||
// } else {
|
||||
// lv_obj_set_style_bg_color(btn_array[i], lv_color_white(), 0);
|
||||
// lv_obj_set_style_text_color(lv_obj_get_child(btn_array[i],0),
|
||||
// lv_color_black(), 0);
|
||||
// }
|
||||
// }
|
||||
|
||||
if (selected)
|
||||
{
|
||||
lv_obj_scroll_to_view(selected, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
|
||||
static void menuInc(int inc)
|
||||
{
|
||||
LOCK();
|
||||
|
||||
currentFocusIndex(&_menuContext);
|
||||
|
||||
ESP_LOGI(TAG, "Current Index: %d", _menuContext.selected);
|
||||
|
||||
lv_obj_t *next = NULL;
|
||||
|
||||
// check if we are at the first or last in the page
|
||||
lv_obj_t *test = lv_obj_get_child(_currentPage, (inc > 0 ? -1 : 0));
|
||||
|
||||
if (_menuContext.obj != test)
|
||||
{
|
||||
next = lv_obj_get_child(_currentPage, _menuContext.selected + inc);
|
||||
lv_obj_add_state(next, LV_STATE_FOCUSED);
|
||||
lv_obj_clear_state(_menuContext.obj, LV_STATE_FOCUSED);
|
||||
lv_obj_scroll_to_view(next, LV_ANIM_ON);
|
||||
|
||||
_menuContext.obj = next;
|
||||
_menuContext.selected += inc;
|
||||
}
|
||||
|
||||
UNLOCK();
|
||||
}
|
||||
|
||||
static void menuNext(void)
|
||||
{
|
||||
menuInc(1);
|
||||
}
|
||||
|
||||
|
||||
static void menuPrevious(void)
|
||||
{
|
||||
menuInc(-1);
|
||||
}
|
||||
|
||||
// Fire the “clicked” event on the selected row
|
||||
static void activate_selected(void)
|
||||
{
|
||||
LOCK();
|
||||
lv_obj_send_event(_menuContext.obj, LV_EVENT_CLICKED, NULL);
|
||||
UNLOCK();
|
||||
}
|
||||
|
||||
static lv_obj_t * addMenuItem(lv_obj_t *page, const char *text)
|
||||
{
|
||||
lv_obj_t * btn = lv_btn_create(page);
|
||||
lv_obj_set_size(btn, LV_PCT(100), ROW_H);
|
||||
|
||||
|
||||
lv_obj_add_style(btn, &_styleUnfocusedBtn, LV_PART_MAIN | LV_STATE_DEFAULT);
|
||||
lv_obj_add_style(btn, &_styleFocusedBtn, LV_PART_MAIN | LV_STATE_FOCUSED);
|
||||
|
||||
lv_obj_add_state(btn, LV_STATE_DEFAULT);
|
||||
|
||||
|
||||
// style it just like your old list
|
||||
// lv_obj_set_style_bg_color(btn, lv_color_white(), 0);
|
||||
lv_obj_set_style_radius(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
// label & center
|
||||
lv_obj_t * lbl = lv_label_create(btn);
|
||||
lv_label_set_text(lbl, text);
|
||||
lv_obj_set_style_radius(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_style_border_width(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
|
||||
// click callback
|
||||
lv_obj_add_event_cb(btn, btn_click_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
return btn;
|
||||
}
|
||||
|
||||
static int getSelectedIndex(lv_obj_t *page)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void currentFocusIndex(menu_context_t *ctx)
|
||||
{
|
||||
ctx->count = lv_obj_get_child_cnt(_currentPage);
|
||||
ctx->obj = NULL;
|
||||
ctx->selected = -1;
|
||||
|
||||
// return the index of the currently focused object
|
||||
for(int i = 0; i < ctx->count; i++) {
|
||||
lv_obj_t * child = lv_obj_get_child(_currentPage, i);
|
||||
|
||||
if (lv_obj_has_state(child, LV_STATE_FOCUSED))
|
||||
{
|
||||
ctx->obj = child;
|
||||
ctx->selected = i;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
// ───── BUILD THE MENU ─────
|
||||
static void build_scrollable_menu(void) {
|
||||
|
||||
|
||||
lv_style_init(&_styleFocusedBtn);
|
||||
lv_style_init(&_styleUnfocusedBtn);
|
||||
|
||||
lv_style_set_bg_color(&_styleUnfocusedBtn, lv_color_make(0xff,0xff,0xff)); // gray bg
|
||||
lv_style_set_text_color(&_styleUnfocusedBtn, lv_color_hex(0xFF8800));
|
||||
|
||||
lv_style_set_bg_color(&_styleFocusedBtn, lv_color_make(0x33,0x99,0xFF)); // blue bg
|
||||
lv_style_set_text_color(&_styleUnfocusedBtn,lv_color_black());
|
||||
|
||||
|
||||
// 2) Inside it, create the lv_menu and hide its sidebar/header
|
||||
lv_obj_t *menu = lv_menu_create(lv_scr_act());
|
||||
_menu = menu;
|
||||
|
||||
lv_obj_set_style_radius(menu, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_style_border_width(menu, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_size(menu, lv_pct(100), lv_pct(100));
|
||||
lv_obj_center(menu);
|
||||
|
||||
lv_obj_set_scrollbar_mode(menu, LV_SCROLLBAR_MODE_AUTO);
|
||||
|
||||
|
||||
lv_obj_t * main = lv_menu_page_create(menu, NULL);
|
||||
lv_obj_set_style_radius(main, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_style_border_width(main, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_scrollbar_mode(main, LV_SCROLLBAR_MODE_AUTO);
|
||||
lv_obj_set_size(main, lv_pct(100), lv_pct(100));
|
||||
|
||||
lv_menu_set_page(menu, main);
|
||||
|
||||
lv_obj_t * tmpObj;
|
||||
|
||||
|
||||
|
||||
lv_obj_t * calMenu = lv_menu_page_create(menu, NULL);
|
||||
lv_obj_set_style_radius(calMenu, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_style_border_width(calMenu, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_scrollbar_mode(calMenu, LV_SCROLLBAR_MODE_AUTO);
|
||||
|
||||
tmpObj = addMenuItem(main, "Bluetooth");
|
||||
lv_obj_add_state(tmpObj, LV_STATE_FOCUSED);
|
||||
//lv_obj_add_flag(tmpObj, LV_OBJ_FLAG_USER_1);
|
||||
|
||||
tmpObj = addMenuItem(main, "Calibration");
|
||||
lv_menu_set_load_page_event(menu, tmpObj, calMenu);
|
||||
|
||||
|
||||
tmpObj = addMenuItem(main, "Volume");
|
||||
|
||||
addMenuItem(main, "About");
|
||||
addMenuItem(main, "Exit");
|
||||
|
||||
|
||||
addMenuItem(calMenu, "Calibrate Level");
|
||||
addMenuItem(calMenu, "Reset Calibration");
|
||||
addMenuItem(calMenu, "Exit");
|
||||
|
||||
_currentPage = main;
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
for(int i = 0; i < ITEM_COUNT; i++) {
|
||||
// create a full-width button in that section
|
||||
lv_obj_t * btn = lv_btn_create(main);
|
||||
lv_obj_set_size(btn, LV_PCT(100), ROW_H);
|
||||
|
||||
// style it just like your old list
|
||||
lv_obj_set_style_bg_color(btn, lv_color_white(), 0);
|
||||
lv_obj_set_style_radius(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_set_style_border_width(btn, 0, LV_PART_MAIN);
|
||||
lv_obj_clear_flag(btn, LV_OBJ_FLAG_SCROLLABLE);
|
||||
|
||||
|
||||
// label & center
|
||||
lv_obj_t * lbl = lv_label_create(btn);
|
||||
lv_label_set_text(lbl, items[i]);
|
||||
lv_obj_set_style_radius(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
lv_obj_set_style_border_width(lbl, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
//lv_obj_center(lbl);
|
||||
|
||||
// click callback
|
||||
lv_obj_add_event_cb(btn, btn_click_cb, LV_EVENT_CLICKED, NULL);
|
||||
|
||||
// save for highlight/scroll
|
||||
btn_array[i] = btn;
|
||||
}
|
||||
|
||||
// lv_obj_t * content = lv_obj_get_child(page, 0);
|
||||
// lv_obj_set_style_radius(content, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
// lv_obj_set_style_border_width(content, 0, LV_PART_MAIN | LV_STATE_ANY);
|
||||
#endif
|
||||
// 6) Initial highlight
|
||||
selected_idx = 0;
|
||||
refresh_highlight();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void gui_task(void)
|
||||
{
|
||||
system_subscribe(xTaskGetCurrentTaskHandle());
|
||||
@@ -349,24 +571,50 @@ static void gui_task(void)
|
||||
QueueHandle_t q = keypad_getQueue();
|
||||
uint32_t ev = 0;
|
||||
|
||||
lv_obj_remove_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(_menu, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
|
||||
if (xQueueReceive(q, &ev, pdMS_TO_TICKS(10)) == pdTRUE)
|
||||
{
|
||||
switch (ev) {
|
||||
case (KEY0 << KEY_SHORT_PRESS):
|
||||
scroll_down();
|
||||
|
||||
if (_mode == GUI_MENU)
|
||||
{
|
||||
menuNext();
|
||||
}
|
||||
ESP_LOGI(TAG, "MAIN: Button 1 SHORT");
|
||||
break;
|
||||
case (KEY0 << KEY_LONG_PRESS):
|
||||
ESP_LOGI(TAG, "MAIN: Button 1 LONG");
|
||||
|
||||
if (_mode != GUI_MENU)
|
||||
{
|
||||
_mode = GUI_MENU;
|
||||
lv_obj_remove_flag(_menu, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
else
|
||||
if (_mode == GUI_MENU)
|
||||
{
|
||||
activate_selected();
|
||||
_mode = GUI_BUBBLE;
|
||||
// lv_obj_remove_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
|
||||
// lv_obj_add_flag(_menu, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
|
||||
break;
|
||||
case (KEY1 << KEY_SHORT_PRESS):
|
||||
scroll_up();
|
||||
ESP_LOGI(TAG, "MAIN: Button 2 SHORT");
|
||||
{
|
||||
if (_mode == GUI_MENU)
|
||||
{
|
||||
menuPrevious();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (KEY1 << KEY_LONG_PRESS):
|
||||
ESP_LOGI(TAG, "MAIN: Button 2 LONG");
|
||||
gpio_set_level(PIN_NUM_nON, 0);
|
||||
@@ -377,24 +625,25 @@ static void gui_task(void)
|
||||
}
|
||||
|
||||
|
||||
if (_mode == GUI_BUBBLE)
|
||||
{
|
||||
uint32_t notifiedBits = 0;
|
||||
// clear on entry (first param), wait for any bit, block forever
|
||||
xTaskNotifyWait(
|
||||
0xFFFFFFFF, // clear any old bits on entry
|
||||
0xFFFFFFFF, // clear bits on exit
|
||||
¬ifiedBits,
|
||||
portMAX_DELAY);
|
||||
pdMS_TO_TICKS(10));
|
||||
|
||||
if (notifiedBits & EM_EVENT_NEW_DATA)
|
||||
{
|
||||
ImuData_t d = system_getImuData();
|
||||
|
||||
//ESP_LOGI(TAG, "Angle: %.2f", a);
|
||||
bubble_setValue(_bubble, -d.filtered[ANGLE_XY]);
|
||||
|
||||
bubble_setValue(_bubble, -d.angle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,12 @@
|
||||
#ifndef GUI_H
|
||||
#define GUI_H
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GUI_MAIN = 0,
|
||||
GUI_MENU,
|
||||
GUI_BUBBLE
|
||||
} GuiMode_t;
|
||||
|
||||
void gui_start(void);
|
||||
|
||||
|
||||
19
main/main.c
19
main/main.c
@@ -168,8 +168,25 @@ static void imu_task(void *pvParameters) {
|
||||
imu.raw[ANGLE_XY] = atan2f((float)imu_data.acc_x, (float)imu_data.acc_y) * 180 / M_PI;
|
||||
|
||||
|
||||
float angle;
|
||||
|
||||
imu.filtered[ANGLE_XY] = LPF_Update(&lpf, imu.raw[ANGLE_XY]);
|
||||
if (imu.raw[ANGLE_XY] > MAX_INDICATION_ANGLE)
|
||||
{
|
||||
angle = MAX_INDICATION_ANGLE;
|
||||
}
|
||||
else
|
||||
if (imu.raw[ANGLE_XY] > MAX_INDICATION_ANGLE)
|
||||
{
|
||||
angle = -MAX_INDICATION_ANGLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle = imu.raw[ANGLE_XY];
|
||||
}
|
||||
|
||||
imu.angle = LPF_Update(&lpf, angle);
|
||||
|
||||
//imu.filtered[ANGLE_XY] = LPF_Update(&lpf, imu.raw[ANGLE_XY]);
|
||||
|
||||
system_setImuData(imu);
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ void system_notifyAll(uint32_t eventBits) {
|
||||
if (xSemaphoreTake(em->mutex, portMAX_DELAY) == pdTRUE) {
|
||||
for (size_t i = 0; i < em->count; ++i) {
|
||||
// set the bits in each task's notification value
|
||||
ESP_LOGI("g", "Notify: %p", em->subscribers[i]);
|
||||
//ESP_LOGI("g", "Notify: %p", em->subscribers[i]);
|
||||
xTaskNotify(em->subscribers[i],
|
||||
eventBits,
|
||||
eSetBits);
|
||||
|
||||
@@ -12,10 +12,13 @@ enum
|
||||
ANGLE_YZ,
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float raw[3];
|
||||
float filtered[3];
|
||||
float angle;
|
||||
} ImuData_t;
|
||||
|
||||
typedef struct SystemState_s
|
||||
@@ -23,9 +26,12 @@ typedef struct SystemState_s
|
||||
ImuData_t imu;
|
||||
|
||||
EventGroupHandle_t event;
|
||||
|
||||
|
||||
} SystemState_t;
|
||||
|
||||
|
||||
#define MAX_INDICATION_ANGLE 10.0f
|
||||
|
||||
#define EM_MAX_SUBSCRIBERS 8 // tweak as needed
|
||||
#define EM_EVENT_NEW_DATA (1UL<<0)
|
||||
|
||||
Reference in New Issue
Block a user