summaryrefslogtreecommitdiff
path: root/src/iim42653.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/iim42653.cpp')
-rw-r--r--src/iim42653.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/iim42653.cpp b/src/iim42653.cpp
new file mode 100644
index 0000000..d9b96d4
--- /dev/null
+++ b/src/iim42653.cpp
@@ -0,0 +1,108 @@
+#include "iim42653.hpp"
+
+int16_t IIM42653::sat_sub(int16_t a, int16_t b) {
+ int32_t result = (int32_t) a - (int32_t) b;
+ if (result < INT16_MIN) {
+ result = INT16_MIN;
+ }
+ if (result > INT16_MAX) {
+ result = INT16_MAX;
+ }
+ return (int16_t) result;
+};
+
+//Startup routine, initialize GPIO clock output
+void IIM42653::initialize() {
+ //Enable 40kHz clock output on GPIO 23
+ clock_gpio_init(MICRO_DEFAULT_CLK_OUTPUT, IIM42653_CLOCK_SOURCE_SYSTEM, IIM42653_CLOCK_DIVISOR);
+ sleep_ms(50); //Allow time for clock output to stabilize
+
+ //Configure Gyroscope FSR and ODR
+ buffer[0] = R_IIM42653_GYRO_CONFIG0;
+ gyro_config0.fields.GYRO_ODR = B_IIM42653_GYRO_CONFIG0_ODR_500HZ;
+ gyro_config0.fields.GYRO_UI_FS_SEL = B_IIM42653_GYRO_CONFIG0_FSR_4000DPS;
+ buffer[1] = gyro_config0.data;
+ i2c_write_blocking(i2c, addr, buffer, 2, false);
+
+ //Configure Accelerometer FSR and ODR
+ buffer[0] = R_IIM42653_ACCEL_CONFIG0;
+ accel_config0.fields.ACCEL_ODR = B_IIM42653_ACCEL_CONFIG0_ODR_500HZ;
+ accel_config0.fields.ACCEL_UI_FS_SEL = B_IIM42653_ACCEL_CONFIG0_FSR_32G;
+ buffer[1] = accel_config0.data;
+ i2c_write_blocking(i2c, addr, buffer, 2, false);
+
+ //Enable Gyroscope, Accelerometer, and Thermocouple
+ buffer[0] = R_IIM42653_PWR_MGMT0;
+ pwr_mgmt0.fields.ACCEL_MODE = B_IIM42653_PWR_MGMT0_ACCEL_MODE_LOW_NOISE;
+ pwr_mgmt0.fields.GYRO_MODE = B_IIM42653_PWR_MGMT0_GYRO_MODE_LOW_NOISE;
+ pwr_mgmt0.fields.TEMP_DIS = B_IIM42653_PWR_MGMT0_TEMP_ENABLE;
+ buffer[1] = pwr_mgmt0.data;
+ i2c_write_blocking(i2c, addr, buffer, 2, false);
+ sleep_ms(10); //Datasheet instructs 200us wait after changing sensor power modes
+
+ //Calibrate gyro bias once all sensors are initialized
+ calibrate_gyro();
+}
+
+//Read all 12 data registers at once and format them into their internal fields
+void IIM42653::sample() {
+ //Read ACCEL_DATA_X1_UI - GYRO_DATA_Z0_UI as a block
+ buffer[0] = R_IIM42653_ACCEL_DATA_X1_UI;
+ i2c_write_blocking(i2c, addr, buffer, 1, true);
+ i2c_read_blocking(i2c, addr, buffer, 12, false);
+
+ //Split buffer into individial fields
+ ax = ((int16_t)buffer[1]) | (((int16_t)buffer[0]) << 8);
+ ay = ((int16_t)buffer[3]) | (((int16_t)buffer[2]) << 8);
+ az = ((int16_t)buffer[5]) | (((int16_t)buffer[4]) << 8);
+ raw_gx = ((int16_t)buffer[7]) | (((int16_t)buffer[6]) << 8);
+ raw_gy = ((int16_t)buffer[9]) | (((int16_t)buffer[8]) << 8);
+ raw_gz = ((int16_t)buffer[11]) | (((int16_t)buffer[10]) << 8);
+}
+void IIM42653::apply_gyro_offset() {
+ gx = sat_sub(raw_gx, bias_gx);
+ gy = sat_sub(raw_gy, bias_gy);
+ gz = sat_sub(raw_gz, bias_gz);
+}
+
+//Request certain number of gyroscope readings, and set the gyro bias values to the averages of the readings
+void IIM42653::calibrate_gyro() {
+ //Initialize buffers
+ int64_t g_x = 0;
+ int64_t g_y = 0;
+ int64_t g_z = 0;
+
+ //Request configured number of samples and l
+ for (int64_t i = 0; i < n_gyro_bias_readings; i++) {
+ sample();
+ g_x += raw_gx;
+ g_y += raw_gy;
+ g_z += raw_gz;
+ sleep_ms(5);
+ }
+
+ //Set bias values to the average readings during the calibration period
+ bias_gx = g_x/n_gyro_bias_readings;
+ bias_gy = g_y/n_gyro_bias_readings;
+ bias_gz = g_z/n_gyro_bias_readings;
+}
+
+#if ( USE_FREERTOS == 1 )
+void IIM42653::update_iim42653_task(void* pvParameters) {
+ TickType_t xLastWakeTime;
+ const TickType_t xFrequency = pdMS_TO_TICKS(1000 / IIM42653_SAMPLE_RATE_HZ);
+
+ xLastWakeTime = xTaskGetTickCount();
+ while (1) {
+ vTaskDelayUntil(&xLastWakeTime, xFrequency);
+ taskENTER_CRITICAL();
+ IIM42653* iim42653 = (IIM42653*) pvParameters;
+ iim42653->sample();
+ iim42653->apply_gyro_offset();
+ taskEXIT_CRITICAL();
+ if ((xLastWakeTime + xFrequency) < xTaskGetTickCount()) {
+ xLastWakeTime = xTaskGetTickCount();
+ }
+ }
+}
+#endif