Marcus Chang / AsyncSerial
Committer:
marcuschang
Date:
Fri Apr 10 16:28:15 2015 +0000
Revision:
13:dbb23efed611
Parent:
12:b45908320b9c
Child:
15:4d7d96cacc18
v1.0.0 complete.

Who changed what in which revision?

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