mirror of
https://github.com/travisgoodspeed/goodwatch
synced 2024-11-22 16:59:57 +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
|
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
|
all: goodwatch.hex
|
||||||
|
|
||||||
goodwatch: $(modules)
|
goodwatch: $(modules)
|
||||||
$(CC) -o goodwatch $(modules)
|
$(CC) -o goodwatch $(modules)
|
||||||
goodwatch.hex: goodwatch
|
goodwatch.hex: goodwatch
|
||||||
msp430-objcopy -O ihex goodwatch goodwatch.hex
|
msp430-objcopy -O ihex goodwatch goodwatch.hex
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *~ *.hex *.elf *.o goodwatch
|
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();
|
lcd_zero();
|
||||||
for(i=0;i<13;i++)
|
for(i=0;i<13;i++)
|
||||||
lcdbm[i]=0xFF;
|
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.
|
//! Moved the LCD memory to the blink memory, then displays the backup.
|
||||||
void lcd_predraw(){
|
void lcd_predraw(){
|
||||||
//Copy the LCD memory to the blink memory, then display blink memory.
|
//Switch to the backup of the previous frame.
|
||||||
memcpy((char*) lcdbm,(char*) lcdm,13);
|
|
||||||
LCDBMEMCTL |= LCDDISP; // Enable blink memory
|
LCDBMEMCTL |= LCDDISP; // Enable blink memory
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Reverts to the main display.
|
//! Reverts to the main display.
|
||||||
void lcd_postdraw(){
|
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.
|
LCDBMEMCTL &= ~LCDDISP; // Return to main display memory.
|
||||||
|
memcpy((char*) lcdbm,(char*) lcdm,13);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! LCD callback when the CPU wakes.
|
//! LCD callback when the CPU wakes.
|
||||||
void lcd_wdt(){
|
void lcd_wdt(){
|
||||||
lcd_predraw();
|
lcd_predraw();
|
||||||
|
|
||||||
|
//lcd_zero();
|
||||||
draw_time();
|
draw_time();
|
||||||
|
|
||||||
lcd_postdraw();
|
lcd_postdraw();
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
//This maps the segments of each digit.
|
//This maps the segments of each digit.
|
||||||
// A, B, C, D, E, F, G, dp 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
|
{0x0b04, 0x0b40, 0x0b20, 0x0b01, 0x0a10, 0x0a20, 0x0b02, 0x0b10}, //0
|
||||||
{0x0940, 0x0a04, 0x0a02, 0x0910, 0x0901, 0x0902, 0x0920, 0x0a01}, //1
|
{0x0940, 0x0a04, 0x0a02, 0x0910, 0x0901, 0x0902, 0x0920, 0x0a01}, //1
|
||||||
{0x0804, 0x0840, 0x0820, 0x0801, 0x0710, 0x0720, 0x0802, 0x0810}, //2
|
{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
|
{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[]={
|
const int numfont[]={
|
||||||
A|B|C|D|E|F, //0
|
A|B|C|D|E|F, //0
|
||||||
B|C, //1
|
B|C, //1
|
||||||
@ -50,15 +54,13 @@ const int numfont[]={
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define DRAWPOINT(todraw) lcdm[todraw>>8]|=todraw&0xFF
|
#define DRAWPOINT(todraw) lcdm[todraw>>8]|=todraw&0xFF
|
||||||
#define DRAWPOINTB(todraw) lcdbm[todraw>>8]|=todraw&0xFF
|
|
||||||
//! Draws one LCD digit.
|
//! Draws one LCD digit.
|
||||||
void lcd_digit(int pos, int digit){
|
void lcd_digit(int pos, int digit){
|
||||||
int segments=numfont[digit];
|
int segments=numfont[digit];
|
||||||
int bit;
|
int bit;
|
||||||
for(bit=0;bit<8;bit++){
|
for(bit=0;bit<8;bit++){
|
||||||
if(segments&(1<<bit)){
|
if(segments&(1<<bit)){
|
||||||
DRAWPOINT(map[pos][bit]);
|
DRAWPOINT(lcdmap[pos][bit]);
|
||||||
//DRAWPOINTB(map[pos][bit]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
|
#include "keypad.h"
|
||||||
|
|
||||||
//Initialize the XT1 crystal, and stabilize it.
|
//Initialize the XT1 crystal, and stabilize it.
|
||||||
void xtal_init(){
|
void xtal_init(){
|
||||||
@ -34,6 +35,7 @@ int main(void) {
|
|||||||
lcd_init();
|
lcd_init();
|
||||||
xtal_init();
|
xtal_init();
|
||||||
rtc_init();
|
rtc_init();
|
||||||
|
key_init();
|
||||||
|
|
||||||
// Setup and enable WDT 250ms, ACLK, interval timer
|
// Setup and enable WDT 250ms, ACLK, interval timer
|
||||||
WDTCTL = WDT_ADLY_250;
|
WDTCTL = WDT_ADLY_250;
|
||||||
|
@ -64,9 +64,9 @@ void rtc_init(){
|
|||||||
|
|
||||||
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void){
|
void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void){
|
||||||
//Display the hex value if we ever drop here.
|
//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){
|
switch(RTCIV&~1){
|
||||||
case 0: break; // No interrupts
|
case 0: break; // No interrupts
|
||||||
case 2: break; // RTCRDYIFG
|
case 2: break; // RTCRDYIFG
|
||||||
|
Loading…
Reference in New Issue
Block a user