1 /****************************************************************************
  2  Module
  3    d:\me218bTNG\Lectures\Lecture31\SMTemplate.c
  4 
  5  Revision
  6    1.0.1
  7 
  8  Description
  9    This is a template file for implementing state machines.
 10 
 11  Notes
 12 
 13  History
 14  When           Who     What/Why
 15  -------------- ---     --------
 16  02/13/10 14:29 jec      revised Start and run to add new kind of entry function
 17                          to make implementing history entry cleaner
 18  02/13/10 12:29 jec      added NewEvent local variable to During function and
 19                          comments about using either it or Event as the return
 20  02/11/10 15:54 jec      more revised comments, removing last comment in during
 21                          function that belongs in the run function
 22  02/09/10 17:21 jec      updated comments about internal transitions on During funtion
 23  02/18/09 10:14 jec      removed redundant call to RunLowerlevelSM in EV_Entry
 24                          processing in During function
 25  02/20/07 21:37 jec      converted to use enumerated type for events & states
 26  02/13/05 19:38 jec      added support for self-transitions, reworked
 27                          to eliminate repeated transition code
 28  02/11/05 16:54 jec      converted to implment hierarchy explicitly
 29  02/25/03 10:32 jec      converted to take a passed event parameter
 30  02/18/99 10:19 jec      built template from MasterMachine.c
 31  02/14/99 10:34 jec      Began Coding
 32 ****************************************************************************/
 33 /*----------------------------- Include Files -----------------------------*/
 34 /* include header files for this state machine as well as any machines at the
 35    next lower level in the hierarchy that are sub-machines to this machine
 36 */
 37 #include "GamePlaySM.h"
 38 #include "PlayingSM.h"
 39 #include "Search_And_DestroySM.h"
 40 #include "ReturnHomeSM.h"
 41 
 42 #include <hidef.h>      /* common defines and macros */
 43 #include <stdlib.h>
 44 #include "SMEVENTS.h"
 45 #include "Movement.h"
 46 #include "Gun.h"
 47 #include "FiringSM.h"
 48 #include "Constants.h"
 49 #include "DeadReckoning.h"
 50 #include "Sensors.h"
 51 
 52 #include <stdio.h>
 53 
 54 /*---------------------------- Module Functions ---------------------------*/
 55 /* prototypes for private functions for this machine, things like during
 56    functions, entry & exit functions.They should be functions relevant to the
 57    behavior of this state machine
 58 */
 59 
 60 static Event_t DuringRotateHome(Event_t Event);
 61 static Event_t DuringGoHome(Event_t Event);
 62 static Event_t DuringAlignTapeHome( Event_t Event);
 63 static Event_t DuringFindTIntersectHome( Event_t Event);
 64 static Event_t DuringCoastHome( Event_t Event);
 65 static Event_t DuringGameOver_HOME( Event_t Event);
 66 
 67 /*---------------------------- Module Variables ---------------------------*/
 68 // everybody needs a state variable, you may need others as well
 69 static ReturnHomeState CurrentState;
 70 static char AngleHomeFlag=1;
 71 
 72 /*------------------------------ Module Code ------------------------------*/
 73 /****************************************************************************
 74  Function
 75     RunTemplateSM
 76 
 77  Parameters
 78    Event_t: the event to process
 79 
 80  Returns
 81    Event_t: an event to return
 82 
 83  Description
 84    add your description here
 85  Notes
 86    uses nested switch/case to implement the machine.
 87  Author
 88    J. Edward Carryer, 2/11/05, 10:45AM
 89 ****************************************************************************/
 90 Event_t RunReturnHomeSM( Event_t CurrentEvent )
 91 {
 92    unsigned char MakeTransition = FALSE;/* are we making a state transition? */
 93    ReturnHomeState NextState = CurrentState;
 94    Event_t EntryEventKind = EV_ENTRY;
 95 
 96    switch ( CurrentState )
 97    {
 98 
 99         case RotateHome :       // If current state is state one
100          // Execute During function for state one. EV_ENTRY & EV_EXIT are
101          // processed here
102          DuringRotateHome(CurrentEvent);
103          //process any events
104          if ( CurrentEvent != EV_NO_EVENT )        //If an event is active
105          {
106             switch (CurrentEvent)
107             {
108                case EV_ROTATE_HOME : //If event is event one
109                   // Execute action function for state one : event one
110                   NextState = GoHome;//Decide what the next state will be
111                   // for internal transitions, skip changing MakeTransition
112                   MakeTransition = TRUE; //mark that we are taking a transition
113                   // if transitioning to a state with history change kind of entry
114                   //EntryEventKind - EV_ENTRY_HISTORY;
115                   // optionally, consume or re-map this event for the upper
116                   // level state machine
117                   //CurrentEvent = NewEvent;
118                   break;
119                 // repeat cases as required for relevant events
120             }
121          }
122          break;
123 
124        case GoHome :       // If current state is state one
125          // Execute During function for state one. EV_ENTRY & EV_EXIT are
126          // processed here
127          DuringGoHome(CurrentEvent);
128          //process any events
129          if ( CurrentEvent != EV_NO_EVENT )        //If an event is active
130          {
131             switch (CurrentEvent)
132             {
133                case EV_GOT_HOME : //If event is event one
134                   // Execute action function for state one : event one
135                   NextState = GameOver_Home;//Decide what the next state will be
136                   // for internal transitions, skip changing MakeTransition
137                   MakeTransition = TRUE; //mark that we are taking a transition
138                   // if transitioning to a state with history change kind of entry
139                   //EntryEventKind - EV_ENTRY_HISTORY;
140                   // optionally, consume or re-map this event for the upper
141                   // level state machine
142                   //CurrentEvent = NewEvent;
143                   break;
144                 // repeat cases as required for relevant events
145             }
146          }
147          break;
148 
149 
150        case GameOver_Home :       // Black Hole!!!, do nothing
151          // Execute During function for state one. EV_ENTRY & EV_EXIT are
152          // processed here
153          (void)printf("Current State is Game Over Home");
154          DuringGameOver_HOME(CurrentEvent);
155          //process any events
156          if ( CurrentEvent != EV_NO_EVENT )        //If an event is active
157          {
158             //Game is over...Lets hang out for all eternity and do nothing!!!
159          }
160 
161        break;
162       // repeat state pattern as required for other states
163     }
164 
165     //   If we are making a state transition
166     if (MakeTransition == TRUE)
167     {
168        //   Execute exit function for current state
169        (void)RunReturnHomeSM(EV_EXIT);
170        CurrentState = NextState; //Modify state variable
171        //   Execute entry function for new state
172        (void)RunReturnHomeSM(EntryEventKind);
173      }
174      return(CurrentEvent);
175 }
176 /****************************************************************************
177  Function
178      StartTemplateSM
179 
180  Parameters
181      None
182 
183  Returns
184      None
185 
186  Description
187      Does any required initialization for this state machine
188  Notes
189 
190  Author
191      J. Edward Carryer, 2/18/99, 10:38AM
192 ****************************************************************************/
193 void StartReturnHomeSM ( void)
194 {
195 
196    (void)printf("StartReturnHomeSM\n\r");
197    // to implement entry to a history state or directly to a substate
198    // you can modify the initialization of the CurrentState variable
199    // otherwise just start in the entry state every time the state machine
200    // is started
201    //if ( EV_ENTRY_HISTORY != CurrentEvent )
202    {
203 
204         CurrentState = RotateHome;
205         //CurrentState = Waiting;
206    }
207    // call the entry function (if any) for the ENTRY_STATE
208    (void)RunReturnHomeSM(EV_ENTRY);
209 }
210 
211 /****************************************************************************
212  Function
213      QueryTemplateSM
214 
215  Parameters
216      None
217 
218  Returns
219      TemplateState_t The current state of the Template state machine
220 
221  Description
222      returns the current state of the Template state machine
223  Notes
224 
225  Author
226      J. Edward Carryer, 2/11/05, 10:38AM
227 ****************************************************************************/
228 char QueryAngleHomeFlag ( void )
229 {
230   static char OldFlag=1;
231   char NewFlag, change=0;
232   NewFlag = AngleHomeFlag;
233   //(void)printf("OldFlag: %i  Newflag is %i\r\n", OldFlag, NewFlag);
234   if((NewFlag == 0) && (OldFlag == 1))
235   {
236     change=1;
237   }
238 
239   OldFlag = NewFlag;
240   if(change == 1)
241     (void)printf("Query Angle Home Flag Change: %i", change);
242   return change;
243 }
244 
245 
246 //Check Front center tape sensor to see if we're aligned
247 char QueryTapeAlignedHomeFlag ( void )
248 {
249   static char OldTape = 0;
250   char NewTape, change = 0;
251 
252   NewTape = CheckTape(1);
253 
254   if(OldTape == 1)
255     if(NewTape == 0)
256       change = 1;
257 
258   OldTape = NewTape;
259 
260   return change;
261 }
262 
263 
264 //Uses front-left and front-right tape sensors to tell if we have reached end of tape
265 char QueryTIntersectHomeFlag ( void )
266 {
267   static char OldTape = 0;
268   char NewTape, change = 0;
269 
270   NewTape = (CheckTape(1) && CheckTape(3) );
271 
272 
273   if(OldTape == 0)
274     if(NewTape == 1)
275       change = 1;
276 
277   OldTape = NewTape;
278 
279   return change;
280 }
281 
282 //For event checker...Checks Dead Reckoing to see if we've reached home
283 char QueryReachHomeFlag ( void )
284 {
285   static char OldStatus = 0;
286   char NewStatus, change = 0, NearRedBase, NearGreenBase;
287 
288 
289   NearRedBase = ( (GetXpos() > (WALL_WIDTH - 8))  && (GetYpos() < 8) );
290   NearGreenBase = ( (GetXpos() < 8)  && (GetYpos() > (WALL_HEIGHT - 8)) );
291   if(  NearRedBase ||  NearGreenBase )
292     NewStatus = 1;
293   else
294     NewStatus = 0;
295 
296 
297   if(OldStatus == 0)
298     if(NewStatus == 1)
299       change = 1;
300 
301   OldStatus = NewStatus;
302 
303   return change;
304 }
305 
306 /***************************************************************************
307  private functions
308  ***************************************************************************/
309 
310 
311 static Event_t DuringRotateHome( Event_t Event)
312 {
313   static int TargetAngle;
314     // process EV_ENTRY, EV_ENTRY_HISTORY & EV_EXIT events
315     if ( (Event == EV_ENTRY) )
316     {
317         //Get TargetAngle
318         TargetAngle = CalculateTargetAngle();
319         (void) printf ("Entering DuringRotateHome\r\n");
320         (void)printf("Target Angle: %f   CurrentAngle:  %f", (TargetAngle*(360.0/TicksPerRotation) ), (GetAngle()*(360.0/TicksPerRotation)) );
321         GunSpeed(0);
322         //DO NOTHING
323     }
324     else if ( Event == EV_EXIT )
325     {
326       (void) printf ("Exiting DuringRotateHome\r\n");
327       WheelSpeed(0,0);
328 
329     }else
330     // do the 'during' function for this state
331     {
332         //Keep aadjusting until you reach appropriate angle
333         AngleHomeFlag = SettingAngle(TargetAngle);
334     }
335     return(Event);
336 }
337 
338 
339 static Event_t DuringGoHome( Event_t Event)
340 {
341 
342     // process EV_ENTRY, EV_ENTRY_HISTORY & EV_EXIT events
343     if ( (Event == EV_ENTRY) )
344     {
345         (void) printf ("Entering DuringGoHome\r\n");
346         //DO NOTHING
347     }
348     else if ( Event == EV_EXIT )
349     {
350       WheelSpeed(0,0);
351 
352     }else
353     // do the 'during' function for this state
354     {
355 
356         WheelSpeed(50,50);     // Rotate to find tape
357     }
358     return(Event);
359 }
360 
361 
362 
363 static Event_t DuringGameOver_HOME( Event_t Event)
364 {
365     // process EV_ENTRY, EV_ENTRY_HISTORY & EV_EXIT events
366     if ( (Event == EV_ENTRY) )
367     {
368       (void)printf("Entering DuringGameOver_HOME");
369     }
370     else if ( Event == EV_EXIT )
371     {
372       //Do nothing
373     }else
374     {
375        //Do Nothing
376     }
377     // Do not remap event
378     return(Event);
379 }