;********************************************************************************

;* Robot Control Code *

;* using PIC16F84 *

;* *

;* Version 1.0 *

;* by Nautilus Robotics *

;* 2001.1.23 *

; *

; PB.0-PB.3 are motor outputs. *

; (+12v dc, four-phase, unipolar, permanent magnet, 1.8 per step) *

; *

; PA4 is input for Photo IC *

; *

; *

;********************************************************************************

 

;********************************************************************************

;* Processor definition and configuration *

;********************************************************************************

; Clock = 4MHz XT

 

LIST P=16F84, F=INHX8M

#include "P16F84.inc"

__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON

 

 

 

#define PHOTO PORTB,7 ; RB7, pin 13, Photo IC input

#define SCORE PORTB,6 ; RB6, pin 12, output to score board

#define FIRE PORTB,5 ; RB5, pin 11, FIRE LED (high = fire)

#define IR_EN PORTB,4 ; RB4, pin 10, IR transmitter enable

 

#define ZERO PORTA,4 ; the zeroing pin (normally high)

; - goes low when pin touches

 

#define FORWARD 0x09 ; RS-> 10xx; LS-> xx01; RS<- 01xx; LS<- xx10

#define BACK 0x06

#define LEFT 0x0A

#define RIGHT 0x05

 

#define RS_FOR 0x08 ; Right side wheels forward, etc...

#define LS_FOR 0x01

#define RS_REV 0x04

#define LS_REV 0x02

 

;********************************************************************************

;Special Registers *

;********************************************************************************

TMR0 equ 0x01

STATUS equ 0x03

PORTA equ 0x05

PORTB equ 0x06

INTCON equ 0x0b

OptionR equ 0x81

TRISA equ 0x85

TRISB equ 0x86

 

;********************************************************************************

;* Define RAM *

;********************************************************************************

CNTR1 equ 0x0c

CNTR2 equ 0x0d

ANGL equ 0x0e

DRTN equ 0x0f

TEMP equ 0x10

COUNT equ 0x11 ; used in counting values of samples received

LOOPCNT equ 0x12

HIGH_S equ 0x13

LOW_S equ 0x14

S_CNT equ 0x15

LEFT_M equ 0x16

RIGHT_M equ 0x17

L_CNT1 equ 0x18

L_CNT2 equ 0x19

MOTOR equ 0x1A ; used as a flag and also a temp variable when setting the motor directions

SIGHT equ 0x1B ; used to flag if we have a sighting at the current stepper angle

 

;********************************************************************************

;* Define flags and bits *

;********************************************************************************

W equ 0 ; Working Register

F equ 1 ; File Register

Z equ 2 ; Z bit of the Status Register

 

;********************************************************************************

;* INIT subroutine, set port directions & options *

;********************************************************************************

org 0x00

 

clrf PORTA ; Initialize PortA

bsf STATUS, RP0 ; Select Bank 1

movlw 0x10 ; Set I/O

movwf TRISA

bcf STATUS, RP0 ; return to Bank 0

movlw 0xFF ; Initialize PortB

movwf PORTB

 

bsf STATUS, RP0 ; Select Bank 1

 

bcf TRISB, 0 ; STEPPER output 1

bcf TRISB, 1 ; STEPPER output 2

bcf TRISB, 2 ; STEPPER output 3

bcf TRISB, 3 ; STEPPER output 4

bcf TRISB, 4 ; IR_EN output

bcf TRISB, 5 ; FIRE output

bcf TRISB, 6 ; SCORE output

bsf TRISB, 7 ; PHOTO input

 

; movlw 0x80 ; Set I/O

; movwf TRISB

bsf OPTION_REG, 7 ; disable internal pullups

bcf STATUS, RP0 ; return to Bank 0

 

clrf INTCON ; disable interupts

 

;********************************************************************************

;* Start of Program *

;********************************************************************************

START clrf PORTB

clrf DRTN ; unnecessary

clrf ANGL ; initialize to 0

; call DELAY ; allow power to stabilize

movlw 0x03

movwf PORTB

 

bsf IR_EN ; set the IR enable pin high

 

Z_LOOP call CCW

call PAUSE ; short delay (10ms)

btfsc ZERO ; break out of loop when pin hits zero

