Fix PCINT on PORTJ for 2560
authorvintagepc <53943260+vintagepc@users.noreply.github.com>
Sat, 18 Jul 2020 20:46:02 +0000 (16:46 -0400)
committervintagepc <53943260+vintagepc@users.noreply.github.com>
Thu, 23 Jul 2020 14:31:28 +0000 (10:31 -0400)
simavr/cores/sim_mega2560.h
simavr/sim/avr_ioport.c
simavr/sim/sim_interrupts.h

index 429300f..7e8974c 100644 (file)
@@ -102,7 +102,17 @@ const struct mcu_t {
        AVR_IOPORT_DECLARE(f, 'F', F),
        AVR_IOPORT_DECLARE(g, 'G', G),
        AVR_IOPORT_DECLARE(h, 'H', H),
-       AVR_IOPORT_DECLARE(j, 'J', J),
+       .portj = {
+               .name = 'J', .r_port = PORTJ, .r_ddr = DDRJ, .r_pin = PINJ,
+               .pcint = {
+                        .enable = AVR_IO_REGBIT(PCICR, PCIE1),
+                        .raised = AVR_IO_REGBIT(PCIFR, PCIF1),
+                        .vector = PCINT1_vect,
+                        .mask = 0b11111110,
+                        .shift = -1
+               },
+               .r_pcint = PCMSK1,
+       },
        AVR_IOPORT_DECLARE(k, 'K', K),
        AVR_IOPORT_DECLARE(l, 'L', L),
 
@@ -353,7 +363,7 @@ const struct mcu_t {
                .r_tcnt = TCNT2,
                // asynchronous timer source bit.. if set, use 32khz frequency
                .as2 = AVR_IO_REGBIT(ASSR, AS2),
-               
+
                .overflow = {
                         .enable = AVR_IO_REGBIT(TIMSK2, TOIE2),
                         .raised = AVR_IO_REGBIT(TIFR2, TOV2),
index e35b2de..64adbc4 100644 (file)
@@ -153,7 +153,18 @@ avr_ioport_irq_notify(
 
        if (p->r_pcint) {
                // if the pcint bit is on, try to raise it
-               int raise = avr->data[p->r_pcint] & mask;
+               int raisedata = avr->data[p->r_pcint];
+               uint8_t uiRegMask = p->pcint.mask;
+               int8_t iShift = p->pcint.shift;
+               if (uiRegMask) // If mask is 0, do nothing (backwards compat)
+                       raisedata &= uiRegMask; // Mask off
+
+               if (iShift>0) // Shift data if necessary for alignment.
+                       raisedata <<= iShift;
+               else if (iShift<0)
+                       raisedata >>= -iShift;
+
+               int raise = raisedata & mask;
                if (raise)
                        avr_raise_interrupt(avr, &p->pcint);
        }
@@ -279,4 +290,3 @@ void avr_ioport_init(avr_t * avr, avr_ioport_t * 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);
 }
-
index b55ad17..bebf614 100644 (file)
@@ -42,6 +42,9 @@ typedef struct avr_int_vector_t {
        avr_regbit_t    enable;                 // IO register index for the "interrupt enable" flag for this vector
        avr_regbit_t    raised;                 // IO register index for the register where the "raised" flag is (optional)
 
+       uint8_t                 mask; // Mask for PCINTs. this is needed for chips like the 2560 where PCINT do not align with IRQs
+       int8_t          shift;  // PCINT8 = E0, PCINT9-15 are on J0-J6. Shift shifts down (<0) or up (>0) for alignment with IRQ#.
+
        // 'pending' IRQ, and 'running' status as signaled here
        avr_irq_t               irq[AVR_INT_IRQ_COUNT];
        uint8_t                 pending : 1,    // 1 while scheduled in the fifo