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