/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC 1T Series MCU Demo Programme -------------------------------*/
/* --- Mobile: (86)13922805190 ----------------------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966 ------------------------*/
/* --- Web: www.STCAI.com ---------------------------------------------*/
/* --- BBS: www.STCAIMCU.com  -----------------------------------------*/
/* --- QQ:  800003751 -------------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

#include "stc.h"
#include "uart.h"
#include "usb.h"
#include "util.h"
#include "usb_req_class.h"

BOOL UartBusy;

void uart_init()
{
    P_SW2 &= ~0x01;     //UART2 switch to: 0: P1.0 P1.1

    P1M0 &= ~0x03;      //P1.0,P1.1设置为准双向模式
    P1M1 &= ~0x03;

    S2CON = 0x50;
    T2L = BR(115200);
    T2H = BR(115200) >> 8;
    AUXR |= 0x14;   //定时器2时钟1T模式,开始计时
    IP2 |= 0x01;    //提高串口2中断优先级，防止数据丢失
    IE2 |= 1;       //允许中断

    LineCoding.dwDTERate = REV4(115200);
    LineCoding.bCharFormat = 0;
    LineCoding.bParityType = 0;
    LineCoding.bDataBits = 8;
}

void uart2_isr() interrupt 8
{
    if((S2CON & 2) != 0)
    {
        S2CON &= ~2;    //Clear Tx flag
        UartBusy = 0;
    }

    if((S2CON & 1) != 0)
    {
        S2CON &= ~1;    //Clear Rx flag
        TxBuffer[TxWptr++] = S2BUF;
    }
}

void uart_set_parity(BYTE parity)
{
    switch (parity)
    {
    case NONE_PARITY:
        S2CON = 0x50;
        break;
    case ODD_PARITY:
    case EVEN_PARITY:
    case MARK_PARITY:
        S2CON = 0xda;
        break;
    case SPACE_PARITY:
        S2CON = 0xd2;
        break;
    }
}

void uart_set_baud(DWORD baud)
{
    WORD temp;

    temp = (WORD)BR(baud);
    T2L = temp;
    T2H = temp >> 8;
}

void uart_polling()
{
    BYTE dat;
    BYTE cnt;

    if (DeviceState != DEVSTATE_CONFIGURED)
        return;

    if (!UsbInBusy && (TxRptr != TxWptr))
    {
        IE2 &= ~0x80;   //EUSB = 0;
        UsbInBusy = 1;
        usb_write_reg(INDEX, 1);
        cnt = 0;
        while (TxRptr != TxWptr)
        {
            usb_write_reg(FIFO1, TxBuffer[TxRptr++]);
            cnt++;
            if (cnt == EP1IN_SIZE) break;
        }
        usb_write_reg(INCSR1, INIPRDY);
        IE2 |= 0x80;    //EUSB = 1;
    }

    if (!UartBusy && (RxRptr != RxWptr))
    {
        dat = RxBuffer[RxRptr++];
        UartBusy = 1;
        switch (LineCoding.bParityType)
        {
        case NONE_PARITY:
        case SPACE_PARITY:
            S2CON &= ~0x08;     //S2TB8 = 0;
            break;
        case ODD_PARITY:
            ACC = dat;
            if(P) S2CON &= ~0x08;   //S2TB8 = !P;
            else  S2CON |= 0x08;
            break;
        case EVEN_PARITY:
            ACC = dat;
            if(P) S2CON |= 0x08;    //S2TB8 = P;
            else  S2CON &= ~0x08;
            break;
        case MARK_PARITY:
            S2CON |= 0x08;      //S2TB8 = 1;
            break;
        }
        S2BUF = dat;

        while (UartBusy);
    }

    if (UsbOutBusy)
    {
        IE2 &= ~0x80;   //EUSB = 0;
        if (RxWptr - RxRptr < 256 - EP1OUT_SIZE)
        {
            UsbOutBusy = 0;
            usb_write_reg(INDEX, 1);
            usb_write_reg(OUTCSR1, 0);
        }
        IE2 |= 0x80;    //EUSB = 1;
    }
}
