123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926 |
- /**\mainpage
- * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * Neither the name of the copyright holder nor the names of the
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
- * OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
- * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
- *
- * The information provided is believed to be accurate and reliable.
- * The copyright holder assumes no responsibility
- * for the consequences of use
- * of such information nor for any infringement of patents or
- * other rights of third parties which may result from its use.
- * No license is granted by implication or otherwise under any patent or
- * patent rights of the copyright holder.
- *
- * File bmm150.c
- * Date 12 Sep 2017
- * Version 1.0.0
- *
- */
- /*! @file bmm150.c
- @brief Sensor driver for BMM150 sensor */
- #include "bmm150.h"
- /************************** Internal macros *******************************/
- /* Sensor ODR, Repetition and axes enable/disable settings */
- #define MODE_SETTING_SEL UINT16_C(0x000F)
- /* Interrupt pin settings like polarity,latch and int_pin enable */
- #define INTERRUPT_PIN_SETTING_SEL UINT16_C(0x01F0)
- /* Settings to enable/disable interrupts */
- #define INTERRUPT_CONFIG_SEL UINT16_C(0x1E00)
- /* Interrupt settings for configuring threshold values */
- #define INTERRUPT_THRESHOLD_CONFIG_SEL UINT16_C(0x6000)
- /********************** Static function declarations ************************/
- /*!
- * @brief This internal API is used to validate the device pointer for
- * null conditions.
- *
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t null_ptr_check(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API sets/resets the power control bit of 0x4B register.
- *
- * @param[in] pwrcntrl_bit : Variable used to select/deselect the suspend mode.
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * pwrcntrl_bit | power mode
- * -----------------|-------------------------
- * 0x00 | Suspend mode
- * 0x01 | Sleep/Active modes
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t set_power_control_bit(uint8_t pwrcntrl_bit, struct bmm150_dev *dev);
- /*!
- * @brief This internal API reads the trim registers of the sensor and stores
- * the trim values in the "trim_data" of device structure.
- *
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t read_trim_registers(struct bmm150_dev *dev);
- /*!
- * @brief This internal API writes the op_mode value in the Opmode bits
- * (bits 1 and 2) of 0x4C register.
- *
- * op_mode | Power mode
- * ------------|-----------------------
- * 0x00 | BMM150_NORMAL_MODE
- * 0x01 | BMM150_FORCED_MODE
- * 0x03 | BMM150_SLEEP_MODE
- *
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t write_op_mode(uint8_t op_mode, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API sets the device from suspend to sleep mode
- * by setting the power control bit to '1' of 0x4B register
- *
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t suspend_to_sleep_mode(struct bmm150_dev *dev);
- /*!
- * @brief This internal API sets the xy repetition value in the 0x51 register.
- *
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * dev->settings.xy_rep | nXY(XY Repetitions)
- * -------------------------|-----------------------
- * 0x00 | 1
- * 0x01 | 3
- * 0x02 | 5
- * . | .
- * . | .
- * 0xFF | 511
- *
- * @note number of XY Repetitions nXY = 1+2(dev->settings.xy_rep)
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t set_xy_rep(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API sets the z repetition value in the 0x52 register.
- *
- * @param[in,out] dev : Structure instance of bmm150_dev
- *
- * dev->settings.z_rep | nZ(Z Repetitions)
- * -------------------------|-----------------------
- * 0x00 | 1
- * 0x01 | 2
- * 0x02 | 3
- * . | .
- * . | .
- * 0xFF | 256
- *
- * @note number of Z Repetitions nZ = 1+(dev->settings.z_rep)
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t set_z_rep(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to set the output data rate of the sensor
- *
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * dev->settings.data_rate | Data rate (ODR)
- * -------------------------|-----------------------
- * 0x00 | BMM150_DATA_RATE_10HZ
- * 0x01 | BMM150_DATA_RATE_02HZ
- * 0x02 | BMM150_DATA_RATE_06HZ
- * 0x03 | BMM150_DATA_RATE_08HZ
- * 0x04 | BMM150_DATA_RATE_15HZ
- * 0x05 | BMM150_DATA_RATE_20HZ
- * 0x06 | BMM150_DATA_RATE_25HZ
- * 0x07 | BMM150_DATA_RATE_30HZ
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t set_odr(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API sets the preset mode ODR and repetition settings.
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * API settings | Representation
- * -------------------------|------------------------------
- * dev->settings.data_rate | Output Data Rate (ODR)
- * dev->settings.xy_rep | XY repetition value
- * dev->settings.z_rep | Z-repetition value
- *
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error.
- */
- static int8_t set_odr_xyz_rep(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to enable or disable the magnetic
- * measurement of x,y,z axes based on the value of xyz_axes_control.
- *
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * dev->settings.xyz_axes_control | Measurement axes/channel
- * -------------------------------|--------------------------
- * Bit 0 | X - Channel
- * Bit 1 | Y - Channel
- * Bit 2 | Z - Channel
- *
- * @note Setting 1 - Disables Channel measurement
- * @note Setting 0 - Enables Channel measurement
- *
- * dev->settings.xyz_axes_control | Measurement axes Enabled/disabled
- * -------------------------------|------------------------------------
- * 0x01 | Disables X axis (Y,Z axes enabled)
- * 0x02 | Disables Y axis (X,Z axes enabled)
- * 0x04 | Disables Z axis (X,Y axes enabled)
- * 0x07 | Disables all X,Y,Z axes measurement
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t set_control_measurement_xyz(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to identify the settings which the user
- * wants to modify in the sensor.
- *
- * @param[in] sub_settings : Contains the settings subset to identify particular
- * group of settings which the user is interested to change.
- * @param[in] settings : Contains the user specified settings.
- *
- * @return Indicates whether user is interested to modify the settings which
- * are related to sub_settings.
- * @retval True -> User wants to modify this group of settings
- * @retval False -> User does not want to modify this group of settings
- */
- static uint8_t are_settings_changed(uint16_t sub_settings, uint16_t settings);
- /*!
- * @brief This API sets the ODR , measurement axes control ,
- * repetition values of xy,z.
- *
- * @param[in] desired_settings : Contains the settings which user wants to
- * change.
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t mode_settings(uint16_t desired_settings, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to parse and store the sensor
- * settings in the device structure
- *
- * @param[in] reg_data : Pointer of an array consisting all sensor
- * setting data from 0x4B to 0x52 registers.
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static void parse_setting(const uint8_t *reg_data, struct bmm150_dev *dev);
- /*!
- * @brief This API is used to enable the interrupts and map them to the
- * corresponding interrupt pins and specify the pin characteristics like the
- * polarity , latch settings for the interrupt pins.
- *
- * @note The other interrupts can be latched or non-latched but,
- * Data ready interrupt is always cleared after reading out the data
- *
- * @param[in] desired_settings : Contains the settings which user wants to
- * change.
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t interrupt_pin_settings(uint16_t desired_settings, const struct bmm150_dev *dev);
- /*!
- * @brief This API is used to enable data overrun , overflow interrupts and
- * enable/disable high/low threshold interrupts for x,y,z axis based on the
- * threshold values set by the user in the High threshold (0x50) and
- * Low threshold (0x4F) registers.
- *
- * @param[in] desired_settings : Contains the settings which user wants to
- * change.
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t interrupt_config(uint16_t desired_settings, const struct bmm150_dev *dev);
- /*!
- * @brief This API is used to write the user specified High/Low threshold value
- * as a reference to generate the high/low threshold interrupt.
- *
- * @param[in] desired_settings : Contains the settings which user wants to
- * change.
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t interrupt_threshold_settings(uint16_t desired_settings, const struct bmm150_dev *dev);
- #ifdef BMM150_USE_FLOATING_POINT
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer X axis data in float.
- *
- * @param[in] mag_data_x : The value of raw X data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated X data value in float
- */
- static float compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Y axis data in float.
- *
- * @param[in] mag_data_y : The value of raw Y data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated Y data value in float
- */
- static float compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Z axis data in float.
- *
- * @param[in] mag_data_z : The value of raw Z data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated Z data value in float
- */
- static float compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev);
- #else
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer X axis data in int16_t.
- *
- * @param[in] mag_data_x : The value of raw X data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated X data value in int16_t format
- */
- static int16_t compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Y axis data in int16_t.
- *
- * @param[in] mag_data_y : The value of raw Y data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated Y data value in int16_t format
- */
- static int16_t compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Z axis data in int16_t.
- *
- * @param[in] mag_data_z : The value of raw Z data
- * @param[in] data_rhall : The value of raw RHALL data
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of compensated Z data value in int16_t format
- */
- static int16_t compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev);
- #endif
- /*!
- * @brief This internal API is used to perform the normal self test
- * of the sensor and return the self test result as return value
- *
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t perform_normal_self_test(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to enable the normal self test by setting
- * the Self Test bit (bit0) of the 0x4C register,
- * which triggers the start of self test
- *
- * @param[out] self_test_enable : The value of self test bit0 in 0x4C register
- * @param[in] dev : Structure instance of bmm150_dev.
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t enable_normal_self_test(uint8_t *self_test_enable, const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to validate the results of normal self test
- * by using the self test status available in the bit0 of registers 0x42,0x44
- * and 0x46.
- *
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t validate_normal_self_test(const struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to perform advanced self test for Z axis
- *
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- *
- * Return value | Status of self-test
- *----------------------|---------------------------
- * 0 | BMM150_OK
- * 8 | BMM150_W_ADV_SELF_TEST_FAIL
- */
- static int8_t perform_adv_self_test(struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to set the desired power mode ,
- * axes control and repetition settings for advanced self test
- *
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t adv_self_test_settings(struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to set the positive or negative value of
- * self-test current and obtain the corresponding magnetometer z axis data
- *
- * @param[in] self_test_current : Self test current either positive/negative
- * @param[out] data_z : Z-axis Magnetometer data
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * self_test_current | Self-test current Direction
- *-------------------------|------------------------------
- * 0x03 | BMM150_ENABLE_POSITIVE_CURRENT
- * 0x02 | BMM150_ENABLE_NEGATIVE_CURRENT
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z, struct bmm150_dev *dev);
- /*!
- * @brief This internal API is used to get the difference between the
- * Z axis mag data obtained by positive and negative self-test current
- * and validate whether the advanced self test is done successfully or not.
- *
- * @param[in] positive_data_z : Z-axis Mag data by positive self-test current
- * @param[in] negative_data_z : Z-axis Mag data by negative self-test current
- *
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- *
- * Return value | Status of self-test
- *----------------------|---------------------------
- * 0 | BMM150_OK
- * 8 | BMM150_W_ADV_SELF_TEST_FAIL
- */
- static int8_t validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z);
- /*!
- * @brief This internal API is used to set the self test current value in
- * the Adv. ST bits (bit6 and bit7) of 0x4C register
- *
- * @param[in] self_test_current : Self test current value (+ve/-ve)
- * @param[in] dev : Structure instance of bmm150_dev
- *
- * self_test_current | Self-test current Direction
- *-------------------------|------------------------------
- * 0x00 | BMM150_DISABLE_SELF_TEST_CURRENT
- * 0x02 | BMM150_ENABLE_NEGATIVE_CURRENT
- * 0x03 | BMM150_ENABLE_POSITIVE_CURRENT
- *
- * @return Result of API execution status
- * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
- */
- static int8_t set_adv_self_test_current(uint8_t self_test_current, const struct bmm150_dev *dev);
- /********************** Global function definitions ************************/
- /*!
- * @brief This API is the entry point, Call this API before using other APIs.
- * This API reads the chip-id of the sensor which is the first step to
- * verify the sensor and updates the trim parameters of the sensor.
- */
- int8_t bmm150_init(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t chip_id = 0;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* Power up the sensor from suspend to sleep mode */
- rslt = set_power_control_bit(BMM150_POWER_CNTRL_ENABLE, dev);
- /* Start-up time delay of 3ms*/
- dev->delay_ms(BMM150_START_UP_TIME);
- if (rslt == BMM150_OK) {
- /* Chip ID of the sensor is read */
- rslt = bmm150_get_regs(BMM150_CHIP_ID_ADDR, &chip_id, 1, dev);
- /* Proceed if everything is fine until now */
- if (rslt == BMM150_OK) {
- /* Check for chip id validity */
- if (chip_id == BMM150_CHIP_ID) {
- dev->chip_id = chip_id;
- /* Function to update trim values */
- rslt = read_trim_registers(dev);
- } else {
- rslt = BMM150_E_DEV_NOT_FOUND;
- }
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This API writes the given data to the register address
- * of the sensor.
- */
- int8_t bmm150_set_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if ((rslt == BMM150_OK) && (reg_data != NULL) && (len != 0)) {
- /* Write the data to the reg_addr */
- /* SPI write requires to set The MSB of reg_addr as 0
- but in default the MSB is always 0 */
- rslt = dev->write(dev->dev_id, reg_addr, reg_data, len);
- } else {
- rslt = BMM150_E_NULL_PTR;
- }
- return rslt;
- }
- /*!
- * @brief This API reads the data from the given register address of the sensor.
- */
- int8_t bmm150_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if ((rslt == BMM150_OK) && (reg_data != NULL)) {
- if (dev->intf != BMM150_I2C_INTF) {
- /* If interface selected is SPI */
- reg_addr = reg_addr | 0x80;
- }
- /* Read the data from the reg_addr */
- rslt = dev->read(dev->dev_id, reg_addr, reg_data, len);
- } else {
- rslt = BMM150_E_NULL_PTR;
- }
- return rslt;
- }
- /*!
- * @brief This API is used to perform soft-reset of the sensor
- * where all the registers are reset to their default values except 0x4B.
- */
- int8_t bmm150_soft_reset(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- rslt = bmm150_get_regs(BMM150_POWER_CONTROL_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- reg_data = reg_data | BMM150_SET_SOFT_RESET;
- rslt = bmm150_set_regs(BMM150_POWER_CONTROL_ADDR, ®_data, 1, dev);
- dev->delay_ms(BMM150_SOFT_RESET_DELAY);
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to set the power mode of the sensor.
- */
- int8_t bmm150_set_op_mode(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t pwr_mode = dev->settings.pwr_mode;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* Select the power mode to set */
- switch (pwr_mode) {
- case BMM150_NORMAL_MODE:
- /* If the sensor is in suspend mode
- put the device to sleep mode */
- rslt = suspend_to_sleep_mode(dev);
- if (rslt == BMM150_OK) {
- /* write the op mode */
- rslt = write_op_mode(pwr_mode, dev);
- }
- break;
- case BMM150_FORCED_MODE:
- /* If the sensor is in suspend mode
- put the device to sleep mode */
- rslt = suspend_to_sleep_mode(dev);
- if (rslt == BMM150_OK) {
- /* write the op mode */
- rslt = write_op_mode(pwr_mode, dev);
- }
- break;
- case BMM150_SLEEP_MODE:
- /* If the sensor is in suspend mode
- put the device to sleep mode */
- rslt = suspend_to_sleep_mode(dev);
- if (rslt == BMM150_OK) {
- /* write the op mode */
- rslt = write_op_mode(pwr_mode, dev);
- }
- break;
- case BMM150_SUSPEND_MODE:
- /* Set the power control bit to zero */
- rslt = set_power_control_bit(BMM150_POWER_CNTRL_DISABLE, dev);
- break;
- default:
- rslt = BMM150_E_INVALID_CONFIG;
- break;
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to get the power mode of the sensor.
- */
- int8_t bmm150_get_op_mode(uint8_t *op_mode, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- if (dev->settings.pwr_cntrl_bit == BMM150_POWER_CNTRL_DISABLE) {
- /* Power mode set is suspend mode*/
- *op_mode = BMM150_SUSPEND_MODE;
- } else {
- /*Power mode set is stored in the op_mode */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- *op_mode = BMM150_GET_BITS(reg_data, BMM150_OP_MODE);
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to set the preset mode of the sensor.
- */
- int8_t bmm150_set_presetmode(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t preset_mode;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- preset_mode = dev->settings.preset_mode;
- switch (preset_mode) {
- case BMM150_PRESETMODE_LOWPOWER:
- /* Set the data rate x,y,z repetition
- for Low Power mode */
- dev->settings.data_rate = BMM150_DATA_RATE_10HZ;
- dev->settings.xy_rep = BMM150_LOWPOWER_REPXY;
- dev->settings.z_rep = BMM150_LOWPOWER_REPZ;
- rslt = set_odr_xyz_rep(dev);
- break;
- case BMM150_PRESETMODE_REGULAR:
- /* Set the data rate x,y,z repetition
- for Regular mode */
- dev->settings.data_rate = BMM150_DATA_RATE_10HZ;
- dev->settings.xy_rep = BMM150_REGULAR_REPXY;
- dev->settings.z_rep = BMM150_REGULAR_REPZ;
- rslt = set_odr_xyz_rep(dev);
- break;
- case BMM150_PRESETMODE_HIGHACCURACY:
- /* Set the data rate x,y,z repetition
- for High Accuracy mode */
- dev->settings.data_rate = BMM150_DATA_RATE_20HZ;
- dev->settings.xy_rep = BMM150_HIGHACCURACY_REPXY;
- dev->settings.z_rep = BMM150_HIGHACCURACY_REPZ;
- rslt = set_odr_xyz_rep(dev);
- break;
- case BMM150_PRESETMODE_ENHANCED:
- /* Set the data rate x,y,z repetition
- for Enhanced Accuracy mode */
- dev->settings.data_rate = BMM150_DATA_RATE_10HZ;
- dev->settings.xy_rep = BMM150_ENHANCED_REPXY;
- dev->settings.z_rep = BMM150_ENHANCED_REPZ;
- rslt = set_odr_xyz_rep(dev);
- break;
- default:
- rslt = BMM150_E_INVALID_CONFIG;
- break;
- }
- }
- return rslt;
- }
- /*!
- * @brief This API sets the sensor settings based on the desired_settings
- * and the dev structure configuration
- */
- int8_t bmm150_set_sensor_settings(uint16_t desired_settings, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- if (are_settings_changed(MODE_SETTING_SEL, desired_settings)) {
- /* ODR, Control measurement, XY,Z repetition values*/
- rslt = mode_settings(desired_settings, dev);
- }
- if ((!rslt) && are_settings_changed(INTERRUPT_PIN_SETTING_SEL, desired_settings)) {
- /* Interrupt pin settings */
- rslt = interrupt_pin_settings(desired_settings, dev);
- }
- if ((!rslt) && are_settings_changed(INTERRUPT_CONFIG_SEL, desired_settings)) {
- /* Interrupt configuration settings */
- rslt = interrupt_config(desired_settings, dev);
- }
- if ((!rslt) && are_settings_changed(INTERRUPT_THRESHOLD_CONFIG_SEL, desired_settings)) {
- /* Interrupt threshold settings */
- rslt = interrupt_threshold_settings(desired_settings, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This API gets the sensor settings and updates the dev structure
- */
- int8_t bmm150_get_sensor_settings(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t setting[BMM150_SETTING_DATA_LEN] = {0};
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /*Read the entire sensor settings */
- rslt = bmm150_get_regs(BMM150_POWER_CONTROL_ADDR, setting, BMM150_SETTING_DATA_LEN, dev);
- if (rslt == BMM150_OK) {
- /*Parse and store the settings */
- parse_setting(setting, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to read the magnetometer data from registers
- * 0x42 to 0x49 and update the dev structure with the
- * compensated mag data in micro-tesla.
- */
- int8_t bmm150_read_mag_data(struct bmm150_dev *dev)
- {
- int8_t rslt;
- int16_t msb_data;
- uint8_t reg_data[BMM150_XYZR_DATA_LEN] = {0};
- struct bmm150_raw_mag_data raw_mag_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /*Read the mag data registers */
- rslt = bmm150_get_regs(BMM150_DATA_X_LSB, reg_data, BMM150_XYZR_DATA_LEN, dev);
- if (rslt == BMM150_OK) {
- /* Mag X axis data */
- reg_data[0] = BMM150_GET_BITS(reg_data[0], BMM150_DATA_X);
- /* Shift the MSB data to left by 5 bits */
- /* Multiply by 32 to get the shift left by 5 value */
- msb_data = ((int16_t)((int8_t)reg_data[1])) * 32;
- /* Raw mag X axis data */
- raw_mag_data.raw_datax = (int16_t)(msb_data | reg_data[0]);
- /* Mag Y axis data */
- reg_data[2] = BMM150_GET_BITS(reg_data[2], BMM150_DATA_Y);
- /* Shift the MSB data to left by 5 bits */
- /* Multiply by 32 to get the shift left by 5 value */
- msb_data = ((int16_t)((int8_t)reg_data[3])) * 32;
- /* Raw mag Y axis data */
- raw_mag_data.raw_datay = (int16_t)(msb_data | reg_data[2]);
- /* Mag Z axis data */
- reg_data[4] = BMM150_GET_BITS(reg_data[4], BMM150_DATA_Z);
- /* Shift the MSB data to left by 7 bits */
- /* Multiply by 128 to get the shift left by 7 value */
- msb_data = ((int16_t)((int8_t)reg_data[5])) * 128;
- /* Raw mag Z axis data */
- raw_mag_data.raw_dataz = (int16_t)(msb_data | reg_data[4]);
- /* Mag R-HALL data */
- reg_data[6] = BMM150_GET_BITS(reg_data[6], BMM150_DATA_RHALL);
- raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)reg_data[7] << 6) | reg_data[6]);
- /* Compensated Mag X data in int16_t format */
- dev->data.x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r, dev);
- /* Compensated Mag Y data in int16_t format */
- dev->data.y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r, dev);
- /* Compensated Mag Z data in int16_t format */
- dev->data.z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to perform the complete self test
- * (both normal and advanced) for the BMM150 sensor
- */
- int8_t bmm150_perform_self_test(uint8_t self_test_mode, struct bmm150_dev *dev)
- {
- int8_t rslt;
- int8_t self_test_rslt = 0;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- switch (self_test_mode) {
- case BMM150_NORMAL_SELF_TEST:
- /* Set the sensor in sleep mode */
- dev->settings.pwr_mode = BMM150_SLEEP_MODE;
- rslt = bmm150_set_op_mode(dev);
- if (rslt == BMM150_OK) {
- /* Perform the normal self test */
- rslt = perform_normal_self_test(dev);
- }
- break;
- case BMM150_ADVANCED_SELF_TEST:
- /* Perform the advanced self test */
- rslt = perform_adv_self_test(dev);
- /* Check to ensure bus error does not occur */
- if (rslt >= BMM150_OK) {
- /* Store the status of self test result */
- self_test_rslt = rslt;
- /* Perform soft reset */
- rslt = bmm150_soft_reset(dev);
- }
- /* Check to ensure bus operations are success */
- if (rslt == BMM150_OK) {
- /* Restore self_test_rslt as return value */
- rslt = self_test_rslt;
- }
- break;
- default:
- rslt = BMM150_E_INVALID_CONFIG;
- break;
- }
- }
- return rslt;
- }
- /*!
- * @brief This API is used to get the status flags of all interrupt
- * which is used to check for the assertion of interrupts
- */
- int8_t bmm150_get_interrupt_status(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t interrupt_status;
- uint8_t data_ready_status;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* Read the data ready status from the register 0x48 */
- rslt = bmm150_get_regs(BMM150_DATA_READY_STATUS, &data_ready_status, 1, dev);
- if (rslt == BMM150_OK) {
- /* Read the interrupt status from the register 0x50 */
- rslt = bmm150_get_regs(BMM150_INTERRUPT_STATUS, &interrupt_status, 1, dev);
- if (rslt == BMM150_OK) {
- /* Mask and store the data ready status bit*/
- data_ready_status = BMM150_GET_BITS_POS_0(data_ready_status, BMM150_DRDY_STATUS);
- /* store the entire interrupt status in dev */
- dev->int_status = (data_ready_status << 8) | interrupt_status;
- }
- }
- }
- return rslt;
- }
- /****************************************************************************/
- /**\name BMM150 as Auxiliary Mag */
- /*!
- * @brief This API is used to compensate the raw mag data
- */
- int8_t bmm150_aux_mag_data(uint8_t *aux_data, struct bmm150_dev *dev)
- {
- int8_t rslt;
- int16_t msb_data;
- struct bmm150_raw_mag_data raw_mag_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if ((rslt == BMM150_OK) && (aux_data != NULL)) {
- /* Mag X axis data */
- aux_data[0] = BMM150_GET_BITS(aux_data[0], BMM150_DATA_X);
- /* Shift the MSB data to left by 5 bits */
- /* Multiply by 32 to get the shift left by 5 value */
- msb_data = ((int16_t)((int8_t)aux_data[1])) * 32;
- /* Raw mag X axis data */
- raw_mag_data.raw_datax = (int16_t)(msb_data | aux_data[0]);
- /* Mag Y axis data */
- aux_data[2] = BMM150_GET_BITS(aux_data[2], BMM150_DATA_Y);
- /* Shift the MSB data to left by 5 bits */
- /* Multiply by 32 to get the shift left by 5 value */
- msb_data = ((int16_t)((int8_t)aux_data[3])) * 32;
- /* Raw mag Y axis data */
- raw_mag_data.raw_datay = (int16_t)(msb_data | aux_data[2]);
- /* Mag Z axis data */
- aux_data[4] = BMM150_GET_BITS(aux_data[4], BMM150_DATA_Z);
- /* Shift the MSB data to left by 7 bits */
- /* Multiply by 128 to get the shift left by 7 value */
- msb_data = ((int16_t)((int8_t)aux_data[5])) * 128;
- /* Raw mag Z axis data */
- raw_mag_data.raw_dataz = (int16_t)(msb_data | aux_data[4]);
- /* Mag R-HALL data */
- aux_data[6] = BMM150_GET_BITS(aux_data[6], BMM150_DATA_RHALL);
- raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)aux_data[7] << 6) | aux_data[6]);
- /* Compensated Mag X data in int16_t format */
- dev->data.x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r, dev);
- /* Compensated Mag Y data in int16_t format */
- dev->data.y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r, dev);
- /* Compensated Mag Z data in int16_t format */
- dev->data.z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r, dev);
- }
- return rslt;
- }
- /****************************************************************************/
- /**\name INTERNAL APIs */
- /*!
- * @brief This internal API is used to validate the device structure pointer for
- * null conditions.
- */
- static int8_t null_ptr_check(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) {
- /* Device structure pointer is not valid */
- rslt = BMM150_E_NULL_PTR;
- } else {
- /* Device structure is fine */
- rslt = BMM150_OK;
- }
- return rslt;
- }
- /*!
- * @brief This internal API sets/resets the power control bit of 0x4B register.
- */
- static int8_t set_power_control_bit(uint8_t pwrcntrl_bit, struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data = 0;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* Power control register 0x4B is read */
- rslt = bmm150_get_regs(BMM150_POWER_CONTROL_ADDR, ®_data, 1, dev);
- /* Proceed if everything is fine until now */
- if (rslt == BMM150_OK) {
- /* Sets the value of power control bit */
- reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_PWR_CNTRL, pwrcntrl_bit);
- rslt = bmm150_set_regs(BMM150_POWER_CONTROL_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /*Store the power control bit
- value in dev structure*/
- dev->settings.pwr_cntrl_bit = pwrcntrl_bit;
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API reads the trim registers of the sensor and stores
- * the trim values in the "trim_data" of device structure.
- */
- static int8_t read_trim_registers(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t trim_x1y1[2] = {0};
- uint8_t trim_xyz_data[4] = {0};
- uint8_t trim_xy1xy2[10] = {0};
- uint16_t temp_msb = 0;
- /* Trim register value is read */
- rslt = bmm150_get_regs(BMM150_DIG_X1, trim_x1y1, 2, dev);
- if (rslt == BMM150_OK) {
- rslt = bmm150_get_regs(BMM150_DIG_Z4_LSB, trim_xyz_data, 4, dev);
- if (rslt == BMM150_OK) {
- rslt = bmm150_get_regs(BMM150_DIG_Z2_LSB, trim_xy1xy2, 10, dev);
- if (rslt == BMM150_OK) {
- /* Trim data which is read is updated
- in the device structure */
- dev->trim_data.dig_x1 = (int8_t)trim_x1y1[0];
- dev->trim_data.dig_y1 = (int8_t)trim_x1y1[1];
- dev->trim_data.dig_x2 = (int8_t)trim_xyz_data[2];
- dev->trim_data.dig_y2 = (int8_t)trim_xyz_data[3];
- temp_msb = ((uint16_t)trim_xy1xy2[3]) << 8;
- dev->trim_data.dig_z1 = (uint16_t)(temp_msb | trim_xy1xy2[2]);
- temp_msb = ((uint16_t)trim_xy1xy2[1]) << 8;
- dev->trim_data.dig_z2 = (int16_t)(temp_msb | trim_xy1xy2[0]);
- temp_msb = ((uint16_t)trim_xy1xy2[7]) << 8;
- dev->trim_data.dig_z3 = (int16_t)(temp_msb | trim_xy1xy2[6]);
- temp_msb = ((uint16_t)trim_xyz_data[1]) << 8;
- dev->trim_data.dig_z4 = (int16_t)(temp_msb | trim_xyz_data[0]);
- dev->trim_data.dig_xy1 = trim_xy1xy2[9];
- dev->trim_data.dig_xy2 = (int8_t)trim_xy1xy2[8];
- temp_msb = ((uint16_t)(trim_xy1xy2[5] & 0x7F)) << 8;
- dev->trim_data.dig_xyz1 = (uint16_t)(temp_msb | trim_xy1xy2[4]);
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API writes the op_mode value in the Opmode bits
- * (bits 1 and 2) of 0x4C register.
- */
- static int8_t write_op_mode(uint8_t op_mode, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* Read the 0x4C register */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /* Set the op_mode value in Opmode bits of 0x4C */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_OP_MODE, op_mode);
- rslt = bmm150_set_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API sets the device from suspend to sleep mode
- * by setting the power control bit to '1' of 0x4B register
- */
- static int8_t suspend_to_sleep_mode(struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- if (dev->settings.pwr_cntrl_bit == BMM150_POWER_CNTRL_DISABLE) {
- rslt = set_power_control_bit(BMM150_POWER_CNTRL_ENABLE, dev);
- /* Start-up time delay of 3ms*/
- dev->delay_ms(BMM150_START_UP_TIME);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API sets the xy repetition value in the 0x51 register.
- */
- static int8_t set_xy_rep(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t rep_xy;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* set the xy repetition */
- rep_xy = dev->settings.xy_rep;
- rslt = bmm150_set_regs(BMM150_REP_XY_ADDR, &rep_xy, 1, dev);
- }
- return rslt;
- }
- /*!
- * @brief This internal API sets the z repetition value in the 0x52 register.
- */
- static int8_t set_z_rep(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t rep_z;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /* set the z repetition */
- rep_z = dev->settings.z_rep;
- rslt = bmm150_set_regs(BMM150_REP_Z_ADDR, &rep_z, 1, dev);
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to set the output data rate of the sensor.
- */
- static int8_t set_odr(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- /*Read the 0x4C register */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /*Set the ODR value */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_ODR, dev->settings.data_rate);
- rslt = bmm150_set_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API sets the preset mode ODR and repetition settings.
- */
- static int8_t set_odr_xyz_rep(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Set the ODR */
- rslt = set_odr(dev);
- if (rslt == BMM150_OK) {
- /* Set the XY-repetitions number */
- rslt = set_xy_rep(dev);
- if (rslt == BMM150_OK) {
- /* Set the Z-repetitions number */
- rslt = set_z_rep(dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to enable or disable the magnetic
- * measurement of x,y,z axes based on the value of xyz_axes_control.
- */
- static int8_t set_control_measurement_xyz(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Check for null pointer in the device structure*/
- rslt = null_ptr_check(dev);
- /* Proceed if null check is fine */
- if (rslt == BMM150_OK) {
- rslt = bmm150_get_regs(BMM150_AXES_ENABLE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /* Set the axes to be enabled/disabled*/
- reg_data = BMM150_SET_BITS(reg_data, BMM150_CONTROL_MEASURE, dev->settings.xyz_axes_control);
- rslt = bmm150_set_regs(BMM150_AXES_ENABLE_ADDR, ®_data, 1, dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to identify the settings which the user
- * wants to modify in the sensor.
- */
- static uint8_t are_settings_changed(uint16_t sub_settings, uint16_t desired_settings)
- {
- uint8_t settings_changed = FALSE;
- if (sub_settings & desired_settings) {
- /* User wants to modify this particular settings */
- settings_changed = TRUE;
- } else {
- /* User don't want to modify this particular settings */
- settings_changed = FALSE;
- }
- return settings_changed;
- }
- /*!
- * @brief This API sets the ODR , measurement axes control ,
- * repetition values of xy,z.
- */
- static int8_t mode_settings(uint16_t desired_settings, const struct bmm150_dev *dev)
- {
- int8_t rslt = BMM150_E_INVALID_CONFIG;
- if (desired_settings & BMM150_DATA_RATE_SEL) {
- /* Sets the ODR */
- rslt = set_odr(dev);
- }
- if (desired_settings & BMM150_CONTROL_MEASURE_SEL) {
- /* Enables/Disables the control measurement axes */
- rslt = set_control_measurement_xyz(dev);
- }
- if (desired_settings & BMM150_XY_REP_SEL) {
- /* Sets the XY repetition */
- rslt = set_xy_rep(dev);
- }
- if (desired_settings & BMM150_Z_REP_SEL) {
- /* Sets the Z repetition */
- rslt = set_z_rep(dev);
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to parse and store the sensor
- * settings in the device structure
- */
- static void parse_setting(const uint8_t *reg_data, struct bmm150_dev *dev)
- {
- /* Parse all the w/r registers and update the
- current sensor settings in the dev structure*/
- dev->settings.z_rep = reg_data[7];
- dev->settings.xy_rep = reg_data[6];
- dev->settings.int_settings.high_threshold = reg_data[5];
- dev->settings.int_settings.low_threshold = reg_data[4];
- dev->settings.xyz_axes_control = BMM150_GET_BITS(reg_data[3], BMM150_CONTROL_MEASURE);
- dev->settings.int_settings.drdy_pin_en = BMM150_GET_BITS(reg_data[3], BMM150_DRDY_EN);
- dev->settings.int_settings.int_pin_en = BMM150_GET_BITS(reg_data[3], BMM150_INT_PIN_EN);
- dev->settings.int_settings.drdy_polarity = BMM150_GET_BITS(reg_data[3], BMM150_DRDY_POLARITY);
- dev->settings.int_settings.int_latch = BMM150_GET_BITS(reg_data[3], BMM150_INT_LATCH);
- dev->settings.int_settings.int_polarity = BMM150_GET_BITS_POS_0(reg_data[3], BMM150_INT_POLARITY);
- dev->settings.int_settings.data_overrun_en = BMM150_GET_BITS(reg_data[2], BMM150_DATA_OVERRUN_INT);
- dev->settings.int_settings.overflow_int_en = BMM150_GET_BITS(reg_data[2], BMM150_OVERFLOW_INT);
- dev->settings.int_settings.high_int_en = BMM150_GET_BITS(reg_data[2], BMM150_HIGH_THRESHOLD_INT);
- dev->settings.int_settings.low_int_en = BMM150_GET_BITS_POS_0(reg_data[2], BMM150_LOW_THRESHOLD_INT);
- dev->settings.data_rate = BMM150_GET_BITS(reg_data[1], BMM150_ODR);
- }
- /*!
- * @brief This API is used to enable the interrupts and map them to the
- * corresponding interrupt pins and specify the pin characteristics like the
- * polarity , latch settings for the interrupt pins.
- */
- static int8_t interrupt_pin_settings(uint16_t desired_settings, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- struct bmm150_int_ctrl_settings int_settings;
- rslt = bmm150_get_regs(BMM150_AXES_ENABLE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- int_settings = dev->settings.int_settings;
- if (desired_settings & BMM150_DRDY_PIN_EN_SEL) {
- /* Enables the Data ready interrupt and
- maps it to the DRDY pin of the sensor */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_DRDY_EN, int_settings.drdy_pin_en);
- }
- if (desired_settings & BMM150_INT_PIN_EN_SEL) {
- /* Sets interrupt pin enable */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_INT_PIN_EN, int_settings.int_pin_en);
- }
- if (desired_settings & BMM150_DRDY_POLARITY_SEL) {
- /* Sets Data ready pin's polarity */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_DRDY_POLARITY, int_settings.drdy_polarity);
- }
- if (desired_settings & BMM150_INT_LATCH_SEL) {
- /* Sets Interrupt in latched or non-latched mode */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_INT_LATCH, int_settings.int_latch);
- }
- if (desired_settings & BMM150_INT_POLARITY_SEL) {
- /* Sets Interrupt pin's polarity */
- reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_INT_POLARITY, int_settings.int_polarity);
- }
- /* Set the interrupt configurations in the 0x4E register */
- rslt = bmm150_set_regs(BMM150_AXES_ENABLE_ADDR, ®_data, 1, dev);
- }
- return rslt;
- }
- /*!
- * @brief This API is used to enable data overrun , overflow interrupts and
- * enable/disable high/low threshold interrupts for x,y,z axis based on the
- * threshold values set by the user in the High threshold (0x50) and
- * Low threshold (0x4F) registers.
- */
- static int8_t interrupt_config(uint16_t desired_settings, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- struct bmm150_int_ctrl_settings int_settings;
- rslt = bmm150_get_regs(BMM150_INT_CONFIG_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- int_settings = dev->settings.int_settings;
- if (desired_settings & BMM150_DATA_OVERRUN_INT_SEL) {
- /* Sets Data overrun interrupt */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_DATA_OVERRUN_INT, int_settings.data_overrun_en);
- }
- if (desired_settings & BMM150_OVERFLOW_INT_SEL) {
- /* Sets Data overflow interrupt */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_OVERFLOW_INT, int_settings.overflow_int_en);
- }
- if (desired_settings & BMM150_HIGH_THRESHOLD_INT_SEL) {
- /* Sets high threshold interrupt */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_HIGH_THRESHOLD_INT, int_settings.high_int_en);
- }
- if (desired_settings & BMM150_LOW_THRESHOLD_INT_SEL) {
- /* Sets low threshold interrupt */
- reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_LOW_THRESHOLD_INT, int_settings.low_int_en);
- }
- /* Set the interrupt configurations in the 0x4D register */
- rslt = bmm150_set_regs(BMM150_INT_CONFIG_ADDR, ®_data, 1, dev);
- }
- return rslt;
- }
- /*!
- * @brief This API is used to write the user specified High/Low threshold value
- * as a reference to generate the high/low threshold interrupt.
- */
- static int8_t interrupt_threshold_settings(uint16_t desired_settings, const struct bmm150_dev *dev)
- {
- int8_t rslt = BMM150_E_INVALID_CONFIG;
- uint8_t reg_data;
- if (desired_settings & BMM150_LOW_THRESHOLD_SETTING_SEL) {
- /* Sets the Low threshold value to trigger interrupt */
- reg_data = dev->settings.int_settings.low_threshold;
- rslt = bmm150_set_regs(BMM150_LOW_THRESHOLD_ADDR, ®_data, 1, dev);
- }
- if (desired_settings & BMM150_HIGH_THRESHOLD_SETTING_SEL) {
- /* Sets the High threshold value to trigger interrupt */
- reg_data = dev->settings.int_settings.high_threshold;
- rslt = bmm150_set_regs(BMM150_HIGH_THRESHOLD_ADDR, ®_data, 1, dev);
- }
- return rslt;
- }
- #ifdef BMM150_USE_FLOATING_POINT
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer x axis data(micro-tesla) in float.
- */
- static float compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- float retval = 0;
- float process_comp_x0;
- float process_comp_x1;
- float process_comp_x2;
- float process_comp_x3;
- float process_comp_x4;
- /* Overflow condition check */
- if ((mag_data_x != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) &&
- (data_rhall != 0) && (dev->trim_data.dig_xyz1 != 0)) {
- /*Processing compensation equations*/
- process_comp_x0 = (((float)dev->trim_data.dig_xyz1) * 16384.0f / data_rhall);
- retval = (process_comp_x0 - 16384.0f);
- process_comp_x1 = ((float)dev->trim_data.dig_xy2) * (retval * retval / 268435456.0f);
- process_comp_x2 = process_comp_x1 + retval * ((float)dev->trim_data.dig_xy1) / 16384.0f;
- process_comp_x3 = ((float)dev->trim_data.dig_x2) + 160.0f;
- process_comp_x4 = mag_data_x * ((process_comp_x2 + 256.0f) * process_comp_x3);
- retval = ((process_comp_x4 / 8192.0f) + (((float)dev->trim_data.dig_x1) * 8.0f)) / 16.0f;
- } else {
- /* overflow, set output to 0.0f */
- retval = BMM150_OVERFLOW_OUTPUT_FLOAT;
- }
- return retval;
- }
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer y axis data(micro-tesla) in float.
- */
- static float compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- float retval = 0;
- float process_comp_y0;
- float process_comp_y1;
- float process_comp_y2;
- float process_comp_y3;
- float process_comp_y4;
- /* Overflow condition check */
- if ((mag_data_y != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL)
- && (data_rhall != 0) && (dev->trim_data.dig_xyz1 != 0)) {
- /*Processing compensation equations*/
- process_comp_y0 = ((float)dev->trim_data.dig_xyz1) * 16384.0f / data_rhall;
- retval = process_comp_y0 - 16384.0f;
- process_comp_y1 = ((float)dev->trim_data.dig_xy2) * (retval * retval / 268435456.0f);
- process_comp_y2 = process_comp_y1 + retval * ((float)dev->trim_data.dig_xy1) / 16384.0f;
- process_comp_y3 = ((float)dev->trim_data.dig_y2) + 160.0f;
- process_comp_y4 = mag_data_y * (((process_comp_y2) + 256.0f) * process_comp_y3);
- retval = ((process_comp_y4 / 8192.0f) + (((float)dev->trim_data.dig_y1) * 8.0f)) / 16.0f;
- } else {
- /* overflow, set output to 0.0f */
- retval = BMM150_OVERFLOW_OUTPUT_FLOAT;
- }
- return retval;
- }
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer z axis data(micro-tesla) in float.
- */
- static float compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- float retval = 0;
- float process_comp_z0;
- float process_comp_z1;
- float process_comp_z2;
- float process_comp_z3;
- float process_comp_z4;
- float process_comp_z5;
- /* Overflow condition check */
- if ((mag_data_z != BMM150_ZAXIS_HALL_OVERFLOW_ADCVAL) &&
- (dev->trim_data.dig_z2 != 0) && (dev->trim_data.dig_z1 != 0)
- && (dev->trim_data.dig_xyz1 != 0) && (data_rhall != 0)) {
- /* Processing compensation equations */
- process_comp_z0 = ((float)mag_data_z) - ((float)dev->trim_data.dig_z4);
- process_comp_z1 = ((float)data_rhall) - ((float)dev->trim_data.dig_xyz1);
- process_comp_z2 = (((float)dev->trim_data.dig_z3) * process_comp_z1);
- process_comp_z3 = ((float)dev->trim_data.dig_z1) * ((float)data_rhall) / 32768.0f;
- process_comp_z4 = ((float)dev->trim_data.dig_z2) + process_comp_z3;
- process_comp_z5 = (process_comp_z0 * 131072.0f) - process_comp_z2;
- retval = (process_comp_z5 / ((process_comp_z4) * 4.0f)) / 16.0f;
- } else {
- /* overflow, set output to 0.0f */
- retval = BMM150_OVERFLOW_OUTPUT_FLOAT;
- }
- return retval;
- }
- #else
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer X axis data(micro-tesla) in int16_t.
- */
- static int16_t compensate_x(int16_t mag_data_x, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- int16_t retval;
- uint16_t process_comp_x0 = 0;
- int32_t process_comp_x1;
- uint16_t process_comp_x2;
- int32_t process_comp_x3;
- int32_t process_comp_x4;
- int32_t process_comp_x5;
- int32_t process_comp_x6;
- int32_t process_comp_x7;
- int32_t process_comp_x8;
- int32_t process_comp_x9;
- int32_t process_comp_x10;
- /* Overflow condition check */
- if (mag_data_x != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) {
- if (data_rhall != 0) {
- /* Availability of valid data*/
- process_comp_x0 = data_rhall;
- } else if (dev->trim_data.dig_xyz1 != 0) {
- process_comp_x0 = dev->trim_data.dig_xyz1;
- } else {
- process_comp_x0 = 0;
- }
- if (process_comp_x0 != 0) {
- /* Processing compensation equations*/
- process_comp_x1 = ((int32_t)dev->trim_data.dig_xyz1) * 16384;
- process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000);
- retval = ((int16_t)process_comp_x2);
- process_comp_x3 = (((int32_t)retval) * ((int32_t)retval));
- process_comp_x4 = (((int32_t)dev->trim_data.dig_xy2) * (process_comp_x3 / 128));
- process_comp_x5 = (int32_t)(((int16_t)dev->trim_data.dig_xy1) * 128);
- process_comp_x6 = ((int32_t)retval) * process_comp_x5;
- process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000));
- process_comp_x8 = ((int32_t)(((int16_t)dev->trim_data.dig_x2) + ((int16_t)0xA0)));
- process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096);
- process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9;
- retval = ((int16_t)(process_comp_x10 / 8192));
- retval = (retval + (((int16_t)dev->trim_data.dig_x1) * 8)) / 16;
- } else {
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- } else {
- /* Overflow condition */
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- return retval;
- }
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Y axis data(micro-tesla) in int16_t.
- */
- static int16_t compensate_y(int16_t mag_data_y, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- int16_t retval;
- uint16_t process_comp_y0 = 0;
- int32_t process_comp_y1;
- uint16_t process_comp_y2;
- int32_t process_comp_y3;
- int32_t process_comp_y4;
- int32_t process_comp_y5;
- int32_t process_comp_y6;
- int32_t process_comp_y7;
- int32_t process_comp_y8;
- int32_t process_comp_y9;
- /* Overflow condition check */
- if (mag_data_y != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) {
- if (data_rhall != 0) {
- /* Availability of valid data*/
- process_comp_y0 = data_rhall;
- } else if (dev->trim_data.dig_xyz1 != 0) {
- process_comp_y0 = dev->trim_data.dig_xyz1;
- } else {
- process_comp_y0 = 0;
- }
- if (process_comp_y0 != 0) {
- /*Processing compensation equations*/
- process_comp_y1 = (((int32_t)dev->trim_data.dig_xyz1) * 16384) / process_comp_y0;
- process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000);
- retval = ((int16_t)process_comp_y2);
- process_comp_y3 = ((int32_t) retval) * ((int32_t)retval);
- process_comp_y4 = ((int32_t)dev->trim_data.dig_xy2) * (process_comp_y3 / 128);
- process_comp_y5 = ((int32_t)(((int16_t)dev->trim_data.dig_xy1) * 128));
- process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512);
- process_comp_y7 = ((int32_t)(((int16_t)dev->trim_data.dig_y2) + ((int16_t)0xA0)));
- process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096);
- process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8);
- retval = (int16_t)(process_comp_y9 / 8192);
- retval = (retval + (((int16_t)dev->trim_data.dig_y1) * 8)) / 16;
- } else {
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- } else {
- /* Overflow condition*/
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- return retval;
- }
- /*!
- * @brief This internal API is used to obtain the compensated
- * magnetometer Z axis data(micro-tesla) in int16_t.
- */
- static int16_t compensate_z(int16_t mag_data_z, uint16_t data_rhall, const struct bmm150_dev *dev)
- {
- int32_t retval;
- int16_t process_comp_z0;
- int32_t process_comp_z1;
- int32_t process_comp_z2;
- int32_t process_comp_z3;
- int16_t process_comp_z4;
- if (mag_data_z != BMM150_ZAXIS_HALL_OVERFLOW_ADCVAL) {
- if ((dev->trim_data.dig_z2 != 0) && (dev->trim_data.dig_z1 != 0)
- && (data_rhall != 0) && (dev->trim_data.dig_xyz1 != 0)) {
- /*Processing compensation equations*/
- process_comp_z0 = ((int16_t)data_rhall) - ((int16_t) dev->trim_data.dig_xyz1);
- process_comp_z1 = (((int32_t)dev->trim_data.dig_z3) * ((int32_t)(process_comp_z0))) / 4;
- process_comp_z2 = (((int32_t)(mag_data_z - dev->trim_data.dig_z4)) * 32768);
- process_comp_z3 = ((int32_t)dev->trim_data.dig_z1) * (((int16_t)data_rhall) * 2);
- process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536);
- retval = ((process_comp_z2 - process_comp_z1) / (dev->trim_data.dig_z2 + process_comp_z4));
- /* saturate result to +/- 2 micro-tesla */
- if (retval > BMM150_POSITIVE_SATURATION_Z) {
- retval = BMM150_POSITIVE_SATURATION_Z;
- } else {
- if (retval < BMM150_NEGATIVE_SATURATION_Z)
- retval = BMM150_NEGATIVE_SATURATION_Z;
- }
- /* Conversion of LSB to micro-tesla*/
- retval = retval / 16;
- } else {
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- } else {
- /* Overflow condition*/
- retval = BMM150_OVERFLOW_OUTPUT;
- }
- return (int16_t)retval;
- }
- #endif
- /*!
- * @brief This internal API is used to perform the normal self test
- * of the sensor and return the self test result as return value
- */
- static int8_t perform_normal_self_test(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t self_test_bit;
- /* Triggers the start of normal self test */
- rslt = enable_normal_self_test(&self_test_bit, dev);
- /* Check for self test completion status */
- if ((rslt == BMM150_OK) && (self_test_bit == 0)) {
- /* Validates the self test results for all 3 axes */
- rslt = validate_normal_self_test(dev);
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to enable the normal self test by setting
- * the Self Test bit (bit0) of the 0x4C register,
- * which triggers the start of self test
- */
- static int8_t enable_normal_self_test(uint8_t *self_test_enable, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- uint8_t self_test_val;
- /* Read the data from register 0x4C */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /* Set the Self Test bit(bit0) of the 0x4C register */
- self_test_val = 1;
- reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_SELF_TEST, self_test_val);
- /* Write the data to 0x4C register to trigger self test */
- rslt = bmm150_set_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- dev->delay_ms(BMM150_NORMAL_SELF_TEST_DELAY);
- if (rslt == BMM150_OK) {
- /* Read the data from register 0x4C */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- /* Self Test bit(bit0) is stored in self_test_enable,
- It will be reset to zero after the self test is over */
- *self_test_enable = BMM150_GET_BITS_POS_0(reg_data, BMM150_SELF_TEST);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to validate the results of normal self test
- * by using the self test status available in the bit0 of registers 0x42,0x44
- * and 0x46.
- */
- static int8_t validate_normal_self_test(const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t status;
- uint8_t self_test_rslt[5];
- /* Read the data from register 0x42 to 0x46 */
- rslt = bmm150_get_regs(BMM150_DATA_X_LSB, self_test_rslt, BMM150_SELF_TEST_LEN, dev);
- if (rslt == BMM150_OK) {
- /* Parse and get the self test status bits */
- /* X-Self-Test (bit0) of 0x42 register is stored*/
- self_test_rslt[0] = BMM150_GET_BITS_POS_0(self_test_rslt[0], BMM150_SELF_TEST);
- /* Y-Self-Test (bit0) of 0x44 register is stored */
- self_test_rslt[2] = BMM150_GET_BITS_POS_0(self_test_rslt[2], BMM150_SELF_TEST);
- /* Z-Self-Test (bit0) of 0x46 register is stored */
- self_test_rslt[4] = BMM150_GET_BITS_POS_0(self_test_rslt[4], BMM150_SELF_TEST);
- /* Combine the self test status and store it in the first
- 3 bits of the status variable for processing*/
- status = (uint8_t)((self_test_rslt[4] << 2) | (self_test_rslt[2] << 1) | self_test_rslt[0]);
- /* Validate status and store Self test result in "rslt" */
- if (status == BMM150_SELF_TEST_STATUS_SUCCESS) {
- /* Self test is success when all status bits are set */
- rslt = BMM150_OK;
- } else {
- if (status == BMM150_SELF_TEST_STATUS_XYZ_FAIL) {
- /* Self test - all axis fail condition */
- rslt = BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL;
- } else {
- /* Self test - some axis fail condition */
- rslt = (int8_t)status;
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to perform advanced self test for Z axis
- */
- static int8_t perform_adv_self_test(struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t self_test_current;
- int16_t positive_data_z;
- int16_t negative_data_z;
- /* Set the desired power mode ,axes control and repetition settings */
- rslt = adv_self_test_settings(dev);
- if (rslt == BMM150_OK) {
- /* Measure the Z axes data with positive self-test current */
- self_test_current = BMM150_ENABLE_POSITIVE_CURRENT;
- rslt = adv_self_test_measurement(self_test_current, &positive_data_z, dev);
- if (rslt == BMM150_OK) {
- /* Measure the Z axes data with
- negative self-test current */
- self_test_current = BMM150_ENABLE_NEGATIVE_CURRENT;
- rslt = adv_self_test_measurement(self_test_current, &negative_data_z, dev);
- if (rslt == BMM150_OK) {
- /* Disable self-test current */
- self_test_current = BMM150_DISABLE_SELF_TEST_CURRENT;
- rslt = set_adv_self_test_current(self_test_current, dev);
- if (rslt == BMM150_OK) {
- /* Validate the advanced self test */
- rslt = validate_adv_self_test(positive_data_z, negative_data_z);
- }
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to set the desired power mode ,
- * axes control and repetition settings for advanced self test
- */
- static int8_t adv_self_test_settings(struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Set the power mode as sleep mode */
- dev->settings.pwr_mode = BMM150_SLEEP_MODE;
- rslt = bmm150_set_op_mode(dev);
- if (rslt == BMM150_OK) {
- /* Disable XY-axis measurement */
- dev->settings.xyz_axes_control = BMM150_DISABLE_XY_AXIS;
- rslt = set_control_measurement_xyz(dev);
- if (rslt == BMM150_OK) {
- /* Repetition value is set as 0x04 */
- dev->settings.z_rep = BMM150_SELF_TEST_REP_Z;
- rslt = set_z_rep(dev);
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to set the positive or negative value of
- * self-test current and obtain the corresponding magnetometer z axis data
- */
- static int8_t adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z, struct bmm150_dev *dev)
- {
- int8_t rslt;
- /* Set the advanced self test current as positive or
- negative based on the value of parameter "self_test_current" */
- rslt = set_adv_self_test_current(self_test_current, dev);
- if (rslt == BMM150_OK) {
- /* Set the device in forced mode*/
- dev->settings.pwr_mode = BMM150_FORCED_MODE;
- rslt = bmm150_set_op_mode(dev);
- /* Delay to ensure measurement is complete */
- dev->delay_ms(BMM150_ADV_SELF_TEST_DELAY);
- if (rslt == BMM150_OK) {
- /* Read Mag data and store the value of Z axis data */
- rslt = bmm150_read_mag_data(dev);
- if (rslt == BMM150_OK) {
- /* Mag Z axis data is stored */
- *data_z = dev->data.z;
- }
- }
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to get the difference between the
- * Z axis mag data obtained by positive and negative self-test current
- * and validate whether the advanced self test is done successfully or not.
- */
- static int8_t validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z)
- {
- int32_t adv_self_test_rslt;
- int8_t rslt;
- /* Advanced self test difference between the Z axis mag data
- obtained by the positive and negative self-test current */
- adv_self_test_rslt = positive_data_z - negative_data_z;
- /* Advanced self test validation */
- /*Value of adv_self_test_rslt should be in between 180-240 micro-tesla*/
- if ((adv_self_test_rslt > 180) && (adv_self_test_rslt < 240)) {
- /* Advanced self test success */
- rslt = BMM150_OK;
- } else {
- /* Advanced self test fail */
- rslt = BMM150_W_ADV_SELF_TEST_FAIL;
- }
- return rslt;
- }
- /*!
- * @brief This internal API is used to set the self test current value in
- * the Adv. ST bits (bit6 and bit7) of 0x4C register
- */
- static int8_t set_adv_self_test_current(uint8_t self_test_current, const struct bmm150_dev *dev)
- {
- int8_t rslt;
- uint8_t reg_data;
- /* Read the 0x4C register */
- rslt = bmm150_get_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- if (rslt == BMM150_OK) {
- /* Set the self test current value in the Adv. ST bits
- (bit6 and bit7) of 0x4c register */
- reg_data = BMM150_SET_BITS(reg_data, BMM150_ADV_SELF_TEST, self_test_current);
- rslt = bmm150_set_regs(BMM150_OP_MODE_ADDR, ®_data, 1, dev);
- }
- return rslt;
- }
|