Add joystick-calibration wizzard (store in nvs), Optimize Menu
- menu:
- Add item joystick calibration wizzard
- Add item RESET (clear nvs and restart)
- Add configuration option to not show/change value. Instead only show confirm message
apply this to all items only running action
- Optimize formatting and comments
- main:
- pass nvsHandle to display task and joystick class
- joystick:
- Add methods to write and load calibration values (axis min/max adc value) from nvs
- Add method to get raw adc value
This commit is contained in:
@@ -8,6 +8,8 @@ extern "C" {
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "nvs.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
#include "font8x8_basic.h"
|
||||
@@ -42,6 +44,7 @@ typedef struct display_task_parameters_t {
|
||||
speedSensor * speedLeft;
|
||||
speedSensor * speedRight;
|
||||
buzzer_t *buzzer;
|
||||
nvs_handle_t * nvsHandle;
|
||||
} display_task_parameters_t;
|
||||
|
||||
|
||||
|
||||
@@ -152,8 +152,8 @@ void createObjects()
|
||||
speedLeft = new speedSensor(speedLeft_config);
|
||||
speedRight = new speedSensor(speedRight_config);
|
||||
|
||||
// create joystic instance (joystick.hpp)
|
||||
joystick = new evaluatedJoystick(configJoystick);
|
||||
// create joystick instance (joystick.hpp)
|
||||
joystick = new evaluatedJoystick(configJoystick, &nvsHandle);
|
||||
|
||||
// create httpJoystick object (http.hpp)
|
||||
httpJoystickMain = new httpJoystick(configHttpJoystickMain);
|
||||
@@ -286,8 +286,8 @@ extern "C" void app_main(void) {
|
||||
//-----------------------------------
|
||||
//----- create task for display -----
|
||||
//-----------------------------------
|
||||
////task that handles the display (show stats, handle menu in 'MENU' mode)
|
||||
display_task_parameters_t display_param = {display_config, control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer};
|
||||
//task that handles the display (show stats, handle menu in 'MENU' mode)
|
||||
display_task_parameters_t display_param = {display_config, control, joystick, encoderQueue, motorLeft, motorRight, speedLeft, speedRight, buzzer, &nvsHandle};
|
||||
xTaskCreate(&display_task, "display_task", 3*2048, &display_param, 3, NULL);
|
||||
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS); //wait for all tasks to finish initializing
|
||||
|
||||
@@ -27,7 +27,8 @@ static int value = 0;
|
||||
//================================
|
||||
// Instructions / Behavior:
|
||||
// - when line4 * and line5 * are empty the value is printed large
|
||||
// - when 3rd element is not NULL (pointer to defaultValue function) that return value is shown in line 2
|
||||
// - when 3rd element is not NULL (pointer to defaultValue function) return int value of that function is shown in line 2
|
||||
// - when 2nd element is NULL (pointer to currentValue function): instead of current value "click to confirm is shown" in line 3
|
||||
|
||||
//#########################
|
||||
//#### center Joystick ####
|
||||
@@ -38,24 +39,146 @@ void item_centerJoystick_action(display_task_parameters_t * objects, SSD1306_t *
|
||||
objects->joystick->defineCenter();
|
||||
objects->buzzer->beep(3, 60, 40);
|
||||
}
|
||||
int item_centerJoystick_value(display_task_parameters_t * objects){
|
||||
return 1;
|
||||
}
|
||||
|
||||
menuItem_t item_centerJoystick = {
|
||||
item_centerJoystick_action, // function action
|
||||
item_centerJoystick_value, // function get initial value
|
||||
NULL, // function get default value or NULL
|
||||
NULL, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
1, // valueMAx
|
||||
1, // valueIncrement
|
||||
"Center Joystick", // title
|
||||
"Center Joystick", // line1 (above value)
|
||||
"click to confirm", // line2 (above value)
|
||||
"defines current", // line4 * (below value)
|
||||
"pos as center", // line5 *
|
||||
"click to confirm", // line6
|
||||
"set 0 to cancel", // line7
|
||||
0, // valueMax
|
||||
0, // valueIncrement
|
||||
"Center Joystick ", // title
|
||||
"Center Joystick ", // line1 (above value)
|
||||
"", // line2 (above value)
|
||||
"defines current ", // line4 * (below value)
|
||||
"pos as center ", // line5 *
|
||||
"", // line6
|
||||
"=>long to cancel", // line7
|
||||
};
|
||||
|
||||
// ############################
|
||||
// #### calibrate Joystick ####
|
||||
// ############################
|
||||
// continously show/update joystick data on display
|
||||
#define CALIBRATE_JOYSTICK_UPDATE_INTERVAL 50
|
||||
void item_calibrateJoystick_action(display_task_parameters_t *objects, SSD1306_t *display, int value)
|
||||
{
|
||||
//--- variables ---
|
||||
bool running = true;
|
||||
joystickCalibrationMode_t mode = X_MIN;
|
||||
rotary_encoder_event_t event;
|
||||
int valueNow = 0;
|
||||
|
||||
//-- pre loop instructions --
|
||||
ESP_LOGW(TAG, "starting joystick calibration sequence");
|
||||
ssd1306_clear_screen(display, false);
|
||||
|
||||
//-- show static lines --
|
||||
// show first line (title)
|
||||
displayTextLine(display, 0, false, true, "calibrate stick");
|
||||
// show last line (info)
|
||||
displayTextLineCentered(display, 7, false, true, " click: confirm ");
|
||||
// show initital state
|
||||
displayTextLineCentered(display, 1, true, false, "%s", "X-min");
|
||||
|
||||
//-- loop until all positions are defined --
|
||||
while (running && objects->control->getCurrentMode() == controlMode_t::MENU)
|
||||
{
|
||||
// repeatedly print adc value depending on currently selected axis
|
||||
switch (mode)
|
||||
{
|
||||
case X_MIN:
|
||||
case X_MAX:
|
||||
displayTextLineCentered(display, 4, true, false, "%d", valueNow = objects->joystick->getRawX()); // large
|
||||
break;
|
||||
case Y_MIN:
|
||||
case Y_MAX:
|
||||
displayTextLineCentered(display, 4, true, false, "%d", valueNow = objects->joystick->getRawY()); // large
|
||||
break;
|
||||
case X_CENTER:
|
||||
case Y_CENTER:
|
||||
displayTextLine(display, 4, false, false, " x = %d", objects->joystick->getRawX());
|
||||
displayTextLine(display, 5, false, false, " y = %d", objects->joystick->getRawY());
|
||||
displayTextLine(display, 6, false, false, "release & click!");
|
||||
break;
|
||||
}
|
||||
|
||||
// handle encoder event
|
||||
// save and next when button clicked, exit when long pressed
|
||||
if (xQueueReceive(objects->encoderQueue, &event, CALIBRATE_JOYSTICK_UPDATE_INTERVAL / portTICK_PERIOD_MS))
|
||||
{
|
||||
objects->control->resetTimeout();
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_BTN_CLICKED:
|
||||
objects->buzzer->beep(2, 120, 50);
|
||||
switch (mode)
|
||||
{
|
||||
case X_MIN:
|
||||
// save x min position
|
||||
ESP_LOGW(TAG, "calibrate-stick: saving X_MIN");
|
||||
objects->joystick->writeCalibration(mode, valueNow);
|
||||
displayTextLineCentered(display, 1, true, false, "%s", "X-max");
|
||||
mode = X_MAX;
|
||||
break;
|
||||
case X_MAX:
|
||||
// save x max position
|
||||
ESP_LOGW(TAG, "calibrate-stick: saving X_MAX");
|
||||
objects->joystick->writeCalibration(mode, valueNow);
|
||||
displayTextLineCentered(display, 1, true, false, "%s", "Y-min");
|
||||
mode = Y_MIN;
|
||||
break;
|
||||
case Y_MIN:
|
||||
// save y min position
|
||||
ESP_LOGW(TAG, "calibrate-stick: saving Y_MIN");
|
||||
objects->joystick->writeCalibration(mode, valueNow);
|
||||
displayTextLineCentered(display, 1, true, false, "%s", "Y-max");
|
||||
mode = Y_MAX;
|
||||
break;
|
||||
case Y_MAX:
|
||||
// save y max position
|
||||
ESP_LOGW(TAG, "calibrate-stick: saving Y_MAX");
|
||||
objects->joystick->writeCalibration(mode, valueNow);
|
||||
displayTextLineCentered(display, 1, true, false, "%s", "CENTR");
|
||||
mode = X_CENTER;
|
||||
break;
|
||||
case X_CENTER:
|
||||
case Y_CENTER:
|
||||
// save center position
|
||||
ESP_LOGW(TAG, "calibrate-stick: saving CENTER -> finished");
|
||||
objects->joystick->defineCenter();
|
||||
// finished
|
||||
running = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
//exit to main-menu
|
||||
objects->buzzer->beep(1, 1000, 10);
|
||||
ESP_LOGW(TAG, "aborting calibration sqeuence");
|
||||
running = false;
|
||||
case RE_ET_CHANGED:
|
||||
case RE_ET_BTN_PRESSED:
|
||||
case RE_ET_BTN_RELEASED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
menuItem_t item_calibrateJoystick = {
|
||||
item_calibrateJoystick_action, // function action
|
||||
NULL, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
0, // valueMax
|
||||
0, // valueIncrement
|
||||
"Calibrate Stick ", // title
|
||||
" Calibrate ", // line1 (above value)
|
||||
" Joystick ", // line2 (above value)
|
||||
" click to start ", // line4 * (below value)
|
||||
" sequence ", // line5 *
|
||||
" ", // line6
|
||||
"=>long to cancel", // line7
|
||||
};
|
||||
|
||||
|
||||
@@ -71,8 +194,6 @@ void item_debugJoystick_action(display_task_parameters_t * objects, SSD1306_t *
|
||||
rotary_encoder_event_t event;
|
||||
|
||||
//-- pre loop instructions --
|
||||
if (!value) // dont open menu when value was set to 0
|
||||
return;
|
||||
ESP_LOGW(TAG, "showing joystick debug page");
|
||||
ssd1306_clear_screen(display, false);
|
||||
// show title
|
||||
@@ -99,36 +220,32 @@ void item_debugJoystick_action(display_task_parameters_t * objects, SSD1306_t *
|
||||
switch (event.type)
|
||||
{
|
||||
case RE_ET_BTN_CLICKED:
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
running = false;
|
||||
break;
|
||||
case RE_ET_CHANGED:
|
||||
case RE_ET_BTN_PRESSED:
|
||||
case RE_ET_BTN_RELEASED:
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int item_debugJoystick_value(display_task_parameters_t * objects){
|
||||
return 1;
|
||||
}
|
||||
|
||||
menuItem_t item_debugJoystick = {
|
||||
item_debugJoystick_action, // function action
|
||||
item_debugJoystick_value, // function get initial value
|
||||
NULL, // function get default value or NULL
|
||||
NULL, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
1, // valueMAx
|
||||
1, // valueIncrement
|
||||
"Debug joystick", // title
|
||||
"Debug joystick", // line1 (above value)
|
||||
0, // valueMax
|
||||
0, // valueIncrement
|
||||
"Debug joystick ", // title
|
||||
"Debug joystick ", // line1 (above value)
|
||||
"", // line2 (above value)
|
||||
"click to enter", // line4 * (below value)
|
||||
"debug screen", // line5 *
|
||||
"prints values", // line6
|
||||
"set 0 to cancel", // line7
|
||||
"", // line4 * (below value)
|
||||
"debug screen ", // line5 *
|
||||
"prints values ", // line6
|
||||
"=>long to cancel", // line7
|
||||
};
|
||||
|
||||
|
||||
@@ -147,12 +264,12 @@ int maxDuty_currentValue(display_task_parameters_t * objects)
|
||||
}
|
||||
menuItem_t item_maxDuty = {
|
||||
maxDuty_action, // function action
|
||||
maxDuty_currentValue, // function get initial value
|
||||
NULL, // function get default value or NULL
|
||||
maxDuty_currentValue, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
1, // valueMin
|
||||
99, // valueMAx
|
||||
99, // valueMax
|
||||
1, // valueIncrement
|
||||
"max duty", // title
|
||||
"max duty ", // title
|
||||
"", // line1 (above value)
|
||||
" set max-duty: ", // line2 (above value)
|
||||
"", // line4 * (below value)
|
||||
@@ -180,18 +297,18 @@ int item_accelLimit_default(display_task_parameters_t * objects)
|
||||
}
|
||||
menuItem_t item_accelLimit = {
|
||||
item_accelLimit_action, // function action
|
||||
item_accelLimit_value, // function get initial value
|
||||
item_accelLimit_default, // function get default value or NULL
|
||||
item_accelLimit_value, // function get initial value or NULL(show in line 2)
|
||||
item_accelLimit_default, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
10000, // valueMAx
|
||||
10000, // valueMax
|
||||
100, // valueIncrement
|
||||
"Accel limit", // title
|
||||
" Fade up time", // line1 (above value)
|
||||
"Accel limit ", // title
|
||||
" Fade up time ", // line1 (above value)
|
||||
"", // line2 <= showing "default = %d"
|
||||
"", // line4 * (below value)
|
||||
"", // line5 *
|
||||
"milliseconds", // line6
|
||||
"from 0 to 100%", // line7
|
||||
"milliseconds ", // line6
|
||||
"from 0 to 100% ", // line7
|
||||
};
|
||||
|
||||
|
||||
@@ -213,18 +330,56 @@ int item_decelLimit_default(display_task_parameters_t * objects)
|
||||
}
|
||||
menuItem_t item_decelLimit = {
|
||||
item_decelLimit_action, // function action
|
||||
item_decelLimit_value, // function get initial value
|
||||
item_decelLimit_default, // function get default value or NULL
|
||||
item_decelLimit_value, // function get initial value or NULL(show in line 2)
|
||||
item_decelLimit_default, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
10000, // valueMAx
|
||||
10000, // valueMax
|
||||
100, // valueIncrement
|
||||
"Decel limit", // title
|
||||
" Fade down time", // line1 (above value)
|
||||
"Decel limit ", // title
|
||||
" Fade down time ", // line1 (above value)
|
||||
"", // line2 <= showing "default = %d"
|
||||
"", // line4 * (below value)
|
||||
"", // line5 *
|
||||
"milliseconds", // line6
|
||||
"from 100 to 0%", // line7
|
||||
"milliseconds ", // line6
|
||||
"from 100 to 0% ", // line7
|
||||
};
|
||||
|
||||
|
||||
//#####################
|
||||
//####### RESET #######
|
||||
//#####################
|
||||
void item_reset_action(display_task_parameters_t *objects, SSD1306_t *display, int value)
|
||||
{
|
||||
objects->buzzer->beep(1, 2000, 0);
|
||||
// close and erase NVS
|
||||
ESP_LOGW(TAG, "closing and ERASING non-volatile-storage...");
|
||||
nvs_close(*(objects->nvsHandle));
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
// show message restarting
|
||||
ssd1306_clear_screen(display, false);
|
||||
displayTextLineCentered(display, 0, false, true, "");
|
||||
displayTextLineCentered(display, 1, true, true, "RE-");
|
||||
displayTextLineCentered(display, 4, true, true, "START");
|
||||
displayTextLineCentered(display, 7, false, true, "");
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS); // wait for buzzer to beep
|
||||
// restart
|
||||
ESP_LOGW(TAG, "RESTARTING");
|
||||
esp_restart();
|
||||
}
|
||||
menuItem_t item_reset = {
|
||||
item_reset_action, // function action
|
||||
NULL, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
0, // valueMin
|
||||
0, // valueMax
|
||||
0, // valueIncrement
|
||||
"RESET defaults ", // title
|
||||
" reset nvs ", // line1 (above value)
|
||||
" and restart ", // line2 <= showing "default = %d"
|
||||
"reset all stored", // line4 * (below value)
|
||||
" parameters ", // line5 *
|
||||
"", // line6
|
||||
"=>long to cancel", // line7
|
||||
};
|
||||
|
||||
|
||||
@@ -243,40 +398,42 @@ int item_example_valueDefault(display_task_parameters_t * objects){
|
||||
}
|
||||
menuItem_t item_example = {
|
||||
item_example_action, // function action
|
||||
item_example_value, // function get initial value
|
||||
NULL, // function get default value or NULL
|
||||
item_example_value, // function get initial value or NULL(show in line 2)
|
||||
NULL, // function get default value or NULL(dont set value, show msg)
|
||||
-255, // valueMin
|
||||
255, // valueMAx
|
||||
255, // valueMax
|
||||
2, // valueIncrement
|
||||
"example-item-max", // title
|
||||
"line 1 - above", // line1 (above value)
|
||||
"line 2 - above", // line2 (above value)
|
||||
"line 4 - below", // line4 * (below value)
|
||||
"line 5 - below", // line5 *
|
||||
"line 6 - below", // line6
|
||||
"line 7 - last", // line7
|
||||
"line 1 - above ", // line1 (above value)
|
||||
"line 2 - above ", // line2 (above value)
|
||||
"line 4 - below ", // line4 * (below value)
|
||||
"line 5 - below ", // line5 *
|
||||
"line 6 - below ", // line6
|
||||
"line 7 - last ", // line7
|
||||
};
|
||||
|
||||
menuItem_t item_last = {
|
||||
item_example_action, // function action
|
||||
item_example_value, // function get initial value
|
||||
item_example_valueDefault, // function get default value or NULL
|
||||
item_example_value, // function get initial value or NULL(show in line 2)
|
||||
item_example_valueDefault, // function get default value or NULL(dont set value, show msg)
|
||||
-500, // valueMin
|
||||
4500, // valueMAx
|
||||
4500, // valueMax
|
||||
50, // valueIncrement
|
||||
"set large number", // title
|
||||
"line 1 - above", // line1 (above value)
|
||||
"line 2 - above", // line2 (above value)
|
||||
"line 1 - above ", // line1 (above value)
|
||||
"line 2 - above ", // line2 (above value)
|
||||
"", // line4 * (below value)
|
||||
"", // line5 *
|
||||
"line 6 - below", // line6
|
||||
"line 7 - last", // line7
|
||||
|
||||
"line 6 - below ", // line6
|
||||
"line 7 - last ", // line7
|
||||
};
|
||||
|
||||
//store all configured menu items in one array
|
||||
const menuItem_t menuItems[] = {item_centerJoystick, item_debugJoystick, item_accelLimit, item_decelLimit, item_example, item_last};
|
||||
const int itemCount = 6;
|
||||
|
||||
//####################################################
|
||||
//### store all configured menu items in one array ###
|
||||
//####################################################
|
||||
const menuItem_t menuItems[] = {item_centerJoystick, item_calibrateJoystick, item_debugJoystick, item_accelLimit, item_decelLimit, item_reset, item_example, item_last};
|
||||
const int itemCount = 8;
|
||||
|
||||
|
||||
|
||||
@@ -322,12 +479,12 @@ void showItemList(SSD1306_t *display, int selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------
|
||||
//--- showValueSelectStatic ---
|
||||
//-----------------------------
|
||||
// function that renders value-select screen to display (one update)
|
||||
// shows configured text of selected item and currently selected value
|
||||
// TODO show previous value in one line?
|
||||
// function that renders lines that do not update of value-select screen to display (initial update)
|
||||
// shows configured text of currently selected item
|
||||
void showValueSelectStatic(display_task_parameters_t * objects, SSD1306_t *display, int selectedItem)
|
||||
{
|
||||
//-- show title line --
|
||||
@@ -336,35 +493,46 @@ void showValueSelectStatic(display_task_parameters_t * objects, SSD1306_t *displ
|
||||
//-- show text above value --
|
||||
displayTextLine(display, 1, false, false, "%-16s", menuItems[selectedItem].line1);
|
||||
|
||||
//-- show line 2 or default value ---
|
||||
//-- show line 2 or default value ---
|
||||
if (menuItems[selectedItem].defaultValue != NULL){
|
||||
displayTextLineCentered(display, 2, false, false, "default = %d", menuItems[selectedItem].defaultValue(objects));
|
||||
}
|
||||
else{
|
||||
//displayTextLine(display, 2, false, false, "previous=%d", menuItems[selectedItem].currentValue(objects)); // <= show previous value
|
||||
displayTextLine(display, 2, false, false, "%-16s", menuItems[selectedItem].line2);
|
||||
}
|
||||
displayTextLineCentered(display, 2, false, false, "default = %d", menuItems[selectedItem].defaultValue(objects));
|
||||
}
|
||||
else
|
||||
{
|
||||
// displayTextLine(display, 2, false, false, "previous=%d", menuItems[selectedItem].currentValue(objects)); // <= show previous value
|
||||
displayTextLine(display, 2, false, false, "%-16s", menuItems[selectedItem].line2);
|
||||
}
|
||||
|
||||
//-- show value and other configured lines --
|
||||
// print value large, if 2 description lines are empty
|
||||
// print value large, if two description lines are empty
|
||||
if (strlen(menuItems[selectedItem].line4) == 0 && strlen(menuItems[selectedItem].line5) == 0)
|
||||
{
|
||||
// print large value + line5 and line6
|
||||
displayTextLineCentered(display, 3, true, false, "%d", value); //large centered
|
||||
// print less lines: line5 and line6 only (due to large value)
|
||||
//displayTextLineCentered(display, 3, true, false, "%d", value); //large centered (value shown in separate function)
|
||||
displayTextLine(display, 6, false, false, "%-16s", menuItems[selectedItem].line6);
|
||||
displayTextLine(display, 7, false, false, "%-16s", menuItems[selectedItem].line7);
|
||||
}
|
||||
else
|
||||
{
|
||||
displayTextLineCentered(display, 3, false, false, "%d", value); //centered
|
||||
//displayTextLineCentered(display, 3, false, false, "%d", value); //centered (value shown in separate function)
|
||||
// print description lines 4 to 7
|
||||
displayTextLine(display, 4, false, false, "%-16s", menuItems[selectedItem].line4);
|
||||
displayTextLine(display, 5, false, false, "%-16s", menuItems[selectedItem].line5);
|
||||
displayTextLine(display, 6, false, false, "%-16s", menuItems[selectedItem].line6);
|
||||
displayTextLine(display, 7, false, false, "%-16s", menuItems[selectedItem].line7);
|
||||
}
|
||||
|
||||
//-- show info msg instead of value --
|
||||
//when pointer to default value func not defined (set value not used, action only)
|
||||
if (menuItems[selectedItem].currentValue == NULL)
|
||||
{
|
||||
//show static text
|
||||
displayTextLineCentered(display, 3, false, true, "%s", "click to confirm");
|
||||
}
|
||||
// otherwise value gets updated in next iteration of menu-handle function
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------
|
||||
//----- updateValueSelect -----
|
||||
//-----------------------------
|
||||
@@ -374,30 +542,29 @@ void updateValueSelect(SSD1306_t *display, int selectedItem)
|
||||
// print value large, if 2 description lines are empty
|
||||
if (strlen(menuItems[selectedItem].line4) == 0 && strlen(menuItems[selectedItem].line5) == 0)
|
||||
{
|
||||
// print large value + line5 and line6
|
||||
displayTextLineCentered(display, 3, true, false, "%d", value); //large centered
|
||||
// print large and centered value in line 3-5
|
||||
displayTextLineCentered(display, 3, true, false, "%d", value); // large centered
|
||||
}
|
||||
else
|
||||
{
|
||||
displayTextLineCentered(display, 3, false, false, "%d", value); //centered
|
||||
//print value centered in line 3
|
||||
displayTextLineCentered(display, 3, false, false, "%d", value); // centered
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================
|
||||
//====== handleMenu ======
|
||||
//========================
|
||||
//controls menu with encoder input and displays the text on oled display
|
||||
//function is repeatedly called by display task when in menu state
|
||||
#define QUEUE_TIMEOUT 3000 //timeout no encoder event - to handle timeout and not block the display loop
|
||||
#define QUEUE_TIMEOUT 3000 //timeout no encoder event - to not block the display loop and actually handle menu-timeout
|
||||
#define MENU_TIMEOUT 60000 //inactivity timeout (switch to IDLE mode) note: should be smaller than IDLE timeout in control task
|
||||
void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
{
|
||||
static uint32_t lastActivity = 0;
|
||||
static int selectedItem = 0;
|
||||
static bool staticContentUpdated = false;
|
||||
rotary_encoder_event_t event; // store event data
|
||||
|
||||
//--- handle different menu states ---
|
||||
@@ -412,6 +579,7 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
// wait for encoder event
|
||||
if (xQueueReceive(objects->encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS))
|
||||
{
|
||||
// reset menu- and control-timeout on any encoder event
|
||||
lastActivity = esp_log_timestamp();
|
||||
objects->control->resetTimeout();
|
||||
switch (event.type)
|
||||
@@ -441,16 +609,20 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
ESP_LOGI(TAG, "Button pressed - switching to state SET_VALUE");
|
||||
// change state (menu to set value)
|
||||
menuState = SET_VALUE;
|
||||
staticContentUpdated = false;
|
||||
// get currently configured value
|
||||
value = menuItems[selectedItem].currentValue(objects);
|
||||
// clear display
|
||||
ssd1306_clear_screen(display, false);
|
||||
//update static content of set-value screen once at change only
|
||||
showValueSelectStatic(objects, display, selectedItem);
|
||||
// get currently configured value, when value-select feature is actually used in this item
|
||||
if (menuItems[selectedItem].currentValue != NULL)
|
||||
value = menuItems[selectedItem].currentValue(objects);
|
||||
else
|
||||
value = 0;
|
||||
break;
|
||||
|
||||
//exit menu mode
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
//change to previous mode (e.g. JOYSTICK)
|
||||
//--- exit menu mode ---
|
||||
// change to previous mode (e.g. JOYSTICK)
|
||||
objects->buzzer->beep(4, 15, 5);
|
||||
objects->control->toggleMode(controlMode_t::MENU); //currently already in MENU -> changes to previous mode
|
||||
ssd1306_clear_screen(display, false);
|
||||
@@ -467,18 +639,12 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
//---- State SET VALUE ----
|
||||
//-------------------------
|
||||
case SET_VALUE:
|
||||
// wait for encoder event
|
||||
if (!staticContentUpdated)
|
||||
{
|
||||
showValueSelectStatic(objects, display, selectedItem);
|
||||
staticContentUpdated = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// update line with currently set value only (increses performance significantly)
|
||||
// update currently selected value
|
||||
// note: static lines are updated at mode change
|
||||
if (menuItems[selectedItem].currentValue != NULL) // dont update when set-value not used for this item
|
||||
updateValueSelect(display, selectedItem);
|
||||
}
|
||||
|
||||
// wait for encoder event
|
||||
if (xQueueReceive(objects->encoderQueue, &event, QUEUE_TIMEOUT / portTICK_PERIOD_MS))
|
||||
{
|
||||
objects->control->resetTimeout();
|
||||
@@ -486,17 +652,21 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
{
|
||||
case RE_ET_CHANGED:
|
||||
//-- change value --
|
||||
objects->buzzer->beep(1, 25, 10);
|
||||
// increment value
|
||||
if (event.diff < 0)
|
||||
value += menuItems[selectedItem].valueIncrement;
|
||||
else
|
||||
value -= menuItems[selectedItem].valueIncrement;
|
||||
// limit to min/max range
|
||||
if (value > menuItems[selectedItem].valueMax)
|
||||
value = menuItems[selectedItem].valueMax;
|
||||
if (value < menuItems[selectedItem].valueMin)
|
||||
value = menuItems[selectedItem].valueMin;
|
||||
// no need to increment value when item configured to not show value
|
||||
if (menuItems[selectedItem].currentValue != NULL)
|
||||
{
|
||||
objects->buzzer->beep(1, 25, 10);
|
||||
// increment value
|
||||
if (event.diff < 0)
|
||||
value += menuItems[selectedItem].valueIncrement;
|
||||
else
|
||||
value -= menuItems[selectedItem].valueIncrement;
|
||||
// limit to min/max range
|
||||
if (value > menuItems[selectedItem].valueMax)
|
||||
value = menuItems[selectedItem].valueMax;
|
||||
if (value < menuItems[selectedItem].valueMin)
|
||||
value = menuItems[selectedItem].valueMin;
|
||||
}
|
||||
break;
|
||||
case RE_ET_BTN_CLICKED:
|
||||
//-- apply value --
|
||||
@@ -505,12 +675,19 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
menuItems[selectedItem].action(objects, display, value);
|
||||
menuState = MAIN_MENU;
|
||||
break;
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
//-- exit value select to main menu --
|
||||
objects->buzzer->beep(2, 100, 50);
|
||||
ssd1306_clear_screen(display, false);
|
||||
menuState = MAIN_MENU;
|
||||
break;
|
||||
case RE_ET_BTN_PRESSED:
|
||||
case RE_ET_BTN_RELEASED:
|
||||
case RE_ET_BTN_LONG_PRESSED:
|
||||
break;
|
||||
}
|
||||
// reset menu- and control-timeout on any encoder event
|
||||
lastActivity = esp_log_timestamp();
|
||||
objects->control->resetTimeout();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -519,10 +696,9 @@ void handleMenu(display_task_parameters_t * objects, SSD1306_t *display)
|
||||
//--------------------
|
||||
//--- menu timeout ---
|
||||
//--------------------
|
||||
//close menu and switch to IDLE mode when no encoder event within MENU_TIMEOUT
|
||||
//close menu and switch to IDLE mode when no encoder event occured within MENU_TIMEOUT
|
||||
if (esp_log_timestamp() - lastActivity > MENU_TIMEOUT)
|
||||
{
|
||||
objects->buzzer->beep(1, 500, 10);
|
||||
ESP_LOGW(TAG, "TIMEOUT - no activity for more than %ds -> closing menu, switching to IDLE", MENU_TIMEOUT/1000);
|
||||
// reset menu
|
||||
selectedItem = 0;
|
||||
|
||||
Reference in New Issue
Block a user