/*
 * H_Common_STM32F4_PWM_1CH.c
 *
 *  Created on: 2024/11/25
 *      Author: egaono-electronics
 */

#include "H_Common_STM32F4_PWM_1CH.h"



// TIM Output Compare Configuration Structure
TIM_OC_InitTypeDef  GLB_struct_TIM_OC_Init;



//----------------------------------------------------------
// 関数 : HAL_TIM_PWM_Init(pHandle_TIMx); が呼び出されたとき
// HAL_TIM_PWM_Init の中から Call される。
//----------------------------------------------------------
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
  GPIO_InitTypeDef struct_GPIO_Init;


  if(htim->Instance == def_TIMx_Beep_PWM)
  {
    // TIMx Peripheral clock enable
    def_TIMx_CLK_ENABLE_Beep_PWM();

    // Enable GPIO Channels Clock
    def_GPIOx_CLK_ENABLE_Beep_PWM_CH();


    // GPIOのPWM使用ピンの設定
    struct_GPIO_Init.Mode = GPIO_MODE_AF_PP;
    struct_GPIO_Init.Pull = GPIO_PULLDOWN;
    struct_GPIO_Init.Speed = GPIO_SPEED_HIGH;
    struct_GPIO_Init.Alternate = def_GPIO_AFx_TIMx_Beep_PWM;


    // Channel のピンを初期化
    struct_GPIO_Init.Pin = def_GPIO_PIN_x_Beep_PWM_CH;

    HAL_GPIO_Init(def_GPIOx_Beep_PWM_CH, &struct_GPIO_Init);
  }
}


//----------------------------------------------------------
// PWM初期化
//----------------------------------------------------------
// 引数;
// TIM_HandleTypeDef *pHandle_TIMx :
//                      Time Base Handle構造体のポインタ
// TIM_TypeDef *TIMx : TIM選択
// uint32_t uint32_Div_Clock : SystemCoreClock の除数
// uint32_t uint32_TIMx_CCRx : TiMx CHx のインターバル


// 戻り値:
//    なし
//----------------------------------------------------------
void Initialize_PWM(TIM_HandleTypeDef *pHandle_TIMx,
                    TIM_TypeDef *TIMx,
                    uint32_t uint32_Div_Clock,
                    uint32_t uint32_TIMx_CCRx)
{
  HAL_StatusTypeDef hal_Status;

  uint32_t uint32_PrescalerValue = 0;


  //------------------------------------------------------------
  // 周波数 : 1 kHz (周期 : 1 mSec) に設定する。 :
  //              uint32_TIMx_CCR1 が 1000 のとき 1kHz になる。
  //              周期 1000uSec : 1mSec
  //------------------------------------------------------------

  // Compute the prescaler value
  //            to have TIMx counter clock equal to 1 MHz
  //------------------------------------------------------------
  uint32_PrescalerValue
    = (uint32_t)((SystemCoreClock / uint32_Div_Clock) / 1000000) - 1;
  //------------------------------------------------------------



  // Instance に TIMx をセット
  pHandle_TIMx->Instance = TIMx;

  //------------------------------------------------------------
  // Period = uint32_TIMx_CCRx - 1 :
  //            uint32_TIMx_CCRx が 1000 のとき 1 kHz になる。
  //                : 周期 1000uSec : 1mSec
  //------------------------------------------------------------
  // Period = uint32_TIMx_CCRx - 1 :
  //            uint32_TIMx_CCRx が 250 のとき 4 kHz になる。
  //                : 周期 250uSec
  //------------------------------------------------------------
  pHandle_TIMx->Init.Period = uint32_TIMx_CCRx - 1;

  pHandle_TIMx->Init.Prescaler = uint32_PrescalerValue;
  pHandle_TIMx->Init.ClockDivision = 0;
  pHandle_TIMx->Init.CounterMode = TIM_COUNTERMODE_UP;

  hal_Status = HAL_TIM_PWM_Init(pHandle_TIMx);
  if(hal_Status != HAL_OK)
  {
      // Initialization Error
    while(1){
      // NGのとき、無限ループ
    }
  }
}



//----------------------------------------------------------
// PWMの周期設定
//----------------------------------------------------------
// 引数;
// TIM_HandleTypeDef *pHandle_TIMx :
//                      Time Base Handle構造体のポインタ
// TIM_TypeDef *TIMx : TIM選択
// uint32_t uint32_PrescalerValue : TIMx のクロック分周比
// uint32_t uint32_TIMx_Period : TiMx CHx の周期


