; $Id: main.asm,v 1.7 1999/04/10 03:38:43 root Exp $ processor 16f84 list f=inhx8m include "p16f84.inc" __config _cp_off & _wdt_off & _rc_osc b_oper equ 0 ; operator footswitch b_child equ 1 ; child trigger b_ready equ 2 ; ready indicator b_1 equ 4 ; channel one b_2 equ 5 ; channel two b_3 equ 6 ; channel three b_beep equ 7 ; piezo buzzer lowram equ 0x0c ; first free file register address midram equ 0x40 ; start of second segment of registers r_port equ portb ; output port r_tris equ trisb ; tristate latch for port cblock lowram portm ; mirror of port trism ; mirror of tris endc org 0x0 goto main ; jump over subroutines ;; ;; identification data to be recorded on chip to assist ;; any future attempt at reverse engineering ;; dt "purpose=random response box selector," dt "revision=c," dt "date=1999-04-10," dt "email=james.cameron@compaq.com," dt "email=quozl@us.netrek.org," dt "client=cochlear," dt "project=99-11707." ;;; ;;; ms10, delay in units of ten milliseconds ;;; ms10 cblock outer ; outer loop counter inner ; inner loop counter endc ;; hardware environment ... ;; clock is 756kHz ;; cycle time is 1/756000*4 = 5.291us ;; 10ms delay = 1890 cycles movwf outer ; save caller provided w ms10_a: movlw d'210' movwf inner ms10_b: nop ; 1 nop ; 2 nop ; 3 nop ; 4 nop ; 5 nop ; 6 decfsz inner,f ; 7 goto ms10_b ; 8/9 decfsz outer,f goto ms10_a retlw 0 ;;; ;;; kick the box counter, modulus three ;;; kick: incf will,f ; choose next box to light movlw d'4' ; check for limit of boxes subwf will,w skpz retlw 0 movlw d'1' ; wrap to first box movwf will retlw 0 ;;; ;;; main program ;;; main: cblock last ; number of last output set will ; number of next output set endc movlw d'2' ; never start with centre box movwf last movlw d'1' movwf will initialise: ; configure port bits clrf portm ; clear port mirror bsf portm,b_child bsf portm,b_oper movf portm,w ; move to w ... movwf r_port ; ... then to port bsf status,rp0 ; read trisb movf r_tris,w bcf status,rp0 movwf trism ; store in mirror bcf trism,b_ready ; drive outputs low bcf trism,b_1 bcf trism,b_2 bcf trism,b_3 bcf trism,b_beep movf trism,w tris r_tris bsf status,rp0 ; start tmr0 running for ready LED bcf option_reg,t0cs bcf option_reg,psa bcf status,rp0 welcome: ; beep for a second to say hello bsf portm,b_beep ; turn on beeper bsf portm,b_ready ; turn on green LED movf portm,w movwf r_port bcf trism,b_oper ; turn on yellow LED bcf trism,b_child ; turn on orange and red LEDs movf trism,w tris r_tris movlw d'100' ; wait one second call ms10 bcf portm,b_beep ; disable beeper movf portm,w movwf r_port bsf trism,b_oper ; turn off yellow LED bsf trism,b_child ; turn off orange and red LEDs movf trism,w tris r_tris movlw d'1' ; wait for inputs to settle call ms10 loop: ; wait for an input to be set bsf trism,b_oper ; turn off response LED bsf trism,b_child ; turn off response LED movf trism,w tris r_tris bcf portm,b_ready ; blink ready LED regularly btfss tmr0,5 goto notready btfsc tmr0,6 bsf portm,b_ready notready: bcf portm,b_1 ; disable outputs bcf portm,b_2 ; disable outputs bcf portm,b_3 ; disable outputs movf portm,w ; apply port changes movwf r_port ;; ;; random selection of box to be lit is implemented by continual ;; rotation through available boxes, in the manner of a dice. ;; call kick ; choose next box to light movf will,w ; check to see if it will be subwf last,w ; same as last box lit bnz notlast ; branch of not call kick ; same, so go to next one notlast: btfsc r_port,b_oper ; check operator footswitch goto next ; jump if set btfss r_port,b_child ; check child trigger goto loop ; loop if not set next: movlw d'1' ; 10ms wait call ms10 ; for contact debounce btfsc r_port,b_oper ; check operator footswitch goto trigger_operator ; jump if set btfss r_port,b_child ; check child trigger goto loop ; loop if not set trigger_child: bcf trism,b_child ; turn on response LED movf trism,w tris r_tris goto beep trigger_operator: bcf trism,b_oper ; turn on response LED movf trism,w tris r_tris goto beep beep: bsf portm,b_ready ; enable ready LED bsf portm,b_beep ; enable beeper ;; ;; choosing which output bit to set based on the number of the ;; randomly selected box ... boringly simple and limited code. ;; movlw d'1' ; are we to set box one? subwf will,w bnz not1 ; no, jump to try another bsf portm,b_1 ; set box one goto half ; continue not1: movlw d'2' ; not box one, how 'bout two? subwf will,w bnz not2 ; no, jump to three bsf portm,b_2 ; is two, set it goto half not2: bsf portm,b_3 ; set box three half: movf will,w ; remember which one we set movwf last movf portm,w ; apply port changes movwf r_port movlw d'25' ; 250ms wait call ms10 bcf portm,b_beep ; disable beeper (sound for 250ms) movf portm,w ; apply port changes movwf r_port movlw d'25' ; 250ms wait call ms10 bsf trism,b_oper ; turn off operator response LED bsf trism,b_child ; turn off child response LED movf trism,w tris r_tris movlw d'1' ; allow for stabilisation ... call ms10 ; ... before reading it again ;; ;; if the operator hits the footswitch for a short burst, treat it ;; as a "reading" of the child's response and behave as if the ;; child has triggered the box ... i.e. follow the same five second ;; activation time sequence. ;; btfss r_port,b_oper ; was footswitch held down? goto child ; jump over if not ;; ;; operator has held down the footswitch for more than half a second, ;; so we go into manual control here ... when they release it, we ;; will turn off the box and immediately be available again. ;; oper: btfsc r_port,b_oper ; wait for release goto oper ; loop movlw d'1' ; contact debounce call ms10 btfsc r_port,b_oper ; wait for release goto oper ; loop movlw d'25' ; 250ms wait call ms10 goto loop ;; ;; child triggered box sequence, show the box for five seconds, ;; then turn it off, and wait another five seconds before allowing ;; the child to respond again. ;; child: cblock cwlc ; child wait loop count endc movlw d'50' ; five seconds on time movwf cwlc pause_1: btfsc r_port,b_oper ; check operator intervention goto loop movlw d'10' ; tenth of a second call ms10 decfsz cwlc,f goto pause_1 bcf portm,b_1 ; disable outputs bcf portm,b_2 ; disable outputs bcf portm,b_3 ; disable outputs movf portm,w ; apply port changes movwf r_port movlw d'50' ; five seconds off time movwf cwlc pause_2: btfsc r_port,b_oper ; check operator intervention goto loop movlw d'10' ; tenth of a second call ms10 decfsz cwlc,f goto pause_2 movlw d'1' ; allow for stabilisation call ms10 goto loop end