Adding a serial interface - MC6850 ACIA

Adding a Serial Interface


This step will add a serial interface to the SBC and in so doing move a big step closer to having a real computer.  The serial interface will provide for full keyboard entry and an ASCII terminal display.  Very exciting!

My first choice asynchronous communication adaptor would have been a 6551 but at the time I couldn't find one in the UK at a reasonable price so I opted for a related, but more basic MC6850 .  It has no baud generator so the choice of a crystal oscillator circuit was more critical than for a 6551.  Also the 6850 uses only two registers by cunningly differentiating two pairs (four total) by making one pair read only (RX buffer and status register) and the other write only (TX buffer and Control register).  Not as elegant as the 6551 but it works.

Conceptually the circuit is simple enough - the 6850 requires 8 data lines, one register select line (A0), PHI2, RW and a chip select line from the address decoding logic.  On the serial side I used an FTDI serial to USB module - FTDI only because I had one; any should work.  Only three lines to connect - TX, RX and ground.  I have not tried using the IRQ line so far.

Clock Generator

The MC6850 has got three options to divide the clock frequency - 1, 16 and 64.  I chose to use a 1.8432MHz crystal divided by 16 in the MC6850 to yield 115200 baud.

Clock generator for 6850
This is the oscillator circuit:

Note that the choice of NAND gate type is important for this circuit to work correctly.  I used a very old 7400 IC (true retro computing!); an 'LS' series worked too.  HC and HCT types will not work correctly because they are much higher gain and are difficult to bias correctly.  Sometimes old is better 😲

The 6850 allows for the clock to be divided by 1, 16 or 64.  I chose 1.8432MHz because dividing by 16 produces 115200.  Dividing by 64 would yield 28800 but I didn't see any advantage in going slower.

The 6551 has a baud rate generator that allows a number of speeds to be set with one crystal but the 6850 is limited to the crystal divided by one of the three values (set in configuration).


6850 Circuit



Not much too this:
  • Connections to data bus
  • Clock oscillator
  • Address decoding logic to 6850 CS
  • RW
  • PHI0
  • A0 to RS

Watch out RX on the 6850 connects to TX on USB to Serial: TX on 6850 to RX on USB Serial.



6850 Configuration

Only 8 bits to write to the configuration file.  This is what I used:

        %00010101

        Bit 7 clear         - no interrupts
        Bits 6 & 5         - select type of interrupt.  Not used
        Bits 4, 3 & 2     - 8 data bits, 1 stop bit and no parity
        Bits 1 & 0         - divide clock by 16

Assembler Code for Testing

Sending

The steps required are to:

  1. Check if the TX buffer is empty by reading the Status register.  Bit 1 signals the TX buffer and is set until the buffer is empty
  2. Store a value from the accumulator into the 6850 data register
Polling the status register can be done like this:

 WAIT:    LDA        Status_Register
         AND        #%00000010
         BEQ        WAIT
         STA        Data_Register

Receiving

The steps required are to:

  1. Check if the RX buffer is full by reading the Status register.  Bit 0 signals the RX buffer and is set when the buffer is full i.e. a complete character has been received.
  2. Load the character into accumulator to clear the RX buffer flag and to allow the next character to be received
Polling the status register can be done like this:

 WAIT:    LDA        Status_Register
         AND        #%00000001
         BEQ        WAIT
         LDA        Data_Register

There is no flow control so the 6502 code must read characters as they arrive - if this is not done an overflow error flag will be raised.

Results

The serial interface transformed what was up to this point mainly a hardware experiment into a useable 6502 SBC!  Having the ability to send and receive from a laptop with full keyboard and screen has been astonishing.  The interface works consistently well and at 115200 is more than fast enough for all my needs.

This short video shows how a terminal on a laptop appears.  Characters are being typed on the laptop keyboard, sent through USB to the 6850 ACIA and received by the 65C02.  The code simply sends the received character back - the characters appearing in the terminal window are coming from the 65C02 via the ACIA:

Where Next?

With the serial interface in place I want to be able to load new code directly into RAM and to execute it.  This requires a basic 'monitor' program in ROM to manage data flow in both directions.  More on these developments in more posts soon!

Another experiment is to compare the 6850 with a 6551 (thanks for the donation Louis!) which includes a baud rate generator so can be configured to run several rates by setting the control register.

Components

Oscillator:
  1. 7400 quad NAND gate (or 74LS00)
  2. 100nF capacitor
  3. 120F capacitor
  4. 2 x 330 ohm resistors
  5. 1.8432MHz crystal
