fork

Dependencies:   BLE_API mbed-dev-bin nRF51822

Dependents:   microbit

Fork of microbit-dal by Lancaster University

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:18:38 2016 +0100
Revision:
58:2ac8d45f1b08
Parent:
29:62f8b007debf
Child:
65:f7ebabf23e15
Synchronized with git rev bf58aac7

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
LancasterUniversity 58:2ac8d45f1b08 43 static GattCharacteristic* txCharacteristic = NULL;
Jonathan Austin 1:8aa5cdb4ab67 44
Jonathan Austin 1:8aa5cdb4ab67 45 /**
LancasterUniversity 58:2ac8d45f1b08 46 * A callback function for whenever a Bluetooth device consumes our TX Buffer
Jonathan Austin 1:8aa5cdb4ab67 47 */
LancasterUniversity 58:2ac8d45f1b08 48 void on_confirmation(uint16_t handle)
Jonathan Austin 1:8aa5cdb4ab67 49 {
LancasterUniversity 58:2ac8d45f1b08 50 if(handle == txCharacteristic->getValueAttribute().getHandle())
Jonathan Austin 1:8aa5cdb4ab67 51 {
Jonathan Austin 1:8aa5cdb4ab67 52 txBufferTail = txBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 53 MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY);
Jonathan Austin 1:8aa5cdb4ab67 54 }
Jonathan Austin 1:8aa5cdb4ab67 55 }
Jonathan Austin 1:8aa5cdb4ab67 56
Jonathan Austin 1:8aa5cdb4ab67 57 /**
Jonathan Austin 1:8aa5cdb4ab67 58 * Constructor for the UARTService.
Jonathan Austin 1:8aa5cdb4ab67 59 * @param _ble an instance of BLEDevice
Jonathan Austin 1:8aa5cdb4ab67 60 * @param rxBufferSize the size of the rxBuffer
Jonathan Austin 1:8aa5cdb4ab67 61 * @param txBufferSize the size of the txBuffer
Jonathan Austin 1:8aa5cdb4ab67 62 *
Jonathan Austin 1:8aa5cdb4ab67 63 * @note defaults to 20
Jonathan Austin 1:8aa5cdb4ab67 64 */
Jonathan Austin 1:8aa5cdb4ab67 65 MicroBitUARTService::MicroBitUARTService(BLEDevice &_ble, uint8_t rxBufferSize, uint8_t txBufferSize) : ble(_ble)
Jonathan Austin 1:8aa5cdb4ab67 66 {
LancasterUniversity 29:62f8b007debf 67 rxBufferSize += 1;
LancasterUniversity 29:62f8b007debf 68 txBufferSize += 1;
Jonathan Austin 1:8aa5cdb4ab67 69
Jonathan Austin 1:8aa5cdb4ab67 70 txBuffer = (uint8_t *)malloc(txBufferSize);
Jonathan Austin 1:8aa5cdb4ab67 71 rxBuffer = (uint8_t *)malloc(rxBufferSize);
Jonathan Austin 1:8aa5cdb4ab67 72
Jonathan Austin 1:8aa5cdb4ab67 73 rxBufferHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 74 rxBufferTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 75 this->rxBufferSize = rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 76
Jonathan Austin 1:8aa5cdb4ab67 77 txBufferHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 78 txBufferTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 79 this->txBufferSize = txBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 80
LancasterUniversity 58:2ac8d45f1b08 81 GattCharacteristic rxCharacteristic(UARTServiceRXCharacteristicUUID, rxBuffer, 1, rxBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE_WITHOUT_RESPONSE);
Jonathan Austin 1:8aa5cdb4ab67 82
LancasterUniversity 58:2ac8d45f1b08 83 txCharacteristic = new GattCharacteristic(UARTServiceTXCharacteristicUUID, txBuffer, 1, txBufferSize, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
Jonathan Austin 1:8aa5cdb4ab67 84
LancasterUniversity 58:2ac8d45f1b08 85 GattCharacteristic *charTable[] = {txCharacteristic, &rxCharacteristic};
Jonathan Austin 1:8aa5cdb4ab67 86
Jonathan Austin 1:8aa5cdb4ab67 87 GattService uartService(UARTServiceUUID, charTable, sizeof(charTable) / sizeof(GattCharacteristic *));
Jonathan Austin 1:8aa5cdb4ab67 88
Jonathan Austin 1:8aa5cdb4ab67 89 _ble.addService(uartService);
Jonathan Austin 1:8aa5cdb4ab67 90
LancasterUniversity 58:2ac8d45f1b08 91 this->rxCharacteristicHandle = rxCharacteristic.getValueAttribute().getHandle();
Jonathan Austin 1:8aa5cdb4ab67 92
Jonathan Austin 1:8aa5cdb4ab67 93 _ble.gattServer().onDataWritten(this, &MicroBitUARTService::onDataWritten);
LancasterUniversity 58:2ac8d45f1b08 94 _ble.gattServer().onConfirmationReceived(on_confirmation);
Jonathan Austin 1:8aa5cdb4ab67 95 }
Jonathan Austin 1:8aa5cdb4ab67 96
Jonathan Austin 1:8aa5cdb4ab67 97 /**
LancasterUniversity 58:2ac8d45f1b08 98 * A callback function for whenever a Bluetooth device writes to our RX characteristic.
Jonathan Austin 1:8aa5cdb4ab67 99 */
Jonathan Austin 1:8aa5cdb4ab67 100 void MicroBitUARTService::onDataWritten(const GattWriteCallbackParams *params) {
LancasterUniversity 58:2ac8d45f1b08 101 if (params->handle == this->rxCharacteristicHandle)
Jonathan Austin 1:8aa5cdb4ab67 102 {
Jonathan Austin 1:8aa5cdb4ab67 103 uint16_t bytesWritten = params->len;
Jonathan Austin 1:8aa5cdb4ab67 104
Jonathan Austin 1:8aa5cdb4ab67 105 for(int byteIterator = 0; byteIterator < bytesWritten; byteIterator++)
Jonathan Austin 1:8aa5cdb4ab67 106 {
Jonathan Austin 1:8aa5cdb4ab67 107 int newHead = (rxBufferHead + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 108
Jonathan Austin 1:8aa5cdb4ab67 109 if(newHead != rxBufferTail)
Jonathan Austin 1:8aa5cdb4ab67 110 {
Jonathan Austin 1:8aa5cdb4ab67 111 char c = params->data[byteIterator];
Jonathan Austin 1:8aa5cdb4ab67 112
Jonathan Austin 1:8aa5cdb4ab67 113 int delimeterOffset = 0;
Jonathan Austin 1:8aa5cdb4ab67 114 int delimLength = this->delimeters.length();
Jonathan Austin 1:8aa5cdb4ab67 115
Jonathan Austin 1:8aa5cdb4ab67 116 //iterate through our delimeters (if any) to see if there is a match
Jonathan Austin 1:8aa5cdb4ab67 117 while(delimeterOffset < delimLength)
Jonathan Austin 1:8aa5cdb4ab67 118 {
Jonathan Austin 1:8aa5cdb4ab67 119 //fire an event if there is to block any waiting fibers
Jonathan Austin 1:8aa5cdb4ab67 120 if(this->delimeters.charAt(delimeterOffset) == c)
Jonathan Austin 1:8aa5cdb4ab67 121 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 122
Jonathan Austin 1:8aa5cdb4ab67 123 delimeterOffset++;
Jonathan Austin 1:8aa5cdb4ab67 124 }
Jonathan Austin 1:8aa5cdb4ab67 125
Jonathan Austin 1:8aa5cdb4ab67 126 rxBuffer[rxBufferHead] = c;
Jonathan Austin 1:8aa5cdb4ab67 127
Jonathan Austin 1:8aa5cdb4ab67 128 rxBufferHead = newHead;
Jonathan Austin 1:8aa5cdb4ab67 129
Jonathan Austin 1:8aa5cdb4ab67 130 if(rxBufferHead == rxBuffHeadMatch)
Jonathan Austin 1:8aa5cdb4ab67 131 {
Jonathan Austin 1:8aa5cdb4ab67 132 rxBuffHeadMatch = -1;
Jonathan Austin 1:8aa5cdb4ab67 133 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 134 }
Jonathan Austin 1:8aa5cdb4ab67 135 }
Jonathan Austin 1:8aa5cdb4ab67 136 else
Jonathan Austin 1:8aa5cdb4ab67 137 MicroBitEvent(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_RX_FULL);
Jonathan Austin 1:8aa5cdb4ab67 138 }
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 * An internal method that copies values from a circular buffer to a linear buffer.
Jonathan Austin 1:8aa5cdb4ab67 144 *
Jonathan Austin 1:8aa5cdb4ab67 145 * @param circularBuff a pointer to the source circular buffer
Jonathan Austin 1:8aa5cdb4ab67 146 * @param circularBuffSize the size of the circular buffer
Jonathan Austin 1:8aa5cdb4ab67 147 * @param linearBuff a pointer to the destination linear buffer
Jonathan Austin 1:8aa5cdb4ab67 148 * @param tailPosition the tail position in the circular buffer you want to copy from
Jonathan Austin 1:8aa5cdb4ab67 149 * @param headPosition the head position in the circular buffer you want to copy to
Jonathan Austin 1:8aa5cdb4ab67 150 *
Jonathan Austin 1:8aa5cdb4ab67 151 * @note this method assumes that the linear buffer has the appropriate amount of
Jonathan Austin 1:8aa5cdb4ab67 152 * memory to contain the copy operation
Jonathan Austin 1:8aa5cdb4ab67 153 */
Jonathan Austin 1:8aa5cdb4ab67 154 void MicroBitUARTService::circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition)
Jonathan Austin 1:8aa5cdb4ab67 155 {
Jonathan Austin 1:8aa5cdb4ab67 156 int toBuffIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 157
Jonathan Austin 1:8aa5cdb4ab67 158 while(tailPosition != headPosition)
Jonathan Austin 1:8aa5cdb4ab67 159 {
Jonathan Austin 1:8aa5cdb4ab67 160 linearBuff[toBuffIndex++] = circularBuff[tailPosition];
Jonathan Austin 1:8aa5cdb4ab67 161
Jonathan Austin 1:8aa5cdb4ab67 162 tailPosition = (tailPosition + 1) % circularBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 163 }
Jonathan Austin 1:8aa5cdb4ab67 164 }
Jonathan Austin 1:8aa5cdb4ab67 165
Jonathan Austin 1:8aa5cdb4ab67 166 /**
Jonathan Austin 1:8aa5cdb4ab67 167 * Retreives a single character from our RxBuffer.
Jonathan Austin 1:8aa5cdb4ab67 168 *
Jonathan Austin 1:8aa5cdb4ab67 169 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 170 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 171 *
Jonathan Austin 1:8aa5cdb4ab67 172 * ASYNC - Will attempt to read a single character, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 173 *
Jonathan Austin 1:8aa5cdb4ab67 174 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 175 *
Jonathan Austin 1:8aa5cdb4ab67 176 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 177 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 178 *
Jonathan Austin 1:8aa5cdb4ab67 179 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, a character or MICROBIT_NO_DATA
Jonathan Austin 1:8aa5cdb4ab67 180 */
Jonathan Austin 1:8aa5cdb4ab67 181 int MicroBitUARTService::getc(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 182 {
Jonathan Austin 1:8aa5cdb4ab67 183 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 184 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 185
Jonathan Austin 1:8aa5cdb4ab67 186 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 187 {
Jonathan Austin 1:8aa5cdb4ab67 188 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 189 return MICROBIT_NO_DATA;
Jonathan Austin 1:8aa5cdb4ab67 190 }
Jonathan Austin 1:8aa5cdb4ab67 191
Jonathan Austin 1:8aa5cdb4ab67 192 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 193 {
Jonathan Austin 1:8aa5cdb4ab67 194 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 195 eventAfter(1, mode);
Jonathan Austin 1:8aa5cdb4ab67 196 }
Jonathan Austin 1:8aa5cdb4ab67 197
Jonathan Austin 1:8aa5cdb4ab67 198 char c = rxBuffer[rxBufferTail];
Jonathan Austin 1:8aa5cdb4ab67 199
Jonathan Austin 1:8aa5cdb4ab67 200 rxBufferTail = (rxBufferTail + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 201
Jonathan Austin 1:8aa5cdb4ab67 202 return c;
Jonathan Austin 1:8aa5cdb4ab67 203 }
Jonathan Austin 1:8aa5cdb4ab67 204
Jonathan Austin 1:8aa5cdb4ab67 205 /**
Jonathan Austin 1:8aa5cdb4ab67 206 * places a single character into our transmission buffer,
Jonathan Austin 1:8aa5cdb4ab67 207 *
Jonathan Austin 1:8aa5cdb4ab67 208 * @param c the character to transmit
Jonathan Austin 1:8aa5cdb4ab67 209 *
LancasterUniversity 58:2ac8d45f1b08 210 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
LancasterUniversity 58:2ac8d45f1b08 211 * gives a different behaviour:
LancasterUniversity 58:2ac8d45f1b08 212 *
LancasterUniversity 58:2ac8d45f1b08 213 * ASYNC - Will copy as many characters as it can into the buffer for transmission,
LancasterUniversity 58:2ac8d45f1b08 214 * and return control to the user.
LancasterUniversity 58:2ac8d45f1b08 215 *
LancasterUniversity 58:2ac8d45f1b08 216 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
LancasterUniversity 58:2ac8d45f1b08 217 *
LancasterUniversity 58:2ac8d45f1b08 218 * SYNC_SLEEP - Will perform a cooperative blocking wait until all
LancasterUniversity 58:2ac8d45f1b08 219 * given characters have been received by the connected
LancasterUniversity 58:2ac8d45f1b08 220 * device.
LancasterUniversity 58:2ac8d45f1b08 221 *
LancasterUniversity 58:2ac8d45f1b08 222 * @return the number of characters written, or MICROBIT_NOT_SUPPORTED if there is
LancasterUniversity 58:2ac8d45f1b08 223 * no connected device, or the connected device has not enabled indications.
Jonathan Austin 1:8aa5cdb4ab67 224 */
LancasterUniversity 58:2ac8d45f1b08 225 int MicroBitUARTService::putc(char c, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 226 {
LancasterUniversity 58:2ac8d45f1b08 227 return (send((uint8_t *)&c, 1, mode) == 1) ? 1 : EOF;
Jonathan Austin 1:8aa5cdb4ab67 228 }
Jonathan Austin 1:8aa5cdb4ab67 229
Jonathan Austin 1:8aa5cdb4ab67 230 /**
Jonathan Austin 1:8aa5cdb4ab67 231 * Copies characters into the buffer used for Transmitting to the central device.
Jonathan Austin 1:8aa5cdb4ab67 232 *
Jonathan Austin 1:8aa5cdb4ab67 233 * @param buf a buffer containing length number of bytes.
Jonathan Austin 1:8aa5cdb4ab67 234 * @param length the size of the buffer.
LancasterUniversity 58:2ac8d45f1b08 235 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
LancasterUniversity 58:2ac8d45f1b08 236 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 237 *
LancasterUniversity 58:2ac8d45f1b08 238 * ASYNC - Will copy as many characters as it can into the buffer for transmission,
LancasterUniversity 58:2ac8d45f1b08 239 * and return control to the user.
LancasterUniversity 58:2ac8d45f1b08 240 *
LancasterUniversity 58:2ac8d45f1b08 241 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 242 *
LancasterUniversity 58:2ac8d45f1b08 243 * SYNC_SLEEP - Will perform a cooperative blocking wait until all
LancasterUniversity 58:2ac8d45f1b08 244 * given characters have been received by the connected
LancasterUniversity 58:2ac8d45f1b08 245 * device.
LancasterUniversity 58:2ac8d45f1b08 246 *
LancasterUniversity 58:2ac8d45f1b08 247 * @return the number of characters written, or MICROBIT_NOT_SUPPORTED if there is
LancasterUniversity 58:2ac8d45f1b08 248 * no connected device, or the connected device has not enabled indications.
Jonathan Austin 1:8aa5cdb4ab67 249 */
LancasterUniversity 58:2ac8d45f1b08 250 int MicroBitUARTService::send(const uint8_t *buf, int length, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 251 {
LancasterUniversity 58:2ac8d45f1b08 252 if(length < 1 || mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 253 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 254
LancasterUniversity 58:2ac8d45f1b08 255 bool updatesEnabled = false;
LancasterUniversity 58:2ac8d45f1b08 256
LancasterUniversity 58:2ac8d45f1b08 257 ble.gattServer().areUpdatesEnabled(*txCharacteristic, &updatesEnabled);
LancasterUniversity 58:2ac8d45f1b08 258
LancasterUniversity 58:2ac8d45f1b08 259 if(!ble.getGapState().connected && !updatesEnabled)
LancasterUniversity 58:2ac8d45f1b08 260 return MICROBIT_NOT_SUPPORTED;
LancasterUniversity 58:2ac8d45f1b08 261
Jonathan Austin 1:8aa5cdb4ab67 262 int bytesWritten = 0;
Jonathan Austin 1:8aa5cdb4ab67 263
LancasterUniversity 58:2ac8d45f1b08 264 while(bytesWritten < length && ble.getGapState().connected && updatesEnabled)
LancasterUniversity 58:2ac8d45f1b08 265 {
LancasterUniversity 58:2ac8d45f1b08 266 for(int bufferIterator = bytesWritten; bufferIterator < length; bufferIterator++)
Jonathan Austin 1:8aa5cdb4ab67 267 {
Jonathan Austin 1:8aa5cdb4ab67 268 int nextHead = (txBufferHead + 1) % txBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 269
Jonathan Austin 1:8aa5cdb4ab67 270 if(nextHead != txBufferTail)
Jonathan Austin 1:8aa5cdb4ab67 271 {
Jonathan Austin 1:8aa5cdb4ab67 272 txBuffer[txBufferHead] = buf[bufferIterator];
Jonathan Austin 1:8aa5cdb4ab67 273
Jonathan Austin 1:8aa5cdb4ab67 274 txBufferHead = nextHead;
Jonathan Austin 1:8aa5cdb4ab67 275
Jonathan Austin 1:8aa5cdb4ab67 276 bytesWritten++;
Jonathan Austin 1:8aa5cdb4ab67 277 }
Jonathan Austin 1:8aa5cdb4ab67 278 }
Jonathan Austin 1:8aa5cdb4ab67 279
Jonathan Austin 1:8aa5cdb4ab67 280 int size = txBufferedSize();
Jonathan Austin 1:8aa5cdb4ab67 281
LancasterUniversity 3:d86a4ddc1867 282 uint8_t temp[size];
Jonathan Austin 1:8aa5cdb4ab67 283
LancasterUniversity 8:ec4465853952 284 memclr(&temp, size);
LancasterUniversity 8:ec4465853952 285
Jonathan Austin 1:8aa5cdb4ab67 286 circularCopy(txBuffer, txBufferSize, temp, txBufferTail, txBufferHead);
Jonathan Austin 1:8aa5cdb4ab67 287
LancasterUniversity 58:2ac8d45f1b08 288
LancasterUniversity 58:2ac8d45f1b08 289 if(mode == SYNC_SLEEP)
LancasterUniversity 58:2ac8d45f1b08 290 fiber_wake_on_event(MICROBIT_ID_NOTIFY, MICROBIT_UART_S_EVT_TX_EMPTY);
LancasterUniversity 58:2ac8d45f1b08 291
LancasterUniversity 58:2ac8d45f1b08 292 ble.gattServer().write(txCharacteristic->getValueAttribute().getHandle(), temp, size);
Jonathan Austin 1:8aa5cdb4ab67 293
LancasterUniversity 58:2ac8d45f1b08 294 if(mode == SYNC_SLEEP)
LancasterUniversity 58:2ac8d45f1b08 295 schedule();
LancasterUniversity 58:2ac8d45f1b08 296 else
LancasterUniversity 58:2ac8d45f1b08 297 break;
Jonathan Austin 1:8aa5cdb4ab67 298
LancasterUniversity 58:2ac8d45f1b08 299 ble.gattServer().areUpdatesEnabled(*txCharacteristic, &updatesEnabled);
LancasterUniversity 58:2ac8d45f1b08 300 }
Jonathan Austin 1:8aa5cdb4ab67 301
Jonathan Austin 1:8aa5cdb4ab67 302 return bytesWritten;
Jonathan Austin 1:8aa5cdb4ab67 303 }
Jonathan Austin 1:8aa5cdb4ab67 304
Jonathan Austin 1:8aa5cdb4ab67 305 /**
Jonathan Austin 1:8aa5cdb4ab67 306 * Copies characters into the buffer used for Transmitting to the central device.
Jonathan Austin 1:8aa5cdb4ab67 307 *
Jonathan Austin 1:8aa5cdb4ab67 308 * @param s the string to transmit
LancasterUniversity 58:2ac8d45f1b08 309 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
LancasterUniversity 58:2ac8d45f1b08 310 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 311 *
LancasterUniversity 58:2ac8d45f1b08 312 * ASYNC - Will copy as many characters as it can into the buffer for transmission,
LancasterUniversity 58:2ac8d45f1b08 313 * and return control to the user.
LancasterUniversity 58:2ac8d45f1b08 314 *
LancasterUniversity 58:2ac8d45f1b08 315 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 316 *
LancasterUniversity 58:2ac8d45f1b08 317 * SYNC_SLEEP - Will perform a cooperative blocking wait until all
LancasterUniversity 58:2ac8d45f1b08 318 * given characters have been received by the connected
LancasterUniversity 58:2ac8d45f1b08 319 * device.
LancasterUniversity 58:2ac8d45f1b08 320 *
LancasterUniversity 58:2ac8d45f1b08 321 * @return the number of characters written, or MICROBIT_NOT_SUPPORTED if there is
LancasterUniversity 58:2ac8d45f1b08 322 * no connected device, or the connected device has not enabled indications.
Jonathan Austin 1:8aa5cdb4ab67 323 */
LancasterUniversity 58:2ac8d45f1b08 324 int MicroBitUARTService::send(ManagedString s, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 325 {
LancasterUniversity 58:2ac8d45f1b08 326 return send((uint8_t *)s.toCharArray(), s.length(), mode);
Jonathan Austin 1:8aa5cdb4ab67 327 }
Jonathan Austin 1:8aa5cdb4ab67 328
Jonathan Austin 1:8aa5cdb4ab67 329 /**
Jonathan Austin 1:8aa5cdb4ab67 330 * Reads a number of characters from the rxBuffer and fills user given buffer.
Jonathan Austin 1:8aa5cdb4ab67 331 *
Jonathan Austin 1:8aa5cdb4ab67 332 * @param buf a pointer to a buffer of len bytes.
Jonathan Austin 1:8aa5cdb4ab67 333 * @param len the size of the user allocated buffer
Jonathan Austin 1:8aa5cdb4ab67 334 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 335 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 336 *
Jonathan Austin 1:8aa5cdb4ab67 337 * ASYNC - Will attempt to read all available characters, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 338 * until the buffer limit is reached
Jonathan Austin 1:8aa5cdb4ab67 339 *
Jonathan Austin 1:8aa5cdb4ab67 340 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 341 *
Jonathan Austin 1:8aa5cdb4ab67 342 * SYNC_SLEEP - Will first of all determine whether the given number of characters
Jonathan Austin 1:8aa5cdb4ab67 343 * are available in our buffer, if not, it will set an event and sleep
Jonathan Austin 1:8aa5cdb4ab67 344 * until the number of characters are avaialable.
Jonathan Austin 1:8aa5cdb4ab67 345 *
Jonathan Austin 1:8aa5cdb4ab67 346 * @return the number of characters digested
Jonathan Austin 1:8aa5cdb4ab67 347 */
Jonathan Austin 1:8aa5cdb4ab67 348 int MicroBitUARTService::read(uint8_t *buf, int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 349 {
Jonathan Austin 1:8aa5cdb4ab67 350 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 351 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 352
Jonathan Austin 1:8aa5cdb4ab67 353 int i = 0;
Jonathan Austin 1:8aa5cdb4ab67 354
Jonathan Austin 1:8aa5cdb4ab67 355 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 356 {
Jonathan Austin 1:8aa5cdb4ab67 357 int c;
Jonathan Austin 1:8aa5cdb4ab67 358
Jonathan Austin 1:8aa5cdb4ab67 359 while((c = getc(mode)) > 0 && i < len)
Jonathan Austin 1:8aa5cdb4ab67 360 {
Jonathan Austin 1:8aa5cdb4ab67 361 buf[i] = c;
Jonathan Austin 1:8aa5cdb4ab67 362 i++;
Jonathan Austin 1:8aa5cdb4ab67 363 }
Jonathan Austin 1:8aa5cdb4ab67 364 }
Jonathan Austin 1:8aa5cdb4ab67 365
Jonathan Austin 1:8aa5cdb4ab67 366 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 367 {
Jonathan Austin 1:8aa5cdb4ab67 368 if(len > rxBufferedSize())
Jonathan Austin 1:8aa5cdb4ab67 369 eventAfter(len - rxBufferedSize(), mode);
Jonathan Austin 1:8aa5cdb4ab67 370
Jonathan Austin 1:8aa5cdb4ab67 371 while(i < len)
Jonathan Austin 1:8aa5cdb4ab67 372 {
Jonathan Austin 1:8aa5cdb4ab67 373 buf[i] = (char)getc(mode);
Jonathan Austin 1:8aa5cdb4ab67 374 i++;
Jonathan Austin 1:8aa5cdb4ab67 375 }
Jonathan Austin 1:8aa5cdb4ab67 376 }
Jonathan Austin 1:8aa5cdb4ab67 377
Jonathan Austin 1:8aa5cdb4ab67 378 return i;
Jonathan Austin 1:8aa5cdb4ab67 379 }
Jonathan Austin 1:8aa5cdb4ab67 380
Jonathan Austin 1:8aa5cdb4ab67 381 /**
Jonathan Austin 1:8aa5cdb4ab67 382 * Reads a number of characters from the rxBuffer and returns them as a ManagedString
Jonathan Austin 1:8aa5cdb4ab67 383 *
Jonathan Austin 1:8aa5cdb4ab67 384 * @param len the number of characters to read.
Jonathan Austin 1:8aa5cdb4ab67 385 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 386 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 387 *
Jonathan Austin 1:8aa5cdb4ab67 388 * ASYNC - Will attempt to read all available characters, and return immediately
Jonathan Austin 1:8aa5cdb4ab67 389 * until the buffer limit is reached
Jonathan Austin 1:8aa5cdb4ab67 390 *
Jonathan Austin 1:8aa5cdb4ab67 391 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 392 *
Jonathan Austin 1:8aa5cdb4ab67 393 * SYNC_SLEEP - Will first of all determine whether the given number of characters
Jonathan Austin 1:8aa5cdb4ab67 394 * are available in our buffer, if not, it will set an event and sleep
Jonathan Austin 1:8aa5cdb4ab67 395 * until the number of characters are avaialable.
Jonathan Austin 1:8aa5cdb4ab67 396 *
Jonathan Austin 1:8aa5cdb4ab67 397 * @return an empty ManagedString on error, or a ManagedString containing characters
Jonathan Austin 1:8aa5cdb4ab67 398 */
Jonathan Austin 1:8aa5cdb4ab67 399 ManagedString MicroBitUARTService::read(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 400 {
LancasterUniversity 3:d86a4ddc1867 401 uint8_t buf[len + 1];
Jonathan Austin 1:8aa5cdb4ab67 402
LancasterUniversity 8:ec4465853952 403 memclr(&buf, len + 1);
LancasterUniversity 8:ec4465853952 404
Jonathan Austin 1:8aa5cdb4ab67 405 int ret = read(buf, len, mode);
Jonathan Austin 1:8aa5cdb4ab67 406
Jonathan Austin 1:8aa5cdb4ab67 407 if(ret < 1)
Jonathan Austin 1:8aa5cdb4ab67 408 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 409
Jonathan Austin 1:8aa5cdb4ab67 410 return ManagedString((const char *)buf);
Jonathan Austin 1:8aa5cdb4ab67 411 }
Jonathan Austin 1:8aa5cdb4ab67 412
Jonathan Austin 1:8aa5cdb4ab67 413 /**
Jonathan Austin 1:8aa5cdb4ab67 414 * Reads characters until a character matches one of the given delimeters
Jonathan Austin 1:8aa5cdb4ab67 415 *
Jonathan Austin 1:8aa5cdb4ab67 416 * @param delimeters the number of characters to match against
Jonathan Austin 1:8aa5cdb4ab67 417 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 418 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 419 *
Jonathan Austin 1:8aa5cdb4ab67 420 * ASYNC - Will attempt read the immediate buffer, and look for a match.
Jonathan Austin 1:8aa5cdb4ab67 421 * If there isn't, an empty ManagedString will be returned.
Jonathan Austin 1:8aa5cdb4ab67 422 *
Jonathan Austin 1:8aa5cdb4ab67 423 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 424 *
Jonathan Austin 1:8aa5cdb4ab67 425 * SYNC_SLEEP - Will first of all consider the characters in the immediate buffer,
Jonathan Austin 1:8aa5cdb4ab67 426 * if a match is not found, it will block on an event, fired when a
Jonathan Austin 1:8aa5cdb4ab67 427 * character is matched.
Jonathan Austin 1:8aa5cdb4ab67 428 *
Jonathan Austin 1:8aa5cdb4ab67 429 * @return an empty ManagedString on error, or a ManagedString containing characters
Jonathan Austin 1:8aa5cdb4ab67 430 */
Jonathan Austin 1:8aa5cdb4ab67 431 ManagedString MicroBitUARTService::readUntil(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 432 {
Jonathan Austin 1:8aa5cdb4ab67 433 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 434 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 435
Jonathan Austin 1:8aa5cdb4ab67 436 int localTail = rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 437 int preservedTail = rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 438
Jonathan Austin 1:8aa5cdb4ab67 439 int foundIndex = -1;
Jonathan Austin 1:8aa5cdb4ab67 440
Jonathan Austin 1:8aa5cdb4ab67 441 //ASYNC mode just iterates through our stored characters checking for any matches.
Jonathan Austin 1:8aa5cdb4ab67 442 while(localTail != rxBufferHead && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 443 {
Jonathan Austin 1:8aa5cdb4ab67 444 //we use localTail to prevent modification of the actual tail.
Jonathan Austin 1:8aa5cdb4ab67 445 char c = rxBuffer[localTail];
Jonathan Austin 1:8aa5cdb4ab67 446
Jonathan Austin 1:8aa5cdb4ab67 447 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 448 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 449 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 450
Jonathan Austin 1:8aa5cdb4ab67 451 localTail = (localTail + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 452 }
Jonathan Austin 1:8aa5cdb4ab67 453
Jonathan Austin 1:8aa5cdb4ab67 454 //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a
Jonathan Austin 1:8aa5cdb4ab67 455 //matching character.
Jonathan Austin 1:8aa5cdb4ab67 456 if(mode == SYNC_SLEEP && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 457 {
Jonathan Austin 1:8aa5cdb4ab67 458 eventOn(delimeters, mode);
Jonathan Austin 1:8aa5cdb4ab67 459
Jonathan Austin 1:8aa5cdb4ab67 460 foundIndex = rxBufferHead - 1;
Jonathan Austin 1:8aa5cdb4ab67 461
Jonathan Austin 1:8aa5cdb4ab67 462 this->delimeters = ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 463 }
Jonathan Austin 1:8aa5cdb4ab67 464
Jonathan Austin 1:8aa5cdb4ab67 465 if(foundIndex >= 0)
Jonathan Austin 1:8aa5cdb4ab67 466 {
Jonathan Austin 1:8aa5cdb4ab67 467 //calculate our local buffer size
Jonathan Austin 1:8aa5cdb4ab67 468 int localBuffSize = (preservedTail > foundIndex) ? (rxBufferSize - preservedTail) + foundIndex : foundIndex - preservedTail;
Jonathan Austin 1:8aa5cdb4ab67 469
LancasterUniversity 3:d86a4ddc1867 470 uint8_t localBuff[localBuffSize + 1];
Jonathan Austin 1:8aa5cdb4ab67 471
LancasterUniversity 8:ec4465853952 472 memclr(&localBuff, localBuffSize + 1);
LancasterUniversity 8:ec4465853952 473
Jonathan Austin 1:8aa5cdb4ab67 474 circularCopy(rxBuffer, rxBufferSize, localBuff, preservedTail, foundIndex);
Jonathan Austin 1:8aa5cdb4ab67 475
Jonathan Austin 1:8aa5cdb4ab67 476 //plus one for the character we listened for...
Jonathan Austin 1:8aa5cdb4ab67 477 rxBufferTail = (rxBufferTail + localBuffSize + 1) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 478
Jonathan Austin 1:8aa5cdb4ab67 479 return ManagedString((char *)localBuff, localBuffSize);
Jonathan Austin 1:8aa5cdb4ab67 480 }
Jonathan Austin 1:8aa5cdb4ab67 481
Jonathan Austin 1:8aa5cdb4ab67 482 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 483 }
Jonathan Austin 1:8aa5cdb4ab67 484
Jonathan Austin 1:8aa5cdb4ab67 485 /**
Jonathan Austin 1:8aa5cdb4ab67 486 * Configures an event to be fired on a match with one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 487 *
Jonathan Austin 1:8aa5cdb4ab67 488 * @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 489 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 490 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 491 *
Jonathan Austin 1:8aa5cdb4ab67 492 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 493 *
Jonathan Austin 1:8aa5cdb4ab67 494 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 495 *
Jonathan Austin 1:8aa5cdb4ab67 496 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 497 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 498 *
Jonathan Austin 1:8aa5cdb4ab67 499 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 500 *
Jonathan Austin 1:8aa5cdb4ab67 501 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 502 */
Jonathan Austin 1:8aa5cdb4ab67 503 int MicroBitUARTService::eventOn(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 504 {
Jonathan Austin 1:8aa5cdb4ab67 505 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 506 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 507
Jonathan Austin 1:8aa5cdb4ab67 508 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 509 this->delimeters = delimeters;
Jonathan Austin 1:8aa5cdb4ab67 510
Jonathan Austin 1:8aa5cdb4ab67 511 //block!
Jonathan Austin 1:8aa5cdb4ab67 512 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 513 fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 514
Jonathan Austin 1:8aa5cdb4ab67 515 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 516 }
Jonathan Austin 1:8aa5cdb4ab67 517
Jonathan Austin 1:8aa5cdb4ab67 518 /**
Jonathan Austin 1:8aa5cdb4ab67 519 * Configures an event to be fired after "len" characters.
Jonathan Austin 1:8aa5cdb4ab67 520 *
Jonathan Austin 1:8aa5cdb4ab67 521 * @param len the number of characters to wait before triggering the event
Jonathan Austin 1:8aa5cdb4ab67 522 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 523 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 524 *
Jonathan Austin 1:8aa5cdb4ab67 525 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 526 *
Jonathan Austin 1:8aa5cdb4ab67 527 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 528 *
Jonathan Austin 1:8aa5cdb4ab67 529 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 530 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 531 *
Jonathan Austin 1:8aa5cdb4ab67 532 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 533 */
Jonathan Austin 1:8aa5cdb4ab67 534 int MicroBitUARTService::eventAfter(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 535 {
Jonathan Austin 1:8aa5cdb4ab67 536 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 537 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 538
Jonathan Austin 1:8aa5cdb4ab67 539 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 540 this->rxBuffHeadMatch = (rxBufferHead + len) % rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 541
Jonathan Austin 1:8aa5cdb4ab67 542 //block!
Jonathan Austin 1:8aa5cdb4ab67 543 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 544 fiber_wait_for_event(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 545
Jonathan Austin 1:8aa5cdb4ab67 546 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 547 }
Jonathan Austin 1:8aa5cdb4ab67 548
Jonathan Austin 1:8aa5cdb4ab67 549 /**
Jonathan Austin 1:8aa5cdb4ab67 550 * Determines if we have space in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 551 *
Jonathan Austin 1:8aa5cdb4ab67 552 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 553 *
Jonathan Austin 1:8aa5cdb4ab67 554 * @note the reason we do not wrap the super's readable() method is so that we
Jonathan Austin 1:8aa5cdb4ab67 555 * don't interfere with communities that use manual calls to uBit.serial.readable()
Jonathan Austin 1:8aa5cdb4ab67 556 */
Jonathan Austin 1:8aa5cdb4ab67 557 int MicroBitUARTService::isReadable()
Jonathan Austin 1:8aa5cdb4ab67 558 {
Jonathan Austin 1:8aa5cdb4ab67 559 return (rxBufferTail != rxBufferHead) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 560 }
Jonathan Austin 1:8aa5cdb4ab67 561
Jonathan Austin 1:8aa5cdb4ab67 562 /**
Jonathan Austin 1:8aa5cdb4ab67 563 * @return The currently buffered number of bytes in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 564 */
Jonathan Austin 1:8aa5cdb4ab67 565 int MicroBitUARTService::rxBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 566 {
Jonathan Austin 1:8aa5cdb4ab67 567 if(rxBufferTail > rxBufferHead)
Jonathan Austin 1:8aa5cdb4ab67 568 return (rxBufferSize - rxBufferTail) + rxBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 569
Jonathan Austin 1:8aa5cdb4ab67 570 return rxBufferHead - rxBufferTail;
Jonathan Austin 1:8aa5cdb4ab67 571 }
Jonathan Austin 1:8aa5cdb4ab67 572
Jonathan Austin 1:8aa5cdb4ab67 573 /**
Jonathan Austin 1:8aa5cdb4ab67 574 * @return The currently buffered number of bytes in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 575 */
Jonathan Austin 1:8aa5cdb4ab67 576 int MicroBitUARTService::txBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 577 {
Jonathan Austin 1:8aa5cdb4ab67 578 if(txBufferTail > txBufferHead)
Jonathan Austin 1:8aa5cdb4ab67 579 return (txBufferSize - txBufferTail) + txBufferHead;
Jonathan Austin 1:8aa5cdb4ab67 580
Jonathan Austin 1:8aa5cdb4ab67 581 return txBufferHead - txBufferTail;
LancasterUniversity 3:d86a4ddc1867 582 }