microbit-dal

Dependencies:   BLE_API mbed-dev-bin nRF51822

Fork of microbit-dal by Lancaster University

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:18:40 2016 +0100
Revision:
61:b597fb218f84
Parent:
60:122814b3e76e
Child:
62:e633e0eeaf19
Synchronized with git rev 64042e4a
Author: James Devine
microbit-dal: BUGFIX cast in MicroBitSerial from int to char

There was an unnecessary cast in MicroBitSerial.read that meant error
codes would never be returned to the user application, this has now
been removed.

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