1 /**
2 * Arduino + Energia Wrapper for BTstack
3 */
4
5 #if !defined(ARDUINO)
6 #error "Not compiling for Arduino/Energia"
7 #endif
8
9 #include <Arduino.h>
10 #ifdef ENERGIA
11 #include <Energia.h>
12 #endif
13 #include <SPI.h>
14
15 #include "hal_uart_dma.h"
16
17 #define HAVE_SHUTDOWN
18
19 #ifdef ENERGIA
20
21 // CMM 9301 Configuration for TI Launchpad
22 #define PIN_SPI_SCK 7
23 #define PIN_CS 8
24 #define PIN_SHUTDOWN 11
25 #define PIN_IRQ_DATA 13
26 #define PIN_SPI_MISO 14
27 #define PIN_SPI_MOSI 15
28 #else // ARDUINO
29
30 // CMM 9301 Configuration for Arduino
31 #define PIN_IRQ_DATA 2
32 #define PIN_CS 4
33 #define PIN_SHUTDOWN 5
34
35 // -- SPI defines for Arduino Mega
36 #ifndef PIN_SPI_MISO
37 #define PIN_SPI_MISO 50
38 #endif
39 #ifndef PIN_SPI_MOSI
40 #define PIN_SPI_MOSI 51
41 #endif
42 #ifndef PIN_SPI_SCK
43 #define PIN_SPI_SCK 52
44 #endif
45
46 #endif
47
48 // rx state
49 static uint16_t bytes_to_read = 0;
50 static uint8_t * rx_buffer_ptr = 0;
51
52 // tx state
53 static uint16_t bytes_to_write = 0;
54 static uint8_t * tx_buffer_ptr = 0;
55
56 // handlers
dummy_handler(void)57 static void dummy_handler(void){};
58 static void (*rx_done_handler)(void) = dummy_handler;
59 static void (*tx_done_handler)(void) = dummy_handler;
60
bt_setup(void)61 static void bt_setup(void){
62 pinMode(PIN_CS, OUTPUT);
63 pinMode(PIN_SPI_MOSI, OUTPUT);
64 pinMode(PIN_SPI_SCK, OUTPUT);
65 pinMode(PIN_SHUTDOWN, OUTPUT);
66 pinMode(PIN_IRQ_DATA, INPUT);
67
68 digitalWrite(PIN_CS, HIGH);
69 digitalWrite(PIN_SPI_MOSI, LOW);
70 digitalWrite(PIN_SHUTDOWN, HIGH);
71
72 // SPI settings are reset in SPI.begin() - calls hang on Arduino Zero, too.
73 // SPI.setBitOrder(MSBFIRST);
74 // SPI.setDataMode(SPI_MODE0);
75 // SPI.end();
76 }
77
78 #ifdef HAVE_SHUTDOWN
bt_power_cycle(void)79 static void bt_power_cycle(void){
80
81 // power cycle. set CPU outputs to input to not power EM9301 via IOs
82 // pinMode(PIN_SPI_MOSI, INPUT);
83 // pinMode(PIN_CS, INPUT);
84 pinMode(PIN_CS, OUTPUT);
85 pinMode(PIN_SPI_MOSI, OUTPUT);
86 pinMode(PIN_SPI_SCK, OUTPUT);
87 pinMode(PIN_SHUTDOWN, OUTPUT);
88 digitalWrite(PIN_CS, LOW);
89 digitalWrite(PIN_SPI_MOSI, LOW);
90 digitalWrite(PIN_SPI_SCK, LOW);
91 digitalWrite(PIN_SHUTDOWN, HIGH);
92 delay(500);
93
94 pinMode(PIN_SPI_MOSI, OUTPUT);
95 pinMode(PIN_CS, OUTPUT);
96 digitalWrite(PIN_SPI_MOSI, LOW);
97 digitalWrite(PIN_CS, HIGH);
98 digitalWrite(PIN_SHUTDOWN, LOW);
99 delay(1000);
100 }
101 #endif
102
103 #ifndef HAVE_SHUTDOWN
bt_send_illegal(void)104 static void bt_send_illegal(void){
105 digitalWrite(PIN_SPI_MOSI, HIGH);
106 digitalWrite(PIN_CS, LOW);
107 printf("Illegal start\n");
108 SPI.begin();
109 int i;
110 for (i=0;i<255;i++){
111 SPI.transfer(0xff);
112 printf(".");
113 }
114 SPI.end();
115 printf("\nIllegal stop\n");
116 digitalWrite(PIN_CS, HIGH);
117 }
118
bt_flush_input(void)119 static void bt_flush_input(void){
120 digitalWrite(PIN_SPI_MOSI, LOW);
121 digitalWrite(PIN_CS, LOW);
122 SPI.begin();
123 while (digitalRead(PIN_IRQ_DATA) == HIGH){
124 SPI.transfer(0x00);
125 }
126 SPI.end();
127 digitalWrite(PIN_CS, HIGH);
128 }
129
bt_send_reset(void)130 static void bt_send_reset(void){
131 digitalWrite(PIN_SPI_MOSI, HIGH);
132 digitalWrite(PIN_CS, LOW);
133 SPI.begin();
134 SPI.transfer(0x01);
135 SPI.transfer(0x03);
136 SPI.transfer(0x0c);
137 SPI.transfer(0x00);
138 SPI.end();
139 digitalWrite(PIN_CS, HIGH);
140 }
141 #endif
142
143
bt_try_send(void)144 static void bt_try_send(void){
145
146 if (!bytes_to_write) return;
147
148 // activate module
149 pinMode(PIN_SPI_MOSI, OUTPUT);
150 digitalWrite(PIN_SPI_MOSI, HIGH);
151 digitalWrite(PIN_CS, LOW);
152
153 // module ready
154 int tx_done = 0;
155 if (digitalRead(PIN_SPI_MISO) == HIGH){
156 // printf("Sending: ");
157
158 SPI.begin();
159 while (bytes_to_write){
160 // printf("%02x ", *tx_buffer_ptr);
161 SPI.transfer(*tx_buffer_ptr);
162 tx_buffer_ptr++;
163 bytes_to_write--;
164 }
165 SPI.end();
166 // printf(".\n");
167 tx_done = 1;
168 }
169
170 // deactivate module
171 digitalWrite(PIN_CS, HIGH);
172 digitalWrite(PIN_SPI_MOSI, LOW);
173 pinMode(PIN_SPI_MOSI, OUTPUT);
174
175 // notify upper layer
176 if (tx_done) {
177 (*tx_done_handler)();
178 }
179 }
180
bt_try_read(void)181 static int bt_try_read(void){
182
183 // check if data available and buffer is ready
184 if (digitalRead(PIN_IRQ_DATA) == LOW) return 0;
185 if (bytes_to_read == 0) return 0;
186
187 int num_bytes_read = 0;
188
189 // printf("Reading (%u): ", bytes_to_read);
190
191 // activate module
192 digitalWrite(PIN_SPI_MOSI, LOW);
193 digitalWrite(PIN_CS, LOW);
194 SPI.begin();
195 do {
196 uint8_t byte_read = SPI.transfer(0x00);
197 // printf("%02x ", byte_read);
198 *rx_buffer_ptr = byte_read;
199 rx_buffer_ptr++;
200 bytes_to_read--;
201 num_bytes_read++;
202 } while (bytes_to_read > 0);
203 SPI.end();
204 digitalWrite(PIN_CS, HIGH);
205
206 // printf("\n");
207
208 // notify upper layer
209 (*rx_done_handler)();
210
211 return num_bytes_read;
212 }
213
hal_uart_dma_init(void)214 extern "C" void hal_uart_dma_init(void){
215 bt_setup();
216
217 #ifdef HAVE_SHUTDOWN
218 bt_power_cycle();
219 #else
220 // bring EM9301 into defined state
221 bt_send_illegal();
222 bt_send_reset();
223 bt_flush_input();
224 #endif
225 }
226
hal_uart_dma_set_block_received(void (* block_handler)(void))227 extern "C" void hal_uart_dma_set_block_received( void (*block_handler)(void)){
228 rx_done_handler = block_handler;
229 }
hal_uart_dma_set_block_sent(void (* block_handler)(void))230 extern "C" void hal_uart_dma_set_block_sent( void (*block_handler)(void)){
231 tx_done_handler = block_handler;
232 }
233
hal_uart_dma_set_csr_irq_handler(void (* csr_irq_handler)(void))234 extern "C" void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){
235 // only used for eHCILL
236 }
237
hal_uart_dma_set_baud(uint32_t baud)238 extern "C" int hal_uart_dma_set_baud(uint32_t baud){
239 return 0;
240 }
241
hal_uart_dma_send_block(const uint8_t * buffer,uint16_t length)242 extern "C" void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
243 // printf("send_block, bytes %u\n", length);
244 tx_buffer_ptr = (uint8_t *) buffer;
245 bytes_to_write = length;
246 }
247
hal_uart_dma_receive_block(uint8_t * buffer,uint16_t length)248 extern "C" void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t length){
249 rx_buffer_ptr = buffer;
250 bytes_to_read = length;
251 }
252
hal_uart_dma_set_sleep(uint8_t sleep)253 extern "C" void hal_uart_dma_set_sleep(uint8_t sleep){
254 // not needed for SPI (doesn't need internal clock to work)
255 }
256
hal_uart_dma_process(void)257 extern "C" void hal_uart_dma_process(void){
258 int num_bytes_read = bt_try_read();
259 if (num_bytes_read == 0){
260 bt_try_send();
261 }
262 }
263
hal_time_ms(void)264 extern "C" uint32_t hal_time_ms(void){
265 return millis();
266 }
267
268