
/*
 *
 *     Module Name: simpleSerial.c
 *	       Version: 1.00
 *   Original Date: 02/24/03	
 *	        Author: Li Zhen
 *	      Language: Ansi C
 * Compile Options:
 * Compile defines:
 *	     Libraries:
 *    Link Options:
 *
 *    Entry Points:  
 *
 *  Copyright (c) Digi International Inc., All Rights Reserved
 *  
 *  This software contains proprietary and confidential information of Digi
 *  International Inc.  By accepting transfer of this copy, Recipient agrees
 *  to retain this software in confidence, to prevent disclosure to others,
 *  and to make no use of this software other than that for which it was
 *  delivered.  This is an unpublished copyrighted work of Digi International
 *  Inc.  Except as permitted by federal law, 17 USC 117, copying is strictly
 *  prohibited.
 *  
 *  Restricted Rights Legend
 * 
 *  Use, duplication, or disclosure by the Government is subject to
 *  restrictions set forth in sub-paragraph (c)(1)(ii) of The Rights in
 *  Technical Data and Computer Software clause at DFARS 252.227-7031 or
 *  subparagraphs (c)(1) and (2) of the Commercial Computer Software -
 *  Restricted Rights at 48 CFR 52.227-19, as applicable.
 * 
 *  Digi International Inc. 11001 Bren Road East, Minnetonka, MN 55343
 */
#if   (defined(SP_ENABLED) || defined(WiSP_ENABLED))
/* Description.
 * =======================================================================
 *  This file contains the code that sets up a simple serial driver to be 
 *  able to output some debugging informations in BSP initilization stage 
 *  before kernel is loaded.
 *  THE CODE IN THIS FILE MUST BE CUSTOMIZED TO SUPPORT YOUR APPLICATION
 *  HARDWARE.  The default implementation supports the NET+OS development
 *  boards -- connectsp and connectwisp, external serial port.
 *
 *
 *
 * Edit Date/Ver   Edit Description
 * ==============  =======================================================
 */
#include "fwtypes.h"
#include <string.h>
#include <gpio.h>
#include "sysClock.h"
#include <reg_def.h>
#include <ncc_init.h>
#include <gpio_def.h>
// #include "bsp.h"
#include <simpleserial.h>
#include "bsp_serial.h"

#define UART_BASE	0x10000000

#define RHR (UART_BASE+0x00)	/* 0 Rx Holding Register */
#define THR (UART_BASE+0x00)	/* 0 Tx Holding Register */
#define IER (UART_BASE+0x02)	/* 1 Interrupt Enable Register */
#define FCR (UART_BASE+0x04)	/* 2 FIFO Control Register */
#define ISR (UART_BASE+0x04)	/* 2 Interrupt Status Register */
#define LCR (UART_BASE+0x06)	/* 3 Line Control Register */
#define MCR (UART_BASE+0x08)	/* 4 Modem Control Register */
#define LSR (UART_BASE+0x0A)	/* 5 Line Status Register */
#define MSR (UART_BASE+0x0C)	/* 6 Modem Status Register */
#define SPR (UART_BASE+0x0E)	/* 7 Scratch Pad Register */

#define DLL (UART_BASE+0x00)	/* 0 Divisor Latch Low */
#define DLH (UART_BASE+0x02)	/* 1 Divisor Latch High */

#define EFR (UART_BASE+0x04)	/* 2 Enhanced Feature Register */
#define Xon1 (UART_BASE+0x08)
#define Xon2 (UART_BASE+0x0A)
#define Xoff1 (UART_BASE+0x0C)
#define Xoff2 (UART_BASE+0x0E)

#define LSR_RXD 0x01	    /* Rx Data present */
#define LSR_THE 0x20

#define LCR_WLB0 0x01
#define LCR_WLB1 0x02
#define LCR_DLE 0x80		/* Divisor Latch Enable */
#define LCR_EFRE 0xBF		/* Enable Enhanced Register Access */

