Browse Source

HDIAG Early Development

- Initial framework.  Just boots up and displays startup messages.
pull/254/head
Wayne Warthen 4 years ago
parent
commit
f8e0fb3a6f
  1. BIN
      Doc/ROM Applications.pdf
  2. BIN
      Doc/RomWBW Applications.pdf
  3. BIN
      Doc/RomWBW Architecture.pdf
  4. BIN
      Doc/RomWBW Disk Catalog.pdf
  5. BIN
      Doc/RomWBW Getting Started.pdf
  6. 1
      Source/BuildShared.cmd
  7. 1
      Source/Clean.cmd
  8. 2
      Source/Doc/ROM_Applications.md
  9. 19
      Source/HDIAG/Build.cmd
  10. 7
      Source/HDIAG/Clean.cmd
  11. 20
      Source/HDIAG/Makefile
  12. 70
      Source/HDIAG/acia.asm
  13. 89
      Source/HDIAG/asci.asm
  14. 588
      Source/HDIAG/hdiag.asm
  15. 2543
      Source/HDIAG/hdiag_old.asm
  16. 108
      Source/HDIAG/sio.asm
  17. 106
      Source/HDIAG/uart.asm
  18. 106
      Source/HDIAG/util.asm
  19. 71
      Source/HDIAG/z180.inc
  20. 49
      Source/HDIAG/z2u.asm
  21. 3
      Source/Makefile
  22. 2
      Source/ver.inc
  23. 2
      Source/ver.lib
  24. 3
      Tools/Makefile.inc

BIN
Doc/ROM Applications.pdf

Binary file not shown.

BIN
Doc/RomWBW Applications.pdf

Binary file not shown.

BIN
Doc/RomWBW Architecture.pdf

Binary file not shown.

BIN
Doc/RomWBW Disk Catalog.pdf

Binary file not shown.

BIN
Doc/RomWBW Getting Started.pdf

Binary file not shown.

1
Source/BuildShared.cmd

@ -1,6 +1,7 @@
@echo off @echo off
setlocal setlocal
pushd HDIAG && call Build || exit /b & popd
pushd CBIOS && call Build || exit /b & popd pushd CBIOS && call Build || exit /b & popd
pushd CPM22 && call Build || exit /b & popd pushd CPM22 && call Build || exit /b & popd
pushd ZCPR && call Build || exit /b & popd pushd ZCPR && call Build || exit /b & popd

1
Source/Clean.cmd

@ -1,6 +1,7 @@
@echo off @echo off
setlocal setlocal
pushd HDIAG && call Clean.cmd & popd
pushd Apps && call Clean.cmd & popd pushd Apps && call Clean.cmd & popd
pushd CPM22 && call Clean.cmd & popd pushd CPM22 && call Clean.cmd & popd
pushd ZCPR && call Clean.cmd & popd pushd ZCPR && call Clean.cmd & popd

2
Source/Doc/ROM_Applications.md

@ -355,7 +355,7 @@ ROMWBW contains two versions of ROM BASIC, a full implementation and a "tiny" BA
The full implementation is a version of Microsoft BASIC from the NASCOM Computer. The full implementation is a version of Microsoft BASIC from the NASCOM Computer.
A comprehensive instruction manual is available in the Doc\Contrib directory.
A comprehensive instruction manual is available in the Doc\\Contrib directory.
## ROMWBW specific features ## ROMWBW specific features

19
Source/HDIAG/Build.cmd

@ -0,0 +1,19 @@
@echo off
setlocal
set TOOLS=../../Tools
set BIN=..\..\Binary
set PATH=%TOOLS%\tasm32;%PATH%
set TASMTABS=%TOOLS%\tasm32
set ZXBINDIR=%TOOLS%/cpm/bin/
set ZXLIBDIR=%TOOLS%/cpm/lib/
set ZXINCDIR=%TOOLS%/cpm/include/
tasm -t180 -g3 -fFF -DAPPBOOT hdiag.asm hdiag.com hdiag_com.lst || exit /b
tasm -t180 -g3 -fFF -DROMBOOT hdiag.asm hdiag.rom hdiag_rom.lst || exit /b
copy hdiag.rom %BIN% || exit /b
copy hdiag.com %BIN% || exit /b

7
Source/HDIAG/Clean.cmd

@ -0,0 +1,7 @@
@echo off
setlocal
if exist *.bin del *.bin
if exist *.com del *.com
if exist *.lst del *.lst
if exist *.hex del *.hex

20
Source/HDIAG/Makefile

@ -0,0 +1,20 @@
OBJECTS = hdiag.com hdiag.rom
DEST = ../../Binary
TOOLS = ../../Tools
include $(TOOLS)/Makefile.inc
TASMFLAGS=-t hd64180
hdiag.com: hdiag.asm
$(TASM) $(TASMFLAGS) -dAPPBOOT $< $@ $*.lst
hdiag.rom: hdiag.asm
$(TASM) $(TASMFLAGS) -dROMBOOT $< $@ $*.lst
#cbios_wbw.bin: cbios.asm
# $(TASM) -dPLTWBW $< $@ cbios_wbw.lst
#
#cbios_una.bin: cbios.asm
# $(TASM) -dPLTUNA $< $@ cbios_una.lst

