amiro-os / components / bluetooth / bluetooth-transport.cpp @ 12463563
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 | } |