-- WaferProberImpl.mesa
-- Access to Wafer Prober

DIRECTORY

  Inline USING [LowHalf],
  IODefs: FROM "IODefs" USING [
    WriteChar, ReadChar, CR, LF, ControlE, ControlS, ControlQ, ControlR, ControlT,
    ControlU, WriteString, WriteDecimal],
  PupStream: FROM "PupStream" USING [
    GetPupAddress, PupAddress, PupPackageDestroy, PupPackageMake, SecondsToTocks,
    PupByteStreamCreate],
  Storage USING [Words, FreeWords, String],
  Stream: FROM "Stream" USING [
    Handle, Delete, SetInputOptions, SendNow, Block, GetBlock, PutBlock, InputOptions,
    CompletionCode, GetChar, PutChar, TimeOut],
  String USING [
    AppendChar, AppendSubString, AppendString, DeleteSubString, SubString,
    EqualSubString, SubStringDescriptor, EquivalentString, WordsForString],
  WaferProber;


WaferProberImpl: PROGRAM
  IMPORTS Inline, IODefs, PupStream, Storage, Stream, String EXPORTS WaferProber
  =
  BEGIN OPEN IODefs, PupStream, Stream, String;

  WaferProberObject: PUBLIC TYPE = RECORD[streamHandle: Stream.Handle, pupAddress: PupAddress, inBlock, outBlock: Block, buffer: STRING ← NIL];
  Handle: TYPE = LONG POINTER TO WaferProberObject;

  MyOptions: InputOptions = [terminateOnEndPhysicalRecord: TRUE, signalLongBlock: FALSE, signalShortBlock: TRUE, signalSSTChange: FALSE, signalEndOfStream: FALSE];

  --
  --
  Open: PUBLIC PROCEDURE [name: STRING] RETURNS [h: Handle ← NIL] =

    BEGIN
    h ← Storage.Words[SIZE[WaferProberObject]];
    h.buffer ← Storage.Words[WordsForString[256]];
    h.buffer↑ ← [length: 0, maxlength: 256, text:];
    h.inBlock.blockPointer ← @h.buffer.text;
    h.inBlock.startIndex ← 0;
    h.inBlock.stopIndexPlusOne ← h.buffer.maxlength;
    h.outBlock.startIndex ← 0;
    PupPackageMake;
    GetPupAddress[Inline.LowHalf[@h.pupAddress], name];
    h.streamHandle ← PupByteStreamCreate[h.pupAddress, SecondsToTocks[60]];
    SetInputOptions[h.streamHandle, MyOptions];
    RETURN[h]
    END;  -- Open


  Close: PUBLIC PROCEDURE [ph: LONG POINTER TO Handle] =

    BEGIN
    h: Handle = ph↑;
    Stream.Delete[h.streamHandle];
    PupPackageDestroy;
    ph↑ ← NIL;
    Storage.FreeWords[h.buffer];
    Storage.FreeWords[Inline.LowHalf[h]];
    END;  -- Close



  Align: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "AL*"];
    END;  -- Align



  GetDeviceCoordinate: PUBLIC PROCEDURE [h: Handle] RETURNS [x, y: STRING ← NIL] =

    BEGIN
    response: STRING = TalkToWaferProber[h, "?DC*", FALSE];
    ssd: SubStringDescriptor;
    ss: SubString = @ssd;
    IF response[0] = 'D AND response[1] = 'C THEN
      {
      indexSep: CARDINAL ← 0;
      indexLast: CARDINAL ← 0;
      FOR i: CARDINAL IN [0..response.length) DO
        IF response[i] = '- THEN indexSep ← i;
        IF response[i] = '* THEN indexLast ← i;
      ENDLOOP;
      x ← Storage.String[indexSep-2];
      ssd ← [base: response, offset: 2, length: x.maxlength];
      AppendSubString[x, ss];
      y ← Storage.String[indexLast-(indexSep+1)];
      ssd ← [base: response, offset: (indexSep+1), length: y.maxlength];
      AppendSubString[y, ss];
      }
      ELSE {ERROR};
    RETURN[x, y]
    END;  -- GetDeviceCoordinate



  GoHide: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "HI*"];
    END;  -- GoHide



  GoHome: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "HO*"];
    END;  -- GoHome



  InitializeZ: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "ZI*"];
    END;  -- InitializeZ



  Load: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "LD*"];
    END;  -- Load



  SetDieSize: PUBLIC PROCEDURE [h: Handle, x, y: STRING] =

    BEGIN
    command: STRING = [128];
    command.length ← 0;
    AppendString[command, "DS"L];
    AppendString[command, x];
    AppendString[command, "-"L];
    AppendString[command, y];
    AppendString[command, "*"L];
    [] ← TalkToWaferProber[h, command];
    END;  -- SetDieSize



  Seek: PUBLIC PROCEDURE [h: Handle, x, y: STRING] =

    BEGIN
    command: STRING = [128];
    command.length ← 0;
    AppendString[command, "SK"L];
    AppendString[command, x];
    AppendString[command, "-"L];
    AppendString[command, y];
    AppendString[command, "*"L];
    [] ← TalkToWaferProber[h, command];
    END;  -- Seek



  SetDeviceCoordinate: PUBLIC PROCEDURE [h: Handle, x, y: STRING] =

    BEGIN
    command: STRING = [128];
    command.length ← 0;
    AppendString[command, "DC"L];
    AppendString[command, x];
    AppendString[command, "-"L];
    AppendString[command, y];
    AppendString[command, "*"L];
    [] ← TalkToWaferProber[h, command];
    END;  -- SetDeviceCoordinate



  ToggleZ: PUBLIC PROCEDURE [h: Handle] =

    BEGIN
    [] ← TalkToWaferProber[h, "ZM*"];
    END;  -- ToggleZ
  --

  --

  --


  TalkToWaferProber: PROCEDURE [h: Handle, DummyPointer: STRING, actionCompleteExpected: BOOLEAN ← TRUE]
    RETURNS [NewPointer: STRING] =
    BEGIN
    Why: CompletionCode;
    h.outBlock.blockPointer ← @DummyPointer.text;
    h.outBlock.stopIndexPlusOne ← DummyPointer.length;
    PutBlock[h.streamHandle, h.outBlock, FALSE];
    SendNow[h.streamHandle];
    [h.buffer.length, Why] ← GetBlock[h.streamHandle, h.inBlock!
      TimeOut =>
        BEGIN
        WriteChar[CR];
        WriteString["No response from LoGlas, it may be busy"];
        WriteChar[CR];
        WriteString["Try Again,Debugger,Quit?"];
        SELECT ReadChar[] FROM
          'T, 't => RETRY;
          'C, 'c => CONTINUE;
          'D, 'd => ERROR TimeOut[nextIndex];
          'Q, 'q => BEGIN
        WriteString["Will now close data base"];
        WriteChar[CR];
        --NoMoreWafers ← TRUE;
        GOTO End;
                END;
          ENDCASE => ERROR;
        END; ];
    SELECT Why FROM
      = normal => NULL;--WriteString["CompletionCode is Normal  "];
      = endRecord => NULL;--WriteString["CompletionCode is endRecord  "];
      = sstChange => WriteString["CompletionCode is sstChange  "];
      = endOfStream => WriteString["CompletionCode is endOfStream  "];
      ENDCASE => WriteString["CompletionCode Error  "];

    --WriteChar[CR];

    SELECT h.buffer[h.buffer.length - 2] FROM
      = ControlS => NULL;
      = ControlQ =>
        BEGIN
        WriteString["On-Line mode Selected---"];
        WriteString["Strike a key to continue"];
        [] ← ReadChar[];
        END;
      = ControlR =>
        BEGIN
        WriteString["Off-Line mode Selected---"];
        WriteString["Strike a key to continue"];
        [] ← ReadChar[];
        END;
      = ControlT =>
        BEGIN
        WriteString["Repeat Transmission---"];
        WriteString["Strike a key to continue"];
        [] ← ReadChar[];
        END;
      = ControlU =>
        BEGIN
        WriteString["Data Not Acknowledged---"];
        WriteString["Strike a key to continue"];
        [] ← ReadChar[];
        END;
      ENDCASE;  -- => WriteString["You must not have found the correct character"];

--    WriteChar[CR];

--    WriteString["Prober responds with "];
--    WriteString[h.buffer];
--    WriteChar[CR];
    NewPointer ← h.buffer;

    EXITS End => NULL;
    END;  -- TalkToWaferProber

  CutOffRecord: SubStringDescriptor;
  CutOff: SubString = @CutOffRecord;
  PromptString: STRING = "COMMAND:";
  PromptRecord: SubStringDescriptor ← [PromptString, 0, 8];
  Prompt: SubString = @PromptRecord;
  BREAKString: STRING = "*BREAK";
  BREAKRecord: SubStringDescriptor ← [BREAKString, 0, 6];
  BREAK: SubString = @BREAKRecord;

  LineRecord: SubStringDescriptor;
  LinePointer: SubString = @LineRecord;

  CRLF: STRING ← [2];
  ContE: STRING ← [1];

  -- Mainline Statements Follow, Initialization only

  AppendChar[CRLF, CR];
  AppendChar[CRLF, LF];

  AppendChar[ContE, ControlE];

  END.-- WaferProberImpl