70
Source/HDIAG/acia.asm

@ -0,0 +1,70 @@
;
;=======================================================================
; HDIAG ACIA Driver
;=======================================================================
;
acia_cmd .equ $80
acia_dat .equ $81
;
;
;
acia_jptbl:
jp acia_cinit ; Initialize serial port
jp acia_cin ; Read byte
jp acia_cout ; Write byte
jp acia_cist ; Input status
jp acia_cost ; Output Status
;
;
;
acia_cinit:
; Detect ACIA
ld a,$03 ; master reset
out (acia_cmd),a ; apply it
in a,(acia_cmd) ; get status
or a ; check for zero (expected)
ret nz ; abort if not
ld a,$02 ; clear master reset
out (acia_cmd),a ; apply it
in a,(acia_cmd) ; get status again
and %00001110 ; isolate reliable bits
cp %00000010 ; check for expected value
ret nz ; abort if not
; Initialize ACIA
ld a,%00010110 ; default config
out (acia_cmd),a ; apply it
xor a ; signal success
ret
;
;
;
acia_cin:
call acia_cist ; check for char ready
jr z,acia_cin ; if not, loop
in a,(acia_dat) ; read byte
ret ; done
;
;
;
acia_cout:
push af ; save incoming
acia_cout1:
call acia_cost ; ready for char?
jr z,acia_cout1 ; loop if not
pop af ; restore incoming
out (acia_dat),a ; write byte
ret ; and done
;
;
;
acia_cist:
in a,(acia_cmd) ; get status
and $01 ; isolate rx ready
ret ; done
;
;
;
acia_cost:
in a,(acia_cmd) ; get status
and $02 ; isolate tx empty
ret ; done

89
Source/HDIAG/asci.asm

@ -0,0 +1,89 @@
;
;=======================================================================
; HDIAG ASCI Driver
;=======================================================================
;
; ASCI0 is programmed with a fixed divisor of 480, resulting in a
; baud rate of 38400 at the standard cpu frequency of 18.432 MHz
;
; The Z180 may relocate it's internal I/O to begin at different
; starting port addresses. This driver relies upon an HDIAG global
; variable to dynamically adjust to the right port address.
;
;
asci_jptbl:
jp asci_cinit ; Initialize serial port
jp asci_cin ; Read byte
jp asci_cout ; Write byte
jp asci_cist ; Input status
jp asci_cost ; Output Status
;
;
;
asci_cinit:
; Detect ASCI
ld a,(hd_cpu) ; get cpu type
cp 1
jr c, asci_cinit1 ; less than Z180, abort
cp 4
jr nc, asci_cinit1 ; greater than Z180, abort
;
; Initialize ASCI
ld a,%01100100 ; rcv enable, xmit enable, no parity
out0 (z180_cntla0),a ; set cntla
ld a,%00100000 ; div 30, div 16, div 1 (38400 baud for 18.432mhz cpu)
out0 (z180_cntlb0),a ; set cntlb
ld a,%01100110 ; no cts, no dcd, no break detect
out0 (z180_asext0),a ; set asext
xor a ; no interrupts
out0 (z180_stat0),a ; set stat0
xor a ; signal success
ret ; done
;
asci_cinit1:
or $FF ; signal error
ret ; done
;
;
;
asci_cin:
call asci_cist ; check for char ready
jr z,asci_cin ; if not, loop
in0 a,(z180_rdr0) ; get char
ret ; done
;
;
;
asci_cout:
push af ; save incoming
asci_cout1:
call asci_cost ; ready for char?
jr z,asci_cout1 ; loop if not
pop af ; restore incoming
out0 (z180_tdr0),a ; write byte
ret ; and done
;
;
;
asci_cist:
in0 a,(z180_stat0) ; get status
push af ; save status
and $70 ; line error?
jr z,asci_cist1 ; continue if no errors
;
; clear line error(s) or nothing further can be received!!!
in0 a,(z180_cntla0) ; read cntla
res 3,a ; clear efr (error flag reset)
out0 (z180_cntla0),a ; update cntla
;
asci_cist1:
pop af ; recover original status
and $80 ; data ready?
ret
;
;
;
asci_cost:
in0 a,(z180_stat0) ; get status
and $02 ; isolate bit 5
ret ; a != 0 if char ready, else 0

588
Source/HDIAG/hdiag.asm

