#define D(_w)
+static void
+avr_ioport_flag_write(
+ struct avr_t * avr,
+ avr_io_addr_t addr,
+ uint8_t v,
+ void * param)
+{
+ avr_ioport_t * p = (avr_ioport_t *)param;
+
+ // Clear interrupt if 1 is written to flag.
+
+ if (avr_regbit_from_value(avr, p->pcint.raised, v))
+ avr_clear_interrupt(avr, &p->pcint);
+}
+
static uint8_t
avr_ioport_read(
struct avr_t * avr,
D(if (avr->data[addr] != v) printf("** DDR%c(%02x) = %02x\r\n", p->name, addr, v);)
avr_raise_irq(p->io.irq + IOPORT_IRQ_DIRECTION_ALL, v);
avr_core_watch_write(avr, addr, v);
-
avr_ioport_update_irqs(p);
}
/* BUG: If DDR bit is set here, there should be no
* interrupt. But a spurious IRQ call by the user
- * is indestinguishable from an internal one
+ * is indistinguishable from an internal one
* caused by writing the output port register and
* that should cause an interrupt. Doh!
*/
avr_register_io_read(avr, p->r_pin, avr_ioport_read, p);
avr_register_io_write(avr, p->r_pin, avr_ioport_pin_write, p);
avr_register_io_write(avr, p->r_ddr, avr_ioport_ddr_write, p);
+ if (p->pcint.raised.reg) {
+ avr_register_io_write(avr, p->pcint.raised.reg,
+ avr_ioport_flag_write, p);
+ }
}
printf("I<%02X ", PIND);
}
+ISR(PCINT0_vect)
+{
+ printf("K ");
+}
+
ISR(PCINT2_vect)
{
printf("J<%02X ", PORTD);
printf("P<%02X ", PIND);
+ // Test "write 1 to clear" on PORT B.
+
+ DDRB = 0xff;
+ PCICR = (1 << PCIE0); /* Interrupt enable. */
+ PCMSK0 = 3; /* Pins 0 and 1. */
+ cli();
+ PORTB = 1;
+ PCIFR = 1; /* Clear interrupt. */
+ sei();
+ printf("| ");
+ cli();
+ PORTB = 3;
+ PCIFR = 6;
+ sei(); /* Interrupt. */
+ printf("| ");
+
// this quits the simulator, since interupts are off
// this is a "feature" that allows running tests cases and exit
cli();