/*----------------------------------------------*/
/* SCIF control module                          */
/*----------------------------------------------*/


#include "cpu.h"
#include "scif.h"


#define BUFFER_SIZE 128

#define PCLK		24000000UL
#define BPS 		38400



/* Tx/Rx buffer  */
static volatile struct {
	int		ri, wi, ct;
	BYTE	buff[BUFFER_SIZE];
} TxFifo, RxFifo;




/*---------------------------------------*/
/* Initialize SCIF ch2                   */
/*---------------------------------------*/

void scif2_init (void)
{
	*STBCR4 &= ~0x20;	/* Enable SCIF2 module */

	*SCSCR2 = 0x0000;	/* Stop SCIF2 */

	/* Attach SCIF2 unit (TxD2/RxD2) to I/O pad */
	*PFCR0 = (*PFCR0 & 0xF00F) | 0x0440;

	/* Initialize SCIF2 */
	*SCEMR2 = 0x0081;						/* Bit rate */
	*SCBRR2 = 25;
	*SCSMR2 = 0x0000;						/* Data format (N81) */
	*SCFCR2 = 0x00B6; *SCFCR2 = 0x00B0;		/* Clear Tx/Rx FIFO */

	/* Clear Tx/Rx Buffer */
	TxFifo.ri = 0; TxFifo.wi = 0; TxFifo.ct = 0;
	RxFifo.ri = 0; RxFifo.wi = 0; RxFifo.ct = 0;

	/* Set SCIF2 interrupt level */
	*IPR17 = (*IPR17 & 0xFF0F) | 0x0010;	/* level 1 */

	*SCSCR2 = 0x0070;	/* Start SCIF2 (Set TE,RE,RIE) */
}



/*---------------------------------------*/
/* Get number of bytes in the Rx Buffer  */
/*---------------------------------------*/

int scif2_test (void)
{
	return RxFifo.ct;
}



/*---------------------------------------*/
/* Get a byte from Rx buffer             */
/*---------------------------------------*/

BYTE scif2_get (void)
{
	BYTE d;
	int i;

	/* Wait while Rx buffer is empty */
	while (!RxFifo.ct) ;

	*SCSCR2 &= ~0x0040;		/* Disable Rx interrupt (Clear RIE) */

	i = RxFifo.ri;
	d = RxFifo.buff[i++];	/* Get a byte from Rx buffer */
	RxFifo.ri = i % BUFFER_SIZE;
	RxFifo.ct--;

	*SCSCR2 |= 0x0040;		/* Enable Rx interrupt (Set RIE) */

	return d;
}



/*---------------------------------------*/
/* Put a byte into Tx buffer             */
/*---------------------------------------*/

void scif2_put (BYTE d)
{
	int i;


	while (TxFifo.ct >= BUFFER_SIZE) ;	/* Wait for buffer ready */

	*SCSCR2 &= ~0x0080;		/* Disable Tx interrupt (Clear TIE) */

	i = TxFifo.wi;			/* Store the data into the Tx buffer */
	TxFifo.buff[i++] = d;
	TxFifo.wi = i % BUFFER_SIZE;
	TxFifo.ct++;

	*SCSCR2 |= 0x0080;		/* Enable Tx interrupt (Set TIE) */
}



/*---------------------------------------*/
/* ISR for data receive event            */
/*---------------------------------------*/

void Isr_RXI2 (void)
{
	int i, cnt;
	BYTE d;


	i = RxFifo.wi;
	cnt = RxFifo.ct;
	do {				/* Read all data from FIFO */
		d = *SCFRDR2;
		if (cnt < BUFFER_SIZE) {	/* Store the byte if buffer is not full */
			RxFifo.buff[i++] = d;
			i %= BUFFER_SIZE;
			cnt++;
		}
	} while (*SCFDR2 & 0x001F);

	*SCFSR2 &= ~0x0083;		/* Clear interrupt flags */

	RxFifo.wi = i;
	RxFifo.ct = cnt;
}



/*---------------------------------------*/
/* ISR for data transimit event          */
/*---------------------------------------*/

void Isr_TXI2 (void)
{
	int i, cnt;


	cnt = TxFifo.ct;
	if (cnt) {
		i = TxFifo.ri;
		do {					/* Fill Tx FIFO */
			*SCFTDR2 = TxFifo.buff[i++];
			i %= BUFFER_SIZE;
			cnt--;
		} while (cnt && (*SCFDR2 >> 8) < 16);
		TxFifo.ri = i;
		TxFifo.ct = cnt;
		*SCFSR2 &= ~0x0020;		/* Clear Tx interrupt flag */
	}
	if (!cnt)	/* Disable Tx irq if no data in the buffer */
		*SCSCR2 &= ~0x0080;		/* Clear TIE */
}