@ -0,0 +1,588 @@
;
;
;=======================================================================
; HDIAG Diagmostic ROM
;=======================================================================
;
; HDIAG is a framework for a diagnotic environment intended to be
; suitable for all systems supported by RomWBW. RomWBW expects hardware
; to be fully functional making it difficult to use it to initially
; check out a system. HDIAG is explicitly constructed to be as simple
; as possible.
;
; There is only a single variant of HDIAG that is built. HDIAG is
; designed to detect the environment it is operating under at startup
; and dynamically adapt to it.
;
; HDIAG can be assembled to boot in one of 2 modes (rom or application)
; as described below. When compiled, you must define exactly one of the
; following macros:
;
; - ROMBOOT: Boot from a rom bank
;
; When ROMBOOT is defined, the file is assembled to be imbedded at the
; start of a rom assuming that the cpu will start execution at address
; 0.
;
; - APPBOOT: Boot as a CP/M style application file
;
; When APPBOOT is defined, the file is assembled as a CP/M application
; assuming that it will be loaded at 100h by the cp/m (or compatible)
; OS.
;
#include "z180.inc"
;
;=======================================================================
; Page Zero Definition
;=======================================================================
;
; Generic page zero setup. Only applies to ROMBOOT startup mode.
;
#ifdef ROMBOOT
;
.org $0000
;
jp hd_start ; rst $00: jump to boot code
.fill ($08-$)
ret ; rst $08
.fill ($10-$)
ret ; rst $10
.fill ($18-$)
ret ; rst $18
.fill ($20-$)
ret ; rst $20
.fill ($28-$)
ret ; rst $28
.fill ($30-$)
ret ; rst $30
.fill ($38-$)
reti ; h/w int return
.fill ($66-$)
retn ; h/w nmi return
.fill ($100-$) ; pad remainder of page zero
;
#else
.org $0100
;
#endif
;
;=======================================================================
; Startup
;=======================================================================
;
; Before transitioning to RAM, we need to determine the memory
; manager to use because some platforms will not have any RAM mapped
; to the upper 32K of CPU address space until the memory manager
; is initialized.
;
hd_start:
;
; Discover CPU Type and Memory Manager
;
; Some of this code is derived from UNA by John Coffman
;
; CPU Type:
; 0: Z80
; 1: Z80180 - ORIGINAL Z180 (EQUIVALENT TO HD64180)
; 2: Z8S180 - ORIGINAL S-CLASS, REV. K, AKA SL1960, NO ASCI BRG
; 3: Z8S180 - REVISED S-CLASS, REV. N, W/ ASCI BRG
; 4: Z8280
;
; Memory Manager:
; 0: SBC/MBC/Zeta 1
; 1: Zeta 2/RC2014
; 2: Z180
; 3: N8?
; 4: Z280
;
;
di ; no interrupts allowed
;
ld a,$80
out ($0D),a
;
; Use H for memory manager, and L for CPU Type
ld hl,0 ; assume Z80 and SBC
;
; Test for Z180 using mlt
ld de,$0506 ; 5 x 6
mlt de ; de = 30 if Z180
ld a,e ; check if multiply happened
cp 30
jr nz,hd_tryZ280 ; if != 30, not a Z180, try Z280
inc l ; Z80180 or better
;
#ifdef APPBOOT
;
; Reset Z180 internal register base to zero
xor a
out0 ($7F),a
out0 ($BF),a
out0 ($FF),a
;
#endif
;
; Test for older S-class (rev K)
in0 a,(z180_ccr) ; supposedly only on s-class
inc a ; FF -> 0
jr z,hd_z180res ; if zero, pre-S, HD61480 or equiv
inc l ; Z8S180 rev K (SL1960) or better
;
; Test for newer S-class (rev N)
; On older S-class, asci time constant reg does not exist
; and will always read back as $FF
out0 (z180_astc1l),d ; d = 0 at this point
in0 a,(z180_astc1l) ; asci time constant reg
inc a ; FF -> 0
jr z,hd_z180res ; if zero, rev-K
inc l ; otherwise Z8S180 rev N w/ asci brg
jr hd_z180res ; go to Z180 reset
;
hd_tryZ280:
; Test for Z280 per Zilog doc
ld a,$40 ; initialize the operand
.db $cb,$37 ; this instruction will set the s flag
; on the Z80 cpu and clear the s flag
; on the Z280 mpu.
jp m,hd_z80res ; if not Z280, we are Z80
ld l,4 ; we are Z280
jr hd_z280res ; handle Z280 initialization
;
hd_z80res:
ld a,$01
out (0),a
; Reset Z80 here (is there anything?)
jr hd_cpu1
;
hd_z180res:
;
; Reset z180 registers here
; Set CPU speed to oscillator X 1
xor a
out0 (z180_cmr),a
ld a,$80
out0 (z180_ccr),a
; Set default wait states
ld a,$%00000100 ; mem wait=0, i/o wait=+1
out0 (z180_dcntl),a
;
#ifdef ROMBOOT
; Setup Z180 MMU
; Keep ROM page zero in lower 32K!!!
ld a,$80 ; Common Base @ 32K, Bank Base @ 0K
out0 (z180_cbar),a
xor a ; Physical address zero
out0 (z180_cbr),a ; ... for Common Base
out0 (z180_bbr),a ; ... and Bank Base
#else
xor a ; Physical address zero
out0 (z180_cbr),a ; ... for Common Base
#endif
;
jr hd_cpu1
;
hd_z280res:
; Reset Z280 registers here
; Make sure memmgr is reset to defaults!
jr hd_cpu1
;
hd_cpu1:
ld a,$02
out ($0D),a
;
; Reset Zeta 2 memory manager (in case it exists)
#ifdef ROMBOOT
xor a ; disable value
out ($7C),a ; write it
xor a ; 16K ROM page 0
out ($78),a
inc a ; 16K ROM page 1
out ($79),a
#endif
ld a,2 ; 16K ROM page 2
out ($7A),a
inc a ; 16K ROM page 3
out ($7B),a
;
; Reset N8 supplemental memory manager
; *** Need to implement this ***
;
ld a,$03
out ($0D),a
;
; If SBC memmgr, RAM is already in himem, otherwise ROM
ld ix,$FFFF ; point to himem
ld a,$A5 ; an unlikely bit pattern
ld (ix),a ; write the value
cp (ix+0) ; check value written
jr z,hd_cpu2 ; SBC memory manager, we are done!
;
ld a,$04
out ($0D),a
;
; Now test for Zeta 2 memory manager
; Start by initializing and enabling the page registers
inc h ; assume Zeta 2 memory manager
#ifdef ROMBOOT
xor a ; ROM page 0
out ($78),a
inc a ; ROM page 1
out ($79),a
#endif
ld a,$20 ; first RAM page
out ($7A),a
inc a ; second RAM page
out ($7B),a
ld a,1 ; enable paging
out ($7C),a
;
ld a,$05
out ($0D),a
;
; Test himem RAM again
ld ix,$FFFF ; point to himem
ld a,$A5 ; an unlikely bit pattern
ld (ix),a ; write the value
cp (ix+0) ; check value written
jr z,hd_cpu2 ; Zeta 2 memory manager, we are done!
;
ld a,$06
out ($0D),a
;
; If neither SBC nor Zeta 2, then we assume the memory
; manager is the native memory manager onboard the CPU
ld a,l ; get cpu type
cp 4 ; Z280?
jr z,hd_z280init ; handle it
or a ; Z80?
jr nz,hd_z180init ; if no, do handle Z180
;
; If we get here, we are stuck. We believe we are a Z80
; but both of the Z80 memory manager tests failed.
hd_halt:
ld a,$07
out ($0D),a
ld hl,str_halt
call prtstr
halt ; give up
;
hd_z180init:
; Initialize Z180 memory manager
; Put first RAM page into himem (commmon)
ld a,$80
out0 (z180_cbr),a
;
ld h,2
jr hd_cpu2
hd_N8init:
; Initialize N8 memory manager
ld h,3
jr hd_cpu2
hd_z280init:
; Initialize Z280 memory manager
ld h,4
jr hd_cpu2
;
hd_cpu2:
ld a,$08
out ($0D),a
;
ld ($8000),hl ; stash cpu/memmgr at $8000
;
; Transition to upper memory (omit page zero)
;
ld hl,$0000+$100
ld de,$8000+$100
ld bc,$8000-$100
ldir
jp hd_start2
;
.org $ + $8000
;
;
;=======================================================================
; Post-relocation Startup
;=======================================================================
;
hd_start2:
;
ld a,$09
out ($0D),a
;
ld sp,$FF00 ; Stack just below FF page
;
; Copy FF page image to real location. Use a decrementing copy
; just in case page image is within $100 bytes of $FF00. Very
; unlikely, but just to be safe.
;
ld hl,ffpgimg+$FF ; Start at end of image
ld de,$FFFF ; To top of RAM
ld bc,$100 ; Copy 1 page
lddr ; Execute
;
; Recover cpu/memmgr codes stashed at $8000 and
; save them in FFpg
;
ld hl,($8000)
ld (hd_cpu),hl
;
; Probe and initialize serial port console driver. We just go
; through the options stopping at the first one that works. The
; order of polling below is intended to find the most reasonable
; console port.
;
;
ld a,$0A
out ($0D),a
;
; Z280 UART
ld ix,z2u_jptbl
call jpix
jr z,hd_start3
; ASCI
ld ix,asci_jptbl
call jpix
jr z,hd_start3
; UART
ld ix,uart_jptbl
call jpix
jr z,hd_start3
; ACIA
ld ix,acia_jptbl
call jpix
jr z,hd_start3
; SIO
ld ix,sio_jptbl
call jpix
jr z,hd_start3
;
; Ugh, nothing worked
ld a,$0C
out ($0D),a
halt
;
;
;
hd_start3:
;
ld a,$0D
out ($0D),a
;
; Copy selected console serial driver vector table into place
;
push ix
pop hl
ld de,hd_serjptbl
ld bc,5*3
ldir
;
;
;
; Map a RAM page to lower 32K
;
; Setup zero page in lower 32K
;
;
;
hd_start4:
;
ld hl,str_banner
call prtstr
;
ld hl,str_cputag
call prtstr
ld a,($8000) ; cpu type
;call prthex8
rlca
ld hl,str_cpu
call addhla
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
call prtstr
;
;
ld hl,str_mmtag
call prtstr
ld a,($8001) ; memory manager
;call prthex8
rlca
ld hl,str_mm
call addhla
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
call prtstr
;
call cin
jp hd_start4
;
;
;
jp hd_halt
;
;=======================================================================
; Helper functions
;=======================================================================
;
;
;=======================================================================
; Include various utility code modules
;=======================================================================
;
#include "util.asm"
;
;=======================================================================
; Console I/O
;=======================================================================
;
; Internal serial driver routing jump table. The console serial
; port is detected at startup and the following table is populated
; dynamically at that time.
;
hd_serjptbl:
jp 0 ; Console port initialization
jp 0 ; Console read byte
jp 0 ; Console write byte
jp 0 ; Console input status
jp 0 ; Console output status
;
; Wrapper functions for console I/O handles routing abstraction and
; ensures that no registers are modified other than AF for input
; functions.
;
hd_cinit:
push af
push bc
push de
push hl
call hd_serjptbl + 0
pop hl
pop de
pop bc
pop af
ret
;
hd_cin:
push bc
push de
push hl
call hd_serjptbl + 3
pop hl
pop de
pop bc
ret
;
hd_cout:
push af
push bc
push de
push hl
call hd_serjptbl + 6
pop hl
pop de
pop bc
pop af
ret
;
hd_cist:
push bc
push de
push hl
call hd_serjptbl + 9
pop hl
pop de
pop bc
ret
;
hd_cost:
push af
push bc
push de
push hl
call hd_serjptbl + 12
pop hl
pop de
pop bc
pop af
ret
;
; Include all serial drivers
;
#include "uart.asm"
#include "asci.asm"
#include "acia.asm"
#include "sio.asm"
#include "z2u.asm"
;
;=======================================================================
; Working literals and internal variables
;=======================================================================
;
str_banner .db "\r\n\r\nHDIAG v0.90",0
str_cputag .db "\r\nCPU Model: ",0
str_mmtag .db "\r\nMemory Manager: ",0
str_halt .db "\r\n\r\n*** System HALTed ***",0
;
str_cpu:
.dw str_cpuz80
.dw str_cpuz180
.dw str_cpuz180K
.dw str_cpuz180N
.dw str_cpuz280
;
str_cpuz80 .db "Z80",0
str_cpuz180 .db "Z80180",0
str_cpuz180K .db "Z8S180-K",0
str_cpuz180N .db "Z8S180-N",0
str_cpuz280 .db "Z80280",0
;
str_mm:
.dw str_mmsbc
.dw str_mmz2
.dw str_mmz180
.dw str_mmn8
.dw str_mmz280
;
str_mmsbc .db "SBC/MBC",0
str_mmz2 .db "Zeta2/RC2014",0
str_mmz180 .db "Z180 Native",0
str_mmn8 .db "Z180 Native (N8)",0
str_mmz280 .db "Z280 Native",0
;
;=======================================================================
; Top page of CPU RAM, global variables and function jump table
;=======================================================================
;
; This area is defined here, but copied to the top page of RAM at
; initialization!
;
; The top page (256 bytes) of CPU address space is used to maintain
; a jump table of functions available to all diagnostic modules.
; It also contains some global variables at fixed locations for use
; by diagnostic modules.
;
ffpgimg .equ $
.org $FF00 ; Set code org
;
hd_jptbl:
cinit jp hd_cinit ; Console port initialization
cin jp hd_cin ; Console read byte
cout jp hd_cout ; Console write byte
cist jp hd_cist ; Console input status
cost jp hd_cost ; Console output status
;
.fill $FF80-$
hd_cpu .db 0 ; CPU type
hd_mmgr .db 0 ; Memory manager type
.end

