Initial commit of fifo and i2c routines
This commit is contained in:
@@ -626,9 +626,9 @@ acsi_dma: // atari dma
|
||||
move.l d1,-(a7)
|
||||
|
||||
lea MCF_PSC0_PSCTB_8BIT,a1 // ++ vr
|
||||
mchar move.l, 'D,'M','A,'\ ,(a1)
|
||||
mchar move.l, 'D','M','A','\'' ,(a1)
|
||||
//move.l #"DMA ",(a1)
|
||||
mchar move.l,'I,'N,'T,'!,(a1)
|
||||
mchar move.l,'I','N','T','!',(a1)
|
||||
// move.l #'INT!',(a1)
|
||||
|
||||
lea 0xf0020110,a5 // fifo daten
|
||||
|
||||
109
i2cspi_BaS_gcc/sources/fifo.c
Normal file
109
i2cspi_BaS_gcc/sources/fifo.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* fifo.c
|
||||
*
|
||||
* A general implementation of a fifo buffer
|
||||
*
|
||||
*/
|
||||
|
||||
#include <fifo.h>
|
||||
|
||||
//This initializes the FIFO structure with the given buffer and size
|
||||
void fifo_init(fifo_t * f, char * buf, int size)
|
||||
{
|
||||
f->head = 0;
|
||||
f->tail = 0;
|
||||
f->size = size;
|
||||
f->buf = buf;
|
||||
}
|
||||
|
||||
// Get one byte from the fifo buffer
|
||||
uint8_t fifo_get(fifo_t *f)
|
||||
{
|
||||
uint8_t ch = 0;
|
||||
|
||||
if( f->tail != f->head && f->tail < f->size )
|
||||
{
|
||||
ch = f->buf[f->tail++];
|
||||
if( f->tail >= f->size )
|
||||
f->tail = 0;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
// Put one byte into the buffer
|
||||
void fifo_put(fifo_t *f, uint8_t byte)
|
||||
{
|
||||
if( f->head == f->tail || f->head >= f->size )
|
||||
return;
|
||||
f->buf[f->head] = byte;
|
||||
fifo_advance(f,&f->head);
|
||||
}
|
||||
|
||||
void fifo_clear(fifo_t *f)
|
||||
{
|
||||
f->head = f->tail = 0;
|
||||
}
|
||||
|
||||
int fifo_used(fifo_t *f)
|
||||
{
|
||||
if( f->head > f->tail )
|
||||
return (f->head - f->tail);
|
||||
return (f->size - f->tail + f->head);
|
||||
}
|
||||
|
||||
int fifo_unused(fifo_t *f)
|
||||
{
|
||||
if( f->head > f->tail )
|
||||
return (f->size-f->head+f->tail);
|
||||
return (f->tail-f->head);
|
||||
}
|
||||
|
||||
int fifo_full(fifo_t *f)
|
||||
{
|
||||
if( f->head+1 >= f->size )
|
||||
return (f->tail == 0);
|
||||
return (f->head+1 == f->tail);
|
||||
}
|
||||
|
||||
int fifo_empty(fifo_t *f)
|
||||
{
|
||||
return (f->head == f->tail);
|
||||
}
|
||||
|
||||
void fifo_advance(fifo_t *f, int *ix)
|
||||
{
|
||||
if( ++*ix > f->size )
|
||||
*ix=0;
|
||||
}
|
||||
|
||||
//This reads at most nbytes bytes from the FIFO
|
||||
//The number of bytes read is returned
|
||||
int fifo_read(fifo_t *f, char *buf, int nbytes){
|
||||
int n = 0;
|
||||
|
||||
while( n < nbytes && !fifo_empty(f) )
|
||||
{
|
||||
n++;
|
||||
*buf++ = f->buf[f->tail];
|
||||
fifo_advance(f,&f->tail);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
//This writes up to nbytes bytes to the FIFO
|
||||
//If the head runs in to the tail, not all bytes are written
|
||||
//The number of bytes written is returned
|
||||
int fifo_write(fifo_t *f, const char *buf, int nbytes){
|
||||
int n = 0;
|
||||
|
||||
while( n < nbytes && !fifo_full(f) )
|
||||
{
|
||||
f->buf[f->head] = *buf++;
|
||||
fifo_advance(f,&f->head);
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
185
i2cspi_BaS_gcc/sources/i2c_firebee.c
Normal file
185
i2cspi_BaS_gcc/sources/i2c_firebee.c
Normal file
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* i2c.c
|
||||
*
|
||||
*/
|
||||
|
||||
#include <MCF5475.h>
|
||||
#include <i2c_firebee.h>
|
||||
|
||||
#include <fifo.h>
|
||||
|
||||
static struct {
|
||||
uint8_t state;
|
||||
long delay;
|
||||
uint16_t len;
|
||||
fifo_t fifo;
|
||||
unsigned char *_buf;
|
||||
uint16_t device;
|
||||
} i2c_param;
|
||||
|
||||
char local_buf[BUFSIZ];
|
||||
|
||||
#define FIFO &i2c_param.fifo
|
||||
|
||||
/*
|
||||
* I2Cinit: I2C initilazation as master
|
||||
*
|
||||
* Parameters: None.
|
||||
*
|
||||
* Return : None.
|
||||
*/
|
||||
void I2C_Init()
|
||||
{
|
||||
i2c_param.fifo.buf = local_buf;
|
||||
i2c_param.fifo.size = BUFSIZ;
|
||||
i2c_param.delay = 133*10L; // We can safely ignore this
|
||||
i2c_param.len = 0;
|
||||
I2C_ioctl(0,0);
|
||||
}
|
||||
|
||||
void __attribute__ ((interrupt)) I2C_InterruptHandler(void)
|
||||
{
|
||||
char ch;
|
||||
|
||||
clear_bit(MCF_I2C_I2SR,MCF_I2C_I2SR_IIF);
|
||||
if( MCF_I2C_I2CR & MCF_I2C_I2CR_MSTA )
|
||||
{ // Masters of the known universe
|
||||
if( MCF_I2C_I2SR & MCF_I2C_I2SR_ICF )
|
||||
{
|
||||
switch( i2c_param.state )
|
||||
{
|
||||
case I2C_MXRX:
|
||||
if( fifo_used(&i2c_param.fifo)+1 == i2c_param.len ) {
|
||||
clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MSTA);
|
||||
i2c_param.state = I2C_READY;
|
||||
} else if( fifo_used(&i2c_param.fifo)+2 == i2c_param.len ) {
|
||||
set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_TXAK);
|
||||
i2c_param.state = I2C_READY;
|
||||
}
|
||||
fifo_put(&i2c_param.fifo,MCF_I2C_I2DR);
|
||||
break;
|
||||
case I2C_ADDR:
|
||||
if( fifo_empty(&i2c_param.fifo) )
|
||||
{
|
||||
i2c_param.state = I2C_MXRX;
|
||||
clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX); // Receive mode
|
||||
set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_RSTA);
|
||||
ch = MCF_I2C_I2DR; // Dummy read
|
||||
break;
|
||||
}
|
||||
case I2C_MXTX:
|
||||
if( fifo_empty(&i2c_param.fifo) || (MCF_I2C_I2SR&MCF_I2C_I2SR_RXAK) ) {
|
||||
clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MSTA);
|
||||
i2c_param.state = I2C_READY;
|
||||
} else
|
||||
MCF_I2C_I2DR = fifo_get(&i2c_param.fifo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else { // Slave mode.
|
||||
int set;
|
||||
|
||||
if( set = (MCF_I2C_I2SR & MCF_I2C_I2SR_IAL) )
|
||||
clear_bit(MCF_I2C_I2SR,MCF_I2C_I2SR_IAL);
|
||||
if( MCF_I2C_I2SR & MCF_I2C_I2SR_IAAS )
|
||||
{
|
||||
if( MCF_I2C_I2SR & MCF_I2C_I2SR_SRW )
|
||||
{
|
||||
set_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX);
|
||||
fifo_put(&i2c_param.fifo,MCF_I2C_I2DR);
|
||||
} else {
|
||||
clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX);
|
||||
ch = MCF_I2C_I2DR;
|
||||
}
|
||||
} else if( !set ) {
|
||||
if( MCF_I2C_I2CR&MCF_I2C_I2CR_MTX )
|
||||
{
|
||||
if( MCF_I2C_I2SR&MCF_I2C_I2SR_RXAK )
|
||||
MCF_I2C_I2DR = fifo_get(&i2c_param.fifo);
|
||||
else {
|
||||
clear_bit(MCF_I2C_I2CR,MCF_I2C_I2CR_MTX);
|
||||
ch = MCF_I2C_I2DR;
|
||||
}
|
||||
} else {
|
||||
fifo_put(&i2c_param.fifo,MCF_I2C_I2DR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void I2C_send(unsigned short device, unsigned char *buf, unsigned short len)
|
||||
{
|
||||
if( len > i2c_param.fifo.size )
|
||||
return;
|
||||
i2c_param.len = len;
|
||||
fifo_clear(&i2c_param.fifo);
|
||||
if( device > 127 ) // Use I2C 10 bit address
|
||||
{
|
||||
fifo_put(FIFO,0b11110|((device>>5)&6)|I2C_WRITE);
|
||||
fifo_put(FIFO,device&255);
|
||||
} else
|
||||
fifo_put(FIFO,((device<<1)&0xFE)|I2C_WRITE);
|
||||
fifo_write(FIFO,buf,len);
|
||||
i2c_param.state = I2C_MXTX;
|
||||
}
|
||||
|
||||
void I2C_receive(unsigned short device, unsigned char *buf, unsigned short len)
|
||||
{
|
||||
if( len > i2c_param.fifo.size )
|
||||
return;
|
||||
i2c_param.len = len;
|
||||
fifo_clear(FIFO);
|
||||
if( device > 127 ) // Use I2C 10 bit address
|
||||
{
|
||||
fifo_put(FIFO,0b11110|((device>>5)&6)|I2C_READ);
|
||||
fifo_put(FIFO,device&255);
|
||||
} else
|
||||
fifo_put(FIFO,((device<<1)&0xFE)|I2C_READ);
|
||||
i2c_param.state = I2C_ADDR;
|
||||
}
|
||||
|
||||
int I2C_ioctl(unsigned int index, unsigned long val)
|
||||
{
|
||||
unsigned short len = val;
|
||||
uint8_t temp;
|
||||
|
||||
// Set device as slave or
|
||||
switch( index )
|
||||
{
|
||||
case I2CTLINIT: // make me master
|
||||
/* set the frequency near 400KHz */
|
||||
MCF_I2C_I2FDR = MCF_I2C_I2FDR_IC(0x10);
|
||||
/* start the module */
|
||||
MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN | MCF_I2C_I2CR_IEN;
|
||||
/* if bit busy set, send a stop condition to slave module */
|
||||
if(MCF_I2C_I2SR & MCF_I2C_I2SR_IBB)
|
||||
{
|
||||
MCF_I2C_I2CR = 0; /* clear control register */
|
||||
MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN|MCF_I2C_I2CR_IEN|MCF_I2C_I2CR_MSTA; /* enable module & send a START condition */
|
||||
temp = MCF_I2C_I2DR; /* dummy read */
|
||||
MCF_I2C_I2SR = 0; /* clear status register */
|
||||
MCF_I2C_I2CR = 0; /* clear control register */
|
||||
MCF_I2C_I2CR = MCF_I2C_I2CR_IIEN|MCF_I2C_I2CR_IEN; /* enable the module again */
|
||||
}
|
||||
i2c_param.state = I2C_READY;
|
||||
i2c_param._buf = 0;
|
||||
break;
|
||||
case I2CTLSBUF:
|
||||
i2c_param._buf = (char *)val;
|
||||
break;
|
||||
case I2CTLDEV:
|
||||
i2c_param.device = val;
|
||||
break;
|
||||
case I2CTLREAD:
|
||||
if( i2c_param._buf == 0 || i2c_param.device == 0 )
|
||||
return -1;
|
||||
I2C_receive(i2c_param.device,i2c_param._buf,len);
|
||||
break;
|
||||
case I2CTLWRITE:
|
||||
if( i2c_param._buf == 0 || i2c_param.device == 0 )
|
||||
return -1;
|
||||
I2C_send(i2c_param.device,i2c_param._buf,len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user