; flash eeprom library ; by JHusak , 04.01.2020 ; free to use. ; x - bank to select on exit ; c - 1 - format, 0 - write ;.print flashcnt flashoppreamble ; $5555<$aa sty $d502 ldy #$aa sty $b555 ; $2aaa<$55 sty $d501 ldy #$55 sty $aaaa ; $5555<$80 sty $d502 ; sector format: carry set scc ldy #$80 ; sector erase scs ldy #$a0 ; byte programm sty $b555 bcc @+ ; $5555<$aa sty $d502 ldy #$aa sty $b555 ; $2aaa<$55 sty $d501 ldy #$55 sty $aaaa ; PREPARE FOR SECTOR TO ERASE ; set upper bank bits @ rts ; -------------------------- ; PROCEDURE flashformatchip sei sec ; format preamble jsr flashoppreamble ; does not touch A sta $d502 lda #$10 sta $b555 lda #$ff sta flashcmp jsr flashcheckresult beq @+ ; cart is off and cli ; sec ; error ; rts @ lda #$1f sta flashformatcounter @ sei flashformatcounter equ*+1 sta $d51f ldx #0 ldy #$20 lda #$a0 sta flashformataddrcheck + 2 lda #$ff jsr flashformataddrcheck bcs @+ ; format error dec flashformatcounter bpl @- @ jmp flashcartoff ; preserves C ; -------------------------- ; PROCEDURE flashformatsector ; x - even sector 00 - 1f ; 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 ;php ;lda #'F' ;jsr PRINTWHAT ;plp 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 ldx #0 ldy #$10 lda #$ff 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 ; flashaddr - addres in flash - must be a000-offset ; do not programm byte if already good sei sta $D500,x ldy #{ cmp.w } jsr flashprocessbyte bne @+ sta $D580 cli clc rts @ sta flashcmp sei clc ; write byte preamble jsr flashoppreamble ; preserves A,X sta $D500,x ldy #{ sta.w } 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 brk ; ---------------------- ; 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)