|  |  | @ -1,5 +1,6 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <cassert> |  |  |  | #include <cassert> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <cstdio> |  |  |  | #include <cstdio> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include <algorithm> | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <unistd.h> |  |  |  | #include <unistd.h> | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "common/swaglog.h" |  |  |  | #include "common/swaglog.h" | 
			
		
	
	
		
		
			
				
					|  |  | @ -7,6 +8,60 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "bmx055_magn.hpp" |  |  |  | #include "bmx055_magn.hpp" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int16_t compensate_x(trim_data_t trim_data, int16_t mag_data_x, uint16_t data_rhall) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint16_t process_comp_x0 = data_rhall; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x1 = ((int32_t)trim_data.dig_xyz1) * 16384; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint16_t process_comp_x2 = ((uint16_t)(process_comp_x1 / process_comp_x0)) - ((uint16_t)0x4000); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int16_t retval = ((int16_t)process_comp_x2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x3 = (((int32_t)retval) * ((int32_t)retval)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x4 = (((int32_t)trim_data.dig_xy2) * (process_comp_x3 / 128)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x5 = (int32_t)(((int16_t)trim_data.dig_xy1) * 128); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x6 = ((int32_t)retval) * process_comp_x5; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x7 = (((process_comp_x4 + process_comp_x6) / 512) + ((int32_t)0x100000)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x8 = ((int32_t)(((int16_t)trim_data.dig_x2) + ((int16_t)0xA0))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x9 = ((process_comp_x7 * process_comp_x8) / 4096); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_x10 = ((int32_t)mag_data_x) * process_comp_x9; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = ((int16_t)(process_comp_x10 / 8192)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = (retval + (((int16_t)trim_data.dig_x1) * 8)) / 16; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return retval; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int16_t compensate_y(trim_data_t trim_data, int16_t mag_data_y, uint16_t data_rhall) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint16_t process_comp_y0 = trim_data.dig_xyz1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y1 = (((int32_t)trim_data.dig_xyz1) * 16384) / process_comp_y0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint16_t process_comp_y2 = ((uint16_t)process_comp_y1) - ((uint16_t)0x4000); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int16_t retval = ((int16_t)process_comp_y2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y3 = ((int32_t) retval) * ((int32_t)retval); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y4 = ((int32_t)trim_data.dig_xy2) * (process_comp_y3 / 128); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y5 = ((int32_t)(((int16_t)trim_data.dig_xy1) * 128)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y6 = ((process_comp_y4 + (((int32_t)retval) * process_comp_y5)) / 512); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y7 = ((int32_t)(((int16_t)trim_data.dig_y2) + ((int16_t)0xA0))); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y8 = (((process_comp_y6 + ((int32_t)0x100000)) * process_comp_y7) / 4096); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_y9 = (((int32_t)mag_data_y) * process_comp_y8); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = (int16_t)(process_comp_y9 / 8192); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = (retval + (((int16_t)trim_data.dig_y1) * 8)) / 16; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return retval; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | static int16_t compensate_z(trim_data_t trim_data, int16_t mag_data_z, uint16_t data_rhall) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int16_t process_comp_z0 = ((int16_t)data_rhall) - ((int16_t) trim_data.dig_xyz1); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_z1 = (((int32_t)trim_data.dig_z3) * ((int32_t)(process_comp_z0))) / 4; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_z2 = (((int32_t)(mag_data_z - trim_data.dig_z4)) * 32768); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t process_comp_z3 = ((int32_t)trim_data.dig_z1) * (((int16_t)data_rhall) * 2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int16_t process_comp_z4 = (int16_t)((process_comp_z3 + (32768)) / 65536); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int32_t retval = ((process_comp_z2 - process_comp_z1) / (trim_data.dig_z2 + process_comp_z4)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   /* saturate result to +/- 2 micro-tesla */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = std::clamp(retval, -32767, 32767); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   /* Conversion of LSB to micro-tesla*/ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   retval = retval / 16; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return (int16_t)retval; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | static int16_t parse_xy(uint8_t lsb, uint8_t msb){ |  |  |  | static int16_t parse_xy(uint8_t lsb, uint8_t msb){ | 
			
		
	
		
		
			
				
					
					|  |  |  |   // 13 bit
 |  |  |  |   // 13 bit
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint16_t combined = (uint16_t(msb) << 5) | uint16_t(lsb >> 3); |  |  |  |   uint16_t combined = (uint16_t(msb) << 5) | uint16_t(lsb >> 3); | 
			
		
	
	
		
		
			
				
					|  |  | @ -19,18 +74,19 @@ static int16_t parse_z(uint8_t lsb, uint8_t msb){ | 
			
		
	
		
		
			
				
					
					|  |  |  |   return int16_t(combined << 1) / (1 << 1); |  |  |  |   return int16_t(combined << 1) / (1 << 1); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /*
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | static uint16_t parse_rhall(uint8_t lsb, uint8_t msb){ |  |  |  | static uint16_t parse_rhall(uint8_t lsb, uint8_t msb){ | 
			
		
	
		
		
			
				
					
					|  |  |  |   // 14 bit
 |  |  |  |   // 14 bit
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   return (uint16_t(msb) << 6) | uint16_t(lsb >> 2); |  |  |  |   return (uint16_t(msb) << 6) | uint16_t(lsb >> 2); | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | BMX055_Magn::BMX055_Magn(I2CBus *bus) : I2CSensor(bus) {} |  |  |  | BMX055_Magn::BMX055_Magn(I2CBus *bus) : I2CSensor(bus) {} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | int BMX055_Magn::init(){ |  |  |  | int BMX055_Magn::init(){ | 
			
		
	
		
		
			
				
					
					|  |  |  |   int ret; |  |  |  |   int ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint8_t buffer[1]; |  |  |  |   uint8_t buffer[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t trim_x1y1[2] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t trim_xyz_data[4] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t trim_xy1xy2[10] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // suspend -> sleep
 |  |  |  |   // suspend -> sleep
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = set_register(BMX055_MAGN_I2C_REG_PWR_0, 0x01); |  |  |  |   ret = set_register(BMX055_MAGN_I2C_REG_PWR_0, 0x01); | 
			
		
	
	
		
		
			
				
					|  |  | @ -52,6 +108,37 @@ int BMX055_Magn::init(){ | 
			
		
	
		
		
			
				
					
					|  |  |  |     return -1; |  |  |  |     return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Load magnetometer trim
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = read_register(BMX055_MAGN_I2C_REG_DIG_X1, trim_x1y1, 2); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(ret < 0){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z4, trim_xyz_data, 4); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(ret < 0){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = read_register(BMX055_MAGN_I2C_REG_DIG_Z2, trim_xy1xy2, 10); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if(ret < 0){ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Read trim data
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_x1 = (int8_t)trim_x1y1[0]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_y1 = (int8_t)trim_x1y1[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_x2 = (int8_t)trim_xyz_data[2]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_y2 = (int8_t)trim_xyz_data[3]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_z1 = read_16_bit(trim_xy1xy2[2], trim_xy1xy2[3]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_z2 = read_16_bit(trim_xy1xy2[0], trim_xy1xy2[1]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_z3 = read_16_bit(trim_xy1xy2[6], trim_xy1xy2[7]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_z4 = read_16_bit(trim_xyz_data[0], trim_xyz_data[1]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_xy1 = trim_xy1xy2[9]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_xy2 = (int8_t)trim_xy1xy2[8]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   trim_data.dig_xyz1 = read_16_bit(trim_xy1xy2[4], trim_xy1xy2[5] & 0x7f); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // TODO: perform self-test
 |  |  |  |   // TODO: perform self-test
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // 9 REPXY and 15 REPZ for 100 Hz
 |  |  |  |   // 9 REPXY and 15 REPZ for 100 Hz
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -82,10 +169,14 @@ void BMX055_Magn::get_event(cereal::SensorEventData::Builder &event){ | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   bool ready = buffer[6] & 0x1; |  |  |  |   bool ready = buffer[6] & 0x1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ready){ |  |  |  |   if (ready){ | 
			
		
	
		
		
			
				
					
					|  |  |  |     float x = parse_xy(buffer[0], buffer[1]); |  |  |  |     int16_t x = parse_xy(buffer[0], buffer[1]); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     float y = parse_xy(buffer[2], buffer[3]); |  |  |  |     int16_t y = parse_xy(buffer[2], buffer[3]); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     float z = parse_z(buffer[4], buffer[5]); |  |  |  |     int16_t z = parse_z(buffer[4], buffer[5]); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |     //uint16_t rhall = parse_rhall(buffer[5], buffer[6]);
 |  |  |  |     int16_t rhall = parse_rhall(buffer[5], buffer[6]); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     x = compensate_x(trim_data, x, rhall); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     y = compensate_y(trim_data, y, rhall); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     z = compensate_z(trim_data, z, rhall); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // TODO: convert to micro tesla:
 |  |  |  |     // TODO: convert to micro tesla:
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // https://github.com/BoschSensortec/BMM150-Sensor-API/blob/master/bmm150.c#L1614
 |  |  |  |     // https://github.com/BoschSensortec/BMM150-Sensor-API/blob/master/bmm150.c#L1614
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -96,7 +187,7 @@ void BMX055_Magn::get_event(cereal::SensorEventData::Builder &event){ | 
			
		
	
		
		
			
				
					
					|  |  |  |     event.setType(SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED); |  |  |  |     event.setType(SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED); | 
			
		
	
		
		
			
				
					
					|  |  |  |     event.setTimestamp(start_time); |  |  |  |     event.setTimestamp(start_time); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     float xyz[] = {x, y, z}; |  |  |  |     float xyz[] = {(float)x, (float)y, (float)z}; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     auto svec = event.initMagneticUncalibrated(); |  |  |  |     auto svec = event.initMagneticUncalibrated(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     svec.setV(xyz); |  |  |  |     svec.setV(xyz); | 
			
		
	
		
		
			
				
					
					|  |  |  |     svec.setStatus(true); |  |  |  |     svec.setStatus(true); | 
			
		
	
	
		
		
			
				
					|  |  | 
 |