aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorishtob <ishtob@gmail.com>2019-02-16 21:39:30 -0500
committerMechMerlin <30334081+mechmerlin@users.noreply.github.com>2019-02-16 18:39:30 -0800
commit2cee371bf125a6ec541dd7c5a809573facc7c456 (patch)
tree7bb6c074b759843d531eee67d65d91618bd79732
parenta7a647b7f6d707e9c952461beeca1f3637039d36 (diff)
downloadqmk_firmware-2cee371bf125a6ec541dd7c5a809573facc7c456.tar.gz
qmk_firmware-2cee371bf125a6ec541dd7c5a809573facc7c456.zip
Haptic feedback generalized - DRV2605 and solenoids (#4939)
* initial work to add eeprom to haptic feedback and decouple the feedback process from keyboards * Haptic feedback enhancements: on/off toggle working, feedback order working todo: -work on modes switching -get modes switching to save to eeprom * haptic enhancement - eeprom and modes added * Added set and get functions for haptic feedback * initial implementation of solenoids under haptic feedback * changed eeprom to 32 bits to reserve blocks for future features * start documentation of haptic feedback * change keycode per comment from reviewers * typo fixes * added eeprom for solenoid configs * added solenoid and docs * Add/fix default parameters configs, improve docs * more doc cleanup * add in solenoid buzz toggle, clean up doc * some fixes for error in compiling solenoid * fix a chibios specific i2c read function and added one for AVR controllers in DRV2605L.c * fixes for avr side issues * update keymap * fix keymap compile error * fix bugs found during solenoid testing * set pin that is not powered during bootloader * added warning about certain pins on the MCU may trip solenoid during DFU/bootloader
-rw-r--r--common_features.mk10
-rw-r--r--docs/feature_haptic_feedback.md147
-rw-r--r--drivers/haptic/DRV2605L.c24
-rw-r--r--drivers/haptic/DRV2605L.h26
-rw-r--r--drivers/haptic/haptic.c248
-rw-r--r--drivers/haptic/haptic.h82
-rw-r--r--drivers/haptic/solenoid.c109
-rw-r--r--drivers/haptic/solenoid.h54
-rw-r--r--keyboards/hadron/ver3/config.h3
-rw-r--r--keyboards/hadron/ver3/keymaps/default/keymap.c4
-rw-r--r--keyboards/hadron/ver3/keymaps/ishtob/keymap.c2
-rw-r--r--keyboards/hadron/ver3/rules.mk2
-rw-r--r--keyboards/hadron/ver3/ver3.c10
-rw-r--r--quantum/quantum.c16
-rw-r--r--quantum/quantum.h4
-rw-r--r--quantum/quantum_keycodes.h49
-rw-r--r--tmk_core/common/eeconfig.c9
-rw-r--r--tmk_core/common/eeconfig.h7
18 files changed, 754 insertions, 52 deletions
diff --git a/common_features.mk b/common_features.mk
index 6f02dbac6..3d3b8506e 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -246,11 +246,21 @@ endif
246 246
247ifeq ($(strip $(HAPTIC_ENABLE)), DRV2605L) 247ifeq ($(strip $(HAPTIC_ENABLE)), DRV2605L)
248 COMMON_VPATH += $(DRIVER_PATH)/haptic 248 COMMON_VPATH += $(DRIVER_PATH)/haptic
249 SRC += haptic.c
249 SRC += DRV2605L.c 250 SRC += DRV2605L.c
250 SRC += i2c_master.c 251 SRC += i2c_master.c
252 OPT_DEFS += -DHAPTIC_ENABLE
251 OPT_DEFS += -DDRV2605L 253 OPT_DEFS += -DDRV2605L
252endif 254endif
253 255
256ifeq ($(strip $(HAPTIC_ENABLE)), SOLENOID)
257 COMMON_VPATH += $(DRIVER_PATH)/haptic
258 SRC += haptic.c
259 SRC += solenoid.c
260 OPT_DEFS += -DHAPTIC_ENABLE
261 OPT_DEFS += -DSOLENOID_ENABLE
262endif
263
254ifeq ($(strip $(HD44780_ENABLE)), yes) 264ifeq ($(strip $(HD44780_ENABLE)), yes)
255 SRC += drivers/avr/hd44780.c 265 SRC += drivers/avr/hd44780.c
256 OPT_DEFS += -DHD44780_ENABLE 266 OPT_DEFS += -DHD44780_ENABLE
diff --git a/docs/feature_haptic_feedback.md b/docs/feature_haptic_feedback.md
new file mode 100644
index 000000000..85fd43964
--- /dev/null
+++ b/docs/feature_haptic_feedback.md
@@ -0,0 +1,147 @@
1# Haptic Feedback
2
3## Haptic feedback rules.mk options
4
5The following options are currently available for haptic feedback in `rule.mk`:
6
7`HAPTIC_ENABLE += DRV2605L`
8
9`HAPTIC_ENABLE += SOLENOID`
10
11## Known Supported Hardware
12
13| Name | Description |
14|--------------------|-------------------------------------------------|
15| [LV061228B-L65-A](https://www.digikey.com/product-detail/en/jinlong-machinery-electronics-inc/LV061228B-L65-A/1670-1050-ND/7732325) | z-axis 2v LRA |
16| [Mini Motor Disc](https://www.adafruit.com/product/1201) | small 2-5v ERM |
17
18## Haptic Keycodes
19
20Not all keycodes below will work depending on which haptic mechanism you have chosen.
21
22| Name | Description |
23|-----------|-------------------------------------------------------|
24|`HPT_ON` | Turn haptic feedback on |
25|`HPT_OFF` | Turn haptic feedback on |
26|`HPT_TOG` | Toggle haptic feedback on/off |
27|`HPT_RST` | Reset haptic feedback config to default |
28|`HPT_FBK` | Toggle feedback to occur on keypress, release or both |
29|`HPT_BUZ` | Toggle solenoid buzz on/off |
30|`HPT_MODI` | Go to next DRV2605L waveform |
31|`HPT_MODD` | Go to previous DRV2605L waveform |
32|`HPT_DWLI` | Increase Solenoid dwell time |
33|`HPT_DWLD` | Decrease Solenoid dwell time |
34
35### Solenoids
36
37First you will need a build a circuit to drive the solenoid through a mosfet as most MCU will not be able to provide the current needed to drive the coil in the solenoid.
38
39[Wiring diagram provided by Adafruit](https://playground.arduino.cc/uploads/Learning/solenoid_driver.pdf)
40
41Select a pin that has PWM for the signal pin
42
43```
44#define SOLENOID_PIN *pin*
45```
46
47Beware that some pins may be powered during bootloader (ie. A13 on the STM32F303 chip) and will result in the solenoid kept in the on state through the whole flashing process. This may overheat and damage the solenoid. If you find that the pin the solenoid is connected to is triggering the solenoid during bootloader/DFU, select another pin.
48
49### DRV2605L
50
51DRV2605L is controlled over i2c protocol, and has to be connected to the SDA and SCL pins, these varies depending on the MCU in use.
52
53#### Feedback motor setup
54
55This driver supports 2 different feedback motors. Set the following in your `config.h` based on which motor you have selected.
56
57##### ERM
58
59Eccentric Rotating Mass vibration motors (ERM) is motor with a off-set weight attached so when drive signal is attached, the off-set weight spins and causes a sinusoidal wave that translate into vibrations.
60
61```
62#define FB_ERM_LRA 0
63#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
64#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
65
66/* Please refer to your datasheet for the optimal setting for your specific motor. */
67#define RATED_VOLTAGE 3
68#define V_PEAK 5
69```
70##### LRA
71
72Linear resonant actuators (LRA, also know as a linear vibrator) works different from a ERM. A LRA has a weight and magnet suspended by springs and a voice coil. When the drive signal is applied, the weight would be vibrate on a single axis (side to side or up and down). Since the weight is attached to a spring, there is a resonance effect at a specific frequency. This frequency is where the LRA will operate the most efficiently. Refer to the motor's datasheet for the recommanded range for this frequency.
73
74```
75#define FB_ERM_LRA 1
76#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
77#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
78
79/* Please refer to your datasheet for the optimal setting for your specific motor. */
80#define RATED_VOLTAGE 2
81#define V_PEAK 2.8
82#define V_RMS 2.0
83#define V_PEAK 2.1
84#define F_LRA 205 /* resonance freq */
85```
86
87#### DRV2605L waveform library
88
89DRV2605L comes with preloaded library of various waveform sequences that can be called and played. If writing a macro, these waveforms can be played using `DRV_pulse(*sequence name or number*)`
90
91List of waveform sequences from the datasheet:
92
93|seq# | Sequence name |seq# | Sequence name |seq# |Sequence name |
94|-----|---------------------|-----|-----------------------------------|-----|--------------------------------------|
95| 1 | strong_click | 43 | lg_dblclick_med_60 | 85 | transition_rampup_med_smooth2 |
96| 2 | strong_click_60 | 44 | lg_dblsharp_tick | 86 | transition_rampup_short_smooth1 |
97| 3 | strong_click_30 | 45 | lg_dblsharp_tick_80 | 87 | transition_rampup_short_smooth2 |
98| 4 | sharp_click | 46 | lg_dblsharp_tick_60 | 88 | transition_rampup_long_sharp1 |
99| 5 | sharp_click_60 | 47 | buzz | 89 | transition_rampup_long_sharp2 |
100| 6 | sharp_click_30 | 48 | buzz_80 | 90 | transition_rampup_med_sharp1 |
101| 7 | soft_bump | 49 | buzz_60 | 91 | transition_rampup_med_sharp2 |
102| 8 | soft_bump_60 | 50 | buzz_40 | 92 | transition_rampup_short_sharp1 |
103| 9 | soft_bump_30 | 51 | buzz_20 | 93 | transition_rampup_short_sharp2 |
104| 10 | dbl_click | 52 | pulsing_strong | 94 | transition_rampdown_long_smooth1_50 |
105| 11 | dbl_click_60 | 53 | pulsing_strong_80 | 95 | transition_rampdown_long_smooth2_50 |
106| 12 | trp_click | 54 | pulsing_medium | 96 | transition_rampdown_med_smooth1_50 |
107| 13 | soft_fuzz | 55 | pulsing_medium_80 | 97 | transition_rampdown_med_smooth2_50 |
108| 14 | strong_buzz | 56 | pulsing_sharp | 98 | transition_rampdown_short_smooth1_50 |
109| 15 | alert_750ms | 57 | pulsing_sharp_80 | 99 | transition_rampdown_short_smooth2_50 |
110| 16 | alert_1000ms | 58 | transition_click | 100 | transition_rampdown_long_sharp1_50 |
111| 17 | strong_click1 | 59 | transition_click_80 | 101 | transition_rampdown_long_sharp2_50 |
112| 18 | strong_click2_80 | 60 | transition_click_60 | 102 | transition_rampdown_med_sharp1_50 |
113| 19 | strong_click3_60 | 61 | transition_click_40 | 103 | transition_rampdown_med_sharp2_50 |
114| 20 | strong_click4_30 | 62 | transition_click_20 | 104 | transition_rampdown_short_sharp1_50 |
115| 21 | medium_click1 | 63 | transition_click_10 | 105 | transition_rampdown_short_sharp2_50 |
116| 22 | medium_click2_80 | 64 | transition_hum | 106 | transition_rampup_long_smooth1_50 |
117| 23 | medium_click3_60 | 65 | transition_hum_80 | 107 | transition_rampup_long_smooth2_50 |
118| 24 | sharp_tick1 | 66 | transition_hum_60 | 108 | transition_rampup_med_smooth1_50 |
119| 25 | sharp_tick2_80 | 67 | transition_hum_40 | 109 | transition_rampup_med_smooth2_50 |
120| 26 | sharp_tick3_60 | 68 | transition_hum_20 | 110 | transition_rampup_short_smooth1_50 |
121| 27 | sh_dblclick_str | 69 | transition_hum_10 | 111 | transition_rampup_short_smooth2_50 |
122| 28 | sh_dblclick_str_80 | 70 | transition_rampdown_long_smooth1 | 112 | transition_rampup_long_sharp1_50 |
123| 29 | sh_dblclick_str_60 | 71 | transition_rampdown_long_smooth2 | 113 | transition_rampup_long_sharp2_50 |
124| 30 | sh_dblclick_str_30 | 72 | transition_rampdown_med_smooth1 | 114 | transition_rampup_med_sharp1_50 |
125| 31 | sh_dblclick_med | 73 | transition_rampdown_med_smooth2 | 115 | transition_rampup_med_sharp2_50 |
126| 32 | sh_dblclick_med_80 | 74 | transition_rampdown_short_smooth1 | 116 | transition_rampup_short_sharp1_50 |
127| 33 | sh_dblclick_med_60 | 75 | transition_rampdown_short_smooth2 | 117 | transition_rampup_short_sharp2_50 |
128| 34 | sh_dblsharp_tick | 76 | transition_rampdown_long_sharp1 | 118 | long_buzz_for_programmatic_stopping |
129| 35 | sh_dblsharp_tick_80 | 77 | transition_rampdown_long_sharp2 | 119 | smooth_hum1_50 |
130| 36 | sh_dblsharp_tick_60 | 78 | transition_rampdown_med_sharp1 | 120 | smooth_hum2_40 |
131| 37 | lg_dblclick_str | 79 | transition_rampdown_med_sharp2 | 121 | smooth_hum3_30 |
132| 38 | lg_dblclick_str_80 | 80 | transition_rampdown_short_sharp1 | 122 | smooth_hum4_20 |
133| 39 | lg_dblclick_str_60 | 81 | transition_rampdown_short_sharp2 | 123 | smooth_hum5_10 |
134| 40 | lg_dblclick_str_30 | 82 | transition_rampup_long_smooth1 | | |
135| 41 | lg_dblclick_med | 83 | transition_rampup_long_smooth2 | | |
136| 42 | lg_dblclick_med_80 | 84 | transition_rampup_med_smooth1 | | |
137### Optional DRV2605L defines
138
139```
140#define DRV_GREETING *sequence name or number*
141```
142If haptic feedback is enabled, the keyboard will vibrate to a specific sqeuence during startup. That can be selected using the following define:
143
144```
145#define DRV_MODE_DEFAULT *sequence name or number*
146```
147This will set what sequence HPT_RST will set as the active mode. If not defined, mode will be set to 1 when HPT_RST is pressed.
diff --git a/drivers/haptic/DRV2605L.c b/drivers/haptic/DRV2605L.c
index 97ca292b9..215e6be3e 100644
--- a/drivers/haptic/DRV2605L.c
+++ b/drivers/haptic/DRV2605L.c
@@ -21,7 +21,7 @@
21#include <math.h> 21#include <math.h>
22 22
23 23
24uint8_t DRV2605L_transfer_buffer[20]; 24uint8_t DRV2605L_transfer_buffer[2];
25uint8_t DRV2605L_tx_register[0]; 25uint8_t DRV2605L_tx_register[0];
26uint8_t DRV2605L_read_buffer[0]; 26uint8_t DRV2605L_read_buffer[0];
27uint8_t DRV2605L_read_register; 27uint8_t DRV2605L_read_register;
@@ -34,6 +34,11 @@ void DRV_write(uint8_t drv_register, uint8_t settings) {
34} 34}
35 35
36uint8_t DRV_read(uint8_t regaddress) { 36uint8_t DRV_read(uint8_t regaddress) {
37#ifdef __AVR__
38 i2c_readReg(DRV2605L_BASE_ADDRESS << 1,
39 regaddress, DRV2605L_read_buffer, 1, 100);
40 DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
41#else
37 DRV2605L_tx_register[0] = regaddress; 42 DRV2605L_tx_register[0] = regaddress;
38 if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1, 43 if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1,
39 DRV2605L_tx_register, 1, 44 DRV2605L_tx_register, 1,
@@ -42,14 +47,13 @@ uint8_t DRV_read(uint8_t regaddress) {
42 printf("err reading reg \n"); 47 printf("err reading reg \n");
43 } 48 }
44 DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0]; 49 DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
50#endif
45return DRV2605L_read_register; 51return DRV2605L_read_register;
46} 52}
47 53
48void DRV_init(void) 54void DRV_init(void)
49{ 55{
50 i2c_init(); 56 i2c_init();
51 i2c_start(DRV2605L_BASE_ADDRESS);
52
53 /* 0x07 sets DRV2605 into calibration mode */ 57 /* 0x07 sets DRV2605 into calibration mode */
54 DRV_write(DRV_MODE,0x07); 58 DRV_write(DRV_MODE,0x07);
55 59
@@ -104,21 +108,17 @@ void DRV_init(void)
104 C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME; 108 C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME;
105 DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte); 109 DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte);
106 DRV_write(DRV_LIB_SELECTION,LIB_SELECTION); 110 DRV_write(DRV_LIB_SELECTION,LIB_SELECTION);
107 //start autocalibration 111
108 DRV_write(DRV_GO, 0x01); 112 DRV_write(DRV_GO, 0x01);
109 113
110 /* 0x00 sets DRV2605 out of standby and to use internal trigger 114 /* 0x00 sets DRV2605 out of standby and to use internal trigger
111 * 0x01 sets DRV2605 out of standby and to use external trigger */ 115 * 0x01 sets DRV2605 out of standby and to use external trigger */
112 DRV_write(DRV_MODE,0x00); 116 DRV_write(DRV_MODE,0x00);
113
114 /* 0x06: LRA library */
115 DRV_write(DRV_WAVEFORM_SEQ_1, 0x01);
116
117 /* 0xB9: LRA, 4x brake factor, medium gain, 7.5x back EMF
118 * 0x39: ERM, 4x brake factor, medium gain, 1.365x back EMF */
119
120 /* TODO: setup auto-calibration as part of initiation */
121 117
118//Play greeting sequence
119 DRV_write(DRV_GO, 0x00);
120 DRV_write(DRV_WAVEFORM_SEQ_1, DRV_GREETING);
121 DRV_write(DRV_GO, 0x01);
122} 122}
123 123
124void DRV_pulse(uint8_t sequence) 124void DRV_pulse(uint8_t sequence)
diff --git a/drivers/haptic/DRV2605L.h b/drivers/haptic/DRV2605L.h
index de9d294e9..836e9cbcd 100644
--- a/drivers/haptic/DRV2605L.h
+++ b/drivers/haptic/DRV2605L.h
@@ -31,13 +31,6 @@
31#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */ 31#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
32#endif 32#endif
33 33
34#ifndef RATED_VOLTAGE
35#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */
36#ifndef V_PEAK
37#define V_PEAK 2.8
38#endif
39#endif
40
41/* LRA specific settings */ 34/* LRA specific settings */
42#if FB_ERM_LRA == 1 35#if FB_ERM_LRA == 1
43#ifndef V_RMS 36#ifndef V_RMS
@@ -49,6 +42,16 @@
49#ifndef F_LRA 42#ifndef F_LRA
50#define F_LRA 205 43#define F_LRA 205
51#endif 44#endif
45#ifndef RATED_VOLTAGE
46#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */
47#endif
48#endif
49
50#ifndef RATED_VOLTAGE
51#define RATED_VOLTAGE 2 /* 2v as safe range in case device voltage is not set */
52#endif
53#ifndef V_PEAK
54#define V_PEAK 2.8
52#endif 55#endif
53 56
54/* Library Selection */ 57/* Library Selection */
@@ -60,6 +63,13 @@
60#endif 63#endif
61#endif 64#endif
62 65
66#ifndef DRV_GREETING
67#define DRV_GREETING alert_750ms
68#endif
69#ifndef DRV_MODE_DEFAULT
70#define DRV_MODE_DEFAULT strong_click1
71#endif
72
63/* Control 1 register settings */ 73/* Control 1 register settings */
64#ifndef DRIVE_TIME 74#ifndef DRIVE_TIME
65#define DRIVE_TIME 25 75#define DRIVE_TIME 25
@@ -162,7 +172,6 @@ void DRV_write(const uint8_t drv_register, const uint8_t settings);
162uint8_t DRV_read(const uint8_t regaddress); 172uint8_t DRV_read(const uint8_t regaddress);
163void DRV_pulse(const uint8_t sequence); 173void DRV_pulse(const uint8_t sequence);
164 174
165
166typedef enum DRV_EFFECT{ 175typedef enum DRV_EFFECT{
167 clear_sequence = 0, 176 clear_sequence = 0,
168 strong_click = 1, 177 strong_click = 1,
@@ -288,6 +297,7 @@ typedef enum DRV_EFFECT{
288 smooth_hum3_30 = 121, 297 smooth_hum3_30 = 121,
289 smooth_hum4_20 = 122, 298 smooth_hum4_20 = 122,
290 smooth_hum5_10 = 123, 299 smooth_hum5_10 = 123,
300 drv_effect_max = 124,
291} DRV_EFFECT; 301} DRV_EFFECT;
292 302
293/* Register bit array unions */ 303/* Register bit array unions */
diff --git a/drivers/haptic/haptic.c b/drivers/haptic/haptic.c
new file mode 100644
index 000000000..a94f05565
--- /dev/null
+++ b/drivers/haptic/haptic.c
@@ -0,0 +1,248 @@
1/* Copyright 2019 ishtob
2 * Driver for haptic feedback written for QMK
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17#include "haptic.h"
18#include "eeconfig.h"
19#include "progmem.h"
20#include "debug.h"
21#ifdef DRV2605L
22#include "DRV2605L.h"
23#endif
24#ifdef SOLENOID_ENABLE
25#include "solenoid.h"
26#endif
27
28haptic_config_t haptic_config;
29
30void haptic_init(void) {
31 debug_enable = 1; //Debug is ON!
32 if (!eeconfig_is_enabled()) {
33 eeconfig_init();
34 }
35 haptic_config.raw = eeconfig_read_haptic();
36 if (haptic_config.mode < 1){
37 haptic_config.mode = 1;
38 }
39 if (!haptic_config.mode){
40 dprintf("No haptic config found in eeprom, setting default configs\n");
41 haptic_reset();
42 }
43 #ifdef SOLENOID_ENABLE
44 solenoid_setup();
45 dprintf("Solenoid driver initialized\n");
46 #endif
47 #ifdef DRV2605L
48 DRV_init();
49 dprintf("DRV2605 driver initialized\n");
50 #endif
51 eeconfig_debug_haptic();
52}
53
54void haptic_task(void) {
55 #ifdef SOLENOID_ENABLE
56 solenoid_check();
57 #endif
58}
59
60void eeconfig_debug_haptic(void) {
61 dprintf("haptic_config eprom\n");
62 dprintf("haptic_config.enable = %d\n", haptic_config.enable);
63 dprintf("haptic_config.mode = %d\n", haptic_config.mode);
64}
65
66void haptic_enable(void) {
67 haptic_config.enable = 1;
68 xprintf("haptic_config.enable = %u\n", haptic_config.enable);
69 eeconfig_update_haptic(haptic_config.raw);
70}
71
72void haptic_disable(void) {
73 haptic_config.enable = 0;
74 xprintf("haptic_config.enable = %u\n", haptic_config.enable);
75 eeconfig_update_haptic(haptic_config.raw);
76}
77
78void haptic_toggle(void) {
79if (haptic_config.enable) {
80 haptic_disable();
81 } else {
82 haptic_enable();
83 }
84 eeconfig_update_haptic(haptic_config.raw);
85}
86
87void haptic_feedback_toggle(void){
88 haptic_config.feedback++;
89 if (haptic_config.feedback >= HAPTIC_FEEDBACK_MAX)
90 haptic_config.feedback = KEY_PRESS;
91 xprintf("haptic_config.feedback = %u\n", !haptic_config.feedback);
92 eeconfig_update_haptic(haptic_config.raw);
93}
94
95void haptic_buzz_toggle(void) {
96 bool buzz_stat = !haptic_config.buzz;
97 haptic_config.buzz = buzz_stat;
98 haptic_set_buzz(buzz_stat);
99}
100
101void haptic_mode_increase(void) {
102 uint8_t mode = haptic_config.mode + 1;
103 #ifdef DRV2605L
104 if (haptic_config.mode >= drv_effect_max) {
105 mode = 1;
106 }
107 #endif
108 haptic_set_mode(mode);
109}
110
111void haptic_mode_decrease(void) {
112 uint8_t mode = haptic_config.mode -1;
113 #ifdef DRV2605L
114 if (haptic_config.mode < 1) {
115 mode = (drv_effect_max - 1);
116 }
117 #endif
118 haptic_set_mode(mode);
119}
120
121void haptic_dwell_increase(void) {
122 uint8_t dwell = haptic_config.dwell + 1;
123 #ifdef SOLENOID_ENABLE
124 if (haptic_config.dwell >= SOLENOID_MAX_DWELL) {
125 dwell = 1;
126 }
127 solenoid_set_dwell(dwell);
128 #endif
129 haptic_set_dwell(dwell);
130}
131
132void haptic_dwell_decrease(void) {
133 uint8_t dwell = haptic_config.dwell -1;
134 #ifdef SOLENOID_ENABLE
135 if (haptic_config.dwell < SOLENOID_MIN_DWELL) {
136 dwell = SOLENOID_MAX_DWELL;
137 }
138 solenoid_set_dwell(dwell);
139 #endif
140 haptic_set_dwell(dwell);
141}
142
143void haptic_reset(void){
144 haptic_config.enable = true;
145 uint8_t feedback = HAPTIC_FEEDBACK_DEFAULT;
146 haptic_config.feedback = feedback;
147 #ifdef DRV2605L
148 uint8_t mode = HAPTIC_MODE_DEFAULT;
149 haptic_config.mode = mode;
150 #endif
151 #ifdef SOLENOID_ENABLE
152 uint8_t dwell = SOLENOID_DEFAULT_DWELL;
153 haptic_config.dwell = dwell;
154 #endif
155 eeconfig_update_haptic(haptic_config.raw);
156 xprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
157 xprintf("haptic_config.mode = %u\n", haptic_config.mode);
158}
159
160void haptic_set_feedback(uint8_t feedback) {
161 haptic_config.feedback = feedback;
162 eeconfig_update_haptic(haptic_config.raw);
163 xprintf("haptic_config.feedback = %u\n", haptic_config.feedback);
164}
165
166void haptic_set_mode(uint8_t mode) {
167 haptic_config.mode = mode;
168 eeconfig_update_haptic(haptic_config.raw);
169 xprintf("haptic_config.mode = %u\n", haptic_config.mode);
170}
171
172void haptic_set_buzz(uint8_t buzz) {
173 haptic_config.buzz = buzz;
174 eeconfig_update_haptic(haptic_config.raw);
175 xprintf("haptic_config.buzz = %u\n", haptic_config.buzz);
176}
177
178void haptic_set_dwell(uint8_t dwell) {
179 haptic_config.dwell = dwell;
180 eeconfig_update_haptic(haptic_config.raw);
181 xprintf("haptic_config.dwell = %u\n", haptic_config.dwell);
182}
183
184uint8_t haptic_get_mode(void) {
185 if (!haptic_config.enable){
186 return false;
187 }
188 return haptic_config.mode;
189}
190
191uint8_t haptic_get_feedback(void) {
192 if (!haptic_config.enable){
193 return false;
194 }
195 return haptic_config.feedback;
196}
197
198uint8_t haptic_get_dwell(void) {
199 if (!haptic_config.enable){
200 return false;
201 }
202 return haptic_config.dwell;
203}
204
205void haptic_play(void) {
206 #ifdef DRV2605L
207 uint8_t play_eff = 0;
208 play_eff = haptic_config.mode;
209 DRV_pulse(play_eff);
210 #endif
211 #ifdef SOLENOID_ENABLE
212 solenoid_fire();
213 #endif
214}
215
216bool process_haptic(uint16_t keycode, keyrecord_t *record) {
217 if (keycode == HPT_ON && record->event.pressed) { haptic_enable(); }
218 if (keycode == HPT_OFF && record->event.pressed) { haptic_disable(); }
219 if (keycode == HPT_TOG && record->event.pressed) { haptic_toggle(); }
220 if (keycode == HPT_RST && record->event.pressed) { haptic_reset(); }
221 if (keycode == HPT_FBK && record->event.pressed) { haptic_feedback_toggle(); }
222 if (keycode == HPT_BUZ && record->event.pressed) { haptic_buzz_toggle(); }
223 if (keycode == HPT_MODI && record->event.pressed) { haptic_mode_increase(); }
224 if (keycode == HPT_MODD && record->event.pressed) { haptic_mode_decrease(); }
225 if (keycode == HPT_DWLI && record->event.pressed) { haptic_dwell_increase(); }
226 if (keycode == HPT_DWLD && record->event.pressed) { haptic_dwell_decrease(); }
227 if (haptic_config.enable) {
228 if ( record->event.pressed ) {
229 // keypress
230 if (haptic_config.feedback < 2) {
231 haptic_play();
232 }
233 } else {
234 //keyrelease
235 if (haptic_config.feedback > 0) {
236 haptic_play();
237 }
238 }
239 }
240 return true;
241}
242
243void haptic_shutdown(void) {
244 #ifdef SOLENOID_ENABLE
245 solenoid_shutdown();
246 #endif
247
248}
diff --git a/drivers/haptic/haptic.h b/drivers/haptic/haptic.h
new file mode 100644
index 000000000..d39dc5c3b
--- /dev/null
+++ b/drivers/haptic/haptic.h
@@ -0,0 +1,82 @@
1/* Copyright 2019 ishtob
2 * Driver for haptic feedback written for QMK
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19#include <stdint.h>
20#include <stdbool.h>
21#include "quantum.h"
22#ifdef DRV2605L
23#include "DRV2605L.h"
24#endif
25
26
27#ifndef HAPTIC_FEEDBACK_DEFAULT
28#define HAPTIC_FEEDBACK_DEFAULT 0
29#endif
30#ifndef HAPTIC_MODE_DEFAULT
31#define HAPTIC_MODE_DEFAULT DRV_MODE_DEFAULT
32#endif
33
34/* EEPROM config settings */
35typedef union {
36 uint32_t raw;
37 struct {
38 bool enable :1;
39 uint8_t feedback :2;
40 uint8_t mode :7;
41 bool buzz :1;
42 uint8_t dwell :7;
43 uint16_t reserved :16;
44 };
45} haptic_config_t;
46
47typedef enum HAPTIC_FEEDBACK{
48 KEY_PRESS,
49 KEY_PRESS_RELEASE,
50 KEY_RELEASE,
51 HAPTIC_FEEDBACK_MAX,
52} HAPTIC_FEEDBACK;
53
54bool process_haptic(uint16_t keycode, keyrecord_t *record);
55void haptic_init(void);
56void haptic_task(void);
57void eeconfig_debug_haptic(void);
58void haptic_enable(void);
59void haptic_disable(void);
60void haptic_toggle(void);
61void haptic_feedback_toggle(void);
62void haptic_mode_increase(void);
63void haptic_mode_decrease(void);
64void haptic_mode(uint8_t mode);
65void haptic_reset(void);
66void haptic_set_feedback(uint8_t feedback);
67void haptic_set_mode(uint8_t mode);
68void haptic_set_dwell(uint8_t dwell);
69void haptic_set_buzz(uint8_t buzz);
70void haptic_buzz_toggle(void);
71uint8_t haptic_get_mode(void);
72uint8_t haptic_get_feedback(void);
73void haptic_dwell_increase(void);
74void haptic_dwell_decrease(void);
75
76void haptic_play(void);
77void haptic_shutdown(void);
78
79
80
81
82
diff --git a/drivers/haptic/solenoid.c b/drivers/haptic/solenoid.c
new file mode 100644
index 000000000..2d39dbc17
--- /dev/null
+++ b/drivers/haptic/solenoid.c
@@ -0,0 +1,109 @@
1/* Copyright 2018 mtdjr - modified by ishtob
2 * Driver for solenoid written for QMK
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <timer.h>
19#include "solenoid.h"
20#include "haptic.h"
21
22bool solenoid_on = false;
23bool solenoid_buzzing = false;
24uint16_t solenoid_start = 0;
25uint8_t solenoid_dwell = SOLENOID_DEFAULT_DWELL;
26
27extern haptic_config_t haptic_config;
28
29
30void solenoid_buzz_on(void) {
31 haptic_set_buzz(1);
32}
33
34void solenoid_buzz_off(void) {
35 haptic_set_buzz(0);
36}
37
38void solenoid_set_buzz(int buzz) {
39 haptic_set_buzz(buzz);
40}
41
42
43void solenoid_dwell_minus(uint8_t solenoid_dwell) {
44 if (solenoid_dwell > 0) solenoid_dwell--;
45}
46
47void solenoid_dwell_plus(uint8_t solenoid_dwell) {
48 if (solenoid_dwell < SOLENOID_MAX_DWELL) solenoid_dwell++;
49}
50
51void solenoid_set_dwell(uint8_t dwell) {
52 solenoid_dwell = dwell;
53}
54
55void solenoid_stop(void) {
56 writePinLow(SOLENOID_PIN);
57 solenoid_on = false;
58 solenoid_buzzing = false;
59}
60
61void solenoid_fire(void) {
62 if (!haptic_config.buzz && solenoid_on) return;
63 if (haptic_config.buzz && solenoid_buzzing) return;
64
65 solenoid_on = true;
66 solenoid_buzzing = true;
67 solenoid_start = timer_read();
68 writePinHigh(SOLENOID_PIN);
69}
70
71void solenoid_check(void) {
72 uint16_t elapsed = 0;
73
74 if (!solenoid_on) return;
75
76 elapsed = timer_elapsed(solenoid_start);
77
78 //Check if it's time to finish this solenoid click cycle
79 if (elapsed > solenoid_dwell) {
80 solenoid_stop();
81 return;
82 }
83
84 //Check whether to buzz the solenoid on and off
85 if (haptic_config.buzz) {
86 if (elapsed / SOLENOID_MIN_DWELL % 2 == 0){
87 if (!solenoid_buzzing) {
88 solenoid_buzzing = true;
89 writePinHigh(SOLENOID_PIN);
90 }
91 }
92 else {
93 if (solenoid_buzzing) {
94 solenoid_buzzing = false;
95 writePinLow(SOLENOID_PIN);
96 }
97 }
98 }
99}
100
101void solenoid_setup(void) {
102 setPinOutput(SOLENOID_PIN);
103 solenoid_fire();
104}
105
106void solenoid_shutdown(void) {
107 writePinLow(SOLENOID_PIN);
108
109}
diff --git a/drivers/haptic/solenoid.h b/drivers/haptic/solenoid.h
new file mode 100644
index 000000000..a08f62a11
--- /dev/null
+++ b/drivers/haptic/solenoid.h
@@ -0,0 +1,54 @@
1/* Copyright 2018 mtdjr - modified by ishtob
2 * Driver for solenoid written for QMK
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#pragma once
19
20#ifndef SOLENOID_DEFAULT_DWELL
21#define SOLENOID_DEFAULT_DWELL 12
22#endif
23
24#ifndef SOLENOID_MAX_DWELL
25#define SOLENOID_MAX_DWELL 100
26#endif
27
28#ifndef SOLENOID_MIN_DWELL
29#define SOLENOID_MIN_DWELL 4
30#endif
31
32#ifndef SOLENOID_ACTIVE
33#define SOLENOID_ACTIVE false
34#endif
35
36#ifndef SOLENOID_PIN
37#define SOLENOID_PIN F6
38#endif
39
40void solenoid_buzz_on(void);
41void solenoid_buzz_off(void);
42void solenoid_set_buzz(int buzz);
43
44void solenoid_dwell_minus(uint8_t solenoid_dwell);
45void solenoid_dwell_plus(uint8_t solenoid_dwell);
46void solenoid_set_dwell(uint8_t dwell);
47
48void solenoid_stop(void);
49void solenoid_fire(void);
50
51void solenoid_check(void);
52
53void solenoid_setup(void);
54void solenoid_shutdown(void);
diff --git a/keyboards/hadron/ver3/config.h b/keyboards/hadron/ver3/config.h
index d6c3830df..180492182 100644
--- a/keyboards/hadron/ver3/config.h
+++ b/keyboards/hadron/ver3/config.h
@@ -192,4 +192,7 @@
192//#define DRIVER_LED_TOTAL RGBLED_NUM 192//#define DRIVER_LED_TOTAL RGBLED_NUM
193 193
194//#define RGB_MATRIX_KEYPRESSES 194//#define RGB_MATRIX_KEYPRESSES
195
196#define SOLENOID_PIN A14
197
195#endif 198#endif
diff --git a/keyboards/hadron/ver3/keymaps/default/keymap.c b/keyboards/hadron/ver3/keymaps/default/keymap.c
index 11761b321..507c8314b 100644
--- a/keyboards/hadron/ver3/keymaps/default/keymap.c
+++ b/keyboards/hadron/ver3/keymaps/default/keymap.c
@@ -190,8 +190,8 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
190 * `--------------------------------------------------------------------------------------------------------' 190 * `--------------------------------------------------------------------------------------------------------'
191 */ 191 */
192[_ADJUST] = LAYOUT( 192[_ADJUST] = LAYOUT(
193 KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \ 193 RESET, HPT_TOG, HPT_FBK, HPT_MODI, HPT_MODD, HPT_RST , _______, _______, _______, _______, _______, _______, \
194 RESET, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, _______, _______, _______, _______, _______, KC_DEL, \ 194 _______, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, _______, _______, _______, _______, _______, KC_DEL, \
195 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, _______, _______, _______, AG_SWAP, QWERTY, COLEMAK, _______, _______, _______, \ 195 _______, _______, _______, AU_ON, AU_OFF, AG_NORM, _______, _______, _______, AG_SWAP, QWERTY, COLEMAK, _______, _______, _______, \
196 _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, BL_DEC, BL_INC, BL_STEP, BL_TOGG, \ 196 _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, BL_DEC, BL_INC, BL_STEP, BL_TOGG, \
197 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CK_RST, CK_DOWN, CK_UP, CK_TOGG\ 197 _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, CK_RST, CK_DOWN, CK_UP, CK_TOGG\
diff --git a/keyboards/hadron/ver3/keymaps/ishtob/keymap.c b/keyboards/hadron/ver3/keymaps/ishtob/keymap.c
index 641c01624..140d148b7 100644
--- a/keyboards/hadron/ver3/keymaps/ishtob/keymap.c
+++ b/keyboards/hadron/ver3/keymaps/ishtob/keymap.c
@@ -165,7 +165,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
165 * `--------------------------------------------------------------------------------------------------------' 165 * `--------------------------------------------------------------------------------------------------------'
166 */ 166 */
167[_ADJUST] = LAYOUT_wrapper( 167[_ADJUST] = LAYOUT_wrapper(
168 KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, \ 168 _______, HPT_TOG, HPT_FBK, HPT_MODI, HPT_MODD, HPT_RST, _______, _______, _______, _______, _______, _______, \
169 RESET, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, _______, _______, _______, _______, _______, KC_DEL, \ 169 RESET, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, _______, _______, _______, _______, _______, KC_DEL, \
170 _______, MAGIC_TOGGLE_NKRO, _______, AU_ON, AU_OFF, AG_NORM, _______, _______, _______, AG_SWAP, QWERTY, COLEMAK, _______, _______, _______, \ 170 _______, MAGIC_TOGGLE_NKRO, _______, AU_ON, AU_OFF, AG_NORM, _______, _______, _______, AG_SWAP, QWERTY, COLEMAK, _______, _______, _______, \
171 _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, BL_DEC, BL_INC, BL_STEP, BL_TOGG, \ 171 _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, _______, _______, _______, _______, BL_DEC, BL_INC, BL_STEP, BL_TOGG, \
diff --git a/keyboards/hadron/ver3/rules.mk b/keyboards/hadron/ver3/rules.mk
index 8375efdd3..2a8662315 100644
--- a/keyboards/hadron/ver3/rules.mk
+++ b/keyboards/hadron/ver3/rules.mk
@@ -52,6 +52,6 @@ NKRO_ENABLE = yes # USB Nkey Rollover
52CUSTOM_MATRIX = yes # Custom matrix file 52CUSTOM_MATRIX = yes # Custom matrix file
53AUDIO_ENABLE = yes 53AUDIO_ENABLE = yes
54RGBLIGHT_ENABLE = no 54RGBLIGHT_ENABLE = no
55HAPTIC_ENABLE = DRV2605L 55HAPTIC_ENABLE += DRV2605L
56QWIIC_ENABLE += MICRO_OLED 56QWIIC_ENABLE += MICRO_OLED
57# SERIAL_LINK_ENABLE = yes 57# SERIAL_LINK_ENABLE = yes
diff --git a/keyboards/hadron/ver3/ver3.c b/keyboards/hadron/ver3/ver3.c
index 5e5e3e009..37169fe2f 100644
--- a/keyboards/hadron/ver3/ver3.c
+++ b/keyboards/hadron/ver3/ver3.c
@@ -17,7 +17,7 @@
17#include "qwiic.h" 17#include "qwiic.h"
18#include "action_layer.h" 18#include "action_layer.h"
19#include "matrix.h" 19#include "matrix.h"
20#include "DRV2605L.h" 20#include "haptic.h"
21 21
22#ifdef QWIIC_MICRO_OLED_ENABLE 22#ifdef QWIIC_MICRO_OLED_ENABLE
23 23
@@ -167,20 +167,12 @@ void encoder_update_kb(uint8_t index, bool clockwise) {
167#endif 167#endif
168 168
169void matrix_init_kb(void) { 169void matrix_init_kb(void) {
170#ifdef DRV2605L
171 DRV_init();
172#endif
173 queue_for_send = true; 170 queue_for_send = true;
174 matrix_init_user(); 171 matrix_init_user();
175} 172}
176 173
177void matrix_scan_kb(void) { 174void matrix_scan_kb(void) {
178
179if (queue_for_send) { 175if (queue_for_send) {
180 #ifdef DRV2605L
181 DRV_EFFECT play_eff = strong_click;
182 DRV_pulse(play_eff);
183 #endif
184#ifdef QWIIC_MICRO_OLED_ENABLE 176#ifdef QWIIC_MICRO_OLED_ENABLE
185 read_host_led_state(); 177 read_host_led_state();
186 draw_ui(); 178 draw_ui();
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 376578ade..cb4d5ee80 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -47,6 +47,9 @@ extern backlight_config_t backlight_config;
47#include "process_midi.h" 47#include "process_midi.h"
48#endif 48#endif
49 49
50#ifdef HAPTIC_ENABLE
51 #include "haptic.h"
52#endif
50 53
51#ifdef ENCODER_ENABLE 54#ifdef ENCODER_ENABLE
52#include "encoder.h" 55#include "encoder.h"
@@ -179,6 +182,9 @@ void reset_keyboard(void) {
179 shutdown_user(); 182 shutdown_user();
180 wait_ms(250); 183 wait_ms(250);
181#endif 184#endif
185#ifdef HAPTIC_ENABLE
186 haptic_shutdown();
187#endif
182// this is also done later in bootloader.c - not sure if it's neccesary here 188// this is also done later in bootloader.c - not sure if it's neccesary here
183#ifdef BOOTLOADER_CATERINA 189#ifdef BOOTLOADER_CATERINA
184 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific 190 *(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
@@ -257,6 +263,9 @@ bool process_record_quantum(keyrecord_t *record) {
257 #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY) 263 #if defined(AUDIO_ENABLE) && defined(AUDIO_CLICKY)
258 process_clicky(keycode, record) && 264 process_clicky(keycode, record) &&
259 #endif //AUDIO_CLICKY 265 #endif //AUDIO_CLICKY
266 #ifdef HAPTIC_ENABLE
267 process_haptic(keycode, record) &&
268 #endif //HAPTIC_ENABLE
260 process_record_kb(keycode, record) && 269 process_record_kb(keycode, record) &&
261 #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_KEYPRESSES) 270 #if defined(RGB_MATRIX_ENABLE) && defined(RGB_MATRIX_KEYPRESSES)
262 process_rgb_matrix(keycode, record) && 271 process_rgb_matrix(keycode, record) &&
@@ -1049,6 +1058,9 @@ void matrix_init_quantum() {
1049 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE) 1058 #if defined(UNICODE_ENABLE) || defined(UNICODEMAP_ENABLE) || defined(UCIS_ENABLE)
1050 unicode_input_mode_init(); 1059 unicode_input_mode_init();
1051 #endif 1060 #endif
1061 #ifdef HAPTIC_ENABLE
1062 haptic_init();
1063 #endif
1052 matrix_init_kb(); 1064 matrix_init_kb();
1053} 1065}
1054 1066
@@ -1091,6 +1103,10 @@ void matrix_scan_quantum() {
1091 encoder_read(); 1103 encoder_read();
1092 #endif 1104 #endif
1093 1105
1106 #ifdef HAPTIC_ENABLE
1107 haptic_task();
1108 #endif
1109
1094 matrix_scan_kb(); 1110 matrix_scan_kb();
1095} 1111}
1096#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) 1112#if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN)
diff --git a/quantum/quantum.h b/quantum/quantum.h
index c6acf83e5..d2c5862f8 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -139,6 +139,10 @@ extern uint32_t default_layer_state;
139 #include "hd44780.h" 139 #include "hd44780.h"
140#endif 140#endif
141 141
142#ifdef HAPTIC_ENABLE
143 #include "haptic.h"
144#endif
145
142//Function substitutions to ease GPIO manipulation 146//Function substitutions to ease GPIO manipulation
143#ifdef __AVR__ 147#ifdef __AVR__
144 #define PIN_ADDRESS(p, offset) _SFR_IO8(ADDRESS_BASE + (p >> PORT_SHIFTER) + offset) 148 #define PIN_ADDRESS(p, offset) _SFR_IO8(ADDRESS_BASE + (p >> PORT_SHIFTER) + offset)
diff --git a/quantum/quantum_keycodes.h b/quantum/quantum_keycodes.h
index 0462291c2..00c84cbf5 100644
--- a/quantum/quantum_keycodes.h
+++ b/quantum/quantum_keycodes.h
@@ -446,25 +446,36 @@ enum quantum_keycodes {
446 KC_LOCK, 446 KC_LOCK,
447#endif 447#endif
448 448
449#ifdef TERMINAL_ENABLE 449 #ifdef TERMINAL_ENABLE
450 TERM_ON, 450 TERM_ON,
451 TERM_OFF, 451 TERM_OFF,
452#endif 452 #endif
453 453
454 EEPROM_RESET, 454 EEPROM_RESET,
455 455
456 UNICODE_MODE_FORWARD, 456 UNICODE_MODE_FORWARD,
457 UNICODE_MODE_REVERSE, 457 UNICODE_MODE_REVERSE,
458 458
459 UNICODE_MODE_OSX, 459 UNICODE_MODE_OSX,
460 UNICODE_MODE_LNX, 460 UNICODE_MODE_LNX,
461 UNICODE_MODE_WIN, 461 UNICODE_MODE_WIN,
462 UNICODE_MODE_BSD, 462 UNICODE_MODE_BSD,
463 UNICODE_MODE_WINC, 463 UNICODE_MODE_WINC,
464 464
465 // always leave at the end 465 HPT_ON,
466 SAFE_RANGE 466 HPT_OFF,
467}; 467 HPT_TOG,
468 HPT_RST,
469 HPT_FBK,
470 HPT_BUZ,
471 HPT_MODI,
472 HPT_MODD,
473 HPT_DWLI,
474 HPT_DWLD,
475
476 // always leave at the end
477 SAFE_RANGE
478 };
468 479
469// Ability to use mods in layouts 480// Ability to use mods in layouts
470#define LCTL(kc) (QK_LCTL | (kc)) 481#define LCTL(kc) (QK_LCTL | (kc))
diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c
index 59b2bffbc..ded27e599 100644
--- a/tmk_core/common/eeconfig.c
+++ b/tmk_core/common/eeconfig.c
@@ -45,6 +45,7 @@ void eeconfig_init_quantum(void) {
45 eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default 45 eeprom_update_byte(EECONFIG_AUDIO, 0xFF); // On by default
46 eeprom_update_dword(EECONFIG_RGBLIGHT, 0); 46 eeprom_update_dword(EECONFIG_RGBLIGHT, 0);
47 eeprom_update_byte(EECONFIG_STENOMODE, 0); 47 eeprom_update_byte(EECONFIG_STENOMODE, 0);
48 eeprom_update_dword(EECONFIG_HAPTIC, 0);
48 49
49 eeconfig_init_kb(); 50 eeconfig_init_kb();
50} 51}
@@ -177,3 +178,11 @@ uint32_t eeconfig_read_user(void) { return eeprom_read_dword(EECONFIG_USER)
177void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); } 178void eeconfig_update_user(uint32_t val) { eeprom_update_dword(EECONFIG_USER, val); }
178 179
179 180
181uint32_t eeconfig_read_haptic(void) { return eeprom_read_dword(EECONFIG_HAPTIC); }
182/** \brief eeconfig update user
183 *
184 * FIXME: needs doc
185 */
186void eeconfig_update_haptic(uint32_t val) { eeprom_update_dword(EECONFIG_HAPTIC, val); }
187
188
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h
index eedd67602..d576634f5 100644
--- a/tmk_core/common/eeconfig.h
+++ b/tmk_core/common/eeconfig.h
@@ -41,6 +41,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
41#define EECONFIG_KEYBOARD (uint32_t *)15 41#define EECONFIG_KEYBOARD (uint32_t *)15
42#define EECONFIG_USER (uint32_t *)19 42#define EECONFIG_USER (uint32_t *)19
43 43
44#define EECONFIG_HAPTIC (uint32_t*)24
45
44/* debug bit */ 46/* debug bit */
45#define EECONFIG_DEBUG_ENABLE (1<<0) 47#define EECONFIG_DEBUG_ENABLE (1<<0)
46#define EECONFIG_DEBUG_MATRIX (1<<1) 48#define EECONFIG_DEBUG_MATRIX (1<<1)
@@ -94,4 +96,9 @@ void eeconfig_update_kb(uint32_t val);
94uint32_t eeconfig_read_user(void); 96uint32_t eeconfig_read_user(void);
95void eeconfig_update_user(uint32_t val); 97void eeconfig_update_user(uint32_t val);
96 98
99#ifdef HAPTIC_ENABLE
100uint32_t eeconfig_read_haptic(void);
101void eeconfig_update_haptic(uint32_t val);
102#endif
103
97#endif 104#endif