Browse code

Use strutils instead of snprintf (to save some bytes), set default year to 2014, partial revamp of the stopwatch

Dario Rodriguez authored on 14/01/2014 22:59:59
Showing 1 changed files
... ...
@@ -6,6 +6,7 @@
6 6
 #include "F5xx_F6xx_Core_Lib/HAL_PMM.h"
7 7
 #include "F5xx_F6xx_Core_Lib/HAL_UCS.h"
8 8
 
9
+#include "strutils.h"
9 10
 #include "mw_main.h"
10 11
 
11 12
 #include "mw_uart.h"
... ...
@@ -351,7 +352,7 @@ void setup_rtc(void)
351 352
 	RTC_1HZ_PORT_SEL |= RTC_1HZ_BIT;  
352 353
 	RTC_1HZ_PORT_DIR |= RTC_1HZ_BIT;  
353 354
 
354
-	RTCYEAR = (unsigned int) 2013;
355
+	RTCYEAR = (unsigned int) 2014;
355 356
 	RTCMON = (unsigned int) 1;
356 357
 	RTCDAY = (unsigned int) 1;
357 358
 	RTCDOW = (unsigned int) 2;
... ...
@@ -368,7 +369,18 @@ void setup_rtc(void)
368 369
 static void dbg_out_rtc(void)
369 370
 {
370 371
 	char clk_str[16];
371
-	snprintf(clk_str, 16, "%02d:%02d.%02d %d\n", RTCHOUR, RTCMIN, RTCSEC, RTCDOW);
372
+	int off;
373
+	off=0;
374
+	off+=num2str(RTCHOUR,clk_str+off,2,2);
375
+	clk_str[off++]=':';
376
+	off+=num2str(RTCMIN,clk_str+off,2,2);
377
+	clk_str[off++]='.';
378
+	off+=num2str(RTCSEC,clk_str+off,2,2);
379
+	clk_str[off++]=' ';
380
+	off+=num2str(RTCDOW,clk_str+off,2,sizeof(clk_str)-off-2);
381
+	clk_str[off++]='\n';
382
+	clk_str[off++]='\0';
383
+
372 384
 	debug_uart_tx(clk_str);
373 385
 }
374 386
 #endif
... ...
@@ -378,8 +390,10 @@ static void handle_button_event(void)
378 390
 	unsigned char _button_state = 0;
379 391
 #if 0
380 392
 	char clk_str[16];
381
-	snprintf(clk_str, 16, "0x%02x\n", _button_state);
393
+	debug_uart_tx("0x");
394
+	hexnum2str(_button_state,clk_str,2);
382 395
 	debug_uart_tx(clk_str);
396
+	debug_uart_tx("\n");
383 397
 #endif
384 398
 	while (_button_state != (BUTTON_PORT_IN & ALL_BUTTONS)) {
385 399
 		__delay_cycles(562500);
... ...
@@ -459,13 +473,23 @@ static void handle_uart_rx_event(void)
459 473
 			int16_t x,y,z;
460 474
 			debug_uart_tx("\nread ACC: ");
461 475
 			mw_acc_read(&x, &y, &z);
462
-			snprintf(tstr, 64, "x:%d y:%d z:%d\n", x,y,z);
476
+			debug_uart_tx("x:");
477
+			num2str(x,tstr,1,5);
478
+			debug_uart_tx(tstr);
479
+			debug_uart_tx(" y:");
480
+			num2str(y,tstr,1,5);
463 481
 			debug_uart_tx(tstr);
482
+			debug_uart_tx(" z:");
483
+			num2str(z,tstr,1,5);
484
+			debug_uart_tx(tstr);
485
+			debug_uart_tx("\n");
464 486
 		} else if (c =='R') {
465 487
 			int16_t al;
466 488
 			al = mw_get_amblight_adc_val();
467
-			snprintf(tstr, 64, "light: %d\n", al);
489
+			debug_uart_tx("light: ");
490
+			num2str(al,tstr,1,5);
468 491
 			debug_uart_tx(tstr);
492
+			debug_uart_tx("\n");
469 493
 		} else if (c == 'b') {
470 494
 			debug_uart_tx("\nenabling BT\n");
471 495
 			mw_enable_bt();
... ...
@@ -473,9 +497,13 @@ static void handle_uart_rx_event(void)
473 497
 			debug_uart_tx("\ndisabling BT\n");
474 498
 			mw_disable_bt();
475 499
 		} else if (c == 'c') {
476
-			debug_uart_tx("\nCharger status: ");
477
-			snprintf(tstr, 16, "0x%04x 0x%04x ", BAT_CHARGE_IN, (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT));
500
+			debug_uart_tx("\nCharger status: 0x");
501
+			hexnum2str(BAT_CHARGE_IN,tstr,4);
502
+			debug_uart_tx(tstr);
503
+			debug_uart_tx(" 0x");
504
+			hexnum2str((BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT),tstr,4);
478 505
 			debug_uart_tx(tstr);
506
+			debug_uart_tx(" ");
479 507
 			if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT)