goto Z_LOOP

 

movlw .28 ; start the stepper motor centered

movwf ANGL

 

 

;********************************************************************************

;* Mainline of Stepper motor control *

;********************************************************************************

MAIN call STEP ; move the stepper

clrf SIGHT ; clear the sighting flag

call SEARCH ; listen for input. Execute a null loop if sighting gets set

goto MAIN

 

;********************************************************************************

;* STEP subroutine *

;********************************************************************************

; 200 steps per full rotation

; ANGL = 28 is limit of CCW rotation

; ANGL = 228 is limit of CW rotation

; DRTN = 1 means go CW

; DRTN = 0 means go CCW

 

STEP movlw .28 ; full motor rotation

xorwf ANGL, W ; test if angle is 28, result in W

btfsc STATUS, Z ; skip next instruction if result was not 0

bsf DRTN, 0 ; set direction to 1

 

movlw .228 ; full motor rotation

xorwf ANGL, W ; test if angle is 228, result in W

btfsc STATUS, Z ; skip next instruction if result was not 0

bcf DRTN, 0 ; set direction to 0

clrw

xorwf DRTN, W

btfss STATUS, Z ; skip if DRTN is 0

goto GO_CW

goto GO_CCW

 

GO_CW incf ANGL, F

call CW ; turn clockwise

return

 

GO_CCW decf ANGL, F

call CCW ; turn counter-clockwise

return

 

;********************************************************************************

;* CW subrouting *

;********************************************************************************

; step motor one step CW by shifting the contents of the lower

; nibble of Port B, leaving the upper nibble unchanged.

 

CW movf PORTB,W

movwf TEMP ; move contents of Port B into TEMP.

rlf TEMP, F ; shift bits left.

bcf TEMP, 0 ; clear bit 0 of TEMP.

btfsc TEMP, 4 ; check what is in bit 4 after shift,

bsf TEMP, 0 ; if bit is 1, set bit 0, else leave it 0

movlw 0x0F

andwf TEMP,F ; mask TEMP (ignore upper nibble)

 

movf PORTB,W ; get current contents of Port B

andlw 0xF0 ; mask Port B (to keep original upper nibble)

iorwf TEMP,W ; upper nibble remains unchanged

movwf PORTB ; only lower nibble is shifted

 

return

 

;********************************************************************************

;* CCW subrouting *

;********************************************************************************

; step motor one step CCW by shifting the contents of the lower

; nibble of Port B, leaving the upper nibble unchanged.

 

CCW movf PORTB,W ; get contents of Port B

andlw 0x0F ; mask contents

movwf TEMP ; move masked contents into TEMP

btfsc TEMP,0 ; check first bit before shifting

bsf TEMP,4 ; if first bit 0, set bit 4

rrf TEMP, F ; shift bits right

movlw 0x0F

andwf TEMP,F ; mask out upper nibble

 

movf PORTB,W ; get current contents of Port B

andlw 0xF0 ; mask out lower nibble

iorwf TEMP,W ; keep upper nibble, replace lower with shifted

movwf PORTB ; only lower nibble is shifted

 

return

;********************************************************************************

;* SEARCH subroutine *

;********************************************************************************

SEARCH movlw 0xFF ; execute the following 20us of code 400 times (=8ms).

movwf CNTR2 ; This will sample 20 bits, thus 1 or 2 complete bytes

; will be sampled after waiting for the start bit

clrf COUNT ; clear count when starting with this code each time

; to avoid problems when hopping to stepper code

clrf MOTOR ; reset the motor-run flag

 

LOOP_2

btfss MOTOR, 0 ; test the motor flag - only run the motor once per step

call LISTEN ; this plus the following delay must be 40us

 

btfsc SIGHT, 0 ; sight is set to 1 if we saw a hit at this angle. Skip the

return ; listening phase if this has occured

movlw .1 ; execute the following delay 1 times (total 5us)

movwf CNTR1

 

LOOP_1 nop

nop

decfsz CNTR1, F

goto LOOP_1 ; this is a 5us delay loop

 

decfsz CNTR2, F

goto LOOP_2 ; this loop will exit after 8000us

 

return

; END SEARCH

 

LISTEN ; this counts consecutive TRUE samples to listen for start bit

