Description
Hello! I am a student working on an open source e-reader project and I would like to use buttons to navigate through the menu screens. I really want the buttons to turn black when focused and to go to a different screen when pressed. I have gotten the style down, but initializing the buttons does not work for me, it does not change focus on the screen by moving through the group.
What MCU/Processor/Board and compiler are you using?
ESP32, Arduino IDE
What do you want to achieve?
Input device buttons move through the group when pressed, focusing different buttons. Screen is currently not updating the buttons correctly.
What have you tried so far?
I have tried printing the states of the buttons and the pointer to the currently focused button. I can see the state change and the focus address change but the screen does not reflect this. Not sure if its a partial refresh issue or the buttons needing extra callbacks. I am using EEZ studio to design the UI. I had originally let EEZ studio take care of initializing the groups, but now I am testing manually making the groups, it still does not refresh properly.
Code to reproduce
Add the relevant code snippets here.
#define SCREEN_HOR 648
#define SCREEN_VER 480
#define BUFFER_SIZE (SCREEN_HOR * SCREEN_VER / 8)
const int BTN_NEXT = 17; // top left rocker (up)
const int BTN_PREV = 12; // bottom left rocker (down)
int32_t page_index;
void setup()
{
Serial.begin(115200);
/* Initialize screen */
pinMode(EPD_CS_PIN, OUTPUT);
pinMode(EPD_DC_PIN, OUTPUT);
pinMode(EPD_RST_PIN, OUTPUT);
pinMode(EPD_BUSY_PIN, INPUT);
/* Initialize buttons*/
pinMode(BTN_NEXT, INPUT);
pinMode(BTN_PREV, INPUT);
digitalWrite(EPD_CS_PIN, 1);
SPI.begin(EPD_SCK_PIN, 12, EPD_MOSI_PIN, EPD_CS_PIN);
EPD_5IN83_V2_Init();
EPD_5IN83_V2_Clear();
/* Initialize buffer & display */
lv_init();
lv_tick_set_cb(get_millis);
Serial.println("LV init");
uint8_t *buf = (uint8_t*) malloc(BUFFER_SIZE);
lv_display_t *display = lv_display_create(SCREEN_HOR, SCREEN_VER);
lv_display_set_flush_cb(display, screen_flush_cb); // Setting display flush callback
lv_display_set_buffers(display, buf, NULL, BUFFER_SIZE, LV_DISPLAY_RENDER_MODE_PARTIAL);
/* Initialize UI */
ui_init();
Serial.println("UI init");
button_init();
}
void loop()
{
lv_timer_handler(); // LVGL timer
ui_tick(); // EEZ studio timer
sleep(10);
Serial.println("tick");
}
uint32_t get_millis(void)
{
return millis();
}
void sleep(int time)
{
delay(time);
}
void screen_flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
{
Serial.println("Flushing");
if(area->x1 == 0 && area->y1 == 0)
{
EPD_5IN83_V2_SendCommand(0x13); // Tell display we're going to send pixel data
}
// Calculate size of buffer
uint32_t len = (area->x2 - area->x1 + EPD_5IN83_V2_WIDTH * (area->y2 - area->y1)) / 8;
px_map += 8; // Adjusts pixel buffer (first 8 bytes are metadata or smth)
EPD_5IN83_V2_SendData_Invert(px_map, len); // transfer pixel data
Serial.println("Flushed!");
if(lv_display_flush_is_last(display))
{
EPD_5IN83_V2_TurnOnDisplay();
}
lv_display_flush_ready(display); // Tell LVGL the buffer can be flushed and reused
}
void button_init()
{
lv_group_t * g = lv_group_create();
lv_obj_t *button1 = lv_obj_get_child(objects.main, 0);
lv_obj_t *button2 = lv_obj_get_child(objects.main, 1);
lv_group_add_obj(g, button1);
lv_group_add_obj(g, button2);
lv_group_focus_obj(button1);
lv_indev_t * indev = lv_indev_create();
lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);
lv_indev_set_read_cb(indev, keyboard_read);
lv_indev_set_group(indev, g);
}
void keyboard_read(lv_indev_t * indev, lv_indev_data_t * data) {
if(digitalRead(BTN_NEXT) == HIGH)
{
data->key = LV_KEY_NEXT; /* Get the last pressed or released key */
data->state = LV_INDEV_STATE_PRESSED;
}
else if (digitalRead(BTN_PREV) == HIGH)
{
data->key = LV_KEY_PREV;
data->state = LV_INDEV_STATE_PRESSED;
}
else
{
data->state = LV_INDEV_STATE_RELEASED;
}
}
Thank you for reading this post, I am at my wits end for this problem.