PROGRAM Autocon30;       { Last Update 4/21/94 }

{full 8087 emulation:}
{$N+,E+}

{********************** CHANGES MADE ***************************}
{*     4/1/94 ver. 1.00 to be tested by Russ Cook              *}
{*     4/4/94 cosmetic changes, add turn off conditioning,     *}
{*            excursion timeout instead of value reached,      *}
{*            wait before start to overlook inital excursion.  *}
{*            stepsize 8 on excursion.                         *}
{*     4/21/94 put conditioning off before keypress to exit.   *}
{*             exit program when 'no' to try again question.   *}
{***************************************************************}

USES Crt,ListPlus,RCM;

TYPE deltaray  = ARRAY[0..3] OF Real; 

CONST
      { *** increments in HT for the various ranges *** }
      DeltakV : deltaray = (0.275,0.275,0.137,0.082);

      { *** Constants used by RCM software *** }
      StepSize = 8;  Focus = 7; Ready = 7;

      { *** HT points that determine range limits *** }
      HTRNG  : deltaray = (300,315,325,330);

      { *** % of old emission that triggers decr. HT by 30kV *** }
      EMISMULT : Real = 2.0;   { 200% }

      { *** % increment in old emission value that you must drop back to *** }
      EMISINC  : Real = 0.2;   { 120% of old }

      { *** increment in old vac that will cause a hold in HT incr *** }
      PRESSHOLDINC : Integer = 2;  { if press >= 2 + old value, hold up }

      { *** increment in old vac reading that you must drop back to *** }
      PRESSBKINC : Integer = 2;  { drop back to <= 2 + old value }

VAR
    igpnew,igpold,stepnbr,j : Integer;
    HT,emisold,emisnew,delta : Real;
    ch : Char;
    panic : Boolean;

LABEL GetOut;    { *** Used to exit program gracefully *** }

{***************************************************************}

   PROCEDURE NoDriver; { writes a message on the screen if there is no driver }
     BEGIN
       Fill(1,1,80,25,Cyan+16*Blue,178);
       Fbox(5,3,75,23,white,blue,2);
       WriteCenter(5,Yellow,Cyan,' The device driver is not present. ');
       WriteCenter(7,black,Cyan,' In the root directory of the disk you boot ');
       WriteCenter(8,black,Cyan,' from is the file CONFIG.SYS. This normal ');
       WriteCenter(9,black,Cyan,' ASCII file must contain the following phrase : ');
       WriteCenter(11,White,Cyan,' Device = RCM.SYS ');
       WriteCenter(13,black,Cyan,'If you do not wish to place the file RCM.SYS ');
       WriteCenter(14,black,Cyan,' in the root directory, but for example in the ');
       WriteCenter(15,black,Cyan,' directory C:\RemoteCM, then this phrase must be : ');
       WriteCenter(17,White,Cyan,' Device = C:\RemoteCM\RCM.SYS ');
       WriteCenter(19,black,Cyan,' You can change the file config.sys with any ');
       WriteCenter(20,black,Cyan,' normal ASCII text editor. ');
       WriteCenter(21,Yellow,Cyan,' Please correct this, then boot again. ');
     END; { of procedure NoDriver }

{***************************************************************}
{ This procedure will Display a comment on all the possible RCM results }
   PROCEDURE DisplayResult (Result: RCMResultType);
     VAR errmsg : string[32];
     BEGIN
       IF Result <> Ok THEN
       BEGIN
         IF Result = DelayedExpected THEN
              BEGIN delay(2000); Exit; END;
         CASE Result of      { The errors returned by the device driver }
          InvalidFunctionId         : errmsg := 'Invalid Function Id';
          EquipmentNotAvailable     : errmsg := 'Equipment Not Available';
          InvalidData               : errmsg := 'Invalid Data';
          InvalidMicroscopeStatus   : errmsg := 'Invalid Microscope Status';
          InvalidPCStatus           : errmsg := 'Invalid PC Status';
          DelayedError              : errmsg := 'Delayed Error';
          DelayedExpected           : errmsg := 'Delay Expected';
          IncorrectDeviceDriver     : errmsg := 'Incorrect Device Driver';
          NotAvailable              : errmsg := 'Not Available';
          PressOnly                 : errmsg := 'Press Only';
          CannotPressButton         : errmsg := 'Cannot Press Button';
          DeviceDriverNotOpened     : errmsg := 'Device Driver Not Opened';
          DirectOperationImpossible : errmsg := 'Direct Operation Impossible';
          NotCalibrated             : errmsg := 'Relocation System Not Calibrated';
          InvalidPos                : errmsg := 'Invalid Location';
          InvalidReg                : errmsg := 'Invalid Register';
        END;  { Case }
        Uhuh;
        TempMsgBx(0,0,Yellow,Red,White,Red,32,3,'Error ! '+errmsg);
      END; { If Result }
    END;  { of display RCM result }

