Updates:
- Re-located repairprocessrow information in dedicated object - added error conditions to repair row and added condition handling to repair process git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@260 05563f52-14a8-4384-a975-3d1654cca0fa
This commit is contained in:
@@ -126,7 +126,6 @@ ErrorStatus Display_clearScreen(struct Display* self)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
returnValue = DisplayDevice_clear(self->displayDevice);
|
||||
vTaskDelay(5);
|
||||
Display_clearShadow(self);
|
||||
return returnValue;
|
||||
}
|
||||
@@ -134,15 +133,16 @@ ErrorStatus Display_clearScreen(struct Display* self)
|
||||
|
||||
ErrorStatus Display_clearLine(struct Display* self, size_t line)
|
||||
{
|
||||
char buffer[self->displayDevice->parameters.numberOfColumns];
|
||||
char buffer[self->displayDevice->parameters.numberOfColumns + 1];
|
||||
|
||||
int loopcounter;
|
||||
for (loopcounter = 0; loopcounter < self->displayDevice->parameters.numberOfColumns; loopcounter++)
|
||||
{
|
||||
buffer[loopcounter] = 0x20;
|
||||
}
|
||||
buffer[self->displayDevice->parameters.numberOfColumns] = '\0';
|
||||
|
||||
return Display_write(self, buffer, self->displayDevice->parameters.numberOfColumns, line, 1);
|
||||
return Display_write(self, buffer, line, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -164,12 +164,13 @@ ErrorStatus Display_setContrast(struct Display* self, size_t contrast)
|
||||
}
|
||||
|
||||
|
||||
ErrorStatus Display_write(struct Display* self, const char* buffer, unsigned int length, size_t row, size_t column)
|
||||
ErrorStatus Display_write(struct Display* self, const char* buffer, size_t row, size_t column)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
int length = 0;
|
||||
// Prior to any action on the display memory, perform necessary checkings
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
@@ -189,6 +190,7 @@ ErrorStatus Display_write(struct Display* self, const char* buffer, unsigned int
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
length = strlen(buffer);
|
||||
// Check that the length request does not exceed the display boundary
|
||||
// This is checked in combination with the column coordinate
|
||||
// numberOfColumns - column >= length
|
||||
@@ -282,7 +284,7 @@ inline static void Display_clearShadow(struct Display* self)
|
||||
// Clear the display shadow
|
||||
size_t rowCounter;
|
||||
size_t colCounter;
|
||||
char buffer[self->displayDevice->parameters.numberOfColumns];
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
{
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
@@ -295,6 +297,7 @@ inline static void Display_clearShadow(struct Display* self)
|
||||
self->displayShadow[rowCounter][colCounter].isUpdated = false;
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ ErrorStatus Error_construct(void)
|
||||
Observable_construct(&observable);
|
||||
|
||||
errorQueue = xQueueCreate(ERROR_QUEUE_SIZE, sizeof(struct ErrorQueueItem));
|
||||
xTaskCreate(ErrorTask, "ErrorTask", 256, NULL, 1, &errorTaskHandle);
|
||||
xTaskCreate(ErrorTask, "ErrorTask", 300, NULL, 1, &errorTaskHandle);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,259 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
/// @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 "Logger.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constant and macro definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#define SPG_0V_OFFSET (450)
|
||||
#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)
|
||||
{
|
||||
self->secondsCounter = 0;
|
||||
self->currentState = SPG_PREPARE;
|
||||
self->initialized = true;
|
||||
self->repairPreset = preset;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void SignalProfileGenerator_destruct(struct SignalProfileGenerator* self)
|
||||
{
|
||||
self->initialized = false;
|
||||
}
|
||||
|
||||
|
||||
void SignalProfileGenerator_calculate(struct SignalProfileGenerator* self)
|
||||
{
|
||||
self->signal = 0;
|
||||
|
||||
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;
|
||||
|
||||
LOGGER_DEBUG(mainLog, "startTime %d - softStartTime %d - HoldTimer %d", self->startTime, self->softStartTimer, self->voltageHoldTimer);
|
||||
|
||||
// If first preset, start voltage is 0
|
||||
if (self->currentPresetIndex == 0)
|
||||
{
|
||||
self->startVoltage = SPG_0V_OFFSET;
|
||||
}
|
||||
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->startTime = self->startTime + SPG_PAUSE_SOFTSTART;
|
||||
self->softStartTimer = self->softStartTimer + SPG_PAUSE_SOFTSTART;
|
||||
self->voltageHoldTimer = self->voltageHoldTimer + SPG_PAUSE_SOFTSTART;
|
||||
self->currentState = SPG_PAUSE_RESTORE_SOFTSTART;
|
||||
break;
|
||||
}
|
||||
case SPG_PAUSE_RESTORE_SOFTSTART:
|
||||
{
|
||||
self->pauseStartVoltage = SPG_0V_OFFSET;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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->voltageHoldTimer >= self->secondsCounter)
|
||||
{
|
||||
returnValue = (self->voltageHoldTimer - self->secondsCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ERROR - negative time
|
||||
returnValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = 0xFFFFFFFF;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
static inline void incrementSecondsCounter(struct SignalProfileGenerator* self)
|
||||
{
|
||||
self->secondsCounter++;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ ErrorStatus hsb_generateStartScreen(struct Display* Display)
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = Display_write(mainDisplay, pcba->name, strlen(pcba->name), 1, 1);
|
||||
returnValue = Display_write(mainDisplay, PCBA_getInstance()->name, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -87,7 +87,7 @@ ErrorStatus hsb_generateStartScreen(struct Display* Display)
|
||||
Version_getInstance()->minor,
|
||||
Version_getInstance()->branch,
|
||||
Version_getInstance()->patch);
|
||||
Display_write(mainDisplay, buffer, strlen(buffer), 3, 4);
|
||||
Display_write(mainDisplay, buffer, 3, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -135,7 +135,7 @@ ErrorStatus hsb_enableSafety(void)
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// TESLA has a second interlock that must be closed
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
if (PCBA_getInstance()->pcba == PCBA_Tesla)
|
||||
{
|
||||
if (Interlock_isClosed(teslalock))
|
||||
{
|
||||
@@ -177,7 +177,7 @@ ErrorStatus hsb_disableSafety(void)
|
||||
|
||||
Interlock_setEXTI(interlock, DISABLE);
|
||||
// TESLA has a second interlock that must be closed
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
if (PCBA_getInstance()->pcba == PCBA_Tesla)
|
||||
{
|
||||
Interlock_setEXTI(teslalock, DISABLE);
|
||||
}
|
||||
|
||||
@@ -895,7 +895,7 @@ static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t b
|
||||
else if (self->menuItemSelected == MENU_TEST_INTERLOCK_2 )
|
||||
{
|
||||
|
||||
if(pcba->pcba == Tesla)
|
||||
if(self->testItems->pcba->pcba == PCBA_Tesla)
|
||||
{
|
||||
|
||||
if( GPIO_getValue(self->testItems->teslaNO, &value1) == SUCCESS &&
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "CathodeMCP.h"
|
||||
#include "Displays.h"
|
||||
#include "Error.h"
|
||||
#include "hsb-mrts.h"
|
||||
@@ -223,7 +224,7 @@ static void initTask(void* parameters)
|
||||
hwTestItems.cat0Relay = cat0Relay;
|
||||
hwTestItems.cat1Relay = cat1Relay;
|
||||
hwTestItems.cat2Relay = cat2Relay;
|
||||
hwTestItems.pcba = pcba;
|
||||
hwTestItems.pcba = PCBA_getInstance();
|
||||
hwTestItems.keypad = keypad;
|
||||
// EEPROM TO BE DONE
|
||||
// HwValidationMenu_construct(hwValidation, &uart1->device, &hwTestItems, 1, 1024);
|
||||
@@ -242,16 +243,30 @@ static void ledBlinkTask (void* parameters)
|
||||
{
|
||||
char high = 1;
|
||||
char low = 0;
|
||||
char indicator[2];
|
||||
indicator[0] = ' ';
|
||||
indicator[1] = '\0';
|
||||
struct LedTaskArguments* arguments = (struct LedTaskArguments*) parameters;
|
||||
struct Gpio* gpio = arguments->led;
|
||||
int frequency = arguments->frequency;
|
||||
while (1)
|
||||
{
|
||||
IODevice_write(&gpio->device, &high, 1);
|
||||
Display_write(mainDisplay, pcba->name, 1, 1, 20);
|
||||
if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
||||
{
|
||||
indicator[0] = CathodeMCP_getInstance()->name[0];
|
||||
Display_write(mainDisplay, indicator, 1, 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
indicator[0] = PCBA_getInstance()->name[0];
|
||||
Display_write(mainDisplay, indicator, 1, 20);
|
||||
}
|
||||
|
||||
vTaskDelay(configTICK_RATE_HZ / (frequency * 2));
|
||||
IODevice_write(&gpio->device, &low, 1);
|
||||
Display_write(mainDisplay, " ", 1, 1, 20);
|
||||
indicator[0] = ' ';
|
||||
Display_write(mainDisplay, indicator, 1, 20);
|
||||
vTaskDelay(configTICK_RATE_HZ / (frequency * 2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "repairProcess.h"
|
||||
#include "repairProcesses.h"
|
||||
|
||||
#include "CathodeMCP.h"
|
||||
#include "Display.h"
|
||||
#include "Error.h"
|
||||
#include "hsb-mrts.h"
|
||||
@@ -64,7 +65,7 @@
|
||||
// File-scope variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static const char cursorValue = 0x7E;
|
||||
static const char cursorValue[2] = {0x7E, '\0'};
|
||||
|
||||
|
||||
// TEMPORARY PRESET STORAGE
|
||||
@@ -99,12 +100,16 @@ static void repairMenu_scrollIndexHandlerReset (struct RepairMenu* self);
|
||||
static void repairMenu_scrollUpIndexHandler(struct RepairMenu* self);
|
||||
static void repairMenu_scrollDownIndexHandler(struct RepairMenu* self);
|
||||
|
||||
static void repairMenu_selectCathodeRepair(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_selectMCPRepair(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_selectPreset(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_solenoidLock(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_solenoidUnlock(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_startRepairProcess(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_stopRepairProcess(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_abortRepairProcessAndGotoMainMenu(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_pauseRepairProcess(struct RepairMenu* self, int cursorIndex);
|
||||
static void repairMenu_continueRepairProcess(struct RepairMenu* self, int cursorIndex);
|
||||
|
||||
static ErrorStatus repairMenu_createMenu(struct RepairMenu* self);
|
||||
static ErrorStatus repairMenu_createMenuPage (struct MenuPage* self, bool hasCursor, int maxNumberOfRows);
|
||||
@@ -210,6 +215,13 @@ void repairMenu_interlockFailed(struct RepairMenu* self, T_INTERLOCK_ID interloc
|
||||
}
|
||||
|
||||
|
||||
void repairMenu_processFailed(struct RepairMenu* self)
|
||||
{
|
||||
repairMenu_changeState(self, ERROR_STATE);
|
||||
snprintf(self->errorMessage, sizeof(self->errorMessage) / sizeof(self->errorMessage[0]), "PROCESS FAILED");
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_task(void* parameters)
|
||||
{
|
||||
struct RepairMenu* self = (struct RepairMenu*)parameters;
|
||||
@@ -220,8 +232,8 @@ static void repairMenu_task(void* parameters)
|
||||
repairMenu_printMenu(self);
|
||||
// Add cursor if necessary
|
||||
repairMenu_printCursor(self);
|
||||
int tempScreenCounter;
|
||||
T_MenuState tempMenuState;
|
||||
int tempScreenCounter = 0;
|
||||
T_MenuState tempMenuState = MAINMENU;
|
||||
|
||||
while(self->runTask)
|
||||
{
|
||||
@@ -273,6 +285,7 @@ static void repairMenu_task(void* parameters)
|
||||
}
|
||||
else if (self->menuState == REPAIR_PAUSE)
|
||||
{
|
||||
|
||||
repairMenu_printPause(self);
|
||||
}
|
||||
else if (self->menuState == FINISH_CONTROL)
|
||||
@@ -296,14 +309,13 @@ static void repairMenu_task(void* parameters)
|
||||
repairMenu_printMenu(self);
|
||||
// Add cursor if necessary
|
||||
repairMenu_printCursor(self);
|
||||
LOGGER_WARNING(mainLog, "menu index is %d", self->menuState);
|
||||
}
|
||||
}
|
||||
vTaskDelay(50);
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting RepairMenu task");
|
||||
vTaskDelete(self->taskHandle);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -311,12 +323,13 @@ static void repairMenu_changeState(struct RepairMenu* self, T_MenuState newState
|
||||
{
|
||||
Display_clearScreen(self->display);
|
||||
self->menuState = newState;
|
||||
LOGGER_WARNING(mainLog, "New menu index is %d", self->menuState);
|
||||
}
|
||||
|
||||
static void repairMenu_printError(struct RepairMenu* self)
|
||||
{
|
||||
Display_write(self->display, "!!ERROR!!", strlen("!!ERROR!!"), 2, 6);
|
||||
Display_write(self->display, self->errorMessage, strlen(self->errorMessage), 3, 1 + ((self->display->displayDevice->parameters.numberOfColumns - strlen(self->errorMessage)) / 2));
|
||||
Display_write(self->display, "!!ERROR!!", 2, 6);
|
||||
Display_write(self->display, self->errorMessage, 3, 1 + ((self->display->displayDevice->parameters.numberOfColumns - strlen(self->errorMessage)) / 2));
|
||||
}
|
||||
|
||||
|
||||
@@ -331,58 +344,79 @@ static void repairMenu_printRepair(struct RepairMenu* self)
|
||||
int loopCounter = 0;
|
||||
char buffer[20];
|
||||
|
||||
if (xSemaphoreTake(self->repairScreenUpdateSemaphore, 0) != pdTRUE)
|
||||
struct RepairProcess* repairProcess = repairProcesses_getMainRepairProcess();
|
||||
if (repairProcess_isProcessRunning(repairProcess))
|
||||
{
|
||||
// Taking semaphore failed - no update on the screen
|
||||
if (xSemaphoreTake(self->repairScreenUpdateSemaphore, 0) != pdTRUE)
|
||||
{
|
||||
// Taking semaphore failed - no update on the screen
|
||||
}
|
||||
else
|
||||
{
|
||||
struct Time remainingTime;
|
||||
RTC_calculateTimeFromSeconds(repairProcess_getRemainingRepairTime(repairProcess), &remainingTime);
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), " %02d:%02d:%02d remain ", remainingTime.hours, remainingTime.minutes, remainingTime.seconds);
|
||||
Display_write(self->display, buffer, 1, 1);
|
||||
LOGGER_DEBUG(mainLog, "%s", buffer);
|
||||
|
||||
// Regulation is unique for each row
|
||||
// For TESLA repair only row 1 (out of 0,1,2) is used
|
||||
// For ANODE and Cathode/MCP, all 3 rows are used
|
||||
for (loopCounter = ((PCBA_getInstance()->pcba == PCBA_Tesla) ? 1 : 0); loopCounter <= ((PCBA_getInstance()->pcba == PCBA_Tesla) ? 1 : 2); loopCounter++)
|
||||
{
|
||||
const struct RepairProcessRow* row;
|
||||
row = repairProcess_getRowInformation(repairProcess, loopCounter);
|
||||
|
||||
snprintf (buffer, sizeof(buffer) / sizeof(buffer[0]), "R%d", loopCounter + 1);
|
||||
Display_write(self->display, buffer, 2, ((loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
|
||||
if (!row->errorData.rowHasError)
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%05dV", row->lastADCValue);
|
||||
Display_write(self->display, buffer, 3, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04dER", row->pidError);
|
||||
Display_write(self->display, buffer, 4, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), " ROW ");
|
||||
Display_write(self->display, buffer, 3, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "ERROR ");
|
||||
Display_write(self->display, buffer, 4, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
struct Time remainingTime;
|
||||
RTC_calculateTimeFromSeconds(repairProcess_getRemainingRepairTime(repairProcesses_getMainRepairProcess()), &remainingTime);
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), " %02d:%02d:%02d remain ", remainingTime.hours, remainingTime.minutes, remainingTime.seconds);
|
||||
Display_write(self->display, buffer, strlen(buffer), 1, 1);
|
||||
|
||||
// Regulation is unique for each row
|
||||
// For TESLA repair only row 1 (out of 0,1,2) is used
|
||||
// For ANODE and Cathode/MCP, all 3 rows are used
|
||||
for (loopCounter = ((PCBA_getInstance()->pcba == Tesla) ? 1 : 0); loopCounter <= ((PCBA_getInstance()->pcba == Tesla) ? 1 : 2); loopCounter++)
|
||||
{
|
||||
struct RepairProcessRow* row;
|
||||
row = repairProcess_getRowInformation(repairProcesses_getMainRepairProcess(), loopCounter);
|
||||
|
||||
snprintf (buffer, sizeof(buffer) / sizeof(buffer[0]), "R%d", loopCounter + 1);
|
||||
Display_write(self->display, buffer, strlen(buffer), 2, ((loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%05dV", row->lastADCValue);
|
||||
Display_write(self->display, buffer, strlen(buffer), 3, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04dER", row->pidError);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, (loopCounter + (loopCounter * (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS)) + (self->display->displayDevice->parameters.numberOfColumns / REPAIRPROCESS_NUMBER_OF_ROWS) / strlen(buffer)));
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "Initialising");
|
||||
Display_write(self->display, buffer, 1, 6);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_printAskPause(struct RepairMenu* self)
|
||||
{
|
||||
Display_write(self->display, "REPAIR BUSY", strlen("REPAIR BUSY"), 2, 6);
|
||||
Display_write(self->display, "Hit X to PAUSE", strlen("Hit X to RESET"), 3, 2);
|
||||
Display_write(self->display, "REPAIR BUSY", 2, 6);
|
||||
Display_write(self->display, "Hit X to PAUSE", 3, 2);
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_printPause(struct RepairMenu* self)
|
||||
{
|
||||
Display_write(self->display, "!!PAUSE!!", strlen("!!PAUSE!!"), 2, 6);
|
||||
Display_write(self->display, "Hit ENT to continue", strlen("Hit ENT to continue"), 3, 2);
|
||||
Display_write(self->display, "Hit X to RESET", strlen("Hit X to RESET"), 4, 2);
|
||||
Display_write(self->display, "!!PAUSE!!", 2, 6);
|
||||
Display_write(self->display, "Hit ENT to continue", 3, 2);
|
||||
Display_write(self->display, "Hit X to RESET", 4, 2);
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_printFinish(struct RepairMenu* self)
|
||||
{
|
||||
Display_write(self->display, "REPAIR FINISHED", strlen("REPAIR FINISHED"), 2, 6);
|
||||
Display_write(self->display, "Hit ENT to continue", strlen("Hit ENT to continue"), 4, 2);
|
||||
Display_write(self->display, "REPAIR FINISHED", 2, 6);
|
||||
Display_write(self->display, "Hit ENT to continue", 4, 2);
|
||||
|
||||
}
|
||||
|
||||
@@ -392,11 +426,11 @@ static void repairMenu_printMenu(struct RepairMenu* self)
|
||||
int loopCounter;
|
||||
|
||||
// Always print Row1 (index0), ignoring the scrolling index
|
||||
Display_write(self->display, self->menuArray[self->menuState].row[0].text, strlen(self->menuArray[self->menuState].row[0].text), 1, 1);
|
||||
Display_write(self->display, self->menuArray[self->menuState].row[0].text, 1, 1);
|
||||
|
||||
for (loopCounter = 1 ; loopCounter < self->display->displayDevice->parameters.numberOfRows; loopCounter++)
|
||||
{
|
||||
Display_write(self->display, self->menuArray[self->menuState].row[loopCounter + self->scrollOffset].text, strlen(self->menuArray[self->menuState].row[loopCounter + self->scrollOffset].text), loopCounter + 1, 1);
|
||||
Display_write(self->display, self->menuArray[self->menuState].row[loopCounter + self->scrollOffset].text, loopCounter + 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +439,7 @@ static void repairMenu_printCursor(struct RepairMenu* self)
|
||||
{
|
||||
if (self->menuArray[self->menuState].hasCursor)
|
||||
{
|
||||
Display_write(self->display, &cursorValue, 1, 1 + self->cursorIndex - self->scrollOffset, 1);
|
||||
Display_write(self->display, cursorValue, 1 + self->cursorIndex - self->scrollOffset, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,6 +597,18 @@ static void repairMenu_scrollDownIndexHandler(struct RepairMenu* self)
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_selectCathodeRepair(struct RepairMenu* self, int cursorIndex)
|
||||
{
|
||||
CathodeMCP_switchToCathode();
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_selectMCPRepair(struct RepairMenu* self, int cursorIndex)
|
||||
{
|
||||
CathodeMCP_switchToMCP();
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_selectPreset(struct RepairMenu* self, int cursorIndex)
|
||||
{
|
||||
self->repairPreset = presetArray[cursorIndex - 1];
|
||||
@@ -601,7 +647,7 @@ static void repairMenu_startRepairProcess(struct RepairMenu* self, int cursorInd
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// For MCP/Cathode, the right settings must be made
|
||||
if (PCBA_getInstance()->pcba == CathodeMCP)
|
||||
if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -612,7 +658,12 @@ static void repairMenu_startRepairProcess(struct RepairMenu* self, int cursorInd
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = repairProcesses_startMainRepairProcess(self->repairPreset, &self->rpParameters);
|
||||
if (returnValue != SUCCESS)
|
||||
{
|
||||
Error_postError(REPAIR_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = repairProcesses_mainRepairProcessAddObserver(self->observer);
|
||||
@@ -645,13 +696,35 @@ static void repairMenu_abortRepairProcessAndGotoMainMenu(struct RepairMenu* self
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_pauseRepairProcess(struct RepairMenu* self, int cursorIndex)
|
||||
{
|
||||
repairMenu_changeState(self, REPAIR_PAUSE);
|
||||
repairProcess_pauseProcess(repairProcesses_getMainRepairProcess());
|
||||
}
|
||||
|
||||
|
||||
static void repairMenu_continueRepairProcess(struct RepairMenu* self, int cursorIndex)
|
||||
{
|
||||
repairMenu_changeState(self, REPAIR_RUNNING);
|
||||
repairProcess_continueProcess(repairProcesses_getMainRepairProcess());
|
||||
}
|
||||
|
||||
|
||||
static ErrorStatus repairMenu_createMenu(struct RepairMenu* self)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[MAINMENU], MENU_HAS_CURSOR, 4);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], PCBA_getInstance()->name, MAINMENU, NULL);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], " 1.Tube repair", REPAIRMENU, NULL);
|
||||
if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
||||
{
|
||||
// For Cathode/MCP PCBA, the type of repair must be selected first
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], " 1.Tube repair", RM_CATHODEMCP_SELECT, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], " 1.Tube repair", REPAIRMENU, NULL);
|
||||
}
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], " 2.Administrator", ADMINMENU, NULL);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[MAINMENU], " 3.Calibration", CALIBRATIONMENU, NULL);
|
||||
repairMenu_addKeyAction_SCROLLUP(&self->menuArray[MAINMENU], 'U', PRESSED);
|
||||
@@ -663,6 +736,18 @@ static ErrorStatus repairMenu_createMenu(struct RepairMenu* self)
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[MAINMENU], '0', PRESSED, repairMenu_solenoidUnlock);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[MAINMENU], '0', RELEASED, repairMenu_solenoidLock);
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[RM_CATHODEMCP_SELECT], MENU_HAS_CURSOR, 3);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[RM_CATHODEMCP_SELECT], "Tube repair", RM_CATHODEMCP_SELECT, NULL);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[RM_CATHODEMCP_SELECT], " 1.Cathode repair", REPAIRMENU, repairMenu_selectCathodeRepair);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[RM_CATHODEMCP_SELECT], " 2.MCP repair", REPAIRMENU, repairMenu_selectMCPRepair);
|
||||
repairMenu_addKeyAction_SCROLLUP(&self->menuArray[RM_CATHODEMCP_SELECT], 'U', PRESSED);
|
||||
repairMenu_addKeyAction_SCROLLDOWN(&self->menuArray[RM_CATHODEMCP_SELECT], 'D', PRESSED);
|
||||
repairMenu_addKeyAction_SELECT(&self->menuArray[RM_CATHODEMCP_SELECT], 'E', PRESSED);
|
||||
repairMenu_addKeyAction_HOTKEYSELECT(&self->menuArray[RM_CATHODEMCP_SELECT], '1', PRESSED, 1);
|
||||
repairMenu_addKeyAction_HOTKEYSELECT(&self->menuArray[RM_CATHODEMCP_SELECT], '2', PRESSED, 2);
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[RM_CATHODEMCP_SELECT], 'X', PRESSED, MAINMENU);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[RM_CATHODEMCP_SELECT], '0', PRESSED, repairMenu_solenoidUnlock);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[RM_CATHODEMCP_SELECT], '0', RELEASED, repairMenu_solenoidLock);
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[REPAIRMENU], MENU_HAS_CURSOR, 4);
|
||||
repairMenu_addMenuPageRow(&self->menuArray[REPAIRMENU], "Tube repair", REPAIRMENU, NULL);
|
||||
@@ -673,7 +758,16 @@ static ErrorStatus repairMenu_createMenu(struct RepairMenu* self)
|
||||
repairMenu_addKeyAction_SELECT(&self->menuArray[REPAIRMENU], 'E', PRESSED);
|
||||
repairMenu_addKeyAction_HOTKEYSELECT(&self->menuArray[REPAIRMENU], '1', PRESSED, 1);
|
||||
repairMenu_addKeyAction_HOTKEYSELECT(&self->menuArray[REPAIRMENU], '2', PRESSED, 2);
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIRMENU], 'X', PRESSED, MAINMENU);
|
||||
if (PCBA_getInstance()->pcba == PCBA_CathodeMCP)
|
||||
{
|
||||
// For Cathode/MCP PCBA, the type of repair must can be selected
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIRMENU], 'X', PRESSED, RM_CATHODEMCP_SELECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIRMENU], 'X', PRESSED, MAINMENU);
|
||||
}
|
||||
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIRMENU], '0', PRESSED, repairMenu_solenoidUnlock);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIRMENU], '0', RELEASED, repairMenu_solenoidLock);
|
||||
|
||||
@@ -720,11 +814,13 @@ static ErrorStatus repairMenu_createMenu(struct RepairMenu* self)
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIR_RUNNING], 'X', PRESSED, REPAIR_ASK_PAUSE);
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[REPAIR_ASK_PAUSE], MENU_HAS_NO_CURSOR, 4);
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIR_ASK_PAUSE], 'X', PRESSED, REPAIR_PAUSE);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIR_ASK_PAUSE], 'X', PRESSED, repairMenu_pauseRepairProcess);
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[REPAIR_PAUSE], MENU_HAS_NO_CURSOR, 4);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIR_PAUSE], 'X', PRESSED, repairMenu_abortRepairProcessAndGotoMainMenu);
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[REPAIR_PAUSE], 'E', PRESSED, REPAIR_RUNNING);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIR_PAUSE], 'E', PRESSED, repairMenu_continueRepairProcess);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIR_PAUSE], '0', PRESSED, repairMenu_solenoidUnlock);
|
||||
repairMenu_addKeyAction_EXECUTEFUNCTION(&self->menuArray[REPAIR_PAUSE], '0', RELEASED, repairMenu_solenoidLock);
|
||||
|
||||
repairMenu_createMenuPage(&self->menuArray[FINISH], MENU_HAS_NO_CURSOR, 4);
|
||||
repairMenu_addKeyAction_GOTOSTATE(&self->menuArray[FINISH], 'E', PRESSED, MAINMENU);
|
||||
|
||||
@@ -119,7 +119,7 @@ static ErrorStatus repairMenu_errorReceive(const void* const data)
|
||||
}
|
||||
else if (errorCode == REPAIR_FAIL)
|
||||
{
|
||||
|
||||
repairMenu_processFailed(mainMenu);
|
||||
}
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "hsb-mrts.h"
|
||||
#include "repairProcess.h"
|
||||
#include "repairPreset.h"
|
||||
|
||||
@@ -64,7 +65,6 @@
|
||||
|
||||
static void repairProcess_task(void* parameters);
|
||||
|
||||
static int SignalProfileGenerator(struct RepairProcess* self);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
@@ -78,12 +78,18 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, struct RepairPro
|
||||
if (!self->initialized)
|
||||
{
|
||||
self->runTask = true;
|
||||
self->taskIsRunning = false;
|
||||
BaseType_t rv = xTaskCreate(repairProcess_task, "RepairProcess", stackSize, self, taskPriority, &self->taskHandle);
|
||||
if (rv != pdTRUE)
|
||||
{
|
||||
LOGGER_ERROR(mainLog, "FAILED to start repair Process task with code %d", (int)rv);
|
||||
returnValue = ERROR;
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = SignalProfileGenerator_construct(&self->signalProfileGenerator, preset);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Create a semaphore to sync access to the display shadow
|
||||
@@ -91,47 +97,28 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, struct RepairPro
|
||||
xSemaphoreTake(self->secondsSyncronisation, 0);
|
||||
|
||||
Observable_construct(&self->observable);
|
||||
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = repairProcessRow_construct(&self->row[0], parameters->adcRow1, parameters->dacRow1, HSB_MAINREPR_OOL_DURATION, HSB_MAINREPR_OOL_VALUE);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = repairProcessRow_construct(&self->row[1], parameters->adcRow2, parameters->dacRow2, HSB_MAINREPR_OOL_DURATION, HSB_MAINREPR_OOL_VALUE);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = repairProcessRow_construct(&self->row[2], parameters->adcRow3, parameters->dacRow3, HSB_MAINREPR_OOL_DURATION, HSB_MAINREPR_OOL_VALUE);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
self->initialized = true;
|
||||
self->taskIsDeleted = false;
|
||||
self->isProcessRunning = false;
|
||||
self->repairPreset = preset;
|
||||
self->currentState = PREPARE;
|
||||
|
||||
|
||||
self->row[0].adcChannel = parameters->adcRow1;
|
||||
self->row[1].adcChannel = parameters->adcRow2;
|
||||
self->row[2].adcChannel = parameters->adcRow3;
|
||||
|
||||
self->row[0].lastADCValue = 0;
|
||||
self->row[1].lastADCValue = 0;
|
||||
self->row[2].lastADCValue = 0;
|
||||
|
||||
self->row[0].dacChannel = parameters->dacRow1;
|
||||
self->row[1].dacChannel = parameters->dacRow2;
|
||||
self->row[2].dacChannel = parameters->dacRow3;
|
||||
|
||||
self->row[0].lastDACValue = 0;
|
||||
self->row[1].lastDACValue = 0;
|
||||
self->row[2].lastDACValue = 0;
|
||||
|
||||
self->row[0].pid.initialized = false;
|
||||
self->row[1].pid.initialized = false;
|
||||
self->row[2].pid.initialized = false;
|
||||
|
||||
self->row[0].rowHasError = false;
|
||||
self->row[1].rowHasError = false;
|
||||
self->row[2].rowHasError = false;
|
||||
|
||||
PID_construct(&self->row[0].pid, 3000, 2000, 0, 0, 100000000);
|
||||
PID_construct(&self->row[1].pid, 3000, 2000, 0, 0, 100000000);
|
||||
PID_construct(&self->row[2].pid, 3000, 2000, 0, 0, 100000000);
|
||||
|
||||
LOGGER_INFO(mainLog, "Repair Process task started");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER_ERROR(mainLog, "FAILED to start repair Process with code %d", (int)rv);
|
||||
self->initialized = false;
|
||||
LOGGER_ERROR(mainLog, "Repair Process failed to construct");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -151,20 +138,20 @@ void repairProcess_destruct(struct RepairProcess* self)
|
||||
MAX5715Channel_setValue(self->row[2].dacChannel, 0);
|
||||
|
||||
self->runTask = false;
|
||||
while (!self->taskIsDeleted)
|
||||
while (!self->taskIsRunning)
|
||||
{
|
||||
vTaskDelay(10);
|
||||
vTaskDelay(1);
|
||||
}
|
||||
Observable_destruct(&self->observable);
|
||||
PID_destruct(&self->row[0].pid);
|
||||
PID_destruct(&self->row[1].pid);
|
||||
PID_destruct(&self->row[2].pid);
|
||||
repairProcessRow_destruct(&self->row[0]);
|
||||
repairProcessRow_destruct(&self->row[1]);
|
||||
repairProcessRow_destruct(&self->row[2]);
|
||||
vSemaphoreDelete(self->secondsSyncronisation);
|
||||
self->initialized = false;
|
||||
}
|
||||
|
||||
|
||||
void repairProcess_feedSecondsCounter(struct RepairProcess* self)
|
||||
void repairProcess_secondsFeed(struct RepairProcess* self)
|
||||
{
|
||||
if (self->initialized)
|
||||
{
|
||||
@@ -172,44 +159,29 @@ void repairProcess_feedSecondsCounter(struct RepairProcess* self)
|
||||
}
|
||||
}
|
||||
|
||||
void repairProcess_feedSecondsCounterFromISR(struct RepairProcess* self)
|
||||
void repairProcess_secondsFeedFromISR(struct RepairProcess* self)
|
||||
{
|
||||
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
xSemaphoreGiveFromISR(self->secondsSyncronisation, &higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
|
||||
bool repairProcess_isProcessRunning(struct RepairProcess* self)
|
||||
{
|
||||
return self->signalProfileGenerator.isProcessRunning;
|
||||
}
|
||||
|
||||
uint32_t repairProcess_getRemainingRepairTime(const struct RepairProcess* self)
|
||||
{
|
||||
uint32_t returnValue;
|
||||
|
||||
if ((self->initialized) && (self->isProcessRunning))
|
||||
{
|
||||
if (self->voltageHoldTimer >= self->secondsCounter)
|
||||
{
|
||||
returnValue = (self->voltageHoldTimer - self->secondsCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ERROR - negative time
|
||||
returnValue = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = 0xFFFFFFFF;
|
||||
}
|
||||
return returnValue;
|
||||
return SignalProfileGenerator_getRemainingTime(&self->signalProfileGenerator);
|
||||
}
|
||||
|
||||
|
||||
struct RepairProcessRow* repairProcess_getRowInformation(const struct RepairProcess* self, int rowIndex)
|
||||
const struct RepairProcessRow* repairProcess_getRowInformation(const struct RepairProcess* self, int rowIndex)
|
||||
{
|
||||
return &self->row[rowIndex];
|
||||
}
|
||||
@@ -221,171 +193,113 @@ const struct Observable* repairProcess_getObservable(struct RepairProcess* self)
|
||||
}
|
||||
|
||||
|
||||
void repairProcess_pauseProcess(struct RepairProcess* self)
|
||||
{
|
||||
SignalProfileGenerator_pause(&self->signalProfileGenerator);
|
||||
}
|
||||
|
||||
|
||||
void repairProcess_continueProcess(struct RepairProcess* self)
|
||||
{
|
||||
SignalProfileGenerator_continue(&self->signalProfileGenerator);
|
||||
}
|
||||
|
||||
|
||||
static void repairProcess_task(void* parameters)
|
||||
{
|
||||
struct RepairProcess* self = (struct RepairProcess*)parameters;
|
||||
|
||||
int signal;
|
||||
int loopCounter;
|
||||
self->taskIsRunning = true;
|
||||
|
||||
// Reset the seconds counter to 0
|
||||
self->secondsCounter = 0;
|
||||
MAX5715Channel_setValue(self->row[0].dacChannel, self->row[0].lastDACValue);
|
||||
MAX5715Channel_setValue(self->row[1].dacChannel, self->row[0].lastDACValue);
|
||||
MAX5715Channel_setValue(self->row[2].dacChannel, self->row[0].lastDACValue);
|
||||
MAX5715Channel_setValue(self->row[1].dacChannel, self->row[1].lastDACValue);
|
||||
MAX5715Channel_setValue(self->row[2].dacChannel, self->row[2].lastDACValue);
|
||||
|
||||
while(self->runTask)
|
||||
{
|
||||
LOGGER_DEBUG(mainLog, "----------------------------------------");
|
||||
xSemaphoreTake(self->secondsSyncronisation, portMAX_DELAY);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "----------------------------------------");
|
||||
|
||||
// The signal profile is identical for all rows in the regulation process
|
||||
signal = SignalProfileGenerator(self);
|
||||
LOGGER_DEBUG(mainLog, "Signal: %d", signal);
|
||||
SignalProfileGenerator_calculate(&self->signalProfileGenerator);
|
||||
LOGGER_DEBUG(mainLog, "Signal: %d, TimeToRemain %d", self->signalProfileGenerator.signal, SignalProfileGenerator_getRemainingTime(&self->signalProfileGenerator));
|
||||
|
||||
// Check for correct signal
|
||||
if (signal >= 0)
|
||||
if (self->signalProfileGenerator.signal >= 0)
|
||||
{
|
||||
// Regulation is unique for each row
|
||||
// For TESLA repair only row 1 (out of 0,1,2) is used
|
||||
// For ANODE and Cathode/MCP, all 3 rows are used
|
||||
for (loopCounter = ((PCBA_getInstance()->pcba == Tesla) ? 1 : 0); loopCounter <= ((PCBA_getInstance()->pcba == Tesla) ? 1 : 2); loopCounter++)
|
||||
for (loopCounter = ((PCBA_getInstance()->pcba == PCBA_Tesla) ? 1 : 0); loopCounter <= ((PCBA_getInstance()->pcba == PCBA_Tesla) ? 1 : 2); loopCounter++)
|
||||
{
|
||||
// Read the last ADC channel value
|
||||
ADCChannel_read(self->row[loopCounter].adcChannel, &self->row[loopCounter].lastADCValue);
|
||||
// Calculate the error
|
||||
self->row[loopCounter].pidError = signal - (int)self->row[loopCounter].lastADCValue;
|
||||
// Calculate the PID
|
||||
self->row[loopCounter].lastDACValue = PID_calculate(&self->row[loopCounter].pid, self->row[loopCounter].pidError);
|
||||
///TODO MUST BE MOVED TO DACDevice
|
||||
// Verify that pid value does not overflow the DAC
|
||||
if (self->row[loopCounter].lastDACValue > 0xFFF)
|
||||
if (!self->row[loopCounter].errorData.rowHasError)
|
||||
{
|
||||
self->row[loopCounter].lastDACValue = 0xFFF;
|
||||
}
|
||||
else if (self->row[loopCounter].lastDACValue < 0)
|
||||
{
|
||||
self->row[loopCounter].lastDACValue = 0;
|
||||
}
|
||||
// Send the PID value to the DAC
|
||||
MAX5715Channel_setValue(self->row[loopCounter].dacChannel, self->row[loopCounter].lastDACValue);
|
||||
// Read the last ADC channel value
|
||||
ADCChannel_read(self->row[loopCounter].adcChannel, &self->row[loopCounter].lastADCValue);
|
||||
// Calculate the error
|
||||
self->row[loopCounter].pidError = self->signalProfileGenerator.signal - (int)self->row[loopCounter].lastADCValue;
|
||||
// Calculate the PID
|
||||
int pidCalculate = PID_calculate(&self->row[loopCounter].pid, self->row[loopCounter].pidError);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "Row %d --- ADC: %d Error: %d PID: %d", loopCounter, self->row[loopCounter].lastADCValue, self->row[loopCounter].pidError, self->row[loopCounter].lastDACValue);
|
||||
///TODO MUST BE MOVED TO DACDevice
|
||||
// Verify that pid value does not overflow the DAC
|
||||
if (pidCalculate > 0xFFF)
|
||||
{
|
||||
self->row[loopCounter].lastDACValue = 0xFFF;
|
||||
}
|
||||
else if (pidCalculate < 0)
|
||||
{
|
||||
self->row[loopCounter].lastDACValue = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->row[loopCounter].lastDACValue = pidCalculate;
|
||||
}
|
||||
|
||||
// Check if the error condition exceeds the tolerated duration
|
||||
if (self->row[loopCounter].errorData.outOfLimitsCounter >= self->row[loopCounter].errorData.outOfLimitsDuration)
|
||||
{
|
||||
// Tolerated duration exceeded - put the current ROW in error state
|
||||
self->row[loopCounter].errorData.rowHasError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Calculate/Update ERROR conditions
|
||||
if ((self->row[loopCounter].lastADCValue < self->signalProfileGenerator.signal - self->row[loopCounter].errorData.outOfLimitsValue)
|
||||
||(self->row[loopCounter].lastADCValue > self->signalProfileGenerator.signal + self->row[loopCounter].errorData.outOfLimitsValue))
|
||||
{
|
||||
// The current ADC value is outside the error boundaries
|
||||
self->row[loopCounter].errorData.outOfLimitsCounter += 1;
|
||||
LOGGER_WARNING(mainLog, "Row %d outside boundaries", loopCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->row[loopCounter].errorData.outOfLimitsCounter = 0;
|
||||
}
|
||||
}
|
||||
// Send the PID value to the DAC
|
||||
MAX5715Channel_setValue(self->row[loopCounter].dacChannel, self->row[loopCounter].lastDACValue);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "Row %d --- ADC: %d Error: %d PID: %d", loopCounter, self->row[loopCounter].lastADCValue, self->row[loopCounter].pidError, self->row[loopCounter].lastDACValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// ROW is in error state
|
||||
self->row[loopCounter].lastDACValue = 0;
|
||||
MAX5715Channel_setValue(self->row[loopCounter].dacChannel, self->row[loopCounter].lastDACValue);
|
||||
LOGGER_ERROR(mainLog, "Row %d --- Row in ERROR state", loopCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify observers that an update is available
|
||||
Observable_notifyObservers(&self->observable, NULL);
|
||||
self->secondsCounter++;
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting repairProcess task");
|
||||
self->taskIsDeleted = true;
|
||||
self->taskIsRunning = false;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
static int SignalProfileGenerator(struct RepairProcess* self)
|
||||
{
|
||||
int returnValue = 0;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
|
||||
switch (self->currentState)
|
||||
{
|
||||
case 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->currentState = SOFTSTART;
|
||||
|
||||
break;
|
||||
}
|
||||
case SOFTSTART:
|
||||
{
|
||||
self->isProcessRunning = true;
|
||||
|
||||
// Still in Softstart
|
||||
int startVoltage = 0;
|
||||
|
||||
// If first preset, start voltage is 0
|
||||
if (self->currentPresetIndex == 0)
|
||||
{
|
||||
startVoltage = 450;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Softstart for another stage - start voltage is hold voltage of previous preset
|
||||
startVoltage = self->repairPreset->preset[self->currentPresetIndex - 1].voltage;
|
||||
}
|
||||
returnValue = ((self->repairPreset->preset[self->currentPresetIndex].voltage - startVoltage) / self->repairPreset->preset[self->currentPresetIndex].softstartDuration) * (self->secondsCounter - self->startTime) + startVoltage;
|
||||
|
||||
// Check for end of softstart
|
||||
if (self->softStartTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = VOLTAGE_HOLD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VOLTAGE_HOLD:
|
||||
{
|
||||
returnValue = self->repairPreset->preset[self->currentPresetIndex].voltage;
|
||||
|
||||
// Check for end of voltage hold
|
||||
if (self->voltageHoldTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = FINISH_VERIFY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAUSE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case PAUSE_RESTORE:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case FINISH_VERIFY:
|
||||
{
|
||||
// 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 = PREPARE;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->currentState = FINISHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FINISHED:
|
||||
{
|
||||
self->isProcessRunning = false;
|
||||
returnValue = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = -1;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
/// @file repairProcessRow.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 repairProcessRow.c
|
||||
/// @ingroup {group_name}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Include files
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "repairProcessRow.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constant and macro definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File-scope variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
ErrorStatus repairProcessRow_construct(struct RepairProcessRow* self, const struct AdcChannel* adcChannel, const struct MAX5715_DAC* dacChannel, int outOfLimitsDuration, int outOfLimitsValue)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
if (!self->initialized)
|
||||
{
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
self->adcChannel = adcChannel;
|
||||
self->dacChannel = dacChannel;
|
||||
self->lastADCValue = 0;
|
||||
self->lastDACValue = 0;
|
||||
self->pid.initialized = false;
|
||||
self->errorData.rowHasError = false;
|
||||
self->errorData.outOfLimitsCounter = 0;
|
||||
self->errorData.outOfLimitsDuration = outOfLimitsDuration;
|
||||
self->errorData.outOfLimitsValue = outOfLimitsValue;
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = PID_construct(&self->pid, 3000, 2000, 0, 0, 100000000);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
self->initialized = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void repairProcessRow_destruct(struct RepairProcessRow* self)
|
||||
{
|
||||
PID_destruct(&self->pid);
|
||||
self->initialized = false;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ ErrorStatus repairProcesses_startMainRepairProcess(const struct RepairPreset* re
|
||||
void repairProcesses_abortMainRepairProcess(void)
|
||||
{
|
||||
Interlock_setEXTI(interlock, DISABLE);
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
if (PCBA_getInstance()->pcba == PCBA_Tesla)
|
||||
{
|
||||
Interlock_setEXTI(teslalock, DISABLE);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ void repairProcesses_abortMainRepairProcess(void)
|
||||
|
||||
static ErrorStatus repairProcesses_feedMainRepairProcessSecondsCounter(const void* const data)
|
||||
{
|
||||
repairProcess_feedSecondsCounterFromISR(&mainRepairProcess);
|
||||
repairProcess_secondsFeedFromISR(&mainRepairProcess);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user