Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MMA7660.cpp 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include "MMA7660.h"
  2. MMA7660::MMA7660(PinName sda, PinName scl, bool active) : _i2c(sda, scl)
  3. {
  4. setActive(active);
  5. samplerate = 64;
  6. }
  7. //Since the MMA lacks a WHO_AM_I register, we can only check if there is a device that answers to the I2C address
  8. bool MMA7660::testConnection( void )
  9. {
  10. if (_i2c.write(MMA7660_ADDRESS, NULL, 0) == 0 )
  11. return true;
  12. else
  13. return false;
  14. }
  15. void MMA7660::setActive(bool state)
  16. {
  17. char modereg = read(MMA7660_MODE_R);
  18. modereg &= ~(1<<0);
  19. //If it somehow was in testmode, disable that
  20. if (modereg && (1<<2)) {
  21. modereg &= ~(1<<2);
  22. write(MMA7660_MODE_R, modereg);
  23. }
  24. modereg += state;
  25. write(MMA7660_MODE_R, modereg);
  26. }
  27. void MMA7660::readData(int *data)
  28. {
  29. if (!active) {
  30. setActive(true);
  31. active = true;
  32. wait(0.012 + 1/samplerate); //Wait until new sample is ready, my experience is that 1/samplerate isnt needed, but datasheet says so
  33. }
  34. char temp[3];
  35. bool alert;
  36. do {
  37. alert = false;
  38. read(MMA7660_XOUT_R, temp, 3);
  39. for (int i = 0; i<3; i++) {
  40. if (temp[i] > 63)
  41. alert = true;
  42. if (temp[i] > 31)
  43. temp[i] += 128+64;
  44. data[i] = (signed char)temp[i];
  45. }
  46. } while (alert);
  47. if (!active)
  48. setActive(false);
  49. }
  50. void MMA7660::readData(float *data)
  51. {
  52. int intdata[3];
  53. readData(intdata);
  54. for (int i = 0; i<3; i++)
  55. data[i] = intdata[i]/MMA7660_SENSITIVITY;
  56. }
  57. float MMA7660::x( void )
  58. {
  59. return getSingle(0);
  60. }
  61. float MMA7660::y( void )
  62. {
  63. return getSingle(1);
  64. }
  65. float MMA7660::z( void )
  66. {
  67. return getSingle(2);
  68. }
  69. void MMA7660::setSampleRate(int samplerate)
  70. {
  71. setActive(false); //Not allowed to be active to change anything
  72. int rates[] = {120, 64, 32, 16, 8, 4, 2, 1}; //Alowed samplerates (and their number in array is also number required for MMA)
  73. int sampleLoc = 0, sampleError = 10000, temp;
  74. for (int i = 0; i<8; i++) {
  75. temp = abs( rates[i] - samplerate );
  76. if (temp<sampleError) {
  77. sampleLoc = i;
  78. sampleError=temp;
  79. }
  80. }
  81. //Update the samplerate reg
  82. temp = read(MMA7660_SR_R);
  83. temp &= ~0x07; //Awake sample rate are lowest 3 bit
  84. temp |= sampleLoc;
  85. write(MMA7660_SR_R, temp);
  86. this->samplerate = rates[sampleLoc];
  87. setActive(active); //Restore previous active state
  88. }
  89. MMA7660::Orientation MMA7660::getSide( void )
  90. {
  91. char tiltreg = read(MMA7660_TILT_R);
  92. //We care about 2 LSBs
  93. tiltreg &= 0x03;
  94. if (tiltreg == 0x01)
  95. return MMA7660::Front;
  96. if (tiltreg == 0x02)
  97. return MMA7660::Back;
  98. return MMA7660::Unknown;
  99. }
  100. MMA7660::Orientation MMA7660::getOrientation( void )
  101. {
  102. char tiltreg = read(MMA7660_TILT_R);
  103. //We care about bit 2, 3 and 4 (counting from zero)
  104. tiltreg &= 0x07<<2;
  105. tiltreg >>= 2;
  106. if (tiltreg == 0x01)
  107. return MMA7660::Left;
  108. if (tiltreg == 0x02)
  109. return MMA7660::Right;
  110. if (tiltreg == 0x05)
  111. return MMA7660::Down;
  112. if (tiltreg == 0x06)
  113. return MMA7660::Up;
  114. return MMA7660::Unknown;
  115. }
  116. //////////////////////////////////////////////
  117. ///////////////PRIVATE////////////////////////
  118. //////////////////////////////////////////////
  119. void MMA7660::write(char address, char data)
  120. {
  121. char temp[2];
  122. temp[0]=address;
  123. temp[1]=data;
  124. _i2c.write(MMA7660_ADDRESS, temp, 2);
  125. }
  126. char MMA7660::read(char address)
  127. {
  128. char retval;
  129. _i2c.write(MMA7660_ADDRESS, &address, 1, true);
  130. _i2c.read(MMA7660_ADDRESS, &retval, 1);
  131. return retval;
  132. }
  133. void MMA7660::read(char address, char *data, int length)
  134. {
  135. _i2c.write(MMA7660_ADDRESS, &address, 1, true);
  136. _i2c.read(MMA7660_ADDRESS, data, length);
  137. }
  138. float MMA7660::getSingle( int number )
  139. {
  140. if (!active) {
  141. setActive(true);
  142. wait(0.012 + 1/samplerate); //Wait until new sample is ready
  143. }
  144. signed char temp;
  145. bool alert;
  146. do {
  147. alert = false;
  148. temp = read(MMA7660_XOUT_R + number);
  149. if (temp > 63)
  150. alert = true;
  151. if (temp > 31)
  152. temp += 128+64;
  153. } while (alert);
  154. if (!active)
  155. setActive(false);
  156. return temp / MMA7660_SENSITIVITY;
  157. }