480 508
 				debug_uart_tx("no ext pwr, ");
481 509
 			else
... ...
@@ -641,8 +669,10 @@ uint8_t handle_event(void)
641 669
 			mw_acc_handle_irq();
642 670
 		} else {
643 671
 #if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
644
-			snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
672
+			debug_uart_tx("unhandled event in 0x");
673
+			hexnum2str(_event_src,tstr,4);
645 674
 			debug_uart_tx(tstr);
675
+			debug_uart_tx("\n");
646 676
 #endif
647 677
 		}
648 678
 	}
Browse code

Add modified LPM3_EXIT_ISR to work around FLL IRQ wake-up problem

Nils Faerber authored on 06/07/2013 21:19:55
Showing 1 changed files
... ...
@@ -20,24 +20,26 @@
20 20
 #include "oswald_main.h"
21 21
 #include "oswald_hal.h"
22 22
 
23
+#include "bluetooth_init_cc256x.h"
23 24
 
24 25
 uint16_t _event_src = 0;
25 26
 
26 27
 #define HARDWARE_REVISION_ADDRESS (0x1a07)
27 28
 
28
-unsigned char GetMsp430HardwareRevision(void)
29
+uint8_t GetMsp430HardwareRevision(void)
29 30
 {
30
-	unsigned char *pDeviceType = (unsigned char *)(unsigned char *)HARDWARE_REVISION_ADDRESS;
31
+	uint8_t *pDeviceType = (uint8_t *)(uint8_t *)HARDWARE_REVISION_ADDRESS;
31 32
   
32 33
 	return pDeviceType[0]+'1';                         
33 34
 }
34 35
 
35 36
 uint8_t DetermineErrata(void)
36 37
 {
37
-	unsigned char Revision = GetMsp430HardwareRevision();
38
+	uint8_t Revision = GetMsp430HardwareRevision();
38 39
   
39 40
 	switch (Revision) {
40 41
 		case 'F':
42
+		case 'G':
41 43
 		case 'H':
42 44
 			return 0;
43 45
 			break;
... ...
@@ -67,6 +69,31 @@ static void set16mhz(void)
67 69
 	}
68 70
 }
69 71
 
72
+static unsigned char PMM15Check(void)
73
+{
74
+  // First check if SVSL/SVML is configured for fast wake-up
75
+  if ((!(SVSMLCTL & SVSLE)) || ((SVSMLCTL & SVSLE) && (SVSMLCTL & SVSLFP)) ||
76
+      (!(SVSMLCTL & SVMLE)) || ((SVSMLCTL & SVMLE) && (SVSMLCTL & SVMLFP)))
77
+  { 
78
+    // Next Check SVSH/SVMH settings to see if settings are affected by PMM15
79
+    if ((SVSMHCTL & SVSHE) && (!(SVSMHCTL & SVSHFP)))
80
+    {
81
+      if ( (!(SVSMHCTL & SVSHMD)) ||
82
+           ((SVSMHCTL & SVSHMD) && (SVSMHCTL & SVSMHACE)) )
83
+        return 1; // SVSH affected configurations
84
+    }
85
+
86
+    if ((SVSMHCTL & SVMHE) && (!(SVSMHCTL & SVMHFP)) && (SVSMHCTL & SVSMHACE))
87
+      return 1; // SVMH affected configurations
88
+  }
89
+
90
+  return 0; // SVS/M settings not affected by PMM15
91
+}
92
+
93
+#define configCPU_CLOCK_HZ ((unsigned long) 16777216) /* 512*32768 */
94
+#define configTICK_RATE_HZ ((unsigned int)1024)
95
+#define ACLK_MULTIPLIER    ((unsigned int)512)
96
+
70 97
 static void setup_clocks(void)
