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

#include "Buzzer.h"

#include "TimerB.h"


#define BUZZER_PWM_CHANNEL  TIMERB_0_CH11
/******************************************************************************
单音列表
******************************************************************************/
const SingleSoundStruct SingleSound[] =
{
    {2381,  210 , 23,      0},    //Tic
    {2174,  230,  41,      0},    //Tac
    {200,  600, 7812, 1500},    //Dong
    { 75,  380, 7844, 1000},    //Pling
    { 96,  180, 5755, 1000},    //Plong
    {127,  640, 1094, 1094},    //Park Beep
};

/******************************************************************************
复合音列表
******************************************************************************/
const ComplexSoundStruct ComplexSound[] =
{
    {{BUZZER_SINGLE_SOUND_TIC},       1},    //Tic
    {{BUZZER_SINGLE_SOUND_TAC},       1},    //Tac
    {{BUZZER_SINGLE_SOUND_DONG},      1},    //Dong
    {{BUZZER_SINGLE_SOUND_PLING},     1},    //Pling
    {{BUZZER_SINGLE_SOUND_PLONG},     1},    //Plong
    {{BUZZER_SINGLE_SOUND_PARK_BEEP}, 1},    //Park Beep
    {{BUZZER_SINGLE_SOUND_PLING, BUZZER_SINGLE_SOUND_PLONG}, 2},    //Pling-Plong
};

/******************************************************************************
全局变量f
******************************************************************************/
uint8_t  BuzzerSoundPlayStat;
uint8_t  BuzzerSoundUpdate;
uint8_t  * pBuzzerSoundID;
uint8_t  BuzzerSoundCnt;
uint16_t BuzzerPrechargeTimer;
uint16_t BuzzerSoundPlayTime;
uint16_t BuzzerSoundFadeOutTime;

TrackInfoStruct BuzTrack[BUZZER_TRACK_CNT];

/******************************************************************************
函数名:Buzzer_Track_Play
功  能:蜂鸣器播放某一音轨
        如果同一时间内有两条或多条音轨同时被播放,只有音轨编号较大的音轨将被播放
        出来
参  数:TrackID :音轨编号
返回值:无
******************************************************************************/
void Buzzer_Track_Play ( uint8_t TrackID )
{
    BuzTrack[TrackID].RepeatTimer = 0;

    if ( BuzTrack[TrackID].RepeatNum == 0 )
        BuzTrack[TrackID].Mode = BUZZER_SOUND_PLAY_NONSTOP;
    else
        BuzTrack[TrackID].Mode = BUZZER_SOUND_PLAY_REPEAT;
}

/******************************************************************************
函数名:Buzzer_Track_Pause
功  能:蜂鸣器暂停播放某一音轨
参  数:TrackID :音轨编号
返回值:无
******************************************************************************/
void Buzzer_Track_Pause ( uint8_t TrackID )
{
    BuzTrack[TrackID].Mode = BUZZER_SOUND_PLAY_IDLE;
}

/******************************************************************************
函数名:Buzzer_Track_Pause
功  能:蜂鸣器停止播放某一音轨
参  数:TrackID :音轨编号
返回值:无
******************************************************************************/
void Buzzer_Track_Stop ( uint8_t TrackID )
{
    BuzTrack[TrackID].Mode      = BUZZER_SOUND_PLAY_IDLE;
    BuzTrack[TrackID].RepeatCnt = BuzTrack[TrackID].RepeatNum;
}

/******************************************************************************
函数名:Buzzer_Stop_All_Track
功  能:停止播放所有音轨
参  数:无
返回值:无
******************************************************************************/
void Buzzer_Stop_All_Track ( void )
{
    uint8_t i;

    for ( i = 0; i < BUZZER_TRACK_CNT; i++ )
    {
        BuzTrack[i].Mode      = BUZZER_SOUND_PLAY_IDLE;
        BuzTrack[i].RepeatCnt = BuzTrack[i].RepeatNum;
    }
}

/******************************************************************************
函数名:Buzzer_Get_Track_Status
功  能:获取蜂鸣器某一音轨的状态
参  数:TrackID :音轨编号
返回值:0 - 空闲 1 - 播放中
******************************************************************************/
uint8_t Buzzer_Get_Track_Status ( uint8_t TrackID )
{
    if ( BuzTrack[TrackID].Mode == BUZZER_SOUND_PLAY_IDLE )
        return 0;
    else
        return 1;
}

