/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
*
© Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#define ARM_MATH_CM4
#include "main.h"
#include "arm_math.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifndef HSEM_ID_0
#define HSEM_ID_0 (0U) /* HW semaphore 0*/
#endif
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2S_HandleTypeDef hi2s1;
DMA_HandleTypeDef hdma_spi1_tx;
DMA_HandleTypeDef hdma_spi1_rx;
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_I2S1_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/*
FIR filter designed with
http://t-filter.appspot.com
sampling frequency: 48000 Hz
* 0 Hz - 2000 Hz
gain = 1
desired ripple = 5 dB
actual ripple = 3.284632065621469 dB
* 5000 Hz - 24000 Hz
gain = 0
desired attenuation = -30 dB
actual attenuation = -32.02295267957132 dB
*/
#define FILTER_TAP_NUM 16
#define BLOCK_SIZE_FLOAT 512
#define BLOCK_SIZE_U16 2048
/*static float filter_taps[FILTER_TAP_NUM] = {
-0.0021834891907904987,
0.023133081888390004,
0.03440125360693663,
0.054016706019288735,
0.07610902012650608,
0.09772535709704201,
0.11593264129629442,
0.12810228628568973,
0.13238343618749146,
0.12810228628568973,
0.11593264129629442,
0.09772535709704201,
0.07610902012650608,
0.054016706019288735,
0.03440125360693663,
0.023133081888390004,
-0.0021834891907904987
};*/
//FIR BP fs48kHz,Order15
static float filter_taps[FILTER_TAP_NUM] = {
-0.0195752460187690,
0.0119915552629445,
0.00717283698280682,
-0.0490010630870986,
0.0710715985018322,
-0.0529488863637266,
-0.0747295317750623,
0.581375225878972,
0.581375225878972,
-0.0747295317750623,
-0.0529488863637266,
0.0710715985018322,
-0.0490010630870986,
0.00717283698280682,
0.0119915552629445,
-0.0195752460187690
};
arm_fir_instance_f32 firsettings_l, firsettings_r;
//fir state size is always number_of_samples + number_of_fir_tabs - 1
float fir_l_state [BLOCK_SIZE_FLOAT + FILTER_TAP_NUM - 1];
float fir_r_state [BLOCK_SIZE_FLOAT + FILTER_TAP_NUM - 1];
uint16_t rxBuf[BLOCK_SIZE_U16*2];
uint16_t txBuf[BLOCK_SIZE_U16*2];
float l_buf_in [BLOCK_SIZE_FLOAT*2];
float r_buf_in [BLOCK_SIZE_FLOAT*2];
float l_buf_out [BLOCK_SIZE_FLOAT*2];
float r_buf_out [BLOCK_SIZE_FLOAT*2];
uint8_t callback_state = 0;
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/* Activate HSEM notification for Cortex-M4*/
HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/*
Domain D2 goes to STOP mode (Cortex-M4 in deep-sleep) waiting for Cortex-M7 to
perform system initialization (system clock config, external memory configuration.. )
*/
HAL_PWREx_ClearPendingEvent();
HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);
/* Clear HSEM flag */
__HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/* USER CODE END Boot_Mode_Sequence_1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_DMA_Init();
MX_GPIO_Init();
MX_I2S1_Init();
/* USER CODE BEGIN 2 */
//init FIR structure
arm_fir_init_f32(&firsettings_l, FILTER_TAP_NUM, &filter_taps[0], &fir_l_state[0], BLOCK_SIZE_FLOAT);
arm_fir_init_f32(&firsettings_r, FILTER_TAP_NUM, &filter_taps[0], &fir_r_state[0], BLOCK_SIZE_FLOAT);
//start i2s with 2048 samples transmission => 4096*u16 words
HAL_I2SEx_TransmitReceive_DMA (&hi2s1, txBuf, rxBuf, BLOCK_SIZE_U16);
int offset_r_ptr;
int offset_w_ptr, w_ptr;
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
if (callback_state != 0) {
//decide if it was half or cplt callback
if (callback_state == 1) {
offset_r_ptr = 0;
offset_w_ptr = 0;
w_ptr = 0;
}
else if (callback_state == 2) {
offset_r_ptr = BLOCK_SIZE_U16;
offset_w_ptr = BLOCK_SIZE_FLOAT;
w_ptr = BLOCK_SIZE_FLOAT;
}
//restore input sample buffer to float array
for (int i=offset_r_ptr; i>16)&0xFFFF;
txBuf[i+1] = ((int)l_buf_out[w_ptr])&0xFFFF;
txBuf[i+2] = (((int)r_buf_out[w_ptr])>>16)&0xFFFF;
txBuf[i+3] = ((int)r_buf_out[w_ptr])&0xFFFF;
w_ptr++;
}
callback_state = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void HAL_I2SEx_TxRxHalfCpltCallback(I2S_HandleTypeDef *hi2s1){
callback_state = 1;
}
void HAL_I2SEx_TxRxCpltCallback(I2S_HandleTypeDef *hi2s1){
callback_state = 2;
}
/**
* @brief I2S1 Initialization Function
* @param None
* @retval None
*/
static void MX_I2S1_Init(void)
{
/* USER CODE BEGIN I2S1_Init 0 */
/* USER CODE END I2S1_Init 0 */
/* USER CODE BEGIN I2S1_Init 1 */
/* USER CODE END I2S1_Init 1 */
hi2s1.Instance = SPI1;
hi2s1.Init.Mode = I2S_MODE_MASTER_TX;
hi2s1.Init.Standard = I2S_STANDARD_PHILIPS;
hi2s1.Init.DataFormat = I2S_DATAFORMAT_24B;
hi2s1.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
hi2s1.Init.AudioFreq = I2S_AUDIOFREQ_48K;
hi2s1.Init.CPOL = I2S_CPOL_LOW;
hi2s1.Init.FirstBit = I2S_FIRSTBIT_MSB;
hi2s1.Init.WSInversion = I2S_WS_INVERSION_DISABLE;
hi2s1.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_RIGHT;
hi2s1.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE;
if (HAL_I2S_Init(&hi2s1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2S1_Init 2 */
/* USER CODE END I2S1_Init 2 */
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
/* DMA1_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LD1_Pin|LD3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : B1_Pin */
GPIO_InitStruct.Pin = B1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : LD1_Pin LD3_Pin */
GPIO_InitStruct.Pin = LD1_Pin|LD3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*Configure GPIO pin : LD2_Pin */
GPIO_InitStruct.Pin = LD2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/