2543
Source/HDIAG/hdiag_old.asm

File diff suppressed because it is too large

108
Source/HDIAG/sio.asm

@ -0,0 +1,108 @@
;
;=======================================================================
; HDIAG SIO Driver
;=======================================================================
;
; Assumes the UART port conventions for RC2014. Command/status port
; at $80 and read/write data port at $81.
; Assuming a UART clock frequency of 1.8432 MHz, the baud rate
; will be 38400.
;
sio_cmd .equ $80 ; SIO command/status port
sio_dat .equ $81 ; SIO read/write port
;
sio_jptbl:
jp sio_cinit ; Initialize serial port
jp sio_cin ; Read byte
jp sio_cout ; Write byte
jp sio_cist ; Input status
jp sio_cost ; Output Status
;
;
;
sio_cinit:
; Detect SIO here...
; Zero the int vector register
ld a,2 ; select WR2 (int vector)
out (sio_cmd+2),a ; do it
xor a ; zero accum
out (sio_cmd+2),a ; write to WR2
; Read the int vector register and check for zero
ld a,2 ; select WR2 (int vector)
out (sio_cmd+2),a ; do it
in a,(sio_cmd+2) ; get int vector value
and $F0 ; only top nibble
ret nz ; abort if not zero
; Set test value in int vector register
ld a,2 ; select WR2 (int vector)
out (sio_cmd+2),a ; do it
ld a,$FF ; test value
out (sio_cmd+2),a ; write to WR2
; Read the int vector register to confirm value written
ld a,2 ; select WR2 (int vector)
out (sio_cmd+2),a ; do it
in a,(sio_cmd+2) ; get int vector value
and $F0 ; only top nibble
cp $F0 ; compare
ret nz ; abort if miscompare
;
; Program the SIO, just channel A
ld c,sio_cmd ; command port
ld hl,sio_initregs ; point to init values
ld b,sio_initlen ; count of bytes to write
otir ; write all values
;
xor a ; signal success
ret ; done
;
;
;
sio_cin:
call sio_cist ; check for char ready
jr z,sio_cin ; if not, loop
in a,(sio_dat) ; read byte
ret ; done
;
;
;
sio_cout:
push af ; save incoming
sio_cout1:
call sio_cost ; ready for char?
jr z,sio_cout1 ; loop if not
pop af ; restore incoming
out (sio_dat),a ; write byte
ret ; and done
;
;
;
sio_cist:
xor a ; select WR0
out (sio_cmd),a ; do it
in a,(sio_cmd) ; get status
and $01 ; isolate rx ready
ret ; a != 0 if rx ready, else 0
;
;
;
sio_cost:
xor a ; select WR0
out (sio_cmd),a ; do it
in a,(sio_cmd) ; get status
and $04 ; isolate tx ready (empty)
ret ; a != 0 if tx ready, else 0
;
; Table for chip register initialization. Simple setup for clock
; divided by 64. Assuming a system clock of 7.3728 MHz, this will
; result in a baud rate of 115200 which is standard for RC2014.
;
sio_initregs:
.db $00, $18 ; wr0: channel reset cmd
.db $04, $C4 ; wr4: clk baud parity stop bit
.db $01, $00 ; wr1: no interrupts
.db $02, $00 ; wr2: im2 vec offset
.db $03, $E1 ; wr3: 8 bit rcv, cts/dcd auto, rx enable
.db $05, $EA ; wr5: dtr, 8 bits send, tx enable, rts 1 11 0 1 0 1 0 (1=dtr,11=8bits,0=sendbreak,1=txenable,0=sdlc,1=rts,0=txcrc)
;
sio_initlen .equ $-sio_initregs

