;
;==================================================================================================
; 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/ DEV 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