#define MCR_DTR 0x01
#define MCR_RTS 0x02
#define MCR_OP1 0x04
#define MCR_OP2 0x08
#define MCR_INT 0x08
#define MCR_LB 0x10

#define MSR_dCTS 0x01
#define MSR_dDSR 0x02
#define MSR_dRI 0x04
#define MSR_dCD 0x08
#define MSR_CTS 0x10
#define MSR_DSR 0x20
#define MSR_RI 0x40
#define MSR_CD 0x80

#define CRYSTAL_FREQUENCY_FOR_ORIG_SP       18432000
#define CRYSTAL_FREQUENCY_FOR_NEW_SP        14745600
#define NA_CONNECTSP_ORIG_SP                0
#define NA_CONNECTSP_NEW_SP_RS232_ONLY      1
#define NA_CONNECTSP_NEW_SP                 2

  

/*  Function: setupSimpleSerial (void)
 *
 *  Description:
 *     This function will setup a Serial Port so BSP can send some info
 *     through the PORTA debugger port.
 *
 *  Parameters:
 *     none
 *  
 *  Return Value:
 *     none
 *
 */

void setupSimpleSerial()
{
    volatile int i;
    
    int boardType = narm_read_reg (NARM_GSSR_REG, NARM_GSSR_ADDR, gen_id1) & 0x7;
    
    if (boardType == NA_CONNECTSP_ORIG_SP)
    {
        /*  Only the original SP uses the 18 Mhz crystal    */
        i = CRYSTAL_FREQUENCY_FOR_ORIG_SP / (9600 * 16);  
    }
    else
    {
        /*  All others use the new crystal  */
        i = CRYSTAL_FREQUENCY_FOR_NEW_SP / (9600 * 16);
    }  
     
        *NARM_CSOR4_ADDR = 0xfff00574;  /* CS4 OptA */
        *NARM_CSAR4_ADDR = 0x10000001;  /* CS4 Base */
        *NARM_CSORB4_ADDR = 0x5;        /* CS4 OptB */

//    *((volatile unsigned short*)SPR) = 'A';
    
    /* disable interrupts */
    *((volatile unsigned short*)IER) = (unsigned char)0;
    /* enable divisor regs */
    *((volatile unsigned short*)LCR) = (unsigned char)LCR_DLE;
    /* set DivH */
    *((volatile unsigned short*)DLH) = (unsigned char)((i>>8)&0xff);
    /* set DivL*/
    *((volatile unsigned short*)DLL) = (unsigned char)(i&0xff);
    /* disable divisor regs */
    *((volatile unsigned short*)LCR) = (unsigned char)(LCR_WLB1 + LCR_WLB0);
    
    *((volatile unsigned short*)MCR) = (unsigned char)3;
    
    /* Enable FIFOs and reset them */
    *((volatile unsigned short*)FCR) = (unsigned char)7; 
    /* remove FIFO reset */
    *((volatile unsigned short*)FCR) = (unsigned char)1;

     i = *((volatile unsigned short*)LSR);
     i = *((volatile unsigned short*)RHR);
    
}
 
/*  Function: bsp_fputc (char out)
 *
 *  Description:
 *     This function will print one byte infomation
 *     through the PORTA debugger port.
 *
 *  Parameters:
 *     out:		byte to be printed
 *  
 *  Return Value:
 *     none
 *
 */
void bsp_fputc (char out)
{
	
// wait for empty, then stuff into fifo

    while (((*((volatile unsigned short*)LSR)) & (unsigned char)(LSR_THE))==0)
    {
	    ;
    }
    *((volatile unsigned short*)THR) = (unsigned char)out;
    
    if (out == 0x0a)  /* If line feed, add carriage return */
	{
		while (((*((volatile unsigned short*)LSR)) & (unsigned char)(LSR_THE))==0)
        {
	        ;
        }
        
        *((volatile unsigned short*)THR) = (unsigned char)0x0d;
	}

}

