Commit dc427b7efc7905fb825722a67bd2a480615dd3b6
authorMichel Pollet <buserror@gmail.com>
Thu, 24 Feb 2011 18:02:35 +0000 (18:02 +0000)
committerMichel Pollet <buserror@gmail.com>
Thu, 24 Feb 2011 18:02:35 +0000 (18:02 +0000)
Yanked the old overengineered version, replaced it with a KISS
version. Untested, work in progress. Needs a new testing harness

Signed-off-by: Michel Pollet <buserror@gmail.com>
4 files changed:
simavr/sim/avr_twi.c
simavr/sim/avr_twi.h
simavr/sim/sim_twi.c [deleted file]
simavr/sim/sim_twi.h [deleted file]

index 589e18e54e1f057cf358ad14911a8036e0edfaac..c60501179f4c826123991eab4fa0286a8204e98a 100644 (file)
 #include <stdio.h>
 #include "avr_twi.h"
 
-static uint8_t avr_twi_read(struct avr_t * avr, avr_io_addr_t addr, void * param)
+/*
+ * This block respectfully nicked straight out from the Atmel sample
+ * code for AVR315. Typos and all.
+ * There is no copyright notice on the original file.
+ */
+/****************************************************************************
+  TWI State codes
+****************************************************************************/
+// General TWI Master staus codes
+#define TWI_START                  0x08  // START has been transmitted
+#define TWI_REP_START              0x10  // Repeated START has been transmitted
+#define TWI_ARB_LOST               0x38  // Arbitration lost
+
+// TWI Master Transmitter staus codes
+#define TWI_MTX_ADR_ACK            0x18  // SLA+W has been tramsmitted and ACK received
+#define TWI_MTX_ADR_NACK           0x20  // SLA+W has been tramsmitted and NACK received
+#define TWI_MTX_DATA_ACK           0x28  // Data byte has been tramsmitted and ACK received
+#define TWI_MTX_DATA_NACK          0x30  // Data byte has been tramsmitted and NACK received
+
+// TWI Master Receiver staus codes
+#define TWI_MRX_ADR_ACK            0x40  // SLA+R has been tramsmitted and ACK received
+#define TWI_MRX_ADR_NACK           0x48  // SLA+R has been tramsmitted and NACK received
+#define TWI_MRX_DATA_ACK           0x50  // Data byte has been received and ACK tramsmitted
+#define TWI_MRX_DATA_NACK          0x58  // Data byte has been received and NACK tramsmitted
+
+// TWI Slave Transmitter staus codes
+#define TWI_STX_ADR_ACK            0xA8  // Own SLA+R has been received; ACK has been returned
+#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0  // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
+#define TWI_STX_DATA_ACK           0xB8  // Data byte in TWDR has been transmitted; ACK has been received
+#define TWI_STX_DATA_NACK          0xC0  // Data byte in TWDR has been transmitted; NOT ACK has been received
+#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8  // Last data byte in TWDR has been transmitted (TWEA = �0�); ACK has been received
+
+// TWI Slave Receiver staus codes
+#define TWI_SRX_ADR_ACK            0x60  // Own SLA+W has been received ACK has been returned
+#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68  // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
+#define TWI_SRX_GEN_ACK            0x70  // General call address has been received; ACK has been returned
+#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78  // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
+#define TWI_SRX_ADR_DATA_ACK       0x80  // Previously addressed with own SLA+W; data has been received; ACK has been returned
+#define TWI_SRX_ADR_DATA_NACK      0x88  // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
+#define TWI_SRX_GEN_DATA_ACK       0x90  // Previously addressed with general call; data has been received; ACK has been returned
+#define TWI_SRX_GEN_DATA_NACK      0x98  // Previously addressed with general call; data has been received; NOT ACK has been returned
+#define TWI_SRX_STOP_RESTART       0xA0  // A STOP condition or repeated START condition has been received while still addressed as Slave
+
+// TWI Miscellaneous status codes
+#define TWI_NO_STATE               0xF8  // No relevant state information available; TWINT = �0�
+#define TWI_BUS_ERROR              0x00  // Bus error due to an illegal START or STOP condition
+
+
+static inline void
+_avr_twi_status_set(
+               avr_twi_t * p,
+               uint8_t v,
+               int interrupt)
 {
-//     avr_twi_t * p = (avr_twi_t *)param;
-//     uint8_t v = p->input_data_register;
-//     p->input_data_register = 0;
-//     printf("avr_twi_read = %02x\n", v);
-       return 0;
+       avr_regbit_setto_raw(p->io.avr, p->twsr, v);
+       avr_raise_irq(p->io.irq + TWI_IRQ_STATUS, v);
+       if (interrupt)
+               avr_raise_interrupt(p->io.avr, &p->twi);
 }
 
