#include "YX5200_uart.h"
#include "YX5200_main.h"
/******************************************************************************************************************

					+--------------------------------------------------+
					                   串口通讯模块
					+--------------------------------------------------+

 - 实现功能：

 - 目前进展：

 - 运行环境：STC   晶振：11.0592M   波特率:9600   [硬件串口操作]

 - 备注    ：在普中科技的51开发板上调试OK --- STC89C516RD+

******************************************************************************************************************/

static INT8U Send_buf[YX5200_MSGLEN] = {0} ;
INT8U Recv_buf[YX5200_MSGLEN] = {0} ;

const INT8U hex[] = {"0123456789ABCDEF"};

void DoSum ( INT8U *Str, INT8U len ) ;
void Uart_Task ( INT8U *pr );

void Clear_Uart2_Recv ( void )
{
    memset ( RxBufferUart2, 0, RxCounterUart2 );
    RxCounterUart2 = 0;
}


void Init_YX5200_VOL(void)
{
#if xy5200_Uart2_def
	input_vol = 25;
	put_msg_lifo ( MSG_VOL_DOWN );
#endif
}

void YX5200_Key_handler ( void )
{
#if xy5200_Uart2_def
    char i;
    static bool key4_play_pause = false;

    if ( System_Flag_Prin_Music )
    {
        if ( POINTNUM_FOLDER == PointFunc ) //指定文件夹的状态
        {
            //播放模式
            if ( Keys[10].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[10].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_SET_PLAYMODE );
            }

            for ( i = 0; i < 10; i++ )
            {
                if ( Keys[i].Res == ONE_HITS_KEY_FLAG )
                {
                    Keys[i].Res = NO_KEY_FLAG;
                    put_msg_lifo ( i );
                }
            }

        }
        else
        {
            //播放模式
            if ( Keys[10].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[10].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_SET_PLAYMODE );
            }

            //上一曲/下一曲
            if ( Keys[0].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[0].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_MUSIC_PREV_FILE );
            }

            if ( Keys[1].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[1].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_MUSIC_NEXT_FILE );
            }

            //音量10-20-30
            if ( Keys[2].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[2].Res = NO_KEY_FLAG;
                input_vol = 13;
                put_msg_lifo ( MSG_VOL_DOWN );
            }
            else if ( Keys[2].Res == TWO_HITS_KEY_FLAG )
            {
                Keys[2].Res = NO_KEY_FLAG;
                input_vol = 19;
                put_msg_lifo ( MSG_VOL_DOWN );
            }
            else if ( Keys[2].Res == THREE_HITS_KEY_FLAG )
            {
                Keys[2].Res = NO_KEY_FLAG;
                input_vol = 25;
                put_msg_lifo ( MSG_VOL_DOWN );
            }
            else if ( Keys[2].Res == LONG_KEY_FLAG )
            {
                Keys[2].Res = NO_KEY_FLAG;
                input_vol = 31;
                put_msg_lifo ( MSG_VOL_DOWN );
            }

            //查询ALLNUM/CURNUM
            if ( Keys[3].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[3].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_QUERY_NUMTOTAL );
            }
            else if ( Keys[3].Res == TWO_HITS_KEY_FLAG )
            {
                Keys[3].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_QUERY_CURNUM );
            }

            //播放/停止
            if ( Keys[4].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[4].Res = NO_KEY_FLAG;
                key4_play_pause = ! key4_play_pause;

                if ( key4_play_pause )
                    put_msg_lifo ( MSG_MUSIC_PLAY );
                else
                    put_msg_lifo ( MSG_MUSIC_PAUSE );

            }

            //全播*全停
            if ( Keys[5].Res == ONE_HITS_KEY_FLAG )
            {
                Keys[5].Res = NO_KEY_FLAG;
                put_msg_lifo ( MSG_PLAYALL );
            }

        }
    }

#endif
}

void YX5200_UART_Handler ( void )
{
#if xy5200_Uart2_def

    if ( YX5200HaveRecFlag )
    {
        YX5200HaveRecFlag = false;
        UartRecvACKFlag = false;
        RecvOver_Flag = 1;
        Uart_communication();
        Clear_Uart2_Recv();
    }
    else
    {

        if ( ( UartRecvACK == 0 ) && UartRecvACKFlag )
        {
            UartRecvACKFlag = 0;
            RecvError_Flag = 1;
            Uart_communication();
        }
    }

#endif
}