106
Source/HDIAG/uart.asm

@ -0,0 +1,106 @@
;
;=======================================================================
; HDIAG UART Driver
;=======================================================================
;
; Assumes the UART conventions for SBC/MBC/Zeta, base port at $68.
; Assuming a UART clock frequency of 1.8432 MHz, the baud rate
; will be 38400.
;
uart_iob .equ $68
uart_osc .equ 1843200
uart_baudrate .equ 38400
uart_divisor .equ uart_osc / uart_baudrate / 16
;
uart_rbr .equ uart_iob + 0 ; dlab=0: rcvr buffer reg (read only)
uart_thr .equ uart_iob + 0 ; dlab=0: xmit holding reg (write only)
uart_ier .equ uart_iob + 1 ; dlab=0: int enable reg
uart_iir .equ uart_iob + 2 ; int ident register (read only)
uart_fcr .equ uart_iob + 2 ; fifo control reg (write only)
uart_lcr .equ uart_iob + 3 ; line control reg
uart_mcr .equ uart_iob + 4 ; modem control reg
uart_lsr .equ uart_iob + 5 ; line status reg
uart_msr .equ uart_iob + 6 ; modem status reg
uart_scr .equ uart_iob + 7 ; scratch register
uart_dll .equ uart_iob + 0 ; dlab=1: divisor latch (ls)
uart_dlm .equ uart_iob + 1 ; dlab=1: divisor latch (ms)
;
;
;
uart_jptbl:
jp uart_cinit ; Initialize serial port
jp uart_cin ; Read byte
jp uart_cout ; Write byte
jp uart_cist ; Input status
jp uart_cost ; Output Status
;
;
;
uart_cinit:
; Test for existence
xor a ; zero accum
out (uart_ier),a ; ier := 0
ld a,$80 ; dlab bit on
out (uart_lcr),a ; output to lcr (dlab regs now active)
ld a,$5A ; load test value
out (uart_dlm),a ; output to dlm
in a,(uart_dlm) ; read it back
cp $5A ; check for test value
ret nz ; nope, unknown uart or not present
xor a ; dlab bit off
out (uart_lcr),a ; output to lcr (dlab regs now inactive)
in a,(uart_ier) ; read ier
cp $5A ; check for test value
jr nz,uart_cinit1 ; if *not* $5A, good to go
or $FF ; signal error
ret ; done
;
uart_cinit1:
ld a,$80 ; lcr := dlab on
out (uart_lcr),a ; set lcr
ld a,uart_divisor & $ff ; low byte of divisor
out (uart_dll),a ; set divisor (lsb)
ld a,uart_divisor / $100 ; high byte of divisor
out (uart_dlm),a ; set divisor (msb)
xor a ; zero accum
out (uart_ier),a ; init ier (no ints)
ld a,$03 ; value for lcr and mcr
out (uart_lcr),a ; lcr := 3, dlab off, 8 data, 1 stop, no parity
out (uart_mcr),a ; mcr := 3, dtr on, rts on
ld a,$07 ; enable & reset fifo's
out (uart_fcr),a ; do it
xor a ; signal success
ret
;
;
;
uart_cin:
call uart_cist ; received char ready?
jr z,uart_cin ; loop if not
in a,(uart_rbr) ; read byte
ret ; and done
;
;
;
uart_cout:
push af ; save incoming
uart_cout1:
call uart_cost ; ready for char?
jr z,uart_cout1 ; loop if not
pop af ; restore incoming
out (uart_thr),a ; write byte
ret ; and done
;
;
;
uart_cist:
in a,(uart_lsr) ; get status
and $01 ; isolate bit 0 (receive data ready)
ret ; a != 0 if char ready, else 0
;
;
;
uart_cost:
in a,(uart_lsr) ; get status
and $20 ; isolate bit 5
ret ; a != 0 if char ready, else 0

