This is a translation of the twitest.c example taken from avr-libc (the original file is provided in the avr-libc
subdirectory):
#include <stdio.h>
#include <stdlib.h>
#include BOARD_H
#if HW_ADDRESS(twi0) != -1
# define TWI twi0
#endif
#define DEBUG 1
#define TWI_SLA_24CXX 0xA0
#define WORD_ADDRESS_16BIT
#define MAX_ITER 200
#define PAGE_SIZE 8
uint8_t twst;
void
ioinit(void)
{
bps, 9600,
receiver, disabled,
transmitter, enabled );
hwa( configure, TWI, bps, 100000 );
}
int
uart_putchar(char c, FILE *unused __attribute__((unused)) )
{
if (c == '\n')
uart_putchar('\r',0);
while ( !
hw(stat,uart0).txqnf ) {}
return 0;
}
int
ee24xx_read_bytes(uint16_t eeaddr, int len, uint8_t *buf)
{
uint8_t sla, n = 0;
int rv = 0;
#ifndef WORD_ADDRESS_16BIT
sla = TWI_SLA_24CXX | ((eeaddr >> 8) & 0x07);
#else
sla = TWI_SLA_24CXX ;
#endif
restart:
if (n++ >= MAX_ITER)
return -1;
begin:
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_START:
case HW_TWI_REP_START:
break;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
return -1;
}
hw( xfr_slaw, TWI, sla>>1 );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_SLA_ACK:
break;
case HW_TWI_MT_SLA_NACK:
goto restart;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
#ifdef WORD_ADDRESS_16BIT
hw( xfr_write, TWI, eeaddr >> 8 );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_DATA_ACK:
break;
case HW_TWI_MT_DATA_NACK:
goto quit;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
#endif
hw( xfr_write, TWI, eeaddr );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_DATA_ACK:
break;
case HW_TWI_MT_DATA_NACK:
goto quit;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_START:
case HW_TWI_REP_START:
break;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
hw( xfr_slar, TWI, sla>>1 );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MR_SLA_ACK:
break;
case HW_TWI_MR_SLA_NACK:
goto quit;
case HW_TWI_MR_ARB_LOST:
goto begin;
default:
goto error;
}
for ( ; len>0 ; len-- ) {
if (len == 1)
hw( xfr_read, TWI, nack );
else
hw( xfr_read, TWI, ack );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MR_DATA_NACK:
len = 0;
case HW_TWI_MR_DATA_ACK:
rv++;
if(twst == HW_TWI_MR_DATA_NACK) goto quit;
break;
default:
goto error;
}
}
quit:
return rv;
error:
rv = -1;
goto quit;
}
int
ee24xx_write_page(uint16_t eeaddr, int len, uint8_t *buf)
{
uint8_t sla, n = 0;
int rv = 0;
uint16_t endaddr;
if (eeaddr + len <= (eeaddr | (PAGE_SIZE - 1)))
endaddr = eeaddr + len;
else
endaddr = (eeaddr | (PAGE_SIZE - 1)) + 1;
len = endaddr - eeaddr;
#ifndef WORD_ADDRESS_16BIT
sla = TWI_SLA_24CXX | ((eeaddr >> 8) & 0x07);
#else
sla = TWI_SLA_24CXX ;
#endif
restart:
if (n++ >= MAX_ITER)
return -1;
begin:
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_REP_START:
case HW_TWI_START:
break;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
return -1;
}
hw( xfr_slaw, TWI, sla>>1 );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_SLA_ACK:
break;
case HW_TWI_MT_SLA_NACK:
goto restart;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
#ifdef WORD_ADDRESS_16BIT
hw( xfr_write, TWI, eeaddr>>8 );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_DATA_ACK:
break;
case HW_TWI_MT_DATA_NACK:
goto quit;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
#endif
hw( xfr_write, TWI, eeaddr );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_DATA_ACK:
break;
case HW_TWI_MT_DATA_NACK:
goto quit;
case HW_TWI_MT_ARB_LOST:
goto begin;
default:
goto error;
}
for ( ; len>0 ; len-- ) {
hw( xfr_write, TWI, (*buf++) );
while( !
hw(read,(TWI,irq)) ) {}
switch( (twst=
hw(stat,TWI)) )
{
case HW_TWI_MT_DATA_NACK:
goto error;
case HW_TWI_MT_DATA_ACK:
rv++;
break;
default:
goto error;
}
}
quit:
return rv;
error:
rv = -1;
goto quit;
}
int
ee24xx_write_bytes(uint16_t eeaddr, int len, uint8_t *buf)
{
int rv, total;
total = 0;
do
{
#if DEBUG
printf("Calling ee24xx_write_page(%d, %d, %p)",
eeaddr, len, buf);
#endif
rv = ee24xx_write_page(eeaddr, len, buf);
#if DEBUG
printf(" => %d\n", rv);
#endif
if (rv == -1)
return -1;
eeaddr += rv;
len -= rv;
buf += rv;
total += rv;
}
while (len > 0);
return total;
}
void
error(void)
{
printf("error: TWI status %#x\n", twst);
exit(0);
}
FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
int
main(void)
{
uint16_t a;
int rv;
uint8_t b[16];
uint8_t x;
ioinit();
stdout = &mystdout;
for (a = 0; a < 256;)
{
printf("%#04x: ", a);
rv = ee24xx_read_bytes(a, 16, b);
if (rv <= 0)
error();
if (rv < 16)
printf("warning: short read %d\n", rv);
a += rv;
for (x = 0; x < rv; x++)
printf("%02x ", b[x]);
putchar('\n');
}
#define EE_WRITE(addr, str) ee24xx_write_bytes(addr, sizeof(str)-1, (uint8_t*)str)
rv = EE_WRITE(55, "The quick brown fox jumps over the lazy dog.");
if (rv < 0)
error();
printf("Wrote %d bytes.\n", rv);
for (a = 0; a < 256;)
{
printf("%#04x: ", a);
rv = ee24xx_read_bytes(a, 16, b);
if (rv <= 0)
error();
if (rv < 16)
printf("warning: short read %d\n", rv);
a += rv;
for (x = 0; x < rv; x++)
printf("%02x ", b[x]);
putchar('\n');
}
printf("done.\n");
return 0;
}