
------------------------------------------------------------------------------
-- Program Name: SZ23937

------------------------------------------------------------------------------

program PN191318;                                                                              
 
#include PN191318.iri 

  -- Constants and aliases definitions 
  g_csProgName          : constant string  := "PN191318"; --Program Name 
  g_csVersion           : constant string  := "1.04"; --Program Version   
  g_ciDigSlot           : constant integer := 0;  
  g_ciPrinter           : constant integer := 0;
  g_ciDigInOn           : constant integer := 0; --Digital Input is On 
  g_ciDigInOff          : constant integer := 1; --Digital Input is Off 
  g_ciDigOutOn          : constant integer := 1; --Digital Output is On
  g_ciDigOutOff         : constant integer := 0; --Digital Output is Off 
  g_ciBackDoorPassword  : constant string  := "2349171";  --Backdoor Password 
  g_ciInt32_Max         : constant integer := 2147483647;  
  g_ciMaxTransDBRecords : constant integer := 5000; 
  g_ciFFFFh             : constant integer := 65535;
  g_ciFFh               : constant integer := 255;
  g_ciMAX               : constant integer := 2147483648;   

  BusInputdata : BusImageReal;
  BusOutputData : BusImageReal; 

  -- Inputs/Outputs  
  g_ciStartAbort    : constant integer := 1;
  g_ciEStop         : constant integer := 2;
  iContEye          : constant integer := 3;
  oFillComplete     : constant integer := 6;  
  oZeroContTol      : constant integer := 7;
  oDischarge        : constant integer := 8;

  oDispenseComplete : constant integer := 6;
  oRefill           : constant integer := 8;

  type Pausedmode is (Yes, No);
  Paused : PausedMode;  
  
  Complete            : constant integer := 0; 
  WaitSSTare          : constant integer := 1; 
  ZeroingScale        : constant integer := 2;    
  FastFill            : constant integer := 3;
  SlowFill            : constant integer := 4;
  WaitSSFull          : constant integer := 5;
  RemoveContainer     : constant integer := 6;
  DelayAfterDischarge : constant integer := 7;

  RefillCheck         : constant integer := 20;
  RefillScale         : constant integer := 21;

  BatchMode : integer;     
      
  -- Screens
  g_ciMain       : constant integer := 1;
  g_ciClearTrans : constant integer := 5;
  g_ciIOTest     : constant integer := 7;    
  g_ciSetup      : constant integer := 10;
  g_ciPassword   : constant integer := 97;
  g_ciYNRestore  : constant integer := 98;  
  g_ciBlank      : constant integer := 99;

  -- Operation Modes
  LockMode                : constant integer := 0;
  EnterRandomPasswordMode : constant integer := 90;
  NoMode                  : constant integer := 100;    
  EnterTargetWeight       : constant integer := 101;
  EnterDribbleWeight      : constant integer := 102;
  EnterPreactWeight       : constant integer := 103;
  EnterZeroContWgt        : constant integer := 104;
  EnterConsecutiveNbr     : constant integer := 105;
  ClearTotal              : constant integer := 106;

  EnterLowLevelWgt        : constant integer := 200;
  EnterHighLevelWgt       : constant integer := 201;
  
  -- Setup Modes
  SetupEnterPasswordMode   : constant integer := 999;
  Setup1Mode               : constant integer := 1000; 
    SetupChangePasswordMode  : constant integer := 1100;
      SetupVerifyPasswordMode  : constant integer := 1101;
    SetupDelayAfterDischargeMode : constant integer :=  4300;
    SetupZeroToleranceMode       : constant integer :=  5200;
    SetupContainerThreshold      : constant integer :=  5300;
    SetupRestoreSetupMode        : constant integer :=  6200;
    ClearTransactions            : constant integer :=  6300;
    SetupSlowCycleTime           : constant integer :=  6400;
  Setup2Mode                     : constant integer :=  20000;

  EntryMode : integer; 

  Blank : constant string := "";      
  type boolean is (False,True); 
  type align_spec is ( left, right,center );  

  -- Global/Types variables definitions 
  g_sSetupPassword : stored string;
  g_iDownload : stored integer;
  g_sTmpPassword : string;  
  g_rCountby : real;    
  g_bUpdate : boolean;
  g_iDecimal : integer;
  g_uUnits : units; 
  g_iWaitSSScale : integer;  
  g_sysResult : syscode;   
  g_sDebug : string;  
  g_iWidget : integer;     
  g_iScreen : integer;      
  g_iLastScreen : integer;
  g_iPromptOpen : integer; 
  g_sPrompt : string;  
  g_sDefault : string;
  g_iPrompt : integer;
  g_iNbrofSetupVariables : integer;
  g_rTargetWgt : stored real;
  g_rDribbleWgt : stored real;
  g_rPreact     : stored real;
  g_iConsecutiveNbr : stored integer;
  g_rTotalWgt : stored real;
  g_iTotalCnt : stored integer;
  g_rTare : real;
  g_bOKDischarge : boolean;
  g_iDelayCnt : integer;
  g_iStop : integer;
  g_rDispensed : real;
  g_iSeed : integer;
  g_iRandNum : integer;
  g_iTmpPassword : integer; 
  g_arhardware : HW_array_type;

  g_sFillingSpeeds : stored string;
  g_sAutoTare : stored string;
  g_sAutoPrint : stored string;
  g_sTransMessage : stored string;
  g_sDischarging : stored string;
  g_sAutoDischarge : stored string;
  g_rDelayAfterDischarge : stored real;
  g_rZeroTolerance : stored real;
  g_rContainerThreshold : stored real;
  g_sContainerPhotoeye : stored string;
  g_sOperationMode : stored string;
  g_sRefillOption  : stored string;
  g_rSlowCycleTime : stored real;
  g_iIOstatus : integer;
  g_rLastFillWgt : real;
  g_iComm : integer;
  g_rLowWgt : stored real;
  g_rHighWgt : stored real;

  type CRCTableType is array [256] of integer;
  crcTable : CRCTableType;   

  TransDB : TransDatabase;

  procedure SetupStartTimer(iTimer : integer; iDuration : integer; itmMode : TimerMode);  -- Setup a Timer and Start                                
  begin
  
    SetTimer(iTimer, iDuration);
    SetTimerMode(iTimer, itmMode);
    StartTimer(iTimer);
    
  end;
  
  function GetMilitaryTime (dtTemp : datetime) : string;   -- Military time
    iHour: integer;
    iMin : integer;
    iSec : integer;
    sHour : string;
    sMin : string;  
    sSec : string;
    s24HourTime : string;  
  begin  
  
    GetTime(dtTemp, iHour, iMin, iSec); 
    
    sHour := IntegerToString(iHour,0);
    if Len(sHour) = 1 then
      sHour := "0" + IntegerToString(iHour,0);
    end if; 
    sMin := IntegerToString(iMin,0);  
    if Len(sMin) = 1 then
      sMin := "0" + IntegerToString(iMin,0);
    end if;
    sSec := IntegerToString(iSec,0);  
    if Len(sSec) = 1 then
      sSec := "0" + IntegerToString(iSec,0);
    end if;
    s24HourTime := sHour + sMin + sSec;  
    return s24HourTime; 
  
  end; 

  function GetFormattedDate (dtTemp : datetime) : string; -- Format Date DDMMYYYY 
    iYear : integer;
    iMonth : integer;
    iDay : integer; 
    sDay : string;
    sFormattedDate : string := BLANK;  
    tmpDate : datetime; 
  begin
    
    GetDate(dtTemp, iyear, imonth, iday);  
    
    -- Configure month
    if iday < 10 then                   
      sDay := "0" + IntegerToString(iDay,0);
    else
      sDay := IntegerToString(iDay,0); 
    end if;  

    sFormattedDate := sDay;         
    
    -- Configure Day
    if iMonth < 10 then                   
      sFormattedDate := sFormattedDate + "0" + IntegerToString(iMonth,0) ;
    else
      sFormattedDate := sFormattedDate + IntegerToString(iMonth,0); 
    end if;
    
    -- configure Year 
    if iyear < 10 then
      sFormattedDate := sFormattedDate + "200" + IntegerToString(iyear,0);  
    else   
      sFormattedDate := sFormattedDate + "20" + IntegerToString(iyear,0);   
    end if;
    
    sFormattedDate := sFormattedDate + GetMilitaryTime(dtTemp);
    
    return sFormattedDate; 

  end;

