|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- # TRS-80 Model 4p
-
- 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.
-
- ![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?
-
- There are many ways to get Collapse OS to run on it. One would involve writing
- it to a floppy. I bought myself old floppy drives for that purpose, but I happen
- to not have any functional computer with a floppy port on it. I still have the
- motherboard of my old pentium, but I don't seem to have a video card for it any
- more.
-
- Because my 4p has a RS-232 port and because I have equipment to do serial
- communication from modern machines (I didn't have a DB-9 to DB-25 adapter
- though, I had to buy one), I chose that route.
-
- ## Gathering parts
-
- * A TRS-80 model 4p with a RS-232 port
- * A TRSDOS 6.x disk
- * A means to do serial communication. In my case, that meant:
- * A USB-to-serial device
- * A null modem cable
- * A DB-9 gender changer
- * A DB-9 to DB-25 adapter
-
- ## Overview
-
- We need to send sizeable binary programs through the RS-232 port and then run
- it. The big challenge here is ensuring data integrity. Sure, serial
- communication has parity check, but it has no helpful way of dealing with
- parity errors. When parity check is enabled and that a parity error occurs, the
- byte is simply dropped on the receiving side. Also, a double bit error could be
- missed by those checks.
-
- What we'll do here is to ping back every received byte back and have the sender
- do the comparison and report mismatched data.
-
- Another problem is ASCII control characters. When those are sent across serial
- communication channels, all hell breaks lose. When sending binary data, those
- characters have to be avoided. We use `tools/ttysafe` for that.
-
- Does TRSDOS have a way to receive this binary inside these constraints? Not to
- 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...
-
- ## Keyboard tips
-
- * `_` is `CLEAR+ENTER`.
-
- ## Building the binary
-
- You can build the binary to send to the TRS-80 with `make`, which will yield
- `os.bin`. You'll need it later.
-
- ## Testing serial communication
-
- The first step here is ensuring that you have bi-directional serial
- communication. To do this, first prepare your TRS-80:
-
- set *cl to com
- setcomm (word=8,parity=no)
-
- The first line loads the communication driver from the `COM/DRV` file on the
- TRSDOS disk and binds it to `*cl`, the name generally used for serial
- communication devices. The second line sets communication parameters in line
- with what is generally the default on modern machine. Note that I left the
- default of 300 bauds as-is.
-
- Then, you can run `COMM *cl` to start a serial communication console.
-
- Then, on the modern side, use your favorite serial communication program and set
- the tty to 300 baud with option "raw". Make sure you have `-parenb`.
-
- If your line is good, then what you type on either side should echo on the
- other side. If it does not, something's wrong. Debug.
-
- ## Punching in the goodie
-
- As stated in the overview, we need a program on the TRS-80 that:
-
- 1. Listens to `*cl`
- 2. Echoes each character back to `*cl`
- 3. Adjusts `ttysafe` escapes
- 4. Stores received bytes in memory
-
- You're in luck: that program has already been written. It's in B502 and B503.
- You can compile it with:
-
- 212 LOAD ( z80 assembler )
- 0x0238 CONSTANT COM_DRV_ADDR
- 0x3000 CONSTANT DEST_ADDR
- 502 LOAD
- 503 LOAD
-
- Then, you can use `DUMP` to visualize the data you'll need to punch in:
-
- H@ ORG @ - ORG @ DUMP
-
- It can run from any offset (all jumps in it are relative), but writes to
- `DEST_ADDR`. Make sure you don't place it in a way to be overwritten by its
- received data.
-
- Wondering what is that `COM_DRV_ADDR` constant? That's the DCB handle of your
- `*cl` device. You will need to get that address before you continue. Go read
- the following section and come back here.
-
- How will you punch that in? The `debug` program! This very useful piece of
- software is supplied in TRSDOS. To invoke it, first run `debug (on)` and then
- 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 `0x5000` which is the offset it's
- designed for.
-
- For reference: to go back to the TRSDOS prompt, it's `o<return>`.
-
- First, display the `0x5000-0x503f` range with the `d5000<space>` command (I
- always press Enter by mistake, but it's space you need to press). Then, you can
- begin punching in with `h5000<space>`. This will bring up a visual indicator of
- the address being edited. Punch in the stuff with a space in between each byte
- and end the edit session with `x`.
-
- ## Getting your DCB address
-
- In the previous step, you need to set `COM_DRV_ADDR` to your "DCB" address for
- `*cl`. That address is your driver "handle". To get it, first get the address
- where the driver is loaded in memory. You can get this by running `device
- (b=y)`. That address you see next to `*cl`? that's it. But that's not our DCB.
-
- To get your DBC, go explore that memory area. Right after the part where there's
- the `*cl` string, there's the DCB address (little endian). On my setup, the
- 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`.
-
- ## Saving that program for later
-
- If you want to save yourself typing for later sessions, why not save the
- program you've painfully typed to disk? TRSDOS enables that easily. Let's say
- that you typed your program at `0x5000` and that you want to save it to
- `RECV/CMD` on your second floppy drive, you'd do:
-
- dump recv/cmd:1 (start=x'5000',end=x'5030',tra='5000')
-
- A memory range dumped this way will be re-loaded at the same offset through
- `load recv/cmd:1`. Even better, `TRA` indicates when to jump after load when
- using the `RUN` command. Therefore, you can avoid all this work above in later
- sessions by simply typing `recv` in the DOS prompt.
-
- Note that you might want to turn `debug` off for these commands to run. I'm not
- sure why, but when the debugger is on, launching the command triggers the
- debugger.
-
- ## Sending binary through the RS-232 port
-
- Once you're finished punching your program in memory, you can run it with
- `g5000<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 < stage1.bin > stage1.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.
-
- *debugging tip*: Sometimes, the communication channel can be a bit stubborn and
- always fail, as if some leftover data was consistently blocking the channel. It
- would cause a data mismatch at the very beginning of the process, all the time.
- What I do in these cases is start a `COMM *cl` session on one side and a screen
- session on the other, type a few characters, and try `pingpong` again.
-
- ## Saving to disk
-
- If everything went well, you could run Collapse OS with `g3000<return>`.
- But instead of doing that, why not save it to disk?
-
- dump cos/cmd:1 (start=x'5000',end=x'7000',tra='5000')
-
- And there we go! A Collapse OS launchable from floppy!
-
- ## Sending blkfs to floppy
-
- As it is, your system fully supports reading and writing to floppy drive 1. It
- also had `*CL<` to read a char from `*cl` and `*CL>` to emit a char to `*cl`.
-
- That's all you need to have a full Collapse OS with access to disk blocks.
-
- First, make sure your floppies are formatted. Collapse OS is currently
- hardcoded to single side and single density, which means there's a limit of 100
- blocks per disk.
-
- You'll need to send those blocks through RS-232. Begin by taking over the
- prompt:
-
- ' *CL> 0x53 RAM+ !
- ' *CL< 0x55 RAM+ !
-
- See B80 for details about those RAM offsets. Your serial link now has the
- prompt. You will also have to make your newlines CRLF. The TRS-80 wants CR
- only, but serial communications (and `blkup`) expect CRLF:
-
- ' CRLF 0x0a RAM+ !
-
- Now, you can use `/tools/blkup` to send a disk's contents. First,
- extract the first 100 blocks from blkfs:
-
- dd if=emul/blkfs bs=1024 count=100 > d1
-
- Now, insert your formatted disk in drive 1 and push your blocks:
-
- tools/blkup /dev/ttyUSB0 0 d1
-
- It takes a while, but you will end up having your first 100 blocks on floppy!
- Go ahead, `LIST` around. Then, repeat for other disks.
-
- ## Floppy organisation
-
- Making blkfs span multiple disk is a bit problematic with regards to absolute
- block references in the code. You'll need to work a bit to design your very
- own Collapse OS floppy set. See Usage guide (B3) for details.
-
- ## Coming back to keyboard
-
- Once you're done, you will want to go back to local control:
-
- ' CR 0x0a RAM+ !
- 0 0x55 RAM+ !
- 0 0x53 RAM+ !
-
- ## Self-hosting
-
- As it is, your installment of Collapse OS is self-hosting using instructions
- very similar to `recipes/rc2014/selhost`. The difference is that instead of
- writing the binary you have in memory to EEPROM, you'll quit to TRSDOS with
- `BYE` and use TRSDOS' `DUMP` utility to save to disk like you already did
- before.
-
|