]> git.karo-electronics.de Git - oswald.git/blob - metawatch/mw_bt.c
Here we are! MetaWatch support in Oswald!
[oswald.git] / metawatch / mw_bt.c
1 #include <msp430.h>
2 #include <msp430xgeneric.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <string.h>
6
7 #include "mw_main.h"
8
9 #include "mw_uart.h"
10 #include "mw_bt.h"
11 #include "bt_hci.h"
12 #include "bt_l2cap.h"
13
14 #include "bluetooth_init_cc256x.h"
15
16
17 static char bt_rx_buf[BT_RX_MAX_SIZE];
18 static unsigned char bt_rx_buf_wpos = 0;
19 static unsigned char bt_rx_buf_rpos = 0;
20 static uint8_t mw_bt_enabled = 0;
21
22 const unsigned char *mw_bt_get_rx_buf(unsigned char **rpos, unsigned char *len)
23 {
24         *rpos = &bt_rx_buf_rpos;
25         if (bt_rx_buf_rpos > bt_rx_buf_wpos)
26                 *len = (BT_RX_MAX_SIZE - bt_rx_buf_rpos) + bt_rx_buf_wpos;
27         else
28                 *len = bt_rx_buf_wpos - bt_rx_buf_rpos;
29
30         if (*len > (BT_RX_MAX_SIZE-(BT_RX_MAX_SIZE/10)))
31                 BT_IO_POUT |= BT_IO_RTS; // low == ready, high == !ready
32
33         return (unsigned char *)bt_rx_buf;
34 }
35
36 #pragma vector=USCI_A1_VECTOR
37 __interrupt void UCA1_ISR (void)
38 {
39         switch (UCA1IV) {
40                 case 2: // RXIFG
41                         /* wake up to handle the received char */
42                         LPM3_EXIT;
43                         bt_rx_buf[bt_rx_buf_wpos++] = UCA1RXBUF;
44                         /* clear IRQ flag */
45                         UCA1IFG  &= ~UCRXIFG;
46                         bt_rx_buf_wpos %= BT_RX_MAX_SIZE;
47                         _event_src |= BT_UART_RCV_EVENT;
48                         break;
49                 case 4: // TXIFG
50                         break;
51                 default:
52                         break;
53         };
54 }
55
56 void mw_init_bt_uart(const bt_uart_baud_t baud)
57 {
58         UCA1CTL1 = UCSWRST;
59         UCA1CTL1 |= UCSSEL__SMCLK;
60         switch (baud) {
61                 case BT_UART_BD115200:
62                 default:
63                         UCA1BR0 = 138;
64                         UCA1MCTL = UCBRS_7 + UCBRF_0;
65                 break;
66         };
67         UCA1STAT = 0;
68         UCA1CTL0 = UCMODE_0;    // UART mode
69         UCA1CTL0 &= ~UC7BIT;    // 8bit char
70
71         UCA1CTL1 &= ~UCSWRST;
72         /* clear interrup flags */
73         UCA1IFG = 0;
74         UCA1IE = UCRXIE;
75 }
76
77 #if 0 // Does never finish, presumably trigger does not trigger, unknown :(
78 void mw_bt_uart_tx(const void *buf, const unsigned int len)
79 {
80         UCA1IE &= UCTXIE;
81
82         DMACTL0 = DMA0TSEL_21;
83
84         DMA0DA  = (unsigned int) &UCA1TXBUF;
85         DMA0SA  = (uint32_t) buf;
86         DMA0SZ  = len;
87
88         //DMA0CTL = 0x03F0;
89         DMA0CTL = DMADT_1 | DMASRCINCR_3 | DMASBDB | DMALEVEL | DMAIE;
90         UCA1IFG &= ~UCTXIFG;
91         DMA0CTL |= DMAEN;
92
93         while ((DMA0CTL & DMAIFG) == 0 && (DMA0CTL & DMAABORT) == 0)
94                 nop();
95 }
96 #else
97 void mw_bt_uart_tx(const void *buf, const unsigned int len)
98 {
99         unsigned int pos;
100         // char txstr[8];
101
102         pos = 0;
103         // debug_uart_tx("BT tx: ");
104         while (pos < len) {
105                 while ((BT_IO_PIN & BT_IO_CTS)) // wait for CTS to go low
106                         nop();
107
108                 UCA1TXBUF = *(unsigned char *) (buf+pos);
109                 // debug_uart_tx_char(*(unsigned char *) (buf+pos));
110                 // snprintf(txstr, 8, "0x%02x ", *(unsigned char *) (buf+pos));
111                 // debug_uart_tx(txstr);
112                 pos++;
113                 while ((UCA1IFG & UCTXIFG) == 0)
114                         nop();
115         }
116         while (UCA1STAT & UCBUSY)
117                 nop();
118         // debug_uart_tx("\n");
119 }
120 #endif
121
122 static void load_cc256x_init_script(void)
123 {
124         uint32_t pos;
125         unsigned char *tptr;
126
127         pos = 0;
128         while (pos < cc256x_init_script_size) {
129                 if (_event_src != 0)
130                         handle_event();
131                 tptr = (unsigned char *)(cc256x_init_script + pos);
132                 mw_bt_uart_tx(tptr, 4 + tptr[3]);
133                 pos += 4 + tptr[3];
134                 // each init script part is one HCI command so wait for reply
135                 if (_event_src != 0)
136                         handle_event();
137         }
138 }
139
140 void mw_enable_bt(void)
141 {
142         int i;
143
144         /* make sure it resets */
145         BT_SHUTDOWN();
146
147         /* enable 32kHz ACLK output to BT module */
148         P11DIR |= BIT0;
149         P11SEL |= BIT0;
150
151         // wait for clock to stabilize
152         __delay_cycles(16000);
153
154         BT_IO_PDIR &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
155         BT_IO_PDIR |= BT_IO_RTS;
156         BT_IO_POUT &= ~(BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
157         BT_IO_POUT &= ~BT_IO_RTS; // low == ready, high == !ready
158
159         /* setup UART pins */
160         BT_UART_PSEL |= BT_UART_TX_PIN | BT_UART_RX_PIN;
161         // P5OUT |= BT_UART_TX_PIN | BT_UART_RX_PIN;
162         // P5REN |= BT_UART_TX_PIN | BT_UART_RX_PIN;
163
164         mw_init_bt_uart(BT_UART_BD115200);
165
166         /* release BT reset pin */
167         BT_ENABLE();
168
169         for (i=0; i<1000; i++) {
170                 __delay_cycles(16000);
171                 if ((BT_IO_PIN & BT_IO_CTS) == 0) // when CTS goes low module is ready
172                         break;
173         }
174         if (i>=1000) {
175                 debug_uart_tx("Timeout waiting for CC256x to lower CTS\n");
176         } else {
177                 debug_uart_tx("CC256x CTS low - uploading init\n");
178                 for (i=0; i<100; i++) {
179                         __delay_cycles(16000); // give it some more before anyone sends data
180                 }
181                 load_cc256x_init_script();
182                 debug_uart_tx("init uploaded\n");
183         }
184         P1IE &= ~BT_IO_CTS;
185         P1IES &= ~BT_IO_CTS;
186         bt_hci_init();
187         init_l2cap();
188         mw_bt_enabled = 1;
189 }
190
191 #pragma vector=PORT1_VECTOR
192 __interrupt void BT_CTS_ISR (void)
193 {
194         P1IFG &= ~BT_IO_CTS;
195
196         debug_uart_tx("BTS CTS triggered\n");
197         bt_hci_ehcill_wake();
198
199         LPM3_EXIT;
200 }
201
202 void mw_disable_bt(void)
203 {
204         mw_bt_enabled = 0;
205
206         /* disable UART RX interrupt */
207         UCA1IE &= ~UCRXIE;
208
209         /* disable UART pins */
210         BT_UART_PSEL &= ~(BT_UART_TX_PIN | BT_UART_RX_PIN);
211
212         /* set BT reset pin */
213         BT_SHUTDOWN();
214
215         /* disable 32kHz ACLK output to BT module */
216         P11DIR &= ~BIT0;
217         P11SEL &= ~BIT0;
218
219         /* make all I/O Pins inputs so we do not drive against a "deaf" module */
220         BT_IO_PDIR &= ~(BT_IO_RTS | BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
221         BT_IO_POUT &= ~(BT_IO_RTS | BT_IO_CTS | BT_IO_PIN1 | BT_IO_PIN2 | BT_IO_CLKREQ);
222 }
223
224 uint8_t mw_bt_is_enabled(void)
225 {
226         return mw_bt_enabled;
227 }
228