-static void avr_twi_write(struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param)
+static inline uint8_t
+_avr_twi_status_get(
+               avr_twi_t * p)
+{
+       return avr_regbit_get_raw(p->io.avr, p->twsr);
+}
+
+static avr_cycle_count_t
+avr_twi_set_state_timer(
+               struct avr_t * avr,
+               avr_cycle_count_t when,
+               void * param)
 {
-#if 0
        avr_twi_t * p = (avr_twi_t *)param;
-       if (addr == p->r_spdr) {
-//             printf("avr_twi_write = %02x\n", v);
-               avr_core_watch_write(avr, addr, v);
-
-               if (avr_regbit_get(avr, p->spe)) {
-                       // in master mode, any byte is sent as it comes..
-                       if (avr_regbit_get(avr, p->mstr)) {
-                               avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, v);
-                       }
-               }
-       }
-#endif
+       _avr_twi_status_set(p, p->next_twstate, 1);
+       p->next_twstate = 0;
+       return 0;
 }
 
-#if 0
-static void avr_twi_irq_input(struct avr_irq_t * irq, uint32_t value, void * param)
+static void
+_avr_twi_delay_state(
+               avr_twi_t * p,
+               int twi_cycles,
+               uint8_t state)
+{
+       p->next_twstate = state;
+       // TODO: calculate clock rate, convert to cycles, and use that
+       avr_cycle_timer_register_usec(
+                       p->io.avr, twi_cycles, avr_twi_set_state_timer, p);
+}
+
+static void
+avr_twi_write(
+               struct avr_t * avr,
+               avr_io_addr_t addr,
+               uint8_t v,
+               void * param)
 {
        avr_twi_t * p = (avr_twi_t *)param;
-       avr_t * avr = p->io.avr;
 
-       // check to see if we are enabled
-       if (!avr_regbit_get(avr, p->twen))
+       uint8_t twen = avr_regbit_get(avr, p->twen);
+       uint8_t twsta = avr_regbit_get(avr, p->twsta);
+       uint8_t twsto = avr_regbit_get(avr, p->twsto);
+       uint8_t twint = avr_regbit_get(avr, p->twi.raised);
+
+       avr_core_watch_write(avr, addr, v);
+
+       if (twen != avr_regbit_get(avr, p->twen)) {
+               twen = !twen;
+               if (!twen) { // if we were running, now now are not
+                       avr_regbit_clear(avr, p->twea);
+                       avr_regbit_clear(avr, p->twsta);
+                       avr_regbit_clear(avr, p->twsto);
+                       avr_clear_interrupt(avr, p->twi.vector);
+                       avr_core_watch_write(avr, p->r_twdr, 0xff);
+                       _avr_twi_status_set(p, TWI_NO_STATE, 0);
+                       p->state = 0;
+                       p->peer_addr = 0;
+               }
+       }
+       if (!twen)
                return;
-#if 0
-       // double buffer the input.. ?
-       p->input_data_register = value;
-       avr_raise_interrupt(avr, &p->twi);
-
-       // if in slave mode, 
-       // 'output' the byte only when we received one...
-       if (!avr_regbit_get(avr, p->mstr)) {
-               avr_raise_irq(p->io.irq + TWI_IRQ_OUTPUT, avr->data[p->r_spdr]);
+
+       int cleared = avr_clear_interupt_if(avr, &p->twi, twint);
+
+       // clear the interrupt if this bit is now written to 1
+       if (cleared) {
+               // interrupt was raised before. The AVR code is acknowledging
+               // something we did, so we go to the next state
+       } else {
+               // interrupt was not raised, were we busy ? we can ignore that
+               // for now...
        }
-#endif
-}
 
-       // handle a data write, after a (re)start
-static int twi_slave_write(struct twi_slave_t* p, uint8_t v)
-{
-       return 0;
+       if (!twsto && avr_regbit_get(avr, p->twsto)) {
+               // generate a stop condition
+
+               if (p->state) { // doing stuff
+                       if (p->state & TWI_COND_START) {
+                               avr_twi_msg_irq_t msg = {
+                                               .u.twi.msg = TWI_COND_STOP,
+                                               .u.twi.addr = p->peer_addr,
+                               };
+                               avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, msg.u.v);
+                       }
+               }
+               p->state = 0;
+       }
+       if (!twsta && avr_regbit_get(avr, p->twsta)) {
+               // generate a start condition
+               if (p->state & TWI_COND_START)
+                       _avr_twi_delay_state(p, 3, TWI_REP_START);
+               else
+                       _avr_twi_delay_state(p, 3, TWI_START);
+               p->state |= TWI_COND_START;
+       }
+
+       if (cleared &&
+                       !avr_regbit_get(avr, p->twsta) &&
+                       !avr_regbit_get(avr, p->twsto)) {
+               // writing or reading a byte
+               if (p->state & TWI_COND_ADDR) {
+                       // a normal data byte
+                       uint8_t msgv = p->peer_addr & 1 ? TWI_COND_READ : TWI_COND_WRITE;
+                       if (avr_regbit_get(avr, p->twea))
+                               msgv |= TWI_COND_ACK;
+                       avr_twi_msg_irq_t msg = {
+                                       .u.twi.msg = msgv,
+                                       .u.twi.addr = p->peer_addr,
+                                       .u.twi.data = avr->data[p->r_twdr],
+                       };
+                       // we send an IRQ and we /expect/ a slave to reply
+                       // immediately via an IRQ to set the COND_ACK bit
+                       // otherwise it's assumed it's been nacked...
+                       avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, msg.u.v);
+
+                       if (p->peer_addr & 1) { // read ?
+                               _avr_twi_delay_state(p, 9,
+                                               p->state & TWI_COND_ACK ?
+                                                               TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK);
+                       } else {
+                               _avr_twi_delay_state(p, 9,
+                                               p->state & TWI_COND_ACK ?
+                                                               TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK);
+                       }
+
+               } else {
+                       // send the address
+                       p->state |= TWI_COND_ADDR;
+                       p->peer_addr = avr->data[p->r_twdr];
+                       avr_twi_msg_irq_t msg = {
+                                       .u.twi.msg = TWI_COND_START,
+                                       .u.twi.addr = p->peer_addr,
+                       };
+                       // we send an IRQ and we /expect/ a slave to reply
+                       // immediately via an IRQ tp set the COND_ACK bit
+                       // otherwise it's assumed it's been nacked...
+                       avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, msg.u.v);
+
+                       if (p->peer_addr & 1) { // read ?
+                               _avr_twi_delay_state(p, 9,
+                                               p->state & TWI_COND_ACK ?
+                                                               TWI_MRX_ADR_ACK : TWI_MRX_ADR_NACK);
+                       } else {
+                               _avr_twi_delay_state(p, 9,
+                                               p->state & TWI_COND_ACK ?
+                                                               TWI_MTX_ADR_ACK : TWI_MTX_ADR_NACK);
+                       }
+               }
+       }
 }
 
