Christian Dupaty 03/2021 Library and demo for BMM150 see datasheet here : https://www.bosch-sensortec.com/products/motion-sensors/magnetometers-bmm150/ Adaptation of BOSCH driver https://github.com/BoschSensortec/BMM150-Sensor-API for ARM MBED and tested on NUCLEO-L073RZ and GEOMAGNETIC CLICK https://www.mikroe.com/geomagnetic-click
Dependents: BMM150_HelloWorld2
bmm150.cpp@1:9651fd7ee8f6, 2021-03-25 (annotated)
- Committer:
- cdupaty
- Date:
- Thu Mar 25 13:08:05 2021 +0000
- Revision:
- 1:9651fd7ee8f6
- Parent:
- 0:ef20a9039c0c
New I2C functions
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
cdupaty | 0:ef20a9039c0c | 1 | /* |
cdupaty | 0:ef20a9039c0c | 2 | Christian Dupaty 03/2021 |
cdupaty | 0:ef20a9039c0c | 3 | Library and demo for BMM150 see datasheet here : https://www.bosch-sensortec.com/products/motion-sensors/magnetometers-bmm150/ |
cdupaty | 0:ef20a9039c0c | 4 | Adaptation of BOSCH driver https://github.com/BoschSensortec/BMM150-Sensor-API |
cdupaty | 0:ef20a9039c0c | 5 | for ARM MBED and tested on NUCLEO-L073RZ and GEOMAGNETIC CLICK |
cdupaty | 0:ef20a9039c0c | 6 | https://www.mikroe.com/geomagnetic-click |
cdupaty | 0:ef20a9039c0c | 7 | */ |
cdupaty | 0:ef20a9039c0c | 8 | |
cdupaty | 0:ef20a9039c0c | 9 | #include "mbed.h" |
cdupaty | 0:ef20a9039c0c | 10 | #include "bmm150.h" |
cdupaty | 0:ef20a9039c0c | 11 | |
cdupaty | 0:ef20a9039c0c | 12 | BMM150::BMM150(PinName sda, PinName scl) |
cdupaty | 0:ef20a9039c0c | 13 | { |
cdupaty | 0:ef20a9039c0c | 14 | //I2C *i2c; |
cdupaty | 0:ef20a9039c0c | 15 | i2c = new I2C(sda, scl); |
cdupaty | 0:ef20a9039c0c | 16 | //100KHz, as specified by the datasheet. |
cdupaty | 0:ef20a9039c0c | 17 | i2c ->frequency(100000); |
cdupaty | 0:ef20a9039c0c | 18 | } |
cdupaty | 0:ef20a9039c0c | 19 | |
cdupaty | 0:ef20a9039c0c | 20 | int8_t BMM150::initialize(void) |
cdupaty | 0:ef20a9039c0c | 21 | { |
cdupaty | 0:ef20a9039c0c | 22 | // i2c.begin(); |
cdupaty | 0:ef20a9039c0c | 23 | |
cdupaty | 0:ef20a9039c0c | 24 | /* Power up the sensor from suspend to sleep mode */ |
cdupaty | 0:ef20a9039c0c | 25 | set_op_mode(BMM150_SLEEP_MODE); |
cdupaty | 0:ef20a9039c0c | 26 | wait_ms(BMM150_START_UP_TIME); |
cdupaty | 0:ef20a9039c0c | 27 | |
cdupaty | 0:ef20a9039c0c | 28 | /* Check chip ID */ |
cdupaty | 0:ef20a9039c0c | 29 | uint8_t id = i2c_read(BMM150_CHIP_ID_ADDR); |
cdupaty | 0:ef20a9039c0c | 30 | if (id != BMM150_CHIP_ID) { |
cdupaty | 0:ef20a9039c0c | 31 | return BMM150_E_ID_NOT_CONFORM; |
cdupaty | 0:ef20a9039c0c | 32 | } |
cdupaty | 0:ef20a9039c0c | 33 | |
cdupaty | 0:ef20a9039c0c | 34 | /* Function to update trim values */ |
cdupaty | 0:ef20a9039c0c | 35 | read_trim_registers(); |
cdupaty | 0:ef20a9039c0c | 36 | |
cdupaty | 0:ef20a9039c0c | 37 | /* Setting the power mode as normal */ |
cdupaty | 0:ef20a9039c0c | 38 | set_op_mode(BMM150_NORMAL_MODE); |
cdupaty | 0:ef20a9039c0c | 39 | |
cdupaty | 0:ef20a9039c0c | 40 | /* Setting the preset mode as Low power mode |
cdupaty | 0:ef20a9039c0c | 41 | i.e. data rate = 10Hz XY-rep = 1 Z-rep = 2*/ |
cdupaty | 0:ef20a9039c0c | 42 | set_presetmode(BMM150_PRESETMODE_LOWPOWER); |
cdupaty | 0:ef20a9039c0c | 43 | // set_presetmode(BMM150_HIGHACCURACY_REPZ); |
cdupaty | 0:ef20a9039c0c | 44 | |
cdupaty | 0:ef20a9039c0c | 45 | return BMM150_OK; |
cdupaty | 0:ef20a9039c0c | 46 | } |
cdupaty | 0:ef20a9039c0c | 47 | |
cdupaty | 0:ef20a9039c0c | 48 | void BMM150::read_mag_data() { |
cdupaty | 0:ef20a9039c0c | 49 | int16_t msb_data; |
cdupaty | 0:ef20a9039c0c | 50 | int8_t reg_data[BMM150_XYZR_DATA_LEN] = {0}; |
cdupaty | 0:ef20a9039c0c | 51 | |
cdupaty | 0:ef20a9039c0c | 52 | i2c_read(BMM150_DATA_X_LSB, reg_data, BMM150_XYZR_DATA_LEN); |
cdupaty | 0:ef20a9039c0c | 53 | |
cdupaty | 0:ef20a9039c0c | 54 | /* Mag X axis data */ |
cdupaty | 0:ef20a9039c0c | 55 | reg_data[0] = BMM150_GET_BITS(reg_data[0], BMM150_DATA_X); |
cdupaty | 0:ef20a9039c0c | 56 | /* Shift the MSB data to left by 5 bits */ |
cdupaty | 0:ef20a9039c0c | 57 | /* Multiply by 32 to get the shift left by 5 value */ |
cdupaty | 0:ef20a9039c0c | 58 | msb_data = ((int16_t)((char)reg_data[1])) * 32; |
cdupaty | 0:ef20a9039c0c | 59 | /* Raw mag X axis data */ |
cdupaty | 0:ef20a9039c0c | 60 | raw_mag_data.raw_datax = (int16_t)(msb_data | reg_data[0]); |
cdupaty | 0:ef20a9039c0c | 61 | /* Mag Y axis data */ |
cdupaty | 0:ef20a9039c0c | 62 | reg_data[2] = BMM150_GET_BITS(reg_data[2], BMM150_DATA_Y); |
cdupaty | 0:ef20a9039c0c | 63 | /* Shift the MSB data to left by 5 bits */ |
cdupaty | 0:ef20a9039c0c | 64 | /* Multiply by 32 to get the shift left by 5 value */ |
cdupaty | 0:ef20a9039c0c | 65 | msb_data = ((int16_t)((char)reg_data[3])) * 32; |
cdupaty | 0:ef20a9039c0c | 66 | /* Raw mag Y axis data */ |
cdupaty | 0:ef20a9039c0c | 67 | raw_mag_data.raw_datay = (int16_t)(msb_data | reg_data[2]); |
cdupaty | 0:ef20a9039c0c | 68 | /* Mag Z axis data */ |
cdupaty | 0:ef20a9039c0c | 69 | reg_data[4] = BMM150_GET_BITS(reg_data[4], BMM150_DATA_Z); |
cdupaty | 0:ef20a9039c0c | 70 | /* Shift the MSB data to left by 7 bits */ |
cdupaty | 0:ef20a9039c0c | 71 | /* Multiply by 128 to get the shift left by 7 value */ |
cdupaty | 0:ef20a9039c0c | 72 | msb_data = ((int16_t)((char)reg_data[5])) * 128; |
cdupaty | 0:ef20a9039c0c | 73 | /* Raw mag Z axis data */ |
cdupaty | 0:ef20a9039c0c | 74 | raw_mag_data.raw_dataz = (int16_t)(msb_data | reg_data[4]); |
cdupaty | 0:ef20a9039c0c | 75 | /* Mag R-HALL data */ |
cdupaty | 0:ef20a9039c0c | 76 | reg_data[6] = BMM150_GET_BITS(reg_data[6], BMM150_DATA_RHALL); |
cdupaty | 0:ef20a9039c0c | 77 | raw_mag_data.raw_data_r = (uint16_t)(((uint16_t)reg_data[7] << 6) | reg_data[6]); |
cdupaty | 0:ef20a9039c0c | 78 | |
cdupaty | 0:ef20a9039c0c | 79 | /* Compensated Mag X data in int16_t format */ |
cdupaty | 0:ef20a9039c0c | 80 | mag_data.x = compensate_x(raw_mag_data.raw_datax, raw_mag_data.raw_data_r); |
cdupaty | 0:ef20a9039c0c | 81 | /* Compensated Mag Y data in int16_t format */ |
cdupaty | 0:ef20a9039c0c | 82 | mag_data.y = compensate_y(raw_mag_data.raw_datay, raw_mag_data.raw_data_r); |
cdupaty | 0:ef20a9039c0c | 83 | /* Compensated Mag Z data in int16_t format */ |
cdupaty | 0:ef20a9039c0c | 84 | mag_data.z = compensate_z(raw_mag_data.raw_dataz, raw_mag_data.raw_data_r); |
cdupaty | 0:ef20a9039c0c | 85 | } |
cdupaty | 0:ef20a9039c0c | 86 | |
cdupaty | 0:ef20a9039c0c | 87 | /* |
cdupaty | 0:ef20a9039c0c | 88 | @brief This internal API is used to obtain the compensated |
cdupaty | 0:ef20a9039c0c | 89 | magnetometer X axis data(micro-tesla) in int16_t. |
cdupaty | 0:ef20a9039c0c | 90 | */ |
cdupaty | 0:ef20a9039c0c | 91 | int16_t BMM150::compensate_x(int16_t mag_data_x, uint16_t data_rhall) |
cdupaty | 0:ef20a9039c0c | 92 | { |
cdupaty | 0:ef20a9039c0c | 93 | int16_t retval; |
cdupaty | 0:ef20a9039c0c | 94 | uint16_t process_comp_x0 = 0; |
cdupaty | 0:ef20a9039c0c | 95 | int32_t process_comp_x1; |
cdupaty | 0:ef20a9039c0c | 96 | uint16_t process_comp_x2; |
cdupaty | 0:ef20a9039c0c | 97 | int32_t process_comp_x3; |
cdupaty | 0:ef20a9039c0c | 98 | int32_t process_comp_x4; |
cdupaty | 0:ef20a9039c0c | 99 | int32_t process_comp_x5; |
cdupaty | 0:ef20a9039c0c | 100 | int32_t process_comp_x6; |
cdupaty | 0:ef20a9039c0c | 101 | int32_t process_comp_x7; |
cdupaty | 0:ef20a9039c0c | 102 | int32_t process_comp_x8; |
cdupaty | 0:ef20a9039c0c | 103 | int32_t process_comp_x9; |
cdupaty | 0:ef20a9039c0c | 104 | int32_t process_comp_x10; |
cdupaty | 0:ef20a9039c0c | 105 | |
cdupaty | 0:ef20a9039c0c | 106 | /* Overflow condition check */ |
cdupaty | 0:ef20a9039c0c | 107 | if (mag_data_x != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) { |
cdupaty | 0:ef20a9039c0c | 108 | if (data_rhall != 0) { |
cdupaty | 0:ef20a9039c0c | 109 | /* Availability of valid data*/ |
cdupaty | 0:ef20a9039c0c | 110 | process_comp_x0 = data_rhall; |
cdupaty | 0:ef20a9039c0c | 111 | } else if (trim_data.dig_xyz1 != 0) { |
cdupaty | 0:ef20a9039c0c | 112 | process_comp_x0 = trim_data.dig_xyz1; |
cdupaty | 0:ef20a9039c0c | 113 | } else { |
cdupaty | 0:ef20a9039c0c | 114 | process_comp_x0 = 0; |
cdupaty | 0:ef20a9039c0c | 115 | } |
cdupaty | 0:ef20a9039c0c | 116 | if (process_comp_x0 != 0) { |
cdupaty | 0:ef20a9039c0c | 117 | /* Processing compensation equations*/ |
cdupaty | 0:ef20a9039c0c | 118 | process_comp_x1 = ((int32_t)trim_data.dig_xyz1) * 16384; |
cdupaty | 0:ef20a9039c0c | 119 | process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000); |
cdupaty | 0:ef20a9039c0c | 120 | retval = ((int16_t)process_comp_x2); |
cdupaty | 0:ef20a9039c0c | 121 | process_comp_x3 = (((int32_t)retval) * ((int32_t)retval)); |
cdupaty | 0:ef20a9039c0c | 122 | process_comp_x4 = (((int32_t)trim_data.dig_xy2) * (process_comp_x3 / 128)); |
cdupaty | 0:ef20a9039c0c | 123 | process_comp_x5 = (int32_t)(((int16_t)trim_data.dig_xy1) * 128); |
cdupaty | 0:ef20a9039c0c | 124 | process_comp_x6 = ((int32_t)retval) * process_comp_x5; |
cdupaty | 0:ef20a9039c0c | 125 | process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000)); |
cdupaty | 0:ef20a9039c0c | 126 | process_comp_x8 = ((int32_t)(((int16_t)trim_data.dig_x2) + ((int16_t)0xA0))); |
cdupaty | 0:ef20a9039c0c | 127 | process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096); |
cdupaty | 0:ef20a9039c0c | 128 | process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9; |
cdupaty | 0:ef20a9039c0c | 129 | retval = ((int16_t)(process_comp_x10 / 8192)); |
cdupaty | 0:ef20a9039c0c | 130 | retval = (retval + (((int16_t)trim_data.dig_x1) * 8)) / 16; |
cdupaty | 0:ef20a9039c0c | 131 | } else { |
cdupaty | 0:ef20a9039c0c | 132 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 133 | } |
cdupaty | 0:ef20a9039c0c | 134 | } else { |
cdupaty | 0:ef20a9039c0c | 135 | /* Overflow condition */ |
cdupaty | 0:ef20a9039c0c | 136 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 137 | } |
cdupaty | 0:ef20a9039c0c | 138 | |
cdupaty | 0:ef20a9039c0c | 139 | return retval; |
cdupaty | 0:ef20a9039c0c | 140 | } |
cdupaty | 0:ef20a9039c0c | 141 | |
cdupaty | 0:ef20a9039c0c | 142 | /* |
cdupaty | 0:ef20a9039c0c | 143 | @brief This internal API is used to obtain the compensated |
cdupaty | 0:ef20a9039c0c | 144 | magnetometer Y axis data(micro-tesla) in int16_t. |
cdupaty | 0:ef20a9039c0c | 145 | */ |
cdupaty | 0:ef20a9039c0c | 146 | int16_t BMM150::compensate_y(int16_t mag_data_y, uint16_t data_rhall) { |
cdupaty | 0:ef20a9039c0c | 147 | int16_t retval; |
cdupaty | 0:ef20a9039c0c | 148 | uint16_t process_comp_y0 = 0; |
cdupaty | 0:ef20a9039c0c | 149 | int32_t process_comp_y1; |
cdupaty | 0:ef20a9039c0c | 150 | uint16_t process_comp_y2; |
cdupaty | 0:ef20a9039c0c | 151 | int32_t process_comp_y3; |
cdupaty | 0:ef20a9039c0c | 152 | int32_t process_comp_y4; |
cdupaty | 0:ef20a9039c0c | 153 | int32_t process_comp_y5; |
cdupaty | 0:ef20a9039c0c | 154 | int32_t process_comp_y6; |
cdupaty | 0:ef20a9039c0c | 155 | int32_t process_comp_y7; |
cdupaty | 0:ef20a9039c0c | 156 | int32_t process_comp_y8; |
cdupaty | 0:ef20a9039c0c | 157 | int32_t process_comp_y9; |
cdupaty | 0:ef20a9039c0c | 158 | |
cdupaty | 0:ef20a9039c0c | 159 | /* Overflow condition check */ |
cdupaty | 0:ef20a9039c0c | 160 | if (mag_data_y != BMM150_XYAXES_FLIP_OVERFLOW_ADCVAL) { |
cdupaty | 0:ef20a9039c0c | 161 | if (data_rhall != 0) { |
cdupaty | 0:ef20a9039c0c | 162 | /* Availability of valid data*/ |
cdupaty | 0:ef20a9039c0c | 163 | process_comp_y0 = data_rhall; |
cdupaty | 0:ef20a9039c0c | 164 | } else if (trim_data.dig_xyz1 != 0) { |
cdupaty | 0:ef20a9039c0c | 165 | process_comp_y0 = trim_data.dig_xyz1; |
cdupaty | 0:ef20a9039c0c | 166 | } else { |
cdupaty | 0:ef20a9039c0c | 167 | process_comp_y0 = 0; |
cdupaty | 0:ef20a9039c0c | 168 | } |
cdupaty | 0:ef20a9039c0c | 169 | if (process_comp_y0 != 0) { |
cdupaty | 0:ef20a9039c0c | 170 | /*Processing compensation equations*/ |
cdupaty | 0:ef20a9039c0c | 171 | process_comp_y1 = (((int32_t)trim_data.dig_xyz1) * 16384) / process_comp_y0; |
cdupaty | 0:ef20a9039c0c | 172 | process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000); |
cdupaty | 0:ef20a9039c0c | 173 | retval = ((int16_t)process_comp_y2); |
cdupaty | 0:ef20a9039c0c | 174 | process_comp_y3 = ((int32_t) retval) * ((int32_t)retval); |
cdupaty | 0:ef20a9039c0c | 175 | process_comp_y4 = ((int32_t)trim_data.dig_xy2) * (process_comp_y3 / 128); |
cdupaty | 0:ef20a9039c0c | 176 | process_comp_y5 = ((int32_t)(((int16_t)trim_data.dig_xy1) * 128)); |
cdupaty | 0:ef20a9039c0c | 177 | process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512); |
cdupaty | 0:ef20a9039c0c | 178 | process_comp_y7 = ((int32_t)(((int16_t)trim_data.dig_y2) + ((int16_t)0xA0))); |
cdupaty | 0:ef20a9039c0c | 179 | process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096); |
cdupaty | 0:ef20a9039c0c | 180 | process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8); |
cdupaty | 0:ef20a9039c0c | 181 | retval = (int16_t)(process_comp_y9 / 8192); |
cdupaty | 0:ef20a9039c0c | 182 | retval = (retval + (((int16_t)trim_data.dig_y1) * 8)) / 16; |
cdupaty | 0:ef20a9039c0c | 183 | } else { |
cdupaty | 0:ef20a9039c0c | 184 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 185 | } |
cdupaty | 0:ef20a9039c0c | 186 | } else { |
cdupaty | 0:ef20a9039c0c | 187 | /* Overflow condition*/ |
cdupaty | 0:ef20a9039c0c | 188 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 189 | } |
cdupaty | 0:ef20a9039c0c | 190 | |
cdupaty | 0:ef20a9039c0c | 191 | return retval; |
cdupaty | 0:ef20a9039c0c | 192 | } |
cdupaty | 0:ef20a9039c0c | 193 | |
cdupaty | 0:ef20a9039c0c | 194 | /* |
cdupaty | 0:ef20a9039c0c | 195 | @brief This internal API is used to obtain the compensated |
cdupaty | 0:ef20a9039c0c | 196 | magnetometer Z axis data(micro-tesla) in int16_t. |
cdupaty | 0:ef20a9039c0c | 197 | */ |
cdupaty | 0:ef20a9039c0c | 198 | int16_t BMM150::compensate_z(int16_t mag_data_z, uint16_t data_rhall) { |
cdupaty | 0:ef20a9039c0c | 199 | int32_t retval; |
cdupaty | 0:ef20a9039c0c | 200 | int16_t process_comp_z0; |
cdupaty | 0:ef20a9039c0c | 201 | int32_t process_comp_z1; |
cdupaty | 0:ef20a9039c0c | 202 | int32_t process_comp_z2; |
cdupaty | 0:ef20a9039c0c | 203 | int32_t process_comp_z3; |
cdupaty | 0:ef20a9039c0c | 204 | int16_t process_comp_z4; |
cdupaty | 0:ef20a9039c0c | 205 | |
cdupaty | 0:ef20a9039c0c | 206 | if (mag_data_z != BMM150_ZAXIS_HALL_OVERFLOW_ADCVAL) { |
cdupaty | 0:ef20a9039c0c | 207 | if ((trim_data.dig_z2 != 0) && (trim_data.dig_z1 != 0) |
cdupaty | 0:ef20a9039c0c | 208 | && (data_rhall != 0) && (trim_data.dig_xyz1 != 0)) { |
cdupaty | 0:ef20a9039c0c | 209 | /*Processing compensation equations*/ |
cdupaty | 0:ef20a9039c0c | 210 | process_comp_z0 = ((int16_t)data_rhall) - ((int16_t) trim_data.dig_xyz1); |
cdupaty | 0:ef20a9039c0c | 211 | process_comp_z1 = (((int32_t)trim_data.dig_z3) * ((int32_t)(process_comp_z0))) / 4; |
cdupaty | 0:ef20a9039c0c | 212 | process_comp_z2 = (((int32_t)(mag_data_z - trim_data.dig_z4)) * 32768); |
cdupaty | 0:ef20a9039c0c | 213 | process_comp_z3 = ((int32_t)trim_data.dig_z1) * (((int16_t)data_rhall) * 2); |
cdupaty | 0:ef20a9039c0c | 214 | process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536); |
cdupaty | 0:ef20a9039c0c | 215 | retval = ((process_comp_z2 - process_comp_z1) / (trim_data.dig_z2 + process_comp_z4)); |
cdupaty | 0:ef20a9039c0c | 216 | |
cdupaty | 0:ef20a9039c0c | 217 | /* saturate result to +/- 2 micro-tesla */ |
cdupaty | 0:ef20a9039c0c | 218 | if (retval > BMM150_POSITIVE_SATURATION_Z) { |
cdupaty | 0:ef20a9039c0c | 219 | retval = BMM150_POSITIVE_SATURATION_Z; |
cdupaty | 0:ef20a9039c0c | 220 | } else { |
cdupaty | 0:ef20a9039c0c | 221 | if (retval < BMM150_NEGATIVE_SATURATION_Z) { |
cdupaty | 0:ef20a9039c0c | 222 | retval = BMM150_NEGATIVE_SATURATION_Z; |
cdupaty | 0:ef20a9039c0c | 223 | } |
cdupaty | 0:ef20a9039c0c | 224 | } |
cdupaty | 0:ef20a9039c0c | 225 | /* Conversion of LSB to micro-tesla*/ |
cdupaty | 0:ef20a9039c0c | 226 | retval = retval / 16; |
cdupaty | 0:ef20a9039c0c | 227 | } else { |
cdupaty | 0:ef20a9039c0c | 228 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 229 | |
cdupaty | 0:ef20a9039c0c | 230 | } |
cdupaty | 0:ef20a9039c0c | 231 | } else { |
cdupaty | 0:ef20a9039c0c | 232 | /* Overflow condition*/ |
cdupaty | 0:ef20a9039c0c | 233 | retval = BMM150_OVERFLOW_OUTPUT; |
cdupaty | 0:ef20a9039c0c | 234 | } |
cdupaty | 0:ef20a9039c0c | 235 | |
cdupaty | 0:ef20a9039c0c | 236 | return (int16_t)retval; |
cdupaty | 0:ef20a9039c0c | 237 | } |
cdupaty | 0:ef20a9039c0c | 238 | |
cdupaty | 0:ef20a9039c0c | 239 | void BMM150::set_presetmode(uint8_t preset_mode) { |
cdupaty | 0:ef20a9039c0c | 240 | switch (preset_mode) { |
cdupaty | 0:ef20a9039c0c | 241 | case BMM150_PRESETMODE_LOWPOWER: |
cdupaty | 0:ef20a9039c0c | 242 | /* Set the data rate x,y,z repetition |
cdupaty | 0:ef20a9039c0c | 243 | for Low Power mode */ |
cdupaty | 0:ef20a9039c0c | 244 | settings.data_rate = BMM150_DATA_RATE_10HZ; |
cdupaty | 0:ef20a9039c0c | 245 | settings.xy_rep = BMM150_LOWPOWER_REPXY; |
cdupaty | 0:ef20a9039c0c | 246 | settings.z_rep = BMM150_LOWPOWER_REPZ; |
cdupaty | 0:ef20a9039c0c | 247 | set_odr_xyz_rep(settings); |
cdupaty | 0:ef20a9039c0c | 248 | break; |
cdupaty | 0:ef20a9039c0c | 249 | case BMM150_PRESETMODE_REGULAR: |
cdupaty | 0:ef20a9039c0c | 250 | /* Set the data rate x,y,z repetition |
cdupaty | 0:ef20a9039c0c | 251 | for Regular mode */ |
cdupaty | 0:ef20a9039c0c | 252 | settings.data_rate = BMM150_DATA_RATE_10HZ; |
cdupaty | 0:ef20a9039c0c | 253 | settings.xy_rep = BMM150_REGULAR_REPXY; |
cdupaty | 0:ef20a9039c0c | 254 | settings.z_rep = BMM150_REGULAR_REPZ; |
cdupaty | 0:ef20a9039c0c | 255 | set_odr_xyz_rep(settings); |
cdupaty | 0:ef20a9039c0c | 256 | break; |
cdupaty | 0:ef20a9039c0c | 257 | case BMM150_PRESETMODE_HIGHACCURACY: |
cdupaty | 0:ef20a9039c0c | 258 | /* Set the data rate x,y,z repetition |
cdupaty | 0:ef20a9039c0c | 259 | for High Accuracy mode */ |
cdupaty | 0:ef20a9039c0c | 260 | settings.data_rate = BMM150_DATA_RATE_20HZ; |
cdupaty | 0:ef20a9039c0c | 261 | settings.xy_rep = BMM150_HIGHACCURACY_REPXY; |
cdupaty | 0:ef20a9039c0c | 262 | settings.z_rep = BMM150_HIGHACCURACY_REPZ; |
cdupaty | 0:ef20a9039c0c | 263 | set_odr_xyz_rep(settings); |
cdupaty | 0:ef20a9039c0c | 264 | break; |
cdupaty | 0:ef20a9039c0c | 265 | case BMM150_PRESETMODE_ENHANCED: |
cdupaty | 0:ef20a9039c0c | 266 | /* Set the data rate x,y,z repetition |
cdupaty | 0:ef20a9039c0c | 267 | for Enhanced Accuracy mode */ |
cdupaty | 0:ef20a9039c0c | 268 | settings.data_rate = BMM150_DATA_RATE_10HZ; |
cdupaty | 0:ef20a9039c0c | 269 | settings.xy_rep = BMM150_ENHANCED_REPXY; |
cdupaty | 0:ef20a9039c0c | 270 | settings.z_rep = BMM150_ENHANCED_REPZ; |
cdupaty | 0:ef20a9039c0c | 271 | set_odr_xyz_rep(settings); |
cdupaty | 0:ef20a9039c0c | 272 | break; |
cdupaty | 0:ef20a9039c0c | 273 | default: |
cdupaty | 0:ef20a9039c0c | 274 | break; |
cdupaty | 0:ef20a9039c0c | 275 | } |
cdupaty | 0:ef20a9039c0c | 276 | } |
cdupaty | 0:ef20a9039c0c | 277 | |
cdupaty | 0:ef20a9039c0c | 278 | void BMM150::set_odr_xyz_rep(struct bmm150_settings settings) { |
cdupaty | 0:ef20a9039c0c | 279 | /* Set the ODR */ |
cdupaty | 0:ef20a9039c0c | 280 | set_odr(settings); |
cdupaty | 0:ef20a9039c0c | 281 | /* Set the XY-repetitions number */ |
cdupaty | 0:ef20a9039c0c | 282 | set_xy_rep(settings); |
cdupaty | 0:ef20a9039c0c | 283 | /* Set the Z-repetitions number */ |
cdupaty | 0:ef20a9039c0c | 284 | set_z_rep(settings); |
cdupaty | 0:ef20a9039c0c | 285 | } |
cdupaty | 0:ef20a9039c0c | 286 | |
cdupaty | 0:ef20a9039c0c | 287 | void BMM150::set_xy_rep(struct bmm150_settings settings) { |
cdupaty | 0:ef20a9039c0c | 288 | uint8_t rep_xy; |
cdupaty | 0:ef20a9039c0c | 289 | rep_xy = settings.xy_rep; |
cdupaty | 0:ef20a9039c0c | 290 | i2c_write(BMM150_REP_XY_ADDR, rep_xy); |
cdupaty | 0:ef20a9039c0c | 291 | |
cdupaty | 0:ef20a9039c0c | 292 | } |
cdupaty | 0:ef20a9039c0c | 293 | |
cdupaty | 0:ef20a9039c0c | 294 | void BMM150::set_z_rep(struct bmm150_settings settings) { |
cdupaty | 0:ef20a9039c0c | 295 | uint8_t rep_z; |
cdupaty | 0:ef20a9039c0c | 296 | rep_z = settings.z_rep; |
cdupaty | 0:ef20a9039c0c | 297 | i2c_write(BMM150_REP_Z_ADDR, rep_z); |
cdupaty | 0:ef20a9039c0c | 298 | } |
cdupaty | 0:ef20a9039c0c | 299 | |
cdupaty | 0:ef20a9039c0c | 300 | |
cdupaty | 0:ef20a9039c0c | 301 | void BMM150::soft_reset() |
cdupaty | 0:ef20a9039c0c | 302 | { |
cdupaty | 0:ef20a9039c0c | 303 | uint8_t reg_data; |
cdupaty | 0:ef20a9039c0c | 304 | |
cdupaty | 0:ef20a9039c0c | 305 | reg_data = i2c_read(BMM150_POWER_CONTROL_ADDR); |
cdupaty | 0:ef20a9039c0c | 306 | reg_data = reg_data | BMM150_SET_SOFT_RESET; |
cdupaty | 0:ef20a9039c0c | 307 | i2c_write(BMM150_POWER_CONTROL_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 308 | wait_ms(BMM150_SOFT_RESET_wait_ms); |
cdupaty | 0:ef20a9039c0c | 309 | } |
cdupaty | 0:ef20a9039c0c | 310 | |
cdupaty | 0:ef20a9039c0c | 311 | |
cdupaty | 0:ef20a9039c0c | 312 | void BMM150::set_odr(struct bmm150_settings settings) |
cdupaty | 0:ef20a9039c0c | 313 | { |
cdupaty | 0:ef20a9039c0c | 314 | uint8_t reg_data; |
cdupaty | 0:ef20a9039c0c | 315 | |
cdupaty | 0:ef20a9039c0c | 316 | reg_data = i2c_read(BMM150_OP_MODE_ADDR); |
cdupaty | 0:ef20a9039c0c | 317 | /*Set the ODR value */ |
cdupaty | 0:ef20a9039c0c | 318 | reg_data = BMM150_SET_BITS(reg_data, BMM150_ODR, settings.data_rate); |
cdupaty | 0:ef20a9039c0c | 319 | i2c_write(BMM150_OP_MODE_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 320 | } |
cdupaty | 0:ef20a9039c0c | 321 | |
cdupaty | 0:ef20a9039c0c | 322 | void BMM150::i2c_write(short address, short data) |
cdupaty | 0:ef20a9039c0c | 323 | { |
cdupaty | 1:9651fd7ee8f6 | 324 | char temp[2]; |
cdupaty | 1:9651fd7ee8f6 | 325 | temp[0]=address; |
cdupaty | 1:9651fd7ee8f6 | 326 | temp[1]=data; |
cdupaty | 1:9651fd7ee8f6 | 327 | i2c->write(BMM150_I2C_Address,temp,2); |
cdupaty | 1:9651fd7ee8f6 | 328 | } |
cdupaty | 1:9651fd7ee8f6 | 329 | |
cdupaty | 1:9651fd7ee8f6 | 330 | void BMM150::i2c_write(short address) |
cdupaty | 1:9651fd7ee8f6 | 331 | { |
cdupaty | 1:9651fd7ee8f6 | 332 | char temp[1]; |
cdupaty | 1:9651fd7ee8f6 | 333 | temp[0]=address; |
cdupaty | 1:9651fd7ee8f6 | 334 | i2c->write(BMM150_I2C_Address,temp,1); |
cdupaty | 0:ef20a9039c0c | 335 | } |
cdupaty | 0:ef20a9039c0c | 336 | |
cdupaty | 0:ef20a9039c0c | 337 | void BMM150::i2c_read(short address, uint8_t* buffer, short length) |
cdupaty | 1:9651fd7ee8f6 | 338 | { |
cdupaty | 1:9651fd7ee8f6 | 339 | i2c_write(address); |
cdupaty | 1:9651fd7ee8f6 | 340 | i2c->read(BMM150_I2C_Address+1,(char *)buffer,length); |
cdupaty | 0:ef20a9039c0c | 341 | } |
cdupaty | 0:ef20a9039c0c | 342 | |
cdupaty | 0:ef20a9039c0c | 343 | |
cdupaty | 0:ef20a9039c0c | 344 | void BMM150::i2c_read(short address, int8_t* buffer, short length) |
cdupaty | 0:ef20a9039c0c | 345 | { |
cdupaty | 1:9651fd7ee8f6 | 346 | i2c_write(address); |
cdupaty | 1:9651fd7ee8f6 | 347 | i2c->read(BMM150_I2C_Address+1,(char *)buffer,length); |
cdupaty | 0:ef20a9039c0c | 348 | } |
cdupaty | 0:ef20a9039c0c | 349 | |
cdupaty | 0:ef20a9039c0c | 350 | uint8_t BMM150::i2c_read(short address) |
cdupaty | 0:ef20a9039c0c | 351 | { |
cdupaty | 1:9651fd7ee8f6 | 352 | char temp[1]; |
cdupaty | 1:9651fd7ee8f6 | 353 | i2c_write(address); |
cdupaty | 1:9651fd7ee8f6 | 354 | i2c->read(BMM150_I2C_Address+1,temp,1); |
cdupaty | 1:9651fd7ee8f6 | 355 | return temp[0]; |
cdupaty | 0:ef20a9039c0c | 356 | } |
cdupaty | 0:ef20a9039c0c | 357 | |
cdupaty | 0:ef20a9039c0c | 358 | |
cdupaty | 0:ef20a9039c0c | 359 | // char* BMM150::getErrorText(short errorCode); |
cdupaty | 0:ef20a9039c0c | 360 | // { |
cdupaty | 0:ef20a9039c0c | 361 | // if(ERRORCODE_1_NUM == 1) |
cdupaty | 0:ef20a9039c0c | 362 | // return ERRORCODE_1; |
cdupaty | 0:ef20a9039c0c | 363 | |
cdupaty | 0:ef20a9039c0c | 364 | // return "Error not defined."; |
cdupaty | 0:ef20a9039c0c | 365 | // } |
cdupaty | 0:ef20a9039c0c | 366 | |
cdupaty | 0:ef20a9039c0c | 367 | void BMM150::set_op_mode(uint8_t pwr_mode) { |
cdupaty | 0:ef20a9039c0c | 368 | /* Select the power mode to set */ |
cdupaty | 0:ef20a9039c0c | 369 | switch (pwr_mode) { |
cdupaty | 0:ef20a9039c0c | 370 | case BMM150_NORMAL_MODE: |
cdupaty | 0:ef20a9039c0c | 371 | /* If the sensor is in suspend mode |
cdupaty | 0:ef20a9039c0c | 372 | put the device to sleep mode */ |
cdupaty | 0:ef20a9039c0c | 373 | suspend_to_sleep_mode(); |
cdupaty | 0:ef20a9039c0c | 374 | /* write the op mode */ |
cdupaty | 0:ef20a9039c0c | 375 | write_op_mode(pwr_mode); |
cdupaty | 0:ef20a9039c0c | 376 | break; |
cdupaty | 0:ef20a9039c0c | 377 | case BMM150_FORCED_MODE: |
cdupaty | 0:ef20a9039c0c | 378 | /* If the sensor is in suspend mode |
cdupaty | 0:ef20a9039c0c | 379 | put the device to sleep mode */ |
cdupaty | 0:ef20a9039c0c | 380 | suspend_to_sleep_mode(); |
cdupaty | 0:ef20a9039c0c | 381 | /* write the op mode */ |
cdupaty | 0:ef20a9039c0c | 382 | write_op_mode(pwr_mode); |
cdupaty | 0:ef20a9039c0c | 383 | break; |
cdupaty | 0:ef20a9039c0c | 384 | case BMM150_SLEEP_MODE: |
cdupaty | 0:ef20a9039c0c | 385 | /* If the sensor is in suspend mode |
cdupaty | 0:ef20a9039c0c | 386 | put the device to sleep mode */ |
cdupaty | 0:ef20a9039c0c | 387 | suspend_to_sleep_mode(); |
cdupaty | 0:ef20a9039c0c | 388 | /* write the op mode */ |
cdupaty | 0:ef20a9039c0c | 389 | write_op_mode(pwr_mode); |
cdupaty | 0:ef20a9039c0c | 390 | break; |
cdupaty | 0:ef20a9039c0c | 391 | case BMM150_SUSPEND_MODE: |
cdupaty | 0:ef20a9039c0c | 392 | /* Set the power control bit to zero */ |
cdupaty | 0:ef20a9039c0c | 393 | set_power_control_bit(BMM150_POWER_CNTRL_DISABLE); |
cdupaty | 0:ef20a9039c0c | 394 | break; |
cdupaty | 0:ef20a9039c0c | 395 | default: |
cdupaty | 0:ef20a9039c0c | 396 | break; |
cdupaty | 0:ef20a9039c0c | 397 | } |
cdupaty | 0:ef20a9039c0c | 398 | } |
cdupaty | 0:ef20a9039c0c | 399 | |
cdupaty | 0:ef20a9039c0c | 400 | void BMM150::suspend_to_sleep_mode(void) { |
cdupaty | 0:ef20a9039c0c | 401 | set_power_control_bit(BMM150_POWER_CNTRL_ENABLE); |
cdupaty | 0:ef20a9039c0c | 402 | /* Start-up time wait_ms of 3ms*/ |
cdupaty | 0:ef20a9039c0c | 403 | wait_ms(3); |
cdupaty | 0:ef20a9039c0c | 404 | } |
cdupaty | 0:ef20a9039c0c | 405 | |
cdupaty | 0:ef20a9039c0c | 406 | |
cdupaty | 0:ef20a9039c0c | 407 | void BMM150::read_trim_registers() { |
cdupaty | 0:ef20a9039c0c | 408 | uint8_t trim_x1y1[2] = {0}; |
cdupaty | 0:ef20a9039c0c | 409 | uint8_t trim_xyz_data[4] = {0}; |
cdupaty | 0:ef20a9039c0c | 410 | uint8_t trim_xy1xy2[10] = {0}; |
cdupaty | 0:ef20a9039c0c | 411 | uint16_t temp_msb = 0; |
cdupaty | 0:ef20a9039c0c | 412 | |
cdupaty | 0:ef20a9039c0c | 413 | /* Trim register value is read */ |
cdupaty | 0:ef20a9039c0c | 414 | i2c_read(BMM150_DIG_X1, trim_x1y1, 2); |
cdupaty | 0:ef20a9039c0c | 415 | i2c_read(BMM150_DIG_Z4_LSB, trim_xyz_data, 4); |
cdupaty | 0:ef20a9039c0c | 416 | i2c_read(BMM150_DIG_Z2_LSB, trim_xy1xy2, 10); |
cdupaty | 0:ef20a9039c0c | 417 | /* Trim data which is read is updated |
cdupaty | 0:ef20a9039c0c | 418 | in the device structure */ |
cdupaty | 0:ef20a9039c0c | 419 | trim_data.dig_x1 = (char)trim_x1y1[0]; |
cdupaty | 0:ef20a9039c0c | 420 | trim_data.dig_y1 = (char)trim_x1y1[1]; |
cdupaty | 0:ef20a9039c0c | 421 | trim_data.dig_x2 = (char)trim_xyz_data[2]; |
cdupaty | 0:ef20a9039c0c | 422 | trim_data.dig_y2 = (char)trim_xyz_data[3]; |
cdupaty | 0:ef20a9039c0c | 423 | temp_msb = ((uint16_t)trim_xy1xy2[3]) << 8; |
cdupaty | 0:ef20a9039c0c | 424 | trim_data.dig_z1 = (uint16_t)(temp_msb | trim_xy1xy2[2]); |
cdupaty | 0:ef20a9039c0c | 425 | temp_msb = ((uint16_t)trim_xy1xy2[1]) << 8; |
cdupaty | 0:ef20a9039c0c | 426 | trim_data.dig_z2 = (int16_t)(temp_msb | trim_xy1xy2[0]); |
cdupaty | 0:ef20a9039c0c | 427 | temp_msb = ((uint16_t)trim_xy1xy2[7]) << 8; |
cdupaty | 0:ef20a9039c0c | 428 | trim_data.dig_z3 = (int16_t)(temp_msb | trim_xy1xy2[6]); |
cdupaty | 0:ef20a9039c0c | 429 | temp_msb = ((uint16_t)trim_xyz_data[1]) << 8; |
cdupaty | 0:ef20a9039c0c | 430 | trim_data.dig_z4 = (int16_t)(temp_msb | trim_xyz_data[0]); |
cdupaty | 0:ef20a9039c0c | 431 | trim_data.dig_xy1 = trim_xy1xy2[9]; |
cdupaty | 0:ef20a9039c0c | 432 | trim_data.dig_xy2 = (char)trim_xy1xy2[8]; |
cdupaty | 0:ef20a9039c0c | 433 | temp_msb = ((uint16_t)(trim_xy1xy2[5] & 0x7F)) << 8; |
cdupaty | 0:ef20a9039c0c | 434 | trim_data.dig_xyz1 = (uint16_t)(temp_msb | trim_xy1xy2[4]); |
cdupaty | 0:ef20a9039c0c | 435 | |
cdupaty | 0:ef20a9039c0c | 436 | } |
cdupaty | 0:ef20a9039c0c | 437 | |
cdupaty | 0:ef20a9039c0c | 438 | void BMM150::write_op_mode(uint8_t op_mode) { |
cdupaty | 0:ef20a9039c0c | 439 | uint8_t reg_data = 0; |
cdupaty | 0:ef20a9039c0c | 440 | reg_data = i2c_read(BMM150_OP_MODE_ADDR); |
cdupaty | 0:ef20a9039c0c | 441 | /* Set the op_mode value in Opmode bits of 0x4C */ |
cdupaty | 0:ef20a9039c0c | 442 | reg_data = BMM150_SET_BITS(reg_data, BMM150_OP_MODE, op_mode); |
cdupaty | 0:ef20a9039c0c | 443 | i2c_write(BMM150_OP_MODE_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 444 | } |
cdupaty | 0:ef20a9039c0c | 445 | |
cdupaty | 0:ef20a9039c0c | 446 | void BMM150::set_power_control_bit(uint8_t pwrcntrl_bit) { |
cdupaty | 0:ef20a9039c0c | 447 | uint8_t reg_data = 0; |
cdupaty | 0:ef20a9039c0c | 448 | /* Power control register 0x4B is read */ |
cdupaty | 0:ef20a9039c0c | 449 | reg_data = i2c_read(BMM150_POWER_CONTROL_ADDR); |
cdupaty | 0:ef20a9039c0c | 450 | /* Sets the value of power control bit */ |
cdupaty | 0:ef20a9039c0c | 451 | reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_PWR_CNTRL, pwrcntrl_bit); |
cdupaty | 0:ef20a9039c0c | 452 | i2c_write(BMM150_POWER_CONTROL_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 453 | } |
cdupaty | 0:ef20a9039c0c | 454 | |
cdupaty | 0:ef20a9039c0c | 455 | |
cdupaty | 0:ef20a9039c0c | 456 | // /*! |
cdupaty | 0:ef20a9039c0c | 457 | // * @brief This API is used to perform the complete self test |
cdupaty | 0:ef20a9039c0c | 458 | // * (both normal and advanced) for the BMM150 sensor |
cdupaty | 0:ef20a9039c0c | 459 | // */ |
cdupaty | 0:ef20a9039c0c | 460 | // char BMM150::perform_self_test(uint8_t self_test_mode) |
cdupaty | 0:ef20a9039c0c | 461 | // { |
cdupaty | 0:ef20a9039c0c | 462 | // char rslt; |
cdupaty | 0:ef20a9039c0c | 463 | // char self_test_rslt = 0; |
cdupaty | 0:ef20a9039c0c | 464 | |
cdupaty | 0:ef20a9039c0c | 465 | // switch (self_test_mode) { |
cdupaty | 0:ef20a9039c0c | 466 | // case BMM150_NORMAL_SELF_TEST: |
cdupaty | 0:ef20a9039c0c | 467 | // /* Set the sensor in sleep mode */ |
cdupaty | 0:ef20a9039c0c | 468 | // settings.pwr_mode = BMM150_SLEEP_MODE; |
cdupaty | 0:ef20a9039c0c | 469 | // set_op_mode(BMM150_SLEEP_MODE); |
cdupaty | 0:ef20a9039c0c | 470 | // /* Perform the normal self test */ |
cdupaty | 0:ef20a9039c0c | 471 | // rslt = perform_normal_self_test(); |
cdupaty | 0:ef20a9039c0c | 472 | // break; |
cdupaty | 0:ef20a9039c0c | 473 | |
cdupaty | 0:ef20a9039c0c | 474 | // case BMM150_ADVANCED_SELF_TEST: |
cdupaty | 0:ef20a9039c0c | 475 | // /* Perform the advanced self test */ |
cdupaty | 0:ef20a9039c0c | 476 | // rslt = perform_adv_self_test(); |
cdupaty | 0:ef20a9039c0c | 477 | // /* Check to ensure bus error does not occur */ |
cdupaty | 0:ef20a9039c0c | 478 | // if (rslt >= BMM150_OK) { |
cdupaty | 0:ef20a9039c0c | 479 | // /* Store the status of self test result */ |
cdupaty | 0:ef20a9039c0c | 480 | // self_test_rslt = rslt; |
cdupaty | 0:ef20a9039c0c | 481 | // /* Perform soft reset */ |
cdupaty | 0:ef20a9039c0c | 482 | // soft_reset(); |
cdupaty | 0:ef20a9039c0c | 483 | // } |
cdupaty | 0:ef20a9039c0c | 484 | // rslt = self_test_rslt; |
cdupaty | 0:ef20a9039c0c | 485 | // break; |
cdupaty | 0:ef20a9039c0c | 486 | // default: |
cdupaty | 0:ef20a9039c0c | 487 | // rslt = BMM150_E_INVALID_CONFIG; |
cdupaty | 0:ef20a9039c0c | 488 | // break; |
cdupaty | 0:ef20a9039c0c | 489 | // } |
cdupaty | 0:ef20a9039c0c | 490 | |
cdupaty | 0:ef20a9039c0c | 491 | // return rslt; |
cdupaty | 0:ef20a9039c0c | 492 | // } |
cdupaty | 0:ef20a9039c0c | 493 | |
cdupaty | 0:ef20a9039c0c | 494 | // /* |
cdupaty | 0:ef20a9039c0c | 495 | // * @brief This internal API is used to perform the normal self test |
cdupaty | 0:ef20a9039c0c | 496 | // * of the sensor and return the self test result as return value |
cdupaty | 0:ef20a9039c0c | 497 | // */ |
cdupaty | 0:ef20a9039c0c | 498 | // char BMM150::perform_normal_self_test() |
cdupaty | 0:ef20a9039c0c | 499 | // { |
cdupaty | 0:ef20a9039c0c | 500 | // char rslt; |
cdupaty | 0:ef20a9039c0c | 501 | // uint8_t self_test_bit; |
cdupaty | 0:ef20a9039c0c | 502 | |
cdupaty | 0:ef20a9039c0c | 503 | // /* Triggers the start of normal self test */ |
cdupaty | 0:ef20a9039c0c | 504 | // enable_normal_self_test(&self_test_bit); |
cdupaty | 0:ef20a9039c0c | 505 | // /* Check for self test completion status */ |
cdupaty | 0:ef20a9039c0c | 506 | // if (self_test_bit == 0) { |
cdupaty | 0:ef20a9039c0c | 507 | // /* Validates the self test results for all 3 axes */ |
cdupaty | 0:ef20a9039c0c | 508 | // rslt = validate_normal_self_test(); |
cdupaty | 0:ef20a9039c0c | 509 | // } |
cdupaty | 0:ef20a9039c0c | 510 | |
cdupaty | 0:ef20a9039c0c | 511 | // return rslt; |
cdupaty | 0:ef20a9039c0c | 512 | // } |
cdupaty | 0:ef20a9039c0c | 513 | |
cdupaty | 0:ef20a9039c0c | 514 | // /*! |
cdupaty | 0:ef20a9039c0c | 515 | // * @brief This internal API is used to enable the normal self test by setting |
cdupaty | 0:ef20a9039c0c | 516 | // * the Self Test bit (bit0) of the 0x4C register, |
cdupaty | 0:ef20a9039c0c | 517 | // * which triggers the start of self test |
cdupaty | 0:ef20a9039c0c | 518 | // */ |
cdupaty | 0:ef20a9039c0c | 519 | // void BMM150::enable_normal_self_test(uint8_t *self_test_enable) |
cdupaty | 0:ef20a9039c0c | 520 | // { |
cdupaty | 0:ef20a9039c0c | 521 | // uint8_t reg_data; |
cdupaty | 0:ef20a9039c0c | 522 | // uint8_t self_test_val; |
cdupaty | 0:ef20a9039c0c | 523 | |
cdupaty | 0:ef20a9039c0c | 524 | // /* Read the data from register 0x4C */ |
cdupaty | 0:ef20a9039c0c | 525 | // reg_data = i2c->read(BMM150_OP_MODE_ADDR); |
cdupaty | 0:ef20a9039c0c | 526 | // /* Set the Self Test bit(bit0) of the 0x4C register */ |
cdupaty | 0:ef20a9039c0c | 527 | // self_test_val = 1; |
cdupaty | 0:ef20a9039c0c | 528 | // reg_data = BMM150_SET_BITS_POS_0(reg_data, BMM150_SELF_TEST, self_test_val); |
cdupaty | 0:ef20a9039c0c | 529 | // /* Write the data to 0x4C register to trigger self test */ |
cdupaty | 0:ef20a9039c0c | 530 | // i2c_write(BMM150_OP_MODE_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 531 | // wait_ms(BMM150_NORMAL_SELF_TEST_wait_ms); |
cdupaty | 0:ef20a9039c0c | 532 | // /* Read the data from register 0x4C */ |
cdupaty | 0:ef20a9039c0c | 533 | // reg_data = i2c->read(BMM150_OP_MODE_ADDR); |
cdupaty | 0:ef20a9039c0c | 534 | // /* Self Test bit(bit0) is stored in self_test_enable, |
cdupaty | 0:ef20a9039c0c | 535 | // It will be reset to zero after the self test is over */ |
cdupaty | 0:ef20a9039c0c | 536 | // *self_test_enable = BMM150_GET_BITS_POS_0(reg_data, BMM150_SELF_TEST); |
cdupaty | 0:ef20a9039c0c | 537 | // } |
cdupaty | 0:ef20a9039c0c | 538 | |
cdupaty | 0:ef20a9039c0c | 539 | // /*! |
cdupaty | 0:ef20a9039c0c | 540 | // * @brief This internal API is used to validate the results of normal self test |
cdupaty | 0:ef20a9039c0c | 541 | // * by using the self test status available in the bit0 of registers 0x42,0x44 |
cdupaty | 0:ef20a9039c0c | 542 | // * and 0x46. |
cdupaty | 0:ef20a9039c0c | 543 | // */ |
cdupaty | 0:ef20a9039c0c | 544 | // char BMM150::validate_normal_self_test() |
cdupaty | 0:ef20a9039c0c | 545 | // { |
cdupaty | 0:ef20a9039c0c | 546 | // char rslt; |
cdupaty | 0:ef20a9039c0c | 547 | // uint8_t status; |
cdupaty | 0:ef20a9039c0c | 548 | // uint8_t self_test_rslt[5]; |
cdupaty | 0:ef20a9039c0c | 549 | |
cdupaty | 0:ef20a9039c0c | 550 | // /* Read the data from register 0x42 to 0x46 */ |
cdupaty | 0:ef20a9039c0c | 551 | // i2c->read(BMM150_DATA_X_LSB, self_test_rslt, BMM150_SELF_TEST_LEN); |
cdupaty | 0:ef20a9039c0c | 552 | // /* Parse and get the self test status bits */ |
cdupaty | 0:ef20a9039c0c | 553 | // /* X-Self-Test (bit0) of 0x42 register is stored*/ |
cdupaty | 0:ef20a9039c0c | 554 | // self_test_rslt[0] = BMM150_GET_BITS_POS_0(self_test_rslt[0], BMM150_SELF_TEST); |
cdupaty | 0:ef20a9039c0c | 555 | // /* Y-Self-Test (bit0) of 0x44 register is stored */ |
cdupaty | 0:ef20a9039c0c | 556 | // self_test_rslt[2] = BMM150_GET_BITS_POS_0(self_test_rslt[2], BMM150_SELF_TEST); |
cdupaty | 0:ef20a9039c0c | 557 | // /* Z-Self-Test (bit0) of 0x46 register is stored */ |
cdupaty | 0:ef20a9039c0c | 558 | // self_test_rslt[4] = BMM150_GET_BITS_POS_0(self_test_rslt[4], BMM150_SELF_TEST); |
cdupaty | 0:ef20a9039c0c | 559 | // /* Combine the self test status and store it in the first |
cdupaty | 0:ef20a9039c0c | 560 | // 3 bits of the status variable for processing*/ |
cdupaty | 0:ef20a9039c0c | 561 | // status = (uint8_t)((self_test_rslt[4] << 2) | (self_test_rslt[2] << 1) | self_test_rslt[0]); |
cdupaty | 0:ef20a9039c0c | 562 | // /* Validate status and store Self test result in "rslt" */ |
cdupaty | 0:ef20a9039c0c | 563 | // if (status == BMM150_SELF_TEST_STATUS_SUCCESS) { |
cdupaty | 0:ef20a9039c0c | 564 | // /* Self test is success when all status bits are set */ |
cdupaty | 0:ef20a9039c0c | 565 | // rslt = BMM150_OK; |
cdupaty | 0:ef20a9039c0c | 566 | // } else { |
cdupaty | 0:ef20a9039c0c | 567 | // if (status == BMM150_SELF_TEST_STATUS_XYZ_FAIL) { |
cdupaty | 0:ef20a9039c0c | 568 | // /* Self test - all axis fail condition */ |
cdupaty | 0:ef20a9039c0c | 569 | // rslt = BMM150_W_NORMAL_SELF_TEST_XYZ_FAIL; |
cdupaty | 0:ef20a9039c0c | 570 | // } else { |
cdupaty | 0:ef20a9039c0c | 571 | // /* Self test - some axis fail condition */ |
cdupaty | 0:ef20a9039c0c | 572 | // rslt = (char)status; |
cdupaty | 0:ef20a9039c0c | 573 | // } |
cdupaty | 0:ef20a9039c0c | 574 | // } |
cdupaty | 0:ef20a9039c0c | 575 | |
cdupaty | 0:ef20a9039c0c | 576 | // return rslt; |
cdupaty | 0:ef20a9039c0c | 577 | // } |
cdupaty | 0:ef20a9039c0c | 578 | |
cdupaty | 0:ef20a9039c0c | 579 | // /*! |
cdupaty | 0:ef20a9039c0c | 580 | // * @brief This internal API is used to perform advanced self test for Z axis |
cdupaty | 0:ef20a9039c0c | 581 | // */ |
cdupaty | 0:ef20a9039c0c | 582 | // char BMM150::perform_adv_self_test() |
cdupaty | 0:ef20a9039c0c | 583 | // { |
cdupaty | 0:ef20a9039c0c | 584 | // uint8_t self_test_current; |
cdupaty | 0:ef20a9039c0c | 585 | // int16_t positive_data_z; |
cdupaty | 0:ef20a9039c0c | 586 | // int16_t negative_data_z; |
cdupaty | 0:ef20a9039c0c | 587 | // char rslt; |
cdupaty | 0:ef20a9039c0c | 588 | |
cdupaty | 0:ef20a9039c0c | 589 | // /* Set the desired power mode ,axes control and repetition settings */ |
cdupaty | 0:ef20a9039c0c | 590 | // adv_self_test_settings(); |
cdupaty | 0:ef20a9039c0c | 591 | // /* Measure the Z axes data with positive self-test current */ |
cdupaty | 0:ef20a9039c0c | 592 | // self_test_current = BMM150_ENABLE_POSITIVE_CURRENT; |
cdupaty | 0:ef20a9039c0c | 593 | // adv_self_test_measurement(self_test_current, &positive_data_z); |
cdupaty | 0:ef20a9039c0c | 594 | // /* Measure the Z axes data with |
cdupaty | 0:ef20a9039c0c | 595 | // negative self-test current */ |
cdupaty | 0:ef20a9039c0c | 596 | // self_test_current = BMM150_ENABLE_NEGATIVE_CURRENT; |
cdupaty | 0:ef20a9039c0c | 597 | // adv_self_test_measurement(self_test_current, &negative_data_z); |
cdupaty | 0:ef20a9039c0c | 598 | // /* Disable self-test current */ |
cdupaty | 0:ef20a9039c0c | 599 | // self_test_current = BMM150_DISABLE_SELF_TEST_CURRENT; |
cdupaty | 0:ef20a9039c0c | 600 | // set_adv_self_test_current(self_test_current); |
cdupaty | 0:ef20a9039c0c | 601 | // /* Validate the advanced self test */ |
cdupaty | 0:ef20a9039c0c | 602 | // rslt = validate_adv_self_test(positive_data_z, negative_data_z); |
cdupaty | 0:ef20a9039c0c | 603 | |
cdupaty | 0:ef20a9039c0c | 604 | // return rslt; |
cdupaty | 0:ef20a9039c0c | 605 | // } |
cdupaty | 0:ef20a9039c0c | 606 | |
cdupaty | 0:ef20a9039c0c | 607 | // /*! |
cdupaty | 0:ef20a9039c0c | 608 | // * @brief This internal API is used to set the desired power mode , |
cdupaty | 0:ef20a9039c0c | 609 | // * axes control and repetition settings for advanced self test |
cdupaty | 0:ef20a9039c0c | 610 | // */ |
cdupaty | 0:ef20a9039c0c | 611 | // void BMM150::adv_self_test_settings() |
cdupaty | 0:ef20a9039c0c | 612 | // { |
cdupaty | 0:ef20a9039c0c | 613 | // /* Set the power mode as sleep mode */ |
cdupaty | 0:ef20a9039c0c | 614 | // settings.pwr_mode = BMM150_SLEEP_MODE; |
cdupaty | 0:ef20a9039c0c | 615 | // set_op_mode(BMM150_SLEEP_MODE); |
cdupaty | 0:ef20a9039c0c | 616 | // /* Disable XY-axis measurement */ |
cdupaty | 0:ef20a9039c0c | 617 | // settings.xyz_axes_control = BMM150_DISABLE_XY_AXIS; |
cdupaty | 0:ef20a9039c0c | 618 | // set_control_measurement_xyz(settings); |
cdupaty | 0:ef20a9039c0c | 619 | // /* Repetition value is set as 0x04 */ |
cdupaty | 0:ef20a9039c0c | 620 | // settings.z_rep = BMM150_SELF_TEST_REP_Z; |
cdupaty | 0:ef20a9039c0c | 621 | // set_z_rep(settings); |
cdupaty | 0:ef20a9039c0c | 622 | // } |
cdupaty | 0:ef20a9039c0c | 623 | |
cdupaty | 0:ef20a9039c0c | 624 | // /*! |
cdupaty | 0:ef20a9039c0c | 625 | // * @brief This internal API is used to set the positive or negative value of |
cdupaty | 0:ef20a9039c0c | 626 | // * self-test current and obtain the corresponding magnetometer z axis data |
cdupaty | 0:ef20a9039c0c | 627 | // */ |
cdupaty | 0:ef20a9039c0c | 628 | // void BMM150::adv_self_test_measurement(uint8_t self_test_current, int16_t *data_z) |
cdupaty | 0:ef20a9039c0c | 629 | // { |
cdupaty | 0:ef20a9039c0c | 630 | // /* Set the advanced self test current as positive or |
cdupaty | 0:ef20a9039c0c | 631 | // negative based on the value of parameter "self_test_current" */ |
cdupaty | 0:ef20a9039c0c | 632 | // set_adv_self_test_current(self_test_current); |
cdupaty | 0:ef20a9039c0c | 633 | // /* Set the device in forced mode*/ |
cdupaty | 0:ef20a9039c0c | 634 | // settings.pwr_mode = BMM150_FORCED_MODE; |
cdupaty | 0:ef20a9039c0c | 635 | // set_op_mode(BMM150_FORCED_MODE); |
cdupaty | 0:ef20a9039c0c | 636 | // /* wait_ms to ensure measurement is complete */ |
cdupaty | 0:ef20a9039c0c | 637 | // wait_ms(4); |
cdupaty | 0:ef20a9039c0c | 638 | // /* Read Mag data and store the value of Z axis data */ |
cdupaty | 0:ef20a9039c0c | 639 | // read_mag_data(); |
cdupaty | 0:ef20a9039c0c | 640 | // /* Mag Z axis data is stored */ |
cdupaty | 0:ef20a9039c0c | 641 | // *data_z = mag_data.z; |
cdupaty | 0:ef20a9039c0c | 642 | // } |
cdupaty | 0:ef20a9039c0c | 643 | |
cdupaty | 0:ef20a9039c0c | 644 | // /*! |
cdupaty | 0:ef20a9039c0c | 645 | // * @brief This internal API is used to get the difference between the |
cdupaty | 0:ef20a9039c0c | 646 | // * Z axis mag data obtained by positive and negative self-test current |
cdupaty | 0:ef20a9039c0c | 647 | // * and validate whether the advanced self test is done successfully or not. |
cdupaty | 0:ef20a9039c0c | 648 | // */ |
cdupaty | 0:ef20a9039c0c | 649 | // char BMM150::validate_adv_self_test(int16_t positive_data_z, int16_t negative_data_z) |
cdupaty | 0:ef20a9039c0c | 650 | // { |
cdupaty | 0:ef20a9039c0c | 651 | // int32_t adv_self_test_rslt; |
cdupaty | 0:ef20a9039c0c | 652 | // char rslt; |
cdupaty | 0:ef20a9039c0c | 653 | |
cdupaty | 0:ef20a9039c0c | 654 | // /* Advanced self test difference between the Z axis mag data |
cdupaty | 0:ef20a9039c0c | 655 | // obtained by the positive and negative self-test current */ |
cdupaty | 0:ef20a9039c0c | 656 | // adv_self_test_rslt = positive_data_z - negative_data_z; |
cdupaty | 0:ef20a9039c0c | 657 | // /* Advanced self test validation */ |
cdupaty | 0:ef20a9039c0c | 658 | // /*Value of adv_self_test_rslt should be in between 180-240 micro-tesla*/ |
cdupaty | 0:ef20a9039c0c | 659 | // if ((adv_self_test_rslt > 180) && (adv_self_test_rslt < 240)) { |
cdupaty | 0:ef20a9039c0c | 660 | // /* Advanced self test success */ |
cdupaty | 0:ef20a9039c0c | 661 | // rslt = BMM150_OK; |
cdupaty | 0:ef20a9039c0c | 662 | // } else { |
cdupaty | 0:ef20a9039c0c | 663 | // /* Advanced self test fail */ |
cdupaty | 0:ef20a9039c0c | 664 | // rslt = BMM150_W_ADV_SELF_TEST_FAIL; |
cdupaty | 0:ef20a9039c0c | 665 | // } |
cdupaty | 0:ef20a9039c0c | 666 | |
cdupaty | 0:ef20a9039c0c | 667 | // return rslt; |
cdupaty | 0:ef20a9039c0c | 668 | // } |
cdupaty | 0:ef20a9039c0c | 669 | |
cdupaty | 0:ef20a9039c0c | 670 | // /* |
cdupaty | 0:ef20a9039c0c | 671 | // * @brief This internal API is used to set the self test current value in |
cdupaty | 0:ef20a9039c0c | 672 | // * the Adv. ST bits (bit6 and bit7) of 0x4C register |
cdupaty | 0:ef20a9039c0c | 673 | // */ |
cdupaty | 0:ef20a9039c0c | 674 | // void BMM150::set_adv_self_test_current(uint8_t self_test_current) |
cdupaty | 0:ef20a9039c0c | 675 | // { |
cdupaty | 0:ef20a9039c0c | 676 | // uint8_t reg_data; |
cdupaty | 0:ef20a9039c0c | 677 | |
cdupaty | 0:ef20a9039c0c | 678 | // /* Read the 0x4C register */ |
cdupaty | 0:ef20a9039c0c | 679 | // reg_data = i2c->read(BMM150_OP_MODE_ADDR); |
cdupaty | 0:ef20a9039c0c | 680 | // /* Set the self test current value in the Adv. ST bits |
cdupaty | 0:ef20a9039c0c | 681 | // (bit6 and bit7) of 0x4c register */ |
cdupaty | 0:ef20a9039c0c | 682 | // reg_data = BMM150_SET_BITS(reg_data, BMM150_ADV_SELF_TEST, self_test_current); |
cdupaty | 0:ef20a9039c0c | 683 | // i2c_write(BMM150_OP_MODE_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 684 | |
cdupaty | 0:ef20a9039c0c | 685 | // } |
cdupaty | 0:ef20a9039c0c | 686 | |
cdupaty | 0:ef20a9039c0c | 687 | // /* |
cdupaty | 0:ef20a9039c0c | 688 | // * @brief This internal API is used to enable or disable the magnetic |
cdupaty | 0:ef20a9039c0c | 689 | // * measurement of x,y,z axes based on the value of xyz_axes_control. |
cdupaty | 0:ef20a9039c0c | 690 | // */ |
cdupaty | 0:ef20a9039c0c | 691 | // void BMM150::set_control_measurement_xyz(struct bmm150_settings settings) |
cdupaty | 0:ef20a9039c0c | 692 | // { |
cdupaty | 0:ef20a9039c0c | 693 | // uint8_t reg_data; |
cdupaty | 0:ef20a9039c0c | 694 | |
cdupaty | 0:ef20a9039c0c | 695 | // reg_data = i2c->read(BMM150_AXES_ENABLE_ADDR); |
cdupaty | 0:ef20a9039c0c | 696 | // /* Set the axes to be enabled/disabled*/ |
cdupaty | 0:ef20a9039c0c | 697 | // reg_data = BMM150_SET_BITS(reg_data, BMM150_CONTROL_MEASURE, settings.xyz_axes_control); |
cdupaty | 0:ef20a9039c0c | 698 | // i2c_write(BMM150_AXES_ENABLE_ADDR, reg_data); |
cdupaty | 0:ef20a9039c0c | 699 | // } |