2017-11-14 19:07:10 +00:00
|
|
|
/*! \file main.c
|
|
|
|
|
|
|
|
\brief Main module. This version just initializes the LCD and then
|
|
|
|
drops to a low power mode, letting the WDT do the work on a slow
|
2017-09-23 15:20:55 +00:00
|
|
|
interval.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <msp430.h>
|
2017-09-25 00:44:05 +00:00
|
|
|
#include <string.h>
|
2017-11-18 17:46:03 +00:00
|
|
|
#include <stdio.h>
|
2018-01-26 19:09:18 +00:00
|
|
|
#include <stdlib.h>
|
2017-09-23 15:20:55 +00:00
|
|
|
|
2017-12-04 19:14:09 +00:00
|
|
|
#include "api.h"
|
2017-11-18 17:46:03 +00:00
|
|
|
#include "dmesg.h"
|
2018-01-26 19:09:18 +00:00
|
|
|
#include "rng.h"
|
2017-09-25 20:26:18 +00:00
|
|
|
|
2017-09-30 16:16:54 +00:00
|
|
|
//! Power On Self Test
|
|
|
|
int post(){
|
|
|
|
if(LCDBIV || (LCDBCTL1&LCDNOCAPIFG)){
|
|
|
|
/* When the LCD cap is missing, of the wrong value, or
|
|
|
|
mis-soldered, the charge pump will be disabled out of
|
|
|
|
self-protection. This looks like a normally dark screen
|
|
|
|
abruptly fading to nothing, but you might still be able to
|
|
|
|
see the response at the right angle.
|
|
|
|
*/
|
2017-10-22 13:59:43 +00:00
|
|
|
lcd_string("lcd lcd");
|
2017-12-06 21:29:42 +00:00
|
|
|
printf("LCD Error.\n");
|
2017-10-22 13:59:43 +00:00
|
|
|
}else if(UCSCTL7&2){
|
|
|
|
/* This flag is triggered when the 32kHz crystal has a fault, such
|
|
|
|
as if it is not populated or if a little drag of solder reaches
|
|
|
|
ground. Watches with this problem will lose minutes a day, but
|
|
|
|
the '430 will fall back to an internal oscillator so that
|
|
|
|
non-watch functions still work.
|
|
|
|
*/
|
|
|
|
lcd_string(" crystal");
|
2017-12-06 21:29:42 +00:00
|
|
|
printf("32kHz crystal error.");
|
2017-12-05 22:34:39 +00:00
|
|
|
/*Can't run this test because of an unfixed errata.
|
2017-11-16 22:18:38 +00:00
|
|
|
}else if(has_radio && RF1AIFERR & 1){
|
|
|
|
lcd_string("RF LOWV");
|
2017-12-05 22:34:39 +00:00
|
|
|
*/
|
2017-11-16 22:18:38 +00:00
|
|
|
}else if(has_radio && RF1AIFERR & 2){
|
|
|
|
lcd_string("RF OPERR");
|
|
|
|
}else if(has_radio && RF1AIFERR & 4){
|
|
|
|
lcd_string("RFOUTERR");
|
|
|
|
}else if(has_radio && RF1AIFERR & 8){
|
|
|
|
lcd_string("RF OVERW");
|
2017-09-30 16:16:54 +00:00
|
|
|
}else{
|
|
|
|
/* Return zero if everything is hunky dory.
|
|
|
|
*/
|
2017-11-16 22:18:38 +00:00
|
|
|
lcd_string("all good");
|
2017-09-30 16:16:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-12-06 21:29:42 +00:00
|
|
|
|
|
|
|
printf("POST failure.\n");
|
2017-10-22 13:59:43 +00:00
|
|
|
//We had a failure, indicated above.
|
2017-09-30 16:16:54 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-11-14 19:07:10 +00:00
|
|
|
//! Main method.
|
2017-09-23 15:20:55 +00:00
|
|
|
int main(void) {
|
2017-11-14 16:55:07 +00:00
|
|
|
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
|
2017-09-26 20:05:55 +00:00
|
|
|
|
|
|
|
//Initialize the various modules.
|
2017-12-08 23:40:33 +00:00
|
|
|
dmesg_init();
|
2018-01-26 19:09:18 +00:00
|
|
|
|
2018-07-07 19:54:14 +00:00
|
|
|
printf("RNG ");
|
2018-01-26 19:09:18 +00:00
|
|
|
srand(true_rand()); // we do this as early as possible, because it messes with clocks
|
|
|
|
|
2018-07-07 19:54:14 +00:00
|
|
|
printf("REF ");
|
|
|
|
ref_init();
|
|
|
|
|
2018-01-26 19:09:18 +00:00
|
|
|
printf("LCD ");
|
2017-09-23 15:20:55 +00:00
|
|
|
lcd_init();
|
2017-11-14 16:55:07 +00:00
|
|
|
|
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
printf("rtc ");
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_string("RTC INIT");
|
2017-09-24 22:00:54 +00:00
|
|
|
rtc_init();
|
2017-12-08 23:40:33 +00:00
|
|
|
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
printf("key ");
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_string("KEY INIT");
|
2017-09-26 13:15:55 +00:00
|
|
|
key_init();
|
2017-11-14 16:55:07 +00:00
|
|
|
|
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
printf("but ");
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_string("BUT INIT");
|
2017-09-26 20:05:55 +00:00
|
|
|
sidebutton_init();
|
2017-11-14 16:55:07 +00:00
|
|
|
|
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
printf("osc ");
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_string("OSC INIT");
|
2017-12-09 12:34:21 +00:00
|
|
|
ucs_init();
|
2017-09-23 15:20:55 +00:00
|
|
|
|
2018-02-08 01:38:41 +00:00
|
|
|
lcd_zero();
|
|
|
|
printf("buzz ");
|
|
|
|
lcd_string("BUZZINIT");
|
|
|
|
buzz_init();
|
2018-02-10 17:28:12 +00:00
|
|
|
tone(NOTE_C7, 500);
|
|
|
|
tone(NOTE_E7, 500);
|
|
|
|
tone(NOTE_G7, 500);
|
2018-02-10 20:15:54 +00:00
|
|
|
tone(NOTE_A8, 500);
|
2018-02-10 17:28:12 +00:00
|
|
|
tone(NOTE_C8, 500);
|
2018-02-08 01:38:41 +00:00
|
|
|
|
2017-11-30 22:50:42 +00:00
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
lcd_string("UARTINIT");
|
|
|
|
uart_init();
|
|
|
|
|
|
|
|
lcd_zero();
|
|
|
|
printf("cp ");
|
2017-11-30 22:50:42 +00:00
|
|
|
lcd_string("CP INIT");
|
|
|
|
codeplug_init();
|
2017-12-03 03:49:33 +00:00
|
|
|
|
2017-11-30 22:50:42 +00:00
|
|
|
|
2017-11-16 17:53:12 +00:00
|
|
|
lcd_zero();
|
2017-12-08 23:40:33 +00:00
|
|
|
printf("rad ");
|
2017-11-16 17:53:12 +00:00
|
|
|
lcd_string("RAD INIT");
|
|
|
|
radio_init();
|
2017-11-30 22:50:42 +00:00
|
|
|
|
2017-12-06 21:29:42 +00:00
|
|
|
printf("Beginning POST.\n");
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_string("POSTPOST");
|
2017-09-30 16:16:54 +00:00
|
|
|
// Run the POST until it passes.
|
|
|
|
while(post());
|
|
|
|
|
2017-11-30 02:33:45 +00:00
|
|
|
lcd_zero();
|
|
|
|
lcd_string("APP INIT");
|
|
|
|
app_init();
|
|
|
|
|
2018-04-21 18:04:00 +00:00
|
|
|
|
|
|
|
descriptor_dump();
|
|
|
|
|
2017-11-30 02:33:45 +00:00
|
|
|
// Setup and enable WDT 250ms, ACLK, interval timer
|
|
|
|
WDTCTL = WDT_ADLY_250;
|
|
|
|
SFRIE1 |= WDTIE;
|
|
|
|
|
2017-12-06 21:29:42 +00:00
|
|
|
printf("Booted.\n");
|
2017-11-14 16:55:07 +00:00
|
|
|
__bis_SR_register(LPM3_bits + GIE); // Enter LPM3
|
2017-12-05 22:34:39 +00:00
|
|
|
//__bis_SR_register(LPM2_bits + GIE); // Enter LPM2
|
2017-09-25 20:26:18 +00:00
|
|
|
//__bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/interrupt
|
2017-11-28 22:24:10 +00:00
|
|
|
while(1){
|
2017-12-05 22:34:39 +00:00
|
|
|
//printf("main while().\n");
|
2017-12-08 23:40:33 +00:00
|
|
|
//uart_tx('T');
|
2018-07-23 23:10:16 +00:00
|
|
|
printf(".");
|
2017-11-28 22:24:10 +00:00
|
|
|
}
|
2017-09-23 15:20:55 +00:00
|
|
|
}
|
|
|
|
|
2017-11-14 19:07:10 +00:00
|
|
|
//! Watchdog Timer interrupt service routine, calls back to handler functions.
|
2017-09-23 15:20:55 +00:00
|
|
|
void __attribute__ ((interrupt(WDT_VECTOR))) watchdog_timer (void) {
|
2017-09-26 20:34:24 +00:00
|
|
|
static int latch=0;
|
2017-09-27 20:10:24 +00:00
|
|
|
|
2017-12-08 23:40:33 +00:00
|
|
|
/* When the UART is in use, we don't want to hog interrupt time, so
|
|
|
|
we will silently return.
|
|
|
|
*/
|
|
|
|
if(uartactive)
|
|
|
|
return;
|
|
|
|
|
2017-09-26 20:34:24 +00:00
|
|
|
if(sidebutton_mode()){
|
2017-11-13 01:47:58 +00:00
|
|
|
/* So if the side button is being pressed, we increment the latch
|
|
|
|
and move to the next application. Some applications, such as the
|
|
|
|
calculator, might hijack the call, so if we are latched for too
|
|
|
|
many poling cycles, we forcibly revert to the clock applicaiton.
|
|
|
|
*/
|
|
|
|
|
2017-09-26 20:34:24 +00:00
|
|
|
lcd_zero();
|
2017-09-28 21:34:46 +00:00
|
|
|
|
2017-09-27 20:10:24 +00:00
|
|
|
//Politely move to the next app if requested.
|
2017-09-26 20:34:24 +00:00
|
|
|
if(!(latch++))
|
|
|
|
app_next();
|
2017-09-28 21:34:46 +00:00
|
|
|
|
2017-09-27 20:10:24 +00:00
|
|
|
//Force a shift to the home if held for 4 seconds (16 polls)
|
|
|
|
if(latch>16)
|
|
|
|
app_forcehome();
|
2017-11-13 01:47:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
}else if(sidebutton_set()){
|
|
|
|
/* Similarly, we'll reboot if the SET/PRGM button has been held for 10
|
|
|
|
seconds (40 polls). We'll draw a countdown if getting close, so
|
|
|
|
there's no ambiguity as to whether the chip reset.
|
|
|
|
|
|
|
|
The other features of this button are handled within each application's
|
|
|
|
draw function.
|
|
|
|
*/
|
|
|
|
if(latch++>40)
|
|
|
|
PMMCTL0 = PMMPW | PMMSWPOR;
|
|
|
|
|
2017-09-26 20:34:24 +00:00
|
|
|
}else{
|
|
|
|
latch=0;
|
|
|
|
}
|
2017-09-28 21:34:46 +00:00
|
|
|
|
|
|
|
/* 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. */
|
2017-11-14 16:55:07 +00:00
|
|
|
lcd_predraw();
|
2017-09-28 21:34:46 +00:00
|
|
|
app_draw();
|
|
|
|
lcd_postdraw();
|
2017-09-23 15:20:55 +00:00
|
|
|
}
|