First draft HMC5883 magnetometer sensor using physical quantities, outputting via serial port using std::cout on mbed os 5

Committer:
skyscraper
Date:
Tue Mar 24 22:43:44 2020 +0000
Revision:
3:2834be4e10ef
Parent:
2:9ffb2f18756b
Child:
7:5d14da0b4c95
Moved calibrate function out to separate source file.; Added raw values function

Who changed what in which revision?

UserRevisionLine numberNew contents of line
skyscraper 2:9ffb2f18756b 1
skyscraper 2:9ffb2f18756b 2
skyscraper 2:9ffb2f18756b 3 #include "mbed.h"
skyscraper 2:9ffb2f18756b 4 #include <iostream>
skyscraper 2:9ffb2f18756b 5 #include <quan/out/magnetic_flux_density.hpp>
skyscraper 2:9ffb2f18756b 6 #include <quan/three_d/out/vect.hpp>
skyscraper 2:9ffb2f18756b 7
skyscraper 3:2834be4e10ef 8 /*
skyscraper 3:2834be4e10ef 9
skyscraper 3:2834be4e10ef 10 MySensor sensor;
skyscraper 3:2834be4e10ef 11
skyscraper 3:2834be4e10ef 12 "HMC5883" -> HMC5883
skyscraper 3:2834be4e10ef 13 I2C ->
skyscraper 3:2834be4e10ef 14 list of I2CBuses
skyscraper 3:2834be4e10ef 15 I2CBusID -> I2C(I2C_SCL,I2C_SDA)
skyscraper 3:2834be4e10ef 16 I2CAddress -> "0x3d" atoi -> 0x3D
skyscraper 3:2834be4e10ef 17
skyscraper 3:2834be4e10ef 18 if (!sensor.open("HMC5883L.I2C[I2CBusID,0x3d]")){
skyscraper 3:2834be4e10ef 19 loop_forever("failed to open \"HMC5883L.I2C[I2CBusID,0x3d]\"");
skyscraper 3:2834be4e10ef 20 }
skyscraper 3:2834be4e10ef 21 sensor.Attach(50.0_Hz, onMagDataUpdated);
skyscraper 3:2834be4e10ef 22 sensor.run();
skyscraper 3:2834be4e10ef 23
skyscraper 3:2834be4e10ef 24 template <typename Quantity>
skyscraper 3:2834be4e10ef 25 struct Sensor{
skyscraper 3:2834be4e10ef 26 static bool open(Sensor& sensor, const char* name);
skyscraper 3:2834be4e10ef 27 bool connected()const;
skyscraper 3:2834be4e10ef 28 bool running() const;
skyscraper 3:2834be4e10ef 29 bool idle() const
skyscraper 3:2834be4e10ef 30 void close();
skyscraper 3:2834be4e10ef 31 bool read(Quantity & q);
skyscraper 3:2834be4e10ef 32 setUpdateCallback(void(*pFun)());
skyscraper 3:2834be4e10ef 33 };
skyscraper 3:2834be4e10ef 34 */
skyscraper 3:2834be4e10ef 35
skyscraper 2:9ffb2f18756b 36 namespace {
skyscraper 2:9ffb2f18756b 37 /*
skyscraper 2:9ffb2f18756b 38 00 Configuration Register A R/W
skyscraper 2:9ffb2f18756b 39 01 Configuration Register B R/W
skyscraper 2:9ffb2f18756b 40 02 Mode Register R/W
skyscraper 2:9ffb2f18756b 41 03 Data Output X MSB Register R
skyscraper 2:9ffb2f18756b 42 04 Data Output X LSB Register R
skyscraper 2:9ffb2f18756b 43 05 Data Output Z MSB Register R
skyscraper 2:9ffb2f18756b 44 06 Data Output Z LSB Register R
skyscraper 2:9ffb2f18756b 45 07 Data Output Y MSB Register R
skyscraper 2:9ffb2f18756b 46 08 Data Output Y LSB Register R
skyscraper 2:9ffb2f18756b 47 09 Status Register R
skyscraper 2:9ffb2f18756b 48 10 Identification Register A R
skyscraper 2:9ffb2f18756b 49 11 Identification Register B R
skyscraper 2:9ffb2f18756b 50 12 Identification Register C R
skyscraper 2:9ffb2f18756b 51 */
skyscraper 2:9ffb2f18756b 52
skyscraper 2:9ffb2f18756b 53 I2C i2c(I2C_SDA, I2C_SCL );
skyscraper 2:9ffb2f18756b 54 constexpr uint8_t i2c_addr = 0x3D;
skyscraper 2:9ffb2f18756b 55 constexpr char cfg_regA = 0;
skyscraper 2:9ffb2f18756b 56 constexpr char cfg_regB = 1;
skyscraper 2:9ffb2f18756b 57 constexpr char mode_reg = 2;
skyscraper 2:9ffb2f18756b 58 constexpr char dout_reg = 3;
skyscraper 2:9ffb2f18756b 59 constexpr char status_reg = 9;
skyscraper 2:9ffb2f18756b 60 constexpr char id_regA = 10U;
skyscraper 2:9ffb2f18756b 61
skyscraper 2:9ffb2f18756b 62 // Set reg index to idx_in
skyscraper 2:9ffb2f18756b 63 // return true if successful
skyscraper 2:9ffb2f18756b 64 bool mag_set_reg_idx(uint8_t idx_in)
skyscraper 2:9ffb2f18756b 65 {
skyscraper 2:9ffb2f18756b 66 char const idx = static_cast<char>(idx_in);
skyscraper 3:2834be4e10ef 67 i2c.lock();
skyscraper 3:2834be4e10ef 68 bool const result = i2c.write(i2c_addr,&idx,1) == 0;
skyscraper 3:2834be4e10ef 69 i2c.unlock();
skyscraper 2:9ffb2f18756b 70 if(result) {
skyscraper 2:9ffb2f18756b 71 return true;
skyscraper 2:9ffb2f18756b 72 } else {
skyscraper 2:9ffb2f18756b 73 std::cout << "mag_set_reg_idx failed\n";
skyscraper 2:9ffb2f18756b 74 return false;
skyscraper 2:9ffb2f18756b 75 }
skyscraper 2:9ffb2f18756b 76 }
skyscraper 2:9ffb2f18756b 77
skyscraper 2:9ffb2f18756b 78 // Write reg at idx with val
skyscraper 2:9ffb2f18756b 79 // return true if successful
skyscraper 2:9ffb2f18756b 80 bool mag_write_reg(uint8_t idx, uint8_t val)
skyscraper 2:9ffb2f18756b 81 {
skyscraper 2:9ffb2f18756b 82 char ar[2] = {idx,val};
skyscraper 3:2834be4e10ef 83 i2c.lock();
skyscraper 3:2834be4e10ef 84 bool const result = i2c.write(i2c_addr,ar,2) == 0;
skyscraper 3:2834be4e10ef 85 i2c.unlock();
skyscraper 2:9ffb2f18756b 86 if(result) {
skyscraper 2:9ffb2f18756b 87 return true;
skyscraper 2:9ffb2f18756b 88 } else {
skyscraper 2:9ffb2f18756b 89 std::cout << " mag_write_reg failed\n";
skyscraper 2:9ffb2f18756b 90 return false;
skyscraper 2:9ffb2f18756b 91 }
skyscraper 2:9ffb2f18756b 92 }
skyscraper 2:9ffb2f18756b 93
skyscraper 2:9ffb2f18756b 94 // Read reg at idx to result
skyscraper 2:9ffb2f18756b 95 // return true if successfull
skyscraper 2:9ffb2f18756b 96 bool mag_get_reg(uint8_t idx_in, uint8_t& result)
skyscraper 2:9ffb2f18756b 97 {
skyscraper 2:9ffb2f18756b 98 if ( mag_set_reg_idx(idx_in)) {
skyscraper 3:2834be4e10ef 99 char temp_result = 0;
skyscraper 3:2834be4e10ef 100 i2c.lock();
skyscraper 3:2834be4e10ef 101 bool const success = i2c.read(i2c_addr,&temp_result,1) == 0;
skyscraper 3:2834be4e10ef 102 i2c.unlock();
skyscraper 3:2834be4e10ef 103 if (success) {
skyscraper 3:2834be4e10ef 104 result = temp_result;
skyscraper 2:9ffb2f18756b 105 return true;
skyscraper 2:9ffb2f18756b 106 } else {
skyscraper 2:9ffb2f18756b 107 std::cout << "mag_get_reg read failed\n";
skyscraper 2:9ffb2f18756b 108 return false;
skyscraper 2:9ffb2f18756b 109 }
skyscraper 2:9ffb2f18756b 110 } else {
skyscraper 2:9ffb2f18756b 111 return false;
skyscraper 2:9ffb2f18756b 112 }
skyscraper 2:9ffb2f18756b 113 }
skyscraper 2:9ffb2f18756b 114
skyscraper 2:9ffb2f18756b 115 // Update value in reg using and and or masks
skyscraper 2:9ffb2f18756b 116 // reg <-- (reg & and_val) | or_val
skyscraper 2:9ffb2f18756b 117 // return true if successfull
skyscraper 2:9ffb2f18756b 118 bool mag_modify_reg(uint8_t idx, uint8_t and_val, uint8_t or_val)
skyscraper 2:9ffb2f18756b 119 {
skyscraper 2:9ffb2f18756b 120 uint8_t cur_val = 0;
skyscraper 2:9ffb2f18756b 121 if(mag_get_reg(idx,cur_val)) {
skyscraper 2:9ffb2f18756b 122 uint8_t const new_val = (cur_val & and_val ) | or_val;
skyscraper 2:9ffb2f18756b 123 return mag_write_reg(idx,new_val);
skyscraper 2:9ffb2f18756b 124 } else {
skyscraper 2:9ffb2f18756b 125 return false;
skyscraper 2:9ffb2f18756b 126 }
skyscraper 2:9ffb2f18756b 127 }
skyscraper 2:9ffb2f18756b 128
skyscraper 2:9ffb2f18756b 129 } // namespace
skyscraper 2:9ffb2f18756b 130
skyscraper 2:9ffb2f18756b 131 // probe for the HMC5883 on I2C
skyscraper 2:9ffb2f18756b 132 // return true if found
skyscraper 2:9ffb2f18756b 133 bool mag_detected()
skyscraper 2:9ffb2f18756b 134 {
skyscraper 2:9ffb2f18756b 135 if ( mag_set_reg_idx(id_regA) ) {
skyscraper 2:9ffb2f18756b 136 char id_input[4];
skyscraper 3:2834be4e10ef 137 i2c.lock();
skyscraper 3:2834be4e10ef 138 bool success = i2c.read(i2c_addr,id_input,3) == 0;
skyscraper 3:2834be4e10ef 139 i2c.unlock();
skyscraper 3:2834be4e10ef 140 if(success) {
skyscraper 2:9ffb2f18756b 141 id_input[3] = '\0';
skyscraper 2:9ffb2f18756b 142 bool const is_hmc = (strcmp(id_input,"H43") == 0);
skyscraper 2:9ffb2f18756b 143 if (is_hmc) {
skyscraper 2:9ffb2f18756b 144 return true;
skyscraper 2:9ffb2f18756b 145 } else {
skyscraper 2:9ffb2f18756b 146 std::cout << "hmc5883 ID string didnt match\n";
skyscraper 2:9ffb2f18756b 147 return false;
skyscraper 2:9ffb2f18756b 148 }
skyscraper 2:9ffb2f18756b 149 } else {
skyscraper 2:9ffb2f18756b 150 std::cout << "id mag read failed\n";
skyscraper 2:9ffb2f18756b 151 return false;
skyscraper 2:9ffb2f18756b 152 }
skyscraper 2:9ffb2f18756b 153 } else {
skyscraper 2:9ffb2f18756b 154 return false;
skyscraper 2:9ffb2f18756b 155 }
skyscraper 2:9ffb2f18756b 156 }
skyscraper 2:9ffb2f18756b 157
skyscraper 2:9ffb2f18756b 158 // only 1,2,4,8 available
skyscraper 2:9ffb2f18756b 159 bool mag_set_samples_average(int n_samples)
skyscraper 2:9ffb2f18756b 160 {
skyscraper 2:9ffb2f18756b 161 uint8_t or_val = 0;
skyscraper 2:9ffb2f18756b 162 switch (n_samples) {
skyscraper 2:9ffb2f18756b 163 case 1 :
skyscraper 2:9ffb2f18756b 164 or_val = 0b00U << 5U;
skyscraper 2:9ffb2f18756b 165 break;
skyscraper 2:9ffb2f18756b 166 case 2 :
skyscraper 2:9ffb2f18756b 167 or_val = 0b01U << 5U;
skyscraper 2:9ffb2f18756b 168 break;
skyscraper 2:9ffb2f18756b 169 case 4 :
skyscraper 2:9ffb2f18756b 170 or_val = 0b10U << 5U;
skyscraper 2:9ffb2f18756b 171 break;
skyscraper 2:9ffb2f18756b 172 case 8 :
skyscraper 2:9ffb2f18756b 173 or_val = 0b11U << 5U;
skyscraper 2:9ffb2f18756b 174 break;
skyscraper 2:9ffb2f18756b 175 default:
skyscraper 2:9ffb2f18756b 176 std::cout << "mag_set_samples_average : invalid n_samples (" << n_samples << ")\n";
skyscraper 2:9ffb2f18756b 177 return false;
skyscraper 2:9ffb2f18756b 178 }
skyscraper 2:9ffb2f18756b 179 uint8_t constexpr and_val = ~(0b11 << 5U);
skyscraper 2:9ffb2f18756b 180 return mag_modify_reg(cfg_regA,and_val,or_val);
skyscraper 2:9ffb2f18756b 181 }
skyscraper 2:9ffb2f18756b 182
skyscraper 2:9ffb2f18756b 183 /*
skyscraper 2:9ffb2f18756b 184 data rate 0.75, 1.5, 3 ,7.5, 15 (Default) , 30, 75
skyscraper 2:9ffb2f18756b 185 */
skyscraper 2:9ffb2f18756b 186 namespace {
skyscraper 2:9ffb2f18756b 187
skyscraper 2:9ffb2f18756b 188 template <int N, int D=1> struct mag_data_rate_id;
skyscraper 2:9ffb2f18756b 189 // values are mag settings for each data rate
skyscraper 2:9ffb2f18756b 190 template <> struct mag_data_rate_id<3,4> : std::integral_constant<uint8_t,(0b000U << 2U)> {};
skyscraper 2:9ffb2f18756b 191 template <> struct mag_data_rate_id<3,2> : std::integral_constant<uint8_t,(0b001U << 2U)> {};
skyscraper 2:9ffb2f18756b 192 template <> struct mag_data_rate_id<3> : std::integral_constant<uint8_t,(0b010U << 2U)> {};
skyscraper 2:9ffb2f18756b 193 template <> struct mag_data_rate_id<15,2> : std::integral_constant<uint8_t,(0b011U << 2U)> {};
skyscraper 2:9ffb2f18756b 194 template <> struct mag_data_rate_id<15> : std::integral_constant<uint8_t,(0b100U << 2U)> {};
skyscraper 2:9ffb2f18756b 195 template <> struct mag_data_rate_id<30> : std::integral_constant<uint8_t,(0b101U << 2U)> {};
skyscraper 2:9ffb2f18756b 196 template <> struct mag_data_rate_id<75> : std::integral_constant<uint8_t,(0b110U << 2U)> {};
skyscraper 2:9ffb2f18756b 197
skyscraper 2:9ffb2f18756b 198 }//namespace
skyscraper 2:9ffb2f18756b 199
skyscraper 2:9ffb2f18756b 200 template <int N, int D>
skyscraper 2:9ffb2f18756b 201 bool mag_set_data_rate()
skyscraper 2:9ffb2f18756b 202 {
skyscraper 2:9ffb2f18756b 203 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b111U << 2U));
skyscraper 2:9ffb2f18756b 204 uint8_t constexpr or_val = mag_data_rate_id<N,D>::value;
skyscraper 2:9ffb2f18756b 205 return mag_modify_reg(cfg_regA,and_val,or_val);
skyscraper 2:9ffb2f18756b 206 }
skyscraper 2:9ffb2f18756b 207
skyscraper 2:9ffb2f18756b 208 template bool mag_set_data_rate<3,4>();
skyscraper 2:9ffb2f18756b 209 template bool mag_set_data_rate<3,2>();
skyscraper 2:9ffb2f18756b 210 template bool mag_set_data_rate<3,1>();
skyscraper 2:9ffb2f18756b 211 template bool mag_set_data_rate<15,2>();
skyscraper 2:9ffb2f18756b 212 template bool mag_set_data_rate<15,1>();
skyscraper 2:9ffb2f18756b 213 template bool mag_set_data_rate<30,1>();
skyscraper 2:9ffb2f18756b 214 template bool mag_set_data_rate<75,1>();
skyscraper 2:9ffb2f18756b 215
skyscraper 2:9ffb2f18756b 216 namespace {
skyscraper 2:9ffb2f18756b 217
skyscraper 2:9ffb2f18756b 218 bool mag_set_positive_bias()
skyscraper 2:9ffb2f18756b 219 {
skyscraper 2:9ffb2f18756b 220 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 221 uint8_t constexpr or_val = 0b01U;
skyscraper 2:9ffb2f18756b 222 return mag_modify_reg(cfg_regA,and_val,or_val);
skyscraper 2:9ffb2f18756b 223 }
skyscraper 2:9ffb2f18756b 224
skyscraper 2:9ffb2f18756b 225 bool mag_set_negative_bias()
skyscraper 2:9ffb2f18756b 226 {
skyscraper 2:9ffb2f18756b 227 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 228 uint8_t constexpr or_val = 0b10U;
skyscraper 2:9ffb2f18756b 229 return mag_modify_reg(cfg_regA,and_val,or_val);
skyscraper 2:9ffb2f18756b 230 }
skyscraper 2:9ffb2f18756b 231
skyscraper 2:9ffb2f18756b 232 bool mag_clear_bias()
skyscraper 2:9ffb2f18756b 233 {
skyscraper 2:9ffb2f18756b 234 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 235 uint8_t constexpr or_val = 0b00U;
skyscraper 2:9ffb2f18756b 236 return mag_modify_reg(cfg_regA,and_val,or_val);
skyscraper 2:9ffb2f18756b 237 }
skyscraper 2:9ffb2f18756b 238
skyscraper 2:9ffb2f18756b 239 QUAN_QUANTITY_LITERAL(magnetic_flux_density,gauss);
skyscraper 2:9ffb2f18756b 240 QUAN_QUANTITY_LITERAL(magnetic_flux_density,milli_gauss);
skyscraper 2:9ffb2f18756b 241 QUAN_QUANTITY_LITERAL(magnetic_flux_density,uT);
skyscraper 2:9ffb2f18756b 242
skyscraper 2:9ffb2f18756b 243 // per lsb defualt resolution
skyscraper 2:9ffb2f18756b 244 quan::magnetic_flux_density::uT mag_resolution = 0.92_milli_gauss;
skyscraper 2:9ffb2f18756b 245 // range before saturation
skyscraper 2:9ffb2f18756b 246 quan::magnetic_flux_density::uT mag_range = 1.3_gauss;
skyscraper 2:9ffb2f18756b 247 }
skyscraper 2:9ffb2f18756b 248
skyscraper 2:9ffb2f18756b 249 // set +- range
skyscraper 2:9ffb2f18756b 250 // sets the nearest greater equal +-range to abs(range_in)
skyscraper 2:9ffb2f18756b 251 bool mag_set_range(quan::magnetic_flux_density::uT const & range_in)
skyscraper 2:9ffb2f18756b 252 {
skyscraper 2:9ffb2f18756b 253 uint8_t or_value = 0;
skyscraper 2:9ffb2f18756b 254 auto const range = abs(range_in);
skyscraper 2:9ffb2f18756b 255
skyscraper 2:9ffb2f18756b 256 if ( range <= 0.88_gauss) {
skyscraper 2:9ffb2f18756b 257 or_value = 0b001U << 5U ;
skyscraper 2:9ffb2f18756b 258 mag_range = 0.88_gauss;
skyscraper 2:9ffb2f18756b 259 mag_resolution = 0.73_milli_gauss;
skyscraper 2:9ffb2f18756b 260 } else if (range <= 1.3_gauss) {
skyscraper 2:9ffb2f18756b 261 or_value = 0b001U << 5U ;
skyscraper 2:9ffb2f18756b 262 mag_range = 1.3_gauss;
skyscraper 2:9ffb2f18756b 263 mag_resolution = 0.92_milli_gauss;
skyscraper 2:9ffb2f18756b 264 } else if (range <= 1.9_gauss) {
skyscraper 2:9ffb2f18756b 265 or_value = 0b010U << 5U ;
skyscraper 2:9ffb2f18756b 266 mag_range = 1.9_gauss;
skyscraper 2:9ffb2f18756b 267 mag_resolution = 1.22_milli_gauss;
skyscraper 2:9ffb2f18756b 268 } else if (range <= 2.5_gauss) {
skyscraper 2:9ffb2f18756b 269 or_value = 0b011U << 5U ;
skyscraper 2:9ffb2f18756b 270 mag_range = 2.5_gauss;
skyscraper 2:9ffb2f18756b 271 mag_resolution = 1.52_milli_gauss;
skyscraper 2:9ffb2f18756b 272 } else if (range <= 4.0_gauss) {
skyscraper 2:9ffb2f18756b 273 or_value = 0b100U << 5U ;
skyscraper 2:9ffb2f18756b 274 mag_range = 4.0_gauss;
skyscraper 2:9ffb2f18756b 275 mag_resolution = 2.27_milli_gauss;
skyscraper 2:9ffb2f18756b 276 } else if (range <= 4.7_gauss) {
skyscraper 2:9ffb2f18756b 277 or_value = 0b101U << 5U ;
skyscraper 2:9ffb2f18756b 278 mag_range = 4.7_gauss;
skyscraper 2:9ffb2f18756b 279 mag_resolution = 2.56_milli_gauss;
skyscraper 2:9ffb2f18756b 280 } else if (range <=5.6_gauss) {
skyscraper 2:9ffb2f18756b 281 or_value = 0b110U << 5U ;
skyscraper 2:9ffb2f18756b 282 mag_range = 5.6_gauss;
skyscraper 2:9ffb2f18756b 283 mag_resolution = 3.03_milli_gauss;
skyscraper 2:9ffb2f18756b 284 } else if ( range <= 8.1_gauss) {
skyscraper 2:9ffb2f18756b 285 or_value = 0b111U << 5U ;
skyscraper 2:9ffb2f18756b 286 mag_range = 8.1_gauss;
skyscraper 2:9ffb2f18756b 287 mag_resolution = 4.35_milli_gauss;
skyscraper 2:9ffb2f18756b 288 } else {
skyscraper 2:9ffb2f18756b 289 quan::magnetic_flux_density::uT constexpr max_range = 8.1_gauss;
skyscraper 2:9ffb2f18756b 290 std::cout << "range too big: max +- range = " << max_range <<"\n";
skyscraper 2:9ffb2f18756b 291 return false;
skyscraper 2:9ffb2f18756b 292 }
skyscraper 2:9ffb2f18756b 293 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b111U << 5U));
skyscraper 2:9ffb2f18756b 294 std::cout << "mag range set to : +- " << mag_range <<'\n';
skyscraper 2:9ffb2f18756b 295 return mag_modify_reg(cfg_regB,and_val,or_value);
skyscraper 2:9ffb2f18756b 296
skyscraper 2:9ffb2f18756b 297 }
skyscraper 2:9ffb2f18756b 298
skyscraper 2:9ffb2f18756b 299 quan::magnetic_flux_density::uT
skyscraper 2:9ffb2f18756b 300 mag_get_range()
skyscraper 2:9ffb2f18756b 301 {
skyscraper 2:9ffb2f18756b 302 return mag_range;
skyscraper 2:9ffb2f18756b 303 }
skyscraper 2:9ffb2f18756b 304
skyscraper 2:9ffb2f18756b 305 bool mag_set_continuous_measurement_mode()
skyscraper 2:9ffb2f18756b 306 {
skyscraper 2:9ffb2f18756b 307 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 308 uint8_t constexpr or_val = 0b00U;
skyscraper 2:9ffb2f18756b 309 return mag_modify_reg(mode_reg,and_val,or_val);
skyscraper 2:9ffb2f18756b 310 }
skyscraper 2:9ffb2f18756b 311
skyscraper 2:9ffb2f18756b 312 bool mag_set_single_measurement_mode()
skyscraper 2:9ffb2f18756b 313 {
skyscraper 2:9ffb2f18756b 314 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 315 uint8_t constexpr or_val = 0b01U;
skyscraper 2:9ffb2f18756b 316 return mag_modify_reg(mode_reg,and_val,or_val);
skyscraper 2:9ffb2f18756b 317 }
skyscraper 2:9ffb2f18756b 318
skyscraper 2:9ffb2f18756b 319 bool mag_set_idle_mode()
skyscraper 2:9ffb2f18756b 320 {
skyscraper 2:9ffb2f18756b 321 uint8_t constexpr and_val = static_cast<uint8_t>(~(0b11U ));
skyscraper 2:9ffb2f18756b 322 uint8_t constexpr or_val = 0b10U;
skyscraper 2:9ffb2f18756b 323 return mag_modify_reg(mode_reg,and_val,or_val);
skyscraper 2:9ffb2f18756b 324 }
skyscraper 2:9ffb2f18756b 325
skyscraper 2:9ffb2f18756b 326 bool mag_data_ready()
skyscraper 2:9ffb2f18756b 327 {
skyscraper 2:9ffb2f18756b 328 uint8_t result = 0;
skyscraper 2:9ffb2f18756b 329 if ( mag_get_reg(status_reg, result)) {
skyscraper 2:9ffb2f18756b 330 return (result & 0b1U) != 0U;
skyscraper 2:9ffb2f18756b 331 } else {
skyscraper 2:9ffb2f18756b 332 std::cout << "mag data ready failed\n";
skyscraper 2:9ffb2f18756b 333 return false;
skyscraper 2:9ffb2f18756b 334 }
skyscraper 2:9ffb2f18756b 335 }
skyscraper 2:9ffb2f18756b 336
skyscraper 2:9ffb2f18756b 337 bool mag_data_locked()
skyscraper 2:9ffb2f18756b 338 {
skyscraper 2:9ffb2f18756b 339 uint8_t result = 0;
skyscraper 2:9ffb2f18756b 340 if ( mag_get_reg(status_reg, result)) {
skyscraper 2:9ffb2f18756b 341 return (result & 0b10U) != 0U;
skyscraper 2:9ffb2f18756b 342 } else {
skyscraper 2:9ffb2f18756b 343 std::cout << "mag data locked failed\n";
skyscraper 2:9ffb2f18756b 344 return false;
skyscraper 2:9ffb2f18756b 345 }
skyscraper 2:9ffb2f18756b 346 }
skyscraper 2:9ffb2f18756b 347
skyscraper 2:9ffb2f18756b 348 // assume mag_data_ready has returned true before call
skyscraper 2:9ffb2f18756b 349 bool mag_read(quan::three_d::vect<quan::magnetic_flux_density::uT> & v)
skyscraper 2:9ffb2f18756b 350 {
skyscraper 2:9ffb2f18756b 351 if( mag_set_reg_idx(dout_reg)) {
skyscraper 2:9ffb2f18756b 352 char arr[7];
skyscraper 3:2834be4e10ef 353 i2c.lock();
skyscraper 3:2834be4e10ef 354 bool success= i2c.read(i2c_addr,arr,7) == 0;
skyscraper 3:2834be4e10ef 355 i2c.unlock();
skyscraper 3:2834be4e10ef 356 if(success) {
skyscraper 2:9ffb2f18756b 357 // TODO check status reg arr[6]
skyscraper 2:9ffb2f18756b 358 // if
skyscraper 2:9ffb2f18756b 359 quan::three_d::vect<int16_t> temp;
skyscraper 2:9ffb2f18756b 360 temp.x = static_cast<int16_t>(arr[1]) + ( static_cast<int16_t>(arr[0]) << 8U);
skyscraper 2:9ffb2f18756b 361 temp.y = static_cast<int16_t>(arr[5]) + ( static_cast<int16_t>(arr[4]) << 8U);
skyscraper 2:9ffb2f18756b 362 temp.z = static_cast<int16_t>(arr[3]) + ( static_cast<int16_t>(arr[2]) << 8U);
skyscraper 2:9ffb2f18756b 363 v = temp * mag_resolution;
skyscraper 2:9ffb2f18756b 364 return true;
skyscraper 2:9ffb2f18756b 365 } else {
skyscraper 2:9ffb2f18756b 366 std::cout << "mag_read failed\n";
skyscraper 2:9ffb2f18756b 367 return false;
skyscraper 2:9ffb2f18756b 368 }
skyscraper 2:9ffb2f18756b 369 } else {
skyscraper 2:9ffb2f18756b 370 return false;
skyscraper 2:9ffb2f18756b 371 }
skyscraper 2:9ffb2f18756b 372 }
skyscraper 2:9ffb2f18756b 373
skyscraper 2:9ffb2f18756b 374 bool mag_do_single_measurement(quan::three_d::vect<quan::magnetic_flux_density::uT>& result)
skyscraper 2:9ffb2f18756b 375 {
skyscraper 2:9ffb2f18756b 376 if ( ! mag_set_single_measurement_mode()) {
skyscraper 2:9ffb2f18756b 377 return false;
skyscraper 2:9ffb2f18756b 378 }
skyscraper 2:9ffb2f18756b 379
skyscraper 2:9ffb2f18756b 380 while (! mag_data_ready()) {
skyscraper 2:9ffb2f18756b 381 ThisThread::sleep_for(5U);
skyscraper 2:9ffb2f18756b 382 }
skyscraper 2:9ffb2f18756b 383 return mag_read(result);
skyscraper 2:9ffb2f18756b 384 }
skyscraper 2:9ffb2f18756b 385
skyscraper 2:9ffb2f18756b 386 namespace {
skyscraper 2:9ffb2f18756b 387 //TODO raname to mag_self_test
skyscraper 2:9ffb2f18756b 388 bool mag_get_offsets(quan::three_d::vect<quan::magnetic_flux_density::uT> & result)
skyscraper 2:9ffb2f18756b 389 {
skyscraper 2:9ffb2f18756b 390 // set single measurement mode
skyscraper 2:9ffb2f18756b 391
skyscraper 2:9ffb2f18756b 392 // to prevent saturation
skyscraper 2:9ffb2f18756b 393 mag_set_range(5.7_gauss);
skyscraper 2:9ffb2f18756b 394 quan::three_d::vect<quan::magnetic_flux_density::uT> mSet;
skyscraper 2:9ffb2f18756b 395 // throw away first
skyscraper 2:9ffb2f18756b 396 mag_do_single_measurement(mSet);
skyscraper 2:9ffb2f18756b 397
skyscraper 2:9ffb2f18756b 398 mag_set_positive_bias();
skyscraper 2:9ffb2f18756b 399 mag_do_single_measurement(mSet);
skyscraper 2:9ffb2f18756b 400 std::cout << "mSet = " << mSet <<'\n';
skyscraper 2:9ffb2f18756b 401
skyscraper 2:9ffb2f18756b 402 mag_set_negative_bias();
skyscraper 2:9ffb2f18756b 403 quan::three_d::vect<quan::magnetic_flux_density::uT> mReset;
skyscraper 2:9ffb2f18756b 404 mag_do_single_measurement(mReset);
skyscraper 2:9ffb2f18756b 405 mag_clear_bias();
skyscraper 2:9ffb2f18756b 406
skyscraper 2:9ffb2f18756b 407 std::cout << "mReset = " << mReset <<'\n';
skyscraper 2:9ffb2f18756b 408
skyscraper 2:9ffb2f18756b 409 result = (mSet - mReset )/2;
skyscraper 2:9ffb2f18756b 410
skyscraper 2:9ffb2f18756b 411 std::cout << "result = " << result << '\n';
skyscraper 2:9ffb2f18756b 412
skyscraper 2:9ffb2f18756b 413 return true;
skyscraper 2:9ffb2f18756b 414 }
skyscraper 2:9ffb2f18756b 415 } // namepsace