;======================================================================
; FLASH LIBRARY
;======================================================================
; FLASH IDENTIFY
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  ISSUE ID COMMAND
;  READ IN ID WORD
;  ISSUE ID EXIT COMMAND
;  SELECT ORIGINAL BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          A  CONTAINS CURRENT BANK 
; ON EXIT  BC CONTAINS ID WORD
;          NO STATUS IS RETURNED 
;======================================================================
;
	.DB	MD_I_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FIDEN_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	LD	D,A			; SAVE CURRENT BANK
;
	LD	A,B			; SELECT BANK
	CALL	HBX_BNKSEL		; TO PROGRAM
;
	LD	HL,$5555		; LD	A,$AA			; COMMAND
	LD	(HL),$AA		; LD	($5555),A		; SETUP
	LD	A,H			; LD	A,$55
	LD	($2AAA),A		; LD	($2AAA),A
	LD	(HL),$90		; LD	A,$90
;					; LD	($5555),A
	LD	BC,($0000)						; READ ID
;
	LD	A,$F0			; LD	A,$F0			; EXIT 
	LD	(HL),A			; LD	($5555),A		; COMMAND
;
	LD	A,D			; RETURN TO ORIGINAL BANK
	JP	HBX_BNKSEL		; WHICH IS OUR RAM BIOS COPY
;
MD_I_SZ	.EQU	$-MD_FIDEN_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
;
;======================================================================
; ERASE FLASH SECTOR. 
;
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  ISSUE ERASE SECTOR COMMAND
;  POLL TOGGLE BIT FOR COMPLETION STATUS.
;  SELECT ORIGINAL BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          A  CONTAINS CURRENT BANK 
; ON EXIT  C  RETURNS STATUS 0=SUCCESS NZ=FAIL
;======================================================================
;
	.DB	MD_S_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FERAS_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	PUSH	AF			; SAVE CURRENT BANK
	LD	A,B			; SELECT BANK
	CALL	HBX_BNKSEL		; TO PROGRAM
;
	LD	HL,$5555		; LD	($5555),A
	LD	DE,$2AAA		; LD	A,$55	
	LD	A,L			; LD	($2AAA),A		
	LD	(HL),E			; LD	A,$80		
	LD	(DE),A			; LD	($5555),A		
	LD	(HL),$80		; LD	A,$AA		
	LD	(HL),E			; LD	($5555),A		
	LD	(DE),A			; LD	A,$55		
;					; LD	($2AAA),A		
	LD	H,C			; SECTOR 
	LD	L,$00			; ADDRESS
;
	LD	A,$30			; SECTOR ERASE
	LD	(HL),A			; COMMAND
;
MD_WT4:	LD	A,(HL)			; DO TWO SUCCESSIVE READS
	LD	C,(HL)			; FROM THE SAME FLASH ADDRESS.
	XOR	C			; IF THE SAME ON BOTH READS
	BIT	6,A			; THEN ERASE IS COMPLETE SO EXIT.
;
	JR	Z,MD_WT5		; BIT 6 = 0 IF SAME ON SUCCESSIVE READS = COMPLETE
					; BIT 6 = 1 IF DIFF ON SUCCESSIVE READS = INCOMPLETE
;
	LD	A,C			; OPERATION IS NOT COMPLETE. CHECK TIMEOUT BIT (BIT 5).
	BIT	5,C			; IF NO TIMEOUT YET THEN LOOP BACK AND KEEP CHECKING TOGGLE STATUS
	JR	Z,MD_WT4		; IF BIT 5=0 THEN RETRY; NZ TRUE IF BIT 5=1
;
	LD	A,(HL)			; WE GOT A TIMOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE 
	XOR	(HL)			; THE OPERATION. DO TWO SUCCESSIVE READS. ARE THEY THE SAME?
	BIT	6,A			; IF THEY ARE THEN OPERATION WAS COMPLETED					
	JR	Z,MD_WT5		; OTHERWISE ERASE OPERATION FAILED OR TIMED OUT.
;
	LD	C,$F0			; COMMON FAIL STATUS / PREPARE DEVICE RESET CODE
	LD	(HL),C			; WRITE DEVICE RESET
	JR	MD_WT6
MD_WT5:	LD	C,L			; SET SUCCESS STATUS
;
MD_WT6:	POP	AF			; RETURN TO ORIGINAL BANK
	JP	HBX_BNKSEL		; WHICH IS OUR RAM BIOS COPY
;
MD_S_SZ	.EQU	$-MD_FERAS_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
;
;======================================================================
; FLASH READ SECTOR. 
;
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  READ SECTOR OF 4096 BYTES, BYTE AT A TIME
;  SELECT SOURCE BANK,  READ DATA,
;	   SELECT DESTINATION BANK, WRITE DATA
;          DESTINATION BANK IS ALWAYS CURRENT BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          DE = 0000 BYTE COUNT
;          IX POINTS TO DATA TO BE WRITTEN
;          A  CONTAINS CURRENT BANK 
; ON EXIT  NO STATUS RETURNED
;======================================================================
;
	.DB	MD_R_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FREAD_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	LD	H,C			; SECTOR
	LD	L,D			; ADDRESS