/********************************************************************************************
 - 功能描述：争对接收的命令进行处理
 - 隶属模块：外部
 - 参数说明：无
 - 返回说明：无
 - 注：
********************************************************************************************/
void Uart_communication ( void )
{
    INT8U i, *pi ;

    INT16U  xorsum = 0, xorsum1 = 0 ;

    if ( 1 == RecvError_Flag ) //接收错误处理
    {
        RecvError_Flag = 0 ;
        UartRecvStatus = UART_RECV_IDLE ;

        if ( ResendCount-- != 0 )
        {
            Uart_ReSendCMD ( 0x40 , 0 , 1 ) ; //错误处理请求重发
        }

        return ;
    }

    if ( 1 == RecvOver_Flag ) //一帧数据接收完毕
    {
        RecvOver_Flag = 0 ;
        pi = Recv_buf;

        for ( i = 0; i < ( * ( pi + 1 ) ); i++ )
        {
            xorsum  = xorsum + pi[i] ;
        }

        xorsum1 = ( ( INT16U ) ( ( * ( pi + i ) ) << 8 ) ) | ( * ( pi + i + 1 ) );
        xorsum  = xorsum + xorsum1;

        if ( !xorsum )
        {
            Uart_Task ( pi ); //串口处理
        }
        else
        {
            RecvError_Flag = 1 ;//错误处理
        }

        UartRecvStatus = UART_RECV_IDLE ;
    }
}

/**********************************************************************************************
 - 功能描述： 串口处理函数
 - 隶属模块： 内部
 - 参数说明： *pr ：串口0需要接收的数据的地址指针
 - 返回说明： 无
 - 注：
**********************************************************************************************/
void Uart_Task ( INT8U *pr )
{
    INT16U Temp16 = 0 ;
    INT8U *pi , tempH , tempL , CMD , FeedBack;
    pi = pr;

    tempH = * ( pi + 4 ) ;
    tempL = * ( pi + 5 ) ;
    Temp16 = ( ( ( INT16U ) ( tempH ) ) << 8 ) | tempL ;
    CMD   = * ( pi + 2 ) ;
    FeedBack = * ( pi + 3 ) ;

    switch ( CMD )
    {
    case ( 0x41 ) : //收到应答ACK
        UartRecvACK = 0 ;
        //PlayledCnt = PLAYLEDCNT ;
        //PlayledStatus = SET_PLAYLED_ON;
        break ;

        /**********************************************************************
        - 1、设备插入拔出消息
        **********************************************************************/
    case ( 0x3A ) : //设备插入
        if ( tempL == 0x01 )
        {
            put_msg_lifo ( MSG_UDISK_IN );
        }
        else if ( tempL == 0x02 )
        {
            put_msg_lifo ( MSG_TF_IN );
        }
        else if ( tempL == 0x04 )
        {
            put_msg_lifo ( MSG_PC_IN );
        }

        break;

    case ( 0x3B ) : //设备拔出
        if ( tempL == 0x01 )
        {
            put_msg_lifo ( MSG_UDISK_OUT );
        }
        else if ( tempL == 0x02 )
        {
            put_msg_lifo ( MSG_TF_OUT );
        }
        else if ( tempL == 0x04 )
        {
            put_msg_lifo ( MSG_PC_OUT );
        }

        break;

        /**********************************************************************
        - 1、收到当前曲目播放完毕消息
        **********************************************************************/
    case ( 0x3C ) : //U盘当前曲目播放完毕
        if ( PLAYDEVICE_UDISK == PlayDevice )
        {
            put_msg_lifo ( MSG_MUSIC_OVER );
        }

        break;

    case ( 0x3D ) : //TF当前曲目播放完毕
        if ( PLAYDEVICE_TFCARD == PlayDevice )
        {
            put_msg_lifo ( MSG_MUSIC_OVER );
        }

        break ;

    case ( 0x3E ) : //FLASH当前曲目播放完毕
        if ( PLAYDEVICE_FLASH == PlayDevice )
        {
            put_msg_lifo ( MSG_MUSIC_OVER );
        }

        break ;

        /**********************************************************************
        - 1、模块上电返回的数据
        **********************************************************************/
    case ( 0x3F ) :
        OnlineDevice = tempL ;
        put_msg_lifo ( MSG_RETURN_MINIT );
        break ;

        /**********************************************************************
        - 1、模块返回的错误
        **********************************************************************/
    case ( 0x40 ) :
        _ErrorStatus = tempL ;
        put_msg_lifo ( MSG_RECV_ERROR );
        break ;

        /**********************************************************************
        - 1、查询参数
        **********************************************************************/
    case ( 0x42 ) : //查询当前状态

        break;

    case ( 0x43 ) : //查询当前系统音量
        input_vol = tempL ;
        put_msg_lifo ( MSG_RETURN_VOL );
        break;

    case ( 0x44 ) : //查询当前EQ
        CurrentEQ = tempL ;
        put_msg_lifo ( MSG_RETURN_EQ );
        break;

    case ( 0x45 ) : //查询当前播放模式
        PlayMode = tempL ;
        put_msg_lifo ( MSG_RETURN_PLAYMODE );
        break;

    case ( 0x46 ) : //查询当前软件版本

        break;

        /**********************************************************************
        - 1、查询参数 --- 设备总文件数
        **********************************************************************/
    case ( 0x47 ) : //查询UDISK文件总数
        UDiskTotal = Temp16 ;
        put_msg_lifo ( MSG_RETURN_NUMTOTAL );
        break ;

    case ( 0x48 ) : //查询TFCARD文件总数
        TFTotal = Temp16 ;
        put_msg_lifo ( MSG_RETURN_NUMTOTAL );
        break ;

    case ( 0x49 ) : //查询FLASH文件总数
        FlashTotal = Temp16 ;
        put_msg_lifo ( MSG_RETURN_NUMTOTAL );
        break;

    case ( 0x4A ) : //保留
        break;

        /**********************************************************************
        - 1、查询参数 --- 设备当前播放的文件数
        **********************************************************************/
    case ( 0x4B ) : //查询UDISK的当前曲目
        UDiskCurFile = Temp16 ;
        put_msg_lifo ( MSG_RETURN_CURNUM );
        break;

    case ( 0x4C ) : //查询TF卡的当前曲目
        TFCurFile = Temp16 ;
        put_msg_lifo ( MSG_RETURN_CURNUM );
        break ;

    case ( 0x4D ) : //查询FLASH的当前曲目
        FlashCurFile = Temp16 ;
        put_msg_lifo ( MSG_RETURN_CURNUM );
        break;

    case ( 0x4E ) : //查询文件总数
        CurFileNum = Temp16 ;
        put_msg_lifo ( MSG_RETURN_FILENUM );
        break;

    case ( 0x4F ) : //查询文件夹数
        CurFoldNum = Temp16 ;
        put_msg_lifo ( MSG_RETURN_FOLDNUM );
        break;

    default:
        break;
    }
}



