So you have an old microcomputer board that has a UART but no PIO. Maybe one like mine. No chance then of driving a couple of digital I/O lines unless you add a PIO chip?

Hmm, let's look at the data sheet for the Intel 8251, a typical UART of a bygone era. Here's part of the page describing the modem lines.

These lines were intended for handshaking between the UART and the data set. In the past this meant the modem, but these days it could be a PC talking to the microcomputer through a serial interface.

If you are don't require handshake, then DTR and RTS can be used as output lines, and DSR can be used as an input line. CTS is an input line, but is not directly readable by the CPU, it only has an effect on the transmit buffer.

Let me cut to the chase. It works.

And here's a short video of it in action. The test setup on the Arduino Uno uses pins 2-9 to drive the data pins of the UART, A0 to drive the Control/~Data line, A1 to drive the ~Read line, A2 to drive the ~Write line and A3 to drive the Reset line. On a MCU board these would already be part of the circuit and you just have to program the UART appropriately.

Here is the program:

//
// Drive 8251 UART with Arduino
// Pins 2-9 are connected to D0-D7
// Pins A0-A3 are connected as #define below
//

#define CNOTD A0
#define READ  A1
#define WRITE A2
#define RESET A3
#define DTRBIT 0x02
#define RTSBIT 0x20

byte cmdinst = 0;

void init8251()
{
  pinMode(CNOTD, OUTPUT);
  pinMode(READ, OUTPUT);
  pinMode(WRITE, OUTPUT);
  pinMode(RESET, OUTPUT);
  digitalWrite(CNOTD, HIGH);
  digitalWrite(READ, HIGH);
  digitalWrite(WRITE, HIGH);
  digitalWrite(RESET, HIGH);  // RESET
  delay(1);
  digitalWrite(RESET, LOW);  // release
  delay(1);
  writecmd(0x4e); // mode: x16, 8 bit, 1 stop bit
  writecmd(0x10); // command: error reset
}

void writecmd(byte b)
{
  for (byte i = 2; i < 10; i++) {
    pinMode(i, OUTPUT);
  }
  for (byte i = 2; i < 10; i++) {
    digitalWrite(i, b & 0x1 ? HIGH : LOW);
    b >>= 1;
  }
  digitalWrite(WRITE, LOW); // pulse /W
  delayMicroseconds(1);
  digitalWrite(WRITE, HIGH);
}

byte readstatus()
{
  byte b = 0;
  for (byte i = 2; i < 10; i++) {
    pinMode(i, INPUT_PULLUP);
  }
  digitalWrite(READ, LOW); // lower /R
  delayMicroseconds(1);
  for (byte i = 2; i < 10; i++) {
    b >>= 1;
    if (digitalRead(i) == HIGH)
      b |= 0x80;
  }
  digitalWrite(READ, HIGH); // raise /R
  return (b);
}

inline void dtr0()
{
  writecmd(cmdinst |= DTRBIT);  // /DTR = 0
}

inline void dtr1()
{
  writecmd(cmdinst &= ~DTRBIT); // /DTR = 1
}

inline void rts0()
{
  writecmd(cmdinst |= RTSBIT);  // /RTS = 0
}

inline void rts1()
{
  writecmd(cmdinst &= ~RTSBIT); // /RTS = 1
}

// First test program
//
void blink()
{
  dtr0();      // /DTR antiphase to /RTS
  delay(500);
  for (;;) {
    dtr1();
    rts0();
    delay(500);
    rts1();
    dtr0();
    delay(500);
  }
}

/*
  Second test program

  Program for displaying counting from 0 - 9999 modified from
  www.funwidelectronics.blogspot.in

  This source code is modified from :
  https://blog.3d-logic.com/2015/01/21/arduino-and-the-tm1637-4-digit-seven-segment-display/

  Thanks for the code
*/

#define clk0 rts0
#define clk1 rts1
#define data0 dtr0
#define data1 dtr1

byte digits[] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f };

void start(void)
{
  clk1();
  data1();
  delayMicroseconds(5);
  data0();
  clk0();
  delayMicroseconds(5);
}

void stop(void)
{
  clk0();
  data0();
  delayMicroseconds(5);
  clk1();
  data1();
  delayMicroseconds(5);
}

bool writebyte(byte value)
{
  for (byte i = 0; i < 8; value >>= 1, i++) {
    clk0();
    delayMicroseconds(5);
    if (value & 0x1)
      data1();
    else
      data0();
    delayMicroseconds(5);
    clk1();
    delayMicroseconds(5);
  }
  // wait for ACK (not available in this implementation)
  clk0();
  delayMicroseconds(5);
  //pinMode(data, INPUT);
  clk1();
  delayMicroseconds(5);
  //bool ack = digitalRead(data) == 0;
  //pinMode(data, OUTPUT);
  return true;
}

void writenumber(byte first, byte second, byte third, byte fourth)
{
  start();
  writebyte(0x40);
  stop();
  start();
 writebyte(...
Read more »