list
P=PIC16F690
#include "p16F690.inc"
__config (_CP_OFF & _WDT_OFF & _PWRTE_ON
& _HS_OSC)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; #defines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
#define NUMBER_OF_BYTES 0x0B
; Framing
#define START_BYTE 0x7E
#define LENGTH_MSB 0x00
#define LENGTH_LSB 0x08
; API identifier
#define API_RX 0x81
#define API_TX 0x01
; Frame ID
#define FRAME_ID 0x00
; Option
#define OPTIONS 0x01
; Addresses
#define ADMIRAL_ADDRESS_MSB 0xBC
#define ADMIRAL_ADDRESS_LSB 0xFF
#define HELM_MSB 0xBC
#define HELM_LSB 0x06
#define CRAFT_MSB 0xAF
#define CRAFT_LSB 0x06
#define BROADCAST_MSB 0xFF
#define BROADCAST_LSB 0xFF
; for ME218C Data Byte 0 Header
#define IBUTTON_HEADER 0x01
#define NAVIGATION_HEADER 0x02
#define ADMIRAL_HEADER 0x04
#define WATERCRAFT_HEADER 0x08
#define PING_RESPONSE_HEADER 0x10
#define ACK_HEADER 0x80
; for ME218C Header Bit Check
Bits
#define IBUTTON_HEADER_BIT 0
#define NAVIGATION_HEADER_BIT 1
#define ADMIRAL_HEADER_BIT 2
#define WATERCRAFT_HEADER_BIT 3
#define PING_RESPONSE_HEADER_BIT 4
#define ACK_HEADER_BIT 7
; Admiral Message Bytes
#define STAND_DOWN 0x01
#define START_GAME 0x02
#define END_GAME 0x04
#define BLUE_GOAL 0x08
#define RED_GOAL 0x10
#define SOFT_RESET 0x20
#define HARD_RESET 0x40
#define ADMIRAL_PING1 0x00
#define ADMIRAL_PING2 0x80
; Admiral Message Bits
#define STAND_DOWN_BIT 0
#define START_GAME_BIT 1
#define END_GAME_BIT 2
#define BLUE_GOAL_BIT 3
#define RED_GOAL_BIT 4
#define SOFT_RESET_BIT 5
#define HARD_RESET_BIT 6
#define ADMIRAL_PING_BIT 7
; Commands from Helm to
Watercraft
#define NO_ACTION_1 0x88
#define NO_ACTION_2 0x00
#define NO_ACTION_NAVIGATION 0x88
#define NO_ACTION_SPECIAL 0x00
; Commands from Watercraft to
Helm
#define STAND_DOWN_RECEIVED_1 0x00
#define STAND_DOWN_RECEIVED_2 0x02
#define MATCHED_1 0x00
#define MATCHED_2 0x01
; Ping Response Bytes
#define PING_WAIT_IBUTTON_BYTE1 0x01
#define PING_WAIT_IBUTTON_BYTE2 0x00
#define PING_WAIT_MATCH_BYTE1 0x02
#define PING_WAIT_MATCH_BYTE2 0x00
#define PING_PAIRED_BYTE1 0x04
; PING_FOR_PAIRED_BYTE2 is the LSB of the matched
boat/helm
; Ping Response Bits
#define PING_WAIT_IBUTTON_BIT 0
#define PING_WAIT_MATCH_BIT 1
#define PING_PAIRED_BIT 2
; iButton variables
#define IBUTTON_TRIS_INPUT b'00010000' ;
iButton tris bits input
#define IBUTTON_TRIS_OUTPUT b'11101111' ;
iButton tris bits output
#define IBUTTON_BIT 4 ;
defined value for iButton bit in PORTB
#define IBUTTON_FAMILY1 0x01 ;
first possible iButton family byte
#define IBUTTON_FAMILY2 0x09 ;
second possible iButton family byte
; Tris bit defines
#define TRISA_BITS b'00000000' ;
all PORTA outputs
#define TRISB_BITS b'01100000' ;
all PORTB outputs except bit 5
#define TRISC_BITS b'00000000' ;
all PORTC bits are inputs
; PIC baudrate define
#define PIC_BAUDRATE d'129' ; calculated baudrate = 9615 so
X = 129 for 20MHz clock
; Navigation defines
#define MOTOR_TIMER_MAX 20 ;
number of flag sets to reach 0.01ms period
#define MOTOR_DUTY_75_FORWARD 15 ;
number of flag sets to reach 75% duty cycle
#define MOTOR_DUTY_50 10 ;
number of flag sets to reach 50% duty cycle
#define MOTOR_DUTY_75_BACKWARD 15 ;
number of flag sets to reach 75% duty cycle
#define SERVO_PIN 0 ;
Pin number for servo signal, portC
#define SERVO_MAX 27 ;
number of flag sets in 20 ms
#define SERVO_LEFT 4 ;
number of flag sets in 1.5 ms
#define SERVO_CENTER 3 ;
number of flag sets in 2 ms
#define SERVO_RIGHT 2 ;
number of flag sets in 2.5 ms
#define MOTOR_DIRECTION_PIN 1 ;
Pin number for motor direction, portC
#define MOTOR_PWM_PIN 2 ;
Pin number for motor PWM, portC
#define PUMP_PIN 3 ;
Pin number for the pump control, portC
#define BLUE_LED 6 ;
Pin number for blue team indicator, portC
#define RED_LED 7 ;
Pin number for red team indicator, portC
#define TEAM_BIT 0 ;
bit of ibutton byte1 to check for team association
; Babysit function defines (stop
moving after 3 seconds no msg receive from helm)
#define NUM_TICKS_3SEC_HIGH 0x0B ;
Actually 1.5 sec because of the implementation
#define NUM_TICKS_3SEC_LOW 0xB8
#define RX_BABYSIT_BIT 0
; Transmit delay defines
(transmit no faster than 5Hz)
#define TRANSMIT_COUNTDOWN_TO_20MS_1 d'200'
#define TRANSMIT_COUNTDOWN_TO_20MS_2 d'2'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; location and variable definitions
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Receive and Transmit Byte
Locations
RX_DATA_HEADER equ 0x20 ;
RX data header byte
RX_DATA_BYTE1 equ 0x21 ;
RX data byte 1
RX_DATA_BYTE2 equ 0x22 ;
RX data byte 2
TX_DATA_HEADER equ 0x23 ;
TX data header byte
TX_DATA_BYTE1 equ 0x24 ;
TX data byte 1
TX_DATA_BYTE2 equ 0x25 ;
TX data byte 2
RECEIVE_BYTE_COUNT equ 0x26 ;
number of received bytes in packet
CHECKSUM equ 0x27 ;
checksum
DEST_ADDRESS_MSB equ 0x28 ;
destination address msb
DEST_ADDRESS_LSB equ 0x29 ;
destination address lsb
DATA_RECEIVED equ 0x2A ;
byte received
SOURCE_ADDRESS_MSB equ 0x2B ;
source address msb
SOURCE_ADDRESS_LSB equ 0x2C ;
source address lsb
PAIRED_ADDRESS_MSB equ 0x2D ;
paired address msb
PAIRED_ADDRESS_LSB equ 0x2E ;
paired address lsb
; Temp registers for ISRs
W_TEMP equ 0x2F ;
temp storage for W
STATUS_TEMP equ 0x30 ;
temp storage for status register
; Ping counter register and
bytes
PING_RESPONSE_BYTE1 equ 0x31 ;
first byte of ping response
PING_RESPONSE_BYTE2 equ 0x32 ;
second byte of ping response
; iButton Bit Definitions
IBUTTON_BYTE0 equ 0x34 ;
location for 1st byte of iButton serial number (contains bits 0-8), family byte
IBUTTON_BYTE1 equ 0x35 ;
location for 2st byte of iButton serial number (contains bits 9-16), 1st keeper
byte
IBUTTON_BYTE2 equ 0x36 ;
location for 3st byte of iButton serial number (contains bits 17-24), 2nd
keeper byte
DELAY_COUNTER equ 0x37 ;
location for delay counter
READ_BYTE_COUNTER equ 0x38 ;
location for read byte counter
READ_BIT_COUNTER equ 0x39 ;
location for read bit counter
; Navigation registers
SPEED_COMMAND equ 0x3B ;
motor speed command byte
DIRECTION_COMMAND equ 0x3C ;
motor direction command byte
MOTOR_TIMER_DESIRED equ 0x3D ;
number of desired timer ticks to hold pwm line high (20 ticks for 100% duty)
SERVO_DESIRED equ 0x3E ;
number of timer ticks high (2 ms is neutral)
NAVIGATION_BYTE equ 0x3F ;
Byte 1 of the command communication to be received via XBEE
SPECIAL_BYTE equ 0x40 ;
Byte 2 of the command communication to be received via XBEE
MOTOR_TIMER_COUNT equ 0x41 ;
increments everytime the TMR2 interrupt flag is tripped
SERVO_TIMER_COUNT equ 0x42 ;
increments everytime the TMR2 interrupt flag is tripped
MOTOR_PORT equ PORTC ;
Port for motor control
PUMP_PORT equ PORTC ;
Port for pump control
SERVO_PORT equ PORTC ;
Port for servo control
THREE_SEC_COUNTER_HIGH equ 0x45 ;
high byte for 3 second shut down counter
THREE_SEC_COUNTER_LOW equ 0x46 ;
low byte for 3 second shut down counter
RX_BABYSIT equ 0x47 ;
stores a flag on whether receiving has occurred
HELM_MATCH_FLAG equ 0x48 ;
flag to signify that the boat has matched with a helm
ACK_FLAG equ 0x49 ;
flag to signify that an acknowledgment is required
HELM_STAND_DOWN_RESPONSE equ 0x4A ;
flag to signify that the helm has received the stand down command
TRANSMIT_COUNTDOWN_1 equ 0x4B ;
first count down timer for transmission delay
TRANSMIT_COUNTDOWN_2 equ 0x4C ;
second count down timer for transmission delay
TRANSMIT_COUNTDOWN_FLAG equ 0x4D ;
flag to signify that the desired count down has been completed
; End Bit Definitions
org 0
GOTO MAIN
org 4
GOTO ISR
org 5
RX_JUMP_TABLE:
ADDWF PCL, F
GOTO Case0
GOTO Case1
GOTO Case2
GOTO Case3
GOTO Case4
GOTO Case5
GOTO Case6
GOTO Case7
GOTO Case8
GOTO Case9
GOTO Case10
GOTO Case11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MAIN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MAIN:
INITIALIZE:
clear_ansel_bits:
BANKSEL ANSEL ; select bank containing
ANSEL
CLRF ANSEL ; clears analog bits
BANKSEL ANSELH ;
select bank containing ANSLEH
CLRF ANSELH ; clears other analog bits
set_data_direction:
BANKSEL TRISA ;
select bank containing TRISA
MOVLW TRISA_BITS ;
write TRISA_BITS to W
MOVWF TRISA ;
write TRISA_BITS from W to TRISA
MOVLW TRISB_BITS ;
write TRISB_BITS to W
MOVWF TRISB ;
write TRISB_BITS from w to TRISB
MOVLW TRISC_BITS ;
write TRISC_BITS to W
MOVWF TRISC ;
write TRISC_BITS from W to TRISC
intialize_general:
BANKSEL SPBRGH ;
select bank containing SPBRGH
CLRF SPBRGH ;
set SPBRGH byte to 0
MOVLW PIC_BAUDRATE ; write the contents of
PIC_BAUDRATE to W
MOVWF SPBRG ;
set x = 64 and calculated baudrate = 9615
BANKSEL TXSTA ;
select bank containing TXSTA
BCF TXSTA, BRGH ;
clear BRGH bit of TXSTA / low speed
BCF TXSTA, SYNC ;
clear SYNC bit of TXSTA / asynchronous mode
BANKSEL BAUDCTL ;
select bank containing BAUDCTL
BSF BAUDCTL, BRG16 ; clear BRG16
bit of BAUDCTL / 16-bit baud rate generator is used
;
SYNC:BRG16:BRGH = 0:1:0 / 16-bit asynchronous / (FOSC/[16*(n+1)])
initialize_variables:
BANKSEL PORTA
CLRF RECEIVE_BYTE_COUNT
CLRF CHECKSUM
CLRF RX_DATA_HEADER
CLRF RX_DATA_BYTE1
CLRF RX_DATA_BYTE2
CLRF TX_DATA_HEADER
CLRF TX_DATA_BYTE1
CLRF TX_DATA_BYTE2
CLRF DEST_ADDRESS_MSB
CLRF DEST_ADDRESS_LSB
CLRF PAIRED_ADDRESS_MSB
CLRF PAIRED_ADDRESS_LSB
CLRF DATA_RECEIVED
CLRF PORTC
CLRF THREE_SEC_COUNTER_LOW
CLRF THREE_SEC_COUNTER_HIGH
CLRF HELM_STAND_DOWN_RESPONSE
CLRF HELM_MATCH_FLAG
CLRF ACK_FLAG
CLRF SPECIAL_BYTE
MOVLW NO_ACTION_NAVIGATION ; write no action to w
MOVWF NAVIGATION_BYTE ;
write no action from w to the navication byte
CLRF TRANSMIT_COUNTDOWN_1
CLRF TRANSMIT_COUNTDOWN_2
CLRF TRANSMIT_COUNTDOWN_FLAG
initialize_interrupts:
BANKSEL INTCON ;
select bank containing INTCON
BSF INTCON, GIE ;
enable global interrupts
BSF INTCON, PEIE ;
enable peripheral interrupts
BANKSEL PIE1 ;
select bank containing PIE1
BSF PIE1, RCIE ;
enable EUSART receive interrupt
initialize_comm:
BANKSEL RCSTA ;
select bank containing RCSTA
BSF RCSTA, SPEN ;
enable serial port
BSF RCSTA, CREN ;
enable receive
BANKSEL TXSTA ;
select bank containing TXSTA
BSF TXSTA, TXEN ;
enable transmit(also enables TXIF in PIR1)
INIT_DELAY_TIMERS:
BANKSEL T2CON ; select bank containing T2CON
BSF T2CON, TMR2ON ;
set TMR2ON bit to turn Timer2 on (Timer2 at 20MHz/4 = 5MHz)
INIT_HARD_RESET:
BCF ACK_FLAG,
HARD_RESET_BIT ; clear the
hard reset acknowledgement flag
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MAIN LOOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PLAY_GAME:
; check for hard
reset
BANKSEL PIR1 ;
select bank containing PIR1
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
GOTO MAIN ;
if a hard reset has been received then goto MAIN
; set ping
response bytes ;
if no hard reset was received, setup the waiting for iButton state ping
response
MOVLW PING_WAIT_IBUTTON_BYTE1
MOVWF PING_RESPONSE_BYTE1
MOVLW PING_WAIT_IBUTTON_BYTE2
MOVWF PING_RESPONSE_BYTE2
; enter wait for
ibutton state
CALL WAIT_FOR_IBUTTON ;
go to the waiting for iButton state
; check for hard
reset
BANKSEL PIR1 ;
select the bank containing PIR1
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
GOTO MAIN ; if a hard reset hsa been received then goto
MAIN
; set ping
response bytes ;
if no hard reset was received, setup the waiting for helm match state ping
response
BANKSEL PIR1 ;
also initialize the navigation and special bytes to no action
CLRF RX_DATA_HEADER
MOVLW NO_ACTION_NAVIGATION
MOVWF NAVIGATION_BYTE
CLRF SPECIAL_BYTE
CALL HANDLE_NAVIGATION_BYTE
CALL HANDLE_SPECIAL_BYTE
MOVLW PING_WAIT_MATCH_BYTE1
MOVWF PING_RESPONSE_BYTE1
MOVLW PING_WAIT_MATCH_BYTE2
MOVWF PING_RESPONSE_BYTE2
; enter wait for
helm match state
CALL WAIT_FOR_HELM_MATCH ; go to the waiting for helm
match state
; check for hard
reset
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
GOTO MAIN ;
if a hard reset has been received, goto main
; set ping
response bytes ;
if no hard reset has been received, setup the paired ping response
MOVLW PING_PAIRED_BYTE1
MOVWF PING_RESPONSE_BYTE1
MOVF PAIRED_ADDRESS_LSB, W
MOVWF PING_RESPONSE_BYTE2
; enter execute
commands state
CALL EXECUTE_COMMANDS ;
goto the execute commands state and begin responding to helm commands
; check for hard
reset
BANKSEL PIR1 ;
select the bank containing PIR1
; BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
; GOTO MAIN ;
if a hard reset has been received goto main
GOTO MAIN ;
if no hard reset was received, an error occured somewhere, goto main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CHECK FOR IBUTTON ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WAIT_FOR_IBUTTON:
CHECK_FOR_IBUTTON:
BANKSEL PIR1 ;
select the bank containing PIR1
BCF ACK_FLAG, STAND_DOWN_BIT ; clear the stand down flag, no
stand down can be responded to in this state
NOP
BCF HELM_STAND_DOWN_RESPONSE,
0 ; clear the helm stand down response
flag, no stand down can be responsed to in this state
NOP
BCF ACK_FLAG, SOFT_RESET_BIT ; clear the soft reset bit, no soft reset can
be responded to in this state
NOP
BTFSC ACK_FLAG, ADMIRAL_PING_BIT ; check if a ping from the admiral
has been received
CALL SEND_PING_RESPONSE ; if a ping from the
admiral has been received, respond to the ping
BANKSEL PIR1 ;
if no ping has been received, select the bank containing PIR1
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
RETURN ;
if a hard reset has been received, break out of this state to respond to the
hard reset
CALL IBUTTON_PIN_TO_OUTPUT ; if no hard reset has been
received, set iButton pin to output
BANKSEL PORTB ;
select the bank containing PORTB
BCF PORTB, IBUTTON_BIT ; set the iButton
pin low
CALL WAIT_500US ;
wait 500us
CALL IBUTTON_PIN_TO_INPUT ; set iButton pin to input
CALL WAIT_50US ;
wait 50us
BANKSEL PORTB ;
select the bank containing PORTB
BTFSC PORTB, IBUTTON_BIT ; check if the
iButton pin is low, it is low if there is an iButton there
GOTO CHECK_FOR_IBUTTON ; if
there is no iButton then check again
GOTO CONDUCT_RESET ; if there is
an iButton the conduct a reset
CONDUCT_RESET:
BANKSEL PORTC ;
select the bank containing PORTC
CALL IBUTTON_PIN_TO_OUTPUT ; set iButton pin to output
BANKSEL PORTB ;
select the bank containing PORTB
BCF PORTB, IBUTTON_BIT ; set the line low
CALL WAIT_500US ;
wait 500us
BANKSEL PORTB ;
select the bank containing PORTB
BSF PORTB, IBUTTON_BIT ; set the line high
CALL WAIT_500US ;
wait 500us
SEND_READ_ROM_COMMAND:
;
Read ROM command is 0x33 (b'00110011'), sending LSB first (b'11001100')
CALL SEND_READ_ROM_BIT_HIGH ; send bit0, 1
CALL SEND_READ_ROM_BIT_HIGH ; send bit1, 1
CALL SEND_READ_ROM_BIT_LOW ; send bit2, 0
CALL SEND_READ_ROM_BIT_LOW ; send bit3, 0
CALL SEND_READ_ROM_BIT_HIGH ; send bit4, 1
CALL SEND_READ_ROM_BIT_HIGH ; send bit5, 1
CALL SEND_READ_ROM_BIT_LOW ; send bit6, 0
CALL SEND_READ_ROM_BIT_LOW ; send bit7, 0
INIT_IBUTTON_READING:
BANKSEL PORTA ;
select the bank containing PORTA
CLRF IBUTTON_BYTE0 ; clear
ibutton byte 0
CLRF IBUTTON_BYTE1 ; clear
ibutton byte 1
CLRF IBUTTON_BYTE2 ; clear
ibutton byte 2
CLRF READ_BYTE_COUNTER ; set
the read byte counter to 0
BSF READ_BYTE_COUNTER, 0 ; set bit 0 of the read
byte counter to 1
CLRF READ_BIT_COUNTER ;
set the read bit counter to 0
BSF READ_BIT_COUNTER, 0 ; set bit 0 of the read
bit counter to 1
READ_IBUTTON_BYTE:
CALL READ_IBUTTON ; read the
iButton
BANKSEL PORTB ;
select the bank containing PORTB
BTFSC READ_BIT_COUNTER, 7 ; check if the read bit
counter is clear, 0
GOTO INIT_NEXT_BYTE_READ ; read the next byte
RLF READ_BIT_COUNTER, F ; shift the read bit
counter left one space
GOTO READ_IBUTTON_BYTE ;
read the next bit of the byte
INIT_NEXT_BYTE_READ:
RLF READ_BYTE_COUNTER, F ; shift the read byte
counter left one space
BTFSC READ_BYTE_COUNTER,3 ; check if bit 3 of the
read byte counter is set, ie. preparing to read a 4th byte
GOTO CHECK_READING_ERROR ; if we are trying to read
a 4th byte, check for a reading error
CLRF READ_BIT_COUNTER ;
if we are still trying to read bytes 1, 2, or 3 clear the read bit counter
BSF READ_BIT_COUNTER, 0 ; set bit 0 of the read
bit counter to 1
GOTO READ_IBUTTON_BYTE ;
read the next byte
CHECK_READING_ERROR:
BANKSEL PORTA ;
select the bank containing PORTA
MOVF IBUTTON_BYTE0, W ;
move iButton byte 0 to W
SUBLW IBUTTON_FAMILY1 ;
subtract IBUTTON_FAMILY1 (0x01) from IBUTTON_BYTE0
BTFSC STATUS,Z ;
test bit Z of STATUS register
GOTO DETERMINE_TEAM ; if
IBUTTON_BYTE0 = IBUTTON_FAMILY1 (0x01), display the appropriate byte
MOVF IBUTTON_BYTE0, W ;
move iButton byte 0 to W
SUBLW IBUTTON_FAMILY2 ;
subtract IBUTTON_FAMILY2 (0x09) from IBUTTON_BYTE0
BTFSC STATUS, Z ;
test bit Z of STATUS register
GOTO
DETERMINE_TEAM ; if
IBUTTON_BYTE0 = IBUTTON_FAMILY2 (0x09), determine and display which team you
are on
GOTO CHECK_FOR_IBUTTON ; if
IBUTTON_BYTE0 is not IBUTTON_FAMILY1 or IBUTTON_FAMILY2, an error occured,
check for the ibutton again
DETERMINE_TEAM:
BANKSEL PORTC ;
select the bank containing PORTC
BCF PORTC, RED_LED ; clear the
signal pin for the red team led on PORTC
NOP
BCF PORTC, BLUE_LED ; clear the
signal pin for the blue team led on PORTC
NOP
BTFSC IBUTTON_BYTE1, TEAM_BIT ; check if the ibutton received
puts the boat on the red team
BSF PORTC, RED_LED ; if the
ibutton is a red team ibutton, turn on the red light
BTFSS IBUTTON_BYTE1, TEAM_BIT ; check if the ibutton received
puts the boat on the blue team
BSF PORTC, BLUE_LED ; if the
ibutton is a blue team ibutton, turn on the blue light
RETURN ;
break out of the waiting for ibutton state
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WAIT FOR MATCH WITH HELM ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WAIT_FOR_HELM_MATCH:
RE_INIT_TIMER2:
BANKSEL T2CON ; select bank containing T2CON
BSF T2CON, TMR2ON ; turn on
timer 2
MOVLW b'01001000' ;
move 01001000 to W
IORWF T2CON, F ;
or W with T2CON to set TOUTPS1-3 to 1001 and postscale timer 2 by 1:10, timer
effectively at 500kHz
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'11110111' ;
d'249'
MOVWF PR2 ; move 11111001 from W to PR2 (Timer 2 Flag set every
1/500kHz * (249+1)ticks = 500us)
BANKSEL PIE1 ;
select the bank containing PIE1
BSF PIE1, TMR2IE ;
enable the TMR2 interrupt
WAIT_TO_RECEIVE_MATCHING_IBUTTON:
BANKSEL PIR1 ;
select the bank containing PIR1
BCF ACK_FLAG,
STAND_DOWN_BIT ; clear the
stand down flag, can not respond to a stand down in this state
NOP
BCF HELM_STAND_DOWN_RESPONSE,
0 ; clear the helm stand down flag, can
not respond to a stand down in this state
NOP
BCF ACK_FLAG,
SOFT_RESET_BIT ; clear the soft reset bit,
can no respond to a soft reset in this state
NOP
NOP
BTFSC ACK_FLAG, ADMIRAL_PING_BIT ; check if a ping has been received
CALL SEND_PING_RESPONSE ; if a ping has been
received, respond to it
BANKSEL PIR1 ;
if no ping has been received, select the bank containing PIR1
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a hard reset has been
received
RETURN ;
if a hard reset has been received, break out of this state to respond to it
BANKSEL PIR1 ;
if no hard reset hsa been received, select the bank containing PIR1
BTFSS HELM_MATCH_FLAG, 0 ; check if a helm has
broadcast a matching ibutton serial
GOTO WAIT_TO_RECEIVE_MATCHING_IBUTTON ; if no helm has broadcast a matching
ibutton serial, keep listening
GOTO TRANSMIT_MATCHED_MSG ; if a helm has broadcast a
matching ibutton serial, transmit a message to the helm signifying receipt
TRANSMIT_MATCHED_MSG:
BANKSEL PIR1 ;
select the bank containing PIR1
BTFSS TRANSMIT_COUNTDOWN_FLAG, 0 ; check if the transmit delay count down
is complete
GOTO WAIT_TO_RECEIVE_MATCHING_IBUTTON ; if the transmit delay count down is
not complete, keep waiting to transmit
CLRF TRANSMIT_COUNTDOWN_1 ; if the count down is
complete, clear the first count down timer
CLRF TRANSMIT_COUNTDOWN_2 ; clear the second count down
timer
CLRF TRANSMIT_COUNTDOWN_FLAG ; clear the count down
complete flag
BANKSEL PIR1 ;
select the bank containing PIR1
MOVF PAIRED_ADDRESS_MSB, W ; move the PAIRED_ADDRESS_MSB
to W
MOVWF DEST_ADDRESS_MSB ;
move the PAIRED_ADDRESS_MSB from W to DEST_ADDRESS_MSB
MOVF PAIRED_ADDRESS_LSB, W ; move the
PAIRED_ADDRESS_LSB to W
MOVWF DEST_ADDRESS_LSB ;
move the PAIRED_ADDRESS_LSB from W to DEST_ADDRESS_LSB
MOVLW WATERCRAFT_HEADER ; move
WATERCRAFT_HEADER to W
MOVWF TX_DATA_HEADER ; move the
WATERCRAFT_HEADER from W to TX_DATA_HEADER
MOVLW MATCHED_1 ;
move MATCHED_1 to W
MOVWF TX_DATA_BYTE1 ; move
MATCHED_1 from W to TX_DATA_BYTE1
MOVLW MATCHED_2 ;
move MATCHED_2 to W
MOVWF TX_DATA_BYTE2 ; move
MATCHED_2 from W to TX_DATA_BYTE2
CALL TRANSMIT ;
transmit the stored message
BTFSS HELM_MATCH_FLAG, 1 ; check if the helm has
responded with a no action
GOTO WAIT_TO_RECEIVE_MATCHING_IBUTTON ; if the helm has not responded, keep
transmitting
RETURN ;
if the helm has responded, break out of this state
; check
address if additional msg checks are needed
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; EXECUTE COMMANDS ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
EXECUTE_COMMANDS:
INIT_COUNTERS: ;
clear all necessary bytes, counters, etc.
BANKSEL PIR1
CLRF MOTOR_TIMER_COUNT
CLRF SERVO_TIMER_COUNT
CLRF ACK_FLAG
CLRF HELM_STAND_DOWN_RESPONSE
CLRF THREE_SEC_COUNTER_HIGH
CLRF
THREE_SEC_COUNTER_LOW
CLRF RX_BABYSIT
CHECK_INCOMING_DATA:
BANKSEL PIR1 ;
select the bank containing PIR1
BTFSC ACK_FLAG, ADMIRAL_PING_BIT ; check if a ping
from the admiral has been received
CALL SEND_PING_RESPONSE ; if a
ping from the admiral has been received,respond to the ping
BANKSEL PIR1 ;
if no ping was received, select the bank containing PIR1
BTFSC ACK_FLAG, STAND_DOWN_BIT ; check if a stand
down command has been issued
CALL SEND_STAND_DOWN_ACK_TO_ADMIRAL ; if a stand down command
has been issued, respond to it
BANKSEL PIR1 ;
if no stand down command was issued, select the bank containing PIR1
BTFSC ACK_FLAG, SOFT_RESET_BIT ; chceck if a soft reset has
been issued
CALL SEND_SOFT_RESET_ACKNOWLEDGEMENTS ; if a soft reset has been issued,
respond to it
BANKSEL PIR1 ;
if no soft reset was issued, select the bank containing PIR1
BTFSC ACK_FLAG, HARD_RESET_BIT ; check if a
hard reset has been issued
GOTO HANDLE_HARD_RESET ; if a
hard reset has been issued, handle it
GOTO HANDLE_INCOMING_DATA ; if no hard
reset has been issued, process the incoming navigation commands
HANDLE_INCOMING_DATA:
BANKSEL PIR1 ;
select the bank containing PIR1
BTFSS HELM_STAND_DOWN_RESPONSE,
0 ; check if a respone
to a stand down from the helm is pending
CALL CHECK_FOR_NAVIGATION_BYTE ; if yes, skip this
step, if not, check to see if the most recent received packet has a navigation
header
CALL HANDLE_NAVIGATION_BYTE ;
handle the most recent navigation byte
CALL HANDLE_SPECIAL_BYTE ;
handle the most recent special byte
BANKSEL PIR1 ;
select the bank containing PIR1
BTFSC HELM_STAND_DOWN_RESPONSE,
0 ; check if a response
to a stand down from the helm is pending
CALL SEND_STAND_DOWN_TO_HELM ; if
yes, send a stand down command to the helm
GOTO CHECK_INCOMING_DATA ; if no
response is pending, begin processing the most recent navigation data
HANDLE_HARD_RESET:
CALL HANDLE_NAVIGATION_BYTE ;
handle the navigation byte
CALL HANDLE_SPECIAL_BYTE ;
handle the special byte
RETURN
CHECK_FOR_NAVIGATION_BYTE:
BANKSEL PIR1
BTFSS RX_DATA_HEADER,
NAVIGATION_HEADER_BIT ; check if
RX_DATA_HEADER is a NAVIGATION_HEADER
RETURN ;
if Z = 0, the RX_DATA_HEADER is not a NAVIGATION_HEADER, go back to waiting for
the correct msg type
MOVF RX_DATA_BYTE1, W ;
if Z = 1, the RX_DATA_HEADER is a NAVIGATION_HEADER, move RX_DATA_BYTE1 to W
MOVWF NAVIGATION_BYTE ; move
RX_DATA_BYTE1 from W to NAVIGATION_BYTE
MOVF RX_DATA_BYTE2, W ;
move RX_DATA_BYTE2 to W
MOVWF SPECIAL_BYTE ;
move RX_DATA_BYTE2 from W to SPECIAL_BYTE
RETURN
HANDLE_NAVIGATION_BYTE:
MOVF NAVIGATION_BYTE,W ;
move NAVIGATION_BYTE to W
ANDLW 0x0F ;
save last four bits of NAVIGATION for Speed
MOVWF SPEED_COMMAND ;
store speed
SWAPF NAVIGATION_BYTE,W ;
move Swapped Navigation byte to W
ANDLW 0x0F ;
save four bits of Navigation for Direction
MOVWF DIRECTION_COMMAND ; store
direction
RETURN
HANDLE_SPECIAL_BYTE:
MOVF SPECIAL_BYTE, W ;
move SPECIAL_BYTE to W
ANDLW 0x0F ;
save last four bits of Special for water
BTFSC STATUS,Z ;
Skip if not zero
BCF PUMP_PORT,PUMP_PIN ; Turn
off Pump
BTFSS STATUS,Z ;
Skip if is zero
BSF PUMP_PORT,PUMP_PIN ; Turn
on Pump
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; SERVO CONTROL SUBROUTINES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SERVICE_SERVO_DIRECTION:
BANKSEL PORTC
BTFSS DIRECTION_COMMAND,3 ; skip if the direction
bit is set (Straight or right)
CALL SET_SERVO_LEFT ; move servo
left command into W
BTFSC DIRECTION_COMMAND,3 ; skip if the direction
bit is clear (Left)
CALL CENTER_OR_RIGHT
RETURN
CENTER_OR_RIGHT:
MOVF DIRECTION_COMMAND,W ; move direction command to
W
ANDLW 0x07 ; save last
three bits of the direction
BTFSC STATUS,Z ;
skip if the result above was not equal to zero
CALL SET_SERVO_CENTER ; set the servo to
the center position
MOVF DIRECTION_COMMAND,W ; move direction command to
W
ANDLW 0x07 ; save last
three bits of the direction
BTFSS STATUS,Z ;
skip if the result above was equal to zero
CALL SET_SERVO_RIGHT ;
set the servo to the center position
RETURN
SET_SERVO_CENTER:
MOVLW SERVO_CENTER ; set the
servo high value to reflect center position
MOVWF SERVO_DESIRED
RETURN
SET_SERVO_RIGHT:
MOVLW SERVO_RIGHT ; set
the servo high value to reflect right position
MOVWF SERVO_DESIRED
RETURN
SET_SERVO_LEFT:
MOVLW SERVO_LEFT ; set
the servo high value to reflect left position
MOVWF SERVO_DESIRED
RETURN
SERVICE_SERVO_TIMER:
BANKSEL PORTC ; select port
bank
MOVF SERVO_TIMER_COUNT,W ; move period position to W
SUBWF SERVO_DESIRED,W ;
subtract SERVO_TIMER_COUNTER from SERVO_DESIRED
BTFSC STATUS,C ;
skip if carry bit is 0 meaning skip if SERVO_AT > SERVO_DESIRED
BSF SERVO_PORT,SERVO_PIN ; set the servo pin high
BTFSS STATUS,C ;
skip if carry bit is 1 meaning skip if SERVO_AT <= SERVO_DESIRED
BCF SERVO_PORT,SERVO_PIN ; set the servo pin low
MOVF SERVO_TIMER_COUNT,W ; move period position to W
SUBLW SERVO_MAX ;
subtract W from SERVO_MAX
BTFSC STATUS,Z ;
skip if subtraction not equal to zero
GOTO RESET_SERVO_TIMER_COUNT ; reset
SERVO_MOTOR_COUNTER for new period
GOTO INCF_SERVO_TIMER_COUNT ; if the
subtraction is non-zero then increment the counters
RESET_SERVO_TIMER_COUNT:
CLRF SERVO_TIMER_COUNT ; clear the SERVO_TIMER_COUNT
RETURN
INCF_SERVO_TIMER_COUNT:
INCF SERVO_TIMER_COUNT, F ; increment the
SERVO_TIMER_COUNT
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; MOTOR CONTROL SUBROUTINES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SERVICE_MOTOR_DIRECTION:
BTFSC SPEED_COMMAND,3 ;
Skip if MSB of Motor command is low (backwards)
CALL GO_FORWARD ; if bit
3 of the speed command is high, go forward
BTFSS SPEED_COMMAND,3 ;
Skip if MSB of Motor command is high (forwards)
CALL GO_BACKWARD ; if bit 3
of the speed command is low go backward
RETURN
GO_FORWARD:
BCF MOTOR_PORT,MOTOR_DIRECTION_PIN ; Set Motor
direction pin low
MOVF SPEED_COMMAND,W ;
Move Speed command to W
ANDLW 0x07 ;
AND speed command with 0000 0111
BTFSC STATUS,Z ;
if result of AND is not zero, skip
CLRF MOTOR_TIMER_DESIRED ;
if the result is zero then a no move command has been issued, don't move
BTFSS STATUS,Z ;
if it is zero then skip (not affected by BCF command)
CALL SET_FORWARD_LEVEL ;
call subroutine to check for full or partial speed
RETURN
GO_BACKWARD:
BSF MOTOR_PORT,MOTOR_DIRECTION_PIN ; Set Motor
direction pin high
MOVF SPEED_COMMAND,F ;
Move the file to itself to test for zero
BTFSC STATUS,Z ;
Skip if speed command not zero
CALL SET_DUTY_75_BACKWARD ; if Z is 1
then full backwards was requested, set duty to 75%
BTFSS STATUS,Z ;
Skip if speed command is zero and was handled with the BCF
CALL SET_DUTY_50 ;
if if Z is 0 then a slower backward speed was requested, set duty to 50%
RETURN
SET_FORWARD_LEVEL:
SUBLW 0x07 ;
subtract 0000 0111 from W, if zero, original speed was full forward
BTFSC STATUS,Z ;
skip if Z is not set, i.e. not full forward
CALL SET_DUTY_75_FORWARD ;
if Z is set, set the motor duty cycle to 75% forward
BTFSS STATUS,Z ;
skip if Z is set, i.e. full speed already set
CALL SET_DUTY_50 ;
if Z is not set, set the motor duty cycle to 50%
RETURN
SET_DUTY_75_FORWARD:
MOVLW MOTOR_DUTY_75_FORWARD ;
move MOTOR_DUTY_75_FORWARD to W
MOVWF MOTOR_TIMER_DESIRED ;
move MOTOR_DTUY_75_FORWARD from W to MOTOR_TIMER_DESIRED
RETURN
SET_DUTY_50:
MOVLW MOTOR_DUTY_50 ;
move MOTOR_DUTY_50 to W
MOVWF MOTOR_TIMER_DESIRED ;
move MOTOR_DUTY_50 from W to MOTOR_TIMER_DESIRED
RETURN
SET_DUTY_75_BACKWARD:
MOVLW MOTOR_DUTY_75_BACKWARD ;
move MOTOR_DUTY_75_BACKWARD, to W
MOVWF MOTOR_TIMER_DESIRED ;
move MOTOR_DUTY_75_BACKWARD from W to MOTOR_TIMER_DESIRED
RETURN
SERVICE_MOTOR_TIMER:
BANKSEL PORTC ;
select port bank
INCF MOTOR_TIMER_COUNT, F ; increment
MOTOR_TIMER_COUNT
MOVF MOTOR_TIMER_COUNT, W ; move period
position to W
DECF MOTOR_TIMER_COUNT, F ; set
MOTOR_TIMER_COUNT back to what it should be
SUBWF MOTOR_TIMER_DESIRED,W ; subtract
MOTOR_TIMER_COUNTER from MOTOR_TIMER_DESIRED
BTFSC STATUS,C ;
skip if carry bit is 0 meaning skip if MOTOR_TIMER_COUNT =>
MOTOR_TIMER_DESIRED (b/c of inc before MOVF)
BSF MOTOR_PORT,MOTOR_PWM_PIN ; set the servo pin high
BTFSS STATUS,C ;
skip if zero bit is 1 meaning skip if MOTOR_TIMER_COUNT <
MOTOR_TIMER_DESIRED
BCF MOTOR_PORT,MOTOR_PWM_PIN ; set the
servo pin low
MOVF MOTOR_TIMER_COUNT,W ;
move period position to W
SUBLW MOTOR_TIMER_MAX ;
subtract W from MOTOR_TIMER_MAX
BTFSC STATUS,Z ;
skip if subtraction not equal to zero
GOTO RESET_MOTOR_TIMER_COUNT ; if
the subtraction is equal to zero, reset MOTOR_TIMER_COUNTER for new period
GOTO INCF_MOTOR_TIMER_COUNT ;
if the subtraction is non-zero then increment the MOTOR_TIMER_COUNTER
RESET_MOTOR_TIMER_COUNT:
CLRF MOTOR_TIMER_COUNT ; clear the
MOTOR_TIMER_COUNT
RETURN
INCF_MOTOR_TIMER_COUNT:
INCF MOTOR_TIMER_COUNT, F ; increment the
MOTOR_TIMER_COUNT
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RESPONSE CODE FOR PINGS ADMIRALS
AND ALL THAT BUSINESS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Ping Responses
SEND_PING_RESPONSE:
BANKSEL PIR1 ; select the
bank containing PIR1
MOVLW ADMIRAL_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB to W
MOVWF DEST_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB from W to DEST_ADDRESS_MSB
MOVLW ADMIRAL_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB to W
MOVWF DEST_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB from W to DEST_ADDRESS_LSB
MOVLW PING_RESPONSE_HEADER ; move the
PING_RESPONSE_HEADER to W
MOVWF TX_DATA_HEADER ; move the
PING_RESPONSE_HEADER from W to TX_DATA_HEADER
MOVF PING_RESPONSE_BYTE1, W ; move the PING_RESPONSE_BYTE1
to W
MOVWF TX_DATA_BYTE1 ; move the
PING_RESPONSE_BYTE1 from W to TX_DATA_BYTE1
MOVF PING_RESPONSE_BYTE2, W ; move the PING_RESPONSE_BYTE2
to W
MOVWF TX_DATA_BYTE2 ; move the
PING_RESPONSE_BYTE2 from W to TX_DATA_BYTE2
CALL TRANSMIT ;
transmit
BANKSEL PORTA ; select the
bank containing PORTA
BCF ACK_FLAG,
ADMIRAL_PING_BIT ; clear the
ping received from admiral flag
RETURN
; Ackowledgements
SEND_SOFT_RESET_ACKNOWLEDGEMENTS:
BANKSEL PIR1 ; select the
bank containing PIR1
MOVLW ADMIRAL_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB to W
MOVWF DEST_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB from W to DEST_ADDRESS_MSB
MOVLW ADMIRAL_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB to W
MOVWF DEST_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB from W to DEST_ADDRESS_LSB
MOVLW ACK_HEADER ; move
ACK_HEADER to W
MOVWF TX_DATA_HEADER ; move the
ACK_HEADER from W to TX_DATA_HEADER
MOVLW 0x00 ; move 0x00
to W
MOVWF TX_DATA_BYTE1 ; move 0x00
from W to TX_DATA_BYTE1
MOVLW SOFT_RESET ;
move SOFT_RESET to W
MOVWF TX_DATA_BYTE2 ; move
SOFT_RESET from W to TX_DATA_BYTE2
CALL TRANSMIT ;
transmit
BANKSEL PORTA ; select the
bank containing PORTA
BCF ACK_FLAG,
SOFT_RESET_BIT ; clear the soft reset
received flag
RETURN
SEND_STAND_DOWN_ACK_TO_ADMIRAL:
BANKSEL PIR1 ; select the
bank containing PIR1
MOVLW ADMIRAL_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB to W
MOVWF DEST_ADDRESS_MSB ; move the
ADMIRAL_ADDRESS_MSB from W to DEST_ADDRESS_MSB
MOVLW ADMIRAL_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB to W
MOVWF DEST_ADDRESS_LSB ; move the
ADMIRAL_ADDRESS_LSB from W to DEST_ADDRESS_LSB
MOVLW ACK_HEADER ; move
ACK_HEADER to W
MOVWF TX_DATA_HEADER ; move the
ACK_HEADER from W to TX_DATA_HEADER
MOVLW 0x00 ; move 0x00
to W
MOVWF TX_DATA_BYTE1 ; move 0x00
from W to TX_DATA_BYTE1
MOVLW STAND_DOWN ; move
STAND_DOWN to W
MOVWF TX_DATA_BYTE2 ; move
STAND_DOWN from W to TX_DATA_BYTE2
CALL TRANSMIT ;
transmit
BANKSEL PORTA ; select the
bank containing PORTA
BCF ACK_FLAG,
STAND_DOWN_BIT ; clear the
stand down received flag
RETURN
SEND_STAND_DOWN_TO_HELM:
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSS TRANSMIT_COUNTDOWN_FLAG, 0 ; check if the transmit count down has
been completed
RETURN ;
if it has not completed, do not proceed with transmission
CLRF TRANSMIT_COUNTDOWN_1 ; if it has completed, clear
the first count down timer
CLRF TRANSMIT_COUNTDOWN_2 ; clear the second count down
timer
CLRF TRANSMIT_COUNTDOWN_FLAG ; clear the count down
timer flag
BANKSEL PIR1 ; select the
bank containing PIR1
MOVF PAIRED_ADDRESS_MSB, W ; move the PAIRED_ADDRESS_MSB
to W
MOVWF DEST_ADDRESS_MSB ; move the
PAIRED_ADDRESS_MSB from W to DEST_ADDRESS_MSB
MOVF PAIRED_ADDRESS_LSB, W ; move the
PAIRED_ADDRESS_LSB to W
MOVWF DEST_ADDRESS_LSB ; move the
PAIRED_ADDRESS_LSB from W to DEST_ADDRESS_LSB
MOVLW WATERCRAFT_HEADER ;
move WATERCRAFT_HEADER to W
MOVWF TX_DATA_HEADER ; move the
WATERCRAFT_HEADER from W to TX_DATA_HEADER
MOVLW STAND_DOWN_RECEIVED_1 ; move STAND_DOWN_RECEIVED_1 to
W
MOVWF TX_DATA_BYTE1 ; move
STAND_DOWN_RECEIVED_1 from W to TX_DATA_BYTE1
MOVLW STAND_DOWN_RECEIVED_2 ; move STAND_DOWN_RECEIVED_2 to
W
MOVWF TX_DATA_BYTE2 ; move
STAND_DOWN_RECEIVED_2 from W to TX_DATA_BYTE2
CALL TRANSMIT ;
transmit
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; INTERRUPT SERVICE ROUTINES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ISR:
SAVE_REGISTERS:
BANKSEL PORTA ; select bank
containing PORTA
MOVWF W_TEMP ; copy pre-interrupt
contents of W to TEMP
SWAPF STATUS, W ;
swap STATUS register and save to W
MOVWF STATUS_TEMP ; save
contents of W to STATUS_TEMP
; INTERRUPT TYPE CHECK
CHECK_INTERRUPT_TYPE:
BANKSEL PIR1
BTFSC PIR1, RCIF ;
check if the receive interrupt flag has been set
GOTO RECEIVE ;
if the RCIE receive interrupt flag is set, run receive protocol
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSS PIR1, TMR2IF ;
check if the timer2 interrupt flag has been set
GOTO RESTORE_REGISTERS ; if timer2 has not
overflowed, restore the registers and break out of the ISR
CALL SERVICE_TRANSMIT_COUNTDOWN ; if it has overflowed, service the
transmit count down timers
GOTO SERVICE_BABYSIT ; service the
baby sit function
; RECEIVE
RECEIVE:
BANKSEL RCSTA ; select the
bank containing RCSTA
BTFSC RCSTA, OERR ;
check for overrun error
CALL CLEAR_OVERRUN_ERROR ; if overrun error occured,
go to CLEAR_OVERRUN_ERROR
MOVF RCREG, W ;
copy the RCREG register to W
BANKSEL PORTA ; select the
bank containing PORTA
MOVWF DATA_RECEIVED ; save the
content of w register to DATA_RECEIVED
MOVF RECEIVE_BYTE_COUNT,W ; move RECEIVED_BYTE_COUNT
to W
CALL RX_JUMP_TABLE ; call jump
table
BANKSEL PIR1 ; select the
bank containing PIR1
MOVF RECEIVE_BYTE_COUNT,F ; move
RECEIVED_BYTE_COUNT to itself
BTFSS STATUS, Z ;
check if bit Z is set, if it is set, then RECEIVED_BYTE_COUNT is zero
GOTO RESTORE_REGISTERS ; if bit Z is not
zero, restore registers and break out of the ISR
GOTO PROCESS ;
if the RECEIVE_BYTE_COUNT is 0 process the received data packet
PROCESS:
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSS HELM_MATCH_FLAG, 0 ; check if the boat has
matched with a helm
GOTO CHECK_FOR_IBUTTON_MATCH ; if no, check for
a broadcast with a matching iButton serial number
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSS HELM_MATCH_FLAG, 1 ; check if the boat has
received a no action command in response to its transmitted matched message
GOTO CHECK_FOR_NO_ACTION_MSG ; if no, check for a
no action message from the paired helm
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSC HELM_STAND_DOWN_RESPONSE,
0 ; check if a helm response to a stand
down is pending
CALL CHECK_STAND_DOWN_ACK ; if yes, check for the
acknoledgement from the helm
GOTO CHECK_IF_RESPONSE_REQUIRED ; if no, check if any other responses
are required
; STATUS CHECKS
CHECK_FOR_IBUTTON_MATCH:
BANKSEL PIR1
BTFSS RX_DATA_HEADER,
IBUTTON_HEADER_BIT ; check if the
RX_DATA_HEADER is an IBUTTON_HEADER
GOTO CHECK_IF_RESPONSE_REQUIRED ; if Z = 0, the
RX_DATA_HEADER is not an IBUTTON_HEADER, go back to waiting for the correct msg
type
MOVF RX_DATA_BYTE1, W ;
if Z = 1, the RX_DATA_HEADER is an IBUTTON_HEADER, check for an iButton serial
number match, move RX_DATA_BYTE1 to W
SUBWF IBUTTON_BYTE1, W ;
subtract RX_DATA_BYTE1 from IBUTTON_BYTE1
BTFSS STATUS, Z ;
check the Z bit of the status register
GOTO CHECK_IF_RESPONSE_REQUIRED ; if Z = 0, the
RX_DATA_BYTE1 is not IBUTTON_BYTE1, go back to waiting for the correct msg type
MOVF RX_DATA_BYTE2, W ;
if Z = 1, the RX_DATA_BYTE1 is IBUTTON_BYTE1, check IBUTTON_BYTE2, move
RX_DATA_BYTE2 to W
SUBWF IBUTTON_BYTE2, W ;
subtract RX_DATA_BYTE2 from IBUTTON_BYTE2
BTFSS STATUS, Z ;
check the Z bit of the status register
GOTO CHECK_IF_RESPONSE_REQUIRED ; if Z = 0, the
RX_DATA_BYTE2 is not IBUTTON_BYTE2, go back to waiting for the correct msg type
GOTO SAVE_PAIRED_ADDRESS ; if Z =
1, the RX_DATA_BYTE2 is IBUTTON_BYTE2, an iButton match has been found, save
source address and send matched msg
SAVE_PAIRED_ADDRESS:
BANKSEL PIR1 ; select the
bank containing PIR1
MOVF SOURCE_ADDRESS_MSB, W ; move the SOURCE_ADDRESS_MSB
to W
MOVWF PAIRED_ADDRESS_MSB ; save the
SOURCE_ADDRESS_MSB to PAIRED_ADDRESS_MSB
MOVF SOURCE_ADDRESS_LSB, W ; move the SOURCE_ADDRESS_LSB
to W
MOVWF PAIRED_ADDRESS_LSB ; save the
SOURCE_ADDRESS_LSB to PAIRED_ADDRESS_LSB
BSF HELM_MATCH_FLAG, 0 ; set the helm match
flag high to signify a sucessful pairing
GOTO CHECK_IF_RESPONSE_REQUIRED ; check if any other responses are
required
CHECK_FOR_NO_ACTION_MSG:
BANKSEL PIR1 ; select the
bank containing PIR1
MOVF SOURCE_ADDRESS_MSB, W ; move the source address msb
to W
SUBWF PAIRED_ADDRESS_MSB, W ; subtract the source address
msb from the paired address msb
BTFSS STATUS, Z ;
check if the Z bit of the status register is set
GOTO CHECK_IF_RESPONSE_REQUIRED ; if it is not set, the source and
paired addresses do not match, check if any other responses are required
MOVF SOURCE_ADDRESS_LSB, W ; if it is set, move the
source address lsb to W
SUBWF PAIRED_ADDRESS_LSB, W ; subtract the source
address lsb from the paired address lsb
BTFSS STATUS, Z ;
check if the Z bit of the status register is set
GOTO CHECK_IF_RESPONSE_REQUIRED ; if it is not set, the source and
paired addresses do not match, check if any other responses are required
BANKSEL PIR1 ; select the
bank containing PIR1
BTFSS RX_DATA_HEADER,
NAVIGATION_HEADER_BIT ; check if
RX_DATA_HEADER is a NAVIGATION_HEADER
GOTO CHECK_IF_RESPONSE_REQUIRED ; if Z = 0, the RX_DATA_HEADER is not a
NAVIGATION_HEADER, go back to waiting for the correct msg type
MOVF RX_DATA_BYTE1, W ; if Z = 1, the
RX_DATA_HEADER is a NAVIGATION_HEADER, check for the no action msg, move
RX_DATA_BYTE1 to W
SUBLW NO_ACTION_1 ;
subtract RX_DATA_BYTE1 from NO_ACTION_1
BTFSS STATUS, Z ;
check the Z bit of the status register
GOTO CHECK_IF_RESPONSE_REQUIRED ; if Z = 0, the RX_DATA_BYTE1 is not
NO_MATCH_1, go back to waiting for the correct msg type
MOVF RX_DATA_BYTE2, W ; if Z = 1, the
RX_DATA_BYTE1 is NO_ACTION_1, check for NO_ACTION_2, move RX_DATA_BYTE2 to W
SUBLW NO_ACTION_2 ;
subtract RX_DATA_BYTE2 from NO_ACTION_2
BTFSC STATUS, Z ;
check the Z bit of the status register
BSF HELM_MATCH_FLAG,
1
GOTO CHECK_IF_RESPONSE_REQUIRED ;
if Z = 0, the RX_DATA_BYTE2 is not NO_ACTION_2, go back to waiting for the
correct msg type
CHECK_STAND_DOWN_ACK:
BANKSEL PORTA ; select the
bank containing PORTA
MOVF SOURCE_ADDRESS_MSB, W ; move the source address msb
to W
SUBWF PAIRED_ADDRESS_MSB, W ; subtract the source address
from the paired address msb
BTFSS STATUS, Z ;
check to see if they match
RETURN ;
if they do not match, no stand down ack was received, return
MOVF SOURCE_ADDRESS_LSB, W ; if they do match, move the
source address lsb to W
SUBWF PAIRED_ADDRESS_LSB, W ; subtract the source
address from the paired address lsb
BTFSS STATUS, Z ;
check to see if they match
RETURN ;
if they do not match, no stand down ack was received, return
BTFSS RX_DATA_HEADER, ACK_HEADER_BIT ; if they do match, check if RX_DATA_HEADER is
a ACK_HEADER
RETURN ;
if Z = 0, the RX_DATA_HEADER is not an ACK_HEADER, go back to waiting for the
correct msg type
MOVF RX_DATA_BYTE1, W ; if Z = 1, the
RX_DATA_HEADER is an ACK_HEADER, check for the no action msg, move
RX_DATA_BYTE1 to W
SUBLW STAND_DOWN_RECEIVED_1 ; subtract RX_DATA_BYTE1 from
STAND_DOWN_RECEIVED_1
BTFSS STATUS, Z ;
check the Z bit of the status register
RETURN ;
if Z = 0, the RX_DATA_BYTE1 is not STAND_DOWN_RECEVIED_1, go back to waiting
for the correct msg type
MOVF RX_DATA_BYTE2, W ; if Z = 1, the
RX_DATA_BYTE1 is STAND_DOWN_RECEIVED_1, check for STAND_DOWN_RECEIVED_2, move
RX_DATA_BYTE2 to W
SUBLW STAND_DOWN_RECEIVED_2 ; subtract RX_DATA_BYTE2 from
STAND_DOWN_RECEIVED_2
BTFSC STATUS, Z ;
check the Z bit of the status register
BCF HELM_STAND_DOWN_RESPONSE,
0 ; if Z = 1, the RX_DATA_BYTE2 is
STAND_DOWN_RECEIVED_2, the stand down ack has been received from the helm
RETURN ;
if Z = 0, the RX_DATA_BYTE2 is not STAND_DOWN_RECEIVED_2, go back to waiting
for the correct msg type
; MESSAGE
RESPONSE CHECKS
CHECK_IF_RESPONSE_REQUIRED:
BANKSEL PORTA ; select the
bank containing PORTA
MOVF SOURCE_ADDRESS_MSB, W ; move the source address msb
to W
SUBWF PAIRED_ADDRESS_MSB, W ; subtract the source address
msb from the paired address msb to W
BTFSS STATUS, Z ;
check if they match
GOTO CHECK_IF_ADMIRAL_MSG ; if they do not match, the
message was not from the helm, check if it was from the admiral
MOVF SOURCE_ADDRESS_LSB, W ; if they do match, move the
source address lsb to W
SUBWF PAIRED_ADDRESS_LSB, W ; subtract the source
address lsb from the paired address lsb
BTFSS STATUS, Z ;
check if they match
GOTO CHECK_IF_ADMIRAL_MSG ; if they don't match, the
message was not from the helm, check if it was from the admiral
BANKSEL PORTA ; select the
bank containing PORTA
BCF RX_BABYSIT,
RX_BABYSIT_BIT ; clear the 3
sec babysit flag since a message was received from the helm
GOTO CHECK_IF_ADMIRAL_MSG ; check if the message was
from the admiral
;
BOAT will only have to send responses to the ADMIRAL
CHECK_IF_ADMIRAL_MSG:
BANKSEL PORTA ; select the
bank containing PORTA
MOVF SOURCE_ADDRESS_MSB, W ; move the source address msb
to W
SUBLW ADMIRAL_ADDRESS_MSB ; subtract the source
address msb from the admiral address msb
BTFSS STATUS, Z ;
check to see if they match
GOTO RESTORE_REGISTERS ; if they don't
match then the message is not from the admiral, restore registers and break out
of the ISR
MOVF SOURCE_ADDRESS_LSB, W ; if they do match, move the
source address lsb to W
SUBLW ADMIRAL_ADDRESS_LSB ; subtract the source
address lsb from the admiral address lsb
BTFSS STATUS, Z ;
check if they match
GOTO RESTORE_REGISTERS ; if they do not
match then the message is not from the admiral, restore registers and break out
of the ISR
BTFSS RX_DATA_HEADER,
ADMIRAL_HEADER_BIT ; if they do
match, check if the RX_DATA_HEADER is an ADMIRAL_HEADER
GOTO RESTORE_REGISTERS ; if the admiral
header bit is 0, the received data is not from the admiral, no response
required
GOTO DETERMINE_RESPONSE_TYPE ; if the message
is indeed from the admiral, determine what response is necessary
DETERMINE_RESPONSE_TYPE:
BANKSEL PORTA
BTFSS HELM_MATCH_FLAG, 0
GOTO PING_AND_HARD_RESET_ONLY
BTFSS HELM_MATCH_FLAG, 1
GOTO PING_AND_HARD_RESET_ONLY
BTFSC RX_DATA_BYTE2,
STAND_DOWN_BIT ; if the
ADMIRAL_PING_BIT is clear, check if the RX_DATA_BYTE2 is a stand down command
GOTO RESPOND_TO_STAND_DOWN ;
if a stand down command was sent, respond accordingly
BTFSC RX_DATA_BYTE2,
SOFT_RESET_BIT
GOTO RESPOND_TO_SOFT_RESET
PING_AND_HARD_RESET_ONLY:
BTFSC RX_DATA_BYTE2,
ADMIRAL_PING_BIT ; check
if the RX_DATA_BYTE2 is a ping from the admiral
GOTO RESPOND_TO_PING ;
if the ADMIRAL_PING_BIT is set, a ping was sent from teh admiral, respond
accordingly
BTFSC RX_DATA_BYTE2,
HARD_RESET_BIT
GOTO RESPOND_TO_HARD_RESET
GOTO RESTORE_REGISTERS ; if
neither a ping nor a stand down command were sent, restore registers
RESPOND_TO_PING:
BANKSEL PORTC
BSF ACK_FLAG,
ADMIRAL_PING_BIT
GOTO RESTORE_REGISTERS
RESPOND_TO_STAND_DOWN:
BANKSEL PORTA
MOVLW NO_ACTION_NAVIGATION
MOVWF NAVIGATION_BYTE
MOVLW NO_ACTION_SPECIAL
MOVWF SPECIAL_BYTE
BSF ACK_FLAG,
STAND_DOWN_BIT ; set the stand
down flag high
NOP
BSF HELM_STAND_DOWN_RESPONSE,
0
GOTO RESTORE_REGISTERS
RESPOND_TO_SOFT_RESET:
BANKSEL PORTA
MOVLW NO_ACTION_NAVIGATION
MOVWF NAVIGATION_BYTE
MOVLW NO_ACTION_SPECIAL
MOVWF SPECIAL_BYTE
BSF ACK_FLAG,
SOFT_RESET_BIT
GOTO RESTORE_REGISTERS
RESPOND_TO_HARD_RESET:
BANKSEL PORTA
MOVLW NO_ACTION_NAVIGATION
MOVWF NAVIGATION_BYTE
MOVLW NO_ACTION_SPECIAL
MOVWF SPECIAL_BYTE
BSF ACK_FLAG,
HARD_RESET_BIT
GOTO RESTORE_REGISTERS
SERVICE_TRANSMIT_COUNTDOWN:
BANKSEL PIR1
INCF TRANSMIT_COUNTDOWN_1, F
MOVF TRANSMIT_COUNTDOWN_1, W
SUBLW TRANSMIT_COUNTDOWN_TO_20MS_1
BTFSS STATUS, Z
RETURN
CLRF TRANSMIT_COUNTDOWN_1
INCF TRANSMIT_COUNTDOWN_2, F
MOVF TRANSMIT_COUNTDOWN_2, W
SUBLW TRANSMIT_COUNTDOWN_TO_20MS_2
BTFSS STATUS, Z
RETURN
BSF TRANSMIT_COUNTDOWN_FLAG,
0
MOVF TRANSMIT_COUNTDOWN_2, W
SUBLW 3
BTFSC STATUS, Z
CLRF TRANSMIT_COUNTDOWN_2
RETURN
SERVICE_BABYSIT:
BANKSEL PIR1
INCF THREE_SEC_COUNTER_LOW, F ; increment the three second
counter low byte
BTFSC STATUS,Z ;
if there is rollover
INCF THREE_SEC_COUNTER_HIGH,
F ; increment the three second
counter high byte
MOVF THREE_SEC_COUNTER_HIGH,W ; move the high byte to W
SUBLW NUM_TICKS_3SEC_HIGH ;
subtract the desired number from W
BTFSC STATUS,Z ;
if there is a match
GOTO CHECK_LOW_BABYSIT ;
check the low byte
GOTO SERVO_CONTROL ;
otherwise go to servo control
CHECK_LOW_BABYSIT:
BANKSEL PIR1
MOVF THREE_SEC_COUNTER_LOW,W ; move the low byte
to W
SUBLW NUM_TICKS_3SEC_LOW ;
subtract the desired number from W
BTFSS STATUS,Z ;
if there is no match
GOTO SERVO_CONTROL ;
go to servo control
CLRF THREE_SEC_COUNTER_HIGH ; clear high
byte of counter
CLRF THREE_SEC_COUNTER_LOW ; clear low byte of counter
BTFSS RX_BABYSIT,RX_BABYSIT_BIT ; if the babysit bit is low (we
have received in the last 3 sec)
GOTO RESET_BABYSIT ;
reset babysit
MOVLW NO_ACTION_NAVIGATION ; move No action byte to W
MOVWF NAVIGATION_BYTE ;
Set NAVIGATION_BYTE to no action
MOVLW NO_ACTION_SPECIAL ;
move NO action byte to W
MOVWF SPECIAL_BYTE ;
Set SPECIAL_BYTE to no action
MOVWF RX_DATA_HEADER
GOTO RESET_BABYSIT
RESET_BABYSIT:
BANKSEL PIR1
BSF RX_BABYSIT,RX_BABYSIT_BIT
GOTO SERVO_CONTROL
; NAVIGATION CONTROL
SERVO_CONTROL: ;
TO BE IMPLEMENTED AS ISR
CALL SERVICE_SERVO_DIRECTION ; service the servo
CALL SERVICE_SERVO_TIMER
GOTO MOTOR_CONTROL
MOTOR_CONTROL: ;
TO BE IMPLEMENTED AS ISR
CALL SERVICE_MOTOR_DIRECTION
CALL SERVICE_MOTOR_TIMER
GOTO RESET_TMR2IF
RESET_TMR2IF:
BANKSEL PIR1
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
GOTO RESTORE_REGISTERS
RESTORE_REGISTERS:
CLRF DATA_RECEIVED ; clear
DATA_RECEIVED
SWAPF STATUS_TEMP, W ; swap nibbles
in STATUS_TEMP register and save in W
MOVWF STATUS ;
restore pre-interrupt STATUS register
SWAPF W_TEMP, F ;
swap nibbles in W_TEMP and save results in W_TEMP
SWAPF W_TEMP, W ;
swap nibbles in W_TEMP and save results in W_TEMP
RETFIE ;
return to interrupted code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TRANSMIT ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TRANSMIT:
CALL CALCULATE_CHECKSUM
; start
sending the data packet
; send
START_BYTE
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW START_BYTE
CALL TRANSMIT_BYTE
; send
LENGTH_MSB
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW LENGTH_MSB ;
0x00
CALL TRANSMIT_BYTE
; send
LENGTH_LSB
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW LENGTH_LSB ;
0x08
CALL TRANSMIT_BYTE
; send API_TX
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW API_TX ;
0x01
CALL TRANSMIT_BYTE
; send
FRAME_ID
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW FRAME_ID ;
0x00
CALL TRANSMIT_BYTE
; send
ADDRESS_MSB
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF DEST_ADDRESS_MSB,W
CALL TRANSMIT_BYTE
; send
ADDRESS_LSB
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF DEST_ADDRESS_LSB,W
CALL TRANSMIT_BYTE
; send
OPTIONS
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVLW OPTIONS ;
0x01
CALL TRANSMIT_BYTE
; send
TX_DATA_HEADER
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF TX_DATA_HEADER,W
CALL TRANSMIT_BYTE
; send
TX_DATA_BYTE1
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF TX_DATA_BYTE1,W
CALL TRANSMIT_BYTE
; send
TX_DATA_BYTE2
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF TX_DATA_BYTE2,W
CALL TRANSMIT_BYTE
; send
CHECKSUM
CALL WAIT_FOR_TSR_EMPTY
BANKSEL PORTA
MOVF CHECKSUM,W
CALL TRANSMIT_BYTE
RETURN
CALCULATE_CHECKSUM:
BANKSEL PORTA
MOVLW FRAME_ID ;
Frame ID (Byte5)
ADDLW API_TX
ADDWF DEST_ADDRESS_MSB, W ; add destination address
MSB (Byte 6)
NOP
ADDWF DEST_ADDRESS_LSB, W ; add destination
address LSM (Byte 7)
NOP
ADDLW OPTIONS ;
add options ACK enabled (Byte 8)
NOP
ADDWF TX_DATA_HEADER,W ; add TX Data Byte
0 of 3 (Byte 11)
NOP
ADDWF TX_DATA_BYTE1, W ; add TX Data
Byte 1 of 3 (Byte 10)
NOP
ADDWF TX_DATA_BYTE2, W ; add TX Data
Byte 2 of 3 (Byte 9)
NOP
SUBLW 0xFF ;
subtract the last 8 bits of the resulting sum from 0xFF
MOVWF CHECKSUM
RETURN
WAIT_FOR_TSR_EMPTY:
BANKSEL TXSTA
BTFSS TXSTA, TRMT
GOTO WAIT_FOR_TSR_EMPTY
RETURN
TRANSMIT_BYTE:
BANKSEL
TXREG
MOVWF TXREG
RETURN
CLEAR_OVERRUN_ERROR:
BANKSEL RCSTA
BCF RCSTA,
CREN ;
disable receive
NOP
BSF RCSTA,
CREN ;
re-enable receive to clear the overrun error
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; JUMP TABLE FOR RECEIVING
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; discard
start byte
Case0:
BANKSEL PORTA ;
select the bank containing PORTA
MOVF DATA_RECEIVED, W ; move
DATA_RECEIVED to W
SUBLW START_BYTE ;
subtract W from START_BYTE
BTFSS STATUS, Z ;
test bit Z of STATUS register
GOTO Error_Detected ; if Z =
0, received data is not START_BYTE, deal with error
INCF RECEIVE_BYTE_COUNT, F ; if Z = 1, received data is START_BYTE,
increment the RECEIVE_BYTE_COUNT and look for the LENGTH_MSB
RETURN
; discard
length MSB byte
Case1:
BANKSEL PORTA ;
select the bank containing PORTA
MOVF DATA_RECEIVED, W ; move
DATA_RECEIVED to W
SUBLW LENGTH_MSB ;
subtract W from LENGTH_MSB
BTFSS STATUS, Z ;
test bit Z of STATUS register
GOTO Error_Detected ; if Z =
0, received data is not START_BYTE, deal with error
INCF RECEIVE_BYTE_COUNT, F ; if Z = 1, received data is LENGTH_MSB,
increment the RECEIVE_BYTE_COUNT and look for the LENGTH_MSB
RETURN
; discard
length LSB byte
Case2:
BANKSEL PORTA ;
select the bank containing PORTA
MOVF DATA_RECEIVED, W ; move
DATA_RECEIVED to W
SUBLW LENGTH_LSB ;
subtract W from LENGTH_LSB
BTFSS STATUS, Z ;
test bit Z of STATUS register
GOTO Error_Detected ; if Z =
0, received data is not START_BYTE, deal with error
INCF RECEIVE_BYTE_COUNT, F ; if Z = 1, received data is LENGTH_LSB,
increment the RECEIVE_BYTE_COUNT and look for the LENGTH_MSB
RETURN
; discard API
ID byte
Case3:
BANKSEL PORTA ;
select the bank containing PORTA
MOVF DATA_RECEIVED, W ; move
DATA_RECEIVED to W
SUBLW API_RX ;
subtract W from API_RX
BTFSS STATUS, Z ;
test bit Z of STATUS register
GOTO Error_Detected ; if Z =
0, received data is not START_BYTE, deal with error
INCF RECEIVE_BYTE_COUNT, F ; if Z = 1, received data is API_ID,
increment the RECEIVE_BYTE_COUNT and look for the LENGTH_MSB
RETURN
; save source
address MSB byte
Case4:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
MOVF DATA_RECEIVED, W
MOVWF SOURCE_ADDRESS_MSB
RETURN
; save source
address LSB byte
Case5:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
MOVF DATA_RECEIVED, W
MOVWF SOURCE_ADDRESS_LSB
RETURN
; discard
RSSI byte
Case6:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
RETURN
; discard
Options byte
Case7:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
RETURN
; save RF
data header byte
Case8:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
MOVF DATA_RECEIVED, W
MOVWF RX_DATA_HEADER
RETURN
Case9:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
MOVF DATA_RECEIVED, W
MOVWF RX_DATA_BYTE1
RETURN
Case10:
BANKSEL PORTA ;
select the bank containing PORTA
INCF RECEIVE_BYTE_COUNT, F
MOVF DATA_RECEIVED, W
MOVWF RX_DATA_BYTE2
RETURN
; discard
checksum byte
Case11:
BANKSEL PORTA ;
select the bank containing PORTA
CLRF RECEIVE_BYTE_COUNT
RETURN
Error_Detected:
BANKSEL PORTA ;
select the bank containing PORTA
CLRF RECEIVE_BYTE_COUNT
RETURN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; CHECK FOR IBUTTON SUBROUNTINES
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IBUTTON_PIN_TO_OUTPUT:
BANKSEL TRISB ;
select bank containing TRISB
MOVLW IBUTTON_TRIS_OUTPUT ; write iButton tris
output bits to W
ANDWF TRISB, f ;
set the iButton pin to output
RETURN ;
return to line after subroutine was called
IBUTTON_PIN_TO_INPUT:
BANKSEL TRISB ;
select bank containing TRISB
MOVLW IBUTTON_TRIS_INPUT ; write iButton tris
input bits to W
IORWF TRISB, f ;
set the iButton pin to input
RETURN ;
return to line after subroutine was called
SEND_READ_ROM_BIT_HIGH:
CALL IBUTTON_PIN_TO_OUTPUT ; set iButton pin to output
BANKSEL PORTB
BCF PORTB,
IBUTTON_BIT ;
set iButton pin low
CALL WAIT_5US ;
wait 5us
CALL IBUTTON_PIN_TO_INPUT ; set iButton pin to input
CALL WAIT_70US ;
wait 70us
RETURN ;
return to line after subroutine was called
SEND_READ_ROM_BIT_LOW:
CALL IBUTTON_PIN_TO_OUTPUT ; set iButton pin to output
BANKSEL PORTB
BCF PORTB,
IBUTTON_BIT ;
set iButton pin low
CALL WAIT_60US ;
wait 60us
CALL IBUTTON_PIN_TO_INPUT ; set iButton pin to input
CALL WAIT_15US ;
wait 15us
RETURN ;
return to line after subroutine was called
READ_IBUTTON:
CALL IBUTTON_PIN_TO_OUTPUT ; set iButton pin to output
BANKSEL PORTB
BCF PORTB,
IBUTTON_BIT ;
set iButton pin low
CALL WAIT_5US ;
wait 5us
CALL IBUTTON_PIN_TO_INPUT ; set iBUTTON pin to input
CALL WAIT_10US ;
wait 10us
BANKSEL PORTB
BTFSC PORTB, IBUTTON_BIT ; if bit1 is set,
check if the iButton pin is high
GOTO IBUTTON_HIGH ; if the
incoming bit is high deal with it
GOTO IBUTTON_LOW ;
if the incoming bit is low deal with it
IBUTTON_HIGH:
BANKSEL PORTB
CLRW ;
clear W
MOVF READ_BIT_COUNTER,W ; move the read bit
counter to W
BTFSC READ_BYTE_COUNTER,0 ; check if we are reading
byte 0
GOTO WRITE_TO_IBUTTON_BYTE0 ; write the high to iButton byte 0
BTFSC READ_BYTE_COUNTER,1 ; check if we are reading
byte 1
GOTO WRITE_TO_IBUTTON_BYTE1 ; write the high to iButton byte 1
BTFSC READ_BYTE_COUNTER,2 ; check if we are reading
byte 2
GOTO WRITE_TO_IBUTTON_BYTE2 ; write the high to iButton byte 2
IBUTTON_LOW:
BANKSEL PORTB
CALL WAIT_60US ;
wait 60us
RETURN ;
return to line after the subroutine was called
WRITE_TO_IBUTTON_BYTE0:
IORWF IBUTTON_BYTE0, f ; or W with iButton byte 0 to
record the high
CALL WAIT_60US ;
wait 60us
RETURN ;
return to line after the subroutine was called
WRITE_TO_IBUTTON_BYTE1:
IORWF IBUTTON_BYTE1, f ; or W with iButton byte 1 to
record the high
CALL WAIT_60US ;
wait 60us
RETURN ;
return to line after the subroutine was called
WRITE_TO_IBUTTON_BYTE2:
IORWF IBUTTON_BYTE2, f ; or W with iButton byte 2 to
record the high
CALL WAIT_60US ;
wait 60us
RETURN ;
return to line after the subroutine was called
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WAIT COMMANDS FOR IBUTTON ROUTINE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
WAIT_5US:
NOP ;
wait for 5us
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
RETURN ;
return to line after subroutine was called
WAIT_10US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'00011101' ;
d'29'
MOVWF PR2 ; move 00110001 from W to
PR2 (Timer 2 Flag set every 1/5MHz * (49+1)ticks = 10us)
BANKSEL PIR1 ; select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
RETURN ;
return to line after subroutine was called
WAIT_15US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'00110110' ;
d'54'
MOVWF PR2 ; move 01001010 from W to
PR2 (Timer 2 Flag set every 1/5MHz * (74+1)ticks = 15us)
BANKSEL PIR1 ; select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
RETURN ;
return to line after subroutine was called
WAIT_50US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'11100101' ;
d'229'
MOVWF PR2 ; move 11111001 from W to
PR2 (Timer 2 Flag set every 1/5MHz * (249+1)ticks = 50us)
BANKSEL PIR1 ; select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
RETURN ;
return to line after subroutine was called
WAIT_60US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
MOVLW b'00001000' ;
move 00001000 to W
IORWF T2CON, F ;
or W with T2CON to set TOUTPS1-3 to 0001 and postscale timer 2 by 1:2, timer
effectively at 2.5MHz
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'10001011' ;
d'139
MOVWF PR2 ; move 10010110 from W to
PR2 (Timer 2 Flag set every 1/2.5MHz * (149+1)ticks = 60us)
BANKSEL PIR1 ; select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1, TMR2IF ;
clear the Timer 2 flag
MOVLW b'00000111' ;
move 00000111 to W
ANDWF T2CON, F ;
and W with TSCON to set TOUTPS1-3 to 0000 and postscale timer 2 by 1:1
RETURN ;
return to line after subroutine was called
WAIT_70US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
MOVLW b'00001000' ;
move 00001000 to W
IORWF T2CON, F ;
or W with T2CON to set TOUTPS1-3 to 1001 and postscale timer 2 by 1:2, timer
effectively at 2.5MHz
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'10100100' ;
d'164'
MOVWF PR2 ; move 10101110 from W to
PR2 (Timer 2 Flag set every 1/2.5MHz * (174+1)ticks = 70us)
BANKSEL PIR1 ; select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
MOVLW b'00000111' ;
move 00000111 to W
ANDWF T2CON, F ;
and W with TSCON to set TOUTPS1-3 to 0000 and postscale timer 2 by 1:1
RETURN ;
return to line after subroutine was called
WAIT_500US:
BANKSEL TMR2 ;
select the bank containing TMR2
CLRF TMR2 ;
clear the timer TMR2
MOVLW b'01001000' ;
move 01001000 to W
IORWF T2CON, F ;
or W with T2CON to set TOUTPS1-3 to 1001 and postscale timer 2 by 1:10, timer
effectively at 500kHz
BANKSEL PR2 ;
select the bank containing PR2
MOVLW b'11110111' ;
d'247'
MOVWF PR2 ; move 11111001 from W to
PR2 (Timer 2 Flag set every 1/500kHz * (249+1)ticks = 500us)
BANKSEL PIR1 ;
select bank containing PIR1
BTFSS PIR1, TMR2IF ; check if Timer 2 flag is set
GOTO $-1 ;
if clear, check again if Timer 2 flag is set
BCF PIR1,
TMR2IF ;
clear the Timer 2 flag
MOVLW b'00000111' ;
move 00000111 to W
ANDWF T2CON, F ;
and W with TSCON to set TOUTPS1-3 to 0000 and postscale timer 2 by 1:1
RETURN ;
return to line after subroutine was called
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; END THE PROGRAM!!!!
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END