245 lines
7.6 KiB
C++
245 lines
7.6 KiB
C++
/* Shared board-authoritative position/range state for every OTA application.
|
|
* This file is included after the motor implementation so it can snapshot and
|
|
* restore the proven per-axis runtime without changing the bundled source. */
|
|
|
|
static bool otaSeatStateLoaded;
|
|
static bool otaSeatLastSaveOk;
|
|
static uint32_t otaSeatPersistedMask;
|
|
static uint32_t otaSeatStateSequence;
|
|
static bool otaSeatJobActive;
|
|
static bool otaSeatJobComplete;
|
|
static bool otaSeatJobSuccess;
|
|
static ota_seat_job_type_t otaSeatJobType = OTA_SEAT_JOB_NONE;
|
|
static ota_seat_job_phase_t otaSeatJobPhase = OTA_SEAT_PHASE_IDLE;
|
|
static uint8_t otaSeatJobAxis = 0x0Fu;
|
|
static uint8_t otaSeatJobError;
|
|
static uint8_t otaSeatJobProgress;
|
|
|
|
static bool OtaSeat_SavePersistentState(void);
|
|
|
|
static uint32_t OtaSeat_RuntimeKind(void)
|
|
{
|
|
#if (MOTOR_OTA_CALIBRATION != 0u)
|
|
return OTA_SEAT_RUNTIME_CALIBRATION;
|
|
#elif (MOTOR_OTA_SELF_COMPOSE != 0u)
|
|
return OTA_SEAT_RUNTIME_DUAL_PROTOCOL;
|
|
#else
|
|
return OTA_SEAT_RUNTIME_FBL;
|
|
#endif
|
|
}
|
|
|
|
static void OtaSeat_RestorePersistentState(void)
|
|
{
|
|
ota_seat_state_data_t stored;
|
|
uint32_t axis;
|
|
uint32_t savedIntrStatus;
|
|
bool normalizePersistentState = false;
|
|
|
|
otaSeatStateLoaded = OtaSeatState_Load(&stored);
|
|
otaSeatLastSaveOk = otaSeatStateLoaded;
|
|
otaSeatPersistedMask = 0ul;
|
|
otaSeatStateSequence = 0ul;
|
|
if(false == otaSeatStateLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
|
otaSeatStateSequence = stored.sequence;
|
|
otaSeatPersistedMask = 0ul;
|
|
for(axis = 0ul; axis < MOTOR_PROFILE_COUNT; axis++)
|
|
{
|
|
uint32_t defaultRange = motorProfiles[axis].defaultMaxHallCount;
|
|
motorRuntime[axis].maxHallCount = defaultRange;
|
|
if((stored.validMask & (1ul << axis)) != 0ul)
|
|
{
|
|
uint32_t position = stored.position[axis];
|
|
|
|
/* The Base owns all four physical Hall ranges. Persistent storage
|
|
* remembers position only and can never override a Base range. */
|
|
if(stored.range[axis] != defaultRange)
|
|
{
|
|
normalizePersistentState = true;
|
|
}
|
|
if(position > defaultRange)
|
|
{
|
|
position = defaultRange;
|
|
normalizePersistentState = true;
|
|
}
|
|
|
|
motorRuntime[axis].positionHallCount = position;
|
|
motorRuntime[axis].positionValid = true;
|
|
otaSeatPersistedMask |= 1ul << axis;
|
|
}
|
|
}
|
|
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
|
|
|
if(false != normalizePersistentState)
|
|
{
|
|
(void)OtaSeat_SavePersistentState();
|
|
}
|
|
}
|
|
|
|
static bool OtaSeat_SavePersistentState(void)
|
|
{
|
|
ota_seat_state_data_t state;
|
|
uint32_t axis;
|
|
uint32_t savedIntrStatus;
|
|
|
|
state.sequence = otaSeatStateSequence + 1ul;
|
|
state.validMask = 0ul;
|
|
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
|
for(axis = 0ul; axis < MOTOR_PROFILE_COUNT; axis++)
|
|
{
|
|
uint32_t range = motorProfiles[axis].defaultMaxHallCount;
|
|
uint32_t position = motorRuntime[axis].positionHallCount;
|
|
motorRuntime[axis].maxHallCount = range;
|
|
if(position > range)
|
|
{
|
|
position = range;
|
|
}
|
|
state.range[axis] = range;
|
|
state.position[axis] = position;
|
|
if(false != motorRuntime[axis].positionValid)
|
|
{
|
|
state.validMask |= 1ul << axis;
|
|
}
|
|
}
|
|
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
|
|
|
otaSeatLastSaveOk = OtaSeatState_Save(&state);
|
|
if(false != otaSeatLastSaveOk)
|
|
{
|
|
otaSeatStateLoaded = true;
|
|
otaSeatStateSequence = state.sequence;
|
|
otaSeatPersistedMask = state.validMask;
|
|
}
|
|
return otaSeatLastSaveOk;
|
|
}
|
|
|
|
static uint32_t OtaSeat_JobStateValue(void)
|
|
{
|
|
uint32_t value =
|
|
((uint32_t)otaSeatJobType << OTA_SEAT_JOB_TYPE_SHIFT) |
|
|
((uint32_t)otaSeatJobPhase << OTA_SEAT_JOB_PHASE_SHIFT) |
|
|
((uint32_t)otaSeatJobAxis << OTA_SEAT_JOB_AXIS_SHIFT) |
|
|
((uint32_t)otaSeatJobError << OTA_SEAT_JOB_ERROR_SHIFT) |
|
|
((uint32_t)otaSeatJobProgress << OTA_SEAT_JOB_PROGRESS_SHIFT);
|
|
|
|
if(false != otaSeatJobActive) value |= OTA_SEAT_JOB_ACTIVE;
|
|
if(false != otaSeatJobComplete) value |= OTA_SEAT_JOB_COMPLETE;
|
|
if(false != otaSeatJobSuccess) value |= OTA_SEAT_JOB_SUCCESS;
|
|
if(false != otaSeatLastSaveOk) value |= OTA_SEAT_JOB_STORAGE_OK;
|
|
return value;
|
|
}
|
|
|
|
static uint32_t OtaSeat_AxisPositionRangeValue(uint32_t axis)
|
|
{
|
|
uint32_t position;
|
|
uint32_t range;
|
|
uint32_t savedIntrStatus;
|
|
|
|
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
|
position = motorRuntime[axis].positionHallCount;
|
|
range = motorRuntime[axis].maxHallCount;
|
|
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
|
if(position > 65535ul) position = 65535ul;
|
|
if(range > 65535ul) range = 65535ul;
|
|
return (range << 16u) | position;
|
|
}
|
|
|
|
static uint32_t OtaSeat_AxisFlagsValue(uint32_t axis)
|
|
{
|
|
uint32_t value;
|
|
uint32_t savedIntrStatus;
|
|
|
|
savedIntrStatus = Cy_SysLib_EnterCriticalSection();
|
|
value = ((uint32_t)motorRuntime[axis].direction <<
|
|
OTA_SEAT_AXIS_DIRECTION_SHIFT) |
|
|
((uint32_t)motorRuntime[axis].lastEvent <<
|
|
OTA_SEAT_AXIS_EVENT_SHIFT);
|
|
if(false != motorRuntime[axis].positionValid)
|
|
{
|
|
value |= OTA_SEAT_AXIS_VALID;
|
|
}
|
|
if((motorRuntime[axis].direction != MOTOR_DIRECTION_STOPPED) ||
|
|
(false != motorRuntime[axis].startPending))
|
|
{
|
|
value |= OTA_SEAT_AXIS_MOVING;
|
|
}
|
|
if(false != motorRuntime[axis].calibrating)
|
|
{
|
|
value |= OTA_SEAT_AXIS_CALIBRATING;
|
|
}
|
|
Cy_SysLib_ExitCriticalSection(savedIntrStatus);
|
|
if(false != driverFaultLatched) value |= OTA_SEAT_AXIS_DRIVER_FAULT;
|
|
if((otaSeatPersistedMask & (1ul << axis)) != 0ul)
|
|
{
|
|
value |= OTA_SEAT_AXIS_PERSISTED;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
static uint32_t OtaSeat_InfoValue(uint8_t selector)
|
|
{
|
|
uint32_t axis;
|
|
|
|
if(selector == OTA_SEAT_INFO_JOB)
|
|
{
|
|
return OtaSeat_JobStateValue();
|
|
}
|
|
if((selector >= OTA_SEAT_INFO_AXIS0_POSITION_RANGE) &&
|
|
(selector <= OTA_SEAT_INFO_AXIS3_POSITION_RANGE))
|
|
{
|
|
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_POSITION_RANGE);
|
|
return OtaSeat_AxisPositionRangeValue(axis);
|
|
}
|
|
if((selector >= OTA_SEAT_INFO_AXIS0_FLAGS) &&
|
|
(selector <= OTA_SEAT_INFO_AXIS3_FLAGS))
|
|
{
|
|
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_FLAGS);
|
|
return OtaSeat_AxisFlagsValue(axis);
|
|
}
|
|
if((selector >= OTA_SEAT_INFO_AXIS0_PHYSICAL_X100) &&
|
|
(selector <= OTA_SEAT_INFO_AXIS3_PHYSICAL_X100))
|
|
{
|
|
axis = (uint32_t)(selector - OTA_SEAT_INFO_AXIS0_PHYSICAL_X100);
|
|
return motorProfiles[axis].maxPhysicalValueX100;
|
|
}
|
|
if(selector == OTA_SEAT_INFO_STORAGE)
|
|
{
|
|
return (otaSeatPersistedMask & 0x0Ful) |
|
|
((false != otaSeatStateLoaded) ? (1ul << 8u) : 0ul) |
|
|
((false != otaSeatLastSaveOk) ? (1ul << 9u) : 0ul) |
|
|
((otaSeatStateSequence & 0xFFFFul) << 16u);
|
|
}
|
|
if(selector == OTA_SEAT_INFO_RUNTIME_KIND)
|
|
{
|
|
return OtaSeat_RuntimeKind();
|
|
}
|
|
return 0ul;
|
|
}
|
|
|
|
static bool OtaSeat_HandleInfoControl(const ota_can_control_frame_t *frame)
|
|
{
|
|
uint8_t selector;
|
|
|
|
if(frame->data[2] != OTA_OPCODE_SEAT_INFO)
|
|
{
|
|
return false;
|
|
}
|
|
selector = frame->data[3];
|
|
if(selector > OTA_SEAT_INFO_RUNTIME_KIND)
|
|
{
|
|
(void)OtaCan_QueueResponse(frame->data[1], frame->data[2],
|
|
OTA_STATUS_BAD_ARGUMENT, selector);
|
|
}
|
|
else
|
|
{
|
|
(void)OtaCan_QueueResponse(frame->data[1], frame->data[2],
|
|
OTA_STATUS_OK,
|
|
OtaSeat_InfoValue(selector));
|
|
}
|
|
return true;
|
|
}
|