106
Source/HDIAG/util.asm

@ -0,0 +1,106 @@
;
;=======================================================================
; HDIAG Utility Functions
;=======================================================================
;
; Print string at HL on console, null terminated.
; HL and AF are trashed.
;
prtstr:
ld a,(hl) ; get next character
or a ; set flags
inc hl ; bump pointer regardless
ret z ; done if null
call cout ; display character
jr prtstr ; loop till done
;
; Print the hex byte value in A
;
prthex8:
push af
push de
call hexascii
ld a,d
call cout
ld a,e
call cout
pop de
pop af
ret
;
; Print the hex word value in BC
;
prthex16:
push af
ld a,b
call prthex8
ld a,c
call prthex8
pop af
ret
;
; Print the hex dword value in DE:HL
;
prthex32:
push bc
push de
pop bc
call prthex16
push hl
pop bc
call prthex16
pop bc
ret
;
; Convert binary value in A to ASCII hex characters in DE
;
hexascii:
ld d,a
call hexconv
ld e,a
ld a,d
rlca
rlca
rlca
rlca
call hexconv
ld d,a
ret
;
; Convert low nibble of A to ASCII hex
;
hexconv:
and $0F ; low nibble only
add a,$90
daa
adc a,$40
daa
ret
;
; Jump to address in HL/IX/IY
;
; No registers affected
; Typically used as "call jphl" to call a routine
; at address in HL register.
;
jphl:
jp (hl)
;
jpix:
jp (ix)
;
jpiy:
jp (iy)
;
; Add hl,a
;
; A register is destroyed!
;
addhla:
add a,l
ld l,a
ret nc
inc h
ret

