Skip to content

Commit

Permalink
Merge branch 'main' into fix/timer
Browse files Browse the repository at this point in the history
  • Loading branch information
finger563 committed Nov 14, 2023
2 parents cbe918c + 3f13896 commit 83311f9
Show file tree
Hide file tree
Showing 107 changed files with 1,936 additions and 176 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ jobs:
target: esp32s3
- path: 'components/state_machine/example'
target: esp32
- path: 'components/t_keyboard/example'
target: esp32s3
- path: 'components/tabulate/example'
target: esp32
- path: 'components/task/example'
Expand Down
13 changes: 12 additions & 1 deletion components/display_drivers/include/ili9341.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class Ili9341 {
{0xC1, {0x11}, 1},
{0xC5, {0x35, 0x3E}, 2},
{0xC7, {0xBE}, 1},
{0x36, {0x28}, 1},
{0x36, {0x28}, 1}, // madctl
{0x3A, {0x55}, 1},
{0xB1, {0x00, 0x1B}, 2},
{0xF2, {0x08}, 1},
Expand All @@ -91,6 +91,17 @@ class Ili9341 {
{0, {0}, 0xff},
};

// NOTE: these configurations operates on the MADCTL command / register
if (config.mirror_x) {
ili_init_cmds[10].data[0] |= LCD_CMD_MX_BIT;
}
if (config.mirror_y) {
ili_init_cmds[10].data[0] |= LCD_CMD_MY_BIT;
}
if (config.swap_xy) {
ili_init_cmds[10].data[0] |= LCD_CMD_MV_BIT;
}

// send the init commands
send_commands(ili_init_cmds);

Expand Down
124 changes: 124 additions & 0 deletions components/input_drivers/include/encoder_input.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#pragma once

#include <algorithm>
#include <functional>

#include "lvgl.h"
#include "sdkconfig.h"

#include "logger.hpp"

namespace espp {
/**
* @brief Light wrapper around LVGL input device driver, specifically
* designed for encoders with optional home buttons.
*/
class EncoderInput {
public:
typedef std::function<void(int *enc_diff, bool button_pressed)> read_fn;

/**
* @brief Configuration structure, containing the read function for the
* encoder itself.
*/
struct Config {
read_fn read; /**< Input function for the encoder and button itself. */
Logger::Verbosity log_level{
Logger::Verbosity::WARN}; /**< Log verbosity for the input driver. */
};

/**
* @brief Initialize and register the input drivers associated with the
* encoder.
* @param config Configuration structure for the EncoderInput.
*/
EncoderInput(const Config &config)
: read_(config.read)
logger_({.tag = "EncoderInput", .level = config.log_level}) {
init();
}

/**
* @brief Unregister the input drivers associated with the Encoder.
*/
~EncoderInput() {
if (indev_encoder_) {
lv_indev_delete(indev_encoder_);
}
if (indev_button_) {
lv_indev_delete(indev_button_);
}
}

/**
* @brief Get the input device driver associated with the encoder.
* @return The input device driver associated with the encoder.
*/
lv_indev_t *get_encoder_input_device() { return indev_encoder_; }

/**
* @brief Get the input device driver associated with the button.
* @return The input device driver associated with the button.
*/
lv_indev_t *get_button_input_device() { return indev_button_; }

protected:
static void encoder_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
EncoderInput *ei = (EncoderInput *)drv->user_data;
if (ei) {
ei->encoder_read_impl(data);
}
}

void encoder_read_impl(lv_indev_data_t *data) {
int enc_diff;
bool button_pressed;
if (!read_) {
logger_.error("Invalid read function!");
return;
}
read_(&enc_diff, &button_pressed);
if (button_pressed) {
button_pressed_ = true;
}
data->state = (button_pressed) ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
data->enc_diff = enc_diff;
}

static void button_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
EncoderInput *ei = (EncoderInput *)drv->user_data;
if (ei) {
ei->home_button_read_impl(data);
}
}

void button_read_impl(lv_indev_data_t *data) {
data->state = button_pressed_ ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED;
}

void init() {
using namespace std::placeholders;
logger_.info("Add encoder input device to LVGL");
lv_indev_drv_init(&indev_drv_enc_);
indev_drv_enc_.type = LV_INDEV_TYPE_POINTER;
indev_drv_enc_.read_cb = &EncoderInput::encoder_read;
indev_drv_enc_.user_data = (void *)this;
indev_encoder_ = lv_indev_drv_register(&indev_drv_enc_);

logger_.info("Add button input to LVGL");
lv_indev_drv_init(&indev_drv_btn_);
indev_drv_btn_.type = LV_INDEV_TYPE_BUTTON;
indev_drv_btn_.read_cb = &EncoderInput::button_read;
indev_drv_btn_.user_data = (void *)this;
indev_button_ = lv_indev_drv_register(&indev_drv_btn_);
}

encoder_read_fn encoder_read_;
std::atomic<bool> button_pressed_{false};
lv_indev_drv_t indev_drv_enc_;
lv_indev_t *indev_encoder_;
lv_indev_drv_t indev_drv_btn_;
lv_indev_t *indev_button_;
Logger logger_;
};
} // namespace espp
108 changes: 108 additions & 0 deletions components/input_drivers/include/keypad_input.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#pragma once

#include <algorithm>
#include <functional>

#include "lvgl.h"
#include "sdkconfig.h"

#include "logger.hpp"