;
	PUSH	AF			; SAVE CURRENT BANK
;
MD_FRD1:LD	A,B			; CHANGE TO SOURCE BANK
	CALL	HBX_BNKSEL		; READ
	LD	C,(HL)			; BYTE
;	
	POP	AF			; RESTORE CURRENT BANK
	PUSH	AF                      ; AND SAVE A COPY FOR NEXT LOOP
	CALL	HBX_BNKSEL		; SELECT BANK TO WRITE TO
;
	LD	(IX+0),C		; WRITE BYTE
;
	INC	HL			; NEXT SOURCE LOCATION
	INC	IX			; NEXT DESTINATION LOCATION
;
	INC	DE			; CONTINUE READING UNTIL
	BIT	4,D			; WE HAVE DONE ONE SECTOR
	JR	Z,MD_FRD1
;
	POP	AF
	RET				
;
MD_R_SZ	.EQU	$-MD_FREAD_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
;
;======================================================================
; FLASH VERIFY SECTOR. 
;
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  VERIFY SECTOR OF 4096 BYTES, BYTE AT A TIME
;  SELECT SOURCE BANK,  READ DATA,
;	   SELECT DESTINATION BANK, COMPARE DATA
;          DESTINATION BANK IS ALWAYS CURRENT BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          DE = 0000 BYTE COUNT
;          IX POINTS TO DATA TO BE VERIFIED
;          A  CONTAINS CURRENT BANK 
; ON EXIT  C  RETURNS STATUS 0=SUCCESS NZ=FAIL
;======================================================================
;
	.DB	MD_V_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FVERI_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	LD	H,C			; SECTOR
	LD	L,D			; ADDRESS
;
	PUSH	AF			; SAVE CURRENT BANK
;
MD_FVE1:LD	A,B			; SELECT BANK
	CALL	HBX_BNKSEL		; TO READ 
	LD	C,(HL)			; READ BYTE
;
	POP	AF			; RESTORE CURRENT BANK
	PUSH	AF			; AND SAVE A COPY FOR NEXT LOOP
	CALL	HBX_BNKSEL		; TO VERIFY AGAINST
;
	LD	A,C
	SUB	(IX+0)			; COMPARE BYTE
	LD	C,A			; SET STATUS
	JR	NZ,MD_FVE2		; EXIT IF MISMATCH
;
	INC	HL			; NEXT SOURCE LOCATION
	INC	IX			; NEXT DESTINATION LOCATION
;
	INC	DE			; CONTINUE READING UNTIL
	BIT	4,D			; WE HAVE DONE ONE SECTOR
	JR	Z,MD_FVE1
;
MD_FVE2:POP	AF
	RET				
;
MD_V_SZ	.EQU	$-MD_FVERI_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
;
;======================================================================
; FLASH WRITE SECTOR. 
;
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  WRITE 1 SECTOR OF 4096 BYTES, BYTE AT A TIME
;   ISSUE WRITE BYTE COMMAND AND WRITE THE DATA BYTE
;   POLL TOGGLE BIT FOR COMPLETION STATUS.
;  SELECT ORIGINAL BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          IX POINTS TO DATA TO BE WRITTEN
;          DE = 0000 BYTE COUNT
;          A  CONTAINS CURRENT BANK 
; ON EXIT  NO STATUS IS RETURNED
;======================================================================
;
	.DB	MD_W_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FWRIT_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	LD	H,C			; SECTOR
	LD	L,D			; ADDRESS
;
	PUSH	AF			; SAVE CURRENT BANK
MD_FWR1:CALL	HBX_BNKSEL		; SELECT BANK TO READ
;
	LD	C,(IX+0)		; READ IN BYTE
;
	LD	A,B			; SELECT BANK
	CALL	HBX_BNKSEL		; TO PROGRAM
;
	LD	A,$AA			; COMMAND
	LD	($5555),A		; SETUP
	LD	A,$55
	LD	($2AAA),A
;
	LD	A,$A0			; WRITE
	LD	($5555),A		; COMMAND
;
	LD	(HL),C			; WRITE OUT BYTE
;
;					; DO TWO SUCCESSIVE READS 
MD_FWR2:LD	A,(HL)			; FROM THE SAME FLASH ADDRESS. 
	LD	C,(HL)			; IF TOGGLE BIT (BIT 6) 
	XOR	C			; IS THE SAME ON BOTH READS
	BIT	6,A			; THEN WRITE IS COMPLETE SO EXIT.
	JR	NZ,MD_FWR2		; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. 
;
	INC	HL			; NEXT DESTINATION LOCATION
	INC	IX			; NEXT SOURCE LOCATION
;
	POP	AF			; RESTORE CURRENT BANK
	PUSH	AF			; AND SAVE A COPY FOR NEXT LOOP
;
	INC	DE			; CONTINUE WRITING UNTIL
	BIT	4,D			; WE HAVE DONE ONE SECTOR
	JR	Z,MD_FWR1
;
	POP	AF			; RESTORE CURRENT BANK
	JP	HBX_BNKSEL		; RETURN TO ORIGINAL BANK WHICH IS OUR RAM BIOS COPY
