|  |  | @ -22,19 +22,22 @@ | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "system/sensord/sensors/lsm6ds3_gyro.h" |  |  |  | #include "system/sensord/sensors/lsm6ds3_gyro.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "system/sensord/sensors/lsm6ds3_temp.h" |  |  |  | #include "system/sensord/sensors/lsm6ds3_temp.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "system/sensord/sensors/mmc5603nj_magn.h" |  |  |  | #include "system/sensord/sensors/mmc5603nj_magn.h" | 
			
		
	
		
		
			
				
					
					|  |  |  | #include "system/sensord/sensors/sensor.h" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #define I2C_BUS_IMU 1 |  |  |  | #define I2C_BUS_IMU 1 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | ExitHandler do_exit; |  |  |  | ExitHandler do_exit; | 
			
		
	
		
		
			
				
					
					|  |  |  | uint64_t init_ts = 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | void interrupt_loop(std::vector<Sensor *>& sensors, |  |  |  | void interrupt_loop(std::vector<std::tuple<Sensor *, std::string, bool, int>> sensors) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                     std::map<Sensor*, std::string>& sensor_service) |  |  |  |   PubMaster pm({"gyroscope", "accelerometer"}); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | { |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   PubMaster pm_int({"gyroscope", "accelerometer"}); |  |  |  |   int fd = -1; | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   for (auto &[sensor, msg_name, required, polling_freq] : sensors) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (sensor->has_interrupt_enabled()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       fd = sensor->gpio_fd; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       break; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   int fd = sensors[0]->gpio_fd; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   struct pollfd fd_list[1] = {0}; |  |  |  |   struct pollfd fd_list[1] = {0}; | 
			
		
	
		
		
			
				
					
					|  |  |  |   fd_list[0].fd = fd; |  |  |  |   fd_list[0].fd = fd; | 
			
		
	
		
		
			
				
					
					|  |  |  |   fd_list[0].events = POLLIN | POLLPRI; |  |  |  |   fd_list[0].events = POLLIN | POLLPRI; | 
			
		
	
	
		
		
			
				
					|  |  | @ -68,130 +71,94 @@ void interrupt_loop(std::vector<Sensor *>& sensors, | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint64_t offset = nanos_since_epoch() - nanos_since_boot(); |  |  |  |     uint64_t offset = nanos_since_epoch() - nanos_since_boot(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     uint64_t ts = evdata[num_events - 1].timestamp - offset; |  |  |  |     uint64_t ts = evdata[num_events - 1].timestamp - offset; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (Sensor *sensor : sensors) { |  |  |  |     for (auto &[sensor, msg_name, required, polling_freq] : sensors) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       if (!sensor->has_interrupt_enabled()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       MessageBuilder msg; |  |  |  |       MessageBuilder msg; | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!sensor->get_event(msg, ts)) { |  |  |  |       if (!sensor->get_event(msg, ts)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         continue; |  |  |  |         continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!sensor->is_data_valid(init_ts, ts)) { |  |  |  |       if (!sensor->is_data_valid(ts)) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         continue; |  |  |  |         continue; | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       pm_int.send(sensor_service[sensor].c_str(), msg); |  |  |  |       pm.send(msg_name.c_str(), msg); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // poweroff sensors, disable interrupts
 |  |  |  |   // poweroff sensors, disable interrupts
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (Sensor *sensor : sensors) { |  |  |  |   for (auto &[sensor, msg_name, required, polling_freq] : sensors) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (sensor->has_interrupt_enabled()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       sensor->shutdown(); |  |  |  |       sensor->shutdown(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | int sensor_loop(I2CBus *i2c_bus_imu) { |  |  |  | void polling_loop(Sensor *sensor, std::string msg_name, int frequency) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   BMX055_Accel bmx055_accel(i2c_bus_imu); |  |  |  |   PubMaster pm({msg_name.c_str()}); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   BMX055_Gyro bmx055_gyro(i2c_bus_imu); |  |  |  |   RateKeeper rk(msg_name, frequency); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   BMX055_Magn bmx055_magn(i2c_bus_imu); |  |  |  |   while (!do_exit) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   BMX055_Temp bmx055_temp(i2c_bus_imu); |  |  |  |     MessageBuilder msg; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |     if (sensor->get_event(msg) && sensor->is_data_valid(nanos_since_boot())) { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   LSM6DS3_Accel lsm6ds3_accel(i2c_bus_imu, GPIO_LSM_INT); |  |  |  |       pm.send(msg_name.c_str(), msg); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   LSM6DS3_Gyro lsm6ds3_gyro(i2c_bus_imu, GPIO_LSM_INT, true); // GPIO shared with accel
 |  |  |  |     } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   LSM6DS3_Temp lsm6ds3_temp(i2c_bus_imu); |  |  |  |     rk.keepTime(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |   } | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   MMC5603NJ_Magn mmc5603nj_magn(i2c_bus_imu); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::map<Sensor*, std::string> sensor_service = { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&bmx055_accel, "accelerometer2"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&bmx055_gyro, "gyroscope2"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&bmx055_magn, "magnetometer"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&bmx055_temp, "temperatureSensor"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&lsm6ds3_accel, "accelerometer"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&lsm6ds3_gyro, "gyroscope"}, |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&lsm6ds3_temp, "temperatureSensor"}, |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     {&mmc5603nj_magn, "magnetometer"}, |  |  |  |   sensor->shutdown(); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   }; |  |  |  | } | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | int sensor_loop(I2CBus *i2c_bus_imu) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Sensor init
 |  |  |  |   // Sensor init
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::vector<std::pair<Sensor *, bool>> sensors_init; // Sensor, required
 |  |  |  |   std::vector<std::tuple<Sensor *, std::string, bool, int>> sensors_init = { | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&bmx055_accel, false}); |  |  |  |     {new BMX055_Accel(i2c_bus_imu), "accelerometer2", false, 100}, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&bmx055_gyro, false}); |  |  |  |     {new BMX055_Gyro(i2c_bus_imu), "gyroscope2", false, 100}, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&bmx055_magn, false}); |  |  |  |     {new BMX055_Magn(i2c_bus_imu), "magnetometer", false, 100}, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&bmx055_temp, false}); |  |  |  |     {new BMX055_Temp(i2c_bus_imu), "temperatureSensor2", false, 100}, | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&lsm6ds3_accel, true}); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&lsm6ds3_gyro, true}); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&lsm6ds3_temp, true}); |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   sensors_init.push_back({&mmc5603nj_magn, false}); |  |  |  |     {new LSM6DS3_Accel(i2c_bus_imu, GPIO_LSM_INT), "accelerometer", true, 100}, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     {new LSM6DS3_Gyro(i2c_bus_imu, GPIO_LSM_INT, true), "gyroscope", true, 100}, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     {new LSM6DS3_Temp(i2c_bus_imu), "temperatureSensor", true, 100}, | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   bool has_magnetometer = false; |  |  |  |     {new MMC5603NJ_Magn(i2c_bus_imu), "magnetometer", false, 100}, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Initialize sensors
 |  |  |  |   // Initialize sensors
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::vector<Sensor *> sensors; |  |  |  |   std::vector<std::thread> threads; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   for (auto &[sensor, required] : sensors_init) { |  |  |  |   for (auto &[sensor, msg_name, required, polling_freq] : sensors_init) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     int err = sensor->init(); |  |  |  |     int err = sensor->init(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (err < 0) { |  |  |  |     if (err < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (required) { |  |  |  |       if (required) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         LOGE("Error initializing sensors"); |  |  |  |         LOGE("Error initializing sensors"); | 
			
		
	
		
		
			
				
					
					|  |  |  |         return -1; |  |  |  |         return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |       } | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else { |  |  |  |       continue; | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (sensor == &bmx055_magn || sensor == &mmc5603nj_magn) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         has_magnetometer = true; |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (!sensor->has_interrupt_enabled()) { |  |  |  |     if (!sensor->has_interrupt_enabled()) { | 
			
		
	
		
		
			
				
					
					|  |  |  |         sensors.push_back(sensor); |  |  |  |       threads.emplace_back(polling_loop, sensor, msg_name, polling_freq); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!has_magnetometer) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("No magnetometer present"); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     return -1; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   // increase interrupt quality by pinning interrupt and process to core 1
 |  |  |  |   // increase interrupt quality by pinning interrupt and process to core 1
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   setpriority(PRIO_PROCESS, 0, -18); |  |  |  |   setpriority(PRIO_PROCESS, 0, -18); | 
			
		
	
		
		
			
				
					
					|  |  |  |   util::set_core_affinity({1}); |  |  |  |   util::set_core_affinity({1}); | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::system("sudo su -c 'echo 1 > /proc/irq/336/smp_affinity_list'"); |  |  |  |   std::system("sudo su -c 'echo 1 > /proc/irq/336/smp_affinity_list'"); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   PubMaster pm_non_int({"gyroscope2", "accelerometer2", "temperatureSensor", "magnetometer"}); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   init_ts = nanos_since_boot(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   // thread for reading events via interrupts
 |  |  |  |   // thread for reading events via interrupts
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::vector<Sensor *> lsm_interrupt_sensors = {&lsm6ds3_accel, &lsm6ds3_gyro}; |  |  |  |   threads.emplace_back(&interrupt_loop, std::ref(sensors_init)); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |   std::thread lsm_interrupt_thread(&interrupt_loop, std::ref(lsm_interrupt_sensors), |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |                                    std::ref(sensor_service)); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   RateKeeper rk("sensord", 100); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   // polling loop for non interrupt handled sensors
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   while (!do_exit) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (Sensor *sensor : sensors) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       MessageBuilder msg; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!sensor->get_event(msg)) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |         continue; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (!sensor->is_data_valid(init_ts, nanos_since_boot())) { |  |  |  |   // wait for all threads to finish
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         continue; |  |  |  |   for (auto &t : threads) { | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     t.join(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       pm_non_int.send(sensor_service[sensor].c_str(), msg); |  |  |  |   for (auto &[sensor, msg_name, required, polling_freq] : sensors_init) { | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     delete sensor; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     rk.keepTime(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   for (Sensor *sensor : sensors) { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     sensor->shutdown(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   lsm_interrupt_thread.join(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   return 0; |  |  |  |   return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |