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