feat: add list and started user input manager

This commit is contained in:
Fritz Heiden 2025-05-25 13:12:08 +02:00
parent 84832271ce
commit 6a104cea00
6 changed files with 214 additions and 13 deletions

View File

@ -57,7 +57,7 @@ namespace Encoder
void handlePress() void handlePress()
{ {
Serial.println("Encoder pressed"); //Serial.println("Encoder pressed");
for (OnButtonPressCallback callback : onButtonPressCallbacks) { for (OnButtonPressCallback callback : onButtonPressCallbacks) {
callback(); callback();
} }
@ -65,7 +65,7 @@ namespace Encoder
void handleRelease() void handleRelease()
{ {
Serial.println("Encoder released"); //Serial.println("Encoder released");
for (OnButtonReleaseCallback callback : onButtonReleaseCallbacks) { for (OnButtonReleaseCallback callback : onButtonReleaseCallbacks) {
callback(); callback();
} }
@ -73,8 +73,8 @@ namespace Encoder
void handleRotate(int8_t rotation) void handleRotate(int8_t rotation)
{ {
Serial.print("Encoder rotated by "); //Serial.print("Encoder rotated by ");
Serial.println(rotation); //Serial.println(rotation);
for (OnRotateCallback callback : onRotateCallbacks) { for (OnRotateCallback callback : onRotateCallbacks) {
callback(rotation); callback(rotation);
} }

View File

@ -0,0 +1,81 @@
#include <Arduino.h>
#include <input/encoder.hpp>
#include <input/user_input_manager.hpp>
#include <vector>
#include <queue>
#include <map>
namespace UserInputManager
{
using std::map;
using std::vector;
using std::queue;
void handleEncoderButtonRelease();
void handleEncoderButtonPress();
void handleEncoderRotate(int);
void pushEvent(InputEvent event);
map<String, queue<InputEvent>> input_event_queues;
void init()
{
Encoder::onButtonRelease(handleEncoderButtonRelease);
Encoder::onButtonPress(handleEncoderButtonPress);
Encoder::onRotate(handleEncoderRotate);
}
void handleEncoderButtonPress()
{
pushEvent(EncoderButtonPress);
}
void handleEncoderButtonRelease()
{
pushEvent(EncoderButtonRelease);
}
void handleEncoderRotate(int rotation)
{
if (rotation > 0)
{
pushEvent(EncoderRotateRight);
}
else
{
pushEvent(EncoderRotateLeft);
}
}
void pushEvent(InputEvent event)
{
Serial.println("pushing new event " + String(event));
for (auto &queue : input_event_queues)
{
Serial.println("pushing event to queue " + queue.first + " (" + String(queue.second.size()) + ")");
queue.second.push(event);
}
}
InputEvent getNextEvent(String name)
{
queue<InputEvent> events = input_event_queues.at(name);
if (events.empty())
{
return InputEvent::None;
}
Serial.print("getting next event (" + String(events.size()) + "->");
InputEvent event = events.front();
events.pop();
Serial.println(String(events.size()) + ")");
return event;
}
void registerForEvents(String name)
{
queue<InputEvent> events = {};
input_event_queues[name] = events;
}
}

View File

@ -0,0 +1,24 @@
#ifndef DRUMZ_USER_INPUT_MANAGER_HPP
#define DRUMZ_USER_INPUT_MANAGER_HPP
#include <Arduino.h>
#include <vector>
namespace UserInputManager
{
using std::vector;
enum InputEvent
{
None,
EncoderButtonPress,
EncoderButtonRelease,
EncoderRotateLeft,
EncoderRotateRight,
};
void init();
InputEvent getNextEvent(String name);
void registerForEvents(String name);
}
#endif // DRUMZ_USER_INPUT_MANAGER_HPP

View File

@ -13,6 +13,7 @@
#include <ui/display.hpp> #include <ui/display.hpp>
#include <input/encoder.hpp> #include <input/encoder.hpp>
#include <input/pad_reader.hpp> #include <input/pad_reader.hpp>
#include <input/user_input_manager.hpp>
#include <audio/tone_generator.hpp> #include <audio/tone_generator.hpp>
const int ONBOARD_LED_PIN = 2; const int ONBOARD_LED_PIN = 2;
@ -26,6 +27,7 @@ void setup()
Encoder::init(); Encoder::init();
Display::init(); Display::init();
ToneGenerator::init(); ToneGenerator::init();
UserInputManager::init();
Serial.println("setup complete"); Serial.println("setup complete");
} }

View File

@ -5,6 +5,9 @@
#include <input/encoder.hpp> #include <input/encoder.hpp>
#include <ui/views/main_view.hpp> #include <ui/views/main_view.hpp>
#include <input/user_input_manager.hpp>
#include <vector>
#ifndef SCREEN_WIDTH #ifndef SCREEN_WIDTH
#define SCREEN_WIDTH 320 #define SCREEN_WIDTH 320
@ -17,16 +20,24 @@
#define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8)) #define DRAW_BUF_SIZE (SCREEN_WIDTH * SCREEN_HEIGHT / 10 * (LV_COLOR_DEPTH / 8))
namespace Display namespace Display
{ {
using std::vector;
using UserInputManager::InputEvent;
const uint8_t MAIN_VIEW = 1; const uint8_t MAIN_VIEW = 1;
const String USER_INPUT_HANDLE = "display";
uint32_t draw_buf[DRAW_BUF_SIZE / 4]; uint32_t draw_buf[DRAW_BUF_SIZE / 4];
uint32_t getTime(); uint32_t getTime();
void handleLvglLogs(lv_log_level_t level, const char *buf); void handleLvglLogs(lv_log_level_t level, const char *buf);
void handleUpdateValues(lv_timer_t *timer); void handleUpdateValues(lv_timer_t *timer);
void handleReadUserInput(lv_indev_t *indev, lv_indev_data_t *data);
void setCurrentView(uint8_t view); void setCurrentView(uint8_t view);
lv_timer_t *update_values_timer; lv_timer_t *update_values_timer;
lv_indev_t *indev;
InputEvent last_input_event;
uint8_t current_view = 0; uint8_t current_view = 0;
void init() void init()
@ -42,7 +53,15 @@ namespace Display
display = lv_tft_espi_create(SCREEN_HEIGHT, SCREEN_WIDTH, draw_buf, sizeof(draw_buf)); display = lv_tft_espi_create(SCREEN_HEIGHT, SCREEN_WIDTH, draw_buf, sizeof(draw_buf));
lv_display_set_rotation(display, LV_DISPLAY_ROTATION_90); lv_display_set_rotation(display, LV_DISPLAY_ROTATION_90);
UserInputManager::registerForEvents(USER_INPUT_HANDLE);
indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
lv_indev_set_read_cb(indev, handleReadUserInput);
setCurrentView(MAIN_VIEW); setCurrentView(MAIN_VIEW);
lv_group_t *group = lv_group_create();
lv_group_add_obj(group, lv_screen_active());
lv_indev_set_group(indev, group);
} }
void update() void update()
@ -60,14 +79,16 @@ namespace Display
return esp_timer_get_time() / 1000; return esp_timer_get_time() / 1000;
} }
void setCurrentView(uint8_t view) { void setCurrentView(uint8_t view)
{
current_view = view; current_view = view;
lv_obj_t *parent = lv_screen_active(); lv_obj_t *parent = lv_screen_active();
lv_obj_clean(parent); lv_obj_clean(parent);
switch(view) { switch (view)
case MAIN_VIEW: {
MainView::render(parent); case MAIN_VIEW:
break; MainView::render(parent);
break;
} }
} }
@ -80,4 +101,48 @@ namespace Display
break; break;
} }
} }
void handleReadUserInput(lv_indev_t *indev, lv_indev_data_t *data)
{
//switch(last_input_event) {
// case InputEvent::EncoderRotateLeft:
// data->key = LV_KEY_PREV;
// data->state = LV_INDEV_STATE_RELEASED;
// last_input_event = InputEvent::None;
// return;
// case InputEvent::EncoderRotateRight:
// data->key = LV_KEY_NEXT;
// data->state = LV_INDEV_STATE_RELEASED;
// last_input_event = InputEvent::None;
// return;
//}
InputEvent event = UserInputManager::getNextEvent(USER_INPUT_HANDLE);
if (event != InputEvent::None) {
Serial.println("processing input event " + String(event));
}
//switch (event)
//{
//case InputEvent::EncoderButtonRelease:
// data->key = LV_KEY_ENTER;
// data->state = LV_INDEV_STATE_RELEASED;
// Serial.println("indev event EncoderButtonRelease");
// break;
//case InputEvent::EncoderButtonPress:
// data->key = LV_KEY_ENTER;
// data->state = LV_INDEV_STATE_PR;
// Serial.println("indev event EncoderButtonPress");
// break;
//case InputEvent::EncoderRotateLeft:
// data->key = LV_KEY_PREV;
// data->state = LV_INDEV_STATE_PRESSED;
// Serial.println("indev event EncoderRotateLeft");
// break;
//case InputEvent::EncoderRotateRight:
// data->key = LV_KEY_NEXT;
// data->state = LV_INDEV_STATE_PRESSED;
// Serial.println("indev event EncoderRotateRight");
// break;
//}
//last_input_event = event;
}
} }