/*  Function: bsp_printf (char *outString)
 *
 *  Description:
 *     This function will print a null terminated string
 *     through the PORTA debugger port. This function is intended only 
 *     to be used in early BSP initialization stage before the kernel and 
 *     device driver are loaded. The string should be as short as possible
 *     due to limited stack.
 *
 *  Parameters:
 *     outString:	pointer to a null terminated string
 *  
 *  Return Value:
 *     none
 *
 */
void bsp_printf (char *outString)
{

	unsigned int i;

    /* if the serial channel is not set up, set it up */
	 
        setupSimpleSerial();


	for (i = 0; i < strlen(outString); i++)
		bsp_fputc(outString[i]);
    
    /*let it finish*/
    while (((*((volatile unsigned short*)LSR)) & (unsigned char)(LSR_THE))==0)
        {
	        ;
        }
}

 
    
int bsp_fgetc(int pollTime)
{
    
    #define BSP_FGET_POLLING_SPEED  1000
    unsigned long wait_time = pollTime * BSP_FGET_POLLING_SPEED; 

       // Wait for the Receiver Buffer Ready
        while((((*((volatile unsigned short*)LSR))&(unsigned char)(LSR_RXD))==0) && (wait_time-- > 0))
        {
	        ;
        }
        
        if (wait_time== 0)
            return -2;
        else
            return ((int)(*((volatile unsigned short*)RHR))) & 0x000000ff;
}


void bsp_flush(void)
{
    while (bsp_fgetc(1000) >= 0);
}

#else
 /* Description.
 * =======================================================================
 *  This file contains the code that sets up a simple serial driver to be 
 *  able to output some debugging informations in BSP initilization stage 
 *  before kernel is loaded.
 *  THE CODE IN THIS FILE MUST BE CUSTOMIZED TO SUPPORT YOUR APPLICATION
 *  HARDWARE.  The default implementation supports the NET+OS development
 *  boards, serial PORTA.
 *
 *
 *
 * Edit Date/Ver   Edit Description
 * ==============  =======================================================
 *
 *  JZW    05/20/03  Include string.h and sysClock.h to pick up functional
 *                   prototypes
 *  JZW    10/24/05  In the function get_baud_div, the tables entitled
 *         Clocks and Clockmodes, were set up in memory. The problem is that
 *         when using simpleserial at very early times, memory may not be totally
 *         set up. This was causing these tables to be loaded with garbage. Due to this
 *         the loops in setupSimpleSerial, when used very early, were continuing
 *         without bounds. This is because of the way memory was at that time, 
 *         there were no 0,0 entries in the tables and so the loop exit criterion would
 *         never be hit. Fix is to set the tables up as const
 *  JZW    10/25/05 re previous fix, gcc requires static const as opposed to const static
 *         GH will take either. So changed declarations of Clocks and Clockmodes to
 *         static const
 *  JZW	   11/1/05 In function bsp_printf if the channel is not enabled, call setupSimpleSerial
 *         before continuing with sending characters over the serial channel
 */
#include "fwtypes.h"
#include <string.h>
#include <gpio.h>
#include "sysClock.h"
#include <reg_def.h>
#include <ncc_init.h>
#include <gpio_def.h>
// #include "bsp.h"
#include "bsp_serial.h"
#include <simpleserial.h>

