-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathAdafruit_DRV2605.cpp
221 lines (193 loc) · 7.41 KB
/
Adafruit_DRV2605.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
/*!
* @file Adafruit_DRV2605.cpp
*
* @mainpage Adafruit DRV2605L Haptic Driver
*
* @section intro_sec Introduction
*
* This is a library for the Adafruit DRV2605L Haptic Driver ---->
* http://www.adafruit.com/products/2305
*
* Check out the links above for our tutorials and wiring diagrams.
*
* This motor/haptic driver uses I2C to communicate.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @section author Author
*
* Written by Limor Fried/Ladyada for Adafruit Industries.
*
* @section license License
*
* MIT license, all text above must be included in any redistribution.
*
*/
/**************************************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Adafruit_DRV2605.h>
/*========================================================================*/
/* CONSTRUCTORS */
/*========================================================================*/
/**************************************************************************/
/*!
@brief Instantiates a new DRV2605 class. I2C, no address adjustments or pins
*/
/**************************************************************************/
Adafruit_DRV2605::Adafruit_DRV2605() {}
/*========================================================================*/
/* PUBLIC FUNCTIONS */
/*========================================================================*/
/**************************************************************************/
/*!
@brief Setup HW using a specified Wire
@param theWire Pointer to a TwoWire object, defaults to &Wire
@return Return value from init()
*/
/**************************************************************************/
bool Adafruit_DRV2605::begin(TwoWire *theWire) {
if (i2c_dev)
delete i2c_dev;
i2c_dev = new Adafruit_I2CDevice(DRV2605_ADDR, theWire);
return init();
}
/**************************************************************************/
/*!
@brief Setup the HW
@return Always true
*/
/**************************************************************************/
bool Adafruit_DRV2605::init() {
if (!i2c_dev->begin())
return false;
// uint8_t id = readRegister8(DRV2605_REG_STATUS);
// Serial.print("Status 0x"); Serial.println(id, HEX);
writeRegister8(DRV2605_REG_MODE, 0x00); // out of standby
writeRegister8(DRV2605_REG_RTPIN, 0x00); // no real-time-playback
writeRegister8(DRV2605_REG_WAVESEQ1, 1); // strong click
writeRegister8(DRV2605_REG_WAVESEQ2, 0); // end sequence
writeRegister8(DRV2605_REG_OVERDRIVE, 0); // no overdrive
writeRegister8(DRV2605_REG_SUSTAINPOS, 0);
writeRegister8(DRV2605_REG_SUSTAINNEG, 0);
writeRegister8(DRV2605_REG_BREAK, 0);
writeRegister8(DRV2605_REG_AUDIOMAX, 0x64);
// ERM open loop
// turn off N_ERM_LRA
writeRegister8(DRV2605_REG_FEEDBACK,
readRegister8(DRV2605_REG_FEEDBACK) & 0x7F);
// turn on ERM_OPEN_LOOP
writeRegister8(DRV2605_REG_CONTROL3,
readRegister8(DRV2605_REG_CONTROL3) | 0x20);
return true;
}
/**************************************************************************/
/*!
@brief Select the haptic waveform to use.
@param slot The waveform slot to set, from 0 to 7
@param w The waveform sequence value, refers to an index in the ROM library.
Playback starts at slot 0 and continues through to slot 7, stopping if it
encounters a value of 0. A list of available waveforms can be found in
section 11.2 of the datasheet: http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void Adafruit_DRV2605::setWaveform(uint8_t slot, uint8_t w) {
writeRegister8(DRV2605_REG_WAVESEQ1 + slot, w);
}
/**************************************************************************/
/*!
@brief Select the waveform library to use.
@param lib Library to use, 0 = Empty, 1-5 are ERM, 6 is LRA.
See section 7.6.4 in the datasheet for more details:
http://www.adafruit.com/datasheets/DRV2605.pdf
*/
/**************************************************************************/
void Adafruit_DRV2605::selectLibrary(uint8_t lib) {
writeRegister8(DRV2605_REG_LIBRARY, lib);
}
/**************************************************************************/
/*!
@brief Start playback of the waveforms (start moving!).
*/
/**************************************************************************/
void Adafruit_DRV2605::go() { writeRegister8(DRV2605_REG_GO, 1); }
/**************************************************************************/
/*!
@brief Stop playback.
*/
/**************************************************************************/
void Adafruit_DRV2605::stop() { writeRegister8(DRV2605_REG_GO, 0); }
/**************************************************************************/
/*!
@brief Set the device mode.
@param mode Mode value, see datasheet section 7.6.2:
http://www.adafruit.com/datasheets/DRV2605.pdf
0: Internal trigger, call go() to start playback\n
1: External trigger, rising edge on IN pin starts playback\n
2: External trigger, playback follows the state of IN pin\n
3: PWM/analog input\n
4: Audio\n
5: Real-time playback\n
6: Diagnostics\n
7: Auto calibration
*/
/**************************************************************************/
void Adafruit_DRV2605::setMode(uint8_t mode) {
writeRegister8(DRV2605_REG_MODE, mode);
}
/**************************************************************************/
/*!
@brief Set the realtime value when in RTP mode, used to directly drive the
haptic motor.
@param rtp 8-bit drive value.
*/
/**************************************************************************/
void Adafruit_DRV2605::setRealtimeValue(uint8_t rtp) {
writeRegister8(DRV2605_REG_RTPIN, rtp);
}
/**************************************************************************/
/*!
@brief Read an 8-bit register.
@param reg The register to read.
@return 8-bit value of the register.
*/
/**************************************************************************/
uint8_t Adafruit_DRV2605::readRegister8(uint8_t reg) {
uint8_t buffer[1] = {reg};
i2c_dev->write_then_read(buffer, 1, buffer, 1);
return buffer[0];
}
/**************************************************************************/
/*!
@brief Write an 8-bit register.
@param reg The register to write.
@param val The value to write.
*/
/**************************************************************************/
void Adafruit_DRV2605::writeRegister8(uint8_t reg, uint8_t val) {
uint8_t buffer[2] = {reg, val};
i2c_dev->write(buffer, 2);
}
/**************************************************************************/
/*!
@brief Use ERM (Eccentric Rotating Mass) mode.
*/
/**************************************************************************/
void Adafruit_DRV2605::useERM() {
writeRegister8(DRV2605_REG_FEEDBACK,
readRegister8(DRV2605_REG_FEEDBACK) & 0x7F);
}
/**************************************************************************/
/*!
@brief Use LRA (Linear Resonance Actuator) mode.
*/
/**************************************************************************/
void Adafruit_DRV2605::useLRA() {
writeRegister8(DRV2605_REG_FEEDBACK,
readRegister8(DRV2605_REG_FEEDBACK) | 0x80);
}