xref: /btstack/src/hci_transport_em9304_spi.c (revision f2e99339cd73629ce3de93235db60523402eb6d5)
1161a5569SMatthias Ringwald /*
2161a5569SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3161a5569SMatthias Ringwald  *
4161a5569SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5161a5569SMatthias Ringwald  * modification, are permitted provided that the following conditions
6161a5569SMatthias Ringwald  * are met:
7161a5569SMatthias Ringwald  *
8161a5569SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9161a5569SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10161a5569SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11161a5569SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12161a5569SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13161a5569SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14161a5569SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15161a5569SMatthias Ringwald  *    from this software without specific prior written permission.
16161a5569SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17161a5569SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18161a5569SMatthias Ringwald  *    monetary gain.
19161a5569SMatthias Ringwald  *
20161a5569SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21161a5569SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22161a5569SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23161a5569SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24161a5569SMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25161a5569SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26161a5569SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27161a5569SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28161a5569SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29161a5569SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30161a5569SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31161a5569SMatthias Ringwald  * SUCH DAMAGE.
32161a5569SMatthias Ringwald  *
33161a5569SMatthias Ringwald  * Please inquire about commercial licensing options at
34161a5569SMatthias Ringwald  * [email protected]
35161a5569SMatthias Ringwald  *
36161a5569SMatthias Ringwald  */
37161a5569SMatthias Ringwald 
38161a5569SMatthias Ringwald #define __BTSTACK_FILE__ "hci_transport_em9304_spi.c"
39161a5569SMatthias Ringwald 
40161a5569SMatthias Ringwald #include "btstack_config.h"
41161a5569SMatthias Ringwald #include "btstack_em9304_spi.h"
42161a5569SMatthias Ringwald 
43161a5569SMatthias Ringwald // EM9304 SPI Driver
44161a5569SMatthias Ringwald static const btstack_em9304_spi_t * btstack_em9304_spi;
45161a5569SMatthias Ringwald 
46161a5569SMatthias Ringwald /////////////////////////
47161a5569SMatthias Ringwald // em9304 engine
48161a5569SMatthias Ringwald #include "btstack_ring_buffer.h"
49161a5569SMatthias Ringwald #include "btstack_debug.h"
50161a5569SMatthias Ringwald #include "btstack_util.h"
51161a5569SMatthias Ringwald #include "hci.h"
52161a5569SMatthias Ringwald #include "hci_transport.h"
53161a5569SMatthias Ringwald 
54161a5569SMatthias Ringwald static void em9304_spi_engine_process(void);
55161a5569SMatthias Ringwald 
56161a5569SMatthias Ringwald #define STS_SLAVE_READY 0xc0
57161a5569SMatthias Ringwald 
58161a5569SMatthias Ringwald #define EM9304_SPI_HEADER_TX        0x42
59161a5569SMatthias Ringwald #define EM9304_SPI_HEADER_RX        0x81
60161a5569SMatthias Ringwald 
61161a5569SMatthias Ringwald #define SPI_EM9304_RX_BUFFER_SIZE     64
62161a5569SMatthias Ringwald #define SPI_EM9304_TX_BUFFER_SIZE     64
63161a5569SMatthias Ringwald #define SPI_EM9304_RING_BUFFER_SIZE  128
64161a5569SMatthias Ringwald 
65161a5569SMatthias Ringwald // state
66161a5569SMatthias Ringwald static volatile enum {
67161a5569SMatthias Ringwald     SPI_EM9304_IDLE,
68161a5569SMatthias Ringwald     SPI_EM9304_RX_W4_READ_COMMAND_SENT,
69161a5569SMatthias Ringwald     SPI_EM9304_RX_READ_COMMAND_SENT,
70161a5569SMatthias Ringwald     SPI_EM9304_RX_W4_STS2_RECEIVED,
71161a5569SMatthias Ringwald     SPI_EM9304_RX_STS2_RECEIVED,
72161a5569SMatthias Ringwald     SPI_EM9304_RX_W4_DATA_RECEIVED,
73161a5569SMatthias Ringwald     SPI_EM9304_RX_DATA_RECEIVED,
74161a5569SMatthias Ringwald     SPI_EM9304_TX_W4_RDY,
75161a5569SMatthias Ringwald     SPI_EM9304_TX_W4_WRITE_COMMAND_SENT,
76161a5569SMatthias Ringwald     SPI_EM9304_TX_WRITE_COMMAND_SENT,
77161a5569SMatthias Ringwald     SPI_EM9304_TX_W4_STS2_RECEIVED,
78161a5569SMatthias Ringwald     SPI_EM9304_TX_STS2_RECEIVED,
79161a5569SMatthias Ringwald     SPI_EM9304_TX_W4_DATA_SENT,
80161a5569SMatthias Ringwald     SPI_EM9304_TX_DATA_SENT,
81161a5569SMatthias Ringwald } em9304_spi_engine_state;
82161a5569SMatthias Ringwald 
83161a5569SMatthias Ringwald static uint16_t em9304_spi_engine_rx_request_len;
84161a5569SMatthias Ringwald static uint16_t em9304_spi_engine_tx_request_len;
85161a5569SMatthias Ringwald 
86161a5569SMatthias Ringwald static btstack_ring_buffer_t em9304_spi_engine_rx_ring_buffer;
87161a5569SMatthias Ringwald static uint8_t em9304_spi_engine_rx_ring_buffer_storage[SPI_EM9304_RING_BUFFER_SIZE];
88161a5569SMatthias Ringwald 
89161a5569SMatthias Ringwald static const uint8_t  * em9304_spi_engine_tx_data;
90161a5569SMatthias Ringwald static uint16_t         em9304_spi_engine_tx_size;
91161a5569SMatthias Ringwald 
92161a5569SMatthias Ringwald // handlers
93*f2e99339SMatthias Ringwald static void (*em9304_spi_engine_rx_available_handler)(void);
94161a5569SMatthias Ringwald static void (*em9304_spi_engine_tx_done_handler)(void);
95161a5569SMatthias Ringwald 
96161a5569SMatthias Ringwald // TODO: get rid of alignment requirement
97161a5569SMatthias Ringwald union {
98161a5569SMatthias Ringwald     uint32_t words[1];
99161a5569SMatthias Ringwald     uint8_t  bytes[1];
100161a5569SMatthias Ringwald } sCommand;
101161a5569SMatthias Ringwald 
102161a5569SMatthias Ringwald union {
103161a5569SMatthias Ringwald     uint32_t words[1];
104161a5569SMatthias Ringwald     uint8_t  bytes[1];
105161a5569SMatthias Ringwald } sStas;
106161a5569SMatthias Ringwald 
107161a5569SMatthias Ringwald union {
108161a5569SMatthias Ringwald     uint32_t words[SPI_EM9304_RX_BUFFER_SIZE/4];
109161a5569SMatthias Ringwald     uint8_t  bytes[SPI_EM9304_RX_BUFFER_SIZE];
110161a5569SMatthias Ringwald } em9304_spi_engine_spi_rx_buffer;
111161a5569SMatthias Ringwald 
112161a5569SMatthias Ringwald static void em9304_spi_engine_ready_callback(void){
113161a5569SMatthias Ringwald     em9304_spi_engine_process();
114161a5569SMatthias Ringwald }
115161a5569SMatthias Ringwald 
116161a5569SMatthias Ringwald static void em9304_spi_engine_transfer_done(void){
117161a5569SMatthias Ringwald     switch (em9304_spi_engine_state){
118161a5569SMatthias Ringwald         case SPI_EM9304_RX_W4_READ_COMMAND_SENT:
119161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_READ_COMMAND_SENT;
120161a5569SMatthias Ringwald             break;
121161a5569SMatthias Ringwald         case SPI_EM9304_RX_W4_STS2_RECEIVED:
122161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_STS2_RECEIVED;
123161a5569SMatthias Ringwald             break;
124161a5569SMatthias Ringwald         case SPI_EM9304_RX_W4_DATA_RECEIVED:
125161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_DATA_RECEIVED;
126161a5569SMatthias Ringwald             break;
127161a5569SMatthias Ringwald         case SPI_EM9304_TX_W4_WRITE_COMMAND_SENT:
128161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_WRITE_COMMAND_SENT;
129161a5569SMatthias Ringwald             break;
130161a5569SMatthias Ringwald         case SPI_EM9304_TX_W4_STS2_RECEIVED:
131161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_STS2_RECEIVED;
132161a5569SMatthias Ringwald             break;
133161a5569SMatthias Ringwald         case SPI_EM9304_TX_W4_DATA_SENT:
134161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_DATA_SENT;
135161a5569SMatthias Ringwald             break;
136161a5569SMatthias Ringwald         default:
137161a5569SMatthias Ringwald             return;
138161a5569SMatthias Ringwald     }
139161a5569SMatthias Ringwald     em9304_spi_engine_process();
140161a5569SMatthias Ringwald }
141161a5569SMatthias Ringwald 
142161a5569SMatthias Ringwald static void em9304_spi_engine_start_tx_transaction(void){
143161a5569SMatthias Ringwald     // state = wait for RDY
144161a5569SMatthias Ringwald     em9304_spi_engine_state = SPI_EM9304_TX_W4_RDY;
145161a5569SMatthias Ringwald 
146161a5569SMatthias Ringwald     // chip select
147161a5569SMatthias Ringwald     btstack_em9304_spi->set_chip_select(1);
148161a5569SMatthias Ringwald 
149161a5569SMatthias Ringwald     // enable IRQ
150161a5569SMatthias Ringwald     btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
151161a5569SMatthias Ringwald }
152161a5569SMatthias Ringwald 
153*f2e99339SMatthias Ringwald static inline int em9304_engine_space_in_rx_buffer(void){
154*f2e99339SMatthias Ringwald     return btstack_ring_buffer_bytes_free(&em9304_spi_engine_rx_ring_buffer) >= SPI_EM9304_RX_BUFFER_SIZE;
155*f2e99339SMatthias Ringwald }
156161a5569SMatthias Ringwald 
157*f2e99339SMatthias Ringwald static void em9304_engine_idle(void){
158*f2e99339SMatthias Ringwald 
159*f2e99339SMatthias Ringwald     if (em9304_spi_engine_state != SPI_EM9304_IDLE) return;
160*f2e99339SMatthias Ringwald 
161161a5569SMatthias Ringwald     if (btstack_em9304_spi->get_ready()){
162161a5569SMatthias Ringwald         // RDY -> data available
163*f2e99339SMatthias Ringwald         if (em9304_engine_space_in_rx_buffer()) {
164161a5569SMatthias Ringwald             // disable interrupt again
165161a5569SMatthias Ringwald             btstack_em9304_spi->set_ready_callback(NULL);
166*f2e99339SMatthias Ringwald 
167161a5569SMatthias Ringwald             // enable chip select
168161a5569SMatthias Ringwald             btstack_em9304_spi->set_chip_select(1);
169161a5569SMatthias Ringwald 
170161a5569SMatthias Ringwald             // send read command
171161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_W4_READ_COMMAND_SENT;
172161a5569SMatthias Ringwald             sCommand.bytes[0] = EM9304_SPI_HEADER_RX;
173161a5569SMatthias Ringwald             btstack_em9304_spi->transmit(sCommand.bytes, 1);
174161a5569SMatthias Ringwald         }
175161a5569SMatthias Ringwald     } else if (em9304_spi_engine_tx_size){
176*f2e99339SMatthias Ringwald         // start TX
177161a5569SMatthias Ringwald         em9304_spi_engine_start_tx_transaction();
178*f2e99339SMatthias Ringwald 
179*f2e99339SMatthias Ringwald     } else if (em9304_engine_space_in_rx_buffer()){
180*f2e99339SMatthias Ringwald         // no data ready for receive or transmit, but space in rx ringbuffer  -> enable READY IRQ
181161a5569SMatthias Ringwald         btstack_em9304_spi->set_ready_callback(&em9304_spi_engine_ready_callback);
182161a5569SMatthias Ringwald     }
183*f2e99339SMatthias Ringwald }
184*f2e99339SMatthias Ringwald 
185*f2e99339SMatthias Ringwald static void em9304_spi_engine_process(void){
186*f2e99339SMatthias Ringwald     uint16_t max_bytes_to_send;
187*f2e99339SMatthias Ringwald 
188*f2e99339SMatthias Ringwald     switch (em9304_spi_engine_state){
189*f2e99339SMatthias Ringwald         case SPI_EM9304_IDLE:
190*f2e99339SMatthias Ringwald             em9304_engine_idle();
191161a5569SMatthias Ringwald             break;
192161a5569SMatthias Ringwald 
193161a5569SMatthias Ringwald         case SPI_EM9304_RX_READ_COMMAND_SENT:
194161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_W4_STS2_RECEIVED;
195161a5569SMatthias Ringwald             btstack_em9304_spi->receive(sStas.bytes, 1);
196161a5569SMatthias Ringwald             break;
197161a5569SMatthias Ringwald 
198161a5569SMatthias Ringwald         case SPI_EM9304_RX_STS2_RECEIVED:
199161a5569SMatthias Ringwald             // check slave status
200161a5569SMatthias Ringwald             log_debug("RX: STS2 0x%02X", sStas.bytes[0]);
201161a5569SMatthias Ringwald 
202161a5569SMatthias Ringwald             // read data and send '0's
203161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_RX_W4_DATA_RECEIVED;
204161a5569SMatthias Ringwald             em9304_spi_engine_rx_request_len = sStas.bytes[0];
205161a5569SMatthias Ringwald             btstack_em9304_spi->receive(em9304_spi_engine_spi_rx_buffer.bytes, em9304_spi_engine_rx_request_len);
206161a5569SMatthias Ringwald             break;
207161a5569SMatthias Ringwald 
208161a5569SMatthias Ringwald         case SPI_EM9304_RX_DATA_RECEIVED:
209161a5569SMatthias Ringwald 
210161a5569SMatthias Ringwald             // chip deselect & done
211161a5569SMatthias Ringwald             btstack_em9304_spi->set_chip_select(0);
212161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_IDLE;
213161a5569SMatthias Ringwald 
214161a5569SMatthias Ringwald             // move data into ring buffer
215161a5569SMatthias Ringwald             btstack_ring_buffer_write(&em9304_spi_engine_rx_ring_buffer, em9304_spi_engine_spi_rx_buffer.bytes, em9304_spi_engine_rx_request_len);
216161a5569SMatthias Ringwald             em9304_spi_engine_rx_request_len = 0;
217161a5569SMatthias Ringwald 
218161a5569SMatthias Ringwald             // deliver new data
219*f2e99339SMatthias Ringwald             (*em9304_spi_engine_rx_available_handler)();
220*f2e99339SMatthias Ringwald 
221*f2e99339SMatthias Ringwald             // idle, look for more work
222*f2e99339SMatthias Ringwald             em9304_engine_idle();
223161a5569SMatthias Ringwald             break;
224161a5569SMatthias Ringwald 
225161a5569SMatthias Ringwald         case SPI_EM9304_TX_W4_RDY:
226161a5569SMatthias Ringwald             // check if ready
227161a5569SMatthias Ringwald             if (!btstack_em9304_spi->get_ready()) break;
228161a5569SMatthias Ringwald 
229161a5569SMatthias Ringwald             // disable interrupt again
230161a5569SMatthias Ringwald             btstack_em9304_spi->set_ready_callback(NULL);
231161a5569SMatthias Ringwald 
232161a5569SMatthias Ringwald             // send write command
233161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_W4_WRITE_COMMAND_SENT;
234161a5569SMatthias Ringwald             sCommand.bytes[0] = EM9304_SPI_HEADER_TX;
235161a5569SMatthias Ringwald             btstack_em9304_spi->transmit(sCommand.bytes, 1);
236161a5569SMatthias Ringwald             break;
237161a5569SMatthias Ringwald 
238161a5569SMatthias Ringwald         case SPI_EM9304_TX_WRITE_COMMAND_SENT:
239161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_W4_STS2_RECEIVED;
240161a5569SMatthias Ringwald             btstack_em9304_spi->receive(sStas.bytes, 1);
241161a5569SMatthias Ringwald             break;
242161a5569SMatthias Ringwald 
243161a5569SMatthias Ringwald         case SPI_EM9304_TX_STS2_RECEIVED:
244161a5569SMatthias Ringwald             // check slave status and em9304 rx buffer space
245161a5569SMatthias Ringwald             log_debug("TX: STS2 0x%02X", sStas.bytes[0]);
246161a5569SMatthias Ringwald             max_bytes_to_send = sStas.bytes[0];
247161a5569SMatthias Ringwald             if (max_bytes_to_send == 0){
248161a5569SMatthias Ringwald                 // chip deselect & retry
249161a5569SMatthias Ringwald                 btstack_em9304_spi->set_chip_select(0);
250161a5569SMatthias Ringwald                 em9304_spi_engine_state = SPI_EM9304_IDLE;
251161a5569SMatthias Ringwald                 break;
252161a5569SMatthias Ringwald             }
253161a5569SMatthias Ringwald 
254161a5569SMatthias Ringwald             // number bytes to send
255161a5569SMatthias Ringwald             em9304_spi_engine_tx_request_len = btstack_min(em9304_spi_engine_tx_size, max_bytes_to_send);
256161a5569SMatthias Ringwald 
257161a5569SMatthias Ringwald             // send command
258161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_TX_W4_DATA_SENT;
259161a5569SMatthias Ringwald             btstack_em9304_spi->transmit( (uint8_t*) em9304_spi_engine_tx_data, em9304_spi_engine_tx_request_len);
260161a5569SMatthias Ringwald             break;
261161a5569SMatthias Ringwald 
262161a5569SMatthias Ringwald         case SPI_EM9304_TX_DATA_SENT:
263161a5569SMatthias Ringwald 
264161a5569SMatthias Ringwald             // chip deselect & done
265161a5569SMatthias Ringwald             btstack_em9304_spi->set_chip_select(0);
266161a5569SMatthias Ringwald             em9304_spi_engine_state = SPI_EM9304_IDLE;
267161a5569SMatthias Ringwald 
268161a5569SMatthias Ringwald             // chunk processed
269161a5569SMatthias Ringwald             em9304_spi_engine_tx_size -= em9304_spi_engine_tx_request_len;
270161a5569SMatthias Ringwald             em9304_spi_engine_tx_data += em9304_spi_engine_tx_request_len;
271161a5569SMatthias Ringwald             em9304_spi_engine_tx_request_len = 0;
272161a5569SMatthias Ringwald 
273161a5569SMatthias Ringwald             // handle TX Complete
274161a5569SMatthias Ringwald             if (em9304_spi_engine_tx_size){
275161a5569SMatthias Ringwald                 // more data to send
276161a5569SMatthias Ringwald                 em9304_spi_engine_start_tx_transaction();
277161a5569SMatthias Ringwald             } else {
278161a5569SMatthias Ringwald                 // notify higher layer
279161a5569SMatthias Ringwald                 (*em9304_spi_engine_tx_done_handler)();
280161a5569SMatthias Ringwald 
281*f2e99339SMatthias Ringwald                 // idle, look for more work
282*f2e99339SMatthias Ringwald                 em9304_engine_idle();
283161a5569SMatthias Ringwald             }
284161a5569SMatthias Ringwald             break;
285161a5569SMatthias Ringwald 
286161a5569SMatthias Ringwald         default:
287161a5569SMatthias Ringwald             break;
288161a5569SMatthias Ringwald     }
289161a5569SMatthias Ringwald }
290161a5569SMatthias Ringwald 
291161a5569SMatthias Ringwald static void em9304_spi_engine_init(void){
292161a5569SMatthias Ringwald     btstack_em9304_spi->open();
293161a5569SMatthias Ringwald     btstack_em9304_spi->set_transfer_done_callback(&em9304_spi_engine_transfer_done);
294161a5569SMatthias Ringwald     btstack_ring_buffer_init(&em9304_spi_engine_rx_ring_buffer, &em9304_spi_engine_rx_ring_buffer_storage[0], SPI_EM9304_RING_BUFFER_SIZE);
295161a5569SMatthias Ringwald }
296161a5569SMatthias Ringwald 
297161a5569SMatthias Ringwald static void em9304_spi_engine_close(void){
298161a5569SMatthias Ringwald     btstack_em9304_spi->close();
299161a5569SMatthias Ringwald }
300161a5569SMatthias Ringwald 
301*f2e99339SMatthias Ringwald static void em9304_spi_engine_set_data_available( void (*the_block_handler)(void)){
302*f2e99339SMatthias Ringwald     em9304_spi_engine_rx_available_handler = the_block_handler;
303161a5569SMatthias Ringwald }
304161a5569SMatthias Ringwald 
305161a5569SMatthias Ringwald static void em9304_spi_engine_set_block_sent( void (*the_block_handler)(void)){
306161a5569SMatthias Ringwald     em9304_spi_engine_tx_done_handler = the_block_handler;
307161a5569SMatthias Ringwald }
308161a5569SMatthias Ringwald 
309161a5569SMatthias Ringwald static void em9304_spi_engine_send_block(const uint8_t *buffer, uint16_t length){
310161a5569SMatthias Ringwald     em9304_spi_engine_tx_data = buffer;
311161a5569SMatthias Ringwald     em9304_spi_engine_tx_size = length;
312161a5569SMatthias Ringwald     em9304_spi_engine_process();
313161a5569SMatthias Ringwald }
314161a5569SMatthias Ringwald 
315*f2e99339SMatthias Ringwald static int em9304_engine_num_bytes_available(void){
316*f2e99339SMatthias Ringwald     return btstack_ring_buffer_bytes_available(&em9304_spi_engine_rx_ring_buffer);
317161a5569SMatthias Ringwald }
318161a5569SMatthias Ringwald 
319*f2e99339SMatthias Ringwald static void em9304_engine_get_bytes(uint8_t * buffer, uint16_t num_bytes){
320*f2e99339SMatthias Ringwald     uint32_t bytes_read;
321*f2e99339SMatthias Ringwald     btstack_ring_buffer_read(&em9304_spi_engine_rx_ring_buffer, buffer, num_bytes, &bytes_read);
322*f2e99339SMatthias Ringwald }
323*f2e99339SMatthias Ringwald 
324*f2e99339SMatthias Ringwald 
325161a5569SMatthias Ringwald //////////////////////////////////////////////////////////////////////////////
326161a5569SMatthias Ringwald 
327161a5569SMatthias Ringwald // assert pre-buffer for packet type is available
328161a5569SMatthias Ringwald #if !defined(HCI_OUTGOING_PRE_BUFFER_SIZE) || (HCI_OUTGOING_PRE_BUFFER_SIZE == 0)
329161a5569SMatthias Ringwald #error HCI_OUTGOING_PRE_BUFFER_SIZE not defined. Please update hci.h
330161a5569SMatthias Ringwald #endif
331161a5569SMatthias Ringwald 
332161a5569SMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size);
333161a5569SMatthias Ringwald 
334161a5569SMatthias Ringwald typedef enum {
335161a5569SMatthias Ringwald     H4_W4_PACKET_TYPE,
336161a5569SMatthias Ringwald     H4_W4_EVENT_HEADER,
337161a5569SMatthias Ringwald     H4_W4_ACL_HEADER,
338161a5569SMatthias Ringwald     H4_W4_PAYLOAD,
339161a5569SMatthias Ringwald } H4_STATE;
340161a5569SMatthias Ringwald 
341161a5569SMatthias Ringwald typedef enum {
342161a5569SMatthias Ringwald     TX_IDLE = 1,
343161a5569SMatthias Ringwald     TX_W4_PACKET_SENT,
344161a5569SMatthias Ringwald } TX_STATE;
345161a5569SMatthias Ringwald 
346161a5569SMatthias Ringwald // write state
347161a5569SMatthias Ringwald static TX_STATE tx_state;
348161a5569SMatthias Ringwald 
349161a5569SMatthias Ringwald static uint8_t packet_sent_event[] = { HCI_EVENT_TRANSPORT_PACKET_SENT, 0};
350161a5569SMatthias Ringwald 
351161a5569SMatthias Ringwald static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size) = dummy_handler;
352161a5569SMatthias Ringwald 
353161a5569SMatthias Ringwald // packet reader state machine
354161a5569SMatthias Ringwald static  H4_STATE h4_state;
355161a5569SMatthias Ringwald static int bytes_to_read;
356161a5569SMatthias Ringwald static int read_pos;
357161a5569SMatthias Ringwald 
358161a5569SMatthias Ringwald // incoming packet buffer
359161a5569SMatthias Ringwald static uint8_t hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE + 1 + HCI_PACKET_BUFFER_SIZE]; // packet type + max(acl header + acl payload, event header + event data)
360161a5569SMatthias Ringwald static uint8_t * hci_packet = &hci_packet_with_pre_buffer[HCI_INCOMING_PRE_BUFFER_SIZE];
361161a5569SMatthias Ringwald 
362*f2e99339SMatthias Ringwald static uint8_t  * hci_transport_em9304_spi_rx_buffer;
363*f2e99339SMatthias Ringwald static uint16_t   hci_transport_em9304_spi_rx_len;
364*f2e99339SMatthias Ringwald 
365*f2e99339SMatthias Ringwald static void hci_transport_em9304_spi_block_read(void);
366*f2e99339SMatthias Ringwald 
367161a5569SMatthias Ringwald static void hci_transport_em9304_spi_reset_statemachine(void){
368161a5569SMatthias Ringwald     h4_state = H4_W4_PACKET_TYPE;
369161a5569SMatthias Ringwald     read_pos = 0;
370161a5569SMatthias Ringwald     bytes_to_read = 1;
371161a5569SMatthias Ringwald }
372161a5569SMatthias Ringwald 
373*f2e99339SMatthias Ringwald static void hci_transport_em9304_spi_process_data(void){
374*f2e99339SMatthias Ringwald     while (1){
375*f2e99339SMatthias Ringwald         int bytes_available = em9304_engine_num_bytes_available();
376*f2e99339SMatthias Ringwald         log_debug("transfer_rx_data: ring buffer has %u -> hci buffer needs %u", bytes_available, hci_transport_em9304_spi_rx_len);
377*f2e99339SMatthias Ringwald 
378*f2e99339SMatthias Ringwald         if (!bytes_available) break;
379*f2e99339SMatthias Ringwald         if (!hci_transport_em9304_spi_rx_len) break;
380*f2e99339SMatthias Ringwald 
381*f2e99339SMatthias Ringwald         int bytes_to_copy = btstack_min(bytes_available, hci_transport_em9304_spi_rx_len);
382*f2e99339SMatthias Ringwald         em9304_engine_get_bytes(hci_transport_em9304_spi_rx_buffer, bytes_to_copy);
383*f2e99339SMatthias Ringwald 
384*f2e99339SMatthias Ringwald         hci_transport_em9304_spi_rx_buffer += bytes_to_copy;
385*f2e99339SMatthias Ringwald         hci_transport_em9304_spi_rx_len    -= bytes_to_copy;
386*f2e99339SMatthias Ringwald 
387*f2e99339SMatthias Ringwald         if (hci_transport_em9304_spi_rx_len == 0){
388*f2e99339SMatthias Ringwald             (*hci_transport_em9304_spi_block_read)();
389*f2e99339SMatthias Ringwald             break;
390*f2e99339SMatthias Ringwald         }
391*f2e99339SMatthias Ringwald     }
392*f2e99339SMatthias Ringwald }
393*f2e99339SMatthias Ringwald 
394*f2e99339SMatthias Ringwald static void em9304_spi_engine_receive_block(uint8_t *buffer, uint16_t length){
395*f2e99339SMatthias Ringwald     log_debug("em9304_spi_engine_receive_block: len %u, ring buffer has %u, UART_RX_LEN %u", length, btstack_ring_buffer_bytes_available(&em9304_spi_engine_rx_ring_buffer), hci_transport_em9304_spi_rx_len);
396*f2e99339SMatthias Ringwald     hci_transport_em9304_spi_rx_buffer = buffer;
397*f2e99339SMatthias Ringwald     hci_transport_em9304_spi_rx_len    = length;
398*f2e99339SMatthias Ringwald     hci_transport_em9304_spi_process_data();
399*f2e99339SMatthias Ringwald     em9304_spi_engine_process();
400*f2e99339SMatthias Ringwald }
401*f2e99339SMatthias Ringwald 
402161a5569SMatthias Ringwald static void hci_transport_em9304_spi_trigger_next_read(void){
403161a5569SMatthias Ringwald     // log_info("hci_transport_em9304_spi_trigger_next_read: %u bytes", bytes_to_read);
404161a5569SMatthias Ringwald     em9304_spi_engine_receive_block(&hci_packet[read_pos], bytes_to_read);
405161a5569SMatthias Ringwald }
406161a5569SMatthias Ringwald 
407161a5569SMatthias Ringwald static void hci_transport_em9304_spi_block_read(void){
408161a5569SMatthias Ringwald 
409161a5569SMatthias Ringwald     read_pos += bytes_to_read;
410161a5569SMatthias Ringwald 
411161a5569SMatthias Ringwald     switch (h4_state) {
412161a5569SMatthias Ringwald         case H4_W4_PACKET_TYPE:
413161a5569SMatthias Ringwald             switch (hci_packet[0]){
414161a5569SMatthias Ringwald                 case HCI_EVENT_PACKET:
415161a5569SMatthias Ringwald                     bytes_to_read = HCI_EVENT_HEADER_SIZE;
416161a5569SMatthias Ringwald                     h4_state = H4_W4_EVENT_HEADER;
417161a5569SMatthias Ringwald                     break;
418161a5569SMatthias Ringwald                 case HCI_ACL_DATA_PACKET:
419161a5569SMatthias Ringwald                     bytes_to_read = HCI_ACL_HEADER_SIZE;
420161a5569SMatthias Ringwald                     h4_state = H4_W4_ACL_HEADER;
421161a5569SMatthias Ringwald                     break;
422161a5569SMatthias Ringwald                 default:
423161a5569SMatthias Ringwald                     log_error("hci_transport_h4: invalid packet type 0x%02x", hci_packet[0]);
424161a5569SMatthias Ringwald                     hci_transport_em9304_spi_reset_statemachine();
425161a5569SMatthias Ringwald                     break;
426161a5569SMatthias Ringwald             }
427161a5569SMatthias Ringwald             break;
428161a5569SMatthias Ringwald 
429161a5569SMatthias Ringwald         case H4_W4_EVENT_HEADER:
430161a5569SMatthias Ringwald             bytes_to_read = hci_packet[2];
431161a5569SMatthias Ringwald             h4_state = H4_W4_PAYLOAD;
432161a5569SMatthias Ringwald             break;
433161a5569SMatthias Ringwald 
434161a5569SMatthias Ringwald         case H4_W4_ACL_HEADER:
435161a5569SMatthias Ringwald             bytes_to_read = little_endian_read_16( hci_packet, 3);
436161a5569SMatthias Ringwald             // check ACL length
437161a5569SMatthias Ringwald             if (HCI_ACL_HEADER_SIZE + bytes_to_read >  HCI_PACKET_BUFFER_SIZE){
438161a5569SMatthias Ringwald                 log_error("hci_transport_h4: invalid ACL payload len %d - only space for %u", bytes_to_read, HCI_PACKET_BUFFER_SIZE - HCI_ACL_HEADER_SIZE);
439161a5569SMatthias Ringwald                 hci_transport_em9304_spi_reset_statemachine();
440161a5569SMatthias Ringwald                 break;
441161a5569SMatthias Ringwald             }
442161a5569SMatthias Ringwald             h4_state = H4_W4_PAYLOAD;
443161a5569SMatthias Ringwald             break;
444161a5569SMatthias Ringwald 
445161a5569SMatthias Ringwald         case H4_W4_PAYLOAD:
446161a5569SMatthias Ringwald             packet_handler(hci_packet[0], &hci_packet[1], read_pos-1);
447161a5569SMatthias Ringwald             hci_transport_em9304_spi_reset_statemachine();
448161a5569SMatthias Ringwald             break;
449161a5569SMatthias Ringwald         default:
450161a5569SMatthias Ringwald             break;
451161a5569SMatthias Ringwald     }
452161a5569SMatthias Ringwald 
453161a5569SMatthias Ringwald     hci_transport_em9304_spi_trigger_next_read();
454161a5569SMatthias Ringwald }
455161a5569SMatthias Ringwald 
456161a5569SMatthias Ringwald static void hci_transport_em9304_spi_block_sent(void){
457161a5569SMatthias Ringwald     switch (tx_state){
458161a5569SMatthias Ringwald         case TX_W4_PACKET_SENT:
459161a5569SMatthias Ringwald             // packet fully sent, reset state
460161a5569SMatthias Ringwald             tx_state = TX_IDLE;
461161a5569SMatthias Ringwald             // notify upper stack that it can send again
462161a5569SMatthias Ringwald             packet_handler(HCI_EVENT_PACKET, &packet_sent_event[0], sizeof(packet_sent_event));
463161a5569SMatthias Ringwald             break;
464161a5569SMatthias Ringwald         default:
465161a5569SMatthias Ringwald             break;
466161a5569SMatthias Ringwald     }
467161a5569SMatthias Ringwald }
468161a5569SMatthias Ringwald 
469161a5569SMatthias Ringwald static int hci_transport_em9304_spi_can_send_now(uint8_t packet_type){
470161a5569SMatthias Ringwald     return tx_state == TX_IDLE;
471161a5569SMatthias Ringwald }
472161a5569SMatthias Ringwald 
473161a5569SMatthias Ringwald static int hci_transport_em9304_spi_send_packet(uint8_t packet_type, uint8_t * packet, int size){
474161a5569SMatthias Ringwald 
475161a5569SMatthias Ringwald     // store packet type before actual data and increase size
476161a5569SMatthias Ringwald     size++;
477161a5569SMatthias Ringwald     packet--;
478161a5569SMatthias Ringwald     *packet = packet_type;
479161a5569SMatthias Ringwald 
480161a5569SMatthias Ringwald     // start sending
481161a5569SMatthias Ringwald     tx_state = TX_W4_PACKET_SENT;
482161a5569SMatthias Ringwald     em9304_spi_engine_send_block(packet, size);
483161a5569SMatthias Ringwald     return 0;
484161a5569SMatthias Ringwald }
485161a5569SMatthias Ringwald 
486161a5569SMatthias Ringwald static void hci_transport_em9304_spi_init(const void * transport_config){
487161a5569SMatthias Ringwald }
488161a5569SMatthias Ringwald 
489161a5569SMatthias Ringwald static int hci_transport_em9304_spi_open(void){
490161a5569SMatthias Ringwald 
491161a5569SMatthias Ringwald     // setup UART driver
492161a5569SMatthias Ringwald     em9304_spi_engine_init();
493*f2e99339SMatthias Ringwald     em9304_spi_engine_set_data_available(&hci_transport_em9304_spi_process_data);
494161a5569SMatthias Ringwald     em9304_spi_engine_set_block_sent(&hci_transport_em9304_spi_block_sent);
495161a5569SMatthias Ringwald     // setup H4 RX
496161a5569SMatthias Ringwald     hci_transport_em9304_spi_reset_statemachine();
497161a5569SMatthias Ringwald     hci_transport_em9304_spi_trigger_next_read();
498161a5569SMatthias Ringwald     // setup H4 TX
499161a5569SMatthias Ringwald     tx_state = TX_IDLE;
500161a5569SMatthias Ringwald     return 0;
501161a5569SMatthias Ringwald }
502161a5569SMatthias Ringwald 
503161a5569SMatthias Ringwald static int hci_transport_em9304_spi_close(void){
504161a5569SMatthias Ringwald     em9304_spi_engine_close();
505161a5569SMatthias Ringwald     return 0;
506161a5569SMatthias Ringwald }
507161a5569SMatthias Ringwald 
508161a5569SMatthias Ringwald static void hci_transport_em9304_spi_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
509161a5569SMatthias Ringwald     packet_handler = handler;
510161a5569SMatthias Ringwald }
511161a5569SMatthias Ringwald 
512161a5569SMatthias Ringwald static void dummy_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
513161a5569SMatthias Ringwald }
514161a5569SMatthias Ringwald 
515161a5569SMatthias Ringwald // --- end of eHCILL implementation ---------
516161a5569SMatthias Ringwald 
517161a5569SMatthias Ringwald static const hci_transport_t hci_transport_em9304_spi = {
518161a5569SMatthias Ringwald     /* const char * name; */                                        "H4",
519161a5569SMatthias Ringwald     /* void   (*init) (const void *transport_config); */            &hci_transport_em9304_spi_init,
520161a5569SMatthias Ringwald     /* int    (*open)(void); */                                     &hci_transport_em9304_spi_open,
521161a5569SMatthias Ringwald     /* int    (*close)(void); */                                    &hci_transport_em9304_spi_close,
522161a5569SMatthias Ringwald     /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_em9304_spi_register_packet_handler,
523161a5569SMatthias Ringwald     /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_em9304_spi_can_send_now,
524161a5569SMatthias Ringwald     /* int    (*send_packet)(...); */                               &hci_transport_em9304_spi_send_packet,
525161a5569SMatthias Ringwald     /* int    (*set_baudrate)(uint32_t baudrate); */                NULL,
526161a5569SMatthias Ringwald     /* void   (*reset_link)(void); */                               NULL,
527161a5569SMatthias Ringwald     /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
528161a5569SMatthias Ringwald };
529161a5569SMatthias Ringwald 
530161a5569SMatthias Ringwald // configure and return h4 singleton
531161a5569SMatthias Ringwald const hci_transport_t * hci_transport_em9304_spi_instance(const btstack_em9304_spi_t * em9304_spi_driver) {
532161a5569SMatthias Ringwald     btstack_em9304_spi = em9304_spi_driver;
533161a5569SMatthias Ringwald     return &hci_transport_em9304_spi;
534161a5569SMatthias Ringwald }
535