Commit 96bd0bcb4872ffebf2756cb321428a62873656e5
authorMichel Pollet <buserror@gmail.com>
Tue, 2 Jul 2013 09:24:45 +0000 (10:24 +0100)
committerMichel Pollet <buserror@gmail.com>
Thu, 5 Sep 2013 12:58:31 +0000 (13:58 +0100)
Need the slave support for TWI, will add bits as I go along

Signed-off-by: Michel Pollet <buserror@gmail.com>
2 files changed:
simavr/sim/avr_twi.c
simavr/sim/avr_twi.h

index 782eef49e9fb16aefbcf009870403f25f16188c1..592e7b1d975aea97afdb800dd59ae7d10f295007 100644 (file)
@@ -159,6 +159,9 @@ avr_twi_write(
                        p->peer_addr = 0;
                }
                printf("TWEN: %d\n", twen);
+               if (avr->data[p->r_twar]) {
+                       printf("TWEN Slave: %02x & %02x\n", avr->data[p->r_twar], avr->data[p->r_twamr]);
+               }
        }
        if (!twen)
                return;
@@ -338,6 +341,34 @@ avr_twi_irq_input(
        avr_twi_msg_irq_t msg;
        msg.u.v = value;
 
+       // receiving an attempt at waking a slave
+       if (msg.u.twi.msg & TWI_COND_START) {
+               p->state = 0;
+               p->peer_addr = 0;
+               if (msg.u.twi.msg & TWI_COND_ADDR) {
+                       uint8_t mask = ~avr->data[p->r_twamr] >> 1;
+                       printf("I2C slave start %2x (want %02x&%02x)\n",
+                               msg.u.twi.addr, avr->data[p->r_twar] >> 1, mask);
+                       p->peer_addr = msg.u.twi.addr & mask;
+                       if (p->peer_addr == ((avr->data[p->r_twar] >> 1) & mask)) {
+                               // address match, we're talking
+                               p->state = TWI_COND_ADDR | TWI_COND_SLAVE;
+                               _avr_twi_delay_state(p, 9, 
+                                       msg.u.twi.msg & TWI_COND_WRITE ?
+                                               TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK );
+                       }
+               } else {
+                       // "general call" address
+                       printf("I2C slave start without address?\n");
+                       if (avr->data[p->r_twar] & 1) {
+                       }
+               }
+       }
+       if (msg.u.twi.msg & TWI_COND_STOP) {
+               _avr_twi_delay_state(p, 9, 
+                       msg.u.twi.msg & TWI_COND_WRITE ?
+                               TWI_SRX_ADR_ACK : TWI_STX_ADR_ACK );
+       }
        // receiving an acknowledge bit
        if (msg.u.twi.msg & TWI_COND_ACK) {
 #if AVR_TWI_DEBUG
@@ -361,6 +392,7 @@ void avr_twi_reset(struct avr_io_t *io)
 {
        avr_twi_t * p = (avr_twi_t *)io;
        avr_irq_register_notify(p->io.irq + TWI_IRQ_MISO, avr_twi_irq_input, p);
+       p->state = p->peer_addr = 0;
 }
 
 static const char * irq_names[TWI_IRQ_COUNT] = {
index 70911a28b65f729edd014d9dafc0f5f46fae1767..a1396e220677e844ca2f098706e656e7ca42b23f 100644 (file)
@@ -44,6 +44,8 @@ enum {
        TWI_COND_ACK = (1 << 3),
        TWI_COND_WRITE = (1 << 4),
        TWI_COND_READ = (1 << 5),
+       // internal state, do not use in irq messages
+       TWI_COND_SLAVE  = (1 << 6),
 };
 
 typedef struct avr_twi_msg_t {