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 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 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 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 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 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 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 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 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 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 227 extern "C" void hal_uart_dma_set_block_received( void (*block_handler)(void)){ 228 rx_done_handler = block_handler; 229 } 230 extern "C" void hal_uart_dma_set_block_sent( void (*block_handler)(void)){ 231 tx_done_handler = block_handler; 232 } 233 234 extern "C" void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){ 235 // only used for eHCILL 236 } 237 238 extern "C" int hal_uart_dma_set_baud(uint32_t baud){ 239 return 0; 240 } 241 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 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 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 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 264 extern "C" uint32_t hal_time_ms(void){ 265 return millis(); 266 } 267 268