Dr. Scott M. Baker

Z80 Retrocomputing 9 – CTC and dual serial ports for RC2014

by admin on Aug.20, 2016, under Electronics Projects

In this post, I add a Z80 CTC (counter-timer) and SIO/2 (serial IO) to the RC2014

If you haven’t read my other Z80 retrocomputing blog posts yet, then please start with the first one, Intro to Z80 Retrocomputing, for an overview of the RC2014 platform.

Motivation

All I wanted to do was connect a GPS module to the RC2014… This turned out to be much more difficult than I anticipated.

I started by designing a dual 68B50 serial board, but I neglected to pay attention that the GPS module I chose (UP501) operated by default at 9600 baud. While you can configure it to operate at additional baud rates, you have to send the configuration command at the power-up default, which is 9600 baud. The 68B50 can be configured with a clock divider of 1, 16, or 64. With the RC2014’s system clock, that allows us to easily select 115,200 baud by using a divider of 64. However, there’s no way to easily select a baud rate that is less than 115,200 baud.

I explored a number of alternatives to adding additional clock chips and dividers. This seemed like a lot of work and special-purpose complication, especially if I wanted to be able to control the baud rate using software. Ultimately I decided to use the Z80 CTC. The CTC offers 4 independent counter/timers. Three of them have external outputs, which we can connect to our serial chip to use as a baud rate reference.

68B50 vs SIO/2

My original solution was a dual 68B50 board. For whatever reason, this proved very unreliable. It was sensitive to which slot it was plugged into the RC2014 backplane. It had to be right next to the CPU, or occasionally it would do weird things like drop characters or fail to reset properly. I spent a fair amount of time trying to debug my dual 68B50 board, and ultimately decided on using the SIO/2 instead.

The SIO/2 is a dual serial chip. It is far more complex than the 68B50, offering different operating modes and fancier interrupt support. For configuration there are eight different write registers and three different read registers. One advantage is that one SIO/2 chip yields two serial ports, whereas I would have needed two 68B50.

CTC Board Design and Implementation

Here is the schematic of the CTC board

RC2014 CTC board Schematic

The schematic is fairly straightforward. There’s a 74HJCT138N for address decoding, which is used as a chip select for the CTC. I’ve brought the CTC’s signals out to a couple of places. TO0, TO1, and TO2 (the outputs) are brought out to a header at the top of the board and to some jumpers that let you easily connect them to the RC2014 backplane’s extra pins. TRG0, TRG1, TRG2, and TRG3 (the triggers) are brought out to a dual pin header block that allows you to easily connect them to either an on-board oscillator or (if the on-board oscillator is not installed) to the system clock. SJ1 is a jumper that allows you to restrict addressing to when A4 is high. This will let you put the board at 10,30,50,70,90,B0,D0 instead of on 00,20,40,60,80,A0,C0,E0 like my other boards. My plan is to put the board at 0×90 so that it shares the 0×80-0×9F address range with the SIO.

Here is my completed CTC board:

RC2014 CTC Board, Assembled

As you can see, I’ve left the footprint for the crystal unpopulated. The jumper to the right of the crystal footprint passes the system clock over to the TRIG/OSC jumper block to the right of the CTC chip, where I’ve jumpered it to the channel 1 trigger.

SIO Board Design and implementation

Here is the schematic of the SIO board:

RC2014 SIO/2 board schematic

This is also a fairly straightforward board. We again have a 74HCT138N for address decoding that allows us to put the board on 00,20,40,60,80,A0,C0, or E0. The serial ports are brought out to a pair of 6-pin headers that allow you to easily connect FTDI cables or other devices like a GPS. I opted not to install a MAX232 driver on-board. If you really want a 9-pin serial port, then a MAX232 can be installed externally.

There are two jumpers, JP6 and JP7 that allow you to either select the system clock as the clock source, or get clock from one of the RC2014 backplane’s extra pins. The idea is that a CTC pin will be brought out to E1 on the CTC board, and then picked up on E1 for the SIO board to allow us to set custom baud rates. The TX and RX pins can be jumpered to the backplane as well. Finally, there is a jumper for the interrupt mode that allows you to either use 5V (interrupts allowed all the time) or to connect the interrupt pin to E3, where it could in theory be connected to the CTC board. For simple implementation, I enable the interrupts all the time, but the CTC and SIO do have a more sophisticated mechanism where they can generate interrupt vectors that identify the device that generated the interrupt.

There is an optional oscillator footprint that allows you to use a custom oscillator, and a jumper to use the system clock instead of the custom oscillator.

Here is the completed board:

RC2014 SIO board, prototype

As you can see, this board has a few … imperfections … I mistakenly wired the IEI pin to GND when it should have been wired to 5V, hence the yellow jumper wire. I also didn’t have any provisions for using separate clocks for ports A and B (not visible, but there is a cut trace under the SIO chip and a piece of yellow wire on the back to deal with this). These issues have been corrected in the schematic, and I’ll soon be sending off for a replacement board.

Here is the revised version:

RC2014 SIO/2 board, rev2

As you can see the revised one fixes the hacked in piece of yellow wire, and adds three new jumpers. The two jumpers on the very right side of the board are the clocks for Ports A and B (note the order is A then B, whereas the order of the port headers on the top of the board is B then A). Immediately beneath the clock jumpers is a jumper marked IEI which selects the source of the IEI pin. If fits a little tight next to the SIO chip, but it does fit. You can either select IEI from 5V to fix the interrupts as enabled, or jumper it to the fourth spare pin on the RC2014 backplane. This board revision is the one that is available on the Osh Park link at the bottom of this page.