View File

@ -4,18 +4,47 @@
#include <input/encoder.hpp> #include <input/encoder.hpp>
#include <audio/tone_generator.hpp> #include <audio/tone_generator.hpp>
#include <vector>
namespace MainView namespace MainView
{ {
using std::vector;
void handleEnterButton(); void handleEnterButton();
lv_obj_t *label; lv_obj_t *label;
lv_obj_t *list;
String label_text; String label_text;
int frequency = ToneGenerator::getFrequency(); int frequency = ToneGenerator::getFrequency();
void render(lv_obj_t *parent) void render(lv_obj_t *parent)
{ {
label = lv_label_create(lv_screen_active()); list = lv_list_create(parent);
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); lv_obj_set_width(list, lv_pct(100));
lv_obj_set_height(list, lv_pct(100));
lv_obj_center(list);
vector<String> items = {
"Michael Jackson",
"The Beatles",
"Rolling Stones",
"Led Zeppelin",
"Queen",
"Prince",
"The Who",
"Nirvana",
"Pink Floyd",
"The Clash"
};
lv_obj_t *btn;
for (String item : items)
{
btn = lv_list_add_btn(list, NULL, item.c_str());
}
//label = lv_label_create(lv_screen_active());
//lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
label_text = "Main view initialized."; label_text = "Main view initialized.";
Encoder::onButtonPress(handleEnterButton); Encoder::onButtonPress(handleEnterButton);