Files
2025-01-12 18:08:57 +01:00

140 lines
4.3 KiB
C++

#ifdef INPUTDRIVER_ENCODER_TYPE
#include "input/EncoderInputDriver.h"
#include "Arduino.h"
#include "util/ILog.h"
volatile EncoderInputDriver::EncoderActionType EncoderInputDriver::action = TB_ACTION_NONE;
EncoderInputDriver::EncoderInputDriver(void) {}
void EncoderInputDriver::init(void)
{
// trackball or joystick type encoder with four directions
if (INPUTDRIVER_ENCODER_TYPE == 3) {
#ifdef INPUTDRIVER_ENCODER_LEFT
pinMode(INPUTDRIVER_ENCODER_LEFT, INPUT_PULLUP);
attachInterrupt(INPUTDRIVER_ENCODER_LEFT, intLeftHandler, RISING);
#endif
#ifdef INPUTDRIVER_ENCODER_RIGHT
pinMode(INPUTDRIVER_ENCODER_RIGHT, INPUT_PULLUP);
attachInterrupt(INPUTDRIVER_ENCODER_RIGHT, intRightHandler, RISING);
#endif
#ifdef INPUTDRIVER_ENCODER_UP
pinMode(INPUTDRIVER_ENCODER_UP, INPUT_PULLUP);
attachInterrupt(INPUTDRIVER_ENCODER_UP, intUpHandler, RISING);
#endif
#ifdef INPUTDRIVER_ENCODER_DOWN
pinMode(INPUTDRIVER_ENCODER_DOWN, INPUT_PULLUP);
attachInterrupt(INPUTDRIVER_ENCODER_DOWN, intDownHandler, RISING);
#endif
#ifdef INPUTDRIVER_ENCODER_BTN
pinMode(INPUTDRIVER_ENCODER_BTN, INPUT);
#endif
}
encoder = lv_indev_create();
lv_indev_set_type(encoder, LV_INDEV_TYPE_ENCODER);
lv_indev_set_read_cb(encoder, encoder_read);
if (!inputGroup) {
inputGroup = lv_group_create();
lv_group_set_default(inputGroup);
}
lv_indev_set_group(encoder, inputGroup);
}
void EncoderInputDriver::encoder_read(lv_indev_t *indev, lv_indev_data_t *data)
{
// encoder w/o interrupts but read GPIOs directly
if (INPUTDRIVER_ENCODER_TYPE == 1) {
#ifdef INPUTDRIVER_ENCODER_LEFT
if (digitalRead(INPUTDRIVER_ENCODER_LEFT))
data->enc_diff = -1;
#endif
#ifdef INPUTDRIVER_ENCODER_RIGHT
if (digitalRead(INPUTDRIVER_ENCODER_RIGHT))
data->enc_diff = 1;
#endif
#ifdef INPUTDRIVER_ENCODER_BTN
// FIXME: need same logix as below to trigger LONG_PRESSED events
if (!digitalRead(INPUTDRIVER_ENCODER_BTN)) {
data->key = LV_KEY_ENTER;
data->state = LV_INDEV_STATE_PRESSED;
}
#endif
}
// trackball/joystick with additional up/down inputs to control sliders
else if (INPUTDRIVER_ENCODER_TYPE == 3) {
static uint32_t prevkey = 0;
static uint32_t lastPressed = millis();
data->key = 0;
data->enc_diff = 0;
data->state = LV_INDEV_STATE_RELEASED;
#ifdef INPUTDRIVER_ENCODER_BTN
if (action == TB_ACTION_NONE) {
if (!digitalRead(INPUTDRIVER_ENCODER_BTN)) {
action = TB_ACTION_PRESSED;
}
}
#endif
// slow down repeating key to max. four events per second
// the button is an exception for LONG_PRESSED monitoring
if (action != TB_ACTION_NONE && (action == TB_ACTION_PRESSED || millis() > lastPressed + 250)) {
if (action == TB_ACTION_PRESSED) {
data->key = LV_KEY_ENTER;
data->state = LV_INDEV_STATE_PRESSED;
} else if (action == TB_ACTION_UP) {
data->enc_diff = -1;
} else if (action == TB_ACTION_DOWN) {
data->enc_diff = 1;
} else if (action == TB_ACTION_LEFT) {
data->key = LV_KEY_DOWN; // slider widget reacts on UP/DOWN
data->state = LV_INDEV_STATE_PRESSED;
} else if (action == TB_ACTION_RIGHT) {
data->key = LV_KEY_UP; // slider widget reacts on UP/DOWN
data->state = LV_INDEV_STATE_PRESSED;
}
lastPressed = millis();
prevkey = data->key;
action = TB_ACTION_NONE;
} else {
// this logic is required for LONG_PRESSED event, see lv_indev.c
if (prevkey != 0) {
data->state = LV_INDEV_STATE_RELEASED;
data->key = prevkey;
prevkey = 0;
}
}
}
}
void EncoderInputDriver::intPressHandler()
{
action = TB_ACTION_PRESSED;
}
void EncoderInputDriver::intDownHandler()
{
action = TB_ACTION_DOWN;
}
void EncoderInputDriver::intUpHandler()
{
action = TB_ACTION_UP;
}
void EncoderInputDriver::intLeftHandler()
{
action = TB_ACTION_LEFT;
}
void EncoderInputDriver::intRightHandler()
{
action = TB_ACTION_RIGHT;
}
#endif