mirror of https://github.com/wwarthen/RomWBW.git
6 changed files with 1294 additions and 6 deletions
@ -0,0 +1,79 @@ |
|||||
|
; |
||||
|
;================================================================================================== |
||||
|
; DECODE 32-BIT VALUES FROM A 5-BIT SHIFT-ENCODED VALUE |
||||
|
;================================================================================================== |
||||
|
; |
||||
|
; Copyright (C) 2014 John R. Coffman. All rights reserved. |
||||
|
; Provided for hobbyist use on the Z180 SBC Mark IV board. |
||||
|
; |
||||
|
; This program is free software: you can redistribute it and/or modify |
||||
|
; it under the terms of the GNU General Public License as published by |
||||
|
; the Free Software Foundation, either version 3 of the License, or |
||||
|
; (at your option) any later version. |
||||
|
; |
||||
|
; This program is distributed in the hope that it will be useful, |
||||
|
; but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
; GNU General Public License for more details. |
||||
|
; |
||||
|
; You should have received a copy of the GNU General Public License |
||||
|
; along with this program. If not, see <http://www.gnu.org/licenses/>. |
||||
|
; |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; |
||||
|
; THE FUNCTION(S) IN THIS FILE ARE BASED ON LIKE FUNCTIONS CREATED BY JOHN COFFMAN |
||||
|
; IN HIS UNA BIOS PROJECT. THEY ARE INCLUDED HERE BASED ON GPLV3 PERMISSIBLE USE. |
||||
|
; |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; |
||||
|
; An encoded value (V) is defined as V = C * 2^X * 3^Y |
||||
|
; where C is a prearranged constant, X is 0 or 1 and Y is 0-15 |
||||
|
; The encoded value is stored as 5 bits: YXXXX |
||||
|
; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding |
||||
|
; |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; DECODE |
||||
|
; |
||||
|
; Enter with: |
||||
|
; HL = word to be decoded (5-bits) FXXXX |
||||
|
; F=extra 3 factor, XXXX=shift factor, reg H must be zero |
||||
|
; DE = encode divisor OSC_DIV = 3, or BAUD_DIV = 75 |
||||
|
; |
||||
|
; Exit with: |
||||
|
; DE:HL = decoded value |
||||
|
; A = non-zero on error |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; |
||||
|
decode: |
||||
|
ld a,h ; set to test |
||||
|
ld c,$ff ; presume error condition |
||||
|
or a ; test for zero |
||||
|
jr nz,decode9 ; not an encoded value |
||||
|
ld a,l ; get low order 5 bits |
||||
|
cp 32 ; test for error |
||||
|
jr nc,decode9 ; error return if not below |
||||
|
; argument hl is validated |
||||
|
ld h,d |
||||
|
ld l,e ; copy to hl |
||||
|
cp 16 |
||||
|
jr c,decode2 ; if < 16, no 3 factor |
||||
|
add hl,de ; introduce factor of 3 |
||||
|
add hl,de ; ** |
||||
|
decode2: |
||||
|
ld de,0 ; zero the high order |
||||
|
and 15 ; mask to 4 bits |
||||
|
jr z,decode8 ; good exit |
||||
|
ld c,b ; save b-reg |
||||
|
ld b,a ; |
||||
|
decode3: |
||||
|
add hl,hl ; shift left by 1, set carry |
||||
|
rl e |
||||
|
rl d ; ** |
||||
|
djnz decode3 |
||||
|
ld b,c ; restore b-reg |
||||
|
decode8: |
||||
|
ld c,0 ; signal good return |
||||
|
decode9: |
||||
|
ld a,c ; error code test |
||||
|
or a ; error code in reg-c and z-flag |
||||
|
ret |
||||
@ -0,0 +1,75 @@ |
|||||
|
; |
||||
|
;================================================================================================== |
||||
|
; ENCODE 32-BIT VALUES TO A 5-BIT SHIFT-ENCODED VALUE |
||||
|
;================================================================================================== |
||||
|
; |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; |
||||
|
; An encoded value (V) is defined as V = C * 2^X * 3^Y |
||||
|
; where C is a prearranged constant, Y is 0 or 1 and X is 0-15 |
||||
|
; The encoded value is stored as 5 bits: YXXXX |
||||
|
; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding |
||||
|
; |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; ENCODE |
||||
|
; |
||||
|
; Enter with: |
||||
|
; DE:HL = dword value to be encoded |
||||
|
; C = divisor (0 < C < 256) |
||||
|
; encode divisor OSC_DIV = 3, or BAUD_DIV = 75 |
||||
|
; |
||||
|
; Exit with: |
||||
|
; C = encoded value |
||||
|
; A = non-zero on error |
||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||||
|
; |
||||
|
encode: |
||||
|
; incoming value of zero is a failure |
||||
|
call encode5 ; test DE:HL for zero |
||||
|
jr z,encode4 ; if zero, failure return |
||||
|
; |
||||
|
; apply encoding divisor |
||||
|
call div32x8 ; DE:HL / C (remainder in A) |
||||
|
or a ; set flags to test for zero |
||||
|
ret nz ; error if not evenly divisible |
||||
|
; |
||||
|
; test divide by 3 to see if it is possible |
||||
|
push de ; save working |
||||
|
push hl ; ... value |
||||
|
ld c,3 ; divide by 3 |
||||
|
call div32x8 ; ... test |
||||
|
pop hl ; restore working |
||||
|
pop de ; ... value |
||||
|
; |
||||
|
; implmement divide by 3 if possible |
||||
|
ld c,$00 ; init result in c w/ div 3 flag clear |
||||
|
or a ; set flags to test for remainder |
||||
|
jr nz,encode2 ; jump if it failed |
||||
|
; |
||||
|
; if divide by 3 worked, do it again for real |
||||
|
ld c,3 ; setup to divide by 3 again |
||||
|
call div32x8 ; do it |
||||
|
ld c,$10 ; init result in c w/ div 3 flag set |
||||
|
; |
||||
|
encode2: |
||||
|
; loop to determine power of 2 |
||||
|
ld b,16 ; can only represent up to 2^15 |
||||
|
encode3: |
||||
|
srl d ; right shift de:hl into carry |
||||
|
rr e ; ... |
||||
|
rr h ; ... |
||||
|
rr l ; ... |
||||
|
jr c,encode5 ; if carry, then done, c has result |
||||
|
inc c ; bump the result value |
||||
|
djnz encode3 ; keep shifting if possible |
||||
|
encode4: |
||||
|
or $ff ; signal error |
||||
|
ret ; and done |
||||
|
; |
||||
|
encode5: |
||||
|
; test de:hl for zero (sets zf, clobbers a) |
||||
|
ld a,h |
||||
|
or l |
||||
|
or d |
||||
|
or e |
||||
|
ret ; ret w/ Z set if DE:HL == 0 |
||||
File diff suppressed because it is too large
@ -0,0 +1,104 @@ |
|||||
|
;; |
||||
|
;; make a bcd number from a binary number |
||||
|
;; 32 bit binary number in hl:bc, result stored at (de) |
||||
|
;; de is preserved, all other regs destroyed |
||||
|
;; |
||||
|
;bin2bcd: |
||||
|
; push ix ; save ix |
||||
|
; push bc ; move bc |
||||
|
; pop ix ; ... to ix |
||||
|
; ld c,32 ; loop for 32 bits of binary dword |
||||
|
;; |
||||
|
;bin2bcd0: |
||||
|
; ; outer loop (once for each bit in binary number) |
||||
|
; ld b,5 ; loop for 5 bytes of result |
||||
|
; push de ; save de |
||||
|
; add ix,ix ; left shift next bit from hl:ix |
||||
|
; adc hl,hl ; ... into carry |
||||
|
;; |
||||
|
;bin2bcd1: |
||||
|
; ; inner loop (once for each byte of bcd number) |
||||
|
; ld a,(de) ; get it |
||||
|
; adc a,a ; double it w/ carry |
||||
|
; daa ; decimal adjust |
||||
|
; ld (de),a ; save it |
||||
|
; inc de ; point to next bcd byte |
||||
|
; djnz bin2bcd1 ; loop thru all bcd bytes |
||||
|
;; |
||||
|
; ; remainder of outer loop |
||||
|
; pop de ; recover de |
||||
|
; dec c ; dec bit counter |
||||
|
; jr nz,bin2bcd0 ; loop till done with all bits |
||||
|
; pop ix ; restore ix |
||||
|
; |
||||
|
; make a bcd number from a binary number |
||||
|
; 32 bit binary number in de:hl, result stored at (bc) |
||||
|
; on output hl = bcd buf adr |
||||
|
; |
||||
|
bin2bcd: |
||||
|
push ix ; save ix |
||||
|
; convert from de:hl -> (bc) to hl:ix -> (de) |
||||
|
; hl -> ix, de -> hl, bc -> de |
||||
|
ex de,hl |
||||
|
push de |
||||
|
pop ix |
||||
|
push bc |
||||
|
pop de |
||||
|
; |
||||
|
ld c,32 ; loop for 32 bits of binary dword |
||||
|
; |
||||
|
bin2bcd0: |
||||
|
; outer loop (once for each bit in binary number) |
||||
|
ld b,5 ; loop for 5 bytes of result |
||||
|
push de ; save de |
||||
|
add ix,ix ; left shift next bit from hl:ix |
||||
|
adc hl,hl ; ... into carry |
||||
|
; |
||||
|
bin2bcd1: |
||||
|
; inner loop (once for each byte of bcd number) |
||||
|
ld a,(de) ; get it |
||||
|
adc a,a ; double it w/ carry |
||||
|
daa ; decimal adjust |
||||
|
ld (de),a ; save it |
||||
|
inc de ; point to next bcd byte |
||||
|
djnz bin2bcd1 ; loop thru all bcd bytes |
||||
|
; |
||||
|
; remainder of outer loop |
||||
|
pop de ; recover de |
||||
|
dec c ; dec bit counter |
||||
|
jr nz,bin2bcd0 ; loop till done with all bits |
||||
|
ex de,hl ; hl -> bcd buf |
||||
|
pop ix ; restore ix |
||||
|
ret |
||||
|
; |
||||
|
; print contents of 5 byte bcd number at (hl) |
||||
|
; with leading zero suppression |
||||
|
; all regs destroyed |
||||
|
; |
||||
|
prtbcd: |
||||
|
inc hl ; bump hl to point to |
||||
|
inc hl ; ... |
||||
|
inc hl ; ... |
||||
|
inc hl ; ... last byte of bcd |
||||
|
ld b,5 ; loop for 5 bytes |
||||
|
ld c,0 ; start by suppressing leading zeroes |
||||
|
; |
||||
|
prtbcd1: |
||||
|
; loop to print one bcd byte (two digits) |
||||
|
xor a ; clear accum |
||||
|
rld ; rotate first nibble into a |
||||
|
call prtbcd2 ; print it |
||||
|
xor a ; clear accum |
||||
|
rld ; rotate second nibble into a |
||||
|
call prtbcd2 ; print it |
||||
|
dec hl ; point to prior byte |
||||
|
djnz prtbcd1 ; loop till done |
||||
|
ret ; return |
||||
|
; |
||||
|
prtbcd2: |
||||
|
; subroutine to print a digit in a |
||||
|
cp c ; compare incoming to c |
||||
|
ret z ; if equal, suppressing, abort |
||||
|
dec c ; make c negative to stop suppression |
||||
|
add a,'0' ; offset to printable value |
||||
|
jp prtchr ; exit via character out |
||||
Loading…
Reference in new issue