basic menu working

This commit is contained in:
Brent Perteet
2025-06-24 09:20:40 -05:00
parent f59eb660cf
commit 311981ceb4
9 changed files with 494 additions and 114 deletions

23
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
}

View File

@@ -25,6 +25,9 @@
static const char *TAG = "gui"; static const char *TAG = "gui";
#define UNLOCK() lvgl_port_unlock()
#define LOCK() lvgl_port_lock(0)
// LCD Pin Configuration // LCD Pin Configuration
#define LCD_PIXEL_CLOCK_HZ (5 * 1000 * 1000) #define LCD_PIXEL_CLOCK_HZ (5 * 1000 * 1000)
#define LCD_SPI_HOST SPI2_HOST #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; 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 gui_task(void);
static void createBubble(lv_obj_t * scr); 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 MAX_ITEMS 10
#define VISIBLE_ITEMS 3 #define VISIBLE_ITEMS 3
@@ -65,72 +77,19 @@ static lv_obj_t *list;
static lv_obj_t *buttons[MAX_ITEMS]; static lv_obj_t *buttons[MAX_ITEMS];
static int selected_index = 0; static int selected_index = 0;
static lv_obj_t *_bubble = NULL; 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 static menu_context_t _menuContext;
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 bool notify_lvgl_flush_ready(void *user_ctx) { static bool notify_lvgl_flush_ready(void *user_ctx) {
if (disp) { if (disp) {
@@ -146,40 +105,13 @@ static void create_lvgl_demo(void)
lvgl_port_lock(0); lvgl_port_lock(0);
// Create a screen with black background // Create a screen with black background
lv_obj_t *scr = lv_scr_act(); 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); //create_menu(scr);
createBubble(scr); createBubble(scr);
build_scrollable_menu();
lvgl_port_unlock(); 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) static void lcd_init(void)
@@ -206,7 +138,6 @@ static void lcd_init(void)
.lcd_param_bits = LCD_PARAM_BITS, .lcd_param_bits = LCD_PARAM_BITS,
.spi_mode = 3, .spi_mode = 3,
.trans_queue_depth = 10, .trans_queue_depth = 10,
//.on_color_trans_done = notify_lvgl_flush_ready,
.user_ctx = NULL, .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)); 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); xTaskCreate(gui_task, "gui_task", 4096, NULL, 5, NULL);
system_notifyAll(EM_EVENT_NEW_DATA);
} }
static uint32_t waitForKeyPress(void) static uint32_t waitForKeyPress(void)
@@ -341,6 +270,299 @@ static void handleMainMenu(void)
lvgl_port_unlock(); 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) static void gui_task(void)
{ {
system_subscribe(xTaskGetCurrentTaskHandle()); system_subscribe(xTaskGetCurrentTaskHandle());
@@ -349,24 +571,50 @@ static void gui_task(void)
QueueHandle_t q = keypad_getQueue(); QueueHandle_t q = keypad_getQueue();
uint32_t ev = 0; uint32_t ev = 0;
lv_obj_remove_flag(_bubble, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(_menu, LV_OBJ_FLAG_HIDDEN);
while (1) while (1)
{ {
if (xQueueReceive(q, &ev, pdMS_TO_TICKS(10)) == pdTRUE) if (xQueueReceive(q, &ev, pdMS_TO_TICKS(10)) == pdTRUE)
{ {
switch (ev) { switch (ev) {
case (KEY0 << KEY_SHORT_PRESS): case (KEY0 << KEY_SHORT_PRESS):
scroll_down();
if (_mode == GUI_MENU)
{
menuNext();
}
ESP_LOGI(TAG, "MAIN: Button 1 SHORT"); ESP_LOGI(TAG, "MAIN: Button 1 SHORT");
break; break;
case (KEY0 << KEY_LONG_PRESS): 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; break;
case (KEY1 << KEY_SHORT_PRESS): case (KEY1 << KEY_SHORT_PRESS):
scroll_up(); {
ESP_LOGI(TAG, "MAIN: Button 2 SHORT"); if (_mode == GUI_MENU)
{
menuPrevious();
}
break; break;
}
case (KEY1 << KEY_LONG_PRESS): case (KEY1 << KEY_LONG_PRESS):
ESP_LOGI(TAG, "MAIN: Button 2 LONG"); ESP_LOGI(TAG, "MAIN: Button 2 LONG");
gpio_set_level(PIN_NUM_nON, 0); gpio_set_level(PIN_NUM_nON, 0);
@@ -376,25 +624,26 @@ static void gui_task(void)
} }
} }
uint32_t notifiedBits = 0; if (_mode == GUI_BUBBLE)
// clear on entry (first param), wait for any bit, block forever
xTaskNotifyWait(
0xFFFFFFFF, // clear any old bits on entry
0xFFFFFFFF, // clear bits on exit
&notifiedBits,
portMAX_DELAY);
if (notifiedBits & EM_EVENT_NEW_DATA)
{ {
ImuData_t d = system_getImuData(); uint32_t notifiedBits = 0;
// clear on entry (first param), wait for any bit, block forever
//ESP_LOGI(TAG, "Angle: %.2f", a); xTaskNotifyWait(
bubble_setValue(_bubble, -d.filtered[ANGLE_XY]); 0xFFFFFFFF, // clear any old bits on entry
0xFFFFFFFF, // clear bits on exit
&notifiedBits,
pdMS_TO_TICKS(10));
if (notifiedBits & EM_EVENT_NEW_DATA)
{
ImuData_t d = system_getImuData();
bubble_setValue(_bubble, -d.angle);
}
} }
} }
} }

View File

@@ -1,6 +1,12 @@
#ifndef GUI_H #ifndef GUI_H
#define GUI_H #define GUI_H
typedef enum
{
GUI_MAIN = 0,
GUI_MENU,
GUI_BUBBLE
} GuiMode_t;
void gui_start(void); void gui_start(void);

View File

@@ -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; 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); system_setImuData(imu);

View File

@@ -94,7 +94,7 @@ void system_notifyAll(uint32_t eventBits) {
if (xSemaphoreTake(em->mutex, portMAX_DELAY) == pdTRUE) { if (xSemaphoreTake(em->mutex, portMAX_DELAY) == pdTRUE) {
for (size_t i = 0; i < em->count; ++i) { for (size_t i = 0; i < em->count; ++i) {
// set the bits in each task's notification value // 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], xTaskNotify(em->subscribers[i],
eventBits, eventBits,
eSetBits); eSetBits);

View File

@@ -12,10 +12,13 @@ enum
ANGLE_YZ, ANGLE_YZ,
}; };
typedef struct typedef struct
{ {
float raw[3]; float raw[3];
float filtered[3]; float filtered[3];
float angle;
} ImuData_t; } ImuData_t;
typedef struct SystemState_s typedef struct SystemState_s
@@ -23,9 +26,12 @@ typedef struct SystemState_s
ImuData_t imu; ImuData_t imu;
EventGroupHandle_t event; EventGroupHandle_t event;
} SystemState_t; } SystemState_t;
#define MAX_INDICATION_ANGLE 10.0f
#define EM_MAX_SUBSCRIBERS 8 // tweak as needed #define EM_MAX_SUBSCRIBERS 8 // tweak as needed
#define EM_EVENT_NEW_DATA (1UL<<0) #define EM_EVENT_NEW_DATA (1UL<<0)