-- SetClock.mesa
-- modified  4-Oct-81 10:43:13 by Taft

DIRECTORY
  IODefs USING [CR, ReadID, Rubout, SP, TAB, WriteChar, WriteDecimal,
    WriteLine, WriteString],
  MiscDefs USING [CommandLineCFA],
  Mopcodes USING [zMISC],
  Process USING [MsecToTicks, Pause],
  StreamDefs USING [GetFA, JumpToFA, NewByteStream, Read, StreamError,
    StreamHandle],
  StringDefs USING [AppendChar, InvalidNumber, StringToDecimal];

SetClock: PROGRAM
  IMPORTS IODefs, MiscDefs, Process, StreamDefs, StringDefs =
  BEGIN OPEN IODefs, StreamDefs, StringDefs;

  -- Operate the Dorado muffler/manifold system.
  RWMufMan: PROCEDURE [MufManArg] RETURNS [MufManResult] = MACHINE CODE
    BEGIN Mopcodes.zMISC, 246B; END;

  MufManArg: TYPE = MACHINE DEPENDENT RECORD [
    useDMD: BOOLEAN,
    unused: [0..7] ← NULL,
    dMuxAddr: [0..7777B]];

  MufManResult: TYPE = MACHINE DEPENDENT RECORD [
    dMuxData: [0..1],
    unused: [0..77777B]];

  comStream: StreamHandle;

  BeginCommandScan: PROCEDURE =
    BEGIN
    comStream ← NewByteStream["Com.cm"L, Read];
    JumpToFA[comStream, @MiscDefs.CommandLineCFA[].fa];
    END;

  EndCommandScan: PROCEDURE =
    BEGIN
    GetFA[comStream, @MiscDefs.CommandLineCFA[].fa];
    comStream.destroy[comStream];
    END;

  GetCommandAtom: PROCEDURE [s, prompt: STRING] =
    BEGIN
    ENABLE StreamError => IF error=StreamAccess THEN
      BEGIN ENABLE Rubout => RETRY;
      WriteChar[CR]; WriteString[prompt];
      ReadID[s];
      GOTO Done;
      END;
    c: CHARACTER;
    s.length ← 0;
    DO
      c ← comStream.get[comStream];
      SELECT c FROM
        SP, TAB => IF s.length#0 THEN EXIT;
        CR => EXIT;
        ENDCASE => AppendChar[s, c];
      ENDLOOP;
    EXITS
      Done => NULL;
    END;


  token: STRING = [50];
  oldRate, newRate: CARDINAL;

  oldClkRate, newClkRate: MACHINE DEPENDENT RECORD [
    SELECT OVERLAID * FROM
      cardinal => [cardinal: CARDINAL],
      nibbles => [unused: [0..377B], high: [0..17B], low: [0..17B]],
      bits => [unused: [0..377B], bits: PACKED ARRAY [0..7] OF [0..1]],
      ENDCASE];

  BeginCommandScan[];

  DO
    ENABLE StringDefs.InvalidNumber => RETRY;
    GetCommandAtom[token, "New clock rate (ns): "L];
    newRate ← StringToDecimal[token];
    IF newRate IN [25..50] THEN EXIT;
    WriteString["Out of bounds."L];
    ENDLOOP;

  EndCommandScan[];

  oldClkRate.cardinal ← 0;
  FOR i: CARDINAL IN [0..7] DO
    oldClkRate.bits[i] ← RWMufMan[[useDMD: FALSE, dMuxAddr: 2200B+i]].dMuxData;
    ENDLOOP;
  oldRate ← 2000/oldClkRate.cardinal;

  WriteLine[""L];
  WriteString["Changing clock rate from "L];
  WriteDecimal[oldRate];
  WriteString[" ns to "];
  WriteDecimal[newRate];
  WriteLine[" ns."];

  newClkRate.cardinal ← 2000/newRate;

  [] ← RWMufMan[[useDMD: TRUE, dMuxAddr: 2200B+newClkRate.high]];
  [] ← RWMufMan[[useDMD: TRUE, dMuxAddr: 2220B+newClkRate.low]];

  Process.Pause[Process.MsecToTicks[1000]];

  END.