Ship Master
Initialize:
Setup internal Clock to 8MHz
Setup EUSART with 9600 baud rate
Setup PWM
Setup SPI
Enable Interrupts
RETURN
InitializeGameState:
Set up Ping status as waiting for iButton
Clear received flag and data index
Set up COM_frameid and COM_options
Set State Machine status as Waiting
RETURN
Main:
Initialize
InitializeGameState
Wait for iButton
Setup ping data as waiting for pairing
Wait for Synch
Set Team Flag
Play_Game:
If Status is Waiting (Hard Reset), Goto Main
Check if we have received an API packet
REPEAT Play_Game
CheckTimer0Flag:
If Timer0 overflow flag is not set, RETURN
ELSE,
Clear overflow flag and transmit data
Decrement 3 second Timeout timer. If timer is zero, shut off actuators
RETURN
APIRx:
Check whether an API packet is received
If not, RETURN
ELSE,
Clear received flag,
If it’s navigation command, GOTO API_Navigation
ELSE If it’s admiral command, GOTO API_Admiral
ELSE RETURN
API_Navigation:
; We've received a navigation command from the helm. Interpret the data
; to water speed, speed, and direction, then apply those parameters
Check if it is from our helm and RETURN if not.
Reset 3 second TimeOutTimer
Set Team flag
Read Direction data
Read Speed data
Read Water Speed data
All the parameters are copied over, send them to slaves in SetParameters function
RETURN
SetParameters:
Send Rudder direction information to slaves
If direction is close to going straight (6 – 10), use only rudder to control direction
If not, use differential motor speed by adding and subtracting direction angle from each motor speed
Send Motor speed information to slaves
Activate the pump according to Water speed information received
RETURN
SendDirectionInfo:
Mark data as direction
Mark as slave left
Pull slave select low
CALL SPI_Transmit
Pull slave select high
RETURN
SendFlag:
Save team in transmit data
Mark as flag info
Mark as slave right
Pull slave select low
CALL SPI_Transmit
Pull slave select high
RETURN
SendWhiteFlag:
Save white flag in transmit data
Mark as flag info
Mark as slave right
Pull slave select low
CALL SPI_Transmit
Pull slave select high
RETURN
SendMotorInfo:
Save Left motor speed in transmit data
Mark as speed
Mark as slave left
Pull slave select low
CALL SPI_Transmit
Pull slave select high
Save Right motor speed in transmit data
Mark as speed
Mark as slave left
Pull slave select low
CALL SPI_Transmit
Pull slave select high
RETURN
API_Admiral:
If the message is from the admiral's address,
Check if it is Ping. If yes, GOTO AdmPing
Check if it is Stand Down. If yes, GOTO AdmStanddown
Check if it is Hard Reset. If yes, GOTO AdmHardreset
Check if it is Soft Reset. If yes, GOTO AdmSoftreset
RETURN
AdmPing:
Respond to admiral's ping by sending back the ping data correctly
Set Address To Admiral
Send ping data
RETURN
; Respond to standdown by shutting off everything, sending ack to admiral,
; passing it on to helm, and then block until helm acknowledges
AdmStanddown:
Shut off everythng
Send ack to admiral
Indicate Stand Down Flag
Pass it on to helm by Set Address To Helm and sending stand down command
Block until helm acknowledges
If helm ack is received, RETURN
SendAckToAdmiral:
Set Address To Admiral
Send Ack
RETURN
AdmSoftreset:
Respond to soft reset by shutting off everything
Acknowledge to admiral
RETURN
ShutOffActuation:
Send direction straight and speed 0 and water strength 0 to slave
RETURN
AdmHardreset:
Shut off all actuators
Set State machine status as waiting (for iButton)
RETURN
SPI_Transmit:
Wait until data been received (transmit complete)
Set W reg = contents of SSPBUF
Save the received data in user RAM
Set W reg = contents of TXDATA
Move it to SSPBUF to xmit
RETURN
Interrupt:
PUSH
Copy W to TEMP register
Swap status to be saved into W
Save status to STATUS_TEMP register
ISR
If we received anything through EUSART, CALL EUSART_Rx_Int
If Timer0 overflow flag is set, CALL Timer0_Int
POP
Swap nibbles in STATUS_TEMP register and place result into W
Move W into STATUS register
Swap nibbles in W_TEMP and place result in W_TEMP
Swap nibbles in W_TEMP and place result into W
RETFIE
EUSART_Rx_Int:
Clear flag first
Read data into appropriate index of receiving buffer
Increment the index of the data
Check whether the first 4 bytes of the received API packets are 0x7E, 0x00, 0x08 and 0x81 for error checking.
If they don’t match, clear data index and received flag.
If not all the packet is received yet, RETURN
ELSE, API frame is done. Set the receive DONE flag and clear data index.
Timer0_Int:
Clear interrupt flag
If 10 overflow has occurred reset the counter and set a flag
RETURN
Waiting_for_Sync:
Wait until we receive data
If we've received an API packet,
If it is iButton reading broadcasted,
Store the address of helm
Setup ping data to respond
Send matched command to the helm
Save Team – if odd, Red team, even then Blue team
Clear Waiting status for state machine
RETURN
ELSE If it is ping command, CALL AdmPing
GOTO Waiting_for_Sync
Ship Slave
Initialize:
Setup Clock to 8MHz
Setup Timer0
Setup Hbridge control lines
Setup SPI
Setup Servo
Enable Interrupts
RETURN
Main:
Initialize
Initialize starting values to neutral motor/rudder
REPEAT
This is the main loop, just do nothing.
All responses are handled in SPI interrupt
FOREVER
Interrupt:
PUSH
Copy W to TEMP register
Swap status to be saved into W
Save status to STATUS_TEMP register
ISR
If we received anything through SPI, CALL SPI_Int
If Timer0 overflow flag is set, CALL Timer0_Int
POP
Swap nibbles in STATUS_TEMP register and place result into W
Move W into STATUS register
Swap nibbles in W_TEMP and place result in W_TEMP
Swap nibbles in W_TEMP and place result into W
RETFIE
SPI_Int:
; ISR that receives/transmits from SPI, but primary purpose is to receive
WREG reg = contents of SSPBUF
Save the received data in user RAM
W reg = contents of TXDATA
Process the command
If the command is for this PIC,
If the command is for direction, set Servo pulse width according to the direction info.
If the command is for speed, set motor speed according to the received data and forward/backward direction
RETURN
Timer0_Int:
Clear overflow flag
Decrement servo counter
If the servo counter is zero, set servo pin high and reset servo counter
ELSE if the servo counter is equal to the servo pulse width, set the pin high
RETURN