; ; File: receiver.asm -- receiver module for cable tester ; ; (C) 1996 Maurizio Fabbri, Fabio Raso, Luigi Rizzo ; Dipartimento di Ingegneria dell'Informazione ; via Diotisalvi 2 -- 56126 PISA (ITALY) ; email: luigi@iet.unipi.it device pic16c84 config CP=off,WDT=off,PWRT=off,OSC=hs nuovo equ 1 include "defs.inc" ; on_1 targer, on_0 target sample the input line and jump to target ; if the desired value is found. Make the program easier to read. on_1 macro ; on_1 target movf PORTB, W ; W <- sample portb andwf maskB, W ; W <- mask & W, set Z flag btfss STATUS, Zbit goto \1 endm on_0 macro ; on_1 target movf PORTB, W ; W <- sample portb andwf maskB, W ; W <- mask & W, set Z flag btfsc STATUS, Zbit goto \1 endm ;--- port usage: portb: input data/ display output ; port A: display cathodes (via transistors) DISPLAY1 equ 1 DISPLAY2 equ 2 ;--- receiver-specific registers ctr1 equ 0x10 ; two generic counters ctr2 equ 0x11 broken equ 0x14 ; 1 for each broken line bitptr equ 0x15 ; bit under test (0..7) maskB equ 0x16 ; corresponding mask digits equ 0x17 ; what goes in digits ? (2 4-bit nibbles) BufP0 equ 0x20 ; what is received on this bit ? [ 8 bytes ] ; -- up to BufP7 equ 0x27 org 0 goto start ; start a new test ; total delay (incl. call+ret) 4*W + 3 wdelay ; a simple delay routine using W addlw -1 ; 4 ck/loop + 5 last one (incl.ret) btfss STATUS,Zbit ; salta se Zbit = 1 goto wdelay return scrambler ;--- bit2display 0..9 -> 0..9 bin2display ; up to 16 codes andlw 0xf ; mask addwf PCL,F ; -gfedcba ; segments retlw B'00111111' ; digit 0 (unused) retlw B'00000110' ; digit 1 retlw B'01011011' ; digit 2 retlw B'01001111' ; digit 3 retlw B'01100110' ; digit 4 retlw B'01101101' ; digit 5 retlw B'01111101' ; digit 6 retlw B'00000111' ; digit 7 retlw B'01111111' ; digit 8 retlw B'00000000' ; blank (digit 9 is unused) stuck1 equ 0x0a retlw B'00000001' ; stuck 1 unconn equ 0x0b retlw B'01000000' ; unconnected - stuck0 equ 0x0c retlw B'00001000' ; stuck 0 retlw B'00111000' ; L retlw B'01111001' ; E retlw B'01110011' ; P ;--- a quick test to see if everything ok (BufP[i] = i) ; returns Z set if everything is OK tutto_ok bsf STATUS,Cbit movf broken,0 ; test broken andlw 0xFF btfss STATUS,Zbit return ; with Z clear. return ; scan for BufP[i] = i ldc 8, ctr2 ; number of pins ok_loop decf ctr2, W addlw BufP0 ; prepare to read movwf FSR movf INDIR, W ; load test result andlw 0x7 ; mask subwf ctr2, W ; indir - W return ; with Z clear if false return ; with Z set if true ; display a couple of digits. uses ctr1 as a counter. display ldc 0xff, ctr1 ; number of cycles ? refreshDisplay movf digits,W call bin2display bcf PORTA,DISPLAY2 movwf PORTB bsf PORTA,DISPLAY1 movlw 0xff call wdelay swapf digits,W call bin2display bcf PORTA,DISPLAY1 movwf PORTB bsf PORTA,DISPLAY2 movlw 0xff ; attesa display2 --> display1 ... call wdelay ; ... circa 60 micro sec. loop ctr1, refreshDisplay return ;--- ; test_line tests a specific line, with mask in maskB ; bitptr also contains the index ; ; uses ctr2, ctr1 as loop counters test_line ; Each bit is sent every 28 cycles, each line carries 8 bits ; followed by about 56 bits of silence (for a cycle time of ; 64 bits). To avoid false detections, we should do as follows: ; 1) wait at most 10 bit times for the line to become '1' ; 2) wait for at least 40 bits of '1' or go to step 1 ; if the above does not complete in more than 6 phases at 1, ; give up and mark the line as broken. ldc 0x0a, ctr2 ; how many times wait for '1' period ? max 10 goto w_hi w_l_again loop ctr2, w_hi movf maskB,0 ; too many retries, abort iorwf broken, 1 ; mark as broken retlw unconn ; wait at most 10 bit times for the line to become '1' ; w_hi_l takes 7 cycles, so 0x30 is more than safe w_hi ldc 0x30, ctr1 w_hi_l on_1 w_l_2 loop ctr1, w_hi_l ; wait again... movf maskB, W ; 1 not found, mark as stuck 0 and return. iorwf broken, F ; mark as broken retlw stuck0 ; wait for bit to stay up for a sufficient time, >= 48 bits. ; the loop w_l_3 is 7 clocks, so ctr1 about (48*28/7) = 192 ; or less if ever. w_l_2 ldc 0xc0, ctr1 w_l_3 on_0 w_l_again loop ctr1, w_l_3 ; ok, '1' for a sufficient time, now wait for 0 again. ; Cannot fail here, but wait at most 20 bit times. This time ; the cycle is 6 clocks, hence ctr1 = (20*28/6) = 93. The error ; on the start bit is at most 6 clocks, i.e. 1/4 bit time. ; From there on, we can simply accumulate bits. ldc 0x5d, ctr1 movf maskB,W ; W <- mask w_l_4 andwf PORTB,W ; W <- portb & mask, set Z btfsc STATUS, Zbit ; Z set if bit = 0 (found) goto start_found loop ctr1, w_l_4 movf maskB,W iorwf broken,1 ; '0' not found. Mark as broken and stuck to 1 retlw stuck1 start_found: ; here we are 4..10 cycles into the start bit. ; wait an additional 7 cycles, then sample every 28 ldc 7, ctr2 ; mask for out data, now ctr2 is a bit counter, clrf ctr1 ; and ctr1 an accumulator movlw 0x6 call wdelay ; 27 cycles get_bit nop nop nop bcf STATUS, Cbit ; clear carry movf maskB,W ; load mask in W. andwf PORTB,W ; sample portb, mask & set Z btfss STATUS, Zbit ; Z set if bit = 0 bsf STATUS, Cbit ; was 1, set carry rlf ctr1, F ; accumulate movlw 0x3 call wdelay ; 15 clocks loop ctr2, get_bit incf ctr1, 0 ; now ctr1 contains the code, inc & store in W andlw 0xf return ;---- main program ---- ; ; Input lines are assumed to be connected to the sender, where ; they are all but one hold to '1'. On the remaining line, ; a code is cyclically transmitted indicating which line is ; this at the remote end. start clrf bitptr ; same (index) clrf broken ; bitmap of broken lines bsf STATUS,RP0bit ; page 1 bcf OPTION_REG, 7 ; pull up enabled ldc 1, TRISA ; set RA0 as input, rest output ldc 0xff, TRISB ; port B input bcf STATUS,RP0bit ; page 0 clrf PORTA ; display off wire movf bitptr, W call make_mask movwf maskB ; line currently under test. call test_line ; test input lines, one at a time. result in W movwf digits ; used as a temp. buffer movf bitptr,W ; W <- &BufP[ bitptr ] addlw BufP0 ; store result movwf FSR movf digits,W ; W <- digits movwf INDIR incf bitptr, F ; this also clears carry, which must be 0 movf bitptr, W andlw 0x7 btfss STATUS,Zbit ; if carry set, we are done goto wire ;--- when the test is over, show the results. --- show ;btfsc PORTA,TastoV ; first, wait for a keypress. ;goto show bsf STATUS,RP0bit ; page 1 clrf TRISB ; portb = out bcf STATUS,RP0bit ; page 0 ldc 5, ctr2 ; shows the result this many times. ; call tutto_ok ; quick check if all ok (Z set if true) ; btfss STATUS,Zbit goto nook ldc 0x28, ctr2 ; since the loop is shorter... infinitoSi ; all ok. Display "SI" forever ldc 0x51, digits ; SI call display decfsz ctr2, F goto infinitoSi goto dormi nook clrf bitptr ; T_OK nook_lp movf bitptr,0 ; read a digit addlw BufP0 movwf FSR movf INDIR,0 ; read BufP[i] andlw 0xf ; mask movwf digits swapf bitptr,W addlw 0x10 andlw 0xf0 iorwf digits,F ; store call display incf bitptr,1 movf bitptr,0 xorlw 0x8 btfss STATUS, Zbit goto nook_lp decfsz ctr2, F goto nook dormi ldc 0x95, digits ; ' S' call display ldc 0x5D, digits ; 'SL' call display ldc 0xdE, digits ; 'LE' call display ldc 0xEE, digits ; 'EE' call display ldc 0xEF, digits ; 'EP' call display bsf STATUS,RP0bit movlw 0xff ; ports off movwf TRISA movwf TRISB bcf STATUS,RP0bit sleep end