Files
hsb/S - Software/0 - HSB MRTS Kathode-MCP/3 - Implementation/0 - Code/hsb-mrts/src/SignalProfileGenerator.c
mmi 553ebd04c1 Fixed number of stages bug.
git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@282 05563f52-14a8-4384-a975-3d1654cca0fa
2017-11-17 13:59:48 +00:00

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++;
}