ossc/ip/i2c_opencores/HAL/src/i2c_opencores.c

207 lines
6.6 KiB
C

#include "alt_types.h"
#include "i2c_opencores_regs.h"
#include "i2c_opencores.h"
// #define I2C_DEBUG
//int I2C_init(alt_u32 base,alt_u32 clk, alt_u32 speed)
//int I2C_start(alt_u32 base, alt_u32 add, alt_u32 write);
//alt_u32 I2C_read(alt_u32 base);
//int I2C_write(alt_u32 base, alt_u8 data);
//int I2C_stop(alt_u32 base);
/* these functions are polled only. */
/* all functions wait until the I2C is done before exiting */
/****************************************************************
int I2C_init
This function inititlizes the prescalor for the scl
and then enables the core. This must be run before
any other i2c code is executed
inputs
base = the base address of the component
clk = freuqency of the clock driving this component ( in Hz)
speed = SCL speed ie 100K, 400K ... (in Hz)
15-OCT-07 initial release
*****************************************************************/
void I2C_init(alt_u32 base,alt_u32 clk,alt_u32 speed)
{
alt_u32 prescale = (clk/( 5 * speed))-1;
#ifdef I2C_DEBUG
printf(" Initializing I2C at 0x%x, \n\twith clock speed 0x%x \n\tand SCL speed 0x%x \n\tand prescale 0x%x\n",base,clk,speed,prescale);
#endif
IOWR_I2C_OPENCORES_CTR(base, 0x00); /* turn off the core*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_IACK_MSK); /* clearn any pening IRQ*/
IOWR_I2C_OPENCORES_PRERLO(base, (0xff & prescale)); /* load low presacle bit*/
IOWR_I2C_OPENCORES_PRERHI(base, (0xff & (prescale>>8))); /* load upper prescale bit */
IOWR_I2C_OPENCORES_CTR(base, I2C_OPENCORES_CTR_EN_MSK); /* turn on the core*/
}
/****************************************************************
int I2C_start
Sets the start bit and then sends the first byte which
is the address of the device + the write bit.
inputs
base = the base address of the component
add = address of I2C device
read = 1== read 0== write
return value
0 if address is acknowledged
1 if address was not acknowledged
15-OCT-07 initial release
*****************************************************************/
int I2C_start(alt_u32 base, alt_u32 add, alt_u32 read)
{
#ifdef I2C_DEBUG
printf(" Start I2C at 0x%x, \n\twith address 0x%x \n\tand read 0x%x \n\tand prescale 0x%x\n",base,add,read);
#endif
/* transmit the address shifted by one and the read/write bit*/
IOWR_I2C_OPENCORES_TXR(base, ((add<<1) + (0x1 & read)));
/* set start and write bits which will start the transaction*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_STA_MSK | I2C_OPENCORES_CR_WR_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now check to see if the address was acknowledged */
if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK)
{
#ifdef I2C_DEBUG
printf("\tNOACK\n");
#endif
return (I2C_NOACK);
}
else
{
#ifdef I2C_DEBUG
printf("\tACK\n");
#endif
return (I2C_ACK);
}
}
/****************************************************************
int I2C_read
assumes that any addressing and start
has already been done.
reads one byte of data from the slave. on the last read
we don't acknowldge and set the stop bit.
inputs
base = the base address of the component
last = on the last read there must not be a ack
return value
byte read back.
15-OCT-07 initial release
*****************************************************************/
alt_u32 I2C_read(alt_u32 base,alt_u32 last)
{
#ifdef I2C_DEBUG
printf(" Read I2C at 0x%x, \n\twith last0x%x\n",base,last);
#endif
if( last)
{
/* start a read and no ack and stop bit*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK |
I2C_OPENCORES_CR_NACK_MSK | I2C_OPENCORES_CR_STO_MSK);
}
else
{
/* start read*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK );
}
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now read the data */
return (IORD_I2C_OPENCORES_RXR(base));
}
/****************************************************************
int I2C_write
assumes that any addressing and start
has already been done.
writes one byte of data from the slave.
If last is set the stop bit set.
inputs
base = the base address of the component
data = byte to write
last = on the last read there must not be a ack
return value
0 if address is acknowledged
1 if address was not acknowledged
15-OCT-07 initial release
*****************************************************************/
alt_u32 I2C_write(alt_u32 base,alt_u8 data, alt_u32 last)
{
#ifdef I2C_DEBUG
printf(" Read I2C at 0x%x, \n\twith data 0x%x,\n\twith last0x%x\n",base,data,last);
#endif
/* transmit the data*/
IOWR_I2C_OPENCORES_TXR(base, data);
if( last)
{
/* start a write with ack and stop bit*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK |
I2C_OPENCORES_CR_STO_MSK);
}
else
{
/* start write with ack */
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK );
}
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now check to see if the address was acknowledged */
if(IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_RXNACK_MSK)
{
#ifdef I2C_DEBUG
printf("\tNOACK\n");
#endif
return (I2C_NOACK);
}
else
{
#ifdef I2C_DEBUG
printf("\tACK\n");
#endif
return (I2C_ACK);
}
}
alt_u32 SPI_read(alt_u32 base)
{
/* start read*/
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_RD_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
/* now read the data */
return (IORD_I2C_OPENCORES_RXR(base));
}
void SPI_write(alt_u32 base,alt_u8 data) {
/* transmit the data*/
IOWR_I2C_OPENCORES_TXR(base, data);
/* start write */
IOWR_I2C_OPENCORES_CR(base, I2C_OPENCORES_CR_WR_MSK|I2C_OPENCORES_CR_NACK_MSK|I2C_OPENCORES_CR_SPIM_MSK );
/* wait for the trnasaction to be over.*/
while( IORD_I2C_OPENCORES_SR(base) & I2C_OPENCORES_SR_TIP_MSK);
}