CircleOS  1
mems.c
Go to the documentation of this file.
1 /****************** COPYRIGHT (C) 2007-2013 KEOLABS S.A.S. ********************/
17 /******************************************************************************/
18 
19 /* Includes ------------------------------------------------------------------*/
20 #include "circle.h"
21 
23 
24 /* Private define ------------------------------------------------------------*/
25 //~ #define MEMS_TESTING_DIVIDER 101
26 #define MARGIN 500
27 #define DELAY_REACT 20
28 #define MIN_REACT 15
29 #define DIV_REACT 10
30 #define GRAD_SHOCK 350000
31 
32 
33 /* Private variables ---------------------------------------------------------*/
34 tMEMS_Info MEMS_Info = {0}; // structure definition in circle.h
35 s32 TestingActive = 0;
36 s32 StartingFromResetOrShockCounter = 1000;
37 s32 TimeCounterForDoubleClick = 0;
38 s32 TimeLastShock = 0;
39 u32 Gradient2;
40 
41 // Gradient
42 s32 GradX = 0;
43 s32 GradY = 0;
44 s32 GradZ = 0;
45 
46 coord_t XInit = 0;
47 coord_t YInit = 0;
48 coord_t ZInit = 0;
49 
50 /* Private function prototypes -----------------------------------------------*/
51 void MEMS_ChipSelect( u8 State );
52 u8 MEMS_SendByte( u8 byte );
53 u32 MEMS_ReadOutXY( void );
54 void MEMS_WakeUp( void );
55 
56 /* Private functions ---------------------------------------------------------*/
57 
58 
59 /* Public functions for CircleOS ---------------------------------------------*/
60 
61 
62 /*******************************************************************************
63 *
64 * MEMS_Handler
65 *
66 *******************************************************************************/
75 /******************************************************************************/
76 IRQ void MEMS_Handler( void )
77 {
78  static s32 delta_time_ms = 0;
79 
80  if ( StartingFromResetOrShockCounter )
81  {
82  StartingFromResetOrShockCounter--;
83  }
84  TimeCounterForDoubleClick++;
85 
86  MEMS_ReadOutXY();
87 
88  // Evaluate gradients
89  GradX = ( MEMS_Info.OutX_F16 >> 4 ) - MEMS_Info.OutX;
90  GradY = ( MEMS_Info.OutY_F16 >> 4 ) - MEMS_Info.OutY;
91  GradZ = ( MEMS_Info.OutZ_F16 >> 4 ) - MEMS_Info.OutZ;
92 
93  Gradient2 = ( s32 )GradX * ( s32 )GradX + ( s32 )GradY * ( s32 )GradY + ( s32 )GradZ * ( s32 )GradZ;
94 
95  Gradient2 *= freqTIM2[CurrentSpeed] ;
96  Gradient2 /= freqTIM2[SPEED_MEDIUM] ;
97 
98 
99  // MEMS is shocked, let's beep!
100  if (( Gradient2 > GRAD_SHOCK ) && ( BUZZER_GetMode() == BUZZER_OFF ) && ( StartingFromResetOrShockCounter == 0 ) )
101  {
102  MEMS_Info.Shocked++;
103  /*FL071007 = 1;
104  Suggested by Bob Seabrook: a further possiblity is to increment Shocked rather than just setting it
105  So it can still be tested for non zero as before but one can get more
106  info from the s32 without extra cost. */
107 
108 #define DELAY_BETWEEN_TWO_SHOCK 200
109 #define MAX_DELAY_FOR_DOUBLECLICK 800
110 
111  delta_time_ms = (( TimeCounterForDoubleClick - TimeLastShock ) * 1000 ) / freqTIM2[CurrentSpeed];
112 
113  if ( delta_time_ms > DELAY_BETWEEN_TWO_SHOCK )
114  {
115  if ( delta_time_ms < MAX_DELAY_FOR_DOUBLECLICK )
116  {
117  MEMS_Info.DoubleClick++;
118 // TimeLastShock = TimeCounterForDoubleClick; // YRT20090304
120  StartingFromResetOrShockCounter = freqTIM2[CurrentSpeed]; //1s off
121  }
122  else
123  {
124 // TimeLastShock = TimeCounterForDoubleClick; // YRT20090304
125  delta_time_ms = 0;
126  StartingFromResetOrShockCounter = 0;
127  }
128  TimeLastShock = TimeCounterForDoubleClick; // YRT20090304
129  }
130  else
131  {
132  ;//TimeLastShock = TimeCounterForDoubleClick;
133  }
134  }
135 }
136 
138 
139 /* Public functions ----------------------------------------------------------*/
140 
141 /*******************************************************************************
142 *
143 * MEMS_GetPosition
144 *
145 *******************************************************************************/
158 /******************************************************************************/
159 void MEMS_GetPosition( coord_t* pX, coord_t* pY )
160 {
161  *pX = MEMS_Info.OutX - XInit;
162  *pY = MEMS_Info.OutY - YInit;
163 }
164 
165 /*******************************************************************************
166 *
167 * MEMS_GetRotation
168 *
169 *******************************************************************************/
177 /******************************************************************************/
179 {
180  s16 sX = MEMS_Info.OutX;
181  s16 sY = MEMS_Info.OutY;
182 
183  if ((( sX <= -MARGIN ) && ( sY <= 0 ) && ( sX <= sY ) ) ||
184  (( sX <= - MARGIN ) && ( sY > 0 ) && ( sX <= ( -sY ) ) ) )
185  {
186  // 1st case: x<0, |x|>y => H12 = V9
187  *pH12 = V9;
188  }
189  else if ((( sY <= -MARGIN ) && ( sX <= 0 ) && ( sY <= sX ) ) ||
190  (( sY <= -MARGIN ) && ( sX > 0 ) && ( sY <= ( -sX ) ) ) )
191  {
192  // 2nd case: y<0, |y|>x => H12 = V12
193  *pH12 = V12;
194  }
195  else if ((( sX >= MARGIN ) && ( sY <= 0 ) && ( sX >= ( -sY ) ) ) ||
196  (( sX >= MARGIN ) && ( sY > 0 ) && ( sX >= sY ) ) )
197  {
198  // 3rd case: x>0, |x|>y => H12=V3
199  *pH12 = V3;
200  }
201  else if ((( sY >= MARGIN ) && ( sX <= 0 ) && ( sY >= ( -sX ) ) ) ||
202  (( sY >= MARGIN ) && ( sX > 0 ) && ( sY >= sX ) ) )
203  {
204  // 4th case: y>0, |y|>x => H12=V6
205  *pH12 = V6;
206  }
207 }
208 
209 /*******************************************************************************
210 *
211 * MEMS_SetNeutral
212 *
213 *******************************************************************************/
219 /******************************************************************************/
220 void MEMS_SetNeutral( void )
221 {
222  // Set Neutral position.
223  MEMS_GetPosition( &XInit, &YInit );
224 }
225 
226 /*******************************************************************************
227 *
228 * MEMS_GetInfo
229 *
230 *******************************************************************************/
238 /******************************************************************************/
240 {
241  return &MEMS_Info;
242 }