amiro-os / components / bluetooth / bluetooth-transport.cpp @ ec052975
History | View | Annotate | Download (9.391 KB)
1 |
#include <ch.hpp> |
---|---|
2 |
#include <hal.h> |
3 |
|
4 |
#include <uart.h> |
5 |
#include <chprintf.h> |
6 |
|
7 |
#include <amiro/bluetooth/bluetooth-transport.hpp> |
8 |
|
9 |
using namespace chibios_rt; |
10 |
using namespace amiro; |
11 |
|
12 |
/*
|
13 |
* Class constructor
|
14 |
*/
|
15 |
BluetoothTransport::BluetoothTransport(UARTDriver* uart) : |
16 |
BaseStaticThread<128>(), UARTConfig(), uart(uart), receiveMailbox{NULL}, |
17 |
storageMailbox(storageMailboxBuffer, BLUETOOTH_TRANSPORT_STORAGE_MAILBOX_SIZE), |
18 |
transmitMailbox(transmitMailboxBuffer, BLUETOOTH_TRANSPORT_TRANSMIT_MAILBOX_SIZE) { |
19 |
|
20 |
UARTConfig::txend1_cb = bluetoothTransportTransmitCompleted_cb; |
21 |
UARTConfig::txend2_cb = NULL;
|
22 |
UARTConfig::rxend_cb = bluetoothTransportReceiveCompleted_cb; |
23 |
UARTConfig::rxchar_cb = bluetoothTransportCharacterReceived_cb; |
24 |
UARTConfig::rxerr_cb = NULL;
|
25 |
speed = 115200;
|
26 |
cr1 = 0;
|
27 |
cr2 = 0;
|
28 |
cr3 = 0;
|
29 |
|
30 |
transmitState = BLUETOOTH_TRANSPORT_PLAIN; |
31 |
receiveState = BLUETOOTH_TRANSPORT_PLAIN; |
32 |
|
33 |
transmit = NULL;
|
34 |
receive = NULL;
|
35 |
} |
36 |
|
37 |
//----------------------------------------------------------------
|
38 |
|
39 |
msg_t BluetoothTransport::main(void) {
|
40 |
setName("BluetoothTransport");
|
41 |
|
42 |
for (int i = 0; i < BLUETOOTH_TRANSPORT_STORAGE_MAILBOX_SIZE; i++) |
43 |
storageMailbox.post((msg_t) &descriptor[i], TIME_INFINITE); |
44 |
|
45 |
BaseThread::sleep(MS2ST(200));
|
46 |
uartStart(uart, this);
|
47 |
|
48 |
while (!this->shouldTerminate()) { |
49 |
|
50 |
if (!this->transmitMailbox.fetch((msg_t *) &transmit, TIME_INFINITE)) { |
51 |
|
52 |
if (!transmit->bluetoothDescriptorGetPayloadLength()) {
|
53 |
storageMailbox.post((msg_t) transmit, TIME_INFINITE); |
54 |
continue;
|
55 |
} |
56 |
|
57 |
if (transmitState == BLUETOOTH_TRANSPORT_PLAIN) {
|
58 |
uint8_t* buffer = transmit->bluetoothDescriptorGetPayload(); |
59 |
size_t length = transmit->bluetoothDescriptorGetPayloadLength(); |
60 |
|
61 |
memcpy(buffer+length, "\r\n", 2); |
62 |
|
63 |
uartStartSend(uart, length + 2, buffer);
|
64 |
} else {
|
65 |
transmitState = BLUETOOTH_TRANSPORT_PAYLOAD; |
66 |
uartStartSend(uart, FRAME_HEADER_SIZE, getEncodeHeader()); |
67 |
} |
68 |
waitAnyEvent((eventmask_t) TRANSMIT_COMPLETED_EVENT); |
69 |
} |
70 |
} |
71 |
return RDY_OK;
|
72 |
} |
73 |
|
74 |
/*
|
75 |
* Interrupt callback handlers
|
76 |
*/
|
77 |
void BluetoothTransport::bluetoothTransportTransmitCompleted_cb(UARTDriver *uart) {
|
78 |
BluetoothTransport *u = (BluetoothTransport *) uart->config; |
79 |
u->bluetoothTransportTransmitCompleted(); |
80 |
} |
81 |
|
82 |
void BluetoothTransport::bluetoothTransportTransmitCompleted() {
|
83 |
switch (transmitState) {
|
84 |
case BLUETOOTH_TRANSPORT_PLAIN: {
|
85 |
postTransmitDescriptorI(); |
86 |
|
87 |
System::lockFromIsr(); |
88 |
signalEventsI((eventmask_t) TRANSMIT_COMPLETED_EVENT); |
89 |
System::unlockFromIsr(); |
90 |
break;
|
91 |
} |
92 |
case BLUETOOTH_TRANSPORT_HEADER: {
|
93 |
System::lockFromIsr(); |
94 |
uartStartSendI(uart, FRAME_HEADER_SIZE, getEncodeHeader()); |
95 |
System::unlockFromIsr(); |
96 |
transmitState = BLUETOOTH_TRANSPORT_PAYLOAD; |
97 |
/* no break */
|
98 |
} |
99 |
case BLUETOOTH_TRANSPORT_PAYLOAD: {
|
100 |
System::lockFromIsr(); |
101 |
uartStartSendI(uart, transmit->bluetoothDescriptorGetPayloadLength(), transmit->bluetoothDescriptorGetPayload()); |
102 |
System::unlockFromIsr(); |
103 |
transmitState = BLUETOOTH_TRANSPORT_TRAILER; |
104 |
break;
|
105 |
} |
106 |
case BLUETOOTH_TRANSPORT_TRAILER: {
|
107 |
postTransmitDescriptorI(); |
108 |
|
109 |
System::lockFromIsr(); |
110 |
uartStartSendI(uart, FRAME_TRAILER_SIZE, getEncodeTailer()); |
111 |
|
112 |
// check whether any new transmision in the mailbox during the present tranmmision
|
113 |
msg_t msg = transmitMailbox.fetchI((msg_t *) &transmit); |
114 |
System::unlockFromIsr(); |
115 |
|
116 |
if (msg == RDY_OK) {
|
117 |
if (transmit->bluetoothDescriptorGetPayloadLength()) {
|
118 |
transmitState = BLUETOOTH_TRANSPORT_HEADER; |
119 |
} else {
|
120 |
postTransmitDescriptorI(); |
121 |
transmitState = BLUETOOTH_TRANSPORT_IDLE; |
122 |
} |
123 |
} else {
|
124 |
transmitState = BLUETOOTH_TRANSPORT_IDLE; |
125 |
} |
126 |
break;
|
127 |
} |
128 |
case BLUETOOTH_TRANSPORT_IDLE: {
|
129 |
System::lockFromIsr(); |
130 |
signalEventsI((eventmask_t) TRANSMIT_COMPLETED_EVENT); |
131 |
System::unlockFromIsr(); |
132 |
break;
|
133 |
} |
134 |
default: {
|
135 |
break;
|
136 |
} |
137 |
} |
138 |
} |
139 |
|
140 |
void BluetoothTransport::bluetoothTransportCharacterReceived_cb(UARTDriver *uart, uint16_t c) {
|
141 |
BluetoothTransport *u = (BluetoothTransport *) uart->config; |
142 |
u->bluetoothTransportCharacterReceived(c); |
143 |
} |
144 |
|
145 |
void BluetoothTransport::bluetoothTransportCharacterReceived(uint16_t c) {
|
146 |
if (c == 0xbf) { |
147 |
receiveFrameBuffer[1] = 0xbf; |
148 |
System::lockFromIsr(); |
149 |
uartStartReceiveI(uart, 3, (void *) &receiveFrameBuffer[2]); |
150 |
System::unlockFromIsr(); |
151 |
|
152 |
receiveState = BLUETOOTH_TRANSPORT_DECODE; |
153 |
if (transmitState == BLUETOOTH_TRANSPORT_PLAIN)
|
154 |
transmitState = BLUETOOTH_TRANSPORT_IDLE; |
155 |
} |
156 |
|
157 |
if (receiveState != BLUETOOTH_TRANSPORT_PLAIN)
|
158 |
return;
|
159 |
|
160 |
if (!receive) {
|
161 |
System::lockFromIsr(); |
162 |
msg_t msg = storageMailbox.fetchI((msg_t *) &receive); |
163 |
System::unlockFromIsr(); |
164 |
|
165 |
if (msg)
|
166 |
return;
|
167 |
|
168 |
receive->bluetoothDescriptorSetLinkId(0xFF);
|
169 |
rcvlength = 0;
|
170 |
} |
171 |
|
172 |
uint8_t* buffer = receive->bluetoothDescriptorGetPayload(); |
173 |
buffer[rcvlength++] = c; |
174 |
|
175 |
if (rcvlength == receive->bluetoothDescriptorGetBufferLength() || c == '\n') { |
176 |
receive->bluetoothDescriptorSetPayloadLength(rcvlength); |
177 |
postReceiveDescriptorI(); |
178 |
} |
179 |
} |
180 |
|
181 |
void BluetoothTransport::bluetoothTransportReceiveCompleted_cb(UARTDriver *uart) {
|
182 |
BluetoothTransport *u = (BluetoothTransport *) uart->config; |
183 |
u->bluetoothTransportReceiveCompleted(); |
184 |
} |
185 |
|
186 |
void BluetoothTransport::bluetoothTransportReceiveCompleted() {
|
187 |
switch (receiveState) {
|
188 |
case BLUETOOTH_TRANSPORT_HEADER: {
|
189 |
if ((uint8_t) ~receiveFrameBuffer[0] != receive->bluetoothDescriptorGetLinkId()) { |
190 |
receiveState = BLUETOOTH_TRANSPORT_IDLE; |
191 |
break;
|
192 |
} |
193 |
System::lockFromIsr(); |
194 |
uartStartReceiveI(uart, 4, (void *) &receiveFrameBuffer[1]); |
195 |
System::unlockFromIsr(); |
196 |
|
197 |
receiveState = BLUETOOTH_TRANSPORT_DECODE; |
198 |
break;
|
199 |
} |
200 |
case BLUETOOTH_TRANSPORT_DECODE: {
|
201 |
if (decodeHeader()) {
|
202 |
receiveState = BLUETOOTH_TRANSPORT_IDLE; |
203 |
break;
|
204 |
} |
205 |
receiveState = BLUETOOTH_TRANSPORT_PAYLOAD; |
206 |
/* no break */
|
207 |
} |
208 |
case BLUETOOTH_TRANSPORT_PAYLOAD: {
|
209 |
if (receive)
|
210 |
postReceiveDescriptorI(); |
211 |
|
212 |
System::lockFromIsr(); |
213 |
msg_t msg = storageMailbox.fetchI((msg_t *) &receive); |
214 |
System::unlockFromIsr(); |
215 |
|
216 |
if (msg) {
|
217 |
receiveState = BLUETOOTH_TRANSPORT_IDLE; |
218 |
break;
|
219 |
} |
220 |
|
221 |
receive->bluetoothDescriptorSetLinkId(receiveFrameBuffer[2]);
|
222 |
if (rcvlength > receive->bluetoothDescriptorGetBufferLength())
|
223 |
receive->bluetoothDescriptorSetPayloadLength(receive->bluetoothDescriptorGetBufferLength()); |
224 |
else
|
225 |
receive->bluetoothDescriptorSetPayloadLength(rcvlength); |
226 |
|
227 |
System::lockFromIsr(); |
228 |
uartStartReceiveI(uart, receive->bluetoothDescriptorGetPayloadLength(), receive->bluetoothDescriptorGetPayload()); |
229 |
System::unlockFromIsr(); |
230 |
|
231 |
rcvlength -= receive->bluetoothDescriptorGetPayloadLength(); |
232 |
|
233 |
if (!rcvlength)
|
234 |
receiveState = BLUETOOTH_TRANSPORT_TRAILER; |
235 |
|
236 |
break;
|
237 |
} |
238 |
case BLUETOOTH_TRANSPORT_TRAILER: {
|
239 |
postReceiveDescriptorI(); |
240 |
|
241 |
System::lockFromIsr(); |
242 |
uartStartReceiveI(uart, 1, (void *) &receiveFrameBuffer[0]); |
243 |
System::unlockFromIsr(); |
244 |
|
245 |
receiveState = BLUETOOTH_TRANSPORT_HEADER; |
246 |
break;
|
247 |
} |
248 |
default: {
|
249 |
break;
|
250 |
} |
251 |
} |
252 |
} |
253 |
|
254 |
/*
|
255 |
* Member functions
|
256 |
*/
|
257 |
|
258 |
void BluetoothTransport::bluetoothTransportResetState() {
|
259 |
transmitState = BLUETOOTH_TRANSPORT_PLAIN; |
260 |
receiveState = BLUETOOTH_TRANSPORT_PLAIN; |
261 |
} |
262 |
|
263 |
bool BluetoothTransport::bluetoothTransportIsMuxMode() {
|
264 |
if (receiveState == BLUETOOTH_TRANSPORT_PLAIN)
|
265 |
return false; |
266 |
|
267 |
return true; |
268 |
} |
269 |
|
270 |
chibios_rt::Mailbox* BluetoothTransport::bluetoothTransportGetStorageMailbox() { |
271 |
return &storageMailbox;
|
272 |
} |
273 |
|
274 |
chibios_rt::Mailbox* BluetoothTransport::bluetoothTransportGetTransmitMailbox() { |
275 |
return &transmitMailbox;
|
276 |
} |
277 |
|
278 |
void BluetoothTransport::bluetoothTransportSetReceiveMailbox(uint8_t linkId, chibios_rt::Mailbox* mailbox) {
|
279 |
System::lock(); |
280 |
receiveMailbox[(linkId > 9) ? 9 : linkId] = mailbox; |
281 |
System::unlock(); |
282 |
} |
283 |
|
284 |
void BluetoothTransport::postReceiveDescriptorI() {
|
285 |
uint8_t linkId = receive->bluetoothDescriptorGetLinkId(); |
286 |
linkId > 9 ? linkId = 9 : linkId; |
287 |
|
288 |
System::lockFromIsr(); |
289 |
msg_t msg = receiveMailbox[linkId]->postI((msg_t) receive); |
290 |
if (msg)
|
291 |
storageMailbox.postI((msg_t) receive); |
292 |
receive = NULL;
|
293 |
System::unlockFromIsr(); |
294 |
} |
295 |
|
296 |
void BluetoothTransport::postTransmitDescriptorI() {
|
297 |
System::lockFromIsr(); |
298 |
storageMailbox.postI((msg_t) transmit); |
299 |
transmit = NULL;
|
300 |
System::unlockFromIsr(); |
301 |
} |
302 |
|
303 |
/*
|
304 |
* The header encode/decode are in compliance with of the multiplexing mode
|
305 |
* Reference: iWRAP4 user guide Version 4.1 page 142-143
|
306 |
*/
|
307 |
uint8_t* BluetoothTransport::getEncodeHeader() { |
308 |
transmitFrameBuffer[1] = 0xbf; |
309 |
transmitFrameBuffer[2] = transmit->bluetoothDescriptorGetLinkId();
|
310 |
transmitFrameBuffer[3] = (transmit->bluetoothDescriptorGetPayloadLength() >> 8) & 0x3; |
311 |
transmitFrameBuffer[4] = transmit->bluetoothDescriptorGetPayloadLength() & 0xFF; |
312 |
return &transmitFrameBuffer[1]; |
313 |
} |
314 |
|
315 |
uint8_t* BluetoothTransport::getEncodeTailer() { |
316 |
transmitFrameBuffer[0] = ~transmitFrameBuffer[2]; |
317 |
return &transmitFrameBuffer[0]; |
318 |
} |
319 |
|
320 |
int BluetoothTransport::decodeHeader() {
|
321 |
if ((receiveFrameBuffer[1] != 0xbf) || |
322 |
((receiveFrameBuffer[2] > 8) && (receiveFrameBuffer[2] != 0xFF))) |
323 |
return -1; |
324 |
|
325 |
rcvlength = (receiveFrameBuffer[3] << 8) | receiveFrameBuffer[4]; |
326 |
if (rcvlength > 1023) |
327 |
return -1; |
328 |
|
329 |
return RDY_OK;
|
330 |
} |