]> git.karo-electronics.de Git - oswald.git/blob - metawatch/mw_main.c
Power saving changes, add new fonts, bitmaps and screens
[oswald.git] / metawatch / mw_main.c
1 #include <msp430.h>
2 #include <msp430xgeneric.h>
3 #include <stdio.h>
4 #include <string.h>
5
6 #include "F5xx_F6xx_Core_Lib/HAL_PMM.h"
7 #include "F5xx_F6xx_Core_Lib/HAL_UCS.h"
8
9 #include "mw_main.h"
10
11 #include "mw_uart.h"
12 #include "mw_lcd.h"
13 #include "mw_bt.h"
14 #include "mw_adc.h"
15 #include "mw_bt.h"
16 #include "mw_acc.h"
17 #include "bt_hci.h"
18 #include "bt_l2cap.h"
19
20 #include "oswald_main.h"
21 #include "oswald_hal.h"
22
23
24 uint16_t _event_src = 0;
25
26 #define HARDWARE_REVISION_ADDRESS (0x1a07)
27
28 unsigned char GetMsp430HardwareRevision(void)
29 {
30         unsigned char *pDeviceType = (unsigned char *)(unsigned char *)HARDWARE_REVISION_ADDRESS;
31   
32         return pDeviceType[0]+'1';                         
33 }
34
35 uint8_t DetermineErrata(void)
36 {
37         unsigned char Revision = GetMsp430HardwareRevision();
38   
39         switch (Revision) {
40                 case 'F':
41                 case 'H':
42                         return 0;
43                         break;
44                 default:
45                         return 1;
46                         break;
47         }
48 }
49
50 static void set16mhz(void)
51 {
52         UCSCTL0 = 0x00;                 // Set lowest possible DCOx, MODx
53         UCSCTL1 = DCORSEL_5;            // Select suitable range
54         UCSCTL2 = 488 + FLLD_1;         // Set DCO Multiplier
55         UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV  |  SELM__DCOCLKDIV ;
56
57         // Worst-case settling time for the DCO when the DCO range bits have been 
58         // changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG 
59         // for optimization.
60         // 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
61         // t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
62   
63         // __delay_cycles(562500);  
64         int i;
65         for (i=0;i<10;i++){
66                 __delay_cycles(56250);  
67         }
68 }
69
70 static void setup_clocks(void)
71 {
72         unsigned long i;
73
74         SetVCore(PMMCOREV_2);
75
76         /* use external oscillator */
77         P7SEL |= BIT0 + BIT1;
78         if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
79                 UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L;
80         }
81         i = 50000;
82         while ((SFRIFG1 & OFIFG) && i--) {
83                 UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
84                 SFRIFG1 &= ~OFIFG;
85         }
86         UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(XT1DRIVE_0);
87
88         set16mhz();
89
90         UCSCTL8 |= SMCLKREQEN;
91
92         // setup for quick wake up from interrupt and
93         // minimal power consumption in sleep mode
94         DISABLE_SVSL();                         // SVS Low side is turned off
95         DISABLE_SVSL_RESET();
96   
97         DISABLE_SVML();                         // Monitor low side is turned off
98         DISABLE_SVML_INTERRUPT();
99   
100         DISABLE_SVMH();                         // Monitor high side is turned off
101         DISABLE_SVMH_INTERRUPT();
102   
103         ENABLE_SVSH();                          // SVS High side is turned on
104         ENABLE_SVSH_RESET();                    // Enable POR on SVS Event
105
106         SVSH_ENABLED_IN_LPM_FULL_PERF();        // SVS high side Full perf mode,
107                                                 // stays on in LPM3,enhanced protect
108
109         // Wait until high side, low side settled
110         while ((PMMIFG & SVSMLDLYIFG) == 0 && (PMMIFG & SVSMHDLYIFG) == 0)
111                 nop();
112         CLEAR_PMM_IFGS();
113
114         // Errata PMM17
115         if (DetermineErrata()) {
116                 *(unsigned int*)(0x0110) = 0x9602;
117                 *(unsigned int*)(0x0112) |= 0x0800;
118         }
119
120         /* enable oscillator fault NMI IRQ */
121 //      SFRIE1 = OFIE;
122 }
123
124 #if 0
125 #pragma vector=PWR_PORT_VECTOR
126 __interrupt void PWR_ISR (void)
127 {
128         /* clear all possible sources */
129         PWR_PORT_IFG &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
130         _event_src |= POWER_SRC_EVENT;
131         LPM3_EXIT();
132         nop();
133 }
134 #endif
135
136 static void mw_init_vibrate_pwm(void)
137 {
138 #ifdef MW_DIGITAL_V2
139         // Start with P7.3 as an output
140         P7OUT &= ~BIT3;   // Low when a digital output
141         P7SEL &= ~BIT3;   // P7 option select = false
142         P7DIR |=  BIT3;   // P7 outputs
143
144         TA1CTL = 0;
145
146         // No expansion divide
147         TA1EX0 = 0;
148
149         // do a PWM with 64 total steps.  This gives a count up of 32 and
150         // a count down of 32
151         TA1CCR0 =  31;
152
153         // Compare channel 2 is used as output
154         TA1CCTL2 = OUTMOD_6;         // PWM output mode: 6 - toggle/set
155         TA1CCR2 = 10;                // 10 is a 2/3 duty cycle
156 #endif
157 }
158
159
160 static void setup_pins(void)
161 {
162         CONFIG_SRAM_PINS();
163         CONFIGURE_BUTTON_PINS();
164 #ifdef MW_DEVBOARD_V2
165         CONFIG_LED_PINS();              // debug LEDs on devboard
166 #endif
167         DISABLE_LCD_LED();              // frontlight
168         CONFIG_DEBUG_PINS();
169         CONFIG_ACCELEROMETER_PINS();
170         //DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
171         ENABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
172
173         HARDWARE_CFG_SENSE_INIT();
174
175         APPLE_CONFIG();
176         APPLE_POWER_DISABLE();
177
178         CONFIG_BT_PINS();
179         BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
180         BT_IO1_CONFIG_AS_OUTPUT_LOW();
181         BT_IO2_CONFIG_AS_OUTPUT_LOW();
182         mw_disable_bt();
183
184         LIGHT_SENSE_INIT();
185         LIGHT_SENSOR_SHUTDOWN();
186
187         BATTERY_SENSE_INIT();
188         BATTERY_SENSE_DISABLE();
189         BAT_CHARGE_DIR &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
190         BAT_CHARGE_OUT |= BAT_CHARGE_PWR_BIT | BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2;                                             // pull-up
191         BAT_CHARGE_REN |= BAT_CHARGE_PWR_BIT;   // enable resistors
192         // BAT_CHARGE_IE |= BAT_CHARGE_PWR_BIT;
193         BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;        // !CE, negative logic
194         BAT_CHARGE_DIR |= BAT_CHARGE_ENABLE_PIN;
195
196         /* disable reset function, enable NMI, do not enable NMI IRQ */
197         /* to avoid accidential reset on charger clip connect */
198 #ifndef MW_DEVBOARD_V2 // but only on real watch
199         SFRRPCR &= ~SYSRSTRE;
200         SFRRPCR |= SYSNMI;
201 #endif
202 }
203
204 #pragma vector=WDT_VECTOR
205 __interrupt void WDT_ISR (void)
206 {
207         /* eventually we will do something here, not for now */
208         _event_src |= WATCHDOG_EVENT;
209         nop();
210 }
211
212 static void setup_wdt(void)
213 {
214 #if 1
215         WDTCTL = WDTPW + WDTHOLD;       // disable watchdog
216 #else
217         WDTCTL = WDT_ADLY_1000;         // 1 second timeout
218         SFRIE1 |= WDTIE;                // Enable WDT interrupt
219 #endif
220 }
221
222 #if 1
223 #pragma vector=UNMI_VECTOR
224 __interrupt void NMI_ISR (void)
225 {
226 #if defined MW_DEVBOARD_V2
227         LED7_TOGGLE();
228         debug_uart_tx_char('n');
229 #endif
230         while ((SFRIFG1 & OFIFG)) {
231                 UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
232                 SFRIFG1 &= ~OFIFG;
233         }
234 }
235 #endif
236
237 #pragma vector=RTC_VECTOR
238 __interrupt void RTC_ISR (void)
239 {
240         switch (RTCIV) {
241                 case RTCIV_NONE:
242                         debug_uart_tx("RTC none IRQ\n");
243                         break;
244                 case RTCIV_RTCRDYIFG:
245                 case RTCIV_RTCTEVIFG:
246                 case RTCIV_RTCAIFG:
247                 case RTCIV_RT0PSIFG:
248                         debug_uart_tx("RTC misc IRQ\n");
249                         break;
250                 case RTCIV_RT1PSIFG:
251                         RTCPS1CTL &= ~RT1PSIFG;
252                         _event_src |= RTC_1HZ_EVENT;
253                         LPM3_EXIT;
254                         nop();
255 #if defined MW_DEVBOARD_V2
256                         LED7_TOGGLE();
257 #endif
258                         break;
259                 default:
260                         break;
261         };
262 }
263
264 void setup_rtc(void)
265 {
266         // stop it
267         RTCCTL01 = RTCHOLD;
268
269         // calibration
270         RTCCTL2 = 0x00 & 0x3f;
271         RTCCTL2 |= RTCCALS;
272
273         // Set the counter for RTC mode
274         RTCCTL01 |= RTCMODE;
275
276         // set 128 Hz rate for prescale 0 interrupt
277         RTCPS0CTL |= RT0IP_7;
278
279         // enable 1 pulse per second interrupt using prescale 1
280         RTCPS1CTL |= RT1IP_6 | RT1PSIE;
281
282         // 1 Hz calibration output
283         RTCCTL23 |= RTCCALF_3;
284
285         // setting the peripheral selection bit makes the other I/O control a don't care
286         // P2.4 = 1 Hz RTC calibration output
287         // Direction needs to be set as output
288         RTC_1HZ_PORT_SEL |= RTC_1HZ_BIT;  
289         RTC_1HZ_PORT_DIR |= RTC_1HZ_BIT;  
290
291         RTCYEAR = (unsigned int) 2013;
292         RTCMON = (unsigned int) 1;
293         RTCDAY = (unsigned int) 1;
294         RTCDOW = (unsigned int) 2;
295         RTCHOUR = (unsigned int) 01;
296         RTCMIN = (unsigned int) 0;
297         RTCSEC = (unsigned int) 0;
298
299         // Enable the RTC
300         RTCCTL01 &= ~RTCHOLD;
301         nop();
302 }
303
304 #if defined MW_DEVBOARD_V2
305 static void dbg_out_rtc(void)
306 {
307         char clk_str[16];
308         snprintf(clk_str, 16, "%02d:%02d.%02d %d\n", RTCHOUR, RTCMIN, RTCSEC, RTCDOW);
309         debug_uart_tx(clk_str);
310 }
311 #endif
312
313 static void handle_button_event(void)
314 {
315         unsigned char _button_state = 0;
316 #if 0
317         char clk_str[16];
318         snprintf(clk_str, 16, "0x%02x\n", _button_state);
319         debug_uart_tx(clk_str);
320 #endif
321         while (_button_state != (BUTTON_PORT_IN & ALL_BUTTONS)) {
322                 __delay_cycles(562500);
323                 _button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
324                 __delay_cycles(562500);
325         }
326         // BUTTON_PORT_IE |= INT_EDGE_SEL_BUTTONS;
327
328         if (_button_state & SW_A) {
329                 debug_uart_tx("switch A\n");
330                 oswald_handle_button_press(BUTTON_A);
331         }
332         if (_button_state & SW_B) {
333                 debug_uart_tx("switch B\n");
334                 oswald_handle_button_press(BUTTON_B);
335         }
336         if (_button_state & SW_C) {
337                 debug_uart_tx("switch C\n");
338                 oswald_handle_button_press(BUTTON_C);
339         }
340         if (_button_state & SW_D) {
341                 debug_uart_tx("switch D\n");
342                 oswald_handle_button_press(BUTTON_D);
343         }
344         if (_button_state & SW_E) {
345                 debug_uart_tx("switch E\n");
346                 oswald_handle_button_press(BUTTON_E);
347         }
348         if (_button_state & SW_F) {
349                 debug_uart_tx("switch F\n");
350                 oswald_handle_button_press(BUTTON_F);
351         }
352 }
353
354 void check_pwr_state(void)
355 {
356         if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT) {
357                 BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
358                 BAT_CHARGE_REN &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2); // disable pull-up
359         } else {
360                 BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
361                 BAT_CHARGE_REN |= BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2; // enable pull-up
362         }
363 }
364
365 static void handle_bt_uart_rx_event(void)
366 {
367         const unsigned char *rx;
368         unsigned char len, *rp, p;
369
370         rx = mw_bt_get_rx_buf(&rp, &len);
371
372         p = 0;
373         while (p < len) {
374                 p += bt_feed_packet_data(rx[(*rp+p)%BT_RX_MAX_SIZE]);
375         }
376         // all consumed
377         *rp = (*rp + len) % BT_RX_MAX_SIZE;
378 }
379
380 #if defined MW_DEVBOARD_V2
381 static void handle_uart_rx_event(void)
382 {
383         char c;
384 #ifndef CC256x_TRANSP
385         char tstr[255];
386
387         if (debug_uart_rx_char(&c)) {
388                 debug_uart_tx_char(c);
389                 if (c == 'a') {
390                         debug_uart_tx("\nenabling ACC\n");
391                         mw_acc_enable();
392                 } else if (c == 'A') {
393                         debug_uart_tx("\ndisabling ACC\n");
394                         mw_acc_disable();
395                 } else if (c == 'r') {
396                         int16_t x,y,z;
397                         debug_uart_tx("\nread ACC: ");
398                         mw_acc_read(&x, &y, &z);
399                         snprintf(tstr, 64, "x:%d y:%d z:%d\n", x,y,z);
400                         debug_uart_tx(tstr);
401                 } else if (c =='R') {
402                         int16_t al;
403                         al = mw_get_amblight_adc_val();
404                         snprintf(tstr, 64, "light: %d\n", al);
405                         debug_uart_tx(tstr);
406                 } else if (c == 'b') {
407                         debug_uart_tx("\nenabling BT\n");
408                         mw_enable_bt();
409                 } else if (c == 'B') {
410                         debug_uart_tx("\ndisabling BT\n");
411                         mw_disable_bt();
412                 } else if (c == 'c') {
413                         debug_uart_tx("\nCharger status: ");
414                         snprintf(tstr, 16, "0x%04x 0x%04x ", BAT_CHARGE_IN, (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT));
415                         debug_uart_tx(tstr);
416                         if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT)
417                                 debug_uart_tx("no ext pwr, ");
418                         else
419                                 debug_uart_tx("ext pwr connected, ");
420                         switch (BAT_CHARGE_IN & (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2)) {
421                                 case BAT_CHARGE_STAT1:
422                                         debug_uart_tx("charge done\n");
423                                         break;
424                                 case BAT_CHARGE_STAT2:
425                                         debug_uart_tx("fast charge\n");
426                                         break;
427                                 case (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2):
428                                         debug_uart_tx("suspend, sleep or fault\n");
429                                         break;
430                                 default:
431                                         debug_uart_tx("precharge\n");
432                                         break;
433                         }
434                         if (BAT_CHARGE_IN & BAT_CHARGE_ENABLE_PIN)
435                                 debug_uart_tx(" !charge\n");
436                         else
437                                 debug_uart_tx(" charge\n");
438                 } else if (c == 'd') {
439                         debug_uart_tx("charging disabled\n");
440                         BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
441                 } else if (c == 'e') {
442                         debug_uart_tx("charging enabled\n");
443                         BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
444                 } else if (c == 'l') {
445                         debug_uart_tx("backlight LED on\n");
446                         hal_lcd_set_backlight(TRUE);
447                 } else if (c == 'L') {
448                         debug_uart_tx("backlight LED off\n");
449                         hal_lcd_set_backlight(FALSE);
450                 } else if (c == 'u') {
451                         mw_lcd_update_screen();
452                 } else if (c == '+') {
453                         nop();
454                 } else if (c == '-') {
455                         nop();
456                 } else if (c == 'H') {
457                         uint8_t dclass[3];
458                         dclass[0] = BT_MW_DEVICE_CLASS & 0xff;
459                         dclass[1] = (BT_MW_DEVICE_CLASS & 0xff00) >> 8;
460                         dclass[2] = (BT_MW_DEVICE_CLASS & 0xff0000) >> 16;
461
462                         debug_uart_tx("HCI reset\n");
463                         bt_hci_cmd(HCI_HC_BB_OGF, HCI_RESET_OCF, 0, NULL);
464                         bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_COD_OCF, 3, dclass);
465                 } else if (c == 'S') {
466                         debug_uart_tx("Scan enable\n");
467                         tstr[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
468                         bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, (uint8_t *)tstr);
469                 } else if (c == 'h') {
470                         RTCHOUR++;
471                         if (RTCHOUR > 23)
472                                 RTCHOUR = 0;
473                 } else if (c == 'm') {
474                         RTCMIN++;
475                         if (RTCMIN > 59)
476                                 RTCMIN = 0;
477                 } else if (c == 'N') {
478                         debug_uart_tx("Set name\n");
479                         tstr[0] = 'O';
480                         tstr[1] = 's';
481                         tstr[2] = 'w';
482                         tstr[3] = 'a';
483                         tstr[4] = 'l';
484                         tstr[5] = 'd';
485                         tstr[6] = 0x00;
486                         bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_LOCAL_NAME_OCF, 0x07, (uint8_t *)tstr);
487                 } else if (c == 'R') {
488                         bt_hci_cmd(HCI_INFO_PARAM_OGF, HCI_R_BD_ADDR_OCF, 0, NULL);
489                 }
490         }
491 #endif
492 }
493 #endif
494
495 void start_timer(int cycles)
496 {
497         TA0EX0 = TAIDEX_0;
498         TA0CTL = TASSEL_1 | TACLR | MC__STOP;   // SMCLK, clear TAR
499         TA0CCTL0 = CCIE;                        // CCR0 interrupt enabled
500         TA0CCR0 = cycles;
501         TA0CTL |= MC_1;                         // Start Timer_A in continuous mode
502 }
503
504 void stop_timer(void)
505 {
506         TA0CCTL0 &= ~CCIE;                      // CCR0 interrupt enabled
507         TA0CTL = MC__STOP;                      // Start Timer_A in continuous mode
508 }
509  
510 // Timer A0 interrupt service routine
511 #pragma vector=TIMER0_A0_VECTOR
512 __interrupt void TIMER0_A0_ISR (void)
513 {
514         TA0CTL &= ~(TAIFG);
515 #if defined xMW_DEVBOARD_V2
516         LED6_TOGGLE();
517 #endif
518         _event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT;
519         LPM3_EXIT;
520 }
521
522 uint8_t handle_event(void)
523 {
524 #if defined MW_DEVBOARD_V2
525         char tstr[64];
526 #endif
527         if (_event_src == 0)
528                 return 1;
529
530         while (_event_src != 0) {
531                 if (_event_src & WATCHDOG_EVENT) {
532                         _event_src &= ~WATCHDOG_EVENT;
533                         debug_uart_tx_char('w');
534                 } else if (_event_src & RTC_1HZ_EVENT) {
535                         _event_src &= ~RTC_1HZ_EVENT;
536                         check_pwr_state();
537                         oswald_one_second_tick();
538 #if defined MW_DEVBOARD_V2
539                         dbg_out_rtc();
540 #endif
541                 } else if (_event_src & BT_UART_RCV_EVENT) {
542                         _event_src &= ~BT_UART_RCV_EVENT;
543                         handle_bt_uart_rx_event();
544                 } else if (_event_src & BT_UART_WAKEUP_EVENT) {
545                         _event_src &= ~BT_UART_WAKEUP_EVENT;
546                         bt_hci_ehcill_wake();
547                 } else if (_event_src & DBG_UART_RCV_EVENT) {
548                         _event_src &= ~DBG_UART_RCV_EVENT;
549 #if defined MW_DEVBOARD_V2
550                         handle_uart_rx_event();
551 #endif
552                 } else if (_event_src & BUTTON_EVENT) {
553                         _event_src &= ~BUTTON_EVENT;
554                         handle_button_event();
555                 } else if (_event_src & TIMER_500MS_EVENT) {
556                         _event_src &= ~TIMER_500MS_EVENT;
557                         oswald_halfsecond_tick();
558                 } else if (_event_src & TIMER_100MS_EVENT) {
559                         _event_src &= ~TIMER_100MS_EVENT;
560                         oswald_centisecond_tick();
561                 } else if (_event_src & ACCEL_EVENT) {
562                         _event_src &= ~ACCEL_EVENT;
563                         mw_acc_handle_irq();
564                 } else {
565 #if defined MW_DEVBOARD_V2
566                         snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
567                         debug_uart_tx(tstr);
568 #endif
569                 }
570         }
571         return 0;
572 }
573
574 #pragma vector=BUTTON_PORT_VECTOR
575 __interrupt void BUTTON_ISR (void)
576 {
577         LPM3_EXIT;
578         BUTTON_PORT_IFG &= ~ALL_BUTTONS;
579         // BUTTON_PORT_IE  &= ~INT_EDGE_SEL_BUTTONS;
580         _event_src |= BUTTON_EVENT;
581         //_button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
582 }
583
584 #pragma vector=PORT1_VECTOR
585 __interrupt void PORT1_GPIO_ISR (void)
586 {
587         if (P1IFG & BT_IO_CTS) {
588                 LPM3_EXIT;
589                 P1IE &= ~BT_IO_CTS;
590                 P1IFG &= ~BT_IO_CTS;
591                 debug_uart_tx("BT CTS irq\n");
592                 _event_src |= BT_UART_WAKEUP_EVENT;
593                 // bt_hci_ehcill_wake();
594         } else if (P1IFG & ACCELEROMETER_INT_PIN) {
595                 LPM3_EXIT;
596                 P1IFG &= ~ACCELEROMETER_INT_PIN;
597                 // debug_uart_tx("ACC irq\n");
598                 _event_src |= ACCEL_EVENT;
599         }
600 }
601
602
603 #if 0
604 #pragma vector=NOVECTOR
605 __interrupt void UNEXP_ISR (void)
606 {
607         debug_uart_tx("unexpected IRQ occured\n");
608 }
609 #endif
610
611
612 int main(void)
613 {
614         setup_wdt();
615         setup_pins();
616         setup_clocks();
617         setup_rtc();
618
619         /* enable interrupts, we will need them! */
620         __enable_interrupt();
621
622 #if defined MW_DEVBOARD_V2
623         init_debug_uart();
624         debug_uart_tx("\nOswald on MetaWatch\n");
625 #endif
626
627         mw_lcd_init();
628         mw_lcd_clear();
629         mw_lcd_update_screen();
630
631         mw_init_adc();
632         mw_init_vibrate_pwm();
633
634         oswald_set_time(RTCHOUR, RTCMIN, RTCSEC, TRUE);
635         oswald_set_date(RTCDAY, RTCMON, RTCYEAR, TRUE);
636         oswald_init();
637
638         while (1) {
639                 /* handle pending events */
640                 handle_event();
641
642                 /* enter LPM3 sleep mode waiting for interrupt */
643                 /* errata PMM11 + PMM12 - divide MCLK before going to sleep */
644                 if (DetermineErrata()) {
645                         MCLK_DIV(2);
646                         nop();
647                 }
648                 LPM3;
649                 nop();
650                 if (DetermineErrata()) {
651                         __delay_cycles(100);
652                         MCLK_DIV(1);
653                 }
654         };
655
656 return 0;
657 }