]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - zumo-cc3200/zumo-cc3200.git/blob - src/Energia/libraries/ZumoCC3200/utility/L3G.cpp
initial commit of content from Adam Dai and Tony Oliverio
[zumo-cc3200/zumo-cc3200.git] / src / Energia / libraries / ZumoCC3200 / utility / L3G.cpp
1 /*
2  *  ======== L3G.cpp ========
3  */
5 #include <Wire.h>
6 #include <math.h>
8 #include "L3G.h"
10 // Defines ////////////////////////////////////////////////////////////////
12 /* The Arduino two-wire interface uses a 7-bit number for the address,
13  * and sets the last bit correctly based on reads and writes
14  */
15 #define D20_SA0_HIGH_ADDRESS      0b1101011 // also applies to D20H
16 #define D20_SA0_LOW_ADDRESS       0b1101010 // also applies to D20H
17 #define L3G4200D_SA0_HIGH_ADDRESS 0b1101001
18 #define L3G4200D_SA0_LOW_ADDRESS  0b1101000
20 #define TEST_REG_ERROR -1
22 #define D20H_WHO_ID     0xD7
23 #define D20_WHO_ID      0xD4
24 #define L3G4200D_WHO_ID 0xD3
26 static int testReg(byte address, L3G::regAddr reg);
28 /*
29  *  ======== L3G ========
30  *  Constructors for L3G gyro
31  */
32 L3G::L3G(void)
33 {
34     _device = device_auto;
36     io_timeout = 0;  // 0 = no timeout
37     did_timeout = false;
38 }
40 /*
41  *  ======== timeoutOccurred ========
42  *  Did a timeout occur in read() since the last call to timeoutOccurred()?
43  */
44 bool L3G::timeoutOccurred()
45 {
46     bool tmp = did_timeout;
47     did_timeout = false;
48     return tmp;
49 }
51 /*
52  *  ======== setTimeout ========
53  */
54 void L3G::setTimeout(unsigned int timeout)
55 {
56     io_timeout = timeout;
57 }
59 /*
60  *  ======== getTimeout ========
61  */
62 unsigned int L3G::getTimeout()
63 {
64     return io_timeout;
65 }
67 /*
68  *  ======== init ========
69  */
70 bool L3G::init(deviceType device, sa0State sa0)
71 {
72     int id;
74     /* perform auto-detection unless device type and SA0 state were both
75      * specified
76      */
77     if (device == device_auto || sa0 == sa0_auto) {
78         /* check for L3GD20H, D20 if device is unidentified or was specified
79          * to be one of these types
80          */
81         if (device == device_auto || device == device_D20H
82                 || device == device_D20) {
83             // check SA0 high address unless SA0 was specified to be low
84             if (sa0
85                     != sa0_low && (id = testReg(D20_SA0_HIGH_ADDRESS, WHO_AM_I)) != TEST_REG_ERROR) {
86                 /* device responds to address 1101011; it's a D20H or D20
87                  * with SA0 high
88                  */
89                 sa0 = sa0_high;
90                 if (device == device_auto) {
91                     // use ID from WHO_AM_I register to determine device type
92                     device = (id == D20H_WHO_ID) ? device_D20H : device_D20;
93                 }
94             }
95             // check SA0 low address unless SA0 was specified to be high
96             else if (sa0
97                     != sa0_high && (id = testReg(D20_SA0_LOW_ADDRESS, WHO_AM_I)) != TEST_REG_ERROR) {
98                 /* device responds to address 1101010; it's a D20H or D20
99                  * with SA0 low
100                  */
101                 sa0 = sa0_low;
102                 if (device == device_auto) {
103                     // use ID from WHO_AM_I register to determine device type
104                     device = (id == D20H_WHO_ID) ? device_D20H : device_D20;
105                 }
106             }
107         }
109         /* check for L3G4200D if device is still unidentified or was specified
110          * to be this type
111          */
112         if (device == device_auto || device == device_4200D) {
113             if (sa0
114                     != sa0_low && testReg(L3G4200D_SA0_HIGH_ADDRESS, WHO_AM_I) == L3G4200D_WHO_ID) {
115                 /* device responds to address 1101001; it's a 4200D with SA0
116                  * high
117                  */
118                 device = device_4200D;
119                 sa0 = sa0_high;
120             }
121             else if (sa0
122                     != sa0_high && testReg(L3G4200D_SA0_LOW_ADDRESS, WHO_AM_I) == L3G4200D_WHO_ID) {
123                 /* device responds to address 1101000; it's a 4200D with SA0
124                  * low
125                  */
126                 device = device_4200D;
127                 sa0 = sa0_low;
128             }
129         }
131         /* make sure device and SA0 were successfully detected; otherwise,
132          * indicate failure
133          */
134         if (device == device_auto || sa0 == sa0_auto) {
135             return false;
136         }
137     }
139     _device = device;
141     // set device address
142     switch (device) {
143         case device_D20H:
144         case device_D20:
145             address =
146                     (sa0 == sa0_high) ?
147                             D20_SA0_HIGH_ADDRESS : D20_SA0_LOW_ADDRESS;
148             break;
150         case device_4200D:
151             address =
152                     (sa0 == sa0_high) ?
153                             L3G4200D_SA0_HIGH_ADDRESS :
154                             L3G4200D_SA0_LOW_ADDRESS;
155             break;
156     }
158     return true;
161 /*
162  *  ======== enableDefault ========
163  *  Enables the L3G's gyro
164  *
165  *  Also:
166  *      - Sets gyro full scale (gain) to default power-on value of +/- 250 dps
167  *       (specified as +/- 245 dps for L3GD20H).
168  *      - Selects 380 Hz ODR (output data rate). (Exact rate is specified as
169  *        189.4 Hz for L3GD20H and 190 Hz for L3GD20.)
170  *  
171  *  Note that this function will also reset other settings controlled by
172  *  the registers it writes to.
173  */
174 void L3G::enableDefault(void)
176     if (_device == device_D20H) {
177         // 0x00 = 0b00000000
178         //     Low_ODR = 0 (low speed ODR disabled)
179         writeReg(LOW_ODR, 0x00);
180     }
182     // 0x00 = 0b00000000
183     //     FS = 00 (+/- 250 dps full scale)
184     writeReg(CTRL_REG4, 0x00);
186     // 0xAF = 0b10101111
187     //     DR = 10 (380 Hz ODR);
188     //     BW = 10 (50 Hz bandwidth);
189     //     PD = 1 (normal mode);
190     //     Zen = Yen = Xen = 1 (all axes enabled)
191     writeReg(CTRL_REG1, 0xAF);
194 /*
195  *  ======== writeReg ========
196  *  Writes a gyro register
197  */
198 void L3G::writeReg(byte reg, byte value)
200     Wire.beginTransmission(address);
201     Wire.write(reg);
202     Wire.write(value);
203     last_status = Wire.endTransmission();
206 /*
207  *  ======== readReg ========
208  *  Reads a gyro register
209  */
210 byte L3G::readReg(byte reg)
212     byte value;
214     Wire.beginTransmission(address);
215     Wire.write(reg);
216     last_status = Wire.endTransmission();
217     Wire.requestFrom(address, (byte) 1);
218     value = Wire.read();
219     Wire.endTransmission();
221     return value;
224 /*
225  *  ======== read ========
226  *  Reads the 3 gyro channels and stores them in vector g
227  */
228 void L3G::read()
230     Wire.beginTransmission(address);
231     // assert the MSB of the address to get the gyro
232     // to do slave-transmit subaddress updating.
233     Wire.write(OUT_X_L | (1 << 7));
234     Wire.endTransmission();
235     Wire.requestFrom(address, (byte) 6);
237     unsigned int millis_start = millis();
238     while (Wire.available() < 6) {
239         if (io_timeout > 0
240                 && ((unsigned int) millis() - millis_start) > io_timeout) {
241             did_timeout = true;
242             return;
243         }
244     }
246     uint8_t xlg = Wire.read();
247     uint8_t xhg = Wire.read();
248     uint8_t ylg = Wire.read();
249     uint8_t yhg = Wire.read();
250     uint8_t zlg = Wire.read();
251     uint8_t zhg = Wire.read();
253     // combine high and low bytes
254     g.x = (int16_t)(xhg << 8 | xlg);
255     g.y = (int16_t)(yhg << 8 | ylg);
256     g.z = (int16_t)(zhg << 8 | zlg);
259 /*
260  *  ======== vector_normalize ========
261  */
262 void L3G::vector_normalize(vector<float> *a)
264     float mag = sqrt(vector_dot(a, a));
265     a->x /= mag;
266     a->y /= mag;
267     a->z /= mag;
270 /*
271  *  ======== testReg ========
272  */
273 static int testReg(byte address, L3G::regAddr reg)
275     Wire.beginTransmission(address);
276     Wire.write((byte) reg);
277     if (Wire.endTransmission() != 0) {
278         return TEST_REG_ERROR;
279     }
281     Wire.requestFrom(address, (byte) 1);
282     if (Wire.available()) {
283         return Wire.read();
284     }
285     else {
286         return TEST_REG_ERROR;
287     }