test

Dependencies:   BLE_API mbed-dev-bin nRF51822

Fork of microbit-dal by Lancaster University

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:17:54 2016 +0100
Revision:
22:23d7b9a4b082
Parent:
8:ec4465853952
Child:
23:6055f6c19fa6
Synchronized with git rev 7cf98c22
Author: James Devine
microbit-dal: patch for fiber_wake_on_event

fiber_wake_on_event used to crash after forking a FOB fiber.

It would attempt to obtain a new fiber context, and would place it on the wait queue.
Then when that fiber was paged in, the context of that fiber would not have been
initialised, as the function presumed schedule would be called immediately after
fiber initialisation.

This patch catches that edge case.

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 22:23d7b9a4b082 167 * @param mode determines whether to configure the current fiber context or not. If
LancasterUniversity 22:23d7b9a4b082 168 * The mode is SYNC_SPINWAIT, the context will not be configured, otherwise
LancasterUniversity 22:23d7b9a4b082 169 * no context will be configured.
LancasterUniversity 22:23d7b9a4b082 170 *
Jonathan Austin 1:8aa5cdb4ab67 171 * @return the number of bytes copied into the buffer.
Jonathan Austin 1:8aa5cdb4ab67 172 */
LancasterUniversity 22:23d7b9a4b082 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 22:23d7b9a4b082 189 if(mode != SYNC_SPINWAIT)
LancasterUniversity 22:23d7b9a4b082 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 22:23d7b9a4b082 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 22:23d7b9a4b082 492 int bytesWritten = setTxInterrupt(buffer, bufferLen, mode);
Jonathan Austin 1:8aa5cdb4ab67 493
Jonathan Austin 1:8aa5cdb4ab67 494 send(mode);
Jonathan Austin 1:8aa5cdb4ab67 495
Jonathan Austin 1:8aa5cdb4ab67 496 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 497
Jonathan Austin 1:8aa5cdb4ab67 498 return bytesWritten;
Jonathan Austin 1:8aa5cdb4ab67 499 }
Jonathan Austin 1:8aa5cdb4ab67 500
Jonathan Austin 1:8aa5cdb4ab67 501 /**
Jonathan Austin 1:8aa5cdb4ab67 502 * Reads a single character from the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 503 *
Jonathan Austin 1:8aa5cdb4ab67 504 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 505 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 506 *
Jonathan Austin 1:8aa5cdb4ab67 507 * ASYNC - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 508 * are no characters to be read, a value of MICROBIT_NO_DATA is returned immediately.
Jonathan Austin 1:8aa5cdb4ab67 509 *
Jonathan Austin 1:8aa5cdb4ab67 510 * SYNC_SPINWAIT - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 511 * are no characters to be read, this method will spin
Jonathan Austin 1:8aa5cdb4ab67 512 * (lock up the processor) until a character is available.
Jonathan Austin 1:8aa5cdb4ab67 513 *
Jonathan Austin 1:8aa5cdb4ab67 514 * SYNC_SLEEP - A character is read from the rxBuff if available, if there
Jonathan Austin 1:8aa5cdb4ab67 515 * are no characters to be read, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 516 * until there is a character available.
Jonathan Austin 1:8aa5cdb4ab67 517 *
Jonathan Austin 1:8aa5cdb4ab67 518 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 519 *
Jonathan Austin 1:8aa5cdb4ab67 520 * @return a character, MICROBIT_SERIAL_IN_USE if another fiber is using the serial instance for reception,
Jonathan Austin 1:8aa5cdb4ab67 521 * MICROBIT_NO_RESOURCES if buffer allocation did not complete successfully, or MICROBIT_NO_DATA if
Jonathan Austin 1:8aa5cdb4ab67 522 * the rx buffer is empty and the mode given is ASYNC.
Jonathan Austin 1:8aa5cdb4ab67 523 */
Jonathan Austin 1:8aa5cdb4ab67 524 int MicroBitSerial::read(MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 525 {
Jonathan Austin 1:8aa5cdb4ab67 526 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 527 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 528
Jonathan Austin 1:8aa5cdb4ab67 529 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 530
Jonathan Austin 1:8aa5cdb4ab67 531 //lazy initialisation of our buffers
Jonathan Austin 1:8aa5cdb4ab67 532 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 533 {
Jonathan Austin 1:8aa5cdb4ab67 534 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 535
Jonathan Austin 1:8aa5cdb4ab67 536 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 537 return result;
Jonathan Austin 1:8aa5cdb4ab67 538 }
Jonathan Austin 1:8aa5cdb4ab67 539
Jonathan Austin 1:8aa5cdb4ab67 540 char c = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 541
Jonathan Austin 1:8aa5cdb4ab67 542 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 543
Jonathan Austin 1:8aa5cdb4ab67 544 return c;
Jonathan Austin 1:8aa5cdb4ab67 545 }
Jonathan Austin 1:8aa5cdb4ab67 546
Jonathan Austin 1:8aa5cdb4ab67 547 /**
Jonathan Austin 1:8aa5cdb4ab67 548 * Reads multiple characters from the rxBuff and returns them as a ManagedString
Jonathan Austin 1:8aa5cdb4ab67 549 *
Jonathan Austin 1:8aa5cdb4ab67 550 * @param size the number of characters to read.
Jonathan Austin 1:8aa5cdb4ab67 551 *
Jonathan Austin 1:8aa5cdb4ab67 552 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 553 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 554 *
Jonathan Austin 1:8aa5cdb4ab67 555 * ASYNC - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 556 * a ManagedString with the expected size. Otherwise, it will read however
Jonathan Austin 1:8aa5cdb4ab67 557 * many characters there are available.
Jonathan Austin 1:8aa5cdb4ab67 558 *
Jonathan Austin 1:8aa5cdb4ab67 559 * SYNC_SPINWAIT - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 560 * a ManagedString with the expected size. Otherwise, this method will spin
Jonathan Austin 1:8aa5cdb4ab67 561 * (lock up the processor) until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 562 *
Jonathan Austin 1:8aa5cdb4ab67 563 * SYNC_SLEEP - If the desired number of characters are available, this will return
Jonathan Austin 1:8aa5cdb4ab67 564 * a ManagedString with the expected size. Otherwise, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 565 * until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 566 *
Jonathan Austin 1:8aa5cdb4ab67 567 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 568 *
Jonathan Austin 1:8aa5cdb4ab67 569 * @return A ManagedString, or an empty ManagedString if an error was encountered during the read.
Jonathan Austin 1:8aa5cdb4ab67 570 */
Jonathan Austin 1:8aa5cdb4ab67 571 ManagedString MicroBitSerial::read(int size, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 572 {
LancasterUniversity 3:d86a4ddc1867 573 uint8_t buff[size + 1];
Jonathan Austin 1:8aa5cdb4ab67 574
LancasterUniversity 8:ec4465853952 575 memclr(&buff, size + 1);
LancasterUniversity 8:ec4465853952 576
Jonathan Austin 1:8aa5cdb4ab67 577 int returnedSize = read((uint8_t *)buff, size, mode);
Jonathan Austin 1:8aa5cdb4ab67 578
Jonathan Austin 1:8aa5cdb4ab67 579 if(returnedSize <= 0)
Jonathan Austin 1:8aa5cdb4ab67 580 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 581
Jonathan Austin 1:8aa5cdb4ab67 582 return ManagedString((char *)buff, returnedSize);
Jonathan Austin 1:8aa5cdb4ab67 583 }
Jonathan Austin 1:8aa5cdb4ab67 584
Jonathan Austin 1:8aa5cdb4ab67 585 /**
Jonathan Austin 1:8aa5cdb4ab67 586 * Reads multiple characters from the rxBuff and fills a user buffer.
Jonathan Austin 1:8aa5cdb4ab67 587 *
Jonathan Austin 1:8aa5cdb4ab67 588 * @param buffer a pointer to a user allocated buffer.
Jonathan Austin 1:8aa5cdb4ab67 589 *
Jonathan Austin 1:8aa5cdb4ab67 590 * @param bufferLen the amount of data that can be safely stored
Jonathan Austin 1:8aa5cdb4ab67 591 *
Jonathan Austin 1:8aa5cdb4ab67 592 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 593 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 594 *
Jonathan Austin 1:8aa5cdb4ab67 595 * ASYNC - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 596 * the given buffer. Otherwise, it will fill the buffer with however
Jonathan Austin 1:8aa5cdb4ab67 597 * many characters there are available.
Jonathan Austin 1:8aa5cdb4ab67 598 *
Jonathan Austin 1:8aa5cdb4ab67 599 * SYNC_SPINWAIT - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 600 * the given buffer. Otherwise, this method will spin (lock up the processor)
Jonathan Austin 1:8aa5cdb4ab67 601 * and fill the buffer until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 602 *
Jonathan Austin 1:8aa5cdb4ab67 603 * SYNC_SLEEP - If the desired number of characters are available, this will fill
Jonathan Austin 1:8aa5cdb4ab67 604 * the given buffer. Otherwise, the calling fiber sleeps
Jonathan Austin 1:8aa5cdb4ab67 605 * until the desired number of characters have been read.
Jonathan Austin 1:8aa5cdb4ab67 606 *
Jonathan Austin 1:8aa5cdb4ab67 607 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 608 *
Jonathan Austin 1:8aa5cdb4ab67 609 * @return the number of characters read, or MICROBIT_SERIAL_IN_USE if another fiber
Jonathan Austin 1:8aa5cdb4ab67 610 * is using the instance for receiving.
Jonathan Austin 1:8aa5cdb4ab67 611 */
Jonathan Austin 1:8aa5cdb4ab67 612 int MicroBitSerial::read(uint8_t *buffer, int bufferLen, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 613 {
Jonathan Austin 1:8aa5cdb4ab67 614 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 615 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 616
Jonathan Austin 1:8aa5cdb4ab67 617 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 618
Jonathan Austin 1:8aa5cdb4ab67 619 //lazy initialisation of our rx buffer
Jonathan Austin 1:8aa5cdb4ab67 620 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 621 {
Jonathan Austin 1:8aa5cdb4ab67 622 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 623
Jonathan Austin 1:8aa5cdb4ab67 624 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 625 return result;
Jonathan Austin 1:8aa5cdb4ab67 626 }
Jonathan Austin 1:8aa5cdb4ab67 627
Jonathan Austin 1:8aa5cdb4ab67 628 int bufferIndex = 0;
Jonathan Austin 1:8aa5cdb4ab67 629
Jonathan Austin 1:8aa5cdb4ab67 630 int temp = 0;
Jonathan Austin 1:8aa5cdb4ab67 631
Jonathan Austin 1:8aa5cdb4ab67 632 if(mode == ASYNC)
Jonathan Austin 1:8aa5cdb4ab67 633 {
Jonathan Austin 1:8aa5cdb4ab67 634 while((temp = getChar(mode)) != MICROBIT_NO_DATA && bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 635 {
Jonathan Austin 1:8aa5cdb4ab67 636 buffer[bufferIndex] = (char)temp;
Jonathan Austin 1:8aa5cdb4ab67 637 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 638 }
Jonathan Austin 1:8aa5cdb4ab67 639 }
Jonathan Austin 1:8aa5cdb4ab67 640
Jonathan Austin 1:8aa5cdb4ab67 641 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 642 {
Jonathan Austin 1:8aa5cdb4ab67 643 while(bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 644 {
Jonathan Austin 1:8aa5cdb4ab67 645 buffer[bufferIndex] = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 646 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 647 }
Jonathan Austin 1:8aa5cdb4ab67 648 }
Jonathan Austin 1:8aa5cdb4ab67 649
Jonathan Austin 1:8aa5cdb4ab67 650 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 651 {
Jonathan Austin 1:8aa5cdb4ab67 652 if(bufferLen > rxBufferedSize())
Jonathan Austin 1:8aa5cdb4ab67 653 eventAfter(bufferLen - rxBufferedSize(), mode);
Jonathan Austin 1:8aa5cdb4ab67 654
Jonathan Austin 1:8aa5cdb4ab67 655 while(bufferIndex < bufferLen)
Jonathan Austin 1:8aa5cdb4ab67 656 {
Jonathan Austin 1:8aa5cdb4ab67 657 buffer[bufferIndex] = (char)getChar(mode);
Jonathan Austin 1:8aa5cdb4ab67 658 bufferIndex++;
Jonathan Austin 1:8aa5cdb4ab67 659 }
Jonathan Austin 1:8aa5cdb4ab67 660 }
Jonathan Austin 1:8aa5cdb4ab67 661
Jonathan Austin 1:8aa5cdb4ab67 662 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 663
Jonathan Austin 1:8aa5cdb4ab67 664 return bufferIndex;
Jonathan Austin 1:8aa5cdb4ab67 665 }
Jonathan Austin 1:8aa5cdb4ab67 666
Jonathan Austin 1:8aa5cdb4ab67 667
Jonathan Austin 1:8aa5cdb4ab67 668 /**
Jonathan Austin 1:8aa5cdb4ab67 669 * Reads until one of the delimeters matches a character in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 670 *
Jonathan Austin 1:8aa5cdb4ab67 671 * @param delimeters a ManagedString containing a sequence of delimeter characters e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 672 *
Jonathan Austin 1:8aa5cdb4ab67 673 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 674 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 675 *
Jonathan Austin 1:8aa5cdb4ab67 676 * ASYNC - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 677 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 678 * Otherwise, it will return an Empty ManagedString.
Jonathan Austin 1:8aa5cdb4ab67 679 *
Jonathan Austin 1:8aa5cdb4ab67 680 * SYNC_SPINWAIT - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 681 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 682 * Otherwise, this method will spin (lock up the processor) until a
Jonathan Austin 1:8aa5cdb4ab67 683 * received character matches one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 684 *
Jonathan Austin 1:8aa5cdb4ab67 685 * SYNC_SLEEP - If one of the delimeters matches a character already in the rxBuff
Jonathan Austin 1:8aa5cdb4ab67 686 * this method will return a ManagedString up to the delimeter.
Jonathan Austin 1:8aa5cdb4ab67 687 * Otherwise, the calling fiber sleeps until a character matching one
Jonathan Austin 1:8aa5cdb4ab67 688 * of the delimeters is seen.
Jonathan Austin 1:8aa5cdb4ab67 689 *
Jonathan Austin 1:8aa5cdb4ab67 690 * Defaults to SYNC_SLEEP.
Jonathan Austin 1:8aa5cdb4ab67 691 *
Jonathan Austin 1:8aa5cdb4ab67 692 * @return A ManagedString containing the characters up to a delimeter, or an Empty ManagedString,
Jonathan Austin 1:8aa5cdb4ab67 693 * if another fiber is currently using this instance for reception.
Jonathan Austin 1:8aa5cdb4ab67 694 *
Jonathan Austin 1:8aa5cdb4ab67 695 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 696 */
Jonathan Austin 1:8aa5cdb4ab67 697 ManagedString MicroBitSerial::readUntil(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 698 {
Jonathan Austin 1:8aa5cdb4ab67 699
Jonathan Austin 1:8aa5cdb4ab67 700 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 701 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 702
Jonathan Austin 1:8aa5cdb4ab67 703 //lazy initialisation of our rx buffer
Jonathan Austin 1:8aa5cdb4ab67 704 if(!(status & MICROBIT_SERIAL_RX_BUFF_INIT))
Jonathan Austin 1:8aa5cdb4ab67 705 {
Jonathan Austin 1:8aa5cdb4ab67 706 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 707
Jonathan Austin 1:8aa5cdb4ab67 708 if(result != MICROBIT_OK)
Jonathan Austin 1:8aa5cdb4ab67 709 return result;
Jonathan Austin 1:8aa5cdb4ab67 710 }
Jonathan Austin 1:8aa5cdb4ab67 711
Jonathan Austin 1:8aa5cdb4ab67 712 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 713
Jonathan Austin 1:8aa5cdb4ab67 714 int localTail = rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 715 int preservedTail = rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 716
Jonathan Austin 1:8aa5cdb4ab67 717 int foundIndex = -1;
Jonathan Austin 1:8aa5cdb4ab67 718
Jonathan Austin 1:8aa5cdb4ab67 719 //ASYNC mode just iterates through our stored characters checking for any matches.
Jonathan Austin 1:8aa5cdb4ab67 720 while(localTail != rxBuffHead && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 721 {
Jonathan Austin 1:8aa5cdb4ab67 722 //we use localTail to prevent modification of the actual tail.
Jonathan Austin 1:8aa5cdb4ab67 723 char c = rxBuff[localTail];
Jonathan Austin 1:8aa5cdb4ab67 724
Jonathan Austin 1:8aa5cdb4ab67 725 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 726 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 727 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 728
Jonathan Austin 1:8aa5cdb4ab67 729 localTail = (localTail + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 730 }
Jonathan Austin 1:8aa5cdb4ab67 731
Jonathan Austin 1:8aa5cdb4ab67 732 //if our mode is SYNC_SPINWAIT and we didn't see any matching characters in our buffer
Jonathan Austin 1:8aa5cdb4ab67 733 //spin until we find a match!
Jonathan Austin 1:8aa5cdb4ab67 734 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 735 {
Jonathan Austin 1:8aa5cdb4ab67 736 while(foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 737 {
Jonathan Austin 1:8aa5cdb4ab67 738 while(localTail == rxBuffHead);
Jonathan Austin 1:8aa5cdb4ab67 739
Jonathan Austin 1:8aa5cdb4ab67 740 char c = rxBuff[localTail];
Jonathan Austin 1:8aa5cdb4ab67 741
Jonathan Austin 1:8aa5cdb4ab67 742 for(int delimeterIterator = 0; delimeterIterator < delimeters.length(); delimeterIterator++)
Jonathan Austin 1:8aa5cdb4ab67 743 if(delimeters.charAt(delimeterIterator) == c)
Jonathan Austin 1:8aa5cdb4ab67 744 foundIndex = localTail;
Jonathan Austin 1:8aa5cdb4ab67 745
Jonathan Austin 1:8aa5cdb4ab67 746 localTail = (localTail + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 747 }
Jonathan Austin 1:8aa5cdb4ab67 748 }
Jonathan Austin 1:8aa5cdb4ab67 749
Jonathan Austin 1:8aa5cdb4ab67 750 //if our mode is SYNC_SLEEP, we set up an event to be fired when we see a
Jonathan Austin 1:8aa5cdb4ab67 751 //matching character.
Jonathan Austin 1:8aa5cdb4ab67 752 if(mode == SYNC_SLEEP && foundIndex == -1)
Jonathan Austin 1:8aa5cdb4ab67 753 {
Jonathan Austin 1:8aa5cdb4ab67 754 eventOn(delimeters, mode);
Jonathan Austin 1:8aa5cdb4ab67 755
Jonathan Austin 1:8aa5cdb4ab67 756 foundIndex = rxBuffHead - 1;
Jonathan Austin 1:8aa5cdb4ab67 757
Jonathan Austin 1:8aa5cdb4ab67 758 this->delimeters = ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 759 }
Jonathan Austin 1:8aa5cdb4ab67 760
Jonathan Austin 1:8aa5cdb4ab67 761 if(foundIndex >= 0)
Jonathan Austin 1:8aa5cdb4ab67 762 {
Jonathan Austin 1:8aa5cdb4ab67 763 //calculate our local buffer size
Jonathan Austin 1:8aa5cdb4ab67 764 int localBuffSize = (preservedTail > foundIndex) ? (rxBuffSize - preservedTail) + foundIndex : foundIndex - preservedTail;
Jonathan Austin 1:8aa5cdb4ab67 765
LancasterUniversity 3:d86a4ddc1867 766 uint8_t localBuff[localBuffSize + 1];
Jonathan Austin 1:8aa5cdb4ab67 767
LancasterUniversity 8:ec4465853952 768 memclr(&localBuff, localBuffSize + 1);
LancasterUniversity 8:ec4465853952 769
Jonathan Austin 1:8aa5cdb4ab67 770 circularCopy(rxBuff, rxBuffSize, localBuff, preservedTail, foundIndex);
Jonathan Austin 1:8aa5cdb4ab67 771
Jonathan Austin 1:8aa5cdb4ab67 772 //plus one for the character we listened for...
Jonathan Austin 1:8aa5cdb4ab67 773 rxBuffTail = (rxBuffTail + localBuffSize + 1) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 774
Jonathan Austin 1:8aa5cdb4ab67 775 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 776
Jonathan Austin 1:8aa5cdb4ab67 777 return ManagedString((char *)localBuff, localBuffSize);
Jonathan Austin 1:8aa5cdb4ab67 778 }
Jonathan Austin 1:8aa5cdb4ab67 779
Jonathan Austin 1:8aa5cdb4ab67 780 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 781
Jonathan Austin 1:8aa5cdb4ab67 782 return ManagedString();
Jonathan Austin 1:8aa5cdb4ab67 783 }
Jonathan Austin 1:8aa5cdb4ab67 784
Jonathan Austin 1:8aa5cdb4ab67 785 /**
Jonathan Austin 1:8aa5cdb4ab67 786 * A wrapper around the inherited method "baud" so we can trap the baud rate
Jonathan Austin 1:8aa5cdb4ab67 787 * as it changes and restore it if redirect() is called.
Jonathan Austin 1:8aa5cdb4ab67 788 *
Jonathan Austin 1:8aa5cdb4ab67 789 * @param baudrate the new baudrate. See:
Jonathan Austin 1:8aa5cdb4ab67 790 * - https://github.com/mbedmicro/mbed/blob/master/libraries/mbed/targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/serial_api.c
Jonathan Austin 1:8aa5cdb4ab67 791 * for permitted baud rates.
Jonathan Austin 1:8aa5cdb4ab67 792 *
Jonathan Austin 1:8aa5cdb4ab67 793 * @return MICROBIT_INVALID_PARAMETER if baud rate is less than 0, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 794 *
Jonathan Austin 1:8aa5cdb4ab67 795 * @note the underlying implementation chooses the first allowable rate at or above that requested.
Jonathan Austin 1:8aa5cdb4ab67 796 */
Jonathan Austin 1:8aa5cdb4ab67 797 void MicroBitSerial::baud(int baudrate)
Jonathan Austin 1:8aa5cdb4ab67 798 {
Jonathan Austin 1:8aa5cdb4ab67 799 if(baudrate < 0)
Jonathan Austin 1:8aa5cdb4ab67 800 return;
Jonathan Austin 1:8aa5cdb4ab67 801
Jonathan Austin 1:8aa5cdb4ab67 802 this->baudrate = baudrate;
Jonathan Austin 1:8aa5cdb4ab67 803
Jonathan Austin 1:8aa5cdb4ab67 804 RawSerial::baud(baudrate);
Jonathan Austin 1:8aa5cdb4ab67 805 }
Jonathan Austin 1:8aa5cdb4ab67 806
Jonathan Austin 1:8aa5cdb4ab67 807 /**
Jonathan Austin 1:8aa5cdb4ab67 808 * A way of dynamically configuring the serial instance to use pins other than USBTX and USBRX.
Jonathan Austin 1:8aa5cdb4ab67 809 *
Jonathan Austin 1:8aa5cdb4ab67 810 * @param tx the new transmission pin.
Jonathan Austin 1:8aa5cdb4ab67 811 *
Jonathan Austin 1:8aa5cdb4ab67 812 * @param rx the new reception pin.
Jonathan Austin 1:8aa5cdb4ab67 813 *
Jonathan Austin 1:8aa5cdb4ab67 814 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently transmitting or receiving, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 815 */
Jonathan Austin 1:8aa5cdb4ab67 816 int MicroBitSerial::redirect(PinName tx, PinName rx)
Jonathan Austin 1:8aa5cdb4ab67 817 {
Jonathan Austin 1:8aa5cdb4ab67 818 if(txInUse() || rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 819 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 820
Jonathan Austin 1:8aa5cdb4ab67 821 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 822 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 823
Jonathan Austin 1:8aa5cdb4ab67 824 if(txBufferedSize() > 0)
LancasterUniversity 6:2e1c2e0d8c7a 825 detach(Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 826
LancasterUniversity 6:2e1c2e0d8c7a 827 detach(Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 828
Jonathan Austin 1:8aa5cdb4ab67 829 serial_free(&_serial);
Jonathan Austin 1:8aa5cdb4ab67 830 serial_init(&_serial, tx, rx);
Jonathan Austin 1:8aa5cdb4ab67 831
LancasterUniversity 6:2e1c2e0d8c7a 832 attach(this, &MicroBitSerial::dataReceived, Serial::RxIrq);
Jonathan Austin 1:8aa5cdb4ab67 833
Jonathan Austin 1:8aa5cdb4ab67 834 if(txBufferedSize() > 0)
LancasterUniversity 6:2e1c2e0d8c7a 835 attach(this, &MicroBitSerial::dataWritten, Serial::TxIrq);
Jonathan Austin 1:8aa5cdb4ab67 836
Jonathan Austin 1:8aa5cdb4ab67 837 this->baud(this->baudrate);
Jonathan Austin 1:8aa5cdb4ab67 838
Jonathan Austin 1:8aa5cdb4ab67 839 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 840 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 841
Jonathan Austin 1:8aa5cdb4ab67 842 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 843 }
Jonathan Austin 1:8aa5cdb4ab67 844
Jonathan Austin 1:8aa5cdb4ab67 845 /**
Jonathan Austin 1:8aa5cdb4ab67 846 * Configures an event to be fired after "len" characters.
Jonathan Austin 1:8aa5cdb4ab67 847 *
Jonathan Austin 1:8aa5cdb4ab67 848 * @param len the number of characters to wait before triggering the event.
Jonathan Austin 1:8aa5cdb4ab67 849 *
Jonathan Austin 1:8aa5cdb4ab67 850 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 851 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 852 *
Jonathan Austin 1:8aa5cdb4ab67 853 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 854 *
Jonathan Austin 1:8aa5cdb4ab67 855 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 856 *
Jonathan Austin 1:8aa5cdb4ab67 857 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 858 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 859 *
Jonathan Austin 1:8aa5cdb4ab67 860 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 861 */
Jonathan Austin 1:8aa5cdb4ab67 862 int MicroBitSerial::eventAfter(int len, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 863 {
Jonathan Austin 1:8aa5cdb4ab67 864 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 865 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 866
Jonathan Austin 1:8aa5cdb4ab67 867 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 868 this->rxBuffHeadMatch = (rxBuffHead + len) % rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 869
Jonathan Austin 1:8aa5cdb4ab67 870 //block!
Jonathan Austin 1:8aa5cdb4ab67 871 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 872 fiber_wait_for_event(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_HEAD_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 873
Jonathan Austin 1:8aa5cdb4ab67 874 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 875 }
Jonathan Austin 1:8aa5cdb4ab67 876
Jonathan Austin 1:8aa5cdb4ab67 877 /**
Jonathan Austin 1:8aa5cdb4ab67 878 * Configures an event to be fired on a match with one of the delimeters.
Jonathan Austin 1:8aa5cdb4ab67 879 *
Jonathan Austin 1:8aa5cdb4ab67 880 * @param delimeters the characters to match received characters against e.g. ManagedString("\r\n")
Jonathan Austin 1:8aa5cdb4ab67 881 *
Jonathan Austin 1:8aa5cdb4ab67 882 * @param mode the selected mode, one of: ASYNC, SYNC_SPINWAIT, SYNC_SLEEP. Each mode
Jonathan Austin 1:8aa5cdb4ab67 883 * gives a different behaviour:
Jonathan Austin 1:8aa5cdb4ab67 884 *
Jonathan Austin 1:8aa5cdb4ab67 885 * ASYNC - Will configure the event and return immediately.
Jonathan Austin 1:8aa5cdb4ab67 886 *
Jonathan Austin 1:8aa5cdb4ab67 887 * SYNC_SPINWAIT - will return MICROBIT_INVALID_PARAMETER
Jonathan Austin 1:8aa5cdb4ab67 888 *
Jonathan Austin 1:8aa5cdb4ab67 889 * SYNC_SLEEP - Will configure the event and block the current fiber until the
Jonathan Austin 1:8aa5cdb4ab67 890 * event is received.
Jonathan Austin 1:8aa5cdb4ab67 891 *
Jonathan Austin 1:8aa5cdb4ab67 892 * @return MICROBIT_INVALID_PARAMETER if the mode given is SYNC_SPINWAIT, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 893 *
Jonathan Austin 1:8aa5cdb4ab67 894 * @note delimeters are matched on a per byte basis.
Jonathan Austin 1:8aa5cdb4ab67 895 */
Jonathan Austin 1:8aa5cdb4ab67 896 int MicroBitSerial::eventOn(ManagedString delimeters, MicroBitSerialMode mode)
Jonathan Austin 1:8aa5cdb4ab67 897 {
Jonathan Austin 1:8aa5cdb4ab67 898 if(mode == SYNC_SPINWAIT)
Jonathan Austin 1:8aa5cdb4ab67 899 return MICROBIT_INVALID_PARAMETER;
Jonathan Austin 1:8aa5cdb4ab67 900
Jonathan Austin 1:8aa5cdb4ab67 901 //configure our head match...
Jonathan Austin 1:8aa5cdb4ab67 902 this->delimeters = delimeters;
Jonathan Austin 1:8aa5cdb4ab67 903
Jonathan Austin 1:8aa5cdb4ab67 904 //block!
Jonathan Austin 1:8aa5cdb4ab67 905 if(mode == SYNC_SLEEP)
Jonathan Austin 1:8aa5cdb4ab67 906 fiber_wait_for_event(MICROBIT_ID_SERIAL, MICROBIT_SERIAL_EVT_DELIM_MATCH);
Jonathan Austin 1:8aa5cdb4ab67 907
Jonathan Austin 1:8aa5cdb4ab67 908 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 909 }
Jonathan Austin 1:8aa5cdb4ab67 910
Jonathan Austin 1:8aa5cdb4ab67 911 /**
Jonathan Austin 1:8aa5cdb4ab67 912 * Determines whether there is any data waiting in our Rx buffer.
Jonathan Austin 1:8aa5cdb4ab67 913 *
Jonathan Austin 1:8aa5cdb4ab67 914 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 915 *
Jonathan Austin 1:8aa5cdb4ab67 916 * @note We do not wrap the super's readable() method as we don't want to
Jonathan Austin 1:8aa5cdb4ab67 917 * interfere with communities that use manual calls to serial.readable().
Jonathan Austin 1:8aa5cdb4ab67 918 */
Jonathan Austin 1:8aa5cdb4ab67 919 int MicroBitSerial::isReadable()
Jonathan Austin 1:8aa5cdb4ab67 920 {
Jonathan Austin 1:8aa5cdb4ab67 921 return (rxBuffTail != rxBuffHead) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 922 }
Jonathan Austin 1:8aa5cdb4ab67 923
Jonathan Austin 1:8aa5cdb4ab67 924 /**
Jonathan Austin 1:8aa5cdb4ab67 925 * Determines if we have space in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 926 *
Jonathan Austin 1:8aa5cdb4ab67 927 * @return 1 if we have space, 0 if we do not.
Jonathan Austin 1:8aa5cdb4ab67 928 *
Jonathan Austin 1:8aa5cdb4ab67 929 * @note We do not wrap the super's writeable() method as we don't want to
Jonathan Austin 1:8aa5cdb4ab67 930 * interfere with communities that use manual calls to serial.writeable().
Jonathan Austin 1:8aa5cdb4ab67 931 */
Jonathan Austin 1:8aa5cdb4ab67 932 int MicroBitSerial::isWriteable()
Jonathan Austin 1:8aa5cdb4ab67 933 {
Jonathan Austin 1:8aa5cdb4ab67 934 return (txBuffHead != (txBuffTail - 1)) ? 1 : 0;
Jonathan Austin 1:8aa5cdb4ab67 935 }
Jonathan Austin 1:8aa5cdb4ab67 936
Jonathan Austin 1:8aa5cdb4ab67 937 /**
Jonathan Austin 1:8aa5cdb4ab67 938 * Reconfigures the size of our rxBuff
Jonathan Austin 1:8aa5cdb4ab67 939 *
Jonathan Austin 1:8aa5cdb4ab67 940 * @param size the new size for our rxBuff
Jonathan Austin 1:8aa5cdb4ab67 941 *
Jonathan Austin 1:8aa5cdb4ab67 942 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 943 * for reception, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 944 */
Jonathan Austin 1:8aa5cdb4ab67 945 int MicroBitSerial::setRxBufferSize(uint8_t size)
Jonathan Austin 1:8aa5cdb4ab67 946 {
Jonathan Austin 1:8aa5cdb4ab67 947 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 948 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 949
Jonathan Austin 1:8aa5cdb4ab67 950 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 951
Jonathan Austin 1:8aa5cdb4ab67 952 this->rxBuffSize = size;
Jonathan Austin 1:8aa5cdb4ab67 953
Jonathan Austin 1:8aa5cdb4ab67 954 int result = initialiseRx();
Jonathan Austin 1:8aa5cdb4ab67 955
Jonathan Austin 1:8aa5cdb4ab67 956 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 957
Jonathan Austin 1:8aa5cdb4ab67 958 return result;
Jonathan Austin 1:8aa5cdb4ab67 959 }
Jonathan Austin 1:8aa5cdb4ab67 960
Jonathan Austin 1:8aa5cdb4ab67 961 /**
Jonathan Austin 1:8aa5cdb4ab67 962 * Reconfigures the size of our txBuff
Jonathan Austin 1:8aa5cdb4ab67 963 *
Jonathan Austin 1:8aa5cdb4ab67 964 * @param size the new size for our txBuff
Jonathan Austin 1:8aa5cdb4ab67 965 *
Jonathan Austin 1:8aa5cdb4ab67 966 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 967 * for transmission, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 968 */
Jonathan Austin 1:8aa5cdb4ab67 969 int MicroBitSerial::setTxBufferSize(uint8_t size)
Jonathan Austin 1:8aa5cdb4ab67 970 {
Jonathan Austin 1:8aa5cdb4ab67 971 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 972 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 973
Jonathan Austin 1:8aa5cdb4ab67 974 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 975
Jonathan Austin 1:8aa5cdb4ab67 976 this->txBuffSize = size;
Jonathan Austin 1:8aa5cdb4ab67 977
Jonathan Austin 1:8aa5cdb4ab67 978 int result = initialiseTx();
Jonathan Austin 1:8aa5cdb4ab67 979
Jonathan Austin 1:8aa5cdb4ab67 980 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 981
Jonathan Austin 1:8aa5cdb4ab67 982 return result;
Jonathan Austin 1:8aa5cdb4ab67 983 }
Jonathan Austin 1:8aa5cdb4ab67 984
Jonathan Austin 1:8aa5cdb4ab67 985 /**
Jonathan Austin 1:8aa5cdb4ab67 986 * The size of our rx buffer in bytes.
Jonathan Austin 1:8aa5cdb4ab67 987 *
Jonathan Austin 1:8aa5cdb4ab67 988 * @return the current size of rxBuff in bytes
Jonathan Austin 1:8aa5cdb4ab67 989 */
Jonathan Austin 1:8aa5cdb4ab67 990 int MicroBitSerial::getRxBufferSize()
Jonathan Austin 1:8aa5cdb4ab67 991 {
Jonathan Austin 1:8aa5cdb4ab67 992 return this->rxBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 993 }
Jonathan Austin 1:8aa5cdb4ab67 994
Jonathan Austin 1:8aa5cdb4ab67 995 /**
Jonathan Austin 1:8aa5cdb4ab67 996 * The size of our tx buffer in bytes.
Jonathan Austin 1:8aa5cdb4ab67 997 *
Jonathan Austin 1:8aa5cdb4ab67 998 * @return the current size of txBuff in bytes
Jonathan Austin 1:8aa5cdb4ab67 999 */
Jonathan Austin 1:8aa5cdb4ab67 1000 int MicroBitSerial::getTxBufferSize()
Jonathan Austin 1:8aa5cdb4ab67 1001 {
Jonathan Austin 1:8aa5cdb4ab67 1002 return this->txBuffSize;
Jonathan Austin 1:8aa5cdb4ab67 1003 }
Jonathan Austin 1:8aa5cdb4ab67 1004
Jonathan Austin 1:8aa5cdb4ab67 1005 /**
Jonathan Austin 1:8aa5cdb4ab67 1006 * Sets the tail to match the head of our circular buffer for reception,
Jonathan Austin 1:8aa5cdb4ab67 1007 * effectively clearing the reception buffer.
Jonathan Austin 1:8aa5cdb4ab67 1008 *
Jonathan Austin 1:8aa5cdb4ab67 1009 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 1010 * for reception, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 1011 */
Jonathan Austin 1:8aa5cdb4ab67 1012 int MicroBitSerial::clearRxBuffer()
Jonathan Austin 1:8aa5cdb4ab67 1013 {
Jonathan Austin 1:8aa5cdb4ab67 1014 if(rxInUse())
Jonathan Austin 1:8aa5cdb4ab67 1015 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 1016
Jonathan Austin 1:8aa5cdb4ab67 1017 lockRx();
Jonathan Austin 1:8aa5cdb4ab67 1018
Jonathan Austin 1:8aa5cdb4ab67 1019 rxBuffTail = rxBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1020
Jonathan Austin 1:8aa5cdb4ab67 1021 unlockRx();
Jonathan Austin 1:8aa5cdb4ab67 1022
Jonathan Austin 1:8aa5cdb4ab67 1023 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 1024 }
Jonathan Austin 1:8aa5cdb4ab67 1025
Jonathan Austin 1:8aa5cdb4ab67 1026 /**
Jonathan Austin 1:8aa5cdb4ab67 1027 * Sets the tail to match the head of our circular buffer for transmission,
Jonathan Austin 1:8aa5cdb4ab67 1028 * effectively clearing the transmission buffer.
Jonathan Austin 1:8aa5cdb4ab67 1029 *
Jonathan Austin 1:8aa5cdb4ab67 1030 * @return MICROBIT_SERIAL_IN_USE if another fiber is currently using this instance
Jonathan Austin 1:8aa5cdb4ab67 1031 * for transmission, otherwise MICROBIT_OK.
Jonathan Austin 1:8aa5cdb4ab67 1032 */
Jonathan Austin 1:8aa5cdb4ab67 1033 int MicroBitSerial::clearTxBuffer()
Jonathan Austin 1:8aa5cdb4ab67 1034 {
Jonathan Austin 1:8aa5cdb4ab67 1035 if(txInUse())
Jonathan Austin 1:8aa5cdb4ab67 1036 return MICROBIT_SERIAL_IN_USE;
Jonathan Austin 1:8aa5cdb4ab67 1037
Jonathan Austin 1:8aa5cdb4ab67 1038 lockTx();
Jonathan Austin 1:8aa5cdb4ab67 1039
Jonathan Austin 1:8aa5cdb4ab67 1040 txBuffTail = txBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1041
Jonathan Austin 1:8aa5cdb4ab67 1042 unlockTx();
Jonathan Austin 1:8aa5cdb4ab67 1043
Jonathan Austin 1:8aa5cdb4ab67 1044 return MICROBIT_OK;
Jonathan Austin 1:8aa5cdb4ab67 1045 }
Jonathan Austin 1:8aa5cdb4ab67 1046
Jonathan Austin 1:8aa5cdb4ab67 1047 /**
Jonathan Austin 1:8aa5cdb4ab67 1048 * The number of bytes currently stored in our rx buffer waiting to be digested,
Jonathan Austin 1:8aa5cdb4ab67 1049 * by the user.
Jonathan Austin 1:8aa5cdb4ab67 1050 *
Jonathan Austin 1:8aa5cdb4ab67 1051 * @return The currently buffered number of bytes in our rxBuff.
Jonathan Austin 1:8aa5cdb4ab67 1052 */
Jonathan Austin 1:8aa5cdb4ab67 1053 int MicroBitSerial::rxBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 1054 {
Jonathan Austin 1:8aa5cdb4ab67 1055 if(rxBuffTail > rxBuffHead)
Jonathan Austin 1:8aa5cdb4ab67 1056 return (rxBuffSize - rxBuffTail) + rxBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1057
Jonathan Austin 1:8aa5cdb4ab67 1058 return rxBuffHead - rxBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 1059 }
Jonathan Austin 1:8aa5cdb4ab67 1060
Jonathan Austin 1:8aa5cdb4ab67 1061 /**
Jonathan Austin 1:8aa5cdb4ab67 1062 * The number of bytes currently stored in our tx buffer waiting to be transmitted
Jonathan Austin 1:8aa5cdb4ab67 1063 * by the hardware.
Jonathan Austin 1:8aa5cdb4ab67 1064 *
Jonathan Austin 1:8aa5cdb4ab67 1065 * @return The currently buffered number of bytes in our txBuff.
Jonathan Austin 1:8aa5cdb4ab67 1066 */
Jonathan Austin 1:8aa5cdb4ab67 1067 int MicroBitSerial::txBufferedSize()
Jonathan Austin 1:8aa5cdb4ab67 1068 {
Jonathan Austin 1:8aa5cdb4ab67 1069 if(txBuffTail > txBuffHead)
Jonathan Austin 1:8aa5cdb4ab67 1070 return (txBuffSize - txBuffTail) + txBuffHead;
Jonathan Austin 1:8aa5cdb4ab67 1071
Jonathan Austin 1:8aa5cdb4ab67 1072 return txBuffHead - txBuffTail;
Jonathan Austin 1:8aa5cdb4ab67 1073 }
Jonathan Austin 1:8aa5cdb4ab67 1074
Jonathan Austin 1:8aa5cdb4ab67 1075 /**
Jonathan Austin 1:8aa5cdb4ab67 1076 * Determines if the serial bus is currently in use by another fiber for reception.
Jonathan Austin 1:8aa5cdb4ab67 1077 *
Jonathan Austin 1:8aa5cdb4ab67 1078 * @return The state of our mutex lock for reception.
Jonathan Austin 1:8aa5cdb4ab67 1079 *
Jonathan Austin 1:8aa5cdb4ab67 1080 * @note Only one fiber can call read at a time
Jonathan Austin 1:8aa5cdb4ab67 1081 */
Jonathan Austin 1:8aa5cdb4ab67 1082 int MicroBitSerial::rxInUse()
Jonathan Austin 1:8aa5cdb4ab67 1083 {
Jonathan Austin 1:8aa5cdb4ab67 1084 return (status & MICROBIT_SERIAL_RX_IN_USE);
Jonathan Austin 1:8aa5cdb4ab67 1085 }
Jonathan Austin 1:8aa5cdb4ab67 1086
Jonathan Austin 1:8aa5cdb4ab67 1087 /**
Jonathan Austin 1:8aa5cdb4ab67 1088 * Determines if the serial bus is currently in use by another fiber for transmission.
Jonathan Austin 1:8aa5cdb4ab67 1089 *
Jonathan Austin 1:8aa5cdb4ab67 1090 * @return The state of our mutex lock for transmition.
Jonathan Austin 1:8aa5cdb4ab67 1091 *
Jonathan Austin 1:8aa5cdb4ab67 1092 * @note Only one fiber can call send at a time
Jonathan Austin 1:8aa5cdb4ab67 1093 */
Jonathan Austin 1:8aa5cdb4ab67 1094 int MicroBitSerial::txInUse()
Jonathan Austin 1:8aa5cdb4ab67 1095 {
Jonathan Austin 1:8aa5cdb4ab67 1096 return (status & MICROBIT_SERIAL_TX_IN_USE);
Jonathan Austin 1:8aa5cdb4ab67 1097 }
Jonathan Austin 1:8aa5cdb4ab67 1098
Jonathan Austin 1:8aa5cdb4ab67 1099 /**
Jonathan Austin 1:8aa5cdb4ab67 1100 * Detaches a previously configured interrupt
Jonathan Austin 1:8aa5cdb4ab67 1101 *
Jonathan Austin 1:8aa5cdb4ab67 1102 * @param interruptType one of Serial::RxIrq or Serial::TxIrq
Jonathan Austin 1:8aa5cdb4ab67 1103 */
Jonathan Austin 1:8aa5cdb4ab67 1104 void MicroBitSerial::detach(Serial::IrqType interruptType)
Jonathan Austin 1:8aa5cdb4ab67 1105 {
Jonathan Austin 1:8aa5cdb4ab67 1106 //we detach by sending a bad value to attach, for some weird reason...
Jonathan Austin 1:8aa5cdb4ab67 1107 attach((MicroBitSerial *)NULL, &MicroBitSerial::dataReceived, interruptType);
LancasterUniversity 3:d86a4ddc1867 1108 }