/*** Serial Channel Bit-Rate Register ***/
/* Control section ... */
#define BIT_GEN_ON             0x80000000U  /* Enable Bit-Rate Generator          */
#define BIT_RATE_X1            0x40000000U  /* Timing mode: 0 = X16 1 = X1        */
#define BIT_RATE_X16           0x00000000U  /* Timing mode: 0 = X16 1 = X1        */
#define BIT_TDCR_RDCR_X1       0x00000000U  /* for 20UM only. Transmit/Receive Divide Clock Rate, D20:19/D17:16=00/00 1X clock mode*/
#define BIT_TDCR_RDCR_X8	   0x00090000U  /* for 20UM only. Transmit/Receive Divide Clock Rate, D20:19/D17:16=01/01 8X clock mode*/
#define BIT_TDCR_RDCR_X16      0x00120000U  /* for 20UM only. Transmit/Receive Divide Clock Rate, D20:19/D17:16=10/10 16X clock mode*/
#define BIT_TDCR_RDCR_X32      0x001b0000U  /* for 20UM only. Transmit/Receive Divide Clock Rate, D20:19/D17:16=11/11 32X clock mode*/
#define RECV_CLK_SRC_EXT       0x20000000U  /* Receive clock source is External   */
#define RECV_CLK_SRC_INT       0x00000000U  /* Receive clock source is Internal   */
#define XMIT_CLK_SRC_EXT       0x10000000U  /* Transmit clock source is External  */
#define XMIT_CLK_SRC_INT       0x00000000U  /* Transmit clock source is Internal  */
#define RECV_CLK_OUT_ON        0x08000000U  /* Drive RXCLK out OUT1 of Port A/B   */
#define RECV_CLK_OUT_OFF       0x00000000U  /* Do not drive RXCLK to OUT1         */
#define XMIT_CLK_OUT_ON        0x04000000U  /* Drive TXCLK out OUT2 of Port C     */
#define XMIT_CLK_OUT_OFF       0x00000000U  /* Do not drive TXCLK to OUT2         */
#define BIT_RATE_CLK_EXT       0x00000000U  /* Use the external Clk source        */
#define BIT_RATE_CLK_SYS       0x01000000U  /* Use System Clk as source Bit-Rate  */
#define BIT_RATE_CLK_OUT1A     0x02000000U  /* Use OUT1A as source Bit-Rate Clk   */
#define BIT_RATE_CLK_OUT2A     0x03000000U  /* Use OUT2A as source Bit-Rate Clk   */
#define BIT_RATE_TXCINV        0x00800000U  /* TXD driven on rising edge of TX clock  */
#define BIT_RATE_RXCINV        0x00400000U  /* RRXD sampled on falling edge of RX clock */
#define BIT_RATE_CLKINV        0x00200000U  /* Receive Clock Invert               */

#define BIT_RATE_RX_DPLL       0x00001000U /* Recover clock from receive data */
/* Bits 23 to 11 are reserved */
/* Divide Rate section */
/* algorithms changed 6/26/00 multiply the baud rate * 10 by 16. Divide the XTAL_FREQ
 * by this product and then as the LAST step, subtract one from this quotient.
 */
#define BIT_RATE_DIV_MASK      0x000007FFU  /* Bit-Rate (baud) divisor count mask */
#define MIN_BAUD_RATE           75
#define MAX_BAUD_RATE           115200
#define DEFAULT_BAUD_RATE       9600  /* default used in case of error */
#define DEFAULT_BAUD_RATE_ERROR 5       /* 1 percent error */

/*** End Serial Channel Bit-Rate Register ***/

#define BSP_FGET_POLLING_SPEED  1000

#define SIMPLESERIAL_ENABLE		0x80000000
#define SIMPLESERIAL_8BITS		0x03000000
#define SIMPLESERIAL_DTR		0x00020000
#define SIMPLESERIAL_RTS		0x00010000
#define SIMPLESERIAL_RCGT		0x04000000
#define SIMPLESERIAL_CLEAN		0xffffffff
#define SIMPLESSERIAL_GAPTIMER  0x000000ff
#define SIMPLESERIAL_BAUDRATE   9600


struct baudTable {
    unsigned int value;
    unsigned int divr_or;
};

enum baudClkIdx {
    XTAL_IDX,
    SYS_IDX,
};

static const struct baudTable Clocks[] = {
    { 1, BIT_RATE_CLK_EXT }, /* XTAL_IDX */
    { 1, BIT_RATE_CLK_SYS }, /* SYS_IDX */
    {0,0},
};

static const struct baudTable Clockmodes[] = {
    {16, BIT_RATE_X16},
    {8, BIT_RATE_X1 | BIT_TDCR_RDCR_X8 | BIT_RATE_RX_DPLL},
    {32, BIT_RATE_X1 | BIT_TDCR_RDCR_X32 | BIT_RATE_RX_DPLL},
    {0,0},
};

