Files
ch32v20x-examples/EVT/EXAM/BLE/SYNC_ADV/APP/broadcaster.c
T
2023-02-01 14:19:13 +08:00

350 lines
11 KiB
C

/********************************** (C) COPYRIGHT *******************************
* File Name : broadcaster.c
* Author : WCH
* Version : V1.0
* Date : 2020/08/06
* Description : Broadcast the application, initialize the broadcast
* connection parameters, and then keep broadcasting in the broadcast state
*********************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include "CONFIG.h"
#include "devinfoservice.h"
#include "broadcaster.h"
/*********************************************************************
* MACROS
*/
/*********************************************************************
* CONSTANTS
*/
// What is the advertising interval when device is discoverable (units of 625us, min is 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL 160
// Company Identifier: WCH
#define WCH_COMPANY_ID 0x07D7
// Length of bd addr as a string
#define B_ADDR_STR_LEN 15
/*********************************************************************
* TYPEDEFS
*/
/*********************************************************************
* GLOBAL VARIABLES
*/
/*********************************************************************
* EXTERNAL VARIABLES
*/
/*********************************************************************
* EXTERNAL FUNCTIONS
*/
/*********************************************************************
* LOCAL VARIABLES
*/
static uint8_t Broadcaster_TaskID; // Task ID for internal task/event processing
// GAP - SCAN RSP data (max size = 31 bytes)
static uint8_t scanRspData[] = {
// complete name
0x0c, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE, 0x42, // 'B'
0x72, // 'r'
0x6f, // 'o'
0x61, // 'a'
0x64, // 'd'
0x63, // 'c'
0x61, // 'a'
0x73, // 's'
0x74, // 't'
0x65, // 'e'
0x72, // 'r'
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL, 0 // 0dBm
};
// GAP - Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8_t advertData[] = {
// Flags; this sets the device to use limited discoverable
// mode (advertises for 30 seconds at a time) instead of general
// discoverable mode (advertises indefinitely)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// Broadcast of the data
0x04, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
'b', 'l', 'e', 0x04,
GAP_ADTYPE_LOCAL_NAME_SHORT,
'a', 'b', 'c'
};
// GAP - Advertisement data (max size = 252 bytes, though this is
// best kept short to conserve power while advertisting)
static uint8_t periodicAdvertData[] = {
// Broadcast of the data
44, // length of this data including the data type byte
GAP_ADTYPE_MANUFACTURER_SPECIFIC, // manufacturer specific advertisement data type
'b', 'l', 'e',
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void Broadcaster_ProcessTMOSMsg(tmos_event_hdr_t *pMsg);
static void Broadcaster_StateNotificationCB(gapRole_States_t newState);
/*********************************************************************
* PROFILE CALLBACKS
*/
// GAP Role Callbacks
static gapRolesBroadcasterCBs_t Broadcaster_BroadcasterCBs = {
Broadcaster_StateNotificationCB, // Profile State Change Callbacks
NULL
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn Broadcaster_Init
*
* @brief Initialization function for the Broadcaster App
* Task. This is called during initialization and should contain
* any application specific initialization (ie. hardware
* initialization/setup, table initialization, power up
* notificaiton ... ).
*
* @param task_id - the ID assigned by TMOS. This ID should be
* used to send messages and set timers.
*
* @return none
*/
void Broadcaster_Init()
{
Broadcaster_TaskID = TMOS_ProcessEventRegister(Broadcaster_ProcessEvent);
// Setup the GAP Broadcaster Role Profile
{
// Device starts advertising upon initialization
uint8_t initial_advertising_enable = TRUE;
uint8_t initial_periodic_advertising_enable = TRUE | (1<<1);
uint8_t initial_adv_event_type = GAP_ADTYPE_EXT_NONCONN_NONSCAN_UNDIRECT;
// Set the GAP Role Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t), &initial_advertising_enable);
GAPRole_SetParameter(GAPROLE_ADV_EVENT_TYPE, sizeof(uint8_t), &initial_adv_event_type);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData), scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_PERIODIC_ADVERT_DATA, sizeof(periodicAdvertData), periodicAdvertData);
GAPRole_SetParameter(GAPROLE_PERIODIC_ADVERT_ENABLED, sizeof(uint8_t), &initial_periodic_advertising_enable);
}
{
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
// Set advertising interval
GAP_SetParamValue(TGAP_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_DISC_ADV_INT_MAX, advInt);
// Set periodic advertising interval (n * 1.25 mSec) (80 = 100ms)
GAP_SetParamValue(TGAP_PERIODIC_ADV_INT_MIN, 80);
GAP_SetParamValue(TGAP_PERIODIC_ADV_INT_MAX, 80);
GAP_SetParamValue(TGAP_PERIODIC_ADV_PROPERTIES, GAP_PERI_PROPERTIES_INCLUDE_TXPOWER);
GAP_SetParamValue(TGAP_ADV_SECONDARY_PHY, GAP_PHY_VAL_LE_1M);
GAP_SetParamValue(TGAP_ADV_SECONDARY_MAX_SKIP, 0);
GAP_SetParamValue(TGAP_ADV_ADVERTISING_SID, 8);
// Enable scan req notify
GAP_SetParamValue(TGAP_ADV_SCAN_REQ_NOTIFY, ENABLE);
}
// Setup a delayed profile startup
tmos_set_event(Broadcaster_TaskID, SBP_START_DEVICE_EVT);
}
/*********************************************************************
* @fn Broadcaster_ProcessEvent
*
* @brief Broadcaster Application Task event processor. This
* function is called to process all events for the task. Events
* include timers, messages and any other user defined events.
*
* @param task_id - The TMOS assigned task ID.
* @param events - events to process. This is a bit map and can
* contain more than one event.
*
* @return events not processed
*/
uint16_t Broadcaster_ProcessEvent(uint8_t task_id, uint16_t events)
{
if(events & SYS_EVENT_MSG)
{
uint8_t *pMsg;
if((pMsg = tmos_msg_receive(Broadcaster_TaskID)) != NULL)
{
Broadcaster_ProcessTMOSMsg((tmos_event_hdr_t *)pMsg);
// Release the TMOS message
tmos_msg_deallocate(pMsg);
}
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
}
if(events & SBP_START_DEVICE_EVT)
{
// Start the Device
GAPRole_BroadcasterStartDevice(&Broadcaster_BroadcasterCBs);
return (events ^ SBP_START_DEVICE_EVT);
}
if(events & SBP_PERIODIC_EVT)
{
// Change periodic adv data
periodicAdvertData[5]++;
GAPRole_SetParameter(GAPROLE_PERIODIC_ADVERT_DATA, sizeof(periodicAdvertData), periodicAdvertData);
tmos_start_task(Broadcaster_TaskID, SBP_PERIODIC_EVT, 160);
return (events ^ SBP_PERIODIC_EVT);
}
// Discard unknown events
return 0;
}
/*********************************************************************
* @fn Broadcaster_ProcessTMOSMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void Broadcaster_ProcessGAPMsg(gapRoleEvent_t *pEvent)
{
switch(pEvent->gap.opcode)
{
case GAP_SCAN_REQUEST_EVENT:
{
PRINT("scanReqEvt.advHandle %x\n", pEvent->scanReqEvt.advHandle);
break;
}
default:
break;
}
}
/*********************************************************************
* @fn Broadcaster_ProcessTMOSMsg
*
* @brief Process an incoming task message.
*
* @param pMsg - message to process
*
* @return none
*/
static void Broadcaster_ProcessTMOSMsg(tmos_event_hdr_t *pMsg)
{
switch(pMsg->event)
{
case GAP_MSG_EVENT:
{
Broadcaster_ProcessGAPMsg((gapRoleEvent_t *)pMsg);
break;
}
default:
break;
}
}
/*********************************************************************
* @fn Broadcaster_StateNotificationCB
*
* @brief Notification from the profile of a state change.
*
* @param newState - new state
*
* @return none
*/
static void Broadcaster_StateNotificationCB(gapRole_States_t newState)
{
if(newState & GAPROLE_PERIODIC_STATE_VALID)
{
switch(newState & GAPROLE_STATE_PERIODIC_MASK)
{
case GAPROLE_PERIODIC_INVALID:
PRINT("periodic invalid..\n");
break;
case GAPROLE_PERIODIC_ENABLE:
PRINT("periodic enable..\n");
tmos_start_task(Broadcaster_TaskID, SBP_PERIODIC_EVT, 160);
break;
case GAPROLE_PERIODIC_WAIT:
PRINT("periodic wait..\n");
break;
case GAPROLE_PERIODIC_ERROR:
PRINT("periodic error..\n");
break;
default:
break;
}
}
else
{
switch(newState & GAPROLE_STATE_ADV_MASK)
{
case GAPROLE_STARTED:
PRINT("Initialized..\n");
break;
case GAPROLE_ADVERTISING:
PRINT("Advertising..\n");
break;
case GAPROLE_WAITING:
PRINT("Waiting for advertising..\n");
break;
case GAPROLE_ERROR:
PRINT("Error..\n");
break;
default:
break;
}
}
}
/*********************************************************************
*********************************************************************/