-       // handle a data read, after a (re)start
-static uint8_t twi_slave_read(struct twi_slave_t* p)
+/*
+ * prevent code from rewriting out status bits, since we actualy use them!
+ */
+static void
+avr_twi_write_status(
+               struct avr_t * avr,
+               avr_io_addr_t addr,
+               uint8_t v,
+               void * param)
 {
-       return 0;
+       avr_twi_t * p = (avr_twi_t *)param;
+       uint8_t sr = avr_regbit_get(avr, p->twsr);
+       uint8_t c = avr_regbit_get(avr, p->twps);
+
+       avr_core_watch_write(avr, addr, v);
+       avr_regbit_setto(avr, p->twsr, sr);     // force restore
+
+       if (c != avr_regbit_get(avr, p->twps)) {
+               // prescaler bits changed...
+       }
 }
-#endif
 
-static int avr_twi_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
+static void
+avr_twi_irq_input(
+               struct avr_irq_t * irq,
+               uint32_t value,
+               void * param)
 {
-       avr_twi_t * p = (avr_twi_t *)port;
-       int res = -1;
+       avr_twi_t * p = (avr_twi_t *)param;
+       avr_t * avr = p->io.avr;
 
-       if (ctl == AVR_IOCTL_TWI_GETSLAVE(p->name)) {
-               *(twi_slave_t**)io_param = &p->slave;
-       } else if (ctl == AVR_IOCTL_TWI_GETBUS(p->name)) {
-               *(twi_bus_t**)io_param = &p->bus;
+       // check to see if we are enabled
+       if (!avr_regbit_get(avr, p->twen))
+               return;
+       switch (irq->irq) {
+               case TWI_IRQ_MISO:
+                       break;
+               case TWI_IRQ_MOSI:
+                       break;
        }
-
-       return res;
 }
 
 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_INPUT, avr_twi_irq_input, p);
