Files
espresso_frame/firmware/main/manage_button.c
T
tfaour e870898490
Build and push server image / build-and-push (push) Successful in 32s
Refine manage overlay: US/CAN state abbreviations, share-QR caption, and an escalating second menu with named-face labels
Two rounds of follow-up work on the manage-button overlay:

1. Location formatting: US/Canada now show abbreviated state/province
   ("CA", "ON") instead of the full name, other countries show the full
   country name, and each is its own line (was one line, now wraps to
   two) so longer international place names have more room without
   threatening to overlap the top-right QR box. The bottom-left share QR
   also gets a "SCAN TO DOWNLOAD" caption.

2. Escalating menu: pressing the manage button again while its overlay
   is already up adds a second level -- each Immich-identified person's
   name labeled next to their face in the photo (using Immich's own
   face recognition/People data, no detection/recognition added to this
   project). A third press exits immediately instead of waiting out the
   30s auto-revert timer. No new Immich API needed -- GET /api/faces
   already embeds a nullable person.name per face; new
   server/app/face_labels.py maps a named face's box into the final
   800x480 frame's pixel space (reusing crop-box math extracted from
   image_pipeline.py's face-aware cropping). Capped at 4 named faces,
   sized to a real firmware RAM budget: each label is its own malloc'd
   overlay region on the device, alongside the 4 fixed corner regions
   already in use. New GET /frame/face-labels returns a flattened
   fixed-slot JSON shape (not a real array) so firmware's existing
   flat-scalar parser can read it without needing an actual array
   parser. No persistent state needed for the escalation itself -- it's
   all local control flow within one continuous awake session
   (frame_client.c's run_management_menu()).
2026-07-19 09:09:06 -04:00

71 lines
2.0 KiB
C

#include "driver/gpio.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "manage_button.h"
static const char *TAG = "manage_button";
#if CONFIG_FRAME_MANAGE_BUTTON_GPIO >= 0
#define MANAGE_BUTTON_GPIO ((gpio_num_t)CONFIG_FRAME_MANAGE_BUTTON_GPIO)
#define MANAGE_BUTTON_DEBOUNCE_MS 20
#define MANAGE_BUTTON_DEBOUNCE_CHECKS 3
void manage_button_init(void)
{
gpio_config_t io_conf = {
.pin_bit_mask = 1ULL << MANAGE_BUTTON_GPIO,
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
};
gpio_config(&io_conf);
/* See reset_button.c for why this API (not ext1) -- it manages the
* pull resistor across the sleep transition itself, so the pin
* doesn't float and wake the device spuriously. */
esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(1ULL << MANAGE_BUTTON_GPIO, ESP_GPIO_WAKEUP_GPIO_LOW);
}
bool manage_button_check(void)
{
/* See next_button.c for why the latched wakeup status is checked
* first: a quick tap can release before a live gpio_get_level() call
* this far into boot would still see it held, even though it's what
* woke the device. */
if (esp_sleep_get_gpio_wakeup_status() & (1ULL << MANAGE_BUTTON_GPIO)) {
ESP_LOGI(TAG, "Manage button caused this wake, showing management QR");
return true;
}
if (gpio_get_level(MANAGE_BUTTON_GPIO) != 0) {
return false;
}
for (int i = 0; i < MANAGE_BUTTON_DEBOUNCE_CHECKS; i++) {
vTaskDelay(pdMS_TO_TICKS(MANAGE_BUTTON_DEBOUNCE_MS));
if (gpio_get_level(MANAGE_BUTTON_GPIO) != 0) {
return false; /* noise, not a real press */
}
}
ESP_LOGI(TAG, "Manage button held during power-on, showing management QR");
return true;
}
bool manage_button_is_pressed(void)
{
return gpio_get_level(MANAGE_BUTTON_GPIO) == 0;
}
#else
void manage_button_init(void) {}
bool manage_button_check(void) { return false; }
bool manage_button_is_pressed(void) { return false; }
#endif