#include "common.h" /* include peripheral declarations */
#define printf print_str

#include "i2c_cfg.h"
#include "dma_common.h"
#include "i2c.h"

void i2c_dma_master_tx(uint8 channel);
void i2c_dma_master_rx(uint8 channel);
void i2c_dma_slave_rx(uint8 channel);
void i2c_dma_slave_tx(uint8 channel);

void run_test(void);

void i2c_dma_master_tx(uint8 channel) 
{
	struct dma_tcd tcd1;
	uint8 i;

	/* Init transmit buffer */
    i2c_tx_buffer.tx_index = 0;
    i2c_tx_buffer.rx_index = 0;
    i2c_tx_buffer.data_present = TRUE;
    i2c_tx_buffer.length = 64;
    i2c_tx_buffer.buf[0] = (uint8)(I2C_SLAVE_ADDR&0x0FF);
	
	for(i=1;i<64;i++)
	{
		i2c_tx_buffer.buf[i] = i;
	}
	
	i2c_init(channel, I2C_MASTER_ADDR, 50000);
	I2C_C1(channel) |= I2C_C1_DMAEN_MASK; //enable dma request
	
	SIM_SCGC4 |= SIM_SCGC4_DMA_MASK;
	tcd1.channel_no = channel;
	tcd1.ctrl = (0 | DMA_DCR_ERQ_MASK 
					| DMA_DCR_SINC_MASK
					| DMA_DCR_CS_MASK
					| DMA_DCR_SSIZE(1)
					| DMA_DCR_DSIZE(1)
					| DMA_DCR_D_REQ_MASK);
	tcd1.daddr = &(I2C_D(channel));
	tcd1.saddr = &(i2c_tx_buffer.buf[0]);
	tcd1.nbytes = 63;	
	dma_config(CONFIG_BASIC_XFR, &tcd1);

	if(channel>3)
	{
		printf("***invalid I2C channel***\r\n");
		return;	
	}
	DMA_REQC &= ~(0x0F000000>>(channel*8));
	DMA_REQC |= (0x84000000>>(channel*8)); // dman, id 4	
	
	/* Make sure bus is idle */
	while (I2C_S(channel) & I2C_S_BUSY_MASK);
	/* Put module in master TX mode (generates START) */
	I2C_C1(channel) |= (I2C_C1_MST_MASK | I2C_C1_TX_MASK);
	I2C_D(channel) = ( 0 | (I2C_SLAVE_ADDR<<1) | I2C_TX);
	
	dma_config(WAIT_FOR_XFR, &tcd1);	
	/* Restore module to it's idle (but active) state */
	while (!(I2C_S(channel) & I2C_S_TCF_MASK));
	I2C_C1(channel) = 0x80;
}

void i2c_dma_master_rx(uint8 channel)
{
	struct dma_tcd tcd1;
	uint8 i;

	printf("@@@ i2c master dma rx test @@@\r\n");
	/* Init transmit buffer */
    i2c_rx_buffer.tx_index = 0;
    i2c_rx_buffer.rx_index = 0;
    i2c_rx_buffer.data_present = FALSE;
    i2c_rx_buffer.length = 64;
	
	i2c_init(channel, I2C_MASTER_ADDR, 50000);

	
	SIM_SCGC4 |= SIM_SCGC4_DMA_MASK;
	tcd1.channel_no = channel;
	tcd1.ctrl = (0 | DMA_DCR_ERQ_MASK 
					| DMA_DCR_CS_MASK
					| DMA_DCR_SSIZE(1)
					| DMA_DCR_DINC_MASK
					| DMA_DCR_DSIZE(1)
					| DMA_DCR_D_REQ_MASK);
	tcd1.saddr = &(I2C_D(channel));
	tcd1.daddr = &(i2c_rx_buffer.buf[0]);
	tcd1.nbytes = 64-2;	
	dma_config(CONFIG_BASIC_XFR, &tcd1);

	if(channel>3)
	{
		printf("***invalid I2C channel***\r\n");
		return;	
	}
	DMA_REQC &= ~(0x0F000000>>(channel*8));
	
	/* Make sure bus is idle */
	while (I2C_S(channel) & I2C_S_BUSY_MASK);
	/* Put module in master TX mode (generates START) */
	I2C_C1(channel) |= (I2C_C1_MST_MASK | I2C_C1_TX_MASK);
	/* Put target address into IBDR */
	I2C_D(channel) = ( 0 | (I2C_SLAVE_ADDR<<1) | I2C_RX);
	/* Wait for I2SR[IBB] (bus busy) to be set */
	while (!(I2C_S(channel) & I2C_S_BUSY_MASK));
	
	/* Wait for address transfer to complete */
	while (!(I2C_S(channel) & I2C_S_IICIF_MASK));
	I2C_S(channel) |= I2C_S_IICIF_MASK;
	
	/* Clear TX/RX bit in order to set receive mode */
	I2C_C1(channel) &= ~I2C_C1_TX_MASK; 
	
	I2C_C1(channel) |= I2C_C1_DMAEN_MASK; //enable dma request
	DMA_REQC |= (0x84000000>>(channel*8)); // dman, id 4	
	
	/* Dummy read of IBDR to signal the module is ready for the next byte */
	I2C_D(channel);

	dma_config(WAIT_FOR_XFR, &tcd1);	
	while (!(I2C_S(channel) & I2C_S_TCF_MASK));	
	I2C_C1(channel) |= I2C_C1_TXAK_MASK;

	I2C_C1(channel) &= ~I2C_C1_DMAEN_MASK; //disable dma request
	DMA_REQC = 0; // disable dma req 	

	i2c_rx_buffer.buf[62] = I2C_D(channel);	
	
	/* receive last byte */
	/* Wait for transfer to complete */
	while (!(I2C_S(channel) & I2C_S_IICIF_MASK));
	I2C_S(channel) |= I2C_S_IICIF_MASK;

	/* Generate STOP */
	I2C_C1(channel) &= ~I2C_C1_MST_MASK;

	i2c_rx_buffer.buf[63] = I2C_D(channel);	
	
	/* Restore module to it's idle (but active) state */
	I2C_C1(channel) = 0x80;	

	for(i=0;i<64;i++)
	{
		if(i%16 == 0)
		{
			printf("\r\n");
		}
		printf("%02x ", i2c_rx_buffer.buf[i]);
	}		
	
}

