Fixed issue with external DAC handlign from repair process
repair process implemented. Simple regulation without feedback (must be addeed, yet) HW validation menu functional but buggy (IOs not OK) Added ClearLine functionality to displayDevice git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@244 05563f52-14a8-4384-a975-3d1654cca0fa
This commit is contained in:
@@ -66,47 +66,57 @@ ErrorStatus Display_construct(struct Display* self, struct DisplayDevice* displa
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
if (!self->initialized)
|
||||
{
|
||||
|
||||
self->displayDevice = displayDevice;
|
||||
self->TaskPriority = TaskPriority;
|
||||
self->stackSize = stackSize;
|
||||
self->maxCharactersPerTransmit = maxCharactersPerTransmit;
|
||||
self->refreshFeedCounter = 0;
|
||||
self->refreshFeedFrequency_ms = refreshFeedFrequency_ms;
|
||||
self->refreshPeriod_ms = refreshPeriod;
|
||||
self->displayDevice = displayDevice;
|
||||
self->TaskPriority = TaskPriority;
|
||||
self->stackSize = stackSize;
|
||||
self->maxCharactersPerTransmit = maxCharactersPerTransmit;
|
||||
self->refreshFeedCounter = 0;
|
||||
self->refreshFeedFrequency_ms = refreshFeedFrequency_ms;
|
||||
self->refreshPeriod_ms = refreshPeriod;
|
||||
|
||||
|
||||
if(returnValue == SUCCESS)
|
||||
{
|
||||
// Create a semaphore to sync access to the display shadow
|
||||
vSemaphoreCreateBinary(self->displayShadowAccessSemaphore);
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
|
||||
// Clear the display shadow
|
||||
size_t rowCounter;
|
||||
size_t colCounter;
|
||||
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
if(returnValue == SUCCESS)
|
||||
{
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
// Create a semaphore to sync access to the display shadow
|
||||
vSemaphoreCreateBinary(self->displayShadowAccessSemaphore);
|
||||
// Create a semaphore to sync writing requests to the display
|
||||
vSemaphoreCreateBinary(self->displayWriteRequest);
|
||||
|
||||
|
||||
// Clear the display shadow
|
||||
size_t rowCounter;
|
||||
size_t colCounter;
|
||||
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
{
|
||||
Display_characterUpdate(&self->displayShadow[rowCounter][colCounter], 0x20);
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
{
|
||||
Display_characterUpdate(&self->displayShadow[rowCounter][colCounter], 0x20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->runTask = true;
|
||||
|
||||
if(returnValue == SUCCESS)
|
||||
{
|
||||
if (xTaskCreate(DisplayTask, (const char*)"DisplayTask", self->stackSize, self, self->TaskPriority, &self->taskHandle) != pdTRUE)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
LOGGER_ERROR(mainLog, "Starting display task failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER_INFO(mainLog, "Display task started");
|
||||
self->initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self->runTask = true;
|
||||
|
||||
if(returnValue == SUCCESS)
|
||||
else
|
||||
{
|
||||
if (xTaskCreate(DisplayTask, (const char*)"DisplayTask", self->stackSize, self, self->TaskPriority, &self->taskHandle) != pdTRUE)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
LOGGER_ERROR(mainLog, "Starting display task failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER_INFO(mainLog, "Display task started");
|
||||
}
|
||||
returnValue = ERROR;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
@@ -147,48 +157,57 @@ 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 returnValue = SUCCESS;
|
||||
// Prior to any action on the display memory, perform necessary checkings
|
||||
if (returnValue == SUCCESS)
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
// Check that the row coordinate does not exceed the display boundary
|
||||
if (row - 1 >= self->displayDevice->parameters.numberOfRows)
|
||||
// Prior to any action on the display memory, perform necessary checkings
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
// Check that the row coordinate does not exceed the display boundary
|
||||
if (row - 1 >= self->displayDevice->parameters.numberOfRows)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Check that the column coordinate does not exceed the display boundary
|
||||
if (column - 1 >= self->displayDevice->parameters.numberOfColumns)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Check that the length request does not exceed the display boundary
|
||||
// This is checked in combination with the column coordinate
|
||||
// numberOfColumns - column >= length
|
||||
// must be valid in order to put the requested message on display
|
||||
if (self->displayDevice->parameters.numberOfColumns - (column - 1) < length)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Get the access semaphore to the display memory - wait for access
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
|
||||
int loopCounter;
|
||||
for (loopCounter = 0; loopCounter < length; loopCounter++)
|
||||
{
|
||||
Display_characterUpdate(&self->displayShadow[row - 1][(column - 1) + loopCounter], buffer[loopCounter]);
|
||||
}
|
||||
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
|
||||
}
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
else
|
||||
{
|
||||
// Check that the column coordinate does not exceed the display boundary
|
||||
if (column - 1 >= self->displayDevice->parameters.numberOfColumns)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Check that the length request does not exceed the display boundary
|
||||
// This is checked in combination with the column coordinate
|
||||
// numberOfColumns - column >= length
|
||||
// must be valid in order to put the requested message on display
|
||||
if (self->displayDevice->parameters.numberOfColumns - (column - 1) < length)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
// Get the access semaphore to the display memory - wait for access
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
|
||||
int loopCounter;
|
||||
for (loopCounter = 0; loopCounter < length; loopCounter++)
|
||||
{
|
||||
Display_characterUpdate(&self->displayShadow[row - 1][(column - 1) + loopCounter], buffer[loopCounter]);
|
||||
}
|
||||
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
|
||||
returnValue = ERROR;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
@@ -196,14 +215,21 @@ ErrorStatus Display_write(struct Display* self, const char* buffer, unsigned int
|
||||
|
||||
void Display_feedRefreshCounter(struct Display* self)
|
||||
{
|
||||
self->refreshFeedCounter++;
|
||||
if (self->initialized)
|
||||
{
|
||||
self->refreshFeedCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline static void Display_characterUpdate (struct DisplayCharacter* displayCharacter, char character)
|
||||
{
|
||||
displayCharacter->character = character;
|
||||
displayCharacter->isUpdated = true;
|
||||
// Sending the same character should not lead to an updated character
|
||||
if (displayCharacter->character != character)
|
||||
{
|
||||
displayCharacter->character = character;
|
||||
displayCharacter->isUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,8 +263,10 @@ static void Display_characterUpdateAll(struct Display* self)
|
||||
}
|
||||
// Give back display memory access semaphore to allow new updates
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
}
|
||||
|
||||
|
||||
static void DisplayTask(void* parameters)
|
||||
{
|
||||
struct Display* self = (struct Display*)parameters;
|
||||
@@ -253,91 +281,98 @@ static void DisplayTask(void* parameters)
|
||||
size_t columnStart;
|
||||
while (self->runTask)
|
||||
{
|
||||
// Get the access semaphore to the shadow - wait until the other functions are finished with updating the shadow
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
leaveLoops = false;
|
||||
bufferIndex = 0;
|
||||
// Wait until a write or refresh function has requested this task to write to the display
|
||||
// xSemaphoreTake(self->displayWriteRequest, portMAX_DELAY);
|
||||
|
||||
// Fragment display writing - writing will be done per line
|
||||
for (; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
// for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
{
|
||||
if (Display_isCharacterUpdated(&self->displayShadow[rowCounter][colCounter]))
|
||||
// Get the access semaphore to the shadow - wait until the other functions are finished with updating the shadow
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
leaveLoops = false;
|
||||
bufferIndex = 0;
|
||||
|
||||
// Fragment display writing - writing will be done per line
|
||||
for (; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
{
|
||||
// Found a character that has been updated
|
||||
// Put the display cursor at the appropriate coordinates
|
||||
rowStart = rowCounter + 1;
|
||||
columnStart = colCounter + 1;
|
||||
for (bufferIndex = 0; (colCounter < self->displayDevice->parameters.numberOfColumns); colCounter++, bufferIndex++)
|
||||
if (Display_isCharacterUpdated(&self->displayShadow[rowCounter][colCounter]))
|
||||
{
|
||||
// Respect the max number of bytes to transmit
|
||||
if (bufferIndex < self->maxCharactersPerTransmit)
|
||||
// Found a character that has been updated
|
||||
// Put the display cursor at the appropriate coordinates
|
||||
rowStart = rowCounter + 1;
|
||||
columnStart = colCounter + 1;
|
||||
for (bufferIndex = 0; (colCounter < self->displayDevice->parameters.numberOfColumns); colCounter++, bufferIndex++)
|
||||
{
|
||||
// Still within the boundaries
|
||||
if (Display_isCharacterUpdated(&self->displayShadow[rowCounter][colCounter]))
|
||||
// Respect the max number of bytes to transmit
|
||||
if (bufferIndex < self->maxCharactersPerTransmit)
|
||||
{
|
||||
// Current character has been updated and must be sent to display
|
||||
// But data from display shadow to transmit buffer
|
||||
buffer[bufferIndex] = Display_getUpdatedCharacter(&self->displayShadow[rowCounter][colCounter]);
|
||||
// Still within the boundaries
|
||||
if (Display_isCharacterUpdated(&self->displayShadow[rowCounter][colCounter]))
|
||||
{
|
||||
// Current character has been updated and must be sent to display
|
||||
// But data from display shadow to transmit buffer
|
||||
buffer[bufferIndex] = Display_getUpdatedCharacter(&self->displayShadow[rowCounter][colCounter]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current character is already on the display
|
||||
// Stop scanning for more updated characters here and leave the loops in order
|
||||
// to start transmission to the display
|
||||
leaveLoops = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Current character is already on the display
|
||||
{
|
||||
// Max number of characters reached
|
||||
// Stop scanning for more updated characters here and leave the loops in order
|
||||
// to start transmission to the display
|
||||
leaveLoops = true;
|
||||
break;
|
||||
}
|
||||
leaveLoops = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max number of characters reached
|
||||
// Stop scanning for more updated characters here and leave the loops in order
|
||||
// to start transmission to the display
|
||||
leaveLoops = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if loop should be left
|
||||
if (leaveLoops)
|
||||
{
|
||||
// An inner loop decided to leave, so leave
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if loop should be left
|
||||
if (leaveLoops)
|
||||
// Give back display memory access semaphore to allow new updates
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
if (bufferIndex > 0)
|
||||
{
|
||||
// An inner loop decided to leave, so leave
|
||||
break;
|
||||
// If there was an update found, send it to the display
|
||||
DisplayDevice_write(self->displayDevice, buffer, bufferIndex, rowStart, columnStart);
|
||||
}
|
||||
}
|
||||
|
||||
// Give back display memory access semaphore to allow new updates
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
if (bufferIndex > 0)
|
||||
{
|
||||
// If there was an update found, send it to the display
|
||||
DisplayDevice_write(self->displayDevice, buffer, bufferIndex, rowStart, columnStart);
|
||||
}
|
||||
|
||||
// Handle the counters for row and column
|
||||
if (colCounter > (self->displayDevice->parameters.numberOfColumns - 1))
|
||||
{
|
||||
// End of row reached - reset column and increment row
|
||||
colCounter = 0;
|
||||
|
||||
if (rowCounter < (self->displayDevice->parameters.numberOfRows - 1))
|
||||
// Handle the counters for row and column
|
||||
if (colCounter > (self->displayDevice->parameters.numberOfColumns - 1))
|
||||
{
|
||||
// Increment row
|
||||
rowCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last row reached - restart at row 0
|
||||
rowCounter = 0;
|
||||
}
|
||||
}
|
||||
// End of row reached - reset column and increment row
|
||||
colCounter = 0;
|
||||
|
||||
// Check for display refresh timings
|
||||
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
|
||||
{
|
||||
self->refreshFeedCounter = 0;
|
||||
Display_characterUpdateAll(self);
|
||||
if (rowCounter < (self->displayDevice->parameters.numberOfRows - 1))
|
||||
{
|
||||
// Increment row
|
||||
rowCounter++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Last row reached - restart at row 0
|
||||
rowCounter = 0;
|
||||
}
|
||||
}
|
||||
// Check for display refresh timings
|
||||
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
|
||||
{
|
||||
self->refreshFeedCounter = 0;
|
||||
Display_characterUpdateAll(self);
|
||||
}
|
||||
|
||||
vTaskDelay(10);
|
||||
}
|
||||
|
||||
vTaskDelay(10);
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
// Email: support@microkey.nl
|
||||
// Web: www.microkey.nl
|
||||
// -----------------------------------------------------------------------------
|
||||
/// $Revision: 235 $
|
||||
/// $Author: swo $
|
||||
/// $Date: 2017-10-05 09:49:28 +0200 (do, 05 okt 2017) $
|
||||
/// $Revision$
|
||||
/// $Author$
|
||||
/// $Date$
|
||||
// (c) 2017 Micro-Key bv
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "DisplayDevice.h"
|
||||
#include "gpio.h"
|
||||
#include "adc.h"
|
||||
#include "internalADC.h"
|
||||
#include "PCBA.h"
|
||||
#include "MAX5715.h"
|
||||
#include "nhd0420.h"
|
||||
@@ -1088,7 +1088,6 @@ static void hwValidationMenuSM(struct HwValidationMenu* self, Button_Pressed_t b
|
||||
}
|
||||
else if( button == BUTTON_ENTER )
|
||||
{
|
||||
bool value = false;
|
||||
if( self->menuItemSelected == MENU_TEST_GENERIC_KEYPAD)
|
||||
{
|
||||
outputBufferLength = sprintf(self->outputBuffer, "[TODO] KEYPAD TEST\r\n");
|
||||
@@ -1397,4 +1396,4 @@ static ErrorStatus hwValidationMenuSetDac(struct HwValidationMenu* self, struct
|
||||
|
||||
return returnValue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "Display.h"
|
||||
#include "hwValidationMenu.h"
|
||||
#include "repairMenu.h"
|
||||
#include "repairProcess.h"
|
||||
|
||||
#include "misc.h"
|
||||
@@ -45,7 +46,7 @@
|
||||
#include "nhd0420.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "adc.h"
|
||||
#include "internalADC.h"
|
||||
#include "gpio.h"
|
||||
#include "IODevice.h"
|
||||
#include "keypadMatrix.h"
|
||||
@@ -88,16 +89,19 @@ static xTaskHandle initTaskHandle;
|
||||
static xTaskHandle ledTaskHandle;
|
||||
static xTaskHandle sysTaskHandle;
|
||||
|
||||
static struct Display _display;
|
||||
static struct Display _display = {.initialized = false};
|
||||
struct Display* display = &_display;
|
||||
|
||||
static struct NHD0420 nhd0420 = {.initialized = false};
|
||||
static struct MAX5715 max5715 = {.initialized = false};
|
||||
static struct RepairProcess _rp = {.initialized = false};
|
||||
|
||||
static struct RepairMenu _rm = {.initialized = false};
|
||||
static struct HwValidationMenu _hwValidation = {.initialized = false};
|
||||
static struct HwValidationMenuItems hwTestItems;
|
||||
|
||||
struct RepairProcess* rp = &_rp;
|
||||
struct MAX5715* dac = &max5715;
|
||||
|
||||
struct RepairMenu* rm = &_rm;
|
||||
struct HwValidationMenu* hwValidation = &_hwValidation;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -120,7 +124,7 @@ int main (void)
|
||||
// Create TaskHandles
|
||||
|
||||
ledTaskArguments.led = ledOrange;
|
||||
ledTaskArguments.frequency = 2;
|
||||
ledTaskArguments.frequency = 1;
|
||||
|
||||
xTaskCreate(initTask, (const char* const)"initTask", 1024, NULL, 5, &initTaskHandle);
|
||||
|
||||
@@ -173,7 +177,9 @@ static ErrorStatus systeminfoCommandHandler(void)
|
||||
vTaskDelay(10);
|
||||
OS_logTaskInfo(keypad->taskHandle);
|
||||
vTaskDelay(10);
|
||||
OS_logTaskInfo(rp->taskHandle);
|
||||
// OS_logTaskInfo(rp->taskHandle);
|
||||
vTaskDelay(10);
|
||||
OS_logTaskInfo(rm->taskHandle);
|
||||
vTaskDelay(10);
|
||||
OS_logTaskInfo(hwValidation->taskHandle);
|
||||
|
||||
@@ -186,11 +192,11 @@ static void initTask(void* parameters)
|
||||
|
||||
xTaskCreate(ledBlinkTask, (const char* const)"ledTask", 100, &ledTaskArguments, 0, &ledTaskHandle);
|
||||
|
||||
Logger_construct(mainLog, &uart3->device, 2, 512);
|
||||
Logger_construct(mainLog, &uart3->device, 1, 512);
|
||||
|
||||
NHD0420_construct(&nhd0420, &spiDisplay->device);
|
||||
|
||||
Display_construct(display, &nhd0420.displayDevice, 0, 256, 10, 1000, 5000);
|
||||
Display_construct(display, &nhd0420.displayDevice, 2, 256, 10, 1000, 10000);
|
||||
|
||||
Display_clearScreen(display);
|
||||
|
||||
@@ -207,6 +213,24 @@ static void initTask(void* parameters)
|
||||
Version_getInstance()->patch);
|
||||
Display_write(display, buffer, strlen(buffer), 3, 4);
|
||||
|
||||
MAX5715_construct(&max5715, &spiDAC->device);
|
||||
|
||||
MAX5715_writeREF_ON_2V5(&max5715);
|
||||
|
||||
MAX5715_writePOWER_NORMAL(&max5715, MAX5715_SEL_DACA | MAX5715_SEL_DACB | MAX5715_SEL_DACC);
|
||||
|
||||
MAX5715_writeCONFIG_LATCH_OFF(&max5715, MAX5715_SEL_DACA | MAX5715_SEL_DACB | MAX5715_SEL_DACC);
|
||||
|
||||
MAX5715Channel_construct(&dac->dac[0], dac, 0);
|
||||
MAX5715Channel_construct(&dac->dac[1], dac, 1);
|
||||
MAX5715Channel_construct(&dac->dac[2], dac, 2);
|
||||
|
||||
xTaskCreate(printSystemInfoTask, (const char* const)"SysInfoTask", 512, NULL, 0, &sysTaskHandle);
|
||||
|
||||
// Let start screen stay for 5 seconds
|
||||
vTaskDelay(INIT_START_SCREEN_DELAY);
|
||||
|
||||
|
||||
hwTestItems.display = &nhd0420.displayDevice;
|
||||
hwTestItems.internalADC = adc1;
|
||||
hwTestItems.externalDAC = &max5715;
|
||||
@@ -223,33 +247,11 @@ static void initTask(void* parameters)
|
||||
hwTestItems.teslaLock = teslaLock;
|
||||
hwTestItems.pcba = pcba;
|
||||
// EEPROM TO BE DONE
|
||||
// HwValidationMenu_construct(hwValidation, &uart1->device, &hwTestItems, 1, 1024);
|
||||
HwValidationMenu_construct(hwValidation, &uart1->device, &hwTestItems, 1, 512);
|
||||
|
||||
|
||||
MAX5715_construct(&max5715, &spiDAC->device);
|
||||
|
||||
MAX5715_writeREF_ON_2V5(&max5715);
|
||||
|
||||
MAX5715_writePOWER_NORMAL(&max5715, MAX5715_SEL_DACA | MAX5715_SEL_DACB | MAX5715_SEL_DACC);
|
||||
|
||||
MAX5715_writeCONFIG_LATCH_OFF(&max5715, MAX5715_SEL_DACA | MAX5715_SEL_DACB | MAX5715_SEL_DACC);
|
||||
|
||||
MAX5715Channel_construct(&max5715.dac[0], &max5715, 0);
|
||||
MAX5715Channel_construct(&max5715.dac[1], &max5715, 1);
|
||||
MAX5715Channel_construct(&max5715.dac[2], &max5715, 2);
|
||||
|
||||
MAX5715Channel_setValue(&max5715.dac[0], 0x200);
|
||||
MAX5715Channel_setValue(&max5715.dac[1], 0x800);
|
||||
MAX5715Channel_setValue(&max5715.dac[2], 0xD00);
|
||||
|
||||
|
||||
repairProcess_construct(rp, 3, 1024);
|
||||
|
||||
xTaskCreate(printSystemInfoTask, (const char* const)"SysInfoTask", 512, NULL, 1, &sysTaskHandle);
|
||||
|
||||
// Let start screen stay for 5 seconds
|
||||
vTaskDelay(INIT_START_SCREEN_DELAY);
|
||||
repairMenu_construct(rm, display, 2, 512);
|
||||
// Delete this init task
|
||||
|
||||
vTaskDelete(NULL);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
/// @file repairMenu.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 repairMenu.c
|
||||
/// @ingroup {group_name}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Include files
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include "repairMenu.h"
|
||||
#include "repairProcess.h"
|
||||
|
||||
#include "Display.h"
|
||||
|
||||
#include "Logger.h"
|
||||
#include "internalADC.h"
|
||||
#include "MAX5715.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constant and macro definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Type definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// File-scope variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static void repairMenu_task(void* parameters);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
ErrorStatus repairMenu_construct(struct RepairMenu* self, struct Display* display, int taskPriority, uint16_t stackSize)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
if (!self->initialized)
|
||||
{
|
||||
// Create a semaphore to sync access to the display shadow
|
||||
vSemaphoreCreateBinary(self->secondsSyncronisation);
|
||||
xSemaphoreGive(self->secondsSyncronisation);
|
||||
|
||||
|
||||
BaseType_t rv = xTaskCreate(repairMenu_task, "RepairMenu", stackSize, self, taskPriority, &self->taskHandle);
|
||||
if (rv != pdTRUE)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
LOGGER_INFO(mainLog, "Repair Menu task started");
|
||||
self->runTask = true;
|
||||
self->initialized = true;
|
||||
self->display = display;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER_ERROR(mainLog, "FAILED to start repair Menu with code %d", (int)rv);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
void repairMenu_destruct (struct RepairMenu* self)
|
||||
{
|
||||
self->initialized = false;
|
||||
}
|
||||
|
||||
|
||||
void repairMenu_feedSecondsCounter(struct RepairMenu* self)
|
||||
{
|
||||
if (self->initialized)
|
||||
{
|
||||
xSemaphoreGive(self->secondsSyncronisation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void repairMenu_feedSecondsCounterFromISR(struct RepairMenu* self)
|
||||
{
|
||||
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
xSemaphoreGiveFromISR(self->secondsSyncronisation, &higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static struct RepairProcess _rp = {.initialized = false};
|
||||
struct RepairProcess* rp = &_rp;
|
||||
extern struct MAX5715* dac;
|
||||
static void repairMenu_task(void* parameters)
|
||||
{
|
||||
struct RepairMenu* self = (struct RepairMenu*)parameters;
|
||||
|
||||
Display_write(self->display, " ", 20, 3, 1);
|
||||
|
||||
struct RepairProcessParameters rpParameters;
|
||||
rpParameters.adcRow1 = &adc1->channel[0];
|
||||
rpParameters.adcRow2 = &adc1->channel[1];
|
||||
rpParameters.adcRow3 = &adc1->channel[2];
|
||||
rpParameters.dacRow1 = &dac->dac[0];
|
||||
rpParameters.dacRow2 = &dac->dac[1];
|
||||
rpParameters.dacRow3 = &dac->dac[2];
|
||||
|
||||
MAX5715Channel_setValue(&dac->dac[1], 0xE00);
|
||||
|
||||
struct RepairPresetParameters presetStage1 = {.voltage = 0xA00, .duration = 5000, .softstartDuration = 1000};
|
||||
struct RepairPresetParameters presetStage2 = {.voltage = 0xE00, .duration = 1000, .softstartDuration = 2000};
|
||||
|
||||
struct RepairPreset repairPreset;
|
||||
repairPreset.numberOfStages = 2;
|
||||
repairPreset.preset[0] = presetStage1;
|
||||
repairPreset.preset[1] = presetStage2;
|
||||
|
||||
rp->repairPreset = &repairPreset;
|
||||
|
||||
repairProcess_construct(rp, &rpParameters, 2, 512);
|
||||
|
||||
|
||||
while(self->runTask)
|
||||
{
|
||||
xSemaphoreTake(self->secondsSyncronisation, portMAX_DELAY);
|
||||
|
||||
uint32_t secondsCounter;
|
||||
repairProcess_getRepairTime(rp, &secondsCounter);
|
||||
int hours = (secondsCounter / (60 * 60));
|
||||
int minutes = (secondsCounter - (hours * 60 * 60)) / 60;
|
||||
int seconds = (secondsCounter - (hours * 60 * 60) - (minutes * 60));
|
||||
char buffer[20];
|
||||
snprintf (buffer, sizeof(buffer) / sizeof(buffer[0]), "%02d:%02d:%02d", hours, minutes, seconds);
|
||||
Display_write(self->display, buffer, strlen(buffer), 2, 7);
|
||||
|
||||
Display_write(self->display, "R1", strlen("R1"), 3, 3);
|
||||
Display_write(self->display, "R2", strlen("R2"), 3, 10);
|
||||
Display_write(self->display, "R3", strlen("R3"), 3, 17);
|
||||
|
||||
uint16_t value;
|
||||
ADCChannel_read(rp->adcRow1, &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 1);
|
||||
|
||||
ADCChannel_read(rp->adcRow2, &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 8);
|
||||
|
||||
ADCChannel_read(rp->adcRow3, &value);
|
||||
snprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), "%04xV", value);
|
||||
Display_write(self->display, buffer, strlen(buffer), 4, 15);
|
||||
|
||||
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting RepairMenu task");
|
||||
vTaskDelete(self->taskHandle);
|
||||
}
|
||||
@@ -34,6 +34,9 @@
|
||||
#include "repairPreset.h"
|
||||
|
||||
#include "Logger.h"
|
||||
#include "MAX5715.h"
|
||||
|
||||
#include "PCBA.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Constant and macro definitions
|
||||
@@ -58,12 +61,14 @@
|
||||
|
||||
static void repairProcess_task(void* parameters);
|
||||
|
||||
static void calculateSoftStartStep (uint32_t currentTime, uint32_t softStartDuration, int targetVoltage, uint16_t* dacValue);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
ErrorStatus repairProcess_construct(struct RepairProcess* self, int taskPriority, uint16_t stackSize)
|
||||
ErrorStatus repairProcess_construct(struct RepairProcess* self, struct RepairProcessParameters* parameters, int taskPriority, uint16_t stackSize)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
@@ -71,10 +76,11 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, int taskPriority
|
||||
{
|
||||
// Create a semaphore to sync access to the display shadow
|
||||
vSemaphoreCreateBinary(self->secondsSyncronisation);
|
||||
xSemaphoreGive(self->secondsSyncronisation);
|
||||
xSemaphoreTake(self->secondsSyncronisation, 0);
|
||||
|
||||
|
||||
if (xTaskCreate(repairProcess_task, "RepairProcess", stackSize, self, taskPriority, &self->taskHandle) != pdTRUE)
|
||||
BaseType_t rv = xTaskCreate(repairProcess_task, "RepairProcess", stackSize, self, taskPriority, &self->taskHandle);
|
||||
if (rv != pdTRUE)
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
@@ -82,6 +88,21 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, int taskPriority
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
self->runTask = true;
|
||||
self->initialized = true;
|
||||
self->currentState = PREPARE;
|
||||
|
||||
self->adcRow1 = parameters->adcRow1;
|
||||
self->adcRow2 = parameters->adcRow2;
|
||||
self->adcRow3 = parameters->adcRow3;
|
||||
self->dacRow1 = parameters->dacRow1;
|
||||
self->dacRow2 = parameters->dacRow2;
|
||||
self->dacRow3 = parameters->dacRow3;
|
||||
|
||||
LOGGER_INFO(mainLog, "Repair Process task started");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER_ERROR(mainLog, "FAILED to start repair Process with code %d", (int)rv);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -95,18 +116,39 @@ ErrorStatus repairProcess_construct(struct RepairProcess* self, int taskPriority
|
||||
|
||||
void repairProcess_feedSecondsCounter(struct RepairProcess* self)
|
||||
{
|
||||
xSemaphoreGive(self->secondsSyncronisation);
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
xSemaphoreGive(self->secondsSyncronisation);
|
||||
}
|
||||
}
|
||||
|
||||
void repairProcess_feedSecondsCounterFromISR(struct RepairProcess* self)
|
||||
{
|
||||
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
xSemaphoreGiveFromISR(self->secondsSyncronisation, &higherPriorityTaskWoken);
|
||||
if (self->initialized)
|
||||
{
|
||||
xSemaphoreGiveFromISR(self->secondsSyncronisation, &higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
|
||||
ErrorStatus repairProcess_getRepairTime(const struct RepairProcess* self, uint32_t* repairTime)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
|
||||
if (self->initialized)
|
||||
{
|
||||
*repairTime = self->secondsCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
returnValue = ERROR;
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
|
||||
@@ -114,17 +156,170 @@ static void repairProcess_task(void* parameters)
|
||||
{
|
||||
struct RepairProcess* self = (struct RepairProcess*)parameters;
|
||||
|
||||
uint8_t presetIndex = 0;
|
||||
uint32_t softStartTimer = 0;
|
||||
uint32_t voltageHoldTimer = 0;
|
||||
|
||||
uint16_t voltageTarget = 0;
|
||||
uint16_t voltageRow1 = 0;
|
||||
uint16_t voltageRow2 = 0;
|
||||
uint16_t voltageRow3 = 0;
|
||||
|
||||
|
||||
// Reset the seconds counter to 0
|
||||
self->secondsCounter = 0;
|
||||
|
||||
while(self->runTask)
|
||||
{
|
||||
xSemaphoreTake(self->secondsSyncronisation, portMAX_DELAY);
|
||||
int hours = (self->secondsCounter / (60 * 60));
|
||||
int minutes = (self->secondsCounter - (hours * 60 * 60)) / 60;
|
||||
int seconds = (self->secondsCounter - (hours * 60 * 60) - (minutes * 60));
|
||||
LOGGER_WARNING(mainLog, "--- Repair clock %02i %02d %02d", hours, minutes, seconds);
|
||||
|
||||
|
||||
switch (self->currentState)
|
||||
{
|
||||
case PREPARE:
|
||||
{
|
||||
LOGGER_DEBUG(mainLog, "Repair Process: Preparing new stage of repair process");
|
||||
// Prepare a new repair process
|
||||
//Load the timers
|
||||
softStartTimer = self->secondsCounter + self->repairPreset->preset[presetIndex].softstartDuration;
|
||||
LOGGER_DEBUG(mainLog, "Softstart timer is %d (%d + %d)", softStartTimer, self->secondsCounter, self->repairPreset->preset[presetIndex].softstartDuration);
|
||||
voltageHoldTimer = self->secondsCounter + self->repairPreset->preset[presetIndex].duration;
|
||||
LOGGER_DEBUG(mainLog, "Voltagehold timer is %d (%d + %d)", voltageHoldTimer, self->secondsCounter, self->repairPreset->preset[presetIndex].duration);
|
||||
|
||||
voltageTarget = self->repairPreset->preset[presetIndex].voltage;
|
||||
|
||||
|
||||
voltageRow1 = 0;
|
||||
voltageRow2 = 0;
|
||||
voltageRow3 = 0;
|
||||
// Anode and CathodeMCP run all 3 ADCs and DACs
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageRow1);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageRow3);
|
||||
|
||||
|
||||
|
||||
///TODO CHECK FOR SAFETLY BEFORE START
|
||||
|
||||
self->currentState = SOFTSTART;
|
||||
break;
|
||||
}
|
||||
|
||||
case SOFTSTART:
|
||||
{
|
||||
// Perform softstart / ramp-up
|
||||
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
{
|
||||
// Tesla repair only runs ADC row2 and DAC row2
|
||||
calculateSoftStartStep(self->secondsCounter, softStartTimer, voltageTarget, &voltageRow2);
|
||||
LOGGER_DEBUG(mainLog, "Softstart running -> new target is %x", voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
}
|
||||
else if ((PCBA_getInstance()->pcba == Anode) || (PCBA_getInstance()->pcba == CathodeMCP))
|
||||
{
|
||||
calculateSoftStartStep(self->secondsCounter, softStartTimer, voltageTarget, &voltageRow1);
|
||||
calculateSoftStartStep(self->secondsCounter, softStartTimer, voltageTarget, &voltageRow2);
|
||||
calculateSoftStartStep(self->secondsCounter, softStartTimer, voltageTarget, &voltageRow3);
|
||||
LOGGER_DEBUG(mainLog, "Softstart running -> new target is %x %x %x", voltageRow1, voltageRow2, voltageRow3);
|
||||
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageRow1);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageRow3);
|
||||
}
|
||||
|
||||
// Check for end of softstart
|
||||
if (softStartTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = VOLTAGE_HOLD;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case VOLTAGE_HOLD:
|
||||
{
|
||||
// Actual repair state - hold target voltage until duration has passed
|
||||
LOGGER_DEBUG(mainLog, "Voltage Hold running -> target is %x", voltageTarget);
|
||||
|
||||
|
||||
if (PCBA_getInstance()->pcba == Tesla)
|
||||
{
|
||||
// Tesla repair only runs ADC row2 and DAC row2
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageTarget);
|
||||
}
|
||||
else if ((PCBA_getInstance()->pcba == Anode) || (PCBA_getInstance()->pcba == CathodeMCP))
|
||||
{
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageTarget);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageTarget);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageTarget);
|
||||
}
|
||||
|
||||
// Check for end of softstart
|
||||
if (voltageHoldTimer < self->secondsCounter)
|
||||
{
|
||||
// softstart finished
|
||||
self->currentState = FINISH_VERIFY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PAUSE:
|
||||
{
|
||||
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 > (presetIndex + 1))
|
||||
{
|
||||
// A next stage is available
|
||||
presetIndex++;
|
||||
self->currentState = PREPARE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case FINISHED:
|
||||
{
|
||||
voltageRow1 = 0;
|
||||
voltageRow2 = 0;
|
||||
voltageRow3 = 0;
|
||||
// Anode and CathodeMCP run all 3 ADCs and DACs
|
||||
MAX5715Channel_setValue(self->dacRow1, voltageRow1);
|
||||
MAX5715Channel_setValue(self->dacRow2, voltageRow2);
|
||||
MAX5715Channel_setValue(self->dacRow3, voltageRow3);
|
||||
|
||||
LOGGER_DEBUG(mainLog, "Repair process finished");
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
LOGGER_ERROR(mainLog, "Repair Process state machine reached unknown state");
|
||||
}
|
||||
|
||||
|
||||
self->secondsCounter++;
|
||||
}
|
||||
|
||||
LOGGER_INFO(mainLog, "Deleting repairProcess task");
|
||||
vTaskDelete(self->taskHandle);
|
||||
}
|
||||
|
||||
|
||||
static void calculateSoftStartStep (uint32_t currentTime, uint32_t softStartDuration, int targetVoltage, uint16_t* dacValue)
|
||||
{
|
||||
int value;
|
||||
|
||||
value = ((currentTime * 1000) / softStartDuration) * targetVoltage;
|
||||
|
||||
value = value / 1000;
|
||||
|
||||
*dacValue = (uint16_t)value;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "stm32f10x_usart.h"
|
||||
|
||||
#include "Display.h"
|
||||
#include "repairMenu.h"
|
||||
#include "repairProcess.h"
|
||||
|
||||
#include "Logger.h"
|
||||
@@ -273,6 +274,7 @@ void EXTI9_5_IRQHandler (void)
|
||||
|
||||
extern struct Display* display;
|
||||
extern struct RepairProcess* rp;
|
||||
extern struct RepairMenu* rm;
|
||||
|
||||
void RTC_IRQHandler(void)
|
||||
{
|
||||
@@ -286,6 +288,8 @@ void RTC_IRQHandler(void)
|
||||
xSemaphoreGiveFromISR(rtc->secondSync, &higherPriorityTaskWoken);
|
||||
Display_feedRefreshCounter(display);
|
||||
repairProcess_feedSecondsCounterFromISR(rp);
|
||||
repairMenu_feedSecondsCounterFromISR(rm);
|
||||
|
||||
|
||||
/* Wait until last write operation on RTC registers has finished */
|
||||
RTC_WaitForLastTask();
|
||||
|
||||
Reference in New Issue
Block a user