//#define TEST

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

SPI.c

ME 218B Project Hats Off

Team Firefox

March 7, 2010

The E128 queries the Target Commander over SPI for command instructions

We are only querying the TC with 0xAA and 0xEx. We do not send 0xBx.

 

LED blinking begins here until TC sends the first active target

 

E128 = master

Target Commander = slave

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

 

 

/*-------------------------- Include Files -----------------------------*/

#include "SPI.h"

#include "myTimer.h"

 

#pragma LINK_INFO DERIVATIVE "SampleS12"

 

#define printf (void)printf

 

/*-------------------------- Module Variables -----------------------------*/

static SPI_Status_t state;

static unsigned char lastCmd;        //Last written byte

static unsigned char receivedByte;

 

static unsigned int lastWriteTime;   //lastAATime, lastExTime;

 

//Stores the activated beacon into an array when TC sends new beacons

static char ActivatedBeacons[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};

static unsigned int curBeaconIndex = 0;

static unsigned int lastActiveBeaconIndex = 0;

static char isCurBeaconHit = FALSE, blinkState = 0;

 

static char requestedTargetStatus = FALSE;

static char unreadTargetStatus = FALSE;

 

static unsigned int blinkTime = 0;

 

/*-------------------------- Module Prototypes -----------------------------*/

unsigned char firstLetter(unsigned char inByte);

unsigned char lastLetter(unsigned char inByte);

void WriteByte(unsigned char myByte);

 

/*-------------------------- Module Code -------------------------------*/

//Debug function

void debug_printActiveBeacons(void) {

  int a;

  for(a=0; a<15; a++){

    printf("%d ", ActivatedBeacons[a]);

  }

  printf("\r\n");

 

  printf("curBeaconIndex = %d\r\n", curBeaconIndex);

}

 

//Increment the curBeaconIndex in ActivatedBeacons array

void SPI_skipCurTarget(void) {

  curBeaconIndex++;

  if (curBeaconIndex > 15) curBeaconIndex = 15;

}

 

//returns the current active target

char SPI_getCurTarget(void){

  return ActivatedBeacons[curBeaconIndex];

}

 

char SPI_isCurTargetHit(void) {

  unreadTargetStatus = FALSE;

  return isCurBeaconHit;

}

 

void SPI_requestTargetStatus(void) {

  requestedTargetStatus = TRUE;

  unreadTargetStatus = FALSE;

}

 

//Initialize the SPI. Set Baud Rate to 24.41kHz.

//Set Active edge as even rising edge and MSB transfer first

void SPI_Init(void) {

  MyTimer_Init();

      SPIBR = 0x77;                   //1. Set Baud Rate with SPPR & SPR bits in SPIBR

                                      //12.21kHz

 

      SPICR1 = SPICR1 | _S12_CPOL;    //2. Initialize CPOL and CPHA bits in SPICR1.

      SPICR1 = SPICR1 | _S12_CPHA;    //CPOL = 1, CPHA = 1 for even rising active edge

 

      SPICR1 = SPICR1 | _S12_MSTR;    //3. Enable Master. Set MSTR in SPICR1

 

//    SPICR1 = SPICR1 | _S12_SPIE;    //4. Interrupts. Set SPIE, SPTIE bits in SPICR1

                                      //(Locally enable interrupts)

 

      SPICR1 = SPICR1 | _S12_SPE;     //5. Enable SPI. Set SPE bits in SPICR1

 

      SPICR1 = SPICR1 &~ _S12_LSFBE;  //Set MSB transfer first. (MSB already default)

      SPICR1 = SPICR1 | _S12_SSOE;    //Set SS to SlaveSelectOutput w/ SSOE and MODFEN

      SPICR2 = SPICR2 | _S12_MODFEN;

 

  SPICR2 = SPICR2 &~ _S12_BIDIROE;   //Not Bi-directional output enable = normal

 

  lastCmd = 0xAA;

  lastWriteTime = MyTimer_GetTime();

 

  receivedByte = 0xDE;

  blinkState = 0;

  blinkTime = MyTimer_GetTime() - 1000;

  printf("Waiting for first active Target\r\n");

 

 //LED blinking begins here until TC sends the first active target (0xCx)

  while (firstLetter(receivedByte) != 0x0C) {  //Blocking code until receivedByte = 0xCx

    WriteByte(lastCmd);

    if ((MyTimer_GetTime() - blinkTime) > 250) {

      blinkTime = MyTimer_GetTime();

      if (blinkState == 1) {

        PTT |= BIT1HI;              //turn on red LED

        PTT &= BIT3LO;              //turn off green LED

        blinkState = 0;

      }

      else {

        PTT |= BIT3HI;             //turn on green LED

        PTT &= BIT1LO;             //turn off red LED

        blinkState = 1;

      }

    }

  }

 

  ActivatedBeacons[lastActiveBeaconIndex] = lastLetter(receivedByte); //store in array

  lastActiveBeaconIndex = 0;

  curBeaconIndex = 0;

  isCurBeaconHit = FALSE;

  //printf("receivedByte initialization: %x \r\n", receivedByte);

}

 

