/******************************************************************************
文 件 名：Buzzer.c
功能描述：蜂鸣器驱动库文件
作    者：张暄
版    本：V2.0
日    期：2018.4.7
******************************************************************************/

#include "Buzzer.h"

BuzzerPlayCtrlStruct  BuzzerPlayCtrl;

/******************************************************************************
函数名：Buzzer_Start_Up
功  能：启动并初始化蜂鸣器
        蜂鸣器PWM使用CLKSA/CLKSB时钟源,推荐的时钟源频率为50kHz~100kHz
参  数：无
返回值：无
******************************************************************************/
void Buzzer_Start_Up(void)
{
  BuzzerPlayCtrl.Mode  = BUZZER_MODE_IDLE;
  
  BuzzerPlayCtrl.Track = 0;
  BuzzerPlayCtrl.Note  = 0;
  BuzzerPlayCtrl.Timer = 0;
  BuzzerPlayCtrl.Fade  = 0;
  
  BUZZER_CTRL = 0;
  PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
  PWM_Channel_Init(BUZZER_PWM_CHANNEL, PWM_CLOCK_SA, PWM_POL_POS, PWM_LEFT_ALIGN, PWM4_PP4);
}

/******************************************************************************
函数名：Buzzer_Shutdown
功  能：关闭蜂鸣器
参  数：无
返回值：无
******************************************************************************/
void Buzzer_Shutdown(void)
{
  BuzzerPlayCtrl.Mode  = BUZZER_MODE_IDLE;
  
  BuzzerPlayCtrl.Track = 0;
  BuzzerPlayCtrl.Note  = 0;
  BuzzerPlayCtrl.Timer = 0;
  BuzzerPlayCtrl.Fade  = 0;
  
  BUZZER_CTRL = 0;
  PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
}

/******************************************************************************
函数名：Buzzer_Play_Track
功  能：单次播放指定音轨
参  数：TrackID - 音轨编号
返回值：无
******************************************************************************/
void Buzzer_Play_Track(uint8_t TrackID)
{
  if (BuzzerPlayCtrl.Mode)
    return;
  
  if (TrackID >= SND_TRACK_TOTAL_NUM)
    return;
  
  BUZZER_CTRL = 1;
  
  BuzzerPlayCtrl.Track = TrackID;
  BuzzerPlayCtrl.Note  = 0;
  BuzzerPlayCtrl.Timer = (uint16_t)SndTracks[TrackID].PreCharge * 20;
  BuzzerPlayCtrl.Fade  = 0;
  
  BuzzerPlayCtrl.Mode  = BUZZER_MODE_SINGLE;
}

/******************************************************************************
函数名：Buzzer_Play_Track
功  能：循环播放指定音轨
参  数：TrackID - 音轨编号
返回值：无
******************************************************************************/
void Buzzer_Repeat_Play_Track(uint8_t TrackID)
{
  if (BuzzerPlayCtrl.Mode)
    return;
  
  if (TrackID >= SND_TRACK_TOTAL_NUM)
    return;
  
  BUZZER_CTRL = 1;
  
  BuzzerPlayCtrl.Track = TrackID;
  BuzzerPlayCtrl.Note  = 0;
  BuzzerPlayCtrl.Timer = (uint16_t)SndTracks[TrackID].PreCharge * 20;
  BuzzerPlayCtrl.Fade  = 0;
  
  BuzzerPlayCtrl.Mode  = BUZZER_MODE_LOOP;
}

/******************************************************************************
函数名：Buzzer_Stop_Play
功  能：停止播放音轨
参  数：无
返回值：无
******************************************************************************/
void Buzzer_Stop_Play(void)
{
  BuzzerPlayCtrl.Mode  = BUZZER_MODE_IDLE;
  
  BuzzerPlayCtrl.Track = 0;
  BuzzerPlayCtrl.Note  = 0;
  BuzzerPlayCtrl.Timer = 0;
  BuzzerPlayCtrl.Fade  = 0;
  
  BUZZER_CTRL = 0;
  PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
}

/******************************************************************************
函数名：Buzzer_Play_ISR
功  能：蜂鸣器播放中断服务函数
参  数：无
返回值：无
******************************************************************************
注  意：该服务函数必须嵌入到50us定时中断内
******************************************************************************/
void Buzzer_Play_ISR(void)
{
  if (BuzzerPlayCtrl.Mode)
  {
    if (BuzzerPlayCtrl.Timer)
      BuzzerPlayCtrl.Timer--;
    
    if (BuzzerPlayCtrl.Timer == 0)
    {
      if (BuzzerPlayCtrl.Note < SndTracks[BuzzerPlayCtrl.Track].NoteNum)
      {
        BUZZER_CTRL = 1;
        
        if (SndTracks[BuzzerPlayCtrl.Track].Note[BuzzerPlayCtrl.Note].Freq)
        {
          PWM_Channel_Set_Freq(BUZZER_PWM_CHANNEL, SndTracks[BuzzerPlayCtrl.Track].Note[BuzzerPlayCtrl.Note].Freq);
          PWM_Channel_Set_Duty_Cycle(BUZZER_PWM_CHANNEL, SndTracks[BuzzerPlayCtrl.Track].Note[BuzzerPlayCtrl.Note].Duty);
          PWM_Channel_Start(BUZZER_PWM_CHANNEL);
        }
        else
          PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
        
        BuzzerPlayCtrl.Timer = SndTracks[BuzzerPlayCtrl.Track].Note[BuzzerPlayCtrl.Note].Interval * 20;
        BuzzerPlayCtrl.Fade  = SndTracks[BuzzerPlayCtrl.Track].Note[BuzzerPlayCtrl.Note].Fade * 20;
        BuzzerPlayCtrl.Note++;
      }
      else
      {
        if (BuzzerPlayCtrl.Mode == BUZZER_MODE_LOOP)
          BuzzerPlayCtrl.Note  = 0;
        else
        {
          BUZZER_CTRL = 0;
          PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
          BuzzerPlayCtrl.Mode  = BUZZER_MODE_IDLE;
        }        
      }
    }
    else if (BuzzerPlayCtrl.Timer < BuzzerPlayCtrl.Fade)
      BUZZER_CTRL = 0;
  }
}