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
Diff: main.cpp
- Revision:
- 0:442c7a6f1978
- Child:
- 1:32c6991f7180
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Dec 15 21:05:18 2014 -0800 @@ -0,0 +1,193 @@ +/* mbed Microcontroller Library + * Copyright (c) 2006-2013 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "BLEDevice.h" +#include "UARTService.h" +#include "nrf_temp.h" + +#define MAX_REPLY_LEN (UARTService::BLE_UART_SERVICE_MAX_DATA_LEN) +#define SENSOR_READ_INTERVAL_S (0.5F) +#define ADV_INTERVAL_MS (1000UL) +#define UART_BAUD_RATE (19200UL) +#define DEVICE_NAME ("DEMO SENSOR") // This can be read AFTER connecting to the device. +#define SHORT_NAME ("HACKDEMO") // Keep this short: max 8 chars if a 128bit UUID is also advertised. + +#define DEBUG(...) { m_serial_port.printf(__VA_ARGS__); } + + +BLEDevice m_ble; +Serial m_serial_port(p9, p11); // TX pin, RX pin +DigitalOut m_cmd_led(LED1); +DigitalOut m_error_led(LED2); +AnalogIn m_analog_in(p1); +uint16_t m_analog_in_value; +UARTService *m_uart_service_ptr; + + +/** + * This callback is used whenever a disconnection occurs. + */ +void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) +{ + switch (reason) { + case Gap::REMOTE_USER_TERMINATED_CONNECTION: + DEBUG("Disconnected (REMOTE_USER_TERMINATED_CONNECTION)\n\r"); + break; + case Gap::LOCAL_HOST_TERMINATED_CONNECTION: + DEBUG("Disconnected (LOCAL_HOST_TERMINATED_CONNECTION)\n\r"); + break; + case Gap::CONN_INTERVAL_UNACCEPTABLE: + DEBUG("Disconnected (CONN_INTERVAL_UNACCEPTABLE)\n\r"); + break; + } + + DEBUG("Restarting the advertising process\n\r"); + m_ble.startAdvertising(); +} + + +/** + * This callback is used whenever the host writes data to one of our GATT characteristics. + */ +void dataWrittenCallback(const GattCharacteristicWriteCBParams *params) +{ + // Ensure that initialization is finished and the host has written to the TX characteristic. + if ((m_uart_service_ptr != NULL) && (params->charHandle == m_uart_service_ptr->getTXCharacteristicHandle())) { + uint8_t buf[MAX_REPLY_LEN]; + uint32_t len = 0; + + if (1 == params->len) { + switch (params->data[0]) { + case '0': + m_cmd_led = 0; + len = snprintf((char*) buf, MAX_REPLY_LEN, "OK"); + break; + case '1': + m_cmd_led = 1; + len = snprintf((char*) buf, MAX_REPLY_LEN, "OK"); + break; + case 'a': + len = snprintf((char*) buf, MAX_REPLY_LEN, "%d", m_analog_in_value); + break; + default: + len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Unknown char"); + break; + } + } + else + { + len = snprintf((char*) buf, MAX_REPLY_LEN, "ERROR: Invalid len"); + } + + m_ble.updateCharacteristicValue(m_uart_service_ptr->getRXCharacteristicHandle(), buf, len); + + DEBUG("%d bytes received from host\n\r", params->len); + } +} + + +/** + * This callback is used whenever a write to a GATT characteristic causes data to be sent to the host. + */ +void dataSentCallback(unsigned count) +{ + // NOTE: The count always seems to be 1 regardless of data. + DEBUG("%d bytes sent to host\n\r", count); +} + + +/** + * This callback is scheduled to be called periodically via a low-priority interrupt. + */ +void periodicCallback(void) +{ + m_analog_in_value = m_analog_in.read_u16(); +} + + +void error(ble_error_t err, uint32_t line) +{ + m_error_led = 1; + DEBUG("Error %d on line number %d\n\r", err, line); +} + + +int main(void) +{ + ble_error_t err; + Ticker ticker; + + m_serial_port.baud(UART_BAUD_RATE); + + DEBUG("Initialising\n\r"); + + m_cmd_led = 0; + m_error_led = 0; + m_analog_in_value = 0; + + ticker.attach(periodicCallback, SENSOR_READ_INTERVAL_S); + + m_ble.init(); + m_ble.onDisconnection(disconnectionCallback); + m_ble.onDataWritten(dataWrittenCallback); + m_ble.onDataSent(dataSentCallback); + + // Set the TX power in dBm units. + // Possible values (in decreasing order): 4, 0, -4, -8, -12, -16, -20. + err = m_ble.setTxPower(4); + if (BLE_ERROR_NONE != err) { + error(err, __LINE__); + } + + // Setup advertising (GAP stuff). + err = m_ble.setDeviceName(DEVICE_NAME); + if (BLE_ERROR_NONE != err) { + error(err, __LINE__); + } + + err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED); + if (BLE_ERROR_NONE != err) { + error(err, __LINE__); + } + + m_ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + + err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::SHORTENED_LOCAL_NAME, + (const uint8_t *)SHORT_NAME, + (sizeof(SHORT_NAME) - 1)); + if (BLE_ERROR_NONE != err) { + error(err, __LINE__); + } + + err = m_ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, + (const uint8_t *)UARTServiceUUID_reversed, + sizeof(UARTServiceUUID_reversed)); + if (BLE_ERROR_NONE != err) { + error(err, __LINE__); + } + + m_ble.setAdvertisingInterval(Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS(ADV_INTERVAL_MS)); + m_ble.startAdvertising(); + + // Create a UARTService object (GATT stuff). + UARTService uartService(m_ble); + m_uart_service_ptr = &uartService; + + while (true) { + m_ble.waitForEvent(); + } +}