Wednesday, September 14, 2011

Test of strength Problem

Problem:
Create a system to play the Test of Strength Game often seen on carnival midways. Inputs A indicate a sensor reading on how hard of an impact the contestant hit the target with the hammer. A non-Zero input A  indicates a valid hit. When the valid bit is asserted, read the ‘impact’ sensor and then output a sequence on the B output that starts with B0 and “rises” to the Nth output bit, then “falls” back to zero.
 When it isn't not hit, the lights will mimic Row 0.  Once a hit has been detected, it will mimic Row 1 and then progress until it reaches the Nth bit.  For example.  if the score is 5 then it should go up to bit 5, thus it shall follow this sequence: row 0->row1->row2->row3->row4->row5->row6->row5->row4->row3->row2->row1->row0

In order to manipulate B to make it easy, we do a little bit of bit manipulation.  We know that left shifting increases the value by a power of two.  We however need a sequence of 1's.  If we want a four continuous 1's then we need to left shift a 1 four times and then subtract one from it.
--------
1<< 4 gives us 0x10
and subtracting it by 1 gives us 0x0F

I continue this pattern and produce the following.

Now it's time for the state machines.  

I use a program called RIBs in order to create the state machines.  It is a great program that generates C code for you based on the state machine you create with it. (When creating this blog it was version 2.4.1)




I used two state machines to accomplish this.  The first state machine deals only with the sensor.  It runs with a period of 200ms in order to capture the hit's without missing any.  The second state machine deals with the lights.  It transitions from state to state every 1000ms.

In the table above I use a formula that looks like this "--(1 << 5)"  how ever, the compiler that the program uses does not accept it so I had to break it into two parts.  I would have to save (1 << 5) into the variable and then subtract 1 from that variable.

As mentioned before, this program generate's C code.  Below is the C code that it generates based off my state machine:

/*
This code was automatically generated using the Riverside-Irvine State machine Builder tool
Version 2.4 --- 9/14/2011 21:7:5 PST
*/

#include "rims.h"


/*This code will be accessible from all State Machines.*/
unsigned char score =0;
unsigned char medium = 0;
unsigned char i = 0;
unsigned char flag = 0;
void TimerISR() {
   flag = 1;
}

const unsigned long int numTasks = 2;

const unsigned long int SM1_period = 200;
const unsigned long int SM2_period = 1000;

const unsigned long int GCD = 200;

typedef struct task {
   int state;
   unsigned long int period;
   unsigned long int elapsedTime;
   int (*TickFct)(int);
} task;


enum SM1_States { SM1_WAIT, SM1_HIT } SM1_State;
int SM1_Tick(int state) {
   /*VARIABLES MUST BE DECLARED STATIC*/
/*e.g., static int x = 0;*/
/*Define User Variables and Functions For this State Machine Here.*/


switch(state) { // Transitions
      case -1:
         state = SM1_State = SM1_WAIT;
         break;
      case SM1_WAIT:
         if (A) {
            state = SM1_State = SM1_HIT;
            score = A;
         }
         else if (!A) {
            state = SM1_State = SM1_WAIT;
         }
         break;
      case SM1_HIT:
         if (!score) {
            state = SM1_State = SM1_WAIT;
         }
         else if (score) {
            state = SM1_State = SM1_HIT;
         }
         break;
      default:
         state = -1;
      } // Transitions

   switch(state) { // State actions
      case SM1_WAIT:
         break;
      case SM1_HIT:
         break;
      default: // ADD default behaviour below
         break;
   } // State actions
   return state;
}


enum SM2_States { SM2_s0, SM2_s1, SM2_s2 } SM2_State;
int SM2_Tick(int state) {
   /*VARIABLES MUST BE DECLARED STATIC*/
/*e.g., static int x = 0;*/
/*Define user variables for this state machine here.*/


switch(state) { // Transitions
      case -1:
         state = SM2_State = SM2_s0;
         break;
      case SM2_s0:
         if (!score) {
            state = SM2_State = SM2_s0;
         }
         else if (score) {
            state = SM2_State = SM2_s2;
         }
         break;
      case SM2_s1:
         if (( i <1)) {
            state = SM2_State = SM2_s0;
            score = 0;
medium = 0;
         }
         else if (!(i < 1)) {
            state = SM2_State = SM2_s1;
            medium = (1 << (--i));
--medium;
         }
         break;
      case SM2_s2:
         if (!(i <= score)) {
            state = SM2_State = SM2_s1;
         }
         else if ((i <= score)) {
            state = SM2_State = SM2_s2;
            medium =(1<<(++i));
--medium;
         }
         break;
      default:
         state = -1;
      } // Transitions

   switch(state) { // State actions
      case SM2_s0:
         B = medium;
i = 0;

         break;
      case SM2_s1:
         B = medium;
         break;
      case SM2_s2:
         B = medium;
         break;
      default: // ADD default behaviour below
         break;
   } // State actions
   return state;
}

int main() {
   unsigned long int i; //scheduler for-loop iterator

   task tasks[2];

   tasks[0].state = -1;
   tasks[0].period = 200;
   tasks[0].elapsedTime = 200;
   tasks[0].TickFct = &SM1_Tick;

   tasks[1].state = -1;
   tasks[1].period = 1000;
   tasks[1].elapsedTime = 1000;
   tasks[1].TickFct = &SM2_Tick;

   TimerSet(GCD);
   TimerOn();
   while(1) {
      for ( i = 0; i < numTasks; ++i ) {
         if ( tasks[i].elapsedTime == tasks[i].period ) {
            tasks[i].state = tasks[i].TickFct(tasks[i].state);
            tasks[i].elapsedTime = 0;
         }
         tasks[i].elapsedTime += GCD;
      }
      while(!flag);
      flag = 0;
   }
   return 0;
}