DUTs

GVLs

Global_Version

{attribute 'TcGenerated'}
// This function has been automatically generated from the project information.
VAR_GLOBAL CONSTANT
    {attribute 'const_non_replaced'}
    {attribute 'linkalways'}
    stLibVersion_txi_hxr_motion : ST_LibVersion := (iMajor := 1, iMinor := 1, iBuild := 0, iRevision := 0, sVersion := '1.1.0');
END_VAR

GVL

{attribute 'qualified_only'}
VAR_GLOBAL
    {attribute 'pytmc' := 'pv: PLC:TXI:MOTION:ARB:01'}
    fbArbiter1: FB_Arbiter(1);

    // For all devices after Stopper
    {attribute 'pytmc' := 'pv: PLC:TXI:MOTION:FFO:01'}
    {attribute 'TcLinkTo' := '.q_xFastFaultOut:=TIIB[PMPS_FFO]^Channel 1^Output'}
    fbFastFaultOutput1: FB_HardwareFFOutput := (bAutoReset := TRUE, i_sNetID:='');

END_VAR

Main

{attribute 'qualified_only'}
VAR_GLOBAL
     // AL1L1-L2SI
    {attribute 'pytmc' := 'pv: AL1L1:L2SI:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[AL1L1-EL7041]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[AL1L1-EL7041]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[AL1L1-EL2004]^Channel 1^Output;
                              .nRawEncoderULINT     := TIIB[AL1L1-EL5042]^FB Inputs Channel 1^Position'}
    M1: DUT_MotionStage := (sName := 'AL1L1:L2SI:MMS');

    // IM2L1-PPM-MMS
    {attribute 'pytmc' := 'pv: IM2L1:PPM:MMS'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[IM2L1-EL7041]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[IM2L1-EL7041]^STM Status^Status^Digital input 2;
                              .bBrakeRelease        := TIIB[IM2L1-EL2004]^Channel 1^Output'}
    M2: DUT_MotionStage := (sName := 'IM2L1:PPM:MMS');

    //SL3L1-SCATTER: 4 Axes
    {attribute 'pytmc' := 'pv: SL3L1:SCATTER:MMS:BOTTOM'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L1-EL7031-E1]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL3L1-EL7031-E1]^STM Status^Status^Digital input 1;
                              .nRawEncoderUINT      := TIIB[SL3L1-EL5101-E2]^ENC Status compact^Counter value'}
    M3: DUT_MotionStage := (sName := 'SL3L1:SCATTER:MMS:BOTTOM');
    {attribute 'pytmc' := 'pv: SL3L1:SCATTER:MMS:TOP'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L1-EL7031-E3]^STM Status^Status^Digital input 2;
                              .bLimitBackwardEnable := TIIB[SL3L1-EL7031-E3]^STM Status^Status^Digital input 1;
                              .nRawEncoderUINT      := TIIB[SL3L1-EL5101-E4]^ENC Status compact^Counter value'}
    M4: DUT_MotionStage := (sName := 'SL3L1:SCATTER:MMS:TOP');
    {attribute 'pytmc' := 'pv: SL3L1:SCATTER:MMS:NORTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L1-EL7031-E5]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L1-EL7031-E5]^STM Status^Status^Digital input 2;
                              .nRawEncoderUINT      := TIIB[SL3L1-EL5101-E6]^ENC Status compact^Counter value'}
    M5: DUT_MotionStage := (sName := 'SL3L1:SCATTER:MMS:NORTH');
    {attribute 'pytmc' := 'pv: SL3L1:SCATTER:MMS:SOUTH'}
    {attribute 'TcLinkTo' := '.bLimitForwardEnable  := TIIB[SL3L1-EL7031-E7]^STM Status^Status^Digital input 1;
                              .bLimitBackwardEnable := TIIB[SL3L1-EL7031-E7]^STM Status^Status^Digital input 2;
                              .nRawEncoderUINT      := TIIB[SL3L1-EL5101-E8]^ENC Status compact^Counter value'}
    M6: DUT_MotionStage := (sName := 'SL3L1:SCATTER:MMS:SOUTH');
END_VAR

POUs

FB_SLITS

FUNCTION_BLOCK FB_SLITS
VAR_IN_OUT
    stTopBlade: DUT_MotionStage;
    stBottomBlade: DUT_MotionStage;
    stNorthBlade: DUT_MotionStage;
    stSouthBlade: DUT_MotionStage;
    bExecuteMotion:BOOL ;
    io_fbFFHWO    :    FB_HardwareFFOutput;
    fbArbiter: FB_Arbiter();
END_VAR

VAR_INPUT

    {attribute 'pytmc' := '
    pv: PMPS_OK;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bMoveOk:BOOL;

        (*Offsets*)
    {attribute 'pytmc' := '
    pv: Offset_Top;
    io: io;
    '}
    rEncoderOffsetTop: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_Bottom;
    io: io;
    '}
    rEncoderOffsetBottom: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_North;
    io: io;
    '}
    rEncoderOffsetNorth: REAL;
    {attribute 'pytmc' := '
    pv: ZeroOffset_South;
    io: io;
    '}
    rEncoderOffsetSouth: REAL;
    i_DevName : STRING; //device name for FFO and PMPS diagnostics
     {attribute 'pytmc' := '
    pv: Home;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bHome:BOOL:=FALSE;
END_VAR

VAR
    fbTopBlade: FB_MotionStage;
    fbBottomBlade: FB_MotionStage;
    fbNorthBlade: FB_MotionStage;
    fbSouthBlade: FB_MotionStage;
    fPosTopBlade: LREAL;
    fPosBottomBlade: LREAL;
    fPosNorthBlade: LREAL;
    fPosSouthBlade: LREAL;

    (*Motion Parameters*)
    fSmallDelta: LREAL := 0.01;
    fBigDelta: LREAL := 10;
    fMaxVelocity: LREAL := 0.2;
    fHighAccel: LREAL := 0.8;
    fLowAccel: LREAL := 0.1;

    stTop: DUT_PositionState;
    stBOTTOM: DUT_PositionState;
    stNorth: DUT_PositionState;
    stSouth: DUT_PositionState;

    {attribute 'pytmc' := 'pv: TOP'}
    fbTop: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: BOTTOM'}
    fbBottom: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: NORTH'}
    fbNorth: FB_StatePTPMove;
    {attribute 'pytmc' := 'pv: SOUTH'}
    fbSouth: FB_StatePTPMove;

    (*EPICS pvs*)
    {attribute 'pytmc' := '
    pv: XWID_REQ;
    io: io;
    '}
    rReqApertureSizeX : REAL;
    {attribute 'pytmc' := '
    pv: YWID_REQ;
    io: io;
    '}
    rReqApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: XCEN_REQ;
    io: io;
    '}
    rReqCenterX: REAL;
    {attribute 'pytmc' := '
    pv: YCEN_REQ;
    io: io;
    '}
    rReqCenterY: REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_XWIDTH;
    io: io;
    '}
    rActApertureSizeX : REAL;

    {attribute 'pytmc' := '
    pv: ACTUAL_YWIDTH;
    io: io;
    '}
    rActApertureSizeY : REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_XCENTER;
    io: io;
    '}
    rActCenterX: REAL;
    {attribute 'pytmc' := '
    pv: ACTUAL_YCENTER;
    io: io;
    '}
    rActCenterY: REAL;

    {attribute 'pytmc' := '
    pv: XCEN_SETZERO;
    io: io;
    '}
    rSetCenterX: BOOL;
    {attribute 'pytmc' := '
    pv: YCEN_SETZERO;
    io: io;
    '}
    rSetCenterY: BOOL;


    {attribute 'pytmc' := '
    pv: OPEN;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bOpen: BOOL;

    {attribute 'pytmc' := '
    pv: CLOSE;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bClose: BOOL;

    {attribute 'pytmc' := '
    pv: BLOCK;
    io: io;
    field: ZNAM False
    field: ONAM True
    '}
    bBlock: BOOL;


     {attribute 'pytmc' := '
    pv: HOME_READY;
    io: i;
    field: ZNAM False
    field: ONAM True
    '}
    bHomeReady:BOOL:=FALSE;


        //Local variables
    bInit: BOOL :=true;
    rTrig_Block: R_TRIG;
    rTrig_Open: R_TRIG;
    rTrig_Close: R_TRIG;

    //old values
    rOldReqApertureSizeX : REAL;
    rOldReqApertureSizeY : REAL;
    rOldReqCenterX: REAL;
    rOldReqCenterY: REAL;

    bExecuteMotionX: BOOL;
    bExecuteMotionY: BOOL;


    fPosBlock: LREAL;
    fPosClose: LREAL;
    fPosOpen: LREAL;

    stSetPositionOptions:ST_SetPositionOptions;
    fbSetPosition_TOP: MC_SetPosition;
    fbSetPosition_Bottom: MC_SetPosition;
    fbSetPosition_North: MC_SetPosition;
    fbSetPosition_South: MC_SetPosition;

    // For logging
    fbLogger : FB_LogMessage := (eSubsystem:=E_SubSystem.MOTION);
    tErrorPresent : R_TRIG;
    tAction : R_TRIG;
    tOverrideActivated : R_TRIG;

    FFO    :    FB_FastFault :=(
        i_DevName := 'Slits',
        i_Desc := 'Fault occurs when center is greated than that requested',
        i_TypeCode := 16#1010);


    bTest: BOOL;

    AptArrayStatus AT %Q* : ST_PMPS_Aperture_IO;
    AptArrayReq AT %I* : ST_PMPS_Aperture_IO;

END_VAR
ACT_init();

// Instantiate Function block for all the blades
ACT_Motion();
//SET and GET the requested and Actual values
ACT_CalculatePositions();
//ACT_BLOCK();

END_FUNCTION_BLOCK

ACTION ACT_BLOCK:
rTrig_Block (CLK:= bBlock);
rTrig_Open (CLK:= bOpen);
rTrig_Close (CLK:= bClose);

if (rTrig_Block.Q) THEN
    //BLOCK

    bBlock := false;
END_IF

if (rTrig_Open.Q) THEN


    bOpen := false;
END_IF

if (rTrig_Close.Q) THEN


    bClose := false;
END_IF
END_ACTION

ACTION ACT_CalculatePositions:
//check if requested center or gap has changed
//check that the requested values are within acceptable motion range
IF (rOldReqApertureSizeX <> rReqApertureSizeX) THEN
        rOldReqApertureSizeX := rReqApertureSizeX;
        bExecuteMotionX := TRUE;
        fbLogger(sMsg:='Requested new X gap.', eSevr:=TcEventSeverity.Verbose);
END_IF

IF (rOldReqCenterX <> rReqCenterX) THEN
    rOldReqCenterX := rReqCenterX;
    bExecuteMotionX := TRUE;
    fbLogger(sMsg:='Requested new X center', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterX := rActCenterX;
END_IF

IF (rOldReqApertureSizeY <> rReqApertureSizeY) THEN
        rOldReqApertureSizeY := rReqApertureSizeY;
        bExecuteMotionY := TRUE;
        fbLogger(sMsg:='Requested new Y gap.', eSevr:=TcEventSeverity.Verbose);

END_IF

IF (rOldReqCenterY <> rReqCenterY) THEN
    rOldReqCenterY := rReqCenterY;
    bExecuteMotionY := TRUE;
    fbLogger(sMsg:='Requested new Y center.', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterY := rActCenterY;
END_IF


//Calculate requested target positions from requested gap and center
fPosTopBlade := (rReqApertureSizeY/2) + (rReqCenterY + rEncoderOffsetTop) ;
fPosBottomBlade := (-1*rReqApertureSizeY/2) + (rReqCenterY+rEncoderOffsetBottom);

fPosNorthBlade := (rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetNorth);
fPosSouthBlade := (-1*rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetSouth);


//Calculate actual gap and center from actual stages positions
rActApertureSizeX := LREAL_TO_REAL((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth) - (stSouthBlade.stAxisStatus.fActPosition- rEncoderOffsetSouth));

rActApertureSizeY := LREAL_TO_REAL((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) - (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom));

rActCenterX := LREAL_TO_REAL((((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth)  + (stSouthBlade.stAxisStatus.fActPosition - rEncoderOffsetSouth ))/2));

rActCenterY := LREAL_TO_REAL((((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) + (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom))/2));



//Update PMPS Arbiter with the Actual Size and Center of the Aperture
END_ACTION

ACTION ACT_Home:

END_ACTION

ACTION ACT_Init:
//  init the motion stages parameters
IF ( bInit) THEN
    stTopBlade.bHardwareEnable := TRUE;
    stBottomBlade.bHardwareEnable := TRUE;
    stNorthBlade.bHardwareEnable := TRUE;
    stSouthBlade.bHardwareEnable := TRUE;
    stTopBlade.bPowerSelf :=TRUE;
    stBottomBlade.bPowerSelf :=TRUE;
    stNorthBlade.bPowerSelf :=TRUE;
    stSouthBlade.bPowerSelf :=TRUE;
    stTopBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stBottomBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stNorthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    stSouthBlade.nBrakeMode := ENUM_StageBrakeMode.NO_BRAKE;
    FFO.i_DevName := i_DevName;
END_IF
END_ACTION

ACTION ACT_Motion:
// Instantiate Function block for all the blades
fbTopBlade(stMotionStage:=stTopBlade);
fbBottomBlade(stMotionStage:=stBottomBlade);
fbNorthBlade(stMotionStage:=stNorthBlade);
fbSouthBlade(stMotionStage:=stSouthBlade);

// PTP Motion for each blade
stTop.sName := 'Top';
stTop.fPosition := fPosTopBlade;
stTop.fDelta := fSmallDelta;
stTop.fVelocity := fMaxVelocity;
stTop.fAccel := fHighAccel;
stTop.fDecel := fHighAccel;

stBOTTOM.sName := 'Bottom';
stBOTTOM.fPosition := fPosBottomBlade;
stBOTTOM.fDelta := fSmallDelta;
stBOTTOM.fVelocity := fMaxVelocity;
stBOTTOM.fAccel := fHighAccel;
stBOTTOM.fDecel := fHighAccel;

stNorth.sName := 'North';
stNorth.fPosition := fPosNorthBlade;
stNorth.fDelta := fSmallDelta;
stNorth.fVelocity := fMaxVelocity;
stNorth.fAccel := fHighAccel;
stNorth.fDecel := fHighAccel;

stSouth.sName := 'South';
stSouth.fPosition := fPosSouthBlade;
stSouth.fDelta := fSmallDelta;
stSouth.fVelocity := fMaxVelocity;
stSouth.fAccel := fHighAccel;
stSouth.fDecel := fHighAccel;

IF (bExecuteMotionY) THEN
    fbTop.bExecute := fbBottom.bExecute := bExecuteMotionY;
    bExecuteMotionY:= FALSE;
END_IF

IF (bExecuteMotionX) THEN
    fbNorth.bExecute := fbSouth.bExecute := bExecuteMotionX;
    bExecuteMotionX:= FALSE;
END_IF


fbTop(
    stPositionState:=stTop,
    bMoveOk:=bMoveOk,
    stMotionStage:=stTopBlade);

fbBottom(
    stPositionState:=stBOTTOM,
    bMoveOk:=bMoveOk,
    stMotionStage:=stBottomBlade);

fbNorth(
    stPositionState:=stNorth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stNorthBlade);

fbSouth(
    stPositionState:=stSouth,
    bMoveOk:=bMoveOk,
    stMotionStage:=stSouthBlade);
END_ACTION

ACTION ACT_Zero:
//ZERO BIAS

// Set Y center to zero

// Set X center to zero
(*
if (rSetCenterY)THEN
        rSetCenterY := false;
        // Set Current Position
        fbSetPosition_TOP.Position :=  stTopBlade.stAxisStatus.fActPosition - rActCenterY ;
        fbSetPosition_TOP.Execute := TRUE;
        fbSetPosition_Bottom.Position := stBottomBlade.stAxisStatus.fActPosition - rActCenterY;
        fbSetPosition_Bottom.Execute := TRUE;
END_IF

if (rSetCenterX)THEN
        rSetCenterX := false;
        // Set Current Position
        fbSetPosition_North.Position := stNorthBlade.stAxisStatus.fActPosition - rActCenterX ;
        fbSetPosition_North.Execute := TRUE;
        fbSetPosition_South.Position := stSouthBlade.stAxisStatus.fActPosition - rActCenterX ; ;
        fbSetPosition_South.Execute := TRUE;
END_IF


//Reset
if (fbSetPosition_TOP.Done ) THEN
    fbSetPosition_TOP.Execute := FALSE;
END_IF
if (fbSetPosition_Bottom.Done ) THEN
    fbSetPosition_Bottom.Execute := FALSE;
END_IF
if (fbSetPosition_North.Done ) THEN
    fbSetPosition_North.Execute := FALSE;
END_IF
if (fbSetPosition_South.Done ) THEN
    fbSetPosition_South.Execute := FALSE;
END_IF

// Set Encoder Position
//Clear position lag error
stSetPositionOptions.ClearPositionLag := TRUE;
fbSetPosition_TOP(
    Axis:=  stTopBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_Bottom(
    Axis:= stBottomBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_North(
    Axis:= stNorthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );
fbSetPosition_South(
    Axis:= stSouthBlade.Axis ,
    Execute:= ,
    Position:= 0 ,
    Mode:= FALSE,
    Options:= stSetPositionOptions,
    Done=> ,
    Busy=> ,
    Error=> ,
    ErrorID=> );

    *)
END_ACTION

METHOD M_CheckPMPS : BOOL
VAR_INPUT
     index: int;
END_VAR
IF(rActApertureSizeX < (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Width)+0.001)
    OR (rActApertureSizeY < (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Height)+0.001) THEN
        FFO.i_xOK := FALSE;
    ELSE
        FFO.i_xOK := TRUE;
END_IF

(*FAST FAULT*)
FFO(i_xOK := ,
    i_xReset := ,
    i_xAutoReset :=TRUE,
    io_fbFFHWO := this^.io_fbFFHWO);
END_METHOD

METHOD M_UpdatePMPS : BOOL
VAR_INPUT
    index: int;
END_VAR
//Keep updating the status of the apertures PMPS
This^.AptArrayStatus.Height := This^.rActApertureSizeY;
This^.AptArrayStatus.Width := This^.rActApertureSizeX;
This^.AptArrayStatus.xOK := NOT (This^.stTopBlade.bError) AND NOT (This^.stBottomBlade.bError)
                                 AND NOT (This^.stNorthBlade.bError) AND NOT (This^.stNorthBlade.bError);

//Evaluate that the current center on the X and the y direction didn't exceed limits
//Fast fault when it does.
IF(rActCenterX > (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Width/2))
    OR (rActCenterY > (PMPS_GVL.stCurrentBeamParameters.astApertures[index].Height/2)) THEN
        FFO.i_xOK := FALSE;
    ELSE
        FFO.i_xOK := TRUE;
END_IF

//Evaluate that the requested gaps on the X and the y direction is not larger than the current gap
// narrow  the gap if the requested is larger
IF(bTest) THEN
    IF (This^.rActApertureSizeX > AptArrayReq.Width) THEN
        rReqApertureSizeX := AptArrayReq.Width;
    END_IF
    IF (This^.rActApertureSizeY > AptArrayReq.Height) THEN
         rReqApertureSizeY := AptArrayReq.Height;
    END_IF
END_IF


(*FAST FAULT*)
FFO(i_xOK := ,
    i_xReset := ,
    i_xAutoReset :=TRUE,
    io_fbFFHWO := io_fbFFHWO);
END_METHOD

FB_SLITS_POWER

FUNCTION_BLOCK FB_SLITS_POWER EXTENDS FB_SLITS
VAR_INPUT
END_VAR
VAR
     {attribute 'pytmc' := '
        pv: FSW
    '}
    fbFlowSwitch: FB_XTES_Flowswitch;



    //RTDs
    {attribute 'pytmc' := '
        pv: TOP:RTD:01
    '}
    RTD_TOP_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: TOP:RTD:02
    '}
    RTD_TOP_2: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:01
    '}
    RTD_Bottom_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: BOTTOM:RTD:02
    '}
    RTD_Bottom_2: FB_TempSensor;

    {attribute 'pytmc' := '
        pv: NORTH:RTD:01
    '}
    RTD_North_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: NORTH:RTD:02
    '}
    RTD_North_2: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:01
    '}
    RTD_South_1: FB_TempSensor;
    {attribute 'pytmc' := '
        pv: SOUTH:RTD:02
    '}
    RTD_South_2: FB_TempSensor;



END_VAR
ACT_RTDs();

END_FUNCTION_BLOCK

ACTION ACT_CalculatePositions:
//check if requested center or gap has changed
//check that the requested values are within acceptable motion range
IF (rOldReqApertureSizeX <> rReqApertureSizeX) THEN
    IF (rReqApertureSizeX <= AptArrayReq.Width)  THEN
        rOldReqApertureSizeX := rReqApertureSizeX;
        bExecuteMotionX := TRUE;
        fbLogger(sMsg:='Requested new X gap.', eSevr:=TcEventSeverity.Verbose);
    ELSE
        fbLogger(sMsg:='Requested new X gap is larger than PMPS request.', eSevr:=TcEventSeverity.Verbose);
    END_IF
  //  ELSE
    //    rReqApertureSizeX := rActApertureSizeX;
END_IF

IF (rOldReqCenterX <> rReqCenterX) THEN
    rOldReqCenterX := rReqCenterX;
    bExecuteMotionX := TRUE;
    fbLogger(sMsg:='Requested new X center', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterX := rActCenterX;
END_IF

IF (rOldReqApertureSizeY <> rReqApertureSizeY) THEN
    IF rReqApertureSizeY <= AptArrayReq.Height THEN
        rOldReqApertureSizeY := rReqApertureSizeY;
        bExecuteMotionY := TRUE;
        fbLogger(sMsg:='Requested new Y gap.', eSevr:=TcEventSeverity.Verbose);
    ELSE
        fbLogger(sMsg:='Requested new Y gap is larger than PMPS request.', eSevr:=TcEventSeverity.Verbose);
    END_IF
   // ELSE
       // rReqApertureSizeY := rActApertureSizeY;
END_IF

IF (rOldReqCenterY <> rReqCenterY) THEN
    rOldReqCenterY := rReqCenterY;
    bExecuteMotionY := TRUE;
    fbLogger(sMsg:='Requested new Y center.', eSevr:=TcEventSeverity.Verbose);
   // ELSE
      //  rReqCenterY := rActCenterY;
END_IF


//Calculate requested target positions from requested gap and center
fPosTopBlade := (rReqApertureSizeY/2) + (rReqCenterY + rEncoderOffsetTop) ;
fPosBottomBlade := (-1*rReqApertureSizeY/2) + (rReqCenterY+rEncoderOffsetBottom);

fPosNorthBlade := (rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetNorth);
fPosSouthBlade := (-1*rReqApertureSizeX/2) + (rReqCenterX + rEncoderOffsetSouth);


//Calculate actual gap and center from actual stages positions
rActApertureSizeX := LREAL_TO_REAL((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth) - (stSouthBlade.stAxisStatus.fActPosition- rEncoderOffsetSouth));

rActApertureSizeY := LREAL_TO_REAL((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) - (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom));

rActCenterX := LREAL_TO_REAL((((stNorthBlade.stAxisStatus.fActPosition - rEncoderOffsetNorth)  + (stSouthBlade.stAxisStatus.fActPosition - rEncoderOffsetSouth ))/2));

rActCenterY := LREAL_TO_REAL((((stTopBlade.stAxisStatus.fActPosition - rEncoderOffsetTop) + (stBottomBlade.stAxisStatus.fActPosition - rEncoderOffsetBottom))/2));



//Update PMPS Arbiter with the Actual Size and Center of the Aperture
END_ACTION

ACTION ACT_RTDs:
////RTDs
RTD_TOP_1();
RTD_TOP_2();
RTD_Bottom_1();
RTD_Bottom_2();
RTD_North_1();
RTD_North_2();
RTD_South_1();
RTD_South_2();

//Flow Switch
fbFlowSwitch();
END_ACTION
Related:

FB_SLITS_SCATTER

FUNCTION_BLOCK FB_SLITS_SCATTER EXTENDS FB_SLITS
VAR_INPUT
END_VAR
VAR



END_VAR


END_FUNCTION_BLOCK
Related:

PRG_01_PLCTASK

PROGRAM PRG_01_PLCTASK
VAR
    fbLogHandler: FB_LogHandler;
END_VAR
PRG_AL1L1_L2SI();
PRG_IM2L1_PPM();
PRG_SL3L1_SCATTER();
PRG_TXI_PM();
PRG_PMPS();
fbLogHandler();

END_PROGRAM
Related:

PRG_AL1L1_L2SI

PROGRAM PRG_AL1L1_L2SI
VAR
    {attribute 'pytmc' := '
        pv: AL1L1:L2SI
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbLaser.iLaserINT := TIIB[AL1L1-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbLaser.iShutdownINT := TIIB[AL1L1-EL4004]^AO Outputs Channel 2^Analog output'}
    fbAL1L1: FB_REF;
END_VAR
//fbAL1L1.nTransitionAssertionID := 16#6120;
//fbAL1L1.nUnknownAssertionID := 16#6129;

fbAL1L1.stOut.fPosition := -38.0; // Upper limit
fbAL1L1.stOut.bUseRawCounts := FALSE;
//fbAL1L1.stOut.nRequestAssertionID := 16#6121;
//fbAL1L1.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
fbAL1L1.stOut.bValid := TRUE;

fbAL1L1.stIn.fPosition := -90.0; // Current position at time of edit
fbAL1L1.stIn.bUseRawCounts := FALSE;
//fbAL1L1.stIn.nRequestAssertionID := 16#6122;
//fbAL1L1.stIn.stBeamParams := PMPS_GVL.cst0RateBeam;
fbAL1L1.stIn.bValid := TRUE;


fbAL1L1(
    stYStage := Main.M1,
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1);

END_PROGRAM
Related:

PRG_IM2L1_PPM

PROGRAM PRG_IM2L1_PPM
VAR
        {attribute 'pytmc' := '
        pv: IM2L1:PPM
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbGige.iIlluminatorINT := TIIB[IM2L1-EL4004]^AO Outputs Channel 1^Analog output;
                              .fbGige.bGigePower := TIIB[IM2L1-EL2004]^Channel 3^Output;
                              .fbPowerMeter.iVoltageINT := TIIB[IM2L1-EL3062]^AI Standard Channel 1^Value;
                              .fbPowerMeter.fbThermoCouple.bError := TIIB[IM2L1-EL3314]^TC Inputs Channel 1^Status^Error;
                              .fbPowerMeter.fbThermoCouple.bUnderrange := TIIB[IM2L1-EL3314]^TC Inputs Channel 1^Status^Underrange;
                              .fbPowerMeter.fbThermoCouple.bOverrange := TIIB[IM2L1-EL3314]^TC Inputs Channel 1^Status^Overrange;
                              .fbPowerMeter.fbThermoCouple.iRaw := TIIB[IM2L1-EL3314]^TC Inputs Channel 1^Value;
                              .fbYagThermoCouple.bError := TIIB[IM2L1-EL3314]^TC Inputs Channel 2^Status^Error;
                              .fbYagThermoCouple.bUnderrange := TIIB[IM2L1-EL3314]^TC Inputs Channel 2^Status^Underrange;
                              .fbYagThermoCouple.bOverrange := TIIB[IM2L1-EL3314]^TC Inputs Channel 2^Status^Overrange;
                              .fbYagThermoCouple.iRaw := TIIB[IM2L1-EL3314]^TC Inputs Channel 2^Value'}
    fbIM2L1: FB_PPM;

END_VAR
fbIM2L1.nTransitionAssertionID := 16#2210;
fbIM2L1.nUnknownAssertionID := 16#2219;

fbIM2L1.stOut.fPosition := -8.82;
fbIM2L1.stOut.bUseRawCounts := FALSE;
fbIM2L1.stOut.nRequestAssertionID := 16#2211;
fbIM2L1.stOut.stBeamParams := PMPS_GVL.cstFullBeam;
fbIM2L1.stOut.bValid := TRUE;

fbIM2L1.stPower.fPosition := -47.92;
fbIM2L1.stPower.bUseRawCounts := FALSE;
fbIM2L1.stPower.nRequestAssertionID := 16#2212;
fbIM2L1.stPower.stBeamParams := PMPS_GVL.cstFullBeam;
fbIM2L1.stPower.bValid := TRUE;

fbIM2L1.stYag1.fPosition := -71.92;
fbIM2L1.stYag1.bUseRawCounts := FALSE;
fbIM2L1.stYag1.nRequestAssertionID := 16#2213;
fbIM2L1.stYag1.stBeamParams := PMPS_GVL.cstFullBeam;
fbIM2L1.stYag1.bValid := TRUE;

fbIM2L1.stYag2.fPosition := -94.92;
fbIM2L1.stYag2.bUseRawCounts := FALSE;
fbIM2L1.stYag2.nRequestAssertionID := 16#2214;
fbIM2L1.stYag2.stBeamParams := PMPS_GVL.cstFullBeam;
fbIM2L1.stYag2.bValid := TRUE;

fbIM2L1(
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := Main.M2);

END_PROGRAM
Related:

PRG_PMPS

PROGRAM PRG_PMPS
VAR
    fbArbiterIO: FB_SubSysToArbiter_IO;
END_VAR
GVL.fbFastFaultOutput1.Execute(i_xVeto := PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.ST1L1]);
fbArbiterIO(
    i_bVeto := PMPS_GVL.stCurrentBeamParameters.aVetoDevices[PMPS.L_Stopper.ST1L1],
    Arbiter:=GVL.fbArbiter1,
    fbFFHWO:=GVL.fbFastFaultOutput1);

END_PROGRAM
Related:

PRG_SL3L1_SCATTER

PROGRAM PRG_SL3L1_SCATTER
VAR
    {attribute 'pytmc' := '
        pv: SL3L1:SCATTER
        io: io
    '}
    fbSL3L1: FB_SLITS;
    //GET PMPS Move Ok bit
    // Default True until it is properly linked to PMPS bit
    bMoveOk:BOOL :=TRUE;
    {attribute 'pytmc' := '
    pv: SL3L1:SCATTER:GO;
    io: io;
    field: ZNAM False;
    field: ONAM True;
    '}
    bExecuteMotion :BOOL :=FALSE;
    bTest:BOOL:=FALSE;
    //for testing purposes only. comment-out/delete once done.
    mcPower : ARRAY [1..4] OF MC_POWER;


    (*Offsets*)
    (* Absolute encoder value at the HLS + Absolure eoncoder value at the centered beam *)
    rEncoderOffsetTop: REAL := -15; (* 0+(-15)*)
    rEncoderOffsetBottom: REAL := -15; (* 0+(-15)*)
    rEncoderOffsetNorth: REAL := -15;(* 0+(-15)*)
    rEncoderOffsetSouth: REAL := -15;(* 0+(-15)*)

END_VAR
fbSL3L1.bMoveOk := bMoveOk;

//for testing purposes only. comment-out/delete once done.
If (bTest) THEN
mcPower[1](axis:=Main.M3.Axis, Enable:=bTest, enable_positive:=Main.M3.bLimitForwardEnable, enable_negative:=Main.M3.bLimitBackwardEnable);
mcPower[2](axis:=Main.M4.Axis, Enable:=bTest, enable_positive:=Main.M4.bLimitForwardEnable, enable_negative:=Main.M4.bLimitBackwardEnable);
mcPower[3](axis:=Main.M5.Axis, Enable:=bTest, enable_positive:=Main.M5.bLimitForwardEnable, enable_negative:=Main.M5.bLimitBackwardEnable);
mcPower[4](axis:=Main.M6.Axis, Enable:=bTest, enable_positive:=Main.M6.bLimitForwardEnable, enable_negative:=Main.M6.bLimitBackwardEnable);
ELSE

//Homing routine parameters
Main.M4.fHomePosition:= 0;
Main.M3.fHomePosition:= -30.6;
Main.M5.fHomePosition:= 0;
Main.M6.fHomePosition:= -30.51;

Main.M4.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
Main.M3.nHomingMode := ENUM_EpicsHomeCmd.LOW_LIMIT;
Main.M5.nHomingMode := ENUM_EpicsHomeCmd.HIGH_LIMIT;
Main.M6.nHomingMode := ENUM_EpicsHomeCmd.LOW_LIMIT;


fbSL3L1.rEncoderOffsetTop := rEncoderOffsetTop;
fbSL3L1.rEncoderOffsetBottom := rEncoderOffsetBottom;
fbSL3L1.rEncoderOffsetNorth := rEncoderOffsetNorth;
fbSL3L1.rEncoderOffsetSouth := rEncoderOffsetSouth;

fbSL3L1(stTopBlade:=  Main.M4,
        stBottomBlade:= Main.M3,
        stNorthBlade:=  Main.M5,
        stSouthBlade:=  Main.M6,
        bExecuteMotion:=bExecuteMotion,
        io_fbFFHWO := GVL.fbFastFaultOutput1,
        fbArbiter := GVL.fbArbiter1);

//fbSL3L1.M_CheckPMPS(2);

END_IF

END_PROGRAM
Related:

PRG_TXI_PM

PROGRAM PRG_TXI_PM
VAR
    {attribute 'pytmc' := '
        pv: TXI:PPM:01
        io: io
    '}
    {attribute 'TcLinkTo' := '.fbPowerMeter.iVoltageINT := TIID^Device 1 (EtherCAT)^TXI Power Meter (EK1100)^PM-EL3064^AI Standard Channel 1^Value'}
    fbTXIPM: FB_PPM;
    dumbymotor : DUT_MotionStage;

END_VAR
fbTXIPM(
    fbArbiter := GVL.fbArbiter1,
    fbFFHWO := GVL.fbFastFaultOutput1,
    stYStage := dumbymotor);

END_PROGRAM
Related: