diff --git a/components/insa/src/ui/MainMenu.cpp b/components/insa/src/ui/MainMenu.cpp index e1cb098..55ef6dc 100644 --- a/components/insa/src/ui/MainMenu.cpp +++ b/components/insa/src/ui/MainMenu.cpp @@ -9,12 +9,12 @@ namespace MainMenuItem constexpr uint8_t LIGHT = 0; constexpr uint8_t EXTERNAL_DEVICES = 1; constexpr uint8_t SETTINGS = 2; -} +} // namespace MainMenuItem MainMenu::MainMenu(menu_options_t *options) : Menu(options), m_options(options) { addText(MainMenuItem::LIGHT, "Lichtsteuerung"); - addText(MainMenuItem::EXTERNAL_DEVICES, "externe Geraete"); + addText(MainMenuItem::EXTERNAL_DEVICES, "Externe Geraete"); addText(MainMenuItem::SETTINGS, "Einstellungen"); } diff --git a/components/insa/src/ui/SplashScreen.cpp b/components/insa/src/ui/SplashScreen.cpp index ea7a58e..ad18bfd 100644 --- a/components/insa/src/ui/SplashScreen.cpp +++ b/components/insa/src/ui/SplashScreen.cpp @@ -2,8 +2,7 @@ #include "ui/MainMenu.h" -#ifdef ESP32 -#else +#ifndef ESP32 #include #include #endif @@ -17,7 +16,11 @@ SplashScreen::SplashScreen(menu_options_t *options) : Widget(options->u8g2), m_o void SplashScreen::update(const uint64_t dt) { counter += dt; +#ifndef ESP32 if (counter > 200000) +#else + if (counter > 10) +#endif { counter = 0; if (m_options && m_options->setScreen) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 76d489c..1b1c76c 100755 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,8 +1,13 @@ idf_component_register(SRCS "main.cpp" "app_task.cpp" + "button_handling.c" + "hal/u8g2_esp32_hal.c" INCLUDE_DIRS "." REQUIRES insa ruth + u8g2 + driver + esp_timer ) diff --git a/main/app_task.cpp b/main/app_task.cpp index e17314f..d4e6231 100644 --- a/main/app_task.cpp +++ b/main/app_task.cpp @@ -1,7 +1,154 @@ #include "app_task.h" + +#include "esp_log.h" +#include "esp_timer.h" +#include "hal/u8g2_esp32_hal.h" +#include "string" +#include "u8g2.h" + +#include "button_handling.h" #include "ui/SplashScreen.h" +#define PIN_SDA GPIO_NUM_35 +#define PIN_SCL GPIO_NUM_36 +#define PIN_RST GPIO_NUM_NC + +static const char *TAG = "app_task"; + +u8g2_t u8g2; +uint8_t last_value = 0; +menu_options_t options; +uint8_t received_signal; + +std::shared_ptr m_widget; +std::vector> m_history; + +extern QueueHandle_t buttonQueue; + +static void setup_screen(void) +{ + u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT; + u8g2_esp32_hal.bus.i2c.sda = PIN_SDA; + u8g2_esp32_hal.bus.i2c.scl = PIN_SCL; + u8g2_esp32_hal.reset = PIN_RST; + u8g2_esp32_hal_init(u8g2_esp32_hal); + + u8g2_Setup_sh1106_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8g2_esp32_i2c_byte_cb, u8g2_esp32_gpio_and_delay_cb); + u8x8_SetI2CAddress(&u8g2.u8x8, 0x3C * 2); + + ESP_LOGI(TAG, "u8g2_InitDisplay"); + u8g2_InitDisplay(&u8g2); + + ESP_LOGI(TAG, "u8g2_SetPowerSave"); + u8g2_SetPowerSave(&u8g2, 0); +} + +void setScreen(const std::shared_ptr &screen) +{ + if (screen != nullptr) + { + m_widget = screen; + m_history.clear(); + m_history.emplace_back(m_widget); + } +} + +void pushScreen(const std::shared_ptr &screen) +{ + if (screen != nullptr) + { + m_widget = screen; + m_history.emplace_back(m_widget); + } +} + +void popScreen() +{ + if (m_history.size() >= 2) + { + m_history.pop_back(); + m_widget = m_history.back(); + } +} + +static void init_ui(void) +{ + options = { + .u8g2 = &u8g2, + .setScreen = [](const std::shared_ptr &screen) { setScreen(screen); }, + .pushScreen = [](const std::shared_ptr &screen) { pushScreen(screen); }, + .popScreen = []() { popScreen(); }, + .onButtonClicked = nullptr, + .persistence = nullptr, + }; + m_widget = std::make_shared(&options); +} + +static void handle_button(uint8_t button) +{ + if (m_widget) + { + switch (button) + { + case 1: + m_widget->onButtonClicked(ButtonType::UP); + break; + + case 3: + m_widget->onButtonClicked(ButtonType::LEFT); + break; + + case 5: + m_widget->onButtonClicked(ButtonType::RIGHT); + break; + + case 6: + m_widget->onButtonClicked(ButtonType::DOWN); + break; + + case 16: + m_widget->onButtonClicked(ButtonType::BACK); + break; + + case 18: + m_widget->onButtonClicked(ButtonType::SELECT); + break; + + default: + ESP_LOGI(TAG, "Unhandled button: %u", button); + break; + } + } +} + void app_task(void *args) { - /// + setup_screen(); + setup_buttons(); + init_ui(); + + while (true) + { + u8g2_ClearBuffer(&u8g2); + + auto oldTime = esp_timer_get_time(); + if (m_widget != nullptr) + { + auto currentTime = esp_timer_get_time(); + auto delta = currentTime - oldTime; + oldTime = currentTime; + + m_widget->update(delta); + m_widget->render(); + } + + u8g2_SendBuffer(&u8g2); + + if (xQueueReceive(buttonQueue, &received_signal, pdMS_TO_TICKS(10)) == pdTRUE) + { + handle_button(received_signal); + } + } + + cleanup_buttons(); } \ No newline at end of file diff --git a/main/button_handling.c b/main/button_handling.c index 76dbad5..2616552 100644 --- a/main/button_handling.c +++ b/main/button_handling.c @@ -17,43 +17,71 @@ static const char *TAG = "button_handling"; -#define DEBOUNCE_TIME_MS (500) - +#define DEBOUNCE_TIME_MS (50) // Shorter debounce time for timer-based debouncing #define BUTTON_QUEUE_LENGTH 5 #define BUTTON_QUEUE_ITEM_SIZE sizeof(uint8_t) -#define WLED_GPIO GPIO_NUM_47 -#define WLED_RMT_CHANNEL RMT_CHANNEL_0 -#define WLED_RESOLUTION_HZ (10000000) -#define WLED_ON_DURATION_MS (100) -#define NUM_LEDS (1) - const uint8_t pins[] = {BUTTON_DOWN, BUTTON_UP, BUTTON_LEFT, BUTTON_RIGHT, BUTTON_SELECT, BUTTON_BACK}; QueueHandle_t buttonQueue = NULL; -volatile int64_t last_interrupt_time = 0; -void IRAM_ATTR button_isr_handler(void *arg) +// Structure for button state +typedef struct { - int64_t now = esp_timer_get_time(); - if ((now - last_interrupt_time) > (DEBOUNCE_TIME_MS * 1000)) + uint8_t pin; + esp_timer_handle_t timer; + bool is_pressed; + int64_t last_interrupt_time; +} button_state_t; + +// Array for button states +static button_state_t button_states[6]; + +// Timer callback for debouncing +static void button_timer_callback(void *arg) +{ + button_state_t *button = (button_state_t *)arg; + + // Check current GPIO state + int level = gpio_get_level(button->pin); + + // Button is pressed (LOW) and was not pressed before + if (level == 0 && !button->is_pressed) { - last_interrupt_time = now; + button->is_pressed = true; - uintptr_t pin_value = (uintptr_t)arg; - uint8_t press_signal = (uint8_t)pin_value; - BaseType_t higherPriorityTaskWoken = pdFALSE; + // Send button press to queue + uint8_t press_signal = button->pin; + xQueueSend(buttonQueue, &press_signal, 0); - xQueueSendFromISR(buttonQueue, &press_signal, &higherPriorityTaskWoken); - - if (higherPriorityTaskWoken) - { - portYIELD_FROM_ISR(); - } + ESP_LOGD(TAG, "Button %d pressed", button->pin); + } + // Button is released (HIGH) and was pressed before + else if (level == 1 && button->is_pressed) + { + button->is_pressed = false; + ESP_LOGD(TAG, "Button %d released", button->pin); } } -void setupButtons(void) +// ISR Handler - only starts the timer +void IRAM_ATTR button_isr_handler(void *arg) +{ + button_state_t *button = (button_state_t *)arg; + int64_t now = esp_timer_get_time(); + + // Simple time-based debouncing in ISR + if ((now - button->last_interrupt_time) > (DEBOUNCE_TIME_MS * 1000)) + { + button->last_interrupt_time = now; + + // Start/restart the timer + esp_timer_stop(button->timer); + esp_timer_start_once(button->timer, DEBOUNCE_TIME_MS * 1000); + } +} + +void setup_buttons(void) { buttonQueue = xQueueCreate(BUTTON_QUEUE_LENGTH, BUTTON_QUEUE_ITEM_SIZE); if (buttonQueue == NULL) @@ -69,24 +97,61 @@ void setupButtons(void) ESP_LOGE(TAG, "Error in gpio_install_isr_service: %s", esp_err_to_name(isr_service_err)); } + // Timer configuration + esp_timer_create_args_t timer_args = {.callback = button_timer_callback, .name = "button_debounce"}; + for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) { const uint8_t pin = pins[i]; - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_NEGEDGE; - io_conf.pin_bit_mask = (1ULL << pin); - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + + // Initialize button state + button_states[i].pin = pin; + button_states[i].is_pressed = false; + button_states[i].last_interrupt_time = 0; + + // Create timer for this button + timer_args.arg = &button_states[i]; + esp_err_t timer_err = esp_timer_create(&timer_args, &button_states[i].timer); + if (timer_err != ESP_OK) + { + ESP_LOGE(TAG, "Failed to create timer for button %d: %s", pin, esp_err_to_name(timer_err)); + continue; + } + + // GPIO configuration + gpio_config_t io_conf = {.intr_type = GPIO_INTR_ANYEDGE, // React to both edges + .pin_bit_mask = (1ULL << pin), + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE}; gpio_config(&io_conf); - uintptr_t pin_as_arg = (uintptr_t)pin; - esp_err_t add_isr_err = gpio_isr_handler_add(pin, button_isr_handler, (void *)pin_as_arg); + // Add ISR handler + esp_err_t add_isr_err = gpio_isr_handler_add(pin, button_isr_handler, &button_states[i]); if (add_isr_err != ESP_OK) { ESP_LOGE(TAG, "Error in gpio_isr_handler_add: %s", esp_err_to_name(add_isr_err)); } - ESP_LOGI(TAG, "Button interrupt configured for GPIO %d", pin); + ESP_LOGD(TAG, "Button interrupt configured for GPIO %d", pin); + } +} + +// Cleanup function (optional) +void cleanup_buttons(void) +{ + for (int i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) + { + if (button_states[i].timer != NULL) + { + esp_timer_stop(button_states[i].timer); + esp_timer_delete(button_states[i].timer); + } + gpio_isr_handler_remove(button_states[i].pin); + } + + if (buttonQueue != NULL) + { + vQueueDelete(buttonQueue); } } diff --git a/main/button_handling.h b/main/button_handling.h index 918a65c..620048a 100644 --- a/main/button_handling.h +++ b/main/button_handling.h @@ -4,7 +4,8 @@ extern "C" { #endif - void setupButtons(void); + void setup_buttons(void); + void cleanup_buttons(void); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/main/hal/u8g2_esp32_hal.c b/main/hal/u8g2_esp32_hal.c new file mode 100644 index 0000000..1917a49 --- /dev/null +++ b/main/hal/u8g2_esp32_hal.c @@ -0,0 +1,262 @@ +#include +#include + +#include "esp_log.h" +#include "sdkconfig.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "u8g2_esp32_hal.h" + +static const char* TAG = "u8g2_hal"; +static const unsigned int I2C_TIMEOUT_MS = 1000; + +static spi_device_handle_t handle_spi; // SPI handle. +static i2c_cmd_handle_t handle_i2c; // I2C handle. +static u8g2_esp32_hal_t u8g2_esp32_hal; // HAL state data. + +#define HOST SPI2_HOST + +#undef ESP_ERROR_CHECK +#define ESP_ERROR_CHECK(x) \ + do { \ + esp_err_t rc = (x); \ + if (rc != ESP_OK) { \ + ESP_LOGE("err", "esp_err_t = %d", rc); \ + assert(0 && #x); \ + } \ + } while (0); + +/* + * Initialze the ESP32 HAL. + */ +void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) { + u8g2_esp32_hal = u8g2_esp32_hal_param; +} // u8g2_esp32_hal_init + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is + * invoked to handle SPI communications. + */ +uint8_t u8g2_esp32_spi_byte_cb(u8x8_t* u8x8, + uint8_t msg, + uint8_t arg_int, + void* arg_ptr) { + ESP_LOGD(TAG, "spi_byte_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", + msg, arg_int, arg_ptr); + switch (msg) { + case U8X8_MSG_BYTE_SET_DC: + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.dc, arg_int); + } + break; + + case U8X8_MSG_BYTE_INIT: { + if (u8g2_esp32_hal.bus.spi.clk == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.bus.spi.mosi == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.bus.spi.cs == U8G2_ESP32_HAL_UNDEFINED) { + break; + } + + spi_bus_config_t bus_config; + memset(&bus_config, 0, sizeof(spi_bus_config_t)); + bus_config.sclk_io_num = u8g2_esp32_hal.bus.spi.clk; // CLK + bus_config.mosi_io_num = u8g2_esp32_hal.bus.spi.mosi; // MOSI + bus_config.miso_io_num = GPIO_NUM_NC; // MISO + bus_config.quadwp_io_num = GPIO_NUM_NC; // Not used + bus_config.quadhd_io_num = GPIO_NUM_NC; // Not used + // ESP_LOGI(TAG, "... Initializing bus."); + ESP_ERROR_CHECK(spi_bus_initialize(HOST, &bus_config, 1)); + + spi_device_interface_config_t dev_config; + dev_config.address_bits = 0; + dev_config.command_bits = 0; + dev_config.dummy_bits = 0; + dev_config.mode = 0; + dev_config.duty_cycle_pos = 0; + dev_config.cs_ena_posttrans = 0; + dev_config.cs_ena_pretrans = 0; + dev_config.clock_speed_hz = 10000; + dev_config.spics_io_num = u8g2_esp32_hal.bus.spi.cs; + dev_config.flags = 0; + dev_config.queue_size = 200; + dev_config.pre_cb = NULL; + dev_config.post_cb = NULL; + // ESP_LOGI(TAG, "... Adding device bus."); + ESP_ERROR_CHECK(spi_bus_add_device(HOST, &dev_config, &handle_spi)); + + break; + } + + case U8X8_MSG_BYTE_SEND: { + spi_transaction_t trans_desc; + trans_desc.addr = 0; + trans_desc.cmd = 0; + trans_desc.flags = 0; + trans_desc.length = 8 * arg_int; // Number of bits NOT number of bytes. + trans_desc.rxlength = 0; + trans_desc.tx_buffer = arg_ptr; + trans_desc.rx_buffer = NULL; + + // ESP_LOGI(TAG, "... Transmitting %d bytes.", arg_int); + ESP_ERROR_CHECK(spi_device_transmit(handle_spi, &trans_desc)); + break; + } + } + return 0; +} // u8g2_esp32_spi_byte_cb + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is + * invoked to handle I2C communications. + */ +uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t* u8x8, + uint8_t msg, + uint8_t arg_int, + void* arg_ptr) { + ESP_LOGD(TAG, "i2c_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", msg, + arg_int, arg_ptr); + + switch (msg) { + case U8X8_MSG_BYTE_SET_DC: { + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.dc, arg_int); + } + break; + } + + case U8X8_MSG_BYTE_INIT: { + if (u8g2_esp32_hal.bus.i2c.sda == U8G2_ESP32_HAL_UNDEFINED || + u8g2_esp32_hal.bus.i2c.scl == U8G2_ESP32_HAL_UNDEFINED) { + break; + } + + i2c_config_t conf = {0}; + conf.mode = I2C_MODE_MASTER; + ESP_LOGI(TAG, "sda_io_num %d", u8g2_esp32_hal.bus.i2c.sda); + conf.sda_io_num = u8g2_esp32_hal.bus.i2c.sda; + conf.sda_pullup_en = GPIO_PULLUP_ENABLE; + ESP_LOGI(TAG, "scl_io_num %d", u8g2_esp32_hal.bus.i2c.scl); + conf.scl_io_num = u8g2_esp32_hal.bus.i2c.scl; + conf.scl_pullup_en = GPIO_PULLUP_ENABLE; + ESP_LOGI(TAG, "clk_speed %d", I2C_MASTER_FREQ_HZ); + conf.master.clk_speed = I2C_MASTER_FREQ_HZ; + ESP_LOGI(TAG, "i2c_param_config %d", conf.mode); + ESP_ERROR_CHECK(i2c_param_config(I2C_MASTER_NUM, &conf)); + ESP_LOGI(TAG, "i2c_driver_install %d", I2C_MASTER_NUM); + ESP_ERROR_CHECK(i2c_driver_install(I2C_MASTER_NUM, conf.mode, + I2C_MASTER_RX_BUF_DISABLE, + I2C_MASTER_TX_BUF_DISABLE, 0)); + break; + } + + case U8X8_MSG_BYTE_SEND: { + uint8_t* data_ptr = (uint8_t*)arg_ptr; + ESP_LOG_BUFFER_HEXDUMP(TAG, data_ptr, arg_int, ESP_LOG_VERBOSE); + + while (arg_int > 0) { + ESP_ERROR_CHECK( + i2c_master_write_byte(handle_i2c, *data_ptr, ACK_CHECK_EN)); + data_ptr++; + arg_int--; + } + break; + } + + case U8X8_MSG_BYTE_START_TRANSFER: { + uint8_t i2c_address = u8x8_GetI2CAddress(u8x8); + handle_i2c = i2c_cmd_link_create(); + ESP_LOGD(TAG, "Start I2C transfer to %02X.", i2c_address >> 1); + ESP_ERROR_CHECK(i2c_master_start(handle_i2c)); + ESP_ERROR_CHECK(i2c_master_write_byte( + handle_i2c, i2c_address | I2C_MASTER_WRITE, ACK_CHECK_EN)); + break; + } + + case U8X8_MSG_BYTE_END_TRANSFER: { + ESP_LOGD(TAG, "End I2C transfer."); + ESP_ERROR_CHECK(i2c_master_stop(handle_i2c)); + ESP_ERROR_CHECK(i2c_master_cmd_begin(I2C_MASTER_NUM, handle_i2c, + pdMS_TO_TICKS(I2C_TIMEOUT_MS))); + i2c_cmd_link_delete(handle_i2c); + break; + } + } + return 0; +} // u8g2_esp32_i2c_byte_cb + +/* + * HAL callback function as prescribed by the U8G2 library. This callback is + * invoked to handle callbacks for GPIO and delay functions. + */ +uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t* u8x8, + uint8_t msg, + uint8_t arg_int, + void* arg_ptr) { + ESP_LOGD(TAG, + "gpio_and_delay_cb: Received a msg: %d, arg_int: %d, arg_ptr: %p", + msg, arg_int, arg_ptr); + + switch (msg) { + // Initialize the GPIO and DELAY HAL functions. If the pins for DC and + // RESET have been specified then we define those pins as GPIO outputs. + case U8X8_MSG_GPIO_AND_DELAY_INIT: { + uint64_t bitmask = 0; + if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) { + bitmask = bitmask | (1ull << u8g2_esp32_hal.dc); + } + if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) { + bitmask = bitmask | (1ull << u8g2_esp32_hal.reset); + } + if (u8g2_esp32_hal.bus.spi.cs != U8G2_ESP32_HAL_UNDEFINED) { + bitmask = bitmask | (1ull << u8g2_esp32_hal.bus.spi.cs); + } + + if (bitmask == 0) { + break; + } + gpio_config_t gpioConfig; + gpioConfig.pin_bit_mask = bitmask; + gpioConfig.mode = GPIO_MODE_OUTPUT; + gpioConfig.pull_up_en = GPIO_PULLUP_DISABLE; + gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE; + gpioConfig.intr_type = GPIO_INTR_DISABLE; + gpio_config(&gpioConfig); + break; + } + + // Set the GPIO reset pin to the value passed in through arg_int. + case U8X8_MSG_GPIO_RESET: + if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.reset, arg_int); + } + break; + // Set the GPIO client select pin to the value passed in through arg_int. + case U8X8_MSG_GPIO_CS: + if (u8g2_esp32_hal.bus.spi.cs != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.bus.spi.cs, arg_int); + } + break; + // Set the Software I²C pin to the value passed in through arg_int. + case U8X8_MSG_GPIO_I2C_CLOCK: + if (u8g2_esp32_hal.bus.i2c.scl != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.bus.i2c.scl, arg_int); + // printf("%c",(arg_int==1?'C':'c')); + } + break; + // Set the Software I²C pin to the value passed in through arg_int. + case U8X8_MSG_GPIO_I2C_DATA: + if (u8g2_esp32_hal.bus.i2c.sda != U8G2_ESP32_HAL_UNDEFINED) { + gpio_set_level(u8g2_esp32_hal.bus.i2c.sda, arg_int); + // printf("%c",(arg_int==1?'D':'d')); + } + break; + + // Delay for the number of milliseconds passed in through arg_int. + case U8X8_MSG_DELAY_MILLI: + vTaskDelay(arg_int / portTICK_PERIOD_MS); + break; + } + return 0; +} // u8g2_esp32_gpio_and_delay_cb diff --git a/main/hal/u8g2_esp32_hal.h b/main/hal/u8g2_esp32_hal.h new file mode 100644 index 0000000..5a126e3 --- /dev/null +++ b/main/hal/u8g2_esp32_hal.h @@ -0,0 +1,92 @@ +#ifndef U8G2_ESP32_HAL_H +#define U8G2_ESP32_HAL_H +/* + * u8g2_esp32_hal.h + * + * Created on: Feb 12, 2017 + * Author: kolban + */ + +#ifndef U8G2_ESP32_HAL_H_ +#define U8G2_ESP32_HAL_H_ +#include "u8g2.h" + +#include "driver/gpio.h" +#include "driver/i2c.h" +#include "driver/spi_master.h" + +#define U8G2_ESP32_HAL_UNDEFINED GPIO_NUM_NC + +#if SOC_I2C_NUM > 1 +#define I2C_MASTER_NUM I2C_NUM_1 // I2C port number for master dev +#else +#define I2C_MASTER_NUM I2C_NUM_0 // I2C port number for master dev +#endif + +#define I2C_MASTER_TX_BUF_DISABLE 0 // I2C master do not need buffer +#define I2C_MASTER_RX_BUF_DISABLE 0 // I2C master do not need buffer +#define I2C_MASTER_FREQ_HZ 50000 // I2C master clock frequency +#define ACK_CHECK_EN 0x1 // I2C master will check ack from slave +#define ACK_CHECK_DIS 0x0 // I2C master will not check ack from slave + +/** @public + * HAL configuration structure. + */ +typedef struct +{ + union { + /* SPI settings. */ + struct + { + /* GPIO num for clock. */ + gpio_num_t clk; + /* GPIO num for SPI mosi. */ + gpio_num_t mosi; + /* GPIO num for SPI slave/chip select. */ + gpio_num_t cs; + } spi; + /* I2C settings. */ + struct + { + /* GPIO num for I2C data. */ + gpio_num_t sda; + /* GPIO num for I2C clock. */ + gpio_num_t scl; + } i2c; + } bus; + /* GPIO num for reset. */ + gpio_num_t reset; + /* GPIO num for DC. */ + gpio_num_t dc; +} u8g2_esp32_hal_t; + +/** + * Construct a default HAL configuration with all fields undefined. + */ +#define U8G2_ESP32_HAL_DEFAULT \ + {.bus = {.spi = {.clk = U8G2_ESP32_HAL_UNDEFINED, \ + .mosi = U8G2_ESP32_HAL_UNDEFINED, \ + .cs = U8G2_ESP32_HAL_UNDEFINED}}, \ + .reset = U8G2_ESP32_HAL_UNDEFINED, \ + .dc = U8G2_ESP32_HAL_UNDEFINED} + +#ifdef __cplusplus +extern "C" +{ +#endif + /** + * Initialize the HAL with the given configuration. + * + * @see u8g2_esp32_hal_t + * @see U8G2_ESP32_HAL_DEFAULT + */ + void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param); + uint8_t u8g2_esp32_spi_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + uint8_t u8g2_esp32_i2c_byte_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + uint8_t u8g2_esp32_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); +#ifdef __cplusplus +} +#endif +#endif /* U8G2_ESP32_HAL_H_ */ + +#endif \ No newline at end of file diff --git a/main/idf_component.yml b/main/idf_component.yml index 4c3e6fe..2565e81 100755 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -1,5 +1,5 @@ dependencies: u8g2: git: https://github.com/olikraus/u8g2.git - u8g2_hal: - git: https://github.com/mkfrey/u8g2-hal-esp-idf.git +# u8g2_hal: +# git: https://github.com/mkfrey/u8g2-hal-esp-idf.git diff --git a/main/setup.c b/main/setup.c index 1244d6d..4156b82 100644 --- a/main/setup.c +++ b/main/setup.c @@ -96,7 +96,7 @@ static void set_wled_color(uint8_t r, uint8_t g, uint8_t b) void setup(void) { - setupButtons(); + setup_buttons(); u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT; u8g2_esp32_hal.bus.i2c.sda = PIN_SDA;