+ const uint8_t oldpin = avr->data[p->r_pin];
+ const uint8_t pin = (oldpin & ~v) | (avr->data[p->r_port] & v);
+ avr_core_watch_write(avr, p->r_pin, pin);
+ for (int i = 0; i < 8; i++)
+ if (((oldpin ^ pin) >> i) & 1)
+ avr_raise_irq(p->io.irq + i, (pin >> i) & 1);
+ avr_raise_irq(p->io.irq + IOPORT_IRQ_PIN_ALL, pin);
+}
+
+/*
+ * this is our "main" pin change callback, it can be triggered by either the
+ * AVR code, or any external piece of code that see fit to do it.
+ * Either way, this will raise pin change interrupts, if needed
+ */
+void avr_ioport_irq_notify(struct avr_irq_t * irq, uint32_t value, void * param)
+{
+ avr_ioport_t * p = (avr_ioport_t *)param;
+ avr_t * avr = p->io.avr;
+
+ int output = value & AVR_IOPORT_OUTPUT;
+ value &= 0xff;
+ uint8_t mask = 1 << irq->irq;
+ // set the real PIN bit. ddr doesn't matter here as it's masked when read.
+ avr->data[p->r_pin] &= ~mask;
+ if (value)
+ avr->data[p->r_pin] |= mask;
+
+ if (output) // if the IRQ was marked as Output, also do the IO write
+ avr_ioport_write(avr, p->r_port, (avr->data[p->r_port] & ~mask) | (value ? mask : 0), p);
+
+ if (p->r_pcint) {
+ // if the pcint bit is on, try to raise it
+ int raise = avr->data[p->r_pcint] & mask;
+ if (raise)
+ avr_raise_interrupt(avr, &p->pcint);
+ }
+}
+
+static void avr_ioport_reset(avr_io_t * port)
+{
+ avr_ioport_t * p = (avr_ioport_t *)port;
+ for (int i = 0; i < IOPORT_IRQ_PIN_ALL; i++)
+ avr_irq_register_notify(p->io.irq + i, avr_ioport_irq_notify, p);
+}
+
+static int avr_ioport_ioctl(struct avr_io_t * port, uint32_t ctl, void * io_param)
+{
+ avr_ioport_t * p = (avr_ioport_t *)port;
+ avr_t * avr = p->io.avr;
+ int res = -1;
+
+ switch(ctl) {
+ case AVR_IOCTL_IOPORT_GETIRQ_REGBIT: {
+ avr_ioport_getirq_t * r = (avr_ioport_getirq_t*)io_param;
+
+ if (r->bit.reg == p->r_port || r->bit.reg == p->r_pin || r->bit.reg == p->r_ddr) {
+ // it's us ! check the special case when the "all pins" irq is requested
+ int o = 0;
+ if (r->bit.mask == 0xff)
+ r->irq[o++] = &p->io.irq[IOPORT_IRQ_PIN_ALL];
+ else {
+ // otherwise fill up the ones needed
+ for (int bi = 0; bi < 8; bi++)
+ if (r->bit.mask & (1 << bi))
+ r->irq[o++] = &p->io.irq[r->bit.bit + bi];