static avr_cycle_count_t avr_twi_set_state_timer( struct avr_t * avr, avr_cycle_count_t when, void * param) { avr_twi_t * p = (avr_twi_t *)param; _avr_twi_status_set(p, p->next_twstate, 1); p->next_twstate = 0; return 0; }
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; 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 AVR_TWI_DEBUG AVR_TRACE(avr, "%s %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", __func__, v, avr_regbit_get(avr, p->twsta), avr_regbit_get(avr, p->twsto), avr_regbit_get(avr, p->twea), avr_regbit_get(avr, p->twi.raised), avr_regbit_get_raw(p->io.avr, p->twsr), p->state); #endif 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); 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; } AVR_TRACE(avr, "TWEN: %d\n", twen); if (avr->data[p->r_twar]) { AVR_TRACE(avr, "TWEN Slave: %02x&%02x\n", avr->data[p->r_twar] >> 1, avr->data[p->r_twamr] >> 1); p->state |= TWI_COND_SLAVE; }
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; 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 AVR_TWI_DEBUG printf("avr_twi_write %02x START:%d STOP:%d ACK:%d INT:%d TWSR:%02x (state %02x)\n", v, avr_regbit_get(avr, p->twsta), avr_regbit_get(avr, p->twsto), avr_regbit_get(avr, p->twea), avr_regbit_get(avr, p->twi.raised), avr_regbit_get_raw(p->io.avr, p->twsr), p->state); #endif 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); 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; } printf("TWEN: %d\n", twen); } if (!twen) return; uint8_t cleared = avr_regbit_get(avr, p->twi.raised); /*int cleared = */avr_clear_interrupt_if(avr, &p->twi, twint); // printf("cleared %d\n", cleared); if (!twsto && avr_regbit_get(avr, p->twsto)) { // generate a stop condition #if AVR_TWI_DEBUG printf("<<<<< I2C stop\n"); #endif if (p->state) { // doing stuff if (p->state & TWI_COND_START) { avr_raise_irq(p->io.irq + TWI_IRQ_MOSI, avr_twi_irq_msg(TWI_COND_STOP, p->peer_addr, 1)); } } p->state = 0; } if (!twsta && avr_regbit_get(avr, p->twsta)) { #if AVR_TWI_DEBUG printf(">>>>> I2C %sstart\n", p->state & TWI_COND_START ? "RE" : ""); #endif // 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->peer_addr = 0; 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) { int do_read = p->peer_addr & 1; #if AVR_TWI_DEBUG if (do_read) printf("I2C READ byte from %02x\n", p->peer_addr); else printf("I2C WRITE byte %02x to %02x\n", avr->data[p->r_twdr], p->peer_addr); #endif // a normal data byte uint8_t msgv = do_read ? TWI_COND_READ : TWI_COND_WRITE; if (avr_regbit_get(avr, p->twea)) msgv |= TWI_COND_ACK; p->state &= ~TWI_COND_ACK; // clear ACK bit // if the latch is ready... as set by writing/reading the TWDR if ((p->state & msgv)) { // 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, avr_twi_irq_msg(msgv, p->peer_addr, avr->data[p->r_twdr])); if (do_read) { // read ? _avr_twi_delay_state(p, 9, msgv & TWI_COND_ACK ? TWI_MRX_DATA_ACK : TWI_MRX_DATA_NACK); } else { _avr_twi_delay_state(p, 9, p->state & TWI_COND_ACK ? TWI_MTX_DATA_ACK : TWI_MTX_DATA_NACK); } } #if AVR_TWI_DEBUG else printf("I2C latch is not ready, do nothing\n"); #endif } else { #if AVR_TWI_DEBUG printf("I2C Master address %02x\n", avr->data[p->r_twdr]); #endif // send the address p->state |= TWI_COND_ADDR; p->peer_addr = avr->data[p->r_twdr]; p->state &= ~TWI_COND_ACK; // clear ACK bit // 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, avr_twi_irq_msg(TWI_COND_START, p->peer_addr, 0)); if (p->peer_addr & 1) { // read ? p->state |= TWI_COND_READ; // always allow read to start with _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); } } p->state &= ~TWI_COND_WRITE; } }