#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_Baudrate( BYTE BR )
  { switch( BR )
      { case BR_1200:   PCON &= 0x7F;            // SMOD = 0 -> Default BR
                        AUXR2 &= ~T1X12;         // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                        TL1 = 0xCC;
                        TH1 = 0xCC;              // 256 - 52
                        break;
        case BR_2400:   PCON |= 0x80;            // SMOD = 1 -> Double BR
                        AUXR2 &= ~T1X12;         // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                        TL1 = 0xCC;
                        TH1 = 0xCC;              // 256 - 52
                        break;
        case BR_4800:   PCON &= 0x7F;            // SMOD = 0 -> Default BR
                        AUXR2 &= ~T1X12;         // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                        TL1 = 0xF3;
                        TH1 = 0xF3;              // 256 - 13
                        break;
        case BR_9600:   PCON |= 0x80;            // SMOD = 1 -> Double BR
                        AUXR2 &= ~T1X12;         // Fosc = Fosc/12 ( 12Mhz/12 = 1Mhz )
                        TL1 = 0xF3;
                        TH1 = 0xF3;              // 256 - 13
                        break;
        case BR_19200:  PCON &= 0x7F;            // SMOD = 0 -> Default BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0xD9;
                        TH1 = 0xD9;              // 256 - 39
                        break;
        case BR_38400:  PCON |= 0x80;            // SMOD = 1 -> Double BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0xD9;
                        TH1 = 0xD9;              // 256 - 39
                        break;
        case BR_57600:  PCON &= 0x7F;            // SMOD = 0 -> Default BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0xF3;
                        TH1 = 0xF3;              // 256 - 13
                        break;
        case BR_115200: PCON |= 0x80;            // SMOD = 1 -> Double BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0xF3;
                        TH1 = 0xF3;              // 256 - 13
                        break;
        case BR_7200:   PCON &= 0x7F;            // SMOD = 0 -> Default BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0x98;
                        TH1 = 0x98;              // 256 - 104
                        break;
        case BR_14400:  PCON |= 0x80;            // SMOD = 1 -> Double BR
                        AUXR2 |= T1X12;          // Fosc = Fosc ( 12Mhz )
                        TL1 = 0x98;
                        TH1 = 0x98;              // 256 - 104
                        break;
      }
  }


void Initial_UART( void )
  { Uart_Baudrate( BR_9600 );
    
    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
  }