/* * This program source code file is part of the KTag project, a DIY laser tag * game with customizable features and wide interoperability. * * 🛡 🃞 * * Copyright © 2024-2026 Joseph P. Kearney and the KTag developers. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * There should be a copy of the GNU Affero General Public License in the LICENSE * file in the root of this repository. If not, see . */ #include #include #include #include #include #include static const char *TAG = "Switches"; // GPIO assignments #define TRIGGER_GPIO GPIO_NUM_1 #define ACCESSORY_GPIO GPIO_NUM_4 static const button_config_t Button_Config = { .long_press_time = CONFIG_BUTTON_LONG_PRESS_TIME_MS, .short_press_time = CONFIG_BUTTON_SHORT_PRESS_TIME_MS, }; static const button_gpio_config_t Trigger_GPIO_Config = { .gpio_num = TRIGGER_GPIO, .active_level = 0, }; static const button_gpio_config_t Accessory_GPIO_Config = { .gpio_num = ACCESSORY_GPIO, .active_level = 0, }; static button_handle_t Trigger_Button; static button_handle_t Accessory_Button; static TickType_t TicksAtTriggerPress = 0; static TickType_t TicksAtAccessoryPress = 0; static TickType_t TicksAtAccessoryRelease = 0; static void trigger_press_cb(void *arg, void *usr_data) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; TicksAtTriggerPress = xTaskGetTickCountFromISR(); KEvent_T switch_event = {.ID = KEVENT_TRIGGER_SWITCH_PRESSED, .Data = NULL}; Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken); } static void trigger_release_cb(void *arg, void *usr_data) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; uint32_t triggerPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtTriggerPress); KEvent_T switch_event = {.ID = KEVENT_TRIGGER_SWITCH_RELEASED, .Data = (void *)triggerPressDurationInms}; Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken); } static void accessory_press_cb(void *arg, void *usr_data) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; TicksAtAccessoryPress = xTaskGetTickCountFromISR(); uint32_t accessoryTimeReleasedInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryRelease); KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_PRESSED, .Data = (void *)accessoryTimeReleasedInms}; Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken); } static void accessory_release_cb(void *arg, void *usr_data) { portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; TicksAtAccessoryRelease = xTaskGetTickCountFromISR(); uint32_t accessoryPressDurationInms = pdTICKS_TO_MS(xTaskGetTickCountFromISR() - TicksAtAccessoryPress); KEvent_T switch_event = {.ID = KEVENT_ACCESSORY_SWITCH_RELEASED, .Data = (void *)accessoryPressDurationInms}; Post_KEvent_From_ISR(&switch_event, &xHigherPriorityTaskWoken); } esp_err_t Initialize_Switches(void) { KLOG_INFO(TAG, "Initializing Switches..."); esp_err_t err; err = iot_button_new_gpio_device( &Button_Config, &Trigger_GPIO_Config, &Trigger_Button); if (err != ESP_OK) { KLOG_ERROR(TAG, "Failed to create Trigger button (%s)", esp_err_to_name(err)); return err; } err = iot_button_new_gpio_device( &Button_Config, &Accessory_GPIO_Config, &Accessory_Button); if (err != ESP_OK) { KLOG_ERROR(TAG, "Failed to create Accessory button (%s)", esp_err_to_name(err)); return err; } err = iot_button_register_cb( Trigger_Button, BUTTON_PRESS_DOWN, NULL, trigger_press_cb, NULL); if (err != ESP_OK) { KLOG_ERROR(TAG, "Trigger PRESS_DOWN cb failed (%s)", esp_err_to_name(err)); return err; } err = iot_button_register_cb( Trigger_Button, BUTTON_PRESS_UP, NULL, trigger_release_cb, NULL); if (err != ESP_OK) { KLOG_ERROR(TAG, "Trigger PRESS_UP cb failed (%s)", esp_err_to_name(err)); return err; } err = iot_button_register_cb( Accessory_Button, BUTTON_PRESS_DOWN, NULL, accessory_press_cb, NULL); if (err != ESP_OK) { KLOG_ERROR(TAG, "Accessory PRESS_DOWN cb failed (%s)", esp_err_to_name(err)); return err; } err = iot_button_register_cb( Accessory_Button, BUTTON_PRESS_UP, NULL, accessory_release_cb, NULL); if (err != ESP_OK) { KLOG_ERROR(TAG, "Accessory PRESS_UP cb failed (%s)", esp_err_to_name(err)); return err; } KLOG_INFO(TAG, "Switch initialization complete"); return ESP_OK; }