//#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
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
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