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.
ADXL362.cpp
00001 /** 00002 * @file ADXL362.cpp 00003 * @brief Source file for ADXL362 00004 * @author Analog Devices Inc. 00005 * 00006 * For support please go to: 00007 * Github: https://github.com/analogdevicesinc/mbed-adi 00008 * Support: https://ez.analog.com/community/linux-device-drivers/microcontroller-no-os-drivers 00009 * Product: http://www.analog.com/adxl362 00010 * More: https://wiki.analog.com/resources/tools-software/mbed-drivers-all 00011 00012 ******************************************************************************** 00013 * Copyright 2016(c) Analog Devices, Inc. 00014 * 00015 * All rights reserved. 00016 * 00017 * Redistribution and use in source and binary forms, with or without 00018 * modification, are permitted provided that the following conditions are met: 00019 * - Redistributions of source code must retain the above copyright 00020 * notice, this list of conditions and the following disclaimer. 00021 * - Redistributions in binary form must reproduce the above copyright 00022 * notice, this list of conditions and the following disclaimer in 00023 * the documentation and/or other materials provided with the 00024 * distribution. 00025 * - Neither the name of Analog Devices, Inc. nor the names of its 00026 * contributors may be used to endorse or promote products derived 00027 * from this software without specific prior written permission. 00028 * - The use of this software may or may not infringe the patent rights 00029 * of one or more patent holders. This license does not release you 00030 * from the requirement that you obtain separate licenses from these 00031 * patent holders to use this software. 00032 * - Use of the software either in source or binary form, must be run 00033 * on or directly connected to an Analog Devices Inc. component. 00034 * 00035 * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR 00036 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, 00037 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00038 * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, 00039 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00040 * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR 00041 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00042 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00043 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00044 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00045 * 00046 ********************************************************************************/ 00047 00048 #include <stdint.h> 00049 #include "mbed.h" 00050 #include "ADXL362.h" 00051 00052 /** 00053 * ADXL362 constructor. Sets CS and SPI bus 00054 * @param CS - CS pin of the ADXL362 00055 * @param MOSI - MOSI pin of the ADXL362 00056 * @param MISO - MISO pin of the ADXL362 00057 * @param SCK- SCK pin of the ADXL362 00058 */ 00059 ADXL362::ADXL362(PinName CS, PinName MOSI, PinName MISO, PinName SCK) : 00060 adxl362(MOSI, MISO, SCK), cs(CS), _int1(NULL), _int2(NULL), _int1_poll(NC), _int2_poll( 00061 NC) 00062 { 00063 cs = true; // cs is active low 00064 adxl362.format(8, _SPI_MODE); 00065 _temp_stored_in_fifo = false; 00066 _int1_act_low = true; 00067 _int2_act_low = true; 00068 } 00069 00070 /** 00071 * Sets ADXL362 SPI bus frequency 00072 * @param hz - frequency in hz 00073 */ 00074 void ADXL362::frequency(int hz) 00075 { 00076 adxl362.frequency(hz); 00077 } 00078 00079 /** 00080 * Resets the ADXL362 00081 * A latency of approximately 0.5 ms is required after soft reset. 00082 */ 00083 void ADXL362::reset() 00084 { 00085 adxl362.format(8, _SPI_MODE); 00086 cs = false; 00087 // Writing Code 0x52 (representing the letter, R, in ASCII or unicode) to this register immediately resets the ADXL362. 00088 write_reg(SOFT_RESET, 0x52); 00089 cs = true; 00090 00091 } 00092 00093 /** 00094 * Writes the reg register with data 00095 * @param reg - ADXL362_register_t register to be written 00096 * @param data - data to be written 00097 */ 00098 void ADXL362::write_reg(ADXL362_register_t reg, uint8_t data) 00099 { 00100 adxl362.format(8, _SPI_MODE); 00101 cs = false; 00102 adxl362.write(_WRITE_REG_CMD); 00103 adxl362.write(static_cast<uint8_t>(reg)); 00104 adxl362.write(static_cast<uint8_t>(data)); 00105 cs = true; 00106 } 00107 00108 /** 00109 * Reads the reg register 00110 * @param reg - ADXL362_register_t register to be read 00111 * @return - data read from the register 00112 */ 00113 uint8_t ADXL362::read_reg(ADXL362_register_t reg) 00114 { 00115 uint8_t ret_val; 00116 adxl362.format(8, _SPI_MODE); 00117 cs = false; 00118 adxl362.write(_READ_REG_CMD); 00119 adxl362.write(static_cast<uint8_t>(reg)); 00120 ret_val = adxl362.write(_DUMMY_BYTE); 00121 cs = true; 00122 return ret_val; 00123 } 00124 00125 /** 00126 * Writes 16 bit registers to the ADXL362. Performs conversion from Intel to Motorola byte order 00127 * @param reg - ADXL362_register_t register to be written 00128 * @param data - data to be written 00129 */ 00130 void ADXL362::write_reg_u16(ADXL362_register_t reg, uint16_t data) 00131 { 00132 adxl362.format(8, _SPI_MODE); 00133 00134 cs = false; 00135 adxl362.write(_WRITE_REG_CMD); 00136 adxl362.write(static_cast<uint8_t>(reg)); 00137 adxl362.write(static_cast<uint8_t>(data & 0xff)); 00138 adxl362.write(static_cast<uint8_t>((data & 0xff00) >> 8)); 00139 00140 cs = true; 00141 } 00142 00143 /** 00144 * Reads 16 bit registers from the ADXL362. Performs conversion from Motorola to Intel Byte order 00145 * @param reg - ADXL362_register_t register to be read 00146 * @return - data read from the ADXL362 00147 */ 00148 uint16_t ADXL362::read_reg_u16(ADXL362_register_t reg) 00149 { 00150 uint16_t ret_val = 0; 00151 adxl362.format(8, _SPI_MODE); 00152 00153 cs = false; 00154 adxl362.write(_READ_REG_CMD); 00155 adxl362.write(static_cast<uint8_t>(reg)); 00156 ret_val = adxl362.write(_DUMMY_BYTE); 00157 ret_val = ret_val | (adxl362.write(_DUMMY_BYTE) << 8); 00158 cs = true; 00159 00160 return ret_val; 00161 } 00162 00163 /** 00164 * Scans the X,Y,Z,T registers for data. 00165 * ADXL362 needs to be in measurement mode to read data 00166 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00167 * @return a 64 bit integer with the following format 0xXXYYZZTT 00168 */ 00169 uint64_t ADXL362::scan() 00170 { 00171 uint64_t ret_val = 0; 00172 uint16_t x, y, z, t = 0; 00173 00174 adxl362.format(8, _SPI_MODE); 00175 cs = false; 00176 adxl362.write(_READ_REG_CMD); 00177 adxl362.write(static_cast<uint8_t>(XDATA_L)); 00178 00179 x = adxl362.write(_DUMMY_BYTE); 00180 x = x | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00181 y = adxl362.write(_DUMMY_BYTE); 00182 y = y | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00183 z = adxl362.write(_DUMMY_BYTE); 00184 z = z | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00185 t = adxl362.write(_DUMMY_BYTE); 00186 t = t | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00187 00188 ret_val = static_cast<uint64_t>(x) << 48; 00189 ret_val |= static_cast<uint64_t>(y) << 32; 00190 ret_val |= static_cast<uint64_t>(z) << 16; 00191 ret_val |= static_cast<uint64_t>(t); 00192 cs = true; 00193 return ret_val; 00194 } 00195 00196 /** 00197 * Reads the X 8 bit register from the ADXL362 00198 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00199 * @return 8 bit X data 00200 */ 00201 uint8_t ADXL362::scanx_u8() 00202 { 00203 return read_reg(XDATA); 00204 } 00205 00206 /** 00207 * Reads the X 16 bit register from the ADXL362 00208 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00209 * @return 16 bit X data 00210 */ 00211 uint16_t ADXL362::scanx() 00212 { 00213 return read_reg_u16(XDATA_L); 00214 } 00215 00216 /** 00217 * Reads the Y 8 bit register from the ADXL362 00218 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00219 * @return 8 bit Y data 00220 */ 00221 uint8_t ADXL362::scany_u8() 00222 { 00223 return read_reg(YDATA); 00224 } 00225 00226 /** 00227 * Reads the Y 16 bit register from the ADXL362 00228 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00229 * @return 16 bit Y data 00230 */ 00231 uint16_t ADXL362::scany() 00232 { 00233 return read_reg_u16(YDATA_L); 00234 } 00235 00236 /** 00237 * Reads the Z 8 bit register from the ADXL362 00238 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00239 * @return 8 bit Z data 00240 */ 00241 uint8_t ADXL362::scanz_u8() 00242 { 00243 return read_reg(ZDATA); 00244 } 00245 00246 /** 00247 * Reads the Z 16 bit register from the ADXL362 00248 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00249 * @return 16 bit Z data 00250 */ 00251 uint16_t ADXL362::scanz() 00252 { 00253 return read_reg_u16(ZDATA_L); 00254 } 00255 00256 /** 00257 * Reads the T 16 bit register from the ADXL362 00258 * ADXL362 is set in measurement mode using ADXL362::set_mode(ADXL362::MEASUREMENT) 00259 * @return 16 bit T data 00260 */ 00261 uint16_t ADXL362::scant() 00262 { 00263 return read_reg_u16(TEMP_L); 00264 } 00265 00266 /** 00267 * Sets the STANDBY/MEASUREMENT mode of the ADXL362 00268 * @param mode - ADXL362_modes_t STANDBY/MEASUREMENT mode 00269 */ 00270 void ADXL362::set_mode(ADXL362_modes_t mode) 00271 { 00272 uint8_t reg_val; 00273 reg_val = read_reg(POWER_CTL); 00274 reg_val = reg_val | static_cast<uint8_t>(mode); 00275 write_reg(POWER_CTL, reg_val); 00276 } 00277 00278 /** 00279 * Sets the activity threshold registers 00280 * To enable activity/inactivity, the ACT_INACT_CTL reg must also be set 00281 * using the ADXL362::set_act_inact_ctl_reg(uint8_t data) method 00282 * @param threshold - activity threshold in natural format 00283 */ 00284 void ADXL362::set_activity_threshold(uint16_t threshold) 00285 { 00286 write_reg_u16(THRESH_ACT_L, threshold); 00287 } 00288 00289 /** 00290 * Sets the activity time register 00291 * To enable activity/inactivity, the ACT_INACT_CTL reg must also be set 00292 * using the ADXL362::set_act_inact_ctl_reg(uint8_t data) method 00293 * @param time - activity time 00294 */ 00295 void ADXL362::set_activity_time(uint8_t time) 00296 { 00297 write_reg(TIME_ACT, time); 00298 } 00299 00300 /** 00301 * Sets the inactivity threshold register 00302 * To enable activity/inactivity, the ACT_INACT_CTL reg must also be set 00303 * using the ADXL362::set_act_inact_ctl_reg(uint8_t data) method 00304 * @param threshold - inactivity threshold in natural format 00305 */ 00306 void ADXL362::set_inactivity_threshold(uint16_t threshold) 00307 { 00308 write_reg_u16(THRESH_INACT_L, threshold); 00309 } 00310 00311 /** 00312 * Sets the inactivity time register 00313 * To enable activity/inactivity, the ACT_INACT_CTL reg must also be set 00314 * using the ADXL362::set_act_inact_ctl_reg(uint8_t data) method 00315 * @param time - inactivity time in natural format 00316 */ 00317 void ADXL362::set_inactivity_time(uint16_t time) 00318 { 00319 write_reg_u16(TIME_INACT_L, time); 00320 } 00321 00322 /** 00323 * Sets the ACT_INACT_CTL register of the ADXL362 00324 * @param data - data to be written to the register 00325 */ 00326 void ADXL362::set_act_inact_ctl_reg(uint8_t data) 00327 { 00328 write_reg(ACT_INACT_CTL, data); 00329 } 00330 00331 /** 00332 * Configures INT1 output of the ADXL362 for polling use 00333 * @param in - uC pin connected to ADXL362's INT1 00334 * @param data - data to be written to INTMAP1 00335 * @param pull - (optional) configures pullup on In pin 00336 */ 00337 void ADXL362::set_polling_interrupt1_pin(PinName in, uint8_t data, 00338 PinMode pull) 00339 { 00340 if ((data & 0x7F) != 0) { 00341 write_reg(INTMAP1, data); 00342 _int1_poll = DigitalIn(in); 00343 _int1_poll.mode(pull); 00344 if (data & 0x80) { 00345 _int1_act_low = true; 00346 } else { 00347 _int1_act_low = false; 00348 } 00349 } 00350 } 00351 00352 /** 00353 * Configures INT2 output of the ADXL362 for polling use 00354 * @param in - uC pin connected to ADXL362's INT2 00355 * @param data - data to be written to INTMAP2 00356 * @param pull - (optional) configures pullup on In pin 00357 */ 00358 void ADXL362::set_polling_interrupt2_pin(PinName in, uint8_t data, 00359 PinMode pull) 00360 { 00361 if ((data & 0x7F) != 0) { 00362 write_reg(INTMAP2, data); 00363 _int2_poll = DigitalIn(in); 00364 _int2_poll.mode(pull); 00365 if (data & 0x80) { 00366 _int2_act_low = true; 00367 } else { 00368 _int2_act_low = false; 00369 } 00370 } 00371 } 00372 00373 /** 00374 * Gets the active state of the INT1 pin 00375 * @return true if active, false if not active 00376 */ 00377 bool ADXL362::get_int1() 00378 { 00379 if(_int1_poll != NC) return (_int1_poll.read() != _int1_act_low); // boolean XOR 00380 else return (_int1->read() != _int1_act_low); 00381 } 00382 00383 /** 00384 * Gets the active state of the INT2 pin 00385 * @return true if active, false if not active 00386 */ 00387 bool ADXL362::get_int2() 00388 { 00389 if(_int2_poll != NC) return (_int1_poll.read() != _int1_act_low); // boolean XOR 00390 else return (_int2->read() != _int2_act_low); 00391 } 00392 00393 00394 /** 00395 * Configures the INT1 pin of the ADXL362 to be used in interrupt mode 00396 * @param in - uC pin connected to ADXL362's INT1 00397 * @param data - data to be written to INTMAP1 00398 * @param callback_rising - rising edge interrupt callback - can be set to NULL if no callback is required for rising edge 00399 * @param callback_falling - falling edge interrupt callback - can be set to NULL if no callback is required for falling edge 00400 * @param pull - (optional) configures pullup on In pin 00401 */ 00402 void ADXL362::set_interrupt1_pin(PinName in, uint8_t data, 00403 void (*callback_rising)(void), void (*callback_falling)(void), PinMode pull) 00404 { 00405 if ((data & 0x7F) != 0) { 00406 write_reg(INTMAP1, data); 00407 delete _int1; 00408 _int1 = new InterruptIn(in); 00409 _int1->mode(pull); 00410 if(callback_falling != NULL) _int1->fall(callback_falling); 00411 if(callback_rising != NULL) _int1->rise(callback_rising); 00412 if (data & 0x80) { 00413 _int1_act_low = true; 00414 } else { 00415 _int1_act_low = false; 00416 } 00417 } 00418 } 00419 00420 00421 /** 00422 * Configures the INT2 pin of the ADXL362 to be used in interrupt mode 00423 * @param in - uC pin connected to ADXL362's INT2 00424 * @param data - data to be written to INTMAP2 00425 * @param callback_rising - rising edge interrupt callback - can be set to NULL if no callback is required for rising edge 00426 * @param callback_falling - falling edge interrupt callback - can be set to NULL if no callback is required for falling edge 00427 * @param pull - (optional) configures pullup on In pin 00428 */ 00429 void ADXL362::set_interrupt2_pin(PinName in, uint8_t data, 00430 void (*callback_rising)(void), void (*callback_falling)(void), PinMode pull) 00431 { 00432 if ((data & 0x7F) != 0) { 00433 write_reg(INTMAP2, data); 00434 delete _int2; 00435 _int2 = new InterruptIn(in); 00436 _int2->mode(pull); 00437 if(callback_falling != NULL) _int2->fall(callback_falling); 00438 if(callback_rising != NULL) _int2->rise(callback_rising); 00439 if (data & 0x80) { 00440 _int2_act_low = true; 00441 } else { 00442 _int2_act_low = false; 00443 } 00444 } 00445 } 00446 00447 /** 00448 * Enables external interrupt registration for pin configured as INT1 00449 * To enable this interrupt, it must first be configured using ADXL362::set_interrupt1_pin() 00450 */ 00451 void ADXL362::enable_interrupt1() 00452 { 00453 _int1->enable_irq(); 00454 } 00455 00456 /** 00457 * Enables external interrupt registration for pin configured as INT2 00458 * * To enable this interrupt, it must first be configured using ADXL362::set_interrupt2_pin() 00459 */ 00460 void ADXL362::enable_interrupt2() 00461 { 00462 _int2->enable_irq(); 00463 } 00464 00465 /** 00466 * Disables external interrupt registration for pin configured as INT1 00467 */ 00468 void ADXL362::disable_interrupt1() 00469 { 00470 _int1->disable_irq(); 00471 } 00472 00473 /** 00474 * Disables external interrupt registration for pin configured as INT2 00475 */ 00476 void ADXL362::disable_interrupt2() 00477 { 00478 _int2->disable_irq(); 00479 } 00480 00481 /** 00482 * Sets the POWER_CTL register 00483 * @param data - data to be written to the register 00484 */ 00485 void ADXL362::set_power_ctl_reg(uint8_t data) 00486 { 00487 write_reg(POWER_CTL, data); 00488 } 00489 00490 /** 00491 * Sets the FILTER_CTL register 00492 * @param data - data to be written to the register 00493 */ 00494 void ADXL362::set_filter_ctl_reg(uint8_t data) 00495 { 00496 write_reg(FILTER_CTL, data); 00497 } 00498 00499 /** 00500 * Reads the STATUS register of the ADXL362 00501 * @return - data in the status register 00502 */ 00503 uint8_t ADXL362::read_status() 00504 { 00505 return read_reg(STATUS); 00506 } 00507 00508 /** 00509 * Reads the FIFO_ENTRIES_L and FIFO_ENTRIES_H register 00510 * @return the number of entries in the FIFO 00511 */ 00512 uint16_t ADXL362::fifo_read_nr_of_entries() 00513 { 00514 return read_reg_u16(FIFO_ENTRIES_L); 00515 } 00516 00517 /** 00518 * Setup for the FIFO 00519 * @param store_temp - boolean, true - temperature will be stored in the fifo. false otherwise 00520 * @param mode - ADXL362_FIFO_modes_t fifo mode 00521 * @param nr_of_entries - number of entries in the FIFO 00522 */ 00523 void ADXL362::fifo_setup(bool store_temp, ADXL362_FIFO_modes_t mode, uint16_t nr_of_entries) 00524 { 00525 uint8_t fifo_ctl = static_cast<uint8_t>(mode); 00526 _temp_stored_in_fifo = store_temp; 00527 00528 fifo_ctl = fifo_ctl | (static_cast<uint8_t>(_temp_stored_in_fifo) << 2); 00529 00530 if (nr_of_entries > 0xff) { 00531 fifo_ctl = fifo_ctl | static_cast<uint8_t>(AH); 00532 } 00533 write_reg(FIFO_CONTROL, fifo_ctl); 00534 write_reg(FIFO_SAMPLES, static_cast<uint8_t>(nr_of_entries & 0xff)); 00535 00536 } 00537 00538 /** 00539 * Reads a FIFO entry 00540 * @return FIFO entry 00541 */ 00542 uint16_t ADXL362::fifo_read_u16() 00543 { 00544 uint16_t ret_val = 0; 00545 adxl362.format(8, _SPI_MODE); 00546 00547 cs = false; 00548 adxl362.write(_READ_FIFO_CMD); 00549 ret_val = adxl362.write(_DUMMY_BYTE); 00550 ret_val = (ret_val) | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00551 cs = true; 00552 00553 return ret_val; 00554 } 00555 00556 /** 00557 * Reads 3(4) bytes from the FIFO(if store_temp was set), assembles the data in the format used by the scan method 00558 * ADXL362::fifo_setup() needs to be called before calling fifo_scan to ensure correct fifo operation 00559 * fifo_scan and fifo_read_u16 should not be used as fifo_read_u16 disaligns the fifo therefore 00560 * fifo_scan will return data from multiple samples 00561 * @return scanned data from the fifo in the 0xXXYYZZTT format 00562 */ 00563 uint64_t ADXL362::fifo_scan() 00564 { 00565 00566 uint64_t ret_val = 0; 00567 uint16_t x = 0, y = 0, z = 0, dummy, t = 0, sample_type; 00568 00569 adxl362.format(8, _SPI_MODE); 00570 cs = false; 00571 adxl362.write(_READ_FIFO_CMD); 00572 uint8_t samples = (_temp_stored_in_fifo) ? 4 : 3; 00573 for(uint8_t i = 0; i < samples; i++) { 00574 dummy = adxl362.write(_DUMMY_BYTE); 00575 dummy = dummy | static_cast<uint16_t>(adxl362.write(_DUMMY_BYTE) << 8); 00576 sample_type = (dummy & 0xc000) >> 14; 00577 dummy = dummy & 0x3fff; 00578 switch(sample_type) { 00579 case 0: // x 00580 x = dummy; 00581 break; 00582 case 1: // y 00583 y = dummy; 00584 break; 00585 case 2: // z 00586 z = dummy; 00587 break; 00588 case 3: // temp 00589 t = dummy; 00590 break; 00591 } 00592 00593 } 00594 00595 // format xxyyzztt 00596 ret_val = static_cast<uint64_t> (x) << 48; 00597 ret_val |= static_cast<uint64_t>(y) << 32; 00598 ret_val |= static_cast<uint64_t>(z) << 16; 00599 ret_val |= static_cast<uint64_t>(t); 00600 cs = true; 00601 return ret_val; 00602 }
Generated on Tue Jul 12 2022 17:59:52 by
1.7.2
CN0357 - Toxic gas measurement
CN0216 - Weight Scale