summaryrefslogtreecommitdiffhomepage
path: root/digital
diff options
context:
space:
mode:
Diffstat (limited to 'digital')
-rw-r--r--digital/asserv/src/asserv/avrconfig.h28
-rw-r--r--digital/asserv/src/asserv/twi_proto.c6
-rw-r--r--digital/avr/modules/twi/Makefile5
-rw-r--r--digital/avr/modules/twi/Makefile.module2
-rw-r--r--digital/avr/modules/twi/README9
-rw-r--r--digital/avr/modules/twi/avrconfig.h45
-rw-r--r--digital/avr/modules/twi/test/Makefile21
-rw-r--r--digital/avr/modules/twi/test/Makefile.master25
-rw-r--r--digital/avr/modules/twi/test/Makefile.slave24
-rw-r--r--digital/avr/modules/twi/test/master/Makefile14
-rw-r--r--digital/avr/modules/twi/test/master/avrconfig.h (renamed from digital/avr/modules/twi/test/avrconfig_master.h)64
-rw-r--r--digital/avr/modules/twi/test/slave/Makefile14
-rw-r--r--digital/avr/modules/twi/test/slave/avrconfig.h (renamed from digital/avr/modules/twi/test/avrconfig_slave.h)71
-rw-r--r--digital/avr/modules/twi/test/test_twi.c (renamed from digital/avr/modules/twi/test/test_twi_master.c)173
-rw-r--r--digital/avr/modules/twi/test/test_twi.py (renamed from digital/avr/modules/twi/test/test_twi_host.py)11
-rw-r--r--digital/avr/modules/twi/test/test_twi_sl.c90
-rw-r--r--digital/avr/modules/twi/twi.avr.c380
-rw-r--r--digital/avr/modules/twi/twi.c77
-rw-r--r--digital/avr/modules/twi/twi.h128
-rw-r--r--digital/avr/modules/twi/twi.host.c168
-rw-r--r--digital/avr/modules/twi/twi_hard.avr.c355
-rw-r--r--digital/io/src/avrconfig.h18
-rw-r--r--digital/io/src/twi_master.c16
-rw-r--r--digital/mimot/src/dirty/avrconfig.h28
-rw-r--r--digital/mimot/src/dirty/twi_proto.c6
25 files changed, 929 insertions, 849 deletions
diff --git a/digital/asserv/src/asserv/avrconfig.h b/digital/asserv/src/asserv/avrconfig.h
index c0403592..a07fa21d 100644
--- a/digital/asserv/src/asserv/avrconfig.h
+++ b/digital/asserv/src/asserv/avrconfig.h
@@ -92,14 +92,28 @@
#define AC_ASSERV_TWI_ADDRESS 4
/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 0
-/** Activate slave part. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
#define AC_TWI_SLAVE_ENABLE 1
-/** Slave recv buffer size. */
-#define AC_TWI_SL_RECV_BUFFER_SIZE 16
-/** Slave send buffer size. */
-#define AC_TWI_SL_SEND_BUFFER_SIZE 16
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 0
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+/** Slave reception buffer size. */
+#define AC_TWI_SLAVE_RECV_BUFFER_SIZE 16
+/** Slave transmission buffer size. */
+#define AC_TWI_SLAVE_SEND_BUFFER_SIZE 16
/* spi - SPI module. */
/** Select driver: HARD, SOFT, or NONE. */
diff --git a/digital/asserv/src/asserv/twi_proto.c b/digital/asserv/src/asserv/twi_proto.c
index 60b8bdc8..ff15c82f 100644
--- a/digital/asserv/src/asserv/twi_proto.c
+++ b/digital/asserv/src/asserv/twi_proto.c
@@ -70,10 +70,10 @@ twi_proto_init (void)
void
twi_proto_update (void)
{
- u8 buf[AC_TWI_SL_RECV_BUFFER_SIZE];
+ u8 buf[AC_TWI_SLAVE_RECV_BUFFER_SIZE];
u8 read_data;
/* Handle incoming command. */
- while ((read_data = twi_sl_poll (buf, sizeof (buf))))
+ while ((read_data = twi_slave_poll (buf, sizeof (buf))))
twi_proto_callback (buf, read_data);
/* Update status. */
u8 status_with_crc[16];
@@ -104,7 +104,7 @@ twi_proto_update (void)
/* Compute CRC. */
status_with_crc[0] = crc_compute (&status_with_crc[1],
sizeof (status_with_crc) - 1);
- twi_sl_update (status_with_crc, sizeof (status_with_crc));
+ twi_slave_update (status_with_crc, sizeof (status_with_crc));
}
/** Handle one command. */
diff --git a/digital/avr/modules/twi/Makefile b/digital/avr/modules/twi/Makefile
deleted file mode 100644
index 731c2ce3..00000000
--- a/digital/avr/modules/twi/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-BASE = ../../..
-DOC = twi.html
-EXTRACTDOC = twi.h avrconfig.h
-
-include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/twi/Makefile.module b/digital/avr/modules/twi/Makefile.module
index e9bfa070..3508cf4f 100644
--- a/digital/avr/modules/twi/Makefile.module
+++ b/digital/avr/modules/twi/Makefile.module
@@ -1 +1 @@
-twi_SOURCES = twi.avr.c twi.host.c
+twi_SOURCES = twi.c twi_hard.avr.c twi.host.c
diff --git a/digital/avr/modules/twi/README b/digital/avr/modules/twi/README
index c588816d..29a6ab81 100644
--- a/digital/avr/modules/twi/README
+++ b/digital/avr/modules/twi/README
@@ -2,11 +2,12 @@ avr.twi - TWI AVR module.
TWI module for AVR.
-Copyright (C) 2005 Demonchy Clément
+Copyright (C) 2005 Clément Demonchy
+Copyright (C) 2010 Nicolas Schodet
-Robot APB Team/Efrei 2006.
- Web: http://assos.efrei.fr/robot/
- Email: robot AT efrei DOT fr
+APBTeam:
+ Web: http://apbteam.org/
+ Email: team AT apbteam DOT org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/digital/avr/modules/twi/avrconfig.h b/digital/avr/modules/twi/avrconfig.h
index 5f94ecd1..afa1fb13 100644
--- a/digital/avr/modules/twi/avrconfig.h
+++ b/digital/avr/modules/twi/avrconfig.h
@@ -3,17 +3,17 @@
/* avrconfig.h - TWI module configuration template. */
/* avr.twi - TWI AVR module. {{{
*
- * Copyright (C) 2005 Demonchy Clément
+ * Copyright (C) 2010 Nicolas Schodet
*
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -26,13 +26,34 @@
* }}} */
/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 0
-/** Activate slave part. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
#define AC_TWI_SLAVE_ENABLE 0
-/** Slave recv buffer size. */
-#define AC_TWI_SL_RECV_BUFFER_SIZE 16
-/** Slave send buffer size. */
-#define AC_TWI_SL_SEND_BUFFER_SIZE 16
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 0
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Master transfer completion callback, optionally defined by the user, called
+ * at end of master transfer. */
+#undef AC_TWI_MASTER_DONE
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+/** Slave reception buffer size. */
+#define AC_TWI_SLAVE_RECV_BUFFER_SIZE 16
+/** Slave transmission buffer size. */
+#define AC_TWI_SLAVE_SEND_BUFFER_SIZE 16
+/** SDA line IO for SOFT driver. */
+#define AC_TWI_SOFT_SDA_IO A, 0
+/** SCL line IO for SOFT driver. */
+#define AC_TWI_SOFT_SCL_IO A, 1
#endif /* avrconfig_h */
diff --git a/digital/avr/modules/twi/test/Makefile b/digital/avr/modules/twi/test/Makefile
deleted file mode 100644
index 1af68de3..00000000
--- a/digital/avr/modules/twi/test/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# Quick dirty makefile to help you build the test program for twi.
-# It is required to clean before building each program because they share the
-# same object with different defines.
-# Files are copied in *.keep.hex.
-all: subclean
- # Slave
- $(MAKE) -f Makefile.slave
- cp test_twi_sl.hex test_twi_sl.keep.hex
- $(MAKE) -f Makefile.slave clean
- # Master
- $(MAKE) -f Makefile.master
- cp test_twi_master.hex test_twi_master.keep.hex
- $(MAKE) -f Makefile.master clean
-
-subclean:
- # General cleaning
- $(MAKE) -f Makefile.slave clean
- $(MAKE) -f Makefile.master clean
-
-clean: subclean
- rm -f test_twi_master.keep.hex test_twi_sl.keep.hex
diff --git a/digital/avr/modules/twi/test/Makefile.master b/digital/avr/modules/twi/test/Makefile.master
deleted file mode 100644
index 55a762c0..00000000
--- a/digital/avr/modules/twi/test/Makefile.master
+++ /dev/null
@@ -1,25 +0,0 @@
-BASE = ../../..
-PROGS = test_twi_master
-test_twi_master_SOURCES = test_twi_master.c
-DOC =
-EXTRACTDOC =
-MODULES = twi uart proto math/random utils
-
-
-CONFIGFILE = avrconfig_master.h
-TEST_CONFIGFILES = avrconfig_master.h
-
-
-# atmega8, atmega8535, atmega128...
-AVR_MCU = atmega128
-# -O2 : speed
-# -Os : size
-OPTIMIZE = -O2
-
-DEFS =
-LIBS =
-
-# Test compilations.
-TEST_MCU = atmega8535 atmega128
-
-include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/twi/test/Makefile.slave b/digital/avr/modules/twi/test/Makefile.slave
deleted file mode 100644
index 35f84bcd..00000000
--- a/digital/avr/modules/twi/test/Makefile.slave
+++ /dev/null
@@ -1,24 +0,0 @@
-BASE = ../../..
-PROGS = test_twi_sl
-test_twi_sl_SOURCES = test_twi_sl.c
-DOC =
-EXTRACTDOC =
-MODULES = twi uart proto utils
-
-
-CONFIGFILE = avrconfig_slave.h
-TEST_CONFIGFILES = avrconfig_slave.h
-
-# atmega8, atmega8535, atmega128...
-AVR_MCU = atmega128
-# -O2 : speed
-# -Os : size
-OPTIMIZE = -O2
-
-DEFS =
-LIBS =
-
-# Test compilations.
-TEST_MCU = atmega8535 atmega128
-
-include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/twi/test/master/Makefile b/digital/avr/modules/twi/test/master/Makefile
new file mode 100644
index 00000000..59e36f55
--- /dev/null
+++ b/digital/avr/modules/twi/test/master/Makefile
@@ -0,0 +1,14 @@
+BASE = ../../../..
+PROGS = test_twi_master
+test_twi_master_SOURCES = test_twi.c
+MODULES = twi uart proto math/random utils
+CONFIGFILE = avrconfig.h
+# atmega8, atmega8535, atmega128...
+AVR_MCU = atmega128
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -Os
+
+vpath %.c ..
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/twi/test/avrconfig_master.h b/digital/avr/modules/twi/test/master/avrconfig.h
index a65f872f..c3b572a3 100644
--- a/digital/avr/modules/twi/test/avrconfig_master.h
+++ b/digital/avr/modules/twi/test/master/avrconfig.h
@@ -3,17 +3,17 @@
/* avrconfig.h */
/* avr.twi - TWI AVR module. {{{
*
- * Copyright (C) 2005 Demonchy Clément
+ * Copyright (C) 2010 Nicolas Schodet
*
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -25,31 +25,11 @@
*
* }}} */
-/* global */
+/* utils */
/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
* 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
#define AC_FREQ 14745600
-/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 1
-/** Activate slave part. */
-#define AC_TWI_SLAVE_ENABLE 0
-/** Slave recv buffer size. */
-#define AC_TWI_SL_RECV_BUFFER_SIZE 16
-/** Slave send buffer size. */
-#define AC_TWI_SL_SEND_BUFFER_SIZE 16
-
-/* proto - Protocol module. */
-/** Maximum argument size. */
-#define AC_PROTO_ARGS_MAX_SIZE 16
-/** Callback function name. */
-#define AC_PROTO_CALLBACK proto_callback
-/** Putchar function name. */
-#define AC_PROTO_PUTC uart0_putc
-/** Support for quote parameter. */
-#define AC_PROTO_QUOTE 1
-
/* uart - UART module. */
/** Select hardware uart for primary uart: 0, 1 or -1 to disable. */
#define AC_UART0_PORT 1
@@ -59,9 +39,9 @@
/** Send mode:
* - POLLING: no interrupts.
* - RING: interrupts, ring buffer. */
-#define AC_UART0_SEND_MODE POLLING
+#define AC_UART0_SEND_MODE RING
/** Recv mode, same as send mode. */
-#define AC_UART0_RECV_MODE POLLING
+#define AC_UART0_RECV_MODE RING
/** Character size: 5, 6, 7, 8, 9 (only 8 implemented). */
#define AC_UART0_CHAR_SIZE 8
/** Parity : ODD, EVEN, NONE. */
@@ -91,7 +71,33 @@
#define AC_UART1_SEND_BUFFER_SIZE 32
#define AC_UART1_RECV_BUFFER_SIZE 32
#define AC_UART1_SEND_BUFFER_FULL WAIT
-#define AC_UART1_HOST_DRIVER STDIO
+#define AC_UART1_HOST_DRIVER PTS
+/* proto - Protocol module. */
+/** Maximum argument size. */
+#define AC_PROTO_ARGS_MAX_SIZE 32
+/** Callback function name. */
+#define AC_PROTO_CALLBACK proto_callback
+/** Putchar function name. */
+#define AC_PROTO_PUTC uart0_putc
+/** Support for quote parameter. */
+#define AC_PROTO_QUOTE 1
+
+/* twi - TWI module. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
+#define AC_TWI_SLAVE_ENABLE 0
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 1
+/** Master transfer completion callback, optionally defined by the user, called
+ * at end of master transfer. */
+#undef AC_TWI_MASTER_DONE
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
#endif /* avrconfig_h */
diff --git a/digital/avr/modules/twi/test/slave/Makefile b/digital/avr/modules/twi/test/slave/Makefile
new file mode 100644
index 00000000..fbabd11d
--- /dev/null
+++ b/digital/avr/modules/twi/test/slave/Makefile
@@ -0,0 +1,14 @@
+BASE = ../../../..
+PROGS = test_twi_slave
+test_twi_slave_SOURCES = test_twi.c
+MODULES = twi uart proto math/random utils
+CONFIGFILE = avrconfig.h
+# atmega8, atmega8535, atmega128...
+AVR_MCU = atmega128
+# -O2 : speed
+# -Os : size
+OPTIMIZE = -Os
+
+vpath %.c ..
+
+include $(BASE)/make/Makefile.gen
diff --git a/digital/avr/modules/twi/test/avrconfig_slave.h b/digital/avr/modules/twi/test/slave/avrconfig.h
index 2635810d..3d01c881 100644
--- a/digital/avr/modules/twi/test/avrconfig_slave.h
+++ b/digital/avr/modules/twi/test/slave/avrconfig.h
@@ -3,17 +3,17 @@
/* avrconfig.h */
/* avr.twi - TWI AVR module. {{{
*
- * Copyright (C) 2005 Demonchy Clément
+ * Copyright (C) 2010 Nicolas Schodet
*
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -25,31 +25,11 @@
*
* }}} */
-/* global */
+/* utils */
/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800,
* 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */
#define AC_FREQ 14745600
-/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 0
-/** Activate slave part. */
-#define AC_TWI_SLAVE_ENABLE 1
-/** Slave recv buffer size. */
-#define AC_TWI_SL_RECV_BUFFER_SIZE 16
-/** Slave send buffer size. */
-#define AC_TWI_SL_SEND_BUFFER_SIZE 16
-
-/* proto - Protocol module. */
-/** Maximum argument size. */
-#define AC_PROTO_ARGS_MAX_SIZE 8
-/** Callback function name. */
-#define AC_PROTO_CALLBACK proto_callback
-/** Putchar function name. */
-#define AC_PROTO_PUTC uart0_putc
-/** Support for quote parameter. */
-#define AC_PROTO_QUOTE 1
-
/* uart - UART module. */
/** Select hardware uart for primary uart: 0, 1 or -1 to disable. */
#define AC_UART0_PORT 1
@@ -59,9 +39,9 @@
/** Send mode:
* - POLLING: no interrupts.
* - RING: interrupts, ring buffer. */
-#define AC_UART0_SEND_MODE POLLING
+#define AC_UART0_SEND_MODE RING
/** Recv mode, same as send mode. */
-#define AC_UART0_RECV_MODE POLLING
+#define AC_UART0_RECV_MODE RING
/** Character size: 5, 6, 7, 8, 9 (only 8 implemented). */
#define AC_UART0_CHAR_SIZE 8
/** Parity : ODD, EVEN, NONE. */
@@ -91,7 +71,40 @@
#define AC_UART1_SEND_BUFFER_SIZE 32
#define AC_UART1_RECV_BUFFER_SIZE 32
#define AC_UART1_SEND_BUFFER_FULL WAIT
-#define AC_UART1_HOST_DRIVER STDIO
+#define AC_UART1_HOST_DRIVER PTS
+/* proto - Protocol module. */
+/** Maximum argument size. */
+#define AC_PROTO_ARGS_MAX_SIZE 32
+/** Callback function name. */
+#define AC_PROTO_CALLBACK proto_callback
+/** Putchar function name. */
+#define AC_PROTO_PUTC uart0_putc
+/** Support for quote parameter. */
+#define AC_PROTO_QUOTE 1
+
+/* twi - TWI module. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
+#define AC_TWI_SLAVE_ENABLE 1
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 0
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+/** Slave reception buffer size. */
+#define AC_TWI_SLAVE_RECV_BUFFER_SIZE 16
+/** Slave transmission buffer size. */
+#define AC_TWI_SLAVE_SEND_BUFFER_SIZE 16
#endif /* avrconfig_h */
diff --git a/digital/avr/modules/twi/test/test_twi_master.c b/digital/avr/modules/twi/test/test_twi.c
index ff3a570a..f3656b20 100644
--- a/digital/avr/modules/twi/test/test_twi_master.c
+++ b/digital/avr/modules/twi/test/test_twi.c
@@ -1,17 +1,18 @@
-/* test_twi_master.c */
-/* avr.twi.master - TWI master module. {{{
+/* test_twi.c */
+/* avr.twi - TWI AVR module. {{{
*
- * Copyright (C) 2005 Clément Demonchy
+ * Copyright (C) 2005 Clément Demonchy
+ * Copyright (C) 2010 Nicolas Schodet
*
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -22,7 +23,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* }}} */
-
#include "common.h"
#include "modules/twi/twi.h"
#include "modules/proto/proto.h"
@@ -41,77 +41,45 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
#define c(cmd, size) (cmd << 8 | size)
switch (c (cmd, size))
{
- case c ('s', 2):
- /* Send one byte to a slave address.
- * 2 parameters:
- * - slave address;
- * - data.
- */
- twi_ms_send (args[0], &args[1], 1);
- while (!twi_ms_is_finished ())
- ;
- break;
- case c ('r', 1):
- /* Read one byte from an address slave
- * 1 parameter:
- * - slave address.
- */
- {
- uint8_t data = 0x00;
- int8_t d = twi_ms_read (args[0], &data, 1);
- if (d != 0)
- proto_send0 ('e');
- else
- {
- while (!twi_ms_is_finished ())
- ;
- proto_send1b ('R', data);
- }
- }
+ case c ('z', 0):
+ /* Reset. */
+ utils_reset ();
break;
+#if AC_TWI_MASTER_ENABLE
case c ('r', 2):
- /* Read n bytes from an address slave
- * 2 parameter:
- * - slave address.
- * - nb of bytes.
- */
+ /* Read n bytes from a slave.
+ * - b: slave address.
+ * - b: nb of bytes. */
{
- uint8_t data[16];
- int8_t d = twi_ms_read (args[0], data, args[1]);
- if (d != 0)
- proto_send0 ('e');
- else
- {
- while (!twi_ms_is_finished ())
- ;
- proto_send ('R', args[1], data);
- }
+ uint8_t data[args[1]];
+ twi_master_recv (args[0], data, args[1]);
+ uint8_t r = twi_master_wait ();
+ proto_send ('R', r, data);
}
break;
- case c ('t', 2):
+ case c ('t', 3):
/* Test for sending and receiving multiple data.
* It sends a random number of bytes to the slave and then read back
* from it the same number, checking the data are the same as the sent
* ones.
- * 2 parameters:
- * - slave address;
- * - number of iterations to try on.
+ * - slave address.
+ * - maximum nb of bytes.
+ * - number of iterations to try on.
*/
{
int error = 0;
- uint8_t compt = args[1];
- while (compt-- != 0)
+ uint8_t max_byte_number = args[1];
+ uint8_t compt = args[2];
+ while (compt-- != 0 && !error)
{
/* Maximum number of bytes of the message */
- static const uint8_t max_byte_number =
- AC_TWI_SL_RECV_BUFFER_SIZE;
/* Get a random number */
uint32_t random = random_u32 ();
/* Extract a number under max_byte_number */
uint8_t byte_number = random % max_byte_number + 1;
/* Table which contains the random bytes */
uint8_t random_bytes[max_byte_number];
- uint8_t i;
+ uint8_t i, ret;
for (i = 0; i < byte_number; i++)
{
uint8_t mod = i % 4;
@@ -122,65 +90,61 @@ proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
random_bytes[i] = (random >> (mod * 8)) & 0xFF;
}
/* Send data */
- twi_ms_send (args[0], random_bytes, byte_number);
- while (!twi_ms_is_finished ())
- ;
+ twi_master_send (args[0], random_bytes, byte_number);
+ ret = twi_master_wait ();
+ /* Check return */
+ if (ret != byte_number)
+ {
+ /* Error */
+ proto_send3b ('S', compt, ret, byte_number);
+ error = 1;
+ break;
+ }
#ifdef HOST
/* Give time to slave to copy data. */
mex_node_wait_date (mex_node_date () + 2);
#endif
-
/* Received buffer */
uint8_t received_buffer[max_byte_number];
/* Receive data */
- int8_t ret = twi_ms_read (args[0], received_buffer,
- byte_number);
+ twi_master_recv (args[0], received_buffer, byte_number);
+ ret = twi_master_wait ();
/* Check return */
- if (ret != 0)
+ if (ret != byte_number)
{
/* Error */
- proto_send0 ('e');
+ proto_send3b ('R', compt, ret, byte_number);
error = 1;
break;
}
- while (!twi_ms_is_finished ())
- ;
for (i = 0; i < byte_number; i++)
{
if (received_buffer[i] != random_bytes[i])
{
+ /* Error */
+ proto_send3b ('C', compt, i, byte_number);
error = 1;
break;
}
}
- if (error != 0)
- break;
- }
- /* Check for error */
- if (error == 0)
- {
- proto_send1b ('T', args[1]);
}
}
break;
- case c ('z', 0):
- /* Reset */
- utils_reset ();
- break;
+#endif /* AC_TWI_MASTER_ENABLE */
default:
/* Variable number of arguments. */
+#if AC_TWI_MASTER_ENABLE
if (cmd == 's')
{
- /* Send n bytes to a slave address.
- * 1+n parameters:
- * - slave address;
- * - n x data.
- */
- twi_ms_send (args[0], &args[1], size - 1);
- while (!twi_ms_is_finished ())
- ;
+ /* Send n bytes to a slave.
+ * - b: slave address.
+ * - xb: x data. */
+ twi_master_send (args[0], &args[1], size - 1);
+ uint8_t r = twi_master_wait ();
+ proto_send1b ('S', r);
}
else
+#endif /* AC_TWI_MASTER_ENABLE */
{
/* Error */
proto_send0 ('?');
@@ -199,25 +163,40 @@ main (int argc, char **argv)
#ifdef HOST
mex_node_connect ();
#endif
- /* Enable interruptions */
+ /* Enable interruptions. */
sei ();
- /* Initialize serial port */
+ /* Initialize serial port. */
uart0_init ();
- /* We have successfully boot */
+ /* We have successfully boot. */
proto_send0 ('z');
- /* Initialize TWI */
+ /* Initialize TWI. */
twi_init (0x04);
- /* I am a master */
+#if AC_TWI_MASTER_ENABLE
+ /* I am a master. */
proto_send0 ('M');
+#endif
+#if AC_TWI_SLAVE_ENABLE
+ /* I am a slave. */
+ proto_send0 ('S');
+#endif
while (42)
{
#ifdef HOST
mex_node_wait_date (mex_node_date () + 1);
+#endif
+#if AC_TWI_SLAVE_ENABLE
+ uint8_t data[AC_TWI_SLAVE_RECV_BUFFER_SIZE];
+ uint8_t data_len;
+ /* Check for data. */
+ data_len = twi_slave_poll (data, AC_TWI_SLAVE_RECV_BUFFER_SIZE);
+ if (data_len)
+ {
+ /* Echo them back.*/
+ twi_slave_update (data, data_len);
+ }
+#endif
while (uart0_poll ())
proto_accept (uart0_getc ());
-#else
- proto_accept (uart0_getc ());
-#endif
}
- return 0;
}
+
diff --git a/digital/avr/modules/twi/test/test_twi_host.py b/digital/avr/modules/twi/test/test_twi.py
index 94cd9628..3b227f5b 100644
--- a/digital/avr/modules/twi/test/test_twi_host.py
+++ b/digital/avr/modules/twi/test/test_twi.py
@@ -5,23 +5,20 @@ from mex.msg import Msg
from mex.node import Node
from utils.forked import Forked
-def log (x):
- print x
-
-h = Hub (min_clients = 3, log = log)
+h = Hub (min_clients = 3)
fh = Forked (h.wait)
n = Node ()
def nf ():
while True:
time.sleep (1)
- n.wait (n.date + 1)
+ n.wait (n.date + 1000)
fn = Forked (nf)
-slave = os.popen ('./test_twi_sl.host', 'w')
+slave = os.popen ('./slave/test_twi_slave.host', 'w')
try:
- os.system ('./test_twi_master.host')
+ os.system ('./master/test_twi_master.host')
finally:
fn.kill ()
fh.kill ()
diff --git a/digital/avr/modules/twi/test/test_twi_sl.c b/digital/avr/modules/twi/test/test_twi_sl.c
deleted file mode 100644
index e52d914f..00000000
--- a/digital/avr/modules/twi/test/test_twi_sl.c
+++ /dev/null
@@ -1,90 +0,0 @@
-/* test_twi_slave.c */
-/* avr.twi.slave - TWI slave module. {{{
- *
- * Copyright (C) 2005 Clément Demonchy
- *
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * }}} */
-
-#include "common.h"
-#include "modules/twi/twi.h"
-#include "modules/proto/proto.h"
-#include "modules/uart/uart.h"
-#include "modules/utils/utils.h"
-#include "io.h"
-
-#ifdef HOST
-# include "modules/host/mex.h"
-#endif
-
-void
-proto_callback (uint8_t cmd, uint8_t size, uint8_t *args)
-{
-#define c(cmd, size) (cmd << 8 | size)
- switch (c (cmd, size))
- {
- /* Reset */
- case 'z':
- utils_reset ();
- break;
- /* Error */
- default:
- proto_send0 ('?');
- return;
- }
- /* Acknowledge what has been done */
- proto_send (cmd, size, args);
-}
-
-int
-main (int argc, char **argv)
-{
- avr_init (argc, argv);
-#ifdef HOST
- mex_node_connect ();
-#endif
- /* Enable interruptions */
- sei ();
- /* Initialize serial port */
- uart0_init ();
- /* We have successfully boot */
- proto_send0 ('z');
- /* Initialize TWI */
- twi_init (0x02);
- /* I am a slave */
- proto_send0 ('S');
- while (42)
- {
-#ifdef HOST
- mex_node_wait_date (mex_node_date () + 1);
-#endif
- uint8_t data[AC_TWI_SL_RECV_BUFFER_SIZE];
- data[0] = 0;
- /* Check for data */
- if (twi_sl_poll (data, AC_TWI_SL_RECV_BUFFER_SIZE))
- {
- /* Receive and store them */
- twi_sl_update (data, AC_TWI_SL_RECV_BUFFER_SIZE);
- }
- while (uart0_poll ())
- proto_accept (uart0_getc ());
- }
- return 0;
-}
diff --git a/digital/avr/modules/twi/twi.avr.c b/digital/avr/modules/twi/twi.avr.c
deleted file mode 100644
index dc07ede2..00000000
--- a/digital/avr/modules/twi/twi.avr.c
+++ /dev/null
@@ -1,380 +0,0 @@
-/* twi.avr.c */
-/* avr.twi - TWI AVR module. {{{
- *
- * Copyright (C) 2005 Demonchy Clément
- *
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * }}} */
-#include "common.h"
-#include "twi.h"
-#include "io.h"
-
-#if !AC_TWI_MASTER_ENABLE && !AC_TWI_SLAVE_ENABLE
-# error "twi: you should enable at least master or slave code"
-#endif
-
-#if AC_TWI_MASTER_ENABLE && AC_TWI_SLAVE_ENABLE
-# error "twi: multi-master not implemented"
-#endif
-
-#include <compat/twi.h>
-// #include "modules/uart/uart.h"
-
-// TODO mettre l'etat partout
-// quand on fait les demandes, et les liberations qui vont bien dans
-// l'interruption
-
-enum
-{
- TWI_SUCCESS,
- TWI_BUSY,
- TWI_FREE,
- TWI_FAILURE
-};
-
-#if AC_TWI_SLAVE_ENABLE
-/* données reçues du master */
-static volatile uint8_t rcpt_buf_sl[AC_TWI_SL_RECV_BUFFER_SIZE];
-static volatile uint8_t data_ready_sl;
-/* données à envoyer au master */
-/* 2 buffers 1 pour envoyer vers l'user et l'autre vers l'i2c */
-static volatile uint8_t send_buf_sl1[AC_TWI_SL_SEND_BUFFER_SIZE];
-static volatile uint8_t send_buf_sl2[AC_TWI_SL_SEND_BUFFER_SIZE];
-static volatile uint8_t *send_sys_sl, *send_user_sl;
-static volatile uint8_t update_sl; /* lock pour savoir si on peut switcher les buffers sans risque */
-static volatile uint8_t send_switch_sl;
-static volatile uint8_t rcpt_idx_sl = 0;
-#endif /* AC_TWI_SLAVE_ENABLE */
-#if AC_TWI_MASTER_ENABLE
-static volatile int8_t state_ms;
-static volatile int8_t nb_retry_ms = 5; // XXX utile ?
-static volatile uint8_t dest_addr_ms;
-static volatile uint8_t len_buf_ms;
-static volatile uint8_t *send_buf_ms;
-#endif /* AC_TWI_MASTER_ENABLE */
-
-void
-twi_init (uint8_t addr)
-{
-#if AC_TWI_SLAVE_ENABLE
- data_ready_sl = 0;
- send_switch_sl = 0;
- update_sl = 0;
- send_sys_sl = send_buf_sl1;
- send_user_sl = send_buf_sl2;
- TWAR = addr;
- TWSR = 0x00;
- TWCR = _BV(TWEA);
-#endif /* AC_TWI_SLAVE_ENABLE */
-#if AC_TWI_MASTER_ENABLE
- #if defined(TWPS0)
- TWSR = 0;
- #endif
- TWBR = (AC_FREQ / 100000UL - 16) / 2;
- state_ms = TWI_FREE;
-#endif /* AC_TWI_MASTER_ENABLE */
- /* Active la twi et les interruptions de la twi */
- TWCR |= _BV (TWEN) | _BV (TWIE);
-}
-
-#if AC_TWI_SLAVE_ENABLE
-uint8_t
-twi_sl_poll (uint8_t *buffer, uint8_t size)
-{
- // XXX state
- if (data_ready_sl)
- {
- data_ready_sl = 0;
- uint8_t to_read, read;
- /* Get how many data we can really read. */
- if (size < rcpt_idx_sl)
- /* FIXME: this case sucks. */
- to_read = size;
- else
- to_read = rcpt_idx_sl;
- /* Copy amount of data read. */
- read = to_read;
- while (to_read --)
- buffer[to_read] = rcpt_buf_sl[to_read];
- /* de nouveau dispo pour traiter de nouvelles requetes */
- TWCR |= _BV (TWEA);
- return read;
- }
- else
- return 0;
-}
-#endif /* AC_TWI_SLAVE_ENABLE */
-
-#if AC_TWI_SLAVE_ENABLE
-void
-twi_sl_update (uint8_t *buffer, uint8_t size)
-{
- // XXX state
- update_sl = 1;
- send_switch_sl = 1; /* demander un swap des buffers */
- while (size --)
- send_user_sl[size] = buffer[size];
- update_sl = 0;
-}
-#endif /* AC_TWI_SLAVE_ENABLE */
-
-#if AC_TWI_MASTER_ENABLE
-int8_t
-twi_ms_is_finished ()
-{
- if (state_ms == TWI_SUCCESS || state_ms == TWI_FAILURE)
- {
- state_ms = TWI_FREE;
- return 1;
- }
- else
- return 0;
-}
-#endif /* AC_TWI_MASTER_ENABLE */
-
-#if AC_TWI_MASTER_ENABLE
-int8_t
-twi_ms_send (uint8_t addr, uint8_t *data, uint8_t len)
-{
- //uart0_putc ('a');
- if (state_ms != TWI_BUSY)
- {
- //uart0_putc ('b');
- state_ms = TWI_BUSY;
- nb_retry_ms = 0;
- dest_addr_ms = addr & 0xfe;
- len_buf_ms = len;
- send_buf_ms = data;
- /* envoie du start */
- TWCR |= _BV(TWSTA) | _BV(TWINT);
- return 0;
- }
- else
- {
- //uart0_putc ('c');
- return -1;
- }
-}
-#endif /* AC_TWI_MASTER_ENABLE */
-
-#if AC_TWI_MASTER_ENABLE
-int8_t
-twi_ms_read (uint8_t addr, uint8_t *data, uint8_t len)
-{
-
- //uart0_putc ('z');
- if (state_ms != TWI_BUSY)
- {
- //uart0_putc ('y');
- state_ms = TWI_BUSY;
- nb_retry_ms = 0;
- dest_addr_ms = addr | 0x01;
- len_buf_ms = len;
- send_buf_ms = data;
- TWCR |= _BV(TWSTA) | _BV (TWINT);
- return 0;
- }
- else
- {
- //uart0_putc ('x');
- return -1;
- }
-}
-#endif /* AC_TWI_MASTER_ENABLE */
-
-SIGNAL (SIG_2WIRE_SERIAL)
-{
-#if AC_TWI_SLAVE_ENABLE
- static uint8_t send_idx_sl = 0;
-#endif /* AC_TWI_SLAVE_ENABLE */
-#if AC_TWI_MASTER_ENABLE
- static uint8_t idx_ms;
-#define NB_RETRY 5
-#endif /* AC_TWI_MASTER_ENABLE */
- switch (TW_STATUS)
- {
-#if AC_TWI_SLAVE_ENABLE
- /***** slave transmitter mode *****/
- /* START + SLA|W + ACK
- * on a recu un start pour une ecriture et on a acquité
- * choisi le buffer d'envoie
- * envoie le premier byte
- */
- case TW_ST_SLA_ACK:
- case TW_ST_ARB_LOST_SLA_ACK:
- if (send_switch_sl && !update_sl)
- {
- volatile uint8_t *tmp = send_sys_sl;
- send_sys_sl = send_user_sl;
- send_user_sl = tmp;
- send_switch_sl = 0;
- }
- send_idx_sl = 0;
- /* NO BREAK */
- /* Recu un ack apres l'envoie d'un bit */
- case TW_ST_DATA_ACK:
- //uart0_putc ('p');
- TWDR = send_sys_sl[send_idx_sl++];
- if (send_idx_sl == AC_TWI_SL_SEND_BUFFER_SIZE)
- TWCR &= ~_BV(TWEA);
- TWCR |= _BV(TWINT);
- break;
- case TW_ST_DATA_NACK:
- case TW_ST_LAST_DATA:
- //uart0_putc ('q');
- TWCR |= _BV (TWEA);
- TWCR |= _BV(TWINT);
- break;
- /***** slave receiver mode *****/
- /* START + SLA|W + ACK */
- case TW_SR_SLA_ACK:
- case TW_SR_ARB_LOST_SLA_ACK:
- case TW_SR_GCALL_ACK:
- case TW_SR_ARB_LOST_GCALL_ACK:
- //uart0_putc ('u');
- data_ready_sl = 0;
- rcpt_idx_sl = 0;
- if (AC_TWI_SL_RECV_BUFFER_SIZE == 1)
- TWCR &= ~_BV(TWEA);
- TWCR |= _BV(TWINT);
- break;
- /* DATA + ACK */
- case TW_SR_DATA_ACK:
- case TW_SR_GCALL_DATA_ACK:
- //uart0_putc ('s');
- rcpt_buf_sl[rcpt_idx_sl++] = TWDR;
- if (AC_TWI_SL_RECV_BUFFER_SIZE - rcpt_idx_sl == 1)
- TWCR &= ~_BV(TWEA);
- TWCR |= _BV(TWINT);
- break;
- /* DATA + NACK */
- case TW_SR_DATA_NACK:
- case TW_SR_GCALL_DATA_NACK:
- //uart0_putc ('o');
- rcpt_buf_sl[rcpt_idx_sl++] = TWDR;
- /* NO BREAK */
- /* STOP */
- case TW_SR_STOP:
- //uart0_putc ('q');
- data_ready_sl = 1;
- TWCR |= _BV(TWINT);
- break;
-#endif /* AC_TWI_SLAVE_ENABLE */
-#if AC_TWI_MASTER_ENABLE
- /* Master */
- case TW_START:
- case TW_REP_START:
- //uart0_putc ('d');
- /* start transmis, on envoie l'adresse */
- TWCR &= ~ (_BV (TWSTA) | _BV (TWSTO) | _BV (TWINT));
- TWDR = dest_addr_ms;
- idx_ms = 0;
- TWCR |= _BV (TWINT);
- break;
- case TW_MT_ARB_LOST: /* valable pour le receiver aussi */
- /* todo */
- break;
- /* Master Transmitter */
- case TW_MT_DATA_ACK:
- case TW_MT_SLA_ACK:
- //uart0_putc ('e');
- /* start transmis, on envoie l'adresse */
- /* slave ok
- * On envoi des données si il en reste
- */
- if (idx_ms < len_buf_ms)
- {
- TWDR = send_buf_ms[idx_ms ++];
- }
- else
- {
- TWCR |= _BV (TWSTO);
- state_ms = TWI_SUCCESS;
- }
- TWCR |= _BV (TWINT);
- break;
- case TW_MT_SLA_NACK:
- //uart0_putc ('f');
- /* start transmis, on envoie l'adresse */
- /* le slave ne repond plus
- * on essaye NB_RETRY avant d'arreter
- */
- if (nb_retry_ms < NB_RETRY)
- {
- TWCR |= _BV (TWSTA);
- nb_retry_ms ++;
- }
- else
- {
- TWCR |= _BV (TWSTO);
- state_ms = TWI_FAILURE;
- }
- TWCR |= _BV (TWINT);
- break;
- case TW_MT_DATA_NACK:
- //uart0_putc ('g');
- /* start transmis, on envoie l'adresse */
- /* le slave ne veut plus de donnée */
- TWCR |= _BV (TWSTO);
- state_ms = TWI_SUCCESS;
- TWCR |= _BV (TWINT);
- break;
- /* Master Receiver */
- case TW_MR_SLA_ACK:
- //uart0_putc ('h');
- /* start transmis, on envoie l'adresse */
- if (len_buf_ms > 1) /* on recoit plusieurs octet */
- {
- TWCR |= _BV (TWEA);
- }
- TWCR |= _BV (TWINT);
- break;
- case TW_MR_SLA_NACK:
- /* start transmis, on envoie l'adresse */
- if (nb_retry_ms < NB_RETRY)
- {
- //uart0_putc ('i');
- TWCR |= _BV (TWEA);
- }
- else
- {
- //uart0_putc ('j');
- TWCR |= _BV (TWSTO);
- state_ms = TWI_FAILURE;
- }
- TWCR |= _BV (TWINT);
- break;
- case TW_MR_DATA_ACK:
- //uart0_putc ('k');
- send_buf_ms[idx_ms ++] = TWDR;
- if (idx_ms == (len_buf_ms - 1))
- TWCR &= ~ _BV (TWEA);
- TWCR |= _BV (TWINT);
- break;
- case TW_MR_DATA_NACK: /* dernier byte */
- //uart0_putc ('l');
- state_ms = TWI_SUCCESS;
- send_buf_ms[idx_ms ++] = TWDR;
- TWCR |= _BV (TWSTO);
- TWCR |= _BV (TWINT);
- break;
-#endif/* AC_TWI_MASTER_ENABLE */
- }
-}
diff --git a/digital/avr/modules/twi/twi.c b/digital/avr/modules/twi/twi.c
new file mode 100644
index 00000000..60a2b811
--- /dev/null
+++ b/digital/avr/modules/twi/twi.c
@@ -0,0 +1,77 @@
+/* twi.c - Common functions for all implementations. */
+/* avr.twi - TWI AVR module. {{{
+ *
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+#include "twi.h"
+
+#if AC_TWI_SLAVE_ENABLE && AC_TWI_SLAVE_POLLED
+
+# include "io.h"
+# include "modules/utils/utils.h"
+# include <string.h>
+
+/** Module context. */
+struct twi_poll_t
+{
+ /** Reception buffer. */
+ uint8_t recv_buffer[AC_TWI_SLAVE_RECV_BUFFER_SIZE];
+ /** Reception buffer current size. */
+ volatile uint8_t recv_buffer_size;
+};
+
+/** Global context. */
+static struct twi_poll_t twi_poll_global;
+# define ctx twi_poll_global
+
+/** Called on data reception from master when in polled mode instead of user
+ * provided callback, interrupts are locked. */
+void
+twi_slave_recv_polled (const uint8_t *buffer, uint8_t size)
+{
+ assert (size <= AC_TWI_SLAVE_RECV_BUFFER_SIZE);
+ memcpy (ctx.recv_buffer, buffer, size);
+ ctx.recv_buffer_size = size;
+}
+
+uint8_t
+twi_slave_poll (uint8_t *buffer, uint8_t size)
+{
+# if !AC_TWI_NO_INTERRUPT
+ /* Lock interrupts. */
+ intr_flags_t flags = intr_lock ();
+# endif
+ /* Copy data. */
+ uint8_t recv_size = ctx.recv_buffer_size;
+ size = UTILS_MIN (size, recv_size);
+ memcpy (buffer, ctx.recv_buffer, size);
+ /* Reset. */
+ ctx.recv_buffer_size = 0;
+# if !AC_TWI_NO_INTERRUPT
+ /* Unlock. */
+ intr_restore (flags);
+# endif
+ return size;
+}
+
+#endif /* AC_TWI_SLAVE_ENABLE && AC_TWI_SLAVE_POLLED */
diff --git a/digital/avr/modules/twi/twi.h b/digital/avr/modules/twi/twi.h
index a96986bf..4ce3e25e 100644
--- a/digital/avr/modules/twi/twi.h
+++ b/digital/avr/modules/twi/twi.h
@@ -3,17 +3,17 @@
/* twi.h */
/* avr.twi - TWI AVR module. {{{
*
- * Copyright (C) 2005 Demonchy Clément
+ * Copyright (C) 2010 Nicolas Schodet
*
- * Robot APB Team/Efrei 2006.
- * Web: http://assos.efrei.fr/robot/
- * Email: robot AT efrei DOT fr
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@@ -25,31 +25,113 @@
*
* }}} */
-/** Initialise twi. */
+#if !AC_TWI_SLAVE_ENABLE && !AC_TWI_MASTER_ENABLE
+# error "twi: no enabled mode"
+#endif
+
+/** Initialise module, configure slave address. Slave address is ignored if
+ * slave mode is disabled. */
void
twi_init (uint8_t addr);
+/** Uninitialise module, will no longer respond to bus events. */
+void
+twi_uninit (void);
+
#if AC_TWI_SLAVE_ENABLE
-/** Récupère dans buffer les données recues en tant qu'esclave.
- * @return the amout of read data.
- */
-uint8_t
-twi_sl_poll (uint8_t *buffer, uint8_t size);
-/** Met à jour le buffer de donnée à envoyer */
-void
-twi_sl_update (uint8_t *buffer, uint8_t size);
+
+# if AC_TWI_SLAVE_POLLED
+# ifdef AC_TWI_SLAVE_RECV
+# error "twi: AC_TWI_SLAVE_RECV should not be set in polled mode"
+# endif
+# define AC_TWI_SLAVE_RECV twi_slave_recv_polled
+# endif
+
+/** Called on data reception from master.
+ *
+ * May run under interrupt context. Bus may be held until this function
+ * returns, so it has to operate quickly. */
+void
+AC_TWI_SLAVE_RECV (const uint8_t *buffer, uint8_t size);
+
+/** Update buffer to be sent to master if requested. */
+void
+twi_slave_update (const uint8_t *buffer, uint8_t size);
+
+# if AC_TWI_SLAVE_POLLED
+
+/** If new data has been received, copy received data to provided buffer and
+ * return received data size. Else, return 0. */
+uint8_t
+twi_slave_poll (uint8_t *buffer, uint8_t size);
+
+# endif
+
#endif /* AC_TWI_SLAVE_ENABLE */
#if AC_TWI_MASTER_ENABLE
-/** Is the current transaction finished ? */
-int8_t
-twi_ms_is_finished (void);
-/** Send len bytes of data to address */
-int8_t
-twi_ms_send (uint8_t address, uint8_t *data, uint8_t len);
-/** Read len bytes at addresse en put them in data */
-int8_t
-twi_ms_read (uint8_t address, uint8_t *data, uint8_t len);
+
+/** Send data to a slave. This is non blocking, you have to poll master
+ * status or use a callback to determine if transfer is terminated.
+ *
+ * Input buffer is not copied, it should be kept valid until transmission is
+ * finished. */
+void
+twi_master_send (uint8_t addr, const uint8_t *buffer, uint8_t size);
+
+/** Receive data from a slave. This is non blocking, you have to poll master
+ * status or use a callback to determine if transfer is terminated.
+ *
+ * Input buffer is directly written, and should be kept valid until reception
+ * is finished. */
+void
+twi_master_recv (uint8_t addr, uint8_t *buffer, uint8_t size);
+
+/** Master status, any other values are the number of bytes transferred. */
+enum
+{
+ /** Busy transferring data. */
+ TWI_MASTER_BUSY = 0xff,
+ /** Last transfer finished badly, ready to process new transfer.
+ * Among errors: no acknowledge, bad CRC (if activated), arbitration
+ * lost... */
+ TWI_MASTER_ERROR = 0,
+};
+
+/** Get current master status. */
+uint8_t
+twi_master_status (void);
+
+/** Wait current master transfer completion and return new status. */
+uint8_t
+twi_master_wait (void);
+
+# ifdef AC_TWI_MASTER_DONE
+
+/** Called on master transfer completion.
+ *
+ * May run under interrupt context. */
+void
+AC_TWI_MASTER_DONE (void);
+
+# endif
+
#endif /* AC_TWI_MASTER_ENABLE */
+#if AC_TWI_NO_INTERRUPT
+
+/** To be call on regular basis, poll events to simulate interrupts. */
+void
+twi_update (void);
+
+#endif /* AC_TWI_NO_INTERRUPT */
+
+/* Define selected driver. */
+#define TWI_DRIVER_HARD 'h'
+#define TWI_DRIVER_SOFT 's'
+#define TWI_DRIVER_USI 'u'
+#define TWI_DRIVER__(drv) TWI_DRIVER_ ## drv
+#define TWI_DRIVER_(drv) TWI_DRIVER__ (drv)
+#define TWI_DRIVER TWI_DRIVER_ (AC_TWI_DRIVER)
+
#endif /* twi_h */
diff --git a/digital/avr/modules/twi/twi.host.c b/digital/avr/modules/twi/twi.host.c
index 69c4e0a8..eabf842a 100644
--- a/digital/avr/modules/twi/twi.host.c
+++ b/digital/avr/modules/twi/twi.host.c
@@ -1,4 +1,4 @@
-/* twi.host.c */
+/* twi.host.c - Implementation for host system. */
/* avr.twi - TWI AVR module. {{{
*
* Copyright (C) 2008 Nicolas Schodet
@@ -24,13 +24,11 @@
* }}} */
#include "common.h"
#include "twi.h"
-#include "modules/host/mex.h"
+#include "modules/utils/utils.h"
+#include "modules/host/mex.h"
#include <string.h>
-/** This implementation should cover all usual cases, and assert in other
- * cases. */
-
/** Read messages are sent as request.
* In request, first byte is address, second byte is length.
* In response, whole payload is data. */
@@ -39,19 +37,28 @@
* First byte is address, rest of payload is data. */
#define TWI_WRITE 0x91
-/** TWI address. */
-static uint8_t twi_address;
-
+/** Module context. */
+struct twi_host_t
+{
+ /** Slave address. */
+ uint8_t address;
#if AC_TWI_SLAVE_ENABLE
+ /** Slave transmission buffer. */
+ uint8_t slave_send_buffer[AC_TWI_SLAVE_SEND_BUFFER_SIZE];
+ /** Slave transmission buffer current size. */
+ uint8_t slave_send_buffer_size;
+#endif /* AC_TWI_SLAVE_ENABLE */
+#if AC_TWI_MASTER_ENABLE
+ /** Current master status. */
+ uint8_t master_current_status;
+#endif /* AC_TWI_MASTER_ENABLE */
+};
-/** Received data. */
-static uint8_t rcpt_buf_sl[AC_TWI_SL_RECV_BUFFER_SIZE];
-/** Received data size. */
-static uint8_t rcpt_size_sl;
-/** Whether new received data are ready. */
-static uint8_t data_ready_sl;
-/** Data sent on master request. */
-static uint8_t send_buf_sl[AC_TWI_SL_SEND_BUFFER_SIZE];
+/** Global context. */
+static struct twi_host_t twi_host_global;
+#define ctx twi_host_global
+
+#if AC_TWI_SLAVE_ENABLE
/** Handle READ requests from master. */
static void
@@ -63,57 +70,51 @@ twi_handle_WRITE (void *user, mex_msg_t *msg);
#endif /* AC_TWI_SLAVE_ENABLE */
-/** Initialise twi. */
void
twi_init (uint8_t addr)
{
- twi_address = addr;
+ assert ((addr & 1) == 0);
+ ctx.address = addr;
#if AC_TWI_SLAVE_ENABLE
- data_ready_sl = 0;
+ ctx.slave_send_buffer_size = 1;
+ ctx.slave_send_buffer[0] = 0;
mex_node_register (TWI_READ, twi_handle_READ, NULL);
mex_node_register (TWI_WRITE, twi_handle_WRITE, NULL);
#endif /* AC_TWI_SLAVE_ENABLE */
+#if AC_TWI_MASTER_ENABLE
+ ctx.master_current_status = TWI_MASTER_ERROR;
+#endif /* AC_TWI_MASTER_ENABLE */
}
-#if AC_TWI_SLAVE_ENABLE
-
-/** Récupère dans buffer les données recues en tant qu'esclave */
-uint8_t
-twi_sl_poll (uint8_t *buffer, uint8_t size)
+void
+twi_uninit (void)
{
- uint8_t i;
- if (data_ready_sl)
- {
- data_ready_sl = 0;
- if (size > rcpt_size_sl)
- size = rcpt_size_sl;
- for (i = 0; i < size; i++)
- buffer[i] = rcpt_buf_sl[i];
- return size;
- }
- else
- return 0;
+ ctx.address = 0xff;
}
-/** Met à jour le buffer de donnée à envoyer */
-void
-twi_sl_update (uint8_t *buffer, uint8_t size)
+#if AC_TWI_SLAVE_ENABLE
+
+/** Update buffer to be sent to master if requested. */
+void
+twi_slave_update (const uint8_t *buffer, uint8_t size)
{
- while (size--)
- send_buf_sl[size] = buffer[size];
+ assert (size && size <= AC_TWI_SLAVE_SEND_BUFFER_SIZE);
+ memcpy (ctx.slave_send_buffer, buffer, size);
+ ctx.slave_send_buffer_size = size;
}
/** Handle READ requests from master. */
static void
twi_handle_READ (void *user, mex_msg_t *msg)
{
- u8 addr, size;
+ uint8_t addr, size;
mex_msg_pop (msg, "BB", &addr, &size);
- if (addr == twi_address)
+ if (addr == ctx.address)
{
- assert (size <= AC_TWI_SL_SEND_BUFFER_SIZE);
+ assert (size <= AC_TWI_SLAVE_SEND_BUFFER_SIZE);
mex_msg_t *m = mex_msg_new (TWI_READ);
- mex_msg_push_buffer (m, send_buf_sl, size);
+ mex_msg_push_buffer (m, ctx.slave_send_buffer,
+ UTILS_MIN (size, ctx.slave_send_buffer_size));
mex_node_response (m);
}
}
@@ -122,15 +123,13 @@ twi_handle_READ (void *user, mex_msg_t *msg)
static void
twi_handle_WRITE (void *user, mex_msg_t *msg)
{
- u8 addr, size;
+ uint8_t addr, size;
mex_msg_pop (msg, "B", &addr);
- if (addr == twi_address)
+ if (addr == ctx.address)
{
size = mex_msg_len (msg);
- assert (size <= AC_TWI_SL_RECV_BUFFER_SIZE);
- memcpy (rcpt_buf_sl, mex_msg_pop_buffer (msg), size);
- rcpt_size_sl = size;
- data_ready_sl = 1;
+ AC_TWI_SLAVE_RECV (mex_msg_pop_buffer (msg),
+ UTILS_MIN (size, AC_TWI_SLAVE_RECV_BUFFER_SIZE));
}
}
@@ -138,35 +137,62 @@ twi_handle_WRITE (void *user, mex_msg_t *msg)
#if AC_TWI_MASTER_ENABLE
-/** Is the current transaction finished ? */
-int8_t
-twi_ms_is_finished (void)
-{
- return 1;
-}
-
-/** Send len bytes of data to address */
-int8_t
-twi_ms_send (uint8_t address, uint8_t *data, uint8_t len)
+void
+twi_master_send (uint8_t addr, const uint8_t *buffer, uint8_t size)
{
+ /* Send message. */
mex_msg_t *m = mex_msg_new (TWI_WRITE);
- mex_msg_push (m, "B", address);
- mex_msg_push_buffer (m, data, len);
+ mex_msg_push (m, "B", addr);
+ mex_msg_push_buffer (m, buffer, size);
mex_node_send (m);
- return 0;
+ /* Update status, there is no background task. */
+ ctx.master_current_status = size;
+ /* If defined, call master done callback. */
+#ifdef AC_TWI_MASTER_DONE
+ AC_TWI_MASTER_DONE ();
+#endif
}
-/** Read len bytes at addresse en put them in data */
-int8_t
-twi_ms_read (uint8_t address, uint8_t *data, uint8_t len)
+void
+twi_master_recv (uint8_t addr, uint8_t *buffer, uint8_t size)
{
+ /* Send request and wait for response. */
mex_msg_t *m = mex_msg_new (TWI_READ);
- mex_msg_push (m, "BB", address, len);
+ mex_msg_push (m, "BB", addr, size);
m = mex_node_request (m);
- assert (mex_msg_len (m) == len);
- memcpy (data, mex_msg_pop_buffer (m), len);
- return 0;
+ int recv = mex_msg_len (m);
+ assert (recv <= size);
+ memcpy (buffer, mex_msg_pop_buffer (m), recv);
+ /* Update status, there is no background task. */
+ ctx.master_current_status = recv;
+ /* If defined, call master done callback. */
+#ifdef AC_TWI_MASTER_DONE
+ AC_TWI_MASTER_DONE ();
+#endif
+}
+
+uint8_t
+twi_master_status (void)
+{
+ return ctx.master_current_status;
+}
+
+uint8_t
+twi_master_wait (void)
+{
+ /* No background task, nothing to wait. */
+ return ctx.master_current_status;
}
#endif /* AC_TWI_MASTER_ENABLE */
+#if AC_TWI_NO_INTERRUPT
+
+void
+twi_update (void)
+{
+ /* Nothing to do. */
+}
+
+#endif /* AC_TWI_NO_INTERRUPT */
+
diff --git a/digital/avr/modules/twi/twi_hard.avr.c b/digital/avr/modules/twi/twi_hard.avr.c
new file mode 100644
index 00000000..b921f5d2
--- /dev/null
+++ b/digital/avr/modules/twi/twi_hard.avr.c
@@ -0,0 +1,355 @@
+/* twi_hard.c - Implementation using hardware TWI. */
+/* avr.twi - TWI AVR module. {{{
+ *
+ * Copyright (C) 2005 Clément Demonchy
+ * Copyright (C) 2010 Nicolas Schodet
+ *
+ * APBTeam:
+ * Web: http://apbteam.org/
+ * Email: team AT apbteam DOT org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * }}} */
+#include "common.h"
+#include "twi.h"
+
+#if TWI_DRIVER == TWI_DRIVER_HARD
+
+# include "modules/utils/utils.h"
+# include "io.h"
+# include <util/twi.h>
+# include <string.h>
+
+# if AC_TWI_MASTER_ENABLE && AC_TWI_SLAVE_ENABLE
+/* To support multi-master mode, care should be taken in the master send and
+ * receive functions as they can no longer assume that the TWI is idle if
+ * master status is busy. */
+# error "twi: multi-master not implemented"
+# endif
+# if AC_TWI_PULL_UP
+# error "twi: pull up not supported"
+# endif
+# if AC_TWI_NO_INTERRUPT
+# warning "twi: no interrupt not supported"
+# endif
+
+/* Tested AVR check. */
+# if defined (__AVR_ATmega32__)
+# elif defined (__AVR_ATmega64__)
+# elif defined (__AVR_ATmega128__)
+# else
+# error "twi: not tested on this chip"
+# endif
+
+/* Default TWCR value, activate TWI and TWI interrupts. */
+# define TWCR_DEFAULT (_BV (TWEN) | _BV (TWIE))
+
+/* TWBR register value for selected baud rate. */
+# define TWBR_VALUE ((AC_FREQ / AC_TWI_FREQ - 16) / 2)
+# if TWBR_VALUE > 255
+# error "twi: bad baud rate"
+# endif
+
+/* Call master done callback if defined. */
+# ifdef AC_TWI_MASTER_DONE
+# define TWI_MASTER_DONE() AC_TWI_MASTER_DONE ()
+# else
+# define TWI_MASTER_DONE()
+# endif
+
+/** Module context. */
+struct twi_hard_t
+{
+# if AC_TWI_SLAVE_ENABLE
+ /** Slave transmission buffer. */
+ uint8_t slave_send_buffer[AC_TWI_SLAVE_SEND_BUFFER_SIZE];
+ /** Slave transmission buffer size, should never be zero! */
+ volatile uint8_t slave_send_buffer_size;
+# endif /* AC_TWI_SLAVE_ENABLE */
+# if AC_TWI_MASTER_ENABLE
+ /** Current master status. */
+ volatile uint8_t master_current_status;
+ /** Current transfer slave address. */
+ volatile uint8_t master_transfer_address;
+ /** Current transfer buffer. */
+ volatile uint8_t *master_transfer_buffer;
+ /** Current transfer buffer size. */
+ volatile uint8_t master_transfer_buffer_size;
+# endif /* AC_TWI_MASTER_ENABLE */
+};
+
+/** Global context. */
+static struct twi_hard_t twi_hard_global;
+# define ctx twi_hard_global
+
+void
+twi_init (uint8_t addr)
+{
+# if AC_TWI_SLAVE_ENABLE
+ /* Initial send buffer, size can not be zero. */
+ ctx.slave_send_buffer_size = 1;
+ ctx.slave_send_buffer[0] = 0;
+ /* Set slave address. */
+ TWAR = addr;
+# endif /* AC_TWI_SLAVE_ENABLE */
+# if AC_TWI_MASTER_ENABLE
+ /* No previous transfer. */
+ ctx.master_current_status = TWI_MASTER_ERROR;
+ /* Set baud rate. */
+# ifdef TWPS0
+ TWSR = 0; /* Prescaler. */
+# endif
+ TWBR = TWBR_VALUE;
+# endif /* AC_TWI_MASTER_ENABLE */
+ /* Activate TWI and TWI interrupts. */
+# if AC_TWI_SLAVE_ENABLE
+ TWCR = TWCR_DEFAULT | _BV (TWEA);
+# else
+ TWCR = TWCR_DEFAULT;
+# endif
+}
+
+void
+twi_uninit (void)
+{
+ /* Disable TWI and TWI interrupts. */
+ TWCR = 0;
+}
+
+# if AC_TWI_SLAVE_ENABLE
+
+void
+twi_slave_update (const uint8_t *buffer, uint8_t size)
+{
+ assert (size && size <= AC_TWI_SLAVE_SEND_BUFFER_SIZE);
+ /* Lock interrupts. */
+ intr_flags_t flags = intr_lock ();
+ /* Copy buffer. */
+ memcpy (ctx.slave_send_buffer, buffer, size);
+ ctx.slave_send_buffer_size = size;
+ /* Unlock. */
+ intr_restore (flags);
+}
+
+# endif /* AC_TWI_SLAVE_ENABLE */
+
+# if AC_TWI_MASTER_ENABLE
+
+void
+twi_master_send (uint8_t addr, const uint8_t *buffer, uint8_t size)
+{
+ /* Now busy. */
+ assert (ctx.master_current_status != TWI_MASTER_BUSY);
+ ctx.master_current_status = TWI_MASTER_BUSY;
+ /* Record send parameters. */
+ ctx.master_transfer_address = addr & 0xfe;
+ ctx.master_transfer_buffer_size = size;
+ ctx.master_transfer_buffer = (uint8_t *) buffer;
+ /* Send start condition. */
+ TWCR |= _BV (TWSTA) | _BV (TWINT);
+}
+
+void
+twi_master_recv (uint8_t addr, uint8_t *buffer, uint8_t size)
+{
+ /* Now busy. */
+ assert (ctx.master_current_status != TWI_MASTER_BUSY);
+ ctx.master_current_status = TWI_MASTER_BUSY;
+ /* Record receive parameters. */
+ ctx.master_transfer_address = addr | 0x01;
+ ctx.master_transfer_buffer_size = size;
+ ctx.master_transfer_buffer = buffer;
+ /* Send start condition. */
+ TWCR |= _BV (TWSTA) | _BV (TWINT);
+}
+
+uint8_t
+twi_master_status (void)
+{
+ return ctx.master_current_status;
+}
+
+uint8_t
+twi_master_wait (void)
+{
+ while (ctx.master_current_status == TWI_MASTER_BUSY)
+ ;
+ return ctx.master_current_status;
+}
+
+# endif /* AC_TWI_MASTER_ENABLE */
+
+SIGNAL (SIG_2WIRE_SERIAL)
+{
+# if AC_TWI_SLAVE_ENABLE
+ /** Slave work buffer. */
+ static uint8_t slave_buffer[UTILS_MAX (AC_TWI_SLAVE_RECV_BUFFER_SIZE,
+ AC_TWI_SLAVE_SEND_BUFFER_SIZE)];
+ /** Slave work buffer size for sending (latched). */
+ static uint8_t slave_buffer_size;
+# endif /* AC_TWI_SLAVE_ENABLE */
+ /** Index in work buffer or master buffer. */
+ static uint8_t index;
+ /* Handle hardware current state. */
+ switch (TW_STATUS)
+ {
+# if AC_TWI_SLAVE_ENABLE
+ /*** Slave transmitter mode. ***/
+ case TW_ST_SLA_ACK:
+ case TW_ST_ARB_LOST_SLA_ACK:
+ /* START + SLA|R + ACK
+ * Start condition for reading detected and acknowledged.
+ * Copy user buffer and send first byte. */
+ slave_buffer_size = ctx.slave_send_buffer_size;
+ memcpy (slave_buffer, ctx.slave_send_buffer, slave_buffer_size);
+ index = 0;
+ /* no break; */
+ case TW_ST_DATA_ACK:
+ /* Previous byte was acknowledged, send next. */
+ TWDR = slave_buffer[index++];
+ if (index == slave_buffer_size)
+ TWCR &= ~_BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_ST_DATA_NACK:
+ case TW_ST_LAST_DATA:
+ /* Previous byte was not acknowledged
+ * or previous byte was last byte.
+ * Ready for next transfer. */
+ TWCR |= _BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ /*** Slave receiver mode. ***/
+ case TW_SR_SLA_ACK:
+ case TW_SR_ARB_LOST_SLA_ACK:
+ case TW_SR_GCALL_ACK:
+ case TW_SR_ARB_LOST_GCALL_ACK:
+ /* START + SLA|W + ACK
+ * Start condition for writing detected and acknowledged.
+ * Receive first byte. */
+ index = 0;
+ if (AC_TWI_SLAVE_RECV_BUFFER_SIZE == 1)
+ TWCR &= ~_BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_SR_DATA_ACK:
+ case TW_SR_GCALL_DATA_ACK:
+ /* DATA + ACK
+ * Data received and acknowledged, receive next byte. */
+ slave_buffer[index++] = TWDR;
+ if (index == AC_TWI_SLAVE_RECV_BUFFER_SIZE - 1)
+ TWCR &= ~_BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_SR_DATA_NACK:
+ case TW_SR_GCALL_DATA_NACK:
+ /* DATA + NACK
+ * Data received, not acknowledged, stop transfer. */
+ slave_buffer[index++] = TWDR;
+ /* no break; */
+ case TW_SR_STOP:
+ /* STOP
+ * Stop transfer. */
+ TWCR |= _BV (TWINT);
+ /* Call reception callback. */
+ AC_TWI_SLAVE_RECV (slave_buffer, index);
+ break;
+# endif /* AC_TWI_SLAVE_ENABLE */
+# if AC_TWI_MASTER_ENABLE
+ /*** Master mode. ***/
+ case TW_START:
+ case TW_REP_START:
+ /* Start condition transmitted, send address. */
+ TWCR &= ~ (_BV (TWSTA) | _BV (TWSTO) | _BV (TWINT));
+ TWDR = ctx.master_transfer_address;
+ index = 0;
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_MT_ARB_LOST:
+ /* Arbitration lost, same as TW_MR_ARB_LOST. */
+ /* TODO */
+ break;
+ /*** Master transmitter mode. ***/
+ case TW_MT_DATA_ACK:
+ case TW_MT_SLA_ACK:
+ /* Address or data acknowledged, send more data or stop. */
+ if (index < ctx.master_transfer_buffer_size)
+ {
+ TWDR = ctx.master_transfer_buffer[index++];
+ TWCR |= _BV (TWINT);
+ }
+ else
+ {
+ TWCR |= _BV (TWSTO);
+ ctx.master_current_status = index;
+ TWCR |= _BV (TWINT);
+ /* Call master done callback. */
+ TWI_MASTER_DONE ();
+ }
+ break;
+ case TW_MT_SLA_NACK:
+ /* Address not acknowledged, stop. */
+ TWCR |= _BV (TWSTO);
+ ctx.master_current_status = TWI_MASTER_ERROR;
+ TWCR |= _BV (TWINT);
+ /* Call master done callback. */
+ TWI_MASTER_DONE ();
+ break;
+ case TW_MT_DATA_NACK:
+ /* Data not acknowledged, there is no more room in slave device,
+ * stop. */
+ TWCR |= _BV (TWSTO);
+ ctx.master_current_status = index;
+ TWCR |= _BV (TWINT);
+ /* Call master done callback. */
+ TWI_MASTER_DONE ();
+ break;
+ /*** Master receiver mode. ***/
+ case TW_MR_SLA_ACK:
+ /* Address acknowledged, receive first data. */
+ if (ctx.master_transfer_buffer_size > 1)
+ TWCR |= _BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_MR_SLA_NACK:
+ /* Address not acknowledged, stop. */
+ TWCR |= _BV (TWSTO);
+ ctx.master_current_status = TWI_MASTER_ERROR;
+ TWCR |= _BV (TWINT);
+ /* Call master done callback. */
+ TWI_MASTER_DONE ();
+ break;
+ case TW_MR_DATA_ACK:
+ /* Data acknowledged, receive next data. */
+ ctx.master_transfer_buffer[index++] = TWDR;
+ if (index == ctx.master_transfer_buffer_size - 1)
+ TWCR &= ~ _BV (TWEA);
+ TWCR |= _BV (TWINT);
+ break;
+ case TW_MR_DATA_NACK:
+ /* Data not acknowledged, last byte, stop transfer. */
+ ctx.master_transfer_buffer[index++] = TWDR;
+ ctx.master_current_status = index;
+ TWCR |= _BV (TWSTO);
+ TWCR |= _BV (TWINT);
+ /* Call master done callback. */
+ TWI_MASTER_DONE ();
+ break;
+# endif/* AC_TWI_MASTER_ENABLE */
+ }
+}
+
+#endif /* TWI_DRIVER == TWI_DRIVER_HARD */
diff --git a/digital/io/src/avrconfig.h b/digital/io/src/avrconfig.h
index a9be1f29..dd3f2e87 100644
--- a/digital/io/src/avrconfig.h
+++ b/digital/io/src/avrconfig.h
@@ -84,10 +84,22 @@
#define AC_PROTO_QUOTE 1
/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 1
-/** Activate slave part. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
#define AC_TWI_SLAVE_ENABLE 0
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 1
+/** Master transfer completion callback, optionally defined by the user, called
+ * at end of master transfer. */
+#undef AC_TWI_MASTER_DONE
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+
/* path - Path finding module. */
/** Report path found for debug. */
diff --git a/digital/io/src/twi_master.c b/digital/io/src/twi_master.c
index 194e0fa4..cb600da8 100644
--- a/digital/io/src/twi_master.c
+++ b/digital/io/src/twi_master.c
@@ -111,10 +111,9 @@ twi_master_send_head (void)
struct twi_master_command_t *c =
&twi_master.pending[twi_master.pending_head];
/* Send command. */
- twi_ms_send (twi_master_slaves[c->slave].address, c->command,
- c->length + 1);
- while (!twi_ms_is_finished ())
- ;
+ twi_master_send (twi_master_slaves[c->slave].address, c->command,
+ c->length + 1);
+ twi_master_wait ();
/* Reset retransmission counter. */
twi_master.retransmit_counter = TWI_MASTER_RETRANSMIT_INTERVAL;
}
@@ -126,10 +125,11 @@ twi_master_update_status (uint8_t slave, uint8_t init)
{
uint8_t buffer[TWI_MASTER_STATUS_PAYLOAD_MAX + 1];
/* Read status. */
- twi_ms_read (twi_master_slaves[slave].address, buffer,
- twi_master_slaves[slave].status_length + 1);
- while (!twi_ms_is_finished ())
- ;
+ twi_master_recv (twi_master_slaves[slave].address, buffer,
+ twi_master_slaves[slave].status_length + 1);
+ uint8_t ret = twi_master_wait ();
+ if (ret != twi_master_slaves[slave].status_length + 1)
+ return 0;
uint8_t crc = crc_compute (buffer + 1,
twi_master_slaves[slave].status_length);
if (crc != buffer[0])
diff --git a/digital/mimot/src/dirty/avrconfig.h b/digital/mimot/src/dirty/avrconfig.h
index c7cc73f3..ca181554 100644
--- a/digital/mimot/src/dirty/avrconfig.h
+++ b/digital/mimot/src/dirty/avrconfig.h
@@ -92,13 +92,27 @@
#define AC_ASSERV_TWI_ADDRESS 6
/* twi - TWI module. */
-/** Activate master part. */
-#define AC_TWI_MASTER_ENABLE 0
-/** Activate slave part. */
+/** Driver to implement TWI: HARD, SOFT, or USI. */
+#define AC_TWI_DRIVER HARD
+/** Do not use interrupts. */
+#define AC_TWI_NO_INTERRUPT 0
+/** TWI frequency, should really be 100 kHz. */
+#define AC_TWI_FREQ 100000
+/** Enable slave part. */
#define AC_TWI_SLAVE_ENABLE 1
-/** Slave recv buffer size. */
-#define AC_TWI_SL_RECV_BUFFER_SIZE 16
-/** Slave send buffer size. */
-#define AC_TWI_SL_SEND_BUFFER_SIZE 16
+/** Enable master part. */
+#define AC_TWI_MASTER_ENABLE 0
+/** Use polled slave mode: received data is stored in a buffer which can be
+ * polled using twi_slave_poll. */
+#define AC_TWI_SLAVE_POLLED 1
+/** Slave reception callback to be defined by the user when not in polled
+ * mode. */
+#undef AC_TWI_SLAVE_RECV
+/** Use internal pull up. */
+#define AC_TWI_PULL_UP 0
+/** Slave reception buffer size. */
+#define AC_TWI_SLAVE_RECV_BUFFER_SIZE 16
+/** Slave transmission buffer size. */
+#define AC_TWI_SLAVE_SEND_BUFFER_SIZE 16
#endif /* avrconfig_h */
diff --git a/digital/mimot/src/dirty/twi_proto.c b/digital/mimot/src/dirty/twi_proto.c
index a6894109..3048c594 100644
--- a/digital/mimot/src/dirty/twi_proto.c
+++ b/digital/mimot/src/dirty/twi_proto.c
@@ -67,10 +67,10 @@ twi_proto_init (void)
void
twi_proto_update (void)
{
- u8 buf[AC_TWI_SL_RECV_BUFFER_SIZE];
+ u8 buf[AC_TWI_SLAVE_RECV_BUFFER_SIZE];
u8 read_data;
/* Handle incoming command. */
- while ((read_data = twi_sl_poll (buf, sizeof (buf))))
+ while ((read_data = twi_slave_poll (buf, sizeof (buf))))
twi_proto_callback (buf, read_data);
/* Update status. */
u8 status_with_crc[8];
@@ -89,7 +89,7 @@ twi_proto_update (void)
/* Compute CRC. */
status_with_crc[0] = crc_compute (&status_with_crc[1],
sizeof (status_with_crc) - 1);
- twi_sl_update (status_with_crc, sizeof (status_with_crc));
+ twi_slave_update (status_with_crc, sizeof (status_with_crc));
}
/** Handle one command. */