Standard Function Blocks¶
This public entry covers shipped bistables, edge detectors, counters, and
timers such as SR, R_TRIG, CTU, TON, and TOF.
Use the full spec below when you need exact signatures, runtime/statefulness boundaries, or documented timer/counter deviations.
Key counter/timer families documented here include CTU, CTD, CTUD, TP,
TON, and TOF.
Related: Standard Functions, Runtime
Standard Function Blocks¶
IEC 61131-3 Edition 3.0 (2013) - Section 6.6.3.5
This specification defines standard function blocks for trust-hir.
1. Overview¶
Standard function blocks are predefined FBs with internal state. They require instantiation and maintain state between calls.
FB Index¶
| Name / Group | Category | Signature Shape | IEC ref | trust-hir | trust-runtime | Deviations |
|---|---|---|---|---|---|---|
SR, RS |
Bistable | fixed BOOL inputs/outputs | Table 43 | signature only | full stateful behavior | none |
R_TRIG, F_TRIG |
Edge detection | fixed BOOL inputs/outputs | Table 44 | signature only | full stateful behavior | none |
CTU, CTD, CTUD |
Counters | fixed or overloaded counter types | Table 45 | signature only | full stateful behavior | CTUD LD profile in docs/IEC_DEVIATIONS.md |
TP, TON, TOF and *_LTIME variants |
Timers | fixed TIME/LTIME signatures | Table 46 | signature only | full stateful behavior | TP/TOF ET exposure in docs/IEC_DEVIATIONS.md |
Common Characteristics¶
- Must be instantiated to use
- Internal variables persist between calls
- Can be overloaded for different data types
- Have standard timing/edge detection behaviors
Deviation Cross-References¶
- Counter/timer runtime deviations are recorded in
docs/IEC_DEVIATIONS.md. trust-hirowns static signatures only; runtime execution owns the stateful behavior described below.
2. Bistable Function Blocks (Table 43)¶
SR - Set Dominant Bistable¶
+-----+
| SR |
BOOL---|S1 Q1|---BOOL
BOOL---|R |
+-----+
| Input | Description |
|---|---|
| S1 | Set (dominant) |
| R | Reset |
| Output | Description |
|---|---|
| Q1 | Output state |
Behavior:
Q1 := S1 OR (NOT R AND Q1)
- S1=TRUE always sets Q1=TRUE (set dominant)
- R=TRUE resets Q1=FALSE only if S1=FALSE
Truth Table: | S1 | R | Q1 (next) | |----|---|-----------| | 0 | 0 | Q1 (unchanged) | | 0 | 1 | 0 | | 1 | 0 | 1 | | 1 | 1 | 1 (set dominant) |
RS - Reset Dominant Bistable¶
+-----+
| RS |
BOOL---|S Q1|---BOOL
BOOL---|R1 |
+-----+
| Input | Description |
|---|---|
| S | Set |
| R1 | Reset (dominant) |
| Output | Description |
|---|---|
| Q1 | Output state |
Behavior:
Q1 := NOT R1 AND (S OR Q1)
- R1=TRUE always resets Q1=FALSE (reset dominant)
- S=TRUE sets Q1=TRUE only if R1=FALSE
Truth Table: | S | R1 | Q1 (next) | |---|----|-----------| | 0 | 0 | Q1 (unchanged) | | 0 | 1 | 0 | | 1 | 0 | 1 | | 1 | 1 | 0 (reset dominant) |
Initial State¶
The initial state of Q1 is FALSE (default BOOL value).
3. Edge Detection (Table 44)¶
R_TRIG - Rising Edge Detector¶
+--------+
| R_TRIG |
BOOL---|CLK Q|---BOOL
+--------+
| Input | Description |
|---|---|
| CLK | Clock input |
| Output | Description |
|---|---|
| Q | Edge detected |
Behavior:
FUNCTION_BLOCK R_TRIG
VAR_INPUT CLK: BOOL; END_VAR
VAR_OUTPUT Q: BOOL; END_VAR
VAR M: BOOL; END_VAR
Q := CLK AND NOT M;
M := CLK;
END_FUNCTION_BLOCK
- Q=TRUE for one execution cycle following a FALSE→TRUE transition of CLK
- Q=FALSE at all other times
Timing:
CLK: ___/‾‾‾‾‾\____/‾‾‾‾\___
Q: ___/‾\_______/‾\_______
(pulse on rising edge)
F_TRIG - Falling Edge Detector¶
+--------+
| F_TRIG |
BOOL---|CLK Q|---BOOL
+--------+
| Input | Description |
|---|---|
| CLK | Clock input |
| Output | Description |
|---|---|
| Q | Edge detected |
Behavior:
FUNCTION_BLOCK F_TRIG
VAR_INPUT CLK: BOOL; END_VAR
VAR_OUTPUT Q: BOOL; END_VAR
VAR M: BOOL; END_VAR
Q := NOT CLK AND NOT M;
M := NOT CLK;
END_FUNCTION_BLOCK
- Q=TRUE for one execution cycle following a TRUE→FALSE transition of CLK
- Q=FALSE at all other times
Timing:
CLK: ‾‾‾\____/‾‾‾‾\____/‾‾‾
Q: ___/‾\_______/‾\_______
(pulse on falling edge)
Cold Restart Behavior¶
- R_TRIG with CLK connected to TRUE: Q=TRUE on first execution after cold restart
- F_TRIG with CLK connected to FALSE: Q=TRUE on first execution after cold restart
4. Counter Function Blocks (Table 45)¶
CTU - Up Counter¶
+-------+
| CTU |
BOOL--->CU Q|---BOOL
BOOL---|R |
INT---|PV CV|---INT
+-------+
| Input | Type | Description |
|---|---|---|
| CU | BOOL (R_EDGE) | Count up (rising edge) |
| R | BOOL | Reset |
| PV | INT | Preset value |
| Output | Type | Description |
|---|---|---|
| Q | BOOL | Counter >= PV |
| CV | INT | Current value |
Behavior:
IF R THEN
CV := 0;
ELSIF CU AND (CV < PVmax) THEN
CV := CV + 1;
END_IF;
Q := (CV >= PV);
Variants:
- CTU_INT - INT counter (default)
- CTU_DINT - DINT counter
- CTU_LINT - LINT counter
- CTU_UDINT - UDINT counter
- CTU_ULINT - ULINT counter
CTD - Down Counter¶
+-------+
| CTD |
BOOL--->CD Q|---BOOL
BOOL---|LD |
INT---|PV CV|---INT
+-------+
| Input | Type | Description |
|---|---|---|
| CD | BOOL (R_EDGE) | Count down (rising edge) |
| LD | BOOL | Load preset |
| PV | INT | Preset value |
| Output | Type | Description |
|---|---|---|
| Q | BOOL | Counter <= 0 |
| CV | INT | Current value |
Behavior:
IF LD THEN
CV := PV;
ELSIF CD AND (CV > PVmin) THEN
CV := CV - 1;
END_IF;
Q := (CV <= 0);
Variants: Same as CTU (CTD_DINT, CTD_LINT, etc.)
CTUD - Up/Down Counter¶
+---------+
| CTUD |
BOOL--->CU QU|---BOOL
BOOL--->CD QD|---BOOL
BOOL---|R |
BOOL---|LD |
INT---|PV CV|---INT
+---------+
| Input | Type | Description |
|---|---|---|
| CU | BOOL (R_EDGE) | Count up (rising edge) |
| CD | BOOL (R_EDGE) | Count down (rising edge) |
| R | BOOL | Reset to 0 |
| LD | BOOL | Load PV |
| PV | INT | Preset value |
| Output | Type | Description |
|---|---|---|
| QU | BOOL | Counter >= PV |
| QD | BOOL | Counter <= 0 |
| CV | INT | Current value |
Behavior:
IF R THEN
CV := 0;
ELSIF LD THEN
CV := PV;
ELSIF NOT (CU AND CD) THEN
IF CU AND (CV < PVmax) THEN
CV := CV + 1;
ELSIF CD AND (CV > PVmin) THEN
CV := CV - 1;
END_IF;
END_IF;
QU := (CV >= PV);
QD := (CV <= 0);
Note: If both CU and CD have rising edges simultaneously, count is unchanged.
Variants: Same as CTU (CTUD_DINT, CTUD_LINT, etc.)
5. Timer Function Blocks (Table 46, Figure 15)¶
Common Timer Interface¶
All timers share:
| Input | Type | Description |
|---|---|---|
| IN | BOOL | Timer input |
| PT | TIME | Preset time |
| Output | Type | Description |
|---|---|---|
| Q | BOOL | Timer output |
| ET | TIME | Elapsed time |
TP - Pulse Timer¶
+-------+
| TP |
BOOL---|IN Q|---BOOL
TIME---|PT ET|---TIME
+-------+
Behavior: Generates a fixed-duration pulse.
- When IN goes TRUE, Q goes TRUE for duration PT
- Q stays TRUE for full PT duration regardless of IN changes
- ET counts up while Q is TRUE, stops at PT
Timing Diagram:
IN: __/‾‾‾‾\____/‾\_______/‾‾‾‾‾‾‾‾‾\_____
Q: __/‾‾‾‾‾‾‾‾\_/‾‾‾‾‾‾‾‾\_/‾‾‾‾‾‾‾‾\____
ET: __/‾‾‾‾‾‾‾‾\_/‾‾‾‾‾‾‾‾\_/‾‾‾‾‾‾‾‾\____
|<--PT-->| |<--PT-->| |<--PT-->|
TON - On-Delay Timer¶
+-------+
| TON |
BOOL---|IN Q|---BOOL
TIME---|PT ET|---TIME
+-------+
Behavior: Delays turning on.
- Q goes TRUE after IN has been TRUE for duration PT
- If IN goes FALSE before PT, Q stays FALSE and ET resets
- ET counts while IN is TRUE and Q is FALSE
Timing Diagram:
IN: __/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\_____/‾‾‾\_____
Q: _______/‾‾‾‾‾‾‾‾‾‾\_____________
ET: __/‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾\____/‾‾‾\_____
|<PT>| |<PT (not reached)
Use Case: Debounce, delayed start
TOF - Off-Delay Timer¶
+-------+
| TOF |
BOOL---|IN Q|---BOOL
TIME---|PT ET|---TIME
+-------+
Behavior: Delays turning off.
- Q goes TRUE immediately when IN goes TRUE
- When IN goes FALSE, Q stays TRUE for duration PT
- If IN goes TRUE again before PT, Q stays TRUE and ET resets
Timing Diagram:
IN: __/‾‾‾‾‾‾\___________/‾\___________
Q: __/‾‾‾‾‾‾‾‾‾‾‾‾‾\____/‾‾‾‾‾‾‾‾‾\___
ET: _________/‾‾‾‾‾‾\________/‾‾‾‾‾‾\___
|<-PT-->| |<-PT-->|
Use Case: Keep motor running after button release, extend output
Timer Variants¶
Standard timers use TIME. Variants for LTIME:
- TP_LTIME
- TON_LTIME
- TOF_LTIME
6. Usage Examples¶
Bistable Example¶
VAR
StartButton: BOOL;
StopButton: BOOL;
MotorRunning: SR;
END_VAR
MotorRunning(S1 := StartButton, R := StopButton);
MotorOutput := MotorRunning.Q1;
Edge Detection Example¶
VAR
Sensor: BOOL;
SensorEdge: R_TRIG;
Count: INT := 0;
END_VAR
SensorEdge(CLK := Sensor);
IF SensorEdge.Q THEN
Count := Count + 1;
END_IF;
Counter Example¶
VAR
PulseInput: BOOL;
ResetButton: BOOL;
Counter: CTU;
END_VAR
Counter(CU := PulseInput, R := ResetButton, PV := 100);
IF Counter.Q THEN
// Counter reached 100
Alarm := TRUE;
END_IF;
CurrentCount := Counter.CV;
Timer Example¶
VAR
StartCommand: BOOL;
DelayTimer: TON;
MotorOn: BOOL;
END_VAR
DelayTimer(IN := StartCommand, PT := T#5s);
MotorOn := DelayTimer.Q; // Motor starts 5 seconds after command
Combined Example¶
VAR
Button: BOOL;
ButtonEdge: R_TRIG;
PulseTimer: TP;
Output: BOOL;
END_VAR
// Generate 500ms pulse on each button press
ButtonEdge(CLK := Button);
PulseTimer(IN := ButtonEdge.Q, PT := T#500ms);
Output := PulseTimer.Q;
7. Timing Considerations¶
Execution Rate¶
Timer accuracy depends on execution rate: - Timer resolution = execution cycle time - For T#10ms timer with 100ms cycle: actual time ≈ 100ms
Edge Detection Accuracy¶
- Edge is detected between consecutive executions
- Multiple edges within one cycle appear as one edge
Counter Overflow¶
- PVmax and PVmin are Implementer specific
- Typically max value of the counter type (e.g., 32767 for INT)
- Counter saturates at limits
Implementation Notes for trust-hir¶
trust-hir validates standard FB calls by signature and static types only; it does not model internal state or timing behavior. (IEC 61131-3 Ed.3, Section 6.6.3.5, Tables 43-46, Figure 15; DEV-010)
The behavioral descriptions above are retained for reference; trust-runtime
executes the stateful timer/counter/trigger behavior for SR, RS, R_TRIG,
F_TRIG, CTU, CTD, CTUD, TP, TON, and TOF. Current runtime
deviations are documented in docs/IEC_DEVIATIONS.md, including the CTUD
single-input LD profile and TP/TOF ET exposure.
FB Definitions¶
trust-hir provides built-in signatures for: 1. Input variables with types and edge qualifiers 2. Output variables with types
Internal state variables and behavioral specifications are documented above but
are not modeled in trust-hir. Runtime execution covers that stateful behavior;
see docs/IEC_DEVIATIONS.md and the runtime timer/counter implementations.
Edge Detection Internal¶
R_EDGE and F_EDGE input qualifiers:
VAR_INPUT
CU: BOOL R_EDGE; // Rising edge detection
END_VAR
Internally equivalent to:
VAR_INPUT
CU: BOOL;
END_VAR
VAR
CU_EDGE: R_TRIG;
END_VAR
// In body: use CU_EDGE(CLK := CU).Q instead of CU
Timer Implementation¶
Timers require: 1. Time tracking (ET accumulation) 2. State machine for IN/Q relationship 3. Comparison with PT
Standard Library¶
trust-hir should provide built-in definitions for: - SR, RS - R_TRIG, F_TRIG - CTU, CTD, CTUD (and typed variants) - TP, TON, TOF (and LTIME variants)