mirror of
https://github.com/travisgoodspeed/goodwatch
synced 2024-11-22 08:09:13 +00:00
Proper getchar() routine, keypad arrangement. Close #2.
This commit is contained in:
parent
5010755477
commit
ffbcb11212
@ -5,14 +5,14 @@ CC = msp430-gcc -mmcu=cc430f6137 -Wall
|
||||
BSL = ../bin/cc430-bsl.py
|
||||
|
||||
|
||||
modules=main.o lcd.o lcdtext.o rtc.o
|
||||
modules=main.o lcd.o lcdtext.o rtc.o keypad.o
|
||||
|
||||
all: goodwatch.hex
|
||||
|
||||
goodwatch: $(modules)
|
||||
$(CC) -o goodwatch $(modules)
|
||||
goodwatch.hex: goodwatch
|
||||
msp430-objcopy -O ihex goodwatch goodwatch.hex
|
||||
msp430-objcopy -O ihex goodwatch goodwatch.hex
|
||||
|
||||
clean:
|
||||
rm -f *~ *.hex *.elf *.o goodwatch
|
||||
|
127
firmware/keypad.c
Normal file
127
firmware/keypad.c
Normal file
@ -0,0 +1,127 @@
|
||||
#include <msp430.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. */
|
||||
|
||||
P2SEL=0x00; //All of port 2 are IO.
|
||||
P2DIR=0x00; //All are input.
|
||||
P2REN|=0xFF; //All resistor.
|
||||
P2OUT=0x00; //Pull all of them down.
|
||||
|
||||
P1SEL&=~0x80; //P1.7 is IO.
|
||||
P1DIR&=~0x80; //P1.7 is input.
|
||||
P1REN|=0x80;
|
||||
P1OUT&=~0x80; //Output low.
|
||||
}
|
||||
|
||||
//! 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;
|
||||
|
||||
|
||||
P1DIR&=~0x80; //All input.
|
||||
P2DIR=0x00;
|
||||
P1OUT&=~0x80; //All down.
|
||||
P2OUT=0x00;
|
||||
|
||||
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);
|
||||
|
||||
P1DIR&=~0x80; //All input.
|
||||
P2DIR=0x00;
|
||||
P1OUT&=~0x80; //All down.
|
||||
P2OUT=0x00;
|
||||
|
||||
//Temporary workaround for what I think is hardware damage in my
|
||||
//prototype.
|
||||
if(col&~1)
|
||||
return col&0xFE;
|
||||
|
||||
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=(key_row()<<4)|key_col();
|
||||
|
||||
if(scan&0xF0)
|
||||
return scan;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* //! Map of presses to buttons. */
|
||||
/* const int keymap[4][4]={ */
|
||||
/* //Lowest row has highest bitmask, so it comes first. */
|
||||
/* {0, '.', '=', '+'}, */
|
||||
/* {1, 2, 3, '-'}, */
|
||||
/* {4, 5, 6, '*'}, */
|
||||
/* {7, 8, 9, '%'} */
|
||||
/* }; */
|
||||
|
||||
//! 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(){
|
||||
return key_chr(key_scan());
|
||||
}
|
5
firmware/keypad.h
Normal file
5
firmware/keypad.h
Normal file
@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
void key_init();
|
||||
char getchar();
|
||||
|
@ -47,34 +47,27 @@ void lcd_init() {
|
||||
lcd_zero();
|
||||
for(i=0;i<13;i++)
|
||||
lcdbm[i]=0xFF;
|
||||
|
||||
//Seems unwired?
|
||||
lcdm[2]^=0x40;
|
||||
//Weird top-right thingys.
|
||||
//lcdm[9]|=0x04;
|
||||
//lcdm[0x0a]|=0x40;
|
||||
//lcdm[0x0c]|=0x01;
|
||||
|
||||
//Beyond the range.
|
||||
//lcdm[0x0c]|=0x10;
|
||||
}
|
||||
|
||||
//! Moved the LCD memory to the blink memory, then displays the backup.
|
||||
void lcd_predraw(){
|
||||
//Copy the LCD memory to the blink memory, then display blink memory.
|
||||
memcpy((char*) lcdbm,(char*) lcdm,13);
|
||||
//Switch to the backup of the previous frame.
|
||||
LCDBMEMCTL |= LCDDISP; // Enable blink memory
|
||||
}
|
||||
|
||||
//! Reverts to the main display.
|
||||
void lcd_postdraw(){
|
||||
//Now swap back the buffer.
|
||||
//Now swap back the buffer and copy it to blink memory for the next round.
|
||||
LCDBMEMCTL &= ~LCDDISP; // Return to main display memory.
|
||||
memcpy((char*) lcdbm,(char*) lcdm,13);
|
||||
}
|
||||
|
||||
//! LCD callback when the CPU wakes.
|
||||
void lcd_wdt(){
|
||||
lcd_predraw();
|
||||
|
||||
//lcd_zero();
|
||||
draw_time();
|
||||
|
||||
lcd_postdraw();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
//This maps the segments of each digit.
|
||||
// A, B, C, D, E, F, G, dp digit
|
||||
const int map[10][8]={
|
||||
const int lcdmap[10][8]={
|
||||
{0x0b04, 0x0b40, 0x0b20, 0x0b01, 0x0a10, 0x0a20, 0x0b02, 0x0b10}, //0
|
||||
{0x0940, 0x0a04, 0x0a02, 0x0910, 0x0901, 0x0902, 0x0920, 0x0a01}, //1
|
||||
{0x0804, 0x0840, 0x0820, 0x0801, 0x0710, 0x0720, 0x0802, 0x0810}, //2
|
||||
@ -29,7 +29,11 @@ const int map[10][8]={
|
||||
{0x0040, 0x0104, 0x0102, 0x0010, 0x0001, 0x0002, 0x0020, 0x0201}, //7
|
||||
};
|
||||
|
||||
enum mappos {A=1, B=2, C=4, D=8, E=0x10, F=0x20, G=0x40, DP=0x80};
|
||||
//These are the fragments of the day of the week: 0x0904, 0x0a40, 0x0c01
|
||||
//0x0c10 is beyond the screen.
|
||||
//0x0240 seems not to be wired to any visible segment.
|
||||
|
||||
enum lcdmappos {A=1, B=2, C=4, D=8, E=0x10, F=0x20, G=0x40, DP=0x80};
|
||||
const int numfont[]={
|
||||
A|B|C|D|E|F, //0
|
||||
B|C, //1
|
||||
@ -50,15 +54,13 @@ const int numfont[]={
|
||||
};
|
||||
|
||||
#define DRAWPOINT(todraw) lcdm[todraw>>8]|=todraw&0xFF
|
||||
#define DRAWPOINTB(todraw) lcdbm[todraw>>8]|=todraw&0xFF
|
||||
//! Draws one LCD digit.
|
||||
void lcd_digit(int pos, int digit){
|
||||
int segments=numfont[digit];
|
||||
int bit;
|
||||
for(bit=0;bit<8;bit++){
|
||||
if(segments&(1<<bit)){
|
||||
DRAWPOINT(map[pos][bit]);
|
||||
//DRAWPOINTB(map[pos][bit]);
|
||||
DRAWPOINT(lcdmap[pos][bit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "lcd.h"
|
||||
#include "rtc.h"
|
||||
#include "keypad.h"
|
||||
|
||||
//Initialize the XT1 crystal, and stabilize it.
|
||||
void xtal_init(){
|
||||
@ -34,6 +35,7 @@ int main(void) {
|
||||
lcd_init();
|
||||
xtal_init();
|
||||
rtc_init();
|
||||
key_init();
|
||||
|
||||
// Setup and enable WDT 250ms, ACLK, interval timer
|
||||
WDTCTL = WDT_ADLY_250;
|
||||
|
@ -64,9 +64,9 @@ void rtc_init(){
|
||||
|
||||
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void){
|
||||
//Display the hex value if we ever drop here.
|
||||
lcd_hex(0xC1000000|RTCIV);
|
||||
//lcd_hex(0xC1000000|RTCIV);
|
||||
|
||||
//switch(__even_in_range(RTCIV,16))
|
||||
//We don't really handly these, but might want to in the future.
|
||||
switch(RTCIV&~1){
|
||||
case 0: break; // No interrupts
|
||||
case 2: break; // RTCRDYIFG
|
||||
|
Loading…
Reference in New Issue
Block a user