EPO provides module Texts which hard-wires the serial device that writes text to the Astrobe terminal. The Texts.Writer parameter that is passed to all output procedures is kept for compatibility, but not actually used.

Texts.Write is the basis for all text output:

PROCEDURE Write*(VAR W: Writer; ch: CHAR)
  CONST data = -56; stat = -52;
  SYSTEM.PUT(data, ORD(ch))
END Write;

Texts.Writer Reborn

To be able to use Texts for formatted output to other devices, for example additional serial terminals or LCD screens, it is extended and changed as follows:

  TextDevice* = POINTER TO TextDeviceDesc;
  TextDeviceDesc* = RECORD END;
  PutCharProc* = PROCEDURE(dev: TextDevice; ch: CHAR);
  Writer* = RECORD
    device: TextDevice;
    putChar: PutCharProc

PROCEDURE OpenWriter(VAR W: Writer; dev: TextDevice; pcp: PutCharProc)
  W.device := dev;
  W.putChar := pcp
END OpenWriter;

PROCEDURE Write(VAR W: Writer; ch: CHAR);
  W.putChar(W.device, ch)
END Write;

Now any device that extends Texts.TextDevice can be “plugged” into a Texts.Writer, and all output procedures of Texts can be used to write formatted text to that device.

For example, the RS232 device is defined like so in module RS232dev:

  Device* = POINTER TO DeviceDesc;
  DeviceDesc* = RECORD(Texts.TextDeviceDesc)
    (* ... *)

With RS232dev.Dev0 being the actual serial device connected to the Astrobe terminal, and RS232.PutChar the single character output procedure over this serial line, the following code makes a corresponding Texts.Writer available to other modules, such as System.

  W*: Texts.Writer;
  dev: RS232dev.Device;

NEW(dev); RS232dev.Init(dev, RS232dev.Dev0);
Texts.OpenWriter(W, dev, RS232.PutChar) 

See Console.

Similarly, the driver for LC displays uses this structure:

  Display* = POINTER TO DisplayDesc;
  DisplayDesc* = RECORD(Texts.TextDeviceDesc)
    W*: Texts.Writer;
    (* ... *)

Hence Texts can be used to output to the LC display.

Other Changes

Texts.WriteClock is modified to print in this format:

yyyy-mm-dd hh:mm:ss

Possible Improvements

The current implementation relies on the single character output procedure Texts.Write for all output. This could be improved as follows:

  • Filling the output buffer could be more efficient if the multi-character output procedures of the underlying serial driver could be used, eg. RS232b.PutBytes.
  • Busy-waiting when the output buffer is full could be avoided if the outputting process could yield control to other processes until output is possible again when the buffer is emptied. While this could be achieved in each outputting process itself, it should be solved on the serial driver level once and for all.