Other:
  1. MC6850 ACIA
  2. USB to Serial module        

Comments

  1. Once again, a very informative post. Would be really good to see the comparisons against the 6551. Thanks for your time to write these up.... keep it up.

    ReplyDelete
    Replies
    1. I appreciate your kind feedback and interest. Will experiment with the 6551 and carry out some comparisons then write up a post here.

      Delete
  2. It's interesting that your 1.8432MHz clock worked reliably for you. Please note the MC6850 datasheet specifies maximum Data Clock Frequency (fC), in /16 & /64 modes, as max 0.8MHz for MC6850, 1.0Mhz for MC68A50, and 1.5MHz for MC68B50.
    Therefore, feeding a 1.8432MHz clock directly into Rx CLK & Tx CLK is significantly exceeding the chip's clock specifications, and therefore also not meeting the minimum Data Clock Width specifications (PWCL & PWCH).
    Given this, it's worth warning others that this may be troublesome depending on your specific 6850 ACIA chip.

    Also, with using such a high data rate (115200 etc.), and without making use of the hardware handshaking, you will likely experience receiver overrun errors (signified by OVRN status bit), if attempting to transmit an actual data stream from your PC... other than just your intermitant key presses :)

    ReplyDelete
  3. Hi Greg, that is very interesting and I was not aware of those limitations. Really helpful to have them exposed here and you've provided me with a new line of experiments!

    Since writing this post I found a 6551 ACIA and have been running that at 9600 without problems, including using Intel Hex File transfer. I'll switch back to the 6850 and see how the issues manifest themselves in practice.

    Thanks for highlighting the issues for us all!

    ReplyDelete
  4. Hi Robin. Just some background, and some additional info that may be helpful…

    Back in the day, I mostly built Motorola MC6800 & MC6809 (my fav retro CPU) systems, mostly using wire wrap, as we did in the late 70’s early 80’s. I’m just now (re)building an IO interface card for an ASSIST09 based 6809, which features MC6840 PTM( timer), MC6821 PIA, and MC6850 ACIA.

    For the Rx & Tx CLK I’m using 4.9152MHz along with a nice compact (14 pin) dual 4-bit binary counter (74HCT393 - note: TTL compatible).

    This allows me to select either a /8, /16, /32, /64 clock output, for more appropriate 38400, 19200, 9600, or 4800 baud rates, with the MC6850 configured in its common /16 Rx & TX CLK divider mode.

    Notes:
    (1) At the fastest /8 input (for 38400 data rate), I’m therefore only driving Rx & Tx CLK at 614.4KHz, which satisfies the MC6850 0.8MHz maximum Data Clock Frequency (fC).
    (2) You could (of course), also use the common 2.4576MHz with /4, /8, /16, /32, for the same result. :-)

    One other point that you don’t appear to have covered, is that with the 6850 ACIA you should always first write a 3 (000011) to the Control Register, before you write your configuration. This is the Master Reset condition, which clears the status register and initialises the receiver and transmitter. The Master Reset bits must be set after power-on etc. (Refer to the datasheet for more info)

    Hope this all helps with your experiments. :-)

    ReplyDelete
    Replies
    1. Been looking more closely at the MC6850 and realised that it does not have RX flow control and RTS/CTS only operates in TX mode. Is that correct?

      That suggests I need to service the IRQ in less time than the fastest possible next character arriving. With those slow data rates I’m guessing that should be perfectly feasible but will set up a slower clock using whatever I can find and do some timings with an oscilloscope. I should be able to do the arithmetic but measuring is always reassuring!

      Have now found the reference to writing ‘3' to the CR to do a master reset but had missed it before. Very enjoyable tinkering!

      Delete
    2. Hi Robin,

      The MC6850 does support both Rx and Tx hardware flow control! For Tx you have the CTS input, which automatically inhibits the Transmit Data Register Empty status flag, allowing the remote device to control your transmit rate.

      For Rx flow control you have the RTS output, which you set to indicate to the remote device whether you are ready to receive. You control the RTS output to function as per your intended use. eg. You could implement as either a RTS, RTR, or DTR function (or not at all).

      In terms of IRQ, whether interrupt driven is necessary depends entirely on your application. If your application is I/O centric, for example a monitor program that spends most of it’s time waiting on user input, then simply polling the ACIA is perfectly fine.
      However, if you have a more complex application, I’d say interrupt driven (implementing transmit and receive buffers), would certainly be the path to take.

      In terms of the data rate: Yes, it’s logical to only support data rates that the CPU can manage to service. But note that, in addition to your interrupt service routine’s time to move a newly received character into your receive buffer (and transmit any next waiting character), you also need to consider your overall application’s ability to process your receive buffer (before it can overflow!).

      Typically, Rx hardware flow control should only really be necessary in the case where an interrupt driven approach could still potentially overrun whatever size receive buffer you’ve choose to implement (to support your application’s needs).

      For what it’s worth, I generally run my 8-bit system ACIA’s no faster than 19200 (more typically 9600) baud, which I find to be plenty fast enough for most needs. Even for downloading larger S1-S9 format files (after all, we are playing in a 64K address space).

      ps. I also use an oscilloscope to review all of my circuits. It’s one thing to theoretically abide by all the datasheet timings, but until you can actually see how your circuit is responding in real life (with circuit capacitance / inductance in play), you don’t really know how reliably your circuit timing is working.

      Enjoy your tinkering. Nothing beats the fun of tinkering in the retro microprocessor space, where you can have complete understanding and full control over the hardware! :-)

      Delete
    3. Very interesting comments again, thanks Greg. If you want to continue in more detail it would be better to switch to email as this thread could get lengthy: robin@g4giy.uk

      I've studied the 6850 datasheet but have not been able to figure out how to control the RTS output with the RDRF status. Could you explain how the RDRF flag is used to toggle the state of RTS output please?

      Delete
    4. If it’s okay with you, I think preferable to keep the discussion going here. It may well be of interest of others, who may also wish to contribute their own knowledge and experience. :-)

      The RTS output is not directly related to RDRF status flag. Indeed, it would not be logical to use the RDRF flag as a determinant for toggling the RTS output, for (notably) asynchronous receive flow control!

      Unlike the transmit flow control, where the CTS input automatically inhibits the TDRE flag (to pause you loading the next byte to transmit), any receive data flow control would be quite specific to your application.
      Consider that, when you de-assert the RTS output, a byte may still be partially in transit. It’s also a function of the remote device as to how it responds to its inbound CTS signalling.

      For this reason, your application (that wishes to use RTS control), would need to manually de-assert the RTS output at a time that is appropriate to its own processing. Specifically, when your implemented receive buffer is *nearly* full. By *nearly*, I am meaning you should expect that you may yet receive 1 or 2 more characters. You would then want to again re-assert RTS as soon as you are able to free-up some receive buffer space (to some lower buffer threshold).

      Note, this is really just a theoretical description of how you would potentially utilise the RTS output in a RTR (Ready To Receive) role. I say theoretical, as I myself have never coded for MC6850 RTS output based hardware handshaking.

      I’d again say that if your chosen data rate is within the capabilities of your CPU, and your application is appropriately designed, then you should not need to implement Rx flow control. You perhaps can also just tie the CTS input to ground and utilise a simple 3-wire interface! After all, we are generally not interfacing with Modems these days. ;-)

      For reference, toggling the RTS output pin is a manual function controlled by the CR5 & CR6 control register bits. These bits control the RTS output pin, in addition to TDRE interrupt control, and break transmission (logic low output).

      Note also that upon a Power-On reset, the RTS line is de-asserted (CR6 = 1 & CR5 = 0), and RTS also remains de-asserted during Master Reset (CR5 & CR6 bits are “don’t care” when writing 3 to the CR), until such a time as you assert the RTS output during subsequent control register initialisation (when CR5 & CR6 are accessible).

      For reading additional to the datasheet, I’d suggest a read-through of Motorola Application Note AN-754 "Device Operation and System Implementation of the Asynchronous Communications Interface Adapter (MC6850)”. You can find this here: https://bit.ly/3qzI7KL (from page 21 on).

      You almost now have me wanting to tinker with some code to explore this RTS receive flow control further. But, I do have too many projects competing for my time already. Plus, as I've noted, if you're able to stick with device appropriate data rates, then this RTS topic possibly does sit in the "over-engineering" category?

      Delete
    5. Now that is VERY helpful. There is a lot to absorb so give me some time to get my head around all that - my thinking was on the wrong track. I am inclined to set up RX flow control just for the challenge - can't see a real need but the real point is self-learning. Your explanation has opened up a whole new area to explore. Like you, I have many projects running in parallel (even being retired doesn't leave sufficient time!) - just acquired a 3D printer and am learning how to design things and print them!

      The application notes should be very useful - got it downloaded and will browse that over the next few days.

      Delete

Post a Comment