Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F haptic disable when usb not configured or suspended #12692

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/feature_haptic_feedback.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ HAPTIC_DRIVER += DRV2605L
HAPTIC_DRIVER += SOLENOID
```

The following `config.h` settings are available for all types of haptic feedback:

| Settings | Default | Description |
|--------------------------------------|---------------|---------------------------------------------------------------------------------------------------------------|
|`HAPTIC_ENABLE_PIN` | *Not defined* |Configures a pin to enable a boost converter for some haptic solution, often used with solenoid drivers. |
|`HAPTIC_ENABLE_PIN_ACTIVE_LOW` | *Not defined* |If defined then the haptic enable pin is active-low. |
|`HAPTIC_ENABLE_STATUS_LED` | *Not defined* |Configures a pin to reflect the current enabled/disabled status of haptic feedback. |
|`HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW` | *Not defined* |If defined then the haptic status led will be active-low. |
|`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. |

## Known Supported Hardware

| Name | Description |
Expand Down Expand Up @@ -48,6 +58,7 @@ First you will need a build a circuit to drive the solenoid through a mosfet as
| Settings | Default | Description |
|----------------------------|----------------------|-------------------------------------------------------|
|`SOLENOID_PIN` | *Not defined* |Configures the pin that the Solenoid is connected to. |
|`SOLENOID_PIN_ACTIVE_LOW` | *Not defined* |If defined then the solenoid trigger pin is active low.|
|`SOLENOID_DEFAULT_DWELL` | `12` ms |Configures the default dwell time for the solenoid. |
|`SOLENOID_MIN_DWELL` | `4` ms |Sets the lower limit for the dwell. |
|`SOLENOID_MAX_DWELL` | `100` ms |Sets the upper limit for the dwell. |
Expand Down
16 changes: 10 additions & 6 deletions drivers/haptic/solenoid.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "solenoid.h"
#include "haptic.h"
#include "gpio.h"
#include "usb_device_state.h"

bool solenoid_on = false;
bool solenoid_buzzing = false;
Expand All @@ -36,7 +37,7 @@ void solenoid_set_buzz(int buzz) { haptic_set_buzz(buzz); }
void solenoid_set_dwell(uint8_t dwell) { solenoid_dwell = dwell; }

void solenoid_stop(void) {
writePinLow(SOLENOID_PIN);
SOLENOID_PIN_WRITE_INACTIVE();
solenoid_on = false;
solenoid_buzzing = false;
}
Expand All @@ -48,7 +49,7 @@ void solenoid_fire(void) {
solenoid_on = true;
solenoid_buzzing = true;
solenoid_start = timer_read();
writePinHigh(SOLENOID_PIN);
SOLENOID_PIN_WRITE_ACTIVE();
}

void solenoid_check(void) {
Expand All @@ -69,20 +70,23 @@ void solenoid_check(void) {
if ((elapsed % (SOLENOID_BUZZ_ACTUATED + SOLENOID_BUZZ_NONACTUATED)) < SOLENOID_BUZZ_ACTUATED) {
if (!solenoid_buzzing) {
solenoid_buzzing = true;
writePinHigh(SOLENOID_PIN);
SOLENOID_PIN_WRITE_ACTIVE();
}
} else {
if (solenoid_buzzing) {
solenoid_buzzing = false;
writePinLow(SOLENOID_PIN);
SOLENOID_PIN_WRITE_INACTIVE();
}
}
}
}

void solenoid_setup(void) {
SOLENOID_PIN_WRITE_INACTIVE();
setPinOutput(SOLENOID_PIN);
solenoid_fire();
if ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED)) {
solenoid_fire();
}
}

void solenoid_shutdown(void) { writePinLow(SOLENOID_PIN); }
void solenoid_shutdown(void) { SOLENOID_PIN_WRITE_INACTIVE(); }
8 changes: 8 additions & 0 deletions drivers/haptic/solenoid.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@
# error SOLENOID_PIN not defined
#endif

#ifdef SOLENOID_PIN_ACTIVE_LOW
# define SOLENOID_PIN_WRITE_ACTIVE() writePinLow(SOLENOID_PIN)
# define SOLENOID_PIN_WRITE_INACTIVE() writePinHigh(SOLENOID_PIN)
#else
# define SOLENOID_PIN_WRITE_ACTIVE() writePinHigh(SOLENOID_PIN)
# define SOLENOID_PIN_WRITE_INACTIVE() writePinLow(SOLENOID_PIN)
#endif

void solenoid_buzz_on(void);
void solenoid_buzz_off(void);
void solenoid_set_buzz(int buzz);
Expand Down
51 changes: 48 additions & 3 deletions quantum/haptic.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "haptic.h"
#include "eeconfig.h"
#include "debug.h"
#include "usb_device_state.h"
#include "gpio.h"
#ifdef DRV2605L
# include "DRV2605L.h"
#endif
Expand All @@ -26,6 +28,29 @@

haptic_config_t haptic_config;

static void update_haptic_enable_gpios(void) {
if (haptic_config.enable && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
#if defined(HAPTIC_ENABLE_PIN)
HAPTIC_ENABLE_PIN_WRITE_ACTIVE();
#endif
#if defined(HAPTIC_ENABLE_STATUS_LED)
HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE();
#endif
} else {
#if defined(HAPTIC_ENABLE_PIN)
HAPTIC_ENABLE_PIN_WRITE_INACTIVE();
#endif
#if defined(HAPTIC_ENABLE_STATUS_LED)
HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE();
#endif
}
}

static void set_haptic_config_enable(bool enabled) {
haptic_config.enable = enabled;
update_haptic_enable_gpios();
}

