Asynchronous Serial Library with flow control and tag detection.
source/AsyncSerial.cpp@21:bdc3c69a1cd7, 2015-04-28 (annotated)
- Committer:
- marcuschang
- Date:
- Tue Apr 28 12:48:28 2015 +0000
- Revision:
- 21:bdc3c69a1cd7
- Parent:
- 20:c36866a2d5a6
Removed debug pin.
Who changed what in which revision?
User | Revision | Line number | New 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 | |
Marcus Chang |
20:c36866a2d5a6 | 23 | |
marcuschang | 0:dfed780dc91a | 24 | AsyncSerial::AsyncSerial(PinName tx, PinName rx, PinName rts, PinName cts) |
marcuschang | 0:dfed780dc91a | 25 | : SerialBase(tx, rx), |
Marcus Chang |
1:a3f39ec7d5f2 | 26 | |
marcuschang | 0:dfed780dc91a | 27 | sendBuffer(NULL), |
marcuschang | 0:dfed780dc91a | 28 | sendLength(0), |
Marcus Chang |
1:a3f39ec7d5f2 | 29 | sendIndex(0), |
Marcus Chang |
1:a3f39ec7d5f2 | 30 | |
Marcus Chang |
4:e0a0eef4ca18 | 31 | receiveBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 32 | receiveMaxLength(0), |
Marcus Chang |
4:e0a0eef4ca18 | 33 | receiveIndex(0), |
Marcus Chang |
10:9d3ae421081b | 34 | receiveStatus(AsyncSerial::RECEIVE_TIMEOUT), |
Marcus Chang |
12:b45908320b9c | 35 | receiveResult(), |
marcuschang | 13:dbb23efed611 | 36 | timeout(), |
Marcus Chang |
4:e0a0eef4ca18 | 37 | |
Marcus Chang |
4:e0a0eef4ca18 | 38 | insideCondition(false), |
Marcus Chang |
4:e0a0eef4ca18 | 39 | conditionStartBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 40 | conditionStartLength(0), |
Marcus Chang |
4:e0a0eef4ca18 | 41 | conditionEndBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 42 | conditionEndLength(0), |
marcuschang | 0:dfed780dc91a | 43 | conditionIndex(0), |
Marcus Chang |
12:b45908320b9c | 44 | |
Marcus Chang |
12:b45908320b9c | 45 | sendHandler(), |
Marcus Chang |
12:b45908320b9c | 46 | receiveHandler(), |
marcuschang | 13:dbb23efed611 | 47 | waitHandler() |
Marcus Chang |
1:a3f39ec7d5f2 | 48 | { |
Marcus Chang |
10:9d3ae421081b | 49 | #if DEVICE_SERIAL_FC |
Marcus Chang |
17:5dd6bcc93a8a | 50 | if ((rts != NC) && (cts != NC)) |
Marcus Chang |
17:5dd6bcc93a8a | 51 | { |
Marcus Chang |
17:5dd6bcc93a8a | 52 | SerialBase::set_flow_control(SerialBase::RTSCTS, rts, cts); |
Marcus Chang |
17:5dd6bcc93a8a | 53 | } |
Marcus Chang |
10:9d3ae421081b | 54 | #endif |
marcuschang | 0:dfed780dc91a | 55 | } |
marcuschang | 0:dfed780dc91a | 56 | |
marcuschang | 19:42ffb517d36a | 57 | AsyncSerial::~AsyncSerial() |
marcuschang | 19:42ffb517d36a | 58 | { |
marcuschang | 19:42ffb517d36a | 59 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); |
marcuschang | 19:42ffb517d36a | 60 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); |
marcuschang | 19:42ffb517d36a | 61 | } |
marcuschang | 19:42ffb517d36a | 62 | |
Marcus Chang |
12:b45908320b9c | 63 | /* Tx ISR |
Marcus Chang |
12:b45908320b9c | 64 | */ |
marcuschang | 0:dfed780dc91a | 65 | void AsyncSerial::putDone() |
marcuschang | 0:dfed780dc91a | 66 | { |
Marcus Chang |
20:c36866a2d5a6 | 67 | // fill Tx buffers (in case the buffer can contain more than 1 byte) |
Marcus Chang |
20:c36866a2d5a6 | 68 | while(SerialBase::writeable()) |
marcuschang | 9:e183765bd81b | 69 | { |
Marcus Chang |
20:c36866a2d5a6 | 70 | if(sendIndex < sendLength) |
Marcus Chang |
20:c36866a2d5a6 | 71 | { |
Marcus Chang |
20:c36866a2d5a6 | 72 | // send next character if there is still more to send |
Marcus Chang |
20:c36866a2d5a6 | 73 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
Marcus Chang |
20:c36866a2d5a6 | 74 | |
Marcus Chang |
20:c36866a2d5a6 | 75 | // sendIndex points to the next byte to send |
Marcus Chang |
20:c36866a2d5a6 | 76 | sendIndex++; |
Marcus Chang |
20:c36866a2d5a6 | 77 | } |
Marcus Chang |
20:c36866a2d5a6 | 78 | else |
Marcus Chang |
20:c36866a2d5a6 | 79 | { |
Marcus Chang |
20:c36866a2d5a6 | 80 | // disable the TX interrupt when there is nothing left to send |
Marcus Chang |
20:c36866a2d5a6 | 81 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); |
Marcus Chang |
20:c36866a2d5a6 | 82 | |
Marcus Chang |
20:c36866a2d5a6 | 83 | // signal callback function |
Marcus Chang |
20:c36866a2d5a6 | 84 | sendHandler.call(); |
Marcus Chang |
20:c36866a2d5a6 | 85 | break; |
Marcus Chang |
20:c36866a2d5a6 | 86 | } |
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 |
20:c36866a2d5a6 | 94 | // read while there are characters in buffer |
Marcus Chang |
20:c36866a2d5a6 | 95 | while(SerialBase::readable()) |
Marcus Chang |
20:c36866a2d5a6 | 96 | { |
Marcus Chang |
20:c36866a2d5a6 | 97 | // read single character from buffer |
Marcus Chang |
20:c36866a2d5a6 | 98 | uint8_t input = SerialBase::_base_getc(); |
Marcus Chang |
15:4d7d96cacc18 | 99 | |
Marcus Chang |
20:c36866a2d5a6 | 100 | DEBUG("%c", input); |
Marcus Chang |
20:c36866a2d5a6 | 101 | |
Marcus Chang |
20:c36866a2d5a6 | 102 | // check if start condition has been met |
Marcus Chang |
20:c36866a2d5a6 | 103 | if (insideCondition) |
Marcus Chang |
15:4d7d96cacc18 | 104 | { |
Marcus Chang |
20:c36866a2d5a6 | 105 | /* If stop condition has been set, check if the |
Marcus Chang |
20:c36866a2d5a6 | 106 | character matches. If it does increment counter |
Marcus Chang |
20:c36866a2d5a6 | 107 | to point to next character in sequence. Otherwise |
Marcus Chang |
20:c36866a2d5a6 | 108 | reset sequence search. |
Marcus Chang |
20:c36866a2d5a6 | 109 | */ |
Marcus Chang |
20:c36866a2d5a6 | 110 | if (conditionEndBuffer != NULL) |
Marcus Chang |
15:4d7d96cacc18 | 111 | { |
Marcus Chang |
20:c36866a2d5a6 | 112 | if (input == conditionEndBuffer[conditionIndex]) |
Marcus Chang |
20:c36866a2d5a6 | 113 | { |
Marcus Chang |
20:c36866a2d5a6 | 114 | conditionIndex++; |
Marcus Chang |
15:4d7d96cacc18 | 115 | |
Marcus Chang |
20:c36866a2d5a6 | 116 | /* End condition has been met. |
Marcus Chang |
20:c36866a2d5a6 | 117 | Set receive status to indicate sequence has been found |
Marcus Chang |
20:c36866a2d5a6 | 118 | and re-arm timer. The timeout is responsible for |
Marcus Chang |
20:c36866a2d5a6 | 119 | signaling the callback function and is useful for |
Marcus Chang |
20:c36866a2d5a6 | 120 | decoupling the callback from the receive ISR. |
Marcus Chang |
20:c36866a2d5a6 | 121 | */ |
Marcus Chang |
20:c36866a2d5a6 | 122 | if (conditionIndex == conditionEndLength) |
Marcus Chang |
20:c36866a2d5a6 | 123 | { |
Marcus Chang |
20:c36866a2d5a6 | 124 | // Disable Rx interrupt |
Marcus Chang |
20:c36866a2d5a6 | 125 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); |
Marcus Chang |
4:e0a0eef4ca18 | 126 | |
Marcus Chang |
20:c36866a2d5a6 | 127 | // Fire timeout to signal callback |
Marcus Chang |
20:c36866a2d5a6 | 128 | receiveStatus = AsyncSerial::RECEIVE_FOUND; |
Marcus Chang |
20:c36866a2d5a6 | 129 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
Marcus Chang |
20:c36866a2d5a6 | 130 | break; |
Marcus Chang |
20:c36866a2d5a6 | 131 | } |
Marcus Chang |
20:c36866a2d5a6 | 132 | } |
Marcus Chang |
20:c36866a2d5a6 | 133 | else |
Marcus Chang |
4:e0a0eef4ca18 | 134 | { |
Marcus Chang |
20:c36866a2d5a6 | 135 | // Character didn't match sequence. Start over. |
Marcus Chang |
4:e0a0eef4ca18 | 136 | conditionIndex = 0; |
Marcus Chang |
4:e0a0eef4ca18 | 137 | } |
Marcus Chang |
4:e0a0eef4ca18 | 138 | } |
Marcus Chang |
20:c36866a2d5a6 | 139 | |
Marcus Chang |
20:c36866a2d5a6 | 140 | /* A receive buffer is available. |
Marcus Chang |
20:c36866a2d5a6 | 141 | Store character in buffer and check if buffer is full, |
Marcus Chang |
20:c36866a2d5a6 | 142 | set receive status and re-arm timeout if it is. |
Marcus Chang |
20:c36866a2d5a6 | 143 | */ |
Marcus Chang |
20:c36866a2d5a6 | 144 | if (receiveBuffer != NULL) |
marcuschang | 9:e183765bd81b | 145 | { |
Marcus Chang |
20:c36866a2d5a6 | 146 | receiveBuffer[receiveIndex] = input; |
Marcus Chang |
20:c36866a2d5a6 | 147 | receiveIndex++; |
Marcus Chang |
20:c36866a2d5a6 | 148 | |
Marcus Chang |
20:c36866a2d5a6 | 149 | /* If end condition has been met we still store the character |
Marcus Chang |
20:c36866a2d5a6 | 150 | but we do not change the receive status nor re-arm the timer. |
Marcus Chang |
20:c36866a2d5a6 | 151 | */ |
Marcus Chang |
20:c36866a2d5a6 | 152 | if ((receiveIndex == receiveMaxLength) && (receiveStatus != AsyncSerial::RECEIVE_FOUND)) |
Marcus Chang |
20:c36866a2d5a6 | 153 | { |
Marcus Chang |
20:c36866a2d5a6 | 154 | // Disable Rx interrupt |
Marcus Chang |
20:c36866a2d5a6 | 155 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); |
Marcus Chang |
20:c36866a2d5a6 | 156 | |
Marcus Chang |
20:c36866a2d5a6 | 157 | // Fire timeout to signal callback |
Marcus Chang |
20:c36866a2d5a6 | 158 | receiveStatus = AsyncSerial::RECEIVE_FULL; |
Marcus Chang |
20:c36866a2d5a6 | 159 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
Marcus Chang |
20:c36866a2d5a6 | 160 | break; |
Marcus Chang |
20:c36866a2d5a6 | 161 | } |
Marcus Chang |
20:c36866a2d5a6 | 162 | } |
Marcus Chang |
20:c36866a2d5a6 | 163 | } |
Marcus Chang |
20:c36866a2d5a6 | 164 | /* Start condition has not been met. |
Marcus Chang |
20:c36866a2d5a6 | 165 | */ |
Marcus Chang |
20:c36866a2d5a6 | 166 | else |
Marcus Chang |
20:c36866a2d5a6 | 167 | { |
Marcus Chang |
20:c36866a2d5a6 | 168 | if (conditionStartBuffer != NULL) |
Marcus Chang |
20:c36866a2d5a6 | 169 | { |
Marcus Chang |
20:c36866a2d5a6 | 170 | if (input == conditionStartBuffer[conditionIndex]) |
Marcus Chang |
20:c36866a2d5a6 | 171 | { |
Marcus Chang |
20:c36866a2d5a6 | 172 | conditionIndex++; |
Marcus Chang |
20:c36866a2d5a6 | 173 | |
Marcus Chang |
20:c36866a2d5a6 | 174 | /* Set condition flag and reset index since it is reused. |
Marcus Chang |
20:c36866a2d5a6 | 175 | */ |
Marcus Chang |
20:c36866a2d5a6 | 176 | if (conditionIndex == conditionStartLength) |
Marcus Chang |
20:c36866a2d5a6 | 177 | { |
Marcus Chang |
20:c36866a2d5a6 | 178 | insideCondition = true; |
Marcus Chang |
20:c36866a2d5a6 | 179 | conditionIndex = 0; |
Marcus Chang |
20:c36866a2d5a6 | 180 | } |
Marcus Chang |
20:c36866a2d5a6 | 181 | } |
Marcus Chang |
20:c36866a2d5a6 | 182 | else |
Marcus Chang |
20:c36866a2d5a6 | 183 | { |
Marcus Chang |
20:c36866a2d5a6 | 184 | // Character didn't match sequence. Start over. |
Marcus Chang |
20:c36866a2d5a6 | 185 | conditionIndex = 0; |
Marcus Chang |
20:c36866a2d5a6 | 186 | } |
marcuschang | 0:dfed780dc91a | 187 | } |
marcuschang | 0:dfed780dc91a | 188 | } |
marcuschang | 0:dfed780dc91a | 189 | } |
marcuschang | 0:dfed780dc91a | 190 | } |
marcuschang | 0:dfed780dc91a | 191 | |
Marcus Chang |
12:b45908320b9c | 192 | /* Common function for signaling receive done handler or wait done handler. |
Marcus Chang |
12:b45908320b9c | 193 | */ |
marcuschang | 5:aecd37846dcc | 194 | void AsyncSerial::getDone(uint8_t status) |
Marcus Chang |
1:a3f39ec7d5f2 | 195 | { |
marcuschang | 11:6b99dbf1b65d | 196 | DEBUG("getDone: %d\r\n", status); |
marcuschang | 7:5ba3a01e13c4 | 197 | |
Marcus Chang |
12:b45908320b9c | 198 | /* Check whether to call the wait handler or the receive handler. |
Marcus Chang |
12:b45908320b9c | 199 | */ |
Marcus Chang |
12:b45908320b9c | 200 | if (receiveBuffer == NULL) |
marcuschang | 0:dfed780dc91a | 201 | { |
marcuschang | 11:6b99dbf1b65d | 202 | waitHandler.call(status); |
marcuschang | 0:dfed780dc91a | 203 | } |
Marcus Chang |
6:9d48f2197243 | 204 | else |
Marcus Chang |
1:a3f39ec7d5f2 | 205 | { |
Marcus Chang |
10:9d3ae421081b | 206 | receiveResult.buffer = receiveBuffer; |
Marcus Chang |
10:9d3ae421081b | 207 | receiveResult.length = receiveIndex; |
Marcus Chang |
10:9d3ae421081b | 208 | receiveResult.status = status; |
Marcus Chang |
10:9d3ae421081b | 209 | |
Marcus Chang |
10:9d3ae421081b | 210 | receiveHandler.call(&receiveResult); |
Marcus Chang |
1:a3f39ec7d5f2 | 211 | } |
marcuschang | 0:dfed780dc91a | 212 | } |
marcuschang | 0:dfed780dc91a | 213 | |
Marcus Chang |
12:b45908320b9c | 214 | /* Send block of data. Function pointer interface. |
Marcus Chang |
12:b45908320b9c | 215 | */ |
marcuschang | 7:5ba3a01e13c4 | 216 | void AsyncSerial::send(send_done_t handler, const char* buffer, uint16_t length) |
marcuschang | 0:dfed780dc91a | 217 | { |
Marcus Chang |
12:b45908320b9c | 218 | sendHandler.attach(handler); |
marcuschang | 11:6b99dbf1b65d | 219 | send(buffer, length); |
marcuschang | 0:dfed780dc91a | 220 | } |
marcuschang | 0:dfed780dc91a | 221 | |
Marcus Chang |
12:b45908320b9c | 222 | /* Common send block of data function. |
Marcus Chang |
12:b45908320b9c | 223 | */ |
marcuschang | 7:5ba3a01e13c4 | 224 | void AsyncSerial::send(const char* buffer, uint16_t length) |
marcuschang | 0:dfed780dc91a | 225 | { |
Marcus Chang |
12:b45908320b9c | 226 | /* Signal callback function immediately if there is nothing to send. |
Marcus Chang |
12:b45908320b9c | 227 | */ |
marcuschang | 11:6b99dbf1b65d | 228 | if ((buffer != NULL) && (length != 0)) |
Marcus Chang |
12:b45908320b9c | 229 | { |
Marcus Chang |
12:b45908320b9c | 230 | // Store book keeping variables |
marcuschang | 11:6b99dbf1b65d | 231 | sendBuffer = buffer; |
marcuschang | 11:6b99dbf1b65d | 232 | sendLength = length; |
marcuschang | 11:6b99dbf1b65d | 233 | sendIndex = 0; |
Marcus Chang |
12:b45908320b9c | 234 | |
Marcus Chang |
20:c36866a2d5a6 | 235 | if(SerialBase::writeable()) |
Marcus Chang |
20:c36866a2d5a6 | 236 | { |
Marcus Chang |
20:c36866a2d5a6 | 237 | // make sure not to cause contention in the irq |
Marcus Chang |
20:c36866a2d5a6 | 238 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); |
Marcus Chang |
12:b45908320b9c | 239 | |
Marcus Chang |
20:c36866a2d5a6 | 240 | // only write to hardware in one place |
Marcus Chang |
20:c36866a2d5a6 | 241 | AsyncSerial::putDone(); |
Marcus Chang |
20:c36866a2d5a6 | 242 | |
Marcus Chang |
20:c36866a2d5a6 | 243 | // enable TX interrupts |
Marcus Chang |
20:c36866a2d5a6 | 244 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::putDone, SerialBase::TxIrq); |
Marcus Chang |
20:c36866a2d5a6 | 245 | } |
marcuschang | 19:42ffb517d36a | 246 | |
marcuschang | 11:6b99dbf1b65d | 247 | DEBUG("send: %p %d\r\n", buffer, length); |
marcuschang | 11:6b99dbf1b65d | 248 | } |
marcuschang | 11:6b99dbf1b65d | 249 | else |
marcuschang | 11:6b99dbf1b65d | 250 | { |
marcuschang | 11:6b99dbf1b65d | 251 | sendHandler.call(); |
marcuschang | 11:6b99dbf1b65d | 252 | } |
marcuschang | 0:dfed780dc91a | 253 | } |
marcuschang | 0:dfed780dc91a | 254 | |
Marcus Chang |
20:c36866a2d5a6 | 255 | |
Marcus Chang |
12:b45908320b9c | 256 | /* Receiving block of data. Function pointer interface. |
Marcus Chang |
12:b45908320b9c | 257 | */ |
marcuschang | 13:dbb23efed611 | 258 | void AsyncSerial::receive(receive_done_t _handler, |
marcuschang | 13:dbb23efed611 | 259 | uint8_t* _receiveBuffer, uint16_t _maxLength, |
marcuschang | 7:5ba3a01e13c4 | 260 | const char* _conditionStartBuffer, uint16_t _conditionStartLength, |
marcuschang | 7:5ba3a01e13c4 | 261 | const char* _conditionEndBuffer, uint16_t _conditionEndLength, |
marcuschang | 13:dbb23efed611 | 262 | uint32_t _timeoutMilli) |
Marcus Chang |
10:9d3ae421081b | 263 | { |
marcuschang | 13:dbb23efed611 | 264 | receiveHandler.attach(_handler); |
marcuschang | 13:dbb23efed611 | 265 | |
Marcus Chang |
12:b45908320b9c | 266 | /* Signal callback function immediately if buffer and maxLength are invalid. |
Marcus Chang |
12:b45908320b9c | 267 | */ |
marcuschang | 13:dbb23efed611 | 268 | if ((_receiveBuffer == NULL) || (_maxLength == 0)) |
Marcus Chang |
12:b45908320b9c | 269 | { |
Marcus Chang |
12:b45908320b9c | 270 | receiveResult.buffer = NULL; |
Marcus Chang |
12:b45908320b9c | 271 | receiveResult.length = 0; |
Marcus Chang |
12:b45908320b9c | 272 | receiveResult.status = AsyncSerial::RECEIVE_FULL; |
Marcus Chang |
1:a3f39ec7d5f2 | 273 | |
Marcus Chang |
12:b45908320b9c | 274 | receiveHandler.call(&receiveResult); |
Marcus Chang |
4:e0a0eef4ca18 | 275 | } |
Marcus Chang |
4:e0a0eef4ca18 | 276 | else |
Marcus Chang |
4:e0a0eef4ca18 | 277 | { |
marcuschang | 13:dbb23efed611 | 278 | receive(_receiveBuffer, _maxLength, |
marcuschang | 13:dbb23efed611 | 279 | _conditionStartBuffer, _conditionStartLength, |
marcuschang | 13:dbb23efed611 | 280 | _conditionEndBuffer, _conditionEndLength, |
marcuschang | 13:dbb23efed611 | 281 | _timeoutMilli); |
marcuschang | 13:dbb23efed611 | 282 | } |
marcuschang | 13:dbb23efed611 | 283 | } |
Marcus Chang |
4:e0a0eef4ca18 | 284 | |
marcuschang | 13:dbb23efed611 | 285 | /* Common receive function. |
marcuschang | 13:dbb23efed611 | 286 | */ |
marcuschang | 13:dbb23efed611 | 287 | void AsyncSerial::receive(uint8_t* _receiveBuffer, uint16_t _maxLength, |
marcuschang | 13:dbb23efed611 | 288 | const char* _conditionStartBuffer, uint16_t _conditionStartLength, |
marcuschang | 13:dbb23efed611 | 289 | const char* _conditionEndBuffer, uint16_t _conditionEndLength, |
marcuschang | 13:dbb23efed611 | 290 | uint32_t _timeoutMilli) |
marcuschang | 13:dbb23efed611 | 291 | { |
marcuschang | 13:dbb23efed611 | 292 | // Book keeping variables for reception |
marcuschang | 13:dbb23efed611 | 293 | receiveBuffer = _receiveBuffer; |
marcuschang | 13:dbb23efed611 | 294 | receiveMaxLength = _maxLength; |
marcuschang | 13:dbb23efed611 | 295 | receiveIndex = 0; |
marcuschang | 13:dbb23efed611 | 296 | receiveStatus = AsyncSerial::RECEIVE_TIMEOUT; |
Marcus Chang |
12:b45908320b9c | 297 | |
marcuschang | 13:dbb23efed611 | 298 | // Book keeping variables for conditions |
marcuschang | 13:dbb23efed611 | 299 | conditionStartBuffer = _conditionStartBuffer; |
marcuschang | 13:dbb23efed611 | 300 | conditionStartLength = _conditionStartLength; |
marcuschang | 13:dbb23efed611 | 301 | conditionEndBuffer = _conditionEndBuffer; |
marcuschang | 13:dbb23efed611 | 302 | conditionEndLength = _conditionEndLength; |
marcuschang | 13:dbb23efed611 | 303 | conditionIndex = 0; |
Marcus Chang |
12:b45908320b9c | 304 | |
marcuschang | 13:dbb23efed611 | 305 | // Check if optional start condition is set |
marcuschang | 13:dbb23efed611 | 306 | if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0)) |
marcuschang | 13:dbb23efed611 | 307 | { |
marcuschang | 13:dbb23efed611 | 308 | insideCondition = false; |
marcuschang | 13:dbb23efed611 | 309 | } |
marcuschang | 13:dbb23efed611 | 310 | else |
marcuschang | 13:dbb23efed611 | 311 | { |
marcuschang | 13:dbb23efed611 | 312 | insideCondition = true; |
marcuschang | 11:6b99dbf1b65d | 313 | } |
marcuschang | 11:6b99dbf1b65d | 314 | |
Marcus Chang |
20:c36866a2d5a6 | 315 | // Arm timer |
Marcus Chang |
20:c36866a2d5a6 | 316 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, _timeoutMilli * 1000); |
marcuschang | 13:dbb23efed611 | 317 | |
Marcus Chang |
20:c36866a2d5a6 | 318 | // Arm Rx interrupts and start receiving |
Marcus Chang |
20:c36866a2d5a6 | 319 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::getReady, SerialBase::RxIrq); |
marcuschang | 13:dbb23efed611 | 320 | |
marcuschang | 13:dbb23efed611 | 321 | DEBUG("receive: %p\r\n", _receiveBuffer); |
marcuschang | 0:dfed780dc91a | 322 | } |
marcuschang | 0:dfed780dc91a | 323 | |
Marcus Chang |
12:b45908320b9c | 324 | /* Wait until timeout or sequence is detected. |
Marcus Chang |
12:b45908320b9c | 325 | */ |
marcuschang | 7:5ba3a01e13c4 | 326 | void AsyncSerial::wait(wait_done_t handler, |
marcuschang | 7:5ba3a01e13c4 | 327 | const char* conditionEndBuffer, uint16_t conditionEndLength, |
Marcus Chang |
6:9d48f2197243 | 328 | uint32_t timeoutMilli) |
Marcus Chang |
6:9d48f2197243 | 329 | { |
marcuschang | 11:6b99dbf1b65d | 330 | waitHandler.attach(handler); |
Marcus Chang |
6:9d48f2197243 | 331 | |
marcuschang | 11:6b99dbf1b65d | 332 | receive(NULL, 0, |
marcuschang | 11:6b99dbf1b65d | 333 | NULL, 0, |
marcuschang | 11:6b99dbf1b65d | 334 | conditionEndBuffer, conditionEndLength, |
marcuschang | 11:6b99dbf1b65d | 335 | timeoutMilli); |
Marcus Chang |
6:9d48f2197243 | 336 | } |
Marcus Chang |
6:9d48f2197243 | 337 | |
Marcus Chang |
12:b45908320b9c | 338 | /* Timeout fired. Call common receive done function. |
Marcus Chang |
12:b45908320b9c | 339 | */ |
marcuschang | 5:aecd37846dcc | 340 | void AsyncSerial::receiveTimeout() |
marcuschang | 5:aecd37846dcc | 341 | { |
marcuschang | 11:6b99dbf1b65d | 342 | DEBUG("timeout\r\n"); |
Marcus Chang |
10:9d3ae421081b | 343 | |
Marcus Chang |
20:c36866a2d5a6 | 344 | // Disable Rx interrupt (interrupts are not disabled if Rx timeouts) |
Marcus Chang |
20:c36866a2d5a6 | 345 | if (receiveStatus == AsyncSerial::RECEIVE_TIMEOUT) |
Marcus Chang |
20:c36866a2d5a6 | 346 | { |
Marcus Chang |
20:c36866a2d5a6 | 347 | SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); |
Marcus Chang |
20:c36866a2d5a6 | 348 | } |
Marcus Chang |
20:c36866a2d5a6 | 349 | |
marcuschang | 9:e183765bd81b | 350 | getDone(receiveStatus); |
marcuschang | 5:aecd37846dcc | 351 | } |
marcuschang | 5:aecd37846dcc | 352 |