--  Calculates the modulo 10 checksum character
  function CalculateCRC16(str : string) : string;
  i : integer;
  val : integer;
  ival : integer;
  iresult : integer;
  begin

    val := 0;
    for i := 1 to Len(str) step 2
    loop
      val := val + Asc(Mid$(str,i,1));
      val := val + 3 * Asc(Mid$(str,i + 1, 1));
    end loop;

    Writeoutln(g_sDebug, val);
    ival := val mod 10;
    if ival <> 0 then
      iresult := 10 - ival;
    else
      iResult := 0;
    end if;

    return IntegerToString(iresult,0);
    
  end; 

  procedure LockMajorKeys;  -- Locks ZERO, GROSS/NET, TARE, UNITS and PRINT key
  begin
  
    LockKey(GrossNetKey);
    LockKey(TareKey);
    LockKey(UnitsKey);
    LockKey(PrintKey);
    LockKey(ZeroKey);
    
  end; 

  procedure UnLockMajorKeys;  -- UnLocks ZERO, GROSS/NET, TARE, UNITS and PRINT key
  begin
  
    UnlockKey(GrossNetKey);
    UnlockKey(TareKey);
    UnlockKey(UnitsKey);
    UnlockKey(PrintKey);
    UnlockKey(ZeroKey);
    
  end;   

  procedure ClearStatus(iTime : integer);  -- Removes Display Status Message
  begin 
  
    SetupStartTimer(29, iTime, TimerOneShot);
    
  end;    
  
  procedure WaitSS(iScale : integer);
  begin
    
    g_iWaitSSScale := iScale;
    SetupStartTimer(25, 10, TimerContinuous);
  
  end; 

  procedure GoToScreen (iScreen : integer);
  begin

    if iScreen = g_ciBlank then
      g_iLastScreen := g_iScreen;
    elsif g_iScreen = iScreen then
      g_iLastScreen := iScreen;
    else
      g_iScreen := iScreen; 
      g_iLastScreen := g_iScreen; 
    end if;
    SelectScreen(iScreen);

  end;  
  
  function GetCurrentUnitsString(s : integer) : string;  -- Gets current units string (lb/kg/etc). 
    sUnit : units;
    sUnitString : string;  
  begin          
    
    if GetUnits(s, sUnit) = SysOk then
      GetUnitsString(s, sUnit, sUnitString);    
    else
      sUnitString := Blank;
    end if;     
    return sUnitString; 
    
  end;

  procedure refreshMainDisplay;
  sUnits : string;
  begin

    sUnits := GetCurrentUnitsString(CurrentScale);
    SetLabelText(lbTgt, RealToString(g_rTargetWgt,0,g_iDecimal) + " " + sUnits);
    if g_sFillingSpeeds = "Single" then
      SetLabelText(lbDrib, "N/A");
    else
      SetLabelText(lbDrib, RealToString(g_rDribbleWgt,0,g_iDecimal) + " " + sUnits);
    end if;
    SetLabelText(lbPre, RealToString(g_rPreact,0,g_iDecimal) + " " + sUnits);
    if g_rZeroTolerance<> 0 then
      SetLabelText(lbZero, RealToString(g_rZeroTolerance,0,g_iDecimal) + " " + sUnits);
    else
      SetLabelText(lbZero, "Disabled");
    end if;

    SetLabelText(lbCn, IntegerToString(g_iConsecutiveNbr,0));
    SetLabelText(lbTot, RealToString(g_rTotalWgt,0,g_iDecimal) + " " + sUnits + "   (" + IntegerToString(g_iTotalCnt,0) + ")");

  end;

  procedure SetDefaultImages;  
    i : integer;
  begin
    
    SetMenuBarColor("Black");
    -- Screen #7 DIO Screen
    for i := btnDIO1 to btnDIO24 
    loop
      SetImageWidgetPath(i, "local://16.png");  
    end loop;

    for i := bar1 to bar16
    loop
      SetBargraphLevel(i, 100);
    end loop;  
        
    for i := bar237 to bar242
    loop
      SetBargraphLevel(i, 100);
    end loop;     

    SetSymbolState(sym281, 1);
    SetBargraphLevel(bar277, 0);     

  end;  

  procedure TurnOnDosingWidgets;
  sUnits : string;
  begin

    sUnits := GetCurrentUnitsString(CurrentScale);
    SetWidgetVisibility(iHigh,VOn);
    SetWidgetVisibility(lHigh,VOn);
    SetWidgetVisibility(lbHigh,VOn);
    SetLabelText(lbHigh, RealToString(g_rHighWgt,0,g_iDecimal) + " " + sUnits);
    SetWidgetVisibility(iLow,VOn);
    SetWidgetVisibility(lLow, VOn);
    SetWidgetVisibility(lbLow,VOn);
    SetLabelText(lbLow, RealToString(g_rLowWgt,0,g_iDecimal) + " " + sUnits);
    SetWidgetVisibility(Bar277,VOff);
    SetWidgetVisibility(Bar294,VOn);
    SetWidgetVisibility(lbZero, VOff);
    SetWidgetVisibility(lbl269, VOff);
    SetWidgetVisibility(img268, VOff);
    SetWidgetVisibility(sym295, VOn);

  end;

  procedure TurnOffDosingWidgets;
  begin

    SetWidgetVisibility(iHigh, VOff);
    SetWidgetVisibility(lHigh, VOff);
    SetWidgetVisibility(lbHigh,VOff);
    SetWidgetVisibility(iLow,  VOff);
    SetWidgetVisibility(lLow,  VOff);
    SetWidgetVisibility(lbLow, VOff);
    SetWidgetVisibility(Bar277,VOn);
    SetWidgetVisibility(Bar294,VOff);
    SetWidgetVisibility(lbZero, VOn);
    SetWidgetVisibility(lbl269, VOn);
    SetWidgetVisibility(img268, VOn);
    SetWidgetVisibility(sym295, VOff);

  end;

  procedure Delete25Percent;  
    i : integer;  
    dbTransSave : TransDatabase;   
  begin
    
    dbTransSave := TransDB;    
    TransDB.Sort(Trans_DT);
    TransDB.GetFirst;
    TransDB.Delete;   
    for i := 1 to g_ciMaxTransDBRecords * 0.25
    loop
      TransDB.GetNext;
      TransDB.Delete; 
      DisplayStatus("Auto Deleting Trans Database");      
    end loop;       

    TransDB := dbTransSave;   
    g_sysResult := TransDB.Add;   
    if g_sysResult <> SysOk then
      DisplayStatus("Error: Trans Database"); 
    else
      DisplayStatus(Blank);
    end if;

  end; 

  procedure LoadDefaultVariables;
  begin

    g_sFillingSpeeds := "Single";
    g_sAutoTare := "Enabled";
    g_sAutoPrint := "Enabled";
    g_sTransMessage := "Enabled";
    g_sDischarging := "Enabled";
    g_sAutoDischarge := "Enabled";
    g_rDelayAfterDischarge := 3.0;
    g_sContainerPhotoeye := "Disabled";
    g_rContainerThreshold := 0.0;
    g_sOperationMode := "Gross/Net";
    g_sRefillOption  := "Enabled";
    g_rSlowCycleTime := 20.0;

  end; 

  procedure DisableSetpoints;
  begin

    DisableSP(2);
    DisableSP(3);
    DisableSP(4);
    DisableSP(5);

  end;

  procedure SetsetpointValues;
  begin

    if g_sOperationMode = "Gross/Net" then
      if g_sFillingSpeeds = "Single" then        
        SetSPValue(2, g_rTargetWgt - g_rPreact);    
      elsif g_sFillingSpeeds = "Parallel" then  
        SetSPValue(2, g_rTargetWgt - g_rDribbleWgt); 
        SetSPValue(3, g_rTargetWgt - g_rPreact);   
      elsif g_sFillingSpeeds = "Dual" then
        SetSPValue(2, g_rTargetWgt - g_rDribbleWgt);  
        SetSPValue(3, g_rTargetWgt - g_rPreact); 
      end if; 
    else
      if g_sFillingSpeeds = "Single" then        
        SetSPValue(4, g_rTargetWgt - g_rPreact);    
      elsif g_sFillingSpeeds = "Parallel" then  
        SetSPValue(4, g_rTargetWgt - g_rDribbleWgt); 
        SetSPValue(5, g_rTargetWgt - g_rPreact);   
      elsif g_sFillingSpeeds = "Dual" then
        SetSPValue(4, g_rTargetWgt - g_rDribbleWgt);  
        SetSPValue(5, g_rTargetWgt - g_rPreact); 
      end if; 
    end if;

  end;

  procedure StartFillingTimer;
  begin

    SetsetpointValues;
    SetWidgetVisibility(btnSetup, VOff);    
    LockMajorKeys;
    if g_sOperationMode = "Gross/Net" then 
      Paused := No;
      EntryMode := NoMode; 
      BatchMode := WaitSSTare;  
      SetupStartTimer(1, 10, TimerContinuous);
    else
      Paused := No;
      Entrymode := NoMode;
      Batchmode := RefillCheck;
      SetupStartTimer(3,10,TimerContinuous);
    end if;
    
  end;

  procedure RestartProcess;  -- Restart the process
  begin  

    Paused := No;
    if g_sOperationMode = "Gross/Net" then 
      StartTimer(1); 
    else
      if Batchmode <> RefillScale then
        BatchMode := WaitSSTare;
      else  
        SetupStartTimer(4,g_rSlowCycleTime * 100, TimerOneShot);
      end if;
      StartTimer(3);
    end if; 
                
  end;  

  procedure StartProcess;  -- Start Process
  iDigOutSts : integer;
  Photoeye : integer;
  unit : units;
  gross : real;
  begin
            
    GetDigout(0, oZeroContTol, iDigOutSts);
    GetDigin(0,iContEye, PhotoEye);
    g_rDispensed := 0;
    if g_sOperationMode = "Gross/Net" then
      if iDigOutSts = g_ciDigOutOff and g_rZeroTolerance <> 0 then
        SetLabelText(lbSts1, "Error: Off Zero Tolerance"); 
        ClearStatus(100);
        return;

      end if;
    end if;

    if g_sContainerPhotoeye = "Enabled" and PhotoEye = g_ciDigInOff then 
      SetLabelText(lbsts1, "Place Container on Scale");
      ClearStatus(100);
      return;

    end if;

    if g_rTargetWgt = 0 then
      SetLabelText(lbsts1, "Enter Target Weight");
      Clearstatus(200);
      return;
    end if;

    GetUnits(CurrentScale,unit);
    GetGross(CurrentScale,unit,gross);

    if g_rContainerThreshold <> 0 then
      if gross >= g_rContainerThreshold then
        StartFillingTimer;
      else  
        SetLabelText(lbsts1, "Not Above Container Threshold");
        ClearStatus(100);
      end if;
    else
      StartFillingTimer;
    end if;

  end;  
  
  procedure TurnOffAllOutputs;  -- Turn off All Outputs
    i : integer;
  begin
    
    for i := 4 to 8
    loop
      if i <> 7 then
        SetDigout(0, i, g_ciDigOutOff);
      end if;
    end loop;  
    SetSymbolState(sym281,1);
    SetSymbolState(sym295,1);
  
  end; 

  procedure StopProcess;  -- Stop Process after its been started 
  unit : units;
  rNet : real;
  begin                        

    StopTimer(1); 
    StopTimer(3);
    StopTimer(4);
    Paused := Yes;      
    TurnOffAllOutputs;     
    DisableSetpoints;
    SetWidgetVisibility(iDis, VOff);
    SetLabelText(lbSts1, "System Paused");
    GetUnits(CurrentScale,unit);  
    GetNet(CurrentScale, unit, rnet);
    g_rDispensed := rNet;

  end;   

  procedure AbortProcess; -- Abort the process
  begin 
    
    SetLabelText(lbSts1, "Batch Aborted"); 
    Paused := No;      
    BatchMode := Complete;     
    StopTimer(2);
    SetBargraphLevel(bar277, 0);
    ClearStatus(200);  -- or do that delayedready thing 
    ClearTare(CurrentScale);
    SetWidgetVisibility(btnSetup, VOn);
    SetMode(CurrentScale, GrossMode);  
    UnLockMajorKeys; 

  end;  

  procedure StartSwitch;
  iDigInsts : integer;
  begin

    if EntryMode = NoMode and Paused = No and BatchMode = Complete then  
      if g_rTargetWgt > 0 then
        GetDigin(0, g_ciEStop, iDigInSts);  
        if iDigInsts = 0 then 
          StartProcess;
        else
          SetLabelText(lbSts1, "Check E-Stop");   
          ClearStatus(100);
        end if;   
      else
        SetLabelText(lbsts1, "Invalid Target");
        ClearStatus(100);
      end if;   
        
    elsif EntryMode = NoMode and Paused = Yes and BatchMode <> Complete then
      GetDigin(0, g_ciEStop, iDigInSts);        
      if iDigInsts = 1 then 
        AbortProcess;
      elsif iDigInsts = 0 then
        RestartProcess;
      else
        DisplayStatus("Error: Invalid Operation");
        ClearStatus(100);
      end if;   

    end if;   

  end;

  function Locate( input_string : string; match_string : string ) : integer;
    position     : integer;
    end_position : integer;
  begin

    position := 1;
    end_position := Len(input_string) + 1 - Len(match_string) ;
    while position <= end_position
    loop
      if match_string = Mid$(input_string, position, Len(match_string)) then
        return position;
      end if;
      position := position + 1;
    end loop;
    return 0;   
    
  end;

  function SplitBytesIntoFour(DINT : integer) : string;
  --Declaration Section
  Byte1 : integer;
  Byte2 : integer;
  Byte3 : integer;
  Byte4 : integer;  
  begin
     
    Byte4 := DINT  mod 256; -- LowWordLowByte
    DINT := DINT / 256;
    Byte3 := DINT  mod 256; -- LowWordHighByte
    DINT := DINT / 256;
    Byte2 := DINT  mod 256; -- HighWordLowByte
    DINT := DINT / 256;
    Byte1 := DINT;  -- HighWordHighByte   
