From 3ec6b5f42f2a69d98f302e90ed8256808579f5d2 Mon Sep 17 00:00:00 2001 From: Travis Goodspeed Date: Tue, 26 Sep 2017 11:44:10 -0400 Subject: [PATCH] Beginnings of app support for #15. Also adds date to RTC. --- bin/cc430-bsl.py | 8 +++++++- firmware/Makefile | 10 +++++----- firmware/api.h | 9 +++++++++ firmware/applist.h | 8 ++++++++ firmware/apps.c | 20 ++++++++++++++++++++ firmware/apps.h | 19 +++++++++++++++++++ firmware/apps/clock.c | 33 +++++++++++++++++++++++++++++++++ firmware/apps/clock.h | 1 + firmware/apps/rpn.c | 6 ++++++ firmware/apps/rpn.h | 1 + firmware/keypad.c | 10 +--------- firmware/lcd.c | 10 +++++++--- firmware/rtc.c | 27 +++++++++++++++++++++++++-- 13 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 firmware/api.h create mode 100644 firmware/applist.h create mode 100644 firmware/apps.c create mode 100644 firmware/apps.h create mode 100644 firmware/apps/clock.c create mode 100644 firmware/apps/clock.h create mode 100644 firmware/apps/rpn.c create mode 100644 firmware/apps/rpn.h diff --git a/bin/cc430-bsl.py b/bin/cc430-bsl.py index 2c9152b..9a15c94 100755 --- a/bin/cc430-bsl.py +++ b/bin/cc430-bsl.py @@ -266,7 +266,13 @@ if __name__=='__main__': bsl.writeihexfile(args.file); if args.time!=None: lt=time.localtime() - timestr=chr(lt.tm_hour)+chr(lt.tm_min)+chr(lt.tm_sec) + #See firmware/rtc.c for the format. + timestr=( + #Hour, Minute, Second first. + chr(lt.tm_hour)+chr(lt.tm_min)+chr(lt.tm_sec)+"\xFF"+ + #u16 Year, u8 Month, u8 Day + chr(lt.tm_year&0xFF)+chr(lt.tm_year>>8)+chr(lt.tm_mon)+chr(lt.tm_mday) + ); bsl.write(0xFF00,timestr); if args.dump!=None: coredump(bsl); diff --git a/firmware/Makefile b/firmware/Makefile index f0b77b8..57f132f 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -1,16 +1,16 @@ #Standard Debian gcc-msp430 and msp430mcu packages. -CC = msp430-gcc -mmcu=cc430f6137 -Wall +CC = msp430-gcc -mmcu=cc430f6137 -Wall -I. BSL = ../bin/cc430-bsl.py - -modules=main.o lcd.o lcdtext.o rtc.o keypad.o +modules=main.o lcd.o lcdtext.o rtc.o keypad.o apps.c +apps= apps/clock.o apps/rpn.o all: goodwatch.hex -goodwatch: $(modules) - $(CC) -o goodwatch $(modules) +goodwatch: $(modules) $(apps) + $(CC) -o goodwatch $(modules) $(apps) goodwatch.hex: goodwatch msp430-objcopy -O ihex goodwatch goodwatch.hex diff --git a/firmware/api.h b/firmware/api.h new file mode 100644 index 0000000..82c2a52 --- /dev/null +++ b/firmware/api.h @@ -0,0 +1,9 @@ +/* This should be the only header file included by applications. It + should allow for general I/O functions, but nothing internal to a + driver. (But of course it includes too much for now.) +*/ + +#include "lcd.h" +#include "lcdtext.h" +#include "keypad.h" +#include "apps.h" diff --git a/firmware/applist.h b/firmware/applist.h new file mode 100644 index 0000000..838a80d --- /dev/null +++ b/firmware/applist.h @@ -0,0 +1,8 @@ +/* + Each of these function pointers is called four times per second. + */ +static struct app apps[]={ + {.init=0, .draw=clock_draw, .exit=0}, //Clock + {.init=0, .draw=rpn_draw, .exit=0}, //RPN Calculator + {.init=0, .draw=0, .exit=0} //End on null entry. +}; diff --git a/firmware/apps.c b/firmware/apps.c new file mode 100644 index 0000000..ea5338e --- /dev/null +++ b/firmware/apps.c @@ -0,0 +1,20 @@ +#include + +#include "apps.h" +#include "lcdtext.h" + +#include "applist.h" + +int appindex=0; + +//! Renders the current app to the screen. +void draw_app(){ + void (*tocall)(void)=apps[appindex].draw; + if(tocall) + tocall(); + else + appindex=0; + return; +} + +//Handles diff --git a/firmware/apps.h b/firmware/apps.h new file mode 100644 index 0000000..9e04751 --- /dev/null +++ b/firmware/apps.h @@ -0,0 +1,19 @@ +/* + These are functions for working with applications and the + user-visible task switcher. + + */ + +#include "apps/clock.h" +#include "apps/rpn.h" + + +struct app { + void (*init)(void); //Called exactly once at startup. + void (*draw)(void); //Called four times per second to draw display. + void (*exit)(void); //Called once when moving to the next applet. +}; + + + +void draw_app(); diff --git a/firmware/apps/clock.c b/firmware/apps/clock.c new file mode 100644 index 0000000..3c8e406 --- /dev/null +++ b/firmware/apps/clock.c @@ -0,0 +1,33 @@ +/* This is the main clock application, which is seen by default + whenever the watch has nothing else to do. +*/ + +#include "api.h" + +//! Draws the clock face in the main application. +void clock_draw(){ + static char oldch=0; + char ch=getchar(); + + if(oldch!=ch) + lcd_zero(); + + switch(ch){ + case '/': + draw_date(); + break; + case '7': + lcd_hex(0xdeadbeef); + break; + case '4': + lcd_hex(0xcafebabe); + break; + case 0: + draw_time(); + break; + default: + lcd_hex(ch); + } + + oldch=ch; +} diff --git a/firmware/apps/clock.h b/firmware/apps/clock.h new file mode 100644 index 0000000..71e459e --- /dev/null +++ b/firmware/apps/clock.h @@ -0,0 +1 @@ +void clock_draw(); diff --git a/firmware/apps/rpn.c b/firmware/apps/rpn.c new file mode 100644 index 0000000..2dec1ee --- /dev/null +++ b/firmware/apps/rpn.c @@ -0,0 +1,6 @@ +#include "api.h" + +//! Draws the RPN calculator. +void rpn_draw(){ + +} diff --git a/firmware/apps/rpn.h b/firmware/apps/rpn.h new file mode 100644 index 0000000..a588b61 --- /dev/null +++ b/firmware/apps/rpn.h @@ -0,0 +1 @@ +void rpn_draw(); diff --git a/firmware/keypad.c b/firmware/keypad.c index 3f2e020..ca79d76 100644 --- a/firmware/keypad.c +++ b/firmware/keypad.c @@ -88,20 +88,12 @@ unsigned int key_scan(){ 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|'%', + 0x1837, 0x1438, 0x1239, 0x1100|'/', 0x2834, 0x2435, 0x2236, 0x2100|'*', 0x4831, 0x4432, 0x4233, 0x4100|'-', 0x8830, 0x8400|'.', 0x8200|'=', 0x8100|'+', diff --git a/firmware/lcd.c b/firmware/lcd.c index 48781c6..2b4b6c6 100755 --- a/firmware/lcd.c +++ b/firmware/lcd.c @@ -7,6 +7,7 @@ #include "lcdtext.h" #include "rtc.h" +#include "apps.h" volatile unsigned char *lcdm=&LCDM1; volatile unsigned char *lcdbm=&LCDBM1; @@ -65,9 +66,12 @@ void lcd_postdraw(){ //! LCD callback when the CPU wakes. void lcd_wdt(){ lcd_predraw(); - - //lcd_zero(); - draw_time(); + + /* The applet is drawn four times per second. We handle + double-buffering, so that incomplete drawings won't be shown to + the user, but everything else is the app's responsibility. */ + + draw_app(); lcd_postdraw(); } diff --git a/firmware/rtc.c b/firmware/rtc.c index 780b9e0..3aa9029 100644 --- a/firmware/rtc.c +++ b/firmware/rtc.c @@ -22,6 +22,7 @@ int get_second(){ return RTCSEC; } +//! Draws the time. void draw_time(){ static int i=0; unsigned int hour=get_hour(); @@ -41,6 +42,26 @@ void draw_time(){ setpm(hour>=12); } +//! Draws the date as yyyy.mm.dd +void draw_date(){ + unsigned int year=RTCYEAR; + unsigned int month=RTCMON; + unsigned int day=RTCDAY; + + lcd_digit(7,(year/1000)%10); + lcd_digit(6,(year/100)%10); + lcd_digit(5,(year/10)%10); + lcd_digit(4,year%10); + setcolon(0); + lcd_digit(3,month/10); + lcd_digit(2,month%10); + lcd_digit(1,day/10); + lcd_digit(0,day%10); + + setam(0); + setpm(0); +} + //! Initializes the clock with the timestamp from memory. void rtc_init(){ // Setup RTC Timer @@ -57,8 +78,10 @@ void rtc_init(){ RTCHOUR = *((unsigned char*) 0xFF00) %24; RTCMIN = *((unsigned char*) 0xFF01) %60; RTCSEC = *((unsigned char*) 0xFF02) %60; - - //__bis_SR_register(LPM3_bits + GIE); + RTCYEAR = *((unsigned int*) 0xFF04) % 4096; + RTCMON = *((unsigned char*) 0xFF06); + RTCDAY = *((unsigned char*) 0xFF07); //Not sure why, but we have to set + RTCDAY = *((unsigned char*) 0xFF07); //the day twice. RTC Errata? } void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void){