Driver for KX134-1211 Accelerometer

Dependents:   KX134-1211 Examples

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers KX134.cpp Source File

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 }