|
|
|
@@ -73,6 +73,9 @@ |
|
|
|
#define PLSR_REPLAN_PREFIX_ITEMS (512U) |
|
|
|
#define PLSR_REPLAN_PREFIX_TIME_US (5000ULL) |
|
|
|
#define PLSR_REPLAN_BUILD_ITEMS (400U) |
|
|
|
/* Cap equal-frequency counted runs so an online update never waits behind an |
|
|
|
arbitrarily long steady run. At low speed one complete pulse is the limit. */ |
|
|
|
#define PLSR_COUNTED_RUN_MAX_TIME_US (2000ULL) |
|
|
|
#define PLSR_BOUNDARY_EVENT_CAPACITY (2U) |
|
|
|
#if ((PLSR_BOUNDARY_EVENT_CAPACITY == 0U) \ |
|
|
|
|| ((PLSR_BOUNDARY_EVENT_CAPACITY \ |
|
|
|
@@ -171,6 +174,7 @@ typedef struct |
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
uint64_t magnitude; |
|
|
|
uint64_t commandMagnitude; |
|
|
|
uint32_t firstFrequencyHz; |
|
|
|
uint32_t secondFrequencyHz; |
|
|
|
uint32_t firstRequestedFrequencyHz; |
|
|
|
@@ -191,6 +195,7 @@ typedef struct |
|
|
|
typedef struct |
|
|
|
{ |
|
|
|
uint64_t magnitude; |
|
|
|
uint64_t commandMagnitude; |
|
|
|
uint32_t firstFrequencyHz; |
|
|
|
uint32_t completedPulses; |
|
|
|
uint8_t nextSegment; |
|
|
|
@@ -269,6 +274,9 @@ static PLSR_CONFIG PlsrActiveConfig; |
|
|
|
static PLSR_CONFIG PlsrCandidateConfig; |
|
|
|
static volatile int32_t PlsrPosition; |
|
|
|
static volatile uint64_t PlsrRemainingPulses; |
|
|
|
/* Full configured displacement still available in the active segment. ACT |
|
|
|
may publish a shorter execution profile without discarding this ceiling. */ |
|
|
|
static volatile uint64_t PlsrCommandRemainingPulses; |
|
|
|
static volatile uint8_t PlsrPulseActive; |
|
|
|
static volatile uint8_t PlsrCutRequested; |
|
|
|
static volatile uint8_t PlsrActTimedCutPlanned; |
|
|
|
@@ -424,10 +432,15 @@ static uint8_t PlsrShortProfileTakeRunLimited( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
PLSR_PROFILE_ENTRY *entry, |
|
|
|
uint32_t maximumRepeats); |
|
|
|
static uint32_t PlsrProfileRunLimit(uint32_t frequencyHz); |
|
|
|
static uint8_t PlsrLimitProfileToActTime( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
uint16_t actTimeMs, |
|
|
|
uint8_t *timedCutPlanned); |
|
|
|
static uint8_t PlsrLimitProfileToActTimeUs( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
uint32_t actTimeUs, |
|
|
|
uint8_t *timedCutPlanned); |
|
|
|
static void PlsrProfileRecordPlannerStatus( |
|
|
|
const PLSR_SHORT_PROFILE *profile); |
|
|
|
static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
@@ -1894,9 +1907,9 @@ static uint8_t PlsrPrepareShortProfile(PLSR_SHORT_PROFILE *profile, |
|
|
|
block.exitHz = 0UL; |
|
|
|
block.pulseBudget = (uint32_t)pulseCount; |
|
|
|
block.referenceSpeedHz = PlsrActiveConfig.defaultSpeedHz; |
|
|
|
block.accelerationTimeMs = PlsrActiveConfig.accelerationTimeMs; |
|
|
|
block.decelerationTimeMs = PlsrActiveConfig.decelerationTimeMs; |
|
|
|
block.curveMode = PlsrActiveConfig.curveMode; |
|
|
|
block.accelerationTimeMs = frequencyConfig->accelerationTimeMs; |
|
|
|
block.decelerationTimeMs = frequencyConfig->decelerationTimeMs; |
|
|
|
block.curveMode = frequencyConfig->curveMode; |
|
|
|
block.pulseOutput = (uint8_t)PlsrActiveConfig.pulseOutput; |
|
|
|
block.boundary = PLSR_BOUNDARY_STOP; |
|
|
|
|
|
|
|
@@ -1916,7 +1929,9 @@ static uint8_t PlsrPrepareShortProfile(PLSR_SHORT_PROFILE *profile, |
|
|
|
} |
|
|
|
else if (nextSegment == 0U) |
|
|
|
{ |
|
|
|
block.exitHz = PlsrEffectiveStopFrequency(targetFrequencyHz); |
|
|
|
block.exitHz = (frequencyConfig->decelerationTimeMs == 0U) |
|
|
|
? targetFrequencyHz |
|
|
|
: PlsrActiveConfig.stopSpeedHz; |
|
|
|
} |
|
|
|
else if (segment->waitType == PLSR_EXT_OR_COMPLETE) |
|
|
|
{ |
|
|
|
@@ -1956,6 +1971,27 @@ static uint8_t PlsrShortProfileTakeRun(PLSR_SHORT_PROFILE *profile, |
|
|
|
return PlsrShortProfileTakeRunLimited(profile, entry, 0xFFFFFFFFUL); |
|
|
|
} |
|
|
|
|
|
|
|
static uint32_t PlsrProfileRunLimit(uint32_t frequencyHz) |
|
|
|
{ |
|
|
|
uint64_t limit; |
|
|
|
|
|
|
|
if (PlsrActiveConfig.outputMode != PLSR_OUTPUT_PULSE_DIR) |
|
|
|
{ |
|
|
|
return 0xFFFFFFFFUL; |
|
|
|
} |
|
|
|
if (frequencyHz == 0UL) |
|
|
|
{ |
|
|
|
return 1UL; |
|
|
|
} |
|
|
|
limit = ((uint64_t)frequencyHz * PLSR_COUNTED_RUN_MAX_TIME_US |
|
|
|
+ 999999ULL) / 1000000ULL; |
|
|
|
if (limit == 0ULL) |
|
|
|
{ |
|
|
|
return 1UL; |
|
|
|
} |
|
|
|
return (limit > 0xFFFFFFFFULL) ? 0xFFFFFFFFUL : (uint32_t)limit; |
|
|
|
} |
|
|
|
|
|
|
|
static uint8_t PlsrShortProfileTakeRunLimited( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
PLSR_PROFILE_ENTRY *entry, |
|
|
|
@@ -1978,6 +2014,15 @@ static uint8_t PlsrShortProfileTakeRunLimited( |
|
|
|
} |
|
|
|
profile->pendingRepeats = profile->pendingItem.repeatCount; |
|
|
|
} |
|
|
|
{ |
|
|
|
uint32_t runLimit = PlsrProfileRunLimit( |
|
|
|
profile->pendingItem.setting.actualFrequencyHz); |
|
|
|
|
|
|
|
if (maximumRepeats > runLimit) |
|
|
|
{ |
|
|
|
maximumRepeats = runLimit; |
|
|
|
} |
|
|
|
} |
|
|
|
repeatCount = profile->pendingRepeats; |
|
|
|
if (repeatCount > profile->pulseCount - profile->nextPeriod) |
|
|
|
{ |
|
|
|
@@ -2017,6 +2062,15 @@ static uint8_t PlsrLimitProfileToActTime( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
uint16_t actTimeMs, |
|
|
|
uint8_t *timedCutPlanned) |
|
|
|
{ |
|
|
|
return PlsrLimitProfileToActTimeUs( |
|
|
|
profile, (uint32_t)actTimeMs * 1000UL, timedCutPlanned); |
|
|
|
} |
|
|
|
|
|
|
|
static uint8_t PlsrLimitProfileToActTimeUs( |
|
|
|
PLSR_SHORT_PROFILE *profile, |
|
|
|
uint32_t actTimeUs, |
|
|
|
uint8_t *timedCutPlanned) |
|
|
|
{ |
|
|
|
PLSR_PLANNER_TIME_PREDICTION prediction; |
|
|
|
|
|
|
|
@@ -2025,8 +2079,7 @@ static uint8_t PlsrLimitProfileToActTime( |
|
|
|
return 0U; |
|
|
|
} |
|
|
|
*timedCutPlanned = 0U; |
|
|
|
if (PlsrPlannerPredictTime(&profile->planner, |
|
|
|
(uint32_t)actTimeMs * 1000UL, |
|
|
|
if (PlsrPlannerPredictTime(&profile->planner, actTimeUs, |
|
|
|
&prediction) == 0U) |
|
|
|
{ |
|
|
|
return 0U; |
|
|
|
@@ -2062,8 +2115,11 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
PLSR_SHORT_PROFILE replacement; |
|
|
|
PLSR_SHORT_PROFILE candidate; |
|
|
|
PLSR_PROFILE_ENTRY entry; |
|
|
|
uint64_t committedTimeUs; |
|
|
|
uint64_t prefixTimeUs = 0ULL; |
|
|
|
uint64_t prefixTimeLimitUs = PLSR_REPLAN_PREFIX_TIME_US; |
|
|
|
uint64_t prefixPulses = 0ULL; |
|
|
|
uint64_t remainingActTimeUs = 0ULL; |
|
|
|
uint32_t committedPulses; |
|
|
|
uint32_t tailFrequencyHz; |
|
|
|
uint32_t sourceGeneration; |
|
|
|
@@ -2078,6 +2134,7 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
uint32_t sourceIndex; |
|
|
|
uint32_t criticalState; |
|
|
|
uint32_t epoch; |
|
|
|
uint32_t segmentElapsedMs; |
|
|
|
uint8_t segmentNumber; |
|
|
|
uint8_t handoffBank; |
|
|
|
uint8_t sourceBank; |
|
|
|
@@ -2085,6 +2142,8 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
uint8_t boundaryWriteIndex; |
|
|
|
uint8_t pipelineStartsNextSegment = 0U; |
|
|
|
uint8_t tailWasClipped = 0U; |
|
|
|
uint8_t actTimeLimited = 0U; |
|
|
|
uint8_t actTimedCutPlanned = 0U; |
|
|
|
uint16_t fillBudget = PLSR_REPLAN_BUILD_ITEMS; |
|
|
|
|
|
|
|
criticalState = PlsrPlatformEnterCritical(); |
|
|
|
@@ -2097,6 +2156,7 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
snapshotWriteIndex = source->writeIndex; |
|
|
|
epoch = PlsrSegmentEpoch; |
|
|
|
segmentNumber = PlsrCurrentSegment; |
|
|
|
segmentElapsedMs = PlsrSegmentElapsedMs; |
|
|
|
handoffBank = PlsrPreparedHandoffBank; |
|
|
|
boundaryWriteIndex = PlsrCountedBoundaryWriteIndex; |
|
|
|
if ((PlsrPulseActive == 0U) || (segmentNumber == 0U) |
|
|
|
@@ -2111,9 +2171,23 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
return PLSR_PLATFORM_SERVICE_DEFERRED; |
|
|
|
} |
|
|
|
if ((forceTerminalExit == 0U) |
|
|
|
&& (PlsrActiveConfig.segments[segmentNumber - 1U].waitType |
|
|
|
== PLSR_ACT_TIME)) |
|
|
|
{ |
|
|
|
uint32_t actTimeMs = |
|
|
|
PlsrActiveConfig.segments[segmentNumber - 1U].actTimeMs; |
|
|
|
|
|
|
|
actTimeLimited = 1U; |
|
|
|
if (actTimeMs > segmentElapsedMs) |
|
|
|
{ |
|
|
|
remainingActTimeUs = |
|
|
|
(uint64_t)(actTimeMs - segmentElapsedMs) * 1000ULL; |
|
|
|
} |
|
|
|
} |
|
|
|
if (PlsrPlatformFinitePipelineSnapshot( |
|
|
|
(uint8_t)PlsrActiveConfig.pulseOutput, |
|
|
|
&committedPulses, &tailFrequencyHz, |
|
|
|
&committedPulses, &committedTimeUs, &tailFrequencyHz, |
|
|
|
&pipelineStartsNextSegment) == 0U) |
|
|
|
{ |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
@@ -2133,6 +2207,19 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
totalPulses = committedPulses; |
|
|
|
} |
|
|
|
availablePlanPulses = totalPulses - committedPulses; |
|
|
|
if (actTimeLimited != 0U) |
|
|
|
{ |
|
|
|
if (committedTimeUs >= remainingActTimeUs) |
|
|
|
{ |
|
|
|
prefixTimeLimitUs = 0ULL; |
|
|
|
actTimedCutPlanned = 1U; |
|
|
|
} |
|
|
|
else if ((remainingActTimeUs - committedTimeUs) |
|
|
|
< prefixTimeLimitUs) |
|
|
|
{ |
|
|
|
prefixTimeLimitUs = remainingActTimeUs - committedTimeUs; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
destination->readIndex = 0UL; |
|
|
|
destination->writeIndex = 0UL; |
|
|
|
@@ -2150,7 +2237,7 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
while ((sourceIndex != snapshotWriteIndex) |
|
|
|
&& (prefixCount < PLSR_REPLAN_PREFIX_ITEMS) |
|
|
|
&& (prefixPulses < availablePlanPulses) |
|
|
|
&& (prefixTimeUs < PLSR_REPLAN_PREFIX_TIME_US)) |
|
|
|
&& (prefixTimeUs < prefixTimeLimitUs)) |
|
|
|
{ |
|
|
|
uint32_t remainingPrefixPulses = |
|
|
|
availablePlanPulses - (uint32_t)prefixPulses; |
|
|
|
@@ -2170,7 +2257,7 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
return PLSR_PLATFORM_SERVICE_FAILED; |
|
|
|
} |
|
|
|
remainingPrefixTimeUs = |
|
|
|
PLSR_REPLAN_PREFIX_TIME_US - prefixTimeUs; |
|
|
|
prefixTimeLimitUs - prefixTimeUs; |
|
|
|
timeLimitedPulses = |
|
|
|
(remainingPrefixTimeUs * frequencyHz + 999999ULL) / 1000000ULL; |
|
|
|
if (timeLimitedPulses == 0ULL) |
|
|
|
@@ -2198,6 +2285,13 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
} |
|
|
|
|
|
|
|
replacementPulses = availablePlanPulses - (uint32_t)prefixPulses; |
|
|
|
if ((actTimeLimited != 0U) |
|
|
|
&& ((committedTimeUs + prefixTimeUs) >= remainingActTimeUs)) |
|
|
|
{ |
|
|
|
replacementPulses = 0UL; |
|
|
|
totalPulses = committedPulses + (uint32_t)prefixPulses; |
|
|
|
actTimedCutPlanned = 1U; |
|
|
|
} |
|
|
|
replacementStartIndex = prefixCount; |
|
|
|
if (replacementPulses != 0UL) |
|
|
|
{ |
|
|
|
@@ -2211,6 +2305,24 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
{ |
|
|
|
return PLSR_PLATFORM_SERVICE_FAILED; |
|
|
|
} |
|
|
|
if (actTimeLimited != 0U) |
|
|
|
{ |
|
|
|
uint64_t consumedTimeUs = committedTimeUs + prefixTimeUs; |
|
|
|
uint64_t replacementTimeUs = |
|
|
|
(remainingActTimeUs > consumedTimeUs) |
|
|
|
? remainingActTimeUs - consumedTimeUs : 0ULL; |
|
|
|
|
|
|
|
if ((replacementTimeUs > 0xFFFFFFFFULL) |
|
|
|
|| (PlsrLimitProfileToActTimeUs( |
|
|
|
&replacement, (uint32_t)replacementTimeUs, |
|
|
|
&actTimedCutPlanned) == 0U)) |
|
|
|
{ |
|
|
|
return PLSR_PLATFORM_SERVICE_FAILED; |
|
|
|
} |
|
|
|
replacementPulses = replacement.pulseCount; |
|
|
|
totalPulses = committedPulses + (uint32_t)prefixPulses |
|
|
|
+ replacementPulses; |
|
|
|
} |
|
|
|
PlsrCopyShortProfile(&destination->producerProfile, &replacement); |
|
|
|
destination->active = 1U; |
|
|
|
candidate = replacement; |
|
|
|
@@ -2229,6 +2341,11 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
&& (PlsrTimerSettingsEqual( |
|
|
|
&destination->entries[prefixCount - 1UL].setting, |
|
|
|
&entry.setting) != 0U) |
|
|
|
&& (entry.repeatCount <= PlsrProfileRunLimit( |
|
|
|
entry.setting.actualFrequencyHz)) |
|
|
|
&& (destination->entries[prefixCount - 1UL].repeatCount |
|
|
|
<= (PlsrProfileRunLimit(entry.setting.actualFrequencyHz) |
|
|
|
- entry.repeatCount)) |
|
|
|
&& (destination->entries[prefixCount - 1UL].repeatCount |
|
|
|
<= (0xFFFFFFFFUL - entry.repeatCount))) |
|
|
|
{ |
|
|
|
@@ -2278,7 +2395,7 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrReplanPulseDir( |
|
|
|
PlsrRamp.active = 0U; |
|
|
|
PlsrHandoffPlan.valid = 0U; |
|
|
|
PlsrCountedHandoffStaged = 0U; |
|
|
|
PlsrActTimedCutPlanned = 0U; |
|
|
|
PlsrActTimedCutPlanned = actTimedCutPlanned; |
|
|
|
PlsrProfileQueueBank = destinationBank; |
|
|
|
PlsrCopyShortProfile(&PlsrShortProfile, |
|
|
|
&destination->producerProfile); |
|
|
|
@@ -2489,6 +2606,12 @@ static uint8_t PlsrProfileQueueAppendLocked( |
|
|
|
&& (entry->startsNextSegment == 0U) |
|
|
|
&& (PlsrTimerSettingsEqual( |
|
|
|
&previous->setting, &entry->setting) != 0U) |
|
|
|
&& (entry->repeatCount <= PlsrProfileRunLimit( |
|
|
|
previous->setting.actualFrequencyHz)) |
|
|
|
&& (previous->repeatCount |
|
|
|
<= (PlsrProfileRunLimit( |
|
|
|
previous->setting.actualFrequencyHz) |
|
|
|
- entry->repeatCount)) |
|
|
|
&& (previous->repeatCount |
|
|
|
<= (0xFFFFFFFFUL - entry->repeatCount))) |
|
|
|
{ |
|
|
|
@@ -3476,6 +3599,10 @@ static PLSR_PLATFORM_SERVICE_RESULT PlsrTryStartPreparedTimedSegment( |
|
|
|
PlsrDirectionDelayActive = 0U; |
|
|
|
PlsrDirectionDelayRemainingMs = 0U; |
|
|
|
PlsrRemainingPulses = magnitude; |
|
|
|
PlsrCommandRemainingPulses = |
|
|
|
(resolvedDisplacement < 0) |
|
|
|
? (uint64_t)(-resolvedDisplacement) |
|
|
|
: (uint64_t)resolvedDisplacement; |
|
|
|
PlsrCountPositive = positive; |
|
|
|
PlsrActTimedCutPlanned = PlsrTimedStart.nextActTimedCut; |
|
|
|
PlsrTimedStart.pendingActivation = 1U; |
|
|
|
@@ -3782,6 +3909,7 @@ static uint8_t PlsrStartSegment(uint8_t segmentNumber, |
|
|
|
|
|
|
|
criticalState = PlsrPlatformEnterCritical(); |
|
|
|
PlsrRemainingPulses = magnitude; |
|
|
|
PlsrCommandRemainingPulses = magnitude; |
|
|
|
PlsrCountPositive = positive; |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
|
|
|
|
@@ -3890,6 +4018,7 @@ static void PlsrFinishCompleted(void) |
|
|
|
PlsrDisarmWaitSignal(); |
|
|
|
PlsrPlatformStopPulse((uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPulseActive = 0U; |
|
|
|
PlsrCutRequested = 0U; |
|
|
|
PlsrActTimedCutPlanned = 0U; |
|
|
|
@@ -3931,6 +4060,7 @@ static void PlsrFinishStopped(void) |
|
|
|
PlsrDiagnosticFinishSegment(0U); |
|
|
|
PlsrPlatformStopPulse((uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPulseActive = 0U; |
|
|
|
PlsrCutRequested = 0U; |
|
|
|
PlsrActTimedCutPlanned = 0U; |
|
|
|
@@ -3972,6 +4102,7 @@ static void PlsrEnterError(PLSR_ERROR error) |
|
|
|
PlsrDiagnosticFinishSegment(0U); |
|
|
|
PlsrPlatformStopPulse((uint8_t)PlsrActiveConfig.pulseOutput); |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPulseActive = 0U; |
|
|
|
PlsrCutRequested = 0U; |
|
|
|
PlsrActTimedCutPlanned = 0U; |
|
|
|
@@ -4123,6 +4254,7 @@ static uint8_t PlsrBuildHandoffPlan(uint8_t sourceSegment, |
|
|
|
|
|
|
|
plan->magnitude = (displacement < 0) ? (uint64_t)(-displacement) |
|
|
|
: (uint64_t)displacement; |
|
|
|
plan->commandMagnitude = plan->magnitude; |
|
|
|
if (carryFrequencyHz == 0UL) |
|
|
|
{ |
|
|
|
carryFrequencyHz = |
|
|
|
@@ -4419,6 +4551,14 @@ static uint8_t PlsrSyncCountedProgress(void) |
|
|
|
PlsrPosition = (int32_t)nextPosition; |
|
|
|
} |
|
|
|
PlsrRemainingPulses = remaining - delta; |
|
|
|
if (delta >= PlsrCommandRemainingPulses) |
|
|
|
{ |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
PlsrCommandRemainingPulses -= delta; |
|
|
|
} |
|
|
|
PlsrCountedObservedPublished = observed; |
|
|
|
PlsrPositionCheckpointDirty = 1U; |
|
|
|
return 1U; |
|
|
|
@@ -4569,6 +4709,7 @@ void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput, |
|
|
|
event = &PlsrCountedBoundaryEvents[ |
|
|
|
writeIndex & (PLSR_BOUNDARY_EVENT_CAPACITY - 1U)]; |
|
|
|
event->magnitude = PlsrHandoffPlan.magnitude; |
|
|
|
event->commandMagnitude = PlsrHandoffPlan.commandMagnitude; |
|
|
|
event->firstFrequencyHz = PlsrHandoffPlan.firstFrequencyHz; |
|
|
|
event->completedPulses = completedPulses; |
|
|
|
event->nextSegment = PlsrHandoffPlan.nextSegment; |
|
|
|
@@ -4701,6 +4842,7 @@ static void PlsrExecServiceCountedBoundaryEvent(void) |
|
|
|
PlsrSegmentEpoch++; |
|
|
|
PlsrCurrentSegment = nextSegment; |
|
|
|
PlsrRemainingPulses = event.magnitude; |
|
|
|
PlsrCommandRemainingPulses = event.commandMagnitude; |
|
|
|
PlsrCountPositive = event.positive; |
|
|
|
PlsrCurrentFrequencyHz = event.firstFrequencyHz; |
|
|
|
PlsrBoundaryFrequencyHz = event.firstFrequencyHz; |
|
|
|
@@ -4938,6 +5080,7 @@ static PLSR_PLATFORM_QUEUE_RESULT PlsrTryContinuousHandoff(void) |
|
|
|
PlsrSegmentEpoch); |
|
|
|
PlsrCurrentSegment = nextSegment; |
|
|
|
PlsrRemainingPulses = magnitude; |
|
|
|
PlsrCommandRemainingPulses = PlsrHandoffPlan.commandMagnitude; |
|
|
|
PlsrCountPositive = positive; |
|
|
|
PlsrActTimedCutPlanned = PlsrHandoffPlan.nextActTimedCut; |
|
|
|
PlsrBoundaryFrequencyHz = PlsrCurrentFrequencyHz; |
|
|
|
@@ -5426,6 +5569,7 @@ uint8_t PlsrInit(void) |
|
|
|
sizeof(PlsrPreparedHandoffPlans)); |
|
|
|
PlsrPreparedHandoffBank = 0U; |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPulseActive = 0U; |
|
|
|
PlsrCutRequested = 0U; |
|
|
|
PlsrActTimedCutPlanned = 0U; |
|
|
|
@@ -5644,6 +5788,7 @@ static uint8_t PlsrExecuteStop(void) |
|
|
|
drainPulses = 1ULL; |
|
|
|
} |
|
|
|
PlsrRemainingPulses = drainPulses; |
|
|
|
PlsrCommandRemainingPulses = drainPulses; |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
if (PlsrReplanPulseDir(stopTargetHz, |
|
|
|
(uint32_t)drainPulses, 1U) |
|
|
|
@@ -5683,6 +5828,7 @@ static void PlsrExecuteClear(void) |
|
|
|
PlsrPosition = 0L; |
|
|
|
PlsrPositionValid = 1U; |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
PlsrPlatformCheckpointPosition(0L, 1U, 0U); |
|
|
|
PlsrCountOverflowPending = 0U; |
|
|
|
@@ -6031,7 +6177,9 @@ void PlsrPoll1ms(void) |
|
|
|
PlsrBoundaryRampStarted = 0U; |
|
|
|
if (PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR) |
|
|
|
{ |
|
|
|
uint64_t remaining = PlsrRemainingPulses; |
|
|
|
uint64_t remaining = |
|
|
|
(activeSegment->waitType == PLSR_ACT_TIME) |
|
|
|
? PlsrCommandRemainingPulses : PlsrRemainingPulses; |
|
|
|
|
|
|
|
if (PlsrCountedHandoffStaged != 0U) |
|
|
|
{ |
|
|
|
@@ -6039,6 +6187,12 @@ void PlsrPoll1ms(void) |
|
|
|
Leave both untouched; the boundary consumer retargets this |
|
|
|
pending update to the segment that hardware enters. */ |
|
|
|
} |
|
|
|
else if ((activeSegment->waitType == PLSR_ACT_TIME) |
|
|
|
&& (PlsrSegmentElapsedMs >= activeSegment->actTimeMs)) |
|
|
|
{ |
|
|
|
/* The normal deadline path below owns the full-pulse cut. */ |
|
|
|
PlsrFrequencyUpdatePending = 0U; |
|
|
|
} |
|
|
|
else if ((remaining == 0ULL) || (remaining > 0xFFFFFFFFULL)) |
|
|
|
{ |
|
|
|
PlsrFrequencyUpdatePending = 0U; |
|
|
|
@@ -6235,6 +6389,10 @@ void PlsrPulseTimerIrq(uint8_t pulseOutput) |
|
|
|
{ |
|
|
|
remainingPulses--; |
|
|
|
PlsrRemainingPulses = remainingPulses; |
|
|
|
if (PlsrCommandRemainingPulses != 0ULL) |
|
|
|
{ |
|
|
|
PlsrCommandRemainingPulses--; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ((remainingPulses == 0UL) || (PlsrCutRequested != 0U) |
|
|
|
@@ -6467,6 +6625,7 @@ PLSR_MB_RESULT PlsrModbusWriteHolding(uint16_t startAddress, |
|
|
|
uint32_t criticalState; |
|
|
|
uint8_t handoffBank = 0U; |
|
|
|
uint8_t updateActiveFrequencies = 0U; |
|
|
|
uint8_t updateActivePlannerParameters = 0U; |
|
|
|
uint8_t drainedToDifferentSegment = 0U; |
|
|
|
uint8_t segmentBeforeDrain; |
|
|
|
uint32_t drainedSegmentTargetHz = 0UL; |
|
|
|
@@ -6622,8 +6781,19 @@ PLSR_MB_RESULT PlsrModbusWriteHolding(uint16_t startAddress, |
|
|
|
updateActiveFrequencies = 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
if ((PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR) |
|
|
|
&& ((PlsrCandidateConfig.accelerationTimeMs |
|
|
|
!= PlsrShadowConfig.accelerationTimeMs) |
|
|
|
|| (PlsrCandidateConfig.decelerationTimeMs |
|
|
|
!= PlsrShadowConfig.decelerationTimeMs) |
|
|
|
|| (PlsrCandidateConfig.curveMode |
|
|
|
!= PlsrShadowConfig.curveMode))) |
|
|
|
{ |
|
|
|
updateActivePlannerParameters = 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
if (updateActiveFrequencies != 0U) |
|
|
|
if ((updateActiveFrequencies != 0U) |
|
|
|
|| (updateActivePlannerParameters != 0U)) |
|
|
|
{ |
|
|
|
handoffBank = PlsrBuildHandoffPlanBank(&PlsrCandidateConfig); |
|
|
|
} |
|
|
|
@@ -6646,9 +6816,18 @@ PLSR_MB_RESULT PlsrModbusWriteHolding(uint16_t startAddress, |
|
|
|
} |
|
|
|
} |
|
|
|
PlsrShadowConfig = PlsrCandidateConfig; |
|
|
|
if (updateActiveFrequencies != 0U) |
|
|
|
if ((updateActiveFrequencies != 0U) |
|
|
|
|| (updateActivePlannerParameters != 0U)) |
|
|
|
{ |
|
|
|
PlsrInvalidateTimedStartLocked(); |
|
|
|
if (updateActivePlannerParameters != 0U) |
|
|
|
{ |
|
|
|
PlsrActiveConfig.accelerationTimeMs = |
|
|
|
PlsrCandidateConfig.accelerationTimeMs; |
|
|
|
PlsrActiveConfig.decelerationTimeMs = |
|
|
|
PlsrCandidateConfig.decelerationTimeMs; |
|
|
|
PlsrActiveConfig.curveMode = PlsrCandidateConfig.curveMode; |
|
|
|
} |
|
|
|
for (index = 0U; index < PlsrActiveConfig.segmentCount; index++) |
|
|
|
{ |
|
|
|
uint8_t frequencyChanged = |
|
|
|
@@ -6672,7 +6851,8 @@ PLSR_MB_RESULT PlsrModbusWriteHolding(uint16_t startAddress, |
|
|
|
} |
|
|
|
} |
|
|
|
PlsrPreparedHandoffBank = handoffBank; |
|
|
|
if (PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR) |
|
|
|
if ((updateActiveFrequencies != 0U) |
|
|
|
&& (PlsrActiveConfig.outputMode == PLSR_OUTPUT_PULSE_DIR)) |
|
|
|
{ |
|
|
|
/* Publish the new prepared-plan bank without touching the stream |
|
|
|
or handoff metadata already visible to the counter IRQ. A |
|
|
|
@@ -6694,7 +6874,7 @@ PLSR_MB_RESULT PlsrModbusWriteHolding(uint16_t startAddress, |
|
|
|
PlsrFrequencyUpdatePending = 1U; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else if (updateActiveFrequencies != 0U) |
|
|
|
{ |
|
|
|
PlsrHandoffPlan.valid = 0U; |
|
|
|
PlsrProfileQueueInvalidateGeneration(); |
|
|
|
@@ -6781,6 +6961,7 @@ void PlsrTestSetPosition(int32_t position, uint8_t positionValid) |
|
|
|
PlsrPosition = position; |
|
|
|
PlsrPositionValid = (positionValid != 0U) ? 1U : 0U; |
|
|
|
PlsrRemainingPulses = 0UL; |
|
|
|
PlsrCommandRemainingPulses = 0ULL; |
|
|
|
PlsrPositionCheckpointDirty = 0U; |
|
|
|
PlsrPlatformExitCritical(criticalState); |
|
|
|
PlsrPlatformCheckpointPosition(position, PlsrPositionValid, 0U); |
|
|
|
|