#ifndef PLSR_PLATFORM_H #define PLSR_PLATFORM_H #include "plsr_internal.h" #include typedef enum { PLSR_PLATFORM_STOP_COMPLETE = 0, PLSR_PLATFORM_STOP_PENDING, PLSR_PLATFORM_STOP_FORCED_FAULT } PLSR_PLATFORM_STOP_RESULT; typedef enum { PLSR_PLATFORM_QUEUE_FAILED = 0, PLSR_PLATFORM_QUEUE_APPLIED, PLSR_PLATFORM_QUEUE_STALE } PLSR_PLATFORM_QUEUE_RESULT; typedef enum { PLSR_PLATFORM_SERVICE_FAILED = 0, PLSR_PLATFORM_SERVICE_READY, PLSR_PLATFORM_SERVICE_DEFERRED } PLSR_PLATFORM_SERVICE_RESULT; typedef struct { uint32_t actualFrequencyHz; uint16_t prescaler; uint16_t pairPrescaler; uint16_t period; uint16_t compare; } PLSR_PLATFORM_TIMER_SETTING; typedef struct { PLSR_PLATFORM_TIMER_SETTING setting; uint32_t pulseCount; uint32_t segmentPulseOffset; uint8_t segmentNumber; uint8_t completesSegment; uint8_t updatesWithSegment; } PLSR_PLATFORM_FINITE_STEP; uint8_t PlsrPlatformInit(void); uint8_t PlsrPlatformPrepare(uint8_t pulseOutput, uint8_t directionOutput, uint8_t directionLevel, uint8_t outputMode, uint8_t directionPositive); uint8_t PlsrPlatformStartPulse(uint8_t pulseOutput, uint32_t firstFrequencyHz, uint32_t queuedFrequencyHz, uint32_t *actualFirstFrequencyHz, uint32_t *actualQueuedFrequencyHz); uint8_t PlsrPlatformBuildTimerSetting( uint8_t pulseOutput, uint8_t outputMode, uint32_t requestedFrequencyHz, PLSR_PLATFORM_TIMER_SETTING *setting); uint8_t PlsrPlatformStartPrepared( uint8_t pulseOutput, const PLSR_PLATFORM_TIMER_SETTING *firstSetting, const PLSR_PLATFORM_TIMER_SETTING *queuedSetting, uint32_t *actualFirstFrequencyHz, uint32_t *actualQueuedFrequencyHz); uint8_t PlsrPlatformSupportsFinitePulseTrain(void); uint8_t PlsrPlatformStartFinitePrepared( uint8_t pulseOutput, const PLSR_PLATFORM_TIMER_SETTING *setting, uint32_t pulseCount, uint32_t *actualFrequencyHz); uint8_t PlsrPlatformStartCountedStreamPrepared( uint8_t pulseOutput, const PLSR_PLATFORM_TIMER_SETTING *setting, uint32_t pulseCount, uint32_t *actualFrequencyHz); uint8_t PlsrPlatformStartFiniteSequencePrepared( uint8_t pulseOutput, PLSR_PLATFORM_FINITE_STEP *steps, uint16_t stepCount, uint32_t *actualFrequencyHz); PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformUpdateFinitePrepared( uint8_t pulseOutput, const PLSR_PLATFORM_TIMER_SETTING *setting, uint32_t *actualFrequencyHz); uint8_t PlsrPlatformRetargetFiniteStop(uint8_t pulseOutput, uint32_t drainPulses); uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput); uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput, uint32_t *activeFrequencyHz); uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, uint64_t *observedPulses, uint32_t *committedPulses, uint64_t *committedTimeUs, uint32_t *tailFrequencyHz, uint8_t *startsNextSegment); uint8_t PlsrPlatformFiniteProgress(uint8_t pulseOutput, uint32_t *completedPulses); uint8_t PlsrPlatformTakeFiniteCompletion(uint8_t pulseOutput, uint32_t *completedPulses); uint8_t PlsrPlatformTakeFiniteBoundary(uint8_t pulseOutput, uint8_t *segmentNumber, uint32_t *completedPulses, uint8_t *sequenceContinues, uint32_t *activeFrequencyHz); /* Counted-stream callbacks are owned by the executor in plsr.c. The platform invokes them only at a hardware counter run boundary. These callbacks must only latch events/snapshots; all bookkeeping runs in the 1 ms task. */ uint8_t PlsrExecTakeCountedRunIrq( uint8_t pulseOutput, PLSR_PLATFORM_TIMER_SETTING *setting, uint32_t *pulseCount, uint8_t *startsNextSegment); void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput, uint32_t completedPulses); void PlsrExecCountedStreamFaultIrq(uint8_t pulseOutput); /* EXTI callback: records an armed WAIT or active EXT input edge. */ void PlsrWaitInputExtiIrq(uint8_t inputSelection); PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq( uint8_t pulseOutput, const PLSR_PLATFORM_TIMER_SETTING *setting, uint32_t *actualFrequencyHz); void PlsrPlatformGateFromIrq(uint8_t pulseOutput); PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformQueueFrequency( uint8_t pulseOutput, uint32_t frequencyHz, uint32_t *actualFrequencyHz); void PlsrPlatformDrainPendingPulse(uint8_t pulseOutput); uint32_t PlsrPlatformActiveFrequency(uint8_t pulseOutput); uint8_t PlsrPlatformExpectedFrequency(uint8_t pulseOutput, uint8_t outputMode, uint32_t requestedFrequencyHz, uint32_t *actualFrequencyHz); uint64_t PlsrPlatformObservedPulses(uint8_t pulseOutput); /* Returns 0, PLSR diagnostic reason 2 (frequency), or 3 (curve/order). */ uint16_t PlsrPlatformDiagnosticFault(void); /* Caller must hold the platform critical section. */ PLSR_PLATFORM_STOP_RESULT PlsrPlatformRequestStopLocked( uint8_t pulseOutput, uint8_t requireZeroBoundary); uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput); void PlsrPlatformStopPulse(uint8_t pulseOutput); uint8_t PlsrPlatformReadInput(uint8_t inputSelection); /* Called from the counted-boundary IRQ before the EXT capture context moves to the next segment. Returns and clears a rising edge pending in EXTI. */ uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection); uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload); PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void); uint8_t PlsrPlatformSave(const PLSR_PERSIST_PAYLOAD *payload); void PlsrPlatformCheckpointConfig(const PLSR_CONFIG *config); void PlsrPlatformCheckpointPosition(int32_t position, uint8_t positionValid, uint8_t wasBusy); void PlsrPlatformForceSafeOutputsFromFault(void); uint32_t PlsrPlatformEnterCritical(void); void PlsrPlatformExitCritical(uint32_t state); #endif /* PLSR_PLATFORM_H */