diff --git a/firmware/Makefile b/firmware/Makefile index 6f0d21f..f0b77b8 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -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 diff --git a/firmware/keypad.c b/firmware/keypad.c new file mode 100644 index 0000000..3f2e020 --- /dev/null +++ b/firmware/keypad.c @@ -0,0 +1,127 @@ +#include + +//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()); +} diff --git a/firmware/keypad.h b/firmware/keypad.h new file mode 100644 index 0000000..f73b9ca --- /dev/null +++ b/firmware/keypad.h @@ -0,0 +1,5 @@ + + +void key_init(); +char getchar(); + diff --git a/firmware/lcd.c b/firmware/lcd.c index 03eb93a..48781c6 100755 --- a/firmware/lcd.c +++ b/firmware/lcd.c @@ -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(); } diff --git a/firmware/lcdtext.c b/firmware/lcdtext.c index 1444a6d..90bd983 100644 --- a/firmware/lcdtext.c +++ b/firmware/lcdtext.c @@ -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<