/***********************************************************************************************//**
* \file main.c
* \brief Silicon Labs Empty Example Project
*
* This example demonstrates the bare minimum needed for a Blue Gecko C application
* that allows Over-the-Air Device Firmware Upgrading (OTA DFU). The application
* starts advertising after boot and restarts advertising after a connection is closed.
***************************************************************************************************
* (C) Copyright 2016 Silicon Labs, http://www.silabs.com
***************************************************************************************************
* This file is licensed under the Silabs License Agreement. See the file
* "Silabs_License_Agreement.txt" for details. Before using this software for
* any purpose, you must agree to the terms of that agreement.
**************************************************************************************************/
/* Board headers */
#include "init_mcu.h"
#include "init_board.h"
#include "init_app.h"
#include "ble-configuration.h"
#include "board_features.h"
/* Bluetooth stack headers */
#include "bg_types.h"
#include "native_gecko.h"
#include "gatt_db.h"
/* Libraries containing default Gecko configuration values */
#include "em_emu.h"
#include "em_cmu.h"
/* Device initialization header */
#include "hal-config.h"
#if defined(HAL_CONFIG)
#include "bsphalconfig.h"
#else
#include "bspconfig.h"
#endif
#include
#include "bsp.h"
#include "em_gpio.h"
#include "infrastructure.h"
/***********************************************************************************************//**
* @addtogroup Application
* @{
**************************************************************************************************/
/***********************************************************************************************//**
* @addtogroup app
* @{
**************************************************************************************************/
#ifndef MAX_CONNECTIONS
#define MAX_CONNECTIONS 4
#endif
uint8_t bluetooth_stack_heap[DEFAULT_BLUETOOTH_HEAP(MAX_CONNECTIONS)];
enum {HANDLE_DEMO, HANDLE_IBEACON};
// Gecko configuration parameters (see gecko_configuration.h)
static const gecko_configuration_t config = {
.config_flags = 0,
.sleep.flags = SLEEP_FLAGS_DEEP_SLEEP_ENABLE,
.bluetooth.max_connections = MAX_CONNECTIONS,
.bluetooth.heap = bluetooth_stack_heap,
.bluetooth.heap_size = sizeof(bluetooth_stack_heap),
.bluetooth.max_advertisers = 1, /* LAB SECTION 2.1 STEP 2 MODIFY MAX # ADVERTISERS */
.bluetooth.sleep_clock_accuracy = 100, // ppm
.gattdb = &bg_gattdb_data,
.ota.flags = 0,
.ota.device_name_len = 3,
.ota.device_name_ptr = "OTA",
#if (HAL_PA_ENABLE) && defined(FEATURE_PA_HIGH_POWER)
.pa.config_enable = 1, // Enable high power PA
.pa.input = GECKO_RADIO_PA_INPUT_VBAT, // Configure PA input to VBAT
#endif // (HAL_PA_ENABLE) && defined(FEATURE_PA_HIGH_POWER)
};
struct phyName{
uint8 flag;
uint8 string[4];
};
struct phyName getPhyName(uint8 flag){
static const struct phyName PHYs[3] = {{1,"1M"}, {2,"2M"}, {4, "125k"}};
for (int i = 0;i<3;i++){
if(PHYs[i].flag == flag){
return PHYs[i];
}
}
}
/* Flag for indicating DFU Reset must be performed */
uint8_t boot_to_dfu = 0;
#define IBEACON 1
#if IBEACON
#define ADV_PKT 0
void bcnSetupAdvBeaconing(void)
{
struct gecko_msg_le_gap_bt5_set_mode_rsp_t *bt5_set_mode_response;
/* This function sets up a custom advertisement package according to iBeacon specifications.
* The advertisement package is 30 bytes long. See the iBeacon specification for further details.
*/
static struct
{
uint8_t flagsLen; /* Length of the Flags field. */
uint8_t flagsType; /* Type of the Flags field. */
uint8_t flags; /* Flags field. */
uint8_t mandataLen; /* Length of the Manufacturer Data field. */
uint8_t mandataType; /* Type of the Manufacturer Data field. */
uint8_t compId[2]; /* Company ID field. */
uint8_t beacType[2]; /* Beacon Type field. */
uint8_t uuid[16]; /* 128-bit Universally Unique Identifier (UUID). The UUID is an identifier for the company using the beacon*/
uint8_t majNum[2]; /* Beacon major number. Used to group related beacons. */
uint8_t minNum[2]; /* Beacon minor number. Used to specify individual beacons within a group.*/
uint8_t txPower; /* The Beacon's measured RSSI at 1 meter distance in dBm. See the iBeacon specification for measurement guidelines. */
}
bcnBeaconAdvData
= {
/* Flag bits - See Bluetooth 4.0 Core Specification , Volume 3, Appendix C, 18.1 for more details on flags. */
2, /* length */
0x01, /* type */
0x04 | 0x02, /* Flags: LE General Discoverable Mode, BR/EDR is disabled. */
/* Manufacturer specific data */
26, /* length of field*/
0xFF, /* type of field */
/* The first two data octets shall contain a company identifier code from
* the Assigned Numbers - Company Identifiers document */
/* 0x004C = Apple */
{ UINT16_TO_BYTES(0x004C) },
/* Beacon type */
/* 0x0215 is iBeacon */
{ UINT16_TO_BYTE1(0x0215), UINT16_TO_BYTE0(0x0215) },
/* 128 bit / 16 byte UUID */
{ 0xE2,0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2, \
0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0 },
/* Beacon major number */
/* Set to 34987 and converted to correct format */
{ UINT16_TO_BYTE1(34987), UINT16_TO_BYTE0(34987) },
/* Beacon minor number */
/* Set as 1025 and converted to correct format */
{ UINT16_TO_BYTE1(1025), UINT16_TO_BYTE0(1025) },
/* The Beacon's measured RSSI at 1 meter distance in dBm */
/* 0xC3 is -61dBm */
0xC3
};
//
uint8_t len = sizeof(bcnBeaconAdvData);
uint8_t *pData = (uint8_t*)(&bcnBeaconAdvData);
/* Set 0 dBm Transmit Power */
gecko_cmd_le_gap_set_advertise_tx_power(HANDLE_IBEACON,0);
/* Set custom advertising data */
gecko_cmd_le_gap_bt5_set_adv_data(HANDLE_IBEACON, ADV_PKT,len, pData);
/* Set advertising parameters. 100ms advertisement interval. All channels used.
* The first two parameters are minimum and maximum advertising interval, both in
* units of (milliseconds * 1.6). The third parameter '7' sets advertising on all channels. */
//no timeout on time nor # events
gecko_cmd_le_gap_set_advertise_timing(HANDLE_IBEACON,160,160,0,0);
gecko_cmd_le_gap_set_advertise_tx_power(HANDLE_IBEACON,0);
/* Start advertising in user mode and enable connections 2000 events before expiring ... just a random number*/
bt5_set_mode_response = gecko_cmd_le_gap_start_advertising(HANDLE_IBEACON,le_gap_user_data, le_gap_non_connectable);
}
#endif
/* LAB SECTION 2.2 STEP 2 AND 3 MODIFY BELOW */
#define ADV_PKT (0)
static uint8_t eddystone_data[] = { 0x02,0x01,0x06,
0x03, //Length of service list
0x03, //service list
0xAA, 0xFE, //Eddystone ID
0x10, //length of service data
0x16, //service data
0xAA, 0xFE, //Eddystone ID
0x10, //frame type Eddyston-URL
0x00, // tx power
0x00, //http://www.
's','i','l','a','b','s','.','c','o','m'
};
#define EDDYSTONE_DATA_LEN sizeof(eddystone_data)
/**
* @brief Main function
*/
void main(void)
{
/* LAB SECTION 3.3 STEP 2 INSERT PHY VARIABLE BELOW */
// Initialize device
initMcu();
// Initialize board
initBoard();
// Initialize application
initApp();
RETARGET_SerialInit();
/* Initialize stack */
gecko_init(&config);
while (1) {
/* Event pointer for handling events */
struct gecko_cmd_packet* evt;
/* Check for stack event. */
evt = gecko_wait_event();
/* Handle events */
switch (BGLIB_MSG_ID(evt->header)) {
uint16 result;
/* This boot event is generated when the system boots up after reset.
* Here the system is set to start advertising immediately after boot procedure. */
case gecko_evt_system_boot_id:
printf("BT5 Server started\r\n");
/* first advertising set - iBeacon. Do this first because it sets the power*/
// bcnSetupAdvBeaconing();
/* Set advertising parameters. 100ms advertisement interval. All channels used.
* The first two parameters are minimum and maximum advertising interval, both in
* units of (milliseconds * 1.6). The third parameter '7' sets advertising on all channels. */
gecko_cmd_le_gap_set_advertise_timing(0,160,160,0,0);
/* LAB Section 1.4 enable scan request*/
gecko_cmd_le_gap_start_advertising(0,le_gap_general_discoverable, le_gap_undirected_connectable);
/* LAB SECTION 2.2 STEP 5 INSERT CODE BELOW */
/* LAB Section 3.1 LE Coded PHY*/
break;
case gecko_evt_le_connection_parameters_id:
break;
case gecko_evt_gatt_mtu_exchanged_id:
break;
case gecko_evt_le_gap_adv_timeout_id:
break;
/* LAB SECTION 1.3 STEP 1 INSERT CODE BELOW */
case gecko_evt_le_connection_opened_id:
/* Should these magic numbers be explained?*/
printf("connection opened\r\n");
break;
/*
* This is an informative event. There is no critical task to perform when this event
*
* */
/* LAB Section 1.4 */
case gecko_evt_le_connection_closed_id:
/* Check if need to boot to dfu mode */
if (boot_to_dfu) {
/* Enter to DFU OTA mode */
gecko_cmd_system_reset(2);
}
else {
/* Restart advertising after client has disconnected */
gecko_cmd_le_gap_start_advertising(0,le_gap_general_discoverable, le_gap_undirected_connectable);
}
break;
/* Events related to OTA upgrading
----------------------------------------------------------------------------- */
/* Check if the user-type OTA Control Characteristic was written.
* If ota_control was written, boot the device into Device Firmware Upgrade (DFU) mode. */
case gecko_evt_gatt_server_user_write_request_id:
if(evt->data.evt_gatt_server_user_write_request.characteristic==gattdb_ota_control)
{
/* Set flag to enter to OTA mode */
boot_to_dfu = 1;
/* Send response to Write Request */
gecko_cmd_gatt_server_send_user_write_response(
evt->data.evt_gatt_server_user_write_request.connection,
gattdb_ota_control,
bg_err_success);
/* Close connection to enter to DFU OTA mode */
gecko_cmd_le_connection_close(evt->data.evt_gatt_server_user_write_request.connection);
}
break;
default: printf("unhandled event 0x%X\r\n", BGLIB_MSG_ID(evt->header));
break;
}
}
}
/** @} (end addtogroup app) */
/** @} (end addtogroup Application) */