recipes/trs80: Collapse OS runs on the TRS-80 Model 4P!

This commit is contained in:
Virgil Dupras 2020-02-12 10:20:47 -05:00
parent c5116b39ae
commit 9515d63d47
6 changed files with 148 additions and 30 deletions

10
kernel/trs80/kbd.asm Normal file
View File

@ -0,0 +1,10 @@
; kbd - TRS-80 keyboard
;
; Implement GetC for TRS-80's keyboard using the system's SVCs.
trs80GetC:
push de ; altered by SVC
ld a, 0x01 ; @KEY
rst 0x28 ; --> A
pop de
ret

16
kernel/trs80/vid.asm Normal file
View File

@ -0,0 +1,16 @@
; vid - TRS-80's video
;
; Implement PutC using TRS-80's SVC calls so that character it put on video
; display.
trs80PutC:
push af
push bc
push de ; altered by SVC
ld c, a
ld a, 0x02 ; @DSP
rst 0x28
pop de
pop bc
pop af
ret

10
recipes/trs80/Makefile Normal file
View File

@ -0,0 +1,10 @@
TARGET = os.bin
BASEDIR = ../..
ZASM = $(BASEDIR)/emul/zasm/zasm
KERNEL = $(BASEDIR)/kernel
APPS = $(BASEDIR)/apps
.PHONY: all
all: $(TARGET)
$(TARGET): glue.asm
$(ZASM) $(KERNEL) $(APPS) < glue.asm > $@

View File

