; Part of NeoGS project, (c) NedoPC 2007-2008
;
; FPGA boot
;
;
include "cpld_ports.inc"
relaxed on
ORG 0
phase 0
stack_top equ 0x4080
recode_tbl equ 0x4100
wbuf_addr equ 0x6000 ;8kB buffer, 8kb boundary
wbuf_size equ 0x2000
wbuf_hsize equ wbuf_size>>8
wbuf_mask equ 1fffh
wbuf_hmask equ wbuf_mask>>8
wbuf_hend equ (wbuf_addr+wbuf_size)>>8
di
di
jr LOAD
jp (ix)
jp (ix)
ret
ret
ret
ret
di
halt
di
halt
DEF_ROM:
di ;for default ROM load
ld sp,stack_top
call prepare
jr ROM
LOAD:
ld sp,stack_top ; use for stack first 128 bytes of RAM
call prepare
in a,(C_CRES)
rlca
jr c,TRY_RAM
ROM:
xor a
out (C_MCFG),a
ld hl,config_data+0x8000
jr loadconfig
TRY_RAM:
ld a,0x81
out (C_MCFG),a ;ram at 8000-FFFF, page 1
ld hl,0x8000
ld b,(hl)
inc l
ld c,(hl)
inc l
ld a,b
or a
jr z,ROM ;$0100 min length!
cp 0x7F
jr nc,ROM ;$7EFF max length!
add hl,bc
ld d,(hl) ;precomputed CRC value
dec (hl) ;KILL CRC
inc hl
ld e,(hl)
inc (hl) ;KILL CRC
push de
inc bc
inc bc
ld hl,0x8000
call CRC16
pop hl
or a
sbc hl,de
jr nz,ROM ;if CRC failed
ld hl,0x8002
;; start configuration
loadconfig:
ld a,0x81
out (C_CRNCFG),a ;clear cold_reset flag
call configure
; end config, see is it correct
wait_init:
in a,(C_NSTCDON)
sra a
jp p,DEF_ROM
jr nc,wait_init
; here CONF_DONE is released, nothing to do more (reboot takes place when INIT_DONE toggles)
di
halt
USE_BUFFER: ;hl - from
;de - len (down to zero)
;kills af,bc,de,hl
ld b,recode_tbl>>8
jr ub_entry
ub_loop:
ld c,(hl)
inc hl
ld a,(bc)
out (C_FPGADAT),a
call ready
dec de
ub_entry: ld a,d
or e
jr nz,ub_loop
ret
prepare:
;reset FPGA by pulling NCONFIG down
xor a
out (C_CRNCFG),a
;switch ROM in 8000-FFFF, first 32k, then check it for CRC
;xor a
out (C_MCFG),a
;calc and compare CRC of rom
ld hl,0x8000
ld bc,crc_is_here
call CRC16
ld a,(hl)
inc hl
ld l,(hl)
ld h,a
or a
sbc hl,de
jr nz,prepare
call mk_recode_tbl
ld a,1
out (C_CRNCFG),a ;release nconfig
wait_nstat:
in a,(C_NSTCDON) ;read nstatus, wait it to be 1
rla
jr nc,wait_nstat
ret
ready:
cfg_rdynbsy: ; wait for ready
in a,(C_FPGADAT)
rla
jr nc,cfg_rdynbsy
; restart if error during configuration
in a,(C_NSTCDON)
rla
jp nc,DEF_ROM
ret
mk_recode_tbl:
ld de,recode_tbl
mrt_loop:
ld a,e
and 0b01001001 ; preserve d0,d3,d6
ld b,a
ld a,e
and 0b10010000 ; d7 and d4
rrca
rrca
rrca
or b
ld b,a ;01011011
ld a,e
and 0b00000010 ; d1
rlca
or b
ld b,a ;01011111
ld a,e
and 0b00000100 ; d2
rlca
rlca
rlca
or b
ld b,a ;01111111
ld a,e
and 0b00100000 ; d5
rlca
rlca
or b ;11111111
ld (de),a
inc e
jr nz,mrt_loop
ret
;; recode config data:
; Z80 fpga
; D0 D0 *
; D1 D4
; D2 D1
; D3 D3 *
; D4 D7
; D5 D2
; D6 D6 *
; D7 D5
configure:
ld de,wbuf_addr
DEC40buf
LD A,0x80
EX AF,AF'
MS LDI
call after_ldi
M0 LD BC,0x2FF
M1 EX AF,AF'
M1X ADD A,A
JR NZ,M2
LD A,(HL)
INC HL
RLA
M2 RL C
JR NC,M1X
EX AF,AF'
DJNZ X2
LD A,2
SRA C
JR C,N1
INC A
INC C
JR Z,N2
LD BC,0x33F
JR M1
X2 DJNZ X3
SRL C
JR C,MS
INC B
JR M1
X6
ADD A,C
N2
LD BC,0x4FF
JR M1
N1
INC C
JR NZ,M4
EX AF,AF'
INC B
N5 RR C
;;;; RET C
jr c,dec40end
RL B
ADD A,A
JR NZ,N6
LD A,(HL)
INC HL
RLA
N6 JR NC,N5
EX AF,AF'
ADD A,B
LD B,6
JR M1
X3
DJNZ X4
LD A,1
JR M3
X4 DJNZ X5
INC C
JR NZ,M4
LD BC,0x51F
JR M1
X5
DJNZ X6
LD B,C
M4 LD C,(HL)
INC HL
M3 DEC B
PUSH HL
LD L,C
LD H,B
ADD HL,DE
LD C,A
LD B,0
;;;; LDIR
call wrap_ldir
POP HL
JR M0
END_DEC40
dec40end:
ex de,hl
ld de,wbuf_addr
or a
sbc hl,de
ex de,hl
jp USE_BUFFER
after_ldi: push af
ld a,d
cp wbuf_hend
jr c,al_nothing
push hl
ld hl,wbuf_addr
ld de,0x2000
call USE_BUFFER
ld de,wbuf_addr
pop hl
al_nothing:
pop af
ret
wrap_ldir:
ld a,h
cp wbuf_addr>>8
jr nc,wl_nohlwrap
add a,wbuf_hsize
ld h,a
wl_nohlwrap:
ld a,wbuf_hend-1
wl_ldiloop:
ldi
jp po,after_ldi
cp d
jr c,wl_dewrap
cp h
jr nc,wl_ldiloop
;wl_hlwrap
ld h,wbuf_addr>>8
jr wl_ldiloop
wl_dewrap:
push bc
call after_ldi
pop bc
jr wl_nohlwrap
CRC16: ;calculates crc16-ccitt with initial value of CRC=$FFFF
;INPUT: HL - memptr
; BC - byte count
;OUTPUT: DE - resulting crc value
; HL - ptr to byte after last processed
;KILLS: AF,BC,IX
;algo: crc = (crc<<8) ^ crc16tab[((crc>>8) ^ *(char *)buf++)&0x00FF];
ld a,c
or a
jr z,$+3
inc b
ld ixl,b
ld b,c
ex de,hl
ld hl,(crc16table&$FF00)+$FF ;high part of table, initial crc.lo
ld c,l ;initial crc.hi
c1_loop
;de - memptr; h - table>>8, c - crc.hi, l - crc.lo, b - counter
ld a,(de)
inc de
xor c
ld c,a ;c=index
ld a,l ;a=crc.lo
ld l,c ;hl=tab.hi
xor (hl) ;a=new crc.hi
inc h
ld l,(hl) ;l=new crc.lo
dec h
ld c,a
djnz c1_loop
dec ixl
jr nz,c1_loop
ld h,c
ex de,hl
ret
org ($+255)&0xFF00
crc16table:
db 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70
db 0x81,0x91,0xa1,0xb1,0xc1,0xd1,0xe1,0xf1
db 0x12,0x02,0x32,0x22,0x52,0x42,0x72,0x62
db 0x93,0x83,0xb3,0xa3,0xd3,0xc3,0xf3,0xe3
db 0x24,0x34,0x04,0x14,0x64,0x74,0x44,0x54
db 0xa5,0xb5,0x85,0x95,0xe5,0xf5,0xc5,0xd5
db 0x36,0x26,0x16,0x06,0x76,0x66,0x56,0x46
db 0xb7,0xa7,0x97,0x87,0xf7,0xe7,0xd7,0xc7
db 0x48,0x58,0x68,0x78,0x08,0x18,0x28,0x38
db 0xc9,0xd9,0xe9,0xf9,0x89,0x99,0xa9,0xb9
db 0x5a,0x4a,0x7a,0x6a,0x1a,0x0a,0x3a,0x2a
db 0xdb,0xcb,0xfb,0xeb,0x9b,0x8b,0xbb,0xab
db 0x6c,0x7c,0x4c,0x5c,0x2c,0x3c,0x0c,0x1c
db 0xed,0xfd,0xcd,0xdd,0xad,0xbd,0x8d,0x9d
db 0x7e,0x6e,0x5e,0x4e,0x3e,0x2e,0x1e,0x0e
db 0xff,0xef,0xdf,0xcf,0xbf,0xaf,0x9f,0x8f
db 0x91,0x81,0xb1,0xa1,0xd1,0xc1,0xf1,0xe1
db 0x10,0x00,0x30,0x20,0x50,0x40,0x70,0x60
db 0x83,0x93,0xa3,0xb3,0xc3,0xd3,0xe3,0xf3
db 0x02,0x12,0x22,0x32,0x42,0x52,0x62,0x72
db 0xb5,0xa5,0x95,0x85,0xf5,0xe5,0xd5,0xc5
db 0x34,0x24,0x14,0x04,0x74,0x64,0x54,0x44
db 0xa7,0xb7,0x87,0x97,0xe7,0xf7,0xc7,0xd7
db 0x26,0x36,0x06,0x16,0x66,0x76,0x46,0x56
db 0xd9,0xc9,0xf9,0xe9,0x99,0x89,0xb9,0xa9
db 0x58,0x48,0x78,0x68,0x18,0x08,0x38,0x28
db 0xcb,0xdb,0xeb,0xfb,0x8b,0x9b,0xab,0xbb
db 0x4a,0x5a,0x6a,0x7a,0x0a,0x1a,0x2a,0x3a
db 0xfd,0xed,0xdd,0xcd,0xbd,0xad,0x9d,0x8d
db 0x7c,0x6c,0x5c,0x4c,0x3c,0x2c,0x1c,0x0c
db 0xef,0xff,0xcf,0xdf,0xaf,0xbf,0x8f,0x9f
db 0x6e,0x7e,0x4e,0x5e,0x2e,0x3e,0x0e,0x1e
db 0x00,0x21,0x42,0x63,0x84,0xa5,0xc6,0xe7
db 0x08,0x29,0x4a,0x6b,0x8c,0xad,0xce,0xef
db 0x31,0x10,0x73,0x52,0xb5,0x94,0xf7,0xd6
db 0x39,0x18,0x7b,0x5a,0xbd,0x9c,0xff,0xde
db 0x62,0x43,0x20,0x01,0xe6,0xc7,0xa4,0x85
db 0x6a,0x4b,0x28,0x09,0xee,0xcf,0xac,0x8d
db 0x53,0x72,0x11,0x30,0xd7,0xf6,0x95,0xb4
db 0x5b,0x7a,0x19,0x38,0xdf,0xfe,0x9d,0xbc
db 0xc4,0xe5,0x86,0xa7,0x40,0x61,0x02,0x23
db 0xcc,0xed,0x8e,0xaf,0x48,0x69,0x0a,0x2b
db 0xf5,0xd4,0xb7,0x96,0x71,0x50,0x33,0x12
db 0xfd,0xdc,0xbf,0x9e,0x79,0x58,0x3b,0x1a
db 0xa6,0x87,0xe4,0xc5,0x22,0x03,0x60,0x41
db 0xae,0x8f,0xec,0xcd,0x2a,0x0b,0x68,0x49
db 0x97,0xb6,0xd5,0xf4,0x13,0x32,0x51,0x70
db 0x9f,0xbe,0xdd,0xfc,0x1b,0x3a,0x59,0x78
db 0x88,0xa9,0xca,0xeb,0x0c,0x2d,0x4e,0x6f
db 0x80,0xa1,0xc2,0xe3,0x04,0x25,0x46,0x67
db 0xb9,0x98,0xfb,0xda,0x3d,0x1c,0x7f,0x5e
db 0xb1,0x90,0xf3,0xd2,0x35,0x14,0x77,0x56
db 0xea,0xcb,0xa8,0x89,0x6e,0x4f,0x2c,0x0d
db 0xe2,0xc3,0xa0,0x81,0x66,0x47,0x24,0x05
db 0xdb,0xfa,0x99,0xb8,0x5f,0x7e,0x1d,0x3c
db 0xd3,0xf2,0x91,0xb0,0x57,0x76,0x15,0x34
db 0x4c,0x6d,0x0e,0x2f,0xc8,0xe9,0x8a,0xab
db 0x44,0x65,0x06,0x27,0xc0,0xe1,0x82,0xa3
db 0x7d,0x5c,0x3f,0x1e,0xf9,0xd8,0xbb,0x9a
db 0x75,0x54,0x37,0x16,0xf1,0xd0,0xb3,0x92
db 0x2e,0x0f,0x6c,0x4d,0xaa,0x8b,0xe8,0xc9
db 0x26,0x07,0x64,0x45,0xa2,0x83,0xe0,0xc1
db 0x1f,0x3e,0x5d,0x7c,0x9b,0xba,0xd9,0xf8
db 0x17,0x36,0x55,0x74,0x93,0xb2,0xd1,0xf0
config_data:
binclude "main.mlz"
crc_is_here: