570 lines
19 KiB
INI
570 lines
19 KiB
INI
/**
|
||
* Test MARTe2 application for UDPStreamer DataSource.
|
||
*
|
||
* Three independent RT threads demonstrate all four UDPStreamer time modes:
|
||
*
|
||
* Thread1 – "Streamer" port 44500 TCP control / 44503 UDP multicast 239.0.0.1
|
||
* (scalar signals, auto-accumulated to arrays[10], multicast mode,
|
||
* 100 Hz flush = 10 samples per packet, 1 kHz source)
|
||
* Counter – uint32 cycle counter
|
||
* Time – uint32 time in microseconds (LinuxTimer, 1 kHz)
|
||
* Sine1 – float32, 1 Hz, quantised to uint16 on wire (PacketTime)
|
||
* Sine2 – float32, 0.3 Hz, raw float32 on wire (PacketTime)
|
||
*
|
||
* Thread2 – "FastStreamer" port 44501 (packed arrays, FirstSample + LastSample)
|
||
* Time – uint32 scalar anchor (5 kHz LinuxTimer)
|
||
* Ch1 – float32[1000], 1 kHz sine (TimeMode = FirstSample)
|
||
* Ch2 – float32[1000], 10 kHz sine (TimeMode = LastSample)
|
||
* Both channels use Time as the anchor and SamplingRate = 5 000 000 Hz so
|
||
* the WebUI reconstructs the 200 ns per-sample timestamps.
|
||
*
|
||
* Thread3 – "FullArrStreamer" port 44502 (packed arrays, FullArray)
|
||
* TimeArray – uint64[1000] per-sample timestamps in ns generated by TimeArrayGAM
|
||
* Ch3 – float32[1000], 3 kHz sine (TimeMode = FullArray)
|
||
* Ch4 – float32[1000], 500 Hz sine (TimeMode = FullArray)
|
||
* The WebUI uses the explicit timestamp for each sample rather than
|
||
* reconstructing them from a scalar anchor.
|
||
*/
|
||
$TestApp = {
|
||
Class = RealTimeApplication
|
||
+Functions = {
|
||
Class = ReferenceContainer
|
||
|
||
// ── Copy Counter + Time from LinuxTimer into the inter-GAM DDB ──────
|
||
+TimerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
Counter = {
|
||
DataSource = Timer
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
Frequency = 1000
|
||
DataSource = Timer
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Counter = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 5 kHz fast timer for packed-array threads ────────────────────────
|
||
+FastTimerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
Time = {
|
||
Frequency = 5000
|
||
DataSource = FastTimer
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Time = {
|
||
DataSource = DDB2
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 1 Hz sinusoidal signal ───────────────────────────────────────────
|
||
+SineGAM1 = {
|
||
Class = WaveformSin
|
||
Amplitude = 10.0
|
||
Frequency = 1.0
|
||
Phase = 0.0
|
||
Offset = 0.0
|
||
InputSignals = {
|
||
Time = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Sine1 = {
|
||
DataSource = DDB
|
||
Type = float32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 0.3 Hz sinusoidal signal (phase-shifted) ─────────────────────────
|
||
+SineGAM2 = {
|
||
Class = WaveformSin
|
||
Amplitude = 5.0
|
||
Frequency = 0.3
|
||
Phase = 1.0472
|
||
Offset = 0.0
|
||
InputSignals = {
|
||
Time = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Sine2 = {
|
||
DataSource = DDB
|
||
Type = float32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 1 kHz sine burst – channel 1 (FirstSample anchor) ───────────────
|
||
+SineGAM3 = {
|
||
Class = SineArrayGAM
|
||
Frequency = 1000.0
|
||
Amplitude = 1.0
|
||
Phase = 0.0
|
||
Offset = 0.0
|
||
SamplingRate = 5000000.0
|
||
OutputSignals = {
|
||
Ch1 = {
|
||
DataSource = DDB2
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 10 kHz sine burst – channel 2 (LastSample anchor) ───────────────
|
||
+SineGAM4 = {
|
||
Class = SineArrayGAM
|
||
Frequency = 10000.0
|
||
Amplitude = 0.5
|
||
Phase = 1.5708
|
||
Offset = 0.0
|
||
SamplingRate = 5000000.0
|
||
OutputSignals = {
|
||
Ch2 = {
|
||
DataSource = DDB2
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Route scalar signals → Streamer ──────────────────────────────────
|
||
+StreamerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
Counter = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
DataSource = DDB
|
||
Type = uint32
|
||
}
|
||
Sine1 = {
|
||
DataSource = DDB
|
||
Type = float32
|
||
}
|
||
Sine2 = {
|
||
DataSource = DDB
|
||
Type = float32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Counter = {
|
||
DataSource = Streamer
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
DataSource = Streamer
|
||
Type = uint32
|
||
}
|
||
Sine1 = {
|
||
DataSource = Streamer
|
||
Type = float32
|
||
}
|
||
Sine2 = {
|
||
DataSource = Streamer
|
||
Type = float32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Route packed arrays → FastStreamer (FirstSample + LastSample) ────
|
||
+FastStreamerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
Time = {
|
||
DataSource = DDB2
|
||
Type = uint32
|
||
}
|
||
Ch1 = {
|
||
DataSource = DDB2
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch2 = {
|
||
DataSource = DDB2
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Time = {
|
||
DataSource = FastStreamer
|
||
Type = uint32
|
||
}
|
||
Ch1 = {
|
||
DataSource = FastStreamer
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch2 = {
|
||
DataSource = FastStreamer
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 3 kHz sine burst – channel 3 (FullArray anchor) ─────────────────
|
||
+SineGAM5 = {
|
||
Class = SineArrayGAM
|
||
Frequency = 3000.0
|
||
Amplitude = 2.0
|
||
Phase = 0.0
|
||
Offset = 0.0
|
||
SamplingRate = 5000000.0
|
||
OutputSignals = {
|
||
Ch3 = {
|
||
DataSource = DDB3
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 500 Hz sine burst – channel 4 (FullArray anchor) ─────────────────
|
||
+SineGAM6 = {
|
||
Class = SineArrayGAM
|
||
Frequency = 500.0
|
||
Amplitude = 3.0
|
||
Phase = 0.7854
|
||
Offset = 0.0
|
||
SamplingRate = 5000000.0
|
||
OutputSignals = {
|
||
Ch4 = {
|
||
DataSource = DDB3
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Build per-sample time array for FullArray channels ────────────────
|
||
// TimeArrayGAM expands the scalar LinuxTimer Time (uint32, µs) into a
|
||
// uint64[1000] array in nanoseconds where element[k] = Time_ns + k * period_ns.
|
||
// Using ns preserves sub-µs resolution at sampling rates > 1 MHz.
|
||
+TimeArrayGAM1 = {
|
||
Class = TimeArrayGAM
|
||
SamplingRate = 5000000.0
|
||
Anchor = FirstSample
|
||
InputSignals = {
|
||
Time = {
|
||
DataSource = DDB3
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
TimeArray = {
|
||
DataSource = DDB3
|
||
Type = uint64
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Fast timer for FullArray thread ───────────────────────────────────
|
||
+FullArrTimerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
Time = {
|
||
Frequency = 5000
|
||
DataSource = FullArrTimer
|
||
Type = uint32
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
Time = {
|
||
DataSource = DDB3
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Route FullArray channels → FullArrStreamer ─────────────────────
|
||
+FullArrStreamerGAM = {
|
||
Class = IOGAM
|
||
InputSignals = {
|
||
TimeArray = {
|
||
DataSource = DDB3
|
||
Type = uint64
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch3 = {
|
||
DataSource = DDB3
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch4 = {
|
||
DataSource = DDB3
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
OutputSignals = {
|
||
TimeArray = {
|
||
DataSource = FullArrStreamer
|
||
Type = uint64
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch3 = {
|
||
DataSource = FullArrStreamer
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch4 = {
|
||
DataSource = FullArrStreamer
|
||
Type = float32
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
+Data = {
|
||
Class = ReferenceContainer
|
||
DefaultDataSource = DDB
|
||
|
||
+DDB = {
|
||
Class = GAMDataSource
|
||
}
|
||
+DDB2 = {
|
||
Class = GAMDataSource
|
||
}
|
||
+DDB3 = {
|
||
Class = GAMDataSource
|
||
}
|
||
|
||
// ── 1 kHz real-time clock (Thread1) ──────────────────────────────────
|
||
+Timer = {
|
||
Class = LinuxTimer
|
||
SleepNature = "Default"
|
||
Signals = {
|
||
Counter = {
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 5 kHz fast timer (Thread2 – FirstSample / LastSample) ────────────
|
||
+FastTimer = {
|
||
Class = LinuxTimer
|
||
SleepNature = "Default"
|
||
Signals = {
|
||
Counter = {
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── 5 kHz fast timer (Thread3 – FullArray) ───────────────────────────
|
||
+FullArrTimer = {
|
||
Class = LinuxTimer
|
||
SleepNature = "Default"
|
||
Signals = {
|
||
Counter = {
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
Type = uint32
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── Streamer: scalar signals, PacketTime (port 44500) ─────────────────
|
||
// Multicast mode: clients connect via TCP on port 44500 to receive the
|
||
// CONFIG packet, then join 239.0.0.1:44503 to receive DATA datagrams.
|
||
// Auto publishing ensures data is sent every RT cycle (1 kHz = 1 ms
|
||
// temporal resolution) but never faster, so the rate is bounded.
|
||
+Streamer = {
|
||
Class = UDPStreamer
|
||
Port = 44500
|
||
MulticastGroup = "239.0.0.1"
|
||
DataPort = 44503
|
||
MaxPayloadSize = 1400
|
||
PublishingMode = "Accumulate"
|
||
MinRefreshRate = 100
|
||
Signals = {
|
||
Counter = {
|
||
Type = uint32
|
||
}
|
||
Time = {
|
||
Type = uint32
|
||
Unit = "us"
|
||
}
|
||
Sine1 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
RangeMin = -10.0
|
||
RangeMax = 10.0
|
||
QuantizedType = "uint16"
|
||
}
|
||
Sine2 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
RangeMin = -5.0
|
||
RangeMax = 5.0
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── FastStreamer: packed arrays, FirstSample + LastSample (port 44501)
|
||
//
|
||
// Ch1 uses TimeMode = FirstSample:
|
||
// Time is the timestamp of sample [0]; later samples are extrapolated
|
||
// forward: t[k] = Time + k / SamplingRate.
|
||
//
|
||
// Ch2 uses TimeMode = LastSample:
|
||
// Time is the timestamp of sample [N-1]; earlier samples are
|
||
// extrapolated backward: t[k] = Time - (N-1-k) / SamplingRate.
|
||
//
|
||
// Both modes produce identical wall-clock placements for a fixed-rate
|
||
// signal and are shown here side-by-side for comparison.
|
||
+FastStreamer = {
|
||
Class = UDPStreamer
|
||
Port = 44501
|
||
MaxPayloadSize = 1400
|
||
Signals = {
|
||
Time = {
|
||
Type = uint32
|
||
Unit = "us"
|
||
}
|
||
Ch1 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
TimeMode = FirstSample
|
||
TimeSignal = Time
|
||
SamplingRate = 5000000.0
|
||
}
|
||
Ch2 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
TimeMode = LastSample
|
||
TimeSignal = Time
|
||
SamplingRate = 5000000.0
|
||
}
|
||
}
|
||
}
|
||
|
||
// ── FullArrStreamer: packed arrays, FullArray (port 44502) ─────────────
|
||
//
|
||
// TimeMode = FullArray: the TimeSignal (TimeArray) has the same
|
||
// NumberOfElements as the data channel. Each sample pair
|
||
// (TimeArray[k], Ch3[k]) provides its own independent timestamp.
|
||
// This mode handles non-uniform sampling and explicit per-sample clocks.
|
||
+FullArrStreamer = {
|
||
Class = UDPStreamer
|
||
Port = 44502
|
||
MaxPayloadSize = 1400
|
||
Signals = {
|
||
TimeArray = {
|
||
Type = uint64
|
||
Unit = "ns"
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
}
|
||
Ch3 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
TimeMode = FullArray
|
||
TimeSignal = TimeArray
|
||
}
|
||
Ch4 = {
|
||
Type = float32
|
||
Unit = "V"
|
||
NumberOfDimensions = 1
|
||
NumberOfElements = 1000
|
||
TimeMode = FullArray
|
||
TimeSignal = TimeArray
|
||
}
|
||
}
|
||
}
|
||
|
||
+Timings = {
|
||
Class = TimingDataSource
|
||
}
|
||
}
|
||
|
||
+States = {
|
||
Class = ReferenceContainer
|
||
+Running = {
|
||
Class = RealTimeState
|
||
+Threads = {
|
||
Class = ReferenceContainer
|
||
// Thread1: scalar signals at 1 kHz
|
||
+Thread1 = {
|
||
Class = RealTimeThread
|
||
CPUs = 0x1
|
||
Functions = {TimerGAM SineGAM1 SineGAM2 StreamerGAM}
|
||
}
|
||
// Thread2: packed arrays at 5 kHz (FirstSample + LastSample)
|
||
+Thread2 = {
|
||
Class = RealTimeThread
|
||
CPUs = 0x2
|
||
Functions = {FastTimerGAM SineGAM3 SineGAM4 FastStreamerGAM}
|
||
}
|
||
// Thread3: packed arrays at 5 kHz (FullArray with explicit timestamps)
|
||
+Thread3 = {
|
||
Class = RealTimeThread
|
||
CPUs = 0x4
|
||
Functions = {FullArrTimerGAM SineGAM5 SineGAM6 TimeArrayGAM1 FullArrStreamerGAM}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
+Scheduler = {
|
||
Class = GAMScheduler
|
||
TimingDataSource = Timings
|
||
}
|
||
}
|