void i2c_dma_slave_rx(uint8 channel)
{
	struct dma_tcd tcd1;
	uint8 i;

	printf("@@@@  i2c dma slave rx test  @@@@\r\n");
	/* Init transmit buffer */
    i2c_rx_buffer.tx_index = 0;
    i2c_rx_buffer.rx_index = 0;
    i2c_rx_buffer.data_present = FALSE;
    i2c_rx_buffer.length = 64;
	
	i2c_init(channel, I2C_SLAVE_ADDR, 50000);
	
	SIM_SCGC4 |= SIM_SCGC4_DMA_MASK;
	tcd1.channel_no = channel;
	tcd1.ctrl = (0 | DMA_DCR_ERQ_MASK 
					| DMA_DCR_CS_MASK
					| DMA_DCR_SSIZE(1)
					| DMA_DCR_DINC_MASK
					| DMA_DCR_DSIZE(1)
					| DMA_DCR_D_REQ_MASK);
	tcd1.saddr = &(I2C_D(channel));
	tcd1.daddr = &(i2c_rx_buffer.buf[0]);
	tcd1.nbytes = 64;	
	dma_config(CONFIG_BASIC_XFR, &tcd1);

	if(channel>3)
	{
		printf("***invalid I2C channel***\r\n");
		return;	
	}
	DMA_REQC &= ~(0x0F000000>>(channel*8));	

	I2C_C1(channel) |= I2C_C1_DMAEN_MASK; //enable dma request
	DMA_REQC |= (0x84000000>>(channel*8)); // dman, id 4	
	
	dma_config(WAIT_FOR_XFR, &tcd1);

	I2C_C1(channel) &= ~I2C_C1_DMAEN_MASK; //disable dma request
	DMA_REQC = 0; // disable dma req 
	
	for(i=0;i<64;i++)
	{
		if(i%16 == 0)
		{
			printf("\r\n");
		}
		printf("%02x ", i2c_rx_buffer.buf[i]);
	}		
}

void i2c_dma_slave_tx(uint8 channel)
{
	struct dma_tcd tcd1;
	uint8 i;

	/* Init transmit buffer */
    i2c_tx_buffer.tx_index = 0;
    i2c_tx_buffer.rx_index = 0;
    i2c_tx_buffer.data_present = TRUE;
    i2c_tx_buffer.length = 64;
    i2c_tx_buffer.buf[0] = (uint8)(I2C_SLAVE_ADDR&0x0FF);
	
	for(i=1;i<64;i++)
	{
		i2c_tx_buffer.buf[i] = i;
	}
	
	i2c_init(channel, I2C_SLAVE_ADDR, 50000);
	
	SIM_SCGC4 |= SIM_SCGC4_DMA_MASK;
	tcd1.channel_no = channel;
	tcd1.ctrl = (0 | DMA_DCR_ERQ_MASK 
					| DMA_DCR_SINC_MASK
					| DMA_DCR_CS_MASK
					| DMA_DCR_SSIZE(1)
					| DMA_DCR_DSIZE(1)
					| DMA_DCR_D_REQ_MASK);
	tcd1.daddr = &(I2C_D(channel));
	tcd1.saddr = &(i2c_tx_buffer.buf[1]);
	tcd1.nbytes = 63;	
	dma_config(CONFIG_BASIC_XFR, &tcd1);

	if(channel>3)
	{
		printf("***invalid I2C channel***\r\n");
		return;	
	}
	DMA_REQC &= ~(0x0F000000>>(channel*8));
	DMA_REQC |= (0x84000000>>(channel*8)); // dman, id 4	

	while (!(I2C_S(channel) & I2C_S_IICIF_MASK));
	I2C_S(channel) |= I2C_S_IICIF_MASK;
	
	if (I2C_S(channel) & I2C_S_IAAS_MASK)
	{
		if (I2C_S(channel) & I2C_S_SRW_MASK)
		{
		    /* Set tx_index to 0 */
		    i2c_tx_buffer.tx_index = 0;
		    
		    /* Master was reading from slave - Set Transmit Mode. */
		    I2C_C1(channel) |= I2C_C1_TX_MASK;
		    
			I2C_C1(channel) |= I2C_C1_DMAEN_MASK; //enable dma request

		    I2C_D(channel) = i2c_tx_buffer.buf[0];
			
			dma_config(WAIT_FOR_XFR, &tcd1);

			I2C_C1(channel) &= ~I2C_C1_DMAEN_MASK; //disable dma request
			DMA_REQC = 0; // disable dma req 
			
			return;
		}
	}
	
	printf("error occurs!\r\n");
}

void run_test(void)
{
	/* This function will call the testcase function */
	SIM_SCGC1 |= 0xF0; // enable I2C clock gate 
//	i2c_dma_master_tx(0);
	i2c_dma_master_rx(0);
//	i2c_dma_slave_rx(0);
//	i2c_dma_slave_tx(0);
}

