HC_Controller.c

/****************************************************************************
 Module
     HC_Controller.c
 
 Description
     Main module for HC state machine.

 Notes

 History

 When           Who     What/Why
 -------------- ---     --------
 April 2010     NRM     Started Coding
****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
#include <hidef.h>      /* common defines and macros */
#include <mc9s12e128.h>     /* derivative information */
#include <stdio.h>
#include <S12E128bits.h>
#include <stdlib.h>
#include "ADS12.h"
#include "SCI.h"
#include "HC_Controller.h"
#include "EventChecker.h"
#include "S12eVec.h"
#include "Servo.h"
#pragma LINK_INFO DERIVATIVE "SampleS12"
/*----------------------------- Module Defines ----------------------------*/
#define _FORW_BACK_ 0
#define _RHT_LFT_   1
#define _CANNON_    2
#define _RHT_AIM_   3
#define _LFT_AIM_   4
#define _TURBO_Prop_ 5
#define _PERIOD_ 38000
#define _Voltage_At_Full_Thrust_ 5
#define _SCALE_ 2
#define _MAX_TURN_ 50
#define _CRAB_ID_SERVO_ 0
#define _CRAB_ACUM_SERVO_ 1
/*---------------------------- Module Functions ---------------------------*/
static void E128_Port_Init(void);
static void during_WAITING_FOR_SWITCH(Event_t);
static void during_WAITING_FOR_FLEET_VALIDATION(Event_t);
static void during_WAIT_FOR_NEPTUNE_GO(Event_t);
static void during_GAME_ON(Event_t);
void Update_Indicators(unsigned char, unsigned char);
void Get_User_Inputs(void);
static void printTheCurrentStateEvent(void);
char Query_Time_To_Send_Inputs_Flag(void);
static void Reset_To_Waiting(void);
/*---------------------------- Module Variables ---------------------------*/
State_t Current_State;  // Variable for current state
Event_t Event;          // Variable for event
Event_t Previous_Event; // previous event
static unsigned char Inputs[6]; // array containing user input values
unsigned char Previous_Switch_State;
char Time_To_Send_Inputs_Flag = 0;  // flag which gets set at 5Hz
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
 Function
     Main
Parameters
     None
Returns
     None.

 Description

 Notes

 Author

     Nick Musser

****************************************************************************/
void main(void)
{
//  Initializations
SCI_Init();                     // Initialize SCI
E128_Port_Init();               // Initialize E128 Ports
Servo_Init();                   // Initialize Servos
Current_State = WAITING_FOR_SWITCH; // Initialize Current State to Waiting for switch
Event = NO_EVENT;               // Initialize Event to No-Event
Previous_Event = NO_EVENT;      // INitialize Previous Event to No_Event
printTheCurrentStateEvent();    // Print out state info

  while (1) // while forever
  {
    if((Event = Check_Events()) != NO_EVENT) // if a new event happened
    {
      Previous_Event = Event;   // assign the Event to Previous Event
      switch(Current_State)     // switch on Current_State
      {
        case WAITING_FOR_SWITCH:
          during_WAITING_FOR_SWITCH(Event);
          break;
        case WAITING_FOR_FLEET_VALIDATION:
          during_WAITING_FOR_FLEET_VALIDATION(Event);
          break;
        case WAIT_FOR_NEPTUNE_GO:
          during_WAIT_FOR_NEPTUNE_GO(Event);
          break;
        case GAME_ON:
          during_GAME_ON(Event);
          break;
      } // end of switch
      printTheCurrentStateEvent(); // print out state info
    } // end of if
  }  // end of while
} // end of main

