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