// 戻り値:
//    なし
//----------------------------------------------------------
void Config_PWM_Period(TIM_HandleTypeDef *pHandle_TIMx,
                       TIM_TypeDef *TIMx,
                       uint32_t uint32_PrescalerValue,
                       uint32_t uint32_TIMx_Period)
{
  HAL_StatusTypeDef hal_Status;


  //------------------------------------------------------------
  // PWMの周期設定
  //------------------------------------------------------------
  // Instance に TIMx をセット
  pHandle_TIMx->Instance = TIMx;

  pHandle_TIMx->Init.Prescaler = uint32_PrescalerValue;
  pHandle_TIMx->Init.Period = uint32_TIMx_Period - 1;

  pHandle_TIMx->Init.ClockDivision = 0;
  pHandle_TIMx->Init.CounterMode = TIM_COUNTERMODE_UP;

  pHandle_TIMx->Init.RepetitionCounter = 0;
  pHandle_TIMx->Init.AutoReloadPreload
                          = TIM_AUTORELOAD_PRELOAD_ENABLE;


  hal_Status = HAL_TIM_PWM_Init(pHandle_TIMx);
  if(hal_Status != HAL_OK)
  {
      // Initialization Error
    while(1){
      // NGのとき、無限ループ
    }
  }
}



//----------------------------------------------------------
// PWMパルス出力設定
//----------------------------------------------------------
// 引数;
// TIM_HandleTypeDef *pHandle_TIMx :
//                      Time Base Handle構造体のポインタ
// TIM_TypeDef *TIMx : TIM選択
// uint32_t uint32_TIM_CHANNEL_x : Channel選択
// uint32_t uint32_Pulse : Pulse出力値


// 戻り値:
//    なし
//----------------------------------------------------------
void Configure_PWM(TIM_HandleTypeDef *pHandle_TIMx,
                   TIM_TypeDef *TIMx,
                   uint32_t uint32_TIM_CHANNEL_x,
                   uint32_t uint32_Pulse)
{
  HAL_StatusTypeDef hal_Status;

  pHandle_TIMx->Instance = TIMx;

  // Common configuration for all channels
  GLB_struct_TIM_OC_Init.OCMode = TIM_OCMODE_PWM1;
  GLB_struct_TIM_OC_Init.OCPolarity = TIM_OCPOLARITY_HIGH;
  GLB_struct_TIM_OC_Init.OCFastMode = TIM_OCFAST_DISABLE;

  // Set the pulse value for channel x
  GLB_struct_TIM_OC_Init.Pulse = uint32_Pulse;


  hal_Status = HAL_TIM_PWM_ConfigChannel(
                    pHandle_TIMx, &GLB_struct_TIM_OC_Init,
                    uint32_TIM_CHANNEL_x);
  if(hal_Status != HAL_OK)
  {
    // Initialization Error
    while(1){
      // NGのとき、無限ループ
    }
  }


  TIM_CHANNEL_STATE_SET(pHandle_TIMx, uint32_TIM_CHANNEL_x,
                        HAL_TIM_STATE_READY);

  // Start PWM signals generation
  hal_Status
    = HAL_TIM_PWM_Start(pHandle_TIMx, uint32_TIM_CHANNEL_x);
}



//----------------------------------------------------------
// PWMパルス出力設定 : 反転出力
//----------------------------------------------------------
// 引数;
// TIM_HandleTypeDef *pHandle_TIMx :
//                      Time Base Handle構造体のポインタ
// TIM_TypeDef *TIMx : TIM選択
// uint32_t uint32_TIM_CHANNEL_x : Channel選択
// uint32_t uint32_Pulse : Pulse出力値


// 戻り値:
//    なし
//----------------------------------------------------------
void Configure_PWM_LOW(TIM_HandleTypeDef *pHandle_TIMx,
                       TIM_TypeDef *TIMx,
                       uint32_t uint32_TIM_CHANNEL_x,
                       uint32_t uint32_Pulse)
{
  HAL_StatusTypeDef hal_Status;


  pHandle_TIMx->Instance = TIMx;

  // Common configuration for all channels
  GLB_struct_TIM_OC_Init.OCMode = TIM_OCMODE_PWM1;
  GLB_struct_TIM_OC_Init.OCPolarity = TIM_OCPOLARITY_LOW;
  GLB_struct_TIM_OC_Init.OCFastMode = TIM_OCFAST_DISABLE;

  // Set the pulse value for channel x
  GLB_struct_TIM_OC_Init.Pulse = uint32_Pulse;


  hal_Status = HAL_TIM_PWM_ConfigChannel(pHandle_TIMx,
            &GLB_struct_TIM_OC_Init, uint32_TIM_CHANNEL_x);
  if(hal_Status != HAL_OK)
  {
    // Initialization Error
    while(1){
      // NGのとき、無限ループ
    }
  }


  TIM_CHANNEL_STATE_SET(pHandle_TIMx, uint32_TIM_CHANNEL_x,
                        HAL_TIM_STATE_READY);

  // Start PWM signals generation
  hal_Status = HAL_TIM_PWM_Start(pHandle_TIMx,
                                 uint32_TIM_CHANNEL_x);
}
