oswald/metawatch/mw_main.c
2021-02-14 18:03:13 +01:00

738 lines
17 KiB
C

#include <msp430.h>
#include <msp430xgeneric.h>
#include <stdio.h>
#include <string.h>
#include "F5xx_F6xx_Core_Lib/HAL_PMM.h"
#include "F5xx_F6xx_Core_Lib/HAL_UCS.h"
#include "mw_main.h"
#include "mw_uart.h"
#include "mw_lcd.h"
#include "mw_bt.h"
#include "mw_adc.h"
#include "mw_bt.h"
#include "mw_acc.h"
#include "bt_hci.h"
#include "bt_l2cap.h"
#include "oswald_main.h"
#include "oswald_hal.h"
#include "bluetooth_init_cc256x.h"
uint16_t _event_src = 0;
#define HARDWARE_REVISION_ADDRESS (0x1a07)
uint8_t GetMsp430HardwareRevision(void)
{
uint8_t *pDeviceType = (uint8_t *)(uint8_t *)HARDWARE_REVISION_ADDRESS;
return pDeviceType[0]+'1';
}
uint8_t DetermineErrata(void)
{
uint8_t Revision = GetMsp430HardwareRevision();
switch (Revision) {
case 'F':
case 'G':
case 'H':
return 0;
break;
default:
return 1;
break;
}
}
static void set16mhz(void)
{
UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
UCSCTL1 = DCORSEL_5; // Select suitable range
UCSCTL2 = 488 + FLLD_1; // Set DCO Multiplier
UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ;
// Worst-case settling time for the DCO when the DCO range bits have been
// changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
// for optimization.
// 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
// t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
// __delay_cycles(562500);
int i;
for (i=0;i<10;i++){
__delay_cycles(56250);
}
}
static unsigned char PMM15Check(void)
{
// First check if SVSL/SVML is configured for fast wake-up
if ((!(SVSMLCTL & SVSLE)) || ((SVSMLCTL & SVSLE) && (SVSMLCTL & SVSLFP)) ||
(!(SVSMLCTL & SVMLE)) || ((SVSMLCTL & SVMLE) && (SVSMLCTL & SVMLFP)))
{
// Next Check SVSH/SVMH settings to see if settings are affected by PMM15
if ((SVSMHCTL & SVSHE) && (!(SVSMHCTL & SVSHFP)))
{
if ( (!(SVSMHCTL & SVSHMD)) ||
((SVSMHCTL & SVSHMD) && (SVSMHCTL & SVSMHACE)) )
return 1; // SVSH affected configurations
}
if ((SVSMHCTL & SVMHE) && (!(SVSMHCTL & SVMHFP)) && (SVSMHCTL & SVSMHACE))
return 1; // SVMH affected configurations
}
return 0; // SVS/M settings not affected by PMM15
}
#define configCPU_CLOCK_HZ ((unsigned long) 16777216) /* 512*32768 */
#define configTICK_RATE_HZ ((unsigned int)1024)
#define ACLK_MULTIPLIER ((unsigned int)512)
static void setup_clocks(void)
{
unsigned long i;
SetVCore(PMMCOREV_2);
/* use external oscillator */
P7SEL |= BIT0 + BIT1;
#if 1
if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L;
}
i = 50000;
while ((SFRIFG1 & OFIFG) && i--) {
UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
SFRIFG1 &= ~OFIFG;
}
UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(XT1DRIVE_0);
set16mhz();
UCSCTL8 |= SMCLKREQEN;
#else
// Startup LFXT1 32 kHz crystal
while (LFXT_Start_Timeout(XT1DRIVE_0, 50000) == UCS_STATUS_ERROR)
nop();
// select the sources for the FLL reference and ACLK
SELECT_ACLK(SELA__XT1CLK);
SELECT_FLLREF(SELREF__XT1CLK);
// 512 * 32768 = 16777216 / 1024
Init_FLL_Settle(configCPU_CLOCK_HZ/configTICK_RATE_HZ, ACLK_MULTIPLIER);
// Disable FLL loop control
// __bis_SR_register(SCG0);
#endif
// setup for quick wake up from interrupt and
// minimal power consumption in sleep mode
DISABLE_SVSL(); // SVS Low side is turned off
DISABLE_SVSL_RESET();
DISABLE_SVML(); // Monitor low side is turned off
DISABLE_SVML_INTERRUPT();
DISABLE_SVMH(); // Monitor high side is turned off
DISABLE_SVMH_INTERRUPT();
ENABLE_SVSH(); // SVS High side is turned on
ENABLE_SVSH_RESET(); // Enable POR on SVS Event
SVSH_ENABLED_IN_LPM_FULL_PERF(); // SVS high side Full perf mode,
// stays on in LPM3,enhanced protect
SVSL_ENABLED_IN_LPM_FAST_WAKE();
// Wait until high side, low side settled
while ((PMMIFG & SVSMLDLYIFG) == 0 && (PMMIFG & SVSMHDLYIFG) == 0)
nop();
CLEAR_PMM_IFGS();
while (PMM15Check());
// Errata PMM17
if (DetermineErrata()) {
*(unsigned int*)(0x0110) = 0x9602;
*(unsigned int*)(0x0112) |= 0x0800;
}
/* enable oscillator fault NMI IRQ */
// SFRIE1 = OFIE;
}
#if 0
#pragma vector=PWR_PORT_VECTOR
__interrupt void PWR_ISR (void)
{
/* clear all possible sources */
PWR_PORT_IFG &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
_event_src |= POWER_SRC_EVENT;
LPM3_EXIT();
nop();
}
#endif
static void mw_init_vibrate_pwm(void)
{
#ifdef MW_DIGITAL_V2
// Start with P7.3 as an output
P7OUT &= ~BIT3; // Low when a digital output
P7SEL &= ~BIT3; // P7 option select = false
P7DIR |= BIT3; // P7 outputs
TA1CTL = 0;
// No expansion divide
TA1EX0 = 0;
// do a PWM with 64 total steps. This gives a count up of 32 and
// a count down of 32
TA1CCR0 = 31;
// Compare channel 2 is used as output
TA1CCTL2 = OUTMOD_6; // PWM output mode: 6 - toggle/set
TA1CCR2 = 10; // 10 is a 2/3 duty cycle
#endif
}
static void setup_pins(void)
{
CONFIG_SRAM_PINS();
CONFIGURE_BUTTON_PINS();
#ifdef MW_DEVBOARD_V2
CONFIG_LED_PINS(); // debug LEDs on devboard
#endif
DISABLE_LCD_LED(); // frontlight
CONFIG_DEBUG_PINS();
CONFIG_ACCELEROMETER_PINS();
//DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
ENABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
HARDWARE_CFG_SENSE_INIT();
APPLE_CONFIG();
APPLE_POWER_DISABLE();
CONFIG_BT_PINS();
// BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
// BT_IO1_CONFIG_AS_OUTPUT_LOW();
// BT_IO2_CONFIG_AS_OUTPUT_LOW();
BT_CLK_REQ_CONFIG_AS_INPUT();
BT_IO1_CONFIG_AS_INPUT();
BT_IO2_CONFIG_AS_INPUT();
mw_disable_bt();
LIGHT_SENSE_INIT();
LIGHT_SENSOR_SHUTDOWN();
BATTERY_SENSE_INIT();
BATTERY_SENSE_DISABLE();
BAT_CHARGE_DIR &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
BAT_CHARGE_OUT |= BAT_CHARGE_PWR_BIT | BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2; // pull-up
BAT_CHARGE_REN |= BAT_CHARGE_PWR_BIT; // enable resistors
// BAT_CHARGE_IE |= BAT_CHARGE_PWR_BIT;
BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN; // !CE, negative logic
BAT_CHARGE_DIR |= BAT_CHARGE_ENABLE_PIN;
/* disable reset function, enable NMI, do not enable NMI IRQ */
/* to avoid accidential reset on charger clip connect */
#ifndef MW_DEVBOARD_V2 // but only on real watch
SFRRPCR &= ~SYSRSTRE;
SFRRPCR |= SYSNMI;
#endif
/* allow debug UART */
/*
P10SEL &= ~(BIT6 | BIT7);
P10DIR |= BIT6 | BIT7;
P10OUT &= ~(BIT6 | BIT7);
*/
#ifndef MW_DEVBOARD_V2
ENABLE_MUX_OUTPUT_CONTROL();
#ifdef MW_DEBUG_UART
MUX_OUTPUT_SELECTS_SERIAL();
#else
MUX_OUTPUT_OFF();
#endif
#endif
}
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR (void)
{
/* eventually we will do something here, not for now */
_event_src |= WATCHDOG_EVENT;
nop();
}
static void setup_wdt(void)
{
#if 1
WDTCTL = WDTPW + WDTHOLD; // disable watchdog
#else
WDTCTL = WDT_ADLY_1000; // 1 second timeout
SFRIE1 |= WDTIE; // Enable WDT interrupt
#endif
}
#if 1
#pragma vector=UNMI_VECTOR
__interrupt void NMI_ISR (void)
{
#if defined MW_DEVBOARD_V2
LED7_TOGGLE();
debug_uart_tx_char('n');
#endif
while ((SFRIFG1 & OFIFG)) {
UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
SFRIFG1 &= ~OFIFG;
}
}
#endif
#pragma vector=RTC_VECTOR
__interrupt void RTC_ISR (void)
{
switch (RTCIV) {
case RTCIV_NONE:
debug_uart_tx("RTC none IRQ\n");
break;
case RTCIV_RTCRDYIFG:
case RTCIV_RTCTEVIFG:
case RTCIV_RTCAIFG:
case RTCIV_RT0PSIFG:
debug_uart_tx("RTC misc IRQ\n");
break;
case RTCIV_RT1PSIFG:
RTCPS1CTL &= ~RT1PSIFG;
_event_src |= RTC_1HZ_EVENT;
// LPM3_EXIT;
LPM3_EXIT_ISR();
#if defined MW_DEVBOARD_V2
LED7_TOGGLE();
#endif
break;
default:
break;
};
}
void setup_rtc(void)
{
// stop it
RTCCTL01 = RTCHOLD;
// calibration
RTCCTL2 = 0x00 & 0x3f;
RTCCTL2 |= RTCCALS;
// Set the counter for RTC mode
RTCCTL01 |= RTCMODE;
// set 128 Hz rate for prescale 0 interrupt
RTCPS0CTL |= RT0IP_7;
// enable 1 pulse per second interrupt using prescale 1
RTCPS1CTL |= RT1IP_6 | RT1PSIE;
// 1 Hz calibration output
RTCCTL23 |= RTCCALF_3;
// setting the peripheral selection bit makes the other I/O control a don't care
// P2.4 = 1 Hz RTC calibration output
// Direction needs to be set as output
RTC_1HZ_PORT_SEL |= RTC_1HZ_BIT;
RTC_1HZ_PORT_DIR |= RTC_1HZ_BIT;
RTCYEAR = (unsigned int) 2013;
RTCMON = (unsigned int) 1;
RTCDAY = (unsigned int) 1;
RTCDOW = (unsigned int) 2;
RTCHOUR = (unsigned int) 01;
RTCMIN = (unsigned int) 0;
RTCSEC = (unsigned int) 0;
// Enable the RTC
RTCCTL01 &= ~RTCHOLD;
nop();
}
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
static void dbg_out_rtc(void)
{
char clk_str[16];
snprintf(clk_str, 16, "%02d:%02d.%02d %d\n", RTCHOUR, RTCMIN, RTCSEC, RTCDOW);
debug_uart_tx(clk_str);
}
#endif
static void handle_button_event(void)
{
unsigned char _button_state = 0;
#if 0
char clk_str[16];
snprintf(clk_str, 16, "0x%02x\n", _button_state);
debug_uart_tx(clk_str);
#endif
while (_button_state != (BUTTON_PORT_IN & ALL_BUTTONS)) {
__delay_cycles(562500);
_button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
__delay_cycles(562500);
}
// BUTTON_PORT_IE |= INT_EDGE_SEL_BUTTONS;
if (_button_state & SW_A) {
debug_uart_tx("switch A\n");
oswald_handle_button_press(BUTTON_A);
}
if (_button_state & SW_B) {
debug_uart_tx("switch B\n");
oswald_handle_button_press(BUTTON_B);
}
if (_button_state & SW_C) {
debug_uart_tx("switch C\n");
oswald_handle_button_press(BUTTON_C);
}
if (_button_state & SW_D) {
debug_uart_tx("switch D\n");
oswald_handle_button_press(BUTTON_D);
}
if (_button_state & SW_E) {
debug_uart_tx("switch E\n");
oswald_handle_button_press(BUTTON_E);
}
if (_button_state & SW_F) {
debug_uart_tx("switch F\n");
oswald_handle_button_press(BUTTON_F);
}
}
void check_pwr_state(void)
{
if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT) {
BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
BAT_CHARGE_REN &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2); // disable pull-up
} else {
BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
BAT_CHARGE_REN |= BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2; // enable pull-up
}
}
static void handle_bt_uart_rx_event(void)
{
const unsigned char *rx;
unsigned char len, *rp, p;
rx = mw_bt_get_rx_buf(&rp, &len);
p = 0;
while (p < len) {
p += bt_feed_packet_data(rx[(*rp+p)%BT_RX_MAX_SIZE]);
}
// all consumed
*rp = (*rp + len) % BT_RX_MAX_SIZE;
}
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
static void handle_uart_rx_event(void)
{
char c;
#ifndef CC256x_TRANSP
char tstr[255];
if (debug_uart_rx_char(&c)) {
debug_uart_tx_char(c);
if (c == 'a') {
debug_uart_tx("\nenabling ACC\n");
mw_acc_enable();
} else if (c == 'A') {
debug_uart_tx("\ndisabling ACC\n");
mw_acc_disable();
} else if (c == 'r') {
int16_t x,y,z;
debug_uart_tx("\nread ACC: ");
mw_acc_read(&x, &y, &z);
snprintf(tstr, 64, "x:%d y:%d z:%d\n", x,y,z);
debug_uart_tx(tstr);
} else if (c =='R') {
int16_t al;
al = mw_get_amblight_adc_val();
snprintf(tstr, 64, "light: %d\n", al);
debug_uart_tx(tstr);
} else if (c == 'b') {
debug_uart_tx("\nenabling BT\n");
mw_enable_bt();
} else if (c == 'B') {
debug_uart_tx("\ndisabling BT\n");
mw_disable_bt();
} else if (c == 'c') {
debug_uart_tx("\nCharger status: ");
snprintf(tstr, 16, "0x%04x 0x%04x ", BAT_CHARGE_IN, (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT));
debug_uart_tx(tstr);
if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT)
debug_uart_tx("no ext pwr, ");
else
debug_uart_tx("ext pwr connected, ");
switch (BAT_CHARGE_IN & (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2)) {
case BAT_CHARGE_STAT1:
debug_uart_tx("charge done\n");
break;
case BAT_CHARGE_STAT2:
debug_uart_tx("fast charge\n");
break;
case (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2):
debug_uart_tx("suspend, sleep or fault\n");
break;
default:
debug_uart_tx("precharge\n");
break;
}
if (BAT_CHARGE_IN & BAT_CHARGE_ENABLE_PIN)
debug_uart_tx(" !charge\n");
else
debug_uart_tx(" charge\n");
} else if (c == 'd') {
debug_uart_tx("charging disabled\n");
BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
} else if (c == 'e') {
debug_uart_tx("charging enabled\n");
BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
} else if (c == 'l') {
debug_uart_tx("backlight LED on\n");
hal_lcd_set_backlight(TRUE);
} else if (c == 'L') {
debug_uart_tx("backlight LED off\n");
hal_lcd_set_backlight(FALSE);
} else if (c == 'u') {
mw_lcd_update_screen();
} else if (c == '+') {
nop();
} else if (c == '-') {
nop();
} else if (c == 'H') {
uint8_t dclass[3];
dclass[0] = BT_MW_DEVICE_CLASS & 0xff;
dclass[1] = (BT_MW_DEVICE_CLASS & 0xff00) >> 8;
dclass[2] = (BT_MW_DEVICE_CLASS & 0xff0000) >> 16;
debug_uart_tx("HCI reset\n");
bt_hci_cmd(HCI_HC_BB_OGF, HCI_RESET_OCF, 0, NULL);
bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_COD_OCF, 3, dclass);
} else if (c == 'i') {
debug_uart_tx("Information:\n");
debug_uart_tx("Oswald ");
debug_uart_tx(MW_MAIN_VERSION);
debug_uart_tx("\n");
debug_uart_tx("Build #");
debug_uart_tx(BUILDNO);
debug_uart_tx("\n");
debug_uart_tx("BT V ");
debug_uart_tx(cc256x_version);
debug_uart_tx("\n");
debug_uart_tx("MCU Rev ");
debug_uart_tx_char(GetMsp430HardwareRevision());
debug_uart_tx("\n");
} else if (c == 'S') {
debug_uart_tx("Scan enable\n");
tstr[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, (uint8_t *)tstr);
} else if (c == 'h') {
RTCHOUR++;
if (RTCHOUR > 23)
RTCHOUR = 0;
} else if (c == 'm') {
RTCMIN++;
if (RTCMIN > 59)
RTCMIN = 0;
} else if (c == 'N') {
debug_uart_tx("Set name\n");
tstr[0] = 'O';
tstr[1] = 's';
tstr[2] = 'w';
tstr[3] = 'a';
tstr[4] = 'l';
tstr[5] = 'd';
tstr[6] = 0x00;
bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_LOCAL_NAME_OCF, 0x07, (uint8_t *)tstr);
} else if (c == 'R') {
bt_hci_cmd(HCI_INFO_PARAM_OGF, HCI_R_BD_ADDR_OCF, 0, NULL);
}
}
#endif
}
#endif
void start_timer(int cycles)
{
TA0EX0 = TAIDEX_0;
TA0CTL = TASSEL_1 | TACLR | MC__STOP; // SMCLK, clear TAR
TA0CCTL0 = CCIE; // CCR0 interrupt enabled
TA0CCR0 = cycles;
TA0CTL |= MC_1; // Start Timer_A in continuous mode
}
void stop_timer(void)
{
TA0CCTL0 &= ~CCIE; // CCR0 interrupt enabled
TA0CTL = MC__STOP; // Start Timer_A in continuous mode
}
// Timer A0 interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void TIMER0_A0_ISR (void)
{
TA0CTL &= ~(TAIFG);
#if defined xMW_DEVBOARD_V2
LED6_TOGGLE();
#endif
_event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT;
// LPM3_EXIT;
LPM3_EXIT_ISR();
}
uint8_t handle_event(void)
{
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
char tstr[64];
#endif
if (_event_src == 0)
return 1;
while (_event_src != 0) {
if (_event_src & WATCHDOG_EVENT) {
_event_src &= ~WATCHDOG_EVENT;
debug_uart_tx_char('w');
} else if (_event_src & RTC_1HZ_EVENT) {
_event_src &= ~RTC_1HZ_EVENT;
check_pwr_state();
oswald_one_second_tick();
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
dbg_out_rtc();
#endif
} else if (_event_src & BT_UART_RCV_EVENT) {
_event_src &= ~BT_UART_RCV_EVENT;
handle_bt_uart_rx_event();
} else if (_event_src & BT_UART_WAKEUP_EVENT) {
_event_src &= ~BT_UART_WAKEUP_EVENT;
bt_hci_ehcill_wake();
} else if (_event_src & DBG_UART_RCV_EVENT) {
_event_src &= ~DBG_UART_RCV_EVENT;
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
handle_uart_rx_event();
#endif
} else if (_event_src & BUTTON_EVENT) {
_event_src &= ~BUTTON_EVENT;
handle_button_event();
} else if (_event_src & TIMER_500MS_EVENT) {
_event_src &= ~TIMER_500MS_EVENT;
oswald_halfsecond_tick();
} else if (_event_src & TIMER_100MS_EVENT) {
_event_src &= ~TIMER_100MS_EVENT;
oswald_centisecond_tick();
} else if (_event_src & ACCEL_EVENT) {
_event_src &= ~ACCEL_EVENT;
mw_acc_handle_irq();
} else {
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
debug_uart_tx(tstr);
#endif
}
}
return 0;
}
#pragma vector=BUTTON_PORT_VECTOR
__interrupt void BUTTON_ISR (void)
{
// LPM3_EXIT;
LPM3_EXIT_ISR();
BUTTON_PORT_IFG &= ~ALL_BUTTONS;
// BUTTON_PORT_IE &= ~INT_EDGE_SEL_BUTTONS;
_event_src |= BUTTON_EVENT;
//_button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
}
#pragma vector=PORT1_VECTOR
__interrupt void PORT1_GPIO_ISR (void)
{
if (P1IFG & BT_IO_CTS) {
//LPM3_EXIT;
LPM3_EXIT_ISR();
P1IE &= ~BT_IO_CTS;
P1IFG &= ~BT_IO_CTS;
debug_uart_tx("BT CTS irq\n");
_event_src |= BT_UART_WAKEUP_EVENT;
// bt_hci_ehcill_wake();
} else if (P1IFG & ACCELEROMETER_INT_PIN) {
//LPM3_EXIT;
LPM3_EXIT_ISR();
P1IFG &= ~ACCELEROMETER_INT_PIN;
// debug_uart_tx("ACC irq\n");
_event_src |= ACCEL_EVENT;
}
}
#if 0
#pragma vector=NOVECTOR
__interrupt void UNEXP_ISR (void)
{
debug_uart_tx("unexpected IRQ occured\n");
}
#endif
int main(void)
{
setup_wdt();
setup_pins();
setup_clocks();
setup_rtc();
/* enable interrupts, we will need them! */
__enable_interrupt();
#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
init_debug_uart();
debug_uart_tx("\nOswald on MetaWatch\n");
#endif
mw_lcd_init();
mw_lcd_clear();
mw_lcd_update_screen();
mw_init_adc();
mw_init_vibrate_pwm();
oswald_set_time(RTCHOUR, RTCMIN, RTCSEC, TRUE);
oswald_set_date(RTCDAY, RTCMON, RTCYEAR, TRUE);
oswald_init();
while (1) {
/* handle pending events */
handle_event();
/* enter LPM3 sleep mode waiting for interrupt */
/* errata PMM11 + PMM12 - divide MCLK before going to sleep */
if (DetermineErrata()) {
MCLK_DIV(2);
nop();
}
LPM3;
nop();
if (DetermineErrata()) {
__delay_cycles(100);
MCLK_DIV(1);
}
};
return 0;
}