71
Source/HDIAG/z180.inc

@ -0,0 +1,71 @@
;
;=======================================================================
; Z180 Internal I/O Ports
;=======================================================================
;
; These are offsets from the Z180 I/O base address.
;
z180_cntla0 .equ $00 ; asci0 control a
z180_cntla1 .equ $01 ; asci1 control a
z180_cntlb0 .equ $02 ; asci0 control b
z180_cntlb1 .equ $03 ; asci1 control b
z180_stat0 .equ $04 ; asci0 status
z180_stat1 .equ $05 ; asci1 status
z180_tdr0 .equ $06 ; asci0 transmit
z180_tdr1 .equ $07 ; asci1 transmit
z180_rdr0 .equ $08 ; asci0 receive
z180_rdr1 .equ $09 ; asci1 receive
z180_cntr .equ $0a ; csi/o control
z180_trdr .equ $0b ; csi/o transmit/receive
z180_tmdr0l .equ $0c ; timer 0 data lo
z180_tmdr0h .equ $0d ; timer 0 data hi
z180_rldr0l .equ $0e ; timer 0 reload lo
z180_rldr0h .equ $0f ; timer 0 reload hi
z180_tcr .equ $10 ; timer control
;
z180_asext0 .equ $12 ; asci0 extension control (z8s180)
z180_asext1 .equ $13 ; asci1 extension control (z8s180)
;
z180_tmdr1l .equ $14 ; timer 1 data lo
z180_tmdr1h .equ $15 ; timer 1 data hi
z180_rldr1l .equ $16 ; timer 1 reload lo
z180_rldr1h .equ $17 ; timer 1 reload hi
z180_frc .equ $18 ; free running counter
;
z180_astc0l .equ $1a ; asci0 time constant lo (z8s180)
z180_astc0h .equ $1b ; asci0 time constant hi (z8s180)
z180_astc1l .equ $1c ; asci1 time constant lo (z8s180)
z180_astc1h .equ $1d ; asci1 time constant hi (z8s180)
z180_cmr .equ $1e ; clock multiplier (latest z8s180)
z180_ccr .equ $1f ; cpu control (z8s180)
;
z180_sar0l .equ $20 ; dma0 source addr lo
z180_sar0h .equ $21 ; dma0 source addr hi
z180_sar0b .equ $22 ; dma0 source addr bank
z180_dar0l .equ $23 ; dma0 dest addr lo
z180_dar0h .equ $24 ; dma0 dest addr hi
z180_dar0b .equ $25 ; dma0 dest addr bank
z180_bcr0l .equ $26 ; dma0 byte count lo
z180_bcr0h .equ $27 ; dma0 byte count hi
z180_mar1l .equ $28 ; dma1 memory addr lo
z180_mar1h .equ $29 ; dma1 memory addr hi
z180_mar1b .equ $2a ; dma1 memory addr bank
z180_iar1l .equ $2b ; dma1 i/o addr lo
z180_iar1h .equ $2c ; dma1 i/o addr hi
z180_iar1b .equ $2d ; dma1 i/o addr bank (z8s180)
z180_bcr1l .equ $2e ; dma1 byte count lo
z180_bcr1h .equ $2f ; dma1 byte count hi
z180_dstat .equ $30 ; dma status
z180_dmode .equ $31 ; dma mode
z180_dcntl .equ $32 ; dma/wait control
z180_il .equ $33 ; interrupt vector load
z180_itc .equ $34 ; int/trap control
;
z180_rcr .equ $36 ; refresh control
;
z180_cbr .equ $38 ; mmu common base register
z180_bbr .equ $39 ; mmu bank base register
z180_cbar .equ $3a ; mmu common/bank area register
;
z180_omcr .equ $3e ; operation mode control
z180_icr .equ $3f ; i/o control register

