Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
source/AsyncSerial.cpp@9:e183765bd81b, 2015-04-10 (annotated)
- Committer:
- marcuschang
- Date:
- Fri Apr 10 13:05:30 2015 +0000
- Revision:
- 9:e183765bd81b
- Parent:
- 8:de7aaaf557ba
- Child:
- 10:9d3ae421081b
Fixed sleep bug. Use timeout to decouple receiveDone with callback function.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| marcuschang | 0:dfed780dc91a | 1 | #include "AsyncSerial/AsyncSerial.h" |
| marcuschang | 0:dfed780dc91a | 2 | |
| marcuschang | 0:dfed780dc91a | 3 | #include "mbed.h" |
| marcuschang | 0:dfed780dc91a | 4 | |
| marcuschang | 9:e183765bd81b | 5 | #define MINIMUM_TIMEOUT 1 |
| marcuschang | 9:e183765bd81b | 6 | |
| marcuschang | 0:dfed780dc91a | 7 | AsyncSerial::AsyncSerial(PinName tx, PinName rx, PinName rts, PinName cts) |
| marcuschang | 0:dfed780dc91a | 8 | : SerialBase(tx, rx), |
| Marcus Chang |
1:a3f39ec7d5f2 | 9 | |
| marcuschang | 0:dfed780dc91a | 10 | sendBuffer(NULL), |
| marcuschang | 0:dfed780dc91a | 11 | sendLength(0), |
| Marcus Chang |
1:a3f39ec7d5f2 | 12 | sendIndex(0), |
| Marcus Chang |
1:a3f39ec7d5f2 | 13 | |
| marcuschang | 0:dfed780dc91a | 14 | sendDoneHandler(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 15 | sendObject(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 16 | sendMember(), |
| Marcus Chang |
1:a3f39ec7d5f2 | 17 | sendDoneObject(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 18 | |
| marcuschang | 0:dfed780dc91a | 19 | receiveDoneHandler(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 20 | receiveObject(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 21 | receiveMember(), |
| Marcus Chang |
1:a3f39ec7d5f2 | 22 | receiveDoneObject(NULL), |
| Marcus Chang |
1:a3f39ec7d5f2 | 23 | |
| marcuschang | 7:5ba3a01e13c4 | 24 | waitDoneHandler(NULL), |
| marcuschang | 7:5ba3a01e13c4 | 25 | waitObject(NULL), |
| marcuschang | 7:5ba3a01e13c4 | 26 | waitMember(), |
| marcuschang | 7:5ba3a01e13c4 | 27 | waitDoneObject(NULL), |
| marcuschang | 7:5ba3a01e13c4 | 28 | |
| Marcus Chang |
4:e0a0eef4ca18 | 29 | isReceiving(false), |
| Marcus Chang |
4:e0a0eef4ca18 | 30 | receiveBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 31 | receiveMaxLength(0), |
| Marcus Chang |
4:e0a0eef4ca18 | 32 | receiveIndex(0), |
| Marcus Chang |
4:e0a0eef4ca18 | 33 | |
| Marcus Chang |
4:e0a0eef4ca18 | 34 | insideCondition(false), |
| Marcus Chang |
4:e0a0eef4ca18 | 35 | conditionStartBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 36 | conditionStartLength(0), |
| Marcus Chang |
4:e0a0eef4ca18 | 37 | conditionEndBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 38 | conditionEndLength(0), |
| marcuschang | 0:dfed780dc91a | 39 | conditionIndex(0), |
| marcuschang | 9:e183765bd81b | 40 | timeout(), |
| marcuschang | 9:e183765bd81b | 41 | receiveStatus(AsyncSerial::RECEIVE_TIMEOUT) |
| Marcus Chang |
1:a3f39ec7d5f2 | 42 | { |
| marcuschang | 0:dfed780dc91a | 43 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::getReady, SerialBase::RxIrq); |
| marcuschang | 0:dfed780dc91a | 44 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::putDone, SerialBase::TxIrq); |
| marcuschang | 0:dfed780dc91a | 45 | } |
| marcuschang | 0:dfed780dc91a | 46 | |
| marcuschang | 0:dfed780dc91a | 47 | void AsyncSerial::putDone() |
| marcuschang | 0:dfed780dc91a | 48 | { |
| marcuschang | 9:e183765bd81b | 49 | sendIndex++; |
| Marcus Chang |
1:a3f39ec7d5f2 | 50 | |
| marcuschang | 9:e183765bd81b | 51 | if (sendIndex < sendLength) |
| marcuschang | 9:e183765bd81b | 52 | { |
| marcuschang | 9:e183765bd81b | 53 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
| marcuschang | 9:e183765bd81b | 54 | } |
| marcuschang | 9:e183765bd81b | 55 | else |
| marcuschang | 9:e183765bd81b | 56 | { |
| marcuschang | 9:e183765bd81b | 57 | if (sendDoneHandler) |
| marcuschang | 0:dfed780dc91a | 58 | { |
| marcuschang | 9:e183765bd81b | 59 | sendDoneHandler(); |
| marcuschang | 9:e183765bd81b | 60 | } |
| marcuschang | 9:e183765bd81b | 61 | else if (sendObject) |
| marcuschang | 9:e183765bd81b | 62 | { |
| marcuschang | 9:e183765bd81b | 63 | sendDoneObject(sendObject, sendMember); |
| marcuschang | 0:dfed780dc91a | 64 | } |
| marcuschang | 0:dfed780dc91a | 65 | } |
| marcuschang | 0:dfed780dc91a | 66 | } |
| marcuschang | 0:dfed780dc91a | 67 | |
| marcuschang | 0:dfed780dc91a | 68 | void AsyncSerial::getReady() |
| marcuschang | 7:5ba3a01e13c4 | 69 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 70 | if (isReceiving) |
| Marcus Chang |
1:a3f39ec7d5f2 | 71 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 72 | uint8_t input = SerialBase::_base_getc(); |
| Marcus Chang |
1:a3f39ec7d5f2 | 73 | |
| marcuschang | 7:5ba3a01e13c4 | 74 | DEBUG("%c", input); |
| marcuschang | 7:5ba3a01e13c4 | 75 | |
| Marcus Chang |
4:e0a0eef4ca18 | 76 | if (insideCondition) |
| marcuschang | 9:e183765bd81b | 77 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 78 | if (conditionEndBuffer != NULL) |
| marcuschang | 0:dfed780dc91a | 79 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 80 | if (input == conditionEndBuffer[conditionIndex]) |
| Marcus Chang |
4:e0a0eef4ca18 | 81 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 82 | conditionIndex++; |
| Marcus Chang |
4:e0a0eef4ca18 | 83 | |
| Marcus Chang |
4:e0a0eef4ca18 | 84 | if (conditionIndex == conditionEndLength) |
| marcuschang | 9:e183765bd81b | 85 | { |
| marcuschang | 9:e183765bd81b | 86 | receiveStatus = AsyncSerial::RECEIVE_FOUND; |
| marcuschang | 9:e183765bd81b | 87 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
| Marcus Chang |
4:e0a0eef4ca18 | 88 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 89 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 90 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 91 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 92 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 93 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 94 | } |
| marcuschang | 9:e183765bd81b | 95 | |
| marcuschang | 9:e183765bd81b | 96 | if (receiveBuffer != NULL) |
| marcuschang | 9:e183765bd81b | 97 | { |
| marcuschang | 9:e183765bd81b | 98 | receiveBuffer[receiveIndex] = input; |
| marcuschang | 9:e183765bd81b | 99 | receiveIndex++; |
| marcuschang | 9:e183765bd81b | 100 | |
| marcuschang | 9:e183765bd81b | 101 | if ((receiveIndex == receiveMaxLength) && (receiveStatus != AsyncSerial::RECEIVE_FOUND)) |
| marcuschang | 9:e183765bd81b | 102 | { |
| marcuschang | 9:e183765bd81b | 103 | receiveStatus = AsyncSerial::RECEIVE_FULL; |
| marcuschang | 9:e183765bd81b | 104 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
| marcuschang | 9:e183765bd81b | 105 | } |
| marcuschang | 9:e183765bd81b | 106 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 107 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 108 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 109 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 110 | if (conditionStartBuffer != NULL) |
| Marcus Chang |
4:e0a0eef4ca18 | 111 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 112 | if (input == conditionStartBuffer[conditionIndex]) |
| Marcus Chang |
4:e0a0eef4ca18 | 113 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 114 | conditionIndex++; |
| Marcus Chang |
4:e0a0eef4ca18 | 115 | |
| Marcus Chang |
4:e0a0eef4ca18 | 116 | if (conditionIndex == conditionStartLength) |
| Marcus Chang |
4:e0a0eef4ca18 | 117 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 118 | insideCondition = true; |
| marcuschang | 9:e183765bd81b | 119 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 120 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 121 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 122 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 123 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 124 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 125 | } |
| marcuschang | 0:dfed780dc91a | 126 | } |
| marcuschang | 0:dfed780dc91a | 127 | } |
| marcuschang | 0:dfed780dc91a | 128 | } |
| marcuschang | 0:dfed780dc91a | 129 | } |
| marcuschang | 0:dfed780dc91a | 130 | |
| marcuschang | 5:aecd37846dcc | 131 | void AsyncSerial::getDone(uint8_t status) |
| Marcus Chang |
1:a3f39ec7d5f2 | 132 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 133 | isReceiving = false; |
| marcuschang | 0:dfed780dc91a | 134 | |
| marcuschang | 7:5ba3a01e13c4 | 135 | DEBUG("getDone: %X %X %X\r\n", this, waitDoneHandler, waitObject); |
| marcuschang | 7:5ba3a01e13c4 | 136 | |
| marcuschang | 9:e183765bd81b | 137 | if ((receiveBuffer == NULL) && (conditionStartBuffer == NULL)) |
| marcuschang | 0:dfed780dc91a | 138 | { |
| Marcus Chang |
6:9d48f2197243 | 139 | if (waitDoneHandler) |
| Marcus Chang |
6:9d48f2197243 | 140 | { |
| marcuschang | 7:5ba3a01e13c4 | 141 | waitDoneHandler(status); |
| Marcus Chang |
6:9d48f2197243 | 142 | } |
| Marcus Chang |
6:9d48f2197243 | 143 | else if (waitObject) |
| Marcus Chang |
6:9d48f2197243 | 144 | { |
| marcuschang | 7:5ba3a01e13c4 | 145 | waitDoneObject(waitObject, waitMember, status); |
| Marcus Chang |
6:9d48f2197243 | 146 | } |
| marcuschang | 0:dfed780dc91a | 147 | } |
| Marcus Chang |
6:9d48f2197243 | 148 | else |
| Marcus Chang |
1:a3f39ec7d5f2 | 149 | { |
| Marcus Chang |
6:9d48f2197243 | 150 | if (receiveDoneHandler) |
| Marcus Chang |
6:9d48f2197243 | 151 | { |
| Marcus Chang |
6:9d48f2197243 | 152 | receiveDoneHandler(receiveBuffer, receiveIndex, status); |
| Marcus Chang |
6:9d48f2197243 | 153 | } |
| Marcus Chang |
6:9d48f2197243 | 154 | else if (receiveObject) |
| Marcus Chang |
6:9d48f2197243 | 155 | { |
| Marcus Chang |
6:9d48f2197243 | 156 | receiveDoneObject(receiveObject, receiveMember, receiveBuffer, receiveIndex, status); |
| Marcus Chang |
6:9d48f2197243 | 157 | } |
| Marcus Chang |
1:a3f39ec7d5f2 | 158 | } |
| marcuschang | 0:dfed780dc91a | 159 | } |
| marcuschang | 0:dfed780dc91a | 160 | |
| marcuschang | 7:5ba3a01e13c4 | 161 | void AsyncSerial::send(send_done_t handler, const char* buffer, uint16_t length) |
| marcuschang | 0:dfed780dc91a | 162 | { |
| marcuschang | 0:dfed780dc91a | 163 | if (handler && buffer && length) |
| Marcus Chang |
1:a3f39ec7d5f2 | 164 | { |
| marcuschang | 0:dfed780dc91a | 165 | sendDoneHandler = handler; |
| Marcus Chang |
1:a3f39ec7d5f2 | 166 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 167 | sendObject = NULL; |
| Marcus Chang |
1:a3f39ec7d5f2 | 168 | |
| marcuschang | 0:dfed780dc91a | 169 | send(buffer, length); |
| marcuschang | 0:dfed780dc91a | 170 | } |
| marcuschang | 0:dfed780dc91a | 171 | } |
| marcuschang | 0:dfed780dc91a | 172 | |
| marcuschang | 7:5ba3a01e13c4 | 173 | void AsyncSerial::send(const char* buffer, uint16_t length) |
| marcuschang | 0:dfed780dc91a | 174 | { |
| marcuschang | 0:dfed780dc91a | 175 | sendBuffer = buffer; |
| marcuschang | 0:dfed780dc91a | 176 | sendLength = length; |
| marcuschang | 0:dfed780dc91a | 177 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 178 | sendIndex = 0; |
| marcuschang | 0:dfed780dc91a | 179 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
| marcuschang | 7:5ba3a01e13c4 | 180 | |
| marcuschang | 7:5ba3a01e13c4 | 181 | DEBUG("send: %X\r\n", waitObject); |
| marcuschang | 0:dfed780dc91a | 182 | } |
| marcuschang | 0:dfed780dc91a | 183 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 184 | void AsyncSerial::receive(receive_done_t handler, |
| Marcus Chang |
1:a3f39ec7d5f2 | 185 | uint8_t* buffer, uint16_t maxLength, |
| marcuschang | 7:5ba3a01e13c4 | 186 | const char* conditionStartBuffer, uint16_t conditionStartLength, |
| marcuschang | 7:5ba3a01e13c4 | 187 | const char* conditionEndBuffer, uint16_t conditionEndLength, |
| marcuschang | 0:dfed780dc91a | 188 | uint32_t timeoutMilli) |
| marcuschang | 0:dfed780dc91a | 189 | { |
| Marcus Chang |
1:a3f39ec7d5f2 | 190 | if (handler) |
| Marcus Chang |
1:a3f39ec7d5f2 | 191 | { |
| Marcus Chang |
1:a3f39ec7d5f2 | 192 | receiveDoneHandler = handler; |
| Marcus Chang |
1:a3f39ec7d5f2 | 193 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 194 | receiveObject = NULL; |
| Marcus Chang |
1:a3f39ec7d5f2 | 195 | |
| Marcus Chang |
4:e0a0eef4ca18 | 196 | receive(buffer, maxLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 197 | conditionStartBuffer, conditionStartLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 198 | conditionEndBuffer, conditionEndLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 199 | timeoutMilli); |
| Marcus Chang |
1:a3f39ec7d5f2 | 200 | } |
| Marcus Chang |
1:a3f39ec7d5f2 | 201 | } |
| marcuschang | 0:dfed780dc91a | 202 | |
| marcuschang | 2:efec63739aa3 | 203 | void AsyncSerial::receive(uint8_t* buffer, uint16_t maxLength, |
| marcuschang | 7:5ba3a01e13c4 | 204 | const char* _conditionStartBuffer, uint16_t _conditionStartLength, |
| marcuschang | 7:5ba3a01e13c4 | 205 | const char* _conditionEndBuffer, uint16_t _conditionEndLength, |
| Marcus Chang |
1:a3f39ec7d5f2 | 206 | uint32_t timeoutMilli) |
| marcuschang | 7:5ba3a01e13c4 | 207 | { |
| marcuschang | 0:dfed780dc91a | 208 | receiveBuffer = buffer; |
| marcuschang | 0:dfed780dc91a | 209 | receiveMaxLength = maxLength; |
| marcuschang | 0:dfed780dc91a | 210 | receiveIndex = 0; |
| Marcus Chang |
1:a3f39ec7d5f2 | 211 | |
| Marcus Chang |
6:9d48f2197243 | 212 | conditionStartBuffer = _conditionStartBuffer; |
| Marcus Chang |
6:9d48f2197243 | 213 | conditionStartLength = _conditionStartLength; |
| Marcus Chang |
4:e0a0eef4ca18 | 214 | conditionEndBuffer = _conditionEndBuffer; |
| Marcus Chang |
4:e0a0eef4ca18 | 215 | conditionEndLength = _conditionEndLength; |
| marcuschang | 0:dfed780dc91a | 216 | conditionIndex = 0; |
| Marcus Chang |
1:a3f39ec7d5f2 | 217 | |
| Marcus Chang |
4:e0a0eef4ca18 | 218 | if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0)) |
| Marcus Chang |
4:e0a0eef4ca18 | 219 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 220 | insideCondition = false; |
| Marcus Chang |
4:e0a0eef4ca18 | 221 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 222 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 223 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 224 | insideCondition = true; |
| Marcus Chang |
4:e0a0eef4ca18 | 225 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 226 | |
| marcuschang | 9:e183765bd81b | 227 | receiveStatus = AsyncSerial::RECEIVE_TIMEOUT; |
| marcuschang | 5:aecd37846dcc | 228 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, timeoutMilli * 1000); |
| Marcus Chang |
4:e0a0eef4ca18 | 229 | isReceiving = true; |
| marcuschang | 7:5ba3a01e13c4 | 230 | |
| marcuschang | 9:e183765bd81b | 231 | DEBUG("receive: %p\r\n", receiveBuffer); |
| marcuschang | 0:dfed780dc91a | 232 | } |
| marcuschang | 0:dfed780dc91a | 233 | |
| marcuschang | 9:e183765bd81b | 234 | |
| marcuschang | 7:5ba3a01e13c4 | 235 | void AsyncSerial::wait(wait_done_t handler, |
| marcuschang | 7:5ba3a01e13c4 | 236 | const char* conditionEndBuffer, uint16_t conditionEndLength, |
| Marcus Chang |
6:9d48f2197243 | 237 | uint32_t timeoutMilli) |
| Marcus Chang |
6:9d48f2197243 | 238 | { |
| Marcus Chang |
6:9d48f2197243 | 239 | if (handler) |
| Marcus Chang |
6:9d48f2197243 | 240 | { |
| Marcus Chang |
6:9d48f2197243 | 241 | waitDoneHandler = handler; |
| Marcus Chang |
6:9d48f2197243 | 242 | |
| Marcus Chang |
6:9d48f2197243 | 243 | waitObject = NULL; |
| Marcus Chang |
6:9d48f2197243 | 244 | |
| Marcus Chang |
6:9d48f2197243 | 245 | receive(NULL, 0, |
| Marcus Chang |
6:9d48f2197243 | 246 | NULL, 0, |
| Marcus Chang |
6:9d48f2197243 | 247 | conditionEndBuffer, conditionEndLength, |
| Marcus Chang |
6:9d48f2197243 | 248 | timeoutMilli); |
| Marcus Chang |
6:9d48f2197243 | 249 | } |
| Marcus Chang |
6:9d48f2197243 | 250 | } |
| Marcus Chang |
6:9d48f2197243 | 251 | |
| marcuschang | 5:aecd37846dcc | 252 | void AsyncSerial::receiveTimeout() |
| marcuschang | 5:aecd37846dcc | 253 | { |
| marcuschang | 8:de7aaaf557ba | 254 | DEBUG("timeout: %X %X\r\n", this, waitObject); |
| marcuschang | 7:5ba3a01e13c4 | 255 | |
| marcuschang | 9:e183765bd81b | 256 | getDone(receiveStatus); |
| marcuschang | 5:aecd37846dcc | 257 | } |
| marcuschang | 5:aecd37846dcc | 258 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 259 | int AsyncSerial::getc() |
| marcuschang | 0:dfed780dc91a | 260 | { |
| marcuschang | 0:dfed780dc91a | 261 | return SerialBase::_base_getc(); |
| marcuschang | 0:dfed780dc91a | 262 | } |
| marcuschang | 0:dfed780dc91a | 263 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 264 | int AsyncSerial::putc(int c) |
| marcuschang | 0:dfed780dc91a | 265 | { |
| marcuschang | 0:dfed780dc91a | 266 | return SerialBase::_base_putc(c); |
| marcuschang | 0:dfed780dc91a | 267 | } |
| marcuschang | 0:dfed780dc91a | 268 | |
| marcuschang | 0:dfed780dc91a | 269 |

