summaryrefslogtreecommitdiff
path: root/n/avr/modules/twi/slave/twi_slave.c
diff options
context:
space:
mode:
Diffstat (limited to 'n/avr/modules/twi/slave/twi_slave.c')
-rw-r--r--n/avr/modules/twi/slave/twi_slave.c151
1 files changed, 151 insertions, 0 deletions
diff --git a/n/avr/modules/twi/slave/twi_slave.c b/n/avr/modules/twi/slave/twi_slave.c
new file mode 100644
index 0000000..58e777e
--- /dev/null
+++ b/n/avr/modules/twi/slave/twi_slave.c
@@ -0,0 +1,151 @@
+/* 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 "twi_slave.h"
+
+#include "io.h"
+
+#include <compat/twi.h>
+
+static volatile uint8_t twi_rcpt_tail;
+static volatile uint8_t send_idx;
+static volatile uint8_t data_ready;
+static volatile uint8_t buf_rcpt[AC_TWI_SLAVE_RCPT_BUF_SIZE];
+static volatile uint8_t buf_send1[AC_TWI_SLAVE_SEND_BUF_SIZE];
+static volatile uint8_t buf_send2[AC_TWI_SLAVE_SEND_BUF_SIZE];
+static volatile uint8_t *buf_send_sys, *buf_send_user;
+static volatile int8_t send_switch;
+static volatile int8_t update;
+
+#if 0
+#define TWI_DEBUG(x) uart0_putc (x)
+#else
+#define TWI_DEBUG(x)
+#endif
+
+void
+twi_init (uint8_t addr)
+{
+ send_switch = 0;
+ update = 0;
+ buf_send_sys = buf_send1;
+ buf_send_user = buf_send2;
+ TWAR = addr;
+ TWSR = 0x00;
+ TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWIE);
+}
+
+
+SIGNAL (SIG_2WIRE_SERIAL)
+{
+ TWI_DEBUG (';');
+ switch (TW_STATUS)
+ {
+ /* slave transmitter mode */
+ /* START + SLA|W + ACK */
+ case TW_ST_SLA_ACK:
+ case TW_ST_ARB_LOST_SLA_ACK:
+ TWI_DEBUG ('a');
+ if (send_switch && !update)
+ {
+ volatile uint8_t *tmp = buf_send_sys;
+ buf_send_sys = buf_send_user;
+ buf_send_user = tmp;
+ send_switch = 0;
+ }
+ send_idx = 0;
+ /* no break */
+ case TW_ST_DATA_ACK:
+ TWI_DEBUG ('b');
+ TWDR = buf_send_sys[send_idx++];
+ if (AC_TWI_SLAVE_SEND_BUF_SIZE == send_idx)
+ TWCR &= ~_BV(TWEA);
+ break;
+ case TW_ST_DATA_NACK:
+ case TW_ST_LAST_DATA:
+ TWI_DEBUG ('c');
+ TWCR |= _BV (TWEA);
+ 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:
+ TWI_DEBUG ('z');
+ data_ready = 0;
+ twi_rcpt_tail = 0;
+ if (AC_TWI_SLAVE_RCPT_BUF_SIZE == 1)
+ TWCR &= ~_BV(TWEA);
+ break;
+ /* DATA + ACK */
+ case TW_SR_DATA_ACK:
+ case TW_SR_GCALL_DATA_ACK:
+ TWI_DEBUG ('y');
+ buf_rcpt[twi_rcpt_tail++] = TWDR;
+ if (AC_TWI_SLAVE_RCPT_BUF_SIZE - twi_rcpt_tail == 1)
+ TWCR &= ~_BV(TWEA);
+ break;
+ /* DATA + NACK */
+ case TW_SR_DATA_NACK:
+ case TW_SR_GCALL_DATA_NACK:
+ TWI_DEBUG ('x');
+ buf_rcpt[twi_rcpt_tail++] = TWDR;
+ /* no break */
+ /* STOP */
+ case TW_SR_STOP:
+ TWI_DEBUG ('w');
+ data_ready = 1;
+ break;
+ }
+ TWCR |= _BV(TWINT);
+}
+
+/** Recopie les données recues dans buf. */
+uint8_t
+twi_poll (uint8_t buf[], uint8_t size)
+{
+ if (data_ready)
+ {
+ data_ready = 0;
+ while (size --)
+ buf[size] = buf_rcpt[size];
+ TWCR |= _BV (TWEA);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+void
+twi_update (uint8_t buf[], uint8_t size)
+{
+ update = 1;
+ send_switch = 1;
+ while (size --)
+ buf_send_user[size] = buf[size];
+ update = 0;
+}
+