Code:
;(c) W.K.Todd 2005
;Read data bits from Vernier scale
;V2.00 - uses on-chip comparator for both inputs
;GP0 - data
;GP1 - clock
;------------------------------------------------------------------
;vernier data is 24bits (lsb first) absolute position
;followed by 24bits relative pos (as displayed)
;clock remains high for 50uS between data bursts
;each bit represents 20480th of an inch
;data is valid on falling edge of clock
;Clock is high for 50uS prior to first valid clock edge
;------------------------------------------------------------------
;4bit digit output from new verniers
;
;verniers tx data as 7 nibbles, first 6 nibbles are display digits lsd-msd,
;7th nibble is: Sign bit(1=-ve), Half thou bit(1=0.0005"), mm/inch bit(1=mm), always high bit
;Data is valid on falling edge of clock
;Clock is high for 50uS prior to first valid clock edge
;-------------------------------------------------------------------
;Vdata equ 0x00 ;4 bytes shift register
; ;Vdata = MSByte
; ;Vdata+1 = NSB
; ;Vdata+2 = nsb+1
; ;Vdata+3 = LSByte
;
;initialise comparator etc
;
VInit BSF status,RP0 ;select bank 1
movlw B'10100011' ;set Vref ~ 0.75v, Vdd = 5v;(24/5)* 0.75
movwf VRCON
BCF status,RP0 ;select bank 0
movlw B'00010110' ;multiplex in, int ref output inverted, output
movwf CMCON
return
;
;get vernier data into buffer
;
GetVD bcf CMCON,CIS ;switch comp to clk input
btfsc Mode,Vtype
goto GetVDD ;get vernier decimal data
call synlp ;gvd
call GetVDB ;get and discard ABS
GetVDB movlw 0x80 ;set hi bit of shift register
movwf Vdata
clrf Vdata+1 ;set-up for 24bits
clrf Vdata+2
clrf vdata+3
cphlp btfss CMCON,COUT ;wait for clock to go high
goto cphlp
bcf status,c ;clear carry ready
;wait clock low - grab bit
cpllp btfsc CMCON,COUT
goto cpllp
bsf CMCON,CIS ;switch comp to data input
btfsc CMCON,COUT ;test data bit
bsf status,c ;set carry if data = 1
rrf Vdata,f ;roll bit into msb buffer...
rrf Vdata+1,f ;then...
rrf Vdata+2,f ;into lsb.
bcf CMCON,CIS ;switch comp to clk input
btfss status,c ;exit when 24 bits shifted
goto cpllp
return
;sync - wait for clock low for >1mS
synlp btfsc CMCON,COUT
clrf Vdata+3 ;use Vdata+3 as temp timer
decfsz Vdata+3,f
goto synlp
return
;
;get decimal vernier data
;
GetVDD movlw Vdata+3
movwf FSR ;set indirection pointer
;set up nibble counter
clrf vdata+3
call synlp
movlw 0x08
call VDbyte ;first nibble 1
decf FSR,f ;Vdata+2
movlw 0x80
call VDbyte ;2&3
decf FSR,f ;Vdata+1
movlw 0x80
call VDbyte ;4&5
decf FSR,f ;Vdata
movlw 0x80 ;get last byte 6&flags
VDbyte ;get byte or nibble
movwf INDF
cphlp1 btfss CMCON,COUT ;wait for clock to go high
goto cphlp1
bcf status,c
cpllp1 btfsc CMCON,COUT
goto cpllp1
bsf CMCON,CIS ;switch comp to data input
btfsc CMCON,COUT ;test data bit
bsf status,c ;set carry if data = 1
rrf INDF,f ;roll bit into msb buffer...
bcf CMCON,CIS ;switch comp to clk input
btfss status,c ;exit when 8 bits shifted
goto cpllp1
return
;measure the vernier reading speed (300mS slow,20mS fast)
measure bcf CMCON,CIS ;switch comp to clk input
call synlp ;wait for clock low >1mS
bcf Mode,Fflg
;if clock occurs within ~25mS then Fast flag will be set
movlw 25
movwf vdata ;borrow vdata as counter
m2lp btfsc CMCON,COUT
bsf Mode,Fflg ;
decfsz vdata+3,f
goto m2lp
decfsz vdata,f
goto m2lp
return
;
;check vernier type by counting clock pulses
;
GetVT bcf CMCON,CIS ;switch comp to clk input
call synlp ;wait for clock low
clrf vdata+1 ;used as timer
movlw 30
movwf vdata+2 ;clock pulse counter
vthlp btfss CMCON,COUT ;wait for clock to go high
goto vthlp
cntlp btfsc CMCON,COUT ;wait for clock low
goto cntlp
decf vdata+2,f ;count bit
clrf vdata+1 ;used as timer
cnthp btfsc CMCON,COUT ;wait for clock high or timeout
goto cntlp ;if clock hi then wait for clock low
decfsz Vdata+1,f ;exit loop if low >~1mS
goto cnthp
bcf Mode,Vtype
btfss Vdata+2,7 ;test if >30 clock pulses
bsf Mode,Vtype ;if not then flag as new type vernier
return