; flash eeprom library
; by JHusak , 04.01.2020
; free to use.
lstore_x dta 0
; x - 0x0 or 0x40 - chip select
; c - 1 - format, 0 - write
	;.print flashcnt
flashoppreamble

	pha
	txa
	pha
	; when write byte x must be set to either 0 or 40 temporarily
	and #$40
	tax
	; $5555<$aa
@	sta $d502,x
	lda #$aa
	sta $b555
	; $2aaa<$55
	sta $d501,x
	lda #$55
	sta $aaaa
	; $5555<$80
	sta $d502,x
	; sector format: carry set
	scc
		lda #$80 ; sector erase
	scs
		lda #$a0 ; byte programm
	sta  $b555
	bcc @+
	; $5555<$aa
	sta $d502,x
	lda #$aa
	sta $b555
	; $2aaa<$55
	sta $d501,x
	lda #$55
	sta $aaaa

	; PREPARE FOR SECTOR TO ERASE

	; set upper bank bits
@	pla
	tax
	pla
	rts

; --------------------------
; PROCEDURE
; x = 0 or 0x40 - flash chip address.
store_x	dta 0
flashformatchip2
	ldx #$40
	dta { bit.w }
flashformatchip

	sei
	stx store_x
	sec ; format preamble
	jsr flashoppreamble ; does not touch A
	sta $d502,x
	lda #$10
	sta $b555
	lda #$ff
	sta flashcmp
	jsr flashcheckresult
	beq @+
		; cart is off and cli
;		sec ; error
;		rts
@	lda #$3f
	sta flashformatcounter
@	sei
	ldx store_x
flashformatcounter equ*+1
	sta $d5FF,x ; set chip (x) and bank
	; set pages count
	ldy #$20
	; reset address
	lda #$a0
	sta flashformataddrcheck + 2
	; check whole sector against 0xff
	jsr flashchecksectorformatted_bare ; destroys x
	bcs @+ ; format error
	dec flashformatcounter
	bpl @-
@	jmp flashcartoff ; preserves C

	
; --------------------------
; PROCEDURE
flashformatsector
; x - even sector 00 - 7f
; a - erase 4KB from $B000 if A=$B0, FROM $A000 IF A=$A0
; format 4kb evensector 
; strange form - easily maps to cartridge banks
; to format bank, must format sector (x<<1) and (x<<1) +1
	; first check if all ff
	; this is to avoid wear
	stx flashformatstorex
	sta flashformatstorea
	sei
	sta $d500,x
	sta flashformataddrcheck + 2
	jsr flashchecksectorformatted	
	bcc flashsectorformatgood
	sei
flashformatstorex	equ * + 1
	ldx #0 ; filled before
flashformatstorea	equ * + 1
	lda #0 ; filled before
; check least sector bit

	sec ; format preamble
	jsr flashoppreamble ; does not touch A,X
	sta $D500,x
	; A must be either $A0 or $B0
	sta flashtmpaddr+1
	sta flashformataddrcheck + 2

	lda #$30
flashtmpaddr	equ	*+1
	sta $a000 ; Format!
	jsr flashcheckresult
	sei

	lda flashformatstorea
	sta flashformataddrcheck+2
	
	ldx flashformatstorex
	sta $d500,x

	; check if all data in sector is $ff
flashchecksectorformatted
	ldy #$10
flashchecksectorformatted_bare
	lda #$ff
	ldx #0
flashformataddrcheck
	cmp $a000,x
	bne flashsectorformaterror
	inx
	bne flashformataddrcheck
	inc flashformataddrcheck + 2
	dey
	bne flashformataddrcheck
	 
flashsectorformatgood
	jsr flashcartoff
	clc
	rts
	
flashsectorformaterror
	jsr flashcartoff
	sec
	rts


; ---------------------
; PROCEDURE

flashwritebyte

; a - byte to write
; x - 8kb bank to switch, $00 to $7f, also chip select
; flashaddr - addres in flash - must be a000-offset
	; do not programm byte if already good
	sei	
	sta $D500,x ; select bank, chip
	ldy #{ cmp.w }
	jsr flashprocessbyte
	bne @+
	 ;clc
	 ;jmp flashcartoff
	sta $D580
	cli
	clc
	rts
@	sta flashcmp

	sei
	clc ; write byte preamble
	jsr flashoppreamble ; preserves A,X
	
	sta $D500,x
	
	ldy #{ sta.w }
	; WRITE BYTE !
	jsr flashprocessbyte

flashcheckresult ; sei mode
	mva #0 flashcnt
	ldy #5 ; first time wait short first turn to speed up byte write.
	bne @+

flashwaitfordone
	; approx 100ms in overall for chip erase:
	; as many cycles needed, as 256*cycles >100ms * (1+epsilon)
	; 100 ms is 180000 cycles
	; so max 256 rough loops must last longer
	; 180000 / 256 = 703
	; 700 cycles by 6 cycles loop lasts = 116.
	; so flipipng values, and adding margin,
	; we count 128*6 cycles in inner loop.
	; max sector erase by datasheet: 25 ms
	; max chip erase by datasheet: 100 ms
	ldy#250
@	dey
	nop
	bne @-
	
@	ldy #{ lda.w }
	jsr flashprocessbyte
	ldy #{ eor.w }
	jsr flashprocessbyte
	inc flashcnt
	bne @+
		jsr flashcartoff
		lda #$ff ; status
		rts
@
	and #$40
	bne flashwaitfordone
; in acc will be mismatched byte
	ldy #{ lda.w }
	jsr flashprocessbyte
	jsr flashcartoff ; preserves axy, not p
flashcmp	equ *+1
	cmp #0
; when non zero = error
	rts

flashcnt
	dta 0
; ----------------------
; PROCEDURE

flashprocessbyte

; y - byteop for cpu to do with byte 
; flashaddr - stored address
	sty flashbyteop
flashaddr	equ *+1
flashbyteop
	sta $aaaa
	rts

flashincaddr
	inw flashaddr
	rts

flashsetaddr
	stx flashaddr
	sty flashaddr+1
	rts

flashcartoff
	pha
	sta $d580
	lda $d013
	sta $3fa
	cli
	pla
	rts

; PROCEDURE
; Y-char to write
PRINTWHAT
	php
	pha
	txa
	pha
	tya
	pha
	jsr $f2b0
	pla
	tay
	pla
	tax
	pla
	plp
	rts
PRINTDOT
	php
	pha
	txa
	pha
	tya
	pha
	lda #'.'
	jsr $f2b0
	pla
	tay
	pla
	tax
	pla
	plp
	rts
; ----------------------- IINT
;	org $2e2
;	dta a($600)
