diff options
| -rw-r--r-- | docs/feature_haptic_feedback.md | 11 | ||||
| -rw-r--r-- | drivers/haptic/solenoid.c | 16 | ||||
| -rw-r--r-- | drivers/haptic/solenoid.h | 8 | ||||
| -rw-r--r-- | quantum/haptic.c | 51 | ||||
| -rw-r--r-- | quantum/haptic.h | 27 | ||||
| -rw-r--r-- | quantum/process_keycode/process_haptic.c | 3 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_device_state.c | 10 |
7 files changed, 115 insertions, 11 deletions
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md index 4054c5d9b..159296a29 100644 --- a/docs/feature_haptic_feedback.md +++ b/docs/feature_haptic_feedback.md | |||
| @@ -11,6 +11,16 @@ HAPTIC_DRIVER += DRV2605L | |||
| 11 | HAPTIC_DRIVER += SOLENOID | 11 | HAPTIC_DRIVER += SOLENOID |
| 12 | ``` | 12 | ``` |
| 13 | 13 | ||
| 14 | The following `config.h` settings are available for all types of haptic feedback: | ||
| 15 | |||
| 16 | | Settings | Default | Description | | ||
| 17 | |--------------------------------------|---------------|---------------------------------------------------------------------------------------------------------------| | ||
| 18 | |`HAPTIC_ENABLE_PIN` | *Not defined* |Configures a pin to enable a boost converter for some haptic solution, often used with solenoid drivers. | | ||
| 19 | |`HAPTIC_ENABLE_PIN_ACTIVE_LOW` | *Not defined* |If defined then the haptic enable pin is active-low. | | ||
| 20 | |`HAPTIC_ENABLE_STATUS_LED` | *Not defined* |Configures a pin to reflect the current enabled/disabled status of haptic feedback. | | ||
| 21 | |`HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW` | *Not defined* |If defined then the haptic status led will be active-low. | | ||
| 22 | |`HAPTIC_OFF_IN_LOW_POWER` | `0` |If set to `1`, haptic feedback is disabled before the device is configured, and while the device is suspended. | | ||
| 23 | |||
| 14 | ## Known Supported Hardware | 24 | ## Known Supported Hardware |
| 15 | 25 | ||
| 16 | | Name | Description | | 26 | | Name | Description | |
| @@ -48,6 +58,7 @@ First you will need a build a circuit to drive the solenoid through a mosfet as | |||
| 48 | | Settings | Default | Description | | 58 | | Settings | Default | Description | |
| 49 | |----------------------------|----------------------|-------------------------------------------------------| | 59 | |----------------------------|----------------------|-------------------------------------------------------| |
| 50 | |`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. | | 60 | |`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. | |
| 61 | |`SOLENOID_PIN_ACTIVE_LOW` | *Not defined* |If defined then the solenoid trigger pin is active low.| | ||
| 51 | |`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. | | 62 | |`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. | |
| 52 | |`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. | | 63 | |`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. | |
| 53 | |`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. | | 64 | |`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. | |
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c index 25cf34465..7a09940f7 100644 --- a/drivers/haptic/solenoid.c +++ b/drivers/haptic/solenoid.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "solenoid.h" | 19 | #include "solenoid.h" |
| 20 | #include "haptic.h" | 20 | #include "haptic.h" |
| 21 | #include "gpio.h" | 21 | #include "gpio.h" |
| 22 | #include "usb_device_state.h" | ||
| 22 | 23 | ||
| 23 | bool solenoid_on = false; | 24 | bool solenoid_on = false; |
| 24 | bool solenoid_buzzing = false; | 25 | bool solenoid_buzzing = false; |
| @@ -36,7 +37,7 @@ void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); } | |||
| 36 | void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } | 37 | void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; } |
| 37 | 38 | ||
| 38 | void solenoid_stop(void) { | 39 | void solenoid_stop(void) { |
| 39 | writePinLow(SOLENOID_PIN); | 40 | SOLENOID_PIN_WRITE_INACTIVE(); |
| 40 | solenoid_on = false; | 41 | solenoid_on = false; |
| 41 | solenoid_buzzing = false; | 42 | solenoid_buzzing = false; |
| 42 | } | 43 | } |
| @@ -48,7 +49,7 @@ void solenoid_fire(void) { | |||
| 48 | solenoid_on = true; | 49 | solenoid_on = true; |
| 49 | solenoid_buzzing = true; | 50 | solenoid_buzzing = true; |
| 50 | solenoid_start = timer_read(); | 51 | solenoid_start = timer_read(); |
| 51 | writePinHigh(SOLENOID_PIN); | 52 | SOLENOID_PIN_WRITE_ACTIVE(); |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | void solenoid_check(void) { | 55 | void solenoid_check(void) { |
| @@ -69,20 +70,23 @@ void solenoid_check(void) { | |||
| 69 | if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { | 70 | if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) { |
| 70 | if (!solenoid_buzzing) { | 71 | if (!solenoid_buzzing) { |
| 71 | solenoid_buzzing = true; | 72 | solenoid_buzzing = true; |
| 72 | writePinHigh(SOLENOID_PIN); | 73 | SOLENOID_PIN_WRITE_ACTIVE(); |
| 73 | } | 74 | } |
| 74 | } else { | 75 | } else { |
| 75 | if (solenoid_buzzing) { | 76 | if (solenoid_buzzing) { |
| 76 | solenoid_buzzing = false; | 77 | solenoid_buzzing = false; |
| 77 | writePinLow(SOLENOID_PIN); | 78 | SOLENOID_PIN_WRITE_INACTIVE(); |
| 78 | } | 79 | } |
| 79 | } | 80 | } |
| 80 | } | 81 | } |
| 81 | } | 82 | } |
| 82 | 83 | ||
| 83 | void solenoid_setup(void) { | 84 | void solenoid_setup(void) { |
| 85 | SOLENOID_PIN_WRITE_INACTIVE(); | ||
| 84 | setPinOutput(SOLENOID_PIN); | 86 | setPinOutput(SOLENOID_PIN); |
| 85 | solenoid_fire(); | 87 | if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) { |
| 88 | solenoid_fire(); | ||
| 89 | } | ||
| 86 | } | 90 | } |
| 87 | 91 | ||
| 88 | void solenoid_shutdown(void) { writePinLow(SOLENOID_PIN); } | 92 | void solenoid_shutdown(void) { SOLENOID_PIN_WRITE_INACTIVE(); } |
diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h index f2a3bc4c3..653148154 100644 --- a/drivers/haptic/solenoid.h +++ b/drivers/haptic/solenoid.h | |||
| @@ -49,6 +49,14 @@ | |||
| 49 | # error SOLENOID_PIN not defined | 49 | # error SOLENOID_PIN not defined |
| 50 | #endif | 50 | #endif |
| 51 | 51 | ||
| 52 | #ifdef SOLENOID_PIN_ACTIVE_LOW | ||
| 53 | # define SOLENOID_PIN_WRITE_ACTIVE() writePinLow(SOLENOID_PIN) | ||
| 54 | # define SOLENOID_PIN_WRITE_INACTIVE() writePinHigh(SOLENOID_PIN) | ||
| 55 | #else | ||
| 56 | # define SOLENOID_PIN_WRITE_ACTIVE() writePinHigh(SOLENOID_PIN) | ||
| 57 | # define SOLENOID_PIN_WRITE_INACTIVE() writePinLow(SOLENOID_PIN) | ||
| 58 | #endif | ||
| 59 | |||
| 52 | void solenoid_buzz_on(void); | 60 | void solenoid_buzz_on(void); |
| 53 | void solenoid_buzz_off(void); | 61 | void solenoid_buzz_off(void); |
| 54 | void solenoid_set_buzz(int buzz); | 62 | void solenoid_set_buzz(int buzz); |
diff --git a/quantum/haptic.c b/quantum/haptic.c index 65abcc15f..f915acf94 100644 --- a/quantum/haptic.c +++ b/quantum/haptic.c | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #include "haptic.h" | 17 | #include "haptic.h" |
| 18 | #include "eeconfig.h" | 18 | #include "eeconfig.h" |
| 19 | #include "debug.h" | 19 | #include "debug.h" |
| 20 | #include "usb_device_state.h" | ||
| 21 | #include "gpio.h" | ||
| 20 | #ifdef DRV2605L | 22 | #ifdef DRV2605L |
| 21 | # include "DRV2605L.h" | 23 | # include "DRV2605L.h" |
| 22 | #endif | 24 | #endif |
| @@ -26,6 +28,29 @@ | |||
| 26 | 28 | ||
| 27 | haptic_config_t haptic_config; | 29 | haptic_config_t haptic_config; |
| 28 | 30 | ||
| 31 | static void update_haptic_enable_gpios(void) { | ||
| 32 | if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { | ||
| 33 | #if defined(HAPTIC_ENABLE_PIN) | ||
| 34 | HAPTIC_ENABLE_PIN_WRITE_ACTIVE(); | ||
| 35 | #endif | ||
| 36 | #if defined(HAPTIC_ENABLE_STATUS_LED) | ||
| 37 | HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE(); | ||
| 38 | #endif | ||
| 39 | } else { | ||
| 40 | #if defined(HAPTIC_ENABLE_PIN) | ||
| 41 | HAPTIC_ENABLE_PIN_WRITE_INACTIVE(); | ||
| 42 | #endif | ||
| 43 | #if defined(HAPTIC_ENABLE_STATUS_LED) | ||
| 44 | HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE(); | ||
| 45 | #endif | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | static void set_haptic_config_enable(bool enabled) { | ||
| 50 | haptic_config.enable = enabled; | ||
| 51 | update_haptic_enable_gpios(); | ||
| 52 | } | ||
| 53 | |||
| 29 | void haptic_init(void) { | 54 | void haptic_init(void) { |
| 30 | if (!eeconfig_is_enabled()) { | 55 | if (!eeconfig_is_enabled()) { |
| 31 | eeconfig_init(); | 56 | eeconfig_init(); |
| @@ -44,6 +69,10 @@ void haptic_init(void) { | |||
| 44 | // or the previous firmware didn't have solenoid enabled, | 69 | // or the previous firmware didn't have solenoid enabled, |
| 45 | // and the current one has solenoid enabled. | 70 | // and the current one has solenoid enabled. |
| 46 | haptic_reset(); | 71 | haptic_reset(); |
| 72 | } else { | ||
| 73 | // Haptic configuration has been loaded through the "raw" union item. | ||
| 74 | // This is to execute any side effects of the configuration. | ||
| 75 | set_haptic_config_enable(haptic_config.enable); | ||
| 47 | } | 76 | } |
| 48 | #ifdef SOLENOID_ENABLE | 77 | #ifdef SOLENOID_ENABLE |
| 49 | solenoid_setup(); | 78 | solenoid_setup(); |
| @@ -54,6 +83,12 @@ void haptic_init(void) { | |||
| 54 | dprintf("DRV2605 driver initialized\n"); | 83 | dprintf("DRV2605 driver initialized\n"); |
| 55 | #endif | 84 | #endif |
| 56 | eeconfig_debug_haptic(); | 85 | eeconfig_debug_haptic(); |
| 86 | #ifdef HAPTIC_ENABLE_PIN | ||
| 87 | setPinOutput(HAPTIC_ENABLE_PIN); | ||
| 88 | #endif | ||
| 89 | #ifdef HAPTIC_ENABLE_STATUS_LED | ||
| 90 | setPinOutput(HAPTIC_ENABLE_STATUS_LED); | ||
| 91 | #endif | ||
| 57 | } | 92 | } |
| 58 | 93 | ||
| 59 | void haptic_task(void) { | 94 | void haptic_task(void) { |
| @@ -69,13 +104,13 @@ void eeconfig_debug_haptic(void) { | |||
| 69 | } | 104 | } |
| 70 | 105 | ||
| 71 | void haptic_enable(void) { | 106 | void haptic_enable(void) { |
| 72 | haptic_config.enable = 1; | 107 | set_haptic_config_enable(true); |
| 73 | xprintf("haptic_config.enable = %u\n", haptic_config.enable); | 108 | xprintf("haptic_config.enable = %u\n", haptic_config.enable); |
| 74 | eeconfig_update_haptic(haptic_config.raw); | 109 | eeconfig_update_haptic(haptic_config.raw); |
| 75 | } | 110 | } |
| 76 | 111 | ||
| 77 | void haptic_disable(void) { | 112 | void haptic_disable(void) { |
| 78 | haptic_config.enable = 0; | 113 | set_haptic_config_enable(false); |
| 79 | xprintf("haptic_config.enable = %u\n", haptic_config.enable); | 114 | xprintf("haptic_config.enable = %u\n", haptic_config.enable); |
| 80 | eeconfig_update_haptic(haptic_config.raw); | 115 | eeconfig_update_haptic(haptic_config.raw); |
| 81 | } | 116 | } |
| @@ -157,7 +192,7 @@ void haptic_dwell_decrease(void) { | |||
| 157 | } | 192 | } |
| 158 | 193 | ||
| 159 | void haptic_reset(void) { | 194 | void haptic_reset(void) { |
| 160 | haptic_config.enable = true; | 195 | set_haptic_config_enable(true); |
| 161 | uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT; | 196 | uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT; |
| 162 | haptic_config.feedback = feedback; | 197 | haptic_config.feedback = feedback; |
| 163 | #ifdef DRV2605L | 198 | #ifdef DRV2605L |
| @@ -293,3 +328,13 @@ void haptic_shutdown(void) { | |||
| 293 | solenoid_shutdown(); | 328 | solenoid_shutdown(); |
| 294 | #endif | 329 | #endif |
| 295 | } | 330 | } |
| 331 | |||
| 332 | void haptic_notify_usb_device_state_change(void) { | ||
| 333 | update_haptic_enable_gpios(); | ||
| 334 | #if defined(HAPTIC_ENABLE_PIN) | ||
| 335 | setPinOutput(HAPTIC_ENABLE_PIN); | ||
| 336 | #endif | ||
| 337 | #if defined(HAPTIC_ENABLE_STATUS_LED) | ||
| 338 | setPinOutput(HAPTIC_ENABLE_STATUS_LED); | ||
| 339 | #endif | ||
| 340 | } | ||
diff --git a/quantum/haptic.h b/quantum/haptic.h index fc7ca2f3e..7d70a0133 100644 --- a/quantum/haptic.h +++ b/quantum/haptic.h | |||
| @@ -75,3 +75,30 @@ void haptic_cont_decrease(void); | |||
| 75 | 75 | ||
| 76 | void haptic_play(void); | 76 | void haptic_play(void); |
| 77 | void haptic_shutdown(void); | 77 | void haptic_shutdown(void); |
| 78 | void haptic_notify_usb_device_state_change(void); | ||
| 79 | |||
| 80 | #ifdef HAPTIC_ENABLE_PIN_ACTIVE_LOW | ||
| 81 | # ifndef HAPTIC_ENABLE_PIN | ||
| 82 | # error HAPTIC_ENABLE_PIN not defined | ||
| 83 | # endif | ||
| 84 | # define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_PIN) | ||
| 85 | # define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_PIN) | ||
| 86 | #else | ||
| 87 | # define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_PIN) | ||
| 88 | # define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_PIN) | ||
| 89 | #endif | ||
| 90 | |||
| 91 | #ifdef HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW | ||
| 92 | # ifndef HAPTIC_ENABLE_STATUS_LED | ||
| 93 | # error HAPTIC_ENABLE_STATUS_LED not defined | ||
| 94 | # endif | ||
| 95 | # define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED) | ||
| 96 | # define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED) | ||
| 97 | #else | ||
| 98 | # define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED) | ||
| 99 | # define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED) | ||
| 100 | #endif | ||
| 101 | |||
| 102 | #ifndef HAPTIC_OFF_IN_LOW_POWER | ||
| 103 | # define HAPTIC_OFF_IN_LOW_POWER 0 | ||
| 104 | #endif | ||
diff --git a/quantum/process_keycode/process_haptic.c b/quantum/process_keycode/process_haptic.c index 1b9c2f24f..466c8e554 100644 --- a/quantum/process_keycode/process_haptic.c +++ b/quantum/process_keycode/process_haptic.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "process_haptic.h" | 17 | #include "process_haptic.h" |
| 18 | #include "quantum_keycodes.h" | 18 | #include "quantum_keycodes.h" |
| 19 | #include "action_tapping.h" | 19 | #include "action_tapping.h" |
| 20 | #include "usb_device_state.h" | ||
| 20 | 21 | ||
| 21 | __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) { | 22 | __attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) { |
| 22 | switch (keycode) { | 23 | switch (keycode) { |
| @@ -131,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) { | |||
| 131 | } | 132 | } |
| 132 | } | 133 | } |
| 133 | 134 | ||
| 134 | if (haptic_get_enable()) { | 135 | if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) { |
| 135 | if (record->event.pressed) { | 136 | if (record->event.pressed) { |
| 136 | // keypress | 137 | // keypress |
| 137 | if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { | 138 | if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) { |
diff --git a/tmk_core/protocol/usb_device_state.c b/tmk_core/protocol/usb_device_state.c index 5ccd309ec..84f01943b 100644 --- a/tmk_core/protocol/usb_device_state.c +++ b/tmk_core/protocol/usb_device_state.c | |||
| @@ -16,6 +16,9 @@ | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include "usb_device_state.h" | 18 | #include "usb_device_state.h" |
| 19 | #if defined(HAPTIC_ENABLE) | ||
| 20 | # include "haptic.h" | ||
| 21 | #endif | ||
| 19 | 22 | ||
| 20 | enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; | 23 | enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT; |
| 21 | 24 | ||
| @@ -23,7 +26,12 @@ __attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_sta | |||
| 23 | 26 | ||
| 24 | __attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} | 27 | __attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {} |
| 25 | 28 | ||
| 26 | static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); } | 29 | static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { |
| 30 | #if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER | ||
| 31 | haptic_notify_usb_device_state_change(); | ||
| 32 | #endif | ||
| 33 | notify_usb_device_state_change_kb(usb_device_state); | ||
| 34 | } | ||
| 27 | 35 | ||
| 28 | void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { | 36 | void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) { |
| 29 | usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; | 37 | usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT; |
