amiro-os / components / bluetooth / bluetooth-transport.cpp @ 4d54a507
History | View | Annotate | Download (9.391 KB)
1 | 58fe0e0b | Thomas Schöpping | #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 | } |