/****************************************************************************

 Function
     E128_Port_Init()

 Parameters

 Returns
     None.

 Description
     Initializes the Data Direction for the Ports on the E128.  Sets up the
     Analog channels as well.

 
Notes


 Author
     Nick Musser
****************************************************************************/
void E128_Port_Init(void)
{
  //(void)printf("Initializing ports\n\r");
  // Set Data Direction for Port
  DDRP &= BIT0LO; // Input for Cannon Fire
  DDRP &= BIT2LO; // Input for start key
  DDRP &= BIT5LO; // Input for extra joystick button
  DDRP |= BIT1HI; // Output for Fleet Cipher Received
  DDRP |= BIT3HI; // Output for GAME ON!! LED
  DDRP |= BIT4HI; // Output for system Unlocked LED

  // Set up Analog Ports. Ports 0-4 are Analog and Ports 5-7 are Digital Input (but can be changed)
  // Analog Input for Forward/Backward = AD0
  // Analog Input for Left/Right Steer = AD1
  // Analog Input for Gun Power = AD2
  // Analog Input for Cannon Right Aim = AD3
  // Analog Input for Cannon Left Aim = AD4
  (void)ADS12_Init("IIIAAAAA");

  // Initialize Timer System
  TIM1_TSCR1 = _S12_TEN;  // turn the timer system on
  TIM1_TSCR2 = (_S12_PR0 | _S12_PR1 | _S12_PR2 );  // set prescaler to  128
  TIM1_TIOS = _S12_IOS4; // set cap/comp 4 to output compare
  TIM1_TCTL1 = TIM1_TCTL1 & ~(_S12_OL4 | _S12_OM4);  // no pin  connected
  TIM1_TC4 = TIM1_TCNT + _PERIOD_; /* schedule first event */
  TIM1_TFLG1 = _S12_C4F; // Clear 0C4 flag
}
/****************************************************************************
 Function
     during_WAITING_FOR_SWITCH()

 Parameters

 Returns
     None.

 
Description


 Notes

 Author
     Nick Musser
****************************************************************************/
void during_WAITING_FOR_SWITCH(Event_t EVENT)
{
  switch(EVENT)
  {
    case SWITCH_ON:
      PTP |= BIT4HI; // Raise pin 4 to turn on LED
      Current_State = WAITING_FOR_FLEET_VALIDATION; // Change state
      SCI1CR2 |= _S12_RIE;  // Enable Interrupt for incoming messages. Start listening for broadcasts from team and Neptune
      break;
    case SKIP_MODE_ON:
      PTP |= BIT3HI; // Raise pin 3 to turn on LED for Game ON
      SCI1CR2 |= _S12_RIE;  // Enable Interrupt for incoming messages. Start listening for broadcasts from team and Neptune
      TIM1_TIE |= _S12_C4I; // enable OC4 interrupt so we can start sending user inputs
      Current_State = GAME_ON; // Change state
      break;
  } // end of switch
} // end of function

/****************************************************************************
 Function
     during_WAITING_FOR_FLEET_VALIDATION()

  Parameters

 Returns
     None.

 Description

 Notes

 Author
     Nick Musser
****************************************************************************/
void during_WAITING_FOR_FLEET_VALIDATION(Event_t EVENT)
{
  switch(EVENT)
  {
    case CIPHER_RECEIVED:
      PTP |= BIT1HI; // Raise pin 1 to turn on LED for cipher received
      Current_State = WAIT_FOR_NEPTUNE_GO; // Change state
      break;
    case SKIP_MODE_ON:
      PTP |= BIT3HI; // Raise pin 3 to turn on LED for Game ON
      TIM1_TIE |= _S12_C4I; // enable OC4 interrupt so we can start sending user inputs
      Current_State = GAME_ON; // Change state
      break;
    case NEW_MESSAGE:
      Process_Message(); // process new message
      break;
    case SWITCH_OFF:
      Current_State = WAITING_FOR_SWITCH; // change state
      Reset_To_Waiting(); // reset lights, etc...
      break;
  } // end of switch
} // end of function

/****************************************************************************

 Function
     during_WAIT_FOR_NEPTUNE_GO()
 
 Parameters


 Returns
     None.

 Description

 Notes

 Author
     Nick Musser
****************************************************************************/
void during_WAIT_FOR_NEPTUNE_GO(Event_t EVENT)
{
  switch(EVENT)
  {
    case GO:
      PTP |= BIT3HI; // Raise pin 3 to turn on LED for Game ON
      TIM1_TIE |= _S12_C4I; // enable OC4 interrupt so we can start sending user inputs
      Current_State = GAME_ON; // Change state
      break;
    case SKIP_MODE_ON:
      PTP |= BIT3HI; // Raise pin 3 to turn on LED for Game ON
      TIM1_TIE |= _S12_C4I; // enable OC4 interrupt so we can start sending user inputs
      Current_State = GAME_ON; // Change state
      break;
    case NEW_MESSAGE:
      Process_Message(); // process new message
      break;
    case SWITCH_OFF:
      Current_State = WAITING_FOR_SWITCH; // change state to "Waiting for Switch"
      Reset_To_Waiting(); // reset lights, etc...
      break;
  } // end of switch
} // end of function

/****************************************************************************

 Function
     during_WAIT_FOR_NEPTUNE_GO()

 
Parameters


 Returns
     None.

 
Description


 Notes

 Author
     Nick Musser
****************************************************************************/
void during_GAME_ON(Event_t EVENT)
{
  switch(EVENT)
  {
    case NEW_MESSAGE:
      Process_Message(); // process new message
      break;
    case TIME_TO_SEND_INPUTS:
      Get_User_Inputs(); // sample user inputs
      Compile_Message(Inputs); // Compile message with user inputs
      Send_Message(); // Initiate sending of message
      break;
    case SWITCH_OFF:
      Current_State = WAITING_FOR_SWITCH; // change state to "Waiting for Switch"
      Reset_To_Waiting(); // reset lights, etc...
      break;
  } // end of switch
} // end of function

