Marcus Chang / AsyncSerial
Committer:
marcuschang
Date:
Tue Apr 21 10:26:45 2015 +0000
Revision:
19:42ffb517d36a
Parent:
18:9127f9fae61f
Child:
20:c36866a2d5a6
Updated test case.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcuschang 16:55e6fbfc1e9d 1 /* mbed Microcontroller Library
marcuschang 16:55e6fbfc1e9d 2 * Copyright (c) 2006-2015 ARM Limited
marcuschang 16:55e6fbfc1e9d 3 *
marcuschang 16:55e6fbfc1e9d 4 * Licensed under the Apache License, Version 2.0 (the "License");
marcuschang 16:55e6fbfc1e9d 5 * you may not use this file except in compliance with the License.
marcuschang 16:55e6fbfc1e9d 6 * You may obtain a copy of the License at
marcuschang 16:55e6fbfc1e9d 7 *
marcuschang 16:55e6fbfc1e9d 8 * http://www.apache.org/licenses/LICENSE-2.0
marcuschang 16:55e6fbfc1e9d 9 *
marcuschang 16:55e6fbfc1e9d 10 * Unless required by applicable law or agreed to in writing, software
marcuschang 16:55e6fbfc1e9d 11 * distributed under the License is distributed on an "AS IS" BASIS,
marcuschang 16:55e6fbfc1e9d 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
marcuschang 16:55e6fbfc1e9d 13 * See the License for the specific language governing permissions and
marcuschang 16:55e6fbfc1e9d 14 * limitations under the License.
marcuschang 16:55e6fbfc1e9d 15 */
marcuschang 16:55e6fbfc1e9d 16
marcuschang 0:dfed780dc91a 17 #include "AsyncSerial/AsyncSerial.h"
marcuschang 0:dfed780dc91a 18
marcuschang 0:dfed780dc91a 19 #include "mbed.h"
marcuschang 0:dfed780dc91a 20
marcuschang 9:e183765bd81b 21 #define MINIMUM_TIMEOUT 1
marcuschang 9:e183765bd81b 22
marcuschang 0:dfed780dc91a 23 AsyncSerial::AsyncSerial(PinName tx, PinName rx, PinName rts, PinName cts)
marcuschang 0:dfed780dc91a 24 : SerialBase(tx, rx),
Marcus Chang 1:a3f39ec7d5f2 25
marcuschang 0:dfed780dc91a 26 sendBuffer(NULL),
marcuschang 0:dfed780dc91a 27 sendLength(0),
Marcus Chang 1:a3f39ec7d5f2 28 sendIndex(0),
Marcus Chang 1:a3f39ec7d5f2 29
Marcus Chang 4:e0a0eef4ca18 30 receiveBuffer(NULL),
Marcus Chang 4:e0a0eef4ca18 31 receiveMaxLength(0),
Marcus Chang 4:e0a0eef4ca18 32 receiveIndex(0),
Marcus Chang 10:9d3ae421081b 33 receiveStatus(AsyncSerial::RECEIVE_TIMEOUT),
Marcus Chang 12:b45908320b9c 34 receiveResult(),
marcuschang 13:dbb23efed611 35 timeout(),
Marcus Chang 4:e0a0eef4ca18 36
Marcus Chang 4:e0a0eef4ca18 37 insideCondition(false),
Marcus Chang 4:e0a0eef4ca18 38 conditionStartBuffer(NULL),
Marcus Chang 4:e0a0eef4ca18 39 conditionStartLength(0),
Marcus Chang 4:e0a0eef4ca18 40 conditionEndBuffer(NULL),
Marcus Chang 4:e0a0eef4ca18 41 conditionEndLength(0),
marcuschang 0:dfed780dc91a 42 conditionIndex(0),
Marcus Chang 12:b45908320b9c 43
Marcus Chang 12:b45908320b9c 44 sendHandler(),
Marcus Chang 12:b45908320b9c 45 receiveHandler(),
marcuschang 13:dbb23efed611 46 waitHandler()
Marcus Chang 1:a3f39ec7d5f2 47 {
Marcus Chang 12:b45908320b9c 48 // register ISR for receiving and sending
marcuschang 0:dfed780dc91a 49 SerialBase::attach<AsyncSerial>(this, &AsyncSerial::getReady, SerialBase::RxIrq);
Marcus Chang 10:9d3ae421081b 50
Marcus Chang 10:9d3ae421081b 51 #if DEVICE_SERIAL_FC
Marcus Chang 17:5dd6bcc93a8a 52 if ((rts != NC) && (cts != NC))
Marcus Chang 17:5dd6bcc93a8a 53 {
Marcus Chang 17:5dd6bcc93a8a 54 SerialBase::set_flow_control(SerialBase::RTSCTS, rts, cts);
Marcus Chang 17:5dd6bcc93a8a 55 }
Marcus Chang 10:9d3ae421081b 56 #endif
marcuschang 0:dfed780dc91a 57 }
marcuschang 0:dfed780dc91a 58
marcuschang 19:42ffb517d36a 59 AsyncSerial::~AsyncSerial()
marcuschang 19:42ffb517d36a 60 {
marcuschang 19:42ffb517d36a 61 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq);
marcuschang 19:42ffb517d36a 62 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq);
marcuschang 19:42ffb517d36a 63 }
marcuschang 19:42ffb517d36a 64
Marcus Chang 12:b45908320b9c 65 /* Tx ISR
Marcus Chang 12:b45908320b9c 66 */
marcuschang 0:dfed780dc91a 67 void AsyncSerial::putDone()
marcuschang 0:dfed780dc91a 68 {
Marcus Chang 12:b45908320b9c 69 // sendIndex points to the next byte to send
marcuschang 9:e183765bd81b 70 sendIndex++;
Marcus Chang 1:a3f39ec7d5f2 71
marcuschang 9:e183765bd81b 72 if (sendIndex < sendLength)
marcuschang 9:e183765bd81b 73 {
Marcus Chang 12:b45908320b9c 74 // send next character if there is still more to send
marcuschang 9:e183765bd81b 75 SerialBase::_base_putc(sendBuffer[sendIndex]);
marcuschang 9:e183765bd81b 76 }
marcuschang 9:e183765bd81b 77 else
marcuschang 9:e183765bd81b 78 {
marcuschang 19:42ffb517d36a 79 // disable TX interrupt
marcuschang 19:42ffb517d36a 80 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq);
marcuschang 19:42ffb517d36a 81
marcuschang 18:9127f9fae61f 82 // reset
marcuschang 18:9127f9fae61f 83 sendLength = 0;
marcuschang 18:9127f9fae61f 84
marcuschang 18:9127f9fae61f 85 // signal callback function
Marcus Chang 12:b45908320b9c 86 sendHandler.call();
marcuschang 0:dfed780dc91a 87 }
marcuschang 0:dfed780dc91a 88 }
marcuschang 0:dfed780dc91a 89
Marcus Chang 12:b45908320b9c 90 /* Rx ISR
Marcus Chang 12:b45908320b9c 91 */
marcuschang 0:dfed780dc91a 92 void AsyncSerial::getReady()
Marcus Chang 10:9d3ae421081b 93 {
Marcus Chang 15:4d7d96cacc18 94 // read character from buffer
Marcus Chang 15:4d7d96cacc18 95 uint8_t input = SerialBase::_base_getc();
Marcus Chang 15:4d7d96cacc18 96
Marcus Chang 15:4d7d96cacc18 97 DEBUG("%c", input);
Marcus Chang 15:4d7d96cacc18 98
Marcus Chang 15:4d7d96cacc18 99 // check if start condition has been met
Marcus Chang 15:4d7d96cacc18 100 if (insideCondition)
Marcus Chang 1:a3f39ec7d5f2 101 {
Marcus Chang 15:4d7d96cacc18 102 /* If stop condition has been set, check if the
Marcus Chang 15:4d7d96cacc18 103 character matches. If it does increment counter
Marcus Chang 15:4d7d96cacc18 104 to point to next character in sequence. Otherwise
Marcus Chang 15:4d7d96cacc18 105 reset sequence search.
Marcus Chang 15:4d7d96cacc18 106 */
Marcus Chang 15:4d7d96cacc18 107 if (conditionEndBuffer != NULL)
Marcus Chang 15:4d7d96cacc18 108 {
Marcus Chang 15:4d7d96cacc18 109 if (input == conditionEndBuffer[conditionIndex])
Marcus Chang 15:4d7d96cacc18 110 {
Marcus Chang 15:4d7d96cacc18 111 conditionIndex++;
Marcus Chang 1:a3f39ec7d5f2 112
Marcus Chang 15:4d7d96cacc18 113 /* End condition has been met.
Marcus Chang 15:4d7d96cacc18 114 Set receive status to indicate sequence has been found
Marcus Chang 15:4d7d96cacc18 115 and re-arm timer. The timeout is responsible for
Marcus Chang 15:4d7d96cacc18 116 signaling the callback function and is useful for
Marcus Chang 15:4d7d96cacc18 117 decoupling the callback from the receive ISR.
Marcus Chang 15:4d7d96cacc18 118 */
Marcus Chang 15:4d7d96cacc18 119 if (conditionIndex == conditionEndLength)
Marcus Chang 15:4d7d96cacc18 120 {
Marcus Chang 15:4d7d96cacc18 121 receiveStatus = AsyncSerial::RECEIVE_FOUND;
Marcus Chang 15:4d7d96cacc18 122 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT);
Marcus Chang 15:4d7d96cacc18 123 }
Marcus Chang 15:4d7d96cacc18 124 }
Marcus Chang 15:4d7d96cacc18 125 else
Marcus Chang 15:4d7d96cacc18 126 {
Marcus Chang 15:4d7d96cacc18 127 // Character didn't match sequence. Start over.
Marcus Chang 15:4d7d96cacc18 128 conditionIndex = 0;
Marcus Chang 15:4d7d96cacc18 129 }
Marcus Chang 15:4d7d96cacc18 130 }
marcuschang 7:5ba3a01e13c4 131
Marcus Chang 15:4d7d96cacc18 132 /* A receive buffer is available.
Marcus Chang 15:4d7d96cacc18 133 Store character in buffer and check if buffer is full,
Marcus Chang 15:4d7d96cacc18 134 set receive status and re-arm timeout if it is.
Marcus Chang 15:4d7d96cacc18 135 */
Marcus Chang 15:4d7d96cacc18 136 if (receiveBuffer != NULL)
Marcus Chang 10:9d3ae421081b 137 {
Marcus Chang 15:4d7d96cacc18 138 receiveBuffer[receiveIndex] = input;
Marcus Chang 15:4d7d96cacc18 139 receiveIndex++;
Marcus Chang 15:4d7d96cacc18 140
Marcus Chang 15:4d7d96cacc18 141 /* If end condition has been met we still store the character
Marcus Chang 15:4d7d96cacc18 142 but we do not change the receive status nor re-arm the timer.
Marcus Chang 12:b45908320b9c 143 */
Marcus Chang 15:4d7d96cacc18 144 if ((receiveIndex == receiveMaxLength) && (receiveStatus != AsyncSerial::RECEIVE_FOUND))
marcuschang 0:dfed780dc91a 145 {
Marcus Chang 15:4d7d96cacc18 146 receiveStatus = AsyncSerial::RECEIVE_FULL;
Marcus Chang 15:4d7d96cacc18 147 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT);
Marcus Chang 15:4d7d96cacc18 148 }
Marcus Chang 15:4d7d96cacc18 149 }
Marcus Chang 15:4d7d96cacc18 150 }
Marcus Chang 15:4d7d96cacc18 151 /* Start condition has not been met.
Marcus Chang 15:4d7d96cacc18 152 */
Marcus Chang 15:4d7d96cacc18 153 else
Marcus Chang 15:4d7d96cacc18 154 {
Marcus Chang 15:4d7d96cacc18 155 if (conditionStartBuffer != NULL)
Marcus Chang 15:4d7d96cacc18 156 {
Marcus Chang 15:4d7d96cacc18 157 if (input == conditionStartBuffer[conditionIndex])
Marcus Chang 15:4d7d96cacc18 158 {
Marcus Chang 15:4d7d96cacc18 159 conditionIndex++;
Marcus Chang 4:e0a0eef4ca18 160
Marcus Chang 15:4d7d96cacc18 161 /* Set condition flag and reset index since it is reused.
Marcus Chang 15:4d7d96cacc18 162 */
Marcus Chang 15:4d7d96cacc18 163 if (conditionIndex == conditionStartLength)
Marcus Chang 4:e0a0eef4ca18 164 {
Marcus Chang 15:4d7d96cacc18 165 insideCondition = true;
Marcus Chang 4:e0a0eef4ca18 166 conditionIndex = 0;
Marcus Chang 4:e0a0eef4ca18 167 }
Marcus Chang 4:e0a0eef4ca18 168 }
Marcus Chang 15:4d7d96cacc18 169 else
marcuschang 9:e183765bd81b 170 {
Marcus Chang 15:4d7d96cacc18 171 // Character didn't match sequence. Start over.
Marcus Chang 15:4d7d96cacc18 172 conditionIndex = 0;
marcuschang 0:dfed780dc91a 173 }
marcuschang 0:dfed780dc91a 174 }
marcuschang 0:dfed780dc91a 175 }
marcuschang 0:dfed780dc91a 176 }
marcuschang 0:dfed780dc91a 177
Marcus Chang 12:b45908320b9c 178 /* Common function for signaling receive done handler or wait done handler.
Marcus Chang 12:b45908320b9c 179 */
marcuschang 5:aecd37846dcc 180 void AsyncSerial::getDone(uint8_t status)
Marcus Chang 1:a3f39ec7d5f2 181 {
marcuschang 11:6b99dbf1b65d 182 DEBUG("getDone: %d\r\n", status);
marcuschang 7:5ba3a01e13c4 183
Marcus Chang 12:b45908320b9c 184 /* Check whether to call the wait handler or the receive handler.
Marcus Chang 12:b45908320b9c 185 */
Marcus Chang 12:b45908320b9c 186 if (receiveBuffer == NULL)
marcuschang 0:dfed780dc91a 187 {
marcuschang 11:6b99dbf1b65d 188 waitHandler.call(status);
marcuschang 0:dfed780dc91a 189 }
Marcus Chang 6:9d48f2197243 190 else
Marcus Chang 1:a3f39ec7d5f2 191 {
Marcus Chang 10:9d3ae421081b 192 receiveResult.buffer = receiveBuffer;
Marcus Chang 10:9d3ae421081b 193 receiveResult.length = receiveIndex;
Marcus Chang 10:9d3ae421081b 194 receiveResult.status = status;
Marcus Chang 10:9d3ae421081b 195
Marcus Chang 10:9d3ae421081b 196 receiveHandler.call(&receiveResult);
Marcus Chang 1:a3f39ec7d5f2 197 }
marcuschang 0:dfed780dc91a 198 }
marcuschang 0:dfed780dc91a 199
Marcus Chang 12:b45908320b9c 200 /* Send block of data. Function pointer interface.
Marcus Chang 12:b45908320b9c 201 */
marcuschang 7:5ba3a01e13c4 202 void AsyncSerial::send(send_done_t handler, const char* buffer, uint16_t length)
marcuschang 0:dfed780dc91a 203 {
Marcus Chang 12:b45908320b9c 204 sendHandler.attach(handler);
marcuschang 11:6b99dbf1b65d 205 send(buffer, length);
marcuschang 0:dfed780dc91a 206 }
marcuschang 0:dfed780dc91a 207
Marcus Chang 12:b45908320b9c 208 /* Common send block of data function.
Marcus Chang 12:b45908320b9c 209 */
marcuschang 7:5ba3a01e13c4 210 void AsyncSerial::send(const char* buffer, uint16_t length)
marcuschang 0:dfed780dc91a 211 {
Marcus Chang 12:b45908320b9c 212 /* Signal callback function immediately if there is nothing to send.
Marcus Chang 12:b45908320b9c 213 */
marcuschang 11:6b99dbf1b65d 214 if ((buffer != NULL) && (length != 0))
Marcus Chang 12:b45908320b9c 215 {
Marcus Chang 12:b45908320b9c 216 // Store book keeping variables
marcuschang 11:6b99dbf1b65d 217 sendBuffer = buffer;
marcuschang 11:6b99dbf1b65d 218 sendLength = length;
marcuschang 11:6b99dbf1b65d 219 sendIndex = 0;
Marcus Chang 12:b45908320b9c 220
Marcus Chang 12:b45908320b9c 221 // Send first character. ISR sends the rest.
marcuschang 11:6b99dbf1b65d 222 SerialBase::_base_putc(sendBuffer[sendIndex]);
Marcus Chang 12:b45908320b9c 223
marcuschang 19:42ffb517d36a 224 // enable TX interrupts
marcuschang 19:42ffb517d36a 225 SerialBase::attach<AsyncSerial>(this, &AsyncSerial::putDone, SerialBase::TxIrq);
marcuschang 19:42ffb517d36a 226
marcuschang 11:6b99dbf1b65d 227 DEBUG("send: %p %d\r\n", buffer, length);
marcuschang 11:6b99dbf1b65d 228 }
marcuschang 11:6b99dbf1b65d 229 else
marcuschang 11:6b99dbf1b65d 230 {
marcuschang 11:6b99dbf1b65d 231 sendHandler.call();
marcuschang 11:6b99dbf1b65d 232 }
marcuschang 0:dfed780dc91a 233 }
marcuschang 0:dfed780dc91a 234
Marcus Chang 12:b45908320b9c 235 /* Receiving block of data. Function pointer interface.
Marcus Chang 12:b45908320b9c 236 */
marcuschang 13:dbb23efed611 237 void AsyncSerial::receive(receive_done_t _handler,
marcuschang 13:dbb23efed611 238 uint8_t* _receiveBuffer, uint16_t _maxLength,
marcuschang 7:5ba3a01e13c4 239 const char* _conditionStartBuffer, uint16_t _conditionStartLength,
marcuschang 7:5ba3a01e13c4 240 const char* _conditionEndBuffer, uint16_t _conditionEndLength,
marcuschang 13:dbb23efed611 241 uint32_t _timeoutMilli)
Marcus Chang 10:9d3ae421081b 242 {
marcuschang 13:dbb23efed611 243 receiveHandler.attach(_handler);
marcuschang 13:dbb23efed611 244
Marcus Chang 12:b45908320b9c 245 /* Signal callback function immediately if buffer and maxLength are invalid.
Marcus Chang 12:b45908320b9c 246 */
marcuschang 13:dbb23efed611 247 if ((_receiveBuffer == NULL) || (_maxLength == 0))
Marcus Chang 12:b45908320b9c 248 {
Marcus Chang 12:b45908320b9c 249 receiveResult.buffer = NULL;
Marcus Chang 12:b45908320b9c 250 receiveResult.length = 0;
Marcus Chang 12:b45908320b9c 251 receiveResult.status = AsyncSerial::RECEIVE_FULL;
Marcus Chang 1:a3f39ec7d5f2 252
Marcus Chang 12:b45908320b9c 253 receiveHandler.call(&receiveResult);
Marcus Chang 4:e0a0eef4ca18 254 }
Marcus Chang 4:e0a0eef4ca18 255 else
Marcus Chang 4:e0a0eef4ca18 256 {
marcuschang 13:dbb23efed611 257 receive(_receiveBuffer, _maxLength,
marcuschang 13:dbb23efed611 258 _conditionStartBuffer, _conditionStartLength,
marcuschang 13:dbb23efed611 259 _conditionEndBuffer, _conditionEndLength,
marcuschang 13:dbb23efed611 260 _timeoutMilli);
marcuschang 13:dbb23efed611 261 }
marcuschang 13:dbb23efed611 262 }
Marcus Chang 4:e0a0eef4ca18 263
marcuschang 13:dbb23efed611 264 /* Common receive function.
marcuschang 13:dbb23efed611 265 */
marcuschang 13:dbb23efed611 266 void AsyncSerial::receive(uint8_t* _receiveBuffer, uint16_t _maxLength,
marcuschang 13:dbb23efed611 267 const char* _conditionStartBuffer, uint16_t _conditionStartLength,
marcuschang 13:dbb23efed611 268 const char* _conditionEndBuffer, uint16_t _conditionEndLength,
marcuschang 13:dbb23efed611 269 uint32_t _timeoutMilli)
marcuschang 13:dbb23efed611 270 {
marcuschang 13:dbb23efed611 271 // Book keeping variables for reception
marcuschang 13:dbb23efed611 272 receiveBuffer = _receiveBuffer;
marcuschang 13:dbb23efed611 273 receiveMaxLength = _maxLength;
marcuschang 13:dbb23efed611 274 receiveIndex = 0;
marcuschang 13:dbb23efed611 275 receiveStatus = AsyncSerial::RECEIVE_TIMEOUT;
Marcus Chang 12:b45908320b9c 276
marcuschang 13:dbb23efed611 277 // Book keeping variables for conditions
marcuschang 13:dbb23efed611 278 conditionStartBuffer = _conditionStartBuffer;
marcuschang 13:dbb23efed611 279 conditionStartLength = _conditionStartLength;
marcuschang 13:dbb23efed611 280 conditionEndBuffer = _conditionEndBuffer;
marcuschang 13:dbb23efed611 281 conditionEndLength = _conditionEndLength;
marcuschang 13:dbb23efed611 282 conditionIndex = 0;
Marcus Chang 12:b45908320b9c 283
marcuschang 13:dbb23efed611 284 // Check if optional start condition is set
marcuschang 13:dbb23efed611 285 if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0))
marcuschang 13:dbb23efed611 286 {
marcuschang 13:dbb23efed611 287 insideCondition = false;
marcuschang 13:dbb23efed611 288 }
marcuschang 13:dbb23efed611 289 else
marcuschang 13:dbb23efed611 290 {
marcuschang 13:dbb23efed611 291 insideCondition = true;
marcuschang 11:6b99dbf1b65d 292 }
marcuschang 11:6b99dbf1b65d 293
marcuschang 13:dbb23efed611 294 // Clear buffer. This re-arms the rx interrupts.
marcuschang 13:dbb23efed611 295 while (SerialBase::readable())
marcuschang 13:dbb23efed611 296 {
marcuschang 13:dbb23efed611 297 SerialBase::_base_getc();
marcuschang 13:dbb23efed611 298 }
marcuschang 13:dbb23efed611 299
marcuschang 13:dbb23efed611 300 // Arm timer and start receiving.
marcuschang 13:dbb23efed611 301 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, _timeoutMilli * 1000);
marcuschang 13:dbb23efed611 302
marcuschang 13:dbb23efed611 303 DEBUG("receive: %p\r\n", _receiveBuffer);
marcuschang 0:dfed780dc91a 304 }
marcuschang 0:dfed780dc91a 305
Marcus Chang 12:b45908320b9c 306 /* Wait until timeout or sequence is detected.
Marcus Chang 12:b45908320b9c 307 */
marcuschang 7:5ba3a01e13c4 308 void AsyncSerial::wait(wait_done_t handler,
marcuschang 7:5ba3a01e13c4 309 const char* conditionEndBuffer, uint16_t conditionEndLength,
Marcus Chang 6:9d48f2197243 310 uint32_t timeoutMilli)
Marcus Chang 6:9d48f2197243 311 {
marcuschang 11:6b99dbf1b65d 312 waitHandler.attach(handler);
Marcus Chang 6:9d48f2197243 313
marcuschang 11:6b99dbf1b65d 314 receive(NULL, 0,
marcuschang 11:6b99dbf1b65d 315 NULL, 0,
marcuschang 11:6b99dbf1b65d 316 conditionEndBuffer, conditionEndLength,
marcuschang 11:6b99dbf1b65d 317 timeoutMilli);
Marcus Chang 6:9d48f2197243 318 }
Marcus Chang 6:9d48f2197243 319
Marcus Chang 12:b45908320b9c 320 /* Timeout fired. Call common receive done function.
Marcus Chang 12:b45908320b9c 321 */
marcuschang 5:aecd37846dcc 322 void AsyncSerial::receiveTimeout()
marcuschang 5:aecd37846dcc 323 {
marcuschang 11:6b99dbf1b65d 324 DEBUG("timeout\r\n");
Marcus Chang 10:9d3ae421081b 325
marcuschang 9:e183765bd81b 326 getDone(receiveStatus);
marcuschang 5:aecd37846dcc 327 }
marcuschang 5:aecd37846dcc 328