;
; first test for Z80 SRAM K1-bus micro computer board
;

#target rom


; -------------------------------------------
;		OPTIONS
; -------------------------------------------

; K1-bus:
;
option_a5	equ	1		; 1 => use A5 for rd=1/wr=0 selection, use A8 for K1-bus A5
					; used when use of WR results in spikes on the k1-bus strobe lines

bSIO_SELECT	equ 	1		; the SIO board is jumpered for D1
bIDE_SELECT	equ 	2		; the IDE board uses D2

mSIO_SELECT 	equ	0xff - 1<<bSIO_SELECT
mIDE_SELECT 	equ	0xff - 1<<bIDE_SELECT

Vcc_fast	equ	0
Vcc_short	equ	1



; -------------------------------------------
; 		MEMORY LAYOUT
; -------------------------------------------

					; $0000 - $007F	  RST vectors, interrupt handler, eeprom helper 
					; $0080 - $00FF	  global variables
user_program	equ	$100		; $0100 - $1FFF	  user program
					;                 
dflt_stacks	equ	$2000		; $2000 - $20FF	  VM RStack (via IX)
					; $2100 - $25FF	  VM VStack (machine stack)
dflt_heap	equ	$2600		; $2600 - 	  dynamically allocated memory
					;       - $7EFF	  handles for allocated memory
sio_buffers	equ	$7F00		; $7F00 - $7FFF	  SIO buffers
ram_end		equ	sio_buffers



; -------------------------------------------
;		CONSTANTS
; -------------------------------------------

; K1-bus:
;
k1_wr_sel	equ	$00		; A765=000	select board
k1_wr_irpt	equ	$40		; A765=010	write interrupt enable mask to boards
k1_wr_hi	equ	$80		; A765=100	write byte to lo-to-hi data latch
k1_wr_data	equ	$c0		; A765=110	write data to selected board; A0-A5 select register

#if option_a5 
k1_rd_irpt	equ	$20		; A765=001	read interrupt state bits (0=active)
k1_rd_i2c	equ	$60		; A765=011	read or write data to i2c bus
k1_rd_data	equ	$a0		; A765=101	read data from selected board; A0-A5 select register
k1_rd_hi	equ	$e0		; A765=111	read data from hi-to-low data latch
#else
k1_rd_irpt	equ	$00		; A76=00	read interrupt state bits (0=active)
k1_rd_i2c	equ	$40		; A76=01	read or write data to i2c bus
k1_rd_data	equ	$80		; A76=10	read data from selected board; A0-A5 select register
k1_rd_hi	equ	$c0		; A76=11	read data from hi-to-low data latch
#endif

i2c_d0_c0	equ	k1_rd_i2c	; i2c data=0 clock=0	$08 = A3 = data
i2c_d0_c1	equ	k1_rd_i2c | $10	; i2c data=0 clock=1	$10 = A4 = clock
i2c_d1_c0	equ	k1_rd_i2c | $08	; i2c data=1 clock=0
i2c_d1_c1	equ	k1_rd_i2c | $18	; i2c data=1 clock=1	= idle bus
i2c_idle	equ	i2c_d1_c1
yellow_led	equ	i2c_d1_c0	; yellow led == i2c clock=0  NOTE: avoid setting red without yellow: 
red_led		equ	i2c_d0_c1	; red led    == i2c data=0	   this is the i2c start condition!
both_leds	equ	i2c_d0_c0	; yellow_led + red_led
no_led		equ	i2c_d1_c1

k1_i2c_din	equ	$80		; mask for D7 = i2c data_in bit


; -------------------------------------------
; 		OTHER CONSTANTS
; -------------------------------------------


; FD:
;
t_ser:: 	equ 	8



; ===========================================
; 		MEMORY LAYOUT
; ===========================================

; RAM:
#data 	DATA, page0end

; ROM:
#code 	GSINIT, 0x8000		; boot code
#code 	PAGE0			; initializer data for RST etc. and memory management
#code	VCC_INT			; implementations of standard Vcc words dealing with 2-byte data
#code	VCC_BYTE		; implementations of Vcc words dealing with 1-byte variables
#code	VCC_LONG		; implementations of Vcc word working with 4-byte data
#code	VCC_STR			; implementations of string and memory related Vcc word
#code	VCC_FUNCTIONS		; functions implemented as Vcc words
#code	VCC_CORE		; implementations of some core Vcc words, e.g. code flow
#code 	CODE			; most other code
#code	CONST			; const data
#code	ROMEND			; for easy calculation



; ===========================================
;	now: adding actual code and data
;	switching between segments as needed
; ===========================================

#code GSINIT
; after power-on the rom is also visible at $0000 so that the Z80 can start here
; we jump immediately to the standard mapping address so we can switch off init mode
	
reset::	jp	8003$
8003$:	di				; disable interrupts (if we jump here deliberately from the running code)
	im	1			; init interrupt mode
	
; reset k1 bus:
	ld	a, 0xff			; note: the first IORQ also resets the INIT flip flop => ram becomes accessible
	out	k1_wr_sel, a		; => deselect all boards (security only)
	out	k1_wr_irpt, a		; => disable interrupts on k1-bus boards
	in	a, i2c_idle 		; => set i2c bus to idle state, note: switches off the debug LEDs 