/****************************************************************************

 Function
     Update_Indicators()
 
 Parameters
     First parameter is the crab pot ID.  The second parameter is the crab accumulation
     rate.
 
 Returns
     None.
 
 Description
 
 Notes
 
 
 Author
     Nick Musser
****************************************************************************/
void Update_Indicators(unsigned char CRAB_POT_ID, unsigned char CRAB_ACCUM_RATE)
{
  Servo_Set_Position(CRAB_POT_ID,_CRAB_ID_SERVO_);// Update Crab pot ID indicator
  Servo_Set_Position((unsigned char)((((unsigned int)CRAB_ACCUM_RATE * 17)/250) + 1),_CRAB_ACUM_SERVO_);// update crab accumulation rate indicator
} // end of function

/****************************************************************************

 Function
     Get_User_Inputs()
 
 Parameters
 
 
 Returns
     None.
 
 Description

 Notes
     A little messy... sorry :)
 
 Author
     Nick Musser
****************************************************************************/
void Get_User_Inputs(void)
{
  short Before_Conversion_Inputs[6];
  short After_Conversion_Inputs[6];
  short ForwardSpeed;
  static int i;
 
  Before_Conversion_Inputs[0] = ADS12_ReadADPin(_FORW_BACK_);  // Read forward/backward
  Before_Conversion_Inputs[1] = ADS12_ReadADPin(_RHT_LFT_);  // Read right/left steer
  if((PTP & BIT0HI) != 0)// if cannon button is pressed
  {
     Before_Conversion_Inputs[2] = ADS12_ReadADPin(_CANNON_);  // Read cannon power
  } else
    {
      Before_Conversion_Inputs[2] = 0x00;  //else assign a zero to cannon power
    }
  Before_Conversion_Inputs[3] = ADS12_ReadADPin(_RHT_AIM_); // Read Right cannon Aim
  Before_Conversion_Inputs[4] = ADS12_ReadADPin(_LFT_AIM_); // Read Left cannon Aim
  Before_Conversion_Inputs[5] = ADS12_ReadADPin(_TURBO_Prop_); // Read Turbo Prop
 
 
  // Make conversion from 10 bit digital to a number between 0 and 100 that represents duty cycle
 
  for(i = 0; i <=5; i++)
  {
    After_Conversion_Inputs[i] = ((Before_Conversion_Inputs[i])/(2*_Voltage_At_Full_Thrust_));
    if(After_Conversion_Inputs[i] > 100)
      After_Conversion_Inputs[i] = 100;
    if(After_Conversion_Inputs[i] < 0)
      After_Conversion_Inputs[i] = 0;
  }
  ForwardSpeed = After_Conversion_Inputs[0]*2;
 
  // Calculate Motor speeds based on the forward set point and steering setpoint
 
  // Turning Right
  if(After_Conversion_Inputs[1] >= 50 )
  {
    After_Conversion_Inputs[0] = ForwardSpeed + (_MAX_TURN_ * (After_Conversion_Inputs[1] - 50))/(_SCALE_*50); // right motor
    After_Conversion_Inputs[1] = ForwardSpeed - (_MAX_TURN_ * (After_Conversion_Inputs[1] - 50))/(_SCALE_*50); // left motor
 }
  else
  {
    After_Conversion_Inputs[0] = ForwardSpeed - (_MAX_TURN_ * (50 - After_Conversion_Inputs[1]))/(_SCALE_*50); // right motor
    After_Conversion_Inputs[1] = ForwardSpeed + (_MAX_TURN_ * (50 - After_Conversion_Inputs[1]))/(_SCALE_*50); // left motor
  }
 
  for(i=0; i<=1; i++)
  {
    if(After_Conversion_Inputs[i] > 200)
      After_Conversion_Inputs[i] = 200;
    if(After_Conversion_Inputs[i] < 0)
      After_Conversion_Inputs[i] = 0;
  }
 
  if((After_Conversion_Inputs[0] > 95) && (After_Conversion_Inputs[0] < 105) && (After_Conversion_Inputs[0] > 95) && (After_Conversion_Inputs[0] < 105)  && (After_Conversion_Inputs[1] > 95) && (After_Conversion_Inputs[1] < 105) )
  {
    After_Conversion_Inputs[0] = 100;
    After_Conversion_Inputs[1] = 100;
  }
 
  // for Left and Right Servo Aim, adjust to a number between 1 and 12
  for(i = 3; i<=4; i++)
  {
    //After_Conversion_Inputs[i] = ((11*After_Conversion_Inputs[i])/60)-6;
    After_Conversion_Inputs[i] = ((2*After_Conversion_Inputs[i])/3)-24;
 }
 
 
  for (i = 0; i <=2; i++)
  {
    Inputs[i] = (unsigned char)After_Conversion_Inputs[i];
  }
  for (i = 3; i <=5; i++)
  {
    Inputs[i] = (unsigned char)After_Conversion_Inputs[i];
    if(Inputs[i] > 42)
      Inputs[i] = 0;
  }
}
 
