Generated reference › Peak Finder — Control Systems/Signal Measurements
kind: generated#block#control-systems-signal-measurements

Peak Finder — Control Systems/Signal Measurements

Control_Systems/Signal_Measurements/Peak_Finder · 1 input / 4 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++, 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.

Peak Finder

Control Systems / Signal Measurements

Finds the local maxima and minima of the frame on its input and reports the first K of them, in index order. An interior sample x[i] is a

  • maximum when x[i] − x[i−1] > T and x[i] − x[i+1] > T,
  • minimum when x[i−1] − x[i] > T and x[i+1] − x[i] > T,

with T the threshold when Ignore Peaks Within Threshold is on and 0 when it is off. Both comparisons are strict, so a plateau is never a peak, and the first and last samples never are, having one neighbour each.

Ports

  • x – the frame, an [N,1] column with N from 1 to 64. One channel: a multi-column input is refused rather than read column by column.
  • cnt (u32, ICoreUInt32) – how many peaks were reported, [1,1], never more than K.
  • idx (u32, ICoreUInt32) – their positions in the frame, [K,1], counted from 0 or from 1 per Index Base. Slots past cnt hold 0.
  • val – their values, [K,1]; slots past cnt hold 0.
  • max (bool, ICoreBool) – true where the peak is a maximum, false where it is a minimum, [K,1]; slots past cnt are false. This is the port that selects maxima or minima downstream.

Parameters

  • Index Base – Zero (the first sample is index 0) or One.
  • Maximum Number of Peaks – K, 1 to 16: the length of the three vector outputs. When a frame has more peaks than this, the first K in index order are reported, not the largest.
  • Ignore Peaks Within Threshold – off or on. On, a point counts only when it stands more than Threshold clear of both neighbours.
  • Threshold – T, read only when the switch above is on.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

Code export

Seven targets: Python, MATLAB, Java, Rust, C, C++ and PLC Structured Text. Every target subtracts first and compares second, as Simulink does – at T = 0.3, 2 − 1.7 is 0.30000000000000004 and clears the threshold, where the algebraically equal x[i] > x[i−1] + T would not.

VHDL, Verilog and SystemVerilog are not applicable: the cnt and idx outputs are unsigned 32-bit integers, which the HDL targets' Q16.16 carrier cannot hold exactly past 32767, so an export to one of them stops and names the port rather than emitting a core that would agree over part of the range. PLC Structured Text unrolls the search over the frame, which is why N is bounded.

Simulink bridge

Import and export, mapped to DSP System Toolbox's dspsigops/Peak Finder. Index Base → indexBase, Maximum Number of Peaks → maxPeaks, Ignore Peaks Within Threshold → NoiseDistinguish and Threshold → thresh, all one to one. Three parameters are fixed: polarity at Maxima and Minima and outputIdx / outputVal at on – choosing Maxima or Minima alone, or switching an output off, removes a Simulink port this block has, so such a block is reported on import rather than brought in with the wrong ports. The Simulink block defines no SampleTime, so a positive Sampling Time (s) stays on this side and is reported.

Notes

  • Algebraic and stateless: every output depends on this frame alone.
  • Verified against R2026a: [1 3 2 5 4 4 6 1] gives count 4, indices [1 2 3 6], values [3 2 5 6] and is-maximum [true false true true]; the plateau [5 4 4 4 6 2 2 3] gives the one peak 6.
  • The count and index outputs are unsigned 32-bit integers and the flag is a boolean, matching the Simulink block's output types.

Code facts#

FactValue
registered typeControl_Systems/Signal_Measurements/Peak_Finder
familyControl_Systems/Signal_Measurements
solver environment classICoreBlock_0_Control_Systems_1_Signal_Measurements_2_Peak_Finder
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Signal_Measurements/Peak_Finder/ICoreBlock_0_Control_Systems_1_Signal_Measurements_2_Peak_Finder.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Signal_Measurements/Peak_Finder/ICoreBlock_0_Control_Systems_1_Signal_Measurements_2_Peak_Finder.h
default size on canvas130 × 100 px
ports at insert1 in, 4 out
code generators implementedPython, MATLAB, Java, Rust, C, C++, PLC Structured Text

