Exercise 6 BLE UART
Dependencies: BLE_API X_NUCLEO_IDB0XA1 mbed
Fork of BLE_UART_IDB0XA1 by
main.cpp@7:8490fe113598, 2017-04-25 (annotated)
- Committer:
- waby38
- Date:
- Tue Apr 25 15:26:50 2017 +0000
- Revision:
- 7:8490fe113598
- Parent:
- 3:e0efdb741bd4
- Child:
- 8:60033323cbcb
UART BLE implementation on X-NUCLEO-IDB0XA1
; Device is bounded when LED2 is blinking
; Com RX/TX on STLINK COM @ 9600 baud
; Android phone, can use nRF UART/UART-BLE/AppInventor UART-BLE
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
apalmieri | 0:aae2d6c2a9eb | 1 | /* mbed Microcontroller Library |
apalmieri | 0:aae2d6c2a9eb | 2 | * Copyright (c) 2006-2013 ARM Limited |
apalmieri | 0:aae2d6c2a9eb | 3 | * |
apalmieri | 0:aae2d6c2a9eb | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
apalmieri | 0:aae2d6c2a9eb | 5 | * you may not use this file except in compliance with the License. |
apalmieri | 0:aae2d6c2a9eb | 6 | * You may obtain a copy of the License at |
apalmieri | 0:aae2d6c2a9eb | 7 | * |
apalmieri | 0:aae2d6c2a9eb | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
apalmieri | 0:aae2d6c2a9eb | 9 | * |
apalmieri | 0:aae2d6c2a9eb | 10 | * Unless required by applicable law or agreed to in writing, software |
apalmieri | 0:aae2d6c2a9eb | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
apalmieri | 0:aae2d6c2a9eb | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
apalmieri | 0:aae2d6c2a9eb | 13 | * See the License for the specific language governing permissions and |
apalmieri | 0:aae2d6c2a9eb | 14 | * limitations under the License. |
apalmieri | 0:aae2d6c2a9eb | 15 | */ |
apalmieri | 0:aae2d6c2a9eb | 16 | |
apalmieri | 0:aae2d6c2a9eb | 17 | #include "mbed.h" |
apalmieri | 0:aae2d6c2a9eb | 18 | #include "ble/BLE.h" |
waby38 | 7:8490fe113598 | 19 | #include "ble/services/UARTService.h" |
waby38 | 7:8490fe113598 | 20 | #include "Serial.h" |
waby38 | 7:8490fe113598 | 21 | |
waby38 | 7:8490fe113598 | 22 | #define UART_BUFFER (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN*10) |
apalmieri | 0:aae2d6c2a9eb | 23 | |
waby38 | 7:8490fe113598 | 24 | const static char DEVICE_NAME[] = "UART"; |
waby38 | 7:8490fe113598 | 25 | UARTService *uartServicePtr; |
waby38 | 7:8490fe113598 | 26 | static uint8_t uartBuff[UART_BUFFER]; |
waby38 | 7:8490fe113598 | 27 | static uint8_t uartBuffPos=0; |
apalmieri | 0:aae2d6c2a9eb | 28 | |
waby38 | 7:8490fe113598 | 29 | void onBleError(ble_error_t error); |
waby38 | 7:8490fe113598 | 30 | |
waby38 | 7:8490fe113598 | 31 | DigitalOut led1(LED1); |
waby38 | 7:8490fe113598 | 32 | Serial uart1(USBTX,USBRX); |
waby38 | 7:8490fe113598 | 33 | Ticker ticker; |
apalmieri | 0:aae2d6c2a9eb | 34 | |
waby38 | 7:8490fe113598 | 35 | #define DEBUG uart1.printf |
waby38 | 7:8490fe113598 | 36 | |
waby38 | 7:8490fe113598 | 37 | /* Ticker */ |
waby38 | 7:8490fe113598 | 38 | void periodicCallback(void) |
apalmieri | 0:aae2d6c2a9eb | 39 | { |
waby38 | 7:8490fe113598 | 40 | led1 = !led1; |
apalmieri | 0:aae2d6c2a9eb | 41 | } |
apalmieri | 0:aae2d6c2a9eb | 42 | |
waby38 | 7:8490fe113598 | 43 | /* UART */ |
waby38 | 7:8490fe113598 | 44 | void uartRx(void) |
waby38 | 7:8490fe113598 | 45 | { |
waby38 | 7:8490fe113598 | 46 | if(uart1.readable()){ |
waby38 | 7:8490fe113598 | 47 | uartBuff[uartBuffPos] = uart1.getc(); |
waby38 | 7:8490fe113598 | 48 | if((uartBuff[uartBuffPos] == '\r') || (uartBuff[uartBuffPos] == '\n') || (uartBuffPos >= UART_BUFFER)) { |
waby38 | 7:8490fe113598 | 49 | uartBuff[uartBuffPos] = '\0'; |
waby38 | 7:8490fe113598 | 50 | /* We are sending the whole string even if less than BLE_UART_SERVICE_MAX_DATA_LEN otherwise we need to wait */ |
waby38 | 7:8490fe113598 | 51 | uartServicePtr->write(uartBuff, (uartBuffPos/UARTService::BLE_UART_SERVICE_MAX_DATA_LEN +1) * UARTService::BLE_UART_SERVICE_MAX_DATA_LEN); |
waby38 | 7:8490fe113598 | 52 | DEBUG("TX : %s\r\n", uartBuff); |
waby38 | 7:8490fe113598 | 53 | memset(uartBuff, 0, UART_BUFFER); |
waby38 | 7:8490fe113598 | 54 | uartBuffPos = 0; |
waby38 | 7:8490fe113598 | 55 | } |
waby38 | 7:8490fe113598 | 56 | else |
waby38 | 7:8490fe113598 | 57 | uartBuffPos++; |
apalmieri | 0:aae2d6c2a9eb | 58 | } |
apalmieri | 0:aae2d6c2a9eb | 59 | } |
apalmieri | 0:aae2d6c2a9eb | 60 | |
waby38 | 7:8490fe113598 | 61 | |
waby38 | 7:8490fe113598 | 62 | /* BLE */ |
waby38 | 7:8490fe113598 | 63 | void BleConnectionCallback(const Gap::ConnectionCallbackParams_t *params) { |
waby38 | 7:8490fe113598 | 64 | DEBUG("BLE Client Connected!\n\r"); |
waby38 | 7:8490fe113598 | 65 | DEBUG("Please type a string and press return\r\n"); |
waby38 | 7:8490fe113598 | 66 | |
waby38 | 7:8490fe113598 | 67 | ticker.attach(periodicCallback, 1); |
waby38 | 7:8490fe113598 | 68 | } |
waby38 | 7:8490fe113598 | 69 | |
waby38 | 7:8490fe113598 | 70 | void BleDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) |
waby38 | 7:8490fe113598 | 71 | { |
waby38 | 7:8490fe113598 | 72 | (void)params; |
waby38 | 7:8490fe113598 | 73 | DEBUG("BLE Client Disconnected!\r\n"); |
waby38 | 7:8490fe113598 | 74 | ticker.detach(); |
waby38 | 7:8490fe113598 | 75 | BLE::Instance().gap().startAdvertising(); // restart advertising |
waby38 | 7:8490fe113598 | 76 | led1=0; |
waby38 | 7:8490fe113598 | 77 | } |
waby38 | 7:8490fe113598 | 78 | |
waby38 | 7:8490fe113598 | 79 | void BleOnDataWrittenCallback(const GattWriteCallbackParams *params) { |
waby38 | 7:8490fe113598 | 80 | if (params->handle == uartServicePtr->getTXCharacteristicHandle()){ |
waby38 | 7:8490fe113598 | 81 | DEBUG("RX: %s\r\n", params->data); |
waby38 | 7:8490fe113598 | 82 | } |
waby38 | 7:8490fe113598 | 83 | } |
waby38 | 7:8490fe113598 | 84 | |
waby38 | 7:8490fe113598 | 85 | void onBleError(ble_error_t error) { |
waby38 | 7:8490fe113598 | 86 | DEBUG("BLE Error: %d\r\n"); |
waby38 | 7:8490fe113598 | 87 | /* Handle error now */ |
apalmieri | 0:aae2d6c2a9eb | 88 | } |
apalmieri | 0:aae2d6c2a9eb | 89 | |
apalmieri | 0:aae2d6c2a9eb | 90 | void bleInitComplete(BLE::InitializationCompleteCallbackContext *params) |
apalmieri | 0:aae2d6c2a9eb | 91 | { |
apalmieri | 0:aae2d6c2a9eb | 92 | BLE& ble = params->ble; |
apalmieri | 0:aae2d6c2a9eb | 93 | ble_error_t error = params->error; |
apalmieri | 0:aae2d6c2a9eb | 94 | |
apalmieri | 0:aae2d6c2a9eb | 95 | if (error != BLE_ERROR_NONE) { |
apalmieri | 0:aae2d6c2a9eb | 96 | /* In case of error, forward the error handling to onBleInitError */ |
waby38 | 7:8490fe113598 | 97 | onBleError(error); |
apalmieri | 0:aae2d6c2a9eb | 98 | return; |
apalmieri | 0:aae2d6c2a9eb | 99 | } |
apalmieri | 0:aae2d6c2a9eb | 100 | |
apalmieri | 0:aae2d6c2a9eb | 101 | /* Ensure that it is the default instance of BLE */ |
apalmieri | 0:aae2d6c2a9eb | 102 | if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { |
apalmieri | 0:aae2d6c2a9eb | 103 | return; |
apalmieri | 0:aae2d6c2a9eb | 104 | } |
apalmieri | 0:aae2d6c2a9eb | 105 | |
waby38 | 7:8490fe113598 | 106 | ble.gap().onConnection(BleConnectionCallback); |
waby38 | 7:8490fe113598 | 107 | ble.gap().onDisconnection(BleDisconnectionCallback); |
waby38 | 7:8490fe113598 | 108 | ble.gattServer().onDataWritten(BleOnDataWrittenCallback); |
apalmieri | 0:aae2d6c2a9eb | 109 | |
waby38 | 7:8490fe113598 | 110 | DEBUG("BLE UARTService: "); |
waby38 | 7:8490fe113598 | 111 | /* Setup primary service. */ |
waby38 | 7:8490fe113598 | 112 | UARTService uartService(ble); |
waby38 | 7:8490fe113598 | 113 | uartServicePtr = &uartService; |
waby38 | 7:8490fe113598 | 114 | DEBUG("Started\r\n"); |
apalmieri | 0:aae2d6c2a9eb | 115 | |
apalmieri | 0:aae2d6c2a9eb | 116 | /* setup advertising */ |
apalmieri | 0:aae2d6c2a9eb | 117 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); |
waby38 | 7:8490fe113598 | 118 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed)); |
apalmieri | 0:aae2d6c2a9eb | 119 | ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); |
apalmieri | 0:aae2d6c2a9eb | 120 | ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
waby38 | 7:8490fe113598 | 121 | ble.gap().setAdvertisingInterval(500); /* 500ms. */ |
apalmieri | 0:aae2d6c2a9eb | 122 | ble.gap().startAdvertising(); |
apalmieri | 0:aae2d6c2a9eb | 123 | |
apalmieri | 0:aae2d6c2a9eb | 124 | while (true) { |
apalmieri | 0:aae2d6c2a9eb | 125 | ble.waitForEvent(); |
apalmieri | 0:aae2d6c2a9eb | 126 | } |
apalmieri | 0:aae2d6c2a9eb | 127 | } |
apalmieri | 0:aae2d6c2a9eb | 128 | |
apalmieri | 0:aae2d6c2a9eb | 129 | int main(void) |
apalmieri | 0:aae2d6c2a9eb | 130 | { |
waby38 | 7:8490fe113598 | 131 | led1=0; |
waby38 | 7:8490fe113598 | 132 | |
waby38 | 7:8490fe113598 | 133 | uart1.baud(9600); |
waby38 | 7:8490fe113598 | 134 | uart1.attach(uartRx,Serial::RxIrq); |
apalmieri | 0:aae2d6c2a9eb | 135 | BLE &ble = BLE::Instance(); |
apalmieri | 0:aae2d6c2a9eb | 136 | ble.init(bleInitComplete); |
apalmieri | 0:aae2d6c2a9eb | 137 | } |
apalmieri | 0:aae2d6c2a9eb | 138 |