diff options
author | Drashna Jaelre <drashna@live.com> | 2022-05-15 04:24:35 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-15 21:24:35 +1000 |
commit | f090881aebbd7af74294b53fabdf55a35004f190 (patch) | |
tree | 53d786c3be9bf1b2823bdee7bf6a55686d8b1461 /drivers/haptic/solenoid.c | |
parent | 4d107feca9621ee3f342507136b04f176e8f2320 (diff) | |
download | qmk_firmware-f090881aebbd7af74294b53fabdf55a35004f190.tar.gz qmk_firmware-f090881aebbd7af74294b53fabdf55a35004f190.zip |
[Feature] Add support for multiple switchs/solenoids to Haptic Feedback engine (#15657)
Diffstat (limited to 'drivers/haptic/solenoid.c')
-rw-r--r-- | drivers/haptic/solenoid.c | 155 |
1 files changed, 114 insertions, 41 deletions
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c index 14d868bffe..637a77da3d 100644 --- a/drivers/haptic/solenoid.c +++ b/drivers/haptic/solenoid.c @@ -20,11 +20,22 @@ #include "haptic.h" #include "gpio.h" #include "usb_device_state.h" - -bool solenoid_on = false; -bool solenoid_buzzing = false; -uint16_t solenoid_start = 0; -uint8_t solenoid_dwell = SOLENOID_DEFAULT_DWELL; +#include <stdlib.h> + +uint8_t solenoid_dwell = SOLENOID_DEFAULT_DWELL; +static pin_t solenoid_pads[] = SOLENOID_PINS; +#define NUMBER_OF_SOLENOIDS (sizeof(solenoid_pads) / sizeof(pin_t)) +bool solenoid_on[NUMBER_OF_SOLENOIDS] = {false}; +bool solenoid_buzzing[NUMBER_OF_SOLENOIDS] = {false}; +uint16_t solenoid_start[NUMBER_OF_SOLENOIDS] = {0}; +#ifdef SOLENOID_PIN_ACTIVE_LOW +# define low true +# define high false +#else +# define low false +# define high true +#endif +static bool solenoid_active_state[NUMBER_OF_SOLENOIDS]; extern haptic_config_t haptic_config; @@ -36,7 +47,7 @@ void solenoid_buzz_off(void) { haptic_set_buzz(0); } -void solenoid_set_buzz(int buzz) { +void solenoid_set_buzz(uint8_t buzz) { haptic_set_buzz(buzz); } @@ -44,59 +55,121 @@ void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } -void solenoid_stop(void) { - SOLENOID_PIN_WRITE_INACTIVE(); - solenoid_on = false; - solenoid_buzzing = false; +/** + * @brief Stops a specific solenoid + * + * @param index select which solenoid to check/stop + */ +void solenoid_stop(uint8_t index) { + writePin(solenoid_pads[index], !solenoid_active_state[index]); + solenoid_on[index] = false; + solenoid_buzzing[index] = false; } -void solenoid_fire(void) { - if (!haptic_config.buzz && solenoid_on) return; - if (haptic_config.buzz && solenoid_buzzing) return; +/** + * @brief Fires off a specific solenoid + * + * @param index Selects which solenoid to fire + */ +void solenoid_fire(uint8_t index) { + if (!haptic_config.buzz && solenoid_on[index]) return; + if (haptic_config.buzz && solenoid_buzzing[index]) return; + + solenoid_on[index] = true; + solenoid_buzzing[index] = true; + solenoid_start[index] = timer_read(); + writePin(solenoid_pads[index], solenoid_active_state[index]); +} - solenoid_on = true; - solenoid_buzzing = true; - solenoid_start = timer_read(); - SOLENOID_PIN_WRITE_ACTIVE(); +/** + * @brief Handles selecting a non-active solenoid, and firing it. + * + */ +void solenoid_fire_handler(void) { +#ifndef SOLENOID_RANDOM_FIRE + if (NUMBER_OF_SOLENOIDS > 1) { + uint8_t i = rand() % NUMBER_OF_SOLENOIDS; + if (!solenoid_on[i]) { + solenoid_fire(i); + } + } else { + solenoid_fire(0); + } +#else + for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) { + if (!solenoid_on[i]) { + solenoid_fire(i); + break; + } + } +#endif } +/** + * @brief Checks active solenoid to stop them, and to handle buzz mode + * + */ void solenoid_check(void) { - uint16_t elapsed = 0; + uint16_t elapsed[NUMBER_OF_SOLENOIDS] = {0}; - if (!solenoid_on) return; + for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) { + if (!solenoid_on[i]) continue; - elapsed = timer_elapsed(solenoid_start); + elapsed[i] = timer_elapsed(solenoid_start[i]); - // Check if it's time to finish this solenoid click cycle - if (elapsed > solenoid_dwell) { - solenoid_stop(); - return; - } + // Check if it's time to finish this solenoid click cycle + if (elapsed[i] > solenoid_dwell) { + solenoid_stop(i); + continue; + } - // Check whether to buzz the solenoid on and off - if (haptic_config.buzz) { - if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { - if (!solenoid_buzzing) { - solenoid_buzzing = true; - SOLENOID_PIN_WRITE_ACTIVE(); - } - } else { - if (solenoid_buzzing) { - solenoid_buzzing = false; - SOLENOID_PIN_WRITE_INACTIVE(); + // Check whether to buzz the solenoid on and off + if (haptic_config.buzz) { + if ((elapsed[i] % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { + if (!solenoid_buzzing[i]) { + solenoid_buzzing[i] = true; + writePin(solenoid_pads[i], solenoid_active_state[i]); + } + } else { + if (solenoid_buzzing[i]) { + solenoid_buzzing[i] = false; + writePin(solenoid_pads[i], !solenoid_active_state[i]); + } } } } } +/** + * @brief Initial configuration for solenoids + * + */ void solenoid_setup(void) { - SOLENOID_PIN_WRITE_INACTIVE(); - setPinOutput(SOLENOID_PIN); - if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) { - solenoid_fire(); +#ifdef SOLENOID_PINS_ACTIVE_STATE + bool state_temp[] = SOLENOID_PINS_ACTIVE_STATE; + uint8_t bound_check = (sizeof(state_temp) / sizeof(bool)); +#endif + + for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) { +#ifdef SOLENOID_PINS_ACTIVE_STATE + solenoid_active_state[i] = (bound_check - i) ? state_temp[i] : high; +#else + solenoid_active_state[i] = high; +#endif + writePin(solenoid_pads[i], !solenoid_active_state[i]); + setPinOutput(solenoid_pads[i]); + if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) { + solenoid_fire(i); + } } } +/** + * @brief stops solenoids prior to device reboot, to prevent them from being locked on + * + */ void solenoid_shutdown(void) { - SOLENOID_PIN_WRITE_INACTIVE(); + for (uint8_t i = 0; i < NUMBER_OF_SOLENOIDS; i++) { + writePin(solenoid_pads[i], !solenoid_active_state[i]); + } } |