mirror of
https://github.com/travisgoodspeed/goodwatch
synced 2024-11-22 16:59:57 +00:00
142 lines
3.2 KiB
C
142 lines
3.2 KiB
C
/*! \file keypad.c
|
|
\brief Keypad driver.
|
|
*/
|
|
|
|
#include <msp430.h>
|
|
|
|
#include "apps.h"
|
|
|
|
//! Initializes the keypad pin directions.
|
|
void key_init(){
|
|
/* The keypad uses P1.7 and all of Port 2. Pins are bridged
|
|
together by rows and columns, which requires active scanning for
|
|
a read but can allow for an initial wakeup on an interrupt. */
|
|
|
|
/* Columns 2.2, 2.1, 2.0, and 1.7 are set to output mode pulled
|
|
high, so that any low row indicates a button press. */
|
|
|
|
P2SEL=0x00; //All of port 2 are IO.
|
|
P2DIR=BIT2|BIT1|BIT0; //Rows are input, columns are output.
|
|
P2REN|=0xFF; //All resistor.
|
|
P2OUT=BIT2|BIT1|BIT0; //Pull all of them down.
|
|
|
|
P1SEL&=~0x80; //P1.7 is IO.
|
|
P1DIR|=0x80; //P1.7 is output.
|
|
P1REN|=0x80;
|
|
P1OUT|=0x80; //Output high.
|
|
}
|
|
|
|
//! Quickly checks to see if a key is pressed.
|
|
int key_pressed(){
|
|
return (P2IN&(BIT3|BIT4|BIT5|BIT6));
|
|
}
|
|
|
|
//! Bitfields indicate pressed rows.
|
|
int key_row(){
|
|
int row;
|
|
P1DIR|=0x80; //P1.7 out.
|
|
P1OUT|=0x80; //P1.7 high.
|
|
P2DIR= 0x07; //P2.0, 2.1, 2.2 out.
|
|
P2OUT= 0x07; //P2.0, 2.1, 2.2 high.
|
|
|
|
//We'll return this result, but after cleaning up.
|
|
row=(P2IN>>3)&0x0F;
|
|
|
|
key_init();
|
|
|
|
return row;
|
|
}
|
|
|
|
//! Bitfields indicate pressed columns.
|
|
int key_col(){
|
|
int col;
|
|
P1DIR&=~0x80; //Input
|
|
P1OUT&=~0x80; //Low
|
|
P2DIR= 0xF8; //P2.1.3, 2.4, 2.5, 2.6 out
|
|
P2OUT= 0xF8; //P2.1.3, 2.4, 2.5, 2.6 high
|
|
|
|
//We'll return this result, but after cleaning up.
|
|
col=((P2IN&0x7)<<1) | ((P2IN&0x80)>>7);
|
|
|
|
|
|
//Temporary workaround for what I think is hardware damage in my
|
|
//prototype.
|
|
if(col&~1)
|
|
return col&0xFE;
|
|
|
|
key_init();
|
|
|
|
return col;
|
|
}
|
|
|
|
|
|
//! Returns the key code of the currently pressed button.
|
|
unsigned int key_scan(){
|
|
/* This is the key matrix. P2.7 isn't used, which would've been
|
|
nice to know earlier.
|
|
|
|
2.2 2.1 2.0 1.7
|
|
| | | |
|
|
2.3----+----+----+----+--10
|
|
| | | |
|
|
2.4----+----+----+----+--20
|
|
| | | |
|
|
2.5----+----+----+----+--40
|
|
| | | |
|
|
2.6----+----+----+----+--80
|
|
| | | |
|
|
08 04 02 01
|
|
*/
|
|
|
|
unsigned int scan;
|
|
|
|
//When no buttons are pressed, we need to shortcut the scan to avoid
|
|
//wasting I/O and energy.
|
|
if(!key_pressed())
|
|
return 0;
|
|
|
|
//Some button is pressed, so do an active scan to figure out which
|
|
//one.
|
|
scan=(key_row()<<4)|key_col();
|
|
key_init();
|
|
|
|
if(scan&0xF0)
|
|
return scan;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
|
|
//! Map of presses to buttons.
|
|
const unsigned int keymap[]={
|
|
/* Upper nybble is the scan code, lower nybble is the byte in ASCII.
|
|
*/
|
|
0x1837, 0x1438, 0x1239, 0x1100|'/',
|
|
0x2834, 0x2435, 0x2236, 0x2100|'*',
|
|
0x4831, 0x4432, 0x4233, 0x4100|'-',
|
|
0x8830, 0x8400|'.', 0x8200|'=', 0x8100|'+',
|
|
0x0000 //End on a null byte.
|
|
};
|
|
|
|
//! Returns a character of the current scan code.
|
|
unsigned int key_chr(code){
|
|
/* Row is the upper nybble, column is the lower nybble.*/
|
|
unsigned int i=0;
|
|
for(i=0;keymap[i];i++){
|
|
if(keymap[i]>>8==code)
|
|
return keymap[i]&0xFF;
|
|
}
|
|
|
|
//Return null for all unknown codes.
|
|
return 00;
|
|
}
|
|
|
|
//! Gets a character as ASCII.
|
|
char getchar(){
|
|
char c=key_chr(key_scan());
|
|
if(c)
|
|
//Clear the app timer when a button is pressed.
|
|
app_cleartimer();
|
|
return c;
|
|
}
|