/**
******************************************************************************
* @file bluevoice_app_per_sensortile.c
* @author Central Labs
* @version V 1.0.0
* @date 13-Jun-2016
* @brief This file contains definitions for BlueVoice peripheral application.
*******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
*
* 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 BE 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 ------------------------------------------------------------------*/
#include "bluevoice_application_peripheral.h"
/** @addtogroup BLUEVOICELINK_APP
* @{
*/
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL BLUEVOICELINK_APP_PERIPHERAL
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL_Private_Defines BLUEVOICELINK_APP_PERIPHERAL_Private_Defines
* @{
*/
#define LED_TOGGLE_ADVERTISEMENT 300000
#define LED_TOGGLE_CONNECTED 80000
#define LED_TOGGLE_STREAMING 15000
#define AUDIO_CHANNELS_IN (uint16_t) (IN_CHANNELS_1) /*!< Input channels number.*/
#define AUDIO_CHANNELS_OUT (uint16_t) (OUT_CHANNELS_1) /*!< Output channels number.*/
#define AUDIO_IN_SAMPLING_FREQUENCY (uint16_t) (SAMPLING_FREQ_8000) /*!< Audio acquisition sampling frequency.*/
#define AUDIO_OUT_SAMPLING_FREQUENCY (uint16_t) (SAMPLING_FREQ_8000) /*!< Audio output sampling frequency.*/
#define PCM_IN_SAMPLES_PER_MS (AUDIO_IN_SAMPLING_FREQUENCY/1000) /*!< Number of PCM samples for each ms of audio acquired.*/
#define PCM_OUT_SAMPLES_PER_MS (AUDIO_OUT_SAMPLING_FREQUENCY/1000) /*!< Number of PCM samples for each ms of audio given as output.*/
#define AUDIO_IN_MS (1) /*!< Number of ms of Audio given as input to the BlueVoice library.*/
#define PCM_AUDIO_IN_SAMPLES (PCM_IN_SAMPLES_PER_MS * AUDIO_IN_MS) /*!< Number of PCM samples input total.*/
#define AUDIO_OUT_MS (10) /*!< Number of ms of Audio buffered in Rx before out stream.*/
#define PCM_BUFFER_OUT_LEN (PCM_OUT_SAMPLES_PER_MS * AUDIO_OUT_MS * 20) /*!< Number of PCM samples output total.*/
#define NAME_WEAR 'B', 'V', '-', 'L', 'I', 'N', 'K'
#define BV_APP_STATUS_ADVERTISEMENT (0x10) /*!< BlueVoice Peripheral device is in advertisement mode.*/
#define BV_APP_STATUS_HANDLE_DISC (0x20) /*!< Service and characteristics discovery procedure active.*/
#define BV_APP_SERVICE_DISC (0x21) /*!< Service discovery procedure.*/
#define BV_APP_CHAR_AUDIO_DISC (0x22) /*!< Audio characteristic discovery procedure.*/
#define BV_APP_CHAR_SYNC_DISC (0x23) /*!< Audio sync characteristic discovery procedure.*/
#define BV_APP_STATUS_RECEIVER_ACTIVATION (0x30) /*!< Discovered handle setting and enable notifications.*/
#define BV_APP_STATUS_READY (0x40) /*!< BlueVoice Peripheral device ready to stream or receive audio.*/
/**
* @}
*/
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL_Private_Variables BLUEVOICELINK_APP_PERIPHERAL_Private_Variables
* @{
*/
uint16_t PDM_Buffer[AUDIO_CHANNELS_IN * PCM_AUDIO_IN_SAMPLES * 64 / 8]; /*!< PDM data is stored here.*/
uint16_t PCM_Buffer[AUDIO_CHANNELS_IN * PCM_AUDIO_IN_SAMPLES]; /*!< PCM data is stored here.*/
static uint16_t PCM_Buffer_Temp[BV_ADPCM_PCM_SAMPLES_PER_PACKET]; /*!< PCM parsed data are stored here.*/
static uint16_t PCM_Buffer_OUT[PCM_BUFFER_OUT_LEN]; /*!< PCM data to be streamed via Audio OUT are stored here.*/
static void *PCM1774_X_0_handle = NULL;
static void *LSM6DSM_X_0_handle = NULL;
static uint32_t AudioOutActive = 0;
static uint32_t led_toggle_count = 0; /*!< Variable used to handle led toggling.*/
BV_ADPCM_ProfileHandle_t tx_handle; /*!< Peripheral service and characteristics handles.*/
BV_ADPCM_ProfileHandle_t rx_handle; /*!< Central service and characteristics handles.*/
BV_ADPCM_uuid_t uuid;
uint16_t service_handle, dev_name_char_handle, appearance_char_handle;
uint16_t conn_handle = 0;
volatile uint8_t BV_APP_PER_state = BV_APP_STATUS_ADVERTISEMENT; /*!< BlueVoice peripheral application state.*/
volatile uint8_t BV_APP_PER_handle_disc_state = BV_APP_SERVICE_DISC; /*!< BlueVoice central serv and char discovery state.*/
volatile uint8_t ready = 0; /*!< Flag used to request stream data when they're ready.*/
volatile uint8_t wait_end_procedure = 0;
volatile uint8_t service_discovered = 0;
volatile uint8_t char_discovered = 0;
uint16_t num_byte_sent = 0;
const uint8_t CENTRAL_BDADDR[] = { 0x55, 0x11, 0x07, 0x01, 0x16, 0xE1 }; /*!< BLE CENTRAL address.*/
const uint8_t PERIPHERAL_BDADDR[] = { 0x55, 0x11, 0x07, 0x01, 0x16, 0xE2 }; /*!< BLE PERIPHERAL address.*/
static const uint8_t audio_adpcm_serv_uuid[16] =
{
0x1b,0xc5,0xd5,0xa5,0x02,0x00,0xb4,0x9a,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x00
}; /*!< Audio service uuid.*/
static const uint8_t audio_adpcm_char_uuid[16] =
{
0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x08
}; /*!< Audio characteristic uuid.*/
static const uint8_t audio_adpcm_sync_char_uuid[16] =
{
0x1b,0xc5,0xd5,0xa5,0x02,0x00,0x36,0xac,0xe1,0x11,0x01,0x00,0x00,0x00,0x00,0x40
}; /*!< Audio synchronization uuid.*/
/**
* @}
*/
BV_APP_Status BVL_APP_PER_Init_Acquisition_Peripherals(uint32_t AudioFreq, uint32_t ChnlNbrIn);
void BVL_APP_PER_AttributeModified_CB(uint16_t attr_handle, uint8_t attr_len, uint8_t *attr_value);
void BVL_APP_PER_GAPConnectionComplete_CB(uint8_t *addr, uint16_t handle);
void BVL_APP_PER_GAPDisconnectionComplete_CB(void);
void BVL_APP_PER_GATTNotification_CB(uint16_t attr_handle, uint8_t attr_len, uint8_t *attr_value);
void BVL_APP_PER_Stream_Handler(void);
void BVL_APP_PER_AudioProcess(void);
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL_Exported_Functions BLUEVOICELINK_APP_PERIPHERAL_Exported_Functions
* @{
*/
/**
* @brief Hardware Initializes depending on the board.
* @param None.
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise..
*/
BV_APP_Status BVL_APP_PER_HWinitialization(void)
{
BV_APP_Status status;
/* Configure LED1 */
BSP_LED_Init(LED1);
/* Initialize the BlueNRG SPI driver */
BNRG_SPI_Init();
/* Initialize the BlueNRG HCI */
HCI_Init();
/* Reset BlueNRG hardware */
BlueNRG_RST();
/* Initialize Acquisition Peripherals */
status = BVL_APP_PER_Init_Acquisition_Peripherals(AUDIO_IN_SAMPLING_FREQUENCY, AUDIO_CHANNELS_IN);
if(status != BV_APP_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
/* Accelerometer initialization */
if(BSP_ACCELERO_Init( LSM6DSM_X_0, &LSM6DSM_X_0_handle ) == COMPONENT_ERROR)
{
BV_APP_PER_Error_Handler();
}
BSP_ACCELERO_Sensor_Enable( LSM6DSM_X_0_handle );
/* Enable duoble tap detection */
if(BSP_ACCELERO_Enable_Double_Tap_Detection_Ext(LSM6DSM_X_0_handle, INT2_PIN)==COMPONENT_ERROR)
{
BV_APP_PER_Error_Handler();
}
return BV_APP_SUCCESS;
}
/**
* @brief Initializes Gatt and Gap; sets the authentication requirements and the tx output power level.
* @param None.
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise.
*/
BV_APP_Status BVL_APP_PER_Init_BLE(void)
{
uint8_t ret = 0;
ret = aci_hal_write_config_data(CONFIG_DATA_PUBADDR_OFFSET, CONFIG_DATA_PUBADDR_LEN, PERIPHERAL_BDADDR);
if (ret != BLE_STATUS_SUCCESS)
{
return BV_APP_ERROR;
}
ret = aci_gatt_init();
if (ret != BLE_STATUS_SUCCESS)
{
return BV_APP_ERROR;
}
ret = aci_gap_init_IDB05A1(GAP_PERIPHERAL_ROLE_IDB05A1, 0, 0x07, &service_handle, &dev_name_char_handle, &appearance_char_handle);
if (ret != BLE_STATUS_SUCCESS)
{
return BV_APP_ERROR;
}
/* Set auth requirement*/
aci_gap_set_auth_requirement(MITM_PROTECTION_REQUIRED,
OOB_AUTH_DATA_ABSENT,
NULL, 7, 16,
USE_FIXED_PIN_FOR_PAIRING, 123456,
BONDING);
/* Set output power level */
aci_hal_set_tx_power_level(1, 5);
return BV_APP_SUCCESS;
}
/**
* @brief This function is called to initialize BlueVoice Profile.
* @param None.
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise.
*/
BV_APP_Status BV_APP_PER_ProfileInit(void)
{
BV_ADPCM_Status status;
/* Enable CRC peripheral to unlock BlueVoice library */
__CRC_CLK_ENABLE();
/* BlueVoice ADPCM library initialization*/
BluevoiceADPCM_Initialize();
BV_ADPCM_Config_t BV_ADPCM_Config;
BV_ADPCM_Config.sampling_frequency = FR_8000;
BV_ADPCM_Config.channel_in = 1;
BV_ADPCM_Config.channel_tot = 1;
status = BluevoiceADPCM_SetConfig(&BV_ADPCM_Config);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
memcpy(uuid.ServiceUUID,
audio_adpcm_serv_uuid,
sizeof(audio_adpcm_serv_uuid));
memcpy(uuid.CharAudioUUID,
audio_adpcm_char_uuid,
sizeof(audio_adpcm_char_uuid));
memcpy(uuid.CharAudioSyncUUID,
audio_adpcm_sync_char_uuid,
sizeof(audio_adpcm_sync_char_uuid));
/*BlueVoice Service and characteristics creation*/
status = BluevoiceADPCM_AddService(uuid.ServiceUUID, &tx_handle.ServiceHandle);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
status = BluevoiceADPCM_AddChar(uuid, tx_handle.ServiceHandle, &tx_handle);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
return BV_APP_SUCCESS;
}
/**
* @brief This function is called from the server in order to go in advertisement mode.
* @param None
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise.
*/
BV_APP_Status BVL_APP_PER_Advertise(void)
{
uint8_t ret = 0;
const char local_name[] =
{
AD_TYPE_COMPLETE_LOCAL_NAME, NAME_WEAR
};
uint8_t manuf_data[20] = {
2,0x0A,0x00 /* 0 dBm */, // Trasmission Power
8,0x09,NAME_WEAR, // Complete Name
7,0xFF,0x01 /* SDK version */,
0x02 /* NUCLEO-Board */,
0x48 /* AudioSync+AudioData */,
0x00,
0x00,
0x00
};
/* disable scan response */
ret = hci_le_set_scan_resp_data(0, NULL);
ret = aci_gap_set_discoverable(ADV_IND, 0, 0, PUBLIC_ADDR, NO_WHITE_LIST_USE,
sizeof(local_name), local_name, 0, NULL, 0, 0);
/* Send Advertising data */
ret = aci_gap_update_adv_data(20, manuf_data);
if (ret != BLE_STATUS_SUCCESS)
{
return BV_APP_ERROR;
}
return BV_APP_SUCCESS;
}
/**
* @brief Initializes the required peripherals using BSP_AUDIO_IN_Init function.
* @param AudioFreq: Audio frequency to be configured for the peripherals.
* @param ChnlNbrIn: Input channel number, used to configure the right peripherals.
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise.
*/
BV_APP_Status BVL_APP_PER_Init_Acquisition_Peripherals(uint32_t AudioFreq, uint32_t ChnlNbrIn)
{
uint8_t ret = 0;
ret = BSP_AUDIO_IN_Init(AudioFreq, 16, ChnlNbrIn);
if(ret != AUDIO_OK)
{
return BV_APP_ERROR;
}
return BV_APP_SUCCESS;
}
/**
* @brief Starts audio acquisition engine and then it pauses it.
* @param None.
* @retval BV_APP_Status: BV_APP_SUCCESS if the configuration is ok, BV_APP_ERROR otherwise.
*/
BV_APP_Status BVL_APP_PER_Start_Acquisition(void)
{
uint8_t ret = 0;
#ifdef STM32L476xx
ret = BSP_AUDIO_IN_Record(PCM_Buffer,0);
#else
ret = BSP_AUDIO_IN_Record(PDM_Buffer, 0);
#endif
ret = BSP_AUDIO_IN_Pause();
if(ret != AUDIO_OK)
{
return BV_APP_ERROR;
}
return BV_APP_SUCCESS;
}
/**
* @brief Process user input.
* @param None.
* @retval None.
*/
void BVL_APP_PER_Process(void)
{
BV_ADPCM_Status status;
switch (BV_APP_PER_state)
{
case BV_APP_STATUS_ADVERTISEMENT:
{
if (led_toggle_count++ >= LED_TOGGLE_ADVERTISEMENT)
{
led_toggle_count = 0;
BSP_LED_Toggle(LED1);
}
}
break;
case BV_APP_STATUS_HANDLE_DISC:
{
switch(BV_APP_PER_handle_disc_state)
{
case BV_APP_SERVICE_DISC:
{
if(!wait_end_procedure)
{
if(aci_gatt_disc_prim_service_by_uuid(conn_handle, UUID_TYPE_128, (uint8_t*)&uuid.ServiceUUID) == BLE_STATUS_SUCCESS)
{
service_discovered = 0;
wait_end_procedure = 1;
}
}
}
break;
case BV_APP_CHAR_AUDIO_DISC:
{
if(!wait_end_procedure)
{
if(aci_gatt_disc_charac_by_uuid(conn_handle, 0x0001, 0xFFFF, UUID_TYPE_128, (uint8_t*)&uuid.CharAudioUUID) == BLE_STATUS_SUCCESS)
{
char_discovered = 0;
wait_end_procedure = 1;
}
}
}
break;
case BV_APP_CHAR_SYNC_DISC:
{
if(!wait_end_procedure)
{
if(aci_gatt_disc_charac_by_uuid(conn_handle, 0x0001, 0xFFFF, UUID_TYPE_128, (uint8_t*)&uuid.CharAudioSyncUUID) == BLE_STATUS_SUCCESS)
{
char_discovered = 0;
wait_end_procedure = 1;
}
}
}
break;
default:
{
}
break;
}
}
break;
case BV_APP_STATUS_RECEIVER_ACTIVATION:
{
if(service_discovered)
{
status = BluevoiceADPCM_SetRxHandle(&rx_handle);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
status = BluevoiceADPCM_EnableNotification();
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
}
BV_APP_PER_state = BV_APP_STATUS_READY;
}
break;
case BV_APP_STATUS_READY:
{
switch(BluevoiceADPCM_GetStatus())
{
case BV_ADPCM_STATUS_READY:
{
if(AudioOutActive)
{
AudioOutActive = 0;
BSP_AUDIO_OUT_Stop(PCM1774_X_0_handle, 0);
/* Configure LED1 */
BSP_LED_Init(LED1);
}
if (led_toggle_count++ >= LED_TOGGLE_CONNECTED)
{
led_toggle_count = 0;
BSP_LED_Toggle(LED1);
}
}
break;
case BV_ADPCM_STATUS_STREAMING:
{
if (led_toggle_count++ >= LED_TOGGLE_STREAMING)
{
led_toggle_count = 0;
BSP_LED_Toggle(LED1);
}
if(ready)
{
status = BluevoiceADPCM_SendData(&num_byte_sent);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
ready = 0;
}
}
break;
case BV_ADPCM_STATUS_RECEIVING:
{
BSP_LED_On(LED1);
}
break;
default:
{
}
break;
}
}
break;
}
}
/**
* @}
*/
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL_Callbacks BLUEVOICELINK_APP_PERIPHERAL_Callbacks
* @{
*/
/**
* @brief Half Transfer user callback, called by BSP functions.
* @param None
* @retval None
*/
void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
{
BVL_APP_PER_AudioProcess();
}
/**
* @brief Complete Transfer user callback, called by BSP functions.
* @param None
* @retval None
*/
void BSP_AUDIO_IN_TransferComplete_CallBack(void)
{
BVL_APP_PER_AudioProcess();
}
/**
* @brief EXTI line detection callback.
* @param GPIO_Pin: Specifies the pins connected EXTI line
* @retval None.
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == BNRG_SPI_EXTI_PIN)
{
HCI_Isr();
}
else if (GPIO_Pin == LSM6DSM_INT2_PIN)
{
uint8_t stat = 0;
BSP_ACCELERO_Get_Double_Tap_Detection_Status_Ext(LSM6DSM_X_0_handle,&stat);
if(stat)
{
BVL_APP_PER_Stream_Handler();
}
}
}
/**
* @brief This function is called whenever there is an ACI event to be processed.
* @note Inside this function each event must be identified and correctly
* parsed.
* @param pckt: Pointer to the ACI packet
* @retval None
*/
void HCI_Event_CB(void *pckt)
{
hci_uart_pckt *hci_pckt = pckt;
hci_event_pckt *event_pckt = (hci_event_pckt*) hci_pckt->data;
if (hci_pckt->type != HCI_EVENT_PKT)
return;
switch (event_pckt->evt)
{
case EVT_DISCONN_COMPLETE:
{
BVL_APP_PER_GAPDisconnectionComplete_CB();
}
break;
case EVT_LE_META_EVENT:
{
evt_le_meta_event *evt = (void *) event_pckt->data;
switch (evt->subevent)
{
case EVT_LE_CONN_COMPLETE:
{
evt_le_connection_complete *cc = (void *) evt->data;
BVL_APP_PER_GAPConnectionComplete_CB(cc->peer_bdaddr, cc->handle);
}
break;
}
}
break;
case EVT_VENDOR:
{
evt_blue_aci *blue_evt = (void*) event_pckt->data;
switch (blue_evt->ecode)
{
case EVT_BLUE_GATT_PROCEDURE_COMPLETE:
{
wait_end_procedure = 0;
if(BV_APP_PER_handle_disc_state == BV_APP_SERVICE_DISC)
{
if(service_discovered)
{
BV_APP_PER_handle_disc_state = BV_APP_CHAR_AUDIO_DISC;
}
else
{
BV_APP_PER_state = BV_APP_STATUS_RECEIVER_ACTIVATION;
}
}
else if(BV_APP_PER_handle_disc_state == BV_APP_CHAR_AUDIO_DISC)
{
if(char_discovered)
{
char_discovered = 0;
BV_APP_PER_handle_disc_state = BV_APP_CHAR_SYNC_DISC;
}
}
else if(BV_APP_PER_handle_disc_state == BV_APP_CHAR_SYNC_DISC)
{
if(char_discovered)
{
char_discovered = 0;
BV_APP_PER_state = BV_APP_STATUS_RECEIVER_ACTIVATION;
}
}
}
break;
case EVT_BLUE_ATT_FIND_BY_TYPE_VAL_RESP:
{
evt_att_find_by_type_val_resp *evt_serv = (evt_att_find_by_type_val_resp*)blue_evt->data;
rx_handle.ServiceHandle = (evt_serv->handles_info_list[1]<<8) + evt_serv->handles_info_list[0];
service_discovered = 1;
}
break;
case EVT_BLUE_GATT_DISC_READ_CHAR_BY_UUID_RESP:
{
evt_gatt_disc_read_char_by_uuid_resp *evt_char = (evt_gatt_disc_read_char_by_uuid_resp*)blue_evt->data;
if(BV_APP_PER_handle_disc_state == BV_APP_CHAR_AUDIO_DISC)
{
rx_handle.CharAudioHandle = evt_char->attr_handle;
char_discovered = 1;
}
else if(BV_APP_PER_handle_disc_state == BV_APP_CHAR_SYNC_DISC)
{
rx_handle.CharAudioSyncHandle = evt_char->attr_handle;
char_discovered = 1;
}
}
break;
case EVT_BLUE_GATT_ATTRIBUTE_MODIFIED:
{
evt_gatt_attr_modified_IDB05A1 *evt = (evt_gatt_attr_modified_IDB05A1*) blue_evt->data;
BVL_APP_PER_AttributeModified_CB(evt->attr_handle, evt->data_length, evt->att_data);
}
break;
case EVT_BLUE_GATT_NOTIFICATION:
{
evt_gatt_attr_notification *evt = (evt_gatt_attr_notification*) blue_evt->data;
BVL_APP_PER_GATTNotification_CB(evt->attr_handle, evt->event_data_length - 2, evt->attr_value);
}
break;
}
}
break;
}
}
/**
* @}
*/
/** @defgroup BLUEVOICELINK_APP_PERIPHERAL_Private_Functions BLUEVOICELINK_APP_PERIPHERAL_Private_Functions
* @{
*/
/**
* @brief This function is called when an attribute gets modified
* @param handle: Handle of the attribute
* @param attr_len: Size of the modified attribute data
* @param attr_value: Pointer to the modified attribute data
* @retval None.
*/
void BVL_APP_PER_AttributeModified_CB(uint16_t attr_handle, uint8_t attr_len, uint8_t *attr_value)
{
if((attr_handle == tx_handle.CharAudioHandle+2) || (attr_handle == tx_handle.CharAudioSyncHandle+2))
{
BluevoiceADPCM_AttributeModified_CB(attr_handle, attr_len, attr_value);
}
}
/**
* @brief This function is called when there is a LE Connection Complete event.
* @param addr: Address of peer device
* @param handle: Connection handle
* @retval None.
*/
void BVL_APP_PER_GAPConnectionComplete_CB(uint8_t *addr, uint16_t handle)
{
/* Connection completed */
BluevoiceADPCM_ConnectionComplete_CB(handle);
/* Connection interval parameters update request in order to be compatible with Android and iOS*/
int ret = aci_l2cap_connection_parameter_update_request(handle,
8 /* interval_min*/,
17 /* interval_max */,
0 /* slave_latency */,
400 /*timeout_multiplier*/);
if (ret != BLE_STATUS_SUCCESS)
{
while (1);
}
conn_handle = handle;
BV_APP_PER_state = BV_APP_STATUS_HANDLE_DISC;
}
/**
* @brief This function is called when the peer device get disconnected.
* @param None.
* @retval None.
*/
void BVL_APP_PER_GAPDisconnectionComplete_CB(void)
{
BluevoiceADPCM_DisconnectionComplete_CB();
BSP_AUDIO_IN_Pause();
BV_APP_PER_state = BV_APP_STATUS_ADVERTISEMENT;
BV_APP_Status status;
/*Set module in advertise mode*/
status = BVL_APP_PER_Advertise();
if(status != BV_APP_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
wait_end_procedure = 0;
}
/**
* @brief This function is called when there is a notification from the Central Server.
* @param attr_handle: Handle of the attribute.
* @param attr_len: Length of attribute value in the notification.
* @param attr_value: Attribute value in the notification.
* @retval None.
*/
void BVL_APP_PER_GATTNotification_CB(uint16_t attr_handle, uint8_t attr_len, uint8_t *attr_value)
{
BV_ADPCM_Status status;
uint8_t PCMsample = 0;
static uint32_t IndexOut = 0;
static uint32_t IndexIn = 0;
/* Data parsing. */
status = BluevoiceADPCM_ParseData(attr_value, attr_len, attr_handle, (uint8_t *) PCM_Buffer_Temp, &PCMsample);
if(status != BV_ADPCM_SUCCESS)
{
BV_APP_PER_Error_Handler();
}
if (PCMsample > 0)
{
for(IndexIn=0;IndexIn<PCMsample;IndexIn++)
{
PCM_Buffer_OUT[IndexOut++] = PCM_Buffer_Temp[IndexIn];
PCM_Buffer_OUT[IndexOut++] = PCM_Buffer_Temp[IndexIn];
}
if (!AudioOutActive && IndexOut==PCM_BUFFER_OUT_LEN/2)
{
/* Configure Audio Output peripheral (SAI) and external DAC */
BSP_AUDIO_OUT_Init(PCM1774_0, &PCM1774_X_0_handle, NULL, 20, AUDIO_OUT_SAMPLING_FREQUENCY);
BSP_AUDIO_OUT_SetVolume(PCM1774_X_0_handle, 20);
/* start audio streaming */
BSP_AUDIO_OUT_Play(PCM1774_X_0_handle,(uint16_t*)PCM_Buffer_OUT, PCM_BUFFER_OUT_LEN);
AudioOutActive=1;
}
if(IndexOut==PCM_BUFFER_OUT_LEN)
{
IndexOut = 0;
}
}
}
/**
* @brief Audio Process function: PDM to PCM conversion and BlueVoice buffer filling.
* @param None.
* @retval None.
*/
void BVL_APP_PER_AudioProcess(void)
{
BV_ADPCM_Status status;
/* for L4 PDM to PCM conversion is performed in hardware by DFSDM peripheral */
#ifndef STM32L476xx
/*PDM to PCM conversion*/
BSP_AUDIO_IN_PDMToPCM((uint16_t *) PDM_Buffer, PCM_Buffer);
#endif
if (BluevoiceADPCM_IsProfileConfigured())
{
/*BlueVoice data filling*/
status = BluevoiceADPCM_AudioIn((uint16_t*) PCM_Buffer, PCM_AUDIO_IN_SAMPLES);
if(status==BV_ADPCM_OUT_BUF_READY)
{
ready=1;
}
}
}
/**
* @brief This function is called when user button is pressed.
* @param None.
* @retval None.
*/
void BVL_APP_PER_Stream_Handler(void)
{
BV_ADPCM_Profile_Status Status;
BV_ADPCM_Mode Mode;
Status = BluevoiceADPCM_GetStatus();
Mode = BluevoiceADPCM_GetMode();
if (Status == BV_ADPCM_STATUS_READY)
{
if((Mode == TRANSMITTER) || (Mode == HALF_DUPLEX))
{
/* Audio acquisition is resumed */
BSP_AUDIO_IN_Resume();
}
}
else if (Status == BV_ADPCM_STATUS_STREAMING)
{
/* Audio acquisition is paused */
BSP_AUDIO_IN_Pause();
}
else if (Status == BV_ADPCM_STATUS_RECEIVING)
{
/*Nothing to be done*/
}
}
/**
* @brief Error handler.
* @param None.
* @retval None.
*/
void BV_APP_PER_Error_Handler(void)
{
while(1)
{
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Comments