-- MouseChipImpl.mesa
-- created by Haeberli:  30-Sep-81 13:15:07

DIRECTORY
  InlineDefs USING [BITAND, BITOR, LowHalf],
  Mouse,
  Storage,
  Tester;

MouseChipImpl: PROGRAM IMPORTS InlineDefs, Storage, Tester EXPORTS Mouse =
  {
  OPEN Mouse;

  StepMax: CARDINAL = 1000;
  StepCount: TYPE = [0..1000);
  StepControl: TYPE = CARDINAL [0..16);
  DataCount: TYPE = [0..4000);
  PatEntry: TYPE = WORD;
  PatRecord: TYPE = RECORD[stepCount: StepCount ← 0, control: LONG POINTER TO PACKED ARRAY [0..0) OF StepControl ← NIL, dataCount: DataCount ← 8,
data: LONG POINTER TO ARRAY [0..0) OF PatEntry ← NIL];

  patterns: ARRAY Pattern OF PatRecord;
  currentPattern: Pattern;
  recording: BOOLEAN ← FALSE;
  tempPatRecord: PatRecord ← [stepCount: 0, control: Words[(StepMax/4)+1], dataCount: 0, data: Words[SIZE[PatEntry] * StepMax]];

  testerStep: WORD = 100000B;
  testerNoop: WORD = 000000B;

  currentPinMap: Mouse.PinMap ← ALL[0];

  EndRecordPat: PUBLIC PROCEDURE = {
    OPEN patterns[currentPattern];
    EnterStep[testerStep];
    -- return old data;
    IF control # NIL THEN Free[control]; control ← NIL;
    IF data # NIL THEN Free[data]; data ← NIL;

    stepCount ← tempPatRecord.stepCount;
    control ← Words[(stepCount/4)+1];
    FOR i:StepCount IN [0..stepCount) DO control[i] ← tempPatRecord.control[i] ENDLOOP;
    tempPatRecord.stepCount ← 0;

    dataCount ← tempPatRecord.dataCount;
    data ← Words[SIZE[PatEntry] * dataCount];
    FOR i:StepCount IN [0..dataCount) DO data[i] ← tempPatRecord.data[i] ENDLOOP;
    tempPatRecord.dataCount ← 8;

    blockCount ← 0;
    recording ← FALSE};

  GetPin: PUBLIC PROCEDURE [pin: Mouse.Pin] RETURNS [value: Mouse.Value] = {
    RETURN[Tester.GetChannelValue[currentPinMap[pin]]]};

  PlayPat: PUBLIC PROCEDURE [pat: Pattern] = {
    OPEN patterns[pat];
    actualStepCount: StepCount ← 0;
    Tester.DoOutput[testerStep, 1];
    actualStepCount ← Tester.DoTest[c: stepCount, control: control, data: data];
    IF actualStepCount # 0 THEN ERROR;
    Tester.DoOutput[testerStep, 1];
    };

  RecordPat: PUBLIC PROCEDURE [pat: Pattern] = {
    currentPattern ← pat;
    tempPatRecord.stepCount ← 0;
    tempPatRecord.dataCount ← 8;
    blockCount ← 0;
    recording ← TRUE};

  Reset: PUBLIC PROCEDURE = {Tester.Reset};

  SetPin: PUBLIC PROCEDURE [pin: Mouse.Pin, value: Mouse.Value] = {
    IF recording THEN {
      first, second: WORD;
      [first, second] ← Tester.SetChannelValueCommands[currentPinMap[pin], value];
      EnterStep[first]; EnterStep[second]
      }
    ELSE Tester.SetChannelValue[currentPinMap[pin], value]};

  SetPinMap: PUBLIC PROCEDURE [pinMap: Mouse.PinMap] = {currentPinMap ← pinMap};

  blockCount: CARDINAL ← 0;

  EnterStep: PROCEDURE [w: WORD] = {
  OPEN tempPatRecord;
  data[dataCount] ← InlineDefs.BITAND[w, 077777B];
  dataCount ← dataCount + 1;
  blockCount ← blockCount + 1;

  IF InlineDefs.BITAND[w, testerStep] # 0 THEN -- block done
    {

    --fill out block to 4 or 8 words (with nops);
    UNTIL ((blockCount > 0) AND ((blockCount MOD 4) = 0)) DO
      data[dataCount] ← testerNoop;
      dataCount ← dataCount + 1;
      blockCount ← blockCount + 1
      ENDLOOP;
    data[dataCount - 1] ← InlineDefs.BITOR[data[dataCount - 1], testerStep];

    --if we have more than 4 blocks in a step, we have to do multiple
    -- steps
    UNTIL blockCount <= 16 DO
      control[stepCount] ← 14B; -- tell tester to do 4 blocks
      stepCount ← stepCount + 1;
      blockCount ← blockCount - 16;
      ENDLOOP;

    blockCount ← blockCount - 4;  --control is biased
    control[stepCount] ← LOOPHOLE[blockCount, StepControl];
    stepCount ← stepCount + 1;
    blockCount ← 0
    };
  };

  SetVersion: PUBLIC PROCEDURE [version: ChipVersion] = {};

  Free: PROCEDURE [lp: LONG POINTER TO UNSPECIFIED] = {
  Storage.FreeWords[InlineDefs.LowHalf[lp]]
  };

  Words: PROCEDURE [length: CARDINAL] RETURNS [lp: LONG POINTER TO UNSPECIFIED] = {
  lp ← Storage.Words[length];
  RETURN[lp]
  };

  Reset;

  }.

MPH   30-Sep-81 13:23:48
	created initially