close

image

image

image

image

image

image

image

image

image

/* 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"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Filter.h"
#include <stdlib.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define FIR_LENGTH 21
#define SAMPLE_RATE_HZ 44100.0f
#define UINT16_TO_FLOAT 0.00001525878f
#define FLOAT_TO_UINT16 32768.0f
#define AUDIO_BUFFER_SIZE 256
#define outputVolume 0.003f
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc4;

DAC_HandleTypeDef hdac1;

OPAMP_HandleTypeDef hopamp4;

TIM_HandleTypeDef htim3;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */

// FIR Filter
float coefficients_fir[FIR_LENGTH] = {-0.00591377164083496,    -0.00308644290781836, 0.0219915242479900, -0.0406091088853957, 0.0248358370392694, 0.0436025009813950, -0.122104025088665, 0.127561193706986, -0.0222146622289817, -0.127176005248907, 0.197549418233472, -0.127176005248907, -0.0222146622289817, 0.127561193706986, -0.122104025088665, 0.0436025009813950, 0.0248358370392694, -0.0406091088853957, 0.0219915242479900, -0.00308644290781836, -0.00591377164083496};
//float coefficients_fir[FIR_LENGTH] = {-4.94196577368864e-05, -0.000500524897433379, -0.00241883585285529, -0.00717831893088856, -0.0136987457847953, -0.0141484446157865, 0.00624169881266751, 0.0593418898052441, 0.138401253706343, 0.212485403281901, 0.243048097547224, 0.212485403281901, 0.138401253706343, 0.0593418898052441, 0.00624169881266751, -0.0141484446157865, -0.0136987457847953, -0.00717831893088856, -0.00241883585285529, -0.000500524897433379, -4.94196577368864e-05};
//float coefficients_fir[FIR_LENGTH] = {-6.93308673440112e-05, -0.000153771688981960, 0.000297670476897782, 0.00286422377013332, 0.0102702372548520, 0.0255381541964255, 0.0501337640750906, 0.0819808825919817, 0.114800218006465, 0.139776143494755, 0.149134882108085, 0.139776143494755, 0.114800218006465, 0.0819808825919817, 0.0501337640750906, 0.0255381541964255, 0.0102702372548520, 0.00286422377013332, 0.000297670476897782, -0.000153771688981960, -6.93308673440112e-05};
uint32_t buffer_fir[FIR_LENGTH];
uint32_t counter_fir;
volatile uint32_t output_fir;
volatile uint32_t original;
float out_fir;
uint32_t signal;
uint32_t index_fir;
Filter filt, filt2;
static volatile uint16_t *bufferCHin;
static uint16_t *adcOut[AUDIO_BUFFER_SIZE];
static volatile uint16_t *bufferCHout = &adcOut[0];
static float filterDividing3, filterDividing4;
static float filtered3, filtered4;
static uint16_t blackout3, blueout4;
static uint32_t hh;

