├── examples ├── bmm350_interrupt │ ├── Makefile │ └── bmm350_interrupt.c ├── bmm350_polling │ ├── Makefile │ └── bmm350_polling.c ├── bmm350_forced_mode │ ├── Makefile │ └── bmm350_forced_mode.c ├── bmm350_normal_mode │ ├── Makefile │ └── bmm350_normal_mode.c ├── bmm350_self_test │ ├── Makefile │ └── bmm350_self_test.c ├── bmm350_sensor_time │ ├── Makefile │ └── bmm350_sensor_time.c ├── bmm350_config_changes │ ├── Makefile │ └── bmm350_config_changes.c ├── bmm350_illegal_command │ ├── Makefile │ └── bmm350_illegal_command.c ├── bmm350_magnetic_reset │ ├── Makefile │ └── bmm350_magnetic_reset.c ├── bmm350_out_of_range_detect │ ├── Makefile │ └── bmm350_out_of_range_detect.c ├── common │ ├── common.h │ └── common.c └── README.md ├── README.md ├── LICENSE ├── bmm350_oor.h ├── bmm350_oor.c └── bmm350.h /examples/bmm350_interrupt/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_interrupt.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | TARGET = MCU_APP30 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_polling/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_polling.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_forced_mode/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_forced_mode.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_normal_mode/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_normal_mode.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_self_test/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_self_test.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_sensor_time/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_sensor_time.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_config_changes/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_config_changes.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_illegal_command/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_illegal_command.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_magnetic_reset/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_magnetic_reset.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | ../common/common.c 10 | 11 | INCLUDEPATHS += \ 12 | $(API_LOCATION) \ 13 | ../common 14 | 15 | COINES_BACKEND=COINES_BRIDGE 16 | 17 | include $(COINES_INSTALL_PATH)/coines.mk 18 | -------------------------------------------------------------------------------- /examples/bmm350_out_of_range_detect/Makefile: -------------------------------------------------------------------------------- 1 | COINES_INSTALL_PATH ?= ../../../.. 2 | 3 | EXAMPLE_FILE ?= bmm350_out_of_range_detect.c 4 | 5 | API_LOCATION ?= ../.. 6 | 7 | C_SRCS += \ 8 | $(API_LOCATION)/bmm350.c \ 9 | $(API_LOCATION)/bmm350_oor.c \ 10 | ../common/common.c 11 | 12 | INCLUDEPATHS += \ 13 | $(API_LOCATION) \ 14 | ../common 15 | 16 | TARGET = MCU_APP30 17 | 18 | include $(COINES_INSTALL_PATH)/coines.mk -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BMM350 SensorAPI - Bosch Sensortec 2 | 3 | > This package contains Bosch Sensortec's BMM350 magnetometer SensorAPI 4 | 5 | ## Sensor Overview 6 | The BMM350 is a 3-axis magnetic sensor which operates in automatic mode or triggered mode. 7 | The magnetic-to-digital conversion technology is based on TMR (tunnel magneto resistance) 8 | The BMM350 has an excellent temperature behaviour with an outstanding low temperature coefficient of the offset (TCO) and temperature coefficient of the sensitivity (TCS). 9 | 10 | ### Applications 11 | 1. Virtual, augmented and mixed reality applications 12 | 2. High-end gaming applications 13 | 3. Platform stabilization applications such as image stabilization, or indoor navigation and dead-reckoning, for example in robotics applications. 14 | 4. Magnetic heading information 15 | 5. Tilt-compensated electronic compass for map rotation, navigation and augmented reality 16 | 6. Gyroscope calibration in 9-DoF applications for mobile devices 17 | 7. In-door navigation, e.g. step counting in combination with accelerometer 18 | 8. Gaming (AR/VR) 19 | 20 | 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 2 | 3 | BSD-3-Clause 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in the 13 | documentation and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /examples/bmm350_illegal_command/bmm350_illegal_command.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_illegal_command.c 34 | * 35 | * @brief This file contains set get operations of illegal commands. 36 | * 37 | */ 38 | 39 | #include 40 | #include "bmm350.h" 41 | #include "common.h" 42 | #include "coines.h" 43 | 44 | /******************************************************************************/ 45 | /*! Functions */ 46 | 47 | /* This function starts the execution of program */ 48 | int main(void) 49 | { 50 | /* Status of api are returned to this variable */ 51 | int8_t rslt; 52 | 53 | /* Sensor initialization configuration */ 54 | struct bmm350_dev dev = { 0 }; 55 | 56 | uint8_t pmu_cmd; 57 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 58 | 59 | /* Update device structure */ 60 | rslt = bmm350_interface_init(&dev); 61 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 62 | 63 | /* Initialize BMM350 */ 64 | rslt = bmm350_init(&dev); 65 | bmm350_error_codes_print_result("bmm350_init", rslt); 66 | 67 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 68 | 69 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 70 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 71 | 72 | printf("Set legal PMU command to the register \n"); 73 | 74 | pmu_cmd = 2; 75 | 76 | rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, &dev); 77 | bmm350_error_codes_print_result("bmm350_set_regs", rslt); 78 | 79 | printf("Write : 0x06 : PMU CMD : 0x%X\n", pmu_cmd); 80 | 81 | /* Check PMU cmd illegal */ 82 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 83 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 84 | 85 | printf("Read : 0x00 : PMU command illegal status : 0x%X\n", pmu_cmd_stat_0.cmd_is_illegal); 86 | 87 | rslt = bmm350_delay_us(40000, &dev); 88 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 89 | 90 | printf("Set illegal PMU command to the register \n"); 91 | 92 | pmu_cmd = 12; 93 | 94 | rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, &dev); 95 | bmm350_error_codes_print_result("bmm350_set_regs", rslt); 96 | 97 | printf("Write : 0x06 : PMU CMD : 0x%X\n", pmu_cmd); 98 | 99 | /* Check PMU cmd illegal */ 100 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 101 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 102 | 103 | printf("Read : 0x00 : PMU command illegal status : 0x%X\n", pmu_cmd_stat_0.cmd_is_illegal); 104 | 105 | bmm350_coines_deinit(); 106 | 107 | return rslt; 108 | } 109 | -------------------------------------------------------------------------------- /bmm350_oor.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_oor.h 34 | * @date 2023-05-26 35 | * @version v1.4.0 36 | * 37 | */ 38 | 39 | #ifndef _BMM350_OOR_H 40 | #define _BMM350_OOR_H 41 | 42 | #include 43 | #include 44 | 45 | #include "bmm350.h" 46 | 47 | /*! CPP guard */ 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | /******************************************************************************/ 53 | /*! @name General Macro Definitions */ 54 | /******************************************************************************/ 55 | 56 | /*! Macro to define half self-test for out of range 57 | * NOTE: Comment this to use both positive and negative self tests */ 58 | #define BMM350_OOR_HALF_SELF_TEST 59 | 60 | /*! Macro to define mag data minimum and maximum range in uT */ 61 | #define BMM350_HALF_ST_THRESHOLD (130.0f) 62 | #define BMM350_FULL_ST_THRESHOLD (300.0f) 63 | 64 | /*! Macro to define threshold values of in range, out of range and self-test */ 65 | #define BMM350_IN_RANGE_THRESHOLD (2000.0f) 66 | #define BMM350_OUT_OF_RANGE_THRESHOLD (2400.0f) 67 | #define BMM350_SELF_TEST_THRESHOLD (2600.0f) 68 | 69 | /************************* Structure definitions *************************/ 70 | 71 | /*! 72 | * @brief Structure to define bmm350 out of range parameters 73 | */ 74 | struct bmm350_oor_params 75 | { 76 | /*! Counter to track what self test to trigger */ 77 | uint8_t st_counter; 78 | 79 | /*! Current self-test command */ 80 | uint8_t st_cmd; 81 | 82 | /*! Stores the last applied self test configuration */ 83 | uint8_t last_st_cmd; 84 | 85 | /*! Store the last measurements for comparing against the self-test */ 86 | float mag_xp, mag_xn, mag_yp, mag_yn; 87 | 88 | /*! Flags to track if the test failed to redo it */ 89 | bool x_failed, y_failed; 90 | 91 | /*! Flags to enable self-test */ 92 | bool enable_selftest; 93 | 94 | /*! Flags to trigger reset */ 95 | bool trigger_reset; 96 | 97 | /*! Variable to store reset counter value */ 98 | uint8_t reset_counter; 99 | }; 100 | 101 | /******************* Function prototype declarations ********************/ 102 | 103 | /*! 104 | * @brief Function to read data and validate if the sensor is out of range 105 | * 106 | * @param[in,out] out_of_range : Flag that indicates that the sensor is out of range 107 | * @param[out] data : Sensor data 108 | * @param[out] oor : Structure that stores the state of the out of range detector 109 | * @param[in,out] dev : Device structure of the BMM350 110 | * 111 | * @return Result of API execution status 112 | * @retval = 0 -> Success 113 | * @retval < 0 -> Error 114 | */ 115 | int8_t bmm350_oor_read(bool *out_of_range, 116 | struct bmm350_mag_temp_data *data, 117 | struct bmm350_oor_params *oor, 118 | struct bmm350_dev *dev); 119 | 120 | /*! 121 | * @brief Function to perform reset sequence in forced mode. 122 | * 123 | * @param[in,out] oor : Structure that stores the state of the out of range detector 124 | * @param[in,out] dev : Structure instance of bmm350_dev. 125 | * 126 | * @return Result of API execution status 127 | * @retval = 0 -> Success 128 | * @retval < 0 -> Error 129 | */ 130 | int8_t bmm350_oor_perform_reset_sequence_forced(struct bmm350_oor_params *oor, struct bmm350_dev *dev); 131 | 132 | #ifdef __cplusplus 133 | } 134 | #endif /* End of CPP guard */ 135 | 136 | #endif /* _BMM350_OOR_H */ 137 | -------------------------------------------------------------------------------- /examples/common/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file common.h 34 | * 35 | */ 36 | 37 | #ifndef _COMMON_H 38 | #define _COMMON_H 39 | 40 | /*! CPP guard */ 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #include 46 | #include "bmm350.h" 47 | #include "coines.h" 48 | 49 | #ifdef MCU_APP30 50 | #define BUTTON_1 COINES_APP30_BUTTON_1 51 | #define BUTTON_2 COINES_APP30_BUTTON_2 52 | #endif 53 | 54 | #ifdef MCU_APP31 55 | #define BUTTON_1 COINES_APP31_BUTTON_2 56 | #define BUTTON_2 COINES_APP31_BUTTON_3 57 | #endif 58 | 59 | /***************************************************************************/ 60 | 61 | /*! User function prototypes 62 | ****************************************************************************/ 63 | 64 | /*! 65 | * @brief Function for reading the sensor's registers through I2C bus. 66 | * 67 | * @param[in] reg_addr : Register address from which data is read. 68 | * @param[out] reg_data : Pointer to data buffer where read data is stored. 69 | * @param[in] length : Number of bytes of data to be read. 70 | * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors 71 | * for interface related call backs. 72 | * 73 | * @return Status of execution 74 | * 75 | * @retval BMM350_INTF_RET_SUCCESS -> Success. 76 | * @retval != BMM350_INTF_RET_SUCCESS -> Fail. 77 | * 78 | */ 79 | BMM350_INTF_RET_TYPE bmm350_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr); 80 | 81 | /*! 82 | * @brief Function for writing the sensor's registers through I2C bus. 83 | * 84 | * @param[in] reg_addr : Register address to which the data is written. 85 | * @param[in] reg_data : Pointer to data buffer in which data to be written 86 | * is stored. 87 | * @param[in] length : Number of bytes of data to be written. 88 | * @param[in, out] intf_ptr : Void pointer that can enable the linking of descriptors 89 | * for interface related call backs 90 | * 91 | * @return Status of execution 92 | * 93 | * @retval BMM350_INTF_RET_SUCCESS -> Success. 94 | * @retval != BMM350_INTF_RET_SUCCESS -> Failure. 95 | * 96 | */ 97 | BMM350_INTF_RET_TYPE bmm350_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr); 98 | 99 | /*! 100 | * @brief This function provides the delay for required time (Microsecond) as per the input provided in some of the 101 | * APIs. 102 | * 103 | * @param[in] period_us : The required wait time in microsecond. 104 | * @return void. 105 | * 106 | */ 107 | void bmm350_delay(uint32_t period_us, void *intf_ptr); 108 | 109 | /*! 110 | * @brief Function to select the interface. 111 | * Also to initialize coines platform. 112 | * 113 | * @param[in] dev : Structure instance of bmm350_dev 114 | * 115 | * @return Status of execution 116 | * @retval 0 -> Success 117 | * @retval < 0 -> Failure Info 118 | */ 119 | int8_t bmm350_interface_init(struct bmm350_dev *dev); 120 | 121 | /*! 122 | * @brief Prints the execution status of the APIs. 123 | * 124 | * @param[in] api_name : Name of the API whose execution status has to be printed. 125 | * @param[in] rslt : Error code returned by the API whose execution status has to be printed. 126 | * 127 | * @return void. 128 | */ 129 | void bmm350_error_codes_print_result(const char api_name[], int8_t rslt); 130 | 131 | /*! 132 | * @brief This function deinitializes coines platform 133 | * 134 | * @return void. 135 | * 136 | */ 137 | void bmm350_coines_deinit(void); 138 | 139 | /** 140 | * @brief Retrieves the state of a button. 141 | * 142 | * This function is used to get the state of a button specified by `button_id`. 143 | * 144 | * @param[in] button_id The ID of the button to retrieve the state from. 145 | * @param[in] btn_dir Pointer to a variable where the button direction will be stored. 146 | * @param[out] btn_value Pointer to a variable where the button state will be stored. 147 | */ 148 | void bmm350_coines_get_button_state(enum coines_multi_io_pin button_id, 149 | enum coines_pin_direction *btn_dir, 150 | enum coines_pin_value *btn_value); 151 | 152 | #ifdef __cplusplus 153 | } 154 | #endif /* End of CPP guard */ 155 | 156 | #endif /* _COMMON_H */ 157 | -------------------------------------------------------------------------------- /examples/bmm350_sensor_time/bmm350_sensor_time.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_sensor_time.c 34 | * 35 | * @brief This file contains reading of sensortime data with respect to power modes, ODR and average. 36 | * 37 | */ 38 | 39 | #include 40 | #include "bmm350.h" 41 | #include "common.h" 42 | #include "coines.h" 43 | 44 | /******************************************************************************/ 45 | /*! Functions */ 46 | 47 | /* This function starts the execution of program */ 48 | int main(void) 49 | { 50 | /* Status of api are returned to this variable */ 51 | int8_t rslt; 52 | 53 | /* Sensor initialization configuration */ 54 | struct bmm350_dev dev = { 0 }; 55 | 56 | uint8_t loop = 20; 57 | uint32_t secs, nano_secs = 0; 58 | 59 | /* Update device structure */ 60 | rslt = bmm350_interface_init(&dev); 61 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 62 | 63 | /* Initialize BMM350 */ 64 | rslt = bmm350_init(&dev); 65 | bmm350_error_codes_print_result("bmm350_init", rslt); 66 | 67 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 68 | 69 | /* Set ODR and performance */ 70 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 71 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 72 | 73 | /* Enable all axis */ 74 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 75 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 76 | 77 | if (rslt == BMM350_OK) 78 | { 79 | rslt = bmm350_set_powermode(BMM350_SUSPEND_MODE, &dev); 80 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 81 | 82 | printf("\nSensortime in suspend mode\n"); 83 | printf("Time(secs)\n"); 84 | 85 | while (loop > 0) 86 | { 87 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 88 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 89 | 90 | printf("%lu.%09lu\n", (long unsigned int)secs, (long unsigned int)nano_secs); 91 | 92 | loop--; 93 | } 94 | 95 | rslt = bmm350_set_ctrl_user(BMM350_CFG_SENS_TIM_AON_EN, &dev); 96 | bmm350_error_codes_print_result("bmm350_set_ctrl_user", rslt); 97 | 98 | loop = 20; 99 | 100 | printf("\nSensortime in forced mode\n"); 101 | 102 | printf("Time(secs)\n"); 103 | 104 | while (loop > 0) 105 | { 106 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE, &dev); 107 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 108 | 109 | rslt = bmm350_delay_us(40000, &dev); 110 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 111 | 112 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 113 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 114 | 115 | printf("\n%lu.%09lu\n", (long unsigned int)secs, (long unsigned int)nano_secs); 116 | 117 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 118 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 119 | 120 | printf("%lu.%09lu\n", (long unsigned int)secs, (long unsigned int)nano_secs); 121 | 122 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 123 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 124 | 125 | printf("%lu.%09lu\n", (long unsigned int)secs, (long unsigned int)nano_secs); 126 | 127 | loop--; 128 | } 129 | 130 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 131 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 132 | 133 | /* Set ODR and performance */ 134 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_2, &dev); 135 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 136 | 137 | loop = 20; 138 | 139 | printf("\nChange in ODR\n"); 140 | 141 | printf("Time(secs)\n"); 142 | 143 | while (loop > 0) 144 | { 145 | rslt = bmm350_delay_us(11000, &dev); 146 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 147 | 148 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 149 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 150 | 151 | printf("%lu.%09lu\n", (long unsigned int)secs, (long unsigned int)nano_secs); 152 | 153 | loop--; 154 | } 155 | } 156 | 157 | bmm350_coines_deinit(); 158 | 159 | return rslt; 160 | } 161 | -------------------------------------------------------------------------------- /examples/bmm350_polling/bmm350_polling.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_polling.c 34 | * 35 | * @brief This file contains reading of magnetometer data in normal mode by polling method. 36 | * 37 | */ 38 | 39 | #include 40 | #include "bmm350.h" 41 | #include "common.h" 42 | #include "coines.h" 43 | 44 | /******************************************************************************/ 45 | /*! Functions */ 46 | 47 | /* This function starts the execution of program */ 48 | int main(void) 49 | { 50 | /* Status of api are returned to this variable */ 51 | int8_t rslt; 52 | 53 | /* Sensor initialization configuration */ 54 | struct bmm350_dev dev = { 0 }; 55 | 56 | uint8_t int_status, int_ctrl, err_reg_data = 0; 57 | uint8_t loop, set_int_ctrl; 58 | uint32_t time_ms = 0; 59 | 60 | struct bmm350_mag_temp_data mag_temp_data; 61 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 62 | 63 | /* Update device structure */ 64 | rslt = bmm350_interface_init(&dev); 65 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 66 | 67 | /* Initialize BMM350 */ 68 | rslt = bmm350_init(&dev); 69 | bmm350_error_codes_print_result("bmm350_init", rslt); 70 | 71 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 72 | 73 | /* Check PMU busy */ 74 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 75 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 76 | 77 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 78 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 79 | 80 | /* Get error data */ 81 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 82 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 83 | 84 | printf("Expected : 0x02 : Error Register : 0x0\n"); 85 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 86 | 87 | /* Configure interrupt settings */ 88 | rslt = bmm350_configure_interrupt(BMM350_PULSED, 89 | BMM350_ACTIVE_HIGH, 90 | BMM350_INTR_PUSH_PULL, 91 | BMM350_UNMAP_FROM_PIN, 92 | &dev); 93 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 94 | 95 | /* Enable data ready interrupt */ 96 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 97 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 98 | 99 | /* Get interrupt settings */ 100 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 101 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 102 | 103 | set_int_ctrl = (BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | (BMM350_ENABLE << 7); 104 | 105 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 106 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 107 | 108 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 109 | { 110 | printf("Data ready enabled\r\n"); 111 | } 112 | 113 | /* Set ODR and performance */ 114 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_25HZ, BMM350_AVERAGING_8, &dev); 115 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 116 | 117 | /* Enable all axis */ 118 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 119 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 120 | 121 | if (rslt == BMM350_OK) 122 | { 123 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 124 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 125 | 126 | loop = 20; 127 | 128 | printf("\nCompensated Magnetometer and temperature data read with delay\n"); 129 | 130 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 131 | 132 | /* Time in milliseconds */ 133 | time_ms = coines_get_millis(); 134 | 135 | while (loop) 136 | { 137 | rslt = bmm350_delay_us(36000, &dev); 138 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 139 | 140 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 141 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 142 | 143 | printf("%lu, %f, %f, %f, %f\n", 144 | (long unsigned int)(coines_get_millis() - time_ms), 145 | mag_temp_data.x, 146 | mag_temp_data.y, 147 | mag_temp_data.z, 148 | mag_temp_data.temperature); 149 | 150 | loop--; 151 | } 152 | 153 | loop = 22; 154 | 155 | printf("\nCompensated Magnetometer and temperature data read with INT\n"); 156 | 157 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 158 | 159 | /* Time in milliseconds */ 160 | time_ms = coines_get_millis(); 161 | 162 | while (loop) 163 | { 164 | int_status = 0; 165 | 166 | /* Get data ready interrupt status */ 167 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 168 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 169 | 170 | /* Check if data ready interrupt occurred */ 171 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 172 | { 173 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 174 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 175 | 176 | printf("%lu, %f, %f, %f, %f\n", 177 | (long unsigned int)(coines_get_millis() - time_ms), 178 | mag_temp_data.x, 179 | mag_temp_data.y, 180 | mag_temp_data.z, 181 | mag_temp_data.temperature); 182 | 183 | loop--; 184 | } 185 | } 186 | } 187 | 188 | bmm350_coines_deinit(); 189 | 190 | return rslt; 191 | } 192 | -------------------------------------------------------------------------------- /examples/bmm350_out_of_range_detect/bmm350_out_of_range_detect.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_out_of_range_detect.c 34 | * 35 | * @brief This file contains an example to robustly detect if the sensor is out of range, even in presence 36 | * of high-magnetic disturbances 37 | * 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "bmm350.h" 47 | #include "bmm350_oor.h" 48 | #include "common.h" 49 | #include "coines.h" 50 | 51 | /******************************************************************************/ 52 | /*! Static Variable Declaration */ 53 | 54 | /* Flag to track when to trigger the magnetic reset */ 55 | static bool trigger_magnetic_reset = false; 56 | 57 | /******************************************************************************/ 58 | /*! Functions */ 59 | 60 | /* This function starts the execution of program */ 61 | int main(void) 62 | { 63 | /* Status of api are returned to this variable */ 64 | int8_t rslt; 65 | 66 | /* Sensor initialization configuration */ 67 | struct bmm350_dev dev = { 0 }; 68 | 69 | /* Structure instance of magnetometer and temperature data */ 70 | struct bmm350_mag_temp_data mag_temp_data = { 0 }; 71 | 72 | /* Structure instance of self-test data */ 73 | struct bmm350_self_test st_data = { 0 }; 74 | 75 | /* Structure instance of out of range detect */ 76 | struct bmm350_oor_params oor = { 0 }; 77 | 78 | enum coines_pin_direction btn_dir = COINES_PIN_DIRECTION_IN; 79 | enum coines_pin_value btn_value = COINES_PIN_VALUE_HIGH; 80 | 81 | bool out_of_range = false; 82 | float field_str = 0.0f; 83 | uint16_t delay_in_us; 84 | 85 | /* Variable to store last measurement time */ 86 | uint32_t last_meas_time = 0; 87 | 88 | /* Update device structure */ 89 | rslt = bmm350_interface_init(&dev); 90 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 91 | 92 | (void)coines_set_led(COINES_LED_RED, COINES_LED_STATE_OFF); 93 | 94 | /* Initialize BMM350 */ 95 | rslt = bmm350_init(&dev); 96 | bmm350_error_codes_print_result("bmm350_init", rslt); 97 | 98 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 99 | 100 | /* Enable all axis */ 101 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 102 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 103 | 104 | rslt = bmm350_perform_self_test(&st_data, &dev); 105 | bmm350_error_codes_print_result("bmm350_perform_self_test", rslt); 106 | if ((st_data.out_ust_x < BMM350_FULL_ST_THRESHOLD) || (st_data.out_ust_y < BMM350_FULL_ST_THRESHOLD)) 107 | { 108 | out_of_range = true; 109 | } 110 | 111 | /* Set ODR to 200hz for best performance */ 112 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_200HZ, BMM350_AVERAGING_2, &dev); 113 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 114 | 115 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE_FAST, &dev); 116 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 117 | 118 | last_meas_time = coines_get_realtime_usec(); 119 | 120 | /* For 200Hz ODR, poll at 5ms */ 121 | delay_in_us = 5000; 122 | 123 | printf("Measuring data from the sensor\n"); 124 | printf( 125 | "\nMx, My, Mz, field_str, OutOfRange, Xfailed, Yfailed, ST DX, ST DY, Reset, Reset counter, ST active, ST counter\n"); 126 | 127 | /* Read data indefinitely */ 128 | while (rslt == BMM350_OK) 129 | { 130 | /* Read data when ready */ 131 | if ((coines_get_realtime_usec() - last_meas_time) >= delay_in_us) 132 | { 133 | last_meas_time = coines_get_realtime_usec(); 134 | 135 | if (oor.trigger_reset) 136 | { 137 | rslt = bmm350_oor_perform_reset_sequence_forced(&oor, &dev); 138 | } 139 | else 140 | { 141 | rslt = bmm350_oor_read(&out_of_range, &mag_temp_data, &oor, &dev); 142 | } 143 | 144 | /* Light up the LED Green or Red to indicate out of range */ 145 | if (out_of_range) 146 | { 147 | (void)coines_set_led(COINES_LED_RED, COINES_LED_STATE_ON); 148 | (void)coines_set_led(COINES_LED_GREEN, COINES_LED_STATE_OFF); 149 | (void)coines_set_pin_config(COINES_MINI_SHUTTLE_PIN_1_4, COINES_PIN_DIRECTION_OUT, 150 | COINES_PIN_VALUE_HIGH); 151 | } 152 | else 153 | { 154 | (void)coines_set_led(COINES_LED_RED, COINES_LED_STATE_OFF); 155 | (void)coines_set_led(COINES_LED_GREEN, COINES_LED_STATE_ON); 156 | (void)coines_set_pin_config(COINES_MINI_SHUTTLE_PIN_1_4, COINES_PIN_DIRECTION_OUT, 157 | COINES_PIN_VALUE_LOW); 158 | } 159 | 160 | field_str = 161 | sqrtf((mag_temp_data.x * mag_temp_data.x) + (mag_temp_data.y * mag_temp_data.y) + 162 | (mag_temp_data.z * mag_temp_data.z)); 163 | 164 | printf("%.2f\t%.2f\t%.2f\t%.2f\t%d\t%u\t%u\t%.2f\t%.2f\t%u\t%u\t%u\t%u\n", 165 | mag_temp_data.x, 166 | mag_temp_data.y, 167 | mag_temp_data.z, 168 | field_str, 169 | (uint8_t)out_of_range, 170 | oor.x_failed, 171 | oor.y_failed, 172 | oor.mag_xp - oor.mag_xn, 173 | oor.mag_yp - oor.mag_yn, 174 | oor.trigger_reset, 175 | oor.reset_counter, 176 | oor.enable_selftest, 177 | oor.st_counter); 178 | } 179 | 180 | /* Press the Button 1 to manually trigger a magnetic reset */ 181 | btn_dir = COINES_PIN_DIRECTION_IN; /* Input */ 182 | btn_value = COINES_PIN_VALUE_HIGH; /* Pull-up */ 183 | bmm350_coines_get_button_state(BUTTON_1, &btn_dir, &btn_value); 184 | 185 | if ((btn_value == COINES_PIN_VALUE_LOW) || (out_of_range)) 186 | { 187 | trigger_magnetic_reset = true; 188 | } 189 | 190 | /* Trigger the magnetic reset once the self tests have passed and the button is not pressed (active-low) */ 191 | if (trigger_magnetic_reset && !out_of_range && (btn_value == COINES_PIN_VALUE_HIGH)) 192 | { 193 | oor.trigger_reset = true; 194 | trigger_magnetic_reset = false; 195 | } 196 | } 197 | 198 | bmm350_coines_deinit(); 199 | 200 | return rslt; 201 | } 202 | -------------------------------------------------------------------------------- /examples/bmm350_self_test/bmm350_self_test.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_self_test.c 34 | * 35 | * @brief This file contains reading of magnetometer data in normal mode by performing before and after self-test. 36 | */ 37 | 38 | #include 39 | #include "coines.h" 40 | #include "common.h" 41 | #include "bmm350.h" 42 | 43 | /******************************************************************************/ 44 | /*! Functions */ 45 | 46 | /* This function starts the execution of program */ 47 | int main(void) 48 | { 49 | /* Status of api are returned to this variable */ 50 | int8_t rslt; 51 | 52 | /* Sensor initialization configuration */ 53 | struct bmm350_dev dev = { 0 }; 54 | 55 | struct bmm350_self_test out_data; 56 | 57 | uint8_t err_reg_data = 0; 58 | uint8_t loop = 10; 59 | uint32_t time_ms = 0; 60 | 61 | struct bmm350_mag_temp_data mag_temp_data; 62 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 63 | 64 | /* Update device structure */ 65 | rslt = bmm350_interface_init(&dev); 66 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 67 | 68 | /* Initialize BMM350 */ 69 | rslt = bmm350_init(&dev); 70 | bmm350_error_codes_print_result("bmm350_init", rslt); 71 | 72 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 73 | 74 | /* Check PMU busy */ 75 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 76 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 77 | 78 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 79 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 80 | 81 | /* Get error data */ 82 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 83 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 84 | 85 | printf("Expected : 0x02 : Error Register : 0x0\n"); 86 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 87 | 88 | /* Set ODR and performance */ 89 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 90 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 91 | 92 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 93 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 94 | 95 | rslt = bmm350_delay_us(10000, &dev); 96 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 97 | 98 | /* Enable all axis */ 99 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 100 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 101 | 102 | if (rslt == BMM350_OK) 103 | { 104 | printf("\n**********BEFORE SELFTEST**********\n"); 105 | 106 | printf("\nPower mode is set to normal mode\n"); 107 | 108 | printf("\nCompensated Magnetometer and temperature data with delay\n"); 109 | 110 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 111 | 112 | /* Time in milliseconds */ 113 | time_ms = coines_get_millis(); 114 | 115 | while (loop) 116 | { 117 | rslt = bmm350_delay_us(100000, &dev); 118 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 119 | 120 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 121 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 122 | 123 | printf("%lu, %f, %f, %f, %f\n", 124 | (long unsigned int)(coines_get_millis() - time_ms), 125 | mag_temp_data.x, 126 | mag_temp_data.y, 127 | mag_temp_data.z, 128 | mag_temp_data.temperature); 129 | 130 | loop--; 131 | } 132 | 133 | printf("\nSelf-test data in suspend mode\n"); 134 | 135 | printf("\nIteration, OUT_UST_X, OUT_UST_Y\n"); 136 | 137 | while (loop < 20) 138 | { 139 | rslt = bmm350_perform_self_test(&out_data, &dev); 140 | bmm350_error_codes_print_result("bmm350_perform_self_test", rslt); 141 | 142 | printf("%d, %f, %f\n", loop, out_data.out_ust_x, out_data.out_ust_y); 143 | 144 | loop++; 145 | } 146 | 147 | printf("\n**********AFTER SELFTEST**********\n"); 148 | 149 | loop = 20; 150 | 151 | printf("\nCompensated Magnetometer and temperature data\n"); 152 | 153 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 154 | 155 | /* Time in milliseconds */ 156 | time_ms = coines_get_millis(); 157 | 158 | while (loop) 159 | { 160 | rslt = bmm350_delay_us(10000, &dev); 161 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 162 | 163 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 164 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 165 | 166 | printf("%lu, %f, %f, %f, %f\n", 167 | (long unsigned int)(coines_get_millis() - time_ms), 168 | mag_temp_data.x, 169 | mag_temp_data.y, 170 | mag_temp_data.z, 171 | mag_temp_data.temperature); 172 | 173 | loop--; 174 | } 175 | 176 | printf("\nSelf-test data in normal mode\n"); 177 | 178 | rslt = bmm350_perform_self_test(&out_data, &dev); 179 | bmm350_error_codes_print_result("bmm350_perform_self_test", rslt); 180 | 181 | printf("Self-test data\n"); 182 | 183 | printf("\nOUT_UST_X, OUT_UST_Y\n"); 184 | 185 | printf("%f, %f\n", out_data.out_ust_x, out_data.out_ust_y); 186 | 187 | loop = 20; 188 | 189 | printf("\nCompensated Magnetometer and temperature data\n"); 190 | 191 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 192 | 193 | /* Time in milliseconds */ 194 | time_ms = coines_get_millis(); 195 | 196 | while (loop) 197 | { 198 | rslt = bmm350_delay_us(10000, &dev); 199 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 200 | 201 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 202 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 203 | 204 | printf("%lu, %f, %f, %f, %f\n", 205 | (long unsigned int)(coines_get_millis() - time_ms), 206 | mag_temp_data.x, 207 | mag_temp_data.y, 208 | mag_temp_data.z, 209 | mag_temp_data.temperature); 210 | 211 | loop--; 212 | } 213 | } 214 | 215 | bmm350_coines_deinit(); 216 | 217 | return rslt; 218 | } 219 | -------------------------------------------------------------------------------- /examples/common/common.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file common.c 34 | * 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | #include "coines.h" 42 | #include "bmm350.h" 43 | #include "common.h" 44 | 45 | /******************************************************************************/ 46 | /*! Structure definition */ 47 | 48 | #define BMM350_SHUTTLE_ID UINT16_C(0x27) 49 | 50 | /******************************************************************************/ 51 | /*! Static variable definition */ 52 | 53 | /*! Variable that holds the I2C device address selection */ 54 | static uint8_t dev_addr; 55 | 56 | /*! Variable to store coines I2C bus selection */ 57 | static enum coines_i2c_bus i2c_bus; 58 | 59 | /******************************************************************************/ 60 | /*! User interface functions */ 61 | 62 | /*! 63 | * I2C read function map to COINES platform 64 | */ 65 | BMM350_INTF_RET_TYPE bmm350_i2c_read(uint8_t reg_addr, uint8_t *reg_data, uint32_t length, void *intf_ptr) 66 | { 67 | uint8_t device_addr = *(uint8_t*)intf_ptr; 68 | 69 | (void)intf_ptr; 70 | 71 | return coines_read_i2c(i2c_bus, device_addr, reg_addr, reg_data, (uint16_t)length); 72 | } 73 | 74 | /*! 75 | * I2C write function map to COINES platform 76 | */ 77 | BMM350_INTF_RET_TYPE bmm350_i2c_write(uint8_t reg_addr, const uint8_t *reg_data, uint32_t length, void *intf_ptr) 78 | { 79 | uint8_t device_addr = *(uint8_t*)intf_ptr; 80 | 81 | (void)intf_ptr; 82 | 83 | return coines_write_i2c(i2c_bus, device_addr, reg_addr, (uint8_t *)reg_data, (uint16_t)length); 84 | } 85 | 86 | /*! 87 | * Delay function map to COINES platform 88 | */ 89 | void bmm350_delay(uint32_t period, void *intf_ptr) 90 | { 91 | (void)intf_ptr; 92 | 93 | #if defined(MCU_APP30) 94 | coines_delay_realtime_usec(period); 95 | #else 96 | coines_delay_usec(period); 97 | #endif 98 | } 99 | 100 | /*! 101 | * @brief Prints the execution status of the APIs. 102 | */ 103 | void bmm350_error_codes_print_result(const char api_name[], int8_t rslt) 104 | { 105 | switch (rslt) 106 | { 107 | case BMM350_OK: 108 | break; 109 | 110 | case BMM350_E_NULL_PTR: 111 | printf("%s Error [%d] : Null pointer\r\n", api_name, rslt); 112 | break; 113 | case BMM350_E_COM_FAIL: 114 | printf("%s Error [%d] : Communication fail\r\n", api_name, rslt); 115 | break; 116 | case BMM350_E_DEV_NOT_FOUND: 117 | printf("%s Error [%d] : Device not found\r\n", api_name, rslt); 118 | break; 119 | case BMM350_E_INVALID_CONFIG: 120 | printf("%s Error [%d] : Invalid configuration\r\n", api_name, rslt); 121 | break; 122 | case BMM350_E_BAD_PAD_DRIVE: 123 | printf("%s Error [%d] : Bad pad drive\r\n", api_name, rslt); 124 | break; 125 | case BMM350_E_RESET_UNFINISHED: 126 | printf("%s Error [%d] : Reset unfinished\r\n", api_name, rslt); 127 | break; 128 | case BMM350_E_INVALID_INPUT: 129 | printf("%s Error [%d] : Invalid input\r\n", api_name, rslt); 130 | break; 131 | case BMM350_E_SELF_TEST_INVALID_AXIS: 132 | printf("%s Error [%d] : Self-test invalid axis selection\r\n", api_name, rslt); 133 | break; 134 | case BMM350_E_OTP_BOOT: 135 | printf("%s Error [%d] : OTP boot\r\n", api_name, rslt); 136 | break; 137 | case BMM350_E_OTP_PAGE_RD: 138 | printf("%s Error [%d] : OTP page read\r\n", api_name, rslt); 139 | break; 140 | case BMM350_E_OTP_PAGE_PRG: 141 | printf("%s Error [%d] : OTP page prog\r\n", api_name, rslt); 142 | break; 143 | case BMM350_E_OTP_SIGN: 144 | printf("%s Error [%d] : OTP sign\r\n", api_name, rslt); 145 | break; 146 | case BMM350_E_OTP_INV_CMD: 147 | printf("%s Error [%d] : OTP invalid command\r\n", api_name, rslt); 148 | break; 149 | case BMM350_E_OTP_UNDEFINED: 150 | printf("%s Error [%d] : OTP undefined\r\n", api_name, rslt); 151 | break; 152 | case BMM350_E_ALL_AXIS_DISABLED: 153 | printf("%s Error [%d] : All axis are disabled\r\n", api_name, rslt); 154 | break; 155 | case BMM350_E_PMU_CMD_VALUE: 156 | printf("%s Error [%d] : Unexpected PMU CMD value\r\n", api_name, rslt); 157 | break; 158 | default: 159 | printf("%s Error [%d] : Unknown error code\r\n", api_name, rslt); 160 | break; 161 | } 162 | } 163 | 164 | /*! 165 | * @brief Function to select the interface. 166 | */ 167 | int8_t bmm350_interface_init(struct bmm350_dev *dev) 168 | { 169 | int8_t rslt = BMM350_OK; 170 | struct coines_board_info board_info; 171 | 172 | if (dev != NULL) 173 | { 174 | int16_t result = coines_open_comm_intf(COINES_COMM_INTF_USB, NULL); 175 | if (result < COINES_SUCCESS) 176 | { 177 | printf( 178 | "\n Unable to connect with Application Board ! \n" " 1. Check if the board is connected and powered on. \n" " 2. Check if Application Board USB driver is installed. \n" 179 | " 3. Check if board is in use by another application. (Insufficient permissions to access USB) \n"); 180 | exit(result); 181 | } 182 | 183 | (void)coines_get_board_info(&board_info); 184 | 185 | if (board_info.shuttle_id == BMM350_SHUTTLE_ID) 186 | { 187 | i2c_bus = COINES_I2C_BUS_0; 188 | } 189 | else 190 | { 191 | i2c_bus = COINES_I2C_BUS_1; 192 | } 193 | 194 | dev_addr = BMM350_I2C_ADSEL_SET_LOW; 195 | dev->intf_ptr = &dev_addr; 196 | dev->read = bmm350_i2c_read; 197 | dev->write = bmm350_i2c_write; 198 | dev->delay_us = bmm350_delay; 199 | 200 | #if !defined(MCU_APP20) 201 | (void)coines_set_pin_config(COINES_MINI_SHUTTLE_PIN_1_4, COINES_PIN_DIRECTION_OUT, COINES_PIN_VALUE_LOW); 202 | #endif 203 | 204 | (void)coines_config_i2c_bus(i2c_bus, COINES_I2C_STANDARD_MODE); 205 | 206 | (void)coines_set_shuttleboard_vdd_vddio_config(0, 0); 207 | 208 | coines_delay_msec(100); 209 | 210 | (void)coines_set_shuttleboard_vdd_vddio_config(1800, 1800); 211 | 212 | coines_delay_msec(100); 213 | } 214 | else 215 | { 216 | rslt = BMM350_E_NULL_PTR; 217 | } 218 | 219 | return rslt; 220 | } 221 | 222 | void bmm350_coines_get_button_state(enum coines_multi_io_pin button_id, 223 | enum coines_pin_direction *btn_dir, 224 | enum coines_pin_value *btn_value) 225 | { 226 | 227 | (void)coines_get_pin_config(button_id, btn_dir, btn_value); 228 | 229 | } 230 | 231 | void bmm350_coines_deinit(void) 232 | { 233 | (void)fflush(stdout); 234 | 235 | (void)coines_set_shuttleboard_vdd_vddio_config(0, 0); 236 | 237 | coines_delay_msec(2000); 238 | 239 | coines_soft_reset(); 240 | 241 | coines_delay_msec(100); 242 | 243 | (void)coines_close_comm_intf(COINES_COMM_INTF_USB, NULL); 244 | } 245 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # BMM350 Examples 2 | 3 | Commands to run tests on MCU: 4 | 5 | To run in Command line : 6 | --------------------------- 7 | 1. mingw32-make clean 8 | 2. mingw32-make TARGET=MCU_APP30 all 9 | 3. mingw32-make TARGET=MCU_APP30 download 10 | 11 | Commands to run tests on PC: 12 | 13 | To run in Command line : 14 | --------------------------- 15 | 1. mingw32-make clean 16 | 2. mingw32-make all 17 | 18 | ### Example 1 : bmm3530 config changes: 19 | 20 | This example is to test the change in configurations like powermode, ODR and AVG, axis enabling/disabling etc. 21 | 22 | #### Procedure: 23 | 24 | 1. Check chip_id 25 | 2. Set normal mode 26 | 3. Read data and print 27 | 4. Calculate mean and noise for 100 samples 28 | 5. Reconfigure ODR and AVG( 50,8x / 400,1x / 25,4x ) in normal mode 29 | 6. Set suspend mode 30 | 7. Read data and print (10x loop) -> no change 31 | 8. Disable x and y axis alone 32 | 9. Set normal mode 33 | 10. Read 20x and print 34 | 35 | #### Usecase: 36 | 37 | 1. To test the behaviour of sensor in normal mode and suspend mode 38 | 39 | ### Example 2 : bmm350 forced mode: 40 | 41 | This example is to read the mag data in forced mode under various configurations 42 | 43 | #### Procedure: 44 | 45 | For combination 1, 46 | 47 | Set forced mode fast and read data with averaging between 4 samples 48 | 49 | Usecase: No change is data so the customer understands that forced mode just does 1 conversion. 50 | 51 | For combination 2, 52 | 53 | Set forced mode fast and read data with averaging between 4 samples in a loop 54 | 55 | Usecase: The value changes for every read 56 | 57 | For combination 3, 58 | 59 | Set forced mode and read data with no averaging between samples in a loop 60 | 61 | Usecase: Customer understands how AVG setting affects forced mode 62 | 63 | For combination 4, 64 | 65 | Set forced mode fast and read data with averaging between 4 samples in a loop 66 | 67 | Usecase: The value changes for every read 68 | 69 | For combination 5, 70 | 71 | Set forced mode and read data with no averaging between samples in a loop 72 | 73 | Usecase: Customer understands how AVG setting affects forced mode 74 | 75 | For combination 6, 76 | 77 | Set forced mode fast and read data with averaging between 2 samples in a loop 78 | 79 | Usecase: The value changes for every read. Also customer understands that a small AVG setting requires less time for a conversion. 80 | 81 | ### Example 3 : bmm350 illegal command: 82 | 83 | This example is to read the flag bit PMU_CMD_STATUS_0.cmd_is_illegal. When PMU_CMD register is set to illegal values, then the flag bit is set. 84 | 85 | #### Procedure: 86 | 87 | 1. Read chip id 88 | 2. Set legal PMU_CMD (0 to 8) 89 | 3. Read PMU_CMD_STATUS_0.cmd_is_illegal 90 | 4. Set illegal PMU_CMD (10 to 15) 91 | 5. Read PMU_CMD_STATUS_0.cmd_is_illegal 92 | 93 | #### Usecase: 94 | 95 | 1. Customer understands bmm350 is robust against bad commands sent to PMU_CMD 96 | 97 | ### Example 4 : bmm350 interrupt: 98 | 99 | This example is to test the interrupts by changing the interrupt pin configurations. 100 | 101 | #### Procedure: 102 | 103 | 1. Check Chip id 104 | 2. Configure interrupt( active HIGH, pulsed, mapped to INT pin, push-pull) 105 | 3. Wait for 10 seconds 106 | 4. Change different ODR 107 | 5. Wait for 10 seconds 108 | 6. Configure interrupt( active LOW, pulsed, mapped to INT pin, push-pull) 109 | 7. Wait for 10 seconds 110 | 8. Configure interrupt( active LOW, latched, mapped to INT pin, push-pull) 111 | 9. Wait for 10 seconds 112 | 10. Configure interrupt( active HIGH, pulsed, mapped to INT pin, push-pull) 113 | 114 | #### Usecase: 115 | 116 | 1. Customer should use oscilloscope to watch INT pin pulsing 117 | 2. Customer will see INT going LOW (active LOW) and stay there 118 | 119 | ##### Scenario 1: 120 | 121 | Read magnetic and temperature data with 100ms delay for 20 times 122 | 123 | ##### Usecase: 124 | 125 | Customer will understand that clearing interrupt status requires reading data 126 | 127 | ##### Scenario 2: 128 | 129 | Read magnetic and temperature data with hardware interrupt by reading INT_STATUS register for 20 times 130 | 131 | ##### Usecase: 132 | 133 | Customer will understand that clearing interrupt status can also be done by reading INT_STATUS 134 | 135 | ### Example 5 : bmm350 magnetic reset: 136 | 137 | This example is to understand what to do to trigger magnetic reset , e.g. after magnetic shock or longer idle times in suspend 138 | 139 | #### Procedure: 140 | 141 | 1. Set normal mode 142 | 2. Read magnetic and temperature data for 20 times and print 143 | 3. Set suspend mode 144 | 4. Send magnetic reset 145 | 5. Set normal mode 146 | 6. Read magnetic and temperature data for 20 times and print 147 | 7. Send magnetic reset 148 | 8. Read magnetic and temperature data for 20 times and print 149 | 150 | #### Usecase: 151 | 152 | 1. Customer understands that API function checks for power mode. It automatically switches to suspend and restores normal mode if this was the mode selected 153 | 154 | ### Example 6 : bmm350 polling: 155 | 156 | This example is to read the magnetic and temperature data by polling machanism. 157 | 158 | #### Procedure: 159 | 160 | ##### Scenario 1: 161 | 162 | 1. Set normal mode 163 | 2. Set ODR = 25Hz, AVG = 8x 164 | 3. Loop = 20 165 | 4. Wait for 36ms (1 ODR period - 10% margin) 166 | 5. Read the magnetic and temperature data and print 167 | 168 | ##### Usecase: 169 | 170 | Customer understands that too fast reading leads to double reads. too slow reading thus leads to loss of data. 171 | 172 | ##### Scenario 2: 173 | 174 | 1. Set normal mode 175 | 2. Set ODR = 25Hz, AVG = 8x 176 | 3. Loop = 22 177 | 4. Read the magnetic and temperature data by reading INT_STATUS register and print 178 | 179 | ##### Usecase: 180 | 181 | Customer understands data loss can be prevented by reading data ready flag before reading data. 182 | 183 | 184 | ### Example 7 : bmm350 self test: 185 | 186 | This example is to test the selftest on various power modes 187 | 188 | #### Procedure: 189 | 190 | ##### Scenario 1: 191 | 192 | 1. Set normal mode 193 | 2. Loop = 10 194 | 3. Read magnetometer and temperature data 195 | 4. Provide 100ms delay 196 | 5. Print magnetometer and temperature data 197 | 198 | ##### Scenario 2: 199 | 200 | 1. Set suspend mode 201 | 2. Loop = 20 202 | 3. Call bmm350_ perform_ self_test API 203 | 4. Print selftest data 204 | 5. Loop 20 times and print magnetic and temperature data 205 | 206 | ##### Usecase: 207 | 208 | Customer understands selftest is called from suspend mode 209 | 210 | ### Example 8 : bmm350 sensor time: 211 | 212 | This example is to test sensortime under various power mode configurations. 213 | 214 | #### Procedure: 215 | 216 | ##### Scenario 1: 217 | 218 | 1. Set suspend mode 219 | 2. Read sensortime and print for 20 loop 220 | 221 | ##### Usecase: 222 | 223 | Customer understands : no change in suspend mode. 224 | 225 | ##### Scenario 2: 226 | 227 | 1. Set CTRL_USER to 0x01 228 | 2. Loop = 20 229 | 3. Set forced mode 230 | 4. Wait for 40ms 231 | 5. Read sensortime (Change in data) 232 | 6. Read sensortime (No change in data) 233 | 7. Read sensortime (No change in data) 234 | 235 | ##### Usecase: 236 | 237 | Customer understands: sensortime is only updated when a conversion happens. 238 | sensortime indicates the SENSOR time at which the last conversion happened 239 | 240 | ##### Scenario 3: 241 | 242 | 1. Set normal mode 243 | 2. Set ODR = 100hz, AVG = 2x 244 | 3. Read sensortime and print for 20 loop (change in data everytime) 245 | 246 | ##### Usecase: 247 | 248 | Customer understands : at every conversion sensortime is updated 249 | this program requires compilation on the ARM since the wait time is short 250 | 251 | ### Example 9 : bmm350 normal mode: 252 | 253 | This example is to read the uncompensated and compensated magnetic and temperature data in normal mode. 254 | 255 | #### Procedure: 256 | 257 | 1. Read chip id 258 | 2. Configure interrupt(active HIGH, pulsed, unmap from pin, push-pull) 259 | 3. Enable data ready interrupt 260 | 4. Set ODR and AVG 261 | 5. Enable all axes 262 | 6. Set normal mode 263 | 7. Read uncompensated magnetometer and temperature data for 20 times by reading INT_STATUS register 264 | 8. Read compensated magnetometer and temperature data for 50 times by reading INT_STATUS register 265 | 266 | #### Usecase: 267 | 268 | To find the difference between uncompensated and compensated magnetic and temperature data read in normal mode. 269 | 270 | ### Example 10 : bmm350 out of range detect: 271 | 272 | This example is to measure the data from the sensor and detects when sensor goes out of range i.e greater than +/- 2400uT 273 | with half self-test threshold and full self-test threshold 274 | 275 | #### Procedure: 276 | 277 | 1. Read chip id 278 | 2. Perform self-test 279 | 3. Set ODR and AVG 280 | 4. Enable all axes 281 | 5. Set forced mode fast 282 | 6. Measure data such as 283 | a. Magnetometer x, y and z axis 284 | b. Field strength 285 | c. Out of range 286 | d. X failed and Y failed 287 | e. Difference in magnetometer positive x and negative x and difference in magnetometer positive y and negative y 288 | f. Reset value and Reset counter 289 | g. Self-test active 290 | h. Self-test counter 291 | 7. Trigger magnetic reset 292 | 293 | #### Usecase: 294 | 295 | To find the sensor state when magnetometer value goes out of range detection 296 | -------------------------------------------------------------------------------- /examples/bmm350_normal_mode/bmm350_normal_mode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_normal_mode.c 34 | * 35 | * @brief This file contains reading of magnetometer data in normal mode. 36 | * 37 | */ 38 | 39 | #include 40 | #include "bmm350.h" 41 | #include "common.h" 42 | #include "coines.h" 43 | 44 | /******************************************************************************/ 45 | /*! Functions */ 46 | 47 | /* This function starts the execution of program */ 48 | int main(void) 49 | { 50 | /* Status of api are returned to this variable */ 51 | int8_t rslt; 52 | 53 | /* Sensor initialization configuration */ 54 | struct bmm350_dev dev = { 0 }; 55 | 56 | uint8_t int_status, int_ctrl, err_reg_data = 0; 57 | uint8_t loop = 10, set_int_ctrl; 58 | uint32_t secs, nano_secs = 0; 59 | uint32_t time_ms = 0; 60 | 61 | struct bmm350_mag_temp_data mag_temp_data; 62 | struct bmm350_raw_mag_data raw_data; 63 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 64 | 65 | /* Update device structure */ 66 | rslt = bmm350_interface_init(&dev); 67 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 68 | 69 | /* Initialize BMM350 */ 70 | rslt = bmm350_init(&dev); 71 | bmm350_error_codes_print_result("bmm350_init", rslt); 72 | 73 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 74 | 75 | printf("-------------\nCoefficients\n-------------\n"); 76 | printf("Magnetometer Offset:: X: %.2f, Y: %.2f, Z: %.2f\n", 77 | dev.mag_comp.dut_offset_coef.offset_x, 78 | dev.mag_comp.dut_offset_coef.offset_y, 79 | dev.mag_comp.dut_offset_coef.offset_z); 80 | printf("Temperature offset %.2f\n", dev.mag_comp.dut_offset_coef.t_offs); 81 | printf("Magnetometer Sensitivity:: X: %.2f, Y: %.2f, Z: %.2f\n", 82 | dev.mag_comp.dut_sensit_coef.sens_x, 83 | dev.mag_comp.dut_sensit_coef.sens_y, 84 | dev.mag_comp.dut_sensit_coef.sens_z); 85 | printf("Temperature sensitivity %.2f\n", dev.mag_comp.dut_sensit_coef.t_sens); 86 | printf("TCO:: X: %.2f, Y: %.2f, Z: %.2f\n", 87 | dev.mag_comp.dut_tco.tco_x, 88 | dev.mag_comp.dut_tco.tco_y, 89 | dev.mag_comp.dut_tco.tco_z); 90 | printf("TCS:: X: %.4f, Y: %.4f, Z: %.4f\n", 91 | dev.mag_comp.dut_tcs.tcs_x, 92 | dev.mag_comp.dut_tcs.tcs_y, 93 | dev.mag_comp.dut_tcs.tcs_z); 94 | printf("T0 %.2f\n", dev.mag_comp.dut_t0); 95 | printf("Cross XY %f\n", dev.mag_comp.cross_axis.cross_x_y); 96 | printf("Cross YX %f\n", dev.mag_comp.cross_axis.cross_y_x); 97 | printf("Cross ZX %f\n", dev.mag_comp.cross_axis.cross_z_x); 98 | printf("Cross ZY %f\n", dev.mag_comp.cross_axis.cross_z_y); 99 | 100 | /* Check PMU busy */ 101 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 102 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 103 | 104 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 105 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 106 | 107 | /* Get error data */ 108 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 109 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 110 | 111 | printf("Expected : 0x02 : Error Register : 0x0\n"); 112 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 113 | 114 | /* Configure interrupt settings */ 115 | rslt = bmm350_configure_interrupt(BMM350_PULSED, 116 | BMM350_ACTIVE_HIGH, 117 | BMM350_INTR_PUSH_PULL, 118 | BMM350_UNMAP_FROM_PIN, 119 | &dev); 120 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 121 | 122 | /* Enable data ready interrupt */ 123 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 124 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 125 | 126 | /* Get interrupt settings */ 127 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 128 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 129 | 130 | set_int_ctrl = ((BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | BMM350_ENABLE << 7); 131 | 132 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 133 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 134 | 135 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 136 | { 137 | printf("Data ready enabled\n"); 138 | } 139 | 140 | /* Set ODR and performance */ 141 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 142 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 143 | 144 | /* Enable all axis */ 145 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 146 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 147 | 148 | if (rslt == BMM350_OK) 149 | { 150 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 151 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 152 | 153 | printf("\nUncompensated magnetometer and temperature data\n"); 154 | 155 | printf("mag_x_raw, mag_y_raw, mag_z_raw, Temperature(raw), time(secs)\n"); 156 | 157 | while (loop > 0) 158 | { 159 | int_status = 0; 160 | 161 | /* Get data ready interrupt status */ 162 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 163 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 164 | 165 | /* Check if data ready interrupt occurred */ 166 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 167 | { 168 | /* Get uncompensated mag data */ 169 | rslt = bmm350_read_uncomp_mag_temp_data(&raw_data, &dev); 170 | bmm350_error_codes_print_result("bmm350_read_uncomp_mag_data", rslt); 171 | 172 | rslt = bmm350_read_sensortime(&secs, &nano_secs, &dev); 173 | bmm350_error_codes_print_result("bmm350_read_sensortime", rslt); 174 | 175 | printf("%ld, %ld, %ld, %ld, %lu.%09lu\n", 176 | (long int)raw_data.raw_xdata, 177 | (long int)raw_data.raw_ydata, 178 | (long int)raw_data.raw_zdata, 179 | (long int)raw_data.raw_data_t, 180 | (long unsigned int)secs, 181 | (long unsigned int)nano_secs); 182 | 183 | loop--; 184 | } 185 | } 186 | 187 | loop = 50; 188 | 189 | printf("\nCompensated magnetometer and temperature data\n"); 190 | 191 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 192 | 193 | /* Time in milliseconds */ 194 | time_ms = coines_get_millis(); 195 | 196 | while (loop) 197 | { 198 | int_status = 0; 199 | 200 | /* Get data ready interrupt status */ 201 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 202 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 203 | 204 | /* Check if data ready interrupt occurred */ 205 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 206 | { 207 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 208 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 209 | 210 | printf("%lu, %f, %f, %f, %f\n", 211 | (long unsigned int)(coines_get_millis() - time_ms), 212 | mag_temp_data.x, 213 | mag_temp_data.y, 214 | mag_temp_data.z, 215 | mag_temp_data.temperature); 216 | 217 | loop--; 218 | } 219 | } 220 | } 221 | 222 | bmm350_coines_deinit(); 223 | 224 | return rslt; 225 | } 226 | -------------------------------------------------------------------------------- /examples/bmm350_interrupt/bmm350_interrupt.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_interrupt.c 34 | * 35 | * @brief This file contains reading of magnetometer data in normal mode by hardware interrupt. 36 | * 37 | */ 38 | 39 | #include 40 | #include 41 | 42 | #include "bmm350.h" 43 | #include "common.h" 44 | #include "coines.h" 45 | 46 | /******************************************************************************/ 47 | /*! Global variable Declaration */ 48 | 49 | volatile bool bmm3_int_recvd = false; 50 | 51 | /******************************************************************************/ 52 | /*! Static Function Declaration */ 53 | 54 | /*! 55 | * @brief This internal API is used to set the data ready interrupt status 56 | * 57 | * @return void 58 | */ 59 | static void bmm3_int_callback(uint32_t val1, uint32_t val2); 60 | 61 | /******************************************************************************/ 62 | /*! Functions */ 63 | 64 | /*! 65 | * @brief This internal API is used to set the data ready interrupt status 66 | */ 67 | static void bmm3_int_callback(uint32_t val1, uint32_t val2) 68 | { 69 | (void)val1; 70 | (void)val2; 71 | bmm3_int_recvd = 1; 72 | } 73 | 74 | /* This function starts the execution of program */ 75 | int main(void) 76 | { 77 | /* Status of api are returned to this variable */ 78 | int8_t rslt; 79 | 80 | /* Sensor initialization configuration */ 81 | struct bmm350_dev dev = { 0 }; 82 | 83 | uint8_t int_status, int_ctrl, err_reg_data = 0; 84 | uint8_t loop = 20, set_int_ctrl; 85 | uint32_t time_ms = 0; 86 | 87 | struct bmm350_mag_temp_data mag_temp_data; 88 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 89 | 90 | /* Update device structure */ 91 | rslt = bmm350_interface_init(&dev); 92 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 93 | 94 | /* Initialize BMM350 */ 95 | rslt = bmm350_init(&dev); 96 | bmm350_error_codes_print_result("bmm350_init", rslt); 97 | 98 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 99 | 100 | /* Check PMU busy */ 101 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 102 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 103 | 104 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 105 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 106 | 107 | /* Get error data */ 108 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 109 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 110 | 111 | printf("Expected : 0x02 : Error Register : 0x0\n"); 112 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 113 | 114 | /* Configure interrupt settings */ 115 | rslt = 116 | bmm350_configure_interrupt(BMM350_PULSED, BMM350_ACTIVE_HIGH, BMM350_INTR_PUSH_PULL, BMM350_MAP_TO_PIN, &dev); 117 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 118 | 119 | /* Enable data ready interrupt */ 120 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 121 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 122 | 123 | /* Get interrupt settings */ 124 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 125 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 126 | 127 | set_int_ctrl = 128 | ((BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | (BMM350_ENABLE << 3) | BMM350_ENABLE << 7); 129 | 130 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 131 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 132 | 133 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 134 | { 135 | printf("Data ready enabled\r\n"); 136 | } 137 | 138 | /* Set ODR and performance */ 139 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 140 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 141 | 142 | rslt = bmm350_delay_us(10000, &dev); 143 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 144 | 145 | /* Configure interrupt settings */ 146 | rslt = bmm350_configure_interrupt(BMM350_PULSED, BMM350_ACTIVE_LOW, BMM350_INTR_PUSH_PULL, BMM350_MAP_TO_PIN, &dev); 147 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 148 | 149 | rslt = bmm350_delay_us(10000, &dev); 150 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 151 | 152 | /* Configure interrupt settings */ 153 | rslt = 154 | bmm350_configure_interrupt(BMM350_LATCHED, BMM350_ACTIVE_LOW, BMM350_INTR_PUSH_PULL, BMM350_MAP_TO_PIN, &dev); 155 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 156 | 157 | rslt = bmm350_delay_us(10000, &dev); 158 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 159 | 160 | /* Configure interrupt settings */ 161 | rslt = 162 | bmm350_configure_interrupt(BMM350_PULSED, BMM350_ACTIVE_HIGH, BMM350_INTR_PUSH_PULL, BMM350_MAP_TO_PIN, &dev); 163 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 164 | 165 | rslt = bmm350_delay_us(10000, &dev); 166 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 167 | 168 | /* Enable all axis */ 169 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 170 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 171 | 172 | if (rslt == BMM350_OK) 173 | { 174 | rslt = bmm350_set_pad_drive(BMM350_PAD_DRIVE_STRONGEST, &dev); 175 | bmm350_error_codes_print_result("bmm350_set_pad_drive", rslt); 176 | 177 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 178 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 179 | 180 | printf("\nPower mode is set to normal mode\n"); 181 | printf("Compensated Magnetometer and temperature data with delay\n"); 182 | 183 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 184 | 185 | /* Time in milliseconds */ 186 | time_ms = coines_get_millis(); 187 | 188 | while (loop) 189 | { 190 | rslt = bmm350_delay_us(100000, &dev); 191 | bmm350_error_codes_print_result("bmm350_delay_us", rslt); 192 | 193 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 194 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 195 | 196 | printf("%lu, %f, %f, %f, %f\n", 197 | (long unsigned int)(coines_get_millis() - time_ms), 198 | mag_temp_data.x, 199 | mag_temp_data.y, 200 | mag_temp_data.z, 201 | mag_temp_data.temperature); 202 | 203 | loop--; 204 | } 205 | 206 | /* Hardware interrupt configuration */ 207 | coines_attach_interrupt(COINES_MINI_SHUTTLE_PIN_1_6, bmm3_int_callback, COINES_PIN_INTERRUPT_RISING_EDGE); 208 | 209 | printf("\nPower mode is set to normal mode\n"); 210 | printf("Compensated Magnetometer and temperature data with hardware interrupt\n"); 211 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 212 | 213 | loop = 0; 214 | 215 | /* Time in milliseconds */ 216 | time_ms = coines_get_millis(); 217 | 218 | for (;;) 219 | { 220 | if (bmm3_int_recvd) 221 | { 222 | bmm3_int_recvd = 0; 223 | int_status = 0; 224 | 225 | /* Get data ready interrupt status */ 226 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 227 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 228 | 229 | /* Check if data ready interrupt occurred */ 230 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 231 | { 232 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 233 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 234 | 235 | printf("%lu, %f, %f, %f, %f\n", 236 | (long unsigned int)(coines_get_millis() - time_ms), 237 | mag_temp_data.x, 238 | mag_temp_data.y, 239 | mag_temp_data.z, 240 | mag_temp_data.temperature); 241 | 242 | loop++; 243 | 244 | if (loop == 20) 245 | { 246 | break; 247 | } 248 | } 249 | } 250 | } 251 | } 252 | 253 | bmm350_coines_deinit(); 254 | 255 | return rslt; 256 | } 257 | -------------------------------------------------------------------------------- /examples/bmm350_magnetic_reset/bmm350_magnetic_reset.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * 34 | * @file bmm350_magnetic_reset.c 35 | * 36 | * @brief This file contains reading of magnetometer data before and after magnetic reset. 37 | * 38 | */ 39 | 40 | #include 41 | #include 42 | 43 | #include "bmm350.h" 44 | #include "common.h" 45 | #include "coines.h" 46 | 47 | /******************************************************************************/ 48 | /*! Functions */ 49 | 50 | /* This function starts the execution of program */ 51 | int main(void) 52 | { 53 | /* Status of api are returned to this variable */ 54 | int8_t rslt; 55 | 56 | /* Sensor initialization configuration */ 57 | struct bmm350_dev dev = { 0 }; 58 | 59 | uint8_t int_status, int_ctrl, err_reg_data = 0; 60 | uint8_t loop = 20, set_int_ctrl; 61 | uint32_t time_ms = 0; 62 | float magnitude = 0.0f; 63 | 64 | struct bmm350_mag_temp_data mag_temp_data = { 0 }; 65 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0; 66 | 67 | /* Update device structure */ 68 | rslt = bmm350_interface_init(&dev); 69 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 70 | 71 | /* Initialize BMM350 */ 72 | rslt = bmm350_init(&dev); 73 | bmm350_error_codes_print_result("bmm350_init", rslt); 74 | 75 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 76 | 77 | /* Check PMU busy */ 78 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 79 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 80 | 81 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 82 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 83 | 84 | /* Get error data */ 85 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 86 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 87 | 88 | printf("Expected : 0x02 : Error Register : 0x0\n"); 89 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 90 | 91 | /* Configure interrupt settings */ 92 | rslt = bmm350_configure_interrupt(BMM350_PULSED, 93 | BMM350_ACTIVE_HIGH, 94 | BMM350_INTR_PUSH_PULL, 95 | BMM350_UNMAP_FROM_PIN, 96 | &dev); 97 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 98 | 99 | /* Enable data ready interrupt */ 100 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 101 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 102 | 103 | /* Get interrupt settings */ 104 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 105 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 106 | 107 | set_int_ctrl = ((BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | BMM350_ENABLE << 7); 108 | 109 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 110 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 111 | 112 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 113 | { 114 | printf("Data ready enabled\r\n"); 115 | } 116 | 117 | /* Set ODR and performance */ 118 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 119 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 120 | 121 | /* Enable all axis */ 122 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 123 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 124 | 125 | if (rslt == BMM350_OK) 126 | { 127 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 128 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 129 | 130 | printf("\nCompensated Magnetometer and temperature data in NORMAL MODE\n"); 131 | 132 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 133 | 134 | /* Time in milliseconds */ 135 | time_ms = coines_get_millis(); 136 | 137 | while (loop) 138 | { 139 | int_status = 0; 140 | 141 | /* Get data ready interrupt status */ 142 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 143 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 144 | 145 | /* Check if data ready interrupt occurred */ 146 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 147 | { 148 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 149 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 150 | 151 | printf("%lu, %f, %f, %f, %f\n", 152 | (long unsigned int)(coines_get_millis() - time_ms), 153 | mag_temp_data.x, 154 | mag_temp_data.y, 155 | mag_temp_data.z, 156 | mag_temp_data.temperature); 157 | 158 | loop--; 159 | } 160 | } 161 | 162 | rslt = bmm350_set_powermode(BMM350_SUSPEND_MODE, &dev); 163 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 164 | 165 | rslt = bmm350_magnetic_reset_and_wait(&dev); 166 | bmm350_error_codes_print_result("bmm350_magnetic_reset_and_wait", rslt); 167 | 168 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 169 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 170 | 171 | printf("\nCompensated Magnetometer and temperature data\n"); 172 | 173 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 174 | 175 | /* Time in milliseconds */ 176 | time_ms = coines_get_millis(); 177 | 178 | loop = 20; 179 | 180 | while (loop) 181 | { 182 | int_status = 0; 183 | 184 | /* Get data ready interrupt status */ 185 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 186 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 187 | 188 | /* Check if data ready interrupt occurred */ 189 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 190 | { 191 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 192 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 193 | 194 | printf("%lu, %f, %f, %f, %f\n", 195 | (long unsigned int)(coines_get_millis() - time_ms), 196 | mag_temp_data.x, 197 | mag_temp_data.y, 198 | mag_temp_data.z, 199 | mag_temp_data.temperature); 200 | 201 | loop--; 202 | } 203 | } 204 | 205 | magnitude = 206 | sqrtf((mag_temp_data.x * mag_temp_data.x) + (mag_temp_data.y * mag_temp_data.y) + 207 | (mag_temp_data.z * mag_temp_data.z)); 208 | 209 | printf("\nMagnitude before applying magnetic reset: %.2f\n\n", magnitude); 210 | 211 | rslt = bmm350_magnetic_reset_and_wait(&dev); 212 | bmm350_error_codes_print_result("bmm350_magnetic_reset_and_wait", rslt); 213 | 214 | printf("\nCompensated Magnetometer and temperature data after mag reset\n"); 215 | 216 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 217 | 218 | /* Time in milliseconds */ 219 | time_ms = coines_get_millis(); 220 | 221 | loop = 20; 222 | 223 | while (loop) 224 | { 225 | int_status = 0; 226 | 227 | /* Get data ready interrupt status */ 228 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 229 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 230 | 231 | /* Check if data ready interrupt occurred */ 232 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 233 | { 234 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 235 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 236 | 237 | printf("%lu, %f, %f, %f, %f\n", 238 | (long unsigned int)(coines_get_millis() - time_ms), 239 | mag_temp_data.x, 240 | mag_temp_data.y, 241 | mag_temp_data.z, 242 | mag_temp_data.temperature); 243 | 244 | loop--; 245 | } 246 | } 247 | 248 | magnitude = 249 | sqrtf((mag_temp_data.x * mag_temp_data.x) + (mag_temp_data.y * mag_temp_data.y) + 250 | (mag_temp_data.z * mag_temp_data.z)); 251 | 252 | printf("\nMagnitude after applying magnetic reset: %.2f\n\n", magnitude); 253 | } 254 | 255 | bmm350_coines_deinit(); 256 | 257 | return rslt; 258 | } 259 | -------------------------------------------------------------------------------- /bmm350_oor.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_oor.c 34 | * @date 2023-05-26 35 | * @version v1.4.0 36 | * 37 | */ 38 | 39 | #include "bmm350_oor.h" 40 | 41 | #ifdef BMM350_OOR_HALF_SELF_TEST 42 | 43 | /*! 44 | * @brief This internal API is used to trigger half self-test 45 | */ 46 | static int8_t trigger_half_selftest(struct bmm350_oor_params *oor, struct bmm350_dev *dev) 47 | { 48 | int8_t rslt = BMM350_OK; 49 | 50 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 51 | 52 | /* Trigger a self-test on every alternate measurement if needed */ 53 | if (oor->enable_selftest) 54 | { 55 | oor->st_counter++; 56 | 57 | switch (oor->st_counter) 58 | { 59 | case 1: 60 | oor->st_cmd = BMM350_SELF_TEST_POS_X; 61 | break; 62 | case 2: 63 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 64 | break; 65 | case 3: 66 | oor->st_cmd = BMM350_SELF_TEST_POS_Y; 67 | break; 68 | case 4: 69 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 70 | break; 71 | 72 | default: 73 | oor->st_counter = 0; 74 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 75 | break; 76 | } 77 | 78 | rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev); 79 | } 80 | else 81 | { 82 | if (oor->last_st_cmd != BMM350_SELF_TEST_DISABLE) 83 | { 84 | rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev); 85 | oor->st_counter = 0; 86 | } 87 | } 88 | 89 | return rslt; 90 | } 91 | 92 | /*! 93 | * @brief This internal API is used to validate half self-test 94 | */ 95 | static void validate_half_selftest(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor) 96 | { 97 | switch (oor->last_st_cmd) 98 | { 99 | case BMM350_SELF_TEST_DISABLE: 100 | oor->mag_xn = data->x; 101 | oor->mag_yn = data->y; 102 | break; 103 | 104 | case BMM350_SELF_TEST_POS_X: 105 | oor->mag_xp = data->x; 106 | oor->x_failed = (oor->mag_xp - oor->mag_xn) < BMM350_HALF_ST_THRESHOLD ? true : false; 107 | break; 108 | 109 | case BMM350_SELF_TEST_POS_Y: 110 | oor->mag_yp = data->y; 111 | oor->y_failed = (oor->mag_yp - oor->mag_yn) < BMM350_HALF_ST_THRESHOLD ? true : false; 112 | break; 113 | 114 | default: 115 | break; 116 | } 117 | } 118 | #else 119 | 120 | /*! 121 | * @brief This internal API is used to trigger full self-test 122 | */ 123 | static int8_t trigger_full_selftest(struct bmm350_oor_params *oor, struct bmm350_dev *dev) 124 | { 125 | int8_t rslt = BMM350_OK; 126 | 127 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 128 | 129 | /* Trigger a self-test on every alternate measurement if needed */ 130 | if (oor->enable_selftest) 131 | { 132 | oor->st_counter++; 133 | 134 | switch (oor->st_counter) 135 | { 136 | case 1: 137 | oor->st_cmd = BMM350_SELF_TEST_POS_X; 138 | break; 139 | case 2: 140 | oor->st_cmd = BMM350_SELF_TEST_NEG_X; 141 | break; 142 | case 3: 143 | oor->st_cmd = BMM350_SELF_TEST_POS_Y; 144 | break; 145 | case 4: 146 | oor->st_cmd = BMM350_SELF_TEST_NEG_Y; 147 | break; 148 | 149 | default: 150 | oor->st_counter = 0; 151 | oor->st_cmd = BMM350_SELF_TEST_DISABLE; 152 | break; 153 | } 154 | 155 | rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev); 156 | } 157 | else 158 | { 159 | if (oor->last_st_cmd != BMM350_SELF_TEST_DISABLE) 160 | { 161 | rslt = bmm350_set_regs(BMM350_REG_TMR_SELFTEST_USER, &(oor->st_cmd), 1, dev); 162 | oor->st_counter = 0; 163 | } 164 | } 165 | 166 | return rslt; 167 | } 168 | 169 | /*! 170 | * @brief This internal API is used to validate full self-test 171 | */ 172 | static void validate_full_selftest(const struct bmm350_mag_temp_data *data, struct bmm350_oor_params *oor) 173 | { 174 | switch (oor->last_st_cmd) 175 | { 176 | case BMM350_SELF_TEST_POS_X: 177 | oor->mag_xp = data->x; 178 | break; 179 | 180 | case BMM350_SELF_TEST_NEG_X: 181 | oor->mag_xn = data->x; 182 | oor->x_failed = (oor->mag_xp - oor->mag_xn) < BMM350_FULL_ST_THRESHOLD ? true : false; 183 | break; 184 | 185 | case BMM350_SELF_TEST_POS_Y: 186 | oor->mag_yp = data->y; 187 | break; 188 | 189 | case BMM350_SELF_TEST_NEG_Y: 190 | oor->mag_yn = data->y; 191 | oor->y_failed = (oor->mag_yp - oor->mag_yn) < BMM350_FULL_ST_THRESHOLD ? true : false; 192 | break; 193 | 194 | default: 195 | break; 196 | } 197 | } 198 | #endif 199 | 200 | /*! 201 | * @brief This internal API is used to validate out of range. 202 | */ 203 | static void validate_out_of_range(bool *out_of_range, 204 | const struct bmm350_mag_temp_data *data, 205 | struct bmm350_oor_params *oor) 206 | { 207 | float field_str = 0.0f; 208 | 209 | /* Threshold to start out of range detection */ 210 | float threshold = BMM350_OUT_OF_RANGE_THRESHOLD; 211 | 212 | /* Threshold to start self-tests */ 213 | float st_threshold = BMM350_SELF_TEST_THRESHOLD; 214 | 215 | /* If either self-test failed, alert that the sensor is out of range and continue self-tests */ 216 | if (oor->x_failed || oor->y_failed) 217 | { 218 | *out_of_range = true; 219 | oor->enable_selftest = true; 220 | } 221 | else 222 | { 223 | field_str = sqrtf((data->x * data->x) + (data->y * data->y) + (data->z * data->z)); 224 | 225 | /* Check for the self-test threshold and perform self-tests to catch if the sensor is out of range */ 226 | if ((fabsf(data->x) >= st_threshold) || (fabsf(data->y) >= st_threshold) || (fabsf(data->z) >= st_threshold) || 227 | (field_str >= st_threshold)) 228 | { 229 | oor->enable_selftest = true; 230 | } 231 | else if (oor->st_counter == 0) /* If a self-test procedure has started, wait for it to complete */ 232 | { 233 | oor->enable_selftest = false; 234 | } 235 | 236 | /* If out of range was previously detected, reduce the threshold to get back in range, 237 | * effectively preventing hysteresis. Selecting 400uT */ 238 | if (*out_of_range) 239 | { 240 | threshold = BMM350_IN_RANGE_THRESHOLD; 241 | } 242 | 243 | /* Check if X or Y or Z > the threshold or the magnitude of all 3 is greater */ 244 | if ((fabsf(data->x) >= threshold) || (fabsf(data->y) >= threshold) || (fabsf(data->z) >= threshold) || 245 | (field_str >= threshold)) 246 | { 247 | *out_of_range = true; 248 | } 249 | else if (oor->st_counter == 0) /* If a self-test procedure has started, wait for it to complete */ 250 | { 251 | *out_of_range = false; 252 | } 253 | } 254 | } 255 | 256 | /*! 257 | * @brief This API is used to perform reset sequence in forced mode. 258 | */ 259 | int8_t bmm350_oor_perform_reset_sequence_forced(struct bmm350_oor_params *oor, struct bmm350_dev *dev) 260 | { 261 | int8_t rslt = 0; 262 | uint8_t pmu_cmd = 0; 263 | 264 | oor->reset_counter++; 265 | 266 | switch (oor->reset_counter) 267 | { 268 | case 1: /* Trigger the Bit reset fast */ 269 | pmu_cmd = BMM350_PMU_CMD_BR_FAST; 270 | rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev); 271 | break; 272 | 273 | case 2: /* Trigger Flux Guide reset */ 274 | pmu_cmd = BMM350_PMU_CMD_FGR; 275 | rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev); 276 | break; 277 | 278 | case 3: /* Flux Guide dummy */ 279 | break; 280 | 281 | default: /* Default acts like the Flux guide reset dummy */ 282 | oor->reset_counter = 0; 283 | oor->trigger_reset = false; 284 | break; 285 | } 286 | 287 | return rslt; 288 | } 289 | 290 | /*! 291 | * @brief This API is used to read out of range in half or full self-test. 292 | */ 293 | int8_t bmm350_oor_read(bool *out_of_range, 294 | struct bmm350_mag_temp_data *data, 295 | struct bmm350_oor_params *oor, 296 | struct bmm350_dev *dev) 297 | { 298 | int8_t rslt = 0; 299 | uint8_t pmu_cmd = BMM350_PMU_CMD_SUS; 300 | 301 | #ifdef BMM350_OOR_HALF_SELF_TEST 302 | rslt = trigger_half_selftest(oor, dev); 303 | #else 304 | rslt = trigger_full_selftest(oor, dev); 305 | #endif 306 | 307 | if (rslt == BMM350_OK) 308 | { 309 | pmu_cmd = BMM350_PMU_CMD_FM_FAST; 310 | rslt = bmm350_set_regs(BMM350_REG_PMU_CMD, &pmu_cmd, 1, dev); 311 | 312 | if (rslt == BMM350_OK) 313 | { 314 | rslt = bmm350_get_compensated_mag_xyz_temp_data(data, dev); 315 | } 316 | } 317 | 318 | #ifdef BMM350_OOR_HALF_SELF_TEST 319 | validate_half_selftest(data, oor); 320 | #else 321 | validate_full_selftest(data, oor); 322 | #endif 323 | 324 | validate_out_of_range(out_of_range, data, oor); 325 | 326 | oor->last_st_cmd = oor->st_cmd; 327 | 328 | return rslt; 329 | } 330 | -------------------------------------------------------------------------------- /examples/bmm350_config_changes/bmm350_config_changes.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_config_changes.c 34 | * 35 | * @brief This file contains the configuration changes of magnetometer like enable disable axes and power mode. 36 | * 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "bmm350.h" 45 | #include "common.h" 46 | #include "coines.h" 47 | 48 | /******************************************************************************/ 49 | /*! Macro Definitions */ 50 | 51 | #define MAG_SAMPLE_COUNT UINT8_C(100) 52 | 53 | /******************************************************************************/ 54 | /*! Static Structure Definitions */ 55 | 56 | /*! 57 | * @brief bmm350 compensated magnetometer data structure 58 | */ 59 | struct bmm350_mag_data 60 | { 61 | /*! Compensated mag X data */ 62 | double x; 63 | 64 | /*! Compensated mag Y data */ 65 | double y; 66 | 67 | /*! Compensated mag Z data */ 68 | double z; 69 | }; 70 | 71 | /******************************************************************************/ 72 | /*! Static Function Declaration */ 73 | 74 | /*! 75 | * @brief This internal API is to calculate noise level for mag data 76 | * 77 | * @param[in] mag_temp_data : Structure instance of bmm350_mag_temp_data. 78 | * @param[in] avg_mag_data : Structure to store average mag data. 79 | * 80 | * @return void. 81 | */ 82 | static void calculate_noise(const struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_mag_data avg_mag_data); 83 | 84 | /******************************************************************************/ 85 | /*! Functions */ 86 | 87 | /* This function starts the execution of program */ 88 | int main(void) 89 | { 90 | /* Status of api are returned to this variable */ 91 | int8_t rslt; 92 | 93 | /* Sensor initialization configuration */ 94 | struct bmm350_dev dev = { 0 }; 95 | 96 | uint8_t int_status, int_ctrl, err_reg_data = 0; 97 | uint8_t loop = 0, set_int_ctrl; 98 | uint32_t time_ms = 0; 99 | 100 | struct bmm350_mag_temp_data mag_temp_data = { 0 }; 101 | struct bmm350_mag_temp_data get_mag_temp_data[MAG_SAMPLE_COUNT] = { { 0 } }; 102 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0 = { 0 }; 103 | struct bmm350_mag_data mean_mag_data = { 0 }; 104 | struct bmm350_mag_data avg_mag_data = { 0 }; 105 | 106 | /* Update device structure */ 107 | rslt = bmm350_interface_init(&dev); 108 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 109 | 110 | /* Initialize BMM350 */ 111 | rslt = bmm350_init(&dev); 112 | bmm350_error_codes_print_result("bmm350_init", rslt); 113 | 114 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 115 | 116 | /* Check PMU busy */ 117 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 118 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 119 | 120 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 121 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 122 | 123 | /* Get error data */ 124 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 125 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 126 | 127 | printf("Expected : 0x02 : Error Register : 0x0\n"); 128 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 129 | 130 | /* Configure interrupt settings */ 131 | rslt = bmm350_configure_interrupt(BMM350_PULSED, 132 | BMM350_ACTIVE_HIGH, 133 | BMM350_INTR_PUSH_PULL, 134 | BMM350_UNMAP_FROM_PIN, 135 | &dev); 136 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 137 | 138 | /* Enable data ready interrupt */ 139 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 140 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 141 | 142 | /* Get interrupt settings */ 143 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 144 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 145 | 146 | set_int_ctrl = ((BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | BMM350_ENABLE << 7); 147 | 148 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 149 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 150 | 151 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 152 | { 153 | printf("Data ready enabled\r\n"); 154 | } 155 | 156 | /* Set ODR and performance */ 157 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 158 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 159 | 160 | /* Enable all axis */ 161 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 162 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 163 | 164 | if (rslt == BMM350_OK) 165 | { 166 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 167 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 168 | 169 | printf("\nCompensated Magnetometer and temperature data in NORMAL MODE\n"); 170 | 171 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 172 | 173 | /* Time in milliseconds */ 174 | time_ms = coines_get_millis(); 175 | 176 | for (loop = 0; loop < MAG_SAMPLE_COUNT;) 177 | { 178 | int_status = 0; 179 | 180 | /* Get data ready interrupt status */ 181 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 182 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 183 | 184 | /* Check if data ready interrupt occurred */ 185 | if ((rslt == BMM350_OK) && (int_status & BMM350_DRDY_DATA_REG_MSK)) 186 | { 187 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&get_mag_temp_data[loop], &dev); 188 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 189 | 190 | printf("%lu, %f, %f, %f, %f\n", 191 | (long unsigned int)(coines_get_millis() - time_ms), 192 | get_mag_temp_data[loop].x, 193 | get_mag_temp_data[loop].y, 194 | get_mag_temp_data[loop].z, 195 | get_mag_temp_data[loop].temperature); 196 | 197 | mean_mag_data.x += get_mag_temp_data[loop].x; 198 | mean_mag_data.y += get_mag_temp_data[loop].y; 199 | mean_mag_data.z += get_mag_temp_data[loop].z; 200 | 201 | loop++; 202 | } 203 | } 204 | 205 | /* Taking average values to calculate percentage deviation */ 206 | avg_mag_data.x = (double)(mean_mag_data.x / MAG_SAMPLE_COUNT); 207 | avg_mag_data.y = (double)(mean_mag_data.y / MAG_SAMPLE_COUNT); 208 | avg_mag_data.z = (double)(mean_mag_data.z / MAG_SAMPLE_COUNT); 209 | 210 | printf("\n***** AVERAGE MAG VALUE *****\n"); 211 | printf("Average_Mag_X(uT), Average_Mag_Y(uT), Average_Mag_Z(uT)\n"); 212 | 213 | printf("%lf, %lf, %lf\n", avg_mag_data.x, avg_mag_data.y, avg_mag_data.z); 214 | 215 | calculate_noise(get_mag_temp_data, avg_mag_data); 216 | 217 | /* Set ODR and performance */ 218 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_50HZ, BMM350_AVERAGING_8, &dev); 219 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 220 | 221 | rslt = bmm350_set_powermode(BMM350_SUSPEND_MODE, &dev); 222 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 223 | 224 | printf("\nCompensated Magnetometer and temperature data in SUSPEND MODE\n"); 225 | 226 | /* Time in milliseconds */ 227 | time_ms = coines_get_millis(); 228 | 229 | loop = 10; 230 | 231 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 232 | 233 | while (loop--) 234 | { 235 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 236 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 237 | 238 | printf("%lu, %f, %f, %f, %f\n", 239 | (long unsigned int)(coines_get_millis() - time_ms), 240 | mag_temp_data.x, 241 | mag_temp_data.y, 242 | mag_temp_data.z, 243 | mag_temp_data.temperature); 244 | } 245 | } 246 | 247 | /* Disable x and y axis, enable z axis */ 248 | rslt = bmm350_enable_axes(BMM350_X_DIS, BMM350_Y_DIS, BMM350_Z_EN, &dev); 249 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 250 | 251 | if (rslt == BMM350_OK) 252 | { 253 | rslt = bmm350_set_powermode(BMM350_NORMAL_MODE, &dev); 254 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 255 | 256 | printf("\nCompensated Magnetometer and temperature data in NORMAL MODE\n"); 257 | printf("Disable x and y axis, enable z axis\n\n"); 258 | 259 | /* Time in milliseconds */ 260 | time_ms = coines_get_millis(); 261 | 262 | loop = 20; 263 | 264 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 265 | 266 | while (loop) 267 | { 268 | int_status = 0; 269 | 270 | /* Get data ready interrupt status */ 271 | rslt = bmm350_get_regs(BMM350_REG_INT_STATUS, &int_status, 1, &dev); 272 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 273 | 274 | /* Check if data ready interrupt occurred */ 275 | if (int_status & BMM350_DRDY_DATA_REG_MSK) 276 | { 277 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 278 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 279 | 280 | printf("%lu, %f, %f, %f, %f\n", 281 | (long unsigned int)(coines_get_millis() - time_ms), 282 | mag_temp_data.x, 283 | mag_temp_data.y, 284 | mag_temp_data.z, 285 | mag_temp_data.temperature); 286 | 287 | loop--; 288 | } 289 | } 290 | } 291 | 292 | bmm350_coines_deinit(); 293 | 294 | return rslt; 295 | } 296 | 297 | /*! 298 | * @brief This internal API is to calculate noise level for mag data. 299 | */ 300 | static void calculate_noise(const struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_mag_data avg_mag_data) 301 | { 302 | double variance_x = 0, variance_y = 0, variance_z = 0; 303 | double noise_level_x, noise_level_y, noise_level_z; 304 | uint8_t index = 0; 305 | 306 | for (index = 0; index < MAG_SAMPLE_COUNT; index++) 307 | { 308 | variance_x += ((mag_temp_data[index].x - avg_mag_data.x) * (mag_temp_data[index].x - avg_mag_data.x)); 309 | 310 | variance_y += ((mag_temp_data[index].y - avg_mag_data.y) * (mag_temp_data[index].y - avg_mag_data.y)); 311 | 312 | variance_z += ((mag_temp_data[index].z - avg_mag_data.z) * (mag_temp_data[index].z - avg_mag_data.z)); 313 | } 314 | 315 | variance_x /= MAG_SAMPLE_COUNT; 316 | noise_level_x = sqrt(variance_x); 317 | 318 | variance_y /= MAG_SAMPLE_COUNT; 319 | noise_level_y = sqrt(variance_y); 320 | 321 | variance_z /= MAG_SAMPLE_COUNT; 322 | noise_level_z = sqrt(variance_z); 323 | 324 | printf("\nNoise level x, Noise level y, Noise level z\n"); 325 | 326 | printf("%lf, %lf, %lf\n", noise_level_x, noise_level_y, noise_level_z); 327 | } 328 | -------------------------------------------------------------------------------- /examples/bmm350_forced_mode/bmm350_forced_mode.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350_forced_mode.c 34 | * 35 | * @brief This file contains reading of magnetometer data in forced mode 36 | * with various combinations of ODR, average and delay. 37 | * 38 | */ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "bmm350.h" 46 | #include "common.h" 47 | #include "coines.h" 48 | 49 | /******************************************************************************/ 50 | /*! Macro Definitions */ 51 | 52 | #define MAG_SAMPLE_COUNT UINT8_C(100) 53 | 54 | /******************************************************************************/ 55 | /*! Static Structure Definitions */ 56 | 57 | /*! 58 | * @brief bmm350 compensated magnetometer data structure 59 | */ 60 | struct bmm350_mag_data 61 | { 62 | /*! Compensated mag X data */ 63 | double x; 64 | 65 | /*! Compensated mag Y data */ 66 | double y; 67 | 68 | /*! Compensated mag Z data */ 69 | double z; 70 | }; 71 | 72 | /******************************************************************************/ 73 | /*! Static Function Declaration */ 74 | 75 | /*! 76 | * @brief This internal API is to calculate noise level for mag data 77 | * 78 | * @param[in] mag_temp_data : Structure instance of bmm350_mag_temp_data. 79 | * @param[in] avg_mag_data : Structure to store average mag data. 80 | * 81 | * @return void. 82 | */ 83 | static void calculate_noise(const struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_mag_data avg_mag_data); 84 | 85 | /******************************************************************************/ 86 | /*! Functions */ 87 | 88 | /* This function starts the execution of program */ 89 | int main(void) 90 | { 91 | /* Status of api are returned to this variable */ 92 | int8_t rslt; 93 | 94 | /* Sensor initialization configuration */ 95 | struct bmm350_dev dev = { 0 }; 96 | 97 | uint8_t int_ctrl, err_reg_data = 0; 98 | uint8_t loop = 10, set_int_ctrl; 99 | uint32_t time_ms = 0; 100 | 101 | struct bmm350_mag_temp_data mag_temp_data = { 0 }; 102 | struct bmm350_pmu_cmd_status_0 pmu_cmd_stat_0 = { 0 }; 103 | struct bmm350_mag_temp_data get_mag_temp_data[MAG_SAMPLE_COUNT] = { { 0 } }; 104 | struct bmm350_mag_data mean_mag_data_1 = { 0 }; 105 | struct bmm350_mag_data mean_mag_data_2 = { 0 }; 106 | struct bmm350_mag_data mean_mag_data_3 = { 0 }; 107 | struct bmm350_mag_data avg_mag_data = { 0 }; 108 | 109 | /* Update device structure */ 110 | rslt = bmm350_interface_init(&dev); 111 | bmm350_error_codes_print_result("bmm350_interface_selection", rslt); 112 | 113 | /* Initialize BMM350 */ 114 | rslt = bmm350_init(&dev); 115 | bmm350_error_codes_print_result("bmm350_init", rslt); 116 | 117 | printf("Read : 0x00 : BMM350 Chip ID : 0x%X\n", dev.chip_id); 118 | 119 | /* Check PMU busy */ 120 | rslt = bmm350_get_pmu_cmd_status_0(&pmu_cmd_stat_0, &dev); 121 | bmm350_error_codes_print_result("bmm350_get_pmu_cmd_status_0", rslt); 122 | 123 | printf("Expected : 0x07 : PMU cmd busy : 0x0\n"); 124 | printf("Read : 0x07 : PMU cmd busy : 0x%X\n", pmu_cmd_stat_0.pmu_cmd_busy); 125 | 126 | /* Get error data */ 127 | rslt = bmm350_get_regs(BMM350_REG_ERR_REG, &err_reg_data, 1, &dev); 128 | bmm350_error_codes_print_result("bmm350_get_error_reg_data", rslt); 129 | 130 | printf("Expected : 0x02 : Error Register : 0x0\n"); 131 | printf("Read : 0x02 : Error Register : 0x%X\n", err_reg_data); 132 | 133 | /* Configure interrupt settings */ 134 | rslt = bmm350_configure_interrupt(BMM350_PULSED, 135 | BMM350_ACTIVE_HIGH, 136 | BMM350_INTR_PUSH_PULL, 137 | BMM350_UNMAP_FROM_PIN, 138 | &dev); 139 | bmm350_error_codes_print_result("bmm350_configure_interrupt", rslt); 140 | 141 | /* Enable data ready interrupt */ 142 | rslt = bmm350_enable_interrupt(BMM350_ENABLE_INTERRUPT, &dev); 143 | bmm350_error_codes_print_result("bmm350_enable_interrupt", rslt); 144 | 145 | /* Get interrupt settings */ 146 | rslt = bmm350_get_regs(BMM350_REG_INT_CTRL, &int_ctrl, 1, &dev); 147 | bmm350_error_codes_print_result("bmm350_get_regs", rslt); 148 | 149 | set_int_ctrl = ((BMM350_INT_POL_ACTIVE_HIGH << 1) | (BMM350_INT_OD_PUSHPULL << 2) | BMM350_ENABLE << 7); 150 | 151 | printf("Expected : 0x2E : Interrupt control : 0x%X\n", set_int_ctrl); 152 | printf("Read : 0x2E : Interrupt control : 0x%X\n", int_ctrl); 153 | 154 | if (int_ctrl & BMM350_DRDY_DATA_REG_EN_MSK) 155 | { 156 | printf("Data ready enabled\r\n"); 157 | } 158 | 159 | printf("Compensated Magnetometer and Temperature data in forced mode and forced mode fast\n"); 160 | 161 | printf("\nCOMBINATION 1 :\n"); 162 | printf("Set forced mode fast and read data with averaging between 4 samples\n"); 163 | 164 | /* Set ODR and performance */ 165 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 166 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 167 | 168 | /* Enable all axis */ 169 | rslt = bmm350_enable_axes(BMM350_X_EN, BMM350_Y_EN, BMM350_Z_EN, &dev); 170 | bmm350_error_codes_print_result("bmm350_enable_axes", rslt); 171 | 172 | if (rslt == BMM350_OK) 173 | { 174 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE_FAST, &dev); 175 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 176 | 177 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 178 | 179 | /* Time in milliseconds */ 180 | time_ms = coines_get_millis(); 181 | 182 | while (loop) 183 | { 184 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 185 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 186 | 187 | printf("%lu, %f, %f, %f, %f\n", 188 | (long unsigned int)(coines_get_millis() - time_ms), 189 | mag_temp_data.x, 190 | mag_temp_data.y, 191 | mag_temp_data.z, 192 | mag_temp_data.temperature); 193 | 194 | loop--; 195 | } 196 | 197 | loop = 10; 198 | 199 | printf("\nCOMBINATION 2 :\n"); 200 | printf("Set forced mode fast and read data with averaging between 4 samples in a loop\n"); 201 | 202 | /* Set ODR and performance */ 203 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 204 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 205 | 206 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 207 | 208 | /* Time in milliseconds */ 209 | time_ms = coines_get_millis(); 210 | 211 | while (loop--) 212 | { 213 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE_FAST, &dev); 214 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 215 | 216 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 217 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 218 | 219 | printf("%lu, %f, %f, %f, %f\n", 220 | (long unsigned int)(coines_get_millis() - time_ms), 221 | mag_temp_data.x, 222 | mag_temp_data.y, 223 | mag_temp_data.z, 224 | mag_temp_data.temperature); 225 | } 226 | 227 | loop = 10; 228 | 229 | printf("\nCOMBINATION 3 :\n"); 230 | printf("Set forced mode and read data with no averaging between samples in a loop\n"); 231 | 232 | /* Set ODR and performance */ 233 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_NO_AVERAGING, &dev); 234 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 235 | 236 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 237 | 238 | /* Time in milliseconds */ 239 | time_ms = coines_get_millis(); 240 | 241 | while (loop--) 242 | { 243 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE, &dev); 244 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 245 | 246 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&mag_temp_data, &dev); 247 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 248 | 249 | printf("%lu, %f, %f, %f, %f\n", 250 | (long unsigned int)(coines_get_millis() - time_ms), 251 | mag_temp_data.x, 252 | mag_temp_data.y, 253 | mag_temp_data.z, 254 | mag_temp_data.temperature); 255 | } 256 | 257 | printf("\nCOMBINATION 4 :\n"); 258 | printf("Set forced mode fast and read data with averaging between 4 samples in a loop\n"); 259 | 260 | /* Set ODR and performance */ 261 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_4, &dev); 262 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 263 | 264 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 265 | 266 | /* Time in milliseconds */ 267 | time_ms = coines_get_millis(); 268 | 269 | for (loop = 0; loop < MAG_SAMPLE_COUNT;) 270 | { 271 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE_FAST, &dev); 272 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 273 | 274 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&get_mag_temp_data[loop], &dev); 275 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 276 | 277 | printf("%lu, %f, %f, %f, %f\n", 278 | (long unsigned int)(coines_get_millis() - time_ms), 279 | get_mag_temp_data[loop].x, 280 | get_mag_temp_data[loop].y, 281 | get_mag_temp_data[loop].z, 282 | get_mag_temp_data[loop].temperature); 283 | 284 | mean_mag_data_1.x += get_mag_temp_data[loop].x; 285 | mean_mag_data_1.y += get_mag_temp_data[loop].y; 286 | mean_mag_data_1.z += get_mag_temp_data[loop].z; 287 | 288 | loop++; 289 | } 290 | 291 | /* Taking average values to calculate percentage deviation */ 292 | avg_mag_data.x = (double)(mean_mag_data_1.x / MAG_SAMPLE_COUNT); 293 | avg_mag_data.y = (double)(mean_mag_data_1.y / MAG_SAMPLE_COUNT); 294 | avg_mag_data.z = (double)(mean_mag_data_1.z / MAG_SAMPLE_COUNT); 295 | 296 | printf("***** AVERAGE MAG VALUE *****\n"); 297 | printf("Average_Mag_X(uT), Average_Mag_Y(uT), Average_Mag_Z(uT)\n"); 298 | 299 | printf("%lf, %lf, %lf\n", avg_mag_data.x, avg_mag_data.y, avg_mag_data.z); 300 | 301 | calculate_noise(get_mag_temp_data, avg_mag_data); 302 | 303 | printf("\nCOMBINATION 5 :\n"); 304 | printf("Set forced mode and read data with no averaging between samples in a loop\n"); 305 | 306 | /* Set ODR and performance */ 307 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_NO_AVERAGING, &dev); 308 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 309 | 310 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 311 | 312 | /* Time in milliseconds */ 313 | time_ms = coines_get_millis(); 314 | 315 | for (loop = 0; loop < MAG_SAMPLE_COUNT;) 316 | { 317 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE, &dev); 318 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 319 | 320 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&get_mag_temp_data[loop], &dev); 321 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 322 | 323 | printf("%lu, %f, %f, %f, %f\n", 324 | (long unsigned int)(coines_get_millis() - time_ms), 325 | get_mag_temp_data[loop].x, 326 | get_mag_temp_data[loop].y, 327 | get_mag_temp_data[loop].z, 328 | get_mag_temp_data[loop].temperature); 329 | 330 | mean_mag_data_2.x += get_mag_temp_data[loop].x; 331 | mean_mag_data_2.y += get_mag_temp_data[loop].y; 332 | mean_mag_data_2.z += get_mag_temp_data[loop].z; 333 | 334 | loop++; 335 | } 336 | 337 | /* Taking average values to calculate percentage deviation */ 338 | avg_mag_data.x = (double)(mean_mag_data_2.x / MAG_SAMPLE_COUNT); 339 | avg_mag_data.y = (double)(mean_mag_data_2.y / MAG_SAMPLE_COUNT); 340 | avg_mag_data.z = (double)(mean_mag_data_2.z / MAG_SAMPLE_COUNT); 341 | 342 | printf("***** AVERAGE MAG VALUE *****\n"); 343 | printf("Average_Mag_X(uT), Average_Mag_Y(uT), Average_Mag_Z(uT)\n"); 344 | 345 | printf("%lf, %lf, %lf\n", avg_mag_data.x, avg_mag_data.y, avg_mag_data.z); 346 | 347 | calculate_noise(get_mag_temp_data, avg_mag_data); 348 | 349 | printf("\nCOMBINATION 6 :\n"); 350 | printf("Set forced mode fast and read data with averaging between 2 samples in a loop\n"); 351 | 352 | /* Set ODR and performance */ 353 | rslt = bmm350_set_odr_performance(BMM350_DATA_RATE_100HZ, BMM350_AVERAGING_2, &dev); 354 | bmm350_error_codes_print_result("bmm350_set_odr_performance", rslt); 355 | 356 | printf("Timestamp(ms), Mag_X(uT), Mag_Y(uT), Mag_Z(uT), Temperature(degC)\n"); 357 | 358 | /* Time in milliseconds */ 359 | time_ms = coines_get_millis(); 360 | 361 | for (loop = 0; loop < MAG_SAMPLE_COUNT;) 362 | { 363 | rslt = bmm350_set_powermode(BMM350_FORCED_MODE_FAST, &dev); 364 | bmm350_error_codes_print_result("bmm350_set_powermode", rslt); 365 | 366 | rslt = bmm350_get_compensated_mag_xyz_temp_data(&get_mag_temp_data[loop], &dev); 367 | bmm350_error_codes_print_result("bmm350_get_compensated_mag_xyz_temp_data", rslt); 368 | 369 | printf("%lu, %f, %f, %f, %f\n", 370 | (long unsigned int)(coines_get_millis() - time_ms), 371 | get_mag_temp_data[loop].x, 372 | get_mag_temp_data[loop].y, 373 | get_mag_temp_data[loop].z, 374 | get_mag_temp_data[loop].temperature); 375 | 376 | mean_mag_data_3.x += get_mag_temp_data[loop].x; 377 | mean_mag_data_3.y += get_mag_temp_data[loop].y; 378 | mean_mag_data_3.z += get_mag_temp_data[loop].z; 379 | 380 | loop++; 381 | } 382 | 383 | /* Taking average values to calculate percentage deviation */ 384 | avg_mag_data.x = (double)(mean_mag_data_3.x / MAG_SAMPLE_COUNT); 385 | avg_mag_data.y = (double)(mean_mag_data_3.y / MAG_SAMPLE_COUNT); 386 | avg_mag_data.z = (double)(mean_mag_data_3.z / MAG_SAMPLE_COUNT); 387 | 388 | printf("***** AVERAGE MAG VALUE *****\n"); 389 | printf("Average_Mag_X(uT), Average_Mag_Y(uT), Average_Mag_Z(uT)\n"); 390 | 391 | printf("%lf, %lf, %lf\n", avg_mag_data.x, avg_mag_data.y, avg_mag_data.z); 392 | 393 | calculate_noise(get_mag_temp_data, avg_mag_data); 394 | } 395 | 396 | bmm350_coines_deinit(); 397 | 398 | return rslt; 399 | } 400 | 401 | /*! 402 | * @brief This internal API is to calculate noise level for mag data. 403 | */ 404 | static void calculate_noise(const struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_mag_data avg_mag_data) 405 | { 406 | double variance_x = 0, variance_y = 0, variance_z = 0; 407 | double noise_level_x, noise_level_y, noise_level_z; 408 | uint8_t index = 0; 409 | 410 | for (index = 0; index < MAG_SAMPLE_COUNT; index++) 411 | { 412 | variance_x += ((mag_temp_data[index].x - avg_mag_data.x) * (mag_temp_data[index].x - avg_mag_data.x)); 413 | 414 | variance_y += ((mag_temp_data[index].y - avg_mag_data.y) * (mag_temp_data[index].y - avg_mag_data.y)); 415 | 416 | variance_z += ((mag_temp_data[index].z - avg_mag_data.z) * (mag_temp_data[index].z - avg_mag_data.z)); 417 | } 418 | 419 | variance_x /= MAG_SAMPLE_COUNT; 420 | noise_level_x = sqrt(variance_x) * 1000; 421 | 422 | variance_y /= MAG_SAMPLE_COUNT; 423 | noise_level_y = sqrt(variance_y) * 1000; 424 | 425 | variance_z /= MAG_SAMPLE_COUNT; 426 | noise_level_z = sqrt(variance_z) * 1000; 427 | 428 | printf("\nNoise level x (nTrms), Noise level y (nTrms), Noise level z (nTrms)\n"); 429 | 430 | printf("%lf, %lf, %lf\n", noise_level_x, noise_level_y, noise_level_z); 431 | } 432 | -------------------------------------------------------------------------------- /bmm350.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2023 Bosch Sensortec GmbH. All rights reserved. 3 | * 4 | * BSD-3-Clause 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * 3. Neither the name of the copyright holder nor the names of its 17 | * contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | * 33 | * @file bmm350.h 34 | * @date 2023-05-26 35 | * @version v1.4.0 36 | * 37 | */ 38 | 39 | /*! 40 | * @defgroup bmm350 BMM350 41 | * @brief Sensor driver for BMM350 sensor 42 | */ 43 | 44 | #ifndef _BMM350_H 45 | #define _BMM350_H 46 | 47 | /*! CPP guard */ 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | /*************************** Header files *******************************/ 53 | 54 | #include "bmm350_defs.h" 55 | 56 | /******************* Function prototype declarations ********************/ 57 | 58 | /** 59 | * \ingroup bmm350 60 | * \defgroup bmm350ApiInit Initialization 61 | * @brief Initialize the sensor and device structure 62 | */ 63 | 64 | /*! 65 | * \ingroup bmm350ApiInit 66 | * \page bmm350_api_bmm350_init bmm350_init 67 | * \code 68 | * int8_t bmm350_init(struct bmm350_dev *dev); 69 | * \endcode 70 | * @details This API is the entry point. Call this API before using other APIs. 71 | * This API reads the chip-id of the sensor which is the first step to 72 | * verify the sensor and also it configures the read mechanism of I2C and 73 | * I3C interface. 74 | * 75 | * @param[in,out] dev : Structure instance of bmm350_dev 76 | * 77 | * @return Result of API execution status 78 | * @retval = 0 -> Success 79 | * @retval < 0 -> Error 80 | */ 81 | int8_t bmm350_init(struct bmm350_dev *dev); 82 | 83 | /** 84 | * \ingroup bmm350 85 | * \defgroup bmm350ApiReset Reset 86 | * @brief Reset APIs 87 | */ 88 | 89 | /*! 90 | * \ingroup bmm350ApiReset 91 | * \page bmm350_api_bmm350_soft_reset bmm350_soft_reset 92 | * \code 93 | * int8_t bmm350_soft_reset(struct bmm350_dev *dev); 94 | * \endcode 95 | * @details This API is used to perform soft-reset of the sensor 96 | * where all the registers are reset to their default values. 97 | * 98 | * @param[in] dev : Structure instance of bmm350_dev. 99 | * 100 | * @return Result of API execution status 101 | * @retval = 0 -> Success 102 | * @retval < 0 -> Error 103 | */ 104 | 105 | int8_t bmm350_soft_reset(struct bmm350_dev *dev); 106 | 107 | /** 108 | * \ingroup bmm350 109 | * \defgroup bmm350ApiSetGet Set-Get 110 | * @brief Set and Get APIs 111 | */ 112 | 113 | /*! 114 | * \ingroup bmm350ApiSetGet 115 | * \page bmm350_api_bmm350_set_regs bmm350_set_regs 116 | * \code 117 | * int8_t bmm350_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev); 118 | * \endcode 119 | * @details This API writes the given data to the register address 120 | * of the sensor. 121 | * 122 | * @param[in] reg_addr : Register address from where the data to be written. 123 | * @param[in] reg_data : Pointer to data buffer which is to be written 124 | * in the reg_addr of sensor. 125 | * @param[in] len : No of bytes of data to write.. 126 | * @param[in, out] dev : Structure instance of bmm350_dev. 127 | * 128 | * @return Result of API execution status 129 | * @retval = 0 -> Success 130 | * @retval < 0 -> Error 131 | */ 132 | int8_t bmm350_set_regs(uint8_t reg_addr, const uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev); 133 | 134 | /*! 135 | * \ingroup bmm350ApiSetGet 136 | * \page bmm350_api_bmm350_get_regs bmm350_get_regs 137 | * \code 138 | * int8_t bmm350_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev); 139 | * \endcode 140 | * @details This API reads the data from the given register address of sensor. 141 | * 142 | * @param[in] reg_addr : Register address from where the data to be read 143 | * @param[out] reg_data : Pointer to data buffer to store the read data. 144 | * @param[in] len : No of bytes of data to be read. 145 | * @param[in] dev : Structure instance of bmm350_dev. 146 | * 147 | * @return Result of API execution status 148 | * @retval = 0 -> Success 149 | * @retval < 0 -> Error 150 | */ 151 | int8_t bmm350_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint16_t len, struct bmm350_dev *dev); 152 | 153 | /** 154 | * \ingroup bmm350 155 | * \defgroup bmm350ApiDelay Delay 156 | * @brief Delay function in microseconds 157 | */ 158 | 159 | /*! 160 | * \ingroup bmm350ApiDelay 161 | * \page bmm350_api_bmm350_delay_us bmm350_delay_us 162 | * \code 163 | * int8_t bmm350_delay_us(uint32_t period_us, const struct bmm350_dev *dev); 164 | * \endcode 165 | * @details This function provides the delay for required time (Microsecond) as per the input provided in some of the 166 | * APIs. 167 | * 168 | * @param[in] period_us : The required wait time in microsecond. 169 | * @param[in] dev : Structure instance of bmm350_dev. 170 | * 171 | * @return Result of API execution status 172 | * @retval = 0 -> Success 173 | * @retval < 0 -> Error 174 | */ 175 | int8_t bmm350_delay_us(uint32_t period_us, const struct bmm350_dev *dev); 176 | 177 | /*! 178 | * \ingroup bmm350ApiSetGet 179 | * \page bmm350_api_bmm350_get_interrupt_status bmm350_get_interrupt_status 180 | * \code 181 | * int8_t bmm350_get_interrupt_status(uint8_t *drdy_status, struct bmm350_dev *dev); 182 | * \endcode 183 | * @details This API obtains the status flags of all interrupt 184 | * which is used to check for the assertion of interrupts 185 | * 186 | * @param[in,out] drdy_status : Variable to store data ready interrupt status. 187 | * @param[in,out] dev : Structure instance of bmm350_dev. 188 | * 189 | * 190 | * @return Result of API execution status and self test result. 191 | * @retval = 0 -> Success 192 | * @retval < 0 -> Error 193 | */ 194 | int8_t bmm350_get_interrupt_status(uint8_t *drdy_status, struct bmm350_dev *dev); 195 | 196 | /*! 197 | * \ingroup bmm350ApiSetGet 198 | * \page bmm350_api_bmm350_set_powermode bmm350_set_powermode 199 | * \code 200 | * int8_t bmm350_set_powermode(enum bmm350_power_modes powermode, struct bmm350_dev *dev); 201 | * \endcode 202 | * @details This API is used to set the power mode of the sensor 203 | * 204 | * @param[in] powermode : Set power mode 205 | * @param[in] dev : Structure instance of bmm350_dev. 206 | * 207 | *@verbatim 208 | powermode | Power mode 209 | -------------------------|----------------------- 210 | | BMM350_SUSPEND_MODE 211 | | BMM350_NORMAL_MODE 212 | | BMM350_FORCED_MODE 213 | | BMM350_FORCED_MODE_FAST 214 | *@endverbatim 215 | * 216 | * @return Result of API execution status 217 | * @retval = 0 -> Success 218 | * @retval < 0 -> Error 219 | */ 220 | int8_t bmm350_set_powermode(enum bmm350_power_modes powermode, struct bmm350_dev *dev); 221 | 222 | /*! 223 | * \ingroup bmm350ApiSetGet 224 | * \page bmm350_api_bmm350_set_odr_performance bmm350_set_odr_performance 225 | * \code 226 | * int8_t bmm350_set_odr_performance(enum bmm350_data_rates odr, 227 | * enum bmm350_performance_parameters avg, 228 | * struct bmm350_dev *dev); 229 | * 230 | * \endcode 231 | * @details This API sets the ODR and averaging factor. 232 | * If ODR and performance is a combination which is not allowed, then 233 | * the combination setting is corrected to the next lower possible setting 234 | * 235 | * @param[in] odr : enum bmm350_data_rates 236 | * 237 | *@verbatim 238 | Data rate (ODR) | odr 239 | -------------------------|----------------------- 240 | 400Hz | BMM350_DATA_RATE_400HZ 241 | 200Hz | BMM350_DATA_RATE_200HZ 242 | 100Hz | BMM350_DATA_RATE_100HZ 243 | 50Hz | BMM350_DATA_RATE_50HZ 244 | 25Hz | BMM350_DATA_RATE_25HZ 245 | 12.5Hz | BMM350_DATA_RATE_12_5HZ 246 | 6.25Hz | BMM350_DATA_RATE_6_25HZ 247 | 3.125Hz | BMM350_DATA_RATE_3_125HZ 248 | 1.5625Hz | BMM350_DATA_RATE_1_5625HZ 249 | *@endverbatim 250 | * 251 | * @param[in] avg : enum bmm350_performance_parameters 252 | * 253 | *@verbatim 254 | avg | averaging factor alias 255 | ---------------------------|------------------------------------------ 256 | low power/highest noise | BMM350_NO_AVERAGING BMM350_LOWPOWER 257 | lesser noise | BMM350_AVERAGING_2 BMM350_REGULARPOWER 258 | even lesser noise | BMM350_AVERAGING_4 BMM350_LOWNOISE 259 | lowest noise/highest power | BMM350_AVERAGING_8 BMM350_ULTRALOWNOISE 260 | *@endverbatim 261 | * 262 | * @param[in,out] dev : Structure instance of bmm350_dev 263 | * 264 | * @return Result of API execution status 265 | * @retval = 0 -> Success 266 | * @retval < 0 -> Error 267 | */ 268 | int8_t bmm350_set_odr_performance(enum bmm350_data_rates odr, 269 | enum bmm350_performance_parameters avg, 270 | struct bmm350_dev *dev); 271 | 272 | /*! 273 | * \ingroup bmm350ApiSetGet 274 | * \page bmm350_api_bmm350_enable_axes bmm350_enable_axes 275 | * \code 276 | * int8_t bmm350_enable_axes(enum bmm350_x_axis_en_dis en_x, enum bmm350_y_axis_en_dis en_y, enum bmm350_z_axis_en_dis en_z, struct bmm350_dev *dev); 277 | * \endcode 278 | * @details This API is used to enable or disable the magnetic 279 | * measurement of x,y,z axes 280 | * 281 | * @param[in] en_x : Enable or disable X axis 282 | * @param[in] en_y : Enable or disable Y axis 283 | * @param[in] en_z : Enable or disable Z axis 284 | * @param[in,out] dev : Structure instance of bmm350_dev. 285 | * 286 | *@verbatim 287 | Value | Axis (en_x, en_y, en_z) 288 | -------------------|----------------------- 289 | BMM350_ENABLE | Enabled 290 | BMM350_DISABLE | Disabled 291 | *@endverbatim 292 | * 293 | * @return Result of API execution status 294 | * @retval = 0 -> Success 295 | * @retval < 0 -> Error 296 | */ 297 | int8_t bmm350_enable_axes(enum bmm350_x_axis_en_dis en_x, 298 | enum bmm350_y_axis_en_dis en_y, 299 | enum bmm350_z_axis_en_dis en_z, 300 | struct bmm350_dev *dev); 301 | 302 | /** 303 | * \ingroup bmm350 304 | * \defgroup bmm350ApiRead Sensortime 305 | * @brief Reads sensortime 306 | */ 307 | 308 | /*! 309 | * \ingroup bmm350ApiRead 310 | * \page bmm350_api_bmm350_read_sensortime bmm350_read_sensortime 311 | * \code 312 | * int8_t bmm350_read_sensortime(uint32_t *seconds, uint32_t *nanoseconds, struct bmm350_dev *dev); 313 | * \endcode 314 | * @details This API is used to read the sensor time. 315 | * It converts the sensor time register values to the representative time value. 316 | * Returns the sensor time in ticks. 317 | * 318 | * @param[out] seconds : Variable to get sensor time in seconds. 319 | * @param[out] nanoseconds : Variable to get sensor time in nanoseconds. 320 | * @param[in] dev : Structure instance of bmm350_dev. 321 | * 322 | * @return Result of API execution status 323 | * @retval = 0 -> Success 324 | * @retval < 0 -> Error 325 | */ 326 | int8_t bmm350_read_sensortime(uint32_t *seconds, uint32_t *nanoseconds, struct bmm350_dev *dev); 327 | 328 | /** 329 | * \ingroup bmm350 330 | * \defgroup bmm350ApiInterrupt Enable Interrupt 331 | * @brief Interrupt enable APIs 332 | */ 333 | 334 | /*! 335 | * \ingroup bmm350ApiInterrupt 336 | * \page bmm350_api_bmm350_enable_interrupt bmm350_enable_interrupt 337 | * \code 338 | * int8_t bmm350_enable_interrupt(enum bmm350_interrupt_enable_disable enable_disable, struct bmm350_dev *dev); 339 | * \endcode 340 | * @details This API is used to enable or disable the data ready interrupt 341 | * 342 | * @param[in] enable_disable : Enable/ Disable data ready interrupt. 343 | * @param[in] dev : Structure instance of bmm350_dev. 344 | * 345 | * @return Result of API execution status 346 | * @retval = 0 -> Success 347 | * @retval < 0 -> Error 348 | */ 349 | int8_t bmm350_enable_interrupt(enum bmm350_interrupt_enable_disable enable_disable, struct bmm350_dev *dev); 350 | 351 | /*! 352 | * \ingroup bmm350ApiInterrupt 353 | * \page bmm350_api_bmm350_configure_interrupt bmm350_configure_interrupt 354 | * \code 355 | * int8_t bmm350_configure_interrupt(enum bmm350_intr_latch latching, 356 | * enum bmm350_intr_polarity polarity, 357 | * enum bmm350_intr_drive drivertype, 358 | * enum bmm350_intr_map map_nomap, 359 | * struct bmm350_dev *dev); 360 | * \endcode 361 | * @details This API is used to configure the interrupt control settings. 362 | * 363 | * @param[in] latching : Sets either latched or pulsed. 364 | * @param[in] polarity : Sets either polarity high or low. 365 | * @param[in] drivertype : Sets either open drain or push pull. 366 | * @param[in] map_nomap : Sets either map or unmap the pins. 367 | * @param[in] dev : Structure instance of bmm350_dev. 368 | * 369 | * @return Result of API execution status 370 | * @retval = 0 -> Success 371 | * @retval < 0 -> Error 372 | */ 373 | int8_t bmm350_configure_interrupt(enum bmm350_intr_latch latching, 374 | enum bmm350_intr_polarity polarity, 375 | enum bmm350_intr_drive drivertype, 376 | enum bmm350_intr_map map_nomap, 377 | struct bmm350_dev *dev); 378 | 379 | /** 380 | * \ingroup bmm350 381 | * \defgroup bmm350ApiUncompMag Uncompensated mag 382 | * @brief Reads uncompensated mag and temperature data 383 | */ 384 | 385 | /*! 386 | * \ingroup bmm350ApiUncompMag 387 | * \page bmm350_api_bmm350_read_uncomp_mag_temp_data bmm350_read_uncomp_mag_temp_data 388 | * \code 389 | * int8_t bmm350_read_uncomp_mag_temp_data(struct bmm350_raw_mag_data *raw_data, struct bmm350_dev *dev); 390 | * \endcode 391 | * @details This API is used to read uncompensated mag and temperature data 392 | * 393 | * @param[in, out] raw_data : Structure instance of bmm350_raw_mag_data. 394 | * @param[in, out] dev : Structure instance of bmm350_dev. 395 | * 396 | * @return Result of API execution status 397 | * @retval = 0 -> Success 398 | * @retval < 0 -> Error 399 | */ 400 | int8_t bmm350_read_uncomp_mag_temp_data(struct bmm350_raw_mag_data *raw_data, struct bmm350_dev *dev); 401 | 402 | /*! 403 | * \ingroup bmm350ApiSetGet 404 | * \page bmm350_api_bmm350_set_int_ctrl_ibi bmm350_set_int_ctrl_ibi 405 | * \code 406 | * int8_t bmm350_set_int_ctrl_ibi(enum bmm350_drdy_int_map_to_ibi en_dis, 407 | * enum bmm350_clear_drdy_int_status_upon_ibi clear_on_ibi, struct bmm350_dev *dev); 408 | * \endcode 409 | * @details This API sets the interrupt control IBI configurations to the sensor. 410 | * And enables conventional interrupt if IBI is enabled. 411 | * 412 | * @param[in] en_dis : Sets either enable or disable IBI. 413 | * @param[in] clear_on_ibi : sets either clear or no clear on IBI. 414 | * @param[in] dev : Structure instance of bmm350_dev. 415 | * 416 | * @return Result of API execution status 417 | * @retval = 0 -> Success 418 | * @retval < 0 -> Error 419 | */ 420 | int8_t bmm350_set_int_ctrl_ibi(enum bmm350_drdy_int_map_to_ibi en_dis, 421 | enum bmm350_clear_drdy_int_status_upon_ibi clear_on_ibi, 422 | struct bmm350_dev *dev); 423 | 424 | /*! 425 | * \ingroup bmm350ApiSetGet 426 | * \page bmm350_api_bmm350_set_pad_drive bmm350_set_pad_drive 427 | * \code 428 | * int8_t bmm350_set_pad_drive(uint8_t drive, struct bmm350_dev *dev); 429 | * \endcode 430 | * @details This API is used to set the pad drive strength 431 | * 432 | * @param[in] drive : Drive settings, range 0 (weak) ..7(strong) 433 | * @param[in] dev : Structure instance of bmm350_dev. 434 | * 435 | * @return Result of API execution status 436 | * @retval = 0 -> Success 437 | * @retval < 0 -> Error 438 | */ 439 | int8_t bmm350_set_pad_drive(uint8_t drive, struct bmm350_dev *dev); 440 | 441 | /*! 442 | * \ingroup bmm350ApiReset 443 | * \page bmm350_api_bmm350_magnetic_reset_and_wait bmm350_magnetic_reset_and_wait 444 | * \code 445 | * int8_t bmm350_magnetic_reset_and_wait(struct bmm350_dev *dev) 446 | * \endcode 447 | * @details This API is used to perform the magnetic reset of the sensor 448 | * which is necessary after a field shock (400mT field applied to sensor). 449 | * It sends flux guide or bit reset to the device in suspend mode. 450 | * 451 | * @param[in] dev : Structure instance of bmm350_dev. 452 | * 453 | * @return Result of API execution status 454 | * @retval = 0 -> Success 455 | * @retval < 0 -> Error 456 | */ 457 | int8_t bmm350_magnetic_reset_and_wait(struct bmm350_dev *dev); 458 | 459 | /** 460 | * \ingroup bmm350 461 | * \defgroup bmm350ApiMagComp Compensation 462 | * @brief Compensation for mag x,y,z axis and temperature API 463 | */ 464 | 465 | /*! 466 | * \ingroup bmm350ApiMagComp 467 | * \page bmm350_api_bmm350_get_compensated_mag_xyz_temp_data bmm350_get_compensated_mag_xyz_temp_data 468 | * \code 469 | * int8_t bmm350_get_compensated_mag_xyz_temp_data(struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_dev *dev); 470 | * \endcode 471 | * @details This API is used to perform compensation for raw magnetometer and temperature data. 472 | * 473 | * @param[out] mag_temp_data : Structure instance of bmm350_mag_temp_data. 474 | * @param[in] dev : Structure instance of bmm350_dev. 475 | * 476 | * @return Result of API execution status 477 | * @retval = 0 -> Success 478 | * @retval < 0 -> Error 479 | */ 480 | int8_t bmm350_get_compensated_mag_xyz_temp_data(struct bmm350_mag_temp_data *mag_temp_data, struct bmm350_dev *dev); 481 | 482 | /** 483 | * \ingroup bmm350 484 | * \defgroup bmm350ApiSelftest Self-test 485 | * @brief Perform self-test for x and y axis 486 | */ 487 | 488 | /*! 489 | * \ingroup bmm350ApiSelftest 490 | * \page bmm350_api_bmm350_perform_self_test bmm350_perform_self_test 491 | * \code 492 | * int8_t bmm350_perform_self_test(struct bmm350_self_test *out_data, struct bmm350_dev *dev); 493 | * \endcode 494 | * @details This API executes FGR and BR sequences to initialize TMR sensor and performs self-test for x and y axis. 495 | * 496 | * @param[in, out] out_data : Structure instance of bmm350_self_test. 497 | * @param[in] dev : Structure instance of bmm350_dev. 498 | * 499 | * @return Result of API execution status 500 | * @retval = 0 -> Success 501 | * @retval < 0 -> Error 502 | */ 503 | int8_t bmm350_perform_self_test(struct bmm350_self_test *out_data, struct bmm350_dev *dev); 504 | 505 | /*! 506 | * \ingroup bmm350ApiSetGet 507 | * \page bmm350_api_bmm350_set_i2c_wdt bmm350_set_i2c_wdt 508 | * \code 509 | * int8_t bmm350_set_i2c_wdt(enum bmm350_i2c_wdt_en i2c_wdt_en_dis, enum bmm350_i2c_wdt_sel i2c_wdt_sel, 510 | * struct bmm350_dev *dev); 511 | * \endcode 512 | * @details This API sets the I2C watchdog timer configurations to the sensor. 513 | * 514 | * @param[in] i2c_wdt_en_dis : Enable/ Disable I2C watchdog timer. 515 | * @param[in] i2c_wdt_sel : I2C watchdog timer selection period. 516 | * @param[in] dev : Structure instance of bmm350_dev. 517 | * 518 | * @return Result of API execution status 519 | * @retval = 0 -> Success 520 | * @retval < 0 -> Error 521 | */ 522 | int8_t bmm350_set_i2c_wdt(enum bmm350_i2c_wdt_en i2c_wdt_en_dis, 523 | enum bmm350_i2c_wdt_sel i2c_wdt_sel, 524 | struct bmm350_dev *dev); 525 | 526 | /*! 527 | * \ingroup bmm350ApiSetGet 528 | * \page bmm350_api_bmm350_set_tmr_selftest_user bmm350_set_tmr_selftest_user 529 | * \code 530 | * int8_t bmm350_set_tmr_selftest_user(enum bmm350_st_igen_en st_igen_en_dis, 531 | * enum bmm350_st_n st_n_en_dis, 532 | * enum bmm350_st_p st_p_en_dis, 533 | * enum bmm350_ist_en_x ist_x_en_dis, 534 | * enum bmm350_ist_en_y ist_y_en_dis, 535 | * struct bmm350_dev *dev); 536 | * \endcode 537 | * @details This API sets the TMR user self-test register 538 | * 539 | * @param[in] st_igen_en_dis : Enable/ Disable self-test internal current gen. 540 | * @param[in] st_n_en_dis : Enable/ Disable dc_st_n signal. 541 | * @param[in] st_p_en_dis : Enable/ Disable dc_st_p signal. 542 | * @param[in] ist_x_en_dis : Enable/ Disable dc_ist_en_x signal. 543 | * @param[in] ist_y_en_dis : Enable/ Disable dc_ist_en_y signal. 544 | * @param[in] dev : Structure instance of bmm350_dev. 545 | * 546 | * @return Result of API execution status 547 | * @retval = 0 -> Success 548 | * @retval < 0 -> Error 549 | */ 550 | int8_t bmm350_set_tmr_selftest_user(enum bmm350_st_igen_en st_igen_en_dis, 551 | enum bmm350_st_n st_n_en_dis, 552 | enum bmm350_st_p st_p_en_dis, 553 | enum bmm350_ist_en_x ist_x_en_dis, 554 | enum bmm350_ist_en_y ist_y_en_dis, 555 | struct bmm350_dev *dev); 556 | 557 | /*! 558 | * \ingroup bmm350ApiSetGet 559 | * \page bmm350_api_bmm350_set_ctrl_user bmm350_set_ctrl_user 560 | * \code 561 | * int8_t bmm350_set_ctrl_user(enum bmm350_ctrl_user cfg_sens_tim_aon_en_dis, struct bmm350_dev *dev); 562 | * \endcode 563 | * @details This API sets the control user configurations to the sensor. 564 | * 565 | * @param[in] cfg_sens_tim_aon_en_dis : Enable/ Disable configuration of sensor time to run on suspend mode. 566 | * @param[in] dev : Structure instance of bmm350_dev. 567 | * 568 | * @return Result of API execution status 569 | * @retval = 0 -> Success 570 | * @retval < 0 -> Error 571 | */ 572 | int8_t bmm350_set_ctrl_user(enum bmm350_ctrl_user cfg_sens_tim_aon_en_dis, struct bmm350_dev *dev); 573 | 574 | /*! 575 | * \ingroup bmm350ApiSetGet 576 | * \page bmm350_api_bmm350_get_pmu_cmd_status_0 bmm350_get_pmu_cmd_status_0 577 | * \code 578 | * int8_t bmm350_get_pmu_cmd_status_0(struct bmm350_pmu_cmd_status_0 *pmu_cmd_stat_0, struct bmm350_dev *dev); 579 | * \endcode 580 | * @details This API gets the PMU command status 0 value. 581 | * 582 | * @param[out] pmu_cmd_stat_0 : Structure instance of bmm350_pmu_cmd_status_0. 583 | * @param[in] dev : Structure instance of bmm350_dev. 584 | * 585 | * @return Result of API execution status 586 | * @retval = 0 -> Success 587 | * @retval < 0 -> Error 588 | */ 589 | int8_t bmm350_get_pmu_cmd_status_0(struct bmm350_pmu_cmd_status_0 *pmu_cmd_stat_0, struct bmm350_dev *dev); 590 | 591 | #ifdef __cplusplus 592 | } 593 | #endif /* End of CPP guard */ 594 | 595 | #endif /* _BMM350_H */ 596 | --------------------------------------------------------------------------------