Core Architecture (Transport, Codec, Core)
This guide explains the stack beneath the core—how bytes move from transports to the frame codec to the core—and the lifecycle flows (initialize, setup, start/stop streaming, mid-stream edits with replies, reset/shutdown).
For a guide focused specifically on setup order, initial setup versus later setup replacement, and where setup changes can be made, see Setup Order and Modification.
Stack Summary
- Transport (
WSSBaseCode/Interfaces/ITransport.cs)- Serial:
WSSBaseCode/SerialPortTransport.cs; Test:WSSBaseCode/TestModeTransport.cs - Surfaces
BytesReceivedchunks (no message boundary guarantee).
- Serial:
- Frame Codec (
WSSBaseCode/Interfaces/IFrameCodec.cs→WSSBaseCode/WssFrameCodec.cs)- Frames/deframes bytes and validates messages.
- Core (
WSSBaseCode/WssStimulationCore.cs)- State machine: Disconnected → Connecting → SettingUp → Ready → Started → Streaming (→ Error)
- Queues setup steps; non-blocking public calls schedule device edits.
- Background streaming loop sends periodic packets when in
Streaming.
flowchart LR
App[Client / App / UI] --> Core[WssStimulationCore]
Core --> Codec[WssFrameCodec]
Codec --> Transport[ITransport]
Transport --> Device[Device]
Device -. bytes .-> Transport -. frames .-> Codec -. messages .-> Core -. callbacks .-> App
Lifecycle: States and Transitions
stateDiagram-v2
[*] --> Disconnected
Disconnected --> Connecting: Initialize()
Connecting --> SettingUp: ConnectAsync ok
Connecting --> Error: Connect fault
SettingUp --> Ready: Setup queue drains
Ready --> Started: Device reports Started
Started --> Streaming: StartStreamingInternal
Streaming --> SettingUp: ScheduleSetupChange
Streaming --> Error: Unhandled exception
Error --> Disconnected: Shutdown()
Startup and Shutdown Sequence
sequenceDiagram
participant App
participant Core
participant Device
App->>Core: Initialize()
Core->>Device: ConnectAsync()
App->>Core: Tick()
Device-->>Core: Connected
Core->>Core: Observes Connected -> NormalSetup()
Core->>Device: Clear/Create/Config/Edit/Add/Sync/(queued)
Device-->>Core: Replies per step
Core->>Core: Queue drains -> Ready
Core->>Device: Start()
Device-->>Core: Started
Core->>Core: Observes Started -> StartStreamingInternal()
Core->>Device: StreamChange()
Device-->>Core: Error
Core->>Core: Observes Error -> StopStreamingInternal()
Core->>Device: DisconnectAsync()
Device-->>Core: Disconnected
Core->>Device: Dispose()
Device-->>Core: Releases resources
Core-->>App: Disconnected
App->>Core: Shutdown()
Core->>Core: StopStreamingInternal()
Core->>Device: DisconnectAsync()
Device-->>Core: Disconnected
Core->>Device: Dispose()
Device-->>Core: Releases resources
Core-->>App: Disconnected
Notes
NormalSetup()seeds a full device configuration and ends withStartStim(...)for each target.Tick()advances the state machine;StartStreamingInternal()begins the background streaming loop.ErrororShutdown()trigger a safe disconnection process whereDispose()prepares for a newInitialize().
Mid‑Stream Setup (Commands Requiring Replies)
sequenceDiagram
participant App
participant Core
participant Device
App->>Core: e.g., Request_Configs(cmd,id)
Core->>Core: StopStreamingInternal()
Core->>Device: Send command (await reply)
Device-->>Core: Reply or timeout
alt Success
alt Queue empty
Core->>Core: StartStreamingInternal()
Core->>Device: StreamChange()
else Queue not empty
Core ->> Core: Repeat with next in queue
end
else Timeout/Error
Core->>Device: DisconnectAsync()
Device-->>Core: Disconnected
Core->>Device: Dispose()
Device-->>Core: Releases resources
Core-->>App: Disconnected
end
Behavior
- Public mutators (e.g.,
StartStim,StopStim,UpdateIPD, waveform edit/load/save/load) callScheduleSetupChangeAsync. - If currently
Streaming, streaming pauses once for the batch, then resumes automatically when the queue drains. - Steps await replies;
StepLoggerthrows on deviceError:or timeout.
Start and Stop
- Start
- From
Ready, callingStartStim(...)schedules a start step; when the device reports started, state advances and streaming begins.
- From
- Stop
- Calling
StopStim(...)schedules stop; if streaming, the core also stops the streaming loop immediately. After the queue drains, streaming resumes if further edits are pending/resume was requested. - To fully stop activity, follow with
Shutdown()or avoid scheduling additional edits.
- Calling
Reset and Shutdown
- Reset (device MCU): use
WssClient.Reset(...)as a scheduled setup step so the core pauses streaming and waits for the reply before resuming. Example:
_ = ScheduleSetupChangeAsync(WssTarget.Wss1,
() => StepLogger(_wss.Reset(WssTarget.Wss1), "Reset[Wss1]"));
- Shutdown
Shutdown()stops streaming, attemptsZeroOutStim(), disconnects, and disposes transport/client.
Edge Cases
- Scheduling edits while
SettingUpappends to the queue; the runner performs additional passes until empty. - Errors during setup set state to
Error;Tick()then stops streaming and disconnects. - Long-running streaming: periodic packets are sent per WSS at the configured cadence; unchanged parameters send minimal data.
Optional Basic Stimulation Layer
IBasicStimulationaugments the core with waveform/event/config operations. In the current implementation,WssStimulationCoreimplements this interface and routes calls throughScheduleSetupChangeAsync, which:- Pauses streaming if active, enqueues setup steps that await device replies, and resumes streaming when the queue drains.
- Ensures mid-stream edits are safe and ordered across targets.
- Future: split into finer capabilities (waveform upload, event editing, config persistence/query) to align with firmware/hardware feature variations.
Navigation: