Digital Sequencer DSL – Instruction Set (Part 1)
Commands for the Digital Sequencer#
With the overall structure of the DSL defined, the next step is to begin defining the instruction set that will be used within the PROCESS block.
At this stage, I want to keep things deliberately minimal. Rather than attempting to design a complete instruction set up front, the focus is on defining a small number of core commands that are sufficient to express simple and useful behaviour.
The initial set of commands is as follows:
SETWAITIFHALT
These form the foundation of the execution model:
SETwill control output statesWAITwill introduce timing into a sequenceIFwill allow conditional execution based on inputsHALTwill terminate program execution
This is intentionally a very small set. If these commands prove to be expressive enough for real-world scenarios, additional functionality can be introduced later without overcomplicating the initial design.
Execution Model Considerations#
Alongside defining the instruction set, I’ve also been considering how programs will be executed at runtime.
Each program will need to be stepped through in a predictable and deterministic way, which implies the presence of a central execution loop acting as the scheduler for all programs within a package.
At the hardware level, this will likely be driven by a timer acting as the pacemaker for the system. Each tick of this timer would advance execution, allowing instructions such as WAIT to be implemented without blocking the entire system.
Whether this execution model is implemented as a custom loop or built on top of something like FreeRTOS is still to be decided. FreeRTOS, for example, provides a system tick driven by a hardware timer and interrupt service routine, which could be used as a foundation for scheduling.
At this stage, the goal is not to commit to a specific implementation, but to ensure that the instruction set and execution model are compatible with a timer-driven, non-blocking design. This is an area that will require careful consideration as the implementation takes shape.
SET Command#
The SET command is the simplest and most fundamental instruction in the DSL. It is used to control the state of an output that has been declared within the program.
Syntax#
SET <output_name> HIGH
SET <output_name> LOW
Description#
The SET command updates the state of the specified output to either HIGH or LOW.
The <output_name> must refer to a symbolic name declared in the DECLARE section as an OUTPUT.
Example#
SET DOOROPEN HIGH
WAIT 2000ms
SET DOOROPEN LOW
In this example:
DOOROPENis set toHIGH- the program waits for 2000ms
DOOROPENis then set toLOW
Behaviour#
- The state change is applied immediately when the instruction is executed
- The output remains in that state until it is changed by another instruction
- The command does not block execution beyond the time required to apply the state change
Validation Rules#
The following conditions must be satisfied:
<output_name>must be declared as anOUTPUTin theDECLAREsection<output_name>must exist within the current program- Attempting to
SETan undeclared or input-mapped name must result in a validation error
Compilation Considerations#
At compile time, symbolic output names can be resolved to their corresponding physical pin identifiers.
This allows the SET instruction to be compiled into a compact bytecode representation, for example:
SET DOOROPEN HIGH → [OP_SET, pin=0, value=1]
SET DOOROPEN LOW → [OP_SET, pin=0, value=0]
The exact encoding is implementation-defined, but the goal is to minimise runtime overhead by resolving names and validation rules ahead of execution.
WAIT Command#
The WAIT command introduces a delay into program execution. Unlike traditional blocking delays, WAIT is intended to operate within a non-blocking, timer-driven execution model.
Syntax#
WAIT <duration>
Where <duration> is specified in ms:
WAIT 2000ms
Description#
The WAIT command suspends execution of the current program for the specified duration.
Rather than blocking the entire system, the delay is handled in a non-blocking manner, allowing other programs to continue executing.
Behaviour#
- When a
WAITinstruction is encountered, the program records the required delay duration - Execution of the current program is paused until the delay has elapsed
- Other programs continue to execute during this time
- Once the delay has completed, execution resumes from the next instruction
Example#
SET DOOROPEN HIGH
WAIT 2000ms
SET DOOROPEN LOW
In this example:
DOOROPENis set toHIGH- the program pauses for 2000ms
DOOROPENis then set toLOW
Validation Rules#
The following conditions must be satisfied:
<duration>must be a positive, non-zero value<duration>must include a valid time unit (currentlyms)- Invalid or malformed durations must result in a validation error
Execution Model Considerations#
The WAIT command relies on a timer-driven execution model.
Internally, this can be implemented using a system tick, where:
- Each program maintains its own delay state
- A countdown or target timestamp is associated with the program
- Execution resumes once the required number of ticks has elapsed
This approach ensures that WAIT does not block the execution of other programs and allows the system to scale across multiple concurrent sequences.
Compilation Considerations#
At compile time, the duration can be converted into a numeric value representing time in ms or system ticks.
For example:
WAIT 2000ms → [OP_WAIT, duration=2000]
If the runtime operates on a fixed tick interval, this value may be converted into tick counts:
WAIT 2000ms → [OP_WAIT, ticks=200]
The exact representation is implementation-defined, but the goal is to minimise runtime computation by resolving timing values during compilation.
IF Command#
The IF command introduces conditional execution into the DSL. It allows instructions to be executed only when a specified condition is met.
Syntax#
IF <input_name> IS HIGH THEN
<instructions>
ENDIF
Description#
The IF command evaluates the state of an input and conditionally executes the enclosed block of instructions.
The <input_name> must refer to a symbolic name declared in the DECLARE section as an INPUT.
If the condition evaluates to TRUE, the enclosed instructions are executed. If the condition evaluates to FALSE, execution continues after the ENDIF.
Example#
IF DOORSWITCH IS HIGH THEN
SET DOOROPEN HIGH
WAIT 2000ms
SET DOOROPEN LOW
ENDIF
In this example:
- The state of
DOORSWITCHis evaluated - If it is
HIGH, the enclosed instructions are executed - If it is
LOW, the block is skipped
Behaviour#
- The condition is evaluated at the point the instruction is encountered
- Execution continues sequentially if the condition is true
- If the condition is false, the instruction pointer skips to the matching
ENDIF - Nested
IFblocks may be supported depending on implementation
Validation Rules#
The following conditions must be satisfied:
<input_name>must be declared as anINPUT<input_name>must exist within the current program- The
IFblock must be properly terminated with a matchingENDIF - Invalid or mismatched control flow must result in a validation error
Compilation Considerations#
At compile time, IF statements can be translated into conditional jump instructions.
For example:
IF DOORSWITCH IS HIGH THEN
SET DOOROPEN HIGH
ENDIF
may be compiled into something similar to:
[OP_IF_NOT_HIGH, pin=0, jump=+2]
[OP_SET, pin=0, value=1]
This allows conditional logic to be executed efficiently at runtime using simple branching operations.
HALT Command#
The HALT command terminates execution of the current program.
Syntax#
HALT
Description#
The HALT command stops execution of the current program immediately.
Once a program has halted, it will not resume execution unless the system is reset or the program is explicitly restarted.
Behaviour#
- When a
HALTinstruction is encountered, execution of the current program stops - The program is marked as inactive
- No further instructions in the program are executed
- Other programs continue to execute unaffected
Example#
SET DOOROPEN HIGH
WAIT 2000ms
SET DOOROPEN LOW
HALT
In this example:
DOOROPENis activated- the program waits for 2000ms
DOOROPENis deactivated- the program then terminates
Validation Rules#
The following conditions must be satisfied:
HALTmust appear within a validPROCESSblock- Any instructions following
HALTare considered unreachable and may generate a warning or validation error
Compilation Considerations#
At compile time, HALT can be translated into a simple termination instruction:
HALT → [OP_HALT]
At runtime, this instruction signals that the program should be removed from the execution loop or marked as inactive.
If you need custom control hardware, programmable timing systems, or embedded firmware designed for your automation needs, discover how we build solutions at Protoworks (NI).
- 2026-10-17 Refining the Protoworks service offerings Lab
- 2026-09-27 Belfast Tech Week Lab
- 2026-09-19 Refining the UCMOD Architecture R&D
- 2026-09-06 Giving AI Agents a Way to Talk to Protoworks Software
- 2026-09-03 A Morning at a Manufacturing Trade Show Lab
- 2026-09-01 Debugging 921600 Baud on the ATtiny1614 R&D