I've been working on some drivers in
Z88DK for the RC2014 SIO/2 board by Spencer.
I'm happy to say that they're pretty much finished now.
Once they're committed it should be easy for anyone to write C or assembly programs using Z88DK, and have full support for the SIO/2.
Until then, I've attached two HEX files which should demonstrate the functions. Just remove the .txt extension.
If you have an SIO/2 board, and can configure the standard 32kB of RAM / 8kB ROM, give them a try.
Be gentle. The paint is still fresh.
The two SIO ports are configured as:
SIOA: stdin, stdout, stderr
SIOB: ttyin, ttyout, ttyerr
By default, the SIOB is configured with no local echo. This is because the assumption is that it will be used as a TTY.
This can be easily reconfigured (and indeed was reconfigured to make the password_siob program work properly).
Below is the password.c program rewritten to address the SIOB I/O. The SIOA I/O password.c program is as found in the repository.
The only change from the standard ACIA is to use the -subtype=sio option.
// zcc +rc2014 -v -subtype=sio -SO3 -clib=sdcc_iy --max-allocs-per-node200000 password.c -o password -create-app
#pragma printf = "%s"
#pragma scanf = "%["
#include <stdio.h>
#include <stropts.h>
#include <string.h>
#include <adt.h>
b_array_t edit_buffer;
char username[20];
char password[20];
void main(void)
{
fprintf(ttyout,"USERNAME + PASSWORD QUERY\n");
fprintf(ttyout,"username pushed into edit buffer\n");
// gather details about the input terminal's buffer
ioctl(3, IOCTL_ITERM_GET_EDITBUF, &edit_buffer);
while(1)
{
fprintf(ttyout,"\n=====\n\nUsername: ");
// push last username into edit buffer
fflush(ttyin);
edit_buffer.size = strlen(username);
strcpy(edit_buffer.data, username);
ioctl(3, IOCTL_ITERM_SET_EDITBUF, &edit_buffer);
// read username
fscanf(ttyin,"%19[^\n]", username);
// read password
fprintf(ttyout,"Password: ");
ioctl(3, IOCTL_ITERM_PASS, 1);
fflush(ttyin);
fscanf(ttyin,"%19[^\n]", password);
ioctl(3, IOCTL_ITERM_PASS, 0);
// echo
fprintf(ttyout,"\n\"%s\"\n", username);
fprintf(ttyout,"\"%s\"\n", password);
}
}
The same drivers will work for any SIO/2 board, including Dr Baker's, by configuring the Command / Data, and Channel A / B defines to suit the actual addressing provided.
From here, my intention is to integrate them into a version of
CPM-IDE, to allow the SIO/2 board as an alternative serial interface.
Since the CP/M implementation supports two serial interfaces anyway, this will be a useful addition to what should be a simple CP/M.
So, what's good about these SIO/2 drivers?
- Well I'm really happy to have learned about the IM2 mode of the Z80, with vectored interrupts. Most of the SIO/2 implementations around tend to configure the SIO to use a single IM2 interrupt vector, and then read the SIO Register 0 to determine what caused the receive interrupt. Also, usually transmit is not buffered. These new drivers implement a IM2 full interrupt table, from which a specific vector address is loaded into the Z80 during the interrupt response. The outcome of this is that the transmit, receive, and error vectors for each channel are separate, and are very short, as they know that when they're called there's something relating specifically to them.
- Also, when reading the datasheet it is clear that Read Register 0 does not need to be written to before being read, yet every implementation seems to do it. It works fine as per the datasheet, and saves time in the interrupts. Writing Register 0 before reading Register 0 seems to be just code folk-law. But, time will tell.
- Finally, the Transmit function is buffered (by default by 15 bytes), but has a cut-through if no characters are waiting to be transmitted. And, the Receive function is buffered, and has a RTS signalling function. I've left the RTS code commented out because many USB serial interfaces don't do anything with it, and it is an expensive (time consuming) feature to have in the interrupts.
Enjoy,
Phillip