+       avr_twi_t * p = (avr_twi_t *)io;
+       avr_irq_register_notify(p->io.irq + TWI_IRQ_MISO, avr_twi_irq_input, p);
 }
 
 static avr_io_t        _io = {
        .kind = "twi",
        .reset = avr_twi_reset,
-       .ioctl = avr_twi_ioctl,
 };
 
 void avr_twi_init(avr_t * avr, avr_twi_t * p)
@@ -115,16 +292,13 @@ void avr_twi_init(avr_t * avr, avr_twi_t * p)
        p->io = _io;
        avr_register_io(avr, &p->io);
        avr_register_vector(avr, &p->twi);
-//     p->slave = slave_driver;        // get default callbacks
-       twi_slave_init(&p->slave, 0, p);
-       twi_bus_init(&p->bus);
 
        //printf("%s TWI%c init\n", __FUNCTION__, p->name);
 
        // allocate this module's IRQ
        avr_io_setirqs(&p->io, AVR_IOCTL_TWI_GETIRQ(p->name), TWI_IRQ_COUNT, NULL);
 
-       avr_register_io_write(avr, p->r_twdr, avr_twi_write, p);
-       avr_register_io_read(avr, p->r_twdr, avr_twi_read, p);
+       avr_register_io_write(avr, p->twen.reg, avr_twi_write, p);
+       avr_register_io_write(avr, p->twsr.reg, avr_twi_write_status, p);
 }
 
index 1de1ef4921a3f3f2f2281dfee8703a2e4ba11570..7dfef6447c3ba204a28c85942e22d028317f3f2d 100644 (file)
 
 #include "sim_avr.h"
 
-#include "sim_twi.h"
+//#include "sim_twi.h"
 
 enum {
-       TWI_IRQ_INPUT = 0,
-       TWI_IRQ_OUTPUT,
+       TWI_IRQ_MISO = 0,
+       TWI_IRQ_MOSI,
+       TWI_IRQ_STATUS,
        TWI_IRQ_COUNT
 };
 
+enum {
+       TWI_COND_START = (1 << 0),
+       TWI_COND_STOP = (1 << 1),
+       TWI_COND_ADDR = (1 << 2),
+       TWI_COND_ACK = (1 << 3),
+       TWI_COND_WRITE = (1 << 4),
+       TWI_COND_READ = (1 << 5),
+};
+
+typedef struct avr_twi_msg_t {
+       uint32_t unused : 8,
+               msg : 8,
+               addr : 8,
+               data : 8;
+} avr_twi_msg_t;
+
+typedef struct avr_twi_msg_irq_t {
+       union {
+               uint32_t v;
+               avr_twi_msg_t twi;
+       } u;
+} avr_twi_msg_irq_t;
 
 // add port number to get the real IRQ
 #define AVR_IOCTL_TWI_GETIRQ(_name) AVR_IOCTL_DEF('t','w','i',(_name))
