f
Dependencies: BLE_API mbed nRF51822
Fork of UART_TEMPLATE by
main.cpp@0:442c7a6f1978, 2014-12-15 (annotated)
- Committer:
- Daniel Veilleux
- Date:
- Mon Dec 15 21:05:18 2014 -0800
- Revision:
- 0:442c7a6f1978
- Child:
- 1:94e2d9e7b447
Initial commit.
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) |
Daniel Veilleux |
0:442c7a6f1978 | 26 | #define DEVICE_NAME ("DEMO SENSOR") // This can be read AFTER connecting to the device. |
Daniel Veilleux |
0:442c7a6f1978 | 27 | #define SHORT_NAME ("HACKDEMO") // 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 | |
Daniel Veilleux |
0:442c7a6f1978 | 31 | |
Daniel Veilleux |
0:442c7a6f1978 | 32 | BLEDevice m_ble; |
Daniel Veilleux |
0:442c7a6f1978 | 33 | Serial m_serial_port(p9, p11); // TX pin, RX pin |
Daniel Veilleux |
0:442c7a6f1978 | 34 | DigitalOut m_cmd_led(LED1); |
Daniel Veilleux |
0:442c7a6f1978 | 35 | DigitalOut m_error_led(LED2); |
Daniel Veilleux |
0:442c7a6f1978 | 36 | AnalogIn m_analog_in(p1); |
Daniel Veilleux |
0:442c7a6f1978 | 37 | uint16_t m_analog_in_value; |
Daniel Veilleux |
0:442c7a6f1978 | 38 | UARTService *m_uart_service_ptr; |
Daniel Veilleux |
0:442c7a6f1978 | 39 | |
Daniel Veilleux |
0:442c7a6f1978 | 40 | |
Daniel Veilleux |
0:442c7a6f1978 | 41 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 42 | * This callback is used whenever a disconnection occurs. |
Daniel Veilleux |
0:442c7a6f1978 | 43 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 44 | void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) |
Daniel Veilleux |
0:442c7a6f1978 | 45 | { |
Daniel Veilleux |
0:442c7a6f1978 | 46 | switch (reason) { |
Daniel Veilleux |
0:442c7a6f1978 | 47 | case Gap::REMOTE_USER_TERMINATED_CONNECTION: |
Daniel Veilleux |
0:442c7a6f1978 | 48 | DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 49 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 50 | case Gap::LOCAL_HOST_TERMINATED_CONNECTION: |
Daniel Veilleux |
0:442c7a6f1978 | 51 | DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 52 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 53 | case Gap::CONN_INTERVAL_UNACCEPTABLE: |
Daniel Veilleux |
0:442c7a6f1978 | 54 | DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 55 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 56 | } |
Daniel Veilleux |
0:442c7a6f1978 | 57 | |
Daniel Veilleux |
0:442c7a6f1978 | 58 | DEBUG("Restarting the advertising process\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 59 | m_ble.startAdvertising(); |
Daniel Veilleux |
0:442c7a6f1978 | 60 | } |
Daniel Veilleux |
0:442c7a6f1978 | 61 | |
Daniel Veilleux |
0:442c7a6f1978 | 62 | |
Daniel Veilleux |
0:442c7a6f1978 | 63 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 64 | * This callback is used whenever the host writes data to one of our GATT characteristics. |
Daniel Veilleux |
0:442c7a6f1978 | 65 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 66 | void dataWrittenCallback(const GattCharacteristicWriteCBParams *params) |
Daniel Veilleux |
0:442c7a6f1978 | 67 | { |
Daniel Veilleux |
0:442c7a6f1978 | 68 | // Ensure that initialization is finished and the host has written to the TX characteristic. |
Daniel Veilleux |
0:442c7a6f1978 | 69 | if ((m_uart_service_ptr != NULL) && (params->charHandle == m_uart_service_ptr->getTXCharacteristicHandle())) { |
Daniel Veilleux |
0:442c7a6f1978 | 70 | uint8_t buf[MAX_REPLY_LEN]; |
Daniel Veilleux |
0:442c7a6f1978 | 71 | uint32_t len = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 72 | |
Daniel Veilleux |
0:442c7a6f1978 | 73 | if (1 == params->len) { |
Daniel Veilleux |
0:442c7a6f1978 | 74 | switch (params->data[0]) { |
Daniel Veilleux |
0:442c7a6f1978 | 75 | case '0': |
Daniel Veilleux |
0:442c7a6f1978 | 76 | m_cmd_led = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 77 | len = snprintf((char*) buf, MAX_REPLY_LEN, "OK"); |
Daniel Veilleux |
0:442c7a6f1978 | 78 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 79 | case '1': |
Daniel Veilleux |
0:442c7a6f1978 | 80 | m_cmd_led = 1; |
Daniel Veilleux |
0:442c7a6f1978 | 81 | len = snprintf((char*) buf, MAX_REPLY_LEN, "OK"); |
Daniel Veilleux |
0:442c7a6f1978 | 82 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 83 | case 'a': |
Daniel Veilleux |
0:442c7a6f1978 | 84 | len = snprintf((char*) buf, MAX_REPLY_LEN, "%d", m_analog_in_value); |
Daniel Veilleux |
0:442c7a6f1978 | 85 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 86 | default: |
Daniel Veilleux |
0:442c7a6f1978 | 87 | len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Unknown char"); |
Daniel Veilleux |
0:442c7a6f1978 | 88 | break; |
Daniel Veilleux |
0:442c7a6f1978 | 89 | } |
Daniel Veilleux |
0:442c7a6f1978 | 90 | } |
Daniel Veilleux |
0:442c7a6f1978 | 91 | else |
Daniel Veilleux |
0:442c7a6f1978 | 92 | { |
Daniel Veilleux |
0:442c7a6f1978 | 93 | len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Invalid len"); |
Daniel Veilleux |
0:442c7a6f1978 | 94 | } |
Daniel Veilleux |
0:442c7a6f1978 | 95 | |
Daniel Veilleux |
0:442c7a6f1978 | 96 | m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len); |
Daniel Veilleux |
0:442c7a6f1978 | 97 | |
Daniel Veilleux |
0:442c7a6f1978 | 98 | DEBUG("%d bytes received from host\n\r", params->len); |
Daniel Veilleux |
0:442c7a6f1978 | 99 | } |
Daniel Veilleux |
0:442c7a6f1978 | 100 | } |
Daniel Veilleux |
0:442c7a6f1978 | 101 | |
Daniel Veilleux |
0:442c7a6f1978 | 102 | |
Daniel Veilleux |
0:442c7a6f1978 | 103 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 104 | * This callback is used whenever a write to a GATT characteristic causes data to be sent to the host. |
Daniel Veilleux |
0:442c7a6f1978 | 105 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 106 | void dataSentCallback(unsigned count) |
Daniel Veilleux |
0:442c7a6f1978 | 107 | { |
Daniel Veilleux |
0:442c7a6f1978 | 108 | // NOTE: The count always seems to be 1 regardless of data. |
Daniel Veilleux |
0:442c7a6f1978 | 109 | DEBUG("%d bytes sent to host\n\r", count); |
Daniel Veilleux |
0:442c7a6f1978 | 110 | } |
Daniel Veilleux |
0:442c7a6f1978 | 111 | |
Daniel Veilleux |
0:442c7a6f1978 | 112 | |
Daniel Veilleux |
0:442c7a6f1978 | 113 | /** |
Daniel Veilleux |
0:442c7a6f1978 | 114 | * This callback is scheduled to be called periodically via a low-priority interrupt. |
Daniel Veilleux |
0:442c7a6f1978 | 115 | */ |
Daniel Veilleux |
0:442c7a6f1978 | 116 | void periodicCallback(void) |
Daniel Veilleux |
0:442c7a6f1978 | 117 | { |
Daniel Veilleux |
0:442c7a6f1978 | 118 | m_analog_in_value = m_analog_in.read_u16(); |
Daniel Veilleux |
0:442c7a6f1978 | 119 | } |
Daniel Veilleux |
0:442c7a6f1978 | 120 | |
Daniel Veilleux |
0:442c7a6f1978 | 121 | |
Daniel Veilleux |
0:442c7a6f1978 | 122 | void error(ble_error_t err, uint32_t line) |
Daniel Veilleux |
0:442c7a6f1978 | 123 | { |
Daniel Veilleux |
0:442c7a6f1978 | 124 | m_error_led = 1; |
Daniel Veilleux |
0:442c7a6f1978 | 125 | DEBUG("Error %d on line number %d\n\r", err, line); |
Daniel Veilleux |
0:442c7a6f1978 | 126 | } |
Daniel Veilleux |
0:442c7a6f1978 | 127 | |
Daniel Veilleux |
0:442c7a6f1978 | 128 | |
Daniel Veilleux |
0:442c7a6f1978 | 129 | int main(void) |
Daniel Veilleux |
0:442c7a6f1978 | 130 | { |
Daniel Veilleux |
0:442c7a6f1978 | 131 | ble_error_t err; |
Daniel Veilleux |
0:442c7a6f1978 | 132 | Ticker ticker; |
Daniel Veilleux |
0:442c7a6f1978 | 133 | |
Daniel Veilleux |
0:442c7a6f1978 | 134 | m_serial_port.baud(UART_BAUD_RATE); |
Daniel Veilleux |
0:442c7a6f1978 | 135 | |
Daniel Veilleux |
0:442c7a6f1978 | 136 | DEBUG("Initialising\n\r"); |
Daniel Veilleux |
0:442c7a6f1978 | 137 | |
Daniel Veilleux |
0:442c7a6f1978 | 138 | m_cmd_led = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 139 | m_error_led = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 140 | m_analog_in_value = 0; |
Daniel Veilleux |
0:442c7a6f1978 | 141 | |
Daniel Veilleux |
0:442c7a6f1978 | 142 | ticker.attach(periodicCallback, SENSOR_READ_INTERVAL_S); |
Daniel Veilleux |
0:442c7a6f1978 | 143 | |
Daniel Veilleux |
0:442c7a6f1978 | 144 | m_ble.init(); |
Daniel Veilleux |
0:442c7a6f1978 | 145 | m_ble.onDisconnection(disconnectionCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 146 | m_ble.onDataWritten(dataWrittenCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 147 | m_ble.onDataSent(dataSentCallback); |
Daniel Veilleux |
0:442c7a6f1978 | 148 | |
Daniel Veilleux |
0:442c7a6f1978 | 149 | // Set the TX power in dBm units. |
Daniel Veilleux |
0:442c7a6f1978 | 150 | // Possible values (in decreasing order): 4, 0, -4, -8, -12, -16, -20. |
Daniel Veilleux |
0:442c7a6f1978 | 151 | err = m_ble.setTxPower(4); |
Daniel Veilleux |
0:442c7a6f1978 | 152 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 153 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 154 | } |
Daniel Veilleux |
0:442c7a6f1978 | 155 | |
Daniel Veilleux |
0:442c7a6f1978 | 156 | // Setup advertising (GAP stuff). |
Daniel Veilleux |
0:442c7a6f1978 | 157 | err = m_ble.setDeviceName(DEVICE_NAME); |
Daniel Veilleux |
0:442c7a6f1978 | 158 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 159 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 160 | } |
Daniel Veilleux |
0:442c7a6f1978 | 161 | |
Daniel Veilleux |
0:442c7a6f1978 | 162 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); |
Daniel Veilleux |
0:442c7a6f1978 | 163 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 164 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 165 | } |
Daniel Veilleux |
0:442c7a6f1978 | 166 | |
Daniel Veilleux |
0:442c7a6f1978 | 167 | m_ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); |
Daniel Veilleux |
0:442c7a6f1978 | 168 | |
Daniel Veilleux |
0:442c7a6f1978 | 169 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, |
Daniel Veilleux |
0:442c7a6f1978 | 170 | (const uint8_t *)SHORT_NAME, |
Daniel Veilleux |
0:442c7a6f1978 | 171 | (sizeof(SHORT_NAME) - 1)); |
Daniel Veilleux |
0:442c7a6f1978 | 172 | if (BLE_ERROR_NONE != err) { |
Daniel Veilleux |
0:442c7a6f1978 | 173 | error(err, __LINE__); |
Daniel Veilleux |
0:442c7a6f1978 | 174 | } |
Daniel Veilleux |
0:442c7a6f1978 | 175 | |
Daniel Veilleux |
0:442c7a6f1978 | 176 | err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, |
Daniel Veilleux |
0:442c7a6f1978 | 177 | (const uint8_t *)UARTServiceUUID_reversed, |
Daniel Veilleux |
0:442c7a6f1978 | 178 | sizeof(UARTServiceUUID_reversed)); |
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 | m_ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADV_INTERVAL_MS)); |
Daniel Veilleux |
0:442c7a6f1978 | 184 | m_ble.startAdvertising(); |
Daniel Veilleux |
0:442c7a6f1978 | 185 | |
Daniel Veilleux |
0:442c7a6f1978 | 186 | // Create a UARTService object (GATT stuff). |
Daniel Veilleux |
0:442c7a6f1978 | 187 | UARTService uartService(m_ble); |
Daniel Veilleux |
0:442c7a6f1978 | 188 | m_uart_service_ptr = &uartService; |
Daniel Veilleux |
0:442c7a6f1978 | 189 | |
Daniel Veilleux |
0:442c7a6f1978 | 190 | while (true) { |
Daniel Veilleux |
0:442c7a6f1978 | 191 | m_ble.waitForEvent(); |
Daniel Veilleux |
0:442c7a6f1978 | 192 | } |
Daniel Veilleux |
0:442c7a6f1978 | 193 | } |