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@11:6b99dbf1b65d, 2015-04-10 (annotated)
- Committer:
- marcuschang
- Date:
- Fri Apr 10 14:27:21 2015 +0000
- Revision:
- 11:6b99dbf1b65d
- Parent:
- 10:9d3ae421081b
- Child:
- 12:b45908320b9c
Changed all callbacks to use function pointer class.
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 | 11:6b99dbf1b65d | 14 | sendHandler(), |
| Marcus Chang |
10:9d3ae421081b | 15 | receiveHandler(), |
| Marcus Chang |
10:9d3ae421081b | 16 | receiveResult(), |
| marcuschang | 11:6b99dbf1b65d | 17 | waitHandler(), |
| marcuschang | 7:5ba3a01e13c4 | 18 | |
| Marcus Chang |
4:e0a0eef4ca18 | 19 | isReceiving(false), |
| Marcus Chang |
4:e0a0eef4ca18 | 20 | receiveBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 21 | receiveMaxLength(0), |
| Marcus Chang |
4:e0a0eef4ca18 | 22 | receiveIndex(0), |
| Marcus Chang |
10:9d3ae421081b | 23 | receiveStatus(AsyncSerial::RECEIVE_TIMEOUT), |
| Marcus Chang |
4:e0a0eef4ca18 | 24 | |
| Marcus Chang |
4:e0a0eef4ca18 | 25 | insideCondition(false), |
| Marcus Chang |
4:e0a0eef4ca18 | 26 | conditionStartBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 27 | conditionStartLength(0), |
| Marcus Chang |
4:e0a0eef4ca18 | 28 | conditionEndBuffer(NULL), |
| Marcus Chang |
4:e0a0eef4ca18 | 29 | conditionEndLength(0), |
| marcuschang | 0:dfed780dc91a | 30 | conditionIndex(0), |
| Marcus Chang |
10:9d3ae421081b | 31 | timeout() |
| Marcus Chang |
1:a3f39ec7d5f2 | 32 | { |
| 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 |
10:9d3ae421081b | 37 | // SerialBase::set_flow_control(SerialBase::RTSCTS, rts, cts); |
| Marcus Chang |
10:9d3ae421081b | 38 | #endif |
| marcuschang | 0:dfed780dc91a | 39 | } |
| marcuschang | 0:dfed780dc91a | 40 | |
| marcuschang | 0:dfed780dc91a | 41 | void AsyncSerial::putDone() |
| marcuschang | 0:dfed780dc91a | 42 | { |
| marcuschang | 9:e183765bd81b | 43 | sendIndex++; |
| Marcus Chang |
1:a3f39ec7d5f2 | 44 | |
| marcuschang | 9:e183765bd81b | 45 | if (sendIndex < sendLength) |
| marcuschang | 9:e183765bd81b | 46 | { |
| marcuschang | 9:e183765bd81b | 47 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
| marcuschang | 9:e183765bd81b | 48 | } |
| marcuschang | 9:e183765bd81b | 49 | else |
| marcuschang | 9:e183765bd81b | 50 | { |
| marcuschang | 11:6b99dbf1b65d | 51 | sendHandler.call(); |
| marcuschang | 0:dfed780dc91a | 52 | } |
| marcuschang | 0:dfed780dc91a | 53 | } |
| marcuschang | 0:dfed780dc91a | 54 | |
| marcuschang | 0:dfed780dc91a | 55 | void AsyncSerial::getReady() |
| Marcus Chang |
10:9d3ae421081b | 56 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 57 | if (isReceiving) |
| Marcus Chang |
1:a3f39ec7d5f2 | 58 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 59 | uint8_t input = SerialBase::_base_getc(); |
| Marcus Chang |
1:a3f39ec7d5f2 | 60 | |
| marcuschang | 7:5ba3a01e13c4 | 61 | DEBUG("%c", input); |
| marcuschang | 7:5ba3a01e13c4 | 62 | |
| Marcus Chang |
4:e0a0eef4ca18 | 63 | if (insideCondition) |
| Marcus Chang |
10:9d3ae421081b | 64 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 65 | if (conditionEndBuffer != NULL) |
| marcuschang | 0:dfed780dc91a | 66 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 67 | if (input == conditionEndBuffer[conditionIndex]) |
| Marcus Chang |
4:e0a0eef4ca18 | 68 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 69 | conditionIndex++; |
| Marcus Chang |
4:e0a0eef4ca18 | 70 | |
| Marcus Chang |
4:e0a0eef4ca18 | 71 | if (conditionIndex == conditionEndLength) |
| Marcus Chang |
10:9d3ae421081b | 72 | { |
| marcuschang | 9:e183765bd81b | 73 | receiveStatus = AsyncSerial::RECEIVE_FOUND; |
| marcuschang | 9:e183765bd81b | 74 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
| Marcus Chang |
4:e0a0eef4ca18 | 75 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 76 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 77 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 78 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 79 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 80 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 81 | } |
| marcuschang | 9:e183765bd81b | 82 | |
| marcuschang | 9:e183765bd81b | 83 | if (receiveBuffer != NULL) |
| marcuschang | 9:e183765bd81b | 84 | { |
| marcuschang | 9:e183765bd81b | 85 | receiveBuffer[receiveIndex] = input; |
| marcuschang | 9:e183765bd81b | 86 | receiveIndex++; |
| marcuschang | 9:e183765bd81b | 87 | |
| marcuschang | 9:e183765bd81b | 88 | if ((receiveIndex == receiveMaxLength) && (receiveStatus != AsyncSerial::RECEIVE_FOUND)) |
| marcuschang | 9:e183765bd81b | 89 | { |
| marcuschang | 9:e183765bd81b | 90 | receiveStatus = AsyncSerial::RECEIVE_FULL; |
| marcuschang | 9:e183765bd81b | 91 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); |
| marcuschang | 9:e183765bd81b | 92 | } |
| marcuschang | 9:e183765bd81b | 93 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 94 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 95 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 96 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 97 | if (conditionStartBuffer != NULL) |
| Marcus Chang |
4:e0a0eef4ca18 | 98 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 99 | if (input == conditionStartBuffer[conditionIndex]) |
| Marcus Chang |
4:e0a0eef4ca18 | 100 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 101 | conditionIndex++; |
| Marcus Chang |
4:e0a0eef4ca18 | 102 | |
| Marcus Chang |
4:e0a0eef4ca18 | 103 | if (conditionIndex == conditionStartLength) |
| Marcus Chang |
4:e0a0eef4ca18 | 104 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 105 | insideCondition = true; |
| marcuschang | 9:e183765bd81b | 106 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 107 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 108 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 109 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 110 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 111 | conditionIndex = 0; |
| Marcus Chang |
4:e0a0eef4ca18 | 112 | } |
| marcuschang | 0:dfed780dc91a | 113 | } |
| marcuschang | 0:dfed780dc91a | 114 | } |
| marcuschang | 0:dfed780dc91a | 115 | } |
| marcuschang | 0:dfed780dc91a | 116 | } |
| marcuschang | 0:dfed780dc91a | 117 | |
| marcuschang | 5:aecd37846dcc | 118 | void AsyncSerial::getDone(uint8_t status) |
| Marcus Chang |
1:a3f39ec7d5f2 | 119 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 120 | isReceiving = false; |
| marcuschang | 0:dfed780dc91a | 121 | |
| marcuschang | 11:6b99dbf1b65d | 122 | DEBUG("getDone: %d\r\n", status); |
| marcuschang | 7:5ba3a01e13c4 | 123 | |
| marcuschang | 9:e183765bd81b | 124 | if ((receiveBuffer == NULL) && (conditionStartBuffer == NULL)) |
| marcuschang | 0:dfed780dc91a | 125 | { |
| marcuschang | 11:6b99dbf1b65d | 126 | waitHandler.call(status); |
| marcuschang | 0:dfed780dc91a | 127 | } |
| Marcus Chang |
6:9d48f2197243 | 128 | else |
| Marcus Chang |
1:a3f39ec7d5f2 | 129 | { |
| Marcus Chang |
10:9d3ae421081b | 130 | receiveResult.buffer = receiveBuffer; |
| Marcus Chang |
10:9d3ae421081b | 131 | receiveResult.length = receiveIndex; |
| Marcus Chang |
10:9d3ae421081b | 132 | receiveResult.status = status; |
| Marcus Chang |
10:9d3ae421081b | 133 | |
| Marcus Chang |
10:9d3ae421081b | 134 | receiveHandler.call(&receiveResult); |
| Marcus Chang |
1:a3f39ec7d5f2 | 135 | } |
| marcuschang | 0:dfed780dc91a | 136 | } |
| marcuschang | 0:dfed780dc91a | 137 | |
| marcuschang | 7:5ba3a01e13c4 | 138 | void AsyncSerial::send(send_done_t handler, const char* buffer, uint16_t length) |
| marcuschang | 0:dfed780dc91a | 139 | { |
| marcuschang | 11:6b99dbf1b65d | 140 | sendHandler.attach(handler); |
| marcuschang | 11:6b99dbf1b65d | 141 | send(buffer, length); |
| marcuschang | 0:dfed780dc91a | 142 | } |
| marcuschang | 0:dfed780dc91a | 143 | |
| marcuschang | 7:5ba3a01e13c4 | 144 | void AsyncSerial::send(const char* buffer, uint16_t length) |
| marcuschang | 0:dfed780dc91a | 145 | { |
| marcuschang | 11:6b99dbf1b65d | 146 | if ((buffer != NULL) && (length != 0)) |
| marcuschang | 11:6b99dbf1b65d | 147 | { |
| marcuschang | 11:6b99dbf1b65d | 148 | sendBuffer = buffer; |
| marcuschang | 11:6b99dbf1b65d | 149 | sendLength = length; |
| marcuschang | 11:6b99dbf1b65d | 150 | |
| marcuschang | 11:6b99dbf1b65d | 151 | sendIndex = 0; |
| marcuschang | 11:6b99dbf1b65d | 152 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
| marcuschang | 11:6b99dbf1b65d | 153 | |
| marcuschang | 11:6b99dbf1b65d | 154 | DEBUG("send: %p %d\r\n", buffer, length); |
| marcuschang | 11:6b99dbf1b65d | 155 | } |
| marcuschang | 11:6b99dbf1b65d | 156 | else |
| marcuschang | 11:6b99dbf1b65d | 157 | { |
| marcuschang | 11:6b99dbf1b65d | 158 | sendHandler.call(); |
| marcuschang | 11:6b99dbf1b65d | 159 | } |
| marcuschang | 0:dfed780dc91a | 160 | } |
| marcuschang | 0:dfed780dc91a | 161 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 162 | void AsyncSerial::receive(receive_done_t handler, |
| Marcus Chang |
1:a3f39ec7d5f2 | 163 | uint8_t* buffer, uint16_t maxLength, |
| marcuschang | 7:5ba3a01e13c4 | 164 | const char* conditionStartBuffer, uint16_t conditionStartLength, |
| marcuschang | 7:5ba3a01e13c4 | 165 | const char* conditionEndBuffer, uint16_t conditionEndLength, |
| marcuschang | 0:dfed780dc91a | 166 | uint32_t timeoutMilli) |
| marcuschang | 0:dfed780dc91a | 167 | { |
| Marcus Chang |
1:a3f39ec7d5f2 | 168 | if (handler) |
| Marcus Chang |
1:a3f39ec7d5f2 | 169 | { |
| marcuschang | 11:6b99dbf1b65d | 170 | receiveHandler.attach(handler); |
| Marcus Chang |
1:a3f39ec7d5f2 | 171 | |
| Marcus Chang |
4:e0a0eef4ca18 | 172 | receive(buffer, maxLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 173 | conditionStartBuffer, conditionStartLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 174 | conditionEndBuffer, conditionEndLength, |
| Marcus Chang |
4:e0a0eef4ca18 | 175 | timeoutMilli); |
| Marcus Chang |
1:a3f39ec7d5f2 | 176 | } |
| Marcus Chang |
1:a3f39ec7d5f2 | 177 | } |
| marcuschang | 0:dfed780dc91a | 178 | |
| marcuschang | 2:efec63739aa3 | 179 | void AsyncSerial::receive(uint8_t* buffer, uint16_t maxLength, |
| marcuschang | 7:5ba3a01e13c4 | 180 | const char* _conditionStartBuffer, uint16_t _conditionStartLength, |
| marcuschang | 7:5ba3a01e13c4 | 181 | const char* _conditionEndBuffer, uint16_t _conditionEndLength, |
| Marcus Chang |
1:a3f39ec7d5f2 | 182 | uint32_t timeoutMilli) |
| Marcus Chang |
10:9d3ae421081b | 183 | { |
| marcuschang | 0:dfed780dc91a | 184 | receiveBuffer = buffer; |
| marcuschang | 0:dfed780dc91a | 185 | receiveMaxLength = maxLength; |
| marcuschang | 0:dfed780dc91a | 186 | receiveIndex = 0; |
| Marcus Chang |
1:a3f39ec7d5f2 | 187 | |
| Marcus Chang |
6:9d48f2197243 | 188 | conditionStartBuffer = _conditionStartBuffer; |
| Marcus Chang |
6:9d48f2197243 | 189 | conditionStartLength = _conditionStartLength; |
| Marcus Chang |
4:e0a0eef4ca18 | 190 | conditionEndBuffer = _conditionEndBuffer; |
| Marcus Chang |
4:e0a0eef4ca18 | 191 | conditionEndLength = _conditionEndLength; |
| marcuschang | 0:dfed780dc91a | 192 | conditionIndex = 0; |
| Marcus Chang |
1:a3f39ec7d5f2 | 193 | |
| Marcus Chang |
4:e0a0eef4ca18 | 194 | if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0)) |
| Marcus Chang |
4:e0a0eef4ca18 | 195 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 196 | insideCondition = false; |
| Marcus Chang |
4:e0a0eef4ca18 | 197 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 198 | else |
| Marcus Chang |
4:e0a0eef4ca18 | 199 | { |
| Marcus Chang |
4:e0a0eef4ca18 | 200 | insideCondition = true; |
| Marcus Chang |
4:e0a0eef4ca18 | 201 | } |
| Marcus Chang |
4:e0a0eef4ca18 | 202 | |
| marcuschang | 11:6b99dbf1b65d | 203 | while (SerialBase::readable()) |
| marcuschang | 11:6b99dbf1b65d | 204 | { |
| marcuschang | 11:6b99dbf1b65d | 205 | SerialBase::_base_getc(); |
| marcuschang | 11:6b99dbf1b65d | 206 | } |
| marcuschang | 11:6b99dbf1b65d | 207 | |
| marcuschang | 9:e183765bd81b | 208 | receiveStatus = AsyncSerial::RECEIVE_TIMEOUT; |
| marcuschang | 5:aecd37846dcc | 209 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, timeoutMilli * 1000); |
| Marcus Chang |
4:e0a0eef4ca18 | 210 | isReceiving = true; |
| marcuschang | 7:5ba3a01e13c4 | 211 | |
| marcuschang | 9:e183765bd81b | 212 | DEBUG("receive: %p\r\n", receiveBuffer); |
| marcuschang | 0:dfed780dc91a | 213 | } |
| marcuschang | 0:dfed780dc91a | 214 | |
| marcuschang | 9:e183765bd81b | 215 | |
| marcuschang | 7:5ba3a01e13c4 | 216 | void AsyncSerial::wait(wait_done_t handler, |
| marcuschang | 7:5ba3a01e13c4 | 217 | const char* conditionEndBuffer, uint16_t conditionEndLength, |
| Marcus Chang |
6:9d48f2197243 | 218 | uint32_t timeoutMilli) |
| Marcus Chang |
6:9d48f2197243 | 219 | { |
| marcuschang | 11:6b99dbf1b65d | 220 | waitHandler.attach(handler); |
| Marcus Chang |
6:9d48f2197243 | 221 | |
| marcuschang | 11:6b99dbf1b65d | 222 | receive(NULL, 0, |
| marcuschang | 11:6b99dbf1b65d | 223 | NULL, 0, |
| marcuschang | 11:6b99dbf1b65d | 224 | conditionEndBuffer, conditionEndLength, |
| marcuschang | 11:6b99dbf1b65d | 225 | timeoutMilli); |
| Marcus Chang |
6:9d48f2197243 | 226 | } |
| Marcus Chang |
6:9d48f2197243 | 227 | |
| marcuschang | 5:aecd37846dcc | 228 | void AsyncSerial::receiveTimeout() |
| marcuschang | 5:aecd37846dcc | 229 | { |
| marcuschang | 11:6b99dbf1b65d | 230 | DEBUG("timeout\r\n"); |
| Marcus Chang |
10:9d3ae421081b | 231 | |
| marcuschang | 9:e183765bd81b | 232 | getDone(receiveStatus); |
| marcuschang | 5:aecd37846dcc | 233 | } |
| marcuschang | 5:aecd37846dcc | 234 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 235 | int AsyncSerial::getc() |
| marcuschang | 0:dfed780dc91a | 236 | { |
| marcuschang | 0:dfed780dc91a | 237 | return SerialBase::_base_getc(); |
| marcuschang | 0:dfed780dc91a | 238 | } |
| marcuschang | 0:dfed780dc91a | 239 | |
| Marcus Chang |
1:a3f39ec7d5f2 | 240 | int AsyncSerial::putc(int c) |
| marcuschang | 0:dfed780dc91a | 241 | { |
| marcuschang | 0:dfed780dc91a | 242 | return SerialBase::_base_putc(c); |
| marcuschang | 0:dfed780dc91a | 243 | } |
| marcuschang | 0:dfed780dc91a | 244 | |
| marcuschang | 0:dfed780dc91a | 245 |

