Driver for KX134-1211 Accelerometer
Dependents: KX134-1211 Examples
KX134.cpp@0:01d5616ba355, 2020-09-22 (annotated)
- Committer:
- Jasper Swallen
- Date:
- Tue Sep 22 19:36:06 2020 -0400
- Revision:
- 0:01d5616ba355
- Child:
- 1:c6e2a348da09
move code from github to mercurial
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jasper Swallen |
0:01d5616ba355 | 1 | #include "KX134.h" |
Jasper Swallen |
0:01d5616ba355 | 2 | #include "math.h" |
Jasper Swallen |
0:01d5616ba355 | 3 | |
Jasper Swallen |
0:01d5616ba355 | 4 | #define SPI_FREQ 100000 |
Jasper Swallen |
0:01d5616ba355 | 5 | |
Jasper Swallen |
0:01d5616ba355 | 6 | char defaultBuffer[2] = {0}; // allows calling writeRegisterOneByte |
Jasper Swallen |
0:01d5616ba355 | 7 | // without buf argument |
Jasper Swallen |
0:01d5616ba355 | 8 | |
Jasper Swallen |
0:01d5616ba355 | 9 | /* Writes one byte to a register |
Jasper Swallen |
0:01d5616ba355 | 10 | */ |
Jasper Swallen |
0:01d5616ba355 | 11 | void KX134::writeRegisterOneByte(Register addr, uint8_t data, |
Jasper Swallen |
0:01d5616ba355 | 12 | char *buf = defaultBuffer) |
Jasper Swallen |
0:01d5616ba355 | 13 | { |
Jasper Swallen |
0:01d5616ba355 | 14 | uint8_t _data[1] = {data}; |
Jasper Swallen |
0:01d5616ba355 | 15 | writeRegister(addr, _data, buf); |
Jasper Swallen |
0:01d5616ba355 | 16 | } |
Jasper Swallen |
0:01d5616ba355 | 17 | |
Jasper Swallen |
0:01d5616ba355 | 18 | KX134::KX134(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName int1, |
Jasper Swallen |
0:01d5616ba355 | 19 | PinName int2, PinName rst) |
Jasper Swallen |
0:01d5616ba355 | 20 | : _spi(mosi, miso, sclk), _int1(int1), _int2(int2), _cs(cs), _rst(rst) |
Jasper Swallen |
0:01d5616ba355 | 21 | { |
Jasper Swallen |
0:01d5616ba355 | 22 | // set default values for settings variables |
Jasper Swallen |
0:01d5616ba355 | 23 | resStatus = 1; // high performance mode |
Jasper Swallen |
0:01d5616ba355 | 24 | drdyeStatus = 0; // Data Ready Engine disabled |
Jasper Swallen |
0:01d5616ba355 | 25 | gsel1Status = 0; // +-8g bit 1 |
Jasper Swallen |
0:01d5616ba355 | 26 | gsel0Status = 0; // +-8g bit 0 |
Jasper Swallen |
0:01d5616ba355 | 27 | tdteStatus = 0; // Tap/Double-Tap engine disabled |
Jasper Swallen |
0:01d5616ba355 | 28 | tpeStatus = 0; // Tilt Position Engine disabled |
Jasper Swallen |
0:01d5616ba355 | 29 | |
Jasper Swallen |
0:01d5616ba355 | 30 | iirBypass = 0; // IIR filter is not bypassed, i.e. filtering is applied |
Jasper Swallen |
0:01d5616ba355 | 31 | lpro = 0; // IIR filter corner frequency set to ODR/9 |
Jasper Swallen |
0:01d5616ba355 | 32 | fstup = 0; // Fast Start is disabled |
Jasper Swallen |
0:01d5616ba355 | 33 | osa3 = 0; // Output Data Rate bits |
Jasper Swallen |
0:01d5616ba355 | 34 | osa2 = 1; // default is 50hz |
Jasper Swallen |
0:01d5616ba355 | 35 | osa1 = 1; |
Jasper Swallen |
0:01d5616ba355 | 36 | osa0 = 0; |
Jasper Swallen |
0:01d5616ba355 | 37 | |
Jasper Swallen |
0:01d5616ba355 | 38 | registerWritingEnabled = 0; |
Jasper Swallen |
0:01d5616ba355 | 39 | |
Jasper Swallen |
0:01d5616ba355 | 40 | deselect(); |
Jasper Swallen |
0:01d5616ba355 | 41 | } |
Jasper Swallen |
0:01d5616ba355 | 42 | |
Jasper Swallen |
0:01d5616ba355 | 43 | bool KX134::init() |
Jasper Swallen |
0:01d5616ba355 | 44 | { |
Jasper Swallen |
0:01d5616ba355 | 45 | deselect(); |
Jasper Swallen |
0:01d5616ba355 | 46 | |
Jasper Swallen |
0:01d5616ba355 | 47 | _spi.frequency(SPI_FREQ); |
Jasper Swallen |
0:01d5616ba355 | 48 | _spi.format(8, 1); |
Jasper Swallen |
0:01d5616ba355 | 49 | |
Jasper Swallen |
0:01d5616ba355 | 50 | return reset(); |
Jasper Swallen |
0:01d5616ba355 | 51 | } |
Jasper Swallen |
0:01d5616ba355 | 52 | |
Jasper Swallen |
0:01d5616ba355 | 53 | bool KX134::reset() |
Jasper Swallen |
0:01d5616ba355 | 54 | { |
Jasper Swallen |
0:01d5616ba355 | 55 | // write registers to start reset |
Jasper Swallen |
0:01d5616ba355 | 56 | writeRegisterOneByte(Register::INTERNAL_0X7F, 0x00); |
Jasper Swallen |
0:01d5616ba355 | 57 | writeRegisterOneByte(Register::CNTL2, 0x00); |
Jasper Swallen |
0:01d5616ba355 | 58 | writeRegisterOneByte(Register::CNTL2, 0x80); |
Jasper Swallen |
0:01d5616ba355 | 59 | |
Jasper Swallen |
0:01d5616ba355 | 60 | // software reset time |
Jasper Swallen |
0:01d5616ba355 | 61 | wait_us(2000); |
Jasper Swallen |
0:01d5616ba355 | 62 | |
Jasper Swallen |
0:01d5616ba355 | 63 | // check existence |
Jasper Swallen |
0:01d5616ba355 | 64 | return checkExistence(); |
Jasper Swallen |
0:01d5616ba355 | 65 | } |
Jasper Swallen |
0:01d5616ba355 | 66 | |
Jasper Swallen |
0:01d5616ba355 | 67 | /* Helper Functions |
Jasper Swallen |
0:01d5616ba355 | 68 | * ==================================================== |
Jasper Swallen |
0:01d5616ba355 | 69 | */ |
Jasper Swallen |
0:01d5616ba355 | 70 | |
Jasper Swallen |
0:01d5616ba355 | 71 | void KX134::deselect() |
Jasper Swallen |
0:01d5616ba355 | 72 | { |
Jasper Swallen |
0:01d5616ba355 | 73 | _cs.write(1); |
Jasper Swallen |
0:01d5616ba355 | 74 | } |
Jasper Swallen |
0:01d5616ba355 | 75 | |
Jasper Swallen |
0:01d5616ba355 | 76 | void KX134::select() |
Jasper Swallen |
0:01d5616ba355 | 77 | { |
Jasper Swallen |
0:01d5616ba355 | 78 | _cs.write(0); |
Jasper Swallen |
0:01d5616ba355 | 79 | } |
Jasper Swallen |
0:01d5616ba355 | 80 | |
Jasper Swallen |
0:01d5616ba355 | 81 | void KX134::readRegister(Register addr, char *rx_buf, int size) |
Jasper Swallen |
0:01d5616ba355 | 82 | { |
Jasper Swallen |
0:01d5616ba355 | 83 | select(); |
Jasper Swallen |
0:01d5616ba355 | 84 | |
Jasper Swallen |
0:01d5616ba355 | 85 | rx_buf[0] = _spi.write((uint8_t)addr | (1 << 7)); |
Jasper Swallen |
0:01d5616ba355 | 86 | |
Jasper Swallen |
0:01d5616ba355 | 87 | for(int i = 1; i < size; ++i) |
Jasper Swallen |
0:01d5616ba355 | 88 | { |
Jasper Swallen |
0:01d5616ba355 | 89 | rx_buf[i] = _spi.write(0x00); |
Jasper Swallen |
0:01d5616ba355 | 90 | } |
Jasper Swallen |
0:01d5616ba355 | 91 | |
Jasper Swallen |
0:01d5616ba355 | 92 | deselect(); |
Jasper Swallen |
0:01d5616ba355 | 93 | } |
Jasper Swallen |
0:01d5616ba355 | 94 | |
Jasper Swallen |
0:01d5616ba355 | 95 | void KX134::writeRegister(Register addr, uint8_t *data, char *rx_buf, int size) |
Jasper Swallen |
0:01d5616ba355 | 96 | { |
Jasper Swallen |
0:01d5616ba355 | 97 | select(); |
Jasper Swallen |
0:01d5616ba355 | 98 | |
Jasper Swallen |
0:01d5616ba355 | 99 | _spi.write((uint8_t)addr); // select register |
Jasper Swallen |
0:01d5616ba355 | 100 | for(int i = 0; i < size; ++i) |
Jasper Swallen |
0:01d5616ba355 | 101 | { |
Jasper Swallen |
0:01d5616ba355 | 102 | rx_buf[i] = _spi.write(data[i]); |
Jasper Swallen |
0:01d5616ba355 | 103 | } |
Jasper Swallen |
0:01d5616ba355 | 104 | |
Jasper Swallen |
0:01d5616ba355 | 105 | deselect(); |
Jasper Swallen |
0:01d5616ba355 | 106 | } |
Jasper Swallen |
0:01d5616ba355 | 107 | |
Jasper Swallen |
0:01d5616ba355 | 108 | /* Returns a 16 bit signed integer representation of a 2 address read |
Jasper Swallen |
0:01d5616ba355 | 109 | * Assumes 2s Complement |
Jasper Swallen |
0:01d5616ba355 | 110 | */ |
Jasper Swallen |
0:01d5616ba355 | 111 | int16_t KX134::read16BitValue(Register lowAddr, Register highAddr) |
Jasper Swallen |
0:01d5616ba355 | 112 | { |
Jasper Swallen |
0:01d5616ba355 | 113 | // get contents of register |
Jasper Swallen |
0:01d5616ba355 | 114 | char lowWord[2], highWord[2]; |
Jasper Swallen |
0:01d5616ba355 | 115 | readRegister(lowAddr, lowWord); |
Jasper Swallen |
0:01d5616ba355 | 116 | readRegister(highAddr, highWord); |
Jasper Swallen |
0:01d5616ba355 | 117 | |
Jasper Swallen |
0:01d5616ba355 | 118 | // combine low & high words |
Jasper Swallen |
0:01d5616ba355 | 119 | uint16_t val2sComplement = |
Jasper Swallen |
0:01d5616ba355 | 120 | (static_cast<uint16_t>(highWord[1] << 8)) | lowWord[1]; |
Jasper Swallen |
0:01d5616ba355 | 121 | int16_t value = static_cast<int16_t>(val2sComplement); |
Jasper Swallen |
0:01d5616ba355 | 122 | |
Jasper Swallen |
0:01d5616ba355 | 123 | return value; |
Jasper Swallen |
0:01d5616ba355 | 124 | } |
Jasper Swallen |
0:01d5616ba355 | 125 | |
Jasper Swallen |
0:01d5616ba355 | 126 | float KX134::convertRawToGravs(int16_t lsbValue) |
Jasper Swallen |
0:01d5616ba355 | 127 | { |
Jasper Swallen |
0:01d5616ba355 | 128 | if(gsel1Status && gsel0Status) |
Jasper Swallen |
0:01d5616ba355 | 129 | { |
Jasper Swallen |
0:01d5616ba355 | 130 | // +-64g |
Jasper Swallen |
0:01d5616ba355 | 131 | return (float)lsbValue * 0.00195f; |
Jasper Swallen |
0:01d5616ba355 | 132 | } |
Jasper Swallen |
0:01d5616ba355 | 133 | else if(gsel1Status && !gsel0Status) |
Jasper Swallen |
0:01d5616ba355 | 134 | { |
Jasper Swallen |
0:01d5616ba355 | 135 | // +-32g |
Jasper Swallen |
0:01d5616ba355 | 136 | return (float)lsbValue * 0.00098f; |
Jasper Swallen |
0:01d5616ba355 | 137 | } |
Jasper Swallen |
0:01d5616ba355 | 138 | else if(!gsel1Status && gsel0Status) |
Jasper Swallen |
0:01d5616ba355 | 139 | { |
Jasper Swallen |
0:01d5616ba355 | 140 | // +-16g |
Jasper Swallen |
0:01d5616ba355 | 141 | return (float)lsbValue * 0.00049f; |
Jasper Swallen |
0:01d5616ba355 | 142 | } |
Jasper Swallen |
0:01d5616ba355 | 143 | else if(!gsel1Status && !gsel0Status) |
Jasper Swallen |
0:01d5616ba355 | 144 | { |
Jasper Swallen |
0:01d5616ba355 | 145 | // +-8g |
Jasper Swallen |
0:01d5616ba355 | 146 | return (float)lsbValue * 0.00024f; |
Jasper Swallen |
0:01d5616ba355 | 147 | } |
Jasper Swallen |
0:01d5616ba355 | 148 | else |
Jasper Swallen |
0:01d5616ba355 | 149 | { |
Jasper Swallen |
0:01d5616ba355 | 150 | return 0; |
Jasper Swallen |
0:01d5616ba355 | 151 | } |
Jasper Swallen |
0:01d5616ba355 | 152 | } |
Jasper Swallen |
0:01d5616ba355 | 153 | |
Jasper Swallen |
0:01d5616ba355 | 154 | void KX134::getAccelerations(int16_t *output) |
Jasper Swallen |
0:01d5616ba355 | 155 | { |
Jasper Swallen |
0:01d5616ba355 | 156 | // read X, Y, and Z |
Jasper Swallen |
0:01d5616ba355 | 157 | output[0] = read16BitValue(Register::XOUT_L, Register::XOUT_H); |
Jasper Swallen |
0:01d5616ba355 | 158 | output[1] = read16BitValue(Register::YOUT_L, Register::YOUT_H); |
Jasper Swallen |
0:01d5616ba355 | 159 | output[2] = read16BitValue(Register::ZOUT_L, Register::ZOUT_H); |
Jasper Swallen |
0:01d5616ba355 | 160 | } |
Jasper Swallen |
0:01d5616ba355 | 161 | |
Jasper Swallen |
0:01d5616ba355 | 162 | bool KX134::checkExistence() |
Jasper Swallen |
0:01d5616ba355 | 163 | { |
Jasper Swallen |
0:01d5616ba355 | 164 | // verify WHO_I_AM |
Jasper Swallen |
0:01d5616ba355 | 165 | char whoami[5]; |
Jasper Swallen |
0:01d5616ba355 | 166 | readRegister(Register::WHO_AM_I, whoami); |
Jasper Swallen |
0:01d5616ba355 | 167 | |
Jasper Swallen |
0:01d5616ba355 | 168 | if(whoami[1] != 0x46) |
Jasper Swallen |
0:01d5616ba355 | 169 | { |
Jasper Swallen |
0:01d5616ba355 | 170 | return false; // WHO_AM_I is incorrect |
Jasper Swallen |
0:01d5616ba355 | 171 | } |
Jasper Swallen |
0:01d5616ba355 | 172 | |
Jasper Swallen |
0:01d5616ba355 | 173 | // verify COTR |
Jasper Swallen |
0:01d5616ba355 | 174 | char cotr[2]; |
Jasper Swallen |
0:01d5616ba355 | 175 | readRegister(Register::COTR, cotr); |
Jasper Swallen |
0:01d5616ba355 | 176 | if(cotr[1] != 0x55) |
Jasper Swallen |
0:01d5616ba355 | 177 | { |
Jasper Swallen |
0:01d5616ba355 | 178 | return false; // COTR is incorrect |
Jasper Swallen |
0:01d5616ba355 | 179 | } |
Jasper Swallen |
0:01d5616ba355 | 180 | |
Jasper Swallen |
0:01d5616ba355 | 181 | return true; |
Jasper Swallen |
0:01d5616ba355 | 182 | } |
Jasper Swallen |
0:01d5616ba355 | 183 | |
Jasper Swallen |
0:01d5616ba355 | 184 | void KX134::setAccelRange(Range range) |
Jasper Swallen |
0:01d5616ba355 | 185 | { |
Jasper Swallen |
0:01d5616ba355 | 186 | gsel0Status = (uint8_t)range & 0b01; |
Jasper Swallen |
0:01d5616ba355 | 187 | gsel1Status = (uint8_t)range & 0b10; |
Jasper Swallen |
0:01d5616ba355 | 188 | |
Jasper Swallen |
0:01d5616ba355 | 189 | uint8_t writeByte = (1 << 7) | (resStatus << 6) | (drdyeStatus << 5) | |
Jasper Swallen |
0:01d5616ba355 | 190 | (gsel1Status << 4) | (gsel0Status << 3) | |
Jasper Swallen |
0:01d5616ba355 | 191 | (tdteStatus << 2) | (tpeStatus); |
Jasper Swallen |
0:01d5616ba355 | 192 | // reserved bit 1, PC1 bit must be enabled |
Jasper Swallen |
0:01d5616ba355 | 193 | |
Jasper Swallen |
0:01d5616ba355 | 194 | writeRegisterOneByte(Register::CNTL1, writeByte); |
Jasper Swallen |
0:01d5616ba355 | 195 | |
Jasper Swallen |
0:01d5616ba355 | 196 | registerWritingEnabled = 0; |
Jasper Swallen |
0:01d5616ba355 | 197 | } |
Jasper Swallen |
0:01d5616ba355 | 198 | |
Jasper Swallen |
0:01d5616ba355 | 199 | void KX134::setOutputDataRateBytes(uint8_t byteHz) |
Jasper Swallen |
0:01d5616ba355 | 200 | { |
Jasper Swallen |
0:01d5616ba355 | 201 | if(!registerWritingEnabled) |
Jasper Swallen |
0:01d5616ba355 | 202 | { |
Jasper Swallen |
0:01d5616ba355 | 203 | return; |
Jasper Swallen |
0:01d5616ba355 | 204 | } |
Jasper Swallen |
0:01d5616ba355 | 205 | |
Jasper Swallen |
0:01d5616ba355 | 206 | osa0 = byteHz & 0b0001; |
Jasper Swallen |
0:01d5616ba355 | 207 | osa1 = byteHz & 0b0010; |
Jasper Swallen |
0:01d5616ba355 | 208 | osa2 = byteHz & 0b0100; |
Jasper Swallen |
0:01d5616ba355 | 209 | osa3 = byteHz & 0b1000; |
Jasper Swallen |
0:01d5616ba355 | 210 | |
Jasper Swallen |
0:01d5616ba355 | 211 | uint8_t writeByte = (iirBypass << 7) | (lpro << 6) | (fstup << 5) | |
Jasper Swallen |
0:01d5616ba355 | 212 | (osa3 << 3) | (osa2 << 2) | (osa1 << 1) | osa0; |
Jasper Swallen |
0:01d5616ba355 | 213 | // reserved bit 4 |
Jasper Swallen |
0:01d5616ba355 | 214 | |
Jasper Swallen |
0:01d5616ba355 | 215 | writeRegisterOneByte(Register::ODCNTL, writeByte); |
Jasper Swallen |
0:01d5616ba355 | 216 | } |
Jasper Swallen |
0:01d5616ba355 | 217 | |
Jasper Swallen |
0:01d5616ba355 | 218 | void KX134::setOutputDataRateHz(uint32_t hz) |
Jasper Swallen |
0:01d5616ba355 | 219 | { |
Jasper Swallen |
0:01d5616ba355 | 220 | // calculate byte representation from new polling rate |
Jasper Swallen |
0:01d5616ba355 | 221 | // bytes = log2(32*rate/25) |
Jasper Swallen |
0:01d5616ba355 | 222 | |
Jasper Swallen |
0:01d5616ba355 | 223 | double new_rate = (double)hz; |
Jasper Swallen |
0:01d5616ba355 | 224 | |
Jasper Swallen |
0:01d5616ba355 | 225 | double bytes_double = log2((32.f / 25.f) * new_rate); |
Jasper Swallen |
0:01d5616ba355 | 226 | uint8_t bytes_int = (uint8_t)ceil(bytes_double); |
Jasper Swallen |
0:01d5616ba355 | 227 | |
Jasper Swallen |
0:01d5616ba355 | 228 | setOutputDataRateBytes(bytes_int); |
Jasper Swallen |
0:01d5616ba355 | 229 | } |
Jasper Swallen |
0:01d5616ba355 | 230 | |
Jasper Swallen |
0:01d5616ba355 | 231 | void KX134::enableRegisterWriting() |
Jasper Swallen |
0:01d5616ba355 | 232 | { |
Jasper Swallen |
0:01d5616ba355 | 233 | writeRegisterOneByte(Register::CNTL1, 0x00); |
Jasper Swallen |
0:01d5616ba355 | 234 | registerWritingEnabled = 1; |
Jasper Swallen |
0:01d5616ba355 | 235 | } |
Jasper Swallen |
0:01d5616ba355 | 236 | |
Jasper Swallen |
0:01d5616ba355 | 237 | void KX134::disableRegisterWriting() |
Jasper Swallen |
0:01d5616ba355 | 238 | { |
Jasper Swallen |
0:01d5616ba355 | 239 | if(!registerWritingEnabled) |
Jasper Swallen |
0:01d5616ba355 | 240 | { |
Jasper Swallen |
0:01d5616ba355 | 241 | return; |
Jasper Swallen |
0:01d5616ba355 | 242 | } |
Jasper Swallen |
0:01d5616ba355 | 243 | |
Jasper Swallen |
0:01d5616ba355 | 244 | uint8_t writeByte = (0 << 7) | (resStatus << 6) | (drdyeStatus << 5) | |
Jasper Swallen |
0:01d5616ba355 | 245 | (gsel1Status << 4) | (gsel0Status << 3) | |
Jasper Swallen |
0:01d5616ba355 | 246 | (tdteStatus << 2) | (tpeStatus); |
Jasper Swallen |
0:01d5616ba355 | 247 | // reserved bit 1, PC1 bit must be enabled |
Jasper Swallen |
0:01d5616ba355 | 248 | |
Jasper Swallen |
0:01d5616ba355 | 249 | writeRegisterOneByte(Register::CNTL1, writeByte); |
Jasper Swallen |
0:01d5616ba355 | 250 | |
Jasper Swallen |
0:01d5616ba355 | 251 | registerWritingEnabled = 0; |
Jasper Swallen |
0:01d5616ba355 | 252 | } |