Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: kionix-kx123-hello
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
Generated on Thu Jul 14 2022 07:48:42 by
1.7.2
Rohm/Kionix KX123-6000 | Accelerometer