#include "REG_MG84FL54.H"
#include "Define.H"
#include "Extern.H"
#include "UART.H"


BYTE OutLen = 0;
XBYTE OutBuffer[UART_MAX] _at_ (0x200-UART_MAX); // XRAM total 576(0~575) bytes ( 512~575
                                                 // for InBuffer , 448~511 for OutBuffer )
UART Uart;


void UART_Send_Data_To_PC( void )
  { if ( Uart.Data_Cnt == 0 )                    // Do Nothing
      return;

    ES = CLR;                                    // Disable " Uart INT " , prevent 
    if (( Uart.Out_Addr + Uart.Data_Cnt  ) > UART_MAX ) // Uart.Data_Cnt Change
      OutLen = UART_MAX - Uart.Out_Addr;         // OutBuffer boundary
    else
      OutLen = Uart.Data_Cnt;
    Uart.Data_Cnt -= OutLen;
    ES = SET;                                    // Enable " Uart INT "
    
    USB_Send_Data_To_PC( OutLen , ( OutBuffer+Uart.Out_Addr ));
    Uart.Out_Addr += OutLen;
    
    if ( Uart.Out_Addr == UART_MAX )             // Top of " OutBuffer "
      Uart.Out_Addr = 0;                         // Reset " Out_Addr " from 0
  }


void UART_Send_Data_To_Device( BYTE Size , BYTE *Buffer )
  { BYTE i = 0;
    
    
    while( i < Size )
      { while( Uart.Tx_Busy == SET );            // Wait Tx Complete
      	Uart.Tx_Busy = SET;
      	SBUF = Buffer[i];                        // Send data
      	i++;
      	UART_Send_Data_To_PC();
      }
  }


void UART_Error( void )
  { Com.State = 0x00;
    // To do
    /*
    Rx Carrier occur ?
    Com.State |= UART_RX_CARRIER;
    
    Tx Carrier occur ?
    Com.State |= UART_TX_CARRIER;
    
    Break occur ?
    Com.State |= UART_BREAK;
    
    Ring signal occur ?
    Com.State |= UART_RING_SIGNAL;
    
    Fram error occur ?
    Com.State |= UART_FRAM_ERROR;
    
    Parity check error occur ?
    Com.State |= UART_PARITY_ERROR;
    
    Over run occur ?
    Com.State |= UART_OVER_RUN;
    */
  }


void UART_Event( void )                          // Do not remove ( Only support N,8,1 )
  { if ( Com.LC.Flag )                           // Line codeing setting by Host ( PC )
      { switch( Com.LC.BaudRate.DW )             // Com.LC.BaudRate.B[3] = LSB , Com.LC.BaudRate.B[0] = MSB
          { case 1200:   PCON &= 0x7F;           // SMOD = 0 -> Default BR
                         AUXR2 &= ~T1X12;        // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                         TL1 = 0xCC;
                         TH1 = 0xCC;             // 256 - 52
                         break;
            case 2400:   PCON |= 0x80;           // SMOD = 1 -> Double BR
                         AUXR2 &= ~T1X12;        // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                         TL1 = 0xCC;
                         TH1 = 0xCC;             // 256 - 52
                         break;
            case 4800:   PCON &= 0x7F;           // SMOD = 0 -> Default BR
                         AUXR2 &= ~T1X12;        // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                         TL1 = 0xF3;
                         TH1 = 0xF3;             // 256 - 13
                         break;
            case 9600:   PCON |= 0x80;           // SMOD = 1 -> Double BR
                         AUXR2 &= ~T1X12;        // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                         TL1 = 0xF3;
                         TH1 = 0xF3;             // 256 - 13
                         break;
            case 19200:  PCON &= 0x7F;           // SMOD = 0 -> Default BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0xD9;
                         TH1 = 0xD9;             // 256 - 39
                         break;
            case 38400:  PCON |= 0x80;           // SMOD = 1 -> Double BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0xD9;
                         TH1 = 0xD9;             // 256 - 39
                         break;
            case 57600:  PCON &= 0x7F;           // SMOD = 0 -> Default BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0xF3;
                         TH1 = 0xF3;             // 256 - 13
                         break;
            case 115200: PCON |= 0x80;           // SMOD = 1 -> Double BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0xF3;
                         TH1 = 0xF3;             // 256 - 13
                         break;
            case 7200:   PCON &= 0x7F;           // SMOD = 0 -> Default BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0x98;
                         TH1 = 0x98;             // 256 - 104
                         break;
            case 14400:  PCON |= 0x80;           // SMOD = 1 -> Double BR
                         AUXR2 |= T1X12;         // Fosc = Fosc ( 12Mhz )
                         TL1 = 0x98;
                         TH1 = 0x98;             // 256 - 104
                         break;
          }
        Com.LC.Flag = CLR;                       // Release this flag
      }
    if ( Com.LS.Flag )                           // Line state setting by Host ( PC )
      { // To do ( Depend on " Com.LS.State " )
      	Com.LS.Flag = CLR;                       // Release this flag
      }
    if ( Com.SB.Flag )                           // Send break by Host ( PC )
      { // To do ( Depend on " Com.SB.Time.W " )
      	Com.SB.Flag = CLR;                       // Release this flag
      }
    
    UART_Error();                                // To do
    if ( Com.State )
      USB_Send_UartState_To_PC( Com.State );
  }


void Initial_UART( void )
  { Com.LC.Flag = SET;
    Com.LC.BaudRate.DW = 9600;                   // Default 9600 BR
    UART_Event();
    
    Uart.In_Addr = 0;
    Uart.Out_Addr = 0;
    Uart.Data_Cnt = 0;
    Uart.Tx_Busy = CLR;
    
    AUXR |= BRADJ0;                              // Double BR
    
    IP |= 0x10;	                                 // hi priority: UART
    
    TMOD |= 0x20;                                // Set Timer1 in Mode2 ( 8 bit )
    SCON = 0x50;                                 // Set UART work at MODE1
        
    ES = SET;                                    // Enable UART interrupt
    TR1 = SET;                                   // Enable Timer1 for UART
  }