if (UCA1STAT & UCRXERR) {
debug_uart_tx("BT UART RXERR: ");
if (UCA1STAT & UCOE)
- debug_uart_tx("overrun\n");
+ debug_uart_tx("overrun ");
if (UCA1STAT & UCPE)
- debug_uart_tx("parity err\n");
+ debug_uart_tx("parity err ");
if (UCA1STAT & UCFE)
- debug_uart_tx("frm-err\n");
+ debug_uart_tx("frm-err ");
+ debug_uart_tx("\n");
}
bt_rx_buf[bt_rx_buf_wpos++] = UCA1RXBUF;
bt_rx_buf_wpos %= BT_RX_MAX_SIZE;
- LPM3_EXIT;
+ // LPM3_EXIT;
+ LPM3_EXIT_ISR();
_event_src |= BT_UART_RCV_EVENT;
break;
case 4: // TXIFG
//UCA1CTL0 |= UCRXEIE;
UCA1CTL1 &= ~UCSWRST;
+
/* clear interrup flags */
- UCA1IE = UCRXIE;
UCA1IFG = 0;
+ UCA1IE = UCRXIE;
}
#if 0 // Does never finish, presumably trigger does not trigger, unknown :(
nop();
}
#else
-void mw_bt_uart_tx(const void *buf, const unsigned int len)
+int mw_bt_uart_tx(const void *buf, const unsigned int len)
{
- unsigned int pos;
+ unsigned int pos, i;
// char txstr[8];
pos = 0;
// debug_uart_tx("BT tx: ");
while (pos < len) {
- // wait for CTS to go low
- while ((BT_IO_PIN & BT_IO_CTS))
- nop();
+ // watch for CTS to be low
+ i = 0;
+ while ((BT_IO_PIN & BT_IO_CTS) && (i < 1000)) {
+ __delay_cycles(16000);
+ i++;
+ if (i >= 1000)
+ return -1;
+ // nop();
+ }
// do not start a transfer if UART is busy, e.g. rx-ing
while (UCA1STAT & UCBUSY)
}
while (UCA1STAT & UCBUSY)
nop();
+
+ return len;
}
#endif
-static void load_cc256x_init_script(void)
+static int load_cc256x_init_script(void)
{
uint32_t pos;
unsigned char *tptr;
+ int tlen;
pos = 0;
while (pos < cc256x_init_script_size) {
if (_event_src != 0)
handle_event();
tptr = (unsigned char *)(cc256x_init_script + pos);
- mw_bt_uart_tx(tptr, 4 + tptr[3]);
- pos += 4 + tptr[3];
+ tlen = mw_bt_uart_tx(tptr, 4 + tptr[3]);
+ if (tlen < 0)
+ return -1;
+ pos += tlen /*4 + tptr[3]*/;
// each init script part is one HCI command so wait for reply
if (_event_src != 0)
handle_event();
}
+ return 0;
}
void mw_enable_bt(void)
/* make sure it resets */
BT_SHUTDOWN();
+ __delay_cycles(16000);
/* enable 32kHz ACLK output to BT module */
P11DIR |= BIT0;
// wait for clock to stabilize
__delay_cycles(16000);
+ // disable the IRQ on CTS, later used to get a wakeup IRQ from eHCILL
+ // will be enabled when going to sleep
+ P1IE &= ~BT_IO_CTS;
+ P1IES &= ~BT_IO_CTS;
+
BT_IO_PDIR &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
BT_IO_PDIR |= BT_IO_RTS;
+
BT_IO_POUT &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
BT_IO_POUT &= ~BT_IO_RTS; // low == ready, high == !ready
+ BT_IO_REN |= BT_IO_CTS; // enable pull-down on CTS, POUT-CTS is 0 already
+
/* setup UART pins */
BT_UART_PSEL |= BT_UART_TX_PIN | BT_UART_RX_PIN;
// P5OUT |= BT_UART_TX_PIN | BT_UART_RX_PIN;
}
if (i>=1000) {
debug_uart_tx("Timeout waiting for CC256x to lower CTS\n");
+ mw_bt_enabled = 0;
} else {
debug_uart_tx("CC256x CTS low - uploading init\n");
- for (i=0; i<100; i++) {
- __delay_cycles(16000); // give it some more before anyone sends data
+
+ // the init script consists of HCI cmds so HCI must be setup before
+ bt_hci_init();
+
+ // give it some more time before anyone sends data
+ for (i=0; i<10; i++) {
+ __delay_cycles(16000);
+ }
+ if (load_cc256x_init_script() < 0) {
+ debug_uart_tx("init upload failed!\n");
+ return;
}
- load_cc256x_init_script();
+
+ __delay_cycles(32000);
+
debug_uart_tx("init uploaded\n");
- }
- P1IE &= ~BT_IO_CTS;
- P1IES &= ~BT_IO_CTS;
+ init_l2cap();
- bt_hci_init();
- init_l2cap();
+ if (_event_src != 0)
+ handle_event();
- mw_bt_enabled = 1;
+ mw_bt_enabled = 1;
+ }
}
void mw_disable_bt(void)
{
mw_bt_enabled = 0;
+ // disable the IRQ on CTS
+ P1IE &= ~BT_IO_CTS;
+ P1IES &= ~BT_IO_CTS;
+ // BT_IO_REN &= ~BT_IO_CTS; // disable pull-down on CTS
+ P1IFG &= ~BT_IO_CTS;
+
/* disable UART RX interrupt */
UCA1IE &= ~UCRXIE;
#include "oswald_main.h"
#include "oswald_hal.h"
+#include "bluetooth_init_cc256x.h"
uint16_t _event_src = 0;
#define HARDWARE_REVISION_ADDRESS (0x1a07)
-unsigned char GetMsp430HardwareRevision(void)
+uint8_t GetMsp430HardwareRevision(void)
{
- unsigned char *pDeviceType = (unsigned char *)(unsigned char *)HARDWARE_REVISION_ADDRESS;
+ uint8_t *pDeviceType = (uint8_t *)(uint8_t *)HARDWARE_REVISION_ADDRESS;
return pDeviceType[0]+'1';
}
uint8_t DetermineErrata(void)
{
- unsigned char Revision = GetMsp430HardwareRevision();
+ uint8_t Revision = GetMsp430HardwareRevision();
switch (Revision) {
case 'F':
+ case 'G':
case 'H':
return 0;
break;
}
}
+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;
/* 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
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;
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
}
case RTCIV_RT1PSIFG:
RTCPS1CTL &= ~RT1PSIFG;
_event_src |= RTC_1HZ_EVENT;
- LPM3_EXIT;
- nop();
+ // LPM3_EXIT;
+ LPM3_EXIT_ISR();
#if defined MW_DEVBOARD_V2
LED7_TOGGLE();
#endif
nop();
}
-#if defined MW_DEVBOARD_V2
+#if defined MW_DEVBOARD_V2 || MW_DEBUG_UART
static void dbg_out_rtc(void)
{
char clk_str[16];
*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;
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;
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();
#endif
} else if (_event_src & BT_UART_RCV_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) {
_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;
+ LPM3_EXIT_ISR();
BUTTON_PORT_IFG &= ~ALL_BUTTONS;
// BUTTON_PORT_IE &= ~INT_EDGE_SEL_BUTTONS;
_event_src |= BUTTON_EVENT;
__interrupt void PORT1_GPIO_ISR (void)
{
if (P1IFG & BT_IO_CTS) {
- LPM3_EXIT;
+ //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;
+ LPM3_EXIT_ISR();
P1IFG &= ~ACCELEROMETER_INT_PIN;
// debug_uart_tx("ACC irq\n");
_event_src |= ACCEL_EVENT;
/* enable interrupts, we will need them! */
__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