mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-29 07:37:48 +01:00
97 lines
3.0 KiB
C++
97 lines
3.0 KiB
C++
//
|
|
// Created by Stepan Usatiuk on 02.03.2025.
|
|
//
|
|
|
|
#include "buttons.hpp"
|
|
|
|
#include <driver/gpio.h>
|
|
#include <esp_err.h>
|
|
#include <power_helper.hpp>
|
|
#include <rom/ets_sys.h>
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
|
|
#include "config.hpp"
|
|
#include "i2c_global.hpp"
|
|
|
|
static i2c_master_dev_handle_t dev_handle;
|
|
static inline i2c_device_config_t dev_cfg = {
|
|
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
|
.device_address = 0x20,
|
|
.scl_speed_hz = 100000,
|
|
};
|
|
|
|
Buttons& Buttons::get() {
|
|
static Buttons buttons;
|
|
return buttons;
|
|
}
|
|
|
|
static void start_pooler(void* arg) { static_cast<Buttons*>(arg)->pooler(); }
|
|
|
|
static bool is_on_low;
|
|
|
|
static void wakeup(void* arg) {
|
|
if (is_on_low) {
|
|
ESP_ERROR_CHECK(gpio_set_intr_type(EXP_INT, GPIO_INTR_HIGH_LEVEL));
|
|
ESP_ERROR_CHECK(gpio_wakeup_enable(EXP_INT, GPIO_INTR_HIGH_LEVEL));
|
|
is_on_low = false;
|
|
|
|
BaseType_t xResult = pdFAIL;
|
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
xTaskNotifyFromISR(Buttons::get()._pooler_task, 0, eNoAction, &xHigherPriorityTaskWoken);
|
|
|
|
PowerHelper::get().reset_slow_isr(&xHigherPriorityTaskWoken);
|
|
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
} else {
|
|
ESP_ERROR_CHECK(gpio_set_intr_type(EXP_INT, GPIO_INTR_LOW_LEVEL));
|
|
ESP_ERROR_CHECK(gpio_wakeup_enable(EXP_INT, GPIO_INTR_LOW_LEVEL));
|
|
is_on_low = true;
|
|
}
|
|
}
|
|
|
|
Buttons::Buttons() {
|
|
ESP_ERROR_CHECK(i2c_master_bus_add_device(I2cGlobal::get().get_bus_handle(), &dev_cfg, &dev_handle));
|
|
uint8_t buf2[2];
|
|
|
|
// Config
|
|
buf2[0] = 6;
|
|
buf2[1] = 0xFF;
|
|
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
|
buf2[0] = 7;
|
|
buf2[1] = 0x80;
|
|
ESP_ERROR_CHECK(i2c_master_transmit(dev_handle, buf2, sizeof(buf2), -1));
|
|
xTaskCreate(&start_pooler, "ButtonsPooler", 2048, this, 1, &_pooler_task);
|
|
|
|
ESP_ERROR_CHECK(gpio_reset_pin(EXP_INT));
|
|
ESP_ERROR_CHECK(gpio_set_direction(EXP_INT, GPIO_MODE_INPUT));
|
|
ESP_ERROR_CHECK(gpio_set_pull_mode(EXP_INT, GPIO_FLOATING));
|
|
ESP_ERROR_CHECK(gpio_set_intr_type(EXP_INT, GPIO_INTR_LOW_LEVEL));
|
|
ESP_ERROR_CHECK(gpio_wakeup_enable(EXP_INT, GPIO_INTR_LOW_LEVEL));
|
|
is_on_low = true;
|
|
}
|
|
|
|
static void delay(unsigned long long loop) {
|
|
for (unsigned long long i = 0; i < loop; i++) {
|
|
asm volatile("nop");
|
|
}
|
|
}
|
|
|
|
void Buttons::pooler() {
|
|
while (true) {
|
|
BaseType_t xResult = xTaskNotifyWait(pdFALSE, ULONG_MAX, nullptr, portMAX_DELAY);
|
|
uint8_t reg = 0;
|
|
uint8_t buffer;
|
|
ESP_ERROR_CHECK(
|
|
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 1, -1));
|
|
_current = buffer;
|
|
// read second port too to clear the interrupt
|
|
reg = 1;
|
|
ESP_ERROR_CHECK(
|
|
i2c_master_transmit_receive(dev_handle, ®, sizeof(reg), reinterpret_cast<uint8_t*>(&buffer), 1, -1));
|
|
}
|
|
}
|
|
uint8_t Buttons::get_pressed() { return _current; }
|
|
void Buttons::install_isr() { gpio_isr_handler_add(EXP_INT, wakeup, nullptr); }
|