Ports#

#DirectionSignal typeDescription label
1inICoreDoublex
2outICoreUInt32cnt
3outICoreUInt32idx
4outICoreDoubleval
5outICoreBoolmax

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 variableDefaultSimulink parameter
Index BaseZero%~%One~~ZeroindexBase
Maximum Number of Peaks10maxPeaks
Ignore Peaks Within Thresholdoff%~%on~~offNoiseDistinguish
Threshold0thresh

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.

supportSupport::Both
Simulink pathdspsigops/Peak Finder
port-count rulePortsParam::None
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
always setpolarity = Maxima and Minima, outputIdx = on, outputVal = on
ICore configSimulink parameterValue translation
Index BaseindexBaseZero → Zero, One → One
Maximum Number of PeaksmaxPeakspasses through
Ignore Peaks Within ThresholdNoiseDistinguishoff → off, on → on
Thresholdthreshpasses through

Caveat (shown to the user): x is the one input; cnt, idx, val and max are Simulink's four outputs in order. polarity is fixed at 'Maxima and Minima' and outputIdx / outputVal at 'on': any other choice removes a Simulink port this block has, so such a block is reported on import. The fixed-point rounding and overflow settings do not apply to a double frame. The Simulink block defines no SampleTime, so the rate stays on the ICore side

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The checker has a blind spot here — it could not resolve something (a grouped port bullet, a computed config name), which is reported and never counted as a pass. A reader has to settle it:

  • B0 no sample under docs/generated/samples/ — nothing to cross-check (P8.1)

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).

Peak Finder -- the local maxima and minima of a frame, dspsigops/Peak Finder maximum at i: x[i] - x[i-1] > T and x[i] - x[i+1] > T minimum at i: x[i-1] - x[i] > T and x[i+1] - x[i] > T 1 <= i <= N-2

T is the threshold when "Ignore Peaks Within Threshold" is on, 0 when it is off. The first maxPeaks found in index order are reported -- count, indices, values, is-maximum -- and the unused slots are zero.

MEASURED AGAINST R2026a, eight frames and six threshold cases, and every rule below was read off a simulation rather than the help page:

  • [1 3 2 5 4 4 6 1] -> count 4, indices [1 2 3 6] (zero-based), values [3 2 5 6], is-max

[1 0 1 1]: the ENDPOINTS are never peaks, and the plateau 4 4 is neither a maximum nor a minimum -- both neighbour comparisons are STRICT.

  • the same frame at maxPeaks = 2 -> [1 2]: the FIRST two in index order, not the largest.
  • [5 4 4 4 6 2 2 3] -> one peak (6 at index 4); the plateaus 4 4 4 and 2 2 are not minima.
  • threshold: a point is kept when BOTH neighbour differences exceed T strictly. At T = 0.5 a

difference of exactly 0.5 drops the point; at T = 0.3, 2 - 1.7 = 0.30000000000000004 keeps it -- so the test is a DIFFERENCE compared with T, not x[i] > x[i-1] + T, which would have dropped it (2 > 2.0 is false). Every backend subtracts first.

  • index base One adds one to every index; the unused slots stay 0 either way.

⚠ ONE ARRANGEMENT ONLY: Peak Type "Maxima and Minima" with the index and value outputs on. Measured: Maxima or Minima alone drops the is-maximum port (4 -> 3 outputs), and the two output switches drop their ports. The bridge has no way to say that a parameter moves a port, so those three are fixed parameters and the block has all four outputs.

Sample results#

No sample run is committed for this block. Samples come from the headless harness (DOCS_PLAN.md P8.1) into docs/generated/samples/; until one exists this block's behaviour is witnessed by the parity and export-verification suites, not by a plot here.