Official Sheffield ARMBand micro:bit program

Committer:
MrBedfordVan
Date:
Mon Oct 17 12:41:20 2016 +0000
Revision:
0:b9164b348919
Official Sheffield ARMBand Micro:bit program

Who changed what in which revision?

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