Bluetooth UART support for the Adafruit BluefruitLE SPI, for the University of York Engineering Stage 1 project
Adafruit_BluefruitLE_SPI.cpp@2:8c341bac60b8, 2021-03-12 (annotated)
- Committer:
- ajp109
- Date:
- Fri Mar 12 14:33:03 2021 +0000
- Revision:
- 2:8c341bac60b8
- Parent:
- 1:6ff0eee2da9c
Last commit before fork - all working
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
ajp109 | 0:a80552d32b80 | 1 | /**************************************************************************/ |
ajp109 | 0:a80552d32b80 | 2 | /*! |
ajp109 | 0:a80552d32b80 | 3 | @file Adafruit_BluefruitLE_SPI.cpp |
ajp109 | 0:a80552d32b80 | 4 | @author hathach, ktown (Adafruit Industries), ajp109 (University of York) |
ajp109 | 0:a80552d32b80 | 5 | |
ajp109 | 0:a80552d32b80 | 6 | @section LICENSE |
ajp109 | 0:a80552d32b80 | 7 | |
ajp109 | 0:a80552d32b80 | 8 | Software License Agreement (BSD License) |
ajp109 | 0:a80552d32b80 | 9 | |
ajp109 | 0:a80552d32b80 | 10 | Copyright (c) 2015, Adafruit Industries (adafruit.com) |
ajp109 | 0:a80552d32b80 | 11 | All rights reserved. |
ajp109 | 0:a80552d32b80 | 12 | |
ajp109 | 0:a80552d32b80 | 13 | Redistribution and use in source and binary forms, with or without |
ajp109 | 0:a80552d32b80 | 14 | modification, are permitted provided that the following conditions are met: |
ajp109 | 0:a80552d32b80 | 15 | 1. Redistributions of source code must retain the above copyright |
ajp109 | 0:a80552d32b80 | 16 | notice, this list of conditions and the following disclaimer. |
ajp109 | 0:a80552d32b80 | 17 | 2. Redistributions in binary form must reproduce the above copyright |
ajp109 | 0:a80552d32b80 | 18 | notice, this list of conditions and the following disclaimer in the |
ajp109 | 0:a80552d32b80 | 19 | documentation and/or other materials provided with the distribution. |
ajp109 | 0:a80552d32b80 | 20 | 3. Neither the name of the copyright holders nor the |
ajp109 | 0:a80552d32b80 | 21 | names of its contributors may be used to endorse or promote products |
ajp109 | 0:a80552d32b80 | 22 | derived from this software without specific prior written permission. |
ajp109 | 0:a80552d32b80 | 23 | |
ajp109 | 0:a80552d32b80 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY |
ajp109 | 0:a80552d32b80 | 25 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
ajp109 | 0:a80552d32b80 | 26 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
ajp109 | 0:a80552d32b80 | 27 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY |
ajp109 | 0:a80552d32b80 | 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
ajp109 | 0:a80552d32b80 | 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
ajp109 | 0:a80552d32b80 | 30 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
ajp109 | 0:a80552d32b80 | 31 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
ajp109 | 0:a80552d32b80 | 32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
ajp109 | 0:a80552d32b80 | 33 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
ajp109 | 0:a80552d32b80 | 34 | */ |
ajp109 | 0:a80552d32b80 | 35 | /**************************************************************************/ |
ajp109 | 0:a80552d32b80 | 36 | #include "mbed.h" |
ajp109 | 0:a80552d32b80 | 37 | #include "Adafruit_BluefruitLE_SPI.h" |
ajp109 | 0:a80552d32b80 | 38 | #include <stdlib.h> |
ajp109 | 0:a80552d32b80 | 39 | |
ajp109 | 0:a80552d32b80 | 40 | #ifndef min |
ajp109 | 0:a80552d32b80 | 41 | #define min(a,b) ((a) < (b) ? (a) : (b)) |
ajp109 | 0:a80552d32b80 | 42 | #endif |
ajp109 | 0:a80552d32b80 | 43 | |
ajp109 | 0:a80552d32b80 | 44 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 45 | /*! |
ajp109 | 0:a80552d32b80 | 46 | @brief Instantiates a new instance of the Adafruit_BluefruitLE_SPI class |
ajp109 | 0:a80552d32b80 | 47 | |
ajp109 | 0:a80552d32b80 | 48 | @param[in] mosi |
ajp109 | 0:a80552d32b80 | 49 | The MOSI pin for the SPI interface |
ajp109 | 0:a80552d32b80 | 50 | @param[in] miso |
ajp109 | 0:a80552d32b80 | 51 | The MISO pin for the SPI interface |
ajp109 | 0:a80552d32b80 | 52 | @param[in] sck |
ajp109 | 0:a80552d32b80 | 53 | The SCK pin for the SPI interface |
ajp109 | 0:a80552d32b80 | 54 | @param[in] cs |
ajp109 | 0:a80552d32b80 | 55 | The CS pin for the SPI interface |
ajp109 | 0:a80552d32b80 | 56 | @param[in] irq |
ajp109 | 0:a80552d32b80 | 57 | The IRQ pin - this must be a HW interrupt pin |
ajp109 | 0:a80552d32b80 | 58 | @param[in] rstPin |
ajp109 | 0:a80552d32b80 | 59 | The RESET pin (optional) |
ajp109 | 0:a80552d32b80 | 60 | */ |
ajp109 | 0:a80552d32b80 | 61 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 62 | Adafruit_BluefruitLE_SPI::Adafruit_BluefruitLE_SPI(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName irq, PinName rst) : |
ajp109 | 0:a80552d32b80 | 63 | m_rx_fifo(m_rx_buffer, sizeof(m_rx_buffer), 1, true), |
ajp109 | 2:8c341bac60b8 | 64 | m_spi(mosi, miso, sclk), |
ajp109 | 2:8c341bac60b8 | 65 | m_cs(cs), |
ajp109 | 0:a80552d32b80 | 66 | m_irq(irq), |
ajp109 | 0:a80552d32b80 | 67 | m_rst(rst) |
ajp109 | 0:a80552d32b80 | 68 | { |
ajp109 | 0:a80552d32b80 | 69 | _physical_transport = BLUEFRUIT_TRANSPORT_HWSPI; |
ajp109 | 0:a80552d32b80 | 70 | |
ajp109 | 2:8c341bac60b8 | 71 | m_spi.frequency(400000); |
ajp109 | 0:a80552d32b80 | 72 | // Mode 0, MSB-first is default |
ajp109 | 0:a80552d32b80 | 73 | |
ajp109 | 0:a80552d32b80 | 74 | if (m_rst.is_connected()) { |
ajp109 | 0:a80552d32b80 | 75 | m_rst = true; |
ajp109 | 0:a80552d32b80 | 76 | } |
ajp109 | 2:8c341bac60b8 | 77 | m_cs = false; |
ajp109 | 2:8c341bac60b8 | 78 | wait_us(5); |
ajp109 | 2:8c341bac60b8 | 79 | m_cs = true; |
ajp109 | 2:8c341bac60b8 | 80 | wait_us(35); |
ajp109 | 0:a80552d32b80 | 81 | |
ajp109 | 0:a80552d32b80 | 82 | m_tx_count = 0; |
ajp109 | 0:a80552d32b80 | 83 | |
ajp109 | 0:a80552d32b80 | 84 | m_mode_switch_command_enabled = true; |
ajp109 | 0:a80552d32b80 | 85 | } |
ajp109 | 0:a80552d32b80 | 86 | |
ajp109 | 0:a80552d32b80 | 87 | |
ajp109 | 0:a80552d32b80 | 88 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 89 | /*! |
ajp109 | 0:a80552d32b80 | 90 | @brief Initialize the HW to enable communication with the BLE module |
ajp109 | 0:a80552d32b80 | 91 | |
ajp109 | 0:a80552d32b80 | 92 | @return Returns 'true' if everything initialised correctly, otherwise |
ajp109 | 0:a80552d32b80 | 93 | 'false' if there was a problem during HW initialisation. If |
ajp109 | 0:a80552d32b80 | 94 | 'irqPin' is not a HW interrupt pin false will be returned. |
ajp109 | 0:a80552d32b80 | 95 | */ |
ajp109 | 0:a80552d32b80 | 96 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 97 | bool Adafruit_BluefruitLE_SPI::begin(bool v, bool blocking) |
ajp109 | 0:a80552d32b80 | 98 | { |
ajp109 | 0:a80552d32b80 | 99 | _verbose = v; |
ajp109 | 0:a80552d32b80 | 100 | |
ajp109 | 0:a80552d32b80 | 101 | bool isOK; |
ajp109 | 0:a80552d32b80 | 102 | |
ajp109 | 0:a80552d32b80 | 103 | // Always try to send Initialize command to reset |
ajp109 | 0:a80552d32b80 | 104 | // Bluefruit since user can define but not wiring RST signal |
ajp109 | 0:a80552d32b80 | 105 | isOK = sendInitializePattern(); |
ajp109 | 0:a80552d32b80 | 106 | |
ajp109 | 0:a80552d32b80 | 107 | // use hardware reset if available |
ajp109 | 0:a80552d32b80 | 108 | if (m_rst.is_connected()) { |
ajp109 | 0:a80552d32b80 | 109 | // pull the RST to GND for 10 ms |
ajp109 | 0:a80552d32b80 | 110 | m_rst = false; |
ajp109 | 0:a80552d32b80 | 111 | thread_sleep_for(10); |
ajp109 | 0:a80552d32b80 | 112 | m_rst = true; |
ajp109 | 0:a80552d32b80 | 113 | |
ajp109 | 0:a80552d32b80 | 114 | isOK= true; |
ajp109 | 0:a80552d32b80 | 115 | } |
ajp109 | 0:a80552d32b80 | 116 | |
ajp109 | 0:a80552d32b80 | 117 | _reset_started_timestamp = Kernel::Clock::now(); |
ajp109 | 0:a80552d32b80 | 118 | |
ajp109 | 0:a80552d32b80 | 119 | // Bluefruit takes 1 second to reboot |
ajp109 | 0:a80552d32b80 | 120 | if (blocking) { |
ajp109 | 0:a80552d32b80 | 121 | thread_sleep_for(1000); |
ajp109 | 0:a80552d32b80 | 122 | } |
ajp109 | 0:a80552d32b80 | 123 | |
ajp109 | 0:a80552d32b80 | 124 | return isOK; |
ajp109 | 0:a80552d32b80 | 125 | } |
ajp109 | 0:a80552d32b80 | 126 | |
ajp109 | 0:a80552d32b80 | 127 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 128 | /*! |
ajp109 | 0:a80552d32b80 | 129 | @brief Uninitializes the SPI interface |
ajp109 | 0:a80552d32b80 | 130 | */ |
ajp109 | 0:a80552d32b80 | 131 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 132 | void Adafruit_BluefruitLE_SPI::end(void) |
ajp109 | 0:a80552d32b80 | 133 | { } |
ajp109 | 0:a80552d32b80 | 134 | |
ajp109 | 0:a80552d32b80 | 135 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 136 | /*! |
ajp109 | 0:a80552d32b80 | 137 | @brief Handle direct "+++" input command from user. |
ajp109 | 0:a80552d32b80 | 138 | User should use setMode instead |
ajp109 | 0:a80552d32b80 | 139 | */ |
ajp109 | 0:a80552d32b80 | 140 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 141 | void Adafruit_BluefruitLE_SPI::simulateSwitchMode(void) |
ajp109 | 0:a80552d32b80 | 142 | { |
ajp109 | 0:a80552d32b80 | 143 | _mode = 1 - _mode; |
ajp109 | 0:a80552d32b80 | 144 | |
ajp109 | 0:a80552d32b80 | 145 | char ch = '0' + _mode; |
ajp109 | 0:a80552d32b80 | 146 | m_rx_fifo.write(&ch); |
ajp109 | 0:a80552d32b80 | 147 | m_rx_fifo.write_n("\r\nOK\r\n", 6); |
ajp109 | 0:a80552d32b80 | 148 | } |
ajp109 | 0:a80552d32b80 | 149 | |
ajp109 | 0:a80552d32b80 | 150 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 151 | /*! |
ajp109 | 0:a80552d32b80 | 152 | @brief Simulate "+++" switch mode command |
ajp109 | 0:a80552d32b80 | 153 | */ |
ajp109 | 0:a80552d32b80 | 154 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 155 | bool Adafruit_BluefruitLE_SPI::setMode(uint8_t new_mode) |
ajp109 | 0:a80552d32b80 | 156 | { |
ajp109 | 0:a80552d32b80 | 157 | // invalid mode |
ajp109 | 0:a80552d32b80 | 158 | if ( !(new_mode == BLUEFRUIT_MODE_COMMAND || new_mode == BLUEFRUIT_MODE_DATA) ) return false; |
ajp109 | 0:a80552d32b80 | 159 | |
ajp109 | 0:a80552d32b80 | 160 | // Already in the wanted mode |
ajp109 | 0:a80552d32b80 | 161 | if ( _mode == new_mode ) return true; |
ajp109 | 0:a80552d32b80 | 162 | |
ajp109 | 0:a80552d32b80 | 163 | // SPI use different SDEP command when in DATA/COMMAND mode. |
ajp109 | 0:a80552d32b80 | 164 | // --> does not switch using +++ command |
ajp109 | 0:a80552d32b80 | 165 | _mode = new_mode; |
ajp109 | 0:a80552d32b80 | 166 | |
ajp109 | 0:a80552d32b80 | 167 | // If we're entering DATA mode, flush any old response, so that it isn't |
ajp109 | 0:a80552d32b80 | 168 | // interpreted as incoming UART data |
ajp109 | 0:a80552d32b80 | 169 | if (_mode == BLUEFRUIT_MODE_DATA) sync(); |
ajp109 | 0:a80552d32b80 | 170 | |
ajp109 | 0:a80552d32b80 | 171 | return true; |
ajp109 | 0:a80552d32b80 | 172 | } |
ajp109 | 0:a80552d32b80 | 173 | |
ajp109 | 0:a80552d32b80 | 174 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 175 | /*! |
ajp109 | 0:a80552d32b80 | 176 | @brief Enable/disable recognition of "+++" switch mode command. |
ajp109 | 0:a80552d32b80 | 177 | Usage of setMode is not affected. |
ajp109 | 0:a80552d32b80 | 178 | */ |
ajp109 | 0:a80552d32b80 | 179 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 180 | void Adafruit_BluefruitLE_SPI::enableModeSwitchCommand(bool enabled) |
ajp109 | 0:a80552d32b80 | 181 | { |
ajp109 | 0:a80552d32b80 | 182 | m_mode_switch_command_enabled = enabled; |
ajp109 | 0:a80552d32b80 | 183 | } |
ajp109 | 0:a80552d32b80 | 184 | |
ajp109 | 0:a80552d32b80 | 185 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 186 | /*! |
ajp109 | 0:a80552d32b80 | 187 | @brief Send initialize pattern to Bluefruit LE to force a reset. This pattern |
ajp109 | 0:a80552d32b80 | 188 | follow the SDEP command syntax with command_id = SDEP_CMDTYPE_INITIALIZE. |
ajp109 | 0:a80552d32b80 | 189 | The command has NO response, and is expected to complete within 1 second |
ajp109 | 0:a80552d32b80 | 190 | */ |
ajp109 | 0:a80552d32b80 | 191 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 192 | bool Adafruit_BluefruitLE_SPI::sendInitializePattern(void) |
ajp109 | 0:a80552d32b80 | 193 | { |
ajp109 | 0:a80552d32b80 | 194 | return sendPacket(SDEP_CMDTYPE_INITIALIZE, NULL, 0, 0); |
ajp109 | 0:a80552d32b80 | 195 | } |
ajp109 | 0:a80552d32b80 | 196 | |
ajp109 | 0:a80552d32b80 | 197 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 198 | /*! |
ajp109 | 0:a80552d32b80 | 199 | @brief Send out an packet with data in m_tx_buffer |
ajp109 | 0:a80552d32b80 | 200 | |
ajp109 | 0:a80552d32b80 | 201 | @param[in] more_data |
ajp109 | 0:a80552d32b80 | 202 | More Data bitfield, 0 indicates this is not end of transfer yet |
ajp109 | 0:a80552d32b80 | 203 | */ |
ajp109 | 0:a80552d32b80 | 204 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 205 | bool Adafruit_BluefruitLE_SPI::sendPacket(uint16_t command, const uint8_t* buf, uint8_t count, uint8_t more_data) |
ajp109 | 0:a80552d32b80 | 206 | { |
ajp109 | 0:a80552d32b80 | 207 | // flush old response before sending the new command, but only if we're *not* |
ajp109 | 0:a80552d32b80 | 208 | // in DATA mode, as the RX FIFO may containg incoming UART data that hasn't |
ajp109 | 0:a80552d32b80 | 209 | // been read yet |
ajp109 | 0:a80552d32b80 | 210 | if (more_data == 0 && _mode != BLUEFRUIT_MODE_DATA) sync(); |
ajp109 | 0:a80552d32b80 | 211 | |
ajp109 | 0:a80552d32b80 | 212 | sdepMsgCommand_t msgCmd; |
ajp109 | 0:a80552d32b80 | 213 | |
ajp109 | 0:a80552d32b80 | 214 | msgCmd.header.msg_type = SDEP_MSGTYPE_COMMAND; |
ajp109 | 0:a80552d32b80 | 215 | msgCmd.header.cmd_id_high = (command >> 8) & 0xFF ; |
ajp109 | 0:a80552d32b80 | 216 | msgCmd.header.cmd_id_low = command & 0xFF; |
ajp109 | 0:a80552d32b80 | 217 | msgCmd.header.length = count; |
ajp109 | 0:a80552d32b80 | 218 | msgCmd.header.more_data = (count == SDEP_MAX_PACKETSIZE) ? more_data : 0; |
ajp109 | 0:a80552d32b80 | 219 | |
ajp109 | 0:a80552d32b80 | 220 | // Copy payload |
ajp109 | 0:a80552d32b80 | 221 | if ( buf != NULL && count > 0) memcpy(msgCmd.payload, buf, count); |
ajp109 | 0:a80552d32b80 | 222 | |
ajp109 | 0:a80552d32b80 | 223 | // Starting SPI transaction |
ajp109 | 0:a80552d32b80 | 224 | m_spi.select(); |
ajp109 | 2:8c341bac60b8 | 225 | m_cs = false; |
ajp109 | 0:a80552d32b80 | 226 | |
ajp109 | 0:a80552d32b80 | 227 | TimeoutTimer tt(_timeout); |
ajp109 | 0:a80552d32b80 | 228 | |
ajp109 | 0:a80552d32b80 | 229 | // Bluefruit may not be ready |
ajp109 | 0:a80552d32b80 | 230 | while ( ( spixfer(msgCmd.header.msg_type) == SPI_IGNORED_BYTE ) && !tt.expired() ) { |
ajp109 | 0:a80552d32b80 | 231 | // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself |
ajp109 | 2:8c341bac60b8 | 232 | m_cs = true; |
ajp109 | 2:8c341bac60b8 | 233 | wait_us(SPI_DEFAULT_DELAY_US); |
ajp109 | 2:8c341bac60b8 | 234 | m_cs = false; |
ajp109 | 0:a80552d32b80 | 235 | } |
ajp109 | 0:a80552d32b80 | 236 | |
ajp109 | 0:a80552d32b80 | 237 | bool result = !tt.expired(); |
ajp109 | 0:a80552d32b80 | 238 | if ( result ) { |
ajp109 | 0:a80552d32b80 | 239 | // transfer the rest of the data |
ajp109 | 0:a80552d32b80 | 240 | spixfer((void*) (((uint8_t*)&msgCmd) +1), sizeof(sdepMsgHeader_t)+count-1); |
ajp109 | 0:a80552d32b80 | 241 | } |
ajp109 | 0:a80552d32b80 | 242 | |
ajp109 | 2:8c341bac60b8 | 243 | m_cs = true; |
ajp109 | 0:a80552d32b80 | 244 | m_spi.deselect(); |
ajp109 | 0:a80552d32b80 | 245 | |
ajp109 | 0:a80552d32b80 | 246 | return result; |
ajp109 | 0:a80552d32b80 | 247 | } |
ajp109 | 0:a80552d32b80 | 248 | |
ajp109 | 0:a80552d32b80 | 249 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 250 | /*! |
ajp109 | 0:a80552d32b80 | 251 | @brief Print API. Either buffer the data internally or send it to bus |
ajp109 | 0:a80552d32b80 | 252 | if possible. \r and \n are command terminators and will force the |
ajp109 | 0:a80552d32b80 | 253 | packet to be sent to the Bluefruit LE module. |
ajp109 | 0:a80552d32b80 | 254 | |
ajp109 | 0:a80552d32b80 | 255 | @param[in] c |
ajp109 | 0:a80552d32b80 | 256 | Character to send |
ajp109 | 0:a80552d32b80 | 257 | */ |
ajp109 | 0:a80552d32b80 | 258 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 259 | ssize_t Adafruit_BluefruitLE_SPI::_putc(int c_int) |
ajp109 | 0:a80552d32b80 | 260 | { |
ajp109 | 0:a80552d32b80 | 261 | uint8_t c = c_int & 0xFF; |
ajp109 | 0:a80552d32b80 | 262 | if (_mode == BLUEFRUIT_MODE_DATA) { |
ajp109 | 0:a80552d32b80 | 263 | sendPacket(SDEP_CMDTYPE_BLE_UARTTX, &c, 1, 0); |
ajp109 | 0:a80552d32b80 | 264 | getResponse(); |
ajp109 | 0:a80552d32b80 | 265 | return 1; |
ajp109 | 0:a80552d32b80 | 266 | } |
ajp109 | 0:a80552d32b80 | 267 | |
ajp109 | 0:a80552d32b80 | 268 | // Following code handle BLUEFRUIT_MODE_COMMAND |
ajp109 | 0:a80552d32b80 | 269 | |
ajp109 | 0:a80552d32b80 | 270 | // Final packet due to \r or \n terminator |
ajp109 | 0:a80552d32b80 | 271 | if (c == '\r' || c == '\n') { |
ajp109 | 0:a80552d32b80 | 272 | if (m_tx_count > 0) { |
ajp109 | 0:a80552d32b80 | 273 | // +++ command to switch mode |
ajp109 | 0:a80552d32b80 | 274 | if (m_mode_switch_command_enabled && memcmp(m_tx_buffer, "+++", 3) == 0) { |
ajp109 | 0:a80552d32b80 | 275 | simulateSwitchMode(); |
ajp109 | 0:a80552d32b80 | 276 | } else { |
ajp109 | 0:a80552d32b80 | 277 | sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 0); |
ajp109 | 0:a80552d32b80 | 278 | } |
ajp109 | 0:a80552d32b80 | 279 | m_tx_count = 0; |
ajp109 | 0:a80552d32b80 | 280 | } |
ajp109 | 0:a80552d32b80 | 281 | } |
ajp109 | 0:a80552d32b80 | 282 | // More than max packet buffered --> send with more_data = 1 |
ajp109 | 0:a80552d32b80 | 283 | else if (m_tx_count == SDEP_MAX_PACKETSIZE) { |
ajp109 | 0:a80552d32b80 | 284 | sendPacket(SDEP_CMDTYPE_AT_WRAPPER, m_tx_buffer, m_tx_count, 1); |
ajp109 | 0:a80552d32b80 | 285 | |
ajp109 | 0:a80552d32b80 | 286 | m_tx_buffer[0] = c; |
ajp109 | 0:a80552d32b80 | 287 | m_tx_count = 1; |
ajp109 | 0:a80552d32b80 | 288 | } |
ajp109 | 0:a80552d32b80 | 289 | // Not enough data, continue to buffer |
ajp109 | 0:a80552d32b80 | 290 | else { |
ajp109 | 0:a80552d32b80 | 291 | m_tx_buffer[m_tx_count++] = c; |
ajp109 | 0:a80552d32b80 | 292 | } |
ajp109 | 0:a80552d32b80 | 293 | |
ajp109 | 0:a80552d32b80 | 294 | if (_verbose) ::printf("%c", (char) c); |
ajp109 | 0:a80552d32b80 | 295 | |
ajp109 | 0:a80552d32b80 | 296 | return 1; |
ajp109 | 0:a80552d32b80 | 297 | } |
ajp109 | 0:a80552d32b80 | 298 | |
ajp109 | 0:a80552d32b80 | 299 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 300 | /*! |
ajp109 | 0:a80552d32b80 | 301 | |
ajp109 | 0:a80552d32b80 | 302 | */ |
ajp109 | 0:a80552d32b80 | 303 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 304 | ssize_t Adafruit_BluefruitLE_SPI::write(const void *v_buf, size_t size) |
ajp109 | 0:a80552d32b80 | 305 | { |
ajp109 | 0:a80552d32b80 | 306 | uint8_t *buf = (uint8_t *)v_buf; |
ajp109 | 0:a80552d32b80 | 307 | if ( _mode == BLUEFRUIT_MODE_DATA ) { |
ajp109 | 0:a80552d32b80 | 308 | if (m_mode_switch_command_enabled && |
ajp109 | 0:a80552d32b80 | 309 | (size >= 3) && |
ajp109 | 0:a80552d32b80 | 310 | !memcmp(buf, "+++", 3) && |
ajp109 | 0:a80552d32b80 | 311 | !(size > 3 && buf[3] != '\r' && buf[3] != '\n') ) { |
ajp109 | 0:a80552d32b80 | 312 | simulateSwitchMode(); |
ajp109 | 0:a80552d32b80 | 313 | } else { |
ajp109 | 0:a80552d32b80 | 314 | size_t remain = size; |
ajp109 | 0:a80552d32b80 | 315 | while(remain) { |
ajp109 | 0:a80552d32b80 | 316 | size_t len = min(remain, SDEP_MAX_PACKETSIZE); |
ajp109 | 0:a80552d32b80 | 317 | remain -= len; |
ajp109 | 0:a80552d32b80 | 318 | |
ajp109 | 0:a80552d32b80 | 319 | sendPacket(SDEP_CMDTYPE_BLE_UARTTX, buf, (uint8_t) len, remain ? 1 : 0); |
ajp109 | 0:a80552d32b80 | 320 | buf += len; |
ajp109 | 0:a80552d32b80 | 321 | } |
ajp109 | 0:a80552d32b80 | 322 | |
ajp109 | 0:a80552d32b80 | 323 | getResponse(); |
ajp109 | 0:a80552d32b80 | 324 | } |
ajp109 | 0:a80552d32b80 | 325 | |
ajp109 | 0:a80552d32b80 | 326 | return size; |
ajp109 | 0:a80552d32b80 | 327 | } |
ajp109 | 0:a80552d32b80 | 328 | // Command mode |
ajp109 | 0:a80552d32b80 | 329 | else { |
ajp109 | 0:a80552d32b80 | 330 | size_t n = size; |
ajp109 | 0:a80552d32b80 | 331 | while (size--) { |
ajp109 | 0:a80552d32b80 | 332 | _putc(*buf++); |
ajp109 | 0:a80552d32b80 | 333 | } |
ajp109 | 0:a80552d32b80 | 334 | return n; |
ajp109 | 0:a80552d32b80 | 335 | } |
ajp109 | 0:a80552d32b80 | 336 | } |
ajp109 | 0:a80552d32b80 | 337 | |
ajp109 | 0:a80552d32b80 | 338 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 339 | /*! |
ajp109 | 0:a80552d32b80 | 340 | @brief Check if the response from the previous command is ready |
ajp109 | 0:a80552d32b80 | 341 | |
ajp109 | 0:a80552d32b80 | 342 | @return 'true' if a response is ready, otherwise 'false' |
ajp109 | 0:a80552d32b80 | 343 | */ |
ajp109 | 0:a80552d32b80 | 344 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 345 | int Adafruit_BluefruitLE_SPI::available(void) |
ajp109 | 0:a80552d32b80 | 346 | { |
ajp109 | 0:a80552d32b80 | 347 | if (! m_rx_fifo.empty() ) { |
ajp109 | 0:a80552d32b80 | 348 | return m_rx_fifo.count(); |
ajp109 | 0:a80552d32b80 | 349 | } |
ajp109 | 0:a80552d32b80 | 350 | |
ajp109 | 0:a80552d32b80 | 351 | if ( _mode == BLUEFRUIT_MODE_DATA ) { |
ajp109 | 0:a80552d32b80 | 352 | // DATA Mode: query for BLE UART data |
ajp109 | 0:a80552d32b80 | 353 | sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0); |
ajp109 | 0:a80552d32b80 | 354 | |
ajp109 | 0:a80552d32b80 | 355 | // Waiting to get response from Bluefruit |
ajp109 | 0:a80552d32b80 | 356 | getResponse(); |
ajp109 | 0:a80552d32b80 | 357 | |
ajp109 | 0:a80552d32b80 | 358 | return m_rx_fifo.count(); |
ajp109 | 0:a80552d32b80 | 359 | } else { |
ajp109 | 0:a80552d32b80 | 360 | return (m_irq.read()); |
ajp109 | 0:a80552d32b80 | 361 | } |
ajp109 | 0:a80552d32b80 | 362 | } |
ajp109 | 0:a80552d32b80 | 363 | |
ajp109 | 0:a80552d32b80 | 364 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 365 | /*! |
ajp109 | 0:a80552d32b80 | 366 | @brief Get a byte from response data, perform SPI transaction if needed |
ajp109 | 0:a80552d32b80 | 367 | |
ajp109 | 0:a80552d32b80 | 368 | @return -1 if no data is available |
ajp109 | 0:a80552d32b80 | 369 | */ |
ajp109 | 0:a80552d32b80 | 370 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 371 | int Adafruit_BluefruitLE_SPI::_getc(void) |
ajp109 | 0:a80552d32b80 | 372 | { |
ajp109 | 0:a80552d32b80 | 373 | uint8_t ch; |
ajp109 | 0:a80552d32b80 | 374 | |
ajp109 | 0:a80552d32b80 | 375 | // try to grab from buffer first... |
ajp109 | 0:a80552d32b80 | 376 | if (!m_rx_fifo.empty()) { |
ajp109 | 0:a80552d32b80 | 377 | m_rx_fifo.read(&ch); |
ajp109 | 0:a80552d32b80 | 378 | return (int)ch; |
ajp109 | 0:a80552d32b80 | 379 | } |
ajp109 | 0:a80552d32b80 | 380 | |
ajp109 | 0:a80552d32b80 | 381 | if ( _mode == BLUEFRUIT_MODE_DATA ) { |
ajp109 | 0:a80552d32b80 | 382 | // DATA Mode: query for BLE UART data |
ajp109 | 0:a80552d32b80 | 383 | sendPacket(SDEP_CMDTYPE_BLE_UARTRX, NULL, 0, 0); |
ajp109 | 0:a80552d32b80 | 384 | |
ajp109 | 0:a80552d32b80 | 385 | // Waiting to get response from Bluefruit |
ajp109 | 0:a80552d32b80 | 386 | getResponse(); |
ajp109 | 0:a80552d32b80 | 387 | } else { |
ajp109 | 0:a80552d32b80 | 388 | // COMMAND Mode: Only read data from Bluefruit if IRQ is raised |
ajp109 | 0:a80552d32b80 | 389 | if ( m_irq.read() ) getResponse(); |
ajp109 | 0:a80552d32b80 | 390 | } |
ajp109 | 0:a80552d32b80 | 391 | |
ajp109 | 0:a80552d32b80 | 392 | return m_rx_fifo.read(&ch) ? ((int) ch) : EOF; |
ajp109 | 0:a80552d32b80 | 393 | |
ajp109 | 0:a80552d32b80 | 394 | } |
ajp109 | 0:a80552d32b80 | 395 | |
ajp109 | 0:a80552d32b80 | 396 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 397 | /*! |
ajp109 | 0:a80552d32b80 | 398 | @brief Flush current response data in the internal FIFO |
ajp109 | 0:a80552d32b80 | 399 | |
ajp109 | 0:a80552d32b80 | 400 | @return -1 if no data is available |
ajp109 | 0:a80552d32b80 | 401 | */ |
ajp109 | 0:a80552d32b80 | 402 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 403 | int Adafruit_BluefruitLE_SPI::sync(void) |
ajp109 | 0:a80552d32b80 | 404 | { |
ajp109 | 0:a80552d32b80 | 405 | m_rx_fifo.clear(); |
ajp109 | 0:a80552d32b80 | 406 | return Adafruit_BLE::sync(); |
ajp109 | 0:a80552d32b80 | 407 | } |
ajp109 | 0:a80552d32b80 | 408 | |
ajp109 | 0:a80552d32b80 | 409 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 410 | /*! |
ajp109 | 0:a80552d32b80 | 411 | @brief Try to perform an full AT response transfer from Bluefruit, or execute |
ajp109 | 0:a80552d32b80 | 412 | as many SPI transaction as internal FIFO can hold up. |
ajp109 | 0:a80552d32b80 | 413 | |
ajp109 | 0:a80552d32b80 | 414 | @note If verbose is enabled, all the received data will be print to Serial |
ajp109 | 0:a80552d32b80 | 415 | |
ajp109 | 0:a80552d32b80 | 416 | @return |
ajp109 | 0:a80552d32b80 | 417 | - true : if succeeded |
ajp109 | 0:a80552d32b80 | 418 | - false : if failed |
ajp109 | 0:a80552d32b80 | 419 | */ |
ajp109 | 0:a80552d32b80 | 420 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 421 | bool Adafruit_BluefruitLE_SPI::getResponse(void) |
ajp109 | 0:a80552d32b80 | 422 | { |
ajp109 | 0:a80552d32b80 | 423 | // Try to read data from Bluefruit if there is enough room in the fifo |
ajp109 | 0:a80552d32b80 | 424 | while ( m_rx_fifo.remaining() >= SDEP_MAX_PACKETSIZE ) { |
ajp109 | 0:a80552d32b80 | 425 | // Get a SDEP packet |
ajp109 | 0:a80552d32b80 | 426 | sdepMsgResponse_t msg_response; |
ajp109 | 0:a80552d32b80 | 427 | memclr(&msg_response, sizeof(sdepMsgResponse_t)); |
ajp109 | 0:a80552d32b80 | 428 | |
ajp109 | 0:a80552d32b80 | 429 | if ( !getPacket(&msg_response) ) return false; |
ajp109 | 0:a80552d32b80 | 430 | |
ajp109 | 0:a80552d32b80 | 431 | // Write to fifo |
ajp109 | 0:a80552d32b80 | 432 | if ( msg_response.header.length > 0) { |
ajp109 | 0:a80552d32b80 | 433 | m_rx_fifo.write_n(msg_response.payload, msg_response.header.length); |
ajp109 | 0:a80552d32b80 | 434 | } |
ajp109 | 0:a80552d32b80 | 435 | |
ajp109 | 0:a80552d32b80 | 436 | // No more packet data |
ajp109 | 0:a80552d32b80 | 437 | if ( !msg_response.header.more_data ) break; |
ajp109 | 0:a80552d32b80 | 438 | |
ajp109 | 0:a80552d32b80 | 439 | // It takes a bit since all Data received to IRQ to get LOW |
ajp109 | 0:a80552d32b80 | 440 | // May need to delay a bit for it to be stable before the next try |
ajp109 | 0:a80552d32b80 | 441 | // delayMicroseconds(SPI_DEFAULT_DELAY_US); |
ajp109 | 0:a80552d32b80 | 442 | } |
ajp109 | 0:a80552d32b80 | 443 | |
ajp109 | 0:a80552d32b80 | 444 | return true; |
ajp109 | 0:a80552d32b80 | 445 | } |
ajp109 | 0:a80552d32b80 | 446 | |
ajp109 | 0:a80552d32b80 | 447 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 448 | /*! |
ajp109 | 0:a80552d32b80 | 449 | @brief Perform a single SPI SDEP transaction and is used by getReponse to |
ajp109 | 0:a80552d32b80 | 450 | get a full response composed of multiple packets. |
ajp109 | 0:a80552d32b80 | 451 | |
ajp109 | 0:a80552d32b80 | 452 | @param[in] buf |
ajp109 | 0:a80552d32b80 | 453 | Memory location where payload is copied to |
ajp109 | 0:a80552d32b80 | 454 | |
ajp109 | 0:a80552d32b80 | 455 | @return number of bytes in SDEP payload |
ajp109 | 0:a80552d32b80 | 456 | */ |
ajp109 | 0:a80552d32b80 | 457 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 458 | bool Adafruit_BluefruitLE_SPI::getPacket(sdepMsgResponse_t* p_response) |
ajp109 | 0:a80552d32b80 | 459 | { |
ajp109 | 0:a80552d32b80 | 460 | // Wait until IRQ is asserted, double timeout since some commands take long time to start responding |
ajp109 | 0:a80552d32b80 | 461 | TimeoutTimer tt(2*_timeout); |
ajp109 | 0:a80552d32b80 | 462 | |
ajp109 | 0:a80552d32b80 | 463 | while ( !m_irq.read() ) { |
ajp109 | 0:a80552d32b80 | 464 | if (tt.expired()) return false; |
ajp109 | 0:a80552d32b80 | 465 | } |
ajp109 | 0:a80552d32b80 | 466 | |
ajp109 | 0:a80552d32b80 | 467 | sdepMsgHeader_t* p_header = &p_response->header; |
ajp109 | 0:a80552d32b80 | 468 | |
ajp109 | 0:a80552d32b80 | 469 | tt.set(_timeout); |
ajp109 | 0:a80552d32b80 | 470 | |
Andy Pomfret |
1:6ff0eee2da9c | 471 | m_spi.select(); |
ajp109 | 2:8c341bac60b8 | 472 | m_cs = false; |
Andy Pomfret |
1:6ff0eee2da9c | 473 | |
ajp109 | 0:a80552d32b80 | 474 | do { |
ajp109 | 0:a80552d32b80 | 475 | if ( tt.expired() ) break; |
ajp109 | 0:a80552d32b80 | 476 | |
ajp109 | 0:a80552d32b80 | 477 | p_header->msg_type = spixfer(0xff); |
ajp109 | 0:a80552d32b80 | 478 | |
ajp109 | 0:a80552d32b80 | 479 | if (p_header->msg_type == SPI_IGNORED_BYTE) { |
ajp109 | 0:a80552d32b80 | 480 | // Bluefruit may not be ready |
ajp109 | 0:a80552d32b80 | 481 | // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself |
ajp109 | 2:8c341bac60b8 | 482 | m_cs = true; |
ajp109 | 2:8c341bac60b8 | 483 | wait_us(SPI_DEFAULT_DELAY_US); |
ajp109 | 2:8c341bac60b8 | 484 | m_cs = false; |
ajp109 | 0:a80552d32b80 | 485 | } else if (p_header->msg_type == SPI_OVERREAD_BYTE) { |
ajp109 | 0:a80552d32b80 | 486 | // IRQ may not be pulled down by Bluefruit when returning all data in previous transfer. |
ajp109 | 0:a80552d32b80 | 487 | // This could happen when Arduino MCU is running at fast rate comparing to Bluefruit's MCU, |
ajp109 | 0:a80552d32b80 | 488 | // causing an SPI_OVERREAD_BYTE to be returned at stage. |
ajp109 | 0:a80552d32b80 | 489 | // |
ajp109 | 0:a80552d32b80 | 490 | // Walkaround: Disable & Re-enable CS with a bit of delay and keep waiting |
ajp109 | 0:a80552d32b80 | 491 | // TODO IRQ is supposed to be OFF then ON, it is better to use GPIO trigger interrupt. |
ajp109 | 0:a80552d32b80 | 492 | |
ajp109 | 2:8c341bac60b8 | 493 | m_cs = true; |
ajp109 | 0:a80552d32b80 | 494 | // wait for the clock to be enabled.. |
ajp109 | 0:a80552d32b80 | 495 | // while (!digitalRead(m_irq)) { |
ajp109 | 0:a80552d32b80 | 496 | // if ( tt.expired() ) break; |
ajp109 | 0:a80552d32b80 | 497 | // } |
ajp109 | 0:a80552d32b80 | 498 | // if (!digitalRead(m_irq)) break; |
ajp109 | 2:8c341bac60b8 | 499 | wait_us(SPI_DEFAULT_DELAY_US); |
ajp109 | 2:8c341bac60b8 | 500 | m_cs = false; |
ajp109 | 0:a80552d32b80 | 501 | } |
ajp109 | 0:a80552d32b80 | 502 | } while (p_header->msg_type == SPI_IGNORED_BYTE || p_header->msg_type == SPI_OVERREAD_BYTE); |
ajp109 | 0:a80552d32b80 | 503 | |
ajp109 | 0:a80552d32b80 | 504 | bool result=false; |
ajp109 | 0:a80552d32b80 | 505 | |
ajp109 | 0:a80552d32b80 | 506 | // Not a loop, just a way to avoid goto with error handling |
ajp109 | 0:a80552d32b80 | 507 | do { |
ajp109 | 0:a80552d32b80 | 508 | // Look for the header |
ajp109 | 0:a80552d32b80 | 509 | // note that we should always get the right header at this point, and not doing so will really mess up things. |
ajp109 | 0:a80552d32b80 | 510 | while ( p_header->msg_type != SDEP_MSGTYPE_RESPONSE && p_header->msg_type != SDEP_MSGTYPE_ERROR && !tt.expired() ) { |
ajp109 | 0:a80552d32b80 | 511 | p_header->msg_type = spixfer(0xff); |
ajp109 | 0:a80552d32b80 | 512 | } |
ajp109 | 0:a80552d32b80 | 513 | |
ajp109 | 0:a80552d32b80 | 514 | if ( tt.expired() ) break; |
ajp109 | 0:a80552d32b80 | 515 | |
ajp109 | 0:a80552d32b80 | 516 | memset( (&p_header->msg_type)+1, 0xff, sizeof(sdepMsgHeader_t) - 1); |
ajp109 | 0:a80552d32b80 | 517 | spixfer((&p_header->msg_type)+1, sizeof(sdepMsgHeader_t) - 1); |
ajp109 | 0:a80552d32b80 | 518 | |
ajp109 | 0:a80552d32b80 | 519 | // Command is 16-bit at odd address, may have alignment issue with 32-bit chip |
ajp109 | 0:a80552d32b80 | 520 | uint16_t cmd_id = (p_header->cmd_id_high << 8) | p_header->cmd_id_low; |
ajp109 | 0:a80552d32b80 | 521 | |
ajp109 | 0:a80552d32b80 | 522 | // Error Message Response |
ajp109 | 0:a80552d32b80 | 523 | if ( p_header->msg_type == SDEP_MSGTYPE_ERROR ) break; |
ajp109 | 0:a80552d32b80 | 524 | |
ajp109 | 0:a80552d32b80 | 525 | // Invalid command |
ajp109 | 0:a80552d32b80 | 526 | if (!(cmd_id == SDEP_CMDTYPE_AT_WRAPPER || |
ajp109 | 0:a80552d32b80 | 527 | cmd_id == SDEP_CMDTYPE_BLE_UARTTX || |
ajp109 | 0:a80552d32b80 | 528 | cmd_id == SDEP_CMDTYPE_BLE_UARTRX) ) { |
ajp109 | 0:a80552d32b80 | 529 | break; |
ajp109 | 0:a80552d32b80 | 530 | } |
ajp109 | 0:a80552d32b80 | 531 | |
ajp109 | 0:a80552d32b80 | 532 | // Invalid length |
ajp109 | 0:a80552d32b80 | 533 | if(p_header->length > SDEP_MAX_PACKETSIZE) break; |
ajp109 | 0:a80552d32b80 | 534 | |
ajp109 | 0:a80552d32b80 | 535 | // read payload |
ajp109 | 0:a80552d32b80 | 536 | memset(p_response->payload, 0xff, p_header->length); |
ajp109 | 0:a80552d32b80 | 537 | spixfer(p_response->payload, p_header->length); |
ajp109 | 0:a80552d32b80 | 538 | |
ajp109 | 0:a80552d32b80 | 539 | result = true; |
ajp109 | 0:a80552d32b80 | 540 | } while(0); |
ajp109 | 0:a80552d32b80 | 541 | |
ajp109 | 2:8c341bac60b8 | 542 | m_cs = true; |
ajp109 | 0:a80552d32b80 | 543 | m_spi.deselect(); |
ajp109 | 0:a80552d32b80 | 544 | |
ajp109 | 0:a80552d32b80 | 545 | return result; |
ajp109 | 0:a80552d32b80 | 546 | } |
ajp109 | 0:a80552d32b80 | 547 | |
ajp109 | 0:a80552d32b80 | 548 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 549 | /*! |
ajp109 | 0:a80552d32b80 | 550 | |
ajp109 | 0:a80552d32b80 | 551 | */ |
ajp109 | 0:a80552d32b80 | 552 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 553 | void Adafruit_BluefruitLE_SPI::spixfer(void *buff, size_t len) |
ajp109 | 0:a80552d32b80 | 554 | { |
ajp109 | 0:a80552d32b80 | 555 | uint8_t *p = (uint8_t *)buff; |
ajp109 | 0:a80552d32b80 | 556 | |
ajp109 | 0:a80552d32b80 | 557 | while (len--) { |
ajp109 | 2:8c341bac60b8 | 558 | *p = spixfer(*p); |
ajp109 | 0:a80552d32b80 | 559 | p++; |
ajp109 | 0:a80552d32b80 | 560 | } |
ajp109 | 0:a80552d32b80 | 561 | } |
ajp109 | 0:a80552d32b80 | 562 | |
ajp109 | 0:a80552d32b80 | 563 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 564 | /*! |
ajp109 | 0:a80552d32b80 | 565 | |
ajp109 | 0:a80552d32b80 | 566 | */ |
ajp109 | 0:a80552d32b80 | 567 | /******************************************************************************/ |
ajp109 | 0:a80552d32b80 | 568 | uint8_t Adafruit_BluefruitLE_SPI::spixfer(uint8_t x) |
ajp109 | 0:a80552d32b80 | 569 | { |
ajp109 | 0:a80552d32b80 | 570 | uint8_t reply = m_spi.write(x); |
ajp109 | 2:8c341bac60b8 | 571 | //::printf("%x -> %x\n",x,reply); |
ajp109 | 0:a80552d32b80 | 572 | //SerialDebug.println(reply, HEX); |
ajp109 | 0:a80552d32b80 | 573 | return reply; |
ajp109 | 0:a80552d32b80 | 574 | } |