- Added WARNING handler - put voltage calculations to dedicated module fixed last errors. Updated menu repair screen without ERROR from PID This is version 0.9.0.3, which is used for the first duration test Will also be tagged git-svn-id: https://svn.vbchaos.nl/svn/hsb/trunk@272 05563f52-14a8-4384-a975-3d1654cca0fa
317 lines
11 KiB
C
317 lines
11 KiB
C
// -----------------------------------------------------------------------------
|
|
/// @file keypadMatrix.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 keypadMatrix.c
|
|
/// @ingroup {group_name}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Include files
|
|
// -----------------------------------------------------------------------------
|
|
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "FreeRTOSFixes.h"
|
|
|
|
#include "Logger.h"
|
|
|
|
#include "keypadMatrix.h"
|
|
#include "platform.h"
|
|
|
|
#include "stm32f10x_it.h"
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Constant and macro definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Type definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// File-scope variables
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Function declarations
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// IO device without WRITE
|
|
static ErrorStatus read(const struct IODevice* self, char* buffer, size_t length, size_t* actualLength);
|
|
static void KeypadTask(void* parameters);
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// Function definitions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
ErrorStatus Keypad_construct(struct Keypad* self, size_t numberOfRows, size_t numberOfColumns, int debounceTime, int taskPriority, uint16_t stackSize, size_t rxQueueSize)
|
|
{
|
|
int rowCounter = 0;
|
|
int colCounter = 0;
|
|
ErrorStatus returnValue = SUCCESS;
|
|
|
|
if(!self->initialized)
|
|
{
|
|
IODevice_construct(&self->device, read, NULL);
|
|
|
|
if(returnValue == SUCCESS)
|
|
{
|
|
//! Create semaphore to synchronize with Keypad/EXTI interrupt handler
|
|
vSemaphoreCreateBinary(self->scanSemaphore);
|
|
}
|
|
|
|
self->waitToDebounce_ms = debounceTime;
|
|
self->rxQueueSize = rxQueueSize;
|
|
self->stackSize = stackSize;
|
|
self->taskPriority = taskPriority;
|
|
self->numberOfRows = numberOfRows;
|
|
self->numberOfColumns = numberOfColumns;
|
|
|
|
// Initialize memory to keep track of state changes per key
|
|
for (rowCounter = 0; rowCounter < self->numberOfRows; rowCounter++)
|
|
{
|
|
for (colCounter = 0; colCounter < self->numberOfColumns; colCounter++)
|
|
{
|
|
self->lastState[rowCounter][colCounter] = RELEASED;
|
|
}
|
|
}
|
|
|
|
//! Create a new FREERTOS queue to handle data from Keypad input to app
|
|
self->rxQueue = xQueueCreate(self->rxQueueSize, sizeof(struct KeypadQueueItem));
|
|
if (self->rxQueue == 0)
|
|
{
|
|
//! Queue identifier is 0 -> error
|
|
returnValue = ERROR; //! Set error flag
|
|
}
|
|
|
|
if(returnValue == SUCCESS)
|
|
{
|
|
xTaskCreate(KeypadTask, (const char*)"keypadTask", self->stackSize, keypad, self->taskPriority, &self->taskHandle);
|
|
}
|
|
|
|
if(returnValue == SUCCESS)
|
|
{
|
|
//! take txSemaphore
|
|
if (xSemaphoreTake(self->scanSemaphore, 0) == pdFALSE)
|
|
{
|
|
//! An error has occurred
|
|
returnValue = ERROR;
|
|
}
|
|
}
|
|
|
|
if(returnValue == SUCCESS)
|
|
{
|
|
LOGGER_INFO(mainLog, "Keypad task started");
|
|
self->initialized = true;
|
|
|
|
// // TUBE REPAIR
|
|
// struct KeypadQueueItem rxQueueItem;
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = PRESSED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = RELEASED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
//
|
|
// // SELECT CATHODE
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = PRESSED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = RELEASED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
//
|
|
// // SELECT PRESET
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = PRESSED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = RELEASED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
//
|
|
// // SELECT PRESET 7
|
|
// rxQueueItem.rowCoordinate = 2;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = PRESSED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
// rxQueueItem.rowCoordinate = 2;
|
|
// rxQueueItem.columnCoordinate = 0;
|
|
// rxQueueItem.keyEvent = RELEASED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
//
|
|
// // START
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 1;
|
|
// rxQueueItem.keyEvent = PRESSED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
// rxQueueItem.rowCoordinate = 0;
|
|
// rxQueueItem.columnCoordinate = 1;
|
|
// rxQueueItem.keyEvent = RELEASED;
|
|
// // Put event in queue
|
|
// xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
LOGGER_ERROR(mainLog, "Keypad task FAILED");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
returnValue = ERROR;
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
void Keypad_Destruct (const struct Keypad* self)
|
|
{
|
|
vTaskDelete(self->taskHandle);
|
|
vQueueDelete(self->rxQueue);
|
|
}
|
|
|
|
|
|
static ErrorStatus read(const struct IODevice* self, char* buffer, size_t length, size_t* actualLength)
|
|
{
|
|
ErrorStatus returnValue = SUCCESS;
|
|
|
|
const struct Keypad* keypad = (const struct Keypad*)self;
|
|
|
|
if (keypad->initialized)
|
|
{
|
|
struct KeypadQueueItem rxQueueItem;
|
|
|
|
if (xQueueReceive(keypad->rxQueue, &rxQueueItem, 0) == pdTRUE)
|
|
{
|
|
*actualLength = sizeof(struct KeypadQueueItem) / sizeof (char);
|
|
memcpy(buffer, &rxQueueItem, sizeof(struct KeypadQueueItem) / sizeof (char));
|
|
}
|
|
else
|
|
{
|
|
returnValue = ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
returnValue = ERROR;
|
|
}
|
|
|
|
return returnValue;
|
|
}
|
|
|
|
|
|
|
|
static void KeypadTask(void* parameters)
|
|
{
|
|
int rowCounter = 0;
|
|
int colCounter = 0;
|
|
struct Keypad* self = (struct Keypad*) parameters;
|
|
while (1)
|
|
{
|
|
// Wait for an interrupt to occur on one of the keypad columns
|
|
xSemaphoreTake(self->scanSemaphore, portMAX_DELAY);
|
|
// Debounce the keypad and wait for debounceTime prior to do anything
|
|
vTaskDelay(self->waitToDebounce_ms);
|
|
|
|
// Set all row outputs
|
|
for (rowCounter = 0; rowCounter < self->numberOfRows; rowCounter++)
|
|
{
|
|
GPIO_SetBits(self->row[rowCounter].gpio.GPIO_Typedef, self->row[rowCounter].gpio.GPIO_InitStruct.GPIO_Pin);
|
|
}
|
|
|
|
// Scan through each row individually by resetting it (output level low) and check all column levels
|
|
|
|
for (rowCounter = 0; rowCounter < self->numberOfRows; rowCounter++)
|
|
{
|
|
GPIO_ResetBits(self->row[rowCounter].gpio.GPIO_Typedef, self->row[rowCounter].gpio.GPIO_InitStruct.GPIO_Pin);
|
|
|
|
for (colCounter = 0; colCounter < self->numberOfColumns; colCounter++)
|
|
{
|
|
if (GPIO_ReadInputDataBit(self->column[colCounter].gpio.GPIO_Typedef, self->column[colCounter].gpio.GPIO_InitStruct.GPIO_Pin) == (uint8_t)Bit_SET)
|
|
{
|
|
if (self->lastState[rowCounter][colCounter] == PRESSED)
|
|
{
|
|
// Key has been released
|
|
struct KeypadQueueItem rxQueueItem;
|
|
rxQueueItem.rowCoordinate = rowCounter;
|
|
rxQueueItem.columnCoordinate = colCounter;
|
|
rxQueueItem.keyEvent = RELEASED;
|
|
// Put event in queue
|
|
xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
self->lastState[rowCounter][colCounter] = RELEASED;
|
|
}
|
|
else
|
|
{
|
|
// nothing changed
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (self->lastState[rowCounter][colCounter] == RELEASED)
|
|
{
|
|
// Key has been pressed
|
|
struct KeypadQueueItem rxQueueItem;
|
|
rxQueueItem.rowCoordinate = rowCounter;
|
|
rxQueueItem.columnCoordinate = colCounter;
|
|
rxQueueItem.keyEvent = PRESSED;
|
|
// Put event in queue
|
|
xQueueSend(self->rxQueue, &rxQueueItem, 0);
|
|
self->lastState[rowCounter][colCounter] = PRESSED;
|
|
}
|
|
else
|
|
{
|
|
// nothing changed
|
|
}
|
|
}
|
|
}
|
|
GPIO_SetBits(self->row[rowCounter].gpio.GPIO_Typedef, self->row[rowCounter].gpio.GPIO_InitStruct.GPIO_Pin);
|
|
}
|
|
|
|
// Reset all row outputs and return to IRQ status
|
|
for (rowCounter = 0; rowCounter < self->numberOfRows; rowCounter++)
|
|
{
|
|
GPIO_ResetBits(self->row[rowCounter].gpio.GPIO_Typedef, self->row[rowCounter].gpio.GPIO_InitStruct.GPIO_Pin);
|
|
}
|
|
|
|
IRQ_setKeypadEXTI(self, ENABLE);
|
|
}
|
|
}
|