/******************************************************************************
函数名:Buzzer_Get_All_Track_Status
功  能:获取蜂鸣器全部音轨的状态
参  数:无
返回值:0 - 空闲 1 - 有某一音轨播放中
******************************************************************************/
uint8_t Buzzer_Get_All_Track_Status ( void )
{
    uint8_t i;
    i = BUZZER_TRACK_CNT;

    while ( i )
    {
        i--;

        if ( BuzTrack[i].Mode != BUZZER_SOUND_PLAY_IDLE )
            return 1;
    }

    return 0;
}

/******************************************************************************
函数名:Buzzer_Get_Track_Remaining_Repeat_Num
功  能:获取蜂鸣器某一音轨的剩余重复次数
参  数:TrackID :音轨编号
返回值:当返回值 大于0 时表示剩余的重复次数
        当返回值 等于0 时 且 该音轨正在播放中 表示当前音轨处于不停的播放状态
******************************************************************************/
uint8_t Buzzer_Get_Track_Remaining_Repeat_Num ( uint8_t TrackID )
{
    return BuzTrack[TrackID].RepeatCnt;
}

/******************************************************************************
函数名:Buzzer_Set_Track_Remaining_Repeat_Num
功  能:重新设定蜂鸣器某一音轨的剩余重复次数
参  数:TrackID   :音轨编号
        RepeatNum :重复次数
返回值:无
******************************************************************************/
void Buzzer_Set_Track_Remaining_Repeat_Num ( uint8_t TrackID, uint8_t RepeatNum )
{
    BuzTrack[TrackID].RepeatCnt = RepeatNum;
}

/******************************************************************************
函数名:Buzzer_Track_Init
功  能:蜂鸣器单音连续播放
参  数:TrackID    :音轨编号,编号数越大,优先级越高
        SoundID    :播放的声音的ID
        RepeatNum  :重复播放次数,0表示不停的播放直到调用停止播放函数为止
        RepeatCycle:重复播放周期,周期 = RepeatCycle * 20ms
返回值:无
******************************************************************************/
void Buzzer_Track_Init ( uint8_t TrackID, uint8_t SoundID, uint8_t RepeatNum, uint8_t RepeatCycle )
{
    BuzTrack[TrackID].Mode        = BUZZER_SOUND_PLAY_IDLE;
    BuzTrack[TrackID].SoundID     = SoundID;
    BuzTrack[TrackID].RepeatNum   = RepeatNum;
    BuzTrack[TrackID].RepeatCnt   = RepeatNum;
    BuzTrack[TrackID].RepeatCycle = RepeatCycle;
}

/******************************************************************************
函数名:Buzzer_Track_Play_Service
功  能:蜂鸣器音轨播放服务函数,用于蜂鸣器播放音轨的后台控制
参  数:无
返回值:无
******************************************************************************
注  意:该服务函数必须每20ms被调用一次
******************************************************************************/
void Buzzer_Track_Play_Service ( void )
{
    uint8_t i;
    i = BUZZER_TRACK_CNT;

    while ( i )
    {
        i--;

        if ( BuzTrack[i].Mode != BUZZER_SOUND_PLAY_IDLE )
        {
            if ( BuzTrack[i].RepeatTimer == 0 )
            {
                Buzzer_Play_Sound ( BuzTrack[i].SoundID );
                BuzTrack[i].RepeatTimer = BuzTrack[i].RepeatCycle;

                if ( BuzTrack[i].Mode == BUZZER_SOUND_PLAY_REPEAT )
                {
                    BuzTrack[i].RepeatCnt--;

                    if ( BuzTrack[i].RepeatCnt == 0 )
                    {
                        BuzTrack[i].Mode = BUZZER_SOUND_PLAY_IDLE;
                        BuzTrack[i].RepeatCnt = BuzTrack[i].RepeatNum;
                    }
                }
            }
            else
                BuzTrack[i].RepeatTimer--;

            return;
        }
    }
}

/******************************************************************************
函数名:Buzzer_Play_Sound
功  能:控制蜂鸣器播放一个复合音
参  数:播放的声音的ID
返回值:无
******************************************************************************/
void Buzzer_Play_Sound ( uint8_t SoundID )
{
    if ( BuzzerSoundPlayStat != 0 ) //(如果当前有声音在播放)打断当前声音播放
    {
        TimerB_PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
        LINE_BUZZER = 1;
        BuzzerSoundPlayStat = 0;
        BuzzerPrechargeTimer = 640;//500;  //这时电容可能未充满电,需要一段预充电时间
    }
    else
        BuzzerPrechargeTimer = 0;    //首次播放不需要预充电

    BuzzerSoundUpdate    = 1;
    pBuzzerSoundID       = (uint8_t *)ComplexSound[SoundID].SoundTable;
    BuzzerSoundCnt       = ComplexSound[SoundID].SoundCnt;
    //播放声音
    BuzzerSoundPlayStat = 1;
}

