Files
hsb/S - Software/0 - HSB MRTS Kathode-MCP/3 - Implementation/0 - Code/hsb-mrts/src/Display.c
mmi ff01d92ea8 Fixed HW validation menu
Fixed some minor issues/bugs

git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@284 05563f52-14a8-4384-a975-3d1654cca0fa
2017-11-21 12:36:16 +00:00

363 lines
11 KiB
C

// -----------------------------------------------------------------------------
/// @file Display.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 Display.c
/// @ingroup {group_name}
// -----------------------------------------------------------------------------
// Include files
// -----------------------------------------------------------------------------
#include <string.h>
#include "Display.h"
#include "Logger.h"
#include "nhd0420.h"
#include "platform.h"
// -----------------------------------------------------------------------------
// Constant and macro definitions
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Type definitions
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// File-scope variables
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// Function declarations
// -----------------------------------------------------------------------------
static void DisplayTask(void* parameters);
// -----------------------------------------------------------------------------
// Function definitions
// -----------------------------------------------------------------------------
ErrorStatus Display_construct(struct Display* self, struct DisplayDevice* displayDevice, int TaskPriority, uint16_t stackSize, int maxCharactersPerTransmit, int refreshFeedFrequency_ms, int refreshPeriod)
{
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;
if(returnValue == SUCCESS)
{
// Create a semaphore to sync writing requests to the display
vSemaphoreCreateBinary(self->displayWriteRequest);
}
if (returnValue == SUCCESS)
{
returnValue = DisplayContent_construct(&self->displayContent, self->displayDevice->parameters.numberOfRows, self->displayDevice->parameters.numberOfColumns);
}
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;
}
}
}
else
{
returnValue = ERROR;
}
return returnValue;
}
void Display_destruct(struct Display* self)
{
self->runTask = false;
}
ErrorStatus Display_clearScreen(struct Display* self)
{
ErrorStatus returnValue = SUCCESS;
DisplayContent_clear(&self->displayContent);
xSemaphoreGive(self->displayWriteRequest);
return returnValue;
}
ErrorStatus Display_clearLine(struct Display* self, size_t line)
{
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, line, 1);
}
ErrorStatus Display_setState(struct Display* self, DisplayDevice_functionalState state)
{
return DisplayDevice_setState(self->displayDevice, state);
}
ErrorStatus Display_setBrightness(struct Display* self, size_t brightness)
{
return DisplayDevice_setBrightness(self->displayDevice, brightness);
}
ErrorStatus Display_setContrast(struct Display* self, size_t contrast)
{
return DisplayDevice_setContrast(self->displayDevice, contrast);
}
ErrorStatus Display_setBlinkingCursorState(struct Display* self, DisplayDevice_functionalState state)
{
return DisplayDevice_setBlinkingCursorState(self->displayDevice, state);
}
ErrorStatus Display_setCursorToPosition(struct Display* self, unsigned int row, unsigned int column)
{
return DisplayDevice_setCursorToPosition(self->displayDevice, row, column);
}
ErrorStatus Display_backspace(struct Display* self)
{
return DisplayDevice_backspace(self->displayDevice);
}
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)
{
// 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)
{
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
// 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)
{
int loopCounter;
for (loopCounter = 0; loopCounter < length; loopCounter++)
{
DisplayContent_updateCharacter(&self->displayContent, (row - 1), (column - 1) + loopCounter, buffer[loopCounter]);
}
xSemaphoreGive(self->displayWriteRequest);
}
}
else
{
returnValue = ERROR;
}
return returnValue;
}
ErrorStatus Display_writeCentered(struct Display* self, const char* buffer, unsigned int row)
{
ErrorStatus returnValue = SUCCESS;
if (self->initialized)
{
int length = 0;
int column;
// Prior to any action on the display memory, perform necessary checkings
if (returnValue == SUCCESS)
{
// Check that the row coordinate does not exceed the display boundary
if (row - 1 >= self->displayDevice->parameters.numberOfRows)
{
returnValue = ERROR;
}
}
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
// must be valid in order to put the requested message on display
if (length > self->displayDevice->parameters.numberOfColumns )
{
returnValue = ERROR;
}
}
if (returnValue == SUCCESS)
{
// Calculate the column to start writing for a centered string
// simply put, the length of the row minus the length of the string divided by two
column = (self->displayDevice->parameters.numberOfColumns - length) / 2;
// In case of an uneven string length, add one column
column += ((self->displayDevice->parameters.numberOfColumns - length) % 2);
// Add one column because the driver should start at column 1 (human readable)
column += 1;
}
if (returnValue == SUCCESS)
{
int loopCounter;
for (loopCounter = 0; loopCounter < length; loopCounter++)
{
DisplayContent_updateCharacter(&self->displayContent, (row - 1), (column - 1) + loopCounter, buffer[loopCounter]);
}
xSemaphoreGive(self->displayWriteRequest);
}
}
else
{
returnValue = ERROR;
}
return returnValue;
}
void Display_feedRefreshCounter(struct Display* self)
{
if (self->initialized)
{
self->refreshFeedCounter++;
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
{
xSemaphoreGive(self->displayWriteRequest);
}
}
}
void Display_feedRefreshCounterFromISR(struct Display* self)
{
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
if (self->initialized)
{
self->refreshFeedCounter++;
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
{
xSemaphoreGiveFromISR(self->displayWriteRequest, &higherPriorityTaskWoken);
}
}
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
}
static void DisplayTask(void* parameters)
{
struct Display* self = (struct Display*)parameters;
char buffer;
int rowCounter = 0;
int colCounter = 0;
while (self->runTask)
{
xSemaphoreTake(self->displayWriteRequest, portMAX_DELAY);
// Check for display refresh timings
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
{
self->refreshFeedCounter = 0;
DisplayContent_refresh(&self->displayContent);
}
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
{
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
{
if (DisplayContent_isCharacterUpdated(&self->displayContent, rowCounter, colCounter))
{
buffer = DisplayContent_getCharacter(&self->displayContent, rowCounter, colCounter);
DisplayDevice_writeCharacter(self->displayDevice, &buffer, rowCounter + 1, colCounter + 1);
}
}
}
vTaskDelay(10);
}
// Task has been marked to end - after leaving the endless loop, end/delete this task
vTaskDelete(NULL);
}