#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_bt.h"
#include "mw_adc.h"
#include "mw_bt.h"
+#include "mw_acc.h"
#include "bt_hci.h"
#include "bt_l2cap.h"
#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)
{
}
}
+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;
}
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;
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();
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();
#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
}
{
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;
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
*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;
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') {
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;
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;
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
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)
_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) {
} 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
#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)
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
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);
}
};