;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; unpacked 8-digit decimal (each digit 0..9) to a 24-bit binary ~
; number in acc[2..0]. Range 0..16,777,215 however NCO range ~
; is 100,000..15,999,900 in 100-Hz steps (acc = frequency/100). ~
; ~
; nco1inc = bin = INT((frequency/100)*65536/10000+0.5) ~
; ~
; isochronous, 534/678 cycles Mike McLaren, K8LH, 28-Jan-'20 ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
radix dec
cblock 0x70
bcd:8 ; 8-digit decimal/bcd number
acc:3 ; 24-bit binary accumulator
ctr ; loop ctr var'
endc
rem equ bcd+4 ; 1-byte 'remainder'
bin equ bcd+6 ; 5-byte 'acc' * 65536
ncoCalc
movlw 24 ; |
movwf ctr ; |
movlw 10 ; |
bcd2lp
lsrf bcd+7,F ; |
skpnc ; |
addwf bcd+6,F ; add 10 |
lsrf bcd+6,F ; |
skpnc ; |
addwf bcd+5,F ; add 10 |
lsrf bcd+5,F ; |
skpnc ; |
addwf bcd+4,F ; add 10 |
lsrf bcd+4,F ; |
skpnc ; |
addwf bcd+3,F ; add 10 |
lsrf bcd+3,F ; |
skpnc ; |
addwf bcd+2,F ; add 10 |
lsrf bcd+2,F ; |
; skpnc ; skipping 2 least significant |
; addwf bcd+1,F ; digits effectively divides |
; lsrf bcd+1,F ; the bcd[7..0] value by 100 |
; skpnc ; |
; addwf bcd+0,F ; |
; lsrf bcd+0,F ; |
rrf acc+2,F ; |
rrf acc+1,F ; |
rrf acc+0,F ; |
decfsz ctr,F ; all 24 bits? yes, skip, else |
bra bcd2lp ; |
call div100 ; divide 'bin' by 10000 |
call div100 ; " |
movlw -50 ; rounding |
addwf rem,W ; " |
movlw 0 ; " |
addwfc bin+0,F ; " |
addwfc bin+1,F ; " |
addwfc bin+2,W ; " |
banksel NCO1INCU ; bank 09 on 16F18313/325 |09
movwf NCO1INCU ; set NCO1INCU |09
movf bin+1,W ; |09
movwf NCO1INCH ; set NCO1INCH |09
movf bin+0,W ; |09
movwf NCO1INCL ; set NCO1INCL |09
return ; |09
div100
movlw 40 ; |
movwf ctr ; |
clrf rem ; clear 'remainder' |
divLp rlf bin+0,W ; |
rlf bin+1,F ; |
rlf bin+2,F ; |
rlf bin+3,F ; |
rlf bin+4,F ; |
rlf rem,F ; |
movlw 100 ; |
subwf rem,W ; Does 100 go in? |
skpnc ; borrow? no, skip, else |
movwf rem ; update remainder (C = 1) |
rlf bin+0,F ; shift in the borrow bit |
decfsz ctr,F ; all 40 bits? yes, skip, else |
bra divLp ; loop |
return ; |