/****************************************************************************
 Function
     printTheCurrentStateEvent()
 
 Parameters
 
 
 Returns
     None.
 
 Description
     Prints the current state, last event, and last user inputs
 
 Notes
 
 
 Author
     Nick Musser
****************************************************************************/
void printTheCurrentStateEvent(void)
{
  //system("cls");
 
  switch(Current_State)
      {
        case WAITING_FOR_SWITCH:
          (void)printf("Current State is: Waiting for Switch.     ");
          break;
        case WAITING_FOR_FLEET_VALIDATION:
          (void)printf("Current State is: Waiting for Fleet Validation     ");
          break;
        case WAIT_FOR_NEPTUNE_GO:
          (void)printf("Current State is: Waiting for Neptune     ");
          break;
        case GAME_ON:
          (void)printf("Current State is: Game ON!!!     ");
          break;
      }
 
  switch(Event)
      {
        case SWITCH_ON:
          (void)printf("Event_ Was: Switch On\n\r");
          break;
        case CIPHER_RECEIVED:
          (void)printf("Event_ Was: Cipher Received\n\r");
          break;
        case GO:
          (void)printf("Event_ Was: Go\n\r");
          break;
        case SKIP_MODE_ON:
          (void)printf("Event_ Was: Skip Mode On\n\r");
          break;
        case NEW_MESSAGE:
          (void)printf("Event_ Was: New Message\n\r");
          break;
        case TIME_TO_SEND_INPUTS:
          (void)printf("Event_ Was: Time to Send Inputs_\n\r");
          break;
        case NO_EVENT:
          (void)printf("Event_ Was: No Event\n\r");
          break;
        case SWITCH_OFF:
          (void)printf("Event_ Was: Switch OFF\n\r");
          break;
 
 
      }
 
  (void)printf("Right Motor DC is %i\n\r", Inputs[0]);
  (void)printf("Left Motor DC is %i\n\r", Inputs[1]);
  (void)printf("Cannon Power Command is %i\n\r", Inputs[2]);
  (void)printf("Right Aim Command is %i\n\r", Inputs[3]);
  (void)printf("Left Aim Command is %i\n\r", Inputs[4]);
}
 
/****************************************************************************
 Function
     Query_New_Message_Flag()
 
 Parameters
     None.
 
 Returns
     1 if the 5Hz timer flag has been set.  0 otherwise
 
 Description
 
 
 Notes
     None.
 
 Author
     Nick Musser
****************************************************************************/
char Query_Time_To_Send_Inputs_Flag(void)
{
  if(Time_To_Send_Inputs_Flag == 1) // if flag has been set
  {
    Time_To_Send_Inputs_Flag = 0;  // clear flag
    return 1; // return 1
  }
  else
    return 0;
}
 
/****************************************************************************
 Function
     Reset_To_Waiting()
 
 Parameters
     None.
 
 Returns
     None.
 
 Description
      Resets the LEDs and interrupts as if the game had started over again.
 
 
 Notes
     None.
 
 Author
     Nick Musser
****************************************************************************/
void Reset_To_Waiting(void)
{
  TIM1_TIE &= (~_S12_C4I); // disable OC4 interrupt so we stop sending user inputs
  SCI1CR2 &= (~_S12_RIE);  // disable Interrupt for incoming messages. Stop listening for broadcasts from team and Neptune
  PTP &= BIT4LO; // Lower pin 4 to turn OFF system unlocked LED
  PTP &= BIT3LO; // Lower pin 3 to turn OFF LED for Game ON
  PTP &= BIT1LO; // Lower pin 1 to turn OFF LED for Cipher Received
} // end of function
 
/****************************************************************************
 Function
     Timer
 
 Parameters
     None.
 
 Returns
     None.
 
 Description
     This is the interrupt response associated with the timer for sending user inputs at 5Hz
 
 Notes
     None.
 
 Author
     Nick Musser
****************************************************************************/
void interrupt _Vec_tim1ch4 Timer(void)
{
  Time_To_Send_Inputs_Flag = 1;  // set flag
  TIM1_TFLG1 = _S12_C4F; // clear OC4 flag
  EnableInterrupts; // enable interrupts
  TIM1_TC4 = TIM1_TCNT + _PERIOD_; // program next compare
}