#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;
}
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;
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)
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);
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
*/
#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)
{
// 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;
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;
}
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;
}
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);
}
#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;
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);