71 98
 {
72 99
 	unsigned long i;
... ...
@@ -75,6 +102,8 @@ static void setup_clocks(void)
75 102
 
76 103
 	/* use external oscillator */
77 104
 	P7SEL |= BIT0 + BIT1;
105
+
106
+#if 1
78 107
 	if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
79 108
 		UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L;
80 109
 	}
... ...
@@ -88,7 +117,21 @@ static void setup_clocks(void)
88 117
 	set16mhz();
89 118
 
90 119
 	UCSCTL8 |= SMCLKREQEN;
120
+#else
121
+	// Startup LFXT1 32 kHz crystal
122
+	while (LFXT_Start_Timeout(XT1DRIVE_0, 50000) == UCS_STATUS_ERROR)
123
+		nop();
124
+
125
+	// select the sources for the FLL reference and ACLK
126
+	SELECT_ACLK(SELA__XT1CLK);
127
+	SELECT_FLLREF(SELREF__XT1CLK);
91 128
 
129
+	// 512 * 32768 = 16777216 / 1024
130
+	Init_FLL_Settle(configCPU_CLOCK_HZ/configTICK_RATE_HZ, ACLK_MULTIPLIER);
131
+  
132
+	// Disable FLL loop control
133
+//	__bis_SR_register(SCG0);
134
+#endif
92 135
 	// setup for quick wake up from interrupt and
93 136
 	// minimal power consumption in sleep mode
94 137
 	DISABLE_SVSL();				// SVS Low side is turned off
... ...
@@ -105,12 +148,15 @@ static void setup_clocks(void)
105 148
 
106 149
 	SVSH_ENABLED_IN_LPM_FULL_PERF();	// SVS high side Full perf mode,
107 150
 						// stays on in LPM3,enhanced protect
151
+	SVSL_ENABLED_IN_LPM_FAST_WAKE();
108 152
 
109 153
 	// Wait until high side, low side settled
110 154
 	while ((PMMIFG & SVSMLDLYIFG) == 0 && (PMMIFG & SVSMHDLYIFG) == 0)
111 155
 		nop();
112 156
 	CLEAR_PMM_IFGS();
113 157
 
158
+	while (PMM15Check());
159
+
114 160
 	// Errata PMM17
115 161
 	if (DetermineErrata()) {
116 162
 		*(unsigned int*)(0x0110) = 0x9602;
... ...
@@ -176,9 +222,12 @@ static void setup_pins(void)
176 222
 	APPLE_POWER_DISABLE();
177 223
 
178 224
 	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();
225
+//	BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
226
+//	BT_IO1_CONFIG_AS_OUTPUT_LOW();
227
+//	BT_IO2_CONFIG_AS_OUTPUT_LOW();
228
+	BT_CLK_REQ_CONFIG_AS_INPUT();
229
+	BT_IO1_CONFIG_AS_INPUT();
230
+	BT_IO2_CONFIG_AS_INPUT();
182 231
 	mw_disable_bt();
183 232
 
184 233
 	LIGHT_SENSE_INIT();
... ...
@@ -198,6 +247,20 @@ static void setup_pins(void)
198 247
 #ifndef MW_DEVBOARD_V2 // but only on real watch
199 248
 	SFRRPCR &= ~SYSRSTRE;
200 249
 	SFRRPCR |= SYSNMI;
250
+#endif
251
+	/* allow debug UART */
252
+/*
253
+	P10SEL &= ~(BIT6 | BIT7);
254
+	P10DIR |= BIT6 | BIT7;
255
+	P10OUT &= ~(BIT6 | BIT7);
256
+*/
257
+#ifndef MW_DEVBOARD_V2
258
+	ENABLE_MUX_OUTPUT_CONTROL();
259
+#ifdef MW_DEBUG_UART
260
+	MUX_OUTPUT_SELECTS_SERIAL();
261
+#else
262
+	MUX_OUTPUT_OFF();
263
+#endif
201 264
 #endif
202 265
 }
203 266
 
... ...
@@ -250,8 +313,8 @@ __interrupt void RTC_ISR (void)
250 313
 		case RTCIV_RT1PSIFG:
251 314
 			RTCPS1CTL &= ~RT1PSIFG;
252 315
 			_event_src |= RTC_1HZ_EVENT;
253
-			LPM3_EXIT;
254
-			nop();
316
+			// LPM3_EXIT;
317
+			LPM3_EXIT_ISR();
255 318
 #if defined MW_DEVBOARD_V2
256 319
 			LED7_TOGGLE();
257 320
 #endif
... ...
@@ -301,7 +364,7 @@ void setup_rtc(void)
301 364
 	nop();
302 365
 }
303 366
 
304
-#if defined MW_DEVBOARD_V2
367
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
305 368
 static void dbg_out_rtc(void)
306 369
 {
307 370
 	char clk_str[16];
... ...
@@ -377,7 +440,7 @@ static void handle_bt_uart_rx_event(void)
377 440
 	*rp = (*rp + len) % BT_RX_MAX_SIZE;
378 441
 }
379 442
 
380
-#if defined MW_DEVBOARD_V2
443
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
381 444
 static void handle_uart_rx_event(void)
382 445
 {
383 446
 	char c;
... ...
@@ -462,6 +525,20 @@ static void handle_uart_rx_event(void)
462 525
 			debug_uart_tx("HCI reset\n");
463 526
 			bt_hci_cmd(HCI_HC_BB_OGF, HCI_RESET_OCF, 0, NULL);
464 527
 			bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_COD_OCF, 3, dclass);
528
+		} else if (c == 'i') {
529
+			debug_uart_tx("Information:\n");
530
+			debug_uart_tx("Oswald ");
531
+			debug_uart_tx(MW_MAIN_VERSION);
532
+			debug_uart_tx("\n");
533
+			debug_uart_tx("Build #");
534
+			debug_uart_tx(BUILDNO);
535
+			debug_uart_tx("\n");
536
+			debug_uart_tx("BT V ");
537
+			debug_uart_tx(cc256x_version);
538
+			debug_uart_tx("\n");
539
+			debug_uart_tx("MCU Rev ");
540
+			debug_uart_tx_char(GetMsp430HardwareRevision());
541
+			debug_uart_tx("\n");
465 542
 		} else if (c == 'S') {
466 543
 			debug_uart_tx("Scan enable\n");
467 544
 			tstr[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
... ...
@@ -516,12 +593,13 @@ __interrupt void TIMER0_A0_ISR (void)
516 593
 	LED6_TOGGLE();
517 594
 #endif
518 595
 	_event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT;
519
-	LPM3_EXIT;
596
+	// LPM3_EXIT;
597
+	LPM3_EXIT_ISR();
520 598
 }
521 599
 
522 600
 uint8_t handle_event(void)
523 601
 {
524
-#if defined MW_DEVBOARD_V2
602
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
525 603
 	char tstr[64];
526 604
 #endif
527 605
 	if (_event_src == 0)
... ...
@@ -535,7 +613,7 @@ uint8_t handle_event(void)
535 613
 			_event_src &= ~RTC_1HZ_EVENT;
536 614
 			check_pwr_state();
537 615
 			oswald_one_second_tick();
538
-#if defined MW_DEVBOARD_V2
616
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
539 617
 			dbg_out_rtc();
540 618
 #endif
541 619
 		} else if (_event_src & BT_UART_RCV_EVENT) {
... ...
@@ -546,7 +624,7 @@ uint8_t handle_event(void)
546 624
 			bt_hci_ehcill_wake();
547 625
 		} else if (_event_src & DBG_UART_RCV_EVENT) {
548 626
 			_event_src &= ~DBG_UART_RCV_EVENT;
549
-#if defined MW_DEVBOARD_V2
627
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
550 628
 			handle_uart_rx_event();
551 629
 #endif
552 630
 		} else if (_event_src & BUTTON_EVENT) {
... ...
@@ -562,7 +640,7 @@ uint8_t handle_event(void)
562 640
 			_event_src &= ~ACCEL_EVENT;
563 641
 			mw_acc_handle_irq();
564 642
 		} else {
565
-#if defined MW_DEVBOARD_V2
643
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
566 644
 			snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
567 645
 			debug_uart_tx(tstr);
568 646
 #endif
... ...
@@ -574,7 +652,8 @@ uint8_t handle_event(void)
574 652
 #pragma vector=BUTTON_PORT_VECTOR
575 653
 __interrupt void BUTTON_ISR (void)
576 654
 {
577
-	LPM3_EXIT;
655
+	// LPM3_EXIT;
656
+	LPM3_EXIT_ISR();
578 657
 	BUTTON_PORT_IFG &= ~ALL_BUTTONS;
579 658
 	// BUTTON_PORT_IE  &= ~INT_EDGE_SEL_BUTTONS;
580 659
 	_event_src |= BUTTON_EVENT;
... ...
@@ -585,14 +664,16 @@ __interrupt void BUTTON_ISR (void)
585 664
 __interrupt void PORT1_GPIO_ISR (void)
586 665
 {
587 666
 	if (P1IFG & BT_IO_CTS) {
588
-		LPM3_EXIT;
667
+		//LPM3_EXIT;
668
+		LPM3_EXIT_ISR();
589 669
 		P1IE &= ~BT_IO_CTS;
590 670
 		P1IFG &= ~BT_IO_CTS;
591 671
 		debug_uart_tx("BT CTS irq\n");
592 672
 		_event_src |= BT_UART_WAKEUP_EVENT;
593 673
 		// bt_hci_ehcill_wake();
594 674
 	} else if (P1IFG & ACCELEROMETER_INT_PIN) {
595
-		LPM3_EXIT;
675
+		//LPM3_EXIT;
676
+		LPM3_EXIT_ISR();
596 677
 		P1IFG &= ~ACCELEROMETER_INT_PIN;
597 678
 		// debug_uart_tx("ACC irq\n");
598 679
 		_event_src |= ACCEL_EVENT;
... ...
@@ -619,7 +700,7 @@ int main(void)
619 700
 	/* enable interrupts, we will need them! */
620 701
 	__enable_interrupt();
621 702
 
622
-#if defined MW_DEVBOARD_V2
703
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
623 704
 	init_debug_uart();
624 705
 	debug_uart_tx("\nOswald on MetaWatch\n");
625 706
 #endif
Browse code

Power saving changes, add new fonts, bitmaps and screens

Nils Faerber authored on 19/05/2013 00:07:04
Showing 1 changed files
... ...
@@ -3,6 +3,9 @@
3 3
 #include <stdio.h>
4 4
 #include <string.h>
5 5
 
6
+#include "F5xx_F6xx_Core_Lib/HAL_PMM.h"
7
+#include "F5xx_F6xx_Core_Lib/HAL_UCS.h"
8
+
6 9
 #include "mw_main.h"
7 10
 
8 11
 #include "mw_uart.h"
... ...
@@ -17,10 +20,32 @@
17 20
 #include "oswald_main.h"
18 21
 #include "oswald_hal.h"
19 22
 
20
-#include "bluetooth_init_cc256x.h"
21 23
 
22 24
 uint16_t _event_src = 0;
23 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
+}
24 49
 
25 50
 static void set16mhz(void)
26 51
 {
... ...
@@ -46,6 +71,8 @@ static void setup_clocks(void)
46 71
 {
47 72
 	unsigned long i;
48 73
 
74
+	SetVCore(PMMCOREV_2);
75
+
49 76
 	/* use external oscillator */
50 77
 	P7SEL |= BIT0 + BIT1;
51 78
 	if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
... ...
@@ -62,6 +89,34 @@ static void setup_clocks(void)
62 89
 
63 90
 	UCSCTL8 |= SMCLKREQEN;
64 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
+
65 120
 	/* enable oscillator fault NMI IRQ */
66 121
 //	SFRIE1 = OFIE;
67 122
 }
... ...
@@ -112,7 +167,8 @@ static void setup_pins(void)
112 167
 	DISABLE_LCD_LED();		// frontlight
113 168
 	CONFIG_DEBUG_PINS();
114 169
 	CONFIG_ACCELEROMETER_PINS();
115
-	DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
170
+	//DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
171
+	ENABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
116 172
 
117 173
 	HARDWARE_CFG_SENSE_INIT();
118 174
 
... ...
@@ -183,16 +239,22 @@ __interrupt void RTC_ISR (void)
183 239
 {
184 240
 	switch (RTCIV) {
185 241
 		case RTCIV_NONE:
242
+			debug_uart_tx("RTC none IRQ\n");
186 243
 			break;
187 244
 		case RTCIV_RTCRDYIFG:
188 245
 		case RTCIV_RTCTEVIFG:
189 246
 		case RTCIV_RTCAIFG:
190 247
 		case RTCIV_RT0PSIFG:
248
+			debug_uart_tx("RTC misc IRQ\n");
191 249
 			break;
192 250
 		case RTCIV_RT1PSIFG:
193 251
 			RTCPS1CTL &= ~RT1PSIFG;
194 252
 			_event_src |= RTC_1HZ_EVENT;
195 253
 			LPM3_EXIT;
254
+			nop();
255
+#if defined MW_DEVBOARD_V2
256
+			LED7_TOGGLE();
257
+#endif
196 258
 			break;
197 259
 		default:
198 260
 			break;
... ...
@@ -245,7 +307,6 @@ static void dbg_out_rtc(void)
245 307
 	char clk_str[16];
246 308
 	snprintf(clk_str, 16, "%02d:%02d.%02d %d\n", RTCHOUR, RTCMIN, RTCSEC, RTCDOW);
247 309
 	debug_uart_tx(clk_str);
248
-	// bt_l2cap_send_channel(0x40, clk_str, strlen(clk_str));
249 310
 }
250 311
 #endif
251 312
 
... ...
@@ -392,13 +453,6 @@ static void handle_uart_rx_event(void)
392 453
 			nop();
393 454
 		} else if (c == '-') {
394 455
 			nop();
395
-		} else if (c == 't') {
396
-			int i;
397
-			debug_uart_tx("cc256x ini content:\n");
398
-			for (i=0; i<16; i++) {
399
-				snprintf(tstr, 16, "0x%04x 0x%02x\n", i, cc256x_init_script[i]);
400
-				debug_uart_tx(tstr);
401
-			}
402 456
 		} else if (c == 'H') {
403 457
 			uint8_t dclass[3];
404 458
 			dclass[0] = BT_MW_DEVICE_CLASS & 0xff;
... ...
@@ -441,16 +495,16 @@ static void handle_uart_rx_event(void)
441 495
 void start_timer(int cycles)
442 496
 {
443 497
 	TA0EX0 = TAIDEX_0;
444
-	TA0CTL = TASSEL_1 | TACLR | MC__STOP;              // SMCLK, clear TAR
445
-	TA0CCTL0 = CCIE;                         // CCR0 interrupt enabled
498
+	TA0CTL = TASSEL_1 | TACLR | MC__STOP;	// SMCLK, clear TAR
499
+	TA0CCTL0 = CCIE;			// CCR0 interrupt enabled
446 500
 	TA0CCR0 = cycles;
447
-	TA0CTL |= MC_1;                         // Start Timer_A in continuous mode
501
+	TA0CTL |= MC_1;				// Start Timer_A in continuous mode
448 502
 }
449 503
 
450 504
 void stop_timer(void)
451 505
 {
452
-	TA0CCTL0 &= ~CCIE;                         // CCR0 interrupt enabled
453
-	TA0CTL = MC__STOP;                         // Start Timer_A in continuous mode
506
+	TA0CCTL0 &= ~CCIE;			// CCR0 interrupt enabled
507
+	TA0CTL = MC__STOP;			// Start Timer_A in continuous mode
454 508
 }
455 509
  
456 510
 // Timer A0 interrupt service routine
... ...
@@ -483,11 +537,13 @@ uint8_t handle_event(void)
483 537
 			oswald_one_second_tick();
484 538
 #if defined MW_DEVBOARD_V2
485 539
 			dbg_out_rtc();
486
-			LED7_TOGGLE();
487 540
 #endif
488 541
 		} else if (_event_src & BT_UART_RCV_EVENT) {
489 542
 			_event_src &= ~BT_UART_RCV_EVENT;
490 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();
491 547
 		} else if (_event_src & DBG_UART_RCV_EVENT) {
492 548
 			_event_src &= ~DBG_UART_RCV_EVENT;
493 549
 #if defined MW_DEVBOARD_V2
... ...
@@ -518,29 +574,28 @@ uint8_t handle_event(void)
518 574
 #pragma vector=BUTTON_PORT_VECTOR
519 575
 __interrupt void BUTTON_ISR (void)
520 576
 {
577
+	LPM3_EXIT;
521 578
 	BUTTON_PORT_IFG &= ~ALL_BUTTONS;
522 579
 	// BUTTON_PORT_IE  &= ~INT_EDGE_SEL_BUTTONS;
523 580
 	_event_src |= BUTTON_EVENT;
524 581
 	//_button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
525
-	LPM3_EXIT;
526 582
 }
527 583
 
528 584
 #pragma vector=PORT1_VECTOR
529 585
 __interrupt void PORT1_GPIO_ISR (void)
530 586
 {
531 587
 	if (P1IFG & BT_IO_CTS) {
588
+		LPM3_EXIT;
589
+		P1IE &= ~BT_IO_CTS;
532 590
 		P1IFG &= ~BT_IO_CTS;
533
-
534 591
 		debug_uart_tx("BT CTS irq\n");
535
-		bt_hci_ehcill_wake();
536
-
592
+		_event_src |= BT_UART_WAKEUP_EVENT;
593
+		// bt_hci_ehcill_wake();
594
+	} else if (P1IFG & ACCELEROMETER_INT_PIN) {
537 595
 		LPM3_EXIT;
538
-	};
539
-	if (P1IFG & ACCELEROMETER_INT_PIN) {
540 596
 		P1IFG &= ~ACCELEROMETER_INT_PIN;
541 597
 		// debug_uart_tx("ACC irq\n");
542 598
 		_event_src |= ACCEL_EVENT;
543
-		LPM3_EXIT;
544 599
 	}
545 600
 }
546 601
 
... ...
@@ -556,15 +611,13 @@ __interrupt void UNEXP_ISR (void)
556 611
 
557 612
 int main(void)
558 613
 {
559
-	int idle = 0;
560
-
561 614
 	setup_wdt();
562 615
 	setup_pins();
563 616
 	setup_clocks();
564 617
 	setup_rtc();
565 618
 
566 619
 	/* enable interrupts, we will need them! */
567
-	__eint();
620
+	__enable_interrupt();
568 621
 
569 622
 #if defined MW_DEVBOARD_V2
570 623
 	init_debug_uart();
... ...
@@ -578,32 +631,25 @@ int main(void)
578 631
 	mw_init_adc();
579 632
 	mw_init_vibrate_pwm();
580 633
 
581
-#if 0
582
-	RTCYEAR = (unsigned int) 2013;
583
-	RTCMON = (unsigned int) 1;
584
-	RTCDAY = (unsigned int) 1;
585
-	RTCDOW = (unsigned int) 2;
586
-	RTCHOUR = (unsigned int) 01;
587
-	RTCMIN = (unsigned int) 0;
588
-	RTCSEC = (unsigned int) 0;
589
-#endif
590
-
591 634
 	oswald_set_time(RTCHOUR, RTCMIN, RTCSEC, TRUE);
592 635
 	oswald_set_date(RTCDAY, RTCMON, RTCYEAR, TRUE);
593 636
 	oswald_init();
594 637
 
595 638
 	while (1) {
596 639
 		/* handle pending events */
597
-		if (handle_event())
598
-			idle++;
599
-		else
600
-			idle = 0;
640
+		handle_event();
601 641
 
602 642
 		/* enter LPM3 sleep mode waiting for interrupt */
603
-		if (idle > 100) {
604
-			idle = 0;
605
-			// debug_uart_tx("z");
606
-			LPM3;
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);
607 653
 		}
608 654
 	};
609 655
 
Browse code

Maybe a little sniff mode, add ambient light adc (not working), fix accelerometer display orientation

Nils Faerber authored on 06/05/2013 23:39:18
Showing 1 changed files
... ...
@@ -337,6 +337,11 @@ static void handle_uart_rx_event(void)
337 337
 			mw_acc_read(&x, &y, &z);
338 338
 			snprintf(tstr, 64, "x:%d y:%d z:%d\n", x,y,z);
339 339
 			debug_uart_tx(tstr);
340
+		} else if (c =='R') {
341
+			int16_t al;
342
+			al = mw_get_amblight_adc_val();
343
+			snprintf(tstr, 64, "light: %d\n", al);
344
+			debug_uart_tx(tstr);
340 345
 		} else if (c == 'b') {
341 346
 			debug_uart_tx("\nenabling BT\n");
342 347
 			mw_enable_bt();
Browse code

Make accelerometer work, interrup driven tilt change mode

Nils Faerber authored on 05/05/2013 21:22:33
Showing 1 changed files
... ...
@@ -10,6 +10,7 @@
10 10
 #include "mw_bt.h"
11 11
 #include "mw_adc.h"
12 12
 #include "mw_bt.h"
13
+#include "mw_acc.h"
13 14
 #include "bt_hci.h"
14 15
 #include "bt_l2cap.h"
15 16
 
... ...
@@ -18,7 +19,7 @@
18 19
 
19 20
 #include "bluetooth_init_cc256x.h"
20 21
 
21
-unsigned int _event_src = 0;
22
+uint16_t _event_src = 0;
22 23
 
23 24
 
24 25
 static void set16mhz(void)
... ...
@@ -111,7 +112,7 @@ static void setup_pins(void)
111 112
 	DISABLE_LCD_LED();		// frontlight
112 113
 	CONFIG_DEBUG_PINS();
113 114
 	CONFIG_ACCELEROMETER_PINS();
114
-	// DISABLE_ACCELEROMETER_POWER(); // there is no accel. power switching!
115
+	DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
115 116
 
116 117
 	HARDWARE_CFG_SENSE_INIT();
117 118
 
... ...
@@ -324,7 +325,19 @@ static void handle_uart_rx_event(void)
324 325
 
325 326
 	if (debug_uart_rx_char(&c)) {
326 327
 		debug_uart_tx_char(c);
327
-		if (c == 'b') {
328
+		if (c == 'a') {
329
+			debug_uart_tx("\nenabling ACC\n");
330
+			mw_acc_enable();
331
+		} else if (c == 'A') {
332
+			debug_uart_tx("\ndisabling ACC\n");
333
+			mw_acc_disable();
334
+		} else if (c == 'r') {
335
+			int16_t x,y,z;
336
+			debug_uart_tx("\nread ACC: ");
337
+			mw_acc_read(&x, &y, &z);
338
+			snprintf(tstr, 64, "x:%d y:%d z:%d\n", x,y,z);
339
+			debug_uart_tx(tstr);
340
+		} else if (c == 'b') {
328 341
 			debug_uart_tx("\nenabling BT\n");
329 342
 			mw_enable_bt();
330 343
 		} else if (c == 'B') {
... ...
@@ -484,6 +497,9 @@ uint8_t handle_event(void)
484 497
 		} else if (_event_src & TIMER_100MS_EVENT) {
485 498
 			_event_src &= ~TIMER_100MS_EVENT;
486 499
 			oswald_centisecond_tick();
500
+		} else if (_event_src & ACCEL_EVENT) {
501
+			_event_src &= ~ACCEL_EVENT;
502
+			mw_acc_handle_irq();
487 503
 		} else {
488 504
 #if defined MW_DEVBOARD_V2
489 505
 			snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
... ...
@@ -504,6 +520,26 @@ __interrupt void BUTTON_ISR (void)
504 520
 	LPM3_EXIT;
505 521
 }
506 522
 
523
+#pragma vector=PORT1_VECTOR
524
+__interrupt void PORT1_GPIO_ISR (void)
525
+{
526
+	if (P1IFG & BT_IO_CTS) {
527
+		P1IFG &= ~BT_IO_CTS;
528
+
529
+		debug_uart_tx("BT CTS irq\n");
530
+		bt_hci_ehcill_wake();
531
+
532
+		LPM3_EXIT;
533
+	};
534
+	if (P1IFG & ACCELEROMETER_INT_PIN) {
535
+		P1IFG &= ~ACCELEROMETER_INT_PIN;
536
+		// debug_uart_tx("ACC irq\n");
537
+		_event_src |= ACCEL_EVENT;
538
+		LPM3_EXIT;
539
+	}
540
+}
541
+
542
+
507 543
 #if 0
508 544
 #pragma vector=NOVECTOR
509 545
 __interrupt void UNEXP_ISR (void)
Browse code

Here we are! MetaWatch support in Oswald!

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