static int get_baud_div(int baudrate, uint32 *divr)
{
    const unsigned int ELEVEN_BIT_MAX = 2047;
    unsigned int Clk, bestClkIdx = 0;
    unsigned int clockMode, bestModeIdx = 0;
    unsigned int err, bestErr = 0xffffffff;
    unsigned int N, bestN = ELEVEN_BIT_MAX + 1;
    int clkindex = 0;
    int modeindex = 0;

    /* Iterate through clocks */
    while (Clocks[clkindex].value) {
        switch(clkindex) {
        case XTAL_IDX:
            Clk = NAgetSysOscFreq();
            break;
        case SYS_IDX:
            Clk = NAgetCpuClkFreq();
            break;
        default:
            return 100; /* 100% error */
        };
        
        modeindex = 0;
        /* Iterate through divisors */
        while ( (clockMode = Clockmodes[modeindex].value) ) {

            /* Compute N */
            N = Clk / (clockMode * 2 * baudrate) - 1;

            /* Round up? */
            if ( (Clk % (clockMode * 2 * baudrate)) 
                 > (clockMode * baudrate)) 
            {
                /* remainder is more than half */
                N++;
            }

            /* Compute err */
            if (N > ELEVEN_BIT_MAX) {
                err = 0xffffffff;
            } else {
                unsigned int realBaud = Clk / (clockMode * 2 * (N + 1)) ;
                if ((int)realBaud > baudrate) {
                    err = realBaud - baudrate;
                } else {
                    err = baudrate - realBaud;
                }
            }

            if (err < bestErr) {
                bestN = N;
                bestErr = err;
                bestModeIdx = modeindex;
                bestClkIdx = clkindex;
            }

            if (bestErr == 0) {
                break;
            }
            modeindex++;
        }

        if (bestErr == 0) {
            break;
        }
        clkindex++;
    }

    if (bestN == ELEVEN_BIT_MAX + 1) {
        return 100;
    }

    if (bestErr == 0xffffffff) {
        return 100;
    }

    *divr = Clocks[bestClkIdx].divr_or 
        | Clockmodes[bestModeIdx].divr_or
        | bestN;

    return bestErr * 100 / baudrate;
    
}


/*  Function: setupSimpleSerial (void)
 *
 *  Description:
 *     This function will setup a Serial Port so BSP can send some info
 *     through the PORTA debugger port.
 *
 *  Parameters:
 *     none
 *  
 *  Return Value:
 *     none
 *
 */

