#include <board.h>
|
|
#include <support.h>
|
#include <support.h>
|
|
#include "interconnect.h"
|
#include "i2c.h"
|
#include "i2c.h"
|
|
|
int i2c_rd_done, i2c_wr_done;
|
int i2c_rd_done, i2c_wr_done;
|
|
|
int i2c_pending_write;
|
int i2c_pending_write;
|
|
|
int i2c_rd_ptr, i2c_wr_ptr;
|
int i2c_rd_ptr, i2c_wr_ptr;
|
|
|
int i2c_buf_overflow;
|
int i2c_buf_overflow;
|
i2c_type i2c_data[I2C_BUF_LEN];
|
i2c_type i2c_data[I2C_BUF_LEN];
|
|
|
unsigned char start, pointer_write, write_hbyte, write_lbyte, read_hbyte, read_lbyte;
|
unsigned char start, pointer_write, write_hbyte, write_lbyte, read_hbyte, read_lbyte;
|
unsigned char cmd_list[5];
|
unsigned char cmd_list[5];
|
unsigned char dat_list[5];
|
unsigned char dat_list[5];
|
int i2c_index;
|
int i2c_index;
|
int i2c_end;
|
int i2c_end;
|
|
|
i2c_type * i2c_get(void)
|
i2c_type * i2c_get(void)
|
{
|
{
|
if ( !i2c_rd_done )
|
if ( !i2c_rd_done )
|
return NULL;
|
return NULL;
|
|
|
i2c_rd_done--;
|
i2c_rd_done--;
|
|
|
int tmp;
|
int tmp;
|
tmp = i2c_rd_ptr;
|
tmp = i2c_rd_ptr;
|
|
|
if (i2c_rd_ptr < I2C_BUF_LEN-1)
|
if (i2c_rd_ptr < I2C_BUF_LEN-1)
|
i2c_rd_ptr++;
|
i2c_rd_ptr++;
|
else
|
else
|
i2c_rd_ptr = 0;
|
i2c_rd_ptr = 0;
|
|
|
return &i2c_data[tmp];
|
return &i2c_data[tmp];
|
}
|
}
|
|
|
void i2c_init(void)
|
void i2c_init(void)
|
{
|
{
|
REG8(I2C_BASE+I2C_PRESC_HI) = 0x00;
|
REG8(I2C_BASE+I2C_PRESC_HI) = 0x00;
|
REG8(I2C_BASE+I2C_PRESC_LO) = 49; //100kHz
|
REG8(I2C_BASE+I2C_PRESC_LO) = 49; //100kHz
|
REG8(I2C_BASE+I2C_CTR) = I2C_CTR_EN | I2C_CTR_IRQ_EN;
|
REG8(I2C_BASE+I2C_CTR) = I2C_CTR_EN | I2C_CTR_IRQ_EN;
|
i2c_rd_done = 0;
|
i2c_rd_done = 0;
|
i2c_wr_done = 0;
|
i2c_wr_done = 0;
|
i2c_index = 0;
|
i2c_index = 0;
|
i2c_wr_ptr = 0;
|
i2c_wr_ptr = 0;
|
i2c_rd_ptr = 0;
|
i2c_rd_ptr = 0;
|
i2c_buf_overflow = 0;
|
i2c_buf_overflow = 0;
|
}
|
}
|
|
|
void i2c_set_ack_lvl(int ack_lvl, int final_ack_lvl)
|
void i2c_set_ack_lvl(int ack_lvl, int final_ack_lvl)
|
{
|
{
|
int ack, final_ack;
|
int ack, final_ack;
|
|
|
ack = ( ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
|
ack = ( ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
|
final_ack = ( final_ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
|
final_ack = ( final_ack_lvl ) ? I2C_CR_NACK : I2C_CR_ACK;
|
|
|
start = I2C_CR_STA | I2C_CR_WR | ack;
|
start = I2C_CR_STA | I2C_CR_WR | ack;
|
pointer_write = I2C_CR_WR | ack;
|
pointer_write = I2C_CR_WR | ack;
|
write_hbyte = I2C_CR_WR | ack;
|
write_hbyte = I2C_CR_WR | ack;
|
write_lbyte = I2C_CR_WR | I2C_CR_STO | final_ack;
|
write_lbyte = I2C_CR_WR | I2C_CR_STO | final_ack;
|
read_hbyte = I2C_CR_RD | ack;
|
read_hbyte = I2C_CR_RD | ack;
|
read_lbyte = I2C_CR_RD | I2C_CR_STO | final_ack;
|
read_lbyte = I2C_CR_RD | I2C_CR_STO | final_ack;
|
}
|
}
|
|
|
void i2c_byte_transfer(void)
|
void i2c_byte_transfer(void)
|
{
|
{
|
if ( i2c_index > 0 )
|
if ( i2c_index > 0 )
|
if ( cmd_list[i2c_index-1] == read_hbyte )
|
if ( cmd_list[i2c_index-1] == read_hbyte )
|
i2c_data[i2c_wr_ptr].data = (REG8(I2C_BASE+I2C_RXR) << 8) & 0xFF00;
|
i2c_data[i2c_wr_ptr].data = (REG8(I2C_BASE+I2C_RXR) << 8) & 0xFF00;
|
|
|
REG8(I2C_BASE+I2C_TXR) = dat_list[i2c_index];
|
REG8(I2C_BASE+I2C_TXR) = dat_list[i2c_index];
|
REG8(I2C_BASE+I2C_CR) = cmd_list[i2c_index];
|
REG8(I2C_BASE+I2C_CR) = cmd_list[i2c_index];
|
|
|
i2c_index++;
|
i2c_index++;
|
}
|
}
|
|
|
void i2c_irq(void)
|
void i2c_irq(void)
|
{
|
{
|
REG8(I2C_BASE+I2C_CR) = I2C_CR_CLR_IRQ;
|
REG8(I2C_BASE+I2C_CR) = I2C_CR_CLR_IRQ;
|
if (i2c_index <= i2c_end )
|
if (i2c_index <= i2c_end )
|
i2c_byte_transfer();
|
i2c_byte_transfer();
|
else
|
else
|
{
|
{
|
if ( cmd_list[i2c_index-1] == read_lbyte )
|
if ( cmd_list[i2c_index-1] == read_lbyte )
|
i2c_data[i2c_wr_ptr].data |= REG8(I2C_BASE+I2C_RXR);
|
i2c_data[i2c_wr_ptr].data |= REG8(I2C_BASE+I2C_RXR);
|
|
|
i2c_index = 0;
|
i2c_index = 0;
|
|
|
if ( i2c_pending_write )
|
if ( i2c_pending_write )
|
i2c_wr_done = 1;
|
i2c_wr_done = 1;
|
else
|
else
|
{
|
{
|
if (i2c_wr_ptr < I2C_BUF_LEN-1)
|
if (i2c_wr_ptr < I2C_BUF_LEN-1)
|
i2c_wr_ptr++;
|
i2c_wr_ptr++;
|
else
|
else
|
i2c_wr_ptr = 0;
|
i2c_wr_ptr = 0;
|
|
|
if (i2c_wr_ptr == i2c_rd_ptr+1)
|
if (i2c_wr_ptr == i2c_rd_ptr+1)
|
{
|
{
|
i2c_rd_done = 1;
|
i2c_rd_done = 1;
|
i2c_buf_overflow++;
|
i2c_buf_overflow++;
|
}
|
}
|
else
|
else
|
i2c_rd_done++;
|
i2c_rd_done++;
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
int i2c_trans(i2c_mode * mode, i2c_type * data)
|
int i2c_trans(i2c_mode * mode, i2c_type * data)
|
{
|
{
|
if ( i2c_index != 0 ) //if previous command not fully processed, bail out
|
if ( i2c_index != 0 ) //if previous command not fully processed, bail out
|
return -1;
|
return -1;
|
|
|
i2c_wr_done = 0;
|
i2c_wr_done = 0;
|
|
|
int i = 0;
|
int i = 0;
|
|
|
if ( mode->ptr_set || mode->read_write ) //start conditions with pointer set: (write always set ptr)
|
if ( mode->ptr_set || mode->read_write ) //start conditions with pointer set: (write always set ptr)
|
{
|
{
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] |= I2C_TXR_W;
|
dat_list[i] |= I2C_TXR_W;
|
cmd_list[i++] = start;
|
cmd_list[i++] = start;
|
|
|
dat_list[i] = data->pointer;
|
dat_list[i] = data->pointer;
|
cmd_list[i++] = pointer_write;
|
cmd_list[i++] = pointer_write;
|
|
|
if ( !mode->read_write ) //REstart for read, NO-REstart for write
|
if ( !mode->read_write ) //REstart for read, NO-REstart for write
|
{
|
{
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] |= I2C_TXR_R;
|
dat_list[i] |= I2C_TXR_R;
|
cmd_list[i++] = start;
|
cmd_list[i++] = start;
|
}
|
}
|
}
|
}
|
else //start conditions with NO pointer set (read only): ONE start
|
else //start conditions with NO pointer set (read only): ONE start
|
{
|
{
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] = (data->address << 1) & I2C_TXR_ADR;
|
dat_list[i] |= I2C_TXR_R;
|
dat_list[i] |= I2C_TXR_R;
|
cmd_list[i++] = start;
|
cmd_list[i++] = start;
|
}
|
}
|
|
|
if ( mode->byte_word ) //read/write high byte
|
if ( mode->byte_word ) //read/write high byte
|
{
|
{
|
dat_list[i] = data->data >> 8;
|
dat_list[i] = data->data >> 8;
|
cmd_list[i++] = (mode->read_write) ? write_hbyte : read_hbyte;
|
cmd_list[i++] = (mode->read_write) ? write_hbyte : read_hbyte;
|
}
|
}
|
|
|
dat_list[i] = data->data; //read/write low byte
|
dat_list[i] = data->data; //read/write low byte
|
cmd_list[i] = (mode->read_write) ? write_lbyte : read_lbyte;
|
cmd_list[i] = (mode->read_write) ? write_lbyte : read_lbyte;
|
|
|
i2c_end = i;
|
i2c_end = i;
|
|
|
if ( !mode->read_write ) //set data to 0 for read, avoid or implications ((short)data |= byte)
|
if ( !mode->read_write ) //set data to 0 for read, avoid or implications ((short)data |= byte)
|
{
|
{
|
i2c_data[i2c_wr_ptr] = *data;
|
i2c_data[i2c_wr_ptr] = *data;
|
i2c_data[i2c_wr_ptr].data = 0x0000;
|
i2c_data[i2c_wr_ptr].data = 0x0000;
|
}
|
}
|
|
|
i2c_pending_write = mode->read_write;
|
i2c_pending_write = mode->read_write;
|
|
|
i2c_index = 0;
|
i2c_index = 0;
|
i2c_byte_transfer();
|
i2c_byte_transfer();
|
|
|
return mode->read_write+1;
|
return mode->read_write+1;
|
}
|
}
|
|
|