; test for SDP write protected eeprom in ram socket:
	ld	h,0			; hl -> ram
	inc	(hl)			; write to ram
	ld	a,(hl)
	xor	(hl)			; 0x00 expected
	cp	0x40			; 0x40 -> D6 toggled -> eeprom
	jp	z,unlock_eeprom_in_ram_socket	

; init sio1 UART early,
; so that the user has enough time to press "F" for firmware download:
	ld	hl,sio1_init_data
	ld	b, sio1_init_data_count
7$:	ld	c,(hl++)
	ld	a,(hl++)
	out	(c),a
	djnz	7$
	in	a,(k1_rd_data+STCR)    	; start C/T 
	in	a,(k1_rd_data+GPR)	; check test value in GPR
	cp	123
	ld	a,ERROR_SIO_NOT_FOUND
	jp	nz,panic

; test & clear ram to $00		
#include "src/ramtest.s"		; -> hl = ramtop = 0x8000
	ld	sp,dflt_heap
	ld	ix,dflt_stacks + 0x80

; copy rst vectors, interrupt vectors and other initialized global variables:
	ld	hl, PAGE0
	ld	de, 0
	ld	bc, page0end - 0
	ldir					

; SDP write-protect eeprom:
	call	lock_eeprom
	jr	c,11$			; CY -> error -> not an eeprom
	ld	hl,sysflags
	inc	(hl)			; OK -> set bEEPROM in sysflags

11$:
; download firmware if uppercase "F" was received on sioA:
	;ld	a,mSIO_SELECT		; sio2 still selected from above
	;out	(k1_wr_sel),a
	call	sioA_test_char
	jr	z,12$			; no key pressed
	cp	a,"F"
	jr	nz,12$			; no "F"
	call	sioA_send_msg
	db	13,10,"download firmware ",0
	call	download_firmware	; may return if user bails out	

;11$:
; print first boot message:
12$:	call	sioA_send_msg
	db	13,10,"ROM "
romdate:: dm	__date__,0

	call	sioA_send_msg
	db	" "
romtime:: dm	__time__,0
	

; initialization of globals and statics:
	;jp	$			



; ===========================================
; 	    INCLUDE EVERYTHING
; ===========================================


#code CODE
#include "Vcc/abort.s"
#include "Vcc/page0.s"
#include "Vcc/vcore.s"
#include "Vcc/memory.s"
#include "Vcc/vcore8.s"
#include "Vcc/vcore16.s"
#include "Vcc/vcore32.s"
#include "Vcc/vcore_str.s"

#include "src/eeprom.s"
#include "src/functions.s"
#include "src/sio.s"

#include "Vcc/test/test_core.s"
#include "Vcc/test/test16.s"
#include "Vcc/test/test8.s"
#include "Vcc/test/test_str.s"
;#include "sio.asm"


; ________________________________________________________
#code GSINIT

; start system:
	call	sioA_send_msg
	db	13,10,"Z80 System Ready.",13,10,"> ",0

	ei				; enable interrupts in the CPU
	ld	a, (k1_irpt_mask)	; enable interrupts on all existing boards
	out	k1_wr_irpt, a

; call main program:

	gget	systemtime

	ld	b,100
100$:	push	bc	

	YELLOW_LED
	call	test_core	
	call	test_16
	call	test_8
	call	test_str
	NO_LEDS
	
	pop	bc
	djnz	100$
	
	gget	systemtime
	swap
	sub16
	di
	ld	a,mSIO_SELECT
	out	(k1_wr_sel),a
	ex	hl,de
	call	sioA_print_hl_hex
	
	
	panic	ERROR_220
	
; str s = "\r\nAll tests passed."
	call	istr			; ISTR
	dw	82$-81$
81$:	db	13,10,"All tests passed."
	db	13,10,"Press key to finish -> "
82$:	

; var i=0;
	ival 0		; stack: s i
	
; while(i<s.count) {
83$:	dup		; s i i
	lget 4		; s i i s
	count8		; s i i n
	ltu		; s i f
	jr0 88$		; s i 
	
; sio_putc(sioA,s[i++])	
	GGET sioA	; s i sioA
	LGET 4		; s i sioA s
	LVAR 4		; s i sioA s &i
	PEEKPPu8	; s i sioA s i
	ATIGETu8	; s i sioA char
	call sio_putc	; s i

; }
	jr 83$
	
88$:	DROP		; stack: s
	DROPSTR		; stack: -

; sio_putc(sioA,sio_getc(sioA))
	GGET sioA
	DUP
	call sio_getc
	call sio_putc
	halt

	ld	a,ERROR_END_OF_CODE
	jp	panic			; blink code


; ________________________________________________________
#code PAGE0
page0end 	= $
page0_size 	= $ - 0

#code VCC_INT
vcc_int_size	equ	$ - VCC_INT

#code VCC_LONG
vcc_long_size	equ	$ - VCC_LONG

#code VCC_BYTE
vcc_byte_size	equ	$ - VCC_BYTE

#code VCC_STR
vcc_str_size	equ	$ - VCC_STR

#code VCC_FUNCTIONS
vcc_fu_size	equ	$ - VCC_FUNCTIONS

#code VCC_CORE
vcc_core_size	equ	$ - VCC_CORE
vcc_total_size	equ	$ - VCC_CORE + vcc_fu_size + vcc_int_size + vcc_byte_size + vcc_long_size + vcc_str_size

#code ROMEND
romend 		= $
rom_size	= $ - 0x8000