void setupSimpleSerial()
{
    uint32 baud_div = 0;
    int error_rate;

#if (BSP_SIMPLE_SERIAL_PORT == BSP_SIMPLE_SERIAL_ON_PORTC)
	/* connectcore7u_a's dialog port is actually portC not portA*/    
	/*setup serial port c control register A*/
	*NARM_SC2CRA_ADDR = SIMPLESERIAL_ENABLE | SIMPLESERIAL_8BITS | SIMPLESERIAL_DTR | SIMPLESERIAL_RTS;
	
	/*setup serial port c control register B*/
	*NARM_SC2CRB_ADDR = SIMPLESERIAL_RCGT;
	
	/*setup serial port c status register*/
	*NARM_SC2SRA_ADDR = SIMPLESERIAL_CLEAN;  

	*NARM_PORTC_ADDR |= GPIO_FULL_FUNCTION_SERIAL_PORT;
 
	/*setup serial port c receive charactor gap timer register*/
	*NARM_SC2RCT_ADDR = SIMPLESERIAL_ENABLE | SIMPLESSERIAL_GAPTIMER;  

	/*setup serial port c bit-rate register, 9600 baudrate */
    error_rate = get_baud_div(NAGetAppBspBaudRate(), &baud_div); 
    if (error_rate < DEFAULT_BAUD_RATE_ERROR) /* less than 5% */
        *NARM_SC2BRG_ADDR = SIMPLESERIAL_ENABLE | baud_div;
    else	
	    *NARM_SC2BRG_ADDR = SIMPLESERIAL_ENABLE | (NAgetSysOscFreq()/(2*16*SIMPLESERIAL_BAUDRATE) -1);  
#else
     
	/*setup serial port A control register A*/
	*NARM_SC1CRA_ADDR = SIMPLESERIAL_ENABLE | SIMPLESERIAL_8BITS | SIMPLESERIAL_DTR | SIMPLESERIAL_RTS;
	
	/*setup serial port A control register B*/
	*NARM_SC1CRB_ADDR = SIMPLESERIAL_RCGT;
	
	/*setup serial port A status register*/
	*NARM_SC1SRA_ADDR = SIMPLESERIAL_CLEAN;  

	*NARM_PORTA_ADDR |= GPIO_FULL_FUNCTION_SERIAL_PORT;
 
	/*setup serial port A receive charactor gap timer register*/
	*NARM_SC1RCT_ADDR = SIMPLESERIAL_ENABLE | SIMPLESSERIAL_GAPTIMER;  

	/*setup serial port A bit-rate register, 9600 baudrate */
    error_rate = get_baud_div(NAGetAppBspBaudRate(), &baud_div); 
    if (error_rate < DEFAULT_BAUD_RATE_ERROR) /* less than 5% */
        *NARM_SC1BRG_ADDR = SIMPLESERIAL_ENABLE | baud_div;
    else	
	    *NARM_SC1BRG_ADDR = SIMPLESERIAL_ENABLE | (NAgetSysOscFreq()/(2*16*SIMPLESERIAL_BAUDRATE) -1);  
#endif
}

/*  Function: bsp_fputc (char out)
 *
 *  Description:
 *     This function will print one byte infomation
 *     through the PORTA debugger port.
 *
 *  Parameters:
 *     out:		byte to be printed
 *  
 *  Return Value:
 *     none
 *
 */
void bsp_fputc (char out)
{
#if (BSP_SIMPLE_SERIAL_PORT == BSP_SIMPLE_SERIAL_ON_PORTC)
    /* Wait for the Transmit Buffer Ready */
	while (narm_read_reg(NARM_SSRA_REG, NARM_SC2SRA_ADDR, txrdy)== 0);

	/* Write the output byte */
	*(BYTE *)NARM_SC2FIFO_ADDR = out;

	if (out == 0x0a)  /* If line feed, add carriage return */
	{
		/* Wait for the Transmit Buffer Ready */
		while (narm_read_reg(NARM_SSRA_REG, NARM_SC2SRA_ADDR, txrdy)== 0);

		/* Write the carriage return byte */
		*(BYTE *)NARM_SC2FIFO_ADDR = 0x0d;
	}
#else
	/* Wait for the Transmit Buffer Ready */
	while (narm_read_reg(NARM_SSRA_REG, NARM_SC1SRA_ADDR, txrdy)== 0);

	/* Write the output byte */
	*(BYTE *)NARM_SC1FIFO_ADDR = out;

	if (out == 0x0a)  /* If line feed, add carriage return */
	{
		/* Wait for the Transmit Buffer Ready */
		while (narm_read_reg(NARM_SSRA_REG, NARM_SC1SRA_ADDR, txrdy)== 0);

		/* Write the carriage return byte */
		*(BYTE *)NARM_SC1FIFO_ADDR = 0x0d;
	}
#endif
}

/*  Function: bsp_printf (char *outString)
 *
 *  Description:
 *     This function will print a null terminated string
 *     through the PORTA debugger port. This function is intended only 
 *     to be used in early BSP initialization stage before the kernel and 
 *     device driver are loaded. The string should be as short as possible
 *     due to limited stack.
 *
 *  Parameters:
 *     outString:	pointer to a null terminated string
 *  
 *  Return Value:
 *     none
 *
 */
