/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 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" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "string.h" #include "ai_platform.h" #include "network.h" #include "network_data.h" #include "arm_math.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ #define DATA_USER 512 /* Input signal sampling rate */ #define SAMPLE_RATE 16000U #define FRAME_SIZE 512//in typical mfcc 1024,512 and 256 #define FRAME_SHIFT 256 //Always 50% of the frame_size #define NUM_MFCC_COEFFS 13 #define NUM_FILTER_BANKS 26//always double of the num_filter_bank /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; CRC_HandleTypeDef hcrc; UART_HandleTypeDef huart2; /* USER CODE BEGIN PV */ int n = 0; uint16_t ecg_x = 0.0; float ecg_buffer[DATA_USER] = {0}; arm_rfft_fast_instance_f32 fft_instance; arm_dct4_instance_f32 dct_instance; arm_cfft_radix4_instance_f32 cfft_instance; arm_rfft_instance_f32 rfft_instance; float mfcc_features[NUM_MFCC_COEFFS * (DATA_USER - FRAME_SIZE) / FRAME_SHIFT + 1]; uint32_t num_frames = (DATA_USER - FRAME_SIZE) / FRAME_SHIFT + 1; float32_t frame[FRAME_SIZE]; float32_t fft_output[FRAME_SIZE]; float32_t power_spectrum[FRAME_SIZE / 2 + 1]; float32_t mel_energies[NUM_FILTER_BANKS]; float32_t log_mel_energies[NUM_FILTER_BANKS]; float32_t dct_output[NUM_FILTER_BANKS]; float32_t pre_emphasized[DATA_USER]; //for cube ai ai_handle network; float aiInData[AI_NETWORK_IN_1_SIZE]; float aiOutData[AI_NETWORK_OUT_1_SIZE]; ai_u8 activations[AI_NETWORK_DATA_ACTIVATIONS_SIZE]; const char* activities[AI_NETWORK_OUT_1_SIZE] = { "1" }; ai_buffer * ai_input; ai_buffer * ai_output; int write_index = 0; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART2_UART_Init(void); static void MX_ADC1_Init(void); static void MX_CRC_Init(void); /* USER CODE BEGIN PFP */ void fill_ecg_buffer(void); int __io_putchar(int ch); void pre_emphasis(float32_t *input, float32_t *output, uint32_t length, float32_t alpha); void apply_hamming_window(float32_t *frame, uint32_t length); void compute_mel_filter_banks(float32_t *power_spectrum, float32_t *mel_energies); void compute_dct(float32_t *input, float32_t *output, uint32_t length); void compute_mfcc(float32_t *input, uint32_t length, float32_t *mfcc); static void AI_Init(void); static void AI_Run(float *pIn, float *pOut); static uint32_t argmax(const float * values, uint32_t len); /* 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 */ uint32_t write_index = 0; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART2_UART_Init(); MX_ADC1_Init(); MX_CRC_Init(); /* USER CODE BEGIN 2 */ printf("Initializing the system"); AI_Init(); HAL_ADC_Start(&hadc1); arm_rfft_fast_init_f32(&fft_instance, FRAME_SIZE); arm_dct4_init_f32(&dct_instance, &rfft_instance, &cfft_instance, NUM_FILTER_BANKS, NUM_FILTER_BANKS / 2, 0.5); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ ecg_x = HAL_ADC_GetValue(&hadc1); ecg_buffer[n] = ecg_x; printf("%d ",ecg_x); HAL_ADC_Start(&hadc1); n++; if(n == DATA_USER) { n = 0; compute_mfcc(ecg_buffer, DATA_USER, mfcc_features); for(int i =0;i max_value) { max_value = values[i]; max_index = i; } } return max_index; } //Now to compute the mfcc features int __io_putchar(int ch) { HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY); return ch; } // Pre-emphasis filter void pre_emphasis(float32_t *input, float32_t *output, uint32_t length, float32_t alpha) { // printf("\r\n Pre-Empahsis"); output[0] = input[0]; for (uint32_t i = 1; i < length; i++) { output[i] = input[i] - alpha * input[i - 1]; // printf("After pre-emphasis[%d]: %0.2f \r\n",i,output[i]); } } void apply_hamming_window(float32_t *frame, uint32_t length) { for (uint32_t i = 0; i < length; i++) { frame[i] *= 0.54 - 0.46 * cosf(2 * PI * i / (length - 1)); // printf("After hamming window[%d]: %0.2f \r\n",i,frame[i]); } } void compute_mel_filter_banks(float32_t *power_spectrum, float32_t *mel_energies) { float32_t mel_min = 0; float32_t mel_max = 2595 * log10(1 + (SAMPLE_RATE / 2) / 700.0); float32_t mel_points[NUM_FILTER_BANKS + 2]; float32_t hz_points[NUM_FILTER_BANKS + 2]; uint32_t bin[NUM_FILTER_BANKS + 2]; for (uint32_t i = 0; i < NUM_FILTER_BANKS + 2; i++) { mel_points[i] = mel_min + i * (mel_max - mel_min) / (NUM_FILTER_BANKS + 1); hz_points[i] = 700 * (pow(10, mel_points[i] / 2595) - 1); bin[i] = (uint32_t) floor((FRAME_SIZE + 1) * hz_points[i] / SAMPLE_RATE); } for (uint32_t i = 0; i < NUM_FILTER_BANKS; i++) { mel_energies[i] = 0; for (uint32_t j = bin[i]; j < bin[i + 1]; j++) { mel_energies[i] += (j - bin[i]) / (float32_t) (bin[i + 1] - bin[i]) * power_spectrum[j]; } for (uint32_t j = bin[i + 1]; j < bin[i + 2]; j++) { mel_energies[i] += (bin[i + 2] - j) / (float32_t) (bin[i + 2] - bin[i + 1]) * power_spectrum[j]; } // printf("After Mel-Energies[%d]: %0.2f \r\n",i,mel_energies[i]); } } void compute_dct(float32_t *input, float32_t *output, uint32_t length) { for (uint32_t k = 0; k < NUM_MFCC_COEFFS; k++) { output[k] = 0; for (uint32_t n = 0; n < length; n++) { output[k] += input[n] * cosf(PI * k * (2 * n + 1) / (2 * length)); } // printf("After DCT[%d]: %0.2f \r\n",k,output[k]); } } void compute_mfcc(float32_t *input, uint32_t length, float32_t *mfcc) { float32_t pre_emphasized[length]; pre_emphasis(input, pre_emphasized, length, 0.97); for (uint32_t i = 0; i < num_frames; i++) { memcpy(frame, &pre_emphasized[i * FRAME_SHIFT], FRAME_SIZE * sizeof(float32_t)); apply_hamming_window(frame, FRAME_SIZE); arm_rfft_fast_f32(&fft_instance, frame, fft_output, 0); arm_cmplx_mag_squared_f32(fft_output, power_spectrum, FRAME_SIZE/2+1 ); compute_mel_filter_banks(power_spectrum, mel_energies); for (uint32_t k = 0; k < NUM_FILTER_BANKS; k++) { log_mel_energies[k] = logf(mel_energies[k] + 1e-19); if(isinf(log_mel_energies[i])){ log_mel_energies[i] = -43.7f; } } compute_dct(log_mel_energies, dct_output, NUM_FILTER_BANKS); for (uint32_t m = 0; m < NUM_MFCC_COEFFS; m++) { mfcc_features[i * NUM_MFCC_COEFFS + m] = dct_output[m]; printf("MFFC Features[%d]: %0.2f\r\n",m,mfcc_features[i * NUM_MFCC_COEFFS + m]); } } } /* 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 */