Bluetooth Low Energy enabled device with "Switch" feature, compatible with BlueST Protocol.
Bluetooth Low Energy enabled device with "Switch" feature, compatible with BlueST Protocol.
Diff: source/main.cpp
- Revision:
- 0:6b34c49b5285
- Child:
- 1:bb6dbece87c1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/main.cpp Tue Apr 17 15:13:04 2018 +0000 @@ -0,0 +1,231 @@ +/** + ******************************************************************************* + * @file main.cpp + * @author Davide Aliprandi, STMicroelectronics + * @version V1.0.0 + * @date March 31st, 2018 + * @brief mbed test application for the STMicroelectronics X-NUCLEO-IDB05A1 + * Bluetooth Low energy Expansion Board. + ******************************************************************************* + * @attention + * + * <h2><center>© COPYRIGHT(c) 2018 STMicroelectronics</center></h2> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************* + */ + + +/* Includes ------------------------------------------------------------------*/ + +/* mbed specific header files. */ +#include <events/mbed_events.h> +#include <mbed.h> +#include "ble/BLE.h" +#include "CustomService.h" + +/* Helper header files. */ +#include "DevSPI.h" + +/* Component specific header files. */ +#include "L6474.h" + + +/* Definitions ---------------------------------------------------------------*/ + +#define BLE_ADVERTISING_INTERVAL_ms 1000 +#define BLUETOOTH_PERIODIC_CALLBACK_ms 500 +#define DELAY_1 100 + + +/* Types ---------------------------------------------------------------------*/ + +/* Toggle state. */ +typedef enum +{ + TOGGLE_OFF = 0, + TOGGLE_ON +} toggle_t; + + +/* Variables -----------------------------------------------------------------*/ + +/* Button state. */ +bool toggle_state; + +/* LED to indicate system state. */ +DigitalOut led_state(LED1); //Conflicts with SPI CLK on D13. + +/* Bluetooth. */ +const static char DEVICE_NAME[] = "SWITCH_DEVICE_2"; +const static uint8_t MANUFACTURER_SPECIFIC_DATA[]= {0x01,0x80,0x20,0x00,0x00,0x00}; +static EventQueue event_queue(/* event count */ 10 * EVENTS_EVENT_SIZE); +CustomService *custom_service; + +/* Button event. */ +InterruptIn event(USER_BUTTON); + + +/* Bluetooth related functions -----------------------------------------------*/ + +void on_disconnection_callback(const Gap::DisconnectionCallbackParams_t *params) +{ + (void) params; + BLE::Instance().gap().startAdvertising(); +} + +/** + * This callback allows the custom service to read updates from the + * characteristic. + * + * @param[in] params + * Information about the characterisitc being updated. + */ +void on_data_read_callback(const GattReadCallbackParams *params) { + static uint16_t time_stamp = 0; + + if (params->handle == custom_service->getValueHandle()) { + // Reading led state and sending it via bluetooth. + if (BLE::Instance().getGapState().connected) { + //event_queue.call(Callback<void(uint16_t, uint8_t)>(custom_service, &CustomService::send_state), time_stamp++, led_state.read() ? CustomService::SWITCH_ON : CustomService::SWITCH_OFF); + event_queue.call(Callback<void(uint16_t, uint8_t)>(custom_service, &CustomService::send_state), time_stamp++, TOGGLE_OFF); // To clean the BLE buffer. + } + } +} + +/** + * This callback allows the custom service to write updates to the + * characteristic. + * + * @param[in] params + * Information about the characterisitc being updated. + */ +void on_data_written_callback(const GattWriteCallbackParams *params) { + + if (params->handle == custom_service->getValueHandle()) { + /* Receiving command via bluetooth and writing it to the led state. */ + led_state.write(((CustomService::switch_state_t) ((uint8_t *) (params->data))[0])); + } +} + +/** + * This function is called periodically. + */ +void periodic_callback(void) +{ + static uint16_t time_stamp = 0; + + /* Reading toggle command and sending it via bluetooth. */ + if (toggle_state) { + if (BLE::Instance().getGapState().connected) { + event_queue.call(Callback<void(uint16_t, uint8_t)>(custom_service, &CustomService::send_state), time_stamp++, toggle_state ? TOGGLE_ON : TOGGLE_OFF); + toggle_state = false; + } + } +} + +/** + * This function is called when the ble initialization process has failled. + */ +void on_ble_init_error_callback(BLE &ble, ble_error_t error) +{ + /* Initialization error handling should go here */ +} + +/** + * Callback triggered when the ble initialization process has finished. + */ +void ble_init_complete(BLE::InitializationCompleteCallbackContext *params) +{ + BLE& ble = params->ble; + ble_error_t error = params->error; + + if (error != BLE_ERROR_NONE) { + /* In case of error, forward the error handling to on_ble_init_error_callback */ + on_ble_init_error_callback(ble, error); + return; + } + + /* Ensure that it is the default instance of BLE */ + if(ble.getInstanceID() != BLE::DEFAULT_INSTANCE) { + return; + } + + ble.gap().onDisconnection(on_disconnection_callback); + ble.gattServer().onDataWritten(on_data_written_callback); + //ble.gattServer().onDataRead(on_data_read_callback); + + custom_service = new CustomService(ble); + + /* Setup advertising data. */ + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); + ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS, (uint8_t *) CUSTOM_SWITCH_SERVICE_UUID, sizeof(CUSTOM_SWITCH_SERVICE_UUID)); + ble.gap().accumulateScanResponse(GapAdvertisingData::MANUFACTURER_SPECIFIC_DATA, MANUFACTURER_SPECIFIC_DATA, sizeof(MANUFACTURER_SPECIFIC_DATA)); + ble.gap().accumulateScanResponse(GapAdvertisingData::COMPLETE_LOCAL_NAME, (const uint8_t *) DEVICE_NAME, sizeof(DEVICE_NAME)); + ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); + ble.gap().setAdvertisingInterval(BLE_ADVERTISING_INTERVAL_ms); + ble.gap().startAdvertising(); +} + +void schedule_ble_events_processing(BLE::OnEventsToProcessCallbackContext* context) { + BLE &ble = BLE::Instance(); + event_queue.call(Callback<void()>(&ble, &BLE::processEvents)); +} + + +/* Custom service related functions ------------------------------------------*/ + +void button_callback(void) { + toggle_state = true; +} + + +/* Main function -------------------------------------------------------------*/ + +int main() +{ + /*----- Initialization. -----*/ + + /* Printing to the console. */ + printf("Switch Node Application Example\r\n\n"); + + /* Bluetooth. */ + event_queue.call_every(BLUETOOTH_PERIODIC_CALLBACK_ms, periodic_callback); + BLE &ble = BLE::Instance(); + ble.onEventsToProcess(schedule_ble_events_processing); + ble.init(ble_init_complete); + + /* Attaching and enabling interrupt handlers. */ + event.fall(button_callback); + + /* Setting up initial state: led OFF, no toggle state. */ + led_state.write(CustomService::SWITCH_OFF); + toggle_state = false; + + /* Start. */ + event_queue.dispatch_forever(); + + return 0; +}