{***************************************************************}
             { Test to see if equipment is available }
   PROCEDURE Test_available;
   Label TestCM;
   BEGIN
     TestCM:
     Fill(1,1,80,25,44,176);
     MsgBx(0,4,White,Cyan,LightCyan,Blue,1,' Testing if equipment available .... ');
     IF NOT EquipmentAvailable then
     BEGIN
       Uhuh;
       Msg(0,0,White,Red,177,
       ' Microscope Not Available!~ Check Remote Control Function.');
       IF ReadYN(0,21,white,blue,' Do you wish to try again (Y/N) ? ')
        THEN Goto TestCM;
       closeremoteCM;
       CursOn;  { turn the cursor back on }
       TextAttr := 7;   { gray on black }
       ClrScr;
       Halt;
     END;
   END;  { of test available }

{***************************************************************}
                   { Read and display Vacuum }
  PROCEDURE vacuum;
    VAR p  : PressureType;
    BEGIN
      PressureReadout(p);
      DisplayResult (RCMResult);
      IF RCMResult = OK  THEN
        BEGIN
          igpnew := Trunc(p[4]);
        END;
    END;

{***************************************************************}
              { Set the starting HT }
   FUNCTION SetkV : Integer;

     CONST kV1 = '  50    100    150    200    250    300   ';
           kV2 = '                  ';
           XCORN = 17;  YCORN = 10;
           volt : ARRAY[0..5] OF Integer = (50,100,150,200,250,300);
     VAR select : Word;
         ch : Char;
     BEGIN
       Fill(1,1,80,25,Blue + 16 * Cyan,178);
       Button(XCORN-4,YCORN-2,XCORN+48,YCORN+2,white,DarkGray,Lightgray);
       WriteAt(XCORN,YCORN,DarkGray,LightGray,kV1);
       WriteAt(XCORN,Succ(YCORN),DarkGray,LightGray,kV2);
       WriteCenter(YCORN+4,White,Blue,
                    ' Select kV using arrow keys and Enter. ');
       FOR select := 0 TO 5 DO
       Attrib(XCORN+8*select,YCORN,5,Black+16*Cyan);
       select := 0; ESCAPED := FALSE; SetkV := 50;
       REPEAT
         Attrib(XCORN+8*select,YCORN,5,White+16*Blue);
         ch := GetKey;
         Attrib(XCORN+8*select,YCORN,5,Black+16*Cyan);
         CASE ch OF
           LARR,MLEFT : IF select > 0 THEN Dec(select)
                         ELSE select := 5;
           RARR,MRIGHT : IF select < 5 THEN Inc(select)
                          ELSE select := 0;
           ESC,MRIGHTB : BEGIN ESCAPED := TRUE; Exit; END;
         END;  { Case }
       UNTIL ch IN [ENTER,MLEFTB];
       SetkV := volt[select];
     END;  { SetkV }

{***************************************************************}
           { Draw background on which HT increments are choosen. }
   PROCEDURE DeltaBkgd;
     CONST K1 = '    0.275    0.275    0.137    0.082  ';
           K2 = '              ';
           K3 = '   0      300      315      325      330      END   ';
           K4 = '                            ';
           XCORN = 12;  YCORN =10;
     VAR j : Integer;
     BEGIN
       Button(XCORN-4,YCORN-2,XCORN+60,YCORN+8,LightCyan,Cyan,Lightgray);
       DrawShadow(XCORN-4,YCORN-2,XCORN+60,YCORN+8);
       WriteAt(XCORN,YCORN+1,DarkGray,LightGray,K1);
       WriteAt(XCORN,YCORN+2,DarkGray,LightGray,K2);
       WriteAt(XCORN,YCORN+3,DarkGray,LightGray,K3);
       WriteAt(XCORN,YCORN+4,DarkGray,LightGray,K4);
       WriteCenter(YCORN-1,White,Blue,
                    ' Select increment using arrow keys ');
       FOR j := 0 TO 3 DO
         WriteAt(XCORN+10*j+7,YCORN+2,Red,LightGray,#25);
       FOR j := 0 TO 3 DO
         Attrib(XCORN+10*j+3,YCORN+1,7,Black+16*Cyan);
       FOR j := 0 TO 5 DO
         Attrib(XCORN+10*j,YCORN+3,5,White+16*Cyan);
       Attrib(XCORN+3,YCORN+1,7,White+16*Blue);    { Range Select Hilite }
       Attrib(XCORN,YCORN+3,5,White+16*Red);    { 0 HT Hilite }
     END;  { DeltaBkgd }

{***************************************************************}
        { Set the individual HT increments }
   PROCEDURE SetDelta(ch : Char);
     CONST select : Word = 0;   { selection }
           XCORN = 12;  YCORN = 10;
     BEGIN
       Attrib(XCORN+10*select+3,YCORN+1,7,Black+16*Cyan);
       CASE ch OF
           LARR,MLEFT : IF select > 0 THEN Dec(select)
                         ELSE select := 3;
           RARR,MRIGHT : IF select < 3 THEN Inc(select)
                          ELSE select := 0;
           UARR,MUP    : BEGIN
                           IF DeltakV[select]  < 0.1 THEN
                              DeltakV[select] := 0.137 ELSE
                             IF DeltakV[select] < 0.2 THEN
                                DeltakV[select] := 0.275 ELSE UhUh;
                       WriteAT(XCORN+10*select+4,YCORN+1,7,Black+16*Cyan,
                                RealToStr(DeltakV[select],5,3));
                         END;
           DARR,MDOWN    : BEGIN
                           IF DeltakV[select] > 0.2 THEN
                              DeltakV[select] := 0.137 ELSE
                             IF DeltakV[select] > 0.1 THEN
                                DeltakV[select] := 0.082 ELSE UhUh;
                       WriteAT(XCORN+10*select+4,YCORN+1,7,Black+16*Cyan,
                                RealToStr(DeltakV[select],5,3));
                         END;

       END;  { Case }
       Attrib(XCORN+10*select+3,YCORN+1,7,White+16*Blue);
     END;  { SetDelta }

{***************************************************************}
   Procedure TitleBx;
     BEGIN
       Fill(20,2,60,5,16*Cyan,32);
       WriteCenter(3,White,Cyan,'AutoConditioning Program for CM30');
       WriteCenter(4,Yellow,Cyan,'Press Esc key to stop program.');
       DrawShadow(20,2,60,5);
     END;  { TitleBx }

{***************************************************************}
    Procedure Excursion;
         BEGIN
           { *** Signal that an excursion has taken place *** }
           Fill(20,2,60,5,16*Red,32);
           WriteCenter(3,White,Red,'An emission excursion has occurred!');
           WriteCenter(4,Yellow,Red,'Reducing HT 27.5 kV and waiting....');
           DrawShadow(20,2,60,5);

           { *** Decrease the HT by 30kV  *** }
           HT := HT - 27.5;
           { *** turn the stepsize knob completely ccw *** }
           Turnknob(StepSize,-9); Displayresult(RCMresult);
           { *** turn the stepsize knob to position 8 *** }
           Turnknob(StepSize,8); Displayresult(RCMresult);
           { *** turn the focus knob ccw 1 unit of stepsize *** }
           { *** should be 27.5 kV down from previous *** }
           Turnknob(focus,-1); Displayresult(RCMresult);

           { *** Wait for 1 minute *** }
           SetWait(60);
           REPEAT
             emisnew := EmissionCurrent;
             TextBackground (Blue );
             TextColor(White); GotoXY(59,17); Write(emisnew:8,' ');

             { *** check for keypress to exit program or change incr *** }
             IF KeyPressed THEN
               BEGIN
                 ch := GetKey;
                 IF ch IN [LARR,RARR,UARR,DARR,MLEFT,MRIGHT,MUP,MDOWN] THEN
                     SetDelta(ch);  { change increment if required }
                 IF ch = #27 THEN    { quit conditioning if desired }
                        BEGIN panic := TRUE;  Exit; END;
               END;  { If }

           UNTIL WaitUP;
           emisold := emisnew;   { reset  the old }
           TitleBx;  { restore the title }
         END;  { Excursion }

{***************************************************************}
   Procedure RiseBx;
       BEGIN
         { *** Signal that a rise has taken place *** }
         Fill(20,2,60,5,16*Blue,32);
         WriteCenter(3,White,Blue,'The Pressure rose suddenly!');
         WriteCenter(4,Yellow,Blue,'Waiting for recovery ....');
         DrawShadow(20,2,60,5);
       END; { RiseBx }

{***************************************************************}
   Procedure PressRise;
       BEGIN
         { *** Signal that a rise has taken place *** }
         RiseBx;

         REPEAT
           { *** read the vacuum and display it *** }
           vacuum;
           WriteAT(12,17,White,Blue,
                   ' Last IGP Reading: '+IntToStr(igpnew,2)+' ');

           { *** read and display emission *** }
           emisnew := EmissionCurrent;
           TextBackground (Blue );
           TextColor(White); GotoXY(59,17); Write(emisnew:8,' ');

           { *** check for large increase in emission current *** }
           IF emisnew > (EMISMULT*emisold) THEN
              BEGIN Excursion; RiseBx; END;

           { *** check for keypress to exit program or change incr *** }
           IF KeyPressed THEN
             BEGIN
               ch := GetKey;
               IF ch IN [LARR,RARR,UARR,DARR,MLEFT,MRIGHT,MUP,MDOWN] THEN
                   SetDelta(ch);  { change increment if required }
               IF ch = #27 THEN    { quit conditioning if desired }
                   BEGIN panic := TRUE;  Exit; END;
             END;  { If }

         UNTIL igpnew <= (igpold + PRESSBKINC);
         igpold := igpnew;  { reset base value }
         SetWait(5);  { Start a new 5 second delay }
         TitleBx;  { restore title }
       END;  { PressRise }

{***************************************************************}
    PROCEDURE WatchNWait(ShowWait:Boolean);
    BEGIN
     REPEAT
       { *** Show wait time if ShowWait is true *** }

       IF ShowWait THEN
         WriteCenter(4,Yellow,Green,
          IntToStr(((NewWait-Waittime) DIV 1080)+1,2)+' Minutes Remaining..');

       { *** check for keypress to change increments or exit program *** }

       IF KeyPressed THEN
           BEGIN
             ch := GetKey;
             IF ch IN [LARR,RARR,UARR,DARR,MLEFT,MRIGHT,MUP,MDOWN] THEN
                SetDelta(ch);  { change increment if required }
             IF ch = #27 THEN panic := TRUE;   { quit conditioning if desired }
           END;  { If }

       { *** read and display emission *** }
       emisnew := EmissionCurrent;
       TextBackground (Blue );
       TextColor(White); GotoXY(59,17); Write(emisnew:8,' ');

       { *** if a drop in emission current, lower the reference current *** }
       IF emisnew < emisold THEN emisold := emisnew;

       { *** check for large increase in emission current *** }
       IF emisnew > (EMISMULT*emisold) THEN  Excursion;
       IF panic THEN Exit;   { ESC pressed in Excursion }

       { *** read the vacuum and display it *** }
       vacuum;
       WriteAT(12,17,White,Blue,
                ' Last IGP Reading: '+IntToStr(igpnew,2)+' ');

       { *** If it gets better then save new reference value *** }
       IF igpnew < igpold THEN igpold := igpnew;

       { *** Check for pressure rise and wait till it subsides *** }
        IF igpnew > 5 THEN           { only if pressure > 5 }
          IF igpnew > (igpold + PRESSHOLDINC) THEN  PressRise;
        IF panic THEN Exit;  { Esc pressed in PressRise }

     UNTIL WaitUp;  { *** repeat until the time is up *** }
    END;  { WatchNWait }

{***************************************************************}
  BEGIN  { Main }
   panic := FALSE;     { *** Flag to get out in emergency *** }
   CursOFF;  { turn off cursor }
   moused := FALSE;  { disable the mouse }
   ClrScr;

  { *** Check for remote driver *** }
   GotoXY(1,6); Write('Testing presence of RC driver ....      ');
   IF NOT OpenRemoteCM THEN BEGIN  NoDriver; Halt(0); END;

  { *** See if we have a controllable microscope *** }
   Test_Available;  { Check if microscope is Remote Controllable }

  { *** Get inital values of vac and emmis current *** }
   vacuum; { first read of igp } igpold := igpnew;
   emisnew := EmissionCurrent;  emisold := emisnew;

  { *** Ask what starting high voltage is *** }
   HT := SetkV;

  { *** turn the proper knobs to start conditioning *** }
   turnknob(StepSize,-9); displayresult(RCMresult); { StepSize CCW }
   pushbutton(Ready, Press); displayresult(RCMresult);  { Push 'Ready' }
   softkey(9,1); displayresult(RCMresult);     { Select 'Parameters' }
   softkey(3,1); displayresult(RCMresult);     { Select 'Conditioning' }

  {  *** delay to ignore initial emission excursion *** }
   Msg(0,13,White,Blue,32,' 15 sec delay before starting ... ');
   SetWait(15);
   WHILE NOT WaitUp DO;

  { *** display the main conditioning screen *** }
   Fill(1,1,80,25,white+16*blue,176);
   TitleBx;
   Msg(0,21,Yellow,Red,32,
        'Do not touch the MICROCONTROLLER during execution of this program');
   DeltaBkgd;    { draw the background for changing increments }

   { *** Display emission current and vacuum *** }
   WriteAT(42,17,White,Blue,' Emission Current: ');
   TextBackground(Blue);
   GotoXY(60,17); Write(emisnew:8,' ');
   WriteAT(12,17,White,Blue,' Last IGP Reading: '+IntToStr(igpnew,2)+' ');

  { *** Now enter the conditioning loop *** }
   ch := #0;  { just to make sure }
   WHILE HT < 330 DO   { *** ramp up to 330 kV *** }
    BEGIN

     { *** determine range of HT and set appropriate delta *** }
     IF HT < HTRNG[0] THEN  delta := deltakV[0]
       ELSE IF HT < HTRNG[1] THEN delta := deltakV[1]
         ELSE IF HT < HTRNG[2] THEN delta := deltakV[2]
           ELSE delta := deltakV[3];

     { *** set new HT ... first determine size of focus control step *** }
     IF delta > 0.15 THEN stepnbr := 2
       ELSE IF delta > 0.1 THEN stepnbr := 1
         ELSE stepnbr := 0;

     { *** Update the HT value and turn knobs to change it *** }
     HT := HT + delta;
     { *** turn the stepsize knob completely ccw *** }
     Turnknob(StepSize,-9); Displayresult(RCMresult);
     { *** now go up zero, one or two clicks depending on stepsize *** }
     Turnknob(StepSize,stepnbr); Displayresult(RCMresult);
     { *** turn the focus knob one unit of stepsize *** }
     Turnknob(focus,1); Displayresult(RCMresult);

     { *** Display new setting of HT on screen. *** }
     WriteCenter(15,White,Blue,
                    ' HT Set to: '+RealToStr(HT,6,3)+' KeV ');

     { *** Highlite HT buttons to this range *** }
     FOR j := 0 TO 3 DO
       IF HT > HTRNG[j] THEN Attrib(22+10*j,13,5,White+16*Red);

     { *** Initialize a waiting loop *** }
     SetWait(5);  { 5 Seconds }

     { *** Now go into wait loop for this increment in HT *** }
     WatchNWait(False);
     IF panic THEN Goto GetOut;

   END;  { While }  { *** repeat until you reach 330 kV *** }

   { *** Now wait at 330 kV for 10 minutes *** }
   SetWait(600);   { 600 seconds wait }

   { *** Display message *** }
   Fill(20,2,60,5,16*Green,32);
   WriteCenter(3,White,Green,'Now waiting at 330 kV for 10 minutes.');
   DrawShadow(20,2,60,5);

  { *** Highlite END HT button *** }
   Attrib(62,13,5,White+16*Red);

   { *** Display time remaining and wait for time up *** }
   WatchNWait(TRUE);

   { *** Signal completion of the conditioning *** }
   Fill(20,2,60,5,16*Cyan,32);
   WriteCenter(3,White,Cyan,'Conditioning Complete.');
   WriteCenter(4,Yellow,Cyan,'Press any key to exit program.');
   DrawShadow(20,2,60,5);
   { turn off conditioning mode }
   softkey(3,1); displayresult(RCMresult);     { Select 'Conditioning' }

   { *** Wait for keypress *** }
   ch := GetKey;

   { *** Exit the program gracefully *** }
   GetOut:
   CloseRemoteCM;     { close the device handling the microscope }
   CursOn;  { turn the cursor back on }
   TextAttr := 7;   { gray on black }
   ClrScr;

  END.   { Main }