//#define TEST /**************************************************************************** Module SCI.c Description Contains functions for using the SCI subsystem on the E128.
Notes History WhenWhoWhat/Why -------------- ----------- April 2010NRMStarted Coding ****************************************************************************/ /*----------------------------- Include Files -----------------------------*/ #include <hidef.h>/* common defines and macros */ #include <mc9s12e128.h>/* derivative information */ #include <stdio.h> #include <stdlib.h> #include <S12E128bits.h>/* E128 bit definitions*/ #include <bitdefs.h>/* BIT0HI, BIT0LO....definitions */ #include"S12eVec.h" #include"S12Vec.h" #include"HC_Controller.h" #include"SCI.h" #include"servo.h" #pragma LINK_INFO DERIVATIVE"SampleS12" /*----------------------------- Module Defines ----------------------------*/ #define Number_of_Bytes_In_Message 15 #define START_BYTE 0x7E #define LENGTH_MSB 0x00 #define LENGTH_LSB 11 #define API_TRANSMIT 0x01 #define FRAME_ID 0x08 #define OPTIONS 0x00 #define CRAFT_MSB 0x21 #define CRAFT_LSB 0x83 #define NEPTUNE_MSB 0x77 #define NEPTUNE_LSB 0x77 #define _BOADCAST_ 0x02 #define _PERSONAL_ 0x00 #define _TEAM_MESSAGE_ 0x01 #define _CIPHER_MESSAGE_ 0x02 #define _CRAB_MESSAGE_ 0x03 /*------------------------------ Module Types -----------------------------*/ // struct for messages typedefstruct{ unsigned charContents[Number_of_Bytes_In_Message];// Contents of Messege intIndex_Counter;// Index intLength;// total length of packet }_MESSAGE_; // struct to hold user inputs typedefstruct{ unsigned charLeft_Prop;// Duty Cycle for Left Propeller unsigned charRight_Prop;// Duty Cycle for Right Propeller unsigned charPump;// Duty Cycle for Pump unsigned charLeft_Aim_Gun;// Duty Cycle for Left Gun Aim unsigned charRight_Aim_Gun;// Duty Cycle for Right Gun Aim unsigned charTurbo_Prop;// Duty Cycle for Turbo Prop }_INPUTS_; /*---------------------------- Module Functions ---------------------------*/ voidSCI_Init(void); unsigned charSCI_Receive(void); voidProcess_Message(); voidCompile_Message(unsigned char[]); voidSend_Message(void); charQuery_Received_Cipher_Flag(void); charQuery_GO_Flag(void); charQuery_New_Message_Flag(void); charQuery_In_Flag(void); /*---------------------------- Module Variables ---------------------------*/ _MESSAGE_ OutgoingMessage;// _MESSAGE_ struct for outgoing message _MESSAGE_ IncomingMessage;// _MESSAGE_ struct for incoming message _MESSAGE_ IncMessageBuffer;// _MESSAGE_ for incoming message buffer _INPUTS_ UserInputs;// _INPUTS_ struct for user inputs unsigned charCIPHER=0xAA;// initialize cipher to 0xAA (same as boat) unsigned charMyTeam=0x44;// initialize to white team charNew_Message_Flag=0;// initialize flag for new message charReceived_Cipher_Flag=0;// initalize flag for cipher received charGO_Flag=0;// initialize flag for neptune GO received /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** Function SCI_Init() Parameters Returns None. Description Initializes SCI system on E128 Notes Author Nick Musser ****************************************************************************/ voidSCI_Init(void) { unsigned chardummy;// Create dummy variable for clearing interrupt flag OutgoingMessage.Index_Counter=0; OutgoingMessage.Length=Number_of_Bytes_In_Message; IncomingMessage.Index_Counter=0; IncomingMessage.Length=Number_of_Bytes_In_Message; // Configure Baud Rate Registers (SCI1BDH, SCI1BDL) // Set baud rate to 9600 SCI1BDH=0x00; SCI1BDL=0x9C; // Configure SCI Control Register 1 (SCI1CR1) // Leave defaults: 8 data bits and Idle line wakeup // Configure SCI Control Register 2 (SCI1CR2) SCI1CR2|= (_S12_TE|_S12_RE);// Enable Transmitter and Reciever dummy=SCI_Receive();//clears receiver interrupt flag EnableInterrupts;// Enable Interrupts globally } /**************************************************************************** Function SCI_Receive() Parameters None Returns Returns the byte of data from the SCI Receive Register in the form of a char Description Clears the receive interrupt flag and returns the byte of data. Notes This will most likely be called in the interrupt response routine following a receive. Author Nick Musser ****************************************************************************/ unsigned charSCI_Receive(void) { static unsigned charMessage_Byte; if(SCI1SR1&_S12_RDRF)// If the recieve flag has been set { // Read SCI1SR1 and SCIDRL to clear the flag Message_Byte=SCI1DRL;// Read SCI Data Register Low returnMessage_Byte;// Return the byte of data } } /**************************************************************************** Function Compile_Message() Parameters Returns None. Description Stuffs the user inputs into the outgoing message stuct Notes Author Nick Musser ****************************************************************************/ voidCompile_Message(unsigned charUser_Inputs[6]) { unsigned charchecksum; checksum=API_TRANSMIT+FRAME_ID+CRAFT_MSB+CRAFT_LSB+OPTIONS+User_Inputs[0] +User_Inputs[1] +User_Inputs[2] +User_Inputs[3] +User_Inputs[4] +User_Inputs[5]; checksum=0xFF-checksum; OutgoingMessage.Contents[0] =START_BYTE; OutgoingMessage.Contents[1] =LENGTH_MSB; OutgoingMessage.Contents[2] =LENGTH_LSB; OutgoingMessage.Contents[3] =API_TRANSMIT; OutgoingMessage.Contents[4] =FRAME_ID; OutgoingMessage.Contents[5] =CRAFT_MSB; OutgoingMessage.Contents[6] =CRAFT_LSB; OutgoingMessage.Contents[7] =OPTIONS; OutgoingMessage.Contents[8] =User_Inputs[0];//Left_Prop; OutgoingMessage.Contents[9] =User_Inputs[1];//Right_Prop; OutgoingMessage.Contents[10] =User_Inputs[2];//Pump; OutgoingMessage.Contents[11] =User_Inputs[3];//Left_Aim_Gun; OutgoingMessage.Contents[12] =User_Inputs[4];//Right_Aim_Gun; OutgoingMessage.Contents[13] =User_Inputs[5];//Turbo_Prop; OutgoingMessage.Contents[14] =checksum; }// end of function /**************************************************************************** Function Send_Message() Parameters None Returns None Description Resets the OutgoingMessage Index Counter to zero.Enables the Transmission buffer empty interrupt.This flag defaults to set, so immediately after it is turned on the interrupt will fire and send the first byte of the OutgoingMessage.Contents[]. The interrupt gets turned off again after the last byte has been sent. Notes Author Nick Musser ****************************************************************************/ voidSend_Message(void) { OutgoingMessage.Index_Counter=0;// reset outgoing index counter to zero SCI1CR2|=_S12_TCIE;// Enable Transmitssion Complete Interrupt.Interrupt will fire immediately after }// end of function
/**************************************************************************** Function Process_Message() Parameters None Returns Description Takes in the message and determines if it is of interest.Depending on what type of message it is, different things will happen. Can also print out the incoming message Notes Author Nick Musser ****************************************************************************/ voidProcess_Message(void) { unsigned charSourceAddressMSB=IncMessageBuffer.Contents[4];// take out the source address MSB unsigned charSourceAddressLSB=IncMessageBuffer.Contents[5];// take out the source address LSB unsigned charMessage_Intention=IncMessageBuffer.Contents[7];// take out the message intention unsigned charTeam_Indicator=IncMessageBuffer.Contents[8];// take out the team indicator unsigned charMessage_Type=IncMessageBuffer.Contents[9];// take out message type
static unsigned charCrab_Pot_Number;// create variable for crab pot number static unsigned charCrab_Accum_Rate;// create variable for cab accum rate /*printf("\r\n%x\r\n",IncMessageBuffer.Contents[0]); printf("%x\r\n",IncMessageBuffer.Contents[1]); printf("%x\r\n",IncMessageBuffer.Contents[2]); printf("%x\r\n",IncMessageBuffer.Contents[3]); printf("%x\r\n",IncMessageBuffer.Contents[4]); printf("%x\r\n",IncMessageBuffer.Contents[5]); printf("%x\r\n",IncMessageBuffer.Contents[6]); printf("%x\r\n",IncMessageBuffer.Contents[7]); printf("%x\r\n",IncMessageBuffer.Contents[8]); printf("%x\r\n",IncMessageBuffer.Contents[9]); printf("%x\r\n",IncMessageBuffer.Contents[10]); printf("%x\r\n",IncMessageBuffer.Contents[11]); printf("%x\r\n",IncMessageBuffer.Contents[12]);*/ switch(IncMessageBuffer.Contents[3]) { case0x89:// case: reply back from your XBee if(IncMessageBuffer.Contents[5] ==0) printf("Success\r\n"); if(IncMessageBuffer.Contents[5] ==1) printf("No ACK\r\n"); if(IncMessageBuffer.Contents[5] ==3) printf("CCA Failure\r\n"); if(IncMessageBuffer.Contents[5] ==4) printf("Purged\r\n"); break; case0x81:// case: message from other XBee if((SourceAddressMSB==NEPTUNE_MSB) && (SourceAddressLSB==NEPTUNE_LSB) && (IncMessageBuffer.Contents[8] ==0x47) && (IncMessageBuffer.Contents[9] ==0x6F) && (IncMessageBuffer.Contents[10] ==0x21))// If broadcast GO message from Neptune { GO_Flag=1;// Set GO_Flag return;// return }// end if if((SourceAddressMSB==CRAFT_MSB) && (SourceAddressLSB==CRAFT_LSB) && (Message_Intention==_PERSONAL_) && (Message_Type==_CIPHER_MESSAGE_))// If personal message from Boat (Cypher) { MyTeam=Team_Indicator;// assign the team to local team variable CIPHER=IncMessageBuffer.Contents[10];// Take cypher and store it Received_Cipher_Flag=1;// Set Recevied Cipher Flag return; }// end if if((Message_Intention==_BOADCAST_) && (Team_Indicator==MyTeam) && (Message_Type==_CRAB_MESSAGE_))// If broadcast message and its from your fleet then its a crab update. save crab data { Crab_Pot_Number= (CIPHER ^ IncMessageBuffer.Contents[10]) -0xA0;// Take crab pot # and decode it with XOR Crab_Accum_Rate=CIPHER ^ IncMessageBuffer.Contents[11];// Take crab pot accum rate and decode it with XOR printf(" Crab Pot ID is %x\r\n",Crab_Pot_Number); printf(" Crab Pot Accum is %x\r\n",Crab_Accum_Rate); Update_Indicators(Crab_Pot_Number,Crab_Accum_Rate);// update indicators return; }// end if break; default: break; }// end of switch }// end of function
/**************************************************************************** Function Query_Received_Cipher_Flag() Parameters None. Returns 1 or 0 Description Queries the Receive Cipher Flag.Returns 1 if set, 0 otherwise Notes None. Author Nick Musser ****************************************************************************/ charQuery_Received_Cipher_Flag(void) { if(Received_Cipher_Flag==1) { Received_Cipher_Flag=0;// clear flag return1; } else return0; } /**************************************************************************** Function Query_GO_Flag() Parameters None. Returns 1 or 0 Description Queries the Neptune GO Flag.Returns 1 if set, 0 otherwise Notes None. Author Nick Musser ****************************************************************************/ charQuery_GO_Flag(void) { if(GO_Flag==1) { GO_Flag=0;// clear flag return1; } else return0; } /**************************************************************************** Function Query_New_Message_Flag() Parameters None. Returns 1 or 0 Description Queries the New Message Flag.Returns 1 if set, 0 otherwise Notes None. Author Nick Musser ****************************************************************************/ charQuery_New_Message_Flag(void) { if(New_Message_Flag==1) { New_Message_Flag=0;// clear flag return1; } else return0; } /**************************************************************************** Function SCI_Resp Parameters None. Returns None. Description This is the interrupt response associated with the Receiver Data Register Full flagand the Transmit Data Register Empty Flag.We must see which one caused the interrupt.
Notes None. Author Nick Musser ****************************************************************************/ voidinterrupt _Vec_sci1SCI_Resp(void) { In_Flag=1; if(SCI1SR1&_S12_RDRF)// Is it Receive Interrupt? { //Read SCI1SR1 and SCIDRL to clear the flag if((IncomingMessage.Index_Counter==0) && (SCI1DRL!=0x7E))// if this is the first index and the first byte {// isnt 0x7E, we know something is wrong - dont return;// do anything. } IncomingMessage.Contents[IncomingMessage.Index_Counter] = SCI1DRL;// Read SCI Data Register Low if(IncomingMessage.Index_Counter==2)// if we are at the LSB length byte of the packet { IncomingMessage.Length=4+IncomingMessage.Contents[2];// This would be the length of the packet } if(IncomingMessage.Index_Counter>IncomingMessage.Length-2)// we are at the end of the message { IncomingMessage.Index_Counter=0;// reset index for next message IncMessageBuffer=IncomingMessage;// store away complete incoming message New_Message_Flag=1;// Set MessageFlag } else// we are not at the end of the message IncomingMessage.Index_Counter++;// Increment index return; } if(SCI1SR1&_S12_TDRE)// Is it transmit interrupt? { if(OutgoingMessage.Index_Counter>=OutgoingMessage.Length)// If Message is done { OutgoingMessage.Index_Counter=0;// Reset Index counter and dont send anything.This leaves the flag set SCI1CR2&= (~_S12_TCIE);// Disable Transmit Interrupt return; } else// else Message is not done.Send the next byte in the sequence { SCI1DRL=OutgoingMessage.Contents[OutgoingMessage.Index_Counter];// write next byte to Transmit data register OutgoingMessage.Index_Counter++;// Increment Index Counter } return; } } /*------------------------------- Footnotes -------------------------------*/ #ifdef TEST voidmain(void){ intKeyStroke; SCI_Init(); //Compile_Message(2,2,2,2,2,2); //Send_Message(); (void)printf("Press a,b,c,d,e,f\r\n"); while(1){ if(kbhit() !=0) { KeyStroke=getchar(); if(KeyStroke=='a')// If button B was pressed { Compile_Message(0,0,0,0,0,0); //Compile_Message(1); (void)printf("000\r\n"); } if(KeyStroke=='b')// If button B was pressed { Compile_Message(0,0,1,0,0,1); //Compile_Message(2); (void)printf("001\r\n"); } if(KeyStroke=='c')// If button B was pressed { Compile_Message(0,1,1,0,1,1); //Compile_Message(1); (void)printf("011\r\n"); } if(KeyStroke=='d')// If button B was pressed { Compile_Message(1,0,1,1,0,1); //Compile_Message(2); (void)printf("101\r\n"); } if(KeyStroke=='e')// If button B was pressed { Compile_Message(1,1,0,1,1,0); //Compile_Message(1); (void)printf("110\r\n"); } if(KeyStroke=='f')// If button B was pressed { Compile_Message(0,1,0,0,1,0); //Compile_Message(2); (void)printf("010\r\n"); } Send_Message(); } if(New_Message_Flag==1) { Process_Message();// Process Message New_Message_Flag=0;// Reset Message_Done Flag } /*printf("interrupt_in counter = %i\n\r", p); printf("interrupt_out counter = %i\n\r", m); printf("first = %x\n\r",IncomingMessage.Contents[0]); printf("second = %x\n\r",IncomingMessage.Contents[1]); printf("third = %x\n\r",IncomingMessage.Contents[2]); printf("fourth= %x\n\r",IncomingMessage.Contents[3]); printf("fifth = %x\n\r",IncomingMessage.Contents[4]); printf("sixth= %x\n\r",IncomingMessage.Contents[5]); printf("seventh= %x\n\r",IncomingMessage.Contents[6]); printf("eighth= %x\n\r",IncomingMessage.Contents[7]); printf("ninth= %x\n\r",IncomingMessage.Contents[8]); printf("tenth= %x\n\r",IncomingMessage.Contents[9]); printf("eleventh= %x\n\r",IncomingMessage.Contents[10]); printf("twelve= %x\n\r",IncomingMessage.Contents[11]); printf("thirteen= %x\n\r",IncomingMessage.Contents[12]); printf("fourteenth= %x\n\r",IncomingMessage.Contents[13]); printf("fifteenth= %x\n\r",IncomingMessage.Contents[14]); printf("process message flag = %i\n\r", Message_Done); */ //printf("outgoing message counter = %i\n\r", OutgoingMessage.Index_Counter); } } #endif /*------------------------------ End of file ------------------------------*/