Marcus Chang / AsyncSerial
Committer:
Marcus Chang
Date:
Wed Apr 15 17:30:47 2015 +0100
Revision:
15:4d7d96cacc18
Parent:
13:dbb23efed611
Child:
16:55e6fbfc1e9d
Changed receive behaviour to drop characters if not receiving.

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