; 2002.11.22 Kevin Timmerman ; list p=12C509 ; CPU type include ; Include file ; __config _MCLRE_OFF & _CP_OFF & _WDT_ON & _IntRC_OSC ; __config _MCLRE_OFF & _CP_ON & _WDT_ON & _IntRC_OSC ; ; ; ; errorlevel -224 ; Disable tris and option warning messages ; radix dec ; Default radix of decimal ; ; ; --- Registers ; 0x0C to 0x1F ; ; -- Serial Tx/Rx rSerBitCnt equ 0x0C ; Serial Rx/Tx bit count rSerBitTmr equ 0x0D ; Serial Rx/Tx bit timer rSerTxChar equ 0x0E ; Char to send to host rSerRxChar equ 0x0E ; Char received from host rByteCnt equ 0x0F ; Tx ASCII byte counter, message byte index ; ; -- Gauge rBitCnt equ 0x0C ; also used by scale rData equ 0x10 ; 6 bytes 0x10-0x15 rChkSum equ rData+6 ; 0x16 ; ; -- Scale & Zero rMode equ 0x19 ; 0=Raw, 1=IN, 2=MM, 3=binary rMult equ 0x0E ; rProduct equ 0x14 ; 3 bytes 0x14-0x16 ; ; -- Binary to ASCII rBcd equ 0x10 ; 4 bytes 0x10-0x13 rAscii equ rBcd ; 8 bytes 0x10-0x17 rBin equ rProduct; 3 bytes 0x14-0x16 rPti equ 0x0C ; rPto equ 0x0D ; rI equ 0x0E ; rCnt equ 0x0F ; rTemp equ 0x18 ; ; ; rFlags equ 0x1A ; used for flags ; ; -- Flags #define _LeadZero rFlags,0 ; Supress zeros #define _Negative rFlags,1 ; Sample is (was) negative #define _ModeLock rFlags,2 ; Model is locked by host #define _HelpMsg rFlags,3 ; Use help message in page 1 #define _BufValid rFlags,4 ; Binary or ASCII buffer is valid #define _DecPoint rFlags,5 ; Decimal point follows this digit #define _ReadGauge rFlags,6 ; In gauge reading routines, handle WDT timeout differently ; PAGE1 equ 0x200 ; ; ; ; ; --- Ports and port bits pSerRx equ GPIO ; Serial Rx from host bSerRx equ 1 ; pSerTx equ GPIO ; Serial Tx to host bSerTx equ 5 ; ; pGauge equ GPIO ; bData equ 2 ; Gauge Data bClk equ 0 ; Gauge Clock ; pMode equ GPIO ; Jumper block bMode0 equ 3 ; bMode1 equ 4 ; ; ; ; ; ; ; org 0 ; --- Program memory starts here ; movwf OSCCAL ; Setup osc. calibration ; goto Start ; ; ; ; ; ************************* Messages ********************* ; Messages ; addwf PCL,F ; ; msgStart ; ; msgCopyright ; DT "Public Domain - Kevin Timmerman calpintf@pcmx.net",13,10,0 ; msgVersion ; DT "2002.11.22",13,10,0 ; GetDp ; movf rMode,W ; Get mode andlw 3 ; Mask off other bits addwf PCL,F ; Jump... retlw 0 ; Raw retlw 4 ; Inches retlw 2 ; mm retlw 0 ; binary ; ; TxMessage ; movwf rByteCnt ; Save message index btfss _HelpMsg ; Help message (in page 1)? goto nothelp ; bsf STATUS,PA0 ; Set page bit (page 1) call msgHelp^PAGE1 ; bcf STATUS,PA0 ; Clear page bit (page 0) goto tstchar ; ; nothelp call Messages ; Get a char ; tstchar xorlw 0 ; End? btfsc STATUS,Z ; No... goto msgdn ; End of message, return... call SerTx ; Send char to host incf rByteCnt,W ; Next char goto TxMessage ; Loop... ; msgdn bcf _HelpMsg ; Clear help msg flag goto breakack ; ; ; ; tblMode ; movf rMode,W ; andlw 3 ; addwf PCL,F ; DT "rimb" ; ; ; ; **************** Async Serial I/O ************** ; ; 104 us/bit = 9615.4 bps ; Stop bit should be at least 106 us to prevent framing errors ; ; --- Send char to host ; Warning: Requies one word of the stack SerTx ; bsf pSerTx,bSerTx ; Start bit clrwdt ; Clear watchdog movwf rSerTxChar ; Move W to Tx char movlw 9 ; 8 data bits + stop bit movwf rSerBitCnt ; movlw 29 ; Wait 1 bit time call Delay ; stxbit call SendBit ; Tx a bit movlw 28 ; Wait 1 bit time call Delay2 ; decfsz rSerBitCnt,F ; Dec bit count goto stxbit ; Not 0, do next bit... goto Delay2 ; Finish stop bit and return ; SendBit ; -- Send bit to host bsf STATUS,C ; 3 Shift in a 1 (stop bit) rrf rSerTxChar,F ; 4 Shift out a bit btfss STATUS,C ; 5 Is it a zero? goto $+4 ; 6(,7) Yes.. nop ; 7 Precise timing bcf pSerTx,bSerTx ; 8 Send a one (data is inverted, non-inverting buffer or direct connection used) retlw 0 ; 9,10 Return bsf pSerTx,bSerTx ; 8 Send a zero (data is inverted, non-inverting buffer or direct connection used) retlw 0 ; 9,10 Return ; ; ; ; --- Get char from host ; Note: Delay subs are not used so that stack usage is minimal SerRx movlw 8 ; 8 bits movwf rSerBitCnt ; clrf rSerRxChar ; Clear Rx char srxwsb clrwdt ; Reset watchdog btfss pSerRx,bSerRx ; Wait for start bit goto srxwsb ; movlw 46 ; Setup bit timer movwf rSerBitTmr ; srxwbt decfsz rSerBitTmr,F ; Wait for 1 1/2 bits time goto srxwbt ; srxbit nop ; bcf STATUS,C ; Assume 0 btfss pSerRx,bSerRx ; Check Rx state bsf STATUS,C ; Got a 1 rrf rSerRxChar,F ; Shift in the bit movlw 31 ; Setup bit timer movwf rSerBitTmr ; srxbt decfsz rSerBitTmr,F ; Wait for 1 bit time goto srxbt ; decfsz rSerBitCnt,F ; Dec bit count goto srxbit ; Not 0, do next bit... retlw 0 ; Return ; ; ; ; **************** Delay subroutines ******************* Delay2 goto $+1 ; --- 6 + ( N * 3 ) Cycle delay Delay ; --- 4 + ( N * 3 ) Cycle delay movwf rSerBitTmr ; 3 Setup timer decfsz rSerBitTmr,F ; 4 Decrement timer goto $-1 ; 5(,6) Loop if not zero... retlw 0 ; 6,7 Return ; ; TxAscii ; *************** Send ASCII results to host ************ ; ; movf rAscii,W ; Get sign btfss STATUS,Z ; Skip positive call SerTx ; To host... ; bsf _LeadZero ; Suppress zeros ; movlw 6 ; 6 bytes to tx movwf rByteCnt ; movlw rAscii+1 ; Setup pointer movwf FSR ; ; nextbyte ; bcf _DecPoint ; Assume not DP call GetDp ; Get decimal place subwf rByteCnt,W ; This one? btfss STATUS,Z ; goto notdec ; No... bsf _DecPoint ; goto txdigit ; Yes... ; notdec ; btfss _LeadZero ; Suppress zeros? goto txdigit ; No.. movf INDF,W ; Get a byte xorlw '0' ; Zero? btfsc STATUS,Z ; goto skiptx ; Yes... bcf _LeadZero ; Non-zero, stop checking for zeros ; txdigit ; movf INDF,W ; Get the byte again call SerTx ; Send to host ; btfss _DecPoint ; Skip if decimal should be sent goto skiptx ; No decimal... bcf _LeadZero ; No more zero supression movlw '.' ; Prepare to send DP call SerTx ; Send it ; skiptx ; incf FSR,F ; Point to next byte decfsz rByteCnt,F ; Dec byte count goto nextbyte ; Next byte... ; movf INDF,W ; Always send last byte call SerTx ; ; movlw 0x0D ; CR call SerTx ; movlw 0x0A ; LF call SerTx ; ; ; goto txdone ; ; ; ; ********************** Main routine ******************** Start ; movlw (1 << NOT_GPWU) | (1 << NOT_GPPU) option ; Set options ; movlw (1 << bSerRx) | (1< 7 andlw 0xf0 ; Low result >7 so don't take the 3 out btfsc INDF,7 ; Test if high result > 7 andlw 0x0f ; High result > 7 so don't take the 3 out subwf INDF,F ; Any results <= 7, subtract back incf FSR,F ; Point to next decfsz rCnt,F ; Dec byte count goto b2bcd3 ; Do next byte... ; rlf rBin+2,f ; Get another bit rlf rBin+1,f ; rlf rBin+0,f ; rlf rBcd+3,f ; Put it into bcd rlf rBcd+2,f ; rlf rBcd+1,f ; rlf rBcd+0,f ; decfsz rI,f ; All done? goto b2bcd2 ; No, loop ; ; ; ; --- Convert the 10 binary coded digits (5 bytes) starting at ; into an ascii string also starting at . Original ; bcd digits are lost. ; bcd2a movlw rAscii+7 ; movwf rPto ; Destination pointer movlw rBcd+3 ; movwf rPti ; Source pointer movlw 4 ; 4 bytes to process movwf rCnt ; ; bcd2a1 movf rPti,W ; Get current input pointer movwf FSR ; decf rPti,F ; Prepare for next movf INDF,W ; Get 2 bcds movwf rTemp ; Save for later movf rPto,W ; Get current output pointer movwf FSR ; decf rPto,F ; Prepare for next decf rPto,F ; movf rTemp,W ; Get digits back andlw 0x0f ; Process lsd movwf INDF ; movlw '0' ; addwf INDF,F ; To output decf FSR,F ; swapf rTemp,W ; Process msd andlw 0x0f ; movwf INDF ; movlw '0' ; addwf INDF,F ; To output decfsz rCnt,F ; All digits? goto bcd2a1 ; ; ; --- Fixup last digit for Inches movf rMode,W ; Get mode xorlw 1 ; Inches? btfss STATUS,Z ; goto mmraw ; No... ; movlw '5' ; Compare to 5 subwf rAscii+7,W ; Get last digit movlw '0' ; Assume <5 btfsc STATUS,C ; <5? movlw '5' ; No movwf rAscii+7 ; Update ; mmraw ; movlw 0 ; Assume no sign btfsc _Negative ; Need it? movlw '-' ; Put negative sign movwf rAscii ; To first char ; ; bcf STATUS,PA0 ; Clear page bit (page 0) goto TxAscii^PAGE1 ; Send to host... ; ; ; org 0x3FF ; ; movlw 0x60 ; 12C509A-JW OscCal ; end