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:
Wed Jul 13 12:18:25 2016 +0100
Revision:
46:c5bb7af0a3f0
Parent:
25:27299423d813
Child:
59:d73a257e9f89
Synchronized with git rev 3b587e14
Author: James Devine
microbit-dal: serial SYNC_SLEEP / SYNC_SPINWAIT modes transmit all characters [issue #141]

In SYNC_SLEEP and SYNC_SPINWAIT modes the maximum length that could be
sent was always dictated by the buffer size.

This was incorrect as these two modes should wait until all characters
have been transmitted from the given buffer before returning control to
the user.

ASYNC mode will still return immediately after copying the number of
bytes available in the TX buffer.

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 #include "mbed.h"
Jonathan Austin 1:8aa5cdb4ab67 27 #include "MicroBitSerial.h"
Jonathan Austin 1:8aa5cdb4ab67 28 #include "ErrorNo.h"
Jonathan Austin 1:8aa5cdb4ab67 29 #include "MicroBitComponent.h"
Jonathan Austin 1:8aa5cdb4ab67 30 #include "MicroBitFiber.h"
Jonathan Austin 1:8aa5cdb4ab67 31 #include "NotifyEvents.h"
Jonathan Austin 1:8aa5cdb4ab67 32
Jonathan Austin 1:8aa5cdb4ab67 33 uint8_t MicroBitSerial::status = 0;
Jonathan Austin 1:8aa5cdb4ab67 34
Jonathan Austin 1:8aa5cdb4ab67 35 int MicroBitSerial::baudrate = 0;
Jonathan Austin 1:8aa5cdb4ab67 36
Jonathan Austin 1:8aa5cdb4ab67 37 /**
Jonathan Austin 1:8aa5cdb4ab67 38 * Constructor.
Jonathan Austin 1:8aa5cdb4ab67 39 * Create an instance of MicroBitSerial
Jonathan Austin 1:8aa5cdb4ab67 40 *
Jonathan Austin 1:8aa5cdb4ab67 41 * @param tx the Pin to be used for transmission
Jonathan Austin 1:8aa5cdb4ab67 42 *
Jonathan Austin 1:8aa5cdb4ab67 43 * @param rx the Pin to be used for receiving data
Jonathan Austin 1:8aa5cdb4ab67 44 *
Jonathan Austin 1:8aa5cdb4ab67 45 * @param rxBufferSize the size of the buffer to be used for receiving bytes
Jonathan Austin 1:8aa5cdb4ab67 46 *
Jonathan Austin 1:8aa5cdb4ab67 47 * @param txBufferSize the size of the buffer to be used for transmitting bytes
Jonathan Austin 1:8aa5cdb4ab67 48 *
Jonathan Austin 1:8aa5cdb4ab67 49 * @code
Jonathan Austin 1:8aa5cdb4ab67 50 * MicroBitSerial serial(USBTX, USBRX);
Jonathan Austin 1:8aa5cdb4ab67 51 * @endcode
Jonathan Austin 1:8aa5cdb4ab67 52 * @note the default baud rate is 115200. More API details can be found:
Jonathan Austin 1:8aa5cdb4ab67 53 * -https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/api/SerialBase.h
Jonathan Austin 1:8aa5cdb4ab67 54 * -https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/api/RawSerial.h
Jonathan Austin 1:8aa5cdb4ab67 55 *
Jonathan Austin 1:8aa5cdb4ab67 56 * Buffers aren't allocated until the first send or receive respectively.
Jonathan Austin 1:8aa5cdb4ab67 57 */
Jonathan Austin 1:8aa5cdb4ab67 58 MicroBitSerial::MicroBitSerial(PinName tx, PinName rx, uint8_t rxBufferSize, uint8_t txBufferSize) : RawSerial(tx,rx), delimeters()
Jonathan Austin 1:8aa5cdb4ab67 59 {
Jonathan Austin 1:8aa5cdb4ab67 60 this->rxBuffSize = rxBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 61 this->txBuffSize = txBufferSize;
Jonathan Austin 1:8aa5cdb4ab67 62
Jonathan Austin 1:8aa5cdb4ab67 63 this->rxBuff = NULL;
Jonathan Austin 1:8aa5cdb4ab67 64 this->txBuff = NULL;
Jonathan Austin 1:8aa5cdb4ab67 65
Jonathan Austin 1:8aa5cdb4ab67 66 this->rxBuffHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 67 this->rxBuffTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 68
Jonathan Austin 1:8aa5cdb4ab67 69 this->txBuffHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 70 this->txBuffTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 71
Jonathan Austin 1:8aa5cdb4ab67 72 this->rxBuffHeadMatch = -1;
Jonathan Austin 1:8aa5cdb4ab67 73
Jonathan Austin 1:8aa5cdb4ab67 74 this->baud(MICROBIT_SERIAL_DEFAULT_BAUD_RATE);
Jonathan Austin 1:8aa5cdb4ab67 75
Jonathan Austin 1:8aa5cdb4ab67 76 #if CONFIG_ENABLED(MICROBIT_DBG)
Jonathan Austin 1:8aa5cdb4ab67 77 SERIAL_DEBUG = this;
Jonathan Austin 1:8aa5cdb4ab67 78 #endif
Jonathan Austin 1:8aa5cdb4ab67 79
Jonathan Austin 1:8aa5cdb4ab67 80 }
Jonathan Austin 1:8aa5cdb4ab67 81
Jonathan Austin 1:8aa5cdb4ab67 82 /**
Jonathan Austin 1:8aa5cdb4ab67 83 * An internal interrupt callback for MicroBitSerial configured for when a
Jonathan Austin 1:8aa5cdb4ab67 84 * character is received.
Jonathan Austin 1:8aa5cdb4ab67 85 *
Jonathan Austin 1:8aa5cdb4ab67 86 * Each time a character is received fill our circular buffer!
Jonathan Austin 1:8aa5cdb4ab67 87 */
Jonathan Austin 1:8aa5cdb4ab67 88 void MicroBitSerial::dataReceived()
Jonathan Austin 1:8aa5cdb4ab67 89 {
Jonathan Austin 1:8aa5cdb4ab67 90 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 91 return;
Jonathan Austin 1:8aa5cdb4ab67 92
Jonathan Austin 1:8aa5cdb4ab67 93 //get the received character
Jonathan Austin 1:8aa5cdb4ab67 94 char c = getc();
Jonathan Austin 1:8aa5cdb4ab67 95
Jonathan Austin 1:8aa5cdb4ab67 96 int delimeterOffset = 0;
Jonathan Austin 1:8aa5cdb4ab67 97 int delimLength = this->delimeters.length();
Jonathan Austin 1:8aa5cdb4ab67 98
Jonathan Austin 1:8aa5cdb4ab67 99 //iterate through our delimeters (if any) to see if there is a match
Jonathan Austin 1:8aa5cdb4ab67 100 while(delimeterOffset < delimLength)
Jonathan Austin 1:8aa5cdb4ab67 101 {
Jonathan Austin 1:8aa5cdb4ab67 102 //fire an event if there is to block any waiting fibers
Jonathan Austin 1:8aa5cdb4ab67 103 if(this->delimeters.charAt(delimeterOffset) == c)
Jonathan Austin 1:8aa5cdb4ab67 104 MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 105
Jonathan Austin 1:8aa5cdb4ab67 106 delimeterOffset++;
Jonathan Austin 1:8aa5cdb4ab67 107 }
Jonathan Austin 1:8aa5cdb4ab67 108
Jonathan Austin 1:8aa5cdb4ab67 109 uint16_t newHead = (rxBuffHead + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 110
Jonathan Austin 1:8aa5cdb4ab67 111 //look ahead to our newHead value to see if we are about to collide with the tail
Jonathan Austin 1:8aa5cdb4ab67 112 if(newHead != rxBuffTail)
Jonathan Austin 1:8aa5cdb4ab67 113 {
Jonathan Austin 1:8aa5cdb4ab67 114 //if we are not, store the character, and update our actual head.
Jonathan Austin 1:8aa5cdb4ab67 115 this->rxBuff[rxBuffHead] = c;
Jonathan Austin 1:8aa5cdb4ab67 116 rxBuffHead = newHead;
Jonathan Austin 1:8aa5cdb4ab67 117
Jonathan Austin 1:8aa5cdb4ab67 118 //if we have any fibers waiting for a specific number of characters, unblock them
Jonathan Austin 1:8aa5cdb4ab67 119 if(rxBuffHeadMatch >= 0)
Jonathan Austin 1:8aa5cdb4ab67 120 if(rxBuffHead == rxBuffHeadMatch)
Jonathan Austin 1:8aa5cdb4ab67 121 {
Jonathan Austin 1:8aa5cdb4ab67 122 rxBuffHeadMatch = -1;
Jonathan Austin 1:8aa5cdb4ab67 123 MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 124 }
Jonathan Austin 1:8aa5cdb4ab67 125 }
Jonathan Austin 1:8aa5cdb4ab67 126 else
Jonathan Austin 1:8aa5cdb4ab67 127 //otherwise, our buffer is full, send an event to the user...
Jonathan Austin 1:8aa5cdb4ab67 128 MicroBitEvent(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_RX_FULL);
Jonathan Austin 1:8aa5cdb4ab67 129 }
Jonathan Austin 1:8aa5cdb4ab67 130
Jonathan Austin 1:8aa5cdb4ab67 131 /**
Jonathan Austin 1:8aa5cdb4ab67 132 * An internal interrupt callback for MicroBitSerial.
Jonathan Austin 1:8aa5cdb4ab67 133 *
Jonathan Austin 1:8aa5cdb4ab67 134 * Each time the Serial module's buffer is empty, write a character if we have
Jonathan Austin 1:8aa5cdb4ab67 135 * characters to write.
Jonathan Austin 1:8aa5cdb4ab67 136 */
Jonathan Austin 1:8aa5cdb4ab67 137 void MicroBitSerial::dataWritten()
Jonathan Austin 1:8aa5cdb4ab67 138 {
Jonathan Austin 1:8aa5cdb4ab67 139 if(txBuffTail == txBuffHead || !(status & MICROBIT_SERIAL_TX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 140 return;
Jonathan Austin 1:8aa5cdb4ab67 141
Jonathan Austin 1:8aa5cdb4ab67 142 //send our current char
Jonathan Austin 1:8aa5cdb4ab67 143 putc(txBuff[txBuffTail]);
Jonathan Austin 1:8aa5cdb4ab67 144
Jonathan Austin 1:8aa5cdb4ab67 145 uint16_t nextTail = (txBuffTail + 1) % txBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 146
Jonathan Austin 1:8aa5cdb4ab67 147 //unblock any waiting fibers that are waiting for transmission to finish.
Jonathan Austin 1:8aa5cdb4ab67 148 if(nextTail == txBuffHead)
Jonathan Austin 1:8aa5cdb4ab67 149 {
Jonathan Austin 1:8aa5cdb4ab67 150 MicroBitEvent(MICROBIT_ID_NOTIFY, MICROBIT_SERIAL_EVT_TX_EMPTY);
LancasterUniversity 6:2e1c2e0d8c7a 151 detach(Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 152 }
Jonathan Austin 1:8aa5cdb4ab67 153
Jonathan Austin 1:8aa5cdb4ab67 154 //update our tail!
Jonathan Austin 1:8aa5cdb4ab67 155 txBuffTail = nextTail;
Jonathan Austin 1:8aa5cdb4ab67 156 }
Jonathan Austin 1:8aa5cdb4ab67 157
Jonathan Austin 1:8aa5cdb4ab67 158 /**
Jonathan Austin 1:8aa5cdb4ab67 159 * An internal method to configure an interrupt on tx buffer and also
Jonathan Austin 1:8aa5cdb4ab67 160 * a best effort copy operation to move bytes from a user buffer to our txBuff
Jonathan Austin 1:8aa5cdb4ab67 161 *
Jonathan Austin 1:8aa5cdb4ab67 162 * @param string a pointer to the first character of the users' buffer.
Jonathan Austin 1:8aa5cdb4ab67 163 *
Jonathan Austin 1:8aa5cdb4ab67 164 * @param len the length of the string, and ultimately the maximum number of bytes
Jonathan Austin 1:8aa5cdb4ab67 165 * that will be copied dependent on the state of txBuff
Jonathan Austin 1:8aa5cdb4ab67 166 *
LancasterUniversity 25:27299423d813 167 * @param mode determines whether to configure the current fiber context or not. If
LancasterUniversity 25:27299423d813 168 * The mode is SYNC_SPINWAIT, the context will not be configured, otherwise
LancasterUniversity 25:27299423d813 169 * no context will be configured.
LancasterUniversity 25:27299423d813 170 *
Jonathan Austin 1:8aa5cdb4ab67 171 * @return the number of bytes copied into the buffer.
Jonathan Austin 1:8aa5cdb4ab67 172 */
LancasterUniversity 25:27299423d813 173 int MicroBitSerial::setTxInterrupt(uint8_t *string, int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 174 {
Jonathan Austin 1:8aa5cdb4ab67 175 int copiedBytes = 0;
Jonathan Austin 1:8aa5cdb4ab67 176
Jonathan Austin 1:8aa5cdb4ab67 177 for(copiedBytes = 0; copiedBytes < len; copiedBytes++)
Jonathan Austin 1:8aa5cdb4ab67 178 {
Jonathan Austin 1:8aa5cdb4ab67 179 uint16_t nextHead = (txBuffHead + 1) % txBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 180 if(nextHead != txBuffTail)
Jonathan Austin 1:8aa5cdb4ab67 181 {
Jonathan Austin 1:8aa5cdb4ab67 182 this->txBuff[txBuffHead] = string[copiedBytes];
Jonathan Austin 1:8aa5cdb4ab67 183 txBuffHead = nextHead;
Jonathan Austin 1:8aa5cdb4ab67 184 }
Jonathan Austin 1:8aa5cdb4ab67 185 else
Jonathan Austin 1:8aa5cdb4ab67 186 break;
Jonathan Austin 1:8aa5cdb4ab67 187 }
Jonathan Austin 1:8aa5cdb4ab67 188
LancasterUniversity 25:27299423d813 189 if(mode != SYNC_SPINWAIT)
LancasterUniversity 25:27299423d813 190 fiber_wake_on_event(MICROBIT_ID_NOTIFY, MICROBIT_SERIAL_EVT_TX_EMPTY);
Jonathan Austin 1:8aa5cdb4ab67 191
Jonathan Austin 1:8aa5cdb4ab67 192 //set the TX interrupt
LancasterUniversity 6:2e1c2e0d8c7a 193 attach(this, &MicroBitSerial::dataWritten, Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 194
Jonathan Austin 1:8aa5cdb4ab67 195 return copiedBytes;
Jonathan Austin 1:8aa5cdb4ab67 196 }
Jonathan Austin 1:8aa5cdb4ab67 197
Jonathan Austin 1:8aa5cdb4ab67 198 /**
Jonathan Austin 1:8aa5cdb4ab67 199 * Locks the mutex so that others can't use this serial instance for reception
Jonathan Austin 1:8aa5cdb4ab67 200 */
Jonathan Austin 1:8aa5cdb4ab67 201 void MicroBitSerial::lockRx()
Jonathan Austin 1:8aa5cdb4ab67 202 {
Jonathan Austin 1:8aa5cdb4ab67 203 status |= MICROBIT_SERIAL_RX_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 204 }
Jonathan Austin 1:8aa5cdb4ab67 205
Jonathan Austin 1:8aa5cdb4ab67 206 /**
Jonathan Austin 1:8aa5cdb4ab67 207 * Locks the mutex so that others can't use this serial instance for transmission
Jonathan Austin 1:8aa5cdb4ab67 208 */
Jonathan Austin 1:8aa5cdb4ab67 209 void MicroBitSerial::lockTx()
Jonathan Austin 1:8aa5cdb4ab67 210 {
Jonathan Austin 1:8aa5cdb4ab67 211 status |= MICROBIT_SERIAL_TX_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 212 }
Jonathan Austin 1:8aa5cdb4ab67 213
Jonathan Austin 1:8aa5cdb4ab67 214 /**
Jonathan Austin 1:8aa5cdb4ab67 215 * Unlocks the mutex so that others can use this serial instance for reception
Jonathan Austin 1:8aa5cdb4ab67 216 */
Jonathan Austin 1:8aa5cdb4ab67 217 void MicroBitSerial::unlockRx()
Jonathan Austin 1:8aa5cdb4ab67 218 {
Jonathan Austin 1:8aa5cdb4ab67 219 status &= ~MICROBIT_SERIAL_RX_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 220 }
Jonathan Austin 1:8aa5cdb4ab67 221
Jonathan Austin 1:8aa5cdb4ab67 222 /**
Jonathan Austin 1:8aa5cdb4ab67 223 * Unlocks the mutex so that others can use this serial instance for transmission
Jonathan Austin 1:8aa5cdb4ab67 224 */
Jonathan Austin 1:8aa5cdb4ab67 225 void MicroBitSerial::unlockTx()
Jonathan Austin 1:8aa5cdb4ab67 226 {
Jonathan Austin 1:8aa5cdb4ab67 227 status &= ~MICROBIT_SERIAL_TX_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 228 }
Jonathan Austin 1:8aa5cdb4ab67 229
Jonathan Austin 1:8aa5cdb4ab67 230 /**
Jonathan Austin 1:8aa5cdb4ab67 231 * We do not want to always have our buffers initialised, especially if users to not
Jonathan Austin 1:8aa5cdb4ab67 232 * use them. We only bring them up on demand.
Jonathan Austin 1:8aa5cdb4ab67 233 */
Jonathan Austin 1:8aa5cdb4ab67 234 int MicroBitSerial::initialiseRx()
Jonathan Austin 1:8aa5cdb4ab67 235 {
Jonathan Austin 1:8aa5cdb4ab67 236 if((status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 237 {
Jonathan Austin 1:8aa5cdb4ab67 238 //ensure that we receive no interrupts after freeing our buffer
LancasterUniversity 6:2e1c2e0d8c7a 239 detach(Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 240 free(this->rxBuff);
Jonathan Austin 1:8aa5cdb4ab67 241 }
Jonathan Austin 1:8aa5cdb4ab67 242
Jonathan Austin 1:8aa5cdb4ab67 243 status &= ~MICROBIT_SERIAL_RX_BUFF_INIT;
Jonathan Austin 1:8aa5cdb4ab67 244
Jonathan Austin 1:8aa5cdb4ab67 245 if((this->rxBuff = (uint8_t *)malloc(rxBuffSize)) == NULL)
Jonathan Austin 1:8aa5cdb4ab67 246 return MICROBIT_NO_RESOURCES;
Jonathan Austin 1:8aa5cdb4ab67 247
Jonathan Austin 1:8aa5cdb4ab67 248 this->rxBuffHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 249 this->rxBuffTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 250
Jonathan Austin 1:8aa5cdb4ab67 251 //set the receive interrupt
Jonathan Austin 1:8aa5cdb4ab67 252 status |= MICROBIT_SERIAL_RX_BUFF_INIT;
LancasterUniversity 6:2e1c2e0d8c7a 253 attach(this, &MicroBitSerial::dataReceived, Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 254
Jonathan Austin 1:8aa5cdb4ab67 255 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 256 }
Jonathan Austin 1:8aa5cdb4ab67 257
Jonathan Austin 1:8aa5cdb4ab67 258 /**
Jonathan Austin 1:8aa5cdb4ab67 259 * We do not want to always have our buffers initialised, especially if users to not
Jonathan Austin 1:8aa5cdb4ab67 260 * use them. We only bring them up on demand.
Jonathan Austin 1:8aa5cdb4ab67 261 */
Jonathan Austin 1:8aa5cdb4ab67 262 int MicroBitSerial::initialiseTx()
Jonathan Austin 1:8aa5cdb4ab67 263 {
Jonathan Austin 1:8aa5cdb4ab67 264 if((status & MICROBIT_SERIAL_TX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 265 {
Jonathan Austin 1:8aa5cdb4ab67 266 //ensure that we receive no interrupts after freeing our buffer
LancasterUniversity 6:2e1c2e0d8c7a 267 detach(Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 268 free(this->txBuff);
Jonathan Austin 1:8aa5cdb4ab67 269 }
Jonathan Austin 1:8aa5cdb4ab67 270
Jonathan Austin 1:8aa5cdb4ab67 271 status &= ~MICROBIT_SERIAL_TX_BUFF_INIT;
Jonathan Austin 1:8aa5cdb4ab67 272
Jonathan Austin 1:8aa5cdb4ab67 273 if((this->txBuff = (uint8_t *)malloc(txBuffSize)) == NULL)
Jonathan Austin 1:8aa5cdb4ab67 274 return MICROBIT_NO_RESOURCES;
Jonathan Austin 1:8aa5cdb4ab67 275
Jonathan Austin 1:8aa5cdb4ab67 276 this->txBuffHead = 0;
Jonathan Austin 1:8aa5cdb4ab67 277 this->txBuffTail = 0;
Jonathan Austin 1:8aa5cdb4ab67 278
Jonathan Austin 1:8aa5cdb4ab67 279 status |= MICROBIT_SERIAL_TX_BUFF_INIT;
Jonathan Austin 1:8aa5cdb4ab67 280
Jonathan Austin 1:8aa5cdb4ab67 281 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 282 }
Jonathan Austin 1:8aa5cdb4ab67 283
Jonathan Austin 1:8aa5cdb4ab67 284 /**
Jonathan Austin 1:8aa5cdb4ab67 285 * An internal method that either spin waits if mode is set to SYNC_SPINWAIT
Jonathan Austin 1:8aa5cdb4ab67 286 * or puts the fiber to sleep if the mode is set to SYNC_SLEEP
Jonathan Austin 1:8aa5cdb4ab67 287 *
Jonathan Austin 1:8aa5cdb4ab67 288 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP
Jonathan Austin 1:8aa5cdb4ab67 289 */
Jonathan Austin 1:8aa5cdb4ab67 290 void MicroBitSerial::send(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 291 {
Jonathan Austin 1:8aa5cdb4ab67 292 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 293 while(txBufferedSize() > 0);
Jonathan Austin 1:8aa5cdb4ab67 294
Jonathan Austin 1:8aa5cdb4ab67 295 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 296 fiber_sleep(0);
Jonathan Austin 1:8aa5cdb4ab67 297 }
Jonathan Austin 1:8aa5cdb4ab67 298
Jonathan Austin 1:8aa5cdb4ab67 299 /**
Jonathan Austin 1:8aa5cdb4ab67 300 * Reads a single character from the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 301 *
Jonathan Austin 1:8aa5cdb4ab67 302 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 303 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 304 *
Jonathan Austin 1:8aa5cdb4ab67 305 * ASYNC - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 306 * are no characters to be read, a value of zero is returned immediately.
Jonathan Austin 1:8aa5cdb4ab67 307 *
Jonathan Austin 1:8aa5cdb4ab67 308 * SYNC_SPINWAIT - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 309 * are no characters to be read, this method will spin
Jonathan Austin 1:8aa5cdb4ab67 310 * (lock up the processor) until a character is available.
Jonathan Austin 1:8aa5cdb4ab67 311 *
Jonathan Austin 1:8aa5cdb4ab67 312 * SYNC_SLEEP - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 313 * are no characters to be read, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 314 * until there is a character available.
Jonathan Austin 1:8aa5cdb4ab67 315 *
Jonathan Austin 1:8aa5cdb4ab67 316 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 317 *
Jonathan Austin 1:8aa5cdb4ab67 318 * @return a character from the circular buffer, or MICROBIT_NO_DATA is there
Jonathan Austin 1:8aa5cdb4ab67 319 * are no characters in the buffer.
Jonathan Austin 1:8aa5cdb4ab67 320 */
Jonathan Austin 1:8aa5cdb4ab67 321 int MicroBitSerial::getChar(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 322 {
Jonathan Austin 1:8aa5cdb4ab67 323 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 324 {
Jonathan Austin 1:8aa5cdb4ab67 325 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 326 return MICROBIT_NO_DATA;
Jonathan Austin 1:8aa5cdb4ab67 327 }
Jonathan Austin 1:8aa5cdb4ab67 328
Jonathan Austin 1:8aa5cdb4ab67 329 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 330 while(!isReadable());
Jonathan Austin 1:8aa5cdb4ab67 331
Jonathan Austin 1:8aa5cdb4ab67 332 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 333 {
Jonathan Austin 1:8aa5cdb4ab67 334 if(!isReadable())
Jonathan Austin 1:8aa5cdb4ab67 335 eventAfter(1, mode);
Jonathan Austin 1:8aa5cdb4ab67 336 }
Jonathan Austin 1:8aa5cdb4ab67 337
Jonathan Austin 1:8aa5cdb4ab67 338 char c = rxBuff[rxBuffTail];
Jonathan Austin 1:8aa5cdb4ab67 339
Jonathan Austin 1:8aa5cdb4ab67 340 rxBuffTail = (rxBuffTail + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 341
Jonathan Austin 1:8aa5cdb4ab67 342 return c;
Jonathan Austin 1:8aa5cdb4ab67 343 }
Jonathan Austin 1:8aa5cdb4ab67 344
Jonathan Austin 1:8aa5cdb4ab67 345 /**
Jonathan Austin 1:8aa5cdb4ab67 346 * An internal method that copies values from a circular buffer to a linear buffer.
Jonathan Austin 1:8aa5cdb4ab67 347 *
Jonathan Austin 1:8aa5cdb4ab67 348 * @param circularBuff a pointer to the source circular buffer
Jonathan Austin 1:8aa5cdb4ab67 349 *
Jonathan Austin 1:8aa5cdb4ab67 350 * @param circularBuffSize the size of the circular buffer
Jonathan Austin 1:8aa5cdb4ab67 351 *
Jonathan Austin 1:8aa5cdb4ab67 352 * @param linearBuff a pointer to the destination linear buffer
Jonathan Austin 1:8aa5cdb4ab67 353 *
Jonathan Austin 1:8aa5cdb4ab67 354 * @param tailPosition the tail position in the circular buffer you want to copy from
Jonathan Austin 1:8aa5cdb4ab67 355 *
Jonathan Austin 1:8aa5cdb4ab67 356 * @param headPosition the head position in the circular buffer you want to copy to
Jonathan Austin 1:8aa5cdb4ab67 357 *
Jonathan Austin 1:8aa5cdb4ab67 358 * @note this method assumes that the linear buffer has the appropriate amount of
Jonathan Austin 1:8aa5cdb4ab67 359 * memory to contain the copy operation
Jonathan Austin 1:8aa5cdb4ab67 360 */
Jonathan Austin 1:8aa5cdb4ab67 361 void MicroBitSerial::circularCopy(uint8_t *circularBuff, uint8_t circularBuffSize, uint8_t *linearBuff, uint16_t tailPosition, uint16_t headPosition)
Jonathan Austin 1:8aa5cdb4ab67 362 {
Jonathan Austin 1:8aa5cdb4ab67 363 int toBuffIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 364
Jonathan Austin 1:8aa5cdb4ab67 365 while(tailPosition != headPosition)
Jonathan Austin 1:8aa5cdb4ab67 366 {
Jonathan Austin 1:8aa5cdb4ab67 367 linearBuff[toBuffIndex++] = circularBuff[tailPosition];
Jonathan Austin 1:8aa5cdb4ab67 368
Jonathan Austin 1:8aa5cdb4ab67 369 tailPosition = (tailPosition + 1) % circularBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 370 }
Jonathan Austin 1:8aa5cdb4ab67 371 }
Jonathan Austin 1:8aa5cdb4ab67 372
Jonathan Austin 1:8aa5cdb4ab67 373 /**
Jonathan Austin 1:8aa5cdb4ab67 374 * Sends a single character over the serial line.
Jonathan Austin 1:8aa5cdb4ab67 375 *
Jonathan Austin 1:8aa5cdb4ab67 376 * @param c the character to send
Jonathan Austin 1:8aa5cdb4ab67 377 *
Jonathan Austin 1:8aa5cdb4ab67 378 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 379 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 380 *
Jonathan Austin 1:8aa5cdb4ab67 381 * ASYNC - the character is copied into the txBuff and returns immediately.
Jonathan Austin 1:8aa5cdb4ab67 382 *
Jonathan Austin 1:8aa5cdb4ab67 383 * SYNC_SPINWAIT - the character is copied into the txBuff and this method
Jonathan Austin 1:8aa5cdb4ab67 384 * will spin (lock up the processor) until the character has
Jonathan Austin 1:8aa5cdb4ab67 385 * been sent.
Jonathan Austin 1:8aa5cdb4ab67 386 *
Jonathan Austin 1:8aa5cdb4ab67 387 * SYNC_SLEEP - the character is copied into the txBuff and the fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 388 * until the character has been sent. This allows other fibers
Jonathan Austin 1:8aa5cdb4ab67 389 * to continue execution.
Jonathan Austin 1:8aa5cdb4ab67 390 *
Jonathan Austin 1:8aa5cdb4ab67 391 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 392 *
Jonathan Austin 1:8aa5cdb4ab67 393 * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
Jonathan Austin 1:8aa5cdb4ab67 394 * is using the serial instance for transmission.
Jonathan Austin 1:8aa5cdb4ab67 395 */
Jonathan Austin 1:8aa5cdb4ab67 396 int MicroBitSerial::sendChar(char c, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 397 {
Jonathan Austin 1:8aa5cdb4ab67 398 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 399 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 400
Jonathan Austin 1:8aa5cdb4ab67 401 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 402
Jonathan Austin 1:8aa5cdb4ab67 403 //lazy initialisation of our tx buffer
Jonathan Austin 1:8aa5cdb4ab67 404 if(!(status & MICROBIT_SERIAL_TX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 405 {
Jonathan Austin 1:8aa5cdb4ab67 406 int result = initialiseTx();
Jonathan Austin 1:8aa5cdb4ab67 407
Jonathan Austin 1:8aa5cdb4ab67 408 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 409 return result;
Jonathan Austin 1:8aa5cdb4ab67 410 }
Jonathan Austin 1:8aa5cdb4ab67 411
Jonathan Austin 1:8aa5cdb4ab67 412 uint8_t toTransmit[2] = { c, '\0'};
Jonathan Austin 1:8aa5cdb4ab67 413
LancasterUniversity 25:27299423d813 414 int bytesWritten = setTxInterrupt(toTransmit, 1, mode);
Jonathan Austin 1:8aa5cdb4ab67 415
Jonathan Austin 1:8aa5cdb4ab67 416 send(mode);
Jonathan Austin 1:8aa5cdb4ab67 417
Jonathan Austin 1:8aa5cdb4ab67 418 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 419
Jonathan Austin 1:8aa5cdb4ab67 420 return bytesWritten;
Jonathan Austin 1:8aa5cdb4ab67 421 }
Jonathan Austin 1:8aa5cdb4ab67 422
Jonathan Austin 1:8aa5cdb4ab67 423 /**
Jonathan Austin 1:8aa5cdb4ab67 424 * Sends a ManagedString over the serial line.
Jonathan Austin 1:8aa5cdb4ab67 425 *
Jonathan Austin 1:8aa5cdb4ab67 426 * @param s the string to send
Jonathan Austin 1:8aa5cdb4ab67 427 *
Jonathan Austin 1:8aa5cdb4ab67 428 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 429 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 430 *
Jonathan Austin 1:8aa5cdb4ab67 431 * ASYNC - bytes are copied into the txBuff and returns immediately.
Jonathan Austin 1:8aa5cdb4ab67 432 *
Jonathan Austin 1:8aa5cdb4ab67 433 * SYNC_SPINWAIT - bytes are copied into the txBuff and this method
Jonathan Austin 1:8aa5cdb4ab67 434 * will spin (lock up the processor) until all bytes
Jonathan Austin 1:8aa5cdb4ab67 435 * have been sent.
Jonathan Austin 1:8aa5cdb4ab67 436 *
Jonathan Austin 1:8aa5cdb4ab67 437 * SYNC_SLEEP - bytes are copied into the txBuff and the fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 438 * until all bytes have been sent. This allows other fibers
Jonathan Austin 1:8aa5cdb4ab67 439 * to continue execution.
Jonathan Austin 1:8aa5cdb4ab67 440 *
Jonathan Austin 1:8aa5cdb4ab67 441 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 442 *
Jonathan Austin 1:8aa5cdb4ab67 443 * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
Jonathan Austin 1:8aa5cdb4ab67 444 * is using the serial instance for transmission.
Jonathan Austin 1:8aa5cdb4ab67 445 */
Jonathan Austin 1:8aa5cdb4ab67 446 int MicroBitSerial::send(ManagedString s, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 447 {
Jonathan Austin 1:8aa5cdb4ab67 448 return send((uint8_t *)s.toCharArray(), s.length(), mode);
Jonathan Austin 1:8aa5cdb4ab67 449 }
Jonathan Austin 1:8aa5cdb4ab67 450
Jonathan Austin 1:8aa5cdb4ab67 451 /**
Jonathan Austin 1:8aa5cdb4ab67 452 * Sends a buffer of known length over the serial line.
Jonathan Austin 1:8aa5cdb4ab67 453 *
Jonathan Austin 1:8aa5cdb4ab67 454 * @param buffer a pointer to the first character of the buffer
Jonathan Austin 1:8aa5cdb4ab67 455 *
Jonathan Austin 1:8aa5cdb4ab67 456 * @param len the number of bytes that are safely available to read.
Jonathan Austin 1:8aa5cdb4ab67 457 *
Jonathan Austin 1:8aa5cdb4ab67 458 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 459 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 460 *
Jonathan Austin 1:8aa5cdb4ab67 461 * ASYNC - bytes are copied into the txBuff and returns immediately.
Jonathan Austin 1:8aa5cdb4ab67 462 *
Jonathan Austin 1:8aa5cdb4ab67 463 * SYNC_SPINWAIT - bytes are copied into the txBuff and this method
Jonathan Austin 1:8aa5cdb4ab67 464 * will spin (lock up the processor) until all bytes
Jonathan Austin 1:8aa5cdb4ab67 465 * have been sent.
Jonathan Austin 1:8aa5cdb4ab67 466 *
Jonathan Austin 1:8aa5cdb4ab67 467 * SYNC_SLEEP - bytes are copied into the txBuff and the fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 468 * until all bytes have been sent. This allows other fibers
Jonathan Austin 1:8aa5cdb4ab67 469 * to continue execution.
Jonathan Austin 1:8aa5cdb4ab67 470 *
Jonathan Austin 1:8aa5cdb4ab67 471 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 472 *
Jonathan Austin 1:8aa5cdb4ab67 473 * @return the number of bytes written, or MICROBIT_SERIAL_IN_USE if another fiber
Jonathan Austin 1:8aa5cdb4ab67 474 * is using the serial instance for transmission.
Jonathan Austin 1:8aa5cdb4ab67 475 */
Jonathan Austin 1:8aa5cdb4ab67 476 int MicroBitSerial::send(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 477 {
Jonathan Austin 1:8aa5cdb4ab67 478 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 479 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 480
Jonathan Austin 1:8aa5cdb4ab67 481 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 482
Jonathan Austin 1:8aa5cdb4ab67 483 //lazy initialisation of our tx buffer
Jonathan Austin 1:8aa5cdb4ab67 484 if(!(status & MICROBIT_SERIAL_TX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 485 {
Jonathan Austin 1:8aa5cdb4ab67 486 int result = initialiseTx();
Jonathan Austin 1:8aa5cdb4ab67 487
Jonathan Austin 1:8aa5cdb4ab67 488 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 489 return result;
Jonathan Austin 1:8aa5cdb4ab67 490 }
Jonathan Austin 1:8aa5cdb4ab67 491
LancasterUniversity 46:c5bb7af0a3f0 492 bool complete = false;
LancasterUniversity 46:c5bb7af0a3f0 493 int bytesWritten = 0;
Jonathan Austin 1:8aa5cdb4ab67 494
LancasterUniversity 46:c5bb7af0a3f0 495 while(!complete)
LancasterUniversity 46:c5bb7af0a3f0 496 {
LancasterUniversity 46:c5bb7af0a3f0 497 bytesWritten += setTxInterrupt(buffer + bytesWritten, bufferLen - bytesWritten, mode);
LancasterUniversity 46:c5bb7af0a3f0 498 send(mode);
LancasterUniversity 46:c5bb7af0a3f0 499
LancasterUniversity 46:c5bb7af0a3f0 500 if(mode == ASYNC || bytesWritten >= bufferLen)
LancasterUniversity 46:c5bb7af0a3f0 501 complete = true;
LancasterUniversity 46:c5bb7af0a3f0 502 }
Jonathan Austin 1:8aa5cdb4ab67 503
Jonathan Austin 1:8aa5cdb4ab67 504 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 505
Jonathan Austin 1:8aa5cdb4ab67 506 return bytesWritten;
Jonathan Austin 1:8aa5cdb4ab67 507 }
Jonathan Austin 1:8aa5cdb4ab67 508
Jonathan Austin 1:8aa5cdb4ab67 509 /**
Jonathan Austin 1:8aa5cdb4ab67 510 * Reads a single character from the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 511 *
Jonathan Austin 1:8aa5cdb4ab67 512 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 513 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 514 *
Jonathan Austin 1:8aa5cdb4ab67 515 * ASYNC - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 516 * are no characters to be read, a value of MICROBIT_NO_DATA is returned immediately.
Jonathan Austin 1:8aa5cdb4ab67 517 *
Jonathan Austin 1:8aa5cdb4ab67 518 * SYNC_SPINWAIT - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 519 * are no characters to be read, this method will spin
Jonathan Austin 1:8aa5cdb4ab67 520 * (lock up the processor) until a character is available.
Jonathan Austin 1:8aa5cdb4ab67 521 *
Jonathan Austin 1:8aa5cdb4ab67 522 * SYNC_SLEEP - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 523 * are no characters to be read, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 524 * until there is a character available.
Jonathan Austin 1:8aa5cdb4ab67 525 *
Jonathan Austin 1:8aa5cdb4ab67 526 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 527 *
Jonathan Austin 1:8aa5cdb4ab67 528 * @return a character, MICROBIT_SERIAL_IN_USE if another fiber is using the serial instance for reception,
Jonathan Austin 1:8aa5cdb4ab67 529 * MICROBIT_NO_RESOURCES if buffer allocation did not complete successfully, or MICROBIT_NO_DATA if
Jonathan Austin 1:8aa5cdb4ab67 530 * the rx buffer is empty and the mode given is ASYNC.
Jonathan Austin 1:8aa5cdb4ab67 531 */
Jonathan Austin 1:8aa5cdb4ab67 532 int MicroBitSerial::read(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 533 {
Jonathan Austin 1:8aa5cdb4ab67 534 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 535 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 536
Jonathan Austin 1:8aa5cdb4ab67 537 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 538
Jonathan Austin 1:8aa5cdb4ab67 539 //lazy initialisation of our buffers
Jonathan Austin 1:8aa5cdb4ab67 540 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 541 {
Jonathan Austin 1:8aa5cdb4ab67 542 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 543
Jonathan Austin 1:8aa5cdb4ab67 544 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 545 return result;
Jonathan Austin 1:8aa5cdb4ab67 546 }
Jonathan Austin 1:8aa5cdb4ab67 547
Jonathan Austin 1:8aa5cdb4ab67 548 char c = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 549
Jonathan Austin 1:8aa5cdb4ab67 550 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 551
Jonathan Austin 1:8aa5cdb4ab67 552 return c;
Jonathan Austin 1:8aa5cdb4ab67 553 }
Jonathan Austin 1:8aa5cdb4ab67 554
Jonathan Austin 1:8aa5cdb4ab67 555 /**
Jonathan Austin 1:8aa5cdb4ab67 556 * Reads multiple characters from the rxBuff and returns them as a ManagedString
Jonathan Austin 1:8aa5cdb4ab67 557 *
Jonathan Austin 1:8aa5cdb4ab67 558 * @param size the number of characters to read.
Jonathan Austin 1:8aa5cdb4ab67 559 *
Jonathan Austin 1:8aa5cdb4ab67 560 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 561 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 562 *
Jonathan Austin 1:8aa5cdb4ab67 563 * ASYNC - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 564 * a ManagedString with the expected size. Otherwise, it will read however
Jonathan Austin 1:8aa5cdb4ab67 565 * many characters there are available.
Jonathan Austin 1:8aa5cdb4ab67 566 *
Jonathan Austin 1:8aa5cdb4ab67 567 * SYNC_SPINWAIT - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 568 * a ManagedString with the expected size. Otherwise, this method will spin
Jonathan Austin 1:8aa5cdb4ab67 569 * (lock up the processor) until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 570 *
Jonathan Austin 1:8aa5cdb4ab67 571 * SYNC_SLEEP - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 572 * a ManagedString with the expected size. Otherwise, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 573 * until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 574 *
Jonathan Austin 1:8aa5cdb4ab67 575 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 576 *
Jonathan Austin 1:8aa5cdb4ab67 577 * @return A ManagedString, or an empty ManagedString if an error was encountered during the read.
Jonathan Austin 1:8aa5cdb4ab67 578 */
Jonathan Austin 1:8aa5cdb4ab67 579 ManagedString MicroBitSerial::read(int size, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 580 {
LancasterUniversity 3:d86a4ddc1867 581 uint8_t buff[size + 1];
Jonathan Austin 1:8aa5cdb4ab67 582
LancasterUniversity 8:ec4465853952 583 memclr(&buff, size + 1);
LancasterUniversity 8:ec4465853952 584
Jonathan Austin 1:8aa5cdb4ab67 585 int returnedSize = read((uint8_t *)buff, size, mode);
Jonathan Austin 1:8aa5cdb4ab67 586
Jonathan Austin 1:8aa5cdb4ab67 587 if(returnedSize <= 0)
Jonathan Austin 1:8aa5cdb4ab67 588 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 589
Jonathan Austin 1:8aa5cdb4ab67 590 return ManagedString((char *)buff, returnedSize);
Jonathan Austin 1:8aa5cdb4ab67 591 }
Jonathan Austin 1:8aa5cdb4ab67 592
Jonathan Austin 1:8aa5cdb4ab67 593 /**
Jonathan Austin 1:8aa5cdb4ab67 594 * Reads multiple characters from the rxBuff and fills a user buffer.
Jonathan Austin 1:8aa5cdb4ab67 595 *
Jonathan Austin 1:8aa5cdb4ab67 596 * @param buffer a pointer to a user allocated buffer.
Jonathan Austin 1:8aa5cdb4ab67 597 *
Jonathan Austin 1:8aa5cdb4ab67 598 * @param bufferLen the amount of data that can be safely stored
Jonathan Austin 1:8aa5cdb4ab67 599 *
Jonathan Austin 1:8aa5cdb4ab67 600 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 601 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 602 *
Jonathan Austin 1:8aa5cdb4ab67 603 * ASYNC - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 604 * the given buffer. Otherwise, it will fill the buffer with however
Jonathan Austin 1:8aa5cdb4ab67 605 * many characters there are available.
Jonathan Austin 1:8aa5cdb4ab67 606 *
Jonathan Austin 1:8aa5cdb4ab67 607 * SYNC_SPINWAIT - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 608 * the given buffer. Otherwise, this method will spin (lock up the processor)
Jonathan Austin 1:8aa5cdb4ab67 609 * and fill the buffer until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 610 *
Jonathan Austin 1:8aa5cdb4ab67 611 * SYNC_SLEEP - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 612 * the given buffer. Otherwise, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 613 * until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 614 *
Jonathan Austin 1:8aa5cdb4ab67 615 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 616 *
Jonathan Austin 1:8aa5cdb4ab67 617 * @return the number of characters read, or MICROBIT_SERIAL_IN_USE if another fiber
Jonathan Austin 1:8aa5cdb4ab67 618 * is using the instance for receiving.
Jonathan Austin 1:8aa5cdb4ab67 619 */
Jonathan Austin 1:8aa5cdb4ab67 620 int MicroBitSerial::read(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 621 {
Jonathan Austin 1:8aa5cdb4ab67 622 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 623 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 624
Jonathan Austin 1:8aa5cdb4ab67 625 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 626
Jonathan Austin 1:8aa5cdb4ab67 627 //lazy initialisation of our rx buffer
Jonathan Austin 1:8aa5cdb4ab67 628 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 629 {
Jonathan Austin 1:8aa5cdb4ab67 630 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 631
Jonathan Austin 1:8aa5cdb4ab67 632 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 633 return result;
Jonathan Austin 1:8aa5cdb4ab67 634 }
Jonathan Austin 1:8aa5cdb4ab67 635
Jonathan Austin 1:8aa5cdb4ab67 636 int bufferIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 637
Jonathan Austin 1:8aa5cdb4ab67 638 int temp = 0;
Jonathan Austin 1:8aa5cdb4ab67 639
Jonathan Austin 1:8aa5cdb4ab67 640 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 641 {
Jonathan Austin 1:8aa5cdb4ab67 642 while((temp = getChar(mode)) != MICROBIT_NO_DATA && bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 643 {
Jonathan Austin 1:8aa5cdb4ab67 644 buffer[bufferIndex] = (char)temp;
Jonathan Austin 1:8aa5cdb4ab67 645 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 646 }
Jonathan Austin 1:8aa5cdb4ab67 647 }
Jonathan Austin 1:8aa5cdb4ab67 648
Jonathan Austin 1:8aa5cdb4ab67 649 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 650 {
Jonathan Austin 1:8aa5cdb4ab67 651 while(bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 652 {
Jonathan Austin 1:8aa5cdb4ab67 653 buffer[bufferIndex] = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 654 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 655 }
Jonathan Austin 1:8aa5cdb4ab67 656 }
Jonathan Austin 1:8aa5cdb4ab67 657
Jonathan Austin 1:8aa5cdb4ab67 658 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 659 {
Jonathan Austin 1:8aa5cdb4ab67 660 if(bufferLen > rxBufferedSize())
Jonathan Austin 1:8aa5cdb4ab67 661 eventAfter(bufferLen - rxBufferedSize(), mode);
Jonathan Austin 1:8aa5cdb4ab67 662
Jonathan Austin 1:8aa5cdb4ab67 663 while(bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 664 {
Jonathan Austin 1:8aa5cdb4ab67 665 buffer[bufferIndex] = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 666 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 667 }
Jonathan Austin 1:8aa5cdb4ab67 668 }
Jonathan Austin 1:8aa5cdb4ab67 669
Jonathan Austin 1:8aa5cdb4ab67 670 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 671
Jonathan Austin 1:8aa5cdb4ab67 672 return bufferIndex;
Jonathan Austin 1:8aa5cdb4ab67 673 }
Jonathan Austin 1:8aa5cdb4ab67 674
Jonathan Austin 1:8aa5cdb4ab67 675
Jonathan Austin 1:8aa5cdb4ab67 676 /**
Jonathan Austin 1:8aa5cdb4ab67 677 * Reads until one of the delimeters matches a character in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 678 *
Jonathan Austin 1:8aa5cdb4ab67 679 * @param delimeters a ManagedString containing a sequence of delimeter characters e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 680 *
Jonathan Austin 1:8aa5cdb4ab67 681 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 682 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 683 *
Jonathan Austin 1:8aa5cdb4ab67 684 * ASYNC - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 685 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 686 * Otherwise, it will return an Empty ManagedString.
Jonathan Austin 1:8aa5cdb4ab67 687 *
Jonathan Austin 1:8aa5cdb4ab67 688 * SYNC_SPINWAIT - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 689 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 690 * Otherwise, this method will spin (lock up the processor) until a
Jonathan Austin 1:8aa5cdb4ab67 691 * received character matches one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 692 *
Jonathan Austin 1:8aa5cdb4ab67 693 * SYNC_SLEEP - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 694 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 695 * Otherwise, the calling fiber sleeps until a character matching one
Jonathan Austin 1:8aa5cdb4ab67 696 * of the delimeters is seen.
Jonathan Austin 1:8aa5cdb4ab67 697 *
Jonathan Austin 1:8aa5cdb4ab67 698 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 699 *
Jonathan Austin 1:8aa5cdb4ab67 700 * @return A ManagedString containing the characters up to a delimeter, or an Empty ManagedString,
Jonathan Austin 1:8aa5cdb4ab67 701 * if another fiber is currently using this instance for reception.
Jonathan Austin 1:8aa5cdb4ab67 702 *
Jonathan Austin 1:8aa5cdb4ab67 703 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 704 */
Jonathan Austin 1:8aa5cdb4ab67 705 ManagedString MicroBitSerial::readUntil(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 706 {
Jonathan Austin 1:8aa5cdb4ab67 707
Jonathan Austin 1:8aa5cdb4ab67 708 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 709 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 710
Jonathan Austin 1:8aa5cdb4ab67 711 //lazy initialisation of our rx buffer
Jonathan Austin 1:8aa5cdb4ab67 712 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 713 {
Jonathan Austin 1:8aa5cdb4ab67 714 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 715
Jonathan Austin 1:8aa5cdb4ab67 716 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 717 return result;
Jonathan Austin 1:8aa5cdb4ab67 718 }
Jonathan Austin 1:8aa5cdb4ab67 719
Jonathan Austin 1:8aa5cdb4ab67 720 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 721
Jonathan Austin 1:8aa5cdb4ab67 722 int localTail = rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 723 int preservedTail = rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 724
Jonathan Austin 1:8aa5cdb4ab67 725 int foundIndex = -1;
Jonathan Austin 1:8aa5cdb4ab67 726
Jonathan Austin 1:8aa5cdb4ab67 727 //ASYNC mode just iterates through our stored characters checking for any matches.
Jonathan Austin 1:8aa5cdb4ab67 728 while(localTail != rxBuffHead && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 729 {
Jonathan Austin 1:8aa5cdb4ab67 730 //we use localTail to prevent modification of the actual tail.
Jonathan Austin 1:8aa5cdb4ab67 731 char c = rxBuff[localTail];
Jonathan Austin 1:8aa5cdb4ab67 732
Jonathan Austin 1:8aa5cdb4ab67 733 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 734 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 735 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 736
Jonathan Austin 1:8aa5cdb4ab67 737 localTail = (localTail + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 738 }
Jonathan Austin 1:8aa5cdb4ab67 739
Jonathan Austin 1:8aa5cdb4ab67 740 //if our mode is SYNC_SPINWAIT and we didn't see any matching characters in our buffer
Jonathan Austin 1:8aa5cdb4ab67 741 //spin until we find a match!
Jonathan Austin 1:8aa5cdb4ab67 742 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 743 {
Jonathan Austin 1:8aa5cdb4ab67 744 while(foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 745 {
Jonathan Austin 1:8aa5cdb4ab67 746 while(localTail == rxBuffHead);
Jonathan Austin 1:8aa5cdb4ab67 747
Jonathan Austin 1:8aa5cdb4ab67 748 char c = rxBuff[localTail];
Jonathan Austin 1:8aa5cdb4ab67 749
Jonathan Austin 1:8aa5cdb4ab67 750 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 751 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 752 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 753
Jonathan Austin 1:8aa5cdb4ab67 754 localTail = (localTail + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 755 }
Jonathan Austin 1:8aa5cdb4ab67 756 }
Jonathan Austin 1:8aa5cdb4ab67 757
Jonathan Austin 1:8aa5cdb4ab67 758 //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a
Jonathan Austin 1:8aa5cdb4ab67 759 //matching character.
Jonathan Austin 1:8aa5cdb4ab67 760 if(mode == SYNC_SLEEP && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 761 {
Jonathan Austin 1:8aa5cdb4ab67 762 eventOn(delimeters, mode);
Jonathan Austin 1:8aa5cdb4ab67 763
Jonathan Austin 1:8aa5cdb4ab67 764 foundIndex = rxBuffHead - 1;
Jonathan Austin 1:8aa5cdb4ab67 765
Jonathan Austin 1:8aa5cdb4ab67 766 this->delimeters = ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 767 }
Jonathan Austin 1:8aa5cdb4ab67 768
Jonathan Austin 1:8aa5cdb4ab67 769 if(foundIndex >= 0)
Jonathan Austin 1:8aa5cdb4ab67 770 {
Jonathan Austin 1:8aa5cdb4ab67 771 //calculate our local buffer size
Jonathan Austin 1:8aa5cdb4ab67 772 int localBuffSize = (preservedTail > foundIndex) ? (rxBuffSize - preservedTail) + foundIndex : foundIndex - preservedTail;
Jonathan Austin 1:8aa5cdb4ab67 773
LancasterUniversity 3:d86a4ddc1867 774 uint8_t localBuff[localBuffSize + 1];
Jonathan Austin 1:8aa5cdb4ab67 775
LancasterUniversity 8:ec4465853952 776 memclr(&localBuff, localBuffSize + 1);
LancasterUniversity 8:ec4465853952 777
Jonathan Austin 1:8aa5cdb4ab67 778 circularCopy(rxBuff, rxBuffSize, localBuff, preservedTail, foundIndex);
Jonathan Austin 1:8aa5cdb4ab67 779
Jonathan Austin 1:8aa5cdb4ab67 780 //plus one for the character we listened for...
Jonathan Austin 1:8aa5cdb4ab67 781 rxBuffTail = (rxBuffTail + localBuffSize + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 782
Jonathan Austin 1:8aa5cdb4ab67 783 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 784
Jonathan Austin 1:8aa5cdb4ab67 785 return ManagedString((char *)localBuff, localBuffSize);
Jonathan Austin 1:8aa5cdb4ab67 786 }
Jonathan Austin 1:8aa5cdb4ab67 787
Jonathan Austin 1:8aa5cdb4ab67 788 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 789
Jonathan Austin 1:8aa5cdb4ab67 790 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 791 }
Jonathan Austin 1:8aa5cdb4ab67 792
Jonathan Austin 1:8aa5cdb4ab67 793 /**
Jonathan Austin 1:8aa5cdb4ab67 794 * A wrapper around the inherited method "baud" so we can trap the baud rate
Jonathan Austin 1:8aa5cdb4ab67 795 * as it changes and restore it if redirect() is called.
Jonathan Austin 1:8aa5cdb4ab67 796 *
Jonathan Austin 1:8aa5cdb4ab67 797 * @param baudrate the new baudrate. See:
Jonathan Austin 1:8aa5cdb4ab67 798 * - https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/serial_api.c
Jonathan Austin 1:8aa5cdb4ab67 799 * for permitted baud rates.
Jonathan Austin 1:8aa5cdb4ab67 800 *
Jonathan Austin 1:8aa5cdb4ab67 801 * @return MICROBIT_INVALID_PARAMETER if baud rate is less than 0, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 802 *
Jonathan Austin 1:8aa5cdb4ab67 803 * @note the underlying implementation chooses the first allowable rate at or above that requested.
Jonathan Austin 1:8aa5cdb4ab67 804 */
Jonathan Austin 1:8aa5cdb4ab67 805 void MicroBitSerial::baud(int baudrate)
Jonathan Austin 1:8aa5cdb4ab67 806 {
Jonathan Austin 1:8aa5cdb4ab67 807 if(baudrate < 0)
Jonathan Austin 1:8aa5cdb4ab67 808 return;
Jonathan Austin 1:8aa5cdb4ab67 809
Jonathan Austin 1:8aa5cdb4ab67 810 this->baudrate = baudrate;
Jonathan Austin 1:8aa5cdb4ab67 811
Jonathan Austin 1:8aa5cdb4ab67 812 RawSerial::baud(baudrate);
Jonathan Austin 1:8aa5cdb4ab67 813 }
Jonathan Austin 1:8aa5cdb4ab67 814
Jonathan Austin 1:8aa5cdb4ab67 815 /**
Jonathan Austin 1:8aa5cdb4ab67 816 * A way of dynamically configuring the serial instance to use pins other than USBTX and USBRX.
Jonathan Austin 1:8aa5cdb4ab67 817 *
Jonathan Austin 1:8aa5cdb4ab67 818 * @param tx the new transmission pin.
Jonathan Austin 1:8aa5cdb4ab67 819 *
Jonathan Austin 1:8aa5cdb4ab67 820 * @param rx the new reception pin.
Jonathan Austin 1:8aa5cdb4ab67 821 *
Jonathan Austin 1:8aa5cdb4ab67 822 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently transmitting or receiving, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 823 */
Jonathan Austin 1:8aa5cdb4ab67 824 int MicroBitSerial::redirect(PinName tx, PinName rx)
Jonathan Austin 1:8aa5cdb4ab67 825 {
Jonathan Austin 1:8aa5cdb4ab67 826 if(txInUse() || rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 827 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 828
Jonathan Austin 1:8aa5cdb4ab67 829 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 830 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 831
Jonathan Austin 1:8aa5cdb4ab67 832 if(txBufferedSize() > 0)
LancasterUniversity 6:2e1c2e0d8c7a 833 detach(Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 834
LancasterUniversity 6:2e1c2e0d8c7a 835 detach(Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 836
Jonathan Austin 1:8aa5cdb4ab67 837 serial_free(&_serial);
Jonathan Austin 1:8aa5cdb4ab67 838 serial_init(&_serial, tx, rx);
Jonathan Austin 1:8aa5cdb4ab67 839
LancasterUniversity 6:2e1c2e0d8c7a 840 attach(this, &MicroBitSerial::dataReceived, Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 841
Jonathan Austin 1:8aa5cdb4ab67 842 if(txBufferedSize() > 0)
LancasterUniversity 6:2e1c2e0d8c7a 843 attach(this, &MicroBitSerial::dataWritten, Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 844
Jonathan Austin 1:8aa5cdb4ab67 845 this->baud(this->baudrate);
Jonathan Austin 1:8aa5cdb4ab67 846
Jonathan Austin 1:8aa5cdb4ab67 847 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 848 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 849
Jonathan Austin 1:8aa5cdb4ab67 850 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 851 }
Jonathan Austin 1:8aa5cdb4ab67 852
Jonathan Austin 1:8aa5cdb4ab67 853 /**
Jonathan Austin 1:8aa5cdb4ab67 854 * Configures an event to be fired after "len" characters.
Jonathan Austin 1:8aa5cdb4ab67 855 *
Jonathan Austin 1:8aa5cdb4ab67 856 * @param len the number of characters to wait before triggering the event.
Jonathan Austin 1:8aa5cdb4ab67 857 *
Jonathan Austin 1:8aa5cdb4ab67 858 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 859 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 860 *
Jonathan Austin 1:8aa5cdb4ab67 861 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 862 *
Jonathan Austin 1:8aa5cdb4ab67 863 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 864 *
Jonathan Austin 1:8aa5cdb4ab67 865 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 866 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 867 *
Jonathan Austin 1:8aa5cdb4ab67 868 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 869 */
Jonathan Austin 1:8aa5cdb4ab67 870 int MicroBitSerial::eventAfter(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 871 {
Jonathan Austin 1:8aa5cdb4ab67 872 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 873 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 874
Jonathan Austin 1:8aa5cdb4ab67 875 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 876 this->rxBuffHeadMatch = (rxBuffHead + len) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 877
Jonathan Austin 1:8aa5cdb4ab67 878 //block!
Jonathan Austin 1:8aa5cdb4ab67 879 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 880 fiber_wait_for_event(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 881
Jonathan Austin 1:8aa5cdb4ab67 882 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 883 }
Jonathan Austin 1:8aa5cdb4ab67 884
Jonathan Austin 1:8aa5cdb4ab67 885 /**
Jonathan Austin 1:8aa5cdb4ab67 886 * Configures an event to be fired on a match with one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 887 *
Jonathan Austin 1:8aa5cdb4ab67 888 * @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 889 *
Jonathan Austin 1:8aa5cdb4ab67 890 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 891 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 892 *
Jonathan Austin 1:8aa5cdb4ab67 893 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 894 *
Jonathan Austin 1:8aa5cdb4ab67 895 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 896 *
Jonathan Austin 1:8aa5cdb4ab67 897 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 898 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 899 *
Jonathan Austin 1:8aa5cdb4ab67 900 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 901 *
Jonathan Austin 1:8aa5cdb4ab67 902 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 903 */
Jonathan Austin 1:8aa5cdb4ab67 904 int MicroBitSerial::eventOn(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 905 {
Jonathan Austin 1:8aa5cdb4ab67 906 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 907 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 908
Jonathan Austin 1:8aa5cdb4ab67 909 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 910 this->delimeters = delimeters;
Jonathan Austin 1:8aa5cdb4ab67 911
Jonathan Austin 1:8aa5cdb4ab67 912 //block!
Jonathan Austin 1:8aa5cdb4ab67 913 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 914 fiber_wait_for_event(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 915
Jonathan Austin 1:8aa5cdb4ab67 916 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 917 }
Jonathan Austin 1:8aa5cdb4ab67 918
Jonathan Austin 1:8aa5cdb4ab67 919 /**
Jonathan Austin 1:8aa5cdb4ab67 920 * Determines whether there is any data waiting in our Rx buffer.
Jonathan Austin 1:8aa5cdb4ab67 921 *
Jonathan Austin 1:8aa5cdb4ab67 922 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 923 *
Jonathan Austin 1:8aa5cdb4ab67 924 * @note We do not wrap the super's readable() method as we don't want to
Jonathan Austin 1:8aa5cdb4ab67 925 * interfere with communities that use manual calls to serial.readable().
Jonathan Austin 1:8aa5cdb4ab67 926 */
Jonathan Austin 1:8aa5cdb4ab67 927 int MicroBitSerial::isReadable()
Jonathan Austin 1:8aa5cdb4ab67 928 {
Jonathan Austin 1:8aa5cdb4ab67 929 return (rxBuffTail != rxBuffHead) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 930 }
Jonathan Austin 1:8aa5cdb4ab67 931
Jonathan Austin 1:8aa5cdb4ab67 932 /**
Jonathan Austin 1:8aa5cdb4ab67 933 * Determines if we have space in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 934 *
Jonathan Austin 1:8aa5cdb4ab67 935 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 936 *
Jonathan Austin 1:8aa5cdb4ab67 937 * @note We do not wrap the super's writeable() method as we don't want to
Jonathan Austin 1:8aa5cdb4ab67 938 * interfere with communities that use manual calls to serial.writeable().
Jonathan Austin 1:8aa5cdb4ab67 939 */
Jonathan Austin 1:8aa5cdb4ab67 940 int MicroBitSerial::isWriteable()
Jonathan Austin 1:8aa5cdb4ab67 941 {
Jonathan Austin 1:8aa5cdb4ab67 942 return (txBuffHead != (txBuffTail - 1)) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 943 }
Jonathan Austin 1:8aa5cdb4ab67 944
Jonathan Austin 1:8aa5cdb4ab67 945 /**
Jonathan Austin 1:8aa5cdb4ab67 946 * Reconfigures the size of our rxBuff
Jonathan Austin 1:8aa5cdb4ab67 947 *
Jonathan Austin 1:8aa5cdb4ab67 948 * @param size the new size for our rxBuff
Jonathan Austin 1:8aa5cdb4ab67 949 *
Jonathan Austin 1:8aa5cdb4ab67 950 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 951 * for reception, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 952 */
Jonathan Austin 1:8aa5cdb4ab67 953 int MicroBitSerial::setRxBufferSize(uint8_t size)
Jonathan Austin 1:8aa5cdb4ab67 954 {
Jonathan Austin 1:8aa5cdb4ab67 955 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 956 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 957
Jonathan Austin 1:8aa5cdb4ab67 958 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 959
Jonathan Austin 1:8aa5cdb4ab67 960 this->rxBuffSize = size;
Jonathan Austin 1:8aa5cdb4ab67 961
Jonathan Austin 1:8aa5cdb4ab67 962 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 963
Jonathan Austin 1:8aa5cdb4ab67 964 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 965
Jonathan Austin 1:8aa5cdb4ab67 966 return result;
Jonathan Austin 1:8aa5cdb4ab67 967 }
Jonathan Austin 1:8aa5cdb4ab67 968
Jonathan Austin 1:8aa5cdb4ab67 969 /**
Jonathan Austin 1:8aa5cdb4ab67 970 * Reconfigures the size of our txBuff
Jonathan Austin 1:8aa5cdb4ab67 971 *
Jonathan Austin 1:8aa5cdb4ab67 972 * @param size the new size for our txBuff
Jonathan Austin 1:8aa5cdb4ab67 973 *
Jonathan Austin 1:8aa5cdb4ab67 974 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 975 * for transmission, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 976 */
Jonathan Austin 1:8aa5cdb4ab67 977 int MicroBitSerial::setTxBufferSize(uint8_t size)
Jonathan Austin 1:8aa5cdb4ab67 978 {
Jonathan Austin 1:8aa5cdb4ab67 979 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 980 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 981
Jonathan Austin 1:8aa5cdb4ab67 982 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 983
Jonathan Austin 1:8aa5cdb4ab67 984 this->txBuffSize = size;
Jonathan Austin 1:8aa5cdb4ab67 985
Jonathan Austin 1:8aa5cdb4ab67 986 int result = initialiseTx();
Jonathan Austin 1:8aa5cdb4ab67 987
Jonathan Austin 1:8aa5cdb4ab67 988 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 989
Jonathan Austin 1:8aa5cdb4ab67 990 return result;
Jonathan Austin 1:8aa5cdb4ab67 991 }
Jonathan Austin 1:8aa5cdb4ab67 992
Jonathan Austin 1:8aa5cdb4ab67 993 /**
Jonathan Austin 1:8aa5cdb4ab67 994 * The size of our rx buffer in bytes.
Jonathan Austin 1:8aa5cdb4ab67 995 *
Jonathan Austin 1:8aa5cdb4ab67 996 * @return the current size of rxBuff in bytes
Jonathan Austin 1:8aa5cdb4ab67 997 */
Jonathan Austin 1:8aa5cdb4ab67 998 int MicroBitSerial::getRxBufferSize()
Jonathan Austin 1:8aa5cdb4ab67 999 {
Jonathan Austin 1:8aa5cdb4ab67 1000 return this->rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 1001 }
Jonathan Austin 1:8aa5cdb4ab67 1002
Jonathan Austin 1:8aa5cdb4ab67 1003 /**
Jonathan Austin 1:8aa5cdb4ab67 1004 * The size of our tx buffer in bytes.
Jonathan Austin 1:8aa5cdb4ab67 1005 *
Jonathan Austin 1:8aa5cdb4ab67 1006 * @return the current size of txBuff in bytes
Jonathan Austin 1:8aa5cdb4ab67 1007 */
Jonathan Austin 1:8aa5cdb4ab67 1008 int MicroBitSerial::getTxBufferSize()
Jonathan Austin 1:8aa5cdb4ab67 1009 {
Jonathan Austin 1:8aa5cdb4ab67 1010 return this->txBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 1011 }
Jonathan Austin 1:8aa5cdb4ab67 1012
Jonathan Austin 1:8aa5cdb4ab67 1013 /**
Jonathan Austin 1:8aa5cdb4ab67 1014 * Sets the tail to match the head of our circular buffer for reception,
Jonathan Austin 1:8aa5cdb4ab67 1015 * effectively clearing the reception buffer.
Jonathan Austin 1:8aa5cdb4ab67 1016 *
Jonathan Austin 1:8aa5cdb4ab67 1017 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 1018 * for reception, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 1019 */
Jonathan Austin 1:8aa5cdb4ab67 1020 int MicroBitSerial::clearRxBuffer()
Jonathan Austin 1:8aa5cdb4ab67 1021 {
Jonathan Austin 1:8aa5cdb4ab67 1022 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 1023 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 1024
Jonathan Austin 1:8aa5cdb4ab67 1025 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 1026
Jonathan Austin 1:8aa5cdb4ab67 1027 rxBuffTail = rxBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1028
Jonathan Austin 1:8aa5cdb4ab67 1029 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 1030
Jonathan Austin 1:8aa5cdb4ab67 1031 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 1032 }
Jonathan Austin 1:8aa5cdb4ab67 1033
Jonathan Austin 1:8aa5cdb4ab67 1034 /**
Jonathan Austin 1:8aa5cdb4ab67 1035 * Sets the tail to match the head of our circular buffer for transmission,
Jonathan Austin 1:8aa5cdb4ab67 1036 * effectively clearing the transmission buffer.
Jonathan Austin 1:8aa5cdb4ab67 1037 *
Jonathan Austin 1:8aa5cdb4ab67 1038 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 1039 * for transmission, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 1040 */
Jonathan Austin 1:8aa5cdb4ab67 1041 int MicroBitSerial::clearTxBuffer()
Jonathan Austin 1:8aa5cdb4ab67 1042 {
Jonathan Austin 1:8aa5cdb4ab67 1043 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 1044 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 1045
Jonathan Austin 1:8aa5cdb4ab67 1046 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 1047
Jonathan Austin 1:8aa5cdb4ab67 1048 txBuffTail = txBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1049
Jonathan Austin 1:8aa5cdb4ab67 1050 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 1051
Jonathan Austin 1:8aa5cdb4ab67 1052 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 1053 }
Jonathan Austin 1:8aa5cdb4ab67 1054
Jonathan Austin 1:8aa5cdb4ab67 1055 /**
Jonathan Austin 1:8aa5cdb4ab67 1056 * The number of bytes currently stored in our rx buffer waiting to be digested,
Jonathan Austin 1:8aa5cdb4ab67 1057 * by the user.
Jonathan Austin 1:8aa5cdb4ab67 1058 *
Jonathan Austin 1:8aa5cdb4ab67 1059 * @return The currently buffered number of bytes in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 1060 */
Jonathan Austin 1:8aa5cdb4ab67 1061 int MicroBitSerial::rxBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 1062 {
Jonathan Austin 1:8aa5cdb4ab67 1063 if(rxBuffTail > rxBuffHead)
Jonathan Austin 1:8aa5cdb4ab67 1064 return (rxBuffSize - rxBuffTail) + rxBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1065
Jonathan Austin 1:8aa5cdb4ab67 1066 return rxBuffHead - rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 1067 }
Jonathan Austin 1:8aa5cdb4ab67 1068
Jonathan Austin 1:8aa5cdb4ab67 1069 /**
Jonathan Austin 1:8aa5cdb4ab67 1070 * The number of bytes currently stored in our tx buffer waiting to be transmitted
Jonathan Austin 1:8aa5cdb4ab67 1071 * by the hardware.
Jonathan Austin 1:8aa5cdb4ab67 1072 *
Jonathan Austin 1:8aa5cdb4ab67 1073 * @return The currently buffered number of bytes in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 1074 */
Jonathan Austin 1:8aa5cdb4ab67 1075 int MicroBitSerial::txBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 1076 {
Jonathan Austin 1:8aa5cdb4ab67 1077 if(txBuffTail > txBuffHead)
Jonathan Austin 1:8aa5cdb4ab67 1078 return (txBuffSize - txBuffTail) + txBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1079
Jonathan Austin 1:8aa5cdb4ab67 1080 return txBuffHead - txBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 1081 }
Jonathan Austin 1:8aa5cdb4ab67 1082
Jonathan Austin 1:8aa5cdb4ab67 1083 /**
Jonathan Austin 1:8aa5cdb4ab67 1084 * Determines if the serial bus is currently in use by another fiber for reception.
Jonathan Austin 1:8aa5cdb4ab67 1085 *
Jonathan Austin 1:8aa5cdb4ab67 1086 * @return The state of our mutex lock for reception.
Jonathan Austin 1:8aa5cdb4ab67 1087 *
Jonathan Austin 1:8aa5cdb4ab67 1088 * @note Only one fiber can call read at a time
Jonathan Austin 1:8aa5cdb4ab67 1089 */
Jonathan Austin 1:8aa5cdb4ab67 1090 int MicroBitSerial::rxInUse()
Jonathan Austin 1:8aa5cdb4ab67 1091 {
Jonathan Austin 1:8aa5cdb4ab67 1092 return (status & MICROBIT_SERIAL_RX_IN_USE);
Jonathan Austin 1:8aa5cdb4ab67 1093 }
Jonathan Austin 1:8aa5cdb4ab67 1094
Jonathan Austin 1:8aa5cdb4ab67 1095 /**
Jonathan Austin 1:8aa5cdb4ab67 1096 * Determines if the serial bus is currently in use by another fiber for transmission.
Jonathan Austin 1:8aa5cdb4ab67 1097 *
Jonathan Austin 1:8aa5cdb4ab67 1098 * @return The state of our mutex lock for transmition.
Jonathan Austin 1:8aa5cdb4ab67 1099 *
Jonathan Austin 1:8aa5cdb4ab67 1100 * @note Only one fiber can call send at a time
Jonathan Austin 1:8aa5cdb4ab67 1101 */
Jonathan Austin 1:8aa5cdb4ab67 1102 int MicroBitSerial::txInUse()
Jonathan Austin 1:8aa5cdb4ab67 1103 {
Jonathan Austin 1:8aa5cdb4ab67 1104 return (status & MICROBIT_SERIAL_TX_IN_USE);
Jonathan Austin 1:8aa5cdb4ab67 1105 }
Jonathan Austin 1:8aa5cdb4ab67 1106
Jonathan Austin 1:8aa5cdb4ab67 1107 /**
Jonathan Austin 1:8aa5cdb4ab67 1108 * Detaches a previously configured interrupt
Jonathan Austin 1:8aa5cdb4ab67 1109 *
Jonathan Austin 1:8aa5cdb4ab67 1110 * @param interruptType one of Serial::RxIrq or Serial::TxIrq
Jonathan Austin 1:8aa5cdb4ab67 1111 */
Jonathan Austin 1:8aa5cdb4ab67 1112 void MicroBitSerial::detach(Serial::IrqType interruptType)
Jonathan Austin 1:8aa5cdb4ab67 1113 {
Jonathan Austin 1:8aa5cdb4ab67 1114 //we detach by sending a bad value to attach, for some weird reason...
Jonathan Austin 1:8aa5cdb4ab67 1115 attach((MicroBitSerial *)NULL, &MicroBitSerial::dataReceived, interruptType);
LancasterUniversity 3:d86a4ddc1867 1116 }