Hoang Nhu
Created October 14, 2017 © GPL3+

Alexa/Google-Assistant Voice/Sensor-Based IoT Automation

Via SensorTile's microphone & sensor, users can tap to send voice command to Alexa/Google-Assistant servers to control IoT appliances

AdvancedFull instructions providedOver 1 day479
 Alexa/Google-Assistant Voice/Sensor-Based IoT Automation

Things used in this project

Hardware components

STEVAL-STLKT01V1
STMicroelectronics STEVAL-STLKT01V1
×1
iPhone
Apple iPhone
×1
Android device
Android device
×1
STM32 Nucleo-64 Board
STMicroelectronics STM32 Nucleo-64 Board
×1
NousLogic - Smart Power Plug
×1

Software apps and online services

IoT Voice Assistant (Android)
IoT Voice Assistant (iOS)
STMicroelectronics FP-SNS-ALLMEMS1
STMicroelectronics FP-AUD-BVLINK1

Story

Read more

Schematics

System Block Diagram

Overview iot xdyjf3xytr

Interaction between Android App (IoT Voice Assistant) and SensorTile

Simplified st bv link   android app diagram (1) 4pgfbsxisq

Interaction between iOS App (IoT Voice Assistant) and SensorTile

Simplified st bv link   ios app diagram (1) ug2gtrdopd

Code

main.c

C/C++
Main file, full source code can be obtained from ST AUD-BVLINK main page
/**
 ******************************************************************************
 * @file    main.c
 * @author  Central Labs
 * @version V2.0.0
 * @date    13-Jun-2016
 * @brief   This software provides an application running on STM32 to
 *          demonstrate half-duplex speech transmission over Bluetooth Low Energy.
 *          It is based on OSXBlueVoice library v2.0.0 (under OSX-LLA License),
 *          configured as PERIPHERAL.
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2015 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 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.
 *
 ******************************************************************************
 */

/**
 * @mainpage Documentation for FP-AUD-BVLINK1 Software for STM32, BlueNRG-MS and digital MEMS microphone
 *
 * @image html st_logo.png
 *
 * <b>Introduction</b>
 *
 * This software is based on the STM32CubeHAL, the hardware abstraction layer for
 * the STM32 microcontroller. The package extends STM32Cube by providing a
 * Board Support Package (BSP) for BlueNRG-MS, MEMS Microphone 
 * expansion boards, SensorTile and BlueCoin. Middleware components for 
 * communication with other Bluetooth LE devices and a dedicated profile 
 * for voice communication
 *
 * <b>Example Application</b>
 *
 * BlueVoice applications (Central and Peripheral) show speech acquisition,
 * compression and transmission over Bluetooth Low Energy of speech data in a
 * bidirectional system. Both module can act as transmitter or receiver of
 * speech according to the selected channel. The module acting as transmitter is
 * responsible for audio acquisition, compression and streaming over BLE according
 * to BlueVoice Profile specification. The module acting as receiver is responsible
 * for audio decompression and USB streaming of audio data via USB.
 */

/* Includes ------------------------------------------------------------------*/

#include "bluevoice_application_peripheral.h"

/* Private defines -----------------------------------------------------------*/
/* Private macros ------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/


/* Private function prototypes -----------------------------------------------*/

/**
 * @brief  Main program.
 * @param  None.
 * @retval None.
 */
int main(void)
{
  /* STM32Cube HAL library initialization:
   *  - Configure the Flash prefetch, Flash preread and Buffer caches
   *  - Systick timer is configured by default as source of time base, but user
   *    can eventually implement his proper time base source (a general purpose
   *    timer for example or other time source), keeping in mind that Time base
   *    duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
   *    handled in milliseconds basis.
   *  - Low Level Initialization
   */
  HAL_Init();

#ifdef STM32L476xx
  /* Enable Power Clock*/
  __HAL_RCC_PWR_CLK_ENABLE();
  /* enable USB power on Pwrctrl CR2 register */
  HAL_PWREx_EnableVddUSB();  
#endif
  
  /* Configure the system clock */
  SystemClock_Config();
 
  BV_APP_Status status;
  
  /* Peripherals Initialization*/
  status = BVL_APP_PER_HWinitialization();
  if(status != BV_APP_SUCCESS)
  {
    BV_APP_PER_Error_Handler();
  } 
 
  /*BLE Initialization*/
  status = BVL_APP_PER_Init_BLE();
  if(status != BV_APP_SUCCESS)
  {
    BV_APP_PER_Error_Handler();
  }
  
  /*BlueVoice profile Initialization*/
  status = BV_APP_PER_ProfileInit();
  if(status != BV_APP_SUCCESS)
  {
    BV_APP_PER_Error_Handler();
  }
 
  /*Audio Start Acquisition*/
  status = BVL_APP_PER_Start_Acquisition();
  if(status != BV_APP_SUCCESS)
  {
    BV_APP_PER_Error_Handler();
  }
  
  /*Set module in advertise mode*/
  status = BVL_APP_PER_Advertise(); 
  if(status != BV_APP_SUCCESS)
  {
    BV_APP_PER_Error_Handler();
  }
  
  while (1)
  {
    HCI_Process();
    BVL_APP_PER_Process();
  }
}


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

bluevoice_app_per_sensortile.c

C/C++
peripheral functionalities
/**
 ******************************************************************************
 * @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>&copy; 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****/

STBlueMS_iOS

For iOS App starting point

AVS Sample App

Alexa Sample App for reference

Credits

Hoang Nhu

Hoang Nhu

1 project • 2 followers
Embedded System Architect
Contact

Comments