
Software Development
Writing the code for this terminal really teleported me back to the 1980’s. Luckily with the convenience of quickly erasable NOR Flash memory instead of UV erasable EPROM’s (which would have added 30 minutes or so to every debug cycle).
My development cycle starts with writing the assembly/C source code on my Linux PC. Then use the z88dk development kit to generate the binary code. I copy this binary code to a Windows VM to program the NOR Flash using the, probably well known, TL866II plus programmer. Unfortunately, the ZIF socket of my TL866II plus isn’t of the greatest quality and I had to reseat the NOR Flash quite often to successfully program the NOR Flash
Once programmed, I then physically move the NOR Flash to the terminal board hoping everything worked what I was working on (which wasn’t often the case…).

The development environment
For this I choose the z88dk development kit which has become quite some development environment over the years supporting many Z80 targets (it originally started as a Cambridge Z88 development kit). Luckily it also supports Z180 CPU as used in the terminal project. The Z180 runs in Z80 mode here but it does have a few new instructions which are supported by the z88dk tools.
I struggled to get the z88dk up and running. There is plenty of documentation
but it’s not always up to date with the latest versions of z88dk. Also, I feel
z88dk prefers to have the source code you work on inside the z88dk directory
structure. Something I don’t like. I prefer to keep tools and my project source
directories separated and under their own source code control. In the end I did
find a solution to keep them separated by setting up my environment like so.
The below content is stored in a set_environment.sh
file in my project
directory:
#!/bin/sh
export PATH=~/Documents/Projects/Retro/Projects/Tools/z88dk/bin/:$PATH
export LPATH=~/Documents/Projects/Retro/Projects/Tools/z88dk/lib
export ZCCCFG=~/Documents/Projects/Retro/Projects/Tools/z88dk/lib/config/
The above paths will of course only work in my set up but it might inspire others for a similar set up.
The only thing I need to do, is open a terminal window in my project directory and execute:
. set_environment.sh
And my environment is set up.
With the above only, assembling/compiling still doesn’t work correctly though and
I got errors about files not found. The only workaround I found was moving my
current working directory to the .../z88dk/libsrc/_DEVELOPMENT/target/z180
directory and assemble/compile my sources from that path. I ended up with this build
script (stored in build.sh
):
export myCWD=($PWD)
pushd .
cd ~/Documents/Projects/Retro/Projects/Tools/z88dk/libsrc/_DEVELOPMENT/target/z180
zcc +z180 \
-mz180 \
-clib=sdcc_iy \
-startup=1 \
-L~/Documents/Projects/Retro/Projects/Tools/z88dk/libsrc/_DEVELOPMENT/lib/sdcc_iy \
@$myCWD/z180_project.lst \
-pragma-include:$myCWD/z180_pragma.inc \
-o $myCWD/terminal \
-create-app -Cz"--org 0 --rombase=0x0000 --romsize=0x8000" \
--c-code-in-asm \
--list \
-zorg=0 \
-m \
-s
popd
Running this script from my working directory like so:
./build.sh
will first store my current working directory in the myCWD
environment
variable after which I do a pushd
to store my current project directory,
from which I started, on the stack as well.
Then I cd
into the z88dk
directory (more specifically .../z88dk/libsrc/_DEVELOPMENT/target/z180
)
from where I call zcc
, which is the compiler front-end which will
compile my assembly/C code sources specified by the $myCWD/z180_project.lst
file which resides in my project directory. The content of my z180_project.lst
currently is:
src/bootZ180.asm
src/crt6845.asm
src/escapeCSIHandling.asm
src/flash.asm
src/interruptVectorTable.asm
src/main.c
src/mainLoop.asm
src/printChar.asm
src/serialPorts.asm
src/setup.c
src/screenHandling.asm
src/utils.c
As you can see, I keep my assembly/C-code sources in a separate src
directory
of my project directory.
The popd
at the end fetches my project directory back from the stack and
makes sure I’m back there again.
After a successful compile, a terminal.rom
file (amongst others) will pop up
in my project directory which is the binary image to be used to program the NOR
Flash chip as discussed at the beginning of this post.
Understood ANSI/VT100 Escape Sequences
Handling of the Escape CSI sequences is done in escapeCSIHandling.asm
(CSI
being ‘Command Sequence Introducer’). Below is an overview of the understood
(correctly I hope) CSI commands:
CSI | Code |
---------------------------|------|----------------------------------------------------------
CursorUp | 'A' | CUU -- Cursor Up -- Host to VT100 and VT100 to Host
| | ESC [ Pn A default value: 1
| |
| | Moves the active position upward without altering the
| | column position. The number of lines moved is determined
| | by the parameter. A parameter value of zero or one moves
| | the active position one line upward. A parameter value
| | of n moves the active position n lines upward. If an
| | attempt is made to move the cursor above the top margin,
| | the cursor stops at the top margin. Editor Function.
---------------------------------------------------------------------------------------------
CursorDown | 'B' | CUD -- Cursor Down -- Host to VT100 and VT100 to Host
| | ESC [ Pn B default value: 1
| |
| | The CUD sequence moves the active position downward
| | without altering the column position. The number of lines
| | moved is determined by the parameter. If the parameter
| | value is zero or one, the active position is moved one
| | line downward. If the parameter value is n, the active
| | position is moved n lines downward. In an attempt is made
| | to move the cursor below the bottom margin, the cursor
| | stops at the bottom margin. Editor Function.
---------------------------------------------------------------------------------------------
CursorForward | 'C' | CUF -- Cursor Forward -- Host to VT100 and VT100 to Host
| | ESC [ Pn C default value: 1
| |
| | The CUF sequence moves the active position to the right.
| | The distance moved is determined by the parameter. A
| | parameter value of zero or one moves the active position
| | one position to the right. A parameter value of n moves
| | the active position n positions to the right. If an
| | attempt is made to move the cursor to the right of the
| | right margin, the cursor stops at the right margin.
| | Editor Function.
---------------------------------------------------------------------------------------------
CursorBack | 'D' | CUB -- Cursor Backward -- Host to VT100 and VT100 to Host
| | ESC [ Pn D default value: 1
| |
| | The CUB sequence moves the active position to the left.
| | The distance moved is determined by the parameter. If
| | the parameter value is zero or one, the active position
| | is moved one position to the left. If the parameter value
| | is n, the active position is moved n positions to the left.
| | If an attempt is made to move the cursor to the left of
| | the left margin, the cursor stops at the left margin.
| | Editor Function.
---------------------------------------------------------------------------------------------
CursorNextLine | 'E' | CNL -- Next Line
| | ESC [ Pn E
| |
| | This sequence causes the active position to move to the
| | first position on the next line downward. If the active
| | position is at the bottom margin, a scroll up is performed.
| | Format Effector.
---------------------------------------------------------------------------------------------
CursorPreviousLine | 'F' | CPL -- Previous Line
| | ESC [ Pn F
| |
| | This sequence causes the active position to move to the
| | first position on the previous line upward. If the active
| | position is at the top margin, a scroll down is performed.
| | Format Effector.
---------------------------------------------------------------------------------------------
CursorHorizontalAbsolute | 'G' | CHA - Cursor Horizontal Absolute
| | ESC [ Pn G
| |
| | Moves the cursor to column n (default 1).
---------------------------------------------------------------------------------------------
Separator | ';' |
---------------------------------------------------------------------------------------------
CursorPosition | 'H' | CUP -- Cursor Position
| | ESC [ Pn ; Pn H default value: 1
| |
| | The CUP sequence moves the active position to the position
| | specified by the parameters. This sequence has two
| | parameter values, the first specifying the line position
| | and the second specifying the column position. A parameter
| | value of zero or one for the first or second parameter
| | moves the active position to the first line or column in
| | the display, respectively. The default condition with no
| | parameters present is equivalent to a cursor to home action.
| | In the VT100, this control behaves identically with its
| | format effector counterpart, HVP. Editor Function
| |
| | The numbering of lines depends on the state of the Origin
| | Mode (DECOM).
---------------------------------------------------------------------------------------------
EraseInDisplay | 'J' | ED -- Erase In Display
| | ESC [ Ps J default value: 0
| |
| | This sequence erases some or all of the characters in the
| | display according to the parameter. Any complete line
| | erased by this sequence will return that line to single
| | width mode. Editor Function
| |
| | Parameter Parameter Meaning
| | 0 Erase from the active position to the end of the
| | screen, inclusive (default)
| | 1 Erase from start of the screen to the active position,
| | inclusive
| | 2 Erase all of the display -- all lines are erased,
| | changed to single-width, and the cursor does not move.
---------------------------------------------------------------------------------------------
EraseInLine | 'K' | EL -- Erase In Line
| | ESC [ Ps K default value: 0
| |
| | Erases some or all characters in the active line according
| | to the parameter. Editor Function
| |
| | Parameter Parameter Meaning
| | 0 Erase from the active position to the end of the line,
| | inclusive (default)
| | 1 Erase from the start of the screen to the active
| | position, inclusive
| | 2 Erase all of the line, inclusive
---------------------------------------------------------------------------------------------
InsertLine | 'L' | IL -- Insert Line
| | ESC [ Pn L
| |
| | Inserts Pn lines at line with cursor. Lines displayed
| | below cursor move down. Lines moved past the bottom
| | margin are lost. This sequence is ignored when cursor is
| | outside scrolling region.
---------------------------------------------------------------------------------------------
DeleteLine | 'M' | DL -- Delete Line (DL)
| | ESC [ Pn M
| |
| | Deletes Pn lines, starting at line with cursor. As lines
| | are deleted, lines displayed below cursor move up. Lines
| | added to bottom of screen have spaces with same character
| | attributes as last line moved up. This sequence is
| | ignored when cursor is outside scrolling region.
---------------------------------------------------------------------------------------------
ScrollUp | 'S' | SU - Scroll Up
| | ESC [ Pn S
| |
| | Scroll whole page up by n (default 1) lines. New lines
| | are added at the bottom.
---------------------------------------------------------------------------------------------
ScrollDown | 'T' | SD - Scroll Down
| | ESC [ Pn T
| |
| | Scroll whole page down by n (default 1) lines. New lines
| | are added at the top.
---------------------------------------------------------------------------------------------
HorizontalVerticalPosition | 'f' | HVP -- Horizontal and Vertical Position
| | ESC [ Pn ; Pn f default value: 1
| |
| | Moves the active position to the position specified by
| | the parameters. This sequence has two parameter values,
| | the first specifying the line position and the second
| | specifying the column. A parameter value of either zero
| | or one causes the active position to move to the first
| | line or column in the display, respectively. The default
| | condition with no parameters present moves the active
| | position to the home position. In the VT100, this control
| | behaves identically with its editor function counterpart,
| | CUP. The numbering of lines and columns depends on the
| | reset or set state of the origin mode (DECOM). Format
| | Effector.
---------------------------------------------------------------------------------------------
SelectGraphicRendition | "m" | SGR -- Select Graphic Rendition
| | ESC [ Ps ; . . . ; Ps m default value: 0
| |
| | Invoke the graphic rendition specified by the
| | parameter(s). All following characters transmitted to
| | the VT100 are rendered according to the parameter(s)
| | until the next occurrence of SGR. Format Effector
| |
| | Parameter Parameter Meaning
| | 0 Attributes off
| | 1 Bold or increased intensity
| | 4 Underscore
| | 5 Blink
| | 7 Negative (reverse) image
| | All other parameter values are ignored.
| |
| | With the Advanced Video Option, only one type of character
| | attribute is possible as determined by the cursor
| | selection; in that case specifying either the underscore
| | or the reverse attribute will activate the currently
| | selected attribute.
| |
| | From <https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#8-colors>
| | Black: \u001b[30m | Bright Black: \u001b[30;1m
| | Red: \u001b[31m | Bright Red: \u001b[31;1m
| | Green: \u001b[32m | Bright Green: \u001b[32;1m
| | Yellow: \u001b[33m | Bright Yellow: \u001b[33;1m
| | Blue: \u001b[34m | Bright Blue: \u001b[34;1m
| | Magenta: \u001b[35m | Bright Magenta: \u001b[35;1m
| | Cyan: \u001b[36m | Bright Cyan: \u001b[36;1m
| | White: \u001b[37m | Bright White: \u001b[37;1m
| |
| | Background Black: \u001b[40m | Background Bright Black: \u001b[40;1m
| | Background Red: \u001b[41m | Background Bright Red: \u001b[41;1m
| | Background Green: \u001b[42m | Background Bright Green: \u001b[42;1m
| | Background Yellow: \u001b[43m | Background Bright Yellow: \u001b[43;1m
| | Background Blue: \u001b[44m | Background Bright Blue: \u001b[44;1m
| | Background Magenta: \u001b[45m | Background Bright Magenta: \u001b[45;1m
| | Background Cyan: \u001b[46m | Background Bright Cyan: \u001b[46;1m
| | Background White: \u001b[47m | Background Bright White: \u001b[47;1m
---------------------------------------------------------------------------------------------