void bsp_printf (char *outString)
{

	unsigned int i;
#if (BSP_SIMPLE_SERIAL_PORT == BSP_SIMPLE_SERIAL_ON_PORTC)
    /* if the serial channel is not set up, set it up */
	if(narm_read_reg(NARM_SCRA_REG, NARM_SC2CRA_ADDR, ce) == 0)
	{
	    setupSimpleSerial();
	}
#else
    /* if the serial channel is not set up, set it up */
	if(narm_read_reg(NARM_SCRA_REG, NARM_SC1CRA_ADDR, ce) == 0)
	{
	    setupSimpleSerial();
	}
#endif

	for (i = 0; i < strlen(outString); i++)
		bsp_fputc(outString[i]);

}

/*  Function: bsp_fgetw (WORD32 *data)
 *
 *  Description:
 *     This function will print up to 4 bytes of data
 *     through the PORTA debugger port.
 *
 *  Parameters:
 *     data:        pointer to the location to store up to 4 bytes of data
 *  
 *  Return Value:
 *     size:        size of the data
 *
 */
char bsp_fgetw(int pollTime, WORD32 *data)
{
    char size = 0;
    unsigned long wait_time = pollTime * BSP_FGET_POLLING_SPEED; 
#if (BSP_SIMPLE_SERIAL_PORT == BSP_SIMPLE_SERIAL_ON_PORTC)
    /* Poll the RDY bit for data or RBC for status */
    do
    {                        
        if (narm_read_reg(NARM_SSRA_REG, NARM_SC2SRA_ADDR, rxrdy) == 1)
        {
            /* RDY bit is set, determine number of valid bytes in FIFO Data Register */
            size = narm_read_reg( NARM_SSRA_REG, NARM_SC2SRA_ADDR, rxfdb );
           
            if (size == 0)
            {
                /* Receive a complete word; set the size to 4 bytes */
                size = sizeof(WORD32);
            }
           
            /* Read the data register */
            memcpy((BYTE *) data, (BYTE *) NARM_SC2FIFO_ADDR, size);
        }

        if (narm_read_reg(NARM_SSRA_REG, NARM_SC2SRA_ADDR, rxbc) == 1)
        {
            /* Receive Buffer is closed; Set RBC bit to acknowledge */
            narm_write_reg( NARM_SSRA_REG, NARM_SC2SRA_ADDR, rxbc, 1 );

            break;
        }

        if (size)
            break; /* data has been read */

    } while(wait_time-- > 0);

    return (size);
#else
    /* Poll the RDY bit for data or RBC for status */
    do
    {                        
        if (narm_read_reg(NARM_SSRA_REG, NARM_SC1SRA_ADDR, rxrdy) == 1)
        {
            /* RDY bit is set, determine number of valid bytes in FIFO Data Register */
            size = narm_read_reg( NARM_SSRA_REG, NARM_SC1SRA_ADDR, rxfdb );
           
            if (size == 0)
            {
                /* Receive a complete word; set the size to 4 bytes */
                size = sizeof(WORD32);
            }
           
            /* Read the data register */
            memcpy((BYTE *) data, (BYTE *) NARM_SC1FIFO_ADDR, size);
        }

        if (narm_read_reg(NARM_SSRA_REG, NARM_SC1SRA_ADDR, rxbc) == 1)
        {
            /* Receive Buffer is closed; Set RBC bit to acknowledge */
            narm_write_reg( NARM_SSRA_REG, NARM_SC1SRA_ADDR, rxbc, 1 );

            break;
        }

        if (size)
            break; /* data has been read */

    } while(wait_time-- > 0);

    return (size);
#endif
}


    
/* This function shold never be called before main() */   
int bsp_fgetc(int pollTime)
{
    static int indx = 0;
    static char size = 0, data[sizeof(WORD32)];
    unsigned long temp;

    if (indx == size)
    {
        size = bsp_fgetw( pollTime, (WORD32 *)&temp );
        memcpy(data, &temp, sizeof(WORD32));
        indx = 0;
        if (size == 0)
        {
            /* Timeout */
            indx = 0;
            return -2;
        }
    }

    return (data[indx++] & 0xFF);
}


void bsp_flush(void)
{
    while (bsp_fgetc(1000) >= 0);
}
#endif