The way I have the board jumpered in the picture above is:

  • address 80h
  • port A clock = clock from RC2014 backplane
  • port B clock = second extra pin on RC2014 backplane (which is in turn supplied by CTC chip)

Programming the CTC as a baud rate generator for the SIO/2

My first attempt was to use the CTC in timer mode. This seemed relatively simple to me, I would take the system clock, prescale by either 256 or 16, and then setup the time constant for the final division to yield the appropriate baud rate. The SIO/2 would be configured to divide by 1. Here are my calculations:

CPU Frequency = 7,372,800 Hz.

Baud Prescaler Time Constant
1200 256 24
2400 16 192
9600 16 48
19200 16 24
38400 16 12
57600 16 8
115200 16 4

Unfortunately, the above scheme didn’t work very well. Sometimes it would work, but sometimes the SIO/2 would end up out of sync with the incoming serial stream and output occasional splotches of gibberish. After some experimentation, I found that my SIO/2 was unreliable whenever the clock mode was set to X1. The same thing would happen when I tried to use my 68B50 with an X1 clock divider. I’m still a little bit confused at this; my reading of the data sheets led me to believe this would work just fine. Maybe it comes down to quality of implementation and my PCB layouts aren’t quite clean enough for the X1 mode.

I did find that the SIO/2 would work perfectly if the clock mode was set to X16. This means we have to output a rate from the CTC that is 16 times higher than our baud rate. For a baud rate of 115,200 that would mean outputting a timer rate of 1,843,200 Hz. Since the CTC always selects a prescaler (either 16 or 256) in timer mode, a 7.3728 MHz system clock is insufficient to produce a timer rate of 1,843,200 Hz.

This led me to try operating the CTC in counter mode with an external trigger. Counter mode works much like timer mode, but it counts external pulses via the trigger input. The advantage to counter mode is that the X16/X256 prescaler is not forced upon you. We can feed the system clock into the trigger input, and then use timer mode to output the baud rate we want.

Baud Timer Rate Time Constant
1200 19200 96
2400 38400 48
9600 153600 24
19200 307200 12
38400 614400 6
57600 921600 4
115200 1843200 2

This worked perfectly. I was able to read from my GPS without constant weird splotches of high-ascii gibberish.

If you check my math in the above table, you’ll notice the time constants are half of what you’d expect them to be. This surprised me, and I think I found the answer in the CTC data sheet: “Although there is no setup time requirement between the triggering edge of the External clock and the rising edge of Φ (Clock), the down-counter is not decremented until the following pulse“. Since I have the trigger connected to the system clock, it’s counting every other trigger pulse.

Modifying RC2014 Basic

I started with Grant Searle’s Z80 SBC modifications to Nascom Basic. A link to Grant Searle’s ZIP file containing source code is here. The changes I made are the following:

  1. Use an SIO/2 instead of a 68B50
  2. Modify interrupt handler, TX, and RX functions for the second serial port.
  3. Add a BAUD rate function to set the baud rate.
  4. Add four new BASIC keywords: ISER, OSER, RSER, and BAUD.

The new basic keywords function as follows:

  • ISER(x) – read a character from serial port (x=0 or 1)
  • RSER(x) – check readiness of serial port (x=0 or 1)
  • OSER x,y – output character Y to serial port X (x=0 or 1)
  • BAUD x,y – set baud rate on port X to Y (x=0 or 1, y=1 for 1200, 2 for 2400, 9 for 9600, 115 for 115200)

Here is a sample program that reads all characters on the second serial port and writes them to the first serial port.

10 REM check port 1
20 IF RSER(1)=0 GOTO 50
30 X=ISER(1)
40 OSER 0,X
50 GOTO 10

Wiring it all up

Here’s a diagram of how everything is connected:

CTC and SIO diagram

Source code

As usual you can find the source code in my github repo at http://www.github.com/sbelectronics.

PC-Board ordering:

As usual, you can find them on osh park:

CTC Board

Order from OSH Park

SIO/2 Board

Order from OSH Park


4 Comments for this entry

  • Robert Reynolds

    Hi Scott

    Love your site and your youtube videos. Thanks for sharing

    I wondered whether you are planning on uploading the designs for your SIO and CTC boards to OshPark?

    Thanks

    Rob

  • admin

    Yes, I’ll be sharing the designs soon. The CTC board design is good. The SIO I had to revise due to a few errors.

  • Paul Bigwood

    Hi Scott, Fixed the problems with OSH Park! My order for 5 of your boards in one go seemed to glitch the website. Jenner fixed and I am waiting for them to arrive. Already gone to FAB so hopefully should here in the UK in short time.

    I think there may be a typo in the Programming the CTC as a baud rate generator section above. in the 4th para you say

    …This led me to try operating the SIO/2 in counter mode with an external trigger. … should this not be CTC?

    Best Regards
    Paul

  • admin

    Yes, that looks like a typo. Thanks. I’ll fix!

    Scott

2 Trackbacks / Pingbacks for this entry

Leave a Reply


nine − = 6

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

New Kickstarter Project!

Interested in Nixie Tube projects? Check out my new Nixie Tube Calculator project on Kickstarter.

Copyright Notice

All content on this website is copyright Scott M. Baker and may not be used or reprinted without explicit permission.

Violators will be eaten by a grue.