etisserant@0: FUNCTION_BLOCK STACK_INT etisserant@0: VAR_INPUT PUSH, POP: BOOL R_EDGE; (* Basic stack operations *) etisserant@0: R1 : BOOL ; (* Over-riding reset *) etisserant@0: IN : INT ; (* Input to be pushed *) etisserant@0: N : INT ; (* Maximum depth after reset *) etisserant@0: END_VAR etisserant@0: VAR_OUTPUT EMPTY : BOOL := 1 ; (* Stack empty *) etisserant@0: OFLO : BOOL := 0 ; (* Stack overflow *) etisserant@0: OUT : INT := 0 ; (* Top of stack data *) etisserant@0: END_VAR etisserant@0: VAR STK : ARRAY[0..127] OF INT; (* Internal stack *) etisserant@0: NI : INT :=128 ; (* Storage for N upon reset *) etisserant@0: PTR : INT := -1 ; (* Stack pointer *) etisserant@0: END_VAR etisserant@0: (* Function Block body *) etisserant@0: LD R1 (* Dispatch on operations *) etisserant@0: JMPC RESET etisserant@0: LD POP etisserant@0: ANDN EMPTY (* Don't pop empty stack *) etisserant@0: JMPC POP_STK etisserant@0: LD PUSH etisserant@0: ANDN OFLO (* Don't push overflowed stack *) etisserant@0: JMPC PUSH_STK etisserant@0: RET (* Return if no operations active *) etisserant@0: RESET: LD 0 (* Stack reset operations *) etisserant@0: ST OFLO etisserant@0: LD 1 etisserant@0: ST EMPTY etisserant@0: LD -1 etisserant@0: ST PTR etisserant@0: CAL LIMIT(MN:=1,IN:=N,MX:=128) etisserant@0: ST NI etisserant@0: JMP ZRO_OUT etisserant@0: POP_STK: LD 0 etisserant@0: ST OFLO (* Popped stack is not overflowing *) etisserant@0: LD PTR etisserant@0: SUB 1 etisserant@0: ST PTR etisserant@0: LT 0 (* Empty when PTR < 0 *) etisserant@0: ST EMPTY etisserant@0: JMPC ZRO_OUT etisserant@0: LD STK[PTR] etisserant@0: JMP SET_OUT etisserant@0: PUSH_STK: LD 0 etisserant@0: ST EMPTY (* Pushed stack is not empty *) etisserant@0: LD PTR etisserant@0: ADD 1 etisserant@0: ST PTR etisserant@0: EQ NI (* Overflow when PTR = NI *) etisserant@0: ST OFLO etisserant@0: JMPC ZRO_OUT etisserant@0: LD IN etisserant@0: ST STK[PTR] (* Push IN onto STK *) etisserant@0: JMP SET_OUT etisserant@0: ZRO_OUT: LD 0 (* OUT=0 for EMPTY or OFLO *) etisserant@0: SET_OUT: ST OUT etisserant@0: etisserant@0: END_FUNCTION_BLOCK