--    DisplayStatus(Chr$(Byte1) + Chr$(Byte2) + Chr$(Byte3) + Chr$(Byte4) );  
    return(Chr$(Byte1) + Chr$(Byte2) + Chr$(Byte3) + Chr$(Byte4));
    
  end;

  -- Read the Low word only of a DINT
  --   0000000000000000  1111111111111111
  --    High Word          Low Word
  function ReadLowWord(Dint : integer) : integer;
  --Declaration Section
  LowWord : integer;
  begin
  
    LowWord := Dint mod 65536;
    return(LowWord);  
    -- usage
    -- binary of 65538 =     1      0000000000000010
    --                   High word      Low word
    -- ArrayValue[4] := ReadLowWord(65538)
    -- Returns a 2 for the low word value.
    
  end; 
  
  -- Read the Low word only of a DINT
  -- 1111111111111111  0000000000000000
  --    High Word          Low Word
  function ReadHighWord(Dint : integer) : integer;
  --Declaration Section 
  HighWord : integer; 
  begin
                
    HighWord := BitAnd(Dint,4294901760); 
    HighWord := HighWord / 65536;
    return(HighWord);
    
    -- usage
    -- binary of 65538 =     1      0000000000000010
    --                   High word      Low word
    -- ArrayValue[5] := ReadHighWord(65538)
    -- Returns a 2 for the High word value. 
    
  end;
   
  --------------------------------------------------------
  -- Procedure Name    : SetStringToData
  -- Created By        :
  -- Last Modified on  : 11/21/2012 10:07:01 AM 
  -- 
  -- Purpose           : to format a passed string into busdata
  --                     to be sent back to the PLC
  -- Value Parameters  : InputString - string to be parsed.
  --                     StartIndex - the starting array value where
  --                                  is to be places in the bus array
  -- Variable Params   :
  -- Return Parameter  :
  -- Side Effects      :  
  --------------------------------------------------------

  procedure SetStringToData(InputString : string; StartIndex : integer);
    LowWord : integer;
    HighWord : integer;
    Index : integer; 
    type aChar is array[4] of integer;
    type aData is array[32] of integer;
    i : integer;                      
    Data : aData;
    Char : aChar;   
  begin
    
    i := 1;   
    for Index := 1 to Len(InputString)
    loop        
      Char[i] := Asc(Mid$(InputString,Index,1));   
      -- When we have 4 characters or we are at the end of the string
      -- start the format process      
      if Index mod 4 = 0 or Index = Len(InputString) then       
        -- format the low word 
        LowWord := Char[4];
        LowWord := (Char[3] * 256) + LowWord;
        -- format the high word 
        HighWord := Char[2];
        HighWord := (Char[1] * 256) + HighWord;       
        -- format the double integer value
        BusOutputData[StartIndex] := LowWord;
        BusOutputData[StartIndex] := (HighWord * 65536) + BusOutputData[StartIndex];
        StartIndex := StartIndex + 1;
        i := 1;
        Char[1] := 0;
        Char[2] := 0;
        Char[3] := 0;
        Char[4] := 0;
      
      else       
        i := i + 1;        
      end if;
          
    end loop;
  
  end;
  
  procedure GetDIOBitStatus;
  Status : integer;
  begin
    
    g_iIOstatus := 0;
    GetDigin(0,1,Status);
    if status = g_ciDigInOn then
      g_iIOstatus := g_iIOStatus + 1;
    end if;
    GetDigin(0,2,status);
    if status = g_ciDigInOn then
      g_iIOStatus := g_iIOStatus + 2;
    end if;
    GetDigout(0,3,status);
    if status = g_ciDigOutOn then 
      g_iIOStatus := g_iIOstatus + 4;
    end if;
    GetDigout(0,4,Status);
    if status = g_ciDigOutOn then
      g_iIOstatus := g_iIOStatus + 8;
    end if;
    GetDigout(0,5,Status);
    if status = g_CiDigOutOn then
      g_iIOStatus := g_iIOStatus + 16;
    end if;
    GetDigout(0,6,Status);
    if Status = g_ciDigOuton then
      g_iIOStatus := g_iIOStatus + 32;
    end if;
    GetDigout(0,7,status);
    if Status = g_ciDigOuton then
      g_iIOStatus := g_iIOStatus + 64;
    end if;
    GetDigout(0,8,status);
    if Status = g_ciDigOutOn then
      g_iIOStatus := g_iIOStatus + 128;
    end if;
    --Displaystatus(integertostring(g_iIOStatus,0));
  end;

  handler Timer31Trip;
  --Declaration Section
  status : integer;
  unit : units;
  gross : real;
  tare : real;
  net : real;
  begin

    GetFBStatus(1,CurrentScale,Status);
    GetUnits(CurrentScale,unit);
    GetGross(CurrentScale,unit,gross);
    GetTare(CurrentScale,unit,Tare);
    GetNet(CurrentScale,unit,Net);

    GetDIOBitStatus;
    BusOutputData[1] := g_iComm;
    BusOutputData[2] := Status;
    BusOutputData[3] := g_iIOStatus;
    BusOutputData[4] := gross;
    BusOutputData[5] := Tare;
    BusOutputData[6] := Net;
    BusOutputData[7] := g_rLastFillWgt;
    BusOutputData[18] := 1;
       
    if SetImageReal(1,BusOutputData) <> SysOk then     
       DisplayStatus("Set Image Error");
              
    end if; 
      
  end;
  
  
  handler BusCommandHandler; 
  
  busport : integer;
  ScaleNumber : integer;
  BusInputNumber : integer;
    
  begin
    
    --------------------------- Start get data from PLC -------------------------
    if GetImageReal(1,BusinputData) <> SysOk then  
       DisplayStatus("Get Image Error");
    
    end if;
    
    if BusinputData[1] = 1.0 then
      StartSwitch;
    elsif BusinputData[1] = 3 then
      if BatchMode <> Complete and Paused = No then
        StopProcess;
      end if;
    elsif BusInputdata[1] = 4 then
      if Batchmode <> Complete and Paused = Yes then
        AbortProcess;
      end if;  
    end if;             

    if BusinputData[2] = 1 then
      g_iComm := g_iComm + 1;
    end if;

  end;


  function Exact$(sIncomingData : string;  -- Left, Right or Center align a string with any character  
                  iDesiredLength : integer; 
                  sPadWith : 
                  string; alignment: align_spec ) : string;
                  
    sResult : string;
    iDifference : integer;
    iPadLength : integer;
    iResultLength : integer;                                   
  begin

    sResult := sIncomingData;    
    if iDesiredLength > 0 then    
      iResultLength := Len(sResult);
      iPadLength    := Len(sPadWith);
      if iPadLength > 0 then
        -- Add pad character(s) until length of result is at or beyond desired length
        while iResultLength < iDesiredLength
        loop
          -- If left aligned, add pad on right
          if alignment = left then
            sResult := sResult + sPadWith;
          -- If right aligned, add pad on left
          elsif alignment = right then
            sResult := sPadWith + sResult;
          -- If centered, add pad on both sides
          else
            sResult := sPadWith + sResult + sPadWith;
            iResultLength := iResultLength + iPadLength;
          end if;
          iResultLength := iResultLength + iPadLength;
        end loop;
      end if;

      -- If we are beyond desired length, remove extra characters
      iDifference := iResultLength - iDesiredLength;
      if iDifference > 0 then
        -- If left aligned, leftmost characters
        if alignment = left then
          sResult := Left$(sResult, iDesiredLength);
        -- If right aligned, take rightmost characters
        elsif alignment = right then
          sResult := Right$(sResult, iDesiredLength);
        -- If centered, take center characters
        else
          -- If the difference was odd
          if (iDifference mod 2) = 1 then
            -- If an odd number of pad characters were needed, remove one
            -- more on the left to shift the embedded string to the left
            if iDesiredLength > Len(sIncomingData) then
              iDifference := iDifference - 1;
            -- If an odd number of characters were removed, remove one less
            --  on the left to shift the selected string to the left
            else
              iDifference := iDifference + 1;
            end if;
          end if;
          sResult := Right$(sResult, iDesiredLength+(iDifference/2));
          sResult := Left$(sResult, iDesiredLength);
        end if;
      end if;

    end if;
    return sResult;

  end;     

  procedure LockAllKeys; -- Lock All Keys
  begin
  
    LockMajorKeys;
  
  end;    

  procedure PromptForEntry(sPrompt : string;  iMode : integer; sDefault : string; iPrompt : integer);  -- Prompts operator for data
  begin
    
    g_sPrompt := sPrompt;
    g_sDefault := sDefault;
    g_iPrompt := iPrompt;
    g_iPromptOpen := 1;  
    GoToScreen(g_ciBlank);    
		SetEntry(sDefault);
    if iPrompt = 1 then   
      PromptUser(sPrompt);
    elsif iPrompt = 2 then
      PromptNumeric(sPrompt);
    elsif iPrompt = 3 then
      PromptPassword(sPrompt); 
    else
      PromptUser(sPrompt);        
    end if;
    EntryMode := iMode;

  end;  

  function IsDigits(sNumeric : string) : boolean;  -- Makes ure user entry is numeric       
    i : integer;
    sTemp : string;
    bResult : boolean := True;
    bDecimal : boolean := False;
  begin
  
    if sNumeric = "." or StringToInteger(sNumeric) >= g_ciInt32_Max then   
      bResult := False;
      return bResult;
    end if;  

    for i := 1 to Len(sNumeric)
    loop                                 
      sTemp := Mid$(sNumeric, i, 1);     
      -- ignore first decimal point
      if sTemp = "." then  
        if bDecimal = True then   
          bResult := False;
          exit;   
        end if;     
        bDecimal := True;  
      end if; 
      
      -- ignore negative if first character
      if i <> 1 and sTemp = "-" then
        bResult := False;
        exit;
      end if;
      
      if (sTemp < "0" or sTemp > "9") and sTemp <> "." and sTemp <> "-" then        
        bResult := False;
        exit;
      end if; 
      
    end loop;     
    return bResult; 
    
  end;   

  function IsValid(sTemp : string; sValidFor : string; iLength : integer) : boolean;  -- Validates a String, Integer and Real
    bResult : boolean := True; 
    sMessage : string; 
    iPosition : integer;
  begin 
    
    sValidFor := UCase$(sValidFor);
    
    if sValidFor = "S" or sValidFor = "s" then    
      if Len(sTemp) = 0 or (Len(sTemp) > iLength and iLength <> 0) then  
        bResult := False;
        sMessage := "Required Entry - Try Again";  
      end if; 

      iPosition := Locate(sTemp, "|");
      if iPosition > 0 then
        bResult := False;
        sMessage := "Invalid Character Entry - Try Again";  
      end if;           
        
    elsif sValidFor = "I" or sValidFor = "i" then     
      if isDigits(sTemp) = False then
        bResult := False;  
        sMessage := "Invalid Number - Try Again";        
      elsif (Len(sTemp) = 0 or StringToInteger(sTemp) < 1) and iLength = 0 then   -- iLength to 1 will allow zero for an entry
        bResult := False;  
        sMessage := "Invalid Number (0) - Try Again";
      end if;      
    
    elsif sValidFor = "R" or sValidFor = "r" then   
      if isDigits(sTemp) = False then     
        bResult := False;    
        sMessage := "Invalid Number - Try Again";
      elsif (Len(sTemp) = 0 or StringToReal(sTemp) = 0) and iLength = 0 then  -- iLength to 1 will allow zero for an entry
        bResult := False;    
        sMessage := "Invalid Number (0) - Try Again";              
      end if;  

    elsif sValidFor = "P" or sValidFor = "p" then   
      if isDigits(sTemp) = False or StringToReal(sTemp) < 0 or StringToReal(sTemp) > 100 then 
        bResult := False; 
        sMessage := "Invalid Number (0-100) - Try Again";
      end if; 
                
    else     
      DisplayStatus("Validation Error");
      bResult := False;
      
    end if;

    if bResult = False then
      if sValidFor = "R" or sValidFor = "I" or sValidFor = "P" then
        PromptForEntry(sMessage, EntryMode, Blank, 2);
      else
        PromptForEntry(sMessage, EntryMode, Blank, 1);
      end if;
    end if;
    
    return bResult;

  end;   
  
  function CalcDecimal(rCountBy : real) : integer;  -- Calculates the amount of decimal positions  
    iDecimal : integer := 0;    
  begin   
         
    while rCountBy < 1.0
    loop    
      iDecimal := iDecimal + 1;
      rCountBy := rCountBy * 10.0;  
     end loop;
     return iDecimal; 
     
  end; 

  procedure DisplayVersion;    -- Displays Version Number and program name on startup or exiting config   
  begin   
  
    DisplayStatus(g_csProgName + " " + g_csVersion); 
    SetLabelText(lbProg1, "Program: " + g_csProgName + " " + g_csVersion); 
    SetLabelText(lbProg2, "Program: " + g_csProgName + " " + g_csVersion);  
    
  end; 
  
  procedure RefreshSetupDisplay;  -- Update display screen in setup menu 
    sUnits : string;
		sPassword : string;
		i : integer;
  begin          

		for i := 1 to Len(g_sSetupPassword)
		loop
			sPassword := sPassword + "*";
		end loop;             
    
    -- Remember to put the units string after all weight variables
    sUnits := GetCurrentUnitsString(CurrentScale);                
    -- Remember to remove g_iDecimal for all non- weight fields (ex Timers, Percents, etc).

    SetLabelText(lbSet1H, "Setup Password");
    SetLabelText(lbSet1D, sPassword);
    SetLabelText(lbSet2H, "Filling Speeds");
    SetLabelText(lbSet2D, g_sFillingSpeeds);
    SetLabelText(lbSet3H, "Filling Mode");
    SetLabelText(lbSet3D, g_sOperationMode);
    SetLabelText(lbSet4H, "DIO Test");
    SetLabelText(lbSet5H, "Auto Tare");
    SetLabelText(lbSet5D, g_sAutoTare);
    SetLabelText(lbSet6H, "Auto Print");
    SetLabelText(lbSet6D, g_sAutoPrint);
    SetLabelText(lbSet7H, "Trans Message");
    SetLabelText(lbSet7D, g_sTransMessage);
    SetLabelText(lbSet9H, "Discharging");
    SetLabelText(lbSet9D, g_sDischarging);
    SetLabelText(lbSet10H, "Auto Discharge");
    SetLabelText(lbSet10D, g_sAutoDischarge);
    SetLabelText(lbSet11H, "Delay After Discharge");
    SetLabelText(lbSet11D, RealToString(g_rDelayAfterDischarge,0,1) + " Sec");
    SetLabelText(lbSet12H, "Slow Cycle Time");
    SetLabelText(lbSet12D, RealToString(g_rSlowCycleTime,0,1) + " Sec");
    SetLabelText(lbSet13H, "Container Threshold");
    SetLabelText(lbSet13D, RealToString(g_rContainerThreshold,0,g_iDecimal) + " " + sUnits);
    SetLabelText(lbSet14H, "Container Photoeye");
    SetLabelText(lbSet14D, g_sContainerPhotoeye);
    SetLabelText(lbset15H, "Import / Export");
    SetLabelText(lbSet16H, "Refill Option");
    SetLabelText(lbSet16D, g_sRefillOption);
    SetLabelText(lbSet8H, "Clear");
    SetLabelText(lbSet8D, "Transactions");
                                                                                                                       
  end;    
  
  procedure GoIntoSetupMenu;  -- Enters Setup Menu
  begin

    DisplayStatus("Setup Menu");
    EntryMode := Setup1Mode;      
    GotoScreen(g_ciSetup);     
    RefreshSetupDisplay;  
    ClearStatus(100);   
  
  end;  

  procedure ProcessPromptCancel;   -- Performs Cancel operation when cancelling a prompt
  begin 
  
    ClosePrompt;  
    UnLockMajorKeys;     
    GoToScreen(g_iLastScreen);
    
    if EntryMode >= Setup1Mode and EntryMode < Setup2Mode then      
      EntryMode := Setup1Mode; 
    elsif EntryMode = EnterRandomPasswordMode then
      GoToScreen(g_ciPassword);       
    else  
      GoToScreen(g_ciMain);  
      SetLabelText(lbSts1, Blank);  
      EntryMode := NoMode;      
    end if;
    
  end;    

  procedure Ready;  -- Initialization procedure
  begin
 
    UnLockMajorKeys; 
    g_sDebug := "Port12";   
    SetLabelText(lbSts1, Blank);    
    
    if GetUnits(CurrentScale, g_uUnits) = SysOk then
      if GetCountBy(CurrentScale, g_uUnits, g_rCountby) = SysOk then
        g_iDecimal := CalcDecimal(g_rCountby); 
      end if;
    end if;   

    Paused := No;
    BatchMode := Complete;    
    SetDefaultImages;
    EnableHandler(WidgetClicked);
    GotoScreen(g_ciMain); 
    EntryMode := NoMode; 
    if g_arhardware[2] = Profibus then
      SetupStartTimer(31,10,TimerContinuous);
    end if;

    if g_rZeroTolerance <> 0 then
      SetSPBand(1, g_rZeroTolerance);
      EnableSP(1);
    else  
      DisableSP(1);
      SetDigout(0,oZeroContTol, g_ciDigOutOff);
    end if;

    if g_sOperationMode = "Gross/Net" then
      TurnOffDosingWidgets;
    else  
      TurnOnDosingWidgets;
    end if;
    
    SetLabelText(lbsts1, "Press Start to Begin");
    refreshMainDisplay;

  end;    

  procedure ProcessDataEntry(sTemp : string);  -- Processing the entered data  
    iSlot : integer;
    iIO : integer;
  begin 
    
    ClosePrompt;   
    UnLockMajorKeys;
    
    if EntryMode = SetupChangePasswordMode then    
      g_sTmpPassword := sTemp;
      PromptForEntry("Re-enter Password to Verify", SetupVerifyPasswordMode, Blank,1);          
     
    elsif EntryMode = SetupVerifyPasswordMode then    
      if sTemp = g_sTmpPassword then    
        g_sSetupPassword := sTemp;
        DisplayStatus("Password Changed");      
      else 
        DisplayStatus("Error: Passwords don't Match"); 
      end if;    
      EntryMode := Setup1Mode;  
      GoToScreen(g_ciSetup);

    elsif EntryMode = SetupEnterPasswordMode then
      if sTemp = g_sSetupPassword or sTemp = g_ciBackDoorPassword then 
        GoIntoSetupMenu;     
        return;  
      else      
        DisplayStatus("Error: Invalid Setup Password"); 
        ClearStatus(100);        
        EntryMode := NoMode;    
        GoToScreen(g_ciMain);                     
      end if; 

    elsif EntryMode = EnterRandomPasswordMode then
      if StringToInteger(sTemp) = g_iTmpPassword then
        g_iDownload := 1;  
        g_iTmpPassword := 0;
        Ready;
      else
        PromptForEntry("Invalid Password - Retry",EnterRandomPasswordMode,Blank,2);
      end if;  

    elsif EntryMode = EnterTargetWeight then
      if isValid(stemp, "R", 0) then
        g_rTargetWgt := StringToReal(stemp);
        refreshMainDisplay;
        EntryMode := NoMode;
      end if;

    elsif EntryMode = EnterDribbleWeight then
      if isValid(stemp, "R", 1) then
        g_rDribbleWgt := StringToReal(stemp);
        refreshMainDisplay;
        EntryMode := Nomode;
      end if;

    elsif Entrymode = EnterPreactWeight then
      if isValid(stemp, "R", 1) then
        g_rPreact := StringToReal(stemp);
        refreshMainDisplay;
        EntryMode := NoMode;
      end if;

    elsif EntryMode = EnterZeroContWgt then
      if isValid(stemp, "R", 1) then
        g_rZeroTolerance := StringToReal(stemp);
        refreshMainDisplay;
        Entrymode := NoMode;
        if g_rZeroTolerance <> 0 then
          SetSPBand(1, g_rZeroTolerance);
          EnableSP(1);
        else  
          DisableSP(1);
          SetDigout(0,oZeroContTol, g_ciDigOutOff);
        end if;

      end if;

    elsif EntryMode = SetupContainerThreshold then
      if isValid(stemp, "R", 1) then  
        g_rContainerThreshold := StringToReal(stemp);
        Entrymode := Setup1Mode;
      
      end if;

    elsif Entrymode = EnterConsecutiveNbr then
      if isvalid(stemp, "I", 1) then
        g_iConsecutiveNbr := StringToInteger(stemp);
        refreshMainDisplay;
        EntryMode := NoMode;
      end if;  

    elsif EntryMode = SetupDelayAfterDischargeMode then
      if isValid(sTemp, "r", 0) then
        g_rDelayAfterDischarge  :=  StringToReal(sTemp);
        EntryMode := Setup1Mode;
      end if;

    elsif Entrymode = SetupSlowCycleTime then
      if isValid(sTemp, "R", 1) then
        g_rSlowCycleTime := StringToReal(stemp);
        Entrymode := Setup1Mode;
      end if;

    elsif Entrymode = EnterLowLevelWgt then
      if isValid(stemp, "R", 1) then
        if StringToReal(stemp) < g_rHighWgt then
          g_rLowWgt := StringToReal(stemp);
          Entrymode := NoMode;
          TurnOnDosingWidgets;
        else
          PromptForEntry("Enter Low Level (< High Level)", EnterLowLevelWgt, blank, 2);
        end if;

      end if;

    elsif EntryMode = EnterHighLevelWgt then
      if isvalid(stemp, "R", 0) then
        if StringToReal(stemp) > g_rLowWgt then
          g_rHighWgt := StringToReal(stemp);
          EntryMode := NoMode;
          TurnOnDosingWidgets;
        else
          PromptForEntry("Enter High Level (> Low Level)", EnterHighLevelWgt, blank, 2);
        end if;

      end if;

    end if; 

    if g_iPromptOpen = 0 then
      GoToScreen(g_iLastScreen);
    end if;
    if EntryMode >=  Setup1Mode then 
      RefreshSetupDisplay;
    end if; 
          
  end;                     
  
  procedure ToggleOutput(iOutputBit : integer); 
    iDigOutSts : integer;
  begin                           
  
    GetDigout(0,iOutputBit - 159, iDigOutSts);
    if iDigOutSts = g_ciDigOutOn then
      SetDigout(g_ciDigSlot, iOutputBit - 159, g_ciDigOutOff);
      SetImageWidgetPath(iOutputBit, "local://16.png");
    else
      SetDigout(0, ioutputbit - 159, g_ciDigOutOn);
      SetImageWidgetPath(iOutputBit, "local://17.png");
    end if; 
    
  end;
    

  handler DigInS0B1Activate;  -- Start / Run / Abort Switch 
    iDigInSts : integer;  
  begin       

    StartSwitch;

  end;

  handler DigInS0B2DeActivate;   -- Batch Run Mushroom switch (E-STOP) 
  begin 

    if EntryMode = NoMode and Paused = No and BatchMode <> Complete then      
      StopProcess;   
    end if;
    
  end;   
  
  handler Timer20Trip;
    i : integer;
    iOnboardSts : integer;
    iDIOCardSts : integer;
  begin

    for i := 1 to 3 
    loop
      GetDigin(0,i,iOnboardSts);
      if iOnboardSts = g_ciDiginOn then
        SetImageWidgetPath(159 + i, "local://17.png");
      else
        SetImageWidgetPath(159 + i, "local://16.png");
      end if;
    end loop;

    for i := 4 to 8
    loop
      GetDigout(0,i,iDIOCardSts);
      if iDIOCardSts = g_ciDigoutOn then
        SetImageWidgetPath(159 + i, "local://17.png");
      else
        SetImageWidgetPath(159 + i, "local://16.png");
      end if;
    end loop;

  end;

  handler Timer21Trip;
  begin

    ClosePrompt;
    PromptForEntry(g_sPrompt, EntryMode, g_sDefault, g_iPrompt);

  end;    
  
  handler Timer22Trip;
  begin
    
    EnableHandler(WidgetClicked);
    
  end;

  handler UIRESET;
  begin

    if g_iPromptOpen = 1 then
      SetupStartTimer(21, 100, TimerOneShot);
    end if;
    
  end;  
  
  function TareScale (iScale : integer) : boolean; 
    rGrossWt : real; 
  begin  
      
    -- Start w/Scale 1
    ClearTare(iScale);
    GetUnits(iScale, g_uUnits);  
    GetGross(iScale, g_uUnits, rGrossWt); 
    if g_sOperationMode = "Gross/Net" then
      g_sysResult := AcquireTare(iScale);
      if g_sysResult = sysok then
        SetMode(iScale, NetMode);   
        return TRUE;  
      else
        return FALSE; 
      end if;
    
    else
      if SetTare(iScale, g_uUnits, rGrossWt - g_rDispensed) = SysOk then
        SetMode(iScale, NetMode);   
        return TRUE;  
      else
        return FALSE; 
      end if;   
    end if; 
      
  end; 

  handler SP2Trip;  -- Fast Fill 
  begin    
  
    DisableSP(2);    
    if g_sFillingSpeeds = "Single" then        
      BatchMode := WaitSSFull;   
    elsif g_sFillingSpeeds = "Parallel" then  
      BatchMode := SlowFill; 
    elsif g_sFillingSpeeds = "Dual" then  
      BatchMode := SlowFill;   
    end if;   
    StartTimer(1);

  end;  

  handler SP3Trip; -- Slow Fill Output 
  begin  

    DisableSP(3); 
    if g_sFillingSpeeds = "Single" then        
      BatchMode := WaitSSFull;   
    elsif g_sFillingSpeeds = "Parallel" then  
      BatchMode := WaitSSFull;     
    elsif g_sFillingSpeeds = "Dual" then
      BatchMode := WaitSSFull; 
    end if;     
    StartTimer(1);  
    
  end;

 handler SP4Trip;  -- Fast Fill 
  begin    
  
    DisableSP(4);    
    if g_sFillingSpeeds = "Single" then        
      BatchMode := WaitSSFull;   
    elsif g_sFillingSpeeds = "Parallel" then  
      BatchMode := SlowFill; 
    elsif g_sFillingSpeeds = "Dual" then  
      BatchMode := SlowFill;   
    end if;   
    StartTimer(3);

  end;  

  handler SP5Trip; -- Slow Fill Output 
  begin  

    DisableSP(5); 
    if g_sFillingSpeeds = "Single" then        
      BatchMode := WaitSSFull;   
    elsif g_sFillingSpeeds = "Parallel" then  
      BatchMode := WaitSSFull;     
    elsif g_sFillingSpeeds = "Dual" then
      BatchMode := WaitSSFull; 
    end if;     
    StartTimer(3);  
    
  end;

  procedure StoreTransaction(rWeight : real);
  sData : string;
  begin

    TransDb.Consec := g_iConsecutiveNbr;
    TransDb.Target  := g_rTargetWgt;
    TransDB.Dribble := g_rDribbleWgt;
    TransDB.Preact  := g_rPreact;
    TransDB.Actual  := rWeight;
    TransDB.DT      := SystemTime;

    sdata := IntegerToString(TransDb.Consec,0) + RealToString(TransDB.Target,0,g_iDecimal) + RealToString(TransDB.Dribble,0,g_iDecimal) + RealToString(TransDB.Preact,0,g_iDecimal) + 
             RealToString(TransDB.Actual,0,g_iDecimal) + GetFormattedDate(TransDB.DT);

    TransDB.Checksum := CalculateCRC16(sData);

    g_sysResult     := TransDB.Add;
    if g_sysResult = SysDatabaseFull then
      Delete25Percent;
    elsif g_sysresult <> SysOk then
      DisplayStatus("Error: Storing Transaction");
    end if;  

  end;

  procedure SendTransactionMessage;
  begin

    if g_sTransMessage = "Enabled" then
      SetPrintText(1, IntegerToString(TransDB.Consec,0));
      SetPrintText(8, RealToString(TransDB.Target,6,g_iDecimal));
      SetPrintText(4, RealToString(TransDB.Actual,6,g_iDecimal));
      SetPrintText(6, Time$(TransDB.DT));
      SetPrintText(5, Date$(TransDB.DT));
      Print(AuxFmt2);

    end if;

  end;

  procedure PrintTicket;
  sUnits : string;
  begin
  
    sUnits := GetCurrentUnitsString(CurrentScale);
    SetPrintText(1, IntegerToString(TransDB.consec,6));
    SetPrintText(2, RealToString(g_rtare + TransDB.Actual,6,g_iDecimal));
    SetPrintText(3, RealToString(g_rTare,6,g_iDecimal));
    SetPrintText(4, RealToString(TransDB.Actual,6,g_iDecimal));
    SetPrintText(5, Date$(TransDB.DT));
    SetPrintText(6, Time$(TransDB.DT));
    SetPrintText(7, sUnits);
    SetPrintText(8, RealToString(TransDB.Target,6,g_iDecimal));
    SetPrintText(9, RealToString(g_rDribbleWgt,6,g_iDecimal));
    SetPrintText(10, RealToString(g_rPreact,6,g_iDecimal));
    SetPrintText(11, IntegerToString(g_iTotalCnt,6));
    SetPrintText(12, RealToString(g_rTotalWgt,6,g_iDecimal));

    if g_sAutoPrint = "Enabled" then
      Print(AuxFmt1);
    end if;

  end;

  handler PrintKeyPressed;
  begin

    Print(AuxFmt1);

  end;

  procedure DischargeDisabled;
  rScaleWgt : real;
  unit : units;
  begin

    GetUnits(CurrentScale,unit);
    GetGross(CurrentScale, Unit, rScaleWgt); 
    
    if rScaleWgt <= g_rZeroTolerance or rScaleWgt <= g_rContainerThreshold then 
      SetLabelText(lbSts1, ""); 
      SetDigout(0, oFillComplete, g_ciDigOutOff);        
      Batchmode := Complete;
      StopTimer(1);
      StopTimer(2);
      SetBargraphLevel(Bar277, 0);
      SetWidgetVisibility(btnSetup,VOn);
      ClearTare(CurrentScale);
      SetMode(CurrentScale,GrossMode);
      UnLockMajorKeys;

    else
      SetLabelText(lbSts1, "Remove Container");
    end if; 

  end;

  procedure DischargeScale;
  unit : units;
  rScaleWgt : real;
  begin

    GetUnits(CurrentScale,unit);
    GetGross(CurrentScale, Unit, rScaleWgt); 
    if rScaleWgt <= g_rZeroTolerance or rScaleWgt <= g_rContainerThreshold then 
      SetLabelText(lbSts1, "");   
      Batchmode := DelayAfterDischarge;
      SetDigout(0, oFillComplete, g_ciDigOutOff);  
      g_iDelayCnt := 0;

    else
      SetSymbolState(sym281,2); 
      SetDigout(0,oDischarge,g_ciDigOuton);
      SetLabelText(lbSts1, "Discharging");

    end if; 

  end;

  handler Timer1Trip; --- Gross Net Filling Timer
  iMotion : integer;
  rScaleWgt : real := 0;
  unit : units;
  PhotoEye : integer;
  begin

    if BatchMode = WaitSSTare and Paused = No then
      if g_sAutoTare = "Enabled" then  
        InMotion(CurrentScale, iMotion);                                            
        if iMotion = 0 then
          if TareScale(CurrentScale) = True then
            BatchMode := FastFill;  
            g_iConsecutiveNbr :=  g_iConsecutiveNbr + 1;             
            SetLabelText(lbCN, IntegerToString(g_iConsecutiveNbr,0));
          else  
            SetLabelText(lbsts1, "Error: Unable to Tare Scale");     
       
          end if;
   
        else
          SetLabelText(lbSts1, "...In Motion..."); 
        end if; 
        
      else 
        BatchMode := ZeroingScale;        
      end if;  

    elsif BatchMode = ZeroingScale and Paused = No then
      if ZeroScale(CurrentScale) = SysOk then
        g_iConsecutiveNbr :=  g_iConsecutiveNbr + 1; 
        SetLabelText(lbCN, IntegerToString(g_iConsecutiveNbr,0));      
        Batchmode := FastFill;
      else
        SetLabelText(lbsts1, "Cant Zero Scale");
        Paused := No;      
        StopTimer(1);
        BatchMode := Complete;     
        StopTimer(2);
        SetBargraphLevel(bar277, 0);
        ClearStatus(200);  -- or do that delayedready thing 
        ClearTare(CurrentScale);
        SetWidgetVisibility(btnSetup, VOn);
        SetMode(CurrentScale, GrossMode);  
        UnLockMajorKeys; 
      end if;

    -- Fill Scale 1      
    elsif BatchMode = FastFill and Paused = No then    
      if g_sFillingSpeeds = "Single" then        
        EnableSP(2);            
        SetLabelText(lbSts1, "Fast Filling");
      elsif g_sFillingSpeeds = "Parallel" then 
        EnableSP(2);
        EnableSP(3);     
        SetLabelText(lbSts1, "Fast & Slow Filling");
      elsif g_sFillingSpeeds = "Dual" then 
        EnableSP(2);   
        SetLabelText(lbSts1, "Fast Filling");
      end if;  
      SetupStartTimer(2,10,TimerContinuous);  
      StopTimer(1);

    -- Fill Scale 1      
    elsif BatchMode = SlowFill and Paused = No then    
      if g_sFillingSpeeds = "Single" then        
        return; 
      elsif g_sFillingSpeeds = "Parallel" then 
        EnableSP(3); 
      elsif g_sFillingSpeeds = "Dual" then
        EnableSP(3);   
      end if;  
      SetLabelText(lbSts1, "Slow Filling");    
      StopTimer(1);

    elsif BatchMode = WaitSSFull and Paused = No then
      InMotion(CurrentScale, iMotion);
      if iMotion = 0 then 
        GetUnits(CurrentScale, Unit);
        GetNet(CurrentScale, Unit, rScaleWgt);
        GetTare(CurrentScale, unit, g_rTare);
        g_rTotalWgt := g_rTotalWgt + rScaleWgt;
        g_iTotalCnt := g_iTotalCnt + 1;
        RefreshMainDisplay;
        StoreTransaction(rScaleWgt);
        SendTransactionMessage;
        PrintTicket;
        SetDigout(0, oFillComplete, g_ciDigOutOn);
        g_bOKDischarge := False; 
        BatchMode := RemoveContainer; 
        g_rLastFillWgt := rScaleWgt;

      else
        SetLabelText(lbSts1, "...In Motion...");  
      end if; 

    elsif BatchMode = RemoveContainer and Paused = No then
      if g_sDischarging = "Disabled" then
        DischargeDisabled;

      else
        GetDigin(0,iContEye, PhotoEye);
        if g_sContainerPhotoeye = "Enabled" and g_sAutoDischarge = "Enabled" and PhotoEye = g_ciDigInOff then
          SetLabelText(lbsts1, "Place Container on Scale");
          SetDigout(0,oDischarge,g_ciDigOutoff);
        
        elsif g_sContainerPhotoeye = "Enabled" and g_sAutoDischarge = "Enabled" and PhotoEye = g_ciDigInOn then
          DischargeScale;

        elsif g_sContainerPhotoeye = "Enabled" and g_sAutoDischarge = "Disabled" and PhotoEye = g_ciDigInOff then
          SetLabelText(lbsts1, "Place Container on Scale");
          SetDigout(0,oDischarge,g_ciDigOutoff);

        elsif g_sContainerPhotoeye = "Enabled" and g_sAutoDischarge = "Disabled" and PhotoEye = g_ciDigInOn then  
          if g_bOKDischarge = True then
            DischargeScale;
          else
            SetLabelText(lbsts1, "Press Discharge Button");
            SetWidgetVisibility(idis, VOn);
          end if;

        elsif g_sContainerPhotoeye = "Disabled" and g_sAutoDischarge = "Disabled" then 
          if g_bOKDischarge = True then
            DischargeScale;
          else
            SetLabelText(lbsts1, "Press Discharge Button");
            SetWidgetVisibility(iDis, VOn);
          end if;

        elsif g_sContainerPhotoeye = "Disabled" and g_sAutoDischarge = "Enabled" then 
          DischargeScale;

        end if;

      end if;

    elsif BatchMode = DelayAfterDischarge and Paused = No then
      g_iDelayCnt := g_iDelayCnt + 1;
      if g_iDelayCnt >= g_rDelayAfterDischarge * 10 then
        SetLabelText(lbsts1, "Fill Complete");
        ClearStatus(200);
        SetDigout(0, oDischarge, g_ciDigOutoff);    
        SetSymbolState(sym281,1);
        StopTimer(1);
        SetWidgetVisibility(btnSetup, VOn);
        StopTimer(2);
        SetBargraphLevel(bar277,0);
        BatchMode := Complete;
        ClearTare(CurrentScale);
        SetMode(CurrentScale, GrossMode);
        UnLockMajorKeys;
      else
        SetLabelText(lbsts1, "Delay After Discharge");
      end if;

    end if;

  end;

  handler Timer2Trip;
  unit : units;
  net : real;
  barlevel : real;
  begin

    GetUnits(CurrentScale,unit);
    GetNet(CurrentScale,unit, net);
    barlevel := (net / g_rTargetWgt);
    Barlevel := barlevel * 100.0;
    SetBargraphLevel(bar277, barlevel);

  end;

  handler Timer3Trip; --- Dosing Batching Timer
  unit : units;
  gross : real;
  iMotion : integer;
  rScaleWgt : real;
  begin

    if BatchMode = RefillCheck and g_sRefillOption = "Enabled" and Paused = No then
      GetUnits(CurrentScale,unit);
      GetGross(CurrentScale,unit,gross);
      if gross < g_rTargetWgt or gross < g_rLowWgt then
        BatchMode := RefillScale;
        SetupStartTimer(4,g_rSlowCycleTime * 100, TimerOneShot);
      else
        if g_iStop = 1 then 
          g_istop := 0;
          BatchMode := Complete;
          SetWidgetVisibility(btnSetup, VOn);
          StopTimer(3);
          UnLockMajorKeys;
          SetLabelText(lbsts1, "Batch Complete");
          ClearStatus(200);
        else
          g_iConsecutiveNbr :=  g_iConsecutiveNbr + 1; 
          BatchMode := WaitSSTare;
          SetDigout(0,oDispenseComplete, g_ciDigOutOff);
          SetDigout(0,oRefill,g_ciDigoutOff);
        end if;

      end if;

    elsif Batchmode = RefillCheck and g_sRefillOption = "Disabled" and Paused = No then
      BatchMode := WaitSSTare;
      SetDigout(0,oDispenseComplete, g_ciDigOutOff);
      SetDigout(0,oRefill,g_ciDigoutOff);

    elsif BatchMode = RefillScale and Paused = No then
      GetUnits(CurrentScale,unit);
      GetGross(CurrentScale,unit,gross);
      if gross >= g_rHighWgt then
        SetDigout(0,oRefill,g_ciDigOutOff);
        SetSymbolState(sym295, 1);
        SetLabelText(lbsts1, "Refill Complete");
        ClearStatus(250);
        StopTimer(3);
        StopTimer(4);
        BatchMode := Complete;
        SetWidgetVisibility(btnSetup, VOn);
        UnLockMajorKeys;
      else
        SetDigout(0,oRefill,g_ciDigOutOn);
        SetSymbolState(sym295,2);
        SetLabelText(lbsts1, "Refilling Scale");
      end if;

    elsif BatchMode = WaitSSTare and Paused = No then
      if g_sAutoTare = "Enabled" then  
        InMotion(CurrentScale, iMotion);                                            
        if iMotion = 0 then
          if TareScale(CurrentScale) = TRUE then
            BatchMode := FastFill;             
            SetLabelText(lbCN, IntegerToString(g_iConsecutiveNbr,0));
          else  
            SetLabelText(lbsts1, "Error: Unable to Tare Scale");     
          end if;
   
        else
          SetLabelText(lbSts1, "...In Motion..."); 
        end if; 
        
      else 
        BatchMode := FastFill;
        SetLabelText(lbCN, IntegerToString(g_iConsecutiveNbr,0));
        
      end if;  

    elsif BatchMode = FastFill and Paused = No then    
      if g_sFillingSpeeds = "Single" then        
        EnableSP(4);            
        SetLabelText(lbSts1, "Fast Dispensing");
      elsif g_sFillingSpeeds = "Parallel" then 
        EnableSP(4);
        EnableSP(5);     
        SetLabelText(lbSts1, "Fast & Slow Dispensing");
      elsif g_sFillingSpeeds = "Dual" then 
        EnableSP(4);   
        SetLabelText(lbSts1, "Fast Dispensing");
      end if;  
      SetSymbolState(sym281, 2);
      SetupStartTimer(4,g_rSlowCycleTime * 100, TimerOneShot);
      StopTimer(3);
     
    elsif BatchMode = SlowFill and Paused = No then    
      if g_sFillingSpeeds = "Single" then        
        return; 
      elsif g_sFillingSpeeds = "Parallel" then 
        EnableSP(5); 
      elsif g_sFillingSpeeds = "Dual" then
        EnableSP(5);   
      end if;  
      SetLabelText(lbSts1, "Slow Dispensing");    
      StopTimer(3);
      SetupStartTimer(4,g_rSlowCycleTime * 100, TimerOneShot);

    elsif Batchmode = WaitSSFull and Paused = No then
      InMotion(CurrentScale, iMotion);
      SetSymbolState(sym281, 1);
      StopTimer(4);
      if iMotion = 0 then 
        GetUnits(CurrentScale, Unit);
        GetNet(CurrentScale, Unit, rScaleWgt);
        GetTare(CurrentScale, unit, g_rTare);
        rScaleWgt := rScaleWgt * -1;
        g_rTotalWgt := g_rTotalWgt + rScaleWgt;
        g_iTotalCnt := g_iTotalCnt + 1;
        RefreshMainDisplay;
        StoreTransaction(rScaleWgt);
        SendTransactionMessage;
        PrintTicket;
        SetDigout(0, oDispenseComplete, g_ciDigOutOn);
        g_bOKDischarge := False; 
        BatchMode := DelayAfterDischarge; 
        g_rLastFillWgt := rScaleWgt;
        g_iDelayCnt := 0;

      else
        SetLabelText(lbSts1, "...In Motion...");  
      end if; 

    elsif BatcHMode = DelayAfterDischarge then
      g_iDelayCnt := g_iDelayCnt + 1;
      if g_iDelayCnt >= g_rDelayAfterDischarge * 10 then
        SetLabelText(lbsts1, Blank);
        ClearTare(CurrentScale);
        SetMode(CurrentScale,GrossMode);
        if g_sRefillOption = "Enabled" then
          Batchmode := RefillCheck;
          g_iStop := 1;
        else
          StopTimer(3);
          SetLabelText(lbsts1, "Batch Complete");
          BatchMode := Complete;
          Entrymode := NoMode;
          ClearStatus(200);
          SetWidgetVisibility(btnSetup, VOn);
          UnLockMajorKeys;
        end if;

      else
        SetLabelText(lbsts1, "Delay After Discharge");
      end if;

    end if; 

  end;

  handler Timer4Trip;
  begin

    StopProcess;
    SetLabelText(lbsts1, "Slow Cycle Error");

  end;

  handler Timer25Trip;  -- Wait for Standstill Timer
    iMotion : integer;
  begin
    
    if g_iWaitSSScale <> 0 then
      InMotion(g_iWaitSSScale, iMotion);
    else
      InMotion(1, iMotion);
    end if;
    
    if iMotion = 0 then
      StopTimer(25);
      DisplayStatus(Blank);  
      SetLabelText(lbSts1,  Blank);
      
    else
      SetLabelText(lbSts1, "...In Motion...");
    end if;

  end;    

  handler Timer29Trip;  -- Removes display status text  
  begin 
 
    DisplayStatus(Blank); 
    SetLabelText(lbSts1, Blank); 
    if BatchMode = Complete then
      SetLabelText(lbsts1, "Press Start to Begin");
    end if;
    
  end;    


  handler UserEntry;  -- Processing a data entry method
    sTemp : string;  
  begin   
    
    g_iPromptOpen := 0;
    sTemp := GetEntry;    
    if EventKey = EnterKey then     --Enter key pressed
      ProcessDataEntry(sTemp); 
    else                            --Cancel key pressed    
      ProcessPromptCancel;    
    end if;

  end;    
  
  handler Cmd31Handler;
  begin

    if g_iDownload = 0 then
      g_iDownload := 1;  
      g_iTmpPassword := 0;
      Ready;
    end if;
    WriteOutLn(EventConnection, "OK");

  end; 

  handler Cmd32Handler;  -- Used to change the debug code
  begin 

    if EventConnection <> Blank then
     g_sDebug := EventConnection;
    else
      g_sDebug := EventConnection;
    end if;
    WriteOutLn(EventConnection, "OK");

  end;    

  function ToggleED(Value : string) : string;
  begin

      if Value = "Enabled" then
        Value := "Disabled";
      else
        Value := "Enabled";
      end if;
      return Value;

  end;

  procedure PrintTotals;
  sUnits : string;
  begin

    sUnits := GetCurrentUnitsString(CurrentScale);
    SetPrintText(1, IntegerToString(g_iTotalCnt,0));
    SetPrintText(2, RealToString(g_rTotalWgt,0,g_iDecimal) + " " + sUnits);
    Print(AuxFmt3);
    DisplayStatus("Totals Printed");
    ClearStatus(100);

  end;

  handler WidgetClicked;
  begin

  	DisableHandler(WidgetClicked);
		g_iWidget := EventWidget;
		DisplayStatus("");

    if g_iWidget = lbSet1H or g_iWidget = lbSet1D then   
      PromptForEntry("Enter Setup Password", SetupChangePasswordMode, Blank,1);           
    elsif g_iWidget =  lbSet2H or g_iWidget = lbSet2D then
      if g_sFillingSpeeds = "Single" then
        g_sFillingSpeeds := "Dual";
      elsif g_sFillingSpeeds = "Dual" then
        g_sFillingSpeeds := "Parallel";
      elsif g_sFillingSpeeds = "Parallel" then
        g_sFillingSpeeds := "Single";
      end if;
    elsif g_iWidget = lbSet3H or g_iWidget = lbSet3D then
      if g_sOperationMode = "Gross/Net" then
        g_sOperationMode := "Dosing";
        TurnOnDosingWidgets;
      else 
        g_sOperationMode := "Gross/Net";
        TurnOffDosingWidgets;
      end if;
      RefreshSetupDisplay;
    elsif g_iWidget =  lbSet4H or g_iWidget = lbSet4D then
      GoToScreen(g_ciIOTest);
      SetupStartTimer(20,10,TimerContinuous);
    elsif g_iWidget =  lbSet5H or g_iWidget = lbSet5D then
      g_sAutoTare := ToggleED(g_sAutoTare);
      if g_sAutoTare = "Disabled" then  
        ClearTare(CurrentScale);
        SetMode(CurrentScale, GrossMode);
      end if;
    elsif g_iWidget =  lbSet6H or g_iWidget = lbSet6D then
      g_sAutoPrint := ToggleED(g_sAutoPrint);
    elsif g_iWidget =  lbSet7H or g_iWidget = lbSet7D then
      g_sTransMessage := ToggleED(g_sTransMessage);
    elsif g_iWidget = lbSet8H or g_iWidget = lbSet8D then    
      GotoScreen(g_ciClearTrans);
      EntryMode := ClearTransactions; 
      SetLabelText(lbMsg1, "Clear Transaction DB");
      SetLabelText(lbMsg2, "Are You Sure?");
    elsif g_iWidget =  lbSet9H or g_iWidget = lbSet9D then
      g_sDischarging := ToggleED(g_sDischarging);
    elsif g_iWidget =  lbSet10H or g_iWidget = lbSet10D then
      g_sAutoDischarge := ToggleED(g_sAutoDischarge);
    elsif g_iWidget =  lbSet11H or g_iWidget = lbSet11D then
      PromptForEntry("Enter Delay After Discharge", SetupDelayAfterDischargeMode, RealToString(g_rDelayAfterDischarge, 0, g_iDecimal), 2);
    elsif g_iWidget = lbSet12H or g_iWidget = lbSet12D then
      PromptForEntry("Enter Slow Cycle Time", SetupSlowCycleTime, RealToString(g_rSlowCycleTime,0,1),2);
    elsif g_iWidget =  lbSet13H or g_iWidget = lbSet13D then
      PromptForEntry("Enter Container Threshold", SetupContainerThreshold, RealToString(g_rContainerThreshold,0,g_iDecimal),2);
    elsif g_iWidget =  lbSet14H or g_iWidget = lbSet14D then
      g_sContainerPhotoeye := ToggleED(g_sContainerPhotoeye);
    elsif g_iWidget =  lbSet15H or g_iWidget = lbSet15D then
      KeyPress(databasekey);  
    elsif g_iWidget = lbSet16H or g_iWidget = lbSet16D then
      if g_sRefillOption = "Enabled" then
        g_sRefillOption := "Disabled";
      else  
        g_sRefillOption := "Enabled";
      end if;
      RefreshSetupDisplay;   
    elsif g_iWidget = btnSetup then -- Setup Menu
      if EntryMode = NoMode then  
        if g_sSetupPassword = "0" or g_sSetupPassword = Blank then
          GoIntoSetupMenu;           
        else     
          PromptForEntry("Enter Password", SetupEnterPasswordMode, Blank, 3);  
        end if;
      end if;
      
    elsif g_iWidget = btnExt2 then
      DisplayStatus(Blank);
    elsif g_iWidget = btnExt3 then
      DisplayStatus(Blank);
    elsif g_iWidget = btnExt4 then  
      DisplayStatus(Blank);
    elsif g_iWidget = btnExt6 then  
      DisplayStatus(Blank);  
      StopTimer(10); 
      EntryMode := Setup1Mode;
      GotoScreen(g_ciSetup); 
    elsif g_iWidget = btnExt10 or g_iWidget = btnExt11 then
      EntryMode := NoMode;
      GoToScreen(g_ciMain); 
    elsif g_iWidget = btnYes5 then
      if Entrymode = ClearTransactions then
        g_sysResult := TransDB.Clear;
        if g_sysresult = SysOk then
          DisplayStatus("Transaction DB Cleared");
        else
          DisplayStatus("Error: Clearing Trans DB");
        end if;
        EntryMode := Setup1Mode;
        GotoScreen(g_ciSetup);
      elsif EntryMode = ClearTotal then
        g_rTotalWgt := 0;  
        g_iTotalCnt := 0; 
        refreshMainDisplay;
        EntryMode := NoMode;
        GotoScreen(g_ciMain);  
        DisplayStatus("Total Cleared");
        ClearStatus(100);  
      end if;

    elsif g_iWidget = btnNo5 then
      if Entrymode = ClearTransactions then
        EntryMode := Setup1Mode;
        GoToScreen(g_ciSetup); 
        DisplayStatus("Cancelled by Operator");
      elsif EntryMode = ClearTotal then
        GotoScreen(g_ciMain);
        Entrymode := NoMode;
      end if;
    elsif g_iWidget >= btnDIO4 and g_iWidget <= btnDIO8 then
      ToggleOutput(g_iWidget);      
    elsif g_iWidget = btnExt7 then
      StopTimer(20);        
      TurnOffAllOutputs;
      EntryMode := Setup1Mode;
      GoToScreen(g_ciSetup); 
    elsif g_iWidget = lbTgt or g_iWidget = lbl263 then
      if batchMode = Complete and EntryMode = NoMode then 
        PromptForEntry("Enter Target Weight", EnterTargetWeight, RealToString(g_rTargetWgt,0,g_iDecimal), 2);   
      end if;

    elsif g_iWidget = lbDrib or g_iWidget = lbl265 then
      if BatchMode = Complete and EntryMode = NoMode then
        if g_sFillingSpeeds <> "Single" then
          PromptForEntry("Enter Dribble Weight", EnterDribbleWeight, RealToString(g_rDribbleWgt,0,g_iDecimal),2);
        else
          DisplayStatus("Dribble Disabled in Single Speed");
          ClearStatus(100);
        end if;

      end if;

    elsif g_iWidget = lbPre or g_iWidget = lbl267 then
      if BatchMode = Complete and EntryMode = NoMode then
        PromptForEntry("Enter Preact Weight", EnterPreactWeight, RealToString(g_rPreact,0,g_iDecimal),2);
      end if;

    elsif g_iWidget = lbZero or g_iWidget = lbl269 then
      if BatchMode = Complete and EntryMode = NoMode then
        PromptForEntry("Enter Zero Tolerance Weight", EnterZeroContWgt, RealToString(g_rZeroTolerance,0,g_iDecimal),2);
      end if;    

    elsif g_iWidget = lbCn or g_iWidget = lbl279 then
      if BatchMode = Complete and EntryMode = NoMode then
        PromptForEntry("Enter Consecutive Number", EnterConsecutiveNbr, IntegerToString(g_iConsecutiveNbr,0),2);
      end if;

    elsif g_iWidget = iPrintT then
      if BatchMode = Complete then
        PrintTotals;  
      end if;

    elsif g_iWidget = iClearT then
      GotoScreen(g_ciClearTrans);
      EntryMode := ClearTotal; 
      SetLabelText(lbmsg1, "Clear Totals");
      SetLabelText(lbMsg2, Blank);
    
    elsif g_iWidget = iDis then
      g_bOKDischarge := True;
      SetWidgetVisibility(iDis, VOff);

    elsif g_iWidget = lbLow or g_iWidget = lLow then
      if Batchmode = Complete and EntryMode = NoMode then
        PromptForEntry("Enter Low Level Weight", EnterLowLevelWgt, RealToString(g_rLowWgt,0,g_iDecimal),2);
      end if;

    elsif g_iWidget = lbHigh or g_iWidget = LHigh then
      if BatchMode = Complete and Entrymode = NoMode then
        PromptForEntry("Enter High Level Weight", EnterHighLevelWgt, RealToString(g_rHighWgt,0,g_iDecimal),2);
      end if;

    elsif g_iWidget = btnPass then
      PromptForEntry("Enter Password",EnterRandomPasswordMode,Blank,2); 

    end if;   
    RefreshSetupDisplay; 
    SetupStartTimer(22, 25, TimerOneShot);
    
  end;

begin

  DisplayVersion;  
  DisableSetpoints;
  g_sDebug := "Port12";  -- Needs to be defaulted to a port to prevent 1280 from power cycling
  Hardware(g_arHardware);
  if g_iDownload = 0 then
    g_sSetupPassword := Blank; 
    LoadDefaultVariables;
    g_rTargetWgt := 100;
    g_rDribbleWgt := 0;
    g_rPreact := 0;
    g_rZeroTolerance := 3.0;
    g_iConsecutiveNbr := 0;
    g_iDownload := 1;
    g_iTmpPassword := 0;

  end if;
  Ready; 

end PN191318; 
