Solution for Bluetooth SIG hands-on training course

Dependencies:   BLE_API mbed-dev-bin nRF51822-bluetooth-mdw

Dependents:   microbit

Fork of microbit-dal-bluetooth-mdw_starter by Martin Woolley

Committer:
LancasterUniversity
Date:
Thu Apr 07 23:39:34 2016 +0100
Revision:
8:ec4465853952
Parent:
3:d86a4ddc1867
Child:
29:62f8b007debf
Synchronized with git rev 6702a5f5
Author: James Devine
microbit-dal: Zero initialised C99 compatible buffers

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jonathan Austin 1:8aa5cdb4ab67 1 /*
Jonathan Austin 1:8aa5cdb4ab67 2 The MIT License (MIT)
Jonathan Austin 1:8aa5cdb4ab67 3
Jonathan Austin 1:8aa5cdb4ab67 4 Copyright (c) 2016 British Broadcasting Corporation.
Jonathan Austin 1:8aa5cdb4ab67 5 This software is provided by Lancaster University by arrangement with the BBC.
Jonathan Austin 1:8aa5cdb4ab67 6
Jonathan Austin 1:8aa5cdb4ab67 7 Permission is hereby granted, free of charge, to any person obtaining a
Jonathan Austin 1:8aa5cdb4ab67 8 copy of this software and associated documentation files (the "Software"),
Jonathan Austin 1:8aa5cdb4ab67 9 to deal in the Software without restriction, including without limitation
Jonathan Austin 1:8aa5cdb4ab67 10 the rights to use, copy, modify, merge, publish, distribute, sublicense,
Jonathan Austin 1:8aa5cdb4ab67 11 and/or sell copies of the Software, and to permit persons to whom the
Jonathan Austin 1:8aa5cdb4ab67 12 Software is furnished to do so, subject to the following conditions:
Jonathan Austin 1:8aa5cdb4ab67 13
Jonathan Austin 1:8aa5cdb4ab67 14 The above copyright notice and this permission notice shall be included in
Jonathan Austin 1:8aa5cdb4ab67 15 all copies or substantial portions of the Software.
Jonathan Austin 1:8aa5cdb4ab67 16
Jonathan Austin 1:8aa5cdb4ab67 17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jonathan Austin 1:8aa5cdb4ab67 18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jonathan Austin 1:8aa5cdb4ab67 19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Jonathan Austin 1:8aa5cdb4ab67 20 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jonathan Austin 1:8aa5cdb4ab67 22 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
Jonathan Austin 1:8aa5cdb4ab67 23 DEALINGS IN THE SOFTWARE.
Jonathan Austin 1:8aa5cdb4ab67 24 */
Jonathan Austin 1:8aa5cdb4ab67 25
Jonathan Austin 1:8aa5cdb4ab67 26 /**
Jonathan Austin 1:8aa5cdb4ab67 27 * Class definition for the custom MicroBit UART Service.
Jonathan Austin 1:8aa5cdb4ab67 28 * Provides a BLE service that acts as a UART port, enabling the reception and transmission
Jonathan Austin 1:8aa5cdb4ab67 29 * of an arbitrary number of bytes.
Jonathan Austin 1:8aa5cdb4ab67 30 */
Jonathan Austin 1:8aa5cdb4ab67 31
Jonathan Austin 1:8aa5cdb4ab67 32 #include "ble/UUID.h"
Jonathan Austin 1:8aa5cdb4ab67 33
Jonathan Austin 1:8aa5cdb4ab67 34 #include "ExternalEvents.h"
Jonathan Austin 1:8aa5cdb4ab67 35 #include "MicroBitUARTService.h"
Jonathan Austin 1:8aa5cdb4ab67 36 #include "MicroBitFiber.h"
Jonathan Austin 1:8aa5cdb4ab67 37 #include "ErrorNo.h"
Jonathan Austin 1:8aa5cdb4ab67 38 #include "NotifyEvents.h"
Jonathan Austin 1:8aa5cdb4ab67 39
Jonathan Austin 1:8aa5cdb4ab67 40 static uint8_t txBufferHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 41 static uint8_t txBufferTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 42
Jonathan Austin 1:8aa5cdb4ab67 43 static GattCharacteristic* rxCharacteristic = NULL;
Jonathan Austin 1:8aa5cdb4ab67 44
Jonathan Austin 1:8aa5cdb4ab67 45 /**
Jonathan Austin 1:8aa5cdb4ab67 46 * A callback function for whenever a Bluetooth device consumes our RX Buffer
Jonathan Austin 1:8aa5cdb4ab67 47 */
Jonathan Austin 1:8aa5cdb4ab67 48 void on_confirmation_received_callback(uint16_t handle)
Jonathan Austin 1:8aa5cdb4ab67 49 {
Jonathan Austin 1:8aa5cdb4ab67 50 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:8aa5cdb4ab67 51 SERIAL_DEBUG->printf("RECEIVED!! %d \r\n",handle);
Jonathan Austin 1:8aa5cdb4ab67 52 #endif
Jonathan Austin 1:8aa5cdb4ab67 53 if(handle == rxCharacteristic->getValueAttribute().getHandle())
Jonathan Austin 1:8aa5cdb4ab67 54 {
Jonathan Austin 1:8aa5cdb4ab67 55 txBufferTail = txBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 56 MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY);
Jonathan Austin 1:8aa5cdb4ab67 57 }
Jonathan Austin 1:8aa5cdb4ab67 58 }
Jonathan Austin 1:8aa5cdb4ab67 59
Jonathan Austin 1:8aa5cdb4ab67 60 /**
Jonathan Austin 1:8aa5cdb4ab67 61 * Constructor for the UARTService.
Jonathan Austin 1:8aa5cdb4ab67 62 * @param _ble an instance of BLEDevice
Jonathan Austin 1:8aa5cdb4ab67 63 * @param rxBufferSize the size of the rxBuffer
Jonathan Austin 1:8aa5cdb4ab67 64 * @param txBufferSize the size of the txBuffer
Jonathan Austin 1:8aa5cdb4ab67 65 *
Jonathan Austin 1:8aa5cdb4ab67 66 * @note defaults to 20
Jonathan Austin 1:8aa5cdb4ab67 67 */
Jonathan Austin 1:8aa5cdb4ab67 68 MicroBitUARTService::MicroBitUARTService(BLEDevice &_ble, uint8_t rxBufferSize, uint8_t txBufferSize) : ble(_ble)
Jonathan Austin 1:8aa5cdb4ab67 69 {
Jonathan Austin 1:8aa5cdb4ab67 70
Jonathan Austin 1:8aa5cdb4ab67 71 txBuffer = (uint8_t *)malloc(txBufferSize);
Jonathan Austin 1:8aa5cdb4ab67 72 rxBuffer = (uint8_t *)malloc(rxBufferSize);
Jonathan Austin 1:8aa5cdb4ab67 73
Jonathan Austin 1:8aa5cdb4ab67 74 rxBufferHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 75 rxBufferTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 76 this->rxBufferSize = rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 77
Jonathan Austin 1:8aa5cdb4ab67 78 txBufferHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 79 txBufferTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 80 this->txBufferSize = txBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 81
Jonathan Austin 1:8aa5cdb4ab67 82 GattCharacteristic txCharacteristic(UARTServiceTXCharacteristicUUID, rxBuffer, 1, rxBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
Jonathan Austin 1:8aa5cdb4ab67 83
Jonathan Austin 1:8aa5cdb4ab67 84 rxCharacteristic = new GattCharacteristic(UARTServiceRXCharacteristicUUID, txBuffer, 1, txBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
Jonathan Austin 1:8aa5cdb4ab67 85
Jonathan Austin 1:8aa5cdb4ab67 86 GattCharacteristic *charTable[] = {&txCharacteristic, rxCharacteristic};
Jonathan Austin 1:8aa5cdb4ab67 87
Jonathan Austin 1:8aa5cdb4ab67 88 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Jonathan Austin 1:8aa5cdb4ab67 89
Jonathan Austin 1:8aa5cdb4ab67 90 _ble.addService(uartService);
Jonathan Austin 1:8aa5cdb4ab67 91
Jonathan Austin 1:8aa5cdb4ab67 92 this->txCharacteristicHandle = txCharacteristic.getValueAttribute().getHandle();
Jonathan Austin 1:8aa5cdb4ab67 93
Jonathan Austin 1:8aa5cdb4ab67 94 _ble.gattServer().onDataWritten(this, &MicroBitUARTService::onDataWritten);
Jonathan Austin 1:8aa5cdb4ab67 95 _ble.gattServer().onConfirmationReceived(on_confirmation_received_callback);
Jonathan Austin 1:8aa5cdb4ab67 96 }
Jonathan Austin 1:8aa5cdb4ab67 97
Jonathan Austin 1:8aa5cdb4ab67 98 /**
Jonathan Austin 1:8aa5cdb4ab67 99 * A callback function for whenever a Bluetooth device writes to our TX characteristic.
Jonathan Austin 1:8aa5cdb4ab67 100 */
Jonathan Austin 1:8aa5cdb4ab67 101 void MicroBitUARTService::onDataWritten(const GattWriteCallbackParams *params) {
Jonathan Austin 1:8aa5cdb4ab67 102 if (params->handle == this->txCharacteristicHandle)
Jonathan Austin 1:8aa5cdb4ab67 103 {
Jonathan Austin 1:8aa5cdb4ab67 104 uint16_t bytesWritten = params->len;
Jonathan Austin 1:8aa5cdb4ab67 105
Jonathan Austin 1:8aa5cdb4ab67 106 for(int byteIterator = 0; byteIterator < bytesWritten; byteIterator++)
Jonathan Austin 1:8aa5cdb4ab67 107 {
Jonathan Austin 1:8aa5cdb4ab67 108 int newHead = (rxBufferHead + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 109
Jonathan Austin 1:8aa5cdb4ab67 110 if(newHead != rxBufferTail)
Jonathan Austin 1:8aa5cdb4ab67 111 {
Jonathan Austin 1:8aa5cdb4ab67 112 char c = params->data[byteIterator];
Jonathan Austin 1:8aa5cdb4ab67 113
Jonathan Austin 1:8aa5cdb4ab67 114 int delimeterOffset = 0;
Jonathan Austin 1:8aa5cdb4ab67 115 int delimLength = this->delimeters.length();
Jonathan Austin 1:8aa5cdb4ab67 116
Jonathan Austin 1:8aa5cdb4ab67 117 //iterate through our delimeters (if any) to see if there is a match
Jonathan Austin 1:8aa5cdb4ab67 118 while(delimeterOffset < delimLength)
Jonathan Austin 1:8aa5cdb4ab67 119 {
Jonathan Austin 1:8aa5cdb4ab67 120 //fire an event if there is to block any waiting fibers
Jonathan Austin 1:8aa5cdb4ab67 121 if(this->delimeters.charAt(delimeterOffset) == c)
Jonathan Austin 1:8aa5cdb4ab67 122 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 123
Jonathan Austin 1:8aa5cdb4ab67 124 delimeterOffset++;
Jonathan Austin 1:8aa5cdb4ab67 125 }
Jonathan Austin 1:8aa5cdb4ab67 126
Jonathan Austin 1:8aa5cdb4ab67 127 rxBuffer[rxBufferHead] = c;
Jonathan Austin 1:8aa5cdb4ab67 128
Jonathan Austin 1:8aa5cdb4ab67 129 rxBufferHead = newHead;
Jonathan Austin 1:8aa5cdb4ab67 130
Jonathan Austin 1:8aa5cdb4ab67 131 if(rxBufferHead == rxBuffHeadMatch)
Jonathan Austin 1:8aa5cdb4ab67 132 {
Jonathan Austin 1:8aa5cdb4ab67 133 rxBuffHeadMatch = -1;
Jonathan Austin 1:8aa5cdb4ab67 134 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 135 }
Jonathan Austin 1:8aa5cdb4ab67 136 }
Jonathan Austin 1:8aa5cdb4ab67 137 else
Jonathan Austin 1:8aa5cdb4ab67 138 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_RX_FULL);
Jonathan Austin 1:8aa5cdb4ab67 139 }
Jonathan Austin 1:8aa5cdb4ab67 140 }
Jonathan Austin 1:8aa5cdb4ab67 141 }
Jonathan Austin 1:8aa5cdb4ab67 142
Jonathan Austin 1:8aa5cdb4ab67 143 /**
Jonathan Austin 1:8aa5cdb4ab67 144 * An internal method that copies values from a circular buffer to a linear buffer.
Jonathan Austin 1:8aa5cdb4ab67 145 *
Jonathan Austin 1:8aa5cdb4ab67 146 * @param circularBuff a pointer to the source circular buffer
Jonathan Austin 1:8aa5cdb4ab67 147 * @param circularBuffSize the size of the circular buffer
Jonathan Austin 1:8aa5cdb4ab67 148 * @param linearBuff a pointer to the destination linear buffer
Jonathan Austin 1:8aa5cdb4ab67 149 * @param tailPosition the tail position in the circular buffer you want to copy from
Jonathan Austin 1:8aa5cdb4ab67 150 * @param headPosition the head position in the circular buffer you want to copy to
Jonathan Austin 1:8aa5cdb4ab67 151 *
Jonathan Austin 1:8aa5cdb4ab67 152 * @note this method assumes that the linear buffer has the appropriate amount of
Jonathan Austin 1:8aa5cdb4ab67 153 * memory to contain the copy operation
Jonathan Austin 1:8aa5cdb4ab67 154 */
Jonathan Austin 1:8aa5cdb4ab67 155 void MicroBitUARTService::circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition)
Jonathan Austin 1:8aa5cdb4ab67 156 {
Jonathan Austin 1:8aa5cdb4ab67 157 int toBuffIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 158
Jonathan Austin 1:8aa5cdb4ab67 159 while(tailPosition != headPosition)
Jonathan Austin 1:8aa5cdb4ab67 160 {
Jonathan Austin 1:8aa5cdb4ab67 161 linearBuff[toBuffIndex++] = circularBuff[tailPosition];
Jonathan Austin 1:8aa5cdb4ab67 162
Jonathan Austin 1:8aa5cdb4ab67 163 tailPosition = (tailPosition + 1) % circularBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 164 }
Jonathan Austin 1:8aa5cdb4ab67 165 }
Jonathan Austin 1:8aa5cdb4ab67 166
Jonathan Austin 1:8aa5cdb4ab67 167 /**
Jonathan Austin 1:8aa5cdb4ab67 168 * Retreives a single character from our RxBuffer.
Jonathan Austin 1:8aa5cdb4ab67 169 *
Jonathan Austin 1:8aa5cdb4ab67 170 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 171 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 172 *
Jonathan Austin 1:8aa5cdb4ab67 173 * ASYNC - Will attempt to read a single character, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 174 *
Jonathan Austin 1:8aa5cdb4ab67 175 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 176 *
Jonathan Austin 1:8aa5cdb4ab67 177 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 178 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 179 *
Jonathan Austin 1:8aa5cdb4ab67 180 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, a character or MICROBIT_NO_DATA
Jonathan Austin 1:8aa5cdb4ab67 181 */
Jonathan Austin 1:8aa5cdb4ab67 182 int MicroBitUARTService::getc(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 183 {
Jonathan Austin 1:8aa5cdb4ab67 184 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 185 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 186
Jonathan Austin 1:8aa5cdb4ab67 187 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 188 {
Jonathan Austin 1:8aa5cdb4ab67 189 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 190 return MICROBIT_NO_DATA;
Jonathan Austin 1:8aa5cdb4ab67 191 }
Jonathan Austin 1:8aa5cdb4ab67 192
Jonathan Austin 1:8aa5cdb4ab67 193 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 194 {
Jonathan Austin 1:8aa5cdb4ab67 195 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 196 eventAfter(1, mode);
Jonathan Austin 1:8aa5cdb4ab67 197 }
Jonathan Austin 1:8aa5cdb4ab67 198
Jonathan Austin 1:8aa5cdb4ab67 199 char c = rxBuffer[rxBufferTail];
Jonathan Austin 1:8aa5cdb4ab67 200
Jonathan Austin 1:8aa5cdb4ab67 201 rxBufferTail = (rxBufferTail + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 202
Jonathan Austin 1:8aa5cdb4ab67 203 return c;
Jonathan Austin 1:8aa5cdb4ab67 204 }
Jonathan Austin 1:8aa5cdb4ab67 205
Jonathan Austin 1:8aa5cdb4ab67 206 /**
Jonathan Austin 1:8aa5cdb4ab67 207 * places a single character into our transmission buffer,
Jonathan Austin 1:8aa5cdb4ab67 208 *
Jonathan Austin 1:8aa5cdb4ab67 209 * @param c the character to transmit
Jonathan Austin 1:8aa5cdb4ab67 210 *
Jonathan Austin 1:8aa5cdb4ab67 211 * @return the number of characters written (0, or 1).
Jonathan Austin 1:8aa5cdb4ab67 212 */
Jonathan Austin 1:8aa5cdb4ab67 213 int MicroBitUARTService::putc(char c)
Jonathan Austin 1:8aa5cdb4ab67 214 {
Jonathan Austin 1:8aa5cdb4ab67 215 return (send((uint8_t *)&c, 1) == 1) ? 1 : EOF;
Jonathan Austin 1:8aa5cdb4ab67 216 }
Jonathan Austin 1:8aa5cdb4ab67 217
Jonathan Austin 1:8aa5cdb4ab67 218 /**
Jonathan Austin 1:8aa5cdb4ab67 219 * Copies characters into the buffer used for Transmitting to the central device.
Jonathan Austin 1:8aa5cdb4ab67 220 *
Jonathan Austin 1:8aa5cdb4ab67 221 * @param buf a buffer containing length number of bytes.
Jonathan Austin 1:8aa5cdb4ab67 222 * @param length the size of the buffer.
Jonathan Austin 1:8aa5cdb4ab67 223 *
Jonathan Austin 1:8aa5cdb4ab67 224 * @return the number of characters copied into the buffer
Jonathan Austin 1:8aa5cdb4ab67 225 *
Jonathan Austin 1:8aa5cdb4ab67 226 * @note no modes for sending are available at the moment, due to interrupt overhead.
Jonathan Austin 1:8aa5cdb4ab67 227 */
Jonathan Austin 1:8aa5cdb4ab67 228 int MicroBitUARTService::send(const uint8_t *buf, int length)
Jonathan Austin 1:8aa5cdb4ab67 229 {
Jonathan Austin 1:8aa5cdb4ab67 230 if(length < 1)
Jonathan Austin 1:8aa5cdb4ab67 231 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 232
Jonathan Austin 1:8aa5cdb4ab67 233 int bytesWritten = 0;
Jonathan Austin 1:8aa5cdb4ab67 234
Jonathan Austin 1:8aa5cdb4ab67 235 if (ble.getGapState().connected) {
Jonathan Austin 1:8aa5cdb4ab67 236
Jonathan Austin 1:8aa5cdb4ab67 237 for(int bufferIterator = 0; bufferIterator < length; bufferIterator++)
Jonathan Austin 1:8aa5cdb4ab67 238 {
Jonathan Austin 1:8aa5cdb4ab67 239 int nextHead = (txBufferHead + 1) % txBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 240
Jonathan Austin 1:8aa5cdb4ab67 241 if(nextHead != txBufferTail)
Jonathan Austin 1:8aa5cdb4ab67 242 {
Jonathan Austin 1:8aa5cdb4ab67 243 txBuffer[txBufferHead] = buf[bufferIterator];
Jonathan Austin 1:8aa5cdb4ab67 244
Jonathan Austin 1:8aa5cdb4ab67 245 txBufferHead = nextHead;
Jonathan Austin 1:8aa5cdb4ab67 246
Jonathan Austin 1:8aa5cdb4ab67 247 bytesWritten++;
Jonathan Austin 1:8aa5cdb4ab67 248 }
Jonathan Austin 1:8aa5cdb4ab67 249 }
Jonathan Austin 1:8aa5cdb4ab67 250
Jonathan Austin 1:8aa5cdb4ab67 251 int size = txBufferedSize();
Jonathan Austin 1:8aa5cdb4ab67 252
Jonathan Austin 1:8aa5cdb4ab67 253 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:8aa5cdb4ab67 254 SERIAL_DEBUG->printf("tx size: %d", size);
Jonathan Austin 1:8aa5cdb4ab67 255 #endif
Jonathan Austin 1:8aa5cdb4ab67 256
LancasterUniversity 3:d86a4ddc1867 257 uint8_t temp[size];
Jonathan Austin 1:8aa5cdb4ab67 258
LancasterUniversity 8:ec4465853952 259 memclr(&temp, size);
LancasterUniversity 8:ec4465853952 260
Jonathan Austin 1:8aa5cdb4ab67 261 circularCopy(txBuffer, txBufferSize, temp, txBufferTail, txBufferHead);
Jonathan Austin 1:8aa5cdb4ab67 262
Jonathan Austin 1:8aa5cdb4ab67 263 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:8aa5cdb4ab67 264 for(int i = 0; i < size; i++)
Jonathan Austin 1:8aa5cdb4ab67 265 SERIAL_DEBUG->printf("%c",temp[i]);
Jonathan Austin 1:8aa5cdb4ab67 266 #endif
Jonathan Austin 1:8aa5cdb4ab67 267
Jonathan Austin 1:8aa5cdb4ab67 268 ble.gattServer().write(rxCharacteristic->getValueAttribute().getHandle(), temp, size);
Jonathan Austin 1:8aa5cdb4ab67 269 }
Jonathan Austin 1:8aa5cdb4ab67 270
Jonathan Austin 1:8aa5cdb4ab67 271 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:8aa5cdb4ab67 272 SERIAL_DEBUG->printf("written: %d \r\n",bytesWritten);
Jonathan Austin 1:8aa5cdb4ab67 273 #endif
Jonathan Austin 1:8aa5cdb4ab67 274
Jonathan Austin 1:8aa5cdb4ab67 275 return bytesWritten;
Jonathan Austin 1:8aa5cdb4ab67 276 }
Jonathan Austin 1:8aa5cdb4ab67 277
Jonathan Austin 1:8aa5cdb4ab67 278 /**
Jonathan Austin 1:8aa5cdb4ab67 279 * Copies characters into the buffer used for Transmitting to the central device.
Jonathan Austin 1:8aa5cdb4ab67 280 *
Jonathan Austin 1:8aa5cdb4ab67 281 * @param s the string to transmit
Jonathan Austin 1:8aa5cdb4ab67 282 *
Jonathan Austin 1:8aa5cdb4ab67 283 * @return the number of characters copied into the buffer
Jonathan Austin 1:8aa5cdb4ab67 284 *
Jonathan Austin 1:8aa5cdb4ab67 285 * @note no modes for sending are available at the moment, due to interrupt overhead.
Jonathan Austin 1:8aa5cdb4ab67 286 */
Jonathan Austin 1:8aa5cdb4ab67 287 int MicroBitUARTService::send(ManagedString s)
Jonathan Austin 1:8aa5cdb4ab67 288 {
Jonathan Austin 1:8aa5cdb4ab67 289 return send((uint8_t *)s.toCharArray(), s.length());
Jonathan Austin 1:8aa5cdb4ab67 290 }
Jonathan Austin 1:8aa5cdb4ab67 291
Jonathan Austin 1:8aa5cdb4ab67 292 /**
Jonathan Austin 1:8aa5cdb4ab67 293 * Reads a number of characters from the rxBuffer and fills user given buffer.
Jonathan Austin 1:8aa5cdb4ab67 294 *
Jonathan Austin 1:8aa5cdb4ab67 295 * @param buf a pointer to a buffer of len bytes.
Jonathan Austin 1:8aa5cdb4ab67 296 * @param len the size of the user allocated buffer
Jonathan Austin 1:8aa5cdb4ab67 297 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 298 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 299 *
Jonathan Austin 1:8aa5cdb4ab67 300 * ASYNC - Will attempt to read all available characters, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 301 * until the buffer limit is reached
Jonathan Austin 1:8aa5cdb4ab67 302 *
Jonathan Austin 1:8aa5cdb4ab67 303 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 304 *
Jonathan Austin 1:8aa5cdb4ab67 305 * SYNC_SLEEP - Will first of all determine whether the given number of characters
Jonathan Austin 1:8aa5cdb4ab67 306 * are available in our buffer, if not, it will set an event and sleep
Jonathan Austin 1:8aa5cdb4ab67 307 * until the number of characters are avaialable.
Jonathan Austin 1:8aa5cdb4ab67 308 *
Jonathan Austin 1:8aa5cdb4ab67 309 * @return the number of characters digested
Jonathan Austin 1:8aa5cdb4ab67 310 */
Jonathan Austin 1:8aa5cdb4ab67 311 int MicroBitUARTService::read(uint8_t *buf, int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 312 {
Jonathan Austin 1:8aa5cdb4ab67 313 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 314 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 315
Jonathan Austin 1:8aa5cdb4ab67 316 int i = 0;
Jonathan Austin 1:8aa5cdb4ab67 317
Jonathan Austin 1:8aa5cdb4ab67 318 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 319 {
Jonathan Austin 1:8aa5cdb4ab67 320 int c;
Jonathan Austin 1:8aa5cdb4ab67 321
Jonathan Austin 1:8aa5cdb4ab67 322 while((c = getc(mode)) > 0 && i < len)
Jonathan Austin 1:8aa5cdb4ab67 323 {
Jonathan Austin 1:8aa5cdb4ab67 324 buf[i] = c;
Jonathan Austin 1:8aa5cdb4ab67 325 i++;
Jonathan Austin 1:8aa5cdb4ab67 326 }
Jonathan Austin 1:8aa5cdb4ab67 327 }
Jonathan Austin 1:8aa5cdb4ab67 328
Jonathan Austin 1:8aa5cdb4ab67 329 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 330 {
Jonathan Austin 1:8aa5cdb4ab67 331 if(len > rxBufferedSize())
Jonathan Austin 1:8aa5cdb4ab67 332 eventAfter(len - rxBufferedSize(), mode);
Jonathan Austin 1:8aa5cdb4ab67 333
Jonathan Austin 1:8aa5cdb4ab67 334 while(i < len)
Jonathan Austin 1:8aa5cdb4ab67 335 {
Jonathan Austin 1:8aa5cdb4ab67 336 buf[i] = (char)getc(mode);
Jonathan Austin 1:8aa5cdb4ab67 337 i++;
Jonathan Austin 1:8aa5cdb4ab67 338 }
Jonathan Austin 1:8aa5cdb4ab67 339 }
Jonathan Austin 1:8aa5cdb4ab67 340
Jonathan Austin 1:8aa5cdb4ab67 341 return i;
Jonathan Austin 1:8aa5cdb4ab67 342 }
Jonathan Austin 1:8aa5cdb4ab67 343
Jonathan Austin 1:8aa5cdb4ab67 344 /**
Jonathan Austin 1:8aa5cdb4ab67 345 * Reads a number of characters from the rxBuffer and returns them as a ManagedString
Jonathan Austin 1:8aa5cdb4ab67 346 *
Jonathan Austin 1:8aa5cdb4ab67 347 * @param len the number of characters to read.
Jonathan Austin 1:8aa5cdb4ab67 348 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 349 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 350 *
Jonathan Austin 1:8aa5cdb4ab67 351 * ASYNC - Will attempt to read all available characters, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 352 * until the buffer limit is reached
Jonathan Austin 1:8aa5cdb4ab67 353 *
Jonathan Austin 1:8aa5cdb4ab67 354 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 355 *
Jonathan Austin 1:8aa5cdb4ab67 356 * SYNC_SLEEP - Will first of all determine whether the given number of characters
Jonathan Austin 1:8aa5cdb4ab67 357 * are available in our buffer, if not, it will set an event and sleep
Jonathan Austin 1:8aa5cdb4ab67 358 * until the number of characters are avaialable.
Jonathan Austin 1:8aa5cdb4ab67 359 *
Jonathan Austin 1:8aa5cdb4ab67 360 * @return an empty ManagedString on error, or a ManagedString containing characters
Jonathan Austin 1:8aa5cdb4ab67 361 */
Jonathan Austin 1:8aa5cdb4ab67 362 ManagedString MicroBitUARTService::read(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 363 {
LancasterUniversity 3:d86a4ddc1867 364 uint8_t buf[len + 1];
Jonathan Austin 1:8aa5cdb4ab67 365
LancasterUniversity 8:ec4465853952 366 memclr(&buf, len + 1);
LancasterUniversity 8:ec4465853952 367
Jonathan Austin 1:8aa5cdb4ab67 368 int ret = read(buf, len, mode);
Jonathan Austin 1:8aa5cdb4ab67 369
Jonathan Austin 1:8aa5cdb4ab67 370 if(ret < 1)
Jonathan Austin 1:8aa5cdb4ab67 371 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 372
Jonathan Austin 1:8aa5cdb4ab67 373 return ManagedString((const char *)buf);
Jonathan Austin 1:8aa5cdb4ab67 374 }
Jonathan Austin 1:8aa5cdb4ab67 375
Jonathan Austin 1:8aa5cdb4ab67 376 /**
Jonathan Austin 1:8aa5cdb4ab67 377 * Reads characters until a character matches one of the given delimeters
Jonathan Austin 1:8aa5cdb4ab67 378 *
Jonathan Austin 1:8aa5cdb4ab67 379 * @param delimeters the number of characters to match against
Jonathan Austin 1:8aa5cdb4ab67 380 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 381 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 382 *
Jonathan Austin 1:8aa5cdb4ab67 383 * ASYNC - Will attempt read the immediate buffer, and look for a match.
Jonathan Austin 1:8aa5cdb4ab67 384 * If there isn't, an empty ManagedString will be returned.
Jonathan Austin 1:8aa5cdb4ab67 385 *
Jonathan Austin 1:8aa5cdb4ab67 386 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 387 *
Jonathan Austin 1:8aa5cdb4ab67 388 * SYNC_SLEEP - Will first of all consider the characters in the immediate buffer,
Jonathan Austin 1:8aa5cdb4ab67 389 * if a match is not found, it will block on an event, fired when a
Jonathan Austin 1:8aa5cdb4ab67 390 * character is matched.
Jonathan Austin 1:8aa5cdb4ab67 391 *
Jonathan Austin 1:8aa5cdb4ab67 392 * @return an empty ManagedString on error, or a ManagedString containing characters
Jonathan Austin 1:8aa5cdb4ab67 393 */
Jonathan Austin 1:8aa5cdb4ab67 394 ManagedString MicroBitUARTService::readUntil(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 395 {
Jonathan Austin 1:8aa5cdb4ab67 396 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 397 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 398
Jonathan Austin 1:8aa5cdb4ab67 399 int localTail = rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 400 int preservedTail = rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 401
Jonathan Austin 1:8aa5cdb4ab67 402 int foundIndex = -1;
Jonathan Austin 1:8aa5cdb4ab67 403
Jonathan Austin 1:8aa5cdb4ab67 404 //ASYNC mode just iterates through our stored characters checking for any matches.
Jonathan Austin 1:8aa5cdb4ab67 405 while(localTail != rxBufferHead && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 406 {
Jonathan Austin 1:8aa5cdb4ab67 407 //we use localTail to prevent modification of the actual tail.
Jonathan Austin 1:8aa5cdb4ab67 408 char c = rxBuffer[localTail];
Jonathan Austin 1:8aa5cdb4ab67 409
Jonathan Austin 1:8aa5cdb4ab67 410 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 411 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 412 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 413
Jonathan Austin 1:8aa5cdb4ab67 414 localTail = (localTail + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 415 }
Jonathan Austin 1:8aa5cdb4ab67 416
Jonathan Austin 1:8aa5cdb4ab67 417 //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a
Jonathan Austin 1:8aa5cdb4ab67 418 //matching character.
Jonathan Austin 1:8aa5cdb4ab67 419 if(mode == SYNC_SLEEP && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 420 {
Jonathan Austin 1:8aa5cdb4ab67 421 eventOn(delimeters, mode);
Jonathan Austin 1:8aa5cdb4ab67 422
Jonathan Austin 1:8aa5cdb4ab67 423 foundIndex = rxBufferHead - 1;
Jonathan Austin 1:8aa5cdb4ab67 424
Jonathan Austin 1:8aa5cdb4ab67 425 this->delimeters = ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 426 }
Jonathan Austin 1:8aa5cdb4ab67 427
Jonathan Austin 1:8aa5cdb4ab67 428 if(foundIndex >= 0)
Jonathan Austin 1:8aa5cdb4ab67 429 {
Jonathan Austin 1:8aa5cdb4ab67 430 //calculate our local buffer size
Jonathan Austin 1:8aa5cdb4ab67 431 int localBuffSize = (preservedTail > foundIndex) ? (rxBufferSize - preservedTail) + foundIndex : foundIndex - preservedTail;
Jonathan Austin 1:8aa5cdb4ab67 432
LancasterUniversity 3:d86a4ddc1867 433 uint8_t localBuff[localBuffSize + 1];
Jonathan Austin 1:8aa5cdb4ab67 434
LancasterUniversity 8:ec4465853952 435 memclr(&localBuff, localBuffSize + 1);
LancasterUniversity 8:ec4465853952 436
Jonathan Austin 1:8aa5cdb4ab67 437 circularCopy(rxBuffer, rxBufferSize, localBuff, preservedTail, foundIndex);
Jonathan Austin 1:8aa5cdb4ab67 438
Jonathan Austin 1:8aa5cdb4ab67 439 //plus one for the character we listened for...
Jonathan Austin 1:8aa5cdb4ab67 440 rxBufferTail = (rxBufferTail + localBuffSize + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 441
Jonathan Austin 1:8aa5cdb4ab67 442 return ManagedString((char *)localBuff, localBuffSize);
Jonathan Austin 1:8aa5cdb4ab67 443 }
Jonathan Austin 1:8aa5cdb4ab67 444
Jonathan Austin 1:8aa5cdb4ab67 445 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 446 }
Jonathan Austin 1:8aa5cdb4ab67 447
Jonathan Austin 1:8aa5cdb4ab67 448 /**
Jonathan Austin 1:8aa5cdb4ab67 449 * Configures an event to be fired on a match with one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 450 *
Jonathan Austin 1:8aa5cdb4ab67 451 * @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 452 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 453 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 454 *
Jonathan Austin 1:8aa5cdb4ab67 455 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 456 *
Jonathan Austin 1:8aa5cdb4ab67 457 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 458 *
Jonathan Austin 1:8aa5cdb4ab67 459 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 460 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 461 *
Jonathan Austin 1:8aa5cdb4ab67 462 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 463 *
Jonathan Austin 1:8aa5cdb4ab67 464 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 465 */
Jonathan Austin 1:8aa5cdb4ab67 466 int MicroBitUARTService::eventOn(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 467 {
Jonathan Austin 1:8aa5cdb4ab67 468 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 469 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 470
Jonathan Austin 1:8aa5cdb4ab67 471 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 472 this->delimeters = delimeters;
Jonathan Austin 1:8aa5cdb4ab67 473
Jonathan Austin 1:8aa5cdb4ab67 474 //block!
Jonathan Austin 1:8aa5cdb4ab67 475 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 476 fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 477
Jonathan Austin 1:8aa5cdb4ab67 478 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 479 }
Jonathan Austin 1:8aa5cdb4ab67 480
Jonathan Austin 1:8aa5cdb4ab67 481 /**
Jonathan Austin 1:8aa5cdb4ab67 482 * Configures an event to be fired after "len" characters.
Jonathan Austin 1:8aa5cdb4ab67 483 *
Jonathan Austin 1:8aa5cdb4ab67 484 * @param len the number of characters to wait before triggering the event
Jonathan Austin 1:8aa5cdb4ab67 485 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 486 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 487 *
Jonathan Austin 1:8aa5cdb4ab67 488 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 489 *
Jonathan Austin 1:8aa5cdb4ab67 490 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 491 *
Jonathan Austin 1:8aa5cdb4ab67 492 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 493 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 494 *
Jonathan Austin 1:8aa5cdb4ab67 495 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 496 */
Jonathan Austin 1:8aa5cdb4ab67 497 int MicroBitUARTService::eventAfter(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 498 {
Jonathan Austin 1:8aa5cdb4ab67 499 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 500 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 501
Jonathan Austin 1:8aa5cdb4ab67 502 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 503 this->rxBuffHeadMatch = (rxBufferHead + len) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 504
Jonathan Austin 1:8aa5cdb4ab67 505 //block!
Jonathan Austin 1:8aa5cdb4ab67 506 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 507 fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 508
Jonathan Austin 1:8aa5cdb4ab67 509 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 510 }
Jonathan Austin 1:8aa5cdb4ab67 511
Jonathan Austin 1:8aa5cdb4ab67 512 /**
Jonathan Austin 1:8aa5cdb4ab67 513 * Determines if we have space in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 514 *
Jonathan Austin 1:8aa5cdb4ab67 515 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 516 *
Jonathan Austin 1:8aa5cdb4ab67 517 * @note the reason we do not wrap the super's readable() method is so that we
Jonathan Austin 1:8aa5cdb4ab67 518 * don't interfere with communities that use manual calls to uBit.serial.readable()
Jonathan Austin 1:8aa5cdb4ab67 519 */
Jonathan Austin 1:8aa5cdb4ab67 520 int MicroBitUARTService::isReadable()
Jonathan Austin 1:8aa5cdb4ab67 521 {
Jonathan Austin 1:8aa5cdb4ab67 522 return (rxBufferTail != rxBufferHead) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 523 }
Jonathan Austin 1:8aa5cdb4ab67 524
Jonathan Austin 1:8aa5cdb4ab67 525 /**
Jonathan Austin 1:8aa5cdb4ab67 526 * @return The currently buffered number of bytes in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 527 */
Jonathan Austin 1:8aa5cdb4ab67 528 int MicroBitUARTService::rxBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 529 {
Jonathan Austin 1:8aa5cdb4ab67 530 if(rxBufferTail > rxBufferHead)
Jonathan Austin 1:8aa5cdb4ab67 531 return (rxBufferSize - rxBufferTail) + rxBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 532
Jonathan Austin 1:8aa5cdb4ab67 533 return rxBufferHead - rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 534 }
Jonathan Austin 1:8aa5cdb4ab67 535
Jonathan Austin 1:8aa5cdb4ab67 536 /**
Jonathan Austin 1:8aa5cdb4ab67 537 * @return The currently buffered number of bytes in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 538 */
Jonathan Austin 1:8aa5cdb4ab67 539 int MicroBitUARTService::txBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 540 {
Jonathan Austin 1:8aa5cdb4ab67 541 if(txBufferTail > txBufferHead)
Jonathan Austin 1:8aa5cdb4ab67 542 return (txBufferSize - txBufferTail) + txBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 543
Jonathan Austin 1:8aa5cdb4ab67 544 return txBufferHead - txBufferTail;
LancasterUniversity 3:d86a4ddc1867 545 }