/**************************************************************************** Module FarmerTopSM.c Pseudo Code ****************************************************************************/ /*----------------------------- Module Defines ----------------------------*/ define definitions /*---------------------------- Module Functions ---------------------------*/ define module functions /*---------------------------- Module Variables ---------------------------*/ define module variables /*------------------------------ Module Code ------------------------------*/ /**************************************************************************** ****************************************************************************/ bool InitFarmerTopSM ( uint8_t Priority ) { set priority /******************************************** Initialization Code *******************************************/ set up I/O lines for debugging (PB2)= start with the lines low (PB2)= initialize current state to waiting to pair initialize current RX state to wait for 7E Initialize variable to 0 (Datapacket length, Xbeepacket length and encryption index) Init UART for communication with Xbee Init UART for communication with TREAT Init other PORT Enable NVIC and enable global interrupt Initialize A/D Channels Init Input Capture and one shot timer Initially set led to unpair mode Print unpair message Print out initializing completion If we want to debug value from encoder, we trigger the printout by using encoder timer Post the initial transition event } /**************************************************************************** ****************************************************************************/ bool PostFarmerTopSM( ES_Event ThisEvent ) { return ES_PostToService( MyPriority, ThisEvent); } /**************************************************************************** ****************************************************************************/ ES_Event RunFarmerTopSM( ES_Event ThisEvent ) { set return event to no event - assume no errors set next state to current state check current state if current state is wait to pair if press c, send request to pair message reset paired dog address broadcast request to pair message set next state to wait for pair response Start lost communicaton timer (set to 1 s) if encoder timer timeout, printout the rpm output update control state print out current RPM value restart encoder sample timer break if current state is wait for pair response if timeout from 1s lost comm timer, go back to wait to pair state set next state to wait to pair print unpair message if received request to pair acknowledge (Header 0x02) locally save address of DOG from the acknowledgement message reset encryption key index to 0 set seed for the random number generator to get unique key each time we generate them call rand once first for the random number generator to work better send encryption packet restart inter message timer (300ms) if received ack for encryption message (check frame id 0x02) start inter message timer (300ms) start lost communication timer set next state to paired set led for pair mode if received nack for encryption message resend encryption packet break if current state is paired if 1s lost communication timer timeout if timeout, go back to wait to pair state set led for unpair mode print unpair message if inter message timer timeout send control message to DOG if pair button is pressed when press pair button during pair state, unpair with dog reset encryption key index go back to wait to pair state set led for unpair mode print unpair message if receive ack for the control message restart lost comm timer when getting ack if receive nack for the control message restart lost comm timer when getting nack reverse encrypt index send control packet if receive DOG's report start inter message timer (300ms) start lost communication timer print status to LCD by posting event to LCD_Control module if receive encryption key reset request reset encryption key index to 0 start inter message timer (300ms) start lost communication timer if receive sound exceeds threshold event during pairing increment clap counter check if clap counter equals max clap set special function boolean to true break default : break update current state return return Event /*************************************************************************** private functions ***************************************************************************/ /* * This function reset the current index of the encryption key to zero */ static void ResetEncryptKeyIndex(){ // reset encryption key index to 0 } /* * This function reset current paired dog address to zero */ static void ResetDogAddress(){ set dog address variable to 0 } /* * This function set current dog address to the input */ static void SetDogAddress(uint16_t input){ set dog address variable to input } /* * This function read the current dog id and set the variable accordingly */ static uint8_t GetDogID(){ if pin PB5 is low, set dog id to 1 else if pin PB6 is low, set dog id to 2 else if pin PB7 is low, set dog id to 3 else set dog id to 8 (not selecting any dog) return dog id } /* * This function construct a packet to be transmitted with option of * broadcasting to all listening devices */ static void ConstructPacket(bool broadcast){ set index 0 byte to start byte set index 1 byte to MSB len set index 2 byte to datapacket len plus data overhead len reset checksum to 0 set index 3 byte to API Transmit ID (0x01) and add to checksum set index 4 byte to frame id and add to checksum set index 5 to broadcast destination MSB address and add to checksum set index 6 to broadcast destination LSB address and add to checksum set index 7 to option byte and add to checksum copy data packet to the xbee packet and add each byte to checksum calculate checksum value by subtraction to addition from 0xff set the last byte to this value update total packet length } /* * This function clear the content of data packet array */ static void ClearDataPacket(){ set all index of data packet to 0 } /* * This function form request to pair message and send out */ static void Send_RequestToPair(){ first clear the data packet set request to pair packet length to 2 first byte is the header second byte is the dog id for request to pair, use frame_id = 0x01 construct packet print out xbee packet transmit it through UART to the Xbee by calling transmit packet } static void PrintUnpairMessage(){ post PRINT_UNPAIR to LCD Control module } /* * This function return random 8 bit integer */ static uint8_t GetRandNum(){ return random integer between 0 and 255 } /* * This function form encryption key message and transmit */ static void Send_Encryption(){ reset encryption index first clear the data packet request to pair packet has length of 2 bytes first byte is the header fill data packet with random number add random value to encryption key array add the encryption key to data packet set frame id specifically for encryption key message set destination address construct packet print out xbee packet transmit it through UART to the Xbee } /* * This function form control message and transmit */ static void Send_Control(){ first clear the data packet request to pair packet has length of 2 bytes first byte is the header read current control state fill data packet with control value set frame id (increment by one everytime we send message) reset frame_id to 0x04 if it reaches 0xff set destination address encrypt message construct packet print out xbee packet transmit it through UART to the Xbee } /* * This function read the current control state and set the variables */ static void UpdateControlState(){ read analog input for forward/backward control input index 0 is input from PE0 index 1 is input from PE1 calculate control 1 (forward and backward) value convert the received rpm to int from 0 to 127 calculate control 2 (left and right) value if PC6 is high, set brake bit in control 3 byte if special function boolean is true set the special function bit set activation bool to false reset clap counter } /* * This function set the msb and lsb variable accordingly to the target address */ static void SetDestinationAddress(){ update msb_rx_address and lsb_rx_address from paired_dog_address variable } /* * This function transmit packet by start writing to UART pin out * We need to call ConstructPacket before calling this function */ static bool TransmitPacket(){ set remaining number of byte to transmit to the Xbee packet length reset index to 0 check if UART Transmit FIFO empty bit is set, this mean we can send write data to UART this if loop is for increasing efficiency of transmitting write data to UART enable TX interrupt return success } else{ else return failure } } /* * This function is the ISR for the UART1 module */ void FARMER_UART1_ISR(){ if UART1 interrupt flag for receiver is set clear RX interrupt flag RX State Machine in ISR We put this state machine here so we don't miss any incoming byte update NextRxState to CurrentRxState if CurrentRxState is WaitFor7E if receive incoming start byte first clear current data packet reset Checksums, received index to 0 set next state to wait for msb break if current state is wait for MSB save msb length of the received packet set next state to wait for lsb break if current state is wait for LSB save lsb length of the received packet form data packet length from the received msb and lsb set next state to get data packet break if current state is wait for get data packet put received data into DataPacket array add the data up to check sum increment the received index compare index to the received index, if equal go to check sum state compute final check sum by subtracting from 0xFF set next state to get check sum break if current state is get check sum set check sum to the byte received check if it equal to our calculated check sum copy values in rx array to temp buffer post received byte to FARMER_RX service set next state to wait for start delimiter bytes break default break update current rx state } if UART1 interrupt flag for transmitter is set write data to UART but first wait till FIFO empty clear TX interrupt flag write data to UART check number of byte remaining if byte remaining is zero, disable interrupt on TX } /* * This function copy data from xbeepacket array to the UART pin out */ static void WriteToUART(){ // write XbeePacket[tx_index] to UARTDR // decrement byte remaining // increment index } /* * This function encrypts data packet */ static void EncryptMessage(int message_len){ go through the data packet and xor by encrypt key index by index increment encryption key index reset index to zero if it reaches 32 } /* * This function initializes the components for encoder input capture (PC4) */ void InitInputCapture_Encoder1( void ){ start by enabling the clock to the timer (Wide Timer 0) enable the clock to Port C since we added this Port C clock init, we can immediately start into configuring the timer, no need for further delay make sure that timer (Timer A) is disabled before configuring set it up in 32bit wide (individual, not concatenated) mode the constant name derives from the 16/32 bit timer, but this is a 32/64 bit timer so we are setting the 32bit mode we want to use the full 32 bit count, so initialize the Interval Load register to 0xffff.ffff (its default value :-) set up timer A in capture mode (TAMR=3, TAAMS = 0), for edge time (TACMR = 1) and up-counting (TACDIR = 1) To set the event to rising edge, we need to modify the TAEVENT bits in GPTMCTL. Rising edge = 00, so we clear the TAEVENT bits Now Set up the port to do the capture (clock was enabled earlier) start by setting the alternate function for Port C bit 4 (WT0CCP0) Then, map bit 4's alternate function to WT0CCP0 7 is the mux value to select WT0CCP0, 16 to shift it over to the right nibble for bit 4 (4 bits/nibble * 4 bits) Enable pin on Port C for digital I/O make pin 4 on Port C into an input back to the timer to enable a local capture interrupt enable the Timer A in Wide Timer 0 interrupt in the NVIC it is interrupt number 94 so appears in EN2 at bit 30 make sure interrupts are enabled globally now kick the timer off by enabling it and enabling the timer to stall while stopped by the debugger } /* * This function is the ISR for the encoder input capture */ void InputCaptureResponse_Encoder1( void ){ start by clearing the source of the interrupt, the input capture event start the one shot timer clear the Flag for One shot because now we are at a new edge now grab the captured value and calculate the period update LastCapture to prepare for the next edge increase the encoder_count from the detected pulse detect the state of PC5 to identify current direction of the wheel and set current direction variable accordingly } /* * This function returns the value of the wheel's current RPM */ double get_RPM_Encoder1(void){ return rpm variable value } /* * This function initializes one shot timer for encoder (detecting stopping event) */ void InitOneShotInt_Encoder1( void ){ start by enabling the clock to the timer (Wide Timer 0) kill a few cycles to let the clock get going make sure that timer (Timer B) is disabled before configuring set it up in 32bit wide (individual, not concatenated) mode the constant name derives from the 16/32 bit timer, but this is a 32/64 bit timer so we are setting the 32bit mode set up timer B in 1-shot mode so that it disables timer on timeouts first mask off the TAMR field (bits 0:1) then set the value for 1-shot mode = 0x01 set timeout enable a local timeout interrupt. TBTOIM = bit 8 enable the Timer B in Wide Timer 0 interrupt in the NVIC it is interrupt number 95 so appears in EN2 at bit 30 make sure interrupts are enabled globally now kick the timer off by enabling it and enabling the timer to stall while stopped by the debugger. TAEN = Bit0, TASTALL = bit1 } /* * This function starts the one shot timer */ void StartOneShot_Encoder1( void ){ kick the timer off by enabling it and enabling the timer to stall while stopped by the debugger } /* * This function is the ISR for one shot timeout */ void OneShotIntResponse_Encoder1( void ){ start by clearing the source of the interrupt reset rpm and direction to 0 set flag one shot timeout to 1 } /* * This function initializes PC5 and PC6 */ static void Init_Port(){ Initialize clock to Port A Initialize clock to Port B Initialize clock to Port C Initialize PA2,3,4,5,6 for LED output Initialize PA7 as output for Sound Control Initialize PB5,6,7 as input for Dog Select Initialize PC5 for Encoder direction reading Initialize PC6 and PC7 for brake input and pair button input set pin PA4,5,6 high } /* * This function converts the current RPM to output control value */ static int ConvertRPM(){ return rpm value times Ctrl_Offset and divided by RPM_MAX; } /* * This function clears data packet ocntent */ static void ClearRXDataPacket(){ set all index of data packet to 0 } /* * This function clear the RX buffer array */ static void ClearRXBuffer(){ set all index of data packet to 0 } /* * This function copies the elements from received data packet * array to the buffer array */ static void CopyToBuffer(){ set all index of buffer array to values in data packet } /* * This function return the element at specific index of the buffer array */ uint8_t GetRXBuffer(int index){ return value of the element in RX buffer array at the specified input index } /*------------------------------- Footnotes -------------------------------*/ /*------------------------------ End of file ------------------------------*/