void haptic_init(void) {
if (!eeconfig_is_enabled()) {
eeconfig_init();
Expand All @@ -44,6 +69,10 @@ void haptic_init(void) {
// or the previous firmware didn't have solenoid enabled,
// and the current one has solenoid enabled.
haptic_reset();
} else {
// Haptic configuration has been loaded through the "raw" union item.
// This is to execute any side effects of the configuration.
set_haptic_config_enable(haptic_config.enable);
}
#ifdef SOLENOID_ENABLE
solenoid_setup();
Expand All @@ -54,6 +83,12 @@ void haptic_init(void) {
dprintf("DRV2605 driver initialized\n");
#endif
eeconfig_debug_haptic();
#ifdef HAPTIC_ENABLE_PIN
setPinOutput(HAPTIC_ENABLE_PIN);
#endif
#ifdef HAPTIC_ENABLE_STATUS_LED
setPinOutput(HAPTIC_ENABLE_STATUS_LED);
#endif
}

void haptic_task(void) {
Expand All @@ -69,13 +104,13 @@ void eeconfig_debug_haptic(void) {
}

void haptic_enable(void) {
haptic_config.enable = 1;
set_haptic_config_enable(true);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}

void haptic_disable(void) {
haptic_config.enable = 0;
set_haptic_config_enable(false);
xprintf("haptic_config.enable = %u\n", haptic_config.enable);
eeconfig_update_haptic(haptic_config.raw);
}
Expand Down Expand Up @@ -157,7 +192,7 @@ void haptic_dwell_decrease(void) {
}

void haptic_reset(void) {
haptic_config.enable = true;
set_haptic_config_enable(true);
uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT;
haptic_config.feedback = feedback;
#ifdef DRV2605L
Expand Down Expand Up @@ -293,3 +328,13 @@ void haptic_shutdown(void) {
solenoid_shutdown();
#endif
}

void haptic_notify_usb_device_state_change(void) {
update_haptic_enable_gpios();
#if defined(HAPTIC_ENABLE_PIN)
setPinOutput(HAPTIC_ENABLE_PIN);
#endif
#if defined(HAPTIC_ENABLE_STATUS_LED)
setPinOutput(HAPTIC_ENABLE_STATUS_LED);
#endif
}
27 changes: 27 additions & 0 deletions quantum/haptic.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,30 @@ void haptic_cont_decrease(void);

void haptic_play(void);
void haptic_shutdown(void);
void haptic_notify_usb_device_state_change(void);

#ifdef HAPTIC_ENABLE_PIN_ACTIVE_LOW
# ifndef HAPTIC_ENABLE_PIN
# error HAPTIC_ENABLE_PIN not defined
# endif
# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
#else
# define HAPTIC_ENABLE_PIN_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_PIN)
# define HAPTIC_ENABLE_PIN_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_PIN)
#endif

#ifdef HAPTIC_ENABLE_STATUS_LED_ACTIVE_LOW
# ifndef HAPTIC_ENABLE_STATUS_LED
# error HAPTIC_ENABLE_STATUS_LED not defined
# endif
# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
#else
# define HAPTIC_ENABLE_STATUS_LED_WRITE_ACTIVE() writePinHigh(HAPTIC_ENABLE_STATUS_LED)
# define HAPTIC_ENABLE_STATUS_LED_WRITE_INACTIVE() writePinLow(HAPTIC_ENABLE_STATUS_LED)
#endif

#ifndef HAPTIC_OFF_IN_LOW_POWER
# define HAPTIC_OFF_IN_LOW_POWER 0
#endif
3 changes: 2 additions & 1 deletion quantum/process_keycode/process_haptic.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "process_haptic.h"
#include "quantum_keycodes.h"
#include "action_tapping.h"
#include "usb_device_state.h"

__attribute__((weak)) bool get_haptic_enabled_key(uint16_t keycode, keyrecord_t *record) {
switch (keycode) {
Expand Down Expand Up @@ -131,7 +132,7 @@ bool process_haptic(uint16_t keycode, keyrecord_t *record) {
}
}

if (haptic_get_enable()) {
if (haptic_get_enable() && ((!HAPTIC_OFF_IN_LOW_POWER) || (usb_device_state == USB_DEVICE_STATE_CONFIGURED))) {
if (record->event.pressed) {
// keypress
if (haptic_get_feedback() < 2 && get_haptic_enabled_key(keycode, record)) {
Expand Down
10 changes: 9 additions & 1 deletion tmk_core/protocol/usb_device_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,22 @@
*/

#include "usb_device_state.h"
#if defined(HAPTIC_ENABLE)
# include "haptic.h"
#endif

enum usb_device_state usb_device_state = USB_DEVICE_STATE_NO_INIT;

__attribute__((weak)) void notify_usb_device_state_change_kb(enum usb_device_state usb_device_state) { notify_usb_device_state_change_user(usb_device_state); }

__attribute__((weak)) void notify_usb_device_state_change_user(enum usb_device_state usb_device_state) {}

static void notify_usb_device_state_change(enum usb_device_state usb_device_state) { notify_usb_device_state_change_kb(usb_device_state); }
static void notify_usb_device_state_change(enum usb_device_state usb_device_state) {
#if defined(HAPTIC_ENABLE) && HAPTIC_OFF_IN_LOW_POWER
haptic_notify_usb_device_state_change();
#endif
notify_usb_device_state_change_kb(usb_device_state);
}

void usb_device_state_set_configuration(bool isConfigured, uint8_t configurationNumber) {
usb_device_state = isConfigured ? USB_DEVICE_STATE_CONFIGURED : USB_DEVICE_STATE_INIT;
Expand Down