; Binary to BCD conversion routine
radix dec
; variables
cblock 0x20
x0,x1,x2,y0,y1,y2
digit0,digit1,digit2,digit3,digit4,digit5
endc
Bin2BCD
;On entry the binary number is in registers y0 (LSB), y1, y2 (MSB)
; maximum allowable binary value is 10*2^16-1 = 655359
clrf digit0 ;initialize the digits to zero
clrf digit1
clrf digit2
clrf digit3
clrf digit4
clrf digit5
movlw Digit0 ; Initialize the digit array pointer
movwf fsr0L
clrf fsr0H
movf y2,w
iorwf y1,w
DigitLoop
; This outer loop iterates once per actual decimal digit. So, if the
; decimal result is only one digit, the loop executes only once.
; For an input value of zero it won't execute at all.
;
; Do While y0<>0 or y1<>0 or y2<>0
iorwf y0,w
btfsc status,z
return
incfsz y0,f ; increment y to compensate for series truncation error
goto Div10
incfsz y1,f
goto Div10
incf y2,f
;******************
Div10
; Divide by 10 using the infinite series method
; On entry the dividend is in registers y0..y2
; On completion the quotient is in y0..y2 with y0 containing part integer and part fraction
; Registers x0, x1, x2 are temporary registers holding the 3 byte series term(i)
lslf y0,w ; multiply dividend by 3
movwf x0 ;copy shifted y to x
rlf y1,w
movwf x1
rlf y2,w
movwf x2
movf x0,w ;add x to y
addwf y0,f
movf x1,w
addwfc y1,f
movf x2,w
addwfc y2,f
lslf y0,f ;now shift y left 3 positions
rlf y1,f
rlf y2,f
lslf y0,f
rlf y1,f
rlf y2,f
lslf y0,f
rlf y1,f
rlf y2,f
movf y0,w ;copy y back to x
movwf x0
movf y1,w
movwf x1
movf y2,w
movwf x2
Div10Loop
; This inner loop never takes more than 4 iterations.
; Number of iterations is proportional to magnitude of y.
; Do While x2<>0 or x1<>0
iorwf x1,w
btfsc status,z
goto Div10Done
;shift x0..x2 right 4 places
lsrf x2,f
rrf x1,f
rrf x0,f
lsrf x2,f
rrf x1,f
rrf x0,f
lsrf x2,f
rrf x1,f
rrf x0,f
lsrf x2,f
rrf x1,f
rrf x0,f
movf x0,w ;add x to y
addwf y0,f
movf x1,w
addwfc y1,f
movf x2,w
addwfc y2,f
goto Div10Loop ; Wend
Div10Done
; Quotient is in y0..y2 (y0 has fractional part; y1,y2 have integer part)
;****************** End of Divide by 10 routine
;
; extract current raw BCD digit from y0 and multiply by 10
lsrf y0,w
movwf x0
lsrf x0,w
movwf x1
lsrf x1,w
addwf x0,f ; digit(i) = high nibble of x0
swapf x0,w
andlw 0x0F
movwi fsr0++ ;save digit in output register
movf y1,w ; divide y by 2^8 for next iteration
movwf y0
movf y2,w
movwf y1
clrf y2
goto DigitLoop ; rinse and repeat
end