A simple program that uses the UARTService to transfer string data over GATT. Can be used with the nRF Toolbox app for rapid prototyping.
Dependencies: BLE_API mbed nRF51822
Fork of UART_TEMPLATE by
main.cpp@1:32c6991f7180, 2017-06-21 (annotated)
- Committer:
- VicenteFerrara
- Date:
- Wed Jun 21 01:33:50 2017 +0000
- Revision:
- 1:32c6991f7180
- Parent:
- 0:442c7a6f1978
Leer caracter?stica y responder en base a ello
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Daniel Veilleux |
0:442c7a6f1978 | 1 | /* mbed Microcontroller Library |
Daniel Veilleux |
0:442c7a6f1978 | 2 | * Copyright (c) 2006-2013 ARM Limited |
Daniel Veilleux |
0:442c7a6f1978 | 3 | * |
Daniel Veilleux |
0:442c7a6f1978 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
Daniel Veilleux |
0:442c7a6f1978 | 5 | * you may not use this file except in compliance with the License. |
Daniel Veilleux |
0:442c7a6f1978 | 6 | * You may obtain a copy of the License at |
Daniel Veilleux |
0:442c7a6f1978 | 7 | * |
Daniel Veilleux |
0:442c7a6f1978 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
Daniel Veilleux |
0:442c7a6f1978 | 9 | * |
Daniel Veilleux |
0:442c7a6f1978 | 10 | * Unless required by applicable law or agreed to in writing, software |
Daniel Veilleux |
0:442c7a6f1978 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
Daniel Veilleux |
0:442c7a6f1978 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
Daniel Veilleux |
0:442c7a6f1978 | 13 | * See the License for the specific language governing permissions and |
Daniel Veilleux |
0:442c7a6f1978 | 14 | * limitations under the License. |
Daniel Veilleux |
0:442c7a6f1978 | 15 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 16 | |
Daniel Veilleux |
0:442c7a6f1978 | 17 | #include "mbed.h" |
Daniel Veilleux |
0:442c7a6f1978 | 18 | #include "BLEDevice.h" |
Daniel Veilleux |
0:442c7a6f1978 | 19 | #include "UARTService.h" |
Daniel Veilleux |
0:442c7a6f1978 | 20 | #include "nrf_temp.h" |
Daniel Veilleux |
0:442c7a6f1978 | 21 | |
Daniel Veilleux |
0:442c7a6f1978 | 22 | #define MAX_REPLY_LEN (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN) |
Daniel Veilleux |
0:442c7a6f1978 | 23 | #define SENSOR_READ_INTERVAL_S (0.5F) |
Daniel Veilleux |
0:442c7a6f1978 | 24 | #define ADV_INTERVAL_MS (1000UL) |
Daniel Veilleux |
0:442c7a6f1978 | 25 | #define UART_BAUD_RATE (19200UL) |
VicenteFerrara | 1:32c6991f7180 | 26 | #define DEVICE_NAME ("EVA") // This can be read AFTER connecting to the device. |
VicenteFerrara | 1:32c6991f7180 | 27 | #define SHORT_NAME ("EVA") // Keep this short: max 8 chars if a 128bit UUID is also advertised. |
Daniel Veilleux |
0:442c7a6f1978 | 28 | |
Daniel Veilleux |
0:442c7a6f1978 | 29 | #define DEBUG(...) { m_serial_port.printf(__VA_ARGS__); } |
Daniel Veilleux |
0:442c7a6f1978 | 30 | |
VicenteFerrara | 1:32c6991f7180 | 31 | //static const char DEVICE_NAME[] = "EVA"; |
Daniel Veilleux |
0:442c7a6f1978 | 32 | |
Daniel Veilleux |
0:442c7a6f1978 | 33 | BLEDevice m_ble; |
Daniel Veilleux |
0:442c7a6f1978 | 34 | Serial m_serial_port(p9, p11); // TX pin, RX pin |
VicenteFerrara | 1:32c6991f7180 | 35 | Serial pc(USBTX, USBRX); // tx, rx |
VicenteFerrara | 1:32c6991f7180 | 36 | DigitalOut led1(LED1); |
Daniel Veilleux |
0:442c7a6f1978 | 37 | AnalogIn m_analog_in(p1); |
Daniel Veilleux |
0:442c7a6f1978 | 38 | uint16_t m_analog_in_value; |
Daniel Veilleux |
0:442c7a6f1978 | 39 | UARTService *m_uart_service_ptr; |
Daniel Veilleux |
0:442c7a6f1978 | 40 | |
Daniel Veilleux |
0:442c7a6f1978 | 41 | |
Daniel Veilleux |
0:442c7a6f1978 | 42 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 43 | * This callback is used whenever a disconnection occurs. |
Daniel Veilleux |
0:442c7a6f1978 | 44 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 45 | void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) |
Daniel Veilleux |
0:442c7a6f1978 | 46 | { |
Daniel Veilleux |
0:442c7a6f1978 | 47 | switch (reason) { |
Daniel Veilleux |
0:442c7a6f1978 | 48 | case Gap::REMOTE_USER_TERMINATED_CONNECTION: |
Daniel Veilleux |
0:442c7a6f1978 | 49 | DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 50 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 51 | case Gap::LOCAL_HOST_TERMINATED_CONNECTION: |
Daniel Veilleux |
0:442c7a6f1978 | 52 | DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 53 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 54 | case Gap::CONN_INTERVAL_UNACCEPTABLE: |
Daniel Veilleux |
0:442c7a6f1978 | 55 | DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 56 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 57 | } |
Daniel Veilleux |
0:442c7a6f1978 | 58 | |
Daniel Veilleux |
0:442c7a6f1978 | 59 | DEBUG("Restarting the advertising process\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 60 | m_ble.startAdvertising(); |
Daniel Veilleux |
0:442c7a6f1978 | 61 | } |
Daniel Veilleux |
0:442c7a6f1978 | 62 | |
Daniel Veilleux |
0:442c7a6f1978 | 63 | |
Daniel Veilleux |
0:442c7a6f1978 | 64 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 65 | * This callback is used whenever the host writes data to one of our GATT characteristics. |
Daniel Veilleux |
0:442c7a6f1978 | 66 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 67 | void dataWrittenCallback(const GattCharacteristicWriteCBParams *params) |
Daniel Veilleux |
0:442c7a6f1978 | 68 | { |
Daniel Veilleux |
0:442c7a6f1978 | 69 | // Ensure that initialization is finished and the host has written to the TX characteristic. |
Daniel Veilleux |
0:442c7a6f1978 | 70 | if ((m_uart_service_ptr != NULL) && (params->charHandle == m_uart_service_ptr->getTXCharacteristicHandle())) { |
Daniel Veilleux |
0:442c7a6f1978 | 71 | uint8_t buf[MAX_REPLY_LEN]; |
VicenteFerrara | 1:32c6991f7180 | 72 | uint8_t buf2[3]= {0xFF, 0x01, 0x02}; |
Daniel Veilleux |
0:442c7a6f1978 | 73 | uint32_t len = 0; |
VicenteFerrara | 1:32c6991f7180 | 74 | |
Daniel Veilleux |
0:442c7a6f1978 | 75 | if (1 == params->len) { |
Daniel Veilleux |
0:442c7a6f1978 | 76 | switch (params->data[0]) { |
Daniel Veilleux |
0:442c7a6f1978 | 77 | case '0': |
Daniel Veilleux |
0:442c7a6f1978 | 78 | len = snprintf((char*) buf, MAX_REPLY_LEN, "OK"); |
VicenteFerrara | 1:32c6991f7180 | 79 | pc.printf("Si llego prro\n"); |
Daniel Veilleux |
0:442c7a6f1978 | 80 | break; |
VicenteFerrara | 1:32c6991f7180 | 81 | case 1: |
VicenteFerrara | 1:32c6991f7180 | 82 | led1 = 1; |
VicenteFerrara | 1:32c6991f7180 | 83 | wait(1.0); |
VicenteFerrara | 1:32c6991f7180 | 84 | led1 = 0; |
VicenteFerrara | 1:32c6991f7180 | 85 | wait(1.0); |
VicenteFerrara | 1:32c6991f7180 | 86 | led1 = 1; |
VicenteFerrara | 1:32c6991f7180 | 87 | wait(1.0); |
VicenteFerrara | 1:32c6991f7180 | 88 | led1 = 0; |
VicenteFerrara | 1:32c6991f7180 | 89 | len = snprintf((char*) buf, MAX_REPLY_LEN, "prrow"); |
Daniel Veilleux |
0:442c7a6f1978 | 90 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 91 | case 'a': |
Daniel Veilleux |
0:442c7a6f1978 | 92 | len = snprintf((char*) buf, MAX_REPLY_LEN, "%d", m_analog_in_value); |
Daniel Veilleux |
0:442c7a6f1978 | 93 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 94 | default: |
Daniel Veilleux |
0:442c7a6f1978 | 95 | len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Unknown char"); |
Daniel Veilleux |
0:442c7a6f1978 | 96 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 97 | } |
Daniel Veilleux |
0:442c7a6f1978 | 98 | } |
Daniel Veilleux |
0:442c7a6f1978 | 99 | else |
Daniel Veilleux |
0:442c7a6f1978 | 100 | { |
Daniel Veilleux |
0:442c7a6f1978 | 101 | len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Invalid len"); |
Daniel Veilleux |
0:442c7a6f1978 | 102 | } |
VicenteFerrara | 1:32c6991f7180 | 103 | //m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len); |
VicenteFerrara | 1:32c6991f7180 | 104 | m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf2, 3); |
Daniel Veilleux |
0:442c7a6f1978 | 105 | |
Daniel Veilleux |
0:442c7a6f1978 | 106 | DEBUG("%d bytes received from host\n\r", params->len); |
Daniel Veilleux |
0:442c7a6f1978 | 107 | } |
Daniel Veilleux |
0:442c7a6f1978 | 108 | } |
Daniel Veilleux |
0:442c7a6f1978 | 109 | |
Daniel Veilleux |
0:442c7a6f1978 | 110 | |
Daniel Veilleux |
0:442c7a6f1978 | 111 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 112 | * This callback is used whenever a write to a GATT characteristic causes data to be sent to the host. |
Daniel Veilleux |
0:442c7a6f1978 | 113 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 114 | void dataSentCallback(unsigned count) |
Daniel Veilleux |
0:442c7a6f1978 | 115 | { |
Daniel Veilleux |
0:442c7a6f1978 | 116 | // NOTE: The count always seems to be 1 regardless of data. |
Daniel Veilleux |
0:442c7a6f1978 | 117 | DEBUG("%d bytes sent to host\n\r", count); |
Daniel Veilleux |
0:442c7a6f1978 | 118 | } |
Daniel Veilleux |
0:442c7a6f1978 | 119 | |
Daniel Veilleux |
0:442c7a6f1978 | 120 | |
Daniel Veilleux |
0:442c7a6f1978 | 121 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 122 | * This callback is scheduled to be called periodically via a low-priority interrupt. |
Daniel Veilleux |
0:442c7a6f1978 | 123 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 124 | void periodicCallback(void) |
Daniel Veilleux |
0:442c7a6f1978 | 125 | { |
Daniel Veilleux |
0:442c7a6f1978 | 126 | m_analog_in_value = m_analog_in.read_u16(); |
Daniel Veilleux |
0:442c7a6f1978 | 127 | } |
Daniel Veilleux |
0:442c7a6f1978 | 128 | |
Daniel Veilleux |
0:442c7a6f1978 | 129 | |
Daniel Veilleux |
0:442c7a6f1978 | 130 | void error(ble_error_t err, uint32_t line) |
Daniel Veilleux |
0:442c7a6f1978 | 131 | { |
VicenteFerrara | 1:32c6991f7180 | 132 | //m_error_led = 1; |
Daniel Veilleux |
0:442c7a6f1978 | 133 | DEBUG("Error %d on line number %d\n\r", err, line); |
Daniel Veilleux |
0:442c7a6f1978 | 134 | } |
Daniel Veilleux |
0:442c7a6f1978 | 135 | |
Daniel Veilleux |
0:442c7a6f1978 | 136 | |
Daniel Veilleux |
0:442c7a6f1978 | 137 | int main(void) |
Daniel Veilleux |
0:442c7a6f1978 | 138 | { |
Daniel Veilleux |
0:442c7a6f1978 | 139 | ble_error_t err; |
Daniel Veilleux |
0:442c7a6f1978 | 140 | Ticker ticker; |
Daniel Veilleux |
0:442c7a6f1978 | 141 | |
Daniel Veilleux |
0:442c7a6f1978 | 142 | m_serial_port.baud(UART_BAUD_RATE); |
Daniel Veilleux |
0:442c7a6f1978 | 143 | |
Daniel Veilleux |
0:442c7a6f1978 | 144 | DEBUG("Initialising\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 145 | |
VicenteFerrara | 1:32c6991f7180 | 146 | led1 = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 147 | m_analog_in_value = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 148 | |
Daniel Veilleux |
0:442c7a6f1978 | 149 | ticker.attach(periodicCallback, SENSOR_READ_INTERVAL_S); |
Daniel Veilleux |
0:442c7a6f1978 | 150 | |
Daniel Veilleux |
0:442c7a6f1978 | 151 | m_ble.init(); |
Daniel Veilleux |
0:442c7a6f1978 | 152 | m_ble.onDisconnection(disconnectionCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 153 | m_ble.onDataWritten(dataWrittenCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 154 | m_ble.onDataSent(dataSentCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 155 | |
Daniel Veilleux |
0:442c7a6f1978 | 156 | // Set the TX power in dBm units. |
Daniel Veilleux |
0:442c7a6f1978 | 157 | // Possible values (in decreasing order): 4, 0, -4, -8, -12, -16, -20. |
Daniel Veilleux |
0:442c7a6f1978 | 158 | err = m_ble.setTxPower(4); |
Daniel Veilleux |
0:442c7a6f1978 | 159 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 160 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 161 | } |
Daniel Veilleux |
0:442c7a6f1978 | 162 | |
Daniel Veilleux |
0:442c7a6f1978 | 163 | // Setup advertising (GAP stuff). |
Daniel Veilleux |
0:442c7a6f1978 | 164 | err = m_ble.setDeviceName(DEVICE_NAME); |
Daniel Veilleux |
0:442c7a6f1978 | 165 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 166 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 167 | } |
Daniel Veilleux |
0:442c7a6f1978 | 168 | |
Daniel Veilleux |
0:442c7a6f1978 | 169 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
Daniel Veilleux |
0:442c7a6f1978 | 170 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 171 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 172 | } |
Daniel Veilleux |
0:442c7a6f1978 | 173 | |
Daniel Veilleux |
0:442c7a6f1978 | 174 | m_ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
Daniel Veilleux |
0:442c7a6f1978 | 175 | |
Daniel Veilleux |
0:442c7a6f1978 | 176 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
Daniel Veilleux |
0:442c7a6f1978 | 177 | (const uint8_t *)SHORT_NAME, |
Daniel Veilleux |
0:442c7a6f1978 | 178 | (sizeof(SHORT_NAME) - 1)); |
Daniel Veilleux |
0:442c7a6f1978 | 179 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 180 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 181 | } |
Daniel Veilleux |
0:442c7a6f1978 | 182 | |
Daniel Veilleux |
0:442c7a6f1978 | 183 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
Daniel Veilleux |
0:442c7a6f1978 | 184 | (const uint8_t *)UARTServiceUUID_reversed, |
Daniel Veilleux |
0:442c7a6f1978 | 185 | sizeof(UARTServiceUUID_reversed)); |
Daniel Veilleux |
0:442c7a6f1978 | 186 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 187 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 188 | } |
Daniel Veilleux |
0:442c7a6f1978 | 189 | |
Daniel Veilleux |
0:442c7a6f1978 | 190 | m_ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADV_INTERVAL_MS)); |
Daniel Veilleux |
0:442c7a6f1978 | 191 | m_ble.startAdvertising(); |
Daniel Veilleux |
0:442c7a6f1978 | 192 | |
Daniel Veilleux |
0:442c7a6f1978 | 193 | // Create a UARTService object (GATT stuff). |
Daniel Veilleux |
0:442c7a6f1978 | 194 | UARTService uartService(m_ble); |
Daniel Veilleux |
0:442c7a6f1978 | 195 | m_uart_service_ptr = &uartService; |
Daniel Veilleux |
0:442c7a6f1978 | 196 | |
Daniel Veilleux |
0:442c7a6f1978 | 197 | while (true) { |
Daniel Veilleux |
0:442c7a6f1978 | 198 | m_ble.waitForEvent(); |
Daniel Veilleux |
0:442c7a6f1978 | 199 | } |
Daniel Veilleux |
0:442c7a6f1978 | 200 | } |