Major updates:
- added DAConverter(s) - added ADConverter(s) - Fixed some display issues - Made repair process and signalProfileGenerator calculate with voltages (signed) instead of DAC/ADC values - Fixed several bugs in task handlings - Put display data mirror into dedicated file displaycontent git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@261 05563f52-14a8-4384-a975-3d1654cca0fa
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
// Include files
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Display.h"
|
||||
#include "Logger.h"
|
||||
|
||||
@@ -53,12 +55,6 @@
|
||||
|
||||
static void DisplayTask(void* parameters);
|
||||
|
||||
inline static void Display_characterUpdate (struct DisplayCharacter* displayCharacter, char character);
|
||||
inline static bool Display_isCharacterUpdated (struct DisplayCharacter* displayCharacter);
|
||||
inline static char Display_getUpdatedCharacter (struct DisplayCharacter* displayCharacter);
|
||||
inline static void Display_characterUpdateAll(struct Display* self);
|
||||
inline static void Display_clearShadow(struct Display* self);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Function definitions
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -81,13 +77,12 @@ ErrorStatus Display_construct(struct Display* self, struct DisplayDevice* displa
|
||||
|
||||
if(returnValue == SUCCESS)
|
||||
{
|
||||
// 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);
|
||||
|
||||
|
||||
Display_clearShadow(self);
|
||||
}
|
||||
if (returnValue == SUCCESS)
|
||||
{
|
||||
returnValue = DisplayContent_construct(&self->displayContent, self->displayDevice->parameters.numberOfRows, self->displayDevice->parameters.numberOfColumns);
|
||||
}
|
||||
|
||||
self->runTask = true;
|
||||
@@ -118,15 +113,14 @@ ErrorStatus Display_construct(struct Display* self, struct DisplayDevice* displa
|
||||
void Display_destruct(struct Display* self)
|
||||
{
|
||||
self->runTask = false;
|
||||
vSemaphoreDelete(self->displayShadowAccessSemaphore);
|
||||
}
|
||||
|
||||
|
||||
ErrorStatus Display_clearScreen(struct Display* self)
|
||||
{
|
||||
ErrorStatus returnValue = SUCCESS;
|
||||
returnValue = DisplayDevice_clear(self->displayDevice);
|
||||
Display_clearShadow(self);
|
||||
DisplayContent_clear(&self->displayContent);
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
@@ -203,16 +197,12 @@ ErrorStatus Display_write(struct Display* self, const char* buffer, size_t row,
|
||||
|
||||
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]);
|
||||
DisplayContent_updateCharacter(&self->displayContent, (row - 1), (column - 1) + loopCounter, buffer[loopCounter]);
|
||||
}
|
||||
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
|
||||
}
|
||||
@@ -230,74 +220,25 @@ void Display_feedRefreshCounter(struct Display* self)
|
||||
if (self->initialized)
|
||||
{
|
||||
self->refreshFeedCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline static void Display_characterUpdate (struct DisplayCharacter* displayCharacter, char character)
|
||||
{
|
||||
// Sending the same character should not lead to an updated character
|
||||
if (displayCharacter->character != character)
|
||||
{
|
||||
displayCharacter->character = character;
|
||||
displayCharacter->isUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline static bool Display_isCharacterUpdated (struct DisplayCharacter* displayCharacter)
|
||||
{
|
||||
return displayCharacter->isUpdated;
|
||||
}
|
||||
|
||||
|
||||
inline static char Display_getUpdatedCharacter (struct DisplayCharacter* displayCharacter)
|
||||
{
|
||||
displayCharacter->isUpdated = false;
|
||||
return displayCharacter->character;
|
||||
}
|
||||
|
||||
|
||||
inline static void Display_characterUpdateAll(struct Display* self)
|
||||
{
|
||||
size_t rowCounter;
|
||||
size_t colCounter;
|
||||
|
||||
// Get the access semaphore to the shadow - wait until the other functions are finished with updating the shadow
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
// Clear the display shadow
|
||||
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
{
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
|
||||
{
|
||||
self->displayShadow[rowCounter][colCounter].isUpdated = true;
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
}
|
||||
}
|
||||
// Give back display memory access semaphore to allow new updates
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
xSemaphoreGive(self->displayWriteRequest);
|
||||
}
|
||||
|
||||
|
||||
inline static void Display_clearShadow(struct Display* self)
|
||||
void Display_feedRefreshCounterFromISR(struct Display* self)
|
||||
{
|
||||
// Clear the display shadow
|
||||
size_t rowCounter;
|
||||
size_t colCounter;
|
||||
xSemaphoreTake(self->displayShadowAccessSemaphore, portMAX_DELAY);
|
||||
for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
|
||||
if (self->initialized)
|
||||
{
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
self->refreshFeedCounter++;
|
||||
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
|
||||
{
|
||||
// All characters of the display shadow are set to BLANK, but the isUpdated flag is kept at FALSE
|
||||
// this is, because the display itself has already received a command to clear its content. So
|
||||
// blanking the shadow without setting isUpdated to TRUE is only an action to update the
|
||||
// shadow to the actual situation on the screen
|
||||
self->displayShadow[rowCounter][colCounter].character = 0x20;
|
||||
self->displayShadow[rowCounter][colCounter].isUpdated = false;
|
||||
xSemaphoreGiveFromISR(self->displayWriteRequest, &higherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
xSemaphoreGive(self->displayShadowAccessSemaphore);
|
||||
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
|
||||
@@ -305,108 +246,32 @@ static void DisplayTask(void* parameters)
|
||||
{
|
||||
struct Display* self = (struct Display*)parameters;
|
||||
|
||||
bool leaveLoops = false;
|
||||
char buffer[NHD0420_NUMBER_OF_COLUMNS];
|
||||
int bufferIndex = 0;
|
||||
char buffer;
|
||||
int rowCounter = 0;
|
||||
int colCounter = 0;
|
||||
|
||||
size_t rowStart;
|
||||
size_t columnStart;
|
||||
|
||||
while (self->runTask)
|
||||
{
|
||||
// Wait until a write or refresh function has requested this task to write to the display
|
||||
// xSemaphoreTake(self->displayWriteRequest, portMAX_DELAY);
|
||||
|
||||
// for (rowCounter = 0; rowCounter < self->displayDevice->parameters.numberOfRows; rowCounter++)
|
||||
xSemaphoreTake(self->displayWriteRequest, portMAX_DELAY);
|
||||
// Check for display refresh timings
|
||||
if (self->refreshFeedCounter * self->refreshFeedFrequency_ms > self->refreshPeriod_ms)
|
||||
{
|
||||
// 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;
|
||||
self->refreshFeedCounter = 0;
|
||||
DisplayContent_refresh(&self->displayContent);
|
||||
}
|
||||
|
||||
// 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++)
|
||||
{
|
||||
for (colCounter = 0; colCounter < self->displayDevice->parameters.numberOfColumns; colCounter++)
|
||||
{
|
||||
if (Display_isCharacterUpdated(&self->displayShadow[rowCounter][colCounter]))
|
||||
if (DisplayContent_isCharacterUpdated(&self->displayContent, rowCounter, 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++)
|
||||
{
|
||||
// Respect the max number of bytes to transmit
|
||||
if (bufferIndex < self->maxCharactersPerTransmit)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
buffer = DisplayContent_getCharacter(&self->displayContent, rowCounter, colCounter);
|
||||
DisplayDevice_write(self->displayDevice, &buffer, 1, rowCounter + 1, colCounter + 1);
|
||||
}
|
||||
|
||||
// Check if loop should be left
|
||||
if (leaveLoops)
|
||||
{
|
||||
// An inner loop decided to leave, so leave
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user