/**
* @file keypad.c
*
* @date 01.02.2015
* @author Pascal Gollor
* web http://www.pgollor.de
*
* @copyright Dieses Werk ist unter einer Creative Commons Lizenz vom Typ
* Namensnennung - Weitergabe unter gleichen Bedingungen 3.0 Deutschland zugänglich.
* Um eine Kopie dieser Lizenz einzusehen, konsultieren Sie
* http://creativecommons.org/licenses/by-sa/3.0/de/ oder wenden Sie sich
* brieflich an Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
*
* -- englisch version --
* @n This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Germany License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
*
*/
#include "keypad.h"
#include <avr/pgmspace.h> // PROGMEM
#include <util/delay.h> // delay_ms
#ifdef KEYPAD_DEBUG
#include "defs.h"
#include "uart.h"
#endif
/**
* @brief keypad keys
*
* for each key you can use everything value from 0-254
* 255 means: no valid key
*/
PROGMEM const uint8_t g_keypad_key[KEYPAD_ROWS][KEYPAD_COLUMNS] = {
{'a', 'b', '#', '*'},
{'1', '2', '3', 'c'},
{'4', '5', '6', 'd'},
{'7', '8', '9', 'e'},
{'<', '0', '>', 'f'}
};
/**
* @brief init io ports for keypad
*/
void keypad_init(void)
{
// columns
KEYPAD_COLUMN_REGISTER |= KEYPAD_COLUMN_BITS; // define columns as output
KEYPAD_COLUMN_OUT &= ~(KEYPAD_COLUMN_BITS); // set columns to zero
// rows
KEYPAD_ROW_REGISTER &= ~(KEYPAD_ROW_BITS); // define rows as input
KEYPAD_ROW_OUT |= KEYPAD_ROW_BITS; // enable pullup for rows
}
/**
* @brief get key from keypad
*/
uint8_t keypad_getKey(void)
{
uint8_t col = KEYPAD_NO_VALID_KEY;
uint8_t row = 0;
// read row channels
row = ((~KEYPAD_ROW_IN) & KEYPAD_ROW_BITS) >> KEYPAD_ROW_FIRST_CHANNEL;
if (row == 0)
{
// no key is pressed
return KEYPAD_NO_VALID_KEY;
}
// wait for debounce
_delay_ms(10);
if (row != ((~KEYPAD_ROW_IN) & KEYPAD_ROW_BITS) >> KEYPAD_ROW_FIRST_CHANNEL)
{
return KEYPAD_NO_VALID_KEY;
}
// set columns to zero
KEYPAD_COLUMN_OUT &= ~(KEYPAD_COLUMN_BITS);
_delay_us(1);
// check for pressed column
for (uint8_t i = KEYPAD_COLUMN_FIRST_CHANNEL; i < (KEYPAD_COLUMN_FIRST_CHANNEL + KEYPAD_COLUMNS); i++)
{
KEYPAD_COLUMN_OUT |= (1 << i);
_delay_us(1);
if ((KEYPAD_ROW_IN & KEYPAD_ROW_BITS) == KEYPAD_ROW_BITS)
{
// debounce
_delay_ms(10);
if ((KEYPAD_ROW_IN & KEYPAD_ROW_BITS) != KEYPAD_ROW_BITS)
{
col = KEYPAD_NO_VALID_KEY;
break;
}
col = i - KEYPAD_COLUMN_FIRST_CHANNEL;
break;
}
KEYPAD_COLUMN_OUT &= ~(1 << i);
_delay_us(1);
}
// set columns to zero
KEYPAD_COLUMN_OUT &= ~(KEYPAD_COLUMN_BITS);
if (col == KEYPAD_NO_VALID_KEY)
{
// no column detected
return KEYPAD_NO_VALID_KEY;
}
// detect row
for (uint8_t i = 0; i < KEYPAD_ROWS; i++)
{
if (row >> i == 1)
{
row = i;
break;
}
}
if (row >= KEYPAD_ROWS)
return KEYPAD_NO_VALID_KEY;
#ifdef KEYPAD_DEBUG
printf("row: %i" CR, row);
printf("column: %i" CR, col);
uart_flush();
#endif
// return key from keylist
return pgm_read_byte(&g_keypad_key[row][col]);
}
/**
* @brief get key and wait to for loosing
*/
uint8_t keypad_getKeyAndWait(void)
{
uint8_t key = keypad_getKey();
uint8_t last_key = KEYPAD_NO_VALID_KEY;
if (key == KEYPAD_NO_VALID_KEY)
{
return KEYPAD_NO_VALID_KEY;
}
last_key = key;
while (key != KEYPAD_NO_VALID_KEY)
{
key = keypad_getKey();
}
return last_key;
}