namespace espp {
/**
* @brief Light wrapper around LVGL input device driver, specifically
* designed for keypads.
*/
class KeypadInput {
public:
typedef std::function<void(bool *up, bool *down, bool *left, bool *right, bool *enter, bool *escape)> read_fn;

/**
* @brief Configuration structure, containing the read function for the
* keypad itself.
*/
struct Config {
read_fn read; /**< Input function for the keypad. */
Logger::Verbosity log_level{
Logger::Verbosity::WARN}; /**< Log verbosity for the input driver. */
};

/**
* @brief Initialize and register the input drivers associated with the
* keypad.
* @param config Configuration structure for the KeypadInput.
*/
KeypadInput(const Config &config)
: read_(config.read),
logger_({.tag = "KeypadInput", .level = config.log_level}) {
init();
}

/**
* @brief Unregister the input drivers associated with the Keypad.
*/
~KeypadInput() {
if (indev_keypad_) {
lv_indev_delete(indev_keypad_);
}
}

/**
* @brief Get the input device driver associated with the keypad.
* @return The input device driver associated with the keypad.
*/
lv_indev_t *get_input_device() { return indev_keypad_; }

protected:
static void keypad_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
KeypadInput *ki = (KeypadInput *)drv->user_data;
if (ki) {
ki->keypad_read_impl(data);
}
}

void keypad_read_impl(lv_indev_data_t *data) {
if (!read_) {
logger_.error("Invalid read function!");
return;
}
logger_.info("Reading keypad...");
bool up,down,left,right,enter,escape;
read_(&up, &down, &left, &right, &enter, &escape);
data->state = LV_INDEV_STATE_PRESSED;
if (escape) {
data->key = LV_KEY_ESC;
} else if (enter) {
data->key = LV_KEY_ENTER;
} else if (up) {
data->key = LV_KEY_UP;
} else if (down) {
data->key = LV_KEY_DOWN;
} else if (left) {
data->key = LV_KEY_LEFT;
} else if (right) {
data->key = LV_KEY_RIGHT;
} else {
data->state = LV_INDEV_STATE_RELEASED;
}
logger_.debug("Keypad state: up: {}, down: {}, left: {}, right: {}, enter: {}, escape: {}",
up, down, left, right, enter, escape);
logger_.debug("Keypad data: state: {}, key: {}", (int)data->state, (int)data->key);
}

void init() {
using namespace std::placeholders;
logger_.info("Add keypad input device to LVGL");
lv_indev_drv_init(&indev_drv_keypad_);
indev_drv_keypad_.type = LV_INDEV_TYPE_KEYPAD;
indev_drv_keypad_.read_cb = &KeypadInput::keypad_read;
indev_drv_keypad_.user_data = (void *)this;
indev_keypad_ = lv_indev_drv_register(&indev_drv_keypad_);
}

read_fn read_;
lv_indev_drv_t indev_drv_keypad_;
lv_indev_t *indev_keypad_;
Logger logger_;
};
} // namespace espp
12 changes: 12 additions & 0 deletions components/input_drivers/include/touchpad_input.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ class TouchpadInput {
}
}

/**
* @brief Get a pointer to the LVGL input device driver for the touchpad.
* @return Pointer to the LVGL input device driver for the touchpad.
*/
lv_indev_t *get_touchpad_input_device() { return indev_touchpad_; }

/**
* @brief Get a pointer to the LVGL input device driver for the home button.
* @return Pointer to the LVGL input device driver for the home button.
*/
lv_indev_t *get_home_button_input_device() { return indev_button_; }

protected:
static void touchpad_read(lv_indev_drv_t *drv, lv_indev_data_t *data) {
TouchpadInput *tpi = (TouchpadInput *)drv->user_data;
Expand Down
2 changes: 1 addition & 1 deletion components/lvgl
Submodule lvgl updated 231 files
4 changes: 4 additions & 0 deletions components/t_keyboard/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
idf_component_register(
INCLUDE_DIRS "include"
REQUIRES "logger"
)
21 changes: 21 additions & 0 deletions components/t_keyboard/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# add the component directories that we want to use
set(EXTRA_COMPONENT_DIRS
"../../../components/"
)

set(
COMPONENTS
"main esptool_py driver task t_keyboard i2c"
CACHE STRING
"List of components to include"
)

project(t_keyboard_example)

set(CMAKE_CXX_STANDARD 20)
28 changes: 28 additions & 0 deletions components/t_keyboard/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# LilyGo T-Keyboard Example

This example shows how to get the user input (key presses) from the LilyGo
T-Keyboard. It is designed to run on a LilyGo T-Deck.

## How to use example

### Hardware Required

LilyGo T-Deck (or any other board which has a LilyGo T-Keyboard connected)

### Build and Flash

Build the project and flash it to the board, then run monitor tool to view serial output:

```
idf.py -p PORT flash monitor
```

(Replace PORT with the name of the serial port to use.)

(To exit the serial monitor, type ``Ctrl-]``.)

See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.

## Example Output

<img width="318" alt="CleanShot 2023-11-10 at 13 17 53@2x" src="https://github.com/esp-cpp/espp/assets/213467/68b89daa-4686-4d29-8a73-400b4d91617d">
2 changes: 2 additions & 0 deletions components/t_keyboard/example/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
idf_component_register(SRC_DIRS "."
INCLUDE_DIRS ".")
Loading

0 comments on commit 83311f9

Please sign in to comment.