/******************************************************************************
函数名:Buzzer_Init
功  能:蜂鸣器播放初始化程序
参  数:无
返回值:无
******************************************************************************/

void Buzzer_Init ( void )
{
  LINE_BUZZER = 0;
  TimerB_PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
  TimerB_PWM_Channel_Init(BUZZER_PWM_CHANNEL, TIMERB_CLOCK_0, TIMERB_HIGH);
  BuzzerSoundPlayStat = 0;

}
/******************************************************************************
函数名:Buzzer_Shutdown
功  能:关闭蜂鸣器
参  数:无
返回值:无
******************************************************************************/
void Buzzer_Shutdown ( void )
{
    LINE_BUZZER = 0;
    TimerB_PWM_Channel_Stop(BUZZER_PWM_CHANNEL);
    BuzzerSoundPlayStat = 0;
}

/******************************************************************************
函数名:Buzzer_Play_ISR
功  能:蜂鸣器播放中断服务函数
参  数:无
返回值:无
******************************************************************************
注  意:该服务函数必须嵌入到64us定时中断内
******************************************************************************/
void Buzzer_Play_ISR ( void )
{
    if ( BuzzerSoundPlayStat )
    {
        if ( BuzzerPrechargeTimer )
            BuzzerPrechargeTimer--;
        else
        {
            if ( BuzzerSoundUpdate )
            {
                TimerB_PWM_Channel_Fre_Set(BUZZER_PWM_CHANNEL, SingleSound[*pBuzzerSoundID].Freq, SingleSound[*pBuzzerSoundID].Duty);
                //TimerB_PWM_Channel_Duty_Set(BUZZER_PWM_CHANNEL, SingleSound[*pBuzzerSoundID].Duty);
                TimerB_PWM_Channel_Start(BUZZER_PWM_CHANNEL);
                BuzzerSoundPlayTime =  SingleSound[*pBuzzerSoundID].PlayTime;
                BuzzerSoundFadeOutTime = SingleSound[*pBuzzerSoundID].FadeOutTime;
                BuzzerSoundUpdate = 0;
            }

            BuzzerSoundPlayTime--;

            if ( BuzzerSoundPlayTime < BuzzerSoundFadeOutTime )
                LINE_BUZZER = 0;

            if ( BuzzerSoundPlayTime == 0 )
            {
                LINE_BUZZER = 1;            //重新对蜂鸣器电容充电
                TimerB_PWM_Channel_Stop(BUZZER_PWM_CHANNEL);          //关闭蜂鸣器频率输出
                BuzzerSoundCnt--;

                if ( BuzzerSoundCnt )
                {
                    BuzzerPrechargeTimer = 640 ;//500; //增加预充电时间32ms
                    BuzzerSoundUpdate = 1;
                    pBuzzerSoundID++;
                }
                else
                    BuzzerSoundPlayStat = 0;
            }
        }
    }
}
void Warning_Sound_Init ( void )
{
    Buzzer_Track_Init ( 0, BUZZER_SOUND_TIC,            1, 25 );  // Track0  Tic          x1    @500ms   转向灯上升沿
    Buzzer_Track_Init ( 1, BUZZER_SOUND_TAC,            1, 25 );  // Track1  Tac          x1    @500ms   转向灯下降沿
    Buzzer_Track_Init ( 2, BUZZER_SOUND_PLING,        120, 48 );  // Track2  Pling        x120  @1000ms  安全带
    Buzzer_Track_Init ( 3, BUZZER_SOUND_PLING,          5, 48 );  // Track3  Pling        x∞   @1000ms  超速
    Buzzer_Track_Init ( 4, BUZZER_SOUND_DONG ,         60, 48 );  // Track4  Dong         x60   @1000ms  门开
    Buzzer_Track_Init ( 5, BUZZER_SOUND_DONG ,         60, 48 );  // Track5  Dong         x60   @1000ms  手刹
    Buzzer_Track_Init ( 6, BUZZER_SOUND_DONG ,          0, 48 );  // Track6  Dong         x∞   @1000ms  小灯未关
    Buzzer_Track_Init ( 7, BUZZER_SOUND_PLING_PLONG ,   3, 50 );  // Track7  Pling-Plong  x3    @1900ms  通用
    Buzzer_Track_Init ( 8, BUZZER_SOUND_DONG ,          3, 50 );  // Track8  Dong         x3    @1000ms  通用
    Buzzer_Track_Init ( 9, BUZZER_SOUND_PARK_BEEP ,     0, 48 );  // Track8  Park Beep    x∞   @1000ms  雷达
}