@ -4,7 +4,20 @@ The TRS-80 (models 1, 3 and 4) are among the most popular z80 machines. They're
very nicely designed and I got my hands on a 4p with two floppy disk drives and
a RS-232 port. In this recipe, we're going to get Collapse OS running on it.
**This is a work in progress. Collapse OS doesn't run on it yet.**
![Collapse OS on a TRS-80 Model 4P](collapseos-on-trs80.jpg)
## Not entirely standalone
Collapse OS uses the TRS-80 drivers rather than its own. On most TRS-80 models,
those drivers are on ROM, but in the case of the 4P model, those drivers are on
the TRSDOS disk (well, from what I understand, not all of it, but still, a big
part of it).
It would be preferable to develop drivers from scratch, but it represents a
significant effort for a modest payout (because it's only actually useful when
you want to use a 4P model that has no TRSDOS disk).
Maybe those drivers will be developed later, but it's not a priority for now.
## Floppy or RS-232?
@ -50,6 +63,11 @@ my knowledge. As far as I know, the COMM program doesn't allow this.
What are we going to do? We're going to punch in a binary program to handle that
kind of reception! You're gonna feel real badass about it too...
## Building the binary
You can start the process by building the binary. Running `make` in this folder
will yield a `os.bin` file. You'll need it later.
## Testing serial communication
The first step here is ensuring that you have bi-directional serial
@ -93,6 +111,8 @@ press the `BREAK` key. You'll get the debug interface which allows you to punch
in any data in any memory address. Let's use `0x4000` which is the offset it's
designed for.
For reference: to go back to the TRSDOS prompt, it's `o<return>`.
First, display the `0x4000-0x403f` range with the `d4000<space>` command (I
always press Enter by mistake, but it's space you need to press). Then, you can
begin punching in with `h4000<space>`. This will bring up a visual indicator of
@ -117,34 +137,6 @@ driver was loaded in `0x0ff4` and the DCB address was 8 bytes after that, with
a value of `0x0238`. Don't forget that z80 is little endian. `38` will come
before `02`.
## Sending data through the RS-232 port
Once you're finished punching your program in memory, you can run it with
`g4000<enter>` (not space). Because it's an infinite loop, your screen will
freeze. You can start sending your data.
To that end, there's the `tools/pingpong` program. It takes a device and a
filename to send. As a test, send anything, but make it go through
`tools/ttysafe` first (which just takes input from stdin and spits tty-safe
content to stdout).
On OpenBSD, the invocation can look like:
doas ./pingpong /dev/ttyU0 mystuff.ttysafe
You will be prompted for a key before the contents is sent. This is because on
OpenBSD, TTY configuration is lost as soon as the TTY is closed, which means
that you can't just run `stty` before running `pingpong`. So, what you'll do is,
before you press your key, run `doas stty -f /dev/ttyU0 300 raw` and then press
any key on the `pingpong` invocation.
If everything goes well, the program will send your contents, verifying every
byte echoed back, and then send a null char to indicate to the receiving end
that it's finished sending. This will end the infinite loop on the TRS-80 side
and return. That should bring you back to a refreshed debug display and you
should see your sent content in memory, at the specified address (`0x3040` if
you didn't change it).
## Saving that program for later
If you want to save yourself typing for later sessions, why not save the
@ -159,4 +151,47 @@ A memory range dumped this way will be re-loaded at the same offset through
using the `RUN` command. Therefore, you can avoid all this work above in later
sessions by simply typing `recv` in the DOS prompt.
**WIP: that's where we are for now...**
## Sending binary through the RS-232 port
Once you're finished punching your program in memory, you can run it with
`g4000<enter>` (not space). If you've saved it to disk, run `recv` instead.
Because it's an infinite loop, your screen will freeze. You can start sending
your data.
To that end, there's the `tools/pingpong` program. It takes a device and a
filename to send. Before you send the binary, make it go through
`tools/ttysafe` first (which just takes input from stdin and spits tty-safe
content to stdout):
./ttysafe < os.bin > os.ttysafe
On OpenBSD, the invocation can look like:
doas ./pingpong /dev/ttyU0 os.ttysafe
You will be prompted for a key before the contents is sent. This is because on
OpenBSD, TTY configuration is lost as soon as the TTY is closed, which means
that you can't just run `stty` before running `pingpong`. So, what you'll do is,
before you press your key, run `doas stty -f /dev/ttyU0 300 raw` and then press
any key on the `pingpong` invocation.
If everything goes well, the program will send your contents, verifying every
byte echoed back, and then send a null char to indicate to the receiving end
that it's finished sending. This will end the infinite loop on the TRS-80 side
and return. That should bring you back to a refreshed debug display and you
should see your sent content in memory, at the specified address (`0x3000` if
you didn't change it).
If there was no error during `pingpong`, the content should be exact.
Nevertheless, I recommend that you manually validate a few bytes using TRSDOS
debugger before carrying on.
## Running Collapse OS
If everything went well, you can run Collapse OS with `g3000<space>`. You'll
get a usable Collapse OS prompt!
Like with the `recv` program, nothing stops you from dumping that binary to a
floppy.
Have fun!

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

47
recipes/trs80/glue.asm Normal file
View File

@ -0,0 +1,47 @@
; RAMSTART is a label at the end of the file
.equ RAMEND 0xcfff
; Free memory in TRSDOS starts at 0x3000
.org 0x3000
jp init
.inc "err.h"
.inc "ascii.h"
.inc "core.asm"
.inc "str.asm"
.inc "trs80/kbd.asm"
.inc "trs80/vid.asm"
.equ STDIO_RAMSTART RAMSTART
.equ STDIO_GETC trs80GetC
.equ STDIO_PUTC trs80PutC
.inc "stdio.asm"
; *** BASIC ***
; RAM space used in different routines for short term processing.
.equ SCRATCHPAD_SIZE STDIO_BUFSIZE
.equ SCRATCHPAD STDIO_RAMEND
.inc "lib/util.asm"
.inc "lib/ari.asm"
.inc "lib/parse.asm"
.inc "lib/fmt.asm"
.equ EXPR_PARSE parseLiteralOrVar
.inc "lib/expr.asm"
.inc "basic/util.asm"
.inc "basic/parse.asm"
.inc "basic/tok.asm"
.equ VAR_RAMSTART SCRATCHPAD+SCRATCHPAD_SIZE
.inc "basic/var.asm"
.equ BUF_RAMSTART VAR_RAMEND
.inc "basic/buf.asm"
.equ BAS_RAMSTART BUF_RAMEND
.inc "basic/main.asm"
init:
ld sp, RAMEND
call basInit
jp basStart
RAMSTART: