2 #include <msp430xgeneric.h>
17 #include "oswald_main.h"
18 #include "oswald_hal.h"
20 #include "bluetooth_init_cc256x.h"
22 uint16_t _event_src = 0;
25 static void set16mhz(void)
27 UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
28 UCSCTL1 = DCORSEL_5; // Select suitable range
29 UCSCTL2 = 488 + FLLD_1; // Set DCO Multiplier
30 UCSCTL4 = SELA__XT1CLK | SELS__DCOCLKDIV | SELM__DCOCLKDIV ;
32 // Worst-case settling time for the DCO when the DCO range bits have been
33 // changed is n x 32 x 32 x f_FLL_reference. See UCS chapter in 5xx UG
35 // 32 x 32 x / f_FLL_reference (32,768 Hz) = .03125 = t_DCO_settle
36 // t_DCO_settle / (1 / 18 MHz) = 562500 = counts_DCO_settle
38 // __delay_cycles(562500);
41 __delay_cycles(56250);
45 static void setup_clocks(void)
49 /* use external oscillator */
51 if ((UCSCTL6 & XT1DRIVE_3) != XT1DRIVE_3) {
52 UCSCTL6_L |= XT1DRIVE1_L + XT1DRIVE0_L;
55 while ((SFRIFG1 & OFIFG) && i--) {
56 UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
59 UCSCTL6 = (UCSCTL6 & ~(XT1DRIVE_3)) |(XT1DRIVE_0);
63 UCSCTL8 |= SMCLKREQEN;
65 /* enable oscillator fault NMI IRQ */
70 #pragma vector=PWR_PORT_VECTOR
71 __interrupt void PWR_ISR (void)
73 /* clear all possible sources */
74 PWR_PORT_IFG &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
75 _event_src |= POWER_SRC_EVENT;
81 static void mw_init_vibrate_pwm(void)
84 // Start with P7.3 as an output
85 P7OUT &= ~BIT3; // Low when a digital output
86 P7SEL &= ~BIT3; // P7 option select = false
87 P7DIR |= BIT3; // P7 outputs
91 // No expansion divide
94 // do a PWM with 64 total steps. This gives a count up of 32 and
98 // Compare channel 2 is used as output
99 TA1CCTL2 = OUTMOD_6; // PWM output mode: 6 - toggle/set
100 TA1CCR2 = 10; // 10 is a 2/3 duty cycle
105 static void setup_pins(void)
108 CONFIGURE_BUTTON_PINS();
109 #ifdef MW_DEVBOARD_V2
110 CONFIG_LED_PINS(); // debug LEDs on devboard
112 DISABLE_LCD_LED(); // frontlight
114 CONFIG_ACCELEROMETER_PINS();
115 DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later
117 HARDWARE_CFG_SENSE_INIT();
120 APPLE_POWER_DISABLE();
123 BT_CLK_REQ_CONFIG_AS_OUTPUT_LOW();
124 BT_IO1_CONFIG_AS_OUTPUT_LOW();
125 BT_IO2_CONFIG_AS_OUTPUT_LOW();
129 LIGHT_SENSOR_SHUTDOWN();
131 BATTERY_SENSE_INIT();
132 BATTERY_SENSE_DISABLE();
133 BAT_CHARGE_DIR &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2 | BAT_CHARGE_PWR_BIT);
134 BAT_CHARGE_OUT |= BAT_CHARGE_PWR_BIT | BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2; // pull-up
135 BAT_CHARGE_REN |= BAT_CHARGE_PWR_BIT; // enable resistors
136 // BAT_CHARGE_IE |= BAT_CHARGE_PWR_BIT;
137 BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN; // !CE, negative logic
138 BAT_CHARGE_DIR |= BAT_CHARGE_ENABLE_PIN;
140 /* disable reset function, enable NMI, do not enable NMI IRQ */
141 /* to avoid accidential reset on charger clip connect */
142 #ifndef MW_DEVBOARD_V2 // but only on real watch
143 SFRRPCR &= ~SYSRSTRE;
148 #pragma vector=WDT_VECTOR
149 __interrupt void WDT_ISR (void)
151 /* eventually we will do something here, not for now */
152 _event_src |= WATCHDOG_EVENT;
156 static void setup_wdt(void)
159 WDTCTL = WDTPW + WDTHOLD; // disable watchdog
161 WDTCTL = WDT_ADLY_1000; // 1 second timeout
162 SFRIE1 |= WDTIE; // Enable WDT interrupt
167 #pragma vector=UNMI_VECTOR
168 __interrupt void NMI_ISR (void)
170 #if defined MW_DEVBOARD_V2
172 debug_uart_tx_char('n');
174 while ((SFRIFG1 & OFIFG)) {
175 UCSCTL7 &= ~(DCOFFG + XT1LFOFFG + XT1HFOFFG + XT2OFFG);
181 #pragma vector=RTC_VECTOR
182 __interrupt void RTC_ISR (void)
187 case RTCIV_RTCRDYIFG:
188 case RTCIV_RTCTEVIFG:
193 RTCPS1CTL &= ~RT1PSIFG;
194 _event_src |= RTC_1HZ_EVENT;
208 RTCCTL2 = 0x00 & 0x3f;
211 // Set the counter for RTC mode
214 // set 128 Hz rate for prescale 0 interrupt
215 RTCPS0CTL |= RT0IP_7;
217 // enable 1 pulse per second interrupt using prescale 1
218 RTCPS1CTL |= RT1IP_6 | RT1PSIE;
220 // 1 Hz calibration output
221 RTCCTL23 |= RTCCALF_3;
223 // setting the peripheral selection bit makes the other I/O control a don't care
224 // P2.4 = 1 Hz RTC calibration output
225 // Direction needs to be set as output
226 RTC_1HZ_PORT_SEL |= RTC_1HZ_BIT;
227 RTC_1HZ_PORT_DIR |= RTC_1HZ_BIT;
229 RTCYEAR = (unsigned int) 2013;
230 RTCMON = (unsigned int) 1;
231 RTCDAY = (unsigned int) 1;
232 RTCDOW = (unsigned int) 2;
233 RTCHOUR = (unsigned int) 01;
234 RTCMIN = (unsigned int) 0;
235 RTCSEC = (unsigned int) 0;
238 RTCCTL01 &= ~RTCHOLD;
242 #if defined MW_DEVBOARD_V2
243 static void dbg_out_rtc(void)
246 snprintf(clk_str, 16, "%02d:%02d.%02d %d\n", RTCHOUR, RTCMIN, RTCSEC, RTCDOW);
247 debug_uart_tx(clk_str);
248 // bt_l2cap_send_channel(0x40, clk_str, strlen(clk_str));
252 static void handle_button_event(void)
254 unsigned char _button_state = 0;
257 snprintf(clk_str, 16, "0x%02x\n", _button_state);
258 debug_uart_tx(clk_str);
260 while (_button_state != (BUTTON_PORT_IN & ALL_BUTTONS)) {
261 __delay_cycles(562500);
262 _button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
263 __delay_cycles(562500);
265 // BUTTON_PORT_IE |= INT_EDGE_SEL_BUTTONS;
267 if (_button_state & SW_A) {
268 debug_uart_tx("switch A\n");
269 oswald_handle_button_press(BUTTON_A);
271 if (_button_state & SW_B) {
272 debug_uart_tx("switch B\n");
273 oswald_handle_button_press(BUTTON_B);
275 if (_button_state & SW_C) {
276 debug_uart_tx("switch C\n");
277 oswald_handle_button_press(BUTTON_C);
279 if (_button_state & SW_D) {
280 debug_uart_tx("switch D\n");
281 oswald_handle_button_press(BUTTON_D);
283 if (_button_state & SW_E) {
284 debug_uart_tx("switch E\n");
285 oswald_handle_button_press(BUTTON_E);
287 if (_button_state & SW_F) {
288 debug_uart_tx("switch F\n");
289 oswald_handle_button_press(BUTTON_F);
293 void check_pwr_state(void)
295 if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT) {
296 BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
297 BAT_CHARGE_REN &= ~(BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2); // disable pull-up
299 BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
300 BAT_CHARGE_REN |= BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2; // enable pull-up
304 static void handle_bt_uart_rx_event(void)
306 const unsigned char *rx;
307 unsigned char len, *rp, p;
309 rx = mw_bt_get_rx_buf(&rp, &len);
313 p += bt_feed_packet_data(rx[(*rp+p)%BT_RX_MAX_SIZE]);
316 *rp = (*rp + len) % BT_RX_MAX_SIZE;
319 #if defined MW_DEVBOARD_V2
320 static void handle_uart_rx_event(void)
323 #ifndef CC256x_TRANSP
326 if (debug_uart_rx_char(&c)) {
327 debug_uart_tx_char(c);
329 debug_uart_tx("\nenabling ACC\n");
331 } else if (c == 'A') {
332 debug_uart_tx("\ndisabling ACC\n");
334 } else if (c == 'r') {
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);
340 } else if (c =='R') {
342 al = mw_get_amblight_adc_val();
343 snprintf(tstr, 64, "light: %d\n", al);
345 } else if (c == 'b') {
346 debug_uart_tx("\nenabling BT\n");
348 } else if (c == 'B') {
349 debug_uart_tx("\ndisabling BT\n");
351 } else if (c == 'c') {
352 debug_uart_tx("\nCharger status: ");
353 snprintf(tstr, 16, "0x%04x 0x%04x ", BAT_CHARGE_IN, (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT));
355 if (BAT_CHARGE_IN & BAT_CHARGE_PWR_BIT)
356 debug_uart_tx("no ext pwr, ");
358 debug_uart_tx("ext pwr connected, ");
359 switch (BAT_CHARGE_IN & (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2)) {
360 case BAT_CHARGE_STAT1:
361 debug_uart_tx("charge done\n");
363 case BAT_CHARGE_STAT2:
364 debug_uart_tx("fast charge\n");
366 case (BAT_CHARGE_STAT1 | BAT_CHARGE_STAT2):
367 debug_uart_tx("suspend, sleep or fault\n");
370 debug_uart_tx("precharge\n");
373 if (BAT_CHARGE_IN & BAT_CHARGE_ENABLE_PIN)
374 debug_uart_tx(" !charge\n");
376 debug_uart_tx(" charge\n");
377 } else if (c == 'd') {
378 debug_uart_tx("charging disabled\n");
379 BAT_CHARGE_OUT |= BAT_CHARGE_ENABLE_PIN;
380 } else if (c == 'e') {
381 debug_uart_tx("charging enabled\n");
382 BAT_CHARGE_OUT &= ~BAT_CHARGE_ENABLE_PIN;
383 } else if (c == 'l') {
384 debug_uart_tx("backlight LED on\n");
385 hal_lcd_set_backlight(TRUE);
386 } else if (c == 'L') {
387 debug_uart_tx("backlight LED off\n");
388 hal_lcd_set_backlight(FALSE);
389 } else if (c == 'u') {
390 mw_lcd_update_screen();
391 } else if (c == '+') {
393 } else if (c == '-') {
395 } else if (c == 't') {
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]);
402 } else if (c == 'H') {
404 dclass[0] = BT_MW_DEVICE_CLASS & 0xff;
405 dclass[1] = (BT_MW_DEVICE_CLASS & 0xff00) >> 8;
406 dclass[2] = (BT_MW_DEVICE_CLASS & 0xff0000) >> 16;
408 debug_uart_tx("HCI reset\n");
409 bt_hci_cmd(HCI_HC_BB_OGF, HCI_RESET_OCF, 0, NULL);
410 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_COD_OCF, 3, dclass);
411 } else if (c == 'S') {
412 debug_uart_tx("Scan enable\n");
413 tstr[0] = HCI_BB_SCAN_INQUIRY | HCI_BB_SCAN_PAGE;
414 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_SCAN_EN_OCF, 1, (uint8_t *)tstr);
415 } else if (c == 'h') {
419 } else if (c == 'm') {
423 } else if (c == 'N') {
424 debug_uart_tx("Set name\n");
432 bt_hci_cmd(HCI_HC_BB_OGF, HCI_W_LOCAL_NAME_OCF, 0x07, (uint8_t *)tstr);
433 } else if (c == 'R') {
434 bt_hci_cmd(HCI_INFO_PARAM_OGF, HCI_R_BD_ADDR_OCF, 0, NULL);
441 void start_timer(int cycles)
444 TA0CTL = TASSEL_1 | TACLR | MC__STOP; // SMCLK, clear TAR
445 TA0CCTL0 = CCIE; // CCR0 interrupt enabled
447 TA0CTL |= MC_1; // Start Timer_A in continuous mode
450 void stop_timer(void)
452 TA0CCTL0 &= ~CCIE; // CCR0 interrupt enabled
453 TA0CTL = MC__STOP; // Start Timer_A in continuous mode
456 // Timer A0 interrupt service routine
457 #pragma vector=TIMER0_A0_VECTOR
458 __interrupt void TIMER0_A0_ISR (void)
461 #if defined xMW_DEVBOARD_V2
464 _event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT;
468 uint8_t handle_event(void)
470 #if defined MW_DEVBOARD_V2
476 while (_event_src != 0) {
477 if (_event_src & WATCHDOG_EVENT) {
478 _event_src &= ~WATCHDOG_EVENT;
479 debug_uart_tx_char('w');
480 } else if (_event_src & RTC_1HZ_EVENT) {
481 _event_src &= ~RTC_1HZ_EVENT;
483 oswald_one_second_tick();
484 #if defined MW_DEVBOARD_V2
488 } else if (_event_src & BT_UART_RCV_EVENT) {
489 _event_src &= ~BT_UART_RCV_EVENT;
490 handle_bt_uart_rx_event();
491 } else if (_event_src & DBG_UART_RCV_EVENT) {
492 _event_src &= ~DBG_UART_RCV_EVENT;
493 #if defined MW_DEVBOARD_V2
494 handle_uart_rx_event();
496 } else if (_event_src & BUTTON_EVENT) {
497 _event_src &= ~BUTTON_EVENT;
498 handle_button_event();
499 } else if (_event_src & TIMER_500MS_EVENT) {
500 _event_src &= ~TIMER_500MS_EVENT;
501 oswald_halfsecond_tick();
502 } else if (_event_src & TIMER_100MS_EVENT) {
503 _event_src &= ~TIMER_100MS_EVENT;
504 oswald_centisecond_tick();
505 } else if (_event_src & ACCEL_EVENT) {
506 _event_src &= ~ACCEL_EVENT;
509 #if defined MW_DEVBOARD_V2
510 snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src);
518 #pragma vector=BUTTON_PORT_VECTOR
519 __interrupt void BUTTON_ISR (void)
521 BUTTON_PORT_IFG &= ~ALL_BUTTONS;
522 // BUTTON_PORT_IE &= ~INT_EDGE_SEL_BUTTONS;
523 _event_src |= BUTTON_EVENT;
524 //_button_state = (BUTTON_PORT_IN & ALL_BUTTONS);
528 #pragma vector=PORT1_VECTOR
529 __interrupt void PORT1_GPIO_ISR (void)
531 if (P1IFG & BT_IO_CTS) {
534 debug_uart_tx("BT CTS irq\n");
535 bt_hci_ehcill_wake();
539 if (P1IFG & ACCELEROMETER_INT_PIN) {
540 P1IFG &= ~ACCELEROMETER_INT_PIN;
541 // debug_uart_tx("ACC irq\n");
542 _event_src |= ACCEL_EVENT;
549 #pragma vector=NOVECTOR
550 __interrupt void UNEXP_ISR (void)
552 debug_uart_tx("unexpected IRQ occured\n");
566 /* enable interrupts, we will need them! */
569 #if defined MW_DEVBOARD_V2
571 debug_uart_tx("\nOswald on MetaWatch\n");
576 mw_lcd_update_screen();
579 mw_init_vibrate_pwm();
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;
591 oswald_set_time(RTCHOUR, RTCMIN, RTCSEC, TRUE);
592 oswald_set_date(RTCDAY, RTCMON, RTCYEAR, TRUE);
596 /* handle pending events */
602 /* enter LPM3 sleep mode waiting for interrupt */
605 // debug_uart_tx("z");