- Tested/debugged the display module. Now functional

- Tested the RTC - currently indicated with green LED toggle - functional

Started with internal ADC driver

git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@226 05563f52-14a8-4384-a975-3d1654cca0fa
This commit is contained in:
mmi
2017-10-02 08:17:27 +00:00
parent f44979bf75
commit b7d4985090
16 changed files with 830 additions and 35 deletions

View File

@@ -0,0 +1,376 @@
// -----------------------------------------------------------------------------
/// @file Display_nhd0420.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_nhd0420.c
/// @ingroup {group_name}
// -----------------------------------------------------------------------------
// Include files
// -----------------------------------------------------------------------------
#include "Display.h"
#include "Logger.h"
#include "nhd0420.h"
// -----------------------------------------------------------------------------
// Constant and macro definitions
// -----------------------------------------------------------------------------
#define DISPLAY_TASK_STACK_SIZE (2048)
#define DISPLAY_TRANSMIT_MAX_CHUNK (10)
// -----------------------------------------------------------------------------
// Type definitions
// -----------------------------------------------------------------------------
struct displayCharacter
{
char character;
bool isUpdated;
};
// -----------------------------------------------------------------------------
// File-scope variables
// -----------------------------------------------------------------------------
static SemaphoreHandle_t displayShadowAccessSemaphore;
static struct displayCharacter displayShadow[NHD0420_NUMBER_OF_ROWS][NHD0420_NUMBER_OF_COLUMNS];
// -----------------------------------------------------------------------------
// Function declarations
// -----------------------------------------------------------------------------
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);
static void printfShadow(void);
// -----------------------------------------------------------------------------
// Function definitions
// -----------------------------------------------------------------------------
ErrorStatus Display_construct(struct Display* self, void* displayDriver)
{
int rowCounter = 0;
int colCounter = 0;
ErrorStatus returnValue = SUCCESS;
// This is of type NHD0420 - Cast is valid only within this C file
self->displayDriver = displayDriver;
// Clear the display shadow
for (rowCounter = 0; rowCounter < NHD0420_NUMBER_OF_ROWS; rowCounter++)
{
for (colCounter = 0; colCounter < NHD0420_NUMBER_OF_COLUMNS; colCounter++)
{
Display_characterUpdate(&displayShadow[rowCounter][colCounter], 0x20);
}
}
if(returnValue == SUCCESS)
{
// Create a semaphore to sync access to the display shadow
vSemaphoreCreateBinary(displayShadowAccessSemaphore);
xSemaphoreGive(displayShadowAccessSemaphore);
}
self->runTask = true;
if(returnValue == SUCCESS)
{
if (xTaskCreate(DisplayTask, (const char*)"DisplayTask", DISPLAY_TASK_STACK_SIZE, self, self->TaskPriority, self->taskHandle) != pdTRUE)
{
returnValue = ERROR;
LOGGER_ERROR("Starting display task failed");
}
else
{
LOGGER_INFO("Display task started");
}
}
if(returnValue == SUCCESS)
{
// If initialisation of module was successful, RESET and adjust the display
NHD0420_clearScreen(self->displayDriver);
vTaskDelay(5);
NHD0420_setContrast(self->displayDriver, 30);
vTaskDelay(5);
NHD0420_setBacklightBrightness(self->displayDriver, 3);
vTaskDelay(5);
NHD0420_turnOnDisplay(self->displayDriver);
vTaskDelay(5);
}
return returnValue;
}
void Display_destruct(struct Display* self)
{
self->runTask = false;
vSemaphoreDelete(displayShadowAccessSemaphore);
}
ErrorStatus Display_write(struct Display* self, const char* buffer, unsigned int length, unsigned int row, unsigned int column)
{
ErrorStatus returnValue = SUCCESS;
// 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 >= NHD0420_NUMBER_OF_ROWS)
{
returnValue = ERROR;
}
}
if (returnValue == SUCCESS)
{
// Check that the column coordinate does not exceed the display boundary
if (column - 1 >= NHD0420_NUMBER_OF_COLUMNS)
{
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
// NHD0420_NUMBER_OF_COLUMNS - column >= length
// must be valid in order to put the requested message on display
if (NHD0420_NUMBER_OF_COLUMNS - (column - 1) < length)
{
returnValue = ERROR;
}
}
if (returnValue == SUCCESS)
{
// Get the access semaphore to the display memory - wait for access
xSemaphoreTake(displayShadowAccessSemaphore, portMAX_DELAY);
int loopCounter;
for (loopCounter = 0; loopCounter < length; loopCounter++)
{
Display_characterUpdate(&displayShadow[row - 1][(column - 1) + loopCounter], buffer[loopCounter]);
}
xSemaphoreGive(displayShadowAccessSemaphore);
}
return returnValue;
}
inline static void Display_characterUpdate (struct displayCharacter* displayCharacter, char 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;
}
static void DisplayTask(void* parameters)
{
const struct Display* self = (const struct Display*)parameters;
const struct NHD0420* displayDriver = (const struct NHD0420*)self->displayDriver;
bool leaveLoops = false;
char buffer[NHD0420_NUMBER_OF_COLUMNS];
int bufferIndex = 0;
int rowCounter = 0;
int colCounter = 0;
while (self->runTask)
{
// Get the access semaphore to the shadow - wait until the write function is finished with updating the shadow
xSemaphoreTake(displayShadowAccessSemaphore, portMAX_DELAY);
leaveLoops = false;
bufferIndex = 0;
// printfShadow();
// Fragment display writing - writing will be done per line
for (; colCounter < NHD0420_NUMBER_OF_COLUMNS; colCounter++)
{
if (Display_isCharacterUpdated(&displayShadow[rowCounter][colCounter]))
{
// Found a character that has been updated
// Put the display cursor at the appropriate coordinates
NHD0420_setCursorToPosition(displayDriver, rowCounter + 1, colCounter + 1);
for (bufferIndex = 0; (colCounter < NHD0420_NUMBER_OF_COLUMNS); colCounter++, bufferIndex++)
{
// Respect the max number of bytes to transmit
if (bufferIndex < DISPLAY_TRANSMIT_MAX_CHUNK)
{
// Still within the boundaries
if (Display_isCharacterUpdated(&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(&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;
}
}
}
// 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(displayShadowAccessSemaphore);
if (bufferIndex > 0)
{
// If there was an update found, send it to the display
IODevice_write(displayDriver->device, buffer, bufferIndex);
}
// Handle the counters for row and column
if (colCounter > (NHD0420_NUMBER_OF_COLUMNS - 1))
{
// End of row reached - reset column and increment row
colCounter = 0;
if (rowCounter < (NHD0420_NUMBER_OF_ROWS - 1))
{
// Increment row
rowCounter++;
}
else
{
// Last row reached - restart at row 0
rowCounter = 0;
}
}
}
// Task has been marked to end - after leaving the endless loop, end/delete this task
vTaskDelete(self->taskHandle);
}
// DEBUG FUNCTION - MIGHT NOT BE NECESSARY LATER ON
static void printfShadow(void)
{
char tempBuffer[21];
char flagBuffer[21];
int tempLoop;
for (tempLoop = 0; tempLoop < 20; tempLoop++)
{
tempBuffer[tempLoop] = displayShadow[0][tempLoop].character;
if (displayShadow[0][tempLoop].isUpdated)
{
flagBuffer[tempLoop] = '1';
}
else
{
flagBuffer[tempLoop] = '0';
}
}
tempBuffer[20] = '\0';
flagBuffer[20] = '\0';
LOGGER_DEBUG("%s -- %s", tempBuffer, flagBuffer);
for (tempLoop = 0; tempLoop < 20; tempLoop++)
{
tempBuffer[tempLoop] = displayShadow[1][tempLoop].character;
if (displayShadow[1][tempLoop].isUpdated)
{
flagBuffer[tempLoop] = '1';
}
else
{
flagBuffer[tempLoop] = '0';
}
}
tempBuffer[20] = '\0';
flagBuffer[20] = '\0';
LOGGER_DEBUG("%s -- %s", tempBuffer, flagBuffer);
for (tempLoop = 0; tempLoop < 20; tempLoop++)
{
tempBuffer[tempLoop] = displayShadow[2][tempLoop].character;
if (displayShadow[2][tempLoop].isUpdated)
{
flagBuffer[tempLoop] = '1';
}
else
{
flagBuffer[tempLoop] = '0';
}
}
tempBuffer[20] = '\0';
flagBuffer[20] = '\0';
LOGGER_DEBUG("%s -- %s", tempBuffer, flagBuffer);
for (tempLoop = 0; tempLoop < 20; tempLoop++)
{
tempBuffer[tempLoop] = displayShadow[3][tempLoop].character;
if (displayShadow[3][tempLoop].isUpdated)
{
flagBuffer[tempLoop] = '1';
}
else
{
flagBuffer[tempLoop] = '0';
}
}
tempBuffer[20] = '\0';
flagBuffer[20] = '\0';
LOGGER_DEBUG("%s -- %s", tempBuffer, flagBuffer);
}

View File

@@ -43,7 +43,7 @@
// Constant and macro definitions
// -----------------------------------------------------------------------------
#define LOGQUEUE_SIZE (16)
#define LOGQUEUE_SIZE (24)
#define LOGGER_STACK_SIZE (512)
#define LOGGER_TASK_PRIORITY (2)

View File

@@ -31,6 +31,8 @@
// FreeRTOS includes
#include "FreeRTOS.h"
#include "task.h"
#include "Display.h"
#include "Logger.h"
#include "misc.h"
@@ -78,6 +80,8 @@ static xTaskHandle initTaskHandle;
static xTaskHandle ledTaskHandle;
static xTaskHandle sysTaskHandle;
static struct Display display;
static struct NHD0420 nhd0420;
static struct MAX5715 max5715;
@@ -157,21 +161,14 @@ static void initTask(void* parameters)
Logger_construct(&uart1->device);
// NHD0420_construct(&nhd0420, &uart1->device);
NHD0420_construct(&nhd0420, &spiDisplay->device);
NHD0420_turnOffDisplay(&nhd0420);
vTaskDelay(1000);
NHD0420_clearScreen(&nhd0420);
vTaskDelay(1000);
NHD0420_turnOnDisplay(&nhd0420);
vTaskDelay(1000);
NHD0420_setContrast(&nhd0420, 30);
vTaskDelay(1000);
NHD0420_setBacklightBrightness(&nhd0420, 3);
vTaskDelay(1000);
NHD0420_setCursorToHome(&nhd0420);
vTaskDelay(1000);
NHD0420_sendData(&nhd0420, "Anode repair A", 20);
Display_construct(&display, &nhd0420);
Display_write(&display, "anode repair", 12, 1, 1);
Display_write(&display, "A", 1, 1, 20);
Display_write(&display, "SW V. 1.0.0.0", 13, 3, 4);
MAX5715_construct(&max5715, &spiDAC->device);

View File

@@ -33,11 +33,15 @@
#include "stm32f10x_it.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_usart.h"
#include "Logger.h"
#include "keypadMatrix.h"
#include "led.h"
#include "platform.h"
#include "rtc.h"
#include "spi.h"
#include "uart.h"
@@ -369,3 +373,30 @@ void EXTI9_5_IRQHandler (void)
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
}
void RTC_IRQHandler(void)
{
static signed portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
/* Clear the RTC Second interrupt */
RTC_ClearITPendingBit(RTC_IT_SEC);
xSemaphoreGiveFromISR(rtc->secondSync, &higherPriorityTaskWoken);
if (ledGreen->status)
{
LED_turnOff(ledGreen);
}
else
{
LED_turnOn(ledGreen);
}
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
portEND_SWITCHING_ISR(higherPriorityTaskWoken);
}
}