1 /*
2  * Author: Jon Trulson <jtrulson@ics.com>
3  * Copyright (c) 2015 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <unistd.h>
26 #include <iostream>
27 #include <stdexcept>
28 #include <string.h>
29 
30 #include "lsm9ds0.h"
31 
32 using namespace upm;
33 using namespace std;
34 
35 
LSM9DS0(int bus,uint8_t gAddress,uint8_t xmAddress)36 LSM9DS0::LSM9DS0(int bus, uint8_t gAddress, uint8_t xmAddress) :
37   m_i2cG(bus), m_i2cXM(bus), m_gpioG_INT(0), m_gpioG_DRDY(0),
38   m_gpioXM_GEN1(0), m_gpioXM_GEN2(0)
39 {
40   m_gAddr = gAddress;
41   m_xmAddr = xmAddress;
42 
43   m_accelX = 0.0;
44   m_accelY = 0.0;
45   m_accelZ = 0.0;
46 
47   m_gyroX = 0.0;
48   m_gyroY = 0.0;
49   m_gyroZ = 0.0;
50 
51   m_magX = 0.0;
52   m_magY = 0.0;
53   m_magZ = 0.0;
54 
55   m_temp = 0.0;
56 
57   m_accelScale = 0.0;
58   m_gyroScale = 0.0;
59   m_magScale = 0.0;
60 
61   mraa::Result rv;
62   if ( (rv = m_i2cG.address(m_gAddr)) != mraa::SUCCESS)
63     {
64       throw std::runtime_error(string(__FUNCTION__) +
65                                ": Could not initialize Gyro i2c address");
66       return;
67     }
68 
69   if ( (rv = m_i2cXM.address(m_xmAddr)) != mraa::SUCCESS)
70     {
71       throw std::runtime_error(string(__FUNCTION__) +
72                                ": Could not initialize XM i2c address");
73       return;
74     }
75 }
76 
~LSM9DS0()77 LSM9DS0::~LSM9DS0()
78 {
79   uninstallISR(INTERRUPT_G_INT);
80   uninstallISR(INTERRUPT_G_DRDY);
81   uninstallISR(INTERRUPT_XM_GEN1);
82   uninstallISR(INTERRUPT_XM_GEN2);
83 }
84 
init()85 bool LSM9DS0::init()
86 {
87   // Init the gyroscope
88 
89   // power up
90   if (!setGyroscopePowerDown(false))
91     {
92       throw std::runtime_error(string(__FUNCTION__) +
93                                ": Unable to wake up gyro");
94       return false;
95     }
96 
97   // enable all axes
98   if (!setGyroscopeEnableAxes(CTRL_REG1_G_YEN |CTRL_REG1_G_XEN |
99                               CTRL_REG1_G_ZEN))
100     {
101       throw std::runtime_error(string(__FUNCTION__) +
102                                ": Unable to enable gyro axes");
103       return false;
104     }
105 
106   // set gyro ODR
107   if (!setGyroscopeODR(G_ODR_95_25))
108     {
109       throw std::runtime_error(string(__FUNCTION__) +
110                                ": Unable to set gyro ODR");
111       return false;
112     }
113 
114   // set gyro scale
115   if (!setGyroscopeScale(G_FS_245))
116     {
117       throw std::runtime_error(string(__FUNCTION__) +
118                                ": Unable to set gyro scale");
119       return false;
120     }
121 
122   // Init the accelerometer
123 
124   // power up and set ODR
125   if (!setAccelerometerODR(XM_AODR_100))
126     {
127       throw std::runtime_error(string(__FUNCTION__) +
128                                ": Unable to set accel ODR");
129       return false;
130     }
131 
132   // enable all axes
133   if (!setAccelerometerEnableAxes(CTRL_REG1_XM_AXEN |CTRL_REG1_XM_AYEN |
134                                   CTRL_REG1_XM_AZEN))
135     {
136       throw std::runtime_error(string(__FUNCTION__) +
137                                ": Unable to enable accel axes");
138       return false;
139     }
140 
141   // set scaling rate
142   if (!setAccelerometerScale(XM_AFS_2))
143     {
144       throw std::runtime_error(string(__FUNCTION__) +
145                                ": Unable to set accel scale");
146       return false;
147     }
148 
149   // temperature sensor
150 
151   // enable the temperature sensor
152   if (!enableTemperatureSensor(true))
153     {
154       throw std::runtime_error(string(__FUNCTION__) +
155                                ": Unable to enable temp sensor");
156       return false;
157     }
158 
159   // Init the magnetometer
160 
161   // set mode (this also powers it up if not XM_MD_POWERDOWN)
162   if (!setMagnetometerMode(XM_MD_CONTINUOUS))
163     {
164       throw std::runtime_error(string(__FUNCTION__) +
165                                ": Unable to set mag scale");
166       return false;
167     }
168 
169   // turn LPM off
170   if (!setMagnetometerLPM(false))
171     {
172       throw std::runtime_error(string(__FUNCTION__) +
173                                ": Unable to disable mag LPM");
174       return false;
175     }
176 
177   // set resolution
178   if (!setMagnetometerResolution(XM_RES_LOW))
179     {
180       throw std::runtime_error(string(__FUNCTION__) +
181                                ": Unable to set mag res");
182       return false;
183     }
184 
185   // set ODR
186   if (!setMagnetometerODR(XM_ODR_12_5))
187     {
188       throw std::runtime_error(string(__FUNCTION__) +
189                                ": Unable to set mag ODR");
190       return false;
191     }
192 
193   // set scale
194   if (!setMagnetometerScale(XM_MFS_2))
195     {
196       throw std::runtime_error(string(__FUNCTION__) +
197                                ": Unable to set mag scale");
198       return false;
199     }
200 
201   return true;
202 }
203 
204 
update()205 void LSM9DS0::update()
206 {
207   updateGyroscope();
208   updateAccelerometer();
209   updateMagnetometer();
210   updateTemperature();
211 }
212 
updateGyroscope()213 void LSM9DS0::updateGyroscope()
214 {
215   uint8_t buffer[6];
216 
217   memset(buffer, 0, 6);
218   readRegs(DEV_GYRO, REG_OUT_X_L_G, buffer, 6);
219 
220   int16_t x, y, z;
221 
222   x =  ( (buffer[1] << 8) | buffer[0] );
223   y =  ( (buffer[3] << 8) | buffer[2] );
224   z =  ( (buffer[5] << 8) | buffer[4] );
225 
226   m_gyroX = float(x);
227   m_gyroY = float(y);
228   m_gyroZ = float(z);
229 }
230 
updateAccelerometer()231 void LSM9DS0::updateAccelerometer()
232 {
233   uint8_t buffer[6];
234 
235   memset(buffer, 0, 6);
236   readRegs(DEV_XM, REG_OUT_X_L_A, buffer, 6);
237 
238   int16_t x, y, z;
239 
240   x =  ( (buffer[1] << 8) | buffer[0] );
241   y =  ( (buffer[3] << 8) | buffer[2] );
242   z =  ( (buffer[5] << 8) | buffer[4] );
243 
244   m_accelX = float(x);
245   m_accelY = float(y);
246   m_accelZ = float(z);
247 }
248 
updateMagnetometer()249 void LSM9DS0::updateMagnetometer()
250 {
251   uint8_t buffer[6];
252 
253   memset(buffer, 0, 6);
254   readRegs(DEV_XM, REG_OUT_X_L_M, buffer, 6);
255 
256   int16_t x, y, z;
257 
258   x =  ( (buffer[1] << 8) | buffer[0] );
259   y =  ( (buffer[3] << 8) | buffer[2] );
260   z =  ( (buffer[5] << 8) | buffer[4] );
261 
262   m_magX = float(x);
263   m_magY = float(y);
264   m_magZ = float(z);
265 }
266 
updateTemperature()267 void LSM9DS0::updateTemperature()
268 {
269   uint8_t buffer[2];
270 
271   memset(buffer, 0, 2);
272   readRegs(DEV_XM, REG_OUT_TEMP_L_XM, buffer, 2);
273 
274   //  cerr << "HIGH: " << int(buffer[1]) << " LOW: " << int(buffer[0]) << endl;
275 
276   // 12b signed
277   int16_t temp = ( (buffer[1] << 8) | (buffer[0] ) );
278   if (temp & 0x0800)
279     {
280       temp &= ~0x0800;
281       temp *= -1;
282     }
283 
284   m_temp = float(temp);
285 }
286 
readReg(DEVICE_T dev,uint8_t reg)287 uint8_t LSM9DS0::readReg(DEVICE_T dev, uint8_t reg)
288 {
289   mraa::I2c *device;
290 
291   switch(dev)
292     {
293     case DEV_GYRO: device = &m_i2cG; break;
294     case DEV_XM:   device = &m_i2cXM; break;
295     default:
296       throw std::logic_error(string(__FUNCTION__) +
297                              ": Internal error, invalid device specified");
298       return 0;
299     }
300 
301   return device->readReg(reg);
302 }
303 
readRegs(DEVICE_T dev,uint8_t reg,uint8_t * buffer,int len)304 void LSM9DS0::readRegs(DEVICE_T dev, uint8_t reg, uint8_t *buffer, int len)
305 {
306   mraa::I2c *device;
307 
308   switch(dev)
309     {
310     case DEV_GYRO: device = &m_i2cG; break;
311     case DEV_XM:   device = &m_i2cXM; break;
312     default:
313       throw std::logic_error(string(__FUNCTION__) +
314                              ": Internal error, invalid device specified");
315       return;
316     }
317 
318   // We need to set the high bit of the register to enable
319   // auto-increment mode for reading multiple registers in one go.
320   device->readBytesReg(reg | m_autoIncrementMode, buffer, len);
321 }
322 
writeReg(DEVICE_T dev,uint8_t reg,uint8_t val)323 bool LSM9DS0::writeReg(DEVICE_T dev, uint8_t reg, uint8_t val)
324 {
325   mraa::I2c *device;
326 
327   switch(dev)
328     {
329     case DEV_GYRO: device = &m_i2cG; break;
330     case DEV_XM:   device = &m_i2cXM; break;
331     default:
332       throw std::logic_error(string(__FUNCTION__) +
333                              ": Internal error, invalid device specified");
334       return false;
335     }
336 
337   mraa::Result rv;
338   if ((rv = device->writeReg(reg, val)) != mraa::SUCCESS)
339     {
340       throw std::runtime_error(std::string(__FUNCTION__) +
341                                ": I2c.writeReg() failed");
342       return false;
343     }
344 
345   return true;
346 }
347 
setGyroscopePowerDown(bool enable)348 bool LSM9DS0::setGyroscopePowerDown(bool enable)
349 {
350   uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
351 
352   if (enable)
353     reg &= ~CTRL_REG1_G_PD;
354   else
355     reg |= CTRL_REG1_G_PD;
356 
357   return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
358 }
359 
setGyroscopeEnableAxes(uint8_t axes)360 bool LSM9DS0::setGyroscopeEnableAxes(uint8_t axes)
361 {
362   uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
363 
364   // filter out any non-axis related data from arg
365   axes &= (CTRL_REG1_G_YEN | CTRL_REG1_G_XEN |  CTRL_REG1_G_ZEN);
366 
367   // clear them in the register
368   reg &= ~(CTRL_REG1_G_YEN | CTRL_REG1_G_XEN |  CTRL_REG1_G_ZEN);
369 
370   // now add them
371   reg |= axes;
372 
373   return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
374 }
375 
setGyroscopeODR(G_ODR_T odr)376 bool LSM9DS0::setGyroscopeODR(G_ODR_T odr)
377 {
378   uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG1_G);
379 
380   reg &= ~(_CTRL_REG1_G_ODR_MASK << _CTRL_REG1_G_ODR_SHIFT);
381 
382   reg |= (odr << _CTRL_REG1_G_ODR_SHIFT);
383 
384   return writeReg(DEV_GYRO, REG_CTRL_REG1_G, reg);
385 }
386 
setGyroscopeScale(G_FS_T scale)387 bool LSM9DS0::setGyroscopeScale(G_FS_T scale)
388 {
389   uint8_t reg = readReg(DEV_GYRO, REG_CTRL_REG4_G);
390 
391   reg &= ~(_CTRL_REG4_G_FS_MASK << _CTRL_REG4_G_FS_SHIFT);
392 
393   reg |= (scale << _CTRL_REG4_G_FS_SHIFT);
394 
395   if (!writeReg(DEV_GYRO, REG_CTRL_REG4_G, reg))
396     {
397       return false;
398     }
399 
400   // store scaling factor (mDeg/s/LSB)
401 
402   switch (scale)
403     {
404     case G_FS_245:
405       m_gyroScale = 8.75;
406       break;
407 
408     case G_FS_500:
409       m_gyroScale = 17.5;
410       break;
411 
412     case G_FS_2000:
413       m_gyroScale = 70.0;
414       break;
415 
416     default: // should never occur, but...
417       m_gyroScale = 0.0;        // set a safe, though incorrect value
418       throw std::logic_error(string(__FUNCTION__) +
419                              ": internal error, unsupported scale");
420       break;
421     }
422 
423   return true;
424 }
425 
setAccelerometerEnableAxes(uint8_t axes)426 bool LSM9DS0::setAccelerometerEnableAxes(uint8_t axes)
427 {
428   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG1_XM);
429 
430   // filter out any non-axis related data from arg
431   axes &= (CTRL_REG1_XM_AXEN | CTRL_REG1_XM_AYEN | CTRL_REG1_XM_AZEN);
432 
433   // clear them in the register
434   reg &= ~(CTRL_REG1_XM_AXEN | CTRL_REG1_XM_AYEN | CTRL_REG1_XM_AZEN);
435 
436   // now add them
437   reg |= axes;
438 
439   return writeReg(DEV_XM, REG_CTRL_REG1_XM, reg);
440 }
441 
setAccelerometerODR(XM_AODR_T odr)442 bool LSM9DS0::setAccelerometerODR(XM_AODR_T odr)
443 {
444   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG1_XM);
445 
446   reg &= ~(_CTRL_REG1_XM_AODR_MASK << _CTRL_REG1_XM_AODR_SHIFT);
447 
448   reg |= (odr << _CTRL_REG1_XM_AODR_SHIFT);
449 
450   return writeReg(DEV_XM, REG_CTRL_REG1_XM, reg);
451 }
452 
setAccelerometerScale(XM_AFS_T scale)453 bool LSM9DS0::setAccelerometerScale(XM_AFS_T scale)
454 {
455   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG2_XM);
456 
457   reg &= ~(_CTRL_REG2_XM_AFS_MASK << _CTRL_REG2_XM_AFS_SHIFT);
458 
459   reg |= (scale << _CTRL_REG2_XM_AFS_SHIFT);
460 
461   if (!writeReg(DEV_XM, REG_CTRL_REG2_XM, reg))
462     {
463       return false;
464     }
465 
466   // store scaling factor
467 
468   switch (scale)
469     {
470     case XM_AFS_2:
471       m_accelScale = 0.061;
472       break;
473 
474     case XM_AFS_4:
475       m_accelScale = 0.122 ;
476       break;
477 
478     case XM_AFS_6:
479       m_accelScale = 0.183 ;
480       break;
481 
482     case XM_AFS_8:
483       m_accelScale = 0.244 ;
484       break;
485 
486     case XM_AFS_16:
487       m_accelScale = 0.732 ;
488       break;
489 
490     default: // should never occur, but...
491       m_accelScale = 0.0;        // set a safe, though incorrect value
492       throw std::logic_error(string(__FUNCTION__) +
493                              ": internal error, unsupported scale");
494       break;
495     }
496 
497   return true;
498 }
499 
setMagnetometerResolution(XM_RES_T res)500 bool LSM9DS0::setMagnetometerResolution(XM_RES_T res)
501 {
502   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
503 
504   reg &= ~(_CTRL_REG5_XM_RES_MASK << _CTRL_REG5_XM_RES_SHIFT);
505 
506   reg |= (res << _CTRL_REG5_XM_RES_SHIFT);
507 
508   return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
509 }
510 
setMagnetometerODR(XM_ODR_T odr)511 bool LSM9DS0::setMagnetometerODR(XM_ODR_T odr)
512 {
513   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
514 
515   reg &= ~(_CTRL_REG5_XM_ODR_MASK << _CTRL_REG5_XM_ODR_SHIFT);
516 
517   reg |= (odr << _CTRL_REG5_XM_ODR_SHIFT);
518 
519   return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
520 }
521 
setMagnetometerMode(XM_MD_T mode)522 bool LSM9DS0::setMagnetometerMode(XM_MD_T mode)
523 {
524   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG7_XM);
525 
526   reg &= ~(_CTRL_REG7_XM_MD_MASK << _CTRL_REG7_XM_MD_SHIFT);
527 
528   reg |= (mode << _CTRL_REG7_XM_MD_SHIFT);
529 
530   return writeReg(DEV_XM, REG_CTRL_REG7_XM, reg);
531 }
532 
setMagnetometerLPM(bool enable)533 bool LSM9DS0::setMagnetometerLPM(bool enable)
534 {
535   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG7_XM);
536 
537   if (enable)
538     reg |= CTRL_REG7_XM_MLP;
539   else
540     reg &= ~CTRL_REG7_XM_MLP;
541 
542   return writeReg(DEV_XM, REG_CTRL_REG7_XM, reg);
543 }
544 
setMagnetometerScale(XM_MFS_T scale)545 bool LSM9DS0::setMagnetometerScale(XM_MFS_T scale)
546 {
547   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG6_XM);
548 
549   reg &= ~(_CTRL_REG6_XM_MFS_MASK << _CTRL_REG6_XM_MFS_SHIFT);
550 
551   reg |= (scale << _CTRL_REG6_XM_MFS_SHIFT);
552 
553   if (!writeReg(DEV_XM, REG_CTRL_REG6_XM, reg))
554     {
555       return false;
556     }
557 
558   // store scaling factor
559 
560   switch (scale)
561     {
562     case XM_MFS_2:
563       m_magScale = 0.08;
564       break;
565 
566     case XM_MFS_4:
567       m_magScale = 0.16;
568       break;
569 
570     case XM_MFS_8:
571       m_magScale = 0.32;
572       break;
573 
574     case XM_MFS_12:
575       m_magScale = 0.48;
576       break;
577 
578     default: // should never occur, but...
579       m_magScale = 0.0;        // set a safe, though incorrect value
580       throw std::logic_error(string(__FUNCTION__) +
581                              ": internal error, unsupported scale");
582       break;
583     }
584 
585   return true;
586 }
587 
getAccelerometer(float * x,float * y,float * z)588 void LSM9DS0::getAccelerometer(float *x, float *y, float *z)
589 {
590   if (x)
591     *x = (m_accelX * m_accelScale) / 1000.0;
592 
593   if (y)
594     *y = (m_accelY * m_accelScale) / 1000.0;
595 
596   if (z)
597     *z = (m_accelZ * m_accelScale) / 1000.0;
598 }
599 
getGyroscope(float * x,float * y,float * z)600 void LSM9DS0::getGyroscope(float *x, float *y, float *z)
601 {
602   if (x)
603     *x = (m_gyroX * m_gyroScale) / 1000.0;
604 
605   if (y)
606     *y = (m_gyroY * m_gyroScale) / 1000.0;
607 
608   if (z)
609     *z = (m_gyroZ * m_gyroScale) / 1000.0;
610 }
611 
getMagnetometer(float * x,float * y,float * z)612 void LSM9DS0::getMagnetometer(float *x, float *y, float *z)
613 {
614   if (x)
615     *x = (m_magX * m_magScale) / 1000.0;
616 
617   if (y)
618     *y = (m_magY * m_magScale) / 1000.0;
619 
620   if (z)
621     *z = (m_magZ * m_magScale) / 1000.0;
622 }
623 
624 #ifdef JAVACALLBACK
getAccelerometer()625 float *LSM9DS0::getAccelerometer()
626 {
627   float *v = new float[3];
628   getAccelerometer(&v[0], &v[1], &v[2]);
629   return v;
630 }
631 
getGyroscope()632 float *LSM9DS0::getGyroscope()
633 {
634   float *v = new float[3];
635   getGyroscope(&v[0], &v[1], &v[2]);
636   return v;
637 }
638 
getMagnetometer()639 float *LSM9DS0::getMagnetometer()
640 {
641   float *v = new float[3];
642   getMagnetometer(&v[0], &v[1], &v[2]);
643   return v;
644 }
645 #endif
646 
getTemperature()647 float LSM9DS0::getTemperature()
648 {
649   // This might be wrong... The datasheet does not provide enough info
650   // to calculate the temperature given a specific sensor reading.  So
651   // - with 12b resolution, signed, and 8 degrees/per LSB, we come up
652   // with the following.  Then scale up and we get a number that seems
653   // pretty close.
654   return (((m_temp / 2048.0) * 8.0) * 100.0);
655 }
656 
enableTemperatureSensor(bool enable)657 bool LSM9DS0::enableTemperatureSensor(bool enable)
658 {
659   uint8_t reg = readReg(DEV_XM, REG_CTRL_REG5_XM);
660 
661   if (enable)
662     reg |= CTRL_REG5_XM_TEMP_EN;
663   else
664     reg &= ~CTRL_REG5_XM_TEMP_EN;
665 
666   return writeReg(DEV_XM, REG_CTRL_REG5_XM, reg);
667 }
668 
getGyroscopeStatus()669 uint8_t LSM9DS0::getGyroscopeStatus()
670 {
671   return readReg(DEV_GYRO, REG_STATUS_REG_G);
672 }
673 
getMagnetometerStatus()674 uint8_t LSM9DS0::getMagnetometerStatus()
675 {
676   return readReg(DEV_XM, REG_STATUS_REG_M);
677 }
678 
getAccelerometerStatus()679 uint8_t LSM9DS0::getAccelerometerStatus()
680 {
681   return readReg(DEV_XM, REG_STATUS_REG_A);
682 }
683 
getGyroscopeInterruptConfig()684 uint8_t LSM9DS0::getGyroscopeInterruptConfig()
685 {
686   return readReg(DEV_GYRO, REG_INT1_CFG_G);
687 }
688 
setGyroscopeInterruptConfig(uint8_t enables)689 bool LSM9DS0::setGyroscopeInterruptConfig(uint8_t enables)
690 {
691   return writeReg(DEV_GYRO, REG_INT1_CFG_G, enables);
692 }
693 
getGyroscopeInterruptSrc()694 uint8_t LSM9DS0::getGyroscopeInterruptSrc()
695 {
696   return readReg(DEV_GYRO, REG_INT1_SRC_G);
697 }
698 
getMagnetometerInterruptControl()699 uint8_t LSM9DS0::getMagnetometerInterruptControl()
700 {
701   return readReg(DEV_XM, REG_INT_CTRL_REG_M);
702 }
703 
setMagnetometerInterruptControl(uint8_t enables)704 bool LSM9DS0::setMagnetometerInterruptControl(uint8_t enables)
705 {
706   return writeReg(DEV_XM, REG_INT_CTRL_REG_M, enables);
707 }
708 
getMagnetometerInterruptSrc()709 uint8_t LSM9DS0::getMagnetometerInterruptSrc()
710 {
711   return readReg(DEV_XM, REG_INT_SRC_REG_M);
712 }
713 
getInterruptGen1()714 uint8_t LSM9DS0::getInterruptGen1()
715 {
716   return readReg(DEV_XM, REG_INT_GEN_1_REG);
717 }
718 
setInterruptGen1(uint8_t enables)719 bool LSM9DS0::setInterruptGen1(uint8_t enables)
720 {
721   return writeReg(DEV_XM, REG_INT_GEN_1_REG, enables);
722 }
723 
getInterruptGen1Src()724 uint8_t LSM9DS0::getInterruptGen1Src()
725 {
726   return readReg(DEV_XM, REG_INT_GEN_1_SRC);
727 }
728 
getInterruptGen2()729 uint8_t LSM9DS0::getInterruptGen2()
730 {
731   return readReg(DEV_XM, REG_INT_GEN_2_REG);
732 }
733 
setInterruptGen2(uint8_t enables)734 bool LSM9DS0::setInterruptGen2(uint8_t enables)
735 {
736   return writeReg(DEV_XM, REG_INT_GEN_2_REG, enables);
737 }
738 
getInterruptGen2Src()739 uint8_t LSM9DS0::getInterruptGen2Src()
740 {
741   return readReg(DEV_XM, REG_INT_GEN_2_SRC);
742 }
743 
744 #ifdef SWIGJAVA
installISR(INTERRUPT_PINS_T intr,int gpio,mraa::Edge level,IsrCallback * cb)745 void LSM9DS0::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
746 			 IsrCallback *cb)
747 {
748         installISR(intr, gpio, level, generic_callback_isr, cb);
749 }
750 #endif
751 
installISR(INTERRUPT_PINS_T intr,int gpio,mraa::Edge level,void (* isr)(void *),void * arg)752 void LSM9DS0::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
753                          void (*isr)(void *), void *arg)
754 {
755   // delete any existing ISR and GPIO context
756   uninstallISR(intr);
757 
758   // greate gpio context
759   getPin(intr) = new mraa::Gpio(gpio);
760 
761   getPin(intr)->dir(mraa::DIR_IN);
762   getPin(intr)->isr(level, isr, arg);
763 }
764 
uninstallISR(INTERRUPT_PINS_T intr)765 void LSM9DS0::uninstallISR(INTERRUPT_PINS_T intr)
766 {
767   if (getPin(intr))
768     {
769       getPin(intr)->isrExit();
770       delete getPin(intr);
771 
772       getPin(intr) = 0;
773     }
774 }
775 
getPin(INTERRUPT_PINS_T intr)776 mraa::Gpio*& LSM9DS0::getPin(INTERRUPT_PINS_T intr)
777 {
778   switch(intr)
779     {
780     case INTERRUPT_G_INT:
781       return m_gpioG_INT;
782       break;
783     case INTERRUPT_G_DRDY:
784       return m_gpioG_DRDY;
785       break;
786     case INTERRUPT_XM_GEN1:
787       return m_gpioXM_GEN1;
788       break;
789     case INTERRUPT_XM_GEN2:
790       return m_gpioXM_GEN2;
791       break;
792     default:
793       throw std::out_of_range(string(__FUNCTION__) +
794                               ": Invalid interrupt enum passed");
795     }
796 }
797