git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@282 05563f52-14a8-4384-a975-3d1654cca0fa
376 lines
12 KiB
C
376 lines
12 KiB
C
// -----------------------------------------------------------------------------
|
|
/// @file SignalProfileGenerator.c
|
|
/// @brief Description
|
|
// -----------------------------------------------------------------------------
|
|
// Micro-Key bv
|
|
// Industrieweg 28, 9804 TG Noordhorn
|
|
// Postbus 92, 9800 AB Zuidhorn
|
|
// The Netherlands
|
|
// Tel: +31 594 503020
|
|
// Fax: +31 594 505825
|
|
// Email: support@microkey.nl
|
|
// Web: www.microkey.nl
|
|
// -----------------------------------------------------------------------------
|
|
/// $Revision$
|
|
/// $Author$
|
|
/// $Date$
|
|
// (c) 2017 Micro-Key bv
|
|
// -----------------------------------------------------------------------------
|
|
|
|
/// @file SignalProfileGenerator.c
|
|
/// @ingroup {group_name}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Include files
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#include "SignalProfileGenerator.h"
|
|
|
|
#include "PCBA.h"
|
|
|
|
#include "Logger.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Constant and macro definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#define SPG_0V_OFFSET_ANODE (1153)
|
|
#define SPG_0V_OFFSET_CMCP (-241)
|
|
#define SPG_0V_OFFSET_TESLA (681)
|
|
#define SPG_PAUSE_SOFTSTART (300) // 5 minutes softstart after pause
|
|
|
|
#define SPG_FIXPOINT_FACTOR (1000)
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Type definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// File-scope variables
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Function declarations
|
|
// -----------------------------------------------------------------------------
|
|
|
|
static inline void incrementSecondsCounter(struct SignalProfileGenerator* self);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Function definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
ErrorStatus SignalProfileGenerator_construct(struct SignalProfileGenerator* self, const struct RepairPreset* preset)
|
|
{
|
|
ErrorStatus returnValue = SUCCESS;
|
|
|
|
if (!self->initialized)
|
|
{
|
|
if (preset != NULL)
|
|
{
|
|
self->secondsCounter = 0;
|
|
self->currentPresetIndex = 0;
|
|
self->currentState = SPG_PREPARE;
|
|
self->initialized = true;
|
|
self->isProcessRunning = false;
|
|
self->repairPreset = preset;
|
|
self->signal = 0;
|
|
self->statePriorToPause = SPG_PREPARE;
|
|
self->totalRunTime = 0;
|
|
self->totalStartTime = 0;
|
|
|
|
self->pauseSoftStartTimer = 0;
|
|
self->pauseStartTime = 0;
|
|
self->pauseStartVoltage = 0;
|
|
|
|
self->softStartTimer = 0;
|
|
self->startTime = 0;
|
|
self->startVoltage = 0;
|
|
|
|
self->voltageHoldTimer = 0;
|
|
self->voltagePriorToPause = 0;
|
|
}
|
|
else
|
|
{
|
|
returnValue = ERROR;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
returnValue = ERROR;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
void SignalProfileGenerator_destruct(struct SignalProfileGenerator* self)
|
|
{
|
|
self->initialized = false;
|
|
}
|
|
|
|
|
|
void SignalProfileGenerator_calculate(struct SignalProfileGenerator* self)
|
|
{
|
|
if (self->initialized)
|
|
{
|
|
|
|
switch (self->currentState)
|
|
{
|
|
case SPG_PREPARE:
|
|
{
|
|
// Prepare a new repair process
|
|
//Load the timers
|
|
self->startTime = self->secondsCounter;
|
|
self->softStartTimer = self->secondsCounter + self->repairPreset->preset[self->currentPresetIndex].softstartDuration;
|
|
self->voltageHoldTimer = self->secondsCounter + self->repairPreset->preset[self->currentPresetIndex].duration + self->repairPreset->preset[self->currentPresetIndex].softstartDuration;
|
|
|
|
// Calculate the complete timer for ALL stages - but only when in first stage, so this
|
|
// calculation does not get re-done with every new stage
|
|
if (self->currentPresetIndex == 0)
|
|
{
|
|
// RESET the total runtime prior to new calculation
|
|
// Take the current time (starttime) as offset
|
|
self->totalStartTime = self->startTime;
|
|
self->totalRunTime = self->startTime;
|
|
// The total run-time is the sum of all softstart times and hold times
|
|
int loopcounter;
|
|
for (loopcounter = 0; loopcounter < self->repairPreset->numberOfStages; loopcounter++)
|
|
{
|
|
self->totalRunTime += self->repairPreset->preset[loopcounter].softstartDuration;
|
|
self->totalRunTime += self->repairPreset->preset[loopcounter].duration;
|
|
}
|
|
}
|
|
|
|
// If first preset, start voltage is 0 (or the representative 0-offset values per PCBA)
|
|
if (self->currentPresetIndex == 0)
|
|
{
|
|
// RESET the signal to 0 at the very start of a new signalprofile
|
|
self->signal = 0;
|
|
if (PCBA_getInstance()->pcba == PCBA_Anode)
|
|
{
|
|
self->startVoltage = SPG_0V_OFFSET_ANODE;
|
|
}
|
|
else if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
|
{
|
|
self->startVoltage = SPG_0V_OFFSET_CMCP;
|
|
}
|
|
else if (PCBA_getInstance()->pcba == PCBA_Tesla)
|
|
{
|
|
self->startVoltage = SPG_0V_OFFSET_TESLA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Softstart for another stage - start voltage is hold voltage of previous preset
|
|
self->startVoltage = self->repairPreset->preset[self->currentPresetIndex - 1].voltage;
|
|
}
|
|
|
|
incrementSecondsCounter(self);
|
|
self->currentState = SPG_SOFTSTART;
|
|
|
|
break;
|
|
}
|
|
case SPG_SOFTSTART:
|
|
{
|
|
self->isProcessRunning = true;
|
|
|
|
self->signal = ((self->repairPreset->preset[self->currentPresetIndex].voltage * SPG_FIXPOINT_FACTOR - (self->startVoltage * SPG_FIXPOINT_FACTOR)) / self->repairPreset->preset[self->currentPresetIndex].softstartDuration) * (self->secondsCounter - self->startTime) + (self->startVoltage * SPG_FIXPOINT_FACTOR);
|
|
self->signal = self->signal / SPG_FIXPOINT_FACTOR;
|
|
|
|
incrementSecondsCounter(self);
|
|
// Check for end of softstart
|
|
if (self->softStartTimer < self->secondsCounter)
|
|
{
|
|
// softstart finished
|
|
self->currentState = SPG_VOLTAGE_HOLD;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_VOLTAGE_HOLD:
|
|
{
|
|
self->signal = self->repairPreset->preset[self->currentPresetIndex].voltage;
|
|
|
|
incrementSecondsCounter(self);
|
|
// Check for end of voltage hold
|
|
if (self->voltageHoldTimer < self->secondsCounter)
|
|
{
|
|
// softstart finished
|
|
self->currentState = SPG_FINISH_VERIFY;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_PAUSE:
|
|
{
|
|
// Nothing happens here, just wait until the process gets continued
|
|
break;
|
|
}
|
|
case SPG_PAUSE_RESTORE:
|
|
{
|
|
self->pauseStartTime = self->secondsCounter;
|
|
self->pauseSoftStartTimer = self->secondsCounter + SPG_PAUSE_SOFTSTART;
|
|
self->softStartTimer = self->softStartTimer + SPG_PAUSE_SOFTSTART;
|
|
self->voltageHoldTimer = self->voltageHoldTimer + SPG_PAUSE_SOFTSTART;
|
|
self->currentState = SPG_PAUSE_RESTORE_SOFTSTART;
|
|
// Add the pause time twice because the total time actually increases
|
|
self->totalRunTime = self->totalRunTime + SPG_PAUSE_SOFTSTART;
|
|
break;
|
|
}
|
|
case SPG_PAUSE_RESTORE_SOFTSTART:
|
|
{
|
|
if (PCBA_getInstance()->pcba == PCBA_Anode)
|
|
{
|
|
self->pauseStartVoltage = SPG_0V_OFFSET_ANODE;
|
|
}
|
|
else if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
|
{
|
|
self->pauseStartVoltage = SPG_0V_OFFSET_CMCP;
|
|
}
|
|
else if (PCBA_getInstance()->pcba == PCBA_Tesla)
|
|
{
|
|
self->pauseStartVoltage = SPG_0V_OFFSET_TESLA;
|
|
}
|
|
|
|
self->signal = ((self->voltagePriorToPause * SPG_FIXPOINT_FACTOR - self->pauseStartVoltage * SPG_FIXPOINT_FACTOR) / SPG_PAUSE_SOFTSTART) * (self->secondsCounter - self->pauseStartTime) + self->pauseStartVoltage * SPG_FIXPOINT_FACTOR;
|
|
self->signal = self->signal / SPG_FIXPOINT_FACTOR;
|
|
|
|
incrementSecondsCounter(self);
|
|
// Check for end of softstart
|
|
if (self->pauseSoftStartTimer < self->secondsCounter)
|
|
{
|
|
// softstart finished
|
|
self->currentState = self->statePriorToPause;
|
|
}
|
|
break;
|
|
}
|
|
case SPG_FINISH_VERIFY:
|
|
{
|
|
incrementSecondsCounter(self);
|
|
// The current preset might contain multiple stages, so before going to FINISHED state
|
|
// verify that no further stage must be entered
|
|
|
|
// presetIndex carries the current index in the preset array
|
|
// number of stages is 1-based (Starting with 1) while presetIndex is 0-based
|
|
// So, the verification must compensate for the different bases
|
|
if (self->repairPreset->numberOfStages > (self->currentPresetIndex + 1))
|
|
{
|
|
// A next stage is available
|
|
self->currentPresetIndex++;
|
|
self->currentState = SPG_PREPARE;
|
|
}
|
|
else
|
|
{
|
|
self->currentState = SPG_FINISHED;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case SPG_FINISHED:
|
|
{
|
|
self->isProcessRunning = false;
|
|
self->signal = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self->signal = -1;
|
|
}
|
|
}
|
|
|
|
|
|
void SignalProfileGenerator_pause(struct SignalProfileGenerator* self)
|
|
{
|
|
self->voltagePriorToPause = self->signal;
|
|
self->statePriorToPause = self->currentState;
|
|
self->currentState = SPG_PAUSE;
|
|
}
|
|
|
|
|
|
bool SignalProfileGenerator_isPaused(struct SignalProfileGenerator* self)
|
|
{
|
|
bool returnValue;
|
|
if (self->currentState == SPG_PAUSE)
|
|
{
|
|
returnValue = true;
|
|
}
|
|
else
|
|
{
|
|
returnValue = false;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
bool SignalProfileGenerator_isFinished(struct SignalProfileGenerator* self)
|
|
{
|
|
bool returnValue;
|
|
if (self->currentState == SPG_FINISHED)
|
|
{
|
|
returnValue = true;
|
|
}
|
|
else
|
|
{
|
|
returnValue = false;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
void SignalProfileGenerator_continue(struct SignalProfileGenerator* self)
|
|
{
|
|
self->currentState = SPG_PAUSE_RESTORE;
|
|
}
|
|
|
|
|
|
uint32_t SignalProfileGenerator_getRemainingTime(const struct SignalProfileGenerator* self)
|
|
{
|
|
uint32_t returnValue;
|
|
|
|
if ((self->initialized) && (self->isProcessRunning))
|
|
{
|
|
|
|
if (self->totalRunTime >= self->secondsCounter)
|
|
{
|
|
returnValue = (self->totalRunTime - self->secondsCounter);
|
|
}
|
|
else
|
|
{
|
|
// ERROR - negative time
|
|
returnValue = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
returnValue = 0xFFFFFFFF;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
uint32_t SignalProfileGenerator_getTotalRepairTime(const struct SignalProfileGenerator* self)
|
|
{
|
|
uint32_t returnValue;
|
|
|
|
if ((self->initialized) && (self->isProcessRunning))
|
|
{
|
|
returnValue = (self->totalRunTime - self->totalStartTime);
|
|
}
|
|
else
|
|
{
|
|
returnValue = 0xFFFFFFFF;
|
|
}
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
static inline void incrementSecondsCounter(struct SignalProfileGenerator* self)
|
|
{
|
|
self->secondsCounter++;
|
|
}
|