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