Driver for KX134-1211 Accelerometer
Dependents: KX134-1211 Examples
KX134.cpp
00001 #include "KX134.h" 00002 #include "math.h" 00003 00004 #define SPI_FREQ 100000 00005 00006 static uint8_t defaultBuffer[2] = {0}; // allows calling writeRegisterOneByte 00007 // without buf argument 00008 00009 /* Writes one byte to a register 00010 */ 00011 void KX134::writeRegisterOneByte(Register addr, uint8_t data, 00012 uint8_t *buf = defaultBuffer) 00013 { 00014 uint8_t _data[1] = {data}; 00015 writeRegister(addr, _data, buf); 00016 } 00017 00018 KX134::KX134(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName int1, 00019 PinName int2, PinName rst) 00020 : _spi(mosi, miso, sclk), _int1(int1), _int2(int2), _cs(cs), _rst(rst) 00021 { 00022 // set default values for settings variables 00023 resStatus = 1; // high performance mode 00024 drdyeStatus = 1; // Data Ready Engine enabled 00025 gsel1Status = 0; // +-8g bit 1 00026 gsel0Status = 0; // +-8g bit 0 00027 tdteStatus = 0; // Tap/Double-Tap engine disabled 00028 tpeStatus = 0; // Tilt Position Engine disabled 00029 00030 iirBypass = 0; // IIR filter is not bypassed, i.e. filtering is applied 00031 lpro = 0; // IIR filter corner frequency set to ODR/9 00032 fstup = 0; // Fast Start is disabled 00033 osa3 = 0; // Output Data Rate bits 00034 osa2 = 1; // default is 50hz 00035 osa1 = 1; 00036 osa0 = 0; 00037 00038 registerWritingEnabled = 0; 00039 00040 deselect(); 00041 } 00042 00043 bool KX134::init() 00044 { 00045 deselect(); 00046 00047 _spi.frequency(SPI_FREQ); 00048 _spi.format(8, 1); 00049 00050 return reset(); 00051 } 00052 00053 bool KX134::reset() 00054 { 00055 // write registers to start reset 00056 writeRegisterOneByte(Register::INTERNAL_0X7F, 0x00); 00057 writeRegisterOneByte(Register::CNTL2, 0x00); 00058 writeRegisterOneByte(Register::CNTL2, 0x80); 00059 00060 // software reset time 00061 wait_us(2000); 00062 00063 // check existence 00064 return checkExistence(); 00065 } 00066 00067 /* Helper Functions 00068 * ==================================================== 00069 */ 00070 00071 void KX134::deselect() 00072 { 00073 _cs.write(1); 00074 } 00075 00076 void KX134::select() 00077 { 00078 _cs.write(0); 00079 } 00080 00081 void KX134::readRegister(Register addr, uint8_t *rx_buf, int size) 00082 { 00083 select(); 00084 00085 rx_buf[0] = _spi.write((uint8_t)addr | (1 << 7)); 00086 00087 for(int i = 1; i < size; ++i) 00088 { 00089 rx_buf[i] = _spi.write(0x00); 00090 } 00091 00092 deselect(); 00093 } 00094 00095 void KX134::writeRegister(Register addr, uint8_t *data, uint8_t *rx_buf, 00096 int size) 00097 { 00098 select(); 00099 00100 _spi.write((uint8_t)addr); // select register 00101 for(int i = 0; i < size; ++i) 00102 { 00103 rx_buf[i] = _spi.write(data[i]); 00104 } 00105 00106 deselect(); 00107 } 00108 00109 int16_t KX134::read16BitValue(Register lowAddr, Register highAddr) 00110 { 00111 // get contents of register 00112 uint8_t lowWord[2], highWord[2]; 00113 readRegister(lowAddr, lowWord); 00114 readRegister(highAddr, highWord); 00115 00116 return convertTo16BitValue(lowWord[1], highWord[1]); 00117 } 00118 00119 int16_t KX134::convertTo16BitValue(uint8_t low, uint8_t high) 00120 { 00121 // combine low & high words 00122 uint16_t val2sComplement = (static_cast<uint16_t>(high << 8)) | low; 00123 int16_t value = static_cast<int16_t>(val2sComplement); 00124 00125 return value; 00126 } 00127 00128 float KX134::convertRawToGravs(int16_t lsbValue) 00129 { 00130 if(gsel1Status && gsel0Status) 00131 { 00132 // +-64g 00133 return (float)lsbValue * 0.00195f; 00134 } 00135 else if(gsel1Status && !gsel0Status) 00136 { 00137 // +-32g 00138 return (float)lsbValue * 0.00098f; 00139 } 00140 else if(!gsel1Status && gsel0Status) 00141 { 00142 // +-16g 00143 return (float)lsbValue * 0.00049f; 00144 } 00145 else if(!gsel1Status && !gsel0Status) 00146 { 00147 // +-8g 00148 return (float)lsbValue * 0.00024f; 00149 } 00150 else 00151 { 00152 return 0; 00153 } 00154 } 00155 00156 void KX134::getAccelerations(int16_t *output) 00157 { 00158 uint8_t words[7]; 00159 00160 // this was the recommended method by Kionix 00161 // for some reason, this has *significantly* less noise than reading 00162 // one-by-one 00163 readRegister(Register::XOUT_L, words, 7); 00164 00165 output[0] = convertTo16BitValue(words[1], words[2]); 00166 output[1] = convertTo16BitValue(words[3], words[4]); 00167 output[2] = convertTo16BitValue(words[5], words[6]); 00168 } 00169 00170 bool KX134::checkExistence() 00171 { 00172 // verify WHO_I_AM 00173 uint8_t whoami[2]; 00174 readRegister(Register::WHO_AM_I, whoami); 00175 00176 if(whoami[1] != 0x46) 00177 { 00178 return false; // WHO_AM_I is incorrect 00179 } 00180 00181 // verify COTR 00182 uint8_t cotr[2]; 00183 readRegister(Register::COTR, cotr); 00184 if(cotr[1] != 0x55) 00185 { 00186 return false; // COTR is incorrect 00187 } 00188 00189 return true; 00190 } 00191 00192 void KX134::setAccelRange(Range range) 00193 { 00194 gsel0Status = (uint8_t)range & 0b01; 00195 gsel1Status = (uint8_t)range & 0b10; 00196 00197 uint8_t writeByte = (1 << 7) | (resStatus << 6) | (drdyeStatus << 5) | 00198 (gsel1Status << 4) | (gsel0Status << 3) | 00199 (tdteStatus << 2) | (tpeStatus); 00200 // reserved bit 1, PC1 bit must be enabled 00201 00202 writeRegisterOneByte(Register::CNTL1, writeByte); 00203 00204 registerWritingEnabled = 0; 00205 } 00206 00207 void KX134::setOutputDataRateBytes(uint8_t byteHz) 00208 { 00209 if(!registerWritingEnabled) 00210 { 00211 return; 00212 } 00213 00214 osa0 = byteHz & 0b0001; 00215 osa1 = byteHz & 0b0010; 00216 osa2 = byteHz & 0b0100; 00217 osa3 = byteHz & 0b1000; 00218 00219 uint8_t writeByte = (iirBypass << 7) | (lpro << 6) | (fstup << 5) | 00220 (osa3 << 3) | (osa2 << 2) | (osa1 << 1) | osa0; 00221 // reserved bit 4 00222 00223 writeRegisterOneByte(Register::ODCNTL, writeByte); 00224 } 00225 00226 void KX134::setOutputDataRateHz(uint32_t hz) 00227 { 00228 // calculate byte representation from new polling rate 00229 // bytes = log2(32*rate/25) 00230 00231 double new_rate = (double)hz; 00232 00233 double bytes_double = log2((32.f / 25.f) * new_rate); 00234 uint8_t bytes_int = (uint8_t)ceil(bytes_double); 00235 00236 setOutputDataRateBytes(bytes_int); 00237 } 00238 00239 void KX134::enableRegisterWriting() 00240 { 00241 writeRegisterOneByte(Register::CNTL1, 0x00); 00242 registerWritingEnabled = 1; 00243 } 00244 00245 void KX134::disableRegisterWriting() 00246 { 00247 if(!registerWritingEnabled) 00248 { 00249 return; 00250 } 00251 00252 uint8_t writeByte = (0 << 7) | (resStatus << 6) | (drdyeStatus << 5) | 00253 (gsel1Status << 4) | (gsel0Status << 3) | 00254 (tdteStatus << 2) | (tpeStatus); 00255 // reserved bit 1, PC1 bit must be enabled 00256 00257 writeRegisterOneByte(Register::CNTL1, writeByte); 00258 00259 registerWritingEnabled = 0; 00260 } 00261 00262 bool KX134::dataReady() 00263 { 00264 uint8_t buf[2]; 00265 readRegister(Register::INS2, buf); 00266 00267 return (buf[1] == 0x10); 00268 }
Generated on Mon Jul 25 2022 06:53:07 by 1.7.2