Improved uo and added timerarraygam for testing

This commit is contained in:
Martino Ferrari
2026-05-20 00:15:38 +02:00
parent 620542a722
commit 62545503c4
13 changed files with 960 additions and 58 deletions
+230 -23
View File
@@ -1,20 +1,27 @@
/**
* Test MARTe2 application for UDPStreamer DataSource.
*
* Generates scalar and high-frequency packed signals and streams them via UDPStreamer.
* Connect with the WebUI client (Client/WebUI) to visualise the signals.
* Three independent RT threads demonstrate all four UDPStreamer time modes:
*
* Signals produced (scalar, 10 kHz):
* Counter uint32 cycle counter from LinuxTimer
* Time uint32 time in microseconds from LinuxTimer
* Sine1 float32, 1 Hz sine, amplitude 10, quantised to uint16 on wire
* Sine2 float32, 0.3 Hz sine, amplitude 5, raw float32 on wire
* Thread1 "Streamer" port 44500 (scalar signals, PacketTime)
* 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)
*
* Signals produced (packed temporal arrays, 10 kHz × 1000 samples = 10 MSps):
* Ch1 float32[1000], 1 kHz sine, amplitude 1.0
* Ch2 float32[1000], 1 kHz sine, amplitude 0.5, phase π/2
* Both channels use TimeMode=FirstSample with Time as the anchor and
* SamplingRate=10000000 so the WebUI reconstructs the per-sample timestamps.
* 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
@@ -46,6 +53,8 @@ $TestApp = {
}
}
}
// ── 5 kHz fast timer for packed-array threads ────────────────────────
+FastTimerGAM = {
Class = IOGAM
InputSignals = {
@@ -61,7 +70,6 @@ $TestApp = {
Type = uint32
}
}
}
// ── 1 Hz sinusoidal signal ───────────────────────────────────────────
@@ -106,14 +114,14 @@ $TestApp = {
}
}
// ── 1 kHz sine burst channel 1 (1000 samples/packet at 10 MSps) ──────
// ── 1 kHz sine burst channel 1 (FirstSample anchor) ───────────────
+SineGAM3 = {
Class = SineArrayGAM
Frequency = 1000.0
Amplitude = 1.0
Phase = 0.0
Offset = 0.0
SamplingRate = 1000000.0
SamplingRate = 5000000.0
OutputSignals = {
Ch1 = {
DataSource = DDB2
@@ -124,14 +132,14 @@ $TestApp = {
}
}
// ── 1 kHz sine burst channel 2 (phase-shifted by π/2) ──────────────
// ── 10 kHz sine burst channel 2 (LastSample anchor) ──────────────
+SineGAM4 = {
Class = SineArrayGAM
Frequency = 10000.0
Amplitude = 0.5
Phase = 1.5708
Offset = 0.0
SamplingRate = 1000000.0
SamplingRate = 5000000.0
OutputSignals = {
Ch2 = {
DataSource = DDB2
@@ -142,7 +150,7 @@ $TestApp = {
}
}
// ── Route signals into UDPStreamer ────────────────────────────────────
// ── Route scalar signals → Streamer ──────────────────────────────────
+StreamerGAM = {
Class = IOGAM
InputSignals = {
@@ -182,6 +190,8 @@ $TestApp = {
}
}
}
// ── Route packed arrays → FastStreamer (FirstSample + LastSample) ────
+FastStreamerGAM = {
Class = IOGAM
InputSignals = {
@@ -221,21 +231,146 @@ $TestApp = {
}
}
}
// ── 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
// ── Inter-GAM data buffer ────────────────────────────────────────────
+DDB = {
Class = GAMDataSource
}
+DDB2 = {
Class = GAMDataSource
}
+DDB3 = {
Class = GAMDataSource
}
// ── Real-time clock / trigger source ─────────────────────────────────
// ── 1 kHz real-time clock (Thread1) ──────────────────────────────────
+Timer = {
Class = LinuxTimer
SleepNature = "Default"
@@ -248,6 +383,8 @@ $TestApp = {
}
}
}
// ── 5 kHz fast timer (Thread2 FirstSample / LastSample) ────────────
+FastTimer = {
Class = LinuxTimer
SleepNature = "Default"
@@ -261,7 +398,21 @@ $TestApp = {
}
}
// ── UDP Streamer DataSource ──────────────────────────────────────────
// ── 5 kHz fast timer (Thread3 FullArray) ───────────────────────────
+FullArrTimer = {
Class = LinuxTimer
SleepNature = "Default"
Signals = {
Counter = {
Type = uint32
}
Time = {
Type = uint32
}
}
}
// ── Streamer: scalar signals, PacketTime (port 44500) ─────────────────
+Streamer = {
Class = UDPStreamer
Port = 44500
@@ -289,6 +440,19 @@ $TestApp = {
}
}
}
// ── 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
@@ -312,14 +476,49 @@ $TestApp = {
Unit = "V"
NumberOfDimensions = 1
NumberOfElements = 1000
TimeMode = FirstSample
TimeMode = LastSample
TimeSignal = Time
SamplingRate = 5000000.0
}
}
}
// ── Timing statistics ────────────────────────────────────────────────
// ── 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
}
@@ -331,16 +530,24 @@ $TestApp = {
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}
}
}
}
}
+19 -3
View File
@@ -6,7 +6,10 @@
# ./run.sh --webui # also start the WebUI Go client in the background
# ./run.sh --help # show this message
#
# The WebUI is started with --source "TestApp@127.0.0.1:44500".
# The WebUI is started with three sources:
# Streamer @ 127.0.0.1:44500 (scalar signals, PacketTime, 1 kHz)
# FastStreamer @ 127.0.0.1:44501 (packed arrays, FirstSample/LastSample, 5 kHz)
# FullArrStreamer @ 127.0.0.1:44502 (packed arrays, FullArray, 5 kHz)
# Additional sources and a persistent source list file (--sources-file) can
# be configured directly in the WebUI or by editing this script.
#
@@ -28,7 +31,7 @@ for arg in "$@"; do
case "$arg" in
--webui) START_WEBUI=1 ;;
--help|-h)
sed -n '2,12p' "$0"
sed -n '2,15p' "$0"
exit 0
;;
esac
@@ -54,6 +57,8 @@ UDPSTREAMER_SRC="${REPO_ROOT}/Source/Components/DataSources/UDPStreamer"
UDPSTREAMER_LIB="${REPO_ROOT}/Build/${TARGET}/Components/DataSources/UDPStreamer"
SINEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/SineArrayGAM"
SINEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/SineArrayGAM"
TIMEARRAYGAM_SRC="${REPO_ROOT}/Source/Components/GAMs/TimeArrayGAM"
TIMEARRAYGAM_LIB="${REPO_ROOT}/Build/${TARGET}/Components/GAMs/TimeArrayGAM"
echo "==> Building UDPStreamer (TARGET=${TARGET})..."
make -C "${UDPSTREAMER_SRC}" \
@@ -66,6 +71,12 @@ make -C "${SINEARRAYGAM_SRC}" \
-f Makefile.gcc \
TARGET="${TARGET}" \
2>&1 | tail -5
echo "==> Building TimeArrayGAM (TARGET=${TARGET})..."
make -C "${TIMEARRAYGAM_SRC}" \
-f Makefile.gcc \
TARGET="${TARGET}" \
2>&1 | tail -5
echo "==> Build done."
# ── Build WebUI binary (if requested and not already built) ──────────────────
@@ -83,6 +94,7 @@ COMP="${MARTe2_Components_DIR}/Build/${TARGET}/Components"
export LD_LIBRARY_PATH="\
${UDPSTREAMER_LIB}:\
${SINEARRAYGAM_LIB}:\
${TIMEARRAYGAM_LIB}:\
${MARTe2_DIR}/Build/${TARGET}/Core:\
${COMP}/DataSources/LinuxTimer:\
${COMP}/DataSources/LoggerDataSource:\
@@ -112,6 +124,7 @@ if [ "${START_WEBUI}" -eq 1 ]; then
"${WEBUI_BIN}" \
--source "Streamer@127.0.0.1:44500" \
--source "FastStreamer@127.0.0.1:44501" \
--source "FullArrStreamer@127.0.0.1:44502" \
--listen :8080 &
WEBUI_PID=$!
echo "==> WebUI PID ${WEBUI_PID}"
@@ -126,7 +139,10 @@ if [ ! -x "${MARTE_APP}" ]; then
exit 1
fi
echo "==> Starting MARTe2 application (state=Running, 100 Hz)..."
echo "==> Starting MARTe2 application (state=Running)..."
echo "==> Thread1: scalar signals 1 kHz → port 44500"
echo "==> Thread2: packed arrays 5 kHz → port 44501 (FirstSample / LastSample)"
echo "==> Thread3: FullArray arrays 5 kHz → port 44502 (FullArray)"
echo "==> Press Ctrl+C to stop."
echo ""