;;; busdemo.asm ;;; ;;; demonstrates use of Handy Cricket bus ;;; toggles a pin when addressed by Cricket, ;;; then gives one of two replies based on resulting state of the pin. ;;; ;;; pin assignments: ;;; Port B 0 is bus I/O, Port B 7 is toggle pin ;;; ;;; bus values: ;;; 17 (decimal) is bus address ;;; 100 or 101 are return values based on toggle pin's state. ;;; ;;; NOTE! ;;; this bus code requires 4 MHz crystal with 1 usec per instruction clock ; device pic16f84 ; config OSC=xt radix dec ;;; register destination constants W equ 0 F equ 1 ;;; register constants INDF equ 0 STATUS equ 3 ; status register C equ 0 ; status C bit Z equ 2 ; status Z bit RP0 equ 5 ; status register page 0 FSR equ 4 PORTB equ 6 ; port B register ;;; bus port and pin BUSPORT equ PORTB BUSTRIS equ PORTB + 0x80 ; for setting bus as output BUSPIN equ 0 ; bit 0 ;;; memory variables buscntr equ 0x20 ; bit counter busdata equ 0x21 ; bus data register counter equ 0x22 ; temp register org 0 start: bsf STATUS,RP0 bcf PORTB,7 ; make port B7 output bcf STATUS,RP0 ;;; the main loop ;;; block until receives word on bus ;;; check if it's cmd or data, if data, ignore. ;;; if cmd, check if it's our magic number, if not, ignore ;;; if it's for us, toggle output pin then generate reply. loop: call bus_tyi ; get word from bus btfss STATUS,C ; if C set, it's a cmd word goto loop movf busdata,W xorlw 17 ; 17 is our magic number btfss STATUS,Z goto loop ; if Z clear, wasn't our number ;; toggle PORTB 7 so we'll know cmd word was received! call toggle ;; now, return 100 if PORTB 7 is low, 101 if high! ;; from logo, "IF (BSR 256 + 17) = 101 [BEEP]" ;; will beep on alternate tries as the pin is toggled. movlw 100 movwf busdata btfsc PORTB,7 ; if PB7 set, incf busdata,F ; incr busdata to 101 call bus_tyo ; now return it. goto loop ;;; inverts state of PORTB 7 toggle: btfsc PORTB,7 goto togclr bsf PORTB,7 return togclr: bcf PORTB,7 return ;;; returns byte in busdata ;;; the inverse of the stop bit in the carry ;;; commands have a 0 stop bit -> carry set ;;; data has a 1 stop bit -> carry clear bus_tyi: btfsc BUSPORT,BUSPIN goto bus_tyi ; loop until bus line goes low ; bcf INTCON,GIE ; disable interrupts (if necessary) btyi20 btfss BUSPORT,BUSPIN goto btyi20 ; wait for end of prestart movlw 8 movwf buscntr call an_rts ; use 4 cycles, into middle of start bit btyi30 nop nop nop rrf busdata,F ; pre-rotate destination byte bcf busdata,7 ; clear high bit (it'll rotate down) btfsc BUSPORT,BUSPIN bsf busdata,7 ; if BUSPIN was set, set busdata bit decfsz buscntr,F goto btyi30 call an_rts nop bsf STATUS,C ; pre-set carry (cmd word) btfsc BUSPORT,BUSPIN bcf STATUS,C ; if no stop bit, clear carry ; bsf INTCON,GIE ; re-enable interrupts (if necessary) an_rts return ;;; send a byte down the bus. ;;; this is the slave device code, so send '1' as stop bit, ;;; indicating a data word. ;;; put the byte to send in busdata before calling. bus_tyo: ; bcf INTCON,GIE ; disable interrupts (if necessary) movlw BUSTRIS movwf FSR ; will be controlling bus to output bcf BUSPORT,BUSPIN ; put 0 into pin register bcf INDF,BUSPIN ; write it out & begin pre-start pulse movlw 33 movwf counter btyo20: decfsz counter,F goto btyo20 ; wait 100 usec bsf BUSPORT,BUSPIN ; end pre-start, begin start bit bsf STATUS,C ; will be stop bit, indicating data word movlw 9 ; 8 data bits plus C bit last movwf counter call an_rts ; use up 4 cycles nop ; plus 1 more making 10 for start bit btyo50: rrf busdata,F ; bit -> carry btfss STATUS,C ; if C is clear, bcf BUSPORT,BUSPIN ; clear bus pin btfsc STATUS,C ; if C was set, bsf BUSPORT,BUSPIN ; set bus pin nop nop ; tune the loop to take 10 us decfsz counter,F goto btyo50 nop nop bsf INDF,BUSPIN ; bus to input again, float high ; bsf INTCON,GIE ; re-enable interrupts (if necessary) return end