Asynchronous Serial Library with flow control and tag detection.
source/AsyncSerial.cpp@5:aecd37846dcc, 2015-04-01 (annotated)
- Committer:
- marcuschang
- Date:
- Wed Apr 01 16:28:02 2015 +0000
- Revision:
- 5:aecd37846dcc
- Parent:
- 4:e0a0eef4ca18
- Child:
- 6:9d48f2197243
checkpoint
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 | 0:dfed780dc91a | 5 | AsyncSerial::AsyncSerial(PinName tx, PinName rx, PinName rts, PinName cts) |
marcuschang | 0:dfed780dc91a | 6 | : SerialBase(tx, rx), |
Marcus Chang |
1:a3f39ec7d5f2 | 7 | |
marcuschang | 0:dfed780dc91a | 8 | sendBuffer(NULL), |
marcuschang | 0:dfed780dc91a | 9 | sendLength(0), |
Marcus Chang |
1:a3f39ec7d5f2 | 10 | sendIndex(0), |
Marcus Chang |
1:a3f39ec7d5f2 | 11 | |
marcuschang | 0:dfed780dc91a | 12 | sendDoneHandler(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 13 | sendObject(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 14 | sendMember(), |
Marcus Chang |
1:a3f39ec7d5f2 | 15 | sendDoneObject(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 16 | |
marcuschang | 0:dfed780dc91a | 17 | receiveDoneHandler(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 18 | receiveObject(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 19 | receiveMember(), |
Marcus Chang |
1:a3f39ec7d5f2 | 20 | receiveDoneObject(NULL), |
Marcus Chang |
1:a3f39ec7d5f2 | 21 | |
Marcus Chang |
4:e0a0eef4ca18 | 22 | isReceiving(false), |
Marcus Chang |
4:e0a0eef4ca18 | 23 | receiveBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 24 | receiveMaxLength(0), |
Marcus Chang |
4:e0a0eef4ca18 | 25 | receiveIndex(0), |
Marcus Chang |
4:e0a0eef4ca18 | 26 | |
Marcus Chang |
4:e0a0eef4ca18 | 27 | insideCondition(false), |
Marcus Chang |
4:e0a0eef4ca18 | 28 | conditionStartBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 29 | conditionStartLength(0), |
Marcus Chang |
4:e0a0eef4ca18 | 30 | conditionEndBuffer(NULL), |
Marcus Chang |
4:e0a0eef4ca18 | 31 | conditionEndLength(0), |
marcuschang | 0:dfed780dc91a | 32 | conditionIndex(0), |
marcuschang | 0:dfed780dc91a | 33 | timeout() |
Marcus Chang |
1:a3f39ec7d5f2 | 34 | { |
marcuschang | 0:dfed780dc91a | 35 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::getReady, SerialBase::RxIrq); |
marcuschang | 0:dfed780dc91a | 36 | SerialBase::attach<AsyncSerial>(this, &AsyncSerial::putDone, SerialBase::TxIrq); |
marcuschang | 0:dfed780dc91a | 37 | } |
marcuschang | 0:dfed780dc91a | 38 | |
marcuschang | 0:dfed780dc91a | 39 | void AsyncSerial::putDone() |
marcuschang | 0:dfed780dc91a | 40 | { |
marcuschang | 0:dfed780dc91a | 41 | if (sendLength > 0) |
marcuschang | 0:dfed780dc91a | 42 | { |
marcuschang | 0:dfed780dc91a | 43 | sendIndex++; |
Marcus Chang |
1:a3f39ec7d5f2 | 44 | |
marcuschang | 0:dfed780dc91a | 45 | if (sendIndex < sendLength) |
marcuschang | 0:dfed780dc91a | 46 | { |
marcuschang | 0:dfed780dc91a | 47 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
marcuschang | 0:dfed780dc91a | 48 | } |
marcuschang | 0:dfed780dc91a | 49 | else |
marcuschang | 0:dfed780dc91a | 50 | { |
Marcus Chang |
1:a3f39ec7d5f2 | 51 | sendLength = 0; |
Marcus Chang |
1:a3f39ec7d5f2 | 52 | |
marcuschang | 0:dfed780dc91a | 53 | if (sendDoneHandler) |
marcuschang | 0:dfed780dc91a | 54 | { |
marcuschang | 0:dfed780dc91a | 55 | sendDoneHandler(sendBuffer, sendLength); |
marcuschang | 0:dfed780dc91a | 56 | sendDoneHandler = NULL; |
Marcus Chang |
1:a3f39ec7d5f2 | 57 | } |
Marcus Chang |
1:a3f39ec7d5f2 | 58 | else if (sendObject) |
Marcus Chang |
1:a3f39ec7d5f2 | 59 | { |
Marcus Chang |
1:a3f39ec7d5f2 | 60 | sendDoneObject(sendObject, sendMember, sendBuffer, sendLength); |
Marcus Chang |
1:a3f39ec7d5f2 | 61 | sendObject = NULL; |
marcuschang | 0:dfed780dc91a | 62 | } |
marcuschang | 0:dfed780dc91a | 63 | } |
marcuschang | 0:dfed780dc91a | 64 | } |
marcuschang | 0:dfed780dc91a | 65 | } |
marcuschang | 0:dfed780dc91a | 66 | |
marcuschang | 0:dfed780dc91a | 67 | void AsyncSerial::getReady() |
marcuschang | 0:dfed780dc91a | 68 | { |
Marcus Chang |
4:e0a0eef4ca18 | 69 | if (isReceiving) |
Marcus Chang |
1:a3f39ec7d5f2 | 70 | { |
Marcus Chang |
4:e0a0eef4ca18 | 71 | uint8_t input = SerialBase::_base_getc(); |
Marcus Chang |
1:a3f39ec7d5f2 | 72 | |
Marcus Chang |
4:e0a0eef4ca18 | 73 | if (insideCondition) |
marcuschang | 0:dfed780dc91a | 74 | { |
Marcus Chang |
4:e0a0eef4ca18 | 75 | if (receiveBuffer != NULL) |
marcuschang | 0:dfed780dc91a | 76 | { |
Marcus Chang |
4:e0a0eef4ca18 | 77 | receiveBuffer[receiveIndex] = input; |
Marcus Chang |
4:e0a0eef4ca18 | 78 | receiveIndex++; |
Marcus Chang |
1:a3f39ec7d5f2 | 79 | |
Marcus Chang |
4:e0a0eef4ca18 | 80 | if (receiveIndex == receiveMaxLength) |
marcuschang | 0:dfed780dc91a | 81 | { |
marcuschang | 0:dfed780dc91a | 82 | timeout.detach(); |
marcuschang | 5:aecd37846dcc | 83 | getDone(AsyncSerial::RECEIVE_FULL); |
marcuschang | 0:dfed780dc91a | 84 | } |
marcuschang | 0:dfed780dc91a | 85 | } |
Marcus Chang |
4:e0a0eef4ca18 | 86 | |
Marcus Chang |
4:e0a0eef4ca18 | 87 | if (conditionEndBuffer != NULL) |
marcuschang | 0:dfed780dc91a | 88 | { |
Marcus Chang |
4:e0a0eef4ca18 | 89 | if (input == conditionEndBuffer[conditionIndex]) |
Marcus Chang |
4:e0a0eef4ca18 | 90 | { |
Marcus Chang |
4:e0a0eef4ca18 | 91 | conditionIndex++; |
Marcus Chang |
4:e0a0eef4ca18 | 92 | |
Marcus Chang |
4:e0a0eef4ca18 | 93 | if (conditionIndex == conditionEndLength) |
Marcus Chang |
4:e0a0eef4ca18 | 94 | { |
Marcus Chang |
4:e0a0eef4ca18 | 95 | timeout.detach(); |
marcuschang | 5:aecd37846dcc | 96 | getDone(AsyncSerial::RECEIVE_FOUND); |
Marcus Chang |
4:e0a0eef4ca18 | 97 | } |
Marcus Chang |
4:e0a0eef4ca18 | 98 | } |
Marcus Chang |
4:e0a0eef4ca18 | 99 | else |
Marcus Chang |
4:e0a0eef4ca18 | 100 | { |
Marcus Chang |
4:e0a0eef4ca18 | 101 | conditionIndex = 0; |
Marcus Chang |
4:e0a0eef4ca18 | 102 | } |
Marcus Chang |
4:e0a0eef4ca18 | 103 | } |
Marcus Chang |
4:e0a0eef4ca18 | 104 | } |
Marcus Chang |
4:e0a0eef4ca18 | 105 | else |
Marcus Chang |
4:e0a0eef4ca18 | 106 | { |
Marcus Chang |
4:e0a0eef4ca18 | 107 | if (conditionStartBuffer != NULL) |
Marcus Chang |
4:e0a0eef4ca18 | 108 | { |
Marcus Chang |
4:e0a0eef4ca18 | 109 | if (input == conditionStartBuffer[conditionIndex]) |
Marcus Chang |
4:e0a0eef4ca18 | 110 | { |
Marcus Chang |
4:e0a0eef4ca18 | 111 | conditionIndex++; |
Marcus Chang |
4:e0a0eef4ca18 | 112 | |
Marcus Chang |
4:e0a0eef4ca18 | 113 | if (conditionIndex == conditionStartLength) |
Marcus Chang |
4:e0a0eef4ca18 | 114 | { |
Marcus Chang |
4:e0a0eef4ca18 | 115 | insideCondition = true; |
Marcus Chang |
4:e0a0eef4ca18 | 116 | } |
Marcus Chang |
4:e0a0eef4ca18 | 117 | } |
Marcus Chang |
4:e0a0eef4ca18 | 118 | else |
Marcus Chang |
4:e0a0eef4ca18 | 119 | { |
Marcus Chang |
4:e0a0eef4ca18 | 120 | conditionIndex = 0; |
Marcus Chang |
4:e0a0eef4ca18 | 121 | } |
marcuschang | 0:dfed780dc91a | 122 | } |
marcuschang | 0:dfed780dc91a | 123 | } |
marcuschang | 0:dfed780dc91a | 124 | } |
marcuschang | 0:dfed780dc91a | 125 | } |
marcuschang | 0:dfed780dc91a | 126 | |
marcuschang | 5:aecd37846dcc | 127 | void AsyncSerial::getDone(uint8_t status) |
Marcus Chang |
1:a3f39ec7d5f2 | 128 | { |
Marcus Chang |
4:e0a0eef4ca18 | 129 | isReceiving = false; |
marcuschang | 0:dfed780dc91a | 130 | |
marcuschang | 0:dfed780dc91a | 131 | if (receiveDoneHandler) |
marcuschang | 0:dfed780dc91a | 132 | { |
marcuschang | 5:aecd37846dcc | 133 | receiveDoneHandler(receiveBuffer, receiveIndex, status); |
marcuschang | 0:dfed780dc91a | 134 | receiveDoneHandler = NULL; |
marcuschang | 0:dfed780dc91a | 135 | } |
Marcus Chang |
1:a3f39ec7d5f2 | 136 | else if (receiveObject) |
Marcus Chang |
1:a3f39ec7d5f2 | 137 | { |
marcuschang | 5:aecd37846dcc | 138 | receiveDoneObject(receiveObject, receiveMember, receiveBuffer, receiveIndex, status); |
Marcus Chang |
1:a3f39ec7d5f2 | 139 | receiveObject = NULL; |
Marcus Chang |
1:a3f39ec7d5f2 | 140 | } |
marcuschang | 0:dfed780dc91a | 141 | } |
marcuschang | 0:dfed780dc91a | 142 | |
marcuschang | 3:af3caa18e928 | 143 | void AsyncSerial::send(send_done_t handler, const uint8_t* buffer, uint16_t length) |
marcuschang | 0:dfed780dc91a | 144 | { |
marcuschang | 0:dfed780dc91a | 145 | if (handler && buffer && length) |
Marcus Chang |
1:a3f39ec7d5f2 | 146 | { |
marcuschang | 0:dfed780dc91a | 147 | sendDoneHandler = handler; |
Marcus Chang |
1:a3f39ec7d5f2 | 148 | |
Marcus Chang |
1:a3f39ec7d5f2 | 149 | sendObject = NULL; |
Marcus Chang |
1:a3f39ec7d5f2 | 150 | |
marcuschang | 0:dfed780dc91a | 151 | send(buffer, length); |
marcuschang | 0:dfed780dc91a | 152 | } |
marcuschang | 0:dfed780dc91a | 153 | } |
marcuschang | 0:dfed780dc91a | 154 | |
marcuschang | 3:af3caa18e928 | 155 | void AsyncSerial::send(const uint8_t* buffer, uint16_t length) |
marcuschang | 0:dfed780dc91a | 156 | { |
marcuschang | 0:dfed780dc91a | 157 | sendBuffer = buffer; |
marcuschang | 0:dfed780dc91a | 158 | sendLength = length; |
marcuschang | 0:dfed780dc91a | 159 | |
Marcus Chang |
1:a3f39ec7d5f2 | 160 | sendIndex = 0; |
marcuschang | 0:dfed780dc91a | 161 | SerialBase::_base_putc(sendBuffer[sendIndex]); |
marcuschang | 0:dfed780dc91a | 162 | } |
marcuschang | 0:dfed780dc91a | 163 | |
Marcus Chang |
1:a3f39ec7d5f2 | 164 | void AsyncSerial::receive(receive_done_t handler, |
Marcus Chang |
1:a3f39ec7d5f2 | 165 | uint8_t* buffer, uint16_t maxLength, |
Marcus Chang |
4:e0a0eef4ca18 | 166 | const uint8_t* conditionStartBuffer, uint16_t conditionStartLength, |
Marcus Chang |
4:e0a0eef4ca18 | 167 | const uint8_t* conditionEndBuffer, uint16_t conditionEndLength, |
marcuschang | 0:dfed780dc91a | 168 | uint32_t timeoutMilli) |
marcuschang | 0:dfed780dc91a | 169 | { |
Marcus Chang |
1:a3f39ec7d5f2 | 170 | if (handler) |
Marcus Chang |
1:a3f39ec7d5f2 | 171 | { |
Marcus Chang |
1:a3f39ec7d5f2 | 172 | receiveDoneHandler = handler; |
Marcus Chang |
1:a3f39ec7d5f2 | 173 | |
Marcus Chang |
1:a3f39ec7d5f2 | 174 | receiveObject = NULL; |
Marcus Chang |
1:a3f39ec7d5f2 | 175 | |
Marcus Chang |
4:e0a0eef4ca18 | 176 | receive(buffer, maxLength, |
Marcus Chang |
4:e0a0eef4ca18 | 177 | conditionStartBuffer, conditionStartLength, |
Marcus Chang |
4:e0a0eef4ca18 | 178 | conditionEndBuffer, conditionEndLength, |
Marcus Chang |
4:e0a0eef4ca18 | 179 | timeoutMilli); |
Marcus Chang |
1:a3f39ec7d5f2 | 180 | } |
Marcus Chang |
1:a3f39ec7d5f2 | 181 | } |
marcuschang | 0:dfed780dc91a | 182 | |
marcuschang | 2:efec63739aa3 | 183 | void AsyncSerial::receive(uint8_t* buffer, uint16_t maxLength, |
Marcus Chang |
4:e0a0eef4ca18 | 184 | const uint8_t* _conditionStartBuffer, uint16_t _conditionStartLength, |
Marcus Chang |
4:e0a0eef4ca18 | 185 | const uint8_t* _conditionEndBuffer, uint16_t _conditionEndLength, |
Marcus Chang |
1:a3f39ec7d5f2 | 186 | uint32_t timeoutMilli) |
Marcus Chang |
1:a3f39ec7d5f2 | 187 | { |
marcuschang | 0:dfed780dc91a | 188 | receiveBuffer = buffer; |
marcuschang | 0:dfed780dc91a | 189 | receiveMaxLength = maxLength; |
marcuschang | 0:dfed780dc91a | 190 | receiveIndex = 0; |
Marcus Chang |
1:a3f39ec7d5f2 | 191 | |
Marcus Chang |
4:e0a0eef4ca18 | 192 | conditionEndBuffer = _conditionEndBuffer; |
Marcus Chang |
4:e0a0eef4ca18 | 193 | conditionEndLength = _conditionEndLength; |
marcuschang | 0:dfed780dc91a | 194 | conditionIndex = 0; |
Marcus Chang |
1:a3f39ec7d5f2 | 195 | |
Marcus Chang |
4:e0a0eef4ca18 | 196 | if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0)) |
Marcus Chang |
4:e0a0eef4ca18 | 197 | { |
Marcus Chang |
4:e0a0eef4ca18 | 198 | insideCondition = false; |
Marcus Chang |
4:e0a0eef4ca18 | 199 | conditionStartBuffer = _conditionStartBuffer; |
Marcus Chang |
4:e0a0eef4ca18 | 200 | conditionStartLength = _conditionStartLength; |
Marcus Chang |
4:e0a0eef4ca18 | 201 | } |
Marcus Chang |
4:e0a0eef4ca18 | 202 | else |
Marcus Chang |
4:e0a0eef4ca18 | 203 | { |
Marcus Chang |
4:e0a0eef4ca18 | 204 | insideCondition = true; |
Marcus Chang |
4:e0a0eef4ca18 | 205 | } |
Marcus Chang |
4:e0a0eef4ca18 | 206 | |
marcuschang | 5:aecd37846dcc | 207 | timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, timeoutMilli * 1000); |
Marcus Chang |
4:e0a0eef4ca18 | 208 | isReceiving = true; |
marcuschang | 0:dfed780dc91a | 209 | } |
marcuschang | 0:dfed780dc91a | 210 | |
marcuschang | 5:aecd37846dcc | 211 | void AsyncSerial::receiveTimeout() |
marcuschang | 5:aecd37846dcc | 212 | { |
marcuschang | 5:aecd37846dcc | 213 | getDone(AsyncSerial::RECEIVE_TIMEOUT); |
marcuschang | 5:aecd37846dcc | 214 | } |
marcuschang | 5:aecd37846dcc | 215 | |
Marcus Chang |
1:a3f39ec7d5f2 | 216 | int AsyncSerial::getc() |
marcuschang | 0:dfed780dc91a | 217 | { |
marcuschang | 0:dfed780dc91a | 218 | return SerialBase::_base_getc(); |
marcuschang | 0:dfed780dc91a | 219 | } |
marcuschang | 0:dfed780dc91a | 220 | |
Marcus Chang |
1:a3f39ec7d5f2 | 221 | int AsyncSerial::putc(int c) |
marcuschang | 0:dfed780dc91a | 222 | { |
marcuschang | 0:dfed780dc91a | 223 | return SerialBase::_base_putc(c); |
marcuschang | 0:dfed780dc91a | 224 | } |
marcuschang | 0:dfed780dc91a | 225 | |
marcuschang | 0:dfed780dc91a | 226 |