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