mma745x.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright (C) 2010 by Rittal GmbH & Co. KG,
  3. * Dawid Sadji <sadji.d@rittal.de> All rights reserved.
  4. * Ulrich Prinz <prinz.u@rittal.de> All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY EMBEDDED IT AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EMBEDDED IT
  23. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  26. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*
  35. * \file dev/mma745x.c
  36. * \brief Driver for Freescale MMA745x velocity sensor.
  37. *
  38. * \verbatim
  39. * $Id$
  40. * \endverbatim
  41. */
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #include <compiler.h>
  45. #include <cfg/os.h>
  46. #include <sys/heap.h>
  47. #include <sys/timer.h>
  48. #include <sys/event.h>
  49. #include <dev/gpio.h>
  50. #include <dev/twif.h>
  51. #include <dev/mma745x.h>
  52. //#define MMA_DEBUG
  53. #ifdef MMA_DEBUG
  54. #include <stdio.h>
  55. #define MPRINTF printf
  56. #define FFLUSH fflush
  57. #else
  58. #define MPRINTF(...)
  59. #define FFLUSH(...)
  60. #endif
  61. #define SGN10BIT 0x0200
  62. #define Con2Cpl( v) if (v & SGN10BIT) { v ^= ~SGN10BIT; v += SGN10BIT; }
  63. const mmaInit_t mmaDefault = {
  64. /* rMODE */ MMA745X_MODE,
  65. /* rINTRST */ 0x00,
  66. /* rCONTROL1 */ 0x00 /*MMA745x_CTL1_THOPT*/,
  67. /* rCONTROL2 */ 0x00,
  68. /* rLEVEL */ 127, /* 128/8x8g = 127 == DISABLED */
  69. /* rPVALUE */ 24, /* 128/8x1,5g = 24*/
  70. /* rPDUR */ 100, /* x0.5ms = 50ms */
  71. /* rLATTV */ 0, /* x1.0ms = 0ms */
  72. /* rTW */ 0, /* x1.0ms = 0ms */
  73. };
  74. /*! brief MMA745x configuration struct.
  75. */
  76. static mmaInit_t *mmaCfg;
  77. static mma8bit_t *mmaForce;
  78. /*! brief write to MMA7455L via I2C.
  79. *
  80. * Write one byte to a register in the sensor.
  81. * \para reg Register in sensor to address.
  82. * \para val Pointer to value to write.
  83. *
  84. * \return 0 if success, -1 on error.
  85. */
  86. int Mma745xWrite( uint_fast8_t reg, void *val, size_t len)
  87. {
  88. int ret;
  89. ret = TwMasterRegWrite(I2C_SLA_MMA745x, reg, 1, val, len, 500);
  90. return (ret == len)?0:-1;
  91. }
  92. /*! brief read from MMA7455L via I2C.
  93. *
  94. * Read one byte from a register in the sensor.
  95. * \para reg Register in sensor to address.
  96. * \para val Pointer to store the value.
  97. *
  98. * \return 0 if success, -1 on error.
  99. */
  100. int Mma745xRead( uint_fast8_t reg, void *val, size_t len)
  101. {
  102. int ret;
  103. ret = TwMasterRegRead(I2C_SLA_MMA745x, reg, 1, val, len, 500);
  104. return (ret == len)?0:-1;
  105. }
  106. /*! bief read all axes of the sensor as raw value.
  107. *
  108. * This function read the current sensor values.
  109. * Depending on the setup the values are in range of:
  110. * 2g Mode: -2g..0g..2g -> 0x80..0x00..0x7f
  111. * 4g Mode: -4g..0g..4g -> 0x80..0x00..0x7f
  112. * 8g Mode: -8g..0g..8g -> 0x80..0x00..0x7f
  113. *
  114. * para Pointer to mma8bit_t struct to store results in.
  115. * result 0 if request was successfull, else -1;
  116. */
  117. int Mma745xReadVal8( mma8bit_t *val)
  118. {
  119. return Mma745xRead(MMA745x_REG_XOUT8, val, sizeof(mma8bit_t));
  120. }
  121. /*! bief read all axes of the sensor as raw value.
  122. *
  123. * This function read the current sensor values.
  124. * Depending on the setup the values are in range of:
  125. * 8g Mode: -8g..0g..8g -> 0x0200..0x0000..0x01ff
  126. *
  127. * para Pointer to mma8bit_t struct to store results in.
  128. * result 0 if request was successfull, else -1;
  129. */
  130. int Mma745xReadVal10( uint8_t ofs, mma10bit_t *val)
  131. {
  132. int ret;
  133. ret = Mma745xRead( ofs, val, sizeof(mma10bit_t));
  134. /* 2's complement to int conversion */
  135. Con2Cpl(val->x);
  136. Con2Cpl(val->y);
  137. Con2Cpl(val->z);
  138. return ret;
  139. }
  140. int Mma745xReadG( mma10bit_t *val)
  141. {
  142. int ret;
  143. ret = Mma745xReadVal8( mmaForce);
  144. switch (mmaCfg->rMODE & MMA745X_MCTL_GLVL_MSK) {
  145. case MMA745X_MCTL_GLVL_8G:
  146. val->x = ((int16_t)mmaForce->x*100/16);
  147. val->y = ((int16_t)mmaForce->y*100/16);
  148. val->z = ((int16_t)mmaForce->z*100/16);
  149. break;
  150. case MMA745X_MCTL_GLVL_4G:
  151. val->x = ((int16_t)mmaForce->x*100/32);
  152. val->y = ((int16_t)mmaForce->y*100/32);
  153. val->z = ((int16_t)mmaForce->z*100/32);
  154. break;
  155. case MMA745X_MCTL_GLVL_2G:
  156. val->x = ((int16_t)mmaForce->x*100/64);
  157. val->y = ((int16_t)mmaForce->y*100/64);
  158. val->z = ((int16_t)mmaForce->z*100/64);
  159. break;
  160. }
  161. return ret;
  162. }
  163. int Mma745xReadCal( mma10bit_t *cal)
  164. {
  165. int ret;
  166. ret = Mma745xReadVal10(MMA745x_REG_XOFFL, cal);
  167. return ret;
  168. }
  169. int Mma745xWriteCal( mma10bit_t *cal)
  170. {
  171. int ret;
  172. ret = Mma745xWrite(MMA745x_REG_XOFFL, cal, sizeof(mma10bit_t));
  173. return ret;
  174. }
  175. int Mma745xCtl( uint_fast8_t fkt, void *val)
  176. {
  177. int ret = -1;
  178. uint8_t irqs;
  179. MPRINTF("MCTL(%u,%p)\n", fkt, val);
  180. switch (fkt) {
  181. case MMA_GET_STATE:
  182. ret = Mma745xRead(MMA745x_REG_STATUS, val, 2);
  183. break;
  184. case MMA_SET_MODE:
  185. ret = Mma745xWrite(MMA745x_REG_MCTL, val, 1);
  186. if (ret == 0)
  187. mmaCfg->rMODE = *(uint8_t*)val;
  188. break;
  189. case MMA_GET_IRQ:
  190. /* Get pending IRQS */
  191. ret = Mma745xRead(MMA745x_REG_DETSRC, val, 1);
  192. break;
  193. #if 0
  194. case MMA_SET_IRQ:
  195. /* Enable IRQs given in val */
  196. irqs = (*(uint8_t*)val) & MMA745x_INTRST_MSK;
  197. ret = Mma745xWrite(MMA745x_REG_INTRST, &irqs, 1);
  198. break;
  199. #endif
  200. case MMA_CLR_IRQ:
  201. /* Clear IRQs given in val */
  202. irqs = (*(uint8_t*)val) & MMA745x_INTRST_MSK;
  203. ret = Mma745xWrite(MMA745x_REG_INTRST, &irqs, 1);
  204. irqs ^= MMA745x_INTRST_MSK;
  205. ret = Mma745xWrite(MMA745x_REG_INTRST, &irqs, 1);
  206. break;
  207. }
  208. return ret;
  209. }
  210. /*! brief MMA7455L Initialization
  211. *
  212. * Configure GPIO connections and preset
  213. * MMA7455L registers.
  214. *
  215. * \return 0 if success, -1 on error.
  216. */
  217. int Mma745xInit( uint_fast8_t selftest, mmaInit_t *init)
  218. {
  219. int ret = 0;
  220. uint8_t ctl = 0;
  221. MPRINTF("Init MMA... ");
  222. mmaCfg = NutHeapAlloc(sizeof(mmaInit_t));
  223. if (mmaCfg==NULL)
  224. return -1;
  225. mmaForce = NutHeapAlloc(sizeof(mma8bit_t));
  226. if (mmaForce==NULL)
  227. return -1;
  228. /* Configure INT1/DRDY and INT2 lines from chip */
  229. #if defined(MMA745X_IRQ1_PORT) && defined(MMA745X_IRQ1_PIN)
  230. GpioPinConfigSet(MMA745X_IRQ1_PORT, MMA745X_IRQ1_PIN, GPIO_CFG_PULLUP);
  231. #endif
  232. #if defined(MMA745X_IRQ2_PORT) && defined(MMA745X_IRQ2_PIN)
  233. GpioPinConfigSet(MMA745X_IRQ2_PORT, MMA745X_IRQ2_PIN, GPIO_CFG_PULLUP);
  234. #endif
  235. /* First time initialization of the chip */
  236. if (init)
  237. memcpy( mmaCfg, init, sizeof(mmaInit_t));
  238. else
  239. memcpy( mmaCfg, &mmaDefault, sizeof(mmaInit_t));
  240. Mma745xWrite(MMA745x_REG_MCTL, mmaCfg, sizeof(mmaInit_t));
  241. /* Check if selftest should be done on startup */
  242. if (selftest) {
  243. // TODO: Selftest is badly described in docs. Try to figure out how it works...
  244. ctl = MMA745X_MCTL_STON;
  245. Mma745xWrite(MMA745x_REG_MCTL, &ctl, 1);
  246. }
  247. return ret;
  248. }