RS232DriverImpl.mesa
Mik Lamming - August 26, 1983 11:58 am
DIRECTORY
RS232Driver,
Inline,
DicentraInputOutput;
RS232DriverImpl: PROGRAM
IMPORTS Inline, DicentraInputOutput, RS232Driver
EXPORTS RS232Driver
= BEGIN
MiscBoardOffset: DicentraInputOutput.IOAddress = LOOPHOLE[LONG[09000H]];
chanB: LONG POINTER TO Words ← MiscBoardOffset; -- channel B
chanA: LONG POINTER TO Words ← MiscBoardOffset + 10H; -- channel A
Words: TYPE = RECORD [
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15: WORD];
Bits8: CARDINAL    = 0C1H;
Clock16x: CARDINAL  = 04CH;
ClockRate:LONG CARDINAL ← 2500000; -- 2.5MHz
Clocks: CARDINAL   = 050H;
DisableInt: CARDINAL   = 0H;
DTR: CARDINAL    = 0EAH;
Enable: CARDINAL   = 003H;
Reset: CARDINAL   = 0C0H;
RXFullBit: CARDINAL   = 01H;
ShiftLeft: CARDINAL  = 002H;
TXEmptyBit: CARDINAL  = 040H;
ComputeBaudPair: PROC[baudRate:CARDINAL] RETURNS[l,h:CARDINAL] = BEGIN
Calculate the magic numbers for the baud rate registers
Kludge: TYPE = MACHINE DEPENDENT RECORD [
SELECT OVERLAID * FROM
card => [c:CARDINAL],
pair => [topHalf:[0..255], bottomHalf:[0..255]],
ENDCASE];
k:Kludge;
k.c← (ClockRate / (32 * baudRate)) - 2;
l ← k.bottomHalf;
h ← k.topHalf;
END;
Open: PUBLIC PROC[baudRate:CARDINAL] = BEGIN
Open RS232 connection and establish baud rate. Can do this at any time.
l,h:CARDINAL;
[l, h] ← ComputeBaudPair[baudRate];
DicentraInputOutput.Output[ShiftLeft, @chanB.r0];  -- Shift Left (ADR0 is ignored)
DicentraInputOutput.Output[Reset, @chanA.r9];   -- Hardware Reset, Dis Ints
DicentraInputOutput.Output[DisableInt, @chanA.r1];  -- Rx No Int, Tx No En
DicentraInputOutput.Output[Bits8, @chanA.r3];   -- 8bits/char, RxE
DicentraInputOutput.Output[Clock16x, @chanA.r4];  -- 16xClock, 2 Stop Bits
DicentraInputOutput.Output[DTR, @chanA.r5];    -- DTR, 8bits/char, TxE, RTS
DicentraInputOutput.Output[Clocks, @chanA.r11];   -- Clocks from BR Gen
DicentraInputOutput.Output[63, @chanA.r12];    -- Low byte of time constant
DicentraInputOutput.Output[0, @chanA.r13];    -- High byte of time constant
DicentraInputOutput.Output[Enable, @chanA.r14];  -- Enable Baud Rate Gen from PClk
END;
TX: PUBLIC PROC[b:RS232Driver.BYTE] = BEGIN DicentraInputOutput.Output[b, @chanA.r8]; END;
Send a byte of data and return without waiting for TX to finish
RX: PUBLIC PROC[] RETURNS[RS232Driver.BYTE] = BEGIN RETURN[DicentraInputOutput.Input[@chanA.r8]]; END;
Read the input data register - should check data present using RXReady
TXEmpty: PUBLIC PROC[] RETURNS[BOOLEAN] = BEGIN
RETURN[Inline.BITAND[DicentraInputOutput.Input[@chanA.r0], TXEmptyBit] # 0];
END;
Check to see if last character transmitted has departed
RXFull: PUBLIC PROC[] RETURNS[BOOLEAN] = BEGIN
RETURN[Inline.BITAND[DicentraInputOutput.Input[@chanA.r0], RXFullBit] # 0];
END;
Check to see if there is anything in the input buffer
WriteString: PUBLIC PROC[string:LONG STRING] = BEGIN
FOR i:NAT IN [0..string.length) DO
RS232Driver.Write[VAL[string[i]]];
ENDLOOP;
END;
WriteInt: PUBLIC PROC[int: INT, base: NAT ← 10, minDigits: NAT ← 1] = BEGIN
card: LONG CARDINAL;
IF int < 0 THEN {RS232Driver.Write[VAL['-]]; card ← -int} ELSE card ← int;
IF card = 0 THEN {FOR i: NAT IN [0..minDigits) DO RS232Driver.Write[VAL['0]] ENDLOOP; RETURN};
WriteInt[card / base, base, MAX[minDigits, 1] - 1];
{d: NAT ← card MOD base; RS232Driver.Write[d + (IF d IN [0..9] THEN VAL['0] ELSE VAL['A])]};
END;
Open[9600];
DO
WriteString[" here is a number: "]; WriteInt[999];
ENDLOOP;
END.