Rohm / kionix-kx123-driver

Dependents:   kionix-kx123-hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers kx123.cpp Source File

kx123.cpp

00001 /*   Copyright 2016 Rohm Semiconductor
00002 
00003    Licensed under the Apache License, Version 2.0 (the "License");
00004    you may not use this file except in compliance with the License.
00005    You may obtain a copy of the License at
00006 
00007        http://www.apache.org/licenses/LICENSE-2.0
00008 
00009    Unless required by applicable law or agreed to in writing, software
00010    distributed under the License is distributed on an "AS IS" BASIS,
00011    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012    See the License for the specific language governing permissions and
00013    limitations under the License.
00014 */
00015 #include "RegisterWriter/RegisterWriter/rohm_hal2.h"
00016 #include "RegisterWriter/RegisterWriter/RegisterWriter.h"
00017 
00018 #include "kx123.h"
00019 
00020 /**
00021 * Create a KX123 instance for communication through pre-instantiated
00022 * RegisterWriter (I2C) -object.
00023 *
00024 * @param i2c_obj pre-instantiated RegisterWriter (I2C) -object reference
00025 * @param sad slave address of sensor.
00026 * @param wai who_am_i value (i.e. sensor type/model)
00027 */
00028 KX123::KX123(RegisterWriter &i2c_obj, uint8_t sad, uint8_t wai) : i2c_rw(i2c_obj) {
00029     _sad = sad;
00030     _wai = wai;        
00031     setup_mode_on = false;
00032 }
00033 
00034 KX123::~KX123(){
00035 }
00036 
00037 /**
00038 * Start setup/stand-by mode and shut off measurements.
00039 * @return true on error, false on ok
00040 */
00041 bool KX123::start_setup_mode(void){
00042     setup_mode_on = true;
00043     return i2c_rw.change_bits(_sad, KX122_CNTL1, KX122_CNTL1_PC1, KX122_CNTL1_PC1);
00044 }
00045 
00046 /**
00047 * Start operating/measurement mode. Setup is not allowed while in this mode.
00048 * @return true on error, false on ok
00049 */
00050 bool KX123::start_measurement_mode(void){
00051     setup_mode_on = false;
00052     return i2c_rw.change_bits(_sad, KX122_CNTL1, KX122_CNTL1_PC1, 0);
00053 }
00054 
00055 /**
00056 * Check if sensor is connected, setup defaults to sensor and start measuring.
00057 * @return true on error, false on ok
00058 */
00059 bool KX123::set_defaults()
00060 {
00061     unsigned char buf;
00062 
00063     DEBUG_print("\n\r");
00064     DEBUG_print("KX123 init started\n\r");
00065     i2c_rw.read_register(_sad, KX122_WHO_AM_I, &buf, 1);
00066     if (buf == KX123_WHO_AM_I_WAI_ID) {
00067         DEBUG_print("KX123 found. (WAI %d) ", buf);
00068     } else {
00069         DEBUG_print("KX123 not found (WAI %d, not %d). ", buf, KX123_WHO_AM_I_WAI_ID);
00070         switch(buf){        
00071             case KX012_WHO_AM_I_WAI_ID:
00072                 DEBUG_print("Found KX012");
00073                 break;
00074             case KX022_WHO_AM_I_WAI_ID:
00075                 DEBUG_print("Found KX022");
00076                 break;
00077             case KX023_WHO_AM_I_WAI_ID:
00078                 DEBUG_print("Found KX023");
00079                 break;
00080             case KX23H_WHO_AM_I_WAI_ID:
00081                 DEBUG_print("Found KX23H");
00082                 break;
00083             case KX112_WHO_AM_I_WAI_ID:
00084                 DEBUG_print("Found KX112");
00085                 break;
00086             case KX122_WHO_AM_I_WAI_ID:
00087                 DEBUG_print("Found KX122");
00088                 break;
00089             case KX124_WHO_AM_I_WAI_ID:
00090                 DEBUG_print("Found KX124");
00091                 break;
00092             case KX222_WHO_AM_I_WAI_ID:
00093                 DEBUG_print("Found KX222");
00094                 break;
00095             case KX224_WHO_AM_I_WAI_ID:
00096                 DEBUG_print("Found KX224");
00097                 break;
00098             default:
00099                 DEBUG_print("Not even other sensor found from same family.\n\r");
00100                 return true;
00101             }
00102             DEBUG_print(" though, trying to use that.\n\r");
00103     }
00104 
00105     //First set CNTL1 PC1-bit to stand-by mode, after that setup can be made
00106     i2c_rw.write_register(_sad, KX122_CNTL1, 0 );
00107     setup_mode_on = true;
00108 
00109     //set_tilt_position_defaults();
00110 
00111     //ODCNTL: Output Data Rate control (ODR) 
00112     i2c_rw.write_register(_sad, KX122_ODCNTL, KX122_ODCNTL_OSA_25600);
00113     //Setup G-range and 8/16-bit resolution + set CNTL1 PC1-bit to operating mode (also WUF_EN, TP_EN and DT_EN)
00114     i2c_rw.write_register(_sad, KX122_CNTL1, ( KX122_CNTL1_PC1 | KX122_CNTL1_GSEL_8G | KX122_CNTL1_RES ) );
00115     setup_mode_on = false;
00116 
00117     //resolution_divider = 32768/2;  //KX122_CNTL1_GSEL_2G
00118     //resolution_divider = 32768/4;  //KX122_CNTL1_GSEL_4G
00119     resolution_divider = 32768/8;  //KX122_CNTL1_GSEL_8G
00120     
00121     return false;
00122 }
00123 
00124 
00125 /**
00126 * Setup default settings for a tilt position
00127 **/
00128 void KX123::set_tilt_position_defaults(){
00129     if (setup_mode_on == false) return;
00130     //CNTL3: Tilt position control, directional tap control and motion wakeup control
00131     i2c_rw.write_register(_sad, KX122_CNTL3, ( KX122_CNTL3_OTP_50 | KX122_CNTL3_OTDT_400 ) ); 
00132     //TILT_TIMER: Setup tilt position timer (~=filter)
00133     i2c_rw.write_register(_sad, KX122_TILT_TIMER, 0x01);
00134     return;
00135 }
00136 
00137 
00138 /**
00139 * Get filtered uint16_t XYZ-values from sensor
00140 * @param *buf to uint16_t[3] for results
00141 * @return true on error, false on read ok.
00142 **/
00143 bool KX123::getresults_highpass(int16_t* buf) {
00144     #define RESULTS_LEN 6
00145     uint8_t tmp[RESULTS_LEN];     //XYZ (lhlhlh)
00146     uint8_t read_bytes;
00147 
00148     read_bytes = i2c_rw.read_register(_sad, KX122_XHP_L, &tmp[0], sizeof(tmp));
00149     if (read_bytes != RESULTS_LEN){
00150         return true;
00151         }
00152     buf[0] = ( tmp[1] << 8 ) | tmp[0];  //X
00153     buf[1] = ( tmp[3] << 8 ) | tmp[2];  //Y
00154     buf[2] = ( tmp[5] << 8 ) | tmp[4];  //Z
00155     return false;
00156 }
00157 
00158 /**
00159 * Get raw uint16_t XYZ-values from sensor
00160 * @param *buf to uint16_t[3] for results
00161 * @return true on error, false on read ok.
00162 **/
00163 bool KX123::getresults_raw(int16_t* buf){
00164     #define RESULTS_LEN 6
00165     uint8_t tmp[RESULTS_LEN];     //XYZ (lhlhlh)
00166     uint8_t read_bytes;
00167 
00168     read_bytes = i2c_rw.read_register(_sad, KX122_XOUT_L, &tmp[0], sizeof(tmp));
00169     if (read_bytes != RESULTS_LEN){
00170         return true;
00171         }
00172     buf[0] = ( tmp[1] << 8 ) | tmp[0];  //X
00173     buf[1] = ( tmp[3] << 8 ) | tmp[2];  //Y
00174     buf[2] = ( tmp[5] << 8 ) | tmp[4];  //Z
00175     return false;
00176 }
00177 
00178 
00179 /**
00180 * Get gravity scaled float XYZ-values from sensor
00181 * @param *buf to float[3] for results
00182 * @return true on error, false on read ok.
00183 **/
00184 bool KX123::getresults_g(float* buf){
00185     int16_t raw[3];
00186     int read_error;
00187 
00188     read_error = getresults_raw(&raw[0]);
00189     if (read_error){
00190         return read_error;
00191         }
00192 
00193     //Scale raw values to G-scale
00194     buf[0] = ((float)raw[0]) / resolution_divider;
00195     buf[1] = ((float)raw[1]) / resolution_divider;
00196     buf[2] = ((float)raw[2]) / resolution_divider;
00197     return false;
00198 }
00199 
00200 /**
00201 * Get gravity scaled float XYZ-values from highpass filtered sensor values
00202 * @param *buf to float[3] for results
00203 * @return true on error, false on read ok.
00204 **/
00205 bool KX123::getresults_highpass_g(float* buf){
00206     int16_t raw[3];
00207     int read_error;
00208 
00209     read_error = getresults_highpass(&raw[0]);
00210     if (read_error){
00211         return read_error;
00212         }
00213 
00214     //Scale raw values to G-scale
00215     buf[0] = ((float)raw[0]) / resolution_divider;
00216     buf[1] = ((float)raw[1]) / resolution_divider;
00217     buf[2] = ((float)raw[2]) / resolution_divider;
00218     return false;
00219 }
00220 
00221 /**
00222 * Get axes of current tilt and previous tilt
00223 * @param *current_previous space for storing 2 (uint8_t) values
00224 * @return true on error
00225 */
00226 bool KX123::get_tilt(enum e_axis* current_previous){
00227     #define GET_TILT_READ_LEN 2
00228     uint8_t read_bytes;
00229 
00230     read_bytes = i2c_rw.read_register(_sad, KX122_TSCP, (uint8_t*)current_previous, GET_TILT_READ_LEN);
00231 
00232     return (read_bytes != GET_TILT_READ_LEN);
00233 }
00234 
00235 /**
00236 * Get axis of triggered tap/double tap interrupt from INS1
00237 * @param *axis space for storing 1 (uint8_t) value in e_axis format
00238 * @return true on error
00239 */
00240 bool KX123::get_tap_interrupt_axis(enum e_axis* axis){
00241     #define GET_TAP_READ_LEN 1
00242     uint8_t read_bytes;
00243     
00244     read_bytes = i2c_rw.read_register(_sad, KX122_INS1, (uint8_t*)axis, GET_TAP_READ_LEN);
00245 
00246     return (read_bytes != GET_TAP_READ_LEN);
00247 }
00248 
00249 /**
00250 * Get axis of triggered motion detect interrupt from INS3
00251 * @param *axis space for storing 1 (uint8_t) value in e_axis format
00252 * @return true on error
00253 */
00254 bool KX123::get_detected_motion_axis(enum e_axis* axis){
00255     #define GET_MOTION_READ_LEN 1
00256     uint8_t read_bytes;
00257     
00258     read_bytes = i2c_rw.read_register(_sad, KX122_INS3, (uint8_t*)axis, GET_MOTION_READ_LEN);
00259 
00260     return (read_bytes != GET_MOTION_READ_LEN);
00261 }
00262 
00263 /**
00264 * Set axis of triggered motion detect interrupt from CNTL2
00265 * @param cnltl2_tilt_mask Orred e_axis values for axes directions to cause interrupt
00266 * @return true on error or setup mode off
00267 */
00268 bool KX123::set_tilt_axis_mask(uint8_t cnltl2_tilt_mask){
00269     if (setup_mode_on == false) return true;
00270     //MSb 00 == no_action
00271     return i2c_rw.write_register(_sad, KX122_CNTL2, (cnltl2_tilt_mask & KX123_AXIS_MASK) );
00272 }
00273 
00274 /**
00275 * get cause of interrupt trigger from INS2
00276 * @param *int_reason space for storing 1 (uint8_t) value in e_interrupt_reason format
00277 * @return true on error
00278 */
00279 bool KX123::get_interrupt_reason(enum e_interrupt_reason* int_reason){
00280     #define INT_REASON_LEN 1
00281     uint8_t read_bytes;
00282     
00283     read_bytes = i2c_rw.read_register(_sad, KX122_INS2, (uint8_t*)int_reason, INT_REASON_LEN);
00284 
00285     return (read_bytes != INT_REASON_LEN);
00286 }
00287 
00288 /**
00289 * Check from sensor register if interrupt has occured. Usable feature when
00290 * multiple sensor interrupts are connected to same interrupt pin.
00291 * @return true when interrupt has occured. False on read fail and no interrupt.
00292 */
00293 bool KX123::has_interrupt_occured(){
00294     uint8_t status_reg;
00295     uint8_t read_bytes;
00296     
00297     read_bytes = i2c_rw.read_register(_sad, KX122_INS2, &status_reg, 1);
00298     return ((read_bytes == 1) && (status_reg & KX122_STATUS_REG_INT));
00299 }
00300 
00301 /**
00302 * Clear interrupt flag when latched. (==Interrupt release) Doesn't work for FIFO
00303 * Buffer Full or FIFO Watermark -interrupts.
00304 */
00305 void KX123::clear_interrupt(){
00306     uint8_t value_discarded;
00307 
00308     i2c_rw.read_register(_sad, KX122_INT_REL, &value_discarded, 1);
00309 
00310     return;
00311 }
00312 
00313 /**
00314 * Initiate software reset and RAM reboot routine and wait untill finished.
00315 */
00316 void KX123::soft_reset(){
00317     uint8_t reset_ongoing;
00318 
00319     i2c_rw.change_bits(_sad, KX122_CNTL2, KX122_CNTL2_SRST, KX122_CNTL2_SRST );
00320     do{
00321         uint8_t cntl2, read_bytes;
00322         
00323         read_bytes = i2c_rw.read_register(_sad, KX122_CNTL2, &cntl2, 1);
00324         reset_ongoing = ((read_bytes == 0) || (cntl2 & KX122_CNTL2_SRST));
00325     } while (reset_ongoing);
00326     
00327     return;
00328 }
00329 
00330 /**
00331 * Verify proper integrated circuit functionality
00332 * @return true on test fail or setup mode off, false on test ok.
00333 **/
00334 bool KX123::self_test(){
00335     uint8_t cotr_value;
00336     bool read_ok;
00337 
00338     if (setup_mode_on == false) return true;
00339     //first read to make sure COTR is in default value
00340     read_ok = i2c_rw.read_register(_sad, KX122_COTR, &cotr_value, 1);
00341     read_ok = i2c_rw.read_register(_sad, KX122_COTR, &cotr_value, 1);
00342     if ((cotr_value != 0x55) || (!read_ok) ){
00343         return true;
00344         }
00345     i2c_rw.change_bits(_sad, KX122_CNTL2, KX122_CNTL2_COTC, KX122_CNTL2_COTC );
00346     read_ok = i2c_rw.read_register(_sad, KX122_COTR, &cotr_value, 1);
00347     if ((cotr_value != 0xAA) || (!read_ok) ){
00348         return true;
00349         }
00350     return false;
00351 }
00352 
00353 /**
00354 * Setup ODR values for Tilt Position, Directional Tap and Motion Detect.
00355 * @param tilt_position_odr KX122_CNTL3_OTP_* -value or 0xff to skip.
00356 * @param directional_tap_odr KX122_CNTL3_OTDT_* -value or 0xff to skip.
00357 * @param motion_wuf_odr motion detect/high-pass odr (KX122_CNTL3_OWUF_* -value) or 0xff to skip.
00358 * @return true on error or setup mode off, false on setup ok.
00359 **/
00360 bool KX123::set_cntl3_odrs(uint8_t tilt_position_odr, uint8_t directional_tap_odr, uint8_t motion_wuf_odr){
00361     uint8_t cntl3;
00362     bool read_ok;
00363 
00364     if (setup_mode_on == false) return true;
00365 
00366     read_ok = i2c_rw.read_register(_sad, KX122_CNTL3, &cntl3, 1);
00367     if(!read_ok) return true;
00368     
00369     if (tilt_position_odr != 0xff){
00370         cntl3 = (cntl3 & ~KX122_CNTL3_OTP_MASK) | (tilt_position_odr & KX122_CNTL3_OTP_MASK);
00371         }
00372     if (directional_tap_odr != 0xff){
00373         cntl3 = (cntl3 & ~KX122_CNTL3_OTDT_MASK) | (directional_tap_odr & KX122_CNTL3_OTDT_MASK);
00374         }
00375     if (motion_wuf_odr != 0xff){
00376         cntl3 = (cntl3 & ~KX122_CNTL3_OWUF_MASK) | (motion_wuf_odr & KX122_CNTL3_OWUF_MASK);
00377         }
00378     return i2c_rw.write_register(_sad, KX122_CNTL3, cntl3);
00379 }
00380 
00381 /**
00382 * Setup ODR value, IIR-filter on/off and lowpass filter corner frequency.
00383 * @param iir_filter_off False to filter ON or true to filter OFF.
00384 * @param lowpass_filter_freq_half Filter corner frequency setup. False to ODR/9. True to ODR/2.
00385 * @param odr Output Data Rate using KX122_ODCNTL_OSA_* -definitions.
00386 * @return true on error or setup mode off, false on setup ok.
00387 **/
00388 bool KX123::set_odcntl(bool iir_filter_off, uint8_t lowpass_filter_freq_half, uint8_t odr){
00389     uint8_t odcntl;
00390 
00391     if (setup_mode_on == false) return true;
00392 
00393     odcntl = (odr & KX122_ODCNTL_OSA_MASK);
00394     if (iir_filter_off){
00395         odcntl = (odcntl | KX122_ODCNTL_IIR_BYPASS);
00396         }
00397     if (lowpass_filter_freq_half){
00398         odcntl = (odcntl | KX122_ODCNTL_LPRO);
00399         }
00400 
00401     return i2c_rw.write_register(_sad, KX122_ODCNTL, odcntl);
00402 }
00403 
00404 /**
00405 * Setup physical int1 pin, selftest polarity and SPI 3-wire on/off.
00406 * @param pwsel Pulse width configuration in KX122_INC1_PWSEL1_* values
00407 * @param physical_int_pin_enabled
00408 * @param physical_int_pin_active_high (default true)
00409 * @param physical_int_pin_latch_disabled
00410 * @param self_test_polarity_positive
00411 * @param spi3wire_enabled Use 3 wires instead of 4.
00412 * @return true on error or setup mode off, false on setup ok.
00413 **/
00414 bool KX123::int1_setup(uint8_t pwsel,
00415     bool physical_int_pin_enabled,
00416     bool physical_int_pin_active_high,
00417     bool physical_int_pin_latch_disabled,
00418     bool self_test_polarity_positive,
00419     bool spi3wire_enabled){
00420 
00421     uint8_t inc1;
00422 
00423     if (setup_mode_on == false) return true;
00424 
00425     inc1 = (pwsel & KX122_INC1_PWSEL1_MASK);
00426     if (physical_int_pin_enabled){
00427         inc1 = (inc1 | KX122_INC1_IEN1);
00428         }
00429     if (physical_int_pin_active_high){
00430         inc1 = (inc1 | KX122_INC1_IEA1);
00431         }
00432     if (physical_int_pin_latch_disabled){
00433         inc1 = (inc1 | KX122_INC1_IEL1);
00434         }
00435     if (self_test_polarity_positive){
00436         inc1 = (inc1 | KX122_INC1_STPOL);
00437         }
00438     if (spi3wire_enabled){
00439         inc1 = (inc1 | KX122_INC1_SPI3E);
00440         }
00441     return i2c_rw.write_register(_sad, KX122_INC1, inc1);
00442 }
00443 
00444 
00445 /**
00446 * Setup physical int2 pin and int1/2 autoclear. 
00447 * @param pwsel Pulse width configuration in KX122_INC1_PWSEL1_* values
00448 * @param physical_int_pin_enabled
00449 * @param physical_int_pin_active_high (default true)
00450 * @param physical_int_pin_latch_disabled
00451 * @param aclr2_enabled
00452 * @param aclr1_enabled 
00453 * @return true on error or setup mode off, false on setup ok.
00454 **/
00455 bool KX123::int2_setup(uint8_t pwsel,
00456     bool physical_int_pin_enabled,
00457     bool physical_int_pin_active_high,
00458     bool physical_int_pin_latch_disabled,
00459     bool aclr2_enabled,
00460     bool aclr1_enabled){
00461 
00462     uint8_t inc5;
00463 
00464     if (setup_mode_on == false) return true;
00465 
00466     inc5 = (pwsel & KX122_INC5_PWSEL2_MASK);
00467     if (physical_int_pin_enabled){
00468         inc5 = (inc5 | KX122_INC5_IEN2);
00469         }
00470     if (physical_int_pin_active_high){
00471         inc5 = (inc5 | KX122_INC5_IEA2);
00472         }
00473     if (physical_int_pin_latch_disabled){
00474         inc5 = (inc5 | KX122_INC5_IEL2);
00475         }
00476     if (aclr2_enabled){
00477         inc5 = (inc5 | KX122_INC5_ACLR2);
00478         }
00479     if (aclr1_enabled){
00480         inc5 = (inc5 | KX122_INC5_ACLR1);
00481         }
00482     return i2c_rw.write_register(_sad, KX122_INC5, inc5);
00483 }
00484 
00485 /**
00486 * Select interrupt reasons that can trigger interrupt for int1.
00487 * @param interrupt_reason One or more e_interrupt_reason -values except doubletap.
00488 * @return true on error or setup mode off, false on setup ok.
00489 **/
00490 bool KX123::set_int1_interrupt_reason(uint8_t interrupt_reason){
00491     if (setup_mode_on == false) return true;
00492     return i2c_rw.write_register(_sad, KX122_INC4, interrupt_reason);
00493 }
00494 
00495 /**
00496 * Select interrupt reasons that can trigger interrupt for int2.
00497 * @param interrupt_reason One or more e_interrupt_reason -values except doubletap.
00498 * @return true on error or setup mode off, false on setup ok.
00499 **/
00500 bool KX123::set_int2_interrupt_reason(uint8_t interrupt_reason){
00501     if (setup_mode_on == false) return true;
00502     return i2c_rw.write_register(_sad, KX122_INC6, interrupt_reason);
00503 }
00504 
00505 /**
00506 * Select axis that are monitored for motion detect interrupt.
00507 * @param xxyyzz combination of e_axis -values for enabling axis
00508 * @param axis_and_combination_enabled true for AND or false for OR
00509 *
00510 * true for AND configuration = (XN || XP) && (YN || YP) && (ZN || ZP)
00511 *
00512 * false for OR configuration = (XN || XP || YN || TP || ZN || ZP)
00513 * @return true on error or setup mode off, false on setup ok.
00514 **/
00515 bool KX123::set_motion_detect_axis(uint8_t xxyyzz, bool axis_and_combination_enabled){
00516     uint8_t inc2;
00517 
00518     if (setup_mode_on == false) return true;
00519 
00520     inc2 = (xxyyzz & KX122_INC2_WUE_MASK);
00521     if (axis_and_combination_enabled){
00522         inc2 = (inc2 | KX122_INC2_AOI_AND);
00523         }
00524     return i2c_rw.write_register(_sad, KX122_INC2, inc2);
00525 }
00526 
00527 /**
00528 * Select axis that are monitored for tap/doubletap interrupt.
00529 * @param xxyyzz combination of e_axis -values for enabling axis
00530 * @return true on error or setup mode off, false on setup ok.
00531 **/
00532 bool KX123::set_tap_axis(uint8_t xxyyzz){
00533     if (setup_mode_on == false) return true;
00534     return i2c_rw.write_register(_sad, KX122_INC3, xxyyzz);
00535 }
00536