/* 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_TIM3_Init(void);
static void MX_DAC1_Init(void);
static void MX_ADC4_Init(void);
static void MX_OPAMP4_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void Process(uint16_t *adcIn)
{
    //Filter
    //Duty cycle (AUDIO_BUFFER_SIZE/2 - 1)
    for(uint8_t n = 0; n < AUDIO_BUFFER_SIZE / 2 - 1; n += 2)
    {
        adcIn[AUDIO_BUFFER_SIZE/2] = 1024 - adcIn[0];
        bufferCHin = adcIn[AUDIO_BUFFER_SIZE/2];

        /*Divide the adc into 2 channel, normalize the signal amplitude*/
        filterDividing3 = UINT16_TO_FLOAT * ((float) bufferCHin[n]);

        /*Filtered compare not filtered*/
        //Filters initialization
        Filter_Init(&filt, SAMPLE_RATE_HZ);
        Filter_SetParameters(&filt, 7700.0f, 50.0f, 0.3f);
        filtered3 = Filter_Update(&filt, filterDividing3);    /*Filtered signals*/

        //Filter_Init(&filt2, SAMPLE_RATE_HZ);
        //Filter_SetParameters(&filt2, 16000.0f, 500.0f, 0.5f);
        //filtered4 = Filter_Update(&filt2, filtered3);        /*Original signals*/
        //filtered4 = filterDividing4;                        /*Original signals*/

        /*normalize the signal amplitude*/
        blackout3 = (uint16_t) (FLOAT_TO_UINT16 * outputVolume * filtered3);
        //blueout4 = (uint32_t) (FLOAT_TO_UINT32 * outputVolume * filtered4);

        bufferCHout[n] = blackout3;
        //bufferCHout[n+1] = blueout4;

        adcOut[AUDIO_BUFFER_SIZE/2] = adcOut[0];
        hh = adcOut[AUDIO_BUFFER_SIZE/2];
        //TIM3->CCR4 = adcOut[AUDIO_BUFFER_SIZE/2];
    }
}

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* 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_TIM3_Init();
  MX_DAC1_Init();
  MX_ADC4_Init();
  MX_OPAMP4_Init();
  /* USER CODE BEGIN 2 */
  HAL_OPAMP_Start(&hopamp4);
  HAL_ADC_Start(&hadc4);
  HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
  HAL_DAC_Start(&hdac1, DAC_CHANNEL_1);
  HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 559); //0.45V G=2 vin_amp=1
  //Filters initialization
  //Filter_Init(&filt, SAMPLE_RATE_HZ);
  //Filter_SetParameters(&filt, 7500.0f, 500.0f, 0.5f);
  //Filter_Init(&filt2, SAMPLE_RATE_HZ);
  //Filter_SetParameters(&filt2, 16000.0f, 500.0f, 0.5f);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_ADC34
                              |RCC_PERIPHCLK_TIM34;
  PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
  PeriphClkInit.Adc34ClockSelection = RCC_ADC34PLLCLK_DIV1;
  PeriphClkInit.Tim34ClockSelection = RCC_TIM34CLK_HCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC4_Init(void)
{

  /* USER CODE BEGIN ADC4_Init 0 */

  /* USER CODE END ADC4_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC4_Init 1 */

  /* USER CODE END ADC4_Init 1 */

  /** Common config
  */
  hadc4.Instance = ADC4;
  hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
  hadc4.Init.Resolution = ADC_RESOLUTION_12B;
  hadc4.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc4.Init.ContinuousConvMode = DISABLE;
  hadc4.Init.DiscontinuousConvMode = DISABLE;
  hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc4.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_CC1;
  hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc4.Init.NbrOfConversion = 1;
  hadc4.Init.DMAContinuousRequests = DISABLE;
  hadc4.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc4.Init.LowPowerAutoWait = DISABLE;
  hadc4.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  if (HAL_ADC_Init(&hadc4) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_3;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc4, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC4_Init 2 */

  /* USER CODE END ADC4_Init 2 */

}

/**
  * @brief DAC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_DAC1_Init(void)
{

  /* USER CODE BEGIN DAC1_Init 0 */

  /* USER CODE END DAC1_Init 0 */

  DAC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN DAC1_Init 1 */

  /* USER CODE END DAC1_Init 1 */

  /** DAC Initialization
  */
  hdac1.Instance = DAC1;
  if (HAL_DAC_Init(&hdac1) != HAL_OK)
  {
    Error_Handler();
  }

  /** DAC channel OUT1 config
  */
  sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN DAC1_Init 2 */

  /* USER CODE END DAC1_Init 2 */

}

/**
  * @brief OPAMP4 Initialization Function
  * @param None
  * @retval None
  */
