Loading...
Searching...
No Matches
kx134_1211.c
1/***********************************************************************************
2 * @file KX134_1211.c *
3 * @author Matt Ricci *
4 * @addtogroup Accelerometer_KX134_1211 *
5 * *
6 * @todo Move private interface methods (read/write register) to static functions *
7 * with internal prototypes. *
8 * @{ *
9 ***********************************************************************************/
10
11#include "kx134_1211.h"
12
13#include "string.h"
14
15/* =============================================================================== */
28 KX134_1211_t *accel,
29 SPI_t *spi,
30 GPIOpin_t cs,
31 uint8_t scale,
32 const uint8_t *axes,
33 const int8_t *sign
34) {
35 accel->spi = spi;
36 accel->cs = cs;
37 accel->base.dataSize = KX134_1211_DATA_TOTAL;
42 accel->base.axes = accel->axes;
43 accel->base.sign = accel->sign;
44 accel->base.accelData = accel->accelData;
45 accel->base.rawAccelData = accel->rawAccelData;
46 memcpy(&accel->axes, axes, KX134_1211_DATA_COUNT);
47 memcpy(&accel->sign, sign, KX134_1211_DATA_COUNT);
48
49 // Set value of GSEL and sensitivity based on selected scale
50 uint8_t GSEL = 0x00;
51 if (scale == 32) {
52 GSEL = KX134_1211_CNTL1_GSEL(32);
53 accel->base.sensitivity = KX134_1211_SENSITIVITY(32);
54 } else if (scale == 16) {
55 GSEL = KX134_1211_CNTL1_GSEL(16);
56 accel->base.sensitivity = KX134_1211_SENSITIVITY(16);
57 }
58
59 // Perform software reset as per datasheet
60 KX134_1211_writeRegister(accel, 0x7F, 0x00);
61 KX134_1211_writeRegister(accel, 0x1C, 0x00);
62 KX134_1211_writeRegister(accel, 0x1C, 0x80);
63
64 // Wait for the spefified period - need to wait for 2ms here.
65 for (uint32_t i = 0; i < 0xFFFF; i++);
66
67 // Make sure reset was successful - must add real checks here
68 // @TODO: add in error checking
69 uint8_t chipID = KX134_1211_readRegister(accel, 0x13);
70 uint8_t cotr = KX134_1211_readRegister(accel, 0x12);
71
72 // Configure accelerometer registers
73 KX134_1211_writeRegister(accel, KX134_1211_CNTL1, KX134_1211_CNTL1_RES | GSEL); // Accel select, selected sensitivity
74 uint8_t ODCNTL = KX134_1211_readRegister(accel, KX134_1211_ODCNTL); // Read from register for reserve mask
75 KX134_1211_writeRegister(accel, KX134_1211_ODCNTL, (KX134_1211_ODCNTL_RESERVED & ODCNTL) | 0x2A); // No filter, fast startup, 800Hz
76 KX134_1211_writeRegister(accel, KX134_1211_CNTL1, KX134_1211_CNTL1_PC1 | KX134_1211_CNTL1_RES | GSEL); // Enable PC1
77
78 return *accel;
79}
80
81/********************************** DEVICE METHODS *********************************/
82
83/* =============================================================================== */
92void KX134_1211_readAccel(Accel_t *accel, float *out) {
93 accel->update(accel);
94 out = accel->accelData;
95}
96
97/* =============================================================================== */
106 accel->readRawBytes(accel, accel->rawAccelData);
107 accel->processRawBytes(accel, accel->rawAccelData, accel->accelData);
108}
109
110/* =============================================================================== */
120void KX134_1211_processRawBytes(Accel_t *accel, uint8_t *bytes, float *out) {
121 //
122 out[0] = accel->sign[0] * accel->sensitivity * (int16_t)(((uint16_t)bytes[0] << 8) | bytes[1]); // Accel X
123 out[1] = accel->sign[1] * accel->sensitivity * (int16_t)(((uint16_t)bytes[2] << 8) | bytes[3]); // Accel Y
124 out[2] = accel->sign[2] * accel->sensitivity * (int16_t)(((uint16_t)bytes[4] << 8) | bytes[5]); // Accel Z
125}
126
127/* =============================================================================== */
136void KX134_1211_readRawBytes(Accel_t *accel, uint8_t *out) {
137 // Map raw indices to mounting axis
138#define INDEX_AXES(index, byte) 2 * accel->axes[index] + byte
139 uint8_t tmp[KX134_1211_DATA_TOTAL];
140 KX134_1211_readRegisters((KX134_1211_t *)accel, KX134_1211_XOUT_L, KX134_1211_DATA_TOTAL, tmp);
141 out[INDEX_AXES(0, 1)] = tmp[0]; // Accel X high
142 out[INDEX_AXES(0, 0)] = tmp[1]; // Accel X low
143 out[INDEX_AXES(1, 1)] = tmp[2]; // Accel Y high
144 out[INDEX_AXES(1, 0)] = tmp[3]; // Accel Y low
145 out[INDEX_AXES(2, 1)] = tmp[4]; // Accel Z high
146 out[INDEX_AXES(2, 0)] = tmp[5]; // Accel Z low
147#undef INDEX_AXES
148}
149
150/******************************** INTERFACE METHODS ********************************/
151
152void KX134_1211_writeRegister(KX134_1211_t *accel, uint8_t address, uint8_t data) {
153 SPI_t *spi = accel->spi;
154 GPIOpin_t cs = accel->cs;
155
156 // Pull CS low
157 cs.reset(&cs);
158
159 // Send read command and address
160 uint8_t payload = address & 0x7F; // Load payload with address and write command
161 spi->transmit(spi, payload); // Transmit payload
162 spi->transmit(spi, data); // Transmit write data
163
164 // Set CS high
165 cs.set(&cs);
166}
167
168uint8_t KX134_1211_readRegister(KX134_1211_t *accel, uint8_t address) {
169 uint8_t response = 0;
170 SPI_t *spi = accel->spi;
171 GPIOpin_t cs = accel->cs;
172
173 // Pull CS low
174 cs.reset(&cs);
175
176 // Send read command and address
177 uint8_t payload = address | 0x80; // Load payload with address and read command
178 response = spi->transmit(spi, payload); // Transmit payload
179 response = spi->transmit(spi, 0xFF); // Transmit dummy data and read response data
180
181 // Set CS high
182 cs.set(&cs);
183
184 return response;
185}
186
187void KX134_1211_readRegisters(KX134_1211_t *accel, uint8_t address, uint8_t count, uint8_t *out) {
188 SPI_t *spi = accel->spi;
189 GPIOpin_t cs = accel->cs;
190
191 // Pull CS low
192 cs.reset(&cs);
193
194 // Send read command and address
195 uint8_t payload = address | 0x80; // Load payload with address and read command
196 spi->transmit(spi, payload); // Transmit payload
197
198 // Auto increment read through registers
199 for (uint8_t i = 0; i < count; i++) {
200 out[i] = spi->transmit(spi, 0xFF);
201 }
202
203 // Set CS high
204 cs.set(&cs);
205}
206
void(* processRawBytes)(struct Accel *accel, uint8_t *bytes, float *out)
Pointer to processRawBytes method.
uint8_t * rawAccelData
Pointer to driver defined raw data array.
void(* update)(struct Accel *accel)
Pointer to update method.
void(* readAccel)(struct Accel *accel, float *out)
Pointer to readAccel method.
float * accelData
Pointer to driver defined data array.
uint8_t * axes
Pointer to driver defined axes.
int8_t * sign
Pointer to driver defined signs.
void(* readRawBytes)(struct Accel *accel, uint8_t *out)
Pointer to readRawBytes method.
uint8_t dataSize
Total data size.
uint8_t axes[KX134_1211_DATA_COUNT]
Array defining axes of mounting.
Definition kx134_1211.h:49
GPIOpin_t cs
Chip select GPIO.
Definition kx134_1211.h:47
float accelData[KX134_1211_DATA_COUNT]
Processed accelerations array.
Definition kx134_1211.h:52
Accel_t base
Base accelerometer API.
Definition kx134_1211.h:45
uint8_t rawAccelData[KX134_1211_DATA_TOTAL]
Raw accelerations array.
Definition kx134_1211.h:51
int8_t sign[KX134_1211_DATA_COUNT]
Array defining sign of axes.
Definition kx134_1211.h:50
SPI_t * spi
Parent SPI interface.
Definition kx134_1211.h:46
void KX134_1211_processRawBytes(Accel_t *, uint8_t *, float *)
Process raw 3-axis data to floating point accelerations.
Definition kx134_1211.c:120
void KX134_1211_update(Accel_t *)
Update internally stored acceleration readings.
Definition kx134_1211.c:105
void KX134_1211_readAccel(Accel_t *, float *)
Read 3-axis floating point accelerations.
Definition kx134_1211.c:92
KX134_1211_t KX134_1211_init(KX134_1211_t *accel, SPI_t *spi, GPIOpin_t cs, uint8_t scale, const uint8_t *axes, const int8_t *sign)
Initialiser for a KX134-1211 accelerometer.
Definition kx134_1211.c:27
void KX134_1211_readRawBytes(Accel_t *, uint8_t *)
Read raw 3-axis data.
Definition kx134_1211.c:136
void(* set)(struct GPIOpin *)
Definition gpiopin.h:155
void(* reset)(struct GPIOpin *)
Definition gpiopin.h:156
Struct definition for a GPIO pin.
Definition gpiopin.h:151
uint16_t(* transmit)(struct SPI *, uint16_t)
SPI transmit method.
Definition spi.h:139
Struct definition for SPI interface. Provides the interface for API consumers to interact with the SP...
Definition spi.h:134