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