|  |  | @ -1,17 +1,132 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "lsm6ds3_accel.h" |  |  |  | #include "lsm6ds3_accel.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include <cassert> |  |  |  | #include <cassert> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include <cmath> | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include <cstring> | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "common/swaglog.h" |  |  |  | #include "common/swaglog.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "common/timing.h" |  |  |  | #include "common/timing.h" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #include "common/util.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | LSM6DS3_Accel::LSM6DS3_Accel(I2CBus *bus, int gpio_nr, bool shared_gpio) : |  |  |  | LSM6DS3_Accel::LSM6DS3_Accel(I2CBus *bus, int gpio_nr, bool shared_gpio) : | 
			
		
	
		
		
			
				
					
					|  |  |  |   I2CSensor(bus, gpio_nr, shared_gpio) {} |  |  |  |   I2CSensor(bus, gpio_nr, shared_gpio) {} | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void LSM6DS3_Accel::wait_for_data_ready() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t drdy = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t buffer[6]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   do { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     read_register(LSM6DS3_ACCEL_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     drdy &= LSM6DS3_ACCEL_DRDY_XLDA; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } while (drdy == 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   read_register(LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, buffer, sizeof(buffer)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | void LSM6DS3_Accel::read_and_avg_data(float* out_buf) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t drdy = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t buffer[6]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   float scaling = 0.061f; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (source == cereal::SensorEventData::SensorSource::LSM6DS3TRC) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     scaling = 0.122f; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (int i = 0; i < 5; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     do { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       read_register(LSM6DS3_ACCEL_I2C_REG_STAT_REG, &drdy, sizeof(drdy)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       drdy &= LSM6DS3_ACCEL_DRDY_XLDA; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } while (drdy == 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     int len = read_register(LSM6DS3_ACCEL_I2C_REG_OUTX_L_XL, buffer, sizeof(buffer)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     assert(len == sizeof(buffer)); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     for (int j = 0; j < 3; j++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       out_buf[j] += (float)read_16_bit(buffer[j*2], buffer[j*2+1]) * scaling; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (int i = 0; i < 3; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     out_buf[i] /= 5.0f; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | int LSM6DS3_Accel::self_test(int test_type) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   float val_st_off[3] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   float val_st_on[3] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   float test_val[3] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   uint8_t ODR_FS_MO = LSM6DS3_ACCEL_ODR_52HZ; // full scale: +-2g, ODR: 52Hz
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // prepare sensor for self-test
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // enable block data update and automatic increment
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   int ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL3_C, LSM6DS3_ACCEL_IF_INC_BDU); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (source == cereal::SensorEventData::SensorSource::LSM6DS3TRC) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     ODR_FS_MO = LSM6DS3_ACCEL_FS_4G | LSM6DS3_ACCEL_ODR_52HZ; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, ODR_FS_MO); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // wait for stable output, and discard first values
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   util::sleep_for(100); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   wait_for_data_ready(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   read_and_avg_data(val_st_off); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // enable Self Test positive (or negative)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL5_C, test_type); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // wait for stable output, and discard first values
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   util::sleep_for(100); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   wait_for_data_ready(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   read_and_avg_data(val_st_on); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // disable sensor
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // disable self test
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL5_C, 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // calculate the mg values for self test
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (int i = 0; i < 3; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     test_val[i] = fabs(val_st_on[i] - val_st_off[i]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // verify test result
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (int i = 0; i < 3; i++) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if ((LSM6DS3_ACCEL_MIN_ST_LIMIT_mg > test_val[i]) || | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         (test_val[i] > LSM6DS3_ACCEL_MAX_ST_LIMIT_mg)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | int LSM6DS3_Accel::init() { |  |  |  | int LSM6DS3_Accel::init() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   int ret = 0; |  |  |  |   int ret = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint8_t buffer[1]; |  |  |  |   uint8_t buffer[1]; | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint8_t value = 0; |  |  |  |   uint8_t value = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   bool do_self_test = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   const char* env_lsm_selftest =env_lsm_selftest = std::getenv("LSM_SELF_TEST"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (env_lsm_selftest != nullptr && strncmp(env_lsm_selftest, "1", 1) == 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     do_self_test = true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = read_register(LSM6DS3_ACCEL_I2C_REG_ID, buffer, 1); |  |  |  |   ret = read_register(LSM6DS3_ACCEL_I2C_REG_ID, buffer, 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if(ret < 0) { |  |  |  |   if(ret < 0) { | 
			
		
	
	
		
		
			
				
					|  |  | @ -29,11 +144,29 @@ int LSM6DS3_Accel::init() { | 
			
		
	
		
		
			
				
					
					|  |  |  |     source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; |  |  |  |     source = cereal::SensorEventData::SensorSource::LSM6DS3TRC; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = self_test(LSM6DS3_ACCEL_POSITIVE_TEST); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     LOGE("LSM6DS3 accel positive self-test failed!"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (do_self_test) goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = self_test(LSM6DS3_ACCEL_NEGATIVE_TEST); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     LOGE("LSM6DS3 accel negative self-test failed!"); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (do_self_test) goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = init_gpio(); |  |  |  |   ret = init_gpio(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ret < 0) { |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     goto fail; |  |  |  |     goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // enable continuous update, and automatic increase
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL3_C, LSM6DS3_ACCEL_IF_INC); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     goto fail; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // TODO: set scale and bandwidth. Default is +- 2G, 50 Hz
 |  |  |  |   // TODO: set scale and bandwidth. Default is +- 2G, 50 Hz
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, LSM6DS3_ACCEL_ODR_104HZ); |  |  |  |   ret = set_register(LSM6DS3_ACCEL_I2C_REG_CTRL1_XL, LSM6DS3_ACCEL_ODR_104HZ); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ret < 0) { |  |  |  |   if (ret < 0) { | 
			
		
	
	
		
		
			
				
					|  |  | 
 |