-// return a pointer to the slave structure related to this TWI port
-#define AVR_IOCTL_TWI_GETSLAVE(_name) AVR_IOCTL_DEF('t','w','s',(_name))
-// retutn this twi interface "master" bus
-#define AVR_IOCTL_TWI_GETBUS(_name) AVR_IOCTL_DEF('t','w','b',(_name))
 
 typedef struct avr_twi_t {
        avr_io_t        io;
        char name;
-       
-       twi_slave_t     slave;          // when we are a slave, to be attached to some bus
-       twi_bus_t               bus;            // when we are a master, to attach slaves to
-       
+
        avr_regbit_t    disabled;       // bit in the PRR
 
        avr_io_addr_t   r_twbr;                 // bit rate register
@@ -65,9 +81,16 @@ typedef struct avr_twi_t {
        avr_regbit_t twsr;              // status registers, (5 bits)
        avr_regbit_t twps;              // prescaler bits (2 bits)
        
-       avr_int_vector_t twi;   // spi interrupt
+       avr_int_vector_t twi;   // twi interrupt
+
+       uint8_t state;
+       uint8_t peer_addr;
+       uint8_t next_twstate;
 } avr_twi_t;
 
-void avr_twi_init(avr_t * avr, avr_twi_t * port);
+void
+avr_twi_init(
+               avr_t * avr,
+               avr_twi_t * port);
 
 #endif /* AVR_TWI_H_ */
diff --git a/simavr/sim/sim_twi.c b/simavr/sim/sim_twi.c
deleted file mode 100644 (file)
index 16bfa97..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
-       sim_twi.c
-
-       Internal TWI/i2c slave/master subsystem
-       
-       Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
-
-       This file is part of simavr.
-
-       simavr 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 3 of the License, or
-       (at your option) any later version.
-
-       simavr 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 simavr.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include "sim_twi.h"
-
-static void twi_bus_master_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
-{
-       twi_bus_t * bus = (twi_bus_t *)param;
-       switch (irq->irq) {
-               case TWI_MASTER_STOP:
-                       bus->peer = NULL;
-                       break;
-               case TWI_MASTER_START:
-                       bus->peer = NULL;
-                       bus->ack = 0;
-                       break;
-               case TWI_MASTER_MISO:
-                       bus->ack = 0;
-                       break;
-               case TWI_MASTER_MOSI:
-                       bus->ack = 0;
-                       break;
-               case TWI_MASTER_ACK:
-                       if (!bus->peer) {
-                       }
-                       break;
-       }
-}
-
-static void twi_bus_slave_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
-{
-       twi_slave_t * slave = (twi_slave_t*)param;
-       twi_bus_t * bus = slave->bus;
-       switch (irq->irq) {
-               case TWI_SLAVE_MISO:
-                       bus->latch = value;
-                       break;
-               case TWI_SLAVE_ACK:
-                       if (!bus->peer) {
-                               bus->peer = slave;
-                               printf("twi bus: slave %x selected\n", slave->address);
-                       }
-                       bus->ack = 0x80 | (value & 1);
-                       break;
-       }
-}
-
-static void twi_slave_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
-{
-       twi_slave_t * slave = (twi_slave_t*)param;
-       switch (irq->irq) {
-               case TWI_MASTER_STOP:
-                       if (slave->match) {
-                               // we were target
-                       }
-                       slave->match = 0;
-                       break;
-               case TWI_MASTER_START:
-                       if ((value & 0xfe) == (slave->address & 0xfe)) {
-                               if (slave->match) {
-                                       // restart
-                               }
-                               slave->match = 1;
-                               avr_raise_irq(slave->irq + TWI_SLAVE_ACK, 1);
-                       }
-                       break;
-               case TWI_MASTER_MISO:
-                       break;
-               case TWI_MASTER_MOSI:
-                       break;
-               case TWI_MASTER_ACK:
-                       break;
-       }
-}
-
-void twi_bus_init(twi_bus_t * bus)
-{
-       memset(bus, 0, sizeof(twi_bus_t));
-       //avr_init_irq(bus->irq, 0, TWI_MASTER_STATE_COUNT);
-       for (int i = 0; i < TWI_MASTER_STATE_COUNT; i++)
-               avr_irq_register_notify(bus->irq + i, twi_bus_master_irq_notify, bus);
-}
-
-void twi_bus_attach(twi_bus_t * bus, twi_slave_t * slave)
-{
-       twi_slave_detach(slave);
-       slave->bus = bus;
-       slave->next = bus->slave;
-       bus->slave = slave;
-       
-       for (int i = 0; i < TWI_SLAVE_STATE_COUNT; i++)
-               avr_irq_register_notify(slave->irq + i, twi_bus_slave_irq_notify, slave);
-       for (int i = 0; i < TWI_MASTER_STATE_COUNT; i++)
-               avr_irq_register_notify(bus->irq + i, twi_slave_irq_notify, slave);
-}
-
-int twi_bus_start(twi_bus_t * bus, uint8_t address)
-{
-       avr_raise_irq(bus->irq + TWI_MASTER_START, address);
-       return bus->peer != NULL ? 1 : 0;
-}
-
-void twi_bus_stop(twi_bus_t * bus)
-{
-       avr_raise_irq(bus->irq + TWI_MASTER_STOP, 0);
-}
-
-
-void twi_slave_init(twi_slave_t * slave, uint8_t address, void * param)
-{
-       memset(slave, 0, sizeof(twi_slave_t));
-       slave->address = address;
-//     slave->param = param;
-}
-
-void twi_slave_detach(twi_slave_t * slave)
-{
-       if (!slave || !slave->bus)
-               return;
-       twi_slave_t *s = slave->bus->slave;
-       while (s) {
-               if (s->next == slave) {
-                       // clear that, too
-                       if (slave->bus->peer == slave)
-                               slave->bus->peer = NULL;
-                               
-                       s->next = slave->next;
-                       slave->next = NULL;
-                       slave->bus = NULL;
-                       return;
-               }
-               s = s->next;
-       }
-}
-
diff --git a/simavr/sim/sim_twi.h b/simavr/sim/sim_twi.h
deleted file mode 100644 (file)
index dbb6b96..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
-       sim_twi.h
-
-       Internal TWI/i2c slave/master subsystem
-
-       You can have a "bus" to talk to a bunch of "slaves"
-       
-       Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
-
-       This file is part of simavr.
-
-       simavr 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 3 of the License, or
-       (at your option) any later version.
-
-       simavr 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 simavr.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef SIM_TWI_H_
-#define SIM_TWI_H_
-
-#include <stdint.h>
-#include "sim_irq.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The TWI system is designed to be representing the same state as 
- * a TWI/i2c bus itself. So each "state" of the bus is an IRQ sent
- * by the master to the slave, with a couple sent from the
- * slave to the master.
- * This is designed to decorelate the operations on the "bus" so
- * the firmware has time to "run" before acknowledging a byte, for
- * example.
- * 
- * IRQ Timeline goes as follow  with an example transaction that
- * does write address, write register, read a byte after a i2c restart
- * then stops the transaction.
- * 
- * Master:     START   MOSI    START   MISO    ACK     STOP
- * Slave:              ACK             ACK             ACK             MISO    
- */
-enum twi_state_e {
-       TWI_MASTER_STOP = 0,
-       TWI_MASTER_START,                       // master does a start with address
-       TWI_MASTER_MOSI,                        // master i2c write
-       TWI_MASTER_MISO,                        // master i2c read
-       TWI_MASTER_ACK,                         // master i2c ACK after a i2c read
-       TWI_MASTER_STATE_COUNT,
-
-       TWI_SLAVE_MISO = 0,                     // slave i2c read.
-       TWI_SLAVE_ACK,                          // slave acknowledges TWI_MASTER_MOSI
-       TWI_SLAVE_STATE_COUNT,  
-};
-
-#define TWI_ADDRESS_READ_MASK  0x01
-
-typedef struct twi_slave_t {
-       avr_irq_t               irq[TWI_SLAVE_STATE_COUNT];
-
-       struct twi_bus_t * bus; // bus we are attached to
-       struct twi_slave_t * next;      // daisy chain on the bus
-       
-       uint32_t                address;        // can specify up to 4 matching addresses here
-       int                             match;          // we are selected on the bus
-       int                             index;          // byte index in the transaction
-       
-       uint8_t                 latch;          // last received byte
-} twi_slave_t;
-
-
-typedef struct twi_bus_t {
-       avr_irq_t               irq[TWI_MASTER_STATE_COUNT];
-       
-       struct twi_slave_t * slave;     // daisy chain on the bus
-       struct twi_slave_t * peer;      // during a transaction, this is the selected slave
-
-       uint8_t                 latch;          // last received byte
-       uint8_t                 ack;            // last received ack
-} twi_bus_t;
-
-void twi_bus_init(twi_bus_t * bus);
-int twi_bus_start(twi_bus_t * bus, uint8_t address);
-int twi_bus_write(twi_bus_t * bus, uint8_t data);
-uint8_t twi_bus_read(twi_bus_t * bus);
-void twi_bus_stop(twi_bus_t * bus);
-
-void twi_slave_init(twi_slave_t * slave, uint8_t address, void * param);
-void twi_slave_detach(twi_slave_t * slave);
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif /*  SIM_TWI_H_ */