Skip to content

Commit 1ce3462

Browse files
authored
Merge pull request #390 from vintagepc/unaligned-PCINTs
Support for non-aligned PCINTs
2 parents 90dca3e + 0453ec8 commit 1ce3462

File tree

3 files changed

+27
-4
lines changed

3 files changed

+27
-4
lines changed

simavr/cores/sim_mega2560.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,17 @@ const struct mcu_t {
102102
AVR_IOPORT_DECLARE(f, 'F', F),
103103
AVR_IOPORT_DECLARE(g, 'G', G),
104104
AVR_IOPORT_DECLARE(h, 'H', H),
105-
AVR_IOPORT_DECLARE(j, 'J', J),
105+
.portj = {
106+
.name = 'J', .r_port = PORTJ, .r_ddr = DDRJ, .r_pin = PINJ,
107+
.pcint = {
108+
.enable = AVR_IO_REGBIT(PCICR, PCIE1),
109+
.raised = AVR_IO_REGBIT(PCIFR, PCIF1),
110+
.vector = PCINT1_vect,
111+
.mask = 0b11111110,
112+
.shift = -1
113+
},
114+
.r_pcint = PCMSK1,
115+
},
106116
AVR_IOPORT_DECLARE(k, 'K', K),
107117
AVR_IOPORT_DECLARE(l, 'L', L),
108118

@@ -353,7 +363,7 @@ const struct mcu_t {
353363
.r_tcnt = TCNT2,
354364
// asynchronous timer source bit.. if set, use 32khz frequency
355365
.as2 = AVR_IO_REGBIT(ASSR, AS2),
356-
366+
357367
.overflow = {
358368
.enable = AVR_IO_REGBIT(TIMSK2, TOIE2),
359369
.raised = AVR_IO_REGBIT(TIFR2, TOV2),

simavr/sim/avr_ioport.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,18 @@ avr_ioport_irq_notify(
153153

154154
if (p->r_pcint) {
155155
// if the pcint bit is on, try to raise it
156-
int raise = avr->data[p->r_pcint] & mask;
156+
int raisedata = avr->data[p->r_pcint];
157+
uint8_t uiRegMask = p->pcint.mask;
158+
int8_t iShift = p->pcint.shift;
159+
if (uiRegMask) // If mask is 0, do nothing (backwards compat)
160+
raisedata &= uiRegMask; // Mask off
161+
162+
if (iShift>0) // Shift data if necessary for alignment.
163+
raisedata <<= iShift;
164+
else if (iShift<0)
165+
raisedata >>= -iShift;
166+
167+
int raise = raisedata & mask;
157168
if (raise)
158169
avr_raise_interrupt(avr, &p->pcint);
159170
}
@@ -279,4 +290,3 @@ void avr_ioport_init(avr_t * avr, avr_ioport_t * p)
279290
avr_register_io_write(avr, p->r_pin, avr_ioport_pin_write, p);
280291
avr_register_io_write(avr, p->r_ddr, avr_ioport_ddr_write, p);
281292
}
282-

simavr/sim/sim_interrupts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ typedef struct avr_int_vector_t {
4242
avr_regbit_t enable; // IO register index for the "interrupt enable" flag for this vector
4343
avr_regbit_t raised; // IO register index for the register where the "raised" flag is (optional)
4444

45+
uint8_t mask; // Mask for PCINTs. this is needed for chips like the 2560 where PCINT do not align with IRQs
46+
int8_t shift; // PCINT8 = E0, PCINT9-15 are on J0-J6. Shift shifts down (<0) or up (>0) for alignment with IRQ#.
47+
4548
// 'pending' IRQ, and 'running' status as signaled here
4649
avr_irq_t irq[AVR_INT_IRQ_COUNT];
4750
uint8_t pending : 1, // 1 while scheduled in the fifo

0 commit comments

Comments
 (0)