Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ if(ARIEC61850_BUILD_TESTS)
add_test(NAME ariec61850_${test_name}_tests COMMAND ariec61850_${test_name}_tests)
endforeach()

add_executable(ariec61850_live_signal_tests tests/test_live_signal.cpp)
target_link_libraries(ariec61850_live_signal_tests PRIVATE ARIEC61850::core)
target_compile_features(ariec61850_live_signal_tests PRIVATE cxx_std_20)
ariec61850_apply_warnings(ariec61850_live_signal_tests)
ariec61850_apply_sanitizers(ariec61850_live_signal_tests)
add_test(NAME ariec61850_live_signal_tests COMMAND ariec61850_live_signal_tests)

add_executable(ariec61850_goose_runtime_tests tests/test_goose_runtime.cpp)
target_link_libraries(ariec61850_goose_runtime_tests PRIVATE ARIEC61850::core)
target_compile_features(ariec61850_goose_runtime_tests PRIVATE cxx_std_20)
Expand Down Expand Up @@ -341,4 +348,4 @@ if(ARIEC61850_BUILD_FUZZERS)
ariec61850_add_fuzzer(ariec61850_fuzz_mms_services fuzz/fuzz_mms_services.cpp)
ariec61850_add_fuzzer(ariec61850_fuzz_mms_file_service fuzz/fuzz_mms_file_service.cpp)
ariec61850_add_fuzzer(ariec61850_fuzz_reporting fuzz/fuzz_reporting.cpp)
endif()
endif()
24 changes: 24 additions & 0 deletions docs/LIVE_INJECTION_STATE_MACHINE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Live injection state machine

The deterministic publisher separates profile lifecycle from live signal lifecycle.

```text
NO_PROFILE
|
v
PROFILE_VALIDATED
|
v
ARMED
|
+---- START ----> RUNNING
| |
| +---- live signal generation N -> N+1
| +---- live signal generation N+1 -> N+2
| |
| +---- STOP ----> STOPPED
| |
+--------------------------------------+
```

Profile identity/layout changes are rejected while RUNNING. Live signal-state changes are allowed and committed coherently at a sample boundary. A development serial transport is currently used to prove this behavior; it will later be replaced by the versioned host/device control protocol without changing the realtime state semantics.
129 changes: 129 additions & 0 deletions docs/LIVE_INJECTION_WORKFLOW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Live Sampled Values Injection Workflow

ARStack61850 targets an instrument workflow in which engineering intent is imported once, validated into a deterministic runtime profile, and signal values can then be changed while the publisher is running without rebuilding firmware or changing the canonical stream identity.

## User workflow

```text
Import SCL / CID / SCD / IID
|
v
Select and validate an SV stream
|
v
Resolve Class-A publisher profile
|
v
Configure initial signal values
|
v
Deploy profile to dedicated hardware
|
v
START
|
+---- live value / phase / frequency changes
|
+---- quality/state changes
|
+---- scenario transitions
|
v
STOP
```

The desktop/host side is the engineering and control plane. The ESP32-P4 is the deterministic realtime execution plane.

## Separation of immutable and mutable state

A running stream has two categories of state.

### Immutable while armed/running

These values define the stream/profile and are not edited in the per-sample hot path:

- destination MAC;
- APPID;
- VLAN / PCP;
- svID and DataSet field-presence policy;
- confRev;
- nofASDU;
- sample-rate / sample-mode policy;
- validated sample-counter policy;
- ordered wire layout and payload widths;
- optional ASDU field policy.

Changing an immutable property requires STOP -> validate/rebuild template -> ARM/START. This prevents half-updated frames.

### Mutable while running

These values are intentionally live:

- per-channel magnitude or raw wire-count target;
- per-channel phase;
- signal frequency where supported by the active signal model;
- quality values;
- scenario/fault state;
- waveform source selector and transition state.

A mutable update must become visible atomically at a sample boundary. The realtime task never parses text/XML, allocates memory, takes a host-facing mutex, or rebuilds BER structures.

## Runtime state machine

```text
EMPTY
-> PROFILE_VALIDATED
-> ARMED
-> RUNNING
-> STOPPED

RUNNING --live signal update--> RUNNING
RUNNING --profile change------> reject; STOP required
```

`START` begins deterministic publication from a validated/armed profile. `STOP` stops canonical publication without destroying the profile. Live signal updates are accepted during RUNNING and committed as one coherent generation.

## Coherent live update model

The host/control task writes a complete next signal state into an inactive bank and then publishes a generation/index atomically. The realtime publisher copies one coherent generation at the start of a sample and uses only that snapshot for the whole payload.

```text
control task realtime publisher
------------ ------------------
copy active state
edit inactive bank
validate values
publish generation ----atomic----> copy coherent generation
synthesize one sample
patch prebuilt frame
transmit
```

This prevents mixed-channel updates such as Ia from a new command while Ib/Ic still belong to an older command.

## Signal synthesis

The first live engine uses a fixed-point phase accumulator plus a precomputed sine lookup table. Floating-point initialization is outside the realtime sample path; the sample hot path uses bounded integer work.

A continuous phase accumulator allows magnitude, phase and frequency changes without restarting `smpCnt`. Frequency changes alter the next phase increment while preserving phase continuity. If realtime notifications are missed, both sample-count state and signal phase advance by the missed-slot count rather than replaying stale samples.

The first bench control surface uses the serial console for direct hardware testing. It is a development transport only. The product control plane will use a versioned bounded command protocol and the same live-state semantics.

## Safety and interoperability

- canonical profile identity is never changed by a live signal-value command;
- profile changes require explicit stop/re-arm;
- `smpSynch` remains evidence-driven and is never promoted by a user value edit;
- SCL/profile scaling and semantic mapping stay host/profile responsibilities; raw wire-count control remains available for exact interoperability testing;
- unsupported channel semantics are rejected rather than guessed;
- diagnostic streams remain separate from canonical output.

## Acceptance path

1. Load a vendor-neutral SCL regression profile and resolve it to Class A.
2. Configure initial 4I+4V values.
3. Start the ESP32-P4 publisher and verify canonical identity/layout.
4. Change Ia/Uc/phase/frequency while RUNNING.
5. Verify the next coherent generation is visible on wire without sequence reset, malformed payload, or mixed-generation channels.
6. Verify STOP suppresses canonical TX and START resumes according to the runtime policy.
7. Repeat for 4000 and 4800 events/s profile families once compiled-device profiles are integrated.
1 change: 1 addition & 0 deletions embedded/esp32p4_smv_injector/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ idf_component_register(
SRCS
"app_main.cpp"
"ethernet_port.c"
"live_control.cpp"
INCLUDE_DIRS "."
REQUIRES arstack_process_bus esp_eth esp_event esp_timer esp_driver_gptimer freertos)

Expand Down
Loading
Loading