TWI: Work in progress
authorMichel Pollet <buserror@gmail.com>
Thu, 25 Feb 2010 22:12:36 +0000 (22:12 +0000)
committerMichel Pollet <buserror@gmail.com>
Thu, 25 Feb 2010 22:12:36 +0000 (22:12 +0000)
Changed to look more like qemu

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

index 0f7e648..6ebe7bb 100644 (file)
@@ -70,14 +70,16 @@ static void avr_twi_irq_input(struct avr_irq_t * irq, uint32_t value, void * par
 #endif
 }
 
-static int twi_slave_has_address(struct twi_slave_t* p, uint8_t address)
-{
-       return 0;
-}
-
-       // handle start conditionto address+w, restart means "stop" wasn't called
-static int twi_slave_start(struct twi_slave_t* p, uint8_t address, int restart)
+static int twi_slave_event(struct twi_slave_t* p, uint8_t address, enum twi_event event)
 {
+       switch (event) {
+               case TWI_START:
+                       break;
+               case TWI_STOP:
+                       break;
+               case TWI_PROBE:
+                       break;
+       }
        return 0;
 }
 
@@ -93,19 +95,26 @@ static uint8_t twi_slave_read(struct twi_slave_t* p)
        return 0;
 }
 
-       // stop condition detected
-static void twi_slave_stop(struct twi_slave_t* p)
-{
-}
-
 static twi_slave_t slave_driver = {
-       .has_address = twi_slave_has_address,
-       .start = twi_slave_start,
-       .stop = twi_slave_stop,
+       .event = twi_slave_event,
        .write = twi_slave_write,
        .read = twi_slave_read
 };
 
+static int avr_twi_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
+{
+       avr_twi_t * p = (avr_twi_t *)port;
+       int res = -1;
+
+       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;
+       }
+
+       return res;
+}
+
 void avr_twi_reset(struct avr_io_t *io)
 {
        avr_twi_t * p = (avr_twi_t *)io;
@@ -115,6 +124,7 @@ void avr_twi_reset(struct avr_io_t *io)
 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)
@@ -123,7 +133,7 @@ void avr_twi_init(avr_t * avr, avr_twi_t * p)
        avr_register_io(avr, &p->io);
        avr_register_vector(avr, &p->twi);
        p->slave = slave_driver;        // get default callbacks
-       twi_slave_init(&p->slave, p);
+       twi_slave_init(&p->slave, 0, p);
        twi_bus_init(&p->bus);
 
        //printf("%s TWI%c init\n", __FUNCTION__, p->name);
index 31c3ca5..1de1ef4 100644 (file)
@@ -57,7 +57,7 @@ typedef struct avr_twi_t {
        avr_io_addr_t   r_twdr;                 // data register
        
        avr_regbit_t twen;              // twi enable bit
-       avr_regbit_t twea;              // enabke acknowledge bit
+       avr_regbit_t twea;              // enable acknowledge bit
        avr_regbit_t twsta;             // start condition
        avr_regbit_t twsto;             // stop condition
        avr_regbit_t twwc;              // write collision
index 9d6501e..b5c19fb 100644 (file)
  */
 
 #include <stdlib.h>
+#include <string.h>
 #include "sim_twi.h"
 
 void twi_bus_init(twi_bus_t * bus)
 {
+       memset(bus, 0, sizeof(twi_bus_t));
 }
 
 void twi_bus_attach(twi_bus_t * bus, twi_slave_t * slave)
@@ -40,14 +42,17 @@ int twi_bus_start(twi_bus_t * bus, uint8_t address)
 {
        // if we already have a peer, check to see if it's 
        // still matching, if so, skip the lookup
-       if (bus->peer && twi_slave_match(bus->peer, address))
-               return bus->peer->start(bus->peer, address, 1);
+       if (bus->peer) {
+               if (twi_slave_match(bus->peer, address))
+                       return bus->peer->event(bus->peer, address, TWI_START);
+               twi_bus_stop(bus);
+       }
                
        bus->peer = NULL;
        twi_slave_t *s = bus->slave;
        while (s) {
                if (twi_slave_match(s, address)) {
-                       if (s->start(s, address, 0)) {
+                       if (s->event(s, address, TWI_START)) {
                                bus->peer = s;
                                s->byte_index = 0;
                                return 1;
@@ -60,8 +65,10 @@ int twi_bus_start(twi_bus_t * bus, uint8_t address)
 
 void twi_bus_stop(twi_bus_t * bus)
 {
-       if (bus->peer && bus->peer->stop)
-               bus->peer->stop(bus->peer);
+       if (bus->peer) {
+               bus->peer->event(bus->peer, 0, TWI_STOP);
+               bus->peer->byte_index = 0;
+       }
        bus->peer = NULL;
 }
 
@@ -87,8 +94,10 @@ uint8_t twi_bus_read(twi_bus_t * bus)
        return res;     
 }
 
-void twi_slave_init(twi_slave_t * slave, void * param)
+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;
 }
 
@@ -114,8 +123,8 @@ void twi_slave_detach(twi_slave_t * slave)
 
 int twi_slave_match(twi_slave_t * slave, uint8_t address)
 {
-       if (slave->has_address)
-               return slave->has_address(slave, address);
-       return (address & ~1) == (slave->address & ~1);
+       if (slave->address)
+               return (address & ~1) == (slave->address & ~1);
+       return slave->event(slave, address, TWI_PROBE);
 }
 
index 7f383cb..0c841f2 100644 (file)
 
 #include <stdint.h>
 
+enum twi_event {
+    TWI_START,
+    TWI_STOP,
+       // return non-zero if this slave address is handled by this slave
+       // if NULL, the "address" field is used instead. If this function
+       // is present, 'address' field is not used.
+    TWI_PROBE,
+    TWI_NACK /* Masker NACKed a receive byte.  */
+};
+
+#define TWI_ADDRESS_READ_MASK  0x01
+
 typedef struct twi_slave_t {
        struct twi_bus_t * bus; // bus we are attached to
        struct twi_slave_t * next;      // daisy chain on the bus
        
-       void * param;           // module parameter
+       void * param;           // module private parameter
        uint8_t address;        // slave address (lowest bit is not used, it's for the W bit)
        int byte_index;         // byte index in the transaction (since last start, restart)
 
-       // return non-zero if this slave address is handled by this slave
-       // if NULL, the "address" field is used instead. If this function
-       // is present, 'address' field is not used.
-       int (*has_address)(struct twi_slave_t* p, uint8_t address);     // optional
-
        // handle start conditionto address+w, restart means "stop" wasn't called
-       int (*start)(struct twi_slave_t* p, uint8_t address, int restart);
+       int (*event)(struct twi_slave_t* p, uint8_t address, enum twi_event event);
+
        // handle a data write, after a (re)start
        int (*write)(struct twi_slave_t* p, uint8_t v);
+
        // handle a data read, after a (re)start
        uint8_t (*read)(struct twi_slave_t* p);
-       // stop condition detected
-       void (*stop)(struct twi_slave_t* p);
 } twi_slave_t;
 
 
@@ -64,7 +71,7 @@ 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, void * param);
+void twi_slave_init(twi_slave_t * slave, uint8_t address, void * param);
 void twi_slave_detach(twi_slave_t * slave);
 int twi_slave_match(twi_slave_t * slave, uint8_t address);