6
6
//
7
7
// Do you like this library? Help support SparkFun. Buy a board!
8
8
//
9
- // SparkFun Triple Axis Accelerometer - KX132/KX134 (Qwiic)
9
+ // SparkFun Triple Axis Accelerometer - KX132/KX134 (Qwiic)
10
10
// * KX132 - https://www.sparkfun.com/products/17871
11
11
// * KX134 - https://www.sparkfun.com/products/17589
12
12
//
13
- // Written by Kirk Benell @ SparkFun Electronics
13
+ // Written by Kirk Benell @ SparkFun Electronics
14
14
// Modified by Elias Santistevan @ SparkFun Electronics, September 2022
15
15
//
16
16
// Repository:
40
40
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
41
41
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42
42
43
-
44
43
// The following classes specify the behavior for communicating
45
44
// over the respective data buses: Inter-Integrated Circuit (I2C)
46
- // and Serial Peripheral Interface (SPI).
45
+ // and Serial Peripheral Interface (SPI).
47
46
48
47
#include " sfe_bus.h"
49
48
#include < Arduino.h>
@@ -54,325 +53,311 @@ namespace sfe_KX13X
54
53
#define kMaxTransferBuffer 32
55
54
#define SPI_READ 0x80
56
55
57
- // What we use for transfer chunk size
58
- const static uint16_t kChunkSize = kMaxTransferBuffer ;
56
+ // What we use for transfer chunk size
57
+ const static uint16_t kChunkSize = kMaxTransferBuffer ;
59
58
60
- // ////////////////////////////////////////////////////////////////////////////////////////////////
61
- // Constructor
62
- //
59
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
60
+ // Constructor
61
+ //
63
62
63
+ QwI2C::QwI2C (void ) : _i2cPort{nullptr }
64
+ {
65
+ }
64
66
65
- QwI2C::QwI2C (void ) : _i2cPort{nullptr }
66
- {
67
- }
67
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
68
+ // I2C init()
69
+ //
70
+ // Methods to init/setup this device. The caller can provide a Wire Port, or this class
71
+ // will use the default
68
72
69
- // ////////////////////////////////////////////////////////////////////////////////////////////////
70
- // I2C init()
71
- //
72
- // Methods to init/setup this device. The caller can provide a Wire Port, or this class
73
- // will use the default
74
-
75
- bool QwI2C::init (TwoWire &wirePort, bool bInit)
76
- {
73
+ bool QwI2C::init (TwoWire &wirePort, bool bInit)
74
+ {
77
75
78
76
// if we don't have a wire port already
79
- if ( !_i2cPort )
77
+ if ( !_i2cPort)
80
78
{
81
- _i2cPort = &wirePort;
79
+ _i2cPort = &wirePort;
82
80
83
- if ( bInit )
84
- _i2cPort->begin ();
81
+ if ( bInit)
82
+ _i2cPort->begin ();
85
83
}
86
-
87
- return true ;
88
- }
89
-
90
- // ////////////////////////////////////////////////////////////////////////////////////////////////
91
- // I2C init()
92
- //
93
- // Methods to init/setup this device. The caller can provide a Wire Port, or this class
94
- // will use the default
95
- bool QwI2C::init ()
96
- {
97
- if ( !_i2cPort )
98
- return init (Wire);
99
- else
100
- return false ;
101
- }
102
-
103
84
85
+ return true ;
86
+ }
87
+
88
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
89
+ // I2C init()
90
+ //
91
+ // Methods to init/setup this device. The caller can provide a Wire Port, or this class
92
+ // will use the default
93
+ bool QwI2C::init ()
94
+ {
95
+ if (!_i2cPort)
96
+ return init (Wire);
97
+ else
98
+ return false ;
99
+ }
100
+
101
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
102
+ // ping()
103
+ //
104
+ // Is a device connected?
105
+ bool QwI2C::ping (uint8_t i2c_address)
106
+ {
104
107
105
- // ////////////////////////////////////////////////////////////////////////////////////////////////
106
- // ping()
107
- //
108
- // Is a device connected?
109
- bool QwI2C::ping (uint8_t i2c_address)
110
- {
111
-
112
- if ( !_i2cPort )
113
- return false ;
108
+ if (!_i2cPort)
109
+ return false ;
114
110
115
111
_i2cPort->beginTransmission (i2c_address);
116
112
return _i2cPort->endTransmission () == 0 ;
117
- }
113
+ }
118
114
119
- // ////////////////////////////////////////////////////////////////////////////////////////////////
120
- // writeRegisterByte()
121
- //
122
- // Write a byte to a register
115
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
116
+ // writeRegisterByte()
117
+ //
118
+ // Write a byte to a register
123
119
124
- bool QwI2C::writeRegisterByte (uint8_t i2c_address, uint8_t offset, uint8_t dataToWrite)
125
- {
120
+ bool QwI2C::writeRegisterByte (uint8_t i2c_address, uint8_t offset, uint8_t dataToWrite)
121
+ {
126
122
127
123
if (!_i2cPort)
128
- return -1 ;
124
+ return -1 ;
129
125
130
126
_i2cPort->beginTransmission (i2c_address);
131
127
_i2cPort->write (offset);
132
128
_i2cPort->write (dataToWrite);
133
129
return (_i2cPort->endTransmission () == 0 ); // true = success, false = error
134
- }
130
+ }
135
131
132
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
133
+ // writeRegisterRegion()
134
+ //
135
+ // Write a block of data to a device.
136
136
137
-
138
- // ////////////////////////////////////////////////////////////////////////////////////////////////
139
- // writeRegisterRegion()
140
- //
141
- // Write a block of data to a device.
142
-
143
- int QwI2C::writeRegisterRegion (uint8_t i2c_address, uint8_t offset, const uint8_t *data, uint16_t length)
144
- {
137
+ int QwI2C::writeRegisterRegion (uint8_t i2c_address, uint8_t offset, const uint8_t *data, uint16_t length)
138
+ {
145
139
146
140
if (!_i2cPort)
147
- return -1 ;
141
+ return -1 ;
148
142
149
143
_i2cPort->beginTransmission (i2c_address);
150
144
_i2cPort->write (offset);
151
145
_i2cPort->write (data, (int )length);
152
146
153
147
return _i2cPort->endTransmission () == 0 ? 0 : -1 ; // 0 = success, -1 = error
154
- }
155
-
156
- // //////////////////////////////////////////////////////////////////////////////////////////////////////////
157
- // readRegisterRegion()
158
- //
159
- // Reads a block of data from an i2c register on the devices.
160
- //
161
- // For large buffers, the data is chuncked over KMaxI2CBufferLength at a time
162
- //
163
- //
164
- int QwI2C::readRegisterRegion (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t numBytes)
165
- {
148
+ }
149
+
150
+ // //////////////////////////////////////////////////////////////////////////////////////////////////////////
151
+ // readRegisterRegion()
152
+ //
153
+ // Reads a block of data from an i2c register on the devices.
154
+ //
155
+ // For large buffers, the data is chuncked over KMaxI2CBufferLength at a time
156
+ //
157
+ //
158
+ int QwI2C::readRegisterRegion (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t numBytes)
159
+ {
166
160
uint8_t nChunk;
167
161
uint16_t nReturned;
168
162
169
163
if (!_i2cPort)
170
- return -1 ;
164
+ return -1 ;
171
165
172
166
int i; // counter in loop
173
167
bool bFirstInter = true ; // Flag for first iteration - used to send register
174
168
175
169
while (numBytes > 0 )
176
170
{
177
- _i2cPort->beginTransmission (addr);
171
+ _i2cPort->beginTransmission (addr);
178
172
179
- if (bFirstInter)
180
- {
181
- _i2cPort->write (reg);
182
- bFirstInter = false ;
183
- }
173
+ if (bFirstInter)
174
+ {
175
+ _i2cPort->write (reg);
176
+ bFirstInter = false ;
177
+ }
184
178
185
- if (_i2cPort->endTransmission () != 0 )
186
- return -1 ; // error with the end transmission
179
+ if (_i2cPort->endTransmission () != 0 )
180
+ return -1 ; // error with the end transmission
187
181
188
- // We're chunking in data - keeping the max chunk to kMaxI2CBufferLength
189
- nChunk = numBytes > kChunkSize ? kChunkSize : numBytes;
182
+ // We're chunking in data - keeping the max chunk to kMaxI2CBufferLength
183
+ nChunk = numBytes > kChunkSize ? kChunkSize : numBytes;
190
184
191
- nReturned = _i2cPort->requestFrom ((int )addr, (int )nChunk, (int )true );
185
+ nReturned = _i2cPort->requestFrom ((int )addr, (int )nChunk, (int )true );
192
186
193
- // No data returned, no dice
194
- if (nReturned == 0 )
195
- return -1 ; // error
187
+ // No data returned, no dice
188
+ if (nReturned == 0 )
189
+ return -1 ; // error
196
190
197
- // Copy the retrieved data chunk to the current index in the data segment
198
- for (i = 0 ; i < nReturned; i++){
199
- *data++ = _i2cPort->read ();
200
- }
201
-
202
- // Decrement the amount of data recieved from the overall data request amount
203
- numBytes = numBytes - nReturned;
191
+ // Copy the retrieved data chunk to the current index in the data segment
192
+ for (i = 0 ; i < nReturned; i++)
193
+ {
194
+ *data++ = _i2cPort->read ();
195
+ }
196
+
197
+ // Decrement the amount of data recieved from the overall data request amount
198
+ numBytes = numBytes - nReturned;
204
199
205
200
} // end while
206
201
207
202
return 0 ; // Success
208
- }
209
-
203
+ }
210
204
205
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
206
+ // Constructor
207
+ //
211
208
212
- // ////////////////////////////////////////////////////////////////////////////////////////////////
213
- // Constructor
214
- //
215
-
216
- SfeSPI::SfeSPI (void ) : _spiPort{nullptr }
217
- {
218
- }
219
-
220
- // //////////////////////////////////////////////////////////////////////////////////////////////
221
- // SPI init()
222
- //
223
- // Methods to init/setup this device. The caller can provide a SPI Port, or this class
224
- // will use the default
209
+ SfeSPI::SfeSPI (void ) : _spiPort{nullptr }
210
+ {
211
+ }
225
212
213
+ // //////////////////////////////////////////////////////////////////////////////////////////////
214
+ // SPI init()
215
+ //
216
+ // Methods to init/setup this device. The caller can provide a SPI Port, or this class
217
+ // will use the default
226
218
227
- bool SfeSPI::init (SPIClass &spiPort, SPISettings& kxSettings, uint8_t cs, bool bInit)
228
- {
219
+ bool SfeSPI::init (SPIClass &spiPort, SPISettings & kxSettings, uint8_t cs, bool bInit)
220
+ {
229
221
230
222
// if we don't have a SPI port already
231
- if ( !_spiPort )
223
+ if ( !_spiPort)
232
224
{
233
- _spiPort = &spiPort;
225
+ _spiPort = &spiPort;
234
226
235
- if ( bInit )
236
- _spiPort->begin ();
227
+ if ( bInit)
228
+ _spiPort->begin ();
237
229
}
238
230
231
+ // SPI settings are needed for every transaction
232
+ _sfeSPISettings = kxSettings;
239
233
240
- // SPI settings are needed for every transaction
241
- _sfeSPISettings = kxSettings;
234
+ // The chip select pin can vary from platform to platform and project to project
235
+ // and so it must be given by the user.
236
+ if (!cs)
237
+ return false ;
242
238
243
- // The chip select pin can vary from platform to platform and project to project
244
- // and so it must be given by the user.
245
- if ( !cs )
246
- return false ;
247
-
248
- _cs = cs;
239
+ _cs = cs;
249
240
250
241
return true ;
251
- }
252
-
253
- // //////////////////////////////////////////////////////////////////////////////////////////////
254
- // SPI init()
255
- //
256
- // Methods to init/setup this device. The caller can provide a SPI Port, or this class
257
- // will use the default
258
- bool SfeSPI::init (uint8_t cs, bool bInit)
259
- {
260
-
261
- // If the transaction settings are not provided by the user they are built here.
262
- SPISettings spiSettings = SPISettings (2000000 , MSBFIRST, SPI_MODE0);
263
-
264
- // In addition of the port is not provided by the user, it defaults to SPI here.
265
- return init (SPI, spiSettings, cs, bInit);
266
-
267
- }
268
-
269
-
270
- // ////////////////////////////////////////////////////////////////////////////////////////////////
271
- // ping()
272
- //
273
- // Is a device connected? The SPI ping is not relevant but is defined here to keep consistency with
274
- // I2C class i.e. provided for the interface.
275
- //
276
-
277
-
278
- bool SfeSPI::ping (uint8_t i2c_address)
279
- {
280
- return true ;
281
- }
242
+ }
243
+
244
+ // //////////////////////////////////////////////////////////////////////////////////////////////
245
+ // SPI init()
246
+ //
247
+ // Methods to init/setup this device. The caller can provide a SPI Port, or this class
248
+ // will use the default
249
+ bool SfeSPI::init (uint8_t cs, bool bInit)
250
+ {
251
+
252
+ // If the transaction settings are not provided by the user they are built here.
253
+ SPISettings spiSettings = SPISettings (2000000 , MSBFIRST, SPI_MODE0);
254
+
255
+ // In addition of the port is not provided by the user, it defaults to SPI here.
256
+ return init (SPI, spiSettings, cs, bInit);
257
+ }
258
+
259
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
260
+ // ping()
261
+ //
262
+ // Is a device connected? The SPI ping is not relevant but is defined here to keep consistency with
263
+ // I2C class i.e. provided for the interface.
264
+ //
265
+
266
+ bool SfeSPI::ping (uint8_t i2c_address)
267
+ {
268
+ return true ;
269
+ }
282
270
283
- // ////////////////////////////////////////////////////////////////////////////////////////////////
284
- // writeRegisterByte()
285
- //
286
- // Write a byte to a register
271
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
272
+ // writeRegisterByte()
273
+ //
274
+ // Write a byte to a register
287
275
288
- bool SfeSPI::writeRegisterByte (uint8_t i2c_address, uint8_t offset, uint8_t dataToWrite)
289
- {
276
+ bool SfeSPI::writeRegisterByte (uint8_t i2c_address, uint8_t offset, uint8_t dataToWrite)
277
+ {
290
278
291
- if ( !_spiPort )
292
- return false ;
279
+ if ( !_spiPort)
280
+ return false ;
293
281
294
- // Apply settings
282
+ // Apply settings
295
283
_spiPort->beginTransaction (_sfeSPISettings);
296
- // Signal communication start
297
- digitalWrite (_cs, LOW);
284
+ // Signal communication start
285
+ digitalWrite (_cs, LOW);
298
286
299
287
_spiPort->transfer (offset);
300
288
_spiPort->transfer (dataToWrite);
301
289
302
- // End communcation
303
- digitalWrite (_cs, HIGH);
290
+ // End communcation
291
+ digitalWrite (_cs, HIGH);
304
292
_spiPort->endTransaction ();
305
293
306
- return true ;
307
- }
294
+ return true ;
295
+ }
308
296
297
+ // ////////////////////////////////////////////////////////////////////////////////////////////////
298
+ // writeRegisterRegion()
299
+ //
300
+ // Write a block of data to a device.
309
301
310
- // ////////////////////////////////////////////////////////////////////////////////////////////////
311
- // writeRegisterRegion()
312
- //
313
- // Write a block of data to a device.
302
+ int SfeSPI::writeRegisterRegion (uint8_t i2c_address, uint8_t offset, const uint8_t *data, uint16_t length)
303
+ {
314
304
315
- int SfeSPI::writeRegisterRegion (uint8_t i2c_address, uint8_t offset, const uint8_t *data, uint16_t length)
316
- {
317
-
318
- if ( !_spiPort )
319
- return -1 ;
305
+ if (!_spiPort)
306
+ return -1 ;
320
307
321
- int i;
308
+ int i;
322
309
323
- // Apply settings
310
+ // Apply settings
324
311
_spiPort->beginTransaction (_sfeSPISettings);
325
- // Signal communication start
326
- digitalWrite (_cs, LOW);
312
+ // Signal communication start
313
+ digitalWrite (_cs, LOW);
327
314
_spiPort->transfer (offset);
328
315
329
- for (i = 0 ; i < length; i++)
330
- {
331
- _spiPort->transfer (*data++);
332
- }
316
+ for (i = 0 ; i < length; i++)
317
+ {
318
+ _spiPort->transfer (*data++);
319
+ }
333
320
334
- // End communication
335
- digitalWrite (_cs, HIGH);
321
+ // End communication
322
+ digitalWrite (_cs, HIGH);
336
323
_spiPort->endTransaction ();
337
324
338
- return 0 ;
339
- }
340
-
341
- // //////////////////////////////////////////////////////////////////////////////////////////////////////////
342
- // readRegisterRegion()
343
- //
344
- // Reads a block of data from the register on the device.
345
- //
346
- //
347
- //
325
+ return 0 ;
326
+ }
348
327
328
+ // //////////////////////////////////////////////////////////////////////////////////////////////////////////
329
+ // readRegisterRegion()
330
+ //
331
+ // Reads a block of data from the register on the device.
332
+ //
333
+ //
334
+ //
349
335
350
- int SfeSPI::readRegisterRegion (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t numBytes)
351
- {
336
+ int SfeSPI::readRegisterRegion (uint8_t addr, uint8_t reg, uint8_t *data, uint16_t numBytes)
337
+ {
352
338
if (!_spiPort)
353
- return -1 ;
339
+ return -1 ;
354
340
355
341
int i; // counter in loop
356
342
357
- // Apply settings
343
+ // Apply settings
358
344
_spiPort->beginTransaction (_sfeSPISettings);
359
- // Signal communication start
360
- digitalWrite (_cs, LOW);
361
- // A leading "1" must be added to transfer with register to indicate a "read"
362
- reg = (reg | SPI_READ);
345
+ // Signal communication start
346
+ digitalWrite (_cs, LOW);
347
+ // A leading "1" must be added to transfer with register to indicate a "read"
348
+ reg = (reg | SPI_READ);
363
349
_spiPort->transfer (reg);
364
350
365
- for (i = 0 ; i < numBytes; i++)
366
- {
367
- *data++ = _spiPort->transfer (0x00 );
368
- }
351
+ for (i = 0 ; i < numBytes; i++)
352
+ {
353
+ *data++ = _spiPort->transfer (0x00 );
354
+ }
369
355
370
- // End transaction
371
- digitalWrite (_cs, HIGH);
356
+ // End transaction
357
+ digitalWrite (_cs, HIGH);
372
358
_spiPort->endTransaction ();
373
359
374
- return 0 ;
375
-
376
- }
360
+ return 0 ;
361
+ }
377
362
378
363
}
0 commit comments