Repeating Sequence — Control Systems/Sources
Control_Systems/Sources/Repeating_Sequence · 0 input / 1 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text
Description#
The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.
Repeating Sequence
Control Systems / Sources
A source that plays a piecewise-linear waveform and repeats it forever:
y(t) = the (time, output) table interpolated linearly at phase(t) = t₀ + (t − t₀) mod T
The two vectors below are read as a list of corner points joined by straight lines. The cycle T is the span of the time values, so the waveform starts again as soon as the last time is reached.
Ports
- Output – the interpolated value, always a scalar. It has no inputs; the position in the waveform comes from the simulation clock.
Parameters
- Time Values – when each corner point occurs, as a row or column vector of at least two strictly increasing values. The span between the first and the last is the period; a repeated or decreasing time has no segment to describe and stops the run with a message naming the block.
- Output Values – what the waveform is at each of those times, as a vector of the same length. Any values are allowed.
- Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period. On this block it only decides how finely the waveform is sampled, not what it computes – so a coarse rate visibly rounds off the corners of a fast sequence.
The wrap, and discontinuous tables
At a period boundary the phase wraps to exactly the first time value, so the block emits the first output value there rather than the last. If the two differ the waveform jumps at every boundary, which is perfectly legal – a sawtooth is written exactly that way – but worth being deliberate about. A table whose first and last output values agree is continuous across the wrap.
Code export
All ten targets: Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog and PLC Structured Text. Each uses a per-block local sample clock rather than a global one. The table is baked into the arithmetic at export time rather than exposed as a tunable parameter, and it has to be: the times decide how many segments there are, so the corner points and the structure of the generated code cannot be separated. Each segment is emitted as its own comparison and straight-line expression, which is the one shape all ten targets spell the same way. The three HDL targets carry the block in simulation-only form: the phase and the interpolation are done in real arithmetic and quantized on the way out to the fixed-point signal ports.
Simulink bridge
Import and export, mapped to simulink/Sources/Repeating Sequence.
"Time Values" to rep_seq_t and "Output Values" to
rep_seq_y, with the same meanings on both sides. The rate does not
cross: Simulink's Repeating Sequence is a masked subsystem and defines no
SampleTime parameter at all (verified against the R2026a block
dialog), so "Sampling Time (s)" stays on the ICore side and the Simulink block
inherits the model's step. A block configured with an explicit positive rate
reports that the rate did not cross.
Notes
- Time-driven and stateless: the output depends only on the current time, so a re-run reproduces the waveform exactly and there is no initial state to seed.
- Not discrete by nature, unlike Repeating Sequence Stair – nothing here is counted, so a continuous solver evaluating the block at its intermediate stages gets the right value at each one.
- See Repeating Sequence Stair for a sample-driven staircase with no time axis, and Repeating Sequence Interpolated for a sample-driven table with a choice of lookup rules.
Code facts#
| Fact | Value |
|---|---|
| registered type | Control_Systems/Sources/Repeating_Sequence |
| family | Control_Systems/Sources |
| solver environment class | ICoreBlock_0_Control_Systems_1_Sources_2_Repeating_Sequence |
| source | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Repeating_Sequence/ICoreBlock_0_Control_Systems_1_Sources_2_Repeating_Sequence.cpp |
| header | src/ICoreSDK/ICoreBlockLibrary/Blocks/Control_Systems/Sources/Repeating_Sequence/ICoreBlock_0_Control_Systems_1_Sources_2_Repeating_Sequence.h |
| default size on canvas | 80 × 70 px |
| ports at insert | 0 in, 1 out |
| code generators implemented | Python, MATLAB, Java, Rust, C, C++, VHDL, Verilog, SystemVerilog, PLC Structured Text |
Ports#
| # | Direction | Signal type | Description label |
|---|---|---|---|
| 1 | out | ICoreDouble | — |
Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.
Configuration variables#
| Config variable | Default | Simulink parameter |
|---|---|---|
Time Values | [0 2] | rep_seq_t |
Output Values | [0 2] | rep_seq_y |
Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.
Simulink bridge#
| support | Support::Both |
| Simulink path | simulink/Sources/Repeating Sequence |
| port-count rule | PortsParam::None |
SampleTime parameter | no — the counterpart defines none; the rate stays on the ICore side |
| ICore config | Simulink parameter | Value translation |
|---|---|---|
Time Values | rep_seq_t | passes through |
Output Values | rep_seq_y | passes through |
Caveat (shown to the user): the rate does not cross - Simulink's Repeating Sequence is a masked subsystem and defines no 'SampleTime' parameter, so it inherits the model's step and any explicit 'Sampling Time (s)' stays on the ICore side
Catalog contract: src/ICoreSDK/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h
Description vs code#
The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.
The verdict above is
tools/docs/check_block_descriptions.py(P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.
File banner (developer view)#
The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).
Repeating Sequence block — a piecewise-linear waveform, repeated forever y(t) = the (time, output) table interpolated linearly at phase(t) phase(t) = t0 + (t - t0) mod T, T = last time value - first time value
Simulink calls this the repeating table: two vectors, one of times and one of outputs, joined by straight lines and started again every T seconds. Verified against simulink/Sources/Repeating Sequence with t = [0 0.1 0.3 0.4], y = [0.5 -1.2 0.8 0.5]: that block ramps 0.5 down to -1.2 over the first tenth of a second, back up to 0.8 over the next two, down to 0.5 over the last, and is at 0.5 again at t = 0.4 -- the wrap landing on the first entry, not the last.
A DISCONTINUOUS TABLE IS LEGAL AND THE WRAP IS WHERE IT SHOWS. If the first and last output values differ, the waveform jumps at every period boundary; the block emits the FIRST value there, since the phase wraps to exactly t0. Verified with t = [0 0.2], y = [0 2], which sawtooths from 0 to 1.9 and returns to 0 at t = 0.2. Worth knowing when configuring one: a table that starts and ends at the same value is continuous across the wrap and is the easier thing to reason about, but nothing requires it.
Time-driven and stateless: the output depends only on the current time, so there is no state to seed and a re-run reproduces the waveform exactly. It is NOT declared discrete-only -- nothing is counted, so a continuous solver evaluating it at intermediate stages gets the right answer at each one.
THE PHASE IS MEASURED FROM A SHIFTED BASE, phaseBase() below, which differs from the first time value by a whole number of periods and is therefore the same phase. The point is that (t - base) is never negative over the run, so every target's floor is a plain truncation -- which is all PLC Structured Text offers, and which C, Rust and Verilog would otherwise get wrong for a negative argument by taking the sign of the left operand.
Code export: all ten targets. The three HDL ones are SIMULATION-ONLY -- they read the testbench's sim_time in real arithmetic and quantize only at the port, exactly as Sine Wave does, because a Q-format datapath has no clock to derive t from.
Sample results#
Plotted: free — No input: the block run alone
Category source · sample time 0.1 · 60 steps · commit ccf005c8 · produced by docsSample --out <folder> --steps 60 · data docs/generated/samples/Control_Systems__Sources__Repeating_Sequence.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).