/* * write to the TIFR register. Watch for code that writes "1" to clear * pending interrupts. */ static void avr_timer_write_pending( struct avr_t * avr, avr_io_addr_t addr, uint8_t v, void * param) { avr_timer_t * p = (avr_timer_t *)param; // save old bits values uint8_t ov = avr_regbit_get(avr, p->overflow.raised); uint8_t ic = avr_regbit_get(avr, p->icr.raised); uint8_t cp[AVR_TIMER_COMP_COUNT]; for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) cp[compi] = avr_regbit_get(avr, p->comp[compi].interrupt.raised); // write the value avr_core_watch_write(avr, addr, v); // clear any interrupts & flags avr_clear_interrupt_if(avr, &p->overflow, ov); avr_clear_interrupt_if(avr, &p->icr, ic); for (int compi = 0; compi < AVR_TIMER_COMP_COUNT; compi++) avr_clear_interrupt_if(avr, &p->comp[compi].interrupt, cp[compi]); }
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; } }