; it called PROCESS once the start bit is received

bcf SCORE ; clear output to start so we can see discrete pulses

 

incf COUNT, F

btfsc PHOTO ; exec next instr if a high (no signal) is received

clrf COUNT ; no TRUE sample was received - reset COUNT to 0.

 

movf COUNT, W

xorlw .18 ; test if we have received 18 TRUE samples since last FALSE.

 

btfsc STATUS, Z

call PROCESS ; 18 TRUE samples -> start bit received

 

return

;END LISTEN

 

 

PROCESS ; this function gets called after a start bit is seen

bcf SCORE ; clear output now for testing (should already be clear)

call SKIP ; end of start bit (double true)

call SKIP ; bit boundary

call SKIP ; start of double false bit

 

call SAMPLE ; looking for LOW (1/2)

btfss LOW_S, 0

return

 

call SKIP

call SKIP

call SKIP

 

call SAMPLE ; looking for LOW (2/2)

btfss LOW_S, 0

return

 

call SKIP

call SKIP

call SKIP

 

call SAMPLE ; looking at DATA1 - this is the robot ID bit

btfss LOW_S, 0

return

 

call SKIP

call SKIP

call SKIP

 

call SAMPLE ; looking at LOW after data1

btfss LOW_S, 0

return

 

call SKIP

call SKIP

call SKIP

 

call SAMPLE ; looking at DATA2 - this is the sig/fire bit

btfsc HIGH_S, 0 ; if we receive a high here we are hit

call WAS_HIT

 

btfss LOW_S, 0 ; extra test - just to be sure a true low was still received

return

 

call SKIP

call SKIP

call SKIP

 

call SAMPLE ; looking at LOW after data2

btfss LOW_S, 0

return

 

; we reach the following code if a signal was successfully received...

 

bsf SIGHT, 0 ; set the sighting flag true

 

 

; test if the signal came from the left or right hemisphere

movf ANGL, W ; check the angle of the stepper

andlw 0x80 ; grab only MSB

xorlw 0x80 ; set Z if MSB is '1' (ie we are right of center)

btfsc STATUS, Z

movlw RIGHT ; drive left side to turn right

btfss STATUS, Z

movlw LEFT ; drive right side to turn left

 

movwf MOTOR ; store this partial setting; overwrite later if straight

 

; test if close to straight just left of center

movf ANGL, W

xorlw 0x70 ; look for 1000xxxx -> change it to 1111xxxx

andlw 0xF0 ; mask the 4 bits we are looking at

xorlw 0xF0 ; test the top 4 bits and set Z if true

btfsc STATUS, Z

call SET_FOR ; set both motors to go straight and FIRE

 

; test if close to straight just right of center

movf ANGL, W

xorlw 0x80 ; look for 0111xxxx -> change it to 1111xxxx

andlw 0xF0 ; mask the 4 bits we are looking at

xorlw 0xF0 ; test the top 4 bits and set Z if true

btfsc STATUS, Z

call SET_FOR ; set both motors to go straight and FIRE

 

movf MOTOR, W

movwf PORTA ; output to motors

call RUN_MOT ; delay so the motors can go somewhere (125ms)

 

bcf FIRE ; stop FIRING

 

clrf PORTA

 

call SKIP

call SKIP

call SKIP

 

bsf MOTOR, 0 ; flag so we know we ran the motor - skip to next step

 

return

;END PROCESS

 

SET_FOR ;sets the motors to go forward

movlw FORWARD

movwf MOTOR

bsf FIRE ; FIRE if the other robot is in front

;END SET_FOR

 

 

SAMPLE ; this will perform 7 samples on a bit to test it

clrf COUNT

 

;sample and inc count ( 7 samples ) - INSERT CODE HERE

 

movlw .7 ; execute the following loop 7 times

movwf S_CNT

 

S_LOOP ; main sampling loop (take 7 samples)

btfsc PHOTO ; exec next instr if a low (TRUE signal) is received

incf COUNT, F ; TRUE sample was received - increment COUNT

movlw .3 ; execute the following delay 11 times

movwf LOOPCNT

D_LOOP nop ; the delay loop (total of 11us)

decfsz LOOPCNT, F

goto D_LOOP ; this is a 4us delay loop

