aboutsummaryrefslogtreecommitdiff
path: root/drivers/haptic
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/haptic')
-rw-r--r--drivers/haptic/DRV2605L.c129
-rw-r--r--drivers/haptic/DRV2605L.h394
2 files changed, 523 insertions, 0 deletions
diff --git a/drivers/haptic/DRV2605L.c b/drivers/haptic/DRV2605L.c
new file mode 100644
index 000000000..97ca292b9
--- /dev/null
+++ b/drivers/haptic/DRV2605L.c
@@ -0,0 +1,129 @@
1/* Copyright 2018 ishtob
2 * Driver for DRV2605L 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 "DRV2605L.h"
18#include "print.h"
19#include <stdlib.h>
20#include <stdio.h>
21#include <math.h>
22
23
24uint8_t DRV2605L_transfer_buffer[20];
25uint8_t DRV2605L_tx_register[0];
26uint8_t DRV2605L_read_buffer[0];
27uint8_t DRV2605L_read_register;
28
29
30void DRV_write(uint8_t drv_register, uint8_t settings) {
31 DRV2605L_transfer_buffer[0] = drv_register;
32 DRV2605L_transfer_buffer[1] = settings;
33 i2c_transmit(DRV2605L_BASE_ADDRESS << 1, DRV2605L_transfer_buffer, 2, 100);
34}
35
36uint8_t DRV_read(uint8_t regaddress) {
37 DRV2605L_tx_register[0] = regaddress;
38 if (MSG_OK != i2c_transmit_receive(DRV2605L_BASE_ADDRESS << 1,
39 DRV2605L_tx_register, 1,
40 DRV2605L_read_buffer, 1
41)){
42 printf("err reading reg \n");
43 }
44 DRV2605L_read_register = (uint8_t)DRV2605L_read_buffer[0];
45return DRV2605L_read_register;
46}
47
48void DRV_init(void)
49{
50 i2c_init();
51 i2c_start(DRV2605L_BASE_ADDRESS);
52
53 /* 0x07 sets DRV2605 into calibration mode */
54 DRV_write(DRV_MODE,0x07);
55
56// DRV_write(DRV_FEEDBACK_CTRL,0xB6);
57
58 #if FB_ERM_LRA == 0
59 /* ERM settings */
60 DRV_write(DRV_RATED_VOLT, (RATED_VOLTAGE/21.33)*1000);
61 #if ERM_OPEN_LOOP == 0
62 DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (((V_PEAK*(DRIVE_TIME+BLANKING_TIME+IDISS_TIME))/0.02133)/(DRIVE_TIME-0.0003)));
63 #elif ERM_OPEN_LOOP == 1
64 DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
65 #endif
66 #elif FB_ERM_LRA == 1
67 DRV_write(DRV_RATED_VOLT, ((V_RMS * sqrt(1 - ((4 * ((150+(SAMPLE_TIME*50))*0.000001)) + 0.0003)* F_LRA)/0.02071)));
68 #if LRA_OPEN_LOOP == 0
69 DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, ((V_PEAK/sqrt(1-(F_LRA*0.0008))/0.02133)));
70 #elif LRA_OPEN_LOOP == 1
71 DRV_write(DRV_OVERDRIVE_CLAMP_VOLT, (V_PEAK/0.02196));
72 #endif
73 #endif
74
75 DRVREG_FBR FB_SET;
76 FB_SET.Bits.ERM_LRA = FB_ERM_LRA;
77 FB_SET.Bits.BRAKE_FACTOR = FB_BRAKEFACTOR;
78 FB_SET.Bits.LOOP_GAIN =FB_LOOPGAIN;
79 FB_SET.Bits.BEMF_GAIN = 0; /* auto-calibration populates this field*/
80 DRV_write(DRV_FEEDBACK_CTRL, (uint8_t) FB_SET.Byte);
81 DRVREG_CTRL1 C1_SET;
82 C1_SET.Bits.C1_DRIVE_TIME = DRIVE_TIME;
83 C1_SET.Bits.C1_AC_COUPLE = AC_COUPLE;
84 C1_SET.Bits.C1_STARTUP_BOOST = STARTUP_BOOST;
85 DRV_write(DRV_CTRL_1, (uint8_t) C1_SET.Byte);
86 DRVREG_CTRL2 C2_SET;
87 C2_SET.Bits.C2_BIDIR_INPUT = BIDIR_INPUT;
88 C2_SET.Bits.C2_BRAKE_STAB = BRAKE_STAB;
89 C2_SET.Bits.C2_SAMPLE_TIME = SAMPLE_TIME;
90 C2_SET.Bits.C2_BLANKING_TIME = BLANKING_TIME;
91 C2_SET.Bits.C2_IDISS_TIME = IDISS_TIME;
92 DRV_write(DRV_CTRL_2, (uint8_t) C2_SET.Byte);
93 DRVREG_CTRL3 C3_SET;
94 C3_SET.Bits.C3_LRA_OPEN_LOOP = LRA_OPEN_LOOP;
95 C3_SET.Bits.C3_N_PWM_ANALOG = N_PWM_ANALOG;
96 C3_SET.Bits.C3_LRA_DRIVE_MODE = LRA_DRIVE_MODE;
97 C3_SET.Bits.C3_DATA_FORMAT_RTO = DATA_FORMAT_RTO;
98 C3_SET.Bits.C3_SUPPLY_COMP_DIS = SUPPLY_COMP_DIS;
99 C3_SET.Bits.C3_ERM_OPEN_LOOP = ERM_OPEN_LOOP;
100 C3_SET.Bits.C3_NG_THRESH = NG_THRESH;
101 DRV_write(DRV_CTRL_3, (uint8_t) C3_SET.Byte);
102 DRVREG_CTRL4 C4_SET;
103 C4_SET.Bits.C4_ZC_DET_TIME = ZC_DET_TIME;
104 C4_SET.Bits.C4_AUTO_CAL_TIME = AUTO_CAL_TIME;
105 DRV_write(DRV_CTRL_4, (uint8_t) C4_SET.Byte);
106 DRV_write(DRV_LIB_SELECTION,LIB_SELECTION);
107 //start autocalibration
108 DRV_write(DRV_GO, 0x01);
109
110 /* 0x00 sets DRV2605 out of standby and to use internal trigger
111 * 0x01 sets DRV2605 out of standby and to use external trigger */
112 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
122}
123
124void DRV_pulse(uint8_t sequence)
125{
126 DRV_write(DRV_GO, 0x00);
127 DRV_write(DRV_WAVEFORM_SEQ_1, sequence);
128 DRV_write(DRV_GO, 0x01);
129} \ No newline at end of file
diff --git a/drivers/haptic/DRV2605L.h b/drivers/haptic/DRV2605L.h
new file mode 100644
index 000000000..de9d294e9
--- /dev/null
+++ b/drivers/haptic/DRV2605L.h
@@ -0,0 +1,394 @@
1/* Copyright 2018 ishtob
2 * Driver for DRV2605L 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 "i2c_master.h"
20
21/* Initialization settings
22
23 * Feedback Control Settings */
24#ifndef FB_ERM_LRA
25#define FB_ERM_LRA 1 /* For ERM:0 or LRA:1*/
26#endif
27#ifndef FB_BRAKEFACTOR
28#define FB_BRAKEFACTOR 3 /* For 1x:0, 2x:1, 3x:2, 4x:3, 6x:4, 8x:5, 16x:6, Disable Braking:7 */
29#endif
30#ifndef FB_LOOPGAIN
31#define FB_LOOPGAIN 1 /* For Low:0, Medium:1, High:2, Very High:3 */
32#endif
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 */
42#if FB_ERM_LRA == 1
43#ifndef V_RMS
44#define V_RMS 2.0
45#endif
46#ifndef V_PEAK
47#define V_PEAK 2.1
48#endif
49#ifndef F_LRA
50#define F_LRA 205
51#endif
52#endif
53
54/* Library Selection */
55#ifndef LIB_SELECTION
56#if FB_ERM_LRA == 1
57#define LIB_SELECTION 6 /* For Empty:0' TS2200 library A to D:1-5, LRA Library: 6 */
58#else
59#define LIB_SELECTION 1
60#endif
61#endif
62
63/* Control 1 register settings */
64#ifndef DRIVE_TIME
65#define DRIVE_TIME 25
66#endif
67#ifndef AC_COUPLE
68#define AC_COUPLE 0
69#endif
70#ifndef STARTUP_BOOST
71#define STARTUP_BOOST 1
72#endif
73
74/* Control 2 Settings */
75#ifndef BIDIR_INPUT
76#define BIDIR_INPUT 1
77#endif
78#ifndef BRAKE_STAB
79#define BRAKE_STAB 1 /* Loopgain is reduced when braking is almost complete to improve stability */
80#endif
81#ifndef SAMPLE_TIME
82#define SAMPLE_TIME 3
83#endif
84#ifndef BLANKING_TIME
85#define BLANKING_TIME 1
86#endif
87#ifndef IDISS_TIME
88#define IDISS_TIME 1
89#endif
90
91/* Control 3 settings */
92#ifndef NG_THRESH
93#define NG_THRESH 2
94#endif
95#ifndef ERM_OPEN_LOOP
96#define ERM_OPEN_LOOP 1
97#endif
98#ifndef SUPPLY_COMP_DIS
99#define SUPPLY_COMP_DIS 0
100#endif
101#ifndef DATA_FORMAT_RTO
102#define DATA_FORMAT_RTO 0
103#endif
104#ifndef LRA_DRIVE_MODE
105#define LRA_DRIVE_MODE 0
106#endif
107#ifndef N_PWM_ANALOG
108#define N_PWM_ANALOG 0
109#endif
110#ifndef LRA_OPEN_LOOP
111#define LRA_OPEN_LOOP 0
112#endif
113
114/* Control 4 settings */
115#ifndef ZC_DET_TIME
116#define ZC_DET_TIME 0
117#endif
118#ifndef AUTO_CAL_TIME
119#define AUTO_CAL_TIME 3
120#endif
121
122/* register defines -------------------------------------------------------- */
123#define DRV2605L_BASE_ADDRESS 0x5A /* DRV2605L Base address */
124#define DRV_STATUS 0x00
125#define DRV_MODE 0x01
126#define DRV_RTP_INPUT 0x02
127#define DRV_LIB_SELECTION 0x03
128#define DRV_WAVEFORM_SEQ_1 0x04
129#define DRV_WAVEFORM_SEQ_2 0x05
130#define DRV_WAVEFORM_SEQ_3 0x06
131#define DRV_WAVEFORM_SEQ_4 0x07
132#define DRV_WAVEFORM_SEQ_5 0x08
133#define DRV_WAVEFORM_SEQ_6 0x09
134#define DRV_WAVEFORM_SEQ_7 0x0A
135#define DRV_WAVEFORM_SEQ_8 0x0B
136#define DRV_GO 0x0C
137#define DRV_OVERDRIVE_TIME_OFFSET 0x0D
138#define DRV_SUSTAIN_TIME_OFFSET_P 0x0E
139#define DRV_SUSTAIN_TIME_OFFSET_N 0x0F
140#define DRV_BRAKE_TIME_OFFSET 0x10
141#define DRV_AUDIO_2_VIBE_CTRL 0x11
142#define DRV_AUDIO_2_VIBE_MIN_IN 0x12
143#define DRV_AUDIO_2_VIBE_MAX_IN 0x13
144#define DRV_AUDIO_2_VIBE_MIN_OUTDRV 0x14
145#define DRV_AUDIO_2_VIBE_MAX_OUTDRV 0x15
146#define DRV_RATED_VOLT 0x16
147#define DRV_OVERDRIVE_CLAMP_VOLT 0x17
148#define DRV_AUTO_CALIB_COMP_RESULT 0x18
149#define DRV_AUTO_CALIB_BEMF_RESULT 0x19
150#define DRV_FEEDBACK_CTRL 0x1A
151#define DRV_CTRL_1 0x1B
152#define DRV_CTRL_2 0x1C
153#define DRV_CTRL_3 0x1D
154#define DRV_CTRL_4 0x1E
155#define DRV_CTRL_5 0x1F
156#define DRV_OPEN_LOOP_PERIOD 0x20
157#define DRV_VBAT_VOLT_MONITOR 0x21
158#define DRV_LRA_RESONANCE_PERIOD 0x22
159
160void DRV_init(void);
161void DRV_write(const uint8_t drv_register, const uint8_t settings);
162uint8_t DRV_read(const uint8_t regaddress);
163void DRV_pulse(const uint8_t sequence);
164
165
166typedef enum DRV_EFFECT{
167 clear_sequence = 0,
168 strong_click = 1,
169 strong_click_60 = 2,
170 strong_click_30 = 3,
171 sharp_click = 4,
172 sharp_click_60 = 5,
173 sharp_click_30 = 6,
174 soft_bump = 7,
175 soft_bump_60 = 8,
176 soft_bump_30 = 9,
177 dbl_click = 10,
178 dbl_click_60 = 11,
179 trp_click = 12,
180 soft_fuzz = 13,
181 strong_buzz = 14,
182 alert_750ms = 15,
183 alert_1000ms = 16,
184 strong_click1 = 17,
185 strong_click2_80 = 18,
186 strong_click3_60 = 19,
187 strong_click4_30 = 20,
188 medium_click1 = 21,
189 medium_click2_80 = 22,
190 medium_click3_60 = 23,
191 sharp_tick1 = 24,
192 sharp_tick2_80 = 25,
193 sharp_tick3_60 = 26,
194 sh_dblclick_str = 27,
195 sh_dblclick_str_80 = 28,
196 sh_dblclick_str_60 = 29,
197 sh_dblclick_str_30 = 30,
198 sh_dblclick_med = 31,
199 sh_dblclick_med_80 = 32,
200 sh_dblclick_med_60 = 33,
201 sh_dblsharp_tick = 34,
202 sh_dblsharp_tick_80 = 35,
203 sh_dblsharp_tick_60 = 36,
204 lg_dblclick_str = 37,
205 lg_dblclick_str_80 = 38,
206 lg_dblclick_str_60 = 39,
207 lg_dblclick_str_30 = 40,
208 lg_dblclick_med = 41,
209 lg_dblclick_med_80 = 42,
210 lg_dblclick_med_60 = 43,
211 lg_dblsharp_tick = 44,
212 lg_dblsharp_tick_80 = 45,
213 lg_dblsharp_tick_60 = 46,
214 buzz = 47,
215 buzz_80 = 48,
216 buzz_60 = 49,
217 buzz_40 = 50,
218 buzz_20 = 51,
219 pulsing_strong = 52,
220 pulsing_strong_80 = 53,
221 pulsing_medium = 54,
222 pulsing_medium_80 = 55,
223 pulsing_sharp = 56,
224 pulsing_sharp_80 = 57,
225 transition_click = 58,
226 transition_click_80 = 59,
227 transition_click_60 = 60,
228 transition_click_40 = 61,
229 transition_click_20 = 62,
230 transition_click_10 = 63,
231 transition_hum = 64,
232 transition_hum_80 = 65,
233 transition_hum_60 = 66,
234 transition_hum_40 = 67,
235 transition_hum_20 = 68,
236 transition_hum_10 = 69,
237 transition_rampdown_long_smooth1 = 70,
238 transition_rampdown_long_smooth2 = 71,
239 transition_rampdown_med_smooth1 = 72,
240 transition_rampdown_med_smooth2 = 73,
241 transition_rampdown_short_smooth1 = 74,
242 transition_rampdown_short_smooth2 = 75,
243 transition_rampdown_long_sharp1 = 76,
244 transition_rampdown_long_sharp2 = 77,
245 transition_rampdown_med_sharp1 = 78,
246 transition_rampdown_med_sharp2 = 79,
247 transition_rampdown_short_sharp1 = 80,
248 transition_rampdown_short_sharp2 = 81,
249 transition_rampup_long_smooth1 = 82,
250 transition_rampup_long_smooth2 = 83,
251 transition_rampup_med_smooth1 = 84,
252 transition_rampup_med_smooth2 = 85,
253 transition_rampup_short_smooth1 = 86,
254 transition_rampup_short_smooth2 = 87,
255 transition_rampup_long_sharp1 = 88,
256 transition_rampup_long_sharp2 = 89,
257 transition_rampup_med_sharp1 = 90,
258 transition_rampup_med_sharp2 = 91,
259 transition_rampup_short_sharp1 = 92,
260 transition_rampup_short_sharp2 = 93,
261 transition_rampdown_long_smooth1_50 = 94,
262 transition_rampdown_long_smooth2_50 = 95,
263 transition_rampdown_med_smooth1_50 = 96,
264 transition_rampdown_med_smooth2_50 = 97,
265 transition_rampdown_short_smooth1_50 = 98,
266 transition_rampdown_short_smooth2_50 = 99,
267 transition_rampdown_long_sharp1_50 = 100,
268 transition_rampdown_long_sharp2_50 = 101,
269 transition_rampdown_med_sharp1_50 = 102,
270 transition_rampdown_med_sharp2_50 = 103,
271 transition_rampdown_short_sharp1_50 = 104,
272 transition_rampdown_short_sharp2_50 = 105,
273 transition_rampup_long_smooth1_50 = 106,
274 transition_rampup_long_smooth2_50 = 107,
275 transition_rampup_med_smooth1_50 = 108,
276 transition_rampup_med_smooth2_50 = 109,
277 transition_rampup_short_smooth1_50 = 110,
278 transition_rampup_short_smooth2_50 = 111,
279 transition_rampup_long_sharp1_50 = 112,
280 transition_rampup_long_sharp2_50 = 113,
281 transition_rampup_med_sharp1_50 = 114,
282 transition_rampup_med_sharp2_50 = 115,
283 transition_rampup_short_sharp1_50 = 116,
284 transition_rampup_short_sharp2_50 = 117,
285 long_buzz_for_programmatic_stopping = 118,
286 smooth_hum1_50 = 119,
287 smooth_hum2_40 = 120,
288 smooth_hum3_30 = 121,
289 smooth_hum4_20 = 122,
290 smooth_hum5_10 = 123,
291} DRV_EFFECT;
292
293/* Register bit array unions */
294
295typedef union DRVREG_STATUS { /* register 0x00 */
296 uint8_t Byte;
297 struct {
298 uint8_t OC_DETECT :1; /* set to 1 when overcurrent event is detected */
299 uint8_t OVER_TEMP :1; /* set to 1 when device exceeds temp threshold */
300 uint8_t FB_STS :1; /* set to 1 when feedback controller has timed out */
301 /* auto-calibration routine and diagnostic result
302 * result | auto-calibation | diagnostic |
303 * 0 | passed | actuator func normal |
304 * 1 | failed | actuator func fault* |
305 * * actuator is not present or is shorted, timing out, or giving out–of-range back-EMF */
306 uint8_t DIAG_RESULT :1;
307 uint8_t :1;
308 uint8_t DEVICE_ID :3; /* Device IDs 3: DRV2605 4: DRV2604 5: DRV2604L 6: DRV2605L */
309 } Bits;
310} DRVREG_STATUS;
311
312typedef union DRVREG_MODE { /* register 0x01 */
313 uint8_t Byte;
314 struct {
315 uint8_t MODE :3; /* Mode setting */
316 uint8_t :3;
317 uint8_t STANDBY :1; /* 0:standby 1:ready */
318 } Bits;
319} DRVREG_MODE;
320
321typedef union DRVREG_WAIT {
322 uint8_t Byte;
323 struct {
324 uint8_t WAIT_MODE :1; /* Set to 1 to interpret as wait for next 7 bits x10ms */
325 uint8_t WAIT_TIME :7;
326 } Bits;
327} DRVREG_WAIT;
328
329typedef union DRVREG_FBR{ /* register 0x1A */
330 uint8_t Byte;
331 struct {
332 uint8_t BEMF_GAIN :2;
333 uint8_t LOOP_GAIN :2;
334 uint8_t BRAKE_FACTOR :3;
335 uint8_t ERM_LRA :1;
336 } Bits;
337} DRVREG_FBR;
338
339typedef union DRVREG_CTRL1{ /* register 0x1B */
340 uint8_t Byte;
341 struct {
342 uint8_t C1_DRIVE_TIME :5;
343 uint8_t C1_AC_COUPLE :1;
344 uint8_t :1;
345 uint8_t C1_STARTUP_BOOST :1;
346 } Bits;
347} DRVREG_CTRL1;
348
349typedef union DRVREG_CTRL2{ /* register 0x1C */
350 uint8_t Byte;
351 struct {
352 uint8_t C2_IDISS_TIME :2;
353 uint8_t C2_BLANKING_TIME :2;
354 uint8_t C2_SAMPLE_TIME :2;
355 uint8_t C2_BRAKE_STAB :1;
356 uint8_t C2_BIDIR_INPUT :1;
357 } Bits;
358} DRVREG_CTRL2;
359
360typedef union DRVREG_CTRL3{ /* register 0x1D */
361 uint8_t Byte;
362 struct {
363 uint8_t C3_LRA_OPEN_LOOP :1;
364 uint8_t C3_N_PWM_ANALOG :1;
365 uint8_t C3_LRA_DRIVE_MODE :1;
366 uint8_t C3_DATA_FORMAT_RTO :1;
367 uint8_t C3_SUPPLY_COMP_DIS :1;
368 uint8_t C3_ERM_OPEN_LOOP :1;
369 uint8_t C3_NG_THRESH :2;
370 } Bits;
371} DRVREG_CTRL3;
372
373typedef union DRVREG_CTRL4{ /* register 0x1E */
374 uint8_t Byte;
375 struct {
376 uint8_t C4_OTP_PROGRAM :1;
377 uint8_t :1;
378 uint8_t C4_OTP_STATUS :1;
379 uint8_t :1;
380 uint8_t C4_AUTO_CAL_TIME :2;
381 uint8_t C4_ZC_DET_TIME :2;
382 } Bits;
383} DRVREG_CTRL4;
384
385typedef union DRVREG_CTRL5{ /* register 0x1F */
386 uint8_t Byte;
387 struct {
388 uint8_t C5_IDISS_TIME :2;
389 uint8_t C5_BLANKING_TIME :2;
390 uint8_t C5_PLAYBACK_INTERVAL :1;
391 uint8_t C5_LRA_AUTO_OPEN_LOOP :1;
392 uint8_t C5_AUTO_OL_CNT :2;
393 } Bits;
394} DRVREG_CTRL5; \ No newline at end of file