Voss Connection Detection  1
Detect a connector click using realtime code on Bela hardware
ICM20948.cpp
Go to the documentation of this file.
1 #include <stdlib.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <linux/i2c.h>
5 #include <linux/i2c-dev.h>
6 #include <sys/ioctl.h>
7 #include <stropts.h>
8 #include <stdio.h>
9 #include "ICM20948.h"
10 #include <iostream>
11 #include <libraries/math_neon/math_neon.h>
12 using namespace std;
13 #define MAX_BUS 64
14 
15 
16 #define GYR_X_LSB 0x34
17 #define GYR_X_MSB 0x33
18 #define GYR_Y_LSB 0x36
19 #define GYR_Y_MSB 0x35
20 #define GYR_Z_LSB 0x38
21 #define GYR_Z_MSB 0x37
22 
23 #define ACC_X_LSB 0x2E
24 #define ACC_X_MSB 0x2D
25 #define ACC_Y_LSB 0x30
26 #define ACC_Y_MSB 0x2F
27 #define ACC_Z_LSB 0x32
28 #define ACC_Z_MSB 0x31
29 
30 ICM20948::ICM20948(int bus, int address) {
31  I2CBus = bus;
32  I2CAddress = address;
33  readFullSensorState();
34 }
35 
46 static inline float vectorLength(const float a, const float b, const float c) {
47  return sqrtf_neon(((a*a)+(b*b)+(c*c))/3.0f);
48 }
49 
51 
52  //cerr << "Starting ICM20948 I2C sensor state read" << endl;
53  char namebuf[MAX_BUS];
54  snprintf(namebuf, sizeof(namebuf), "/dev/i2c-%d", I2CBus);
55  int file;
56  _error = false;
57 
58  if ((file = open(namebuf, O_RDWR)) < 0){
59  cerr << "Failed to open ICM20948 Sensor on " << namebuf << " I2C Bus" << endl;
60  _error = true;
61  return(1);
62  }
63  if (ioctl(file, I2C_SLAVE, I2CAddress) < 0){
64  cerr << "I2C_SLAVE address " << I2CAddress << " failed..." << endl;
65  _error = true;
66  return(2);
67  }
68 
69  // According to the BMA180 datasheet on page 59, you need to send the first address
70  // in write mode and then a stop/start condition is issued. Data bytes are
71  // transferred with automatic address increment.
72  char buf[1] = { 0x00 };
73  if(write(file, buf, 1) !=1){
74  cerr << "Failed to Reset Address in readFullSensorState() " << endl;
75  _error = true;
76  }
77 
78  int numberBytes = ICM20948_I2C_BUFFER;
79  int bytesRead = read(file, this->dataBuffer, numberBytes);
80  //cerr << "numberBytes " << numberBytes << endl;
81  if (bytesRead == -1){
82  cerr << "Failure to read Byte Stream in readFullSensorState()" << endl;
83  _error = true;
84  }
85  close(file);
86 
87  if (this->dataBuffer[0]!=0xEA){
88  /* cerr << "MAJOR FAILURE: DATA WITH IMU HAS LOST SYNC!" << endl; */
89  _error = true;
90  }
91 
92  gyroX = convertGyro(GYR_X_MSB, GYR_X_LSB);
93  gyroY = convertGyro(GYR_Y_MSB, GYR_Y_LSB);
94  gyroZ = convertGyro(GYR_Z_MSB, GYR_Z_LSB);
95 
96  gyroAbs = vectorLength(gyroX, gyroY, gyroZ);
97 
98  accX = convertAcc(ACC_X_MSB, ACC_X_LSB);
99  accY = convertAcc(ACC_Y_MSB, ACC_Y_LSB);
100  accZ = convertAcc(ACC_Z_MSB, ACC_Z_LSB);
101 
102  accAbs = vectorLength(accX, accY, accZ);
103 
104  return 0;
105 }
106 
107 float ICM20948::convertGyro(int msb_reg_addr, int lsb_reg_addr){
108  short temp = dataBuffer[msb_reg_addr];
109  temp = (temp<<8) | dataBuffer[lsb_reg_addr];
110  return (float) temp / 32767.0f;
111 }
112 
113 float ICM20948::convertAcc(int msb_reg_addr, int lsb_reg_addr){
114  short temp = dataBuffer[msb_reg_addr];
115  temp = (temp<<8) | dataBuffer[lsb_reg_addr];
116  const float scale_fac = 32767.0f;
117  return (float) temp/scale_fac;
118 }
119 
120 void ICM20948::displayMode(int iterations){
121  for(int i=0; i<iterations; i++){
122  this->readFullSensorState();
123  /* printf("Rotation X,Y,Z,Abs (\t\t%d,\t %d,\t %d,\t %.2f\t) \tAcceleration (\t%.2f,\t %.2f,\t %.2f)\n", gyroX, gyroY, gyroZ, Abs, accX, accY, accZ); */
124  }
125 }
126 
128  char temp = 0b00000001;
129  if(this->writeI2CDeviceByte(6, temp)!=0){
130  cerr << "Failure to Wake chip" << endl;
131  }
132 
133  temp = 0b01010000;
134  if(this->writeI2CDeviceByte(5, temp)!=0){
135  cerr << "Failure to set Gyro" << endl;
136  }
137 }
138 
140  char Bank0 = 0b00000000;
141  char Bank2 = 0b00100000;
142  this->writeI2CDeviceByte(127, Bank2);
143  this->readFullSensorState();
144  /* char temp = dataBuffer[1]; */
145  /* cerr << "Bank2 Reg 1: " << (int)temp << endl; */
146  this->writeI2CDeviceByte(127, Bank0);
147 }
148 
150  char Bank0 = 0b00000000;
151  char Bank2 = 0b00100000;
152  this->writeI2CDeviceByte(127, Bank2);
153  this->writeI2CDeviceByte(1, 0b00000111);
154  this->readFullSensorState();
155  /* char temp0 = dataBuffer[0]; */
156  /* char temp = dataBuffer[1]; */
157  /* cerr << "Bank2 Reg 0: " << (int)temp0 << endl; */
158  /* cerr << "Bank2 Reg 1: " << (int)temp << endl; */
159  this->writeI2CDeviceByte(127, Bank0);
160  this->readFullSensorState();
161  /* temp0 = dataBuffer[0]; */
162  /* cerr << "Bank0 Reg 0: " << (int)temp0 << endl; */
163  /* cerr << "Scale set to 2000" << endl; */
164 }
165 
167  char Bank0 = 0b00000000;
168  char Bank2 = 0b00100000;
169  this->writeI2CDeviceByte(127, Bank2);
170  this->writeI2CDeviceByte(1, 0b00000001);
171  this->readFullSensorState();
172  /* char temp0 = dataBuffer[0]; */
173  /* char temp = dataBuffer[1]; */
174  /* cerr << "Bank2 Reg 0: " << (int)temp0 << endl; */
175  /* cerr << "Bank2 Reg 1: " << (int)temp << endl; */
176  this->writeI2CDeviceByte(127, Bank0);
177  this->readFullSensorState();
178  /* temp0 = dataBuffer[0]; */
179  /* cerr << "Bank0 Reg 0: " << (int)temp0 << endl; */
180  /* cerr << "Scale set to 250" << endl; */
181 }
182 
184  char Bank0 = 0b00000000;
185  char Bank2 = 0b00100000;
186  this->writeI2CDeviceByte(127, Bank2);
187  this->writeI2CDeviceByte(6, 0b10000000);
188  this->writeI2CDeviceByte(127, Bank0);
189  this->readFullSensorState();
190  /* char temp0 = dataBuffer[0]; */
191  /* cerr << "Bank0 Reg 0: " << (int)temp0 << endl; */
192 }
193 
194 int ICM20948::writeI2CDeviceByte(char address, char value){
195 
196  /* cerr << "Starting ICM20948 I2C sensor state write" << endl; */
197  char namebuf[MAX_BUS];
198  snprintf(namebuf, sizeof(namebuf), "/dev/i2c-%d", I2CBus);
199  int file;
200  if ((file = open(namebuf, O_RDWR)) < 0){
201  cerr << "Failed to open ICM20948 Sensor on " << namebuf << " I2C Bus" << endl;
202  return(1);
203  }
204  if (ioctl(file, I2C_SLAVE, I2CAddress) < 0){
205  cerr << "I2C_SLAVE address " << I2CAddress << " failed..." << endl;
206  return(2);
207  }
208 
209  char buffer[2];
210  buffer[0] = address;
211  buffer[1] = value;
212  if ( write(file, buffer, 2) != 2) {
213  cerr << "Failure to write values to I2C Device address." << endl;
214  return(3);
215  }
216  close(file);
217  /* cerr << "Finished ICM20948 I2C sensor state write" << endl; */
218  return 0;
219 }
220 
221 
ICM20948::WakeUp
void WakeUp()
Definition: ICM20948.cpp:127
ACC_Y_LSB
#define ACC_Y_LSB
Definition: ICM20948.cpp:25
ICM20948::ICM20948
ICM20948(int bus, int address)
Definition: ICM20948.cpp:30
GYR_X_LSB
#define GYR_X_LSB
Definition: ICM20948.cpp:16
GYR_X_MSB
#define GYR_X_MSB
Definition: ICM20948.cpp:17
ICM20948.h
ACC_X_LSB
#define ACC_X_LSB
Definition: ICM20948.cpp:23
ICM20948::GetScale
void GetScale()
Definition: ICM20948.cpp:139
ICM20948::displayMode
void displayMode(int iterations)
Definition: ICM20948.cpp:120
ACC_X_MSB
#define ACC_X_MSB
Definition: ICM20948.cpp:24
GYR_Y_LSB
#define GYR_Y_LSB
Definition: ICM20948.cpp:18
ACC_Z_LSB
#define ACC_Z_LSB
Definition: ICM20948.cpp:27
ICM20948::readFullSensorState
int readFullSensorState()
Definition: ICM20948.cpp:50
GYR_Z_LSB
#define GYR_Z_LSB
Definition: ICM20948.cpp:20
ICM20948::ResetChip
void ResetChip()
Definition: ICM20948.cpp:183
GYR_Z_MSB
#define GYR_Z_MSB
Definition: ICM20948.cpp:21
ICM20948::SetScale2000
void SetScale2000()
Definition: ICM20948.cpp:149
GYR_Y_MSB
#define GYR_Y_MSB
Definition: ICM20948.cpp:19
ICM20948_I2C_BUFFER
#define ICM20948_I2C_BUFFER
Definition: ICM20948.h:4
ACC_Z_MSB
#define ACC_Z_MSB
Definition: ICM20948.cpp:28
ICM20948::SetScale250
void SetScale250()
Definition: ICM20948.cpp:166
ACC_Y_MSB
#define ACC_Y_MSB
Definition: ICM20948.cpp:26
MAX_BUS
#define MAX_BUS
Definition: ICM20948.cpp:13