nop

nop

decfsz S_CNT, F

goto S_LOOP ; this is the main sampling loop

 

clrf HIGH_S ; criteria for high: 6 or 7 true samples

clrf LOW_S ; criteria for low: 0 or 1 true samples

movf COUNT, W

andlw 0x06 ; test if count is 6 or 7 (xxxx x11x)

; andlw 0x04 ; test if count is 4-7 (xxxx x1xx)

btfsc STATUS, Z

bsf HIGH_S, 0 ; set HIGH=1

movf COUNT, W

; xorlw 0x06 ; flip bits 2 and 3 (don't care about others)

; andlw 0x06 ; test if count is 0 or 1 (xxxx x00x before bit flip)

xorlw 0x04 ; flip bit 3 (don't care about others)

andlw 0x04 ; test if count is 0-3 (xxxx x0xx before bit flip)

btfsc STATUS, Z

bsf LOW_S, 0 ; set LOW=1

return

;END SAMPLE

 

SKIP ; delays are as follows (Total = 20us)

; call(2), setup(2), loop(3*5-1=14), return(2)

movlw .3 ; execute the following delay 3 times

movwf LOOPCNT

SKIP_1 nop

nop

decfsz LOOPCNT, F

goto SKIP_1 ; this is a 5us delay loop

 

return ; END SKIP

 

RUN_MOT

movlw .125 ; delay 0.125 seconds

movwf L_CNT2

MOT_2

movlw .200 ; delay 1ms

movwf L_CNT1

MOT_1 nop

nop

decfsz L_CNT1, F

goto MOT_1 ; this is a 5us delay loop

 

decfsz L_CNT2, F

goto MOT_2

 

return ; RUN_MOT

 

PAUSE

movlw .10 ; delay 0.010 seconds

movwf L_CNT2

P_2

movlw .200 ; delay 1ms

movwf L_CNT1

P_1 nop

nop

decfsz L_CNT1, F

goto MOT_1 ; this is a 5us delay loop

 

decfsz L_CNT2, F

goto MOT_2

 

return ; PAUSE

 

WAS_HIT ;the robot was hit!!!

 

; turn off the IR to go invisible for a moment

bcf IR_EN

 

; send a pulse to the SCOREBOARD

bsf SCORE

call PAUSE ; 10ms

bcf SCORE

 

; run away for 1s

movlw BACK

movwf PORTA ; output to motors

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

movlw RIGHT

movwf PORTA ; output to motors

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

movlw BACK

movwf PORTA ; output to motors

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

movlw RIGHT

movwf PORTA ; output to motors

call RUN_MOT ; delay so the motors can go somewhere (1/8s each)

clrf PORTA ; stop the motors

 

; pause for 1 second

;the following are just delays - the motors won't be running

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

call RUN_MOT

 

; re-enable the IR

bsf IR_EN

 

return

 

;********************************************************************************

;* END of program *

;********************************************************************************

end

 

 


 

 

 

;********************************************************************************

;* Transmit Controller *

;* using PIC12C509A *

;* *

;* Version 1.0 *

;* by Nautilus Robotics *

;* 2001.1.23 *

;********************************************************************************

 

 

;********************************************************************************

;* Processor definition and configuration *

;********************************************************************************

; Clock = 4MHz XT

 

list P=12C509A

 

#include "P12C509A.inc"

 

__CONFIG _CP_OFF & _MCLRE_OFF & _WDT_OFF & _IntRC_OSC

 

 

;********************************************************************************

;* Hardware declaration *

;********************************************************************************

 

#define FIRE GPIO, 0 ; Pin 7, FIRE command input

#define IR_EN GPIO, 1 ; Pin 6, IR_EN command input

#define IRLED GPIO, 2 ; Pin 5, IR LED output

#define IR_ON GPIO, 4 ; Pin 3, IR_ON indicate output

#define LASER GPIO, 5 ; Pin 2, Red LED LASER output

 

;********************************************************************************

;* Variable declaration *

;********************************************************************************

 

COUNT equ 0x07

TEMP equ 0x08

CNTR1 equ 0x09

CNTR2 equ 0x0A

ZERO equ 0x0B

 

;********************************************************************************

;* Start of Program *

;********************************************************************************

 

ORG 0x00 ; start of program memory

; MOVLW 0x6C ; EPROM callibration (for EPROM only)

MOVWF OSCCAL ; Store factory callibration value

MOVLW 0

MOVWF GPIO ; clear GPIO

MOVLW 0x03 ; GP0, GP1 input,GP2, GP4, GP5 output

TRIS GPIO

MOVLW 0x0C3 ; TMR0 enable with 1:16 prescalar

 

OPTION

 

clrf GPIO ; initialize outputs to 0

 

;********************************************************************************

;* Start of main program loop *

;********************************************************************************

MAIN ; this loop should split the set and clear operations by 13us

 

btfss FIRE

goto NO_FIRE

 

;the following is run if we are to transmit the fire code

 

incf COUNT, F

movf COUNT, W

movwf TEMP ; store COUNT in TEMP before shifting

rrf TEMP, F

rrf TEMP, F ; (last line of READY: bsf IRLED)

rrf TEMP, F

movf TEMP, W

andlw 0x07 ; TEMP is COUNT div 8 (0 to 7)

 

bcf LASER ; this should be 13us before bit set high

bcf IRLED ; clear this in case it was on when FIRE changed states

 

F_WAIT btfss IR_EN

goto F_WAIT ; this is a loop to freeze output if ENABLE is off

 

nop

call DO_FIRE

andlw 1 ; allows STATUS to be changed

btfss STATUS, Z

 

bsf LASER ; if W is 1 pulse IR LED or LASER

 

goto MAIN

 

;the following is run if we are to transmit the signature code

NO_FIRE

incf COUNT, F

movf COUNT, W

movwf TEMP ; store COUNT in TEMP before shifting

rrf TEMP, F

rrf TEMP, F ; (last line of READY: bsf IRLED)

rrf TEMP, F

movf TEMP, W

 

bcf IRLED ; this should be 13us before bit set high

bcf LASER ; clear this in case it was on when FIRE changed states

 

NF_WAIT btfss IR_EN

goto NF_WAIT ; this is a loop to freeze output if ENABLE is off

 

andlw 0x07 ; TEMP is COUNT div 8 (0 to 7)

call DO_SIG

andlw 1 ; allows STATUS to be changed

btfss STATUS, Z

 

bsf IRLED ; if W is 1 pulse IR LED or LASER

 

goto MAIN

; begin signature lookup table

DO_SIG addwf PCL, F ; output byte

retlw 1 ; start bit

retlw 1 ; start bit

retlw 0 ; validity bit

retlw 0 ; validity bit

retlw 1 ; data bit 1 - SET THIS TO MATCH THE ROBOT

retlw 0 ; data 1 validity bit

retlw 0 ; data bit 2 - 0 = send signature pulse

retlw 0 ; data 2 validity bit

 

; begin fire lookup table

DO_FIRE addwf PCL, F

retlw 1 ; start bit

retlw 1 ; start bit

retlw 0 ; validity bit

retlw 0 ; validity bit

retlw 1 ; data bit 1 - SET THIS TO MATCH THE ROBOT

retlw 0 ; data 1 validity bit

retlw 1 ; data bit 2 - 1 = send FIRE pulse

retlw 0 ; data 2 validity bit

 

 

;********************************************************************************

;* DELAY subroutine *

;********************************************************************************

DELAY nop

nop

nop

nop

nop

nop

nop

nop

nop

nop

nop

nop

nop

 

bcf IRLED ; clear IR LED output

 

return

 

;********************************************************************************

;* END of program *

;********************************************************************************

end

 

 


 

 

;********************************************************************************

;* Score Controller *

;* using PIC12C509A *

;* *

;* Version 1.0 *

;* by Nautilus Robotics *

;* 2001.3.14 *

;********************************************************************************

 

 

;********************************************************************************

;* Processor definition and configuration *

;********************************************************************************

; Clock = 4MHz XT

 

list P=12C509A

 

#include "P12C509A.inc"

 

__CONFIG _CP_OFF & _MCLRE_OFF & _WDT_OFF & _IntRC_OSC

 

 

;********************************************************************************

;* Hardware declaration *

;********************************************************************************

 

#define HIT GPIO, 3 ; Pin 4, HIT input

#define LED0 GPIO, 4 ; Pin 3, Score position 1

#define LED1 GPIO, 0 ; Pin 7, Score position 2

#define LED2 GPIO, 1 ; Pin 6, Score position 3

#define LED3 GPIO, 2 ; Pin 5, Score position 4

 

 

;********************************************************************************

;* Variable declaration *

;********************************************************************************

 

CNTR1 equ 0x07

CNTR2 equ 0x08

CNTR3 equ 0x09

FLAG equ 0x0A

KEY equ 0x0B

NEWKEY equ 0x0C

OLDKEY equ 0x0D

COUNT equ 0x0E

 

 

;********************************************************************************

;* Start of Program *

;********************************************************************************

 

ORG 0x00 ; start of program memory

; MOVLW 0x6C ; EPROM callibration (for EPROM only)

MOVWF OSCCAL ; Store factory callibration value

MOVLW 0

MOVWF GPIO ; clear GPIO

MOVLW 0x08 ; GP3 input, the rest output

TRIS GPIO

MOVLW 0xC3 ; TMR0 enable with 1:16 prescalar

OPTION

 

 

;********************************************************************************

;* Start program *

;********************************************************************************

; start by testing LEDs, also allows for main controller to start up and

; initialize its I/O before SCORE begins to sample inputs.

 

START call TEST ; test LEDs upon start-up

bcf FLAG, 0

 

;********************************************************************************

;* Start of main program loop *

;********************************************************************************

 

MAIN clrf COUNT ; clear hit counter

movlw 0xFF

movwf GPIO ; clear score board

 

bcf LED0 ; LED0 on

movlw 0x01

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED0 ; LED0 off

 

bcf LED1 ; LED1 on

movlw 0x01

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED1 ; LED1 off

 

bcf LED2 ; LED2 on

movlw 0x01 ; 1 second

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED2 ; LED2 off

 

bcf LED3 ; LED3 on

movlw 0x01

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED3 ; LED3 off

 

bcf LED2 ; LED2 on

movlw 0x01 ; 1 second

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED2 ; LED2 off

 

bcf LED1 ; LED1 on

movlw 0x01

call DELAY ; delay

btfsc FLAG, 0 ; if flag is set then go to SCORE

goto SCORE ; else continue

bsf LED1 ; LED1 off

 

goto MAIN ; loop in MAIN until a hit is recieved

 

 

SCORE movlw 0xFF

movwf GPIO ; all LEDs off

CHECK bcf FLAG, 0 ; clear flag for next hit to occur

incf COUNT, F ; increment hit counter

movlw 0x05

xorwf COUNT, W ; check number of hits

btfsc STATUS, Z

goto MAIN ; if more than 4 hits then go to MAIN

 

OUTPUT movlw 0x01

xorwf COUNT, W ; test contents of COUNT

btfsc STATUS, Z ; if COUNT is 1

goto HIT_1 ; then go to HIT_1

 

movlw 0x02

xorwf COUNT, W ; test contents of COUNT

btfsc STATUS, Z ; if COUNT is 2

goto HIT_2 ; then go to HIT_2

 

movlw 0x03

xorwf COUNT, W ; test contents of COUNT

btfsc STATUS, Z ; if COUNT is 3

goto HIT_3 ; then go to HIT_3

 

movlw 0x04

xorwf COUNT, W ; test contents of COUNT

btfsc STATUS, Z ; if COUNT is 4

goto HIT_4 ; then go to HIT_4

 

goto OUTPUT ; loop in output until more than 4 hits

 

 

HIT_1 call BLINK ; flash all LEDs once

bcf LED0

HOLD_1 movlw 0x01 ; call for delay and

call DELAY ; test score input pin

btfsc FLAG, 0 ; if flag is set

goto CHECK ; then go CHECK to increment COUNT

goto HOLD_1 ; else go to HOLD_1

 

HIT_2 call BLINK ; flash all LEDs twice

bcf LED0

bcf LED1

HOLD_2 movlw 0x01 ; call for delay and

call DELAY ; test score input pin

btfsc FLAG, 0 ; if flag is set

goto CHECK ; then go CHECK to increment COUNT

goto HOLD_2 ; else go to HOLD_2

 

HIT_3 call BLINK ; flash all LEDs three times

bcf LED0

bcf LED1

bcf LED2

HOLD_3 movlw 0x01 ; call for delay and

call DELAY ; test score input pin

btfsc FLAG, 0 ; if flag is set

goto CHECK ; then go CHECK to increment COUNT

goto HOLD_3 ; else go to HOLD_3

 

HIT_4 call BLINK ; flash all LEDs four times

bcf LED0

bcf LED1

bcf LED2

bcf LED3

HOLD_4 movlw 0x01 ; call for delay and

call DELAY ; test score input pin

btfsc FLAG, 0 ; if flag is set

goto CHECK ; then go CHECK to increment COUNT

goto HOLD_4 ; else go to HOLD_4

 

 

;********************************************************************************

;* TEST subroutine - flash all LEDs on and off once *

;********************************************************************************

 

TEST clrf GPIO ; all LEDs on

call DELAY_2 ; delay while LEDs on

movlw 0xFF

movwf GPIO ; all LEDs off

call DELAY_2 ; delay while LEDs off

return

 

 

;********************************************************************************

;* DELAY Subroutine - debounce feature for button input *

;********************************************************************************

; The inner loop of delay routine polls GPIO, 3 button input continuously for

; time t and thus performs both delay and button poll function. The button poll

; also debounces the input.

 

DELAY movwf CNTR3 ; W is loaded with constant before entering DELAY

; the delay time is W seconds

LOOP3 movlw 1 ; outer loop of delay, executed CNTR1 times

movwf CNTR1

btfss FLAG, 0 ; if FLAG is set then do LOOP2 only once

movlw 0x64

movwf CNTR2 ; else do LOOP2 100 times

 

LOOP2 movlw 1 ; secondary loop of delay, executed CNTR2 times

movwf CNTR1

btfss FLAG, 0 ; if FLAG is set then do LOOP1 only once

movlw 0x64

movwf CNTR1 ; else do LOOP1 100 times

 

LOOP1 movf NEWKEY, W ; inner most loop of delay, executed CNTR3 times

movwf OLDKEY ; store NEWKEY into OLDKEY

movf GPIO, W ; read GPIO

andlw 0x08 ; mask GPIO for input 3

movwf NEWKEY

comf NEWKEY, F

andwf OLDKEY, W

movwf KEY ; KEY = OLDKEY AND COMPL(NEWKEY)

btfsc KEY, 3

bsf FLAG, 0

 

decfsz CNTR1,F

goto LOOP1

 

decfsz CNTR2,F

goto LOOP2

 

decfsz CNTR3,F

goto LOOP3

 

return

 

 

;********************************************************************************

;* DELAY_2 Subroutine - 0.33 second simple delay routine *

;********************************************************************************

 

DELAY_2 clrf CNTR2

LOOP_2 clrf CNTR1 ; outer loop, executed CNTR2 times

LOOP_1 nop ; inner loop, executed CNTR1 times

nop

decfsz CNTR1,F ; first decrement rolls CNTR1 over to 255

goto LOOP_1

 

decfsz CNTR2,F ; first decrement rolls CNTR2 over to 255

goto LOOP_2

 

return

 

;********************************************************************************

;* DELAY_3 subroutine - simple short delay for BLINK *

;********************************************************************************

 

DELAY_3 movlw .50

movwf CNTR2

LOOP_B clrf CNTR1 ; outer loop, executed CNTR2 times

LOOP_A nop ; inner loop, executed CNTR1 times

nop

decfsz CNTR1,F ; first decrement rolls CNTR1 over to 255

goto LOOP_A

 

decfsz CNTR2,F

goto LOOP_B

 

return

 

;********************************************************************************

;* BLINK subroutine - flash all LEDs on and off CNTR3 times *

;********************************************************************************

 

BLINK

movlw .20

movwf CNTR3

B_LOOP clrf GPIO ; all LEDs on

call DELAY_3 ; delay while LEDs on

movlw 0xFF

movwf GPIO ; all LEDs off

call DELAY_3 ; delay while LEDs off

 

decfsz CNTR3, F

goto B_LOOP

 

return

 

;********************************************************************************

;* End of program *

;********************************************************************************

end