My fork

Dependencies:   BLE_API nRF51822-bluetooth-mdw

Fork of microbit-dal by Lancaster University

Committer:
LancasterUniversity
Date:
Wed Jul 13 12:18:47 2016 +0100
Revision:
67:99cfde195ff3
Parent:
66:2fc7d7c2fffc
Synchronized with git rev 05c03b06
Author: James Devine
microbit-dal: added validation to send [#151]

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