/********************************************************************************************
 - 功能描述： 串口向外发送命令[包括控制和查询]
 - 隶属模块： 外部
 - 参数说明： CMD:表示控制指令，请查阅指令表，还包括查询的相关指令
              feedback:是否需要应答[0:不需要应答，1:需要应答]
              data:传送的参数
 - 返回说明：
 - 注：
********************************************************************************************/
void Uart_SendCMD ( INT8U CMD , INT8U feedback , INT16U dat )
{
    Send_buf[0] = 0x7E;    //保留字节
    Send_buf[1] = 0xff;    //保留字节
    Send_buf[2] = 0x06;    //长度
    Send_buf[3] = CMD;     //控制指令
    Send_buf[4] = feedback;//是否需要反馈
    Send_buf[5] = ( INT8U ) ( dat >> 8 ); //datah
    Send_buf[6] = ( INT8U ) ( dat ); //datal
    DoSum ( &Send_buf[1], 6 );    //校验
    Send_buf[9] = 0xEF;    //结束

    Uart2Send ( ( char * ) Send_buf, YX5200_MSGLEN );
    UartRecvACK = WAIT_ACK_TIME ;//设定等待应答的时间[300ms]
    UartRecvACKFlag = true;
    ResendCount = 3;
}

void Uart_ReSendCMD ( INT8U CMD , INT8U feedback , INT16U dat )
{
    Send_buf[0] = 0x7E;    //保留字节
    Send_buf[1] = 0xff;    //保留字节
    Send_buf[2] = 0x06;    //长度
    Send_buf[3] = CMD;     //控制指令
    Send_buf[4] = feedback;//是否需要反馈
    Send_buf[5] = ( INT8U ) ( dat >> 8 ); //datah
    Send_buf[6] = ( INT8U ) ( dat ); //datal
    DoSum ( &Send_buf[1], 6 );    //校验
    Send_buf[9] = 0xEF;    //结束

    Uart2Send ( ( char * ) Send_buf, YX5200_MSGLEN );
    UartRecvACK = WAIT_ACK_TIME ;//设定等待应答的时间[300ms]
    UartRecvACKFlag = true;
}

/********************************************************************************************
 - 功能描述：求和校验
 - 隶属模块：
 - 参数说明：
 - 返回说明：
 - 注：      和校验的思路如下
             发送的指令，去掉起始和结束。将中间的6个字节进行累加，最后取反码
             接收端就将接收到的一帧数据，去掉起始和结束。将中间的数据累加，再加上接收到的校验
             字节。刚好为0.这样就代表接收到的数据完全正确。
********************************************************************************************/
void DoSum ( INT8U *Str, INT8U len )
{
    INT16U xorsum = 0;
    INT8U i;

    for ( i = 0; i < len; i++ )
    {
        xorsum  = xorsum + Str[i];
    }

    xorsum     = 0 - xorsum;
    * ( Str + i )   = ( INT8U ) ( xorsum >> 8 );
    * ( Str + i + 1 ) = ( INT8U ) ( xorsum & 0x00ff );
}