;
MD_W_SZ	.EQU	$-MD_FWRIT_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
;
;======================================================================
; ERASE FLASH CHIP. 
;
;  SELECT THE APPROPRIATE BANK / ADDRESS
;  ISSUE ERASE COMMAND
;  POLL TOGGLE BIT FOR COMPLETION STATUS.
;  SELECT ORIGINAL BANK
;
; ON ENTRY BC CONTAINS BANK AND SECTOR DATA
;          A  CONTAINS CURRENT BANK 
; ON EXIT  A  RETURNS STATUS 0=SUCCESS FF=FAIL
;======================================================================
;
	.DB	MD_E_SZ			; SIZE OF RELOCATABLE CODE BUFFER REQUIRED
MD_FERAC_R:				; THIS CODE GETS RELOCATED TO HIGH MEMORY
;
	PUSH	AF			; SAVE CURRENT BANK
	LD	A,B			; SELECT BANK
	CALL	HBX_BNKSEL		; TO PROGRAM
;
	LD	HL,$5555		; LD	A,$AA		; COMMAND
	LD	(HL),$AA		; LD	($5555),A	; SETUP
	LD	A,L			; LD	A,$55
	LD	($2AAA),A		; LD	($2AAA),A
	LD	(HL),$80		; LD	A,$80
	LD	(HL),$AA		; LD	($5555),A
	LD	A,L			; LD	A,$AA
	LD	($2AAA),A		; LD	($5555),A
	LD	(HL),$10		; LD	A,$55
					; LD	($2AAA),A
					; LD	A,$10
					; LD	($5555),A
;
FF_WT2:	LD	A,(HL)			; DO TWO SUCCESSIVE READS FROM THE SAME FLASH ADDRESS. 
	LD	C,(HL)			; IF TOGGLE BIT (BIT 6) 
	XOR	C			; IS THE SAME ON BOTH READS
	BIT	6,A			; THEN ERASE IS COMPLETE SO EXIT.
	JR	Z,FF_WT1		; Z TRUE IF BIT 6=0 I.E. "NO TOGGLE" WAS DETECTED. 
;
	LD	A,C			; OPERATION IS NOT COMPLETE. CHECK TIMEOUT BIT (BIT 5).
	BIT	5,C			; IF NO TIMEOUT YET THEN LOOP BACK AND KEEP CHECKING TOGGLE STATUS
	JR	Z,FF_WT2		; IF BIT 5=0 THEN RETRY; NZ TRUE IF BIT 5=1
;
	LD	A,(HL)			; WE GOT A TIMEOUT. RECHECK TOGGLE BIT IN CASE WE DID COMPLETE 
	XOR	(HL)			; THE OPERATION. DO TWO SUCCESSIVE READS. ARE THEY THE SAME?
	BIT	6,A			; IF THEY ARE THEN OPERATION WAS COMPLETED					
	JR	Z,FF_WT1		; OTHERWISE ERASE OPERATION FAILED OR TIMED OUT.
;
	LD	(HL),$F0		; WRITE DEVICE RESET
	LD	C,$FF			; SET FAIL STATUS
	JR	FF_WT3
;
FF_WT1:	LD	C,0			; SET SUCCESS STATUS
FF_WT3:	POP	AF
;	LD	A,B			; RETURN TO ORIGINAL BANK
	JP	HBX_BNKSEL		; WHICH IS OUR RAM BIOS COPY
;
MD_E_SZ	.EQU	$-MD_FERAC_R		; SIZE OF RELOCATABLE CODE BUFFER REQUIRED

;======================================================================
;
; RELOCATABLE CODE SPACE REQUIREMENTS CHECK
;
;======================================================================
;
MD_CSIZE	.EQU	0
;
#IF (MD_W_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_W_SZ
#ENDIF
#IF (MD_S_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_S_SZ
#ENDIF
#IF (MD_I_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_I_SZ
#ENDIF
#IF (MD_R_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_R_SZ
#ENDIF
#IF (MD_V_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_V_SZ
#ENDIF
#IF (MD_E_SZ>MD_CSIZE)
MD_CSIZE	.SET	MD_E_SZ
#ENDIF
;
#IF (MD_CSIZE>64)
		.ECHO	"Warning: Flash code exceeds available space by "
		.ECHO	MD_CSIZE-64
		.ECHO	" bytes.\n"
		.ECHO	"MD_FIDEN_R "
		.ECHO	MD_I_SZ
		.ECHO	"\n"
;
		.ECHO	"MD_FREAD_R "
		.ECHO	MD_R_SZ
		.ECHO	"\n"
;
		.ECHO	"MD_FVERI_R "
		.ECHO	MD_V_SZ
		.ECHO	"\n"
;
		.ECHO	"MD_FERAS_R "
		.ECHO	MD_S_SZ
		.ECHO	"\n"
;
		.ECHO	"MD_FWRIT_R "
		.ECHO	MD_W_SZ
		.ECHO	"\n"
;
		.ECHO	"MD_FERAC_R "
		.ECHO	MD_E_SZ
		.ECHO	"\n"
#ENDIF