ORG #0000 ld a,0 out (#F8),a ; blank status LEDs ld sp, #700 ; set stack pointer to something sensible jp ProgramRom ; Blank space until some restart handlers are written ; Fill all below NMI with NOPs ASSERT $ <= #66 BLOCK #66 - 6, 0 NMI retn ; do nothing ; The meat of the program. ProgramRom ld hl, #8000 ; first ROM sector call EraseSector cp 0 ; return code = 0 if all went OK jr z, ProgramRom.Write halt ; erk, it went horribly wrong ; note: NMI will try and program anyway ProgramRom.Write ld hl, TESTPROGRAM ld de, #8000 ld b, TESTPROGRAMEND call WriteData AllDone halt jp AllDone ; just in case of an NMI ; EraseSector subroutine erases a 16K Flash ROM sector. ; Only 32K of the 128K ROM is actually mapped in, so there's only two ; sector addresses we can choose from (0 or 1). ; Pass the sector address in HL ; Result is returned in A (0 = OK) ; Status LED = 1 = preparing to erase, 11 = Erasing, lights out = done ; 10 = borked EraseSector ld a, 1 out (#F8), a ; status LED = 0000 0001 ld a, #AA ; unlock code 1 ld (#8555), a ; unlock addr 1 ld a, #55 ; unlock code 2 ld (#82AA), a ; unlock addr 2 ld a, #80 ; erase cmd 1 ld (#8555), a ; erase cmd addr 1 ld a, #AA ; erase cmd 2 ld (#8555), a ; erase cmd addr 2 ld a, #55 ; erase cmd 3 ld (#82AA), a ; erase cmd addr 3 ld a, #30 ; erase cmd 4 ld (hl), a ; erase sector address ld a, 3 ; status lights = 0000 0011 out (#F8), a ; update lights EraseSector.wait bit 7, (hl) ; test DQ7 - should be 1 when complete jr nz, EraseSector.complete bit 5, (hl) ; test DQ5 - should be 1 to continue jr z, EraseSector.wait bit 7, (hl) ; test DQ7 again jr z, EraseSector.borked EraseSector.complete ld a,0 ; status = OK out (#F8), a ; extinguish status LEDs ret EraseSector.borked ld a, #2 ; 0000 0010 out (#F8), a ; update LEDs ret ; WriteData ; Copy data pointed to by HL to Flash ROM at address DE, for B bytes. ; On return, A=0 means write OK ; Status LEDs: 0001 0000 = Writing ; 0011 0000 = Checking status ; 0000 0000 = Complete OK ; 0010 0000 = Borked WriteData ld a, #10 out (#F8), a ; status LED = 0001 0000 ld a, #AA ; unlock 1 ld (#8555), a ; unlock address 1 ld a, #55 ; unlock 2 ld (#82AA), a ; unlock address 2 ld a, #A0 ; Program ld (#8555), a ; Program address ld a, (hl) ; Get byte to program ld (de), a ; program it push bc ; save BC for later ld c,a ; store A ld a, #30 out (#F8), a ; status LED = 0011 0000 WriteData.wait ld a, (de) ; read programmed address ld b, a ; save status xor c bit 7, a ; If bit 7 = 0 the bit 7 = data jr z, writeData.byteComplete bit 5, b ; test DQ5 jr nz, WriteData.wait ld a, (de) ; read programmed address xor c bit 7, a ; Does DQ7 = programmed data? 0 if true jr nz, writeData.borked writeData.byteComplete pop bc ; retrieve BC inc hl inc de djnz WriteData ld a, 0 out (#F8), a ; extinguish status lights ret writeData.borked ld a, #20 out (#F8), a ; status lights = 0010 0000 ret ; A test program to load into ROM. To run from ROM, I swap the chip select ; lines (so that ROM maps in at 0x0000 - 0x7FFF, and the 2K static RAM ; gets mapped from 0x8000 to 0x87FF TESTPROGRAM org #0000 start di ld sp,#8400 ; Stack must be in RAM! loop ld a,#C0 rightwards out (#f8),a rra cp 0 jr nz,rightwards ld a,#07 leftwards out (#f8),a rla cp 0 jr nz,leftwards ld a,1 increment out (#f8),a inc a cp #10 jr nz,increment shiftout rla out (#f8),a cp 0 jr nz,shiftout halt jp loop ASSERT $ <= #66 BLOCK #66 - $, 0 testnmi ex af,af' ; save A and F registers ld a,#aa out (#f8),a ld a,#55 out (#f8),a xor a out (#f8),a ex af,af' ; restore AF retn nop TESTPROGRAMEND