//Determine the firstLetter of the receivedByte

unsigned char firstLetter(unsigned char inByte) {

  return (inByte/16);

}

 

//Determine the lastLetter of the receivedByte

unsigned char lastLetter(unsigned char inByte) {

  return (inByte%16);

}

 

//myByte is either a 0xAA or 0xEx

//Puts the received byte into receivedByte

void WriteByte(unsigned char myByte) {

  static char curWriteGood = TRUE;

  static unsigned char tempByte;

  static char timeout = FALSE;

  static char FBcount = 0;

  static int i = 0;

  static unsigned int waitTime = 11;            //Need to send a command after >10ms

 

  if (curWriteGood) {

    if ((SPISR & _S12_SPIF) == _S12_SPIF) {     //Check read flag

      receivedByte = SPIDR;                     //Read good

      if (receivedByte == 0xFB) FBcount++;      //"Busy" count, used for debugging timeouts from radio overload

      else FBcount = 0;

      if (FBcount > 10) printf("FB timeout %d\r\n", FBcount);

        //printf("Received Byte: %x\r\n", receivedByte);

    }

    if ((MyTimer_GetTime() - lastWriteTime) > waitTime) {

      if ((SPISR & _S12_SPTEF) == _S12_SPTEF) {             //Check write flag

        lastWriteTime = MyTimer_GetTime();

        SPIDR = myByte;                                     //Write out good byte to SPI lines

        //printf("Sent Byte: %x\r\n", myByte);

        curWriteGood = FALSE;

      }

    }

  }

  else {

    if ((SPISR & _S12_SPIF) == _S12_SPIF) {                 //Check read flag

      tempByte = SPIDR;                                     //Read bad

    }

    if ((MyTimer_GetTime() - lastWriteTime) > waitTime) {

      if ((SPISR & _S12_SPTEF) == _S12_SPTEF) {             //Check write flag

        lastWriteTime = MyTimer_GetTime();

        SPIDR = 0x00;                                       //Write out bad byte to SPI lines

        curWriteGood = TRUE;

      }

    }

  }

}

 

//Returns SPI_READY, SPI_TARGET_STATUS_READY, SPI_GAME_OVER, SPI_DELAY, or SPI_ERROR