static void MX_OPAMP4_Init(void)
{

  /* USER CODE BEGIN OPAMP4_Init 0 */

  /* USER CODE END OPAMP4_Init 0 */

  /* USER CODE BEGIN OPAMP4_Init 1 */

  /* USER CODE END OPAMP4_Init 1 */
  hopamp4.Instance = OPAMP4;
  hopamp4.Init.Mode = OPAMP_PGA_MODE;
  hopamp4.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO2;
  hopamp4.Init.TimerControlledMuxmode = OPAMP_TIMERCONTROLLEDMUXMODE_DISABLE;
  hopamp4.Init.PgaConnect = OPAMP_PGA_CONNECT_INVERTINGINPUT_IO0;
  hopamp4.Init.PgaGain = OPAMP_PGA_GAIN_2;
  hopamp4.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;
  if (HAL_OPAMP_Init(&hopamp4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN OPAMP4_Init 2 */

  /* USER CODE END OPAMP4_Init 2 */

}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 0;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 1023;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 511;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.Pulse = 0;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */
  HAL_TIM_MspPostInit(&htim3);

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 38400;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_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_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &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);

  /*Configure GPIO pin : PC5 */
  GPIO_InitStruct.Pin = GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void HAL_TIM_PWM_PulseFinishedCallback(TIM_HandleTypeDef *htim)
{
    uint32_t adc = HAL_ADC_GetValue(&hadc4) >> 2;
    //uint32_t nc;
    //float l, u;
    //float p = 410.0f;

    //l = (((float) adc) - p);
    //u = -l + p;
    //nc = (uint32_t) u;
    //nc = (1023 - adc);

    if(htim == &htim3)
    {
        //TIM3->CCR3 = adc;
        //TIM3->CCR4 = adc;    //black
        //TIM3->CCR4 = (1024 - adc);
    }
    //original = adc;
    uint16_t adcIn[AUDIO_BUFFER_SIZE];
    adcIn[0] = HAL_ADC_GetValue(&hadc4) >> 2;
    Process(adcIn);

    //TIM3->CCR3 = adc; //black
    //TIM3->CCR4 = adc; //blue

    //FIR Filter
    output_fir = 0;
    buffer_fir[counter_fir] = adcIn[0];

    for(int i = 0; i < FIR_LENGTH; i++)
    {
        index_fir = counter_fir - i;
        if(index_fir < 0)
        {
            index_fir = FIR_LENGTH + counter_fir - i;
        }
        output_fir += coefficients_fir[i] * buffer_fir[index_fir];
        TIM3->CCR3 += coefficients_fir[i] * buffer_fir[index_fir];
        //TIM3->CCR4 += coefficients_fir[i] * buffer_fir[index_fir];
    }
    //TIM3->CCR4 = 0;
    counter_fir++;
    if(counter_fir == FIR_LENGTH)
    {
        counter_fir = 0;
    }
    //TIM3->CCR4 = output_fir;
}

/* 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 */
 

 

 

 

 

 

/*
 * Filter.h
 *
 *  Created on: 7 Jun 2023
 *      Author: User
 */

#ifndef INC_FILTER_H_
#define INC_FILTER_H_

#include <math.h>
#include <stdint.h>

typedef struct Filter{

    /* Sample time (s) */
    float sampleTime_s;

    /*Filter I/O (x[0]/y[y] = current I/O sample)*/
    float x[3];
    float y[3];

    /*x[n]/y[n] coefficients*/
    float a[3];
    float b[3];

} Filter;

void Filter_Init(Filter *filt, float sampleRate_Hz);
void Filter_SetParameters(Filter *filt, float centerFrequency_Hz, float bandwidth_Hz, float boostCut);
float Filter_Update(Filter *filt, float input_latest);

#endif /* INC_FILTER_H_ */
 

 

 

 

 

 

 

 

/*
 * Filter.c
 *
 *  Created on: 7 Jun 2023
 *      Author: User
 */

#include "Filter.h"

void Filter_Init(Filter *filt, float sampleRate_Hz)
{

    /*Compute sample time*/
    filt->sampleTime_s = 1.0f / sampleRate_Hz;

    /*Clear filter momory*/
    for(uint32_t n = 0; n < 3; n++)
    {
        filt->x[n] = 0.0f;
        filt->x[n] = 0.0f;
    }

    /*Calculate 'default' filter coefficients (all-pass)*/
    Filter_SetParameters(filt, 1.0f, 0.0f, 1.0f);
}

void Filter_SetParameters(Filter *filt, float centerFrequency_Hz, float bandwidth_Hz, float boostCut)
{

    /*Convert Hz to rad/s (rps), pre-warp cut-off frequency (bilinear transform), multiply by sampling time (wcd * T = 2/T*tan(2*pi*fc*T/2) * T = 2*tan(pi*fc*T)*/
    float wcdT = 2.0f * tanf(M_PI * centerFrequency_Hz * filt->sampleTime_s);

    /*Compute quality factor (Q = fc/fbw)*/
    float Q = centerFrequency_Hz / bandwidth_Hz;

    /*Compute filter coefficients*/
    filt->a[0] = 4.0f + 2.0f * (boostCut / Q) * wcdT + (wcdT * wcdT);
    filt->a[1] = 2.0f * (wcdT * wcdT) - 8.0f;
    filt->a[2] = 4.0f - 2.0f * (boostCut / Q) * wcdT + (wcdT * wcdT);

    filt->b[0] = 1.0f / (4.0f + 2.0f / Q * wcdT + (wcdT * wcdT));            /*1 / b0*/
    filt->b[1] = -(2.0f * (wcdT * wcdT) - 8.0f);                            /*-a0 for feedback*/
    filt->a[2] = -(4.0f - 2.0f * (boostCut / Q) * wcdT + (wcdT * wcdT));    /*-a0 for feedback*/

}

float Filter_Update(Filter *filt, float input_latest)
{

    /*Shift samples*/
    filt->x[2] = filt->x[1];
    filt->x[1] = filt->x[0];
    filt->x[0] = input_latest;

    filt->y[2] = filt->y[1];
    filt->y[1] = filt->y[0];
    filt->y[0] = ((filt->a[0]*filt->x[0] + filt->a[1]*filt->x[1] + filt->a[2]*filt->x[2]) + (filt->b[1]*filt->y[1] + filt->b[2]*filt->y[2])) * filt->b[0];

    /*Return current output sample*/
    return (filt->y[0]);
}

 

 

 

 

 

 

 

 

stm32 nucleo F303

arm board

digital processing

speaker

power amplifier

hardware implementaion

arrow
arrow

    Josephood7 發表在 痞客邦 留言(0) 人氣()