; *** Consts ***
; Memory address where the AT28 is configured to start
equ     AT28W_MEMSTART          0x2000

; Value mismatch during validation
equ     AT28W_ERR_MISMATCH      0x10

; *** Variables ***
equ     AT28W_MAXBYTES  AT28W_RAMSTART
equ     AT28W_RAMEND    @+2
; *** Code ***

at28wMain:
       ld      de, AT28W_MAXBYTES
       ld      a, (hl)
       or      a
       jr      z, at28wInner           ; no arg
       call    parseHexadecimal        ; --> DE
       jr      z, at28wInner
       ; bad args
       ld      a, SHELL_ERR_BAD_ARGS
       ret

at28wInner:
       ; Reminder: words in parseArgs aren't little endian. High byte is first.
       ld      a, (AT28W_MAXBYTES)
       ld      b, a
       ld      a, (AT28W_MAXBYTES+1)
       ld      c, a
       ld      hl, AT28W_MEMSTART
       call    at28wBCZero
       jr      nz, .loop
       ; BC is zero, default to 0x2000 (8k, the size of the AT28)
       ld      bc, 0x2000
loop:
       call    blkGetB
       jr      nz, .loopend
       ld      (hl), a
       ld      e, a            ; save expected data for verification
       ; initiate polling
       ld      a, (hl)
       ld      d, a
wait:
       ; as long as writing operation is running, IO/6 will toggle at each
       ; read attempt. We know that write is finished when we read the same
       ; value twice.
       ld      a, (hl)
       cp      d
       jr      z, .waitend
       ld      d, a
       jr      .wait
waitend:

       ; same value was read twice. A contains our final value for this memory
       ; address. Let's compare with what we're written.
       cp      e
       jr      nz, .mismatch
       inc     hl
       dec     bc
       call    at28wBCZero
       jr      nz, .loop

loopend:
       ; We're finished. Success!
       xor     a
       ret

mismatch:
       ld      a, AT28W_ERR_MISMATCH
       ret

at28wBCZero:
       xor     a
       cp      b
       ret     nz
       cp      c
       ret