#include "board_controls.hpp" #include #include #include namespace microbu { namespace { const char* TAG = "board"; constexpr std::int64_t blink_us = CONFIG_MICROBU_TX_LED_BLINK_MS * 1000LL; } BoardControls::BoardControls() { #if CONFIG_MICROBU_TX_LED_GPIO < 0 ESP_LOGI(TAG, "no activity LED configured"); #else gpio_config_t led = {}; led.pin_bit_mask = 1ULL << CONFIG_MICROBU_TX_LED_GPIO; led.mode = GPIO_MODE_OUTPUT; led.pull_up_en = GPIO_PULLUP_DISABLE; led.pull_down_en = GPIO_PULLDOWN_DISABLE; led.intr_type = GPIO_INTR_DISABLE; ESP_ERROR_CHECK(gpio_config(&led)); #if CONFIG_MICROBU_LED_INVERTED_RX mode_ = LedMode::inverted_rx; #else mode_ = LedMode::normal_tx; #endif apply_led_state(); ESP_LOGI(TAG, "LED GPIO %d (mode: %s)", CONFIG_MICROBU_TX_LED_GPIO, mode_ == LedMode::inverted_rx ? "inverted_rx (normally ON)" : "normal_tx (normally OFF)"); #endif } void BoardControls::apply_led_state() { #if CONFIG_MICROBU_TX_LED_GPIO >= 0 // The XIAO ESP32-C5 user LED is wired active-low (0 = ON, 1 = OFF). // In normal_tx mode: default OFF (1), pulsing ON (0). // In inverted_rx mode: default ON (0), pulsing OFF (1). bool led_illuminated = false; if (mode_ == LedMode::normal_tx) { led_illuminated = pulsing_; } else { led_illuminated = !pulsing_; } gpio_set_level(static_cast(CONFIG_MICROBU_TX_LED_GPIO), led_illuminated ? 0 : 1); #endif } void BoardControls::blink() { pulse_until_us_ = esp_timer_get_time() + blink_us; if (!pulsing_) { pulsing_ = true; apply_led_state(); } } void BoardControls::tick() { if (pulsing_ && esp_timer_get_time() >= pulse_until_us_) { pulsing_ = false; apply_led_state(); } } } // namespace microbu