/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2023 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "FreeRTOS.h" #include "cmsis_os2.h" #include "fatfs.h" #include "app_touchgfx.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stm32h7s78_discovery_audio.h" #include "audio_effects.h" #include "audio_analysis.h" #include "audio_looper.h" #include /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define AUDIO_SAMPLES 512 /* AXI SRAM, aligné 32 (cache H7S) */ int32_t adf_buf[AUDIO_SAMPLES] __attribute__((section("noncacheable_buffer"),aligned(32))); MDF_DmaConfigTypeDef sDmaConfig; #define AUDIO_OUT_SAMPLES (AUDIO_SAMPLES * 2) // = 1024 int16_t, stéréo entrelacé int16_t audio_out_buf[AUDIO_OUT_SAMPLES] __attribute__((section("noncacheable_buffer"),aligned(32))); #define FIFO_SIZE 2048 // en trames stéréo - doit rester une puissance de 2 int16_t audio_fifo[FIFO_SIZE * 2] __attribute__((section("noncacheable_buffer"),aligned(32))); // stéréo entrelacé : FIFO_SIZE trames = FIFO_SIZE*2 int16_t (L+R) /* Index monotones (jamais repliés) : write_idx n'est écrit que par push_to_fifo (IRQ ADF), * read_idx que par pull_from_fifo (IRQ audio out) -> pas de race condition entre les deux IRQ. */ volatile uint32_t fifo_write_idx = 0; volatile uint32_t fifo_read_idx = 0; /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ MDF_HandleTypeDef AdfHandle0; MDF_FilterConfigTypeDef AdfFilterConfig0; DMA_NodeTypeDef Node_GPDMA1_Channel0 __attribute__((section("noncacheable_buffer"))); DMA_QListTypeDef List_GPDMA1_Channel0; DMA_HandleTypeDef handle_GPDMA1_Channel0; CRC_HandleTypeDef hcrc; DMA2D_HandleTypeDef hdma2d; GPU2D_HandleTypeDef hgpu2d; I2C_HandleTypeDef hi2c1; I2S_HandleTypeDef hi2s6; JPEG_HandleTypeDef hjpeg; DMA_HandleTypeDef handle_HPDMA1_Channel1; DMA_HandleTypeDef handle_HPDMA1_Channel0; LTDC_HandleTypeDef hltdc; SD_HandleTypeDef hsd1; SPI_HandleTypeDef hspi4; DMA_HandleTypeDef handle_GPDMA1_Channel5; DMA_HandleTypeDef handle_GPDMA1_Channel4; /* Definitions for defaultTask */ osThreadId_t defaultTaskHandle; const osThreadAttr_t defaultTask_attributes = { .name = "defaultTask", .stack_size = 128 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* Definitions for TouchGFXTask */ osThreadId_t TouchGFXTaskHandle; const osThreadAttr_t TouchGFXTask_attributes = { .name = "TouchGFXTask", .stack_size = 4096 * 4, .priority = (osPriority_t) osPriorityNormal, }; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ static void MPU_Config(void); static void MX_GPIO_Init(void); static void MX_HPDMA1_Init(void); static void MX_GPDMA1_Init(void); static void MX_LTDC_Init(void); static void MX_CRC_Init(void); static void MX_DMA2D_Init(void); static void MX_JPEG_Init(void); static void MX_FLASH_Init(void); static void MX_I2C1_Init(void); static void MX_GPU2D_Init(void); static void MX_ICACHE_GPU2D_Init(void); static void MX_ADF1_Init(void); static void MX_SPI4_Init(void); static void MX_I2S6_Init(void); static void MX_SDMMC1_SD_Init(void); void StartDefaultTask(void *argument); extern void TouchGFX_Task(void *argument); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MPU Configuration--------------------------------------------------------*/ MPU_Config(); /* Enable the CPU Cache */ /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); /* MCU Configuration--------------------------------------------------------*/ /* Update SystemCoreClock variable according to RCC registers values. */ SystemCoreClockUpdate(); /* 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_GPIO_Init(); MX_HPDMA1_Init(); MX_GPDMA1_Init(); MX_LTDC_Init(); MX_CRC_Init(); MX_DMA2D_Init(); MX_JPEG_Init(); MX_FLASH_Init(); MX_I2C1_Init(); MX_GPU2D_Init(); MX_ICACHE_GPU2D_Init(); MX_ADF1_Init(); MX_SPI4_Init(); MX_FATFS_Init(); MX_TouchGFX_Init(); /* Call PreOsInit function */ MX_TouchGFX_PreOSInit(); /* USER CODE BEGIN 2 */ /* FIFO initialisée à moitié pleine de silence avant de démarrer les DMA */ memset(audio_fifo, 0, sizeof(audio_fifo)); fifo_write_idx = FIFO_SIZE / 2; fifo_read_idx = 0; AudioEffects_Init(); AudioAnalysis_Init(); AudioLooper_Init(); sDmaConfig.Address = (uint32_t)adf_buf; sDmaConfig.DataLength = AUDIO_SAMPLES * sizeof(int32_t); /* OCTETS */ sDmaConfig.MsbOnly = DISABLE; /* 32-bit/sample ; ENABLE si buffer int16 */ if (HAL_MDF_AcqStart_DMA(&AdfHandle0, &AdfFilterConfig0, &sDmaConfig) != HAL_OK) { Error_Handler(); } BSP_AUDIO_Init_t audioOutInit = { .Device = AUDIO_OUT_HEADPHONE, .SampleRate = AUDIO_FREQUENCY_48K, .BitsPerSample = AUDIO_RESOLUTION_16B, .ChannelsNbr = 2, .Volume = 70 }; if (BSP_AUDIO_OUT_Init(0, &audioOutInit) != BSP_ERROR_NONE) { Error_Handler(); } if (BSP_AUDIO_OUT_Play(0, (uint8_t *)audio_out_buf, AUDIO_OUT_SAMPLES * sizeof(int16_t)) != BSP_ERROR_NONE) { Error_Handler(); } /* USER CODE END 2 */ /* Init scheduler */ osKernelInitialize(); /* USER CODE BEGIN RTOS_MUTEX */ /* add mutexes, ... */ /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ /* add semaphores, ... */ /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ /* start timers, add new ones, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ /* add queues, ... */ /* USER CODE END RTOS_QUEUES */ /* Create the thread(s) */ /* creation of defaultTask */ defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes); /* creation of TouchGFXTask */ TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_EVENTS */ /* add events, ... */ /* USER CODE END RTOS_EVENTS */ /* Start scheduler */ osKernelStart(); /* We should never get here as control is now taken by the scheduler */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } /** * @brief ADF1 Initialization Function * @param None * @retval None */ static void MX_ADF1_Init(void) { /* USER CODE BEGIN ADF1_Init 0 */ /* USER CODE END ADF1_Init 0 */ /* USER CODE BEGIN ADF1_Init 1 */ /* USER CODE END ADF1_Init 1 */ /** AdfHandle0 structure initialization and HAL_MDF_Init function call */ AdfHandle0.Instance = ADF1_Filter0; AdfHandle0.Init.CommonParam.ProcClockDivider = 2; AdfHandle0.Init.CommonParam.OutputClock.Activation = ENABLE; AdfHandle0.Init.CommonParam.OutputClock.Pins = MDF_OUTPUT_CLOCK_0; AdfHandle0.Init.CommonParam.OutputClock.Divider = 4; AdfHandle0.Init.CommonParam.OutputClock.Trigger.Activation = DISABLE; AdfHandle0.Init.SerialInterface.Activation = ENABLE; AdfHandle0.Init.SerialInterface.Mode = MDF_SITF_NORMAL_SPI_MODE; AdfHandle0.Init.SerialInterface.ClockSource = MDF_SITF_CCK0_SOURCE; AdfHandle0.Init.SerialInterface.Threshold = 31; AdfHandle0.Init.FilterBistream = MDF_BITSTREAM0_FALLING; if (HAL_MDF_Init(&AdfHandle0) != HAL_OK) { Error_Handler(); } /** AdfFilterConfig0 structure initialization WARNING : only structure is filled, no specific init function call for filter */ AdfFilterConfig0.DataSource = MDF_DATA_SOURCE_BSMX; AdfFilterConfig0.Delay = 0; AdfFilterConfig0.CicMode = MDF_ONE_FILTER_SINC4; AdfFilterConfig0.DecimationRatio = 16; AdfFilterConfig0.Gain = 24; AdfFilterConfig0.ReshapeFilter.Activation = ENABLE; AdfFilterConfig0.ReshapeFilter.DecimationRatio = MDF_RSF_DECIMATION_RATIO_4; AdfFilterConfig0.HighPassFilter.Activation = ENABLE; AdfFilterConfig0.HighPassFilter.CutOffFrequency = MDF_HPF_CUTOFF_0_000625FPCM; AdfFilterConfig0.SoundActivity.Activation = DISABLE; AdfFilterConfig0.AcquisitionMode = MDF_MODE_ASYNC_CONT; AdfFilterConfig0.FifoThreshold = MDF_FIFO_THRESHOLD_NOT_EMPTY; AdfFilterConfig0.DiscardSamples = 0; /* USER CODE BEGIN ADF1_Init 2 */ /* USER CODE END ADF1_Init 2 */ } /** * @brief CRC Initialization Function * @param None * @retval None */ static void MX_CRC_Init(void) { /* USER CODE BEGIN CRC_Init 0 */ /* USER CODE END CRC_Init 0 */ /* USER CODE BEGIN CRC_Init 1 */ /* USER CODE END CRC_Init 1 */ hcrc.Instance = CRC; hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE; hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE; hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; if (HAL_CRC_Init(&hcrc) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN CRC_Init 2 */ /* USER CODE END CRC_Init 2 */ } /** * @brief DMA2D Initialization Function * @param None * @retval None */ static void MX_DMA2D_Init(void) { /* USER CODE BEGIN DMA2D_Init 0 */ /* USER CODE END DMA2D_Init 0 */ /* USER CODE BEGIN DMA2D_Init 1 */ /* USER CODE END DMA2D_Init 1 */ hdma2d.Instance = DMA2D; hdma2d.Init.Mode = DMA2D_R2M; hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888; hdma2d.Init.OutputOffset = 0; if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN DMA2D_Init 2 */ /* USER CODE END DMA2D_Init 2 */ } /** * @brief FLASH Initialization Function * @param None * @retval None */ static void MX_FLASH_Init(void) { /* USER CODE BEGIN FLASH_Init 0 */ /* USER CODE END FLASH_Init 0 */ FLASH_OBProgramInitTypeDef pOBInit = {0}; /* USER CODE BEGIN FLASH_Init 1 */ /* USER CODE END FLASH_Init 1 */ HAL_FLASHEx_OBGetConfig(&pOBInit); if ((pOBInit.USERConfig1 & OB_IWDG_SW) != OB_IWDG_SW|| (pOBInit.USERConfig1 & OB_XSPI1_HSLV_ENABLE) != OB_XSPI1_HSLV_ENABLE|| (pOBInit.USERConfig1 & OB_XSPI2_HSLV_ENABLE) != OB_XSPI2_HSLV_ENABLE|| (pOBInit.USERConfig2 & OB_I2C_NI3C_I2C) != OB_I2C_NI3C_I2C) { if (HAL_FLASH_Unlock() != HAL_OK) { Error_Handler(); } if (HAL_FLASH_OB_Unlock() != HAL_OK) { Error_Handler(); } pOBInit.OptionType = OPTIONBYTE_USER; pOBInit.USERType = OB_USER_IWDG_SW|OB_USER_XSPI1_HSLV |OB_USER_XSPI2_HSLV|OB_USER_I2C_NI3C; pOBInit.USERConfig1 = OB_IWDG_SW|OB_XSPI1_HSLV_ENABLE |OB_XSPI2_HSLV_ENABLE; pOBInit.USERConfig2 = OB_I2C_NI3C_I2C; if (HAL_FLASHEx_OBProgram(&pOBInit) != HAL_OK) { Error_Handler(); } if (HAL_FLASH_OB_Lock() != HAL_OK) { Error_Handler(); } if (HAL_FLASH_Lock() != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN FLASH_Init 2 */ /* USER CODE END FLASH_Init 2 */ } /** * @brief GPDMA1 Initialization Function * @param None * @retval None */ static void MX_GPDMA1_Init(void) { /* USER CODE BEGIN GPDMA1_Init 0 */ /* USER CODE END GPDMA1_Init 0 */ /* Peripheral clock enable */ __HAL_RCC_GPDMA1_CLK_ENABLE(); /* GPDMA1 interrupt Init */ HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 2, 0); HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn); HAL_NVIC_SetPriority(GPDMA1_Channel4_IRQn, 5, 0); HAL_NVIC_EnableIRQ(GPDMA1_Channel4_IRQn); HAL_NVIC_SetPriority(GPDMA1_Channel5_IRQn, 5, 0); HAL_NVIC_EnableIRQ(GPDMA1_Channel5_IRQn); /* USER CODE BEGIN GPDMA1_Init 1 */ /* USER CODE END GPDMA1_Init 1 */ /* USER CODE BEGIN GPDMA1_Init 2 */ /* USER CODE END GPDMA1_Init 2 */ } /** * @brief GPU2D Initialization Function * @param None * @retval None */ static void MX_GPU2D_Init(void) { /* USER CODE BEGIN GPU2D_Init 0 */ /* USER CODE END GPU2D_Init 0 */ /* USER CODE BEGIN GPU2D_Init 1 */ /* USER CODE END GPU2D_Init 1 */ hgpu2d.Instance = GPU2D; if (HAL_GPU2D_Init(&hgpu2d) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN GPU2D_Init 2 */ /* USER CODE END GPU2D_Init 2 */ } /** * @brief HPDMA1 Initialization Function * @param None * @retval None */ static void MX_HPDMA1_Init(void) { /* USER CODE BEGIN HPDMA1_Init 0 */ /* USER CODE END HPDMA1_Init 0 */ /* Peripheral clock enable */ __HAL_RCC_HPDMA1_CLK_ENABLE(); /* HPDMA1 interrupt Init */ HAL_NVIC_SetPriority(HPDMA1_Channel0_IRQn, 5, 0); HAL_NVIC_EnableIRQ(HPDMA1_Channel0_IRQn); HAL_NVIC_SetPriority(HPDMA1_Channel1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(HPDMA1_Channel1_IRQn); /* USER CODE BEGIN HPDMA1_Init 1 */ /* USER CODE END HPDMA1_Init 1 */ /* USER CODE BEGIN HPDMA1_Init 2 */ /* USER CODE END HPDMA1_Init 2 */ } /** * @brief I2C1 Initialization Function * @param None * @retval None */ static void MX_I2C1_Init(void) { /* USER CODE BEGIN I2C1_Init 0 */ /* USER CODE END I2C1_Init 0 */ /* USER CODE BEGIN I2C1_Init 1 */ /* USER CODE END I2C1_Init 1 */ hi2c1.Instance = I2C1; hi2c1.Init.Timing = 0x00E063FF; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } /** Configure Analogue filter */ if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) { Error_Handler(); } /** Configure Digital filter */ if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ /* USER CODE END I2C1_Init 2 */ } /** * @brief I2S6 Initialization Function * @param None * @retval None */ static void MX_I2S6_Init(void) { /* USER CODE BEGIN I2S6_Init 0 */ /* USER CODE END I2S6_Init 0 */ /* USER CODE BEGIN I2S6_Init 1 */ /* USER CODE END I2S6_Init 1 */ hi2s6.Instance = SPI6; hi2s6.Init.Mode = I2S_MODE_MASTER_TX; hi2s6.Init.Standard = I2S_STANDARD_PHILIPS; hi2s6.Init.DataFormat = I2S_DATAFORMAT_16B; hi2s6.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; hi2s6.Init.AudioFreq = I2S_AUDIOFREQ_48K; hi2s6.Init.CPOL = I2S_CPOL_LOW; hi2s6.Init.FirstBit = I2S_FIRSTBIT_MSB; hi2s6.Init.WSInversion = I2S_WS_INVERSION_DISABLE; hi2s6.Init.Data24BitAlignment = I2S_DATA_24BIT_ALIGNMENT_RIGHT; hi2s6.Init.MasterKeepIOState = I2S_MASTER_KEEP_IO_STATE_DISABLE; if (HAL_I2S_Init(&hi2s6) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2S6_Init 2 */ /* USER CODE END I2S6_Init 2 */ } /** * @brief ICACHE_GPU2D Initialization Function * @param None * @retval None */ static void MX_ICACHE_GPU2D_Init(void) { /* USER CODE BEGIN ICACHE_GPU2D_Init 0 */ /* USER CODE END ICACHE_GPU2D_Init 0 */ /* USER CODE BEGIN ICACHE_GPU2D_Init 1 */ /* USER CODE END ICACHE_GPU2D_Init 1 */ /** Enable instruction cache (default 2-ways set associative cache) */ if (HAL_ICACHE_Enable() != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ICACHE_GPU2D_Init 2 */ /* USER CODE END ICACHE_GPU2D_Init 2 */ } /** * @brief JPEG Initialization Function * @param None * @retval None */ static void MX_JPEG_Init(void) { /* USER CODE BEGIN JPEG_Init 0 */ /* USER CODE END JPEG_Init 0 */ /* USER CODE BEGIN JPEG_Init 1 */ /* USER CODE END JPEG_Init 1 */ hjpeg.Instance = JPEG; if (HAL_JPEG_Init(&hjpeg) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN JPEG_Init 2 */ /* USER CODE END JPEG_Init 2 */ } /** * @brief LTDC Initialization Function * @param None * @retval None */ static void MX_LTDC_Init(void) { /* USER CODE BEGIN LTDC_Init 0 */ /* USER CODE END LTDC_Init 0 */ LTDC_LayerCfgTypeDef pLayerCfg = {0}; /* USER CODE BEGIN LTDC_Init 1 */ /* USER CODE END LTDC_Init 1 */ hltdc.Instance = LTDC; hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL; hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL; hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC; hltdc.Init.HorizontalSync = 4; hltdc.Init.VerticalSync = 4; hltdc.Init.AccumulatedHBP = 12; hltdc.Init.AccumulatedVBP = 12; hltdc.Init.AccumulatedActiveW = 812; hltdc.Init.AccumulatedActiveH = 492; hltdc.Init.TotalWidth = 820; hltdc.Init.TotalHeigh = 506; hltdc.Init.Backcolor.Blue = 0; hltdc.Init.Backcolor.Green = 0; hltdc.Init.Backcolor.Red = 0; if (HAL_LTDC_Init(&hltdc) != HAL_OK) { Error_Handler(); } pLayerCfg.WindowX0 = 0; pLayerCfg.WindowX1 = 800; pLayerCfg.WindowY0 = 0; pLayerCfg.WindowY1 = 480; pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; pLayerCfg.Alpha = 255; pLayerCfg.Alpha0 = 0; pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; pLayerCfg.FBStartAdress = 0; pLayerCfg.ImageWidth = 800; pLayerCfg.ImageHeight = 480; pLayerCfg.Backcolor.Blue = 0; pLayerCfg.Backcolor.Green = 0; pLayerCfg.Backcolor.Red = 0; if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN LTDC_Init 2 */ /* USER CODE END LTDC_Init 2 */ } /** * @brief SDMMC1 Initialization Function * @param None * @retval None */ static void MX_SDMMC1_SD_Init(void) { /* USER CODE BEGIN SDMMC1_Init 0 */ /* USER CODE END SDMMC1_Init 0 */ /* USER CODE BEGIN SDMMC1_Init 1 */ /* USER CODE END SDMMC1_Init 1 */ hsd1.Instance = SDMMC1; hsd1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; hsd1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; hsd1.Init.BusWide = SDMMC_BUS_WIDE_4B; hsd1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE; hsd1.Init.ClockDiv = 0; if (HAL_SD_Init(&hsd1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SDMMC1_Init 2 */ /* USER CODE END SDMMC1_Init 2 */ } /** * @brief SPI4 Initialization Function * @param None * @retval None */ static void MX_SPI4_Init(void) { /* USER CODE BEGIN SPI4_Init 0 */ /* USER CODE END SPI4_Init 0 */ /* USER CODE BEGIN SPI4_Init 1 */ /* USER CODE END SPI4_Init 1 */ /* SPI4 parameter configuration*/ hspi4.Instance = SPI4; hspi4.Init.Mode = SPI_MODE_MASTER; hspi4.Init.Direction = SPI_DIRECTION_2LINES; hspi4.Init.DataSize = SPI_DATASIZE_8BIT; hspi4.Init.CLKPolarity = SPI_POLARITY_LOW; hspi4.Init.CLKPhase = SPI_PHASE_1EDGE; hspi4.Init.NSS = SPI_NSS_SOFT; hspi4.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi4.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi4.Init.TIMode = SPI_TIMODE_DISABLE; hspi4.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi4.Init.CRCPolynomial = 0x7; hspi4.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; hspi4.Init.NSSPolarity = SPI_NSS_POLARITY_LOW; hspi4.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; hspi4.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; hspi4.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; hspi4.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; hspi4.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE; hspi4.Init.IOSwap = SPI_IO_SWAP_DISABLE; hspi4.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY; hspi4.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH; if (HAL_SPI_Init(&hspi4) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI4_Init 2 */ /* USER CODE END SPI4_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOE_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOM_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SD_Detect_GPIO_Port, SD_Detect_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LCD_EN_GPIO_Port, LCD_EN_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LCD_BL_CTRL_GPIO_Port, LCD_BL_CTRL_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(SPI4_CS_GPIO_Port, SPI4_CS_Pin, GPIO_PIN_SET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOD, ST67_BOOT_Pin|ST67_CHIP_EN_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : SD_Detect_Pin */ GPIO_InitStruct.Pin = SD_Detect_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(SD_Detect_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LCD_EN_Pin */ GPIO_InitStruct.Pin = LCD_EN_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LCD_EN_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : TP_IRQ_Pin */ GPIO_InitStruct.Pin = TP_IRQ_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(TP_IRQ_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LCD_BL_CTRL_Pin */ GPIO_InitStruct.Pin = LCD_BL_CTRL_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LCD_BL_CTRL_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : SPI4_CS_Pin */ GPIO_InitStruct.Pin = SPI4_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(SPI4_CS_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : MIC_DET_Pin */ GPIO_InitStruct.Pin = MIC_DET_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(MIC_DET_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : ST67_BOOT_Pin ST67_CHIP_EN_Pin */ GPIO_InitStruct.Pin = ST67_BOOT_Pin|ST67_CHIP_EN_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /*Configure GPIO pin : SPI_RDY_Pin */ GPIO_InitStruct.Pin = SPI_RDY_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(SPI_RDY_GPIO_Port, &GPIO_InitStruct); /* EXTI interrupt init*/ HAL_NVIC_SetPriority(TP_IRQ_EXTI_IRQn, 5, 0); HAL_NVIC_EnableIRQ(TP_IRQ_EXTI_IRQn); HAL_NVIC_SetPriority(SPI_RDY_EXTI_IRQn, 5, 0); HAL_NVIC_EnableIRQ(SPI_RDY_EXTI_IRQn); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ static inline float adf_sample_to_float(int32_t raw) { int32_t v = raw >> 8; // 24 bits -> valeur signee sur 24 bits return (float)v / 8388608.0f; // normalisation en [-1.0, 1.0] } static inline int16_t float_to_pcm16(float x) { float v = x * 32767.0f; if (v > 32767.0f) v = 32767.0f; if (v < -32768.0f) v = -32768.0f; return (int16_t)v; } static void push_to_fifo(int32_t raw) { if ((fifo_write_idx - fifo_read_idx) >= FIFO_SIZE) { return; // FIFO pleine : on jette l'échantillon plutôt que d'écraser du non-lu } float sample = adf_sample_to_float(raw); sample = AudioEffects_Process(sample); sample = AudioLooper_Process(sample); AudioAnalysis_PushSample(sample); int16_t s = float_to_pcm16(sample); uint32_t idx = fifo_write_idx & (FIFO_SIZE - 1); audio_fifo[idx * 2] = s; audio_fifo[idx * 2 + 1] = s; fifo_write_idx++; } static void pull_from_fifo(int16_t *dst, uint32_t nbFrames) { for (uint32_t i = 0; i < nbFrames; i++) { if (fifo_write_idx == fifo_read_idx) { uint32_t last = (fifo_read_idx - 1) & (FIFO_SIZE - 1); dst[2*i] = audio_fifo[last * 2]; dst[2*i + 1] = audio_fifo[last * 2 + 1]; } else { uint32_t idx = fifo_read_idx & (FIFO_SIZE - 1); dst[2*i] = audio_fifo[idx * 2]; dst[2*i + 1] = audio_fifo[idx * 2 + 1]; fifo_read_idx++; } } } void HAL_MDF_AcqHalfCpltCallback(MDF_HandleTypeDef *hmdf) { (void)hmdf; for (int i = 0; i < AUDIO_SAMPLES/2; i++) { push_to_fifo(adf_buf[i]); } } void HAL_MDF_AcqCpltCallback(MDF_HandleTypeDef *hmdf) { (void)hmdf; for (int i = AUDIO_SAMPLES/2; i < AUDIO_SAMPLES; i++) { push_to_fifo(adf_buf[i]); } } void BSP_AUDIO_OUT_HalfTransfer_CallBack(uint32_t Instance) { pull_from_fifo(&audio_out_buf[0], AUDIO_OUT_SAMPLES/2 / 2); // /2 car stéréo } void BSP_AUDIO_OUT_TransferComplete_CallBack(uint32_t Instance) { pull_from_fifo(&audio_out_buf[AUDIO_OUT_SAMPLES/2], AUDIO_OUT_SAMPLES/2 / 2); } HAL_StatusTypeDef MX_I2S6_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t SampleRate) { UNUSED(hi2s); UNUSED(SampleRate); RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; /* PLL2Q est déjà actif (614.4 MHz VCO / 13 = 47.26 MHz) via SystemClock_Config(). On se contente de router SPI6 dessus, sans reconfigurer aucun PLL. */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SPI6; PeriphClkInitStruct.Spi6ClockSelection = RCC_SPI6CLKSOURCE_PLL2Q; return HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); } /* USER CODE END 4 */ /* USER CODE BEGIN Header_StartDefaultTask */ /** * @brief Function implementing the defaultTask thread. * @param argument: Not used * @retval None */ /* USER CODE END Header_StartDefaultTask */ void StartDefaultTask(void *argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for (;;) { osDelay(1); } /* USER CODE END 5 */ } /* MPU Configuration */ static void MPU_Config(void) { MPU_Region_InitTypeDef MPU_InitStruct = {0}; /* Disables the MPU */ HAL_MPU_Disable(); /* Disables all MPU regions */ for(uint8_t i=0; i<__MPU_REGIONCOUNT; i++) { HAL_MPU_DisableRegion(i); } /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Enable = MPU_REGION_ENABLE; MPU_InitStruct.Number = MPU_REGION_NUMBER0; MPU_InitStruct.BaseAddress = 0x0; MPU_InitStruct.Size = MPU_REGION_SIZE_4GB; MPU_InitStruct.SubRegionDisable = 0x87; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER1; MPU_InitStruct.BaseAddress = 0x70000000; MPU_InitStruct.Size = MPU_REGION_SIZE_128MB; MPU_InitStruct.SubRegionDisable = 0x0; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1; MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS; MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER2; MPU_InitStruct.Size = MPU_REGION_SIZE_2MB; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER3; MPU_InitStruct.BaseAddress = 0x90000000; MPU_InitStruct.Size = MPU_REGION_SIZE_32MB; MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER4; MPU_InitStruct.BaseAddress = 0x20000000; MPU_InitStruct.Size = MPU_REGION_SIZE_64KB; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER5; MPU_InitStruct.BaseAddress = 0x24000000; MPU_InitStruct.Size = MPU_REGION_SIZE_512KB; MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER6; MPU_InitStruct.BaseAddress = 0x24060000; MPU_InitStruct.Size = MPU_REGION_SIZE_64KB; MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; HAL_MPU_ConfigRegion(&MPU_InitStruct); /** Initializes and configures the Region and the memory to be protected */ MPU_InitStruct.Number = MPU_REGION_NUMBER7; MPU_InitStruct.BaseAddress = 0x24070000; MPU_InitStruct.Size = MPU_REGION_SIZE_16KB; HAL_MPU_ConfigRegion(&MPU_InitStruct); /* Enables the MPU */ HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT); } /** * @brief Period elapsed callback in non blocking mode * @note This function is called when TIM6 interrupt took place, inside * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment * a global variable "uwTick" used as application time base. * @param htim TIM handle * @retval None */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { /* USER CODE BEGIN Callback 0 */ /* USER CODE END Callback 0 */ if (htim->Instance == TIM6) { HAL_IncTick(); } /* USER CODE BEGIN Callback 1 */ /* USER CODE END Callback 1 */ } /** * @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 */