SPI_Status_t SPI_getStatus(void) {

 

  switch (state) {

    case SPI_GAME_OVER:

      return state;

      break;

    case SPI_ERROR:

      return state;

      break;

    case SPI_DELAY:

      lastCmd = 0xAA;         //Send AA into WriteByte until response is not OxDE

    case SPI_READY:

      WriteByte(lastCmd);

      if (receivedByte == 0xFB) return state;          //Do nothing

      else {                                          //Process response

        switch(firstLetter(receivedByte)) {           //Get the firstLetter of the receivedByte

          case 0x0C:                                  //if C, Active beacon

            if (lastLetter(receivedByte) != ActivatedBeacons[lastActiveBeaconIndex]) {

              lastActiveBeaconIndex++;                //got a new target assignment

              ActivatedBeacons[lastActiveBeaconIndex] = lastLetter(receivedByte);

            }

            state = SPI_READY;

            break;

          case 0x0D: //Special command

            if (lastLetter(receivedByte) == 0x0E) state = SPI_DELAY;

            else state = SPI_GAME_OVER;

            break;

          case 0x05:    //Current beacon is active but not lit. Do the same thing as for case 0x06

          case 0x06:    //Current beacon is active and lit

            if (lastLetter(receivedByte) == ActivatedBeacons[curBeaconIndex]) {

              isCurBeaconHit = FALSE;           //set isCurBeacon to show it is not hit

              requestedTargetStatus = FALSE;    //Only requestTargetStatus (call 0xEx) after beacon is hit (called in Main)

              unreadTargetStatus = TRUE;        //TargetStatus has not been read

            }

            break;

          case 0x07: //Current beacon has been hit but not lit

          case 0x08: //Current beacon has been hit and lit

            if (lastLetter(receivedByte) == ActivatedBeacons[curBeaconIndex]) {

              requestedTargetStatus = FALSE;

              unreadTargetStatus = TRUE;

              isCurBeaconHit = TRUE;                  //set TRUE to show it has been hit

              curBeaconIndex++;                       //get the index for next activatedBeacon

            }

            state = SPI_READY;

            break;

          case 0x0F:

            state = SPI_ERROR;

            break;

        }

        if (requestedTargetStatus) {                             //if TRUE (set in Main after hitting the beacon)

          if (ActivatedBeacons[curBeaconIndex] != -1) {

            lastCmd = 0xE0 + ActivatedBeacons[curBeaconIndex];   //Send 0xEx to TC

          }

        }

        else lastCmd = 0xAA;                                     //otherwise, always write 0xAA to TC

      }

 

      if (state == SPI_READY && unreadTargetStatus) return SPI_TARGET_STATUS_READY;

      else return state;

      break;

  }

}

 

 

 

//Test Harness

#ifdef TEST

 

void main(void){

  char ch;

  int a=0;

  SPI_Status_t status, lastStatus;

 

  SPI_Init();

  MyTimer_Init();

 

  printf("Test started\r\n");

  lastStatus = SPI_ERROR;

 

   while (1){

 

    status = SPI_getStatus();

    if (status != lastStatus) {

      lastStatus = status;

      switch(status){

        case SPI_GAME_OVER:

          printf("GAME_OVER\r\n");

          break;

        case SPI_ERROR:

          printf("ERROR\r\n");

          printf("lastCmd= \r\n", lastCmd);

          break;

        case SPI_DELAY:

          printf("DELAY\r\n");

          break;

        case SPI_READY:

          break;

        case SPI_TARGET_STATUS_READY:

          printf("Target Status is Ready!\r\n");

          break;

      }

    }

 

    if(kbhit()){

      printf("Enter Command: ");

      ch = (char) getchar(); //pauses execution, waiting for input

 

      switch (ch) {

        case 'a':

          printf("Requested current target: ");

          printf("%d \r\n", SPI_getCurTarget());

          break;

        case 'h':

          printf("Is Current Target Hit? ");

          printf("%d \r\n", SPI_isCurTargetHit());

          break;

        case 'p':

                for(a=0; a<15; a++){

                  printf("%d ", ActivatedBeacons[a]);

          }

          printf("\r\n");

                break;

        case 't':

          printf("Requested Current Target Status . . . .\r\n");

          SPI_requestTargetStatus();

          break;

              case 'r':

          printf("ReceivedByte= ");

          printf("%x \r\n", receivedByte);

          break;

        case 's':

          printf("SentByte= ");

          printf("%x \r\n", lastCmd);

          break;

        case 'z':

          printf("skipping cur target\r\n");

          SPI_skipCurTarget();

          break;

      }

    }

   }

}

#endif