Files
hsb/S - Software/0 - HSB MRTS Kathode-MCP/3 - Implementation/0 - Code/Platform/src/keypadMatrix.c
mmi 711f8e72be Fixed multiple bugs and errors.
- 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
2017-11-15 15:40:39 +00:00

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);
}
}