49
Source/HDIAG/z2u.asm

@ -0,0 +1,49 @@
;
;=======================================================================
; HDIAG Z180 UART Driver
;=======================================================================
;
z2u_jptbl:
jp z2u_cinit ; Initialize serial port
jp z2u_cin ; Read byte
jp z2u_cout ; Write byte
jp z2u_cist ; Input status
jp z2u_cost ; Output Status
;
;
;
z2u_cinit:
; initialize port here
or $FF ; signal failure for now
ret
;
;
;
z2u_cin:
call z2u_cist ; check for char ready
jr z,z2u_cin ; if not, loop
; read byte here
ret ; done
;
;
;
z2u_cout:
push af ; save incoming
z2u_cout1:
call z2u_cost ; ready for char?
jr z,z2u_cout1 ; loop if not
pop af ; restore incoming
; write byte here
ret ; and done
;
;
;
z2u_cist:
; check input status here
ret
;
;
;
z2u_cost:
; check output status here
ret ; a != 0 if char ready, else 0

3
Source/Makefile

@ -1,7 +1,8 @@
# #
# order is actually important, because of build dependencies # order is actually important, because of build dependencies
# #
SUBDIRS = Prop
SUBDIRS = HDIAG
SUBDIRS += Prop
SUBDIRS += Apps SUBDIRS += Apps
SUBDIRS += CBIOS SUBDIRS += CBIOS
SUBDIRS += Forth SUBDIRS += Forth

2
Source/ver.inc

@ -2,4 +2,4 @@
#DEFINE RMN 1 #DEFINE RMN 1
#DEFINE RUP 1 #DEFINE RUP 1
#DEFINE RTP 0 #DEFINE RTP 0
#DEFINE BIOSVER "3.1.1-pre.116"
#DEFINE BIOSVER "3.1.1-pre.117"

2
Source/ver.lib

@ -3,5 +3,5 @@ rmn equ 1
rup equ 1 rup equ 1
rtp equ 0 rtp equ 0
biosver macro biosver macro
db "3.1.1-pre.116"
db "3.1.1-pre.117"
endm endm

3
Tools/Makefile.inc

@ -69,6 +69,9 @@ CPM=$(TOOLS)/cpm/bin
rm -f $$($(CASEFN) $*.hex) ; \ rm -f $$($(CASEFN) $*.hex) ; \
fi fi
%.rom: %.asm
$(TASM) $(TASMFLAGS) $< $@ $*.lst
%.hex: %.asm %.hex: %.asm
$(ZXCC) $(CPM)/MAC -$< -$$PO $(ZXCC) $(CPM)/MAC -$< -$$PO

Loading…
Cancel
Save