Statistics
| Branch: | Tag: | Revision:

amiro-os / components / bluetooth / bluetooth-transport.cpp @ 8c99e03a

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
}