X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=metawatch%2Fmw_main.c;h=07f8ba581a3c1c4493d02caf420ca31ca6eb87e4;hb=cd477f0823f08be745cb22521bafb6c6cee192c7;hp=89b014ebe748be909e475509957392796cf23304;hpb=1553c23cf33de5d8a193ffc8c7014cf826fc9fd3;p=oswald.git diff --git a/metawatch/mw_main.c b/metawatch/mw_main.c index 89b014e..07f8ba5 100644 --- a/metawatch/mw_main.c +++ b/metawatch/mw_main.c @@ -3,6 +3,9 @@ #include #include +#include "F5xx_F6xx_Core_Lib/HAL_PMM.h" +#include "F5xx_F6xx_Core_Lib/HAL_UCS.h" + #include "mw_main.h" #include "mw_uart.h" @@ -10,6 +13,7 @@ #include "mw_bt.h" #include "mw_adc.h" #include "mw_bt.h" +#include "mw_acc.h" #include "bt_hci.h" #include "bt_l2cap.h" @@ -18,8 +22,32 @@ #include "bluetooth_init_cc256x.h" -unsigned int _event_src = 0; +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) { @@ -41,12 +69,41 @@ static void set16mhz(void) } } +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; } @@ -60,6 +117,51 @@ static void setup_clocks(void) 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; @@ -111,7 +213,8 @@ static void setup_pins(void) DISABLE_LCD_LED(); // frontlight CONFIG_DEBUG_PINS(); CONFIG_ACCELEROMETER_PINS(); - // DISABLE_ACCELEROMETER_POWER(); // there is no accel. power switching! + //DISABLE_ACCELEROMETER_POWER(); // starts from config 5 and later + ENABLE_ACCELEROMETER_POWER(); // starts from config 5 and later HARDWARE_CFG_SENSE_INIT(); @@ -119,9 +222,12 @@ static void setup_pins(void) 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_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(); @@ -141,6 +247,20 @@ static void setup_pins(void) #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 } @@ -182,16 +302,22 @@ __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; + LPM3_EXIT_ISR(); +#if defined MW_DEVBOARD_V2 + LED7_TOGGLE(); +#endif break; default: break; @@ -238,13 +364,12 @@ void setup_rtc(void) nop(); } -#if defined MW_DEVBOARD_V2 +#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); - // bt_l2cap_send_channel(0x40, clk_str, strlen(clk_str)); } #endif @@ -315,7 +440,7 @@ static void handle_bt_uart_rx_event(void) *rp = (*rp + len) % BT_RX_MAX_SIZE; } -#if defined MW_DEVBOARD_V2 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART static void handle_uart_rx_event(void) { char c; @@ -324,7 +449,24 @@ static void handle_uart_rx_event(void) if (debug_uart_rx_char(&c)) { debug_uart_tx_char(c); - if (c == 'b') { + 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') { @@ -374,13 +516,6 @@ static void handle_uart_rx_event(void) nop(); } else if (c == '-') { nop(); - } else if (c == 't') { - int i; - debug_uart_tx("cc256x ini content:\n"); - for (i=0; i<16; i++) { - snprintf(tstr, 16, "0x%04x 0x%02x\n", i, cc256x_init_script[i]); - debug_uart_tx(tstr); - } } else if (c == 'H') { uint8_t dclass[3]; dclass[0] = BT_MW_DEVICE_CLASS & 0xff; @@ -390,6 +525,20 @@ static void handle_uart_rx_event(void) 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; @@ -423,16 +572,16 @@ static void handle_uart_rx_event(void) void start_timer(int cycles) { TA0EX0 = TAIDEX_0; - TA0CTL = TASSEL_1 | TACLR | MC__STOP; // SMCLK, clear TAR - TA0CCTL0 = CCIE; // CCR0 interrupt enabled + 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 + 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 + TA0CCTL0 &= ~CCIE; // CCR0 interrupt enabled + TA0CTL = MC__STOP; // Start Timer_A in continuous mode } // Timer A0 interrupt service routine @@ -444,12 +593,13 @@ __interrupt void TIMER0_A0_ISR (void) LED6_TOGGLE(); #endif _event_src |= TIMER_500MS_EVENT | TIMER_100MS_EVENT; - LPM3_EXIT; + // LPM3_EXIT; + LPM3_EXIT_ISR(); } uint8_t handle_event(void) { -#if defined MW_DEVBOARD_V2 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART char tstr[64]; #endif if (_event_src == 0) @@ -463,16 +613,18 @@ uint8_t handle_event(void) _event_src &= ~RTC_1HZ_EVENT; check_pwr_state(); oswald_one_second_tick(); -#if defined MW_DEVBOARD_V2 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART dbg_out_rtc(); - LED7_TOGGLE(); #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 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART handle_uart_rx_event(); #endif } else if (_event_src & BUTTON_EVENT) { @@ -484,8 +636,11 @@ uint8_t handle_event(void) } 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 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART snprintf(tstr, 64, "unhandled event in 0x%04x\n", _event_src); debug_uart_tx(tstr); #endif @@ -497,13 +652,35 @@ uint8_t handle_event(void) #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); - LPM3_EXIT; } +#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) @@ -515,17 +692,15 @@ __interrupt void UNEXP_ISR (void) int main(void) { - int idle = 0; - setup_wdt(); setup_pins(); setup_clocks(); setup_rtc(); /* enable interrupts, we will need them! */ - __eint(); + __enable_interrupt(); -#if defined MW_DEVBOARD_V2 +#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART init_debug_uart(); debug_uart_tx("\nOswald on MetaWatch\n"); #endif @@ -537,32 +712,25 @@ int main(void) mw_init_adc(); mw_init_vibrate_pwm(); -#if 0 - 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; -#endif - oswald_set_time(RTCHOUR, RTCMIN, RTCSEC, TRUE); oswald_set_date(RTCDAY, RTCMON, RTCYEAR, TRUE); oswald_init(); while (1) { /* handle pending events */ - if (handle_event()) - idle++; - else - idle = 0; + handle_event(); /* enter LPM3 sleep mode waiting for interrupt */ - if (idle > 100) { - idle = 0; - // debug_uart_tx("z"); - LPM3; + /* 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); } };