@@ -158,23 +158,34 @@ avr_ioport_irq_notify(
158
158
uint8_t mask = irq -> irq == IOPORT_IRQ_PIN_ALL_IN ?
159
159
0xff : (1 << irq -> irq );
160
160
uint8_t ddr = avr -> data [p -> r_ddr ];
161
+ uint8_t new_pin ;
161
162
162
163
value &= 0xff ;
163
164
value = (irq -> irq == IOPORT_IRQ_PIN_ALL_IN ) ?
164
165
value : (!!value << irq -> irq );
166
+ new_pin = (avr -> data [p -> r_pin ] & ~mask ) | (value ? mask : 0 );
165
167
if (output ) {
166
- if ((mask & ddr ) == 0 )
167
- return ; // TODO: stop further processing of IRQ.
168
+ uint8_t new_out ;
169
+
170
+ new_out = (avr -> data [p -> r_port ] & ~mask ) | (value ? mask : 0 );
171
+ if (mask & ddr ) {
172
+ // If the IRQ was marked as Output, do the IO write.
173
+
174
+ avr_ioport_write (avr , p -> r_port , new_out , p );
175
+ avr_core_watch_write (avr , p -> r_pin , new_pin );
176
+ } else {
177
+ /* Set the PORT register so the output will be visible
178
+ * when the corresponding DDR bit is set.
179
+ * Real hardware does not do this.
180
+ */
168
181
169
- // If the IRQ was marked as Output, also do the IO write.
170
- avr_ioport_write (avr ,
171
- p -> r_port ,
172
- (avr -> data [p -> r_port ] & ~mask ) | value ,
173
- p );
182
+ avr -> data [p -> r_port ] = new_out ;
183
+ return ; // TODO: stop further processing of IRQ.
184
+ }
174
185
} else {
175
186
// Set the real PIN bit. Ignore DDR as it's masked when read.
176
- avr_core_watch_write ( avr , p -> r_pin ,
177
- (avr -> data [ p -> r_pin ] & ~ mask ) | value );
187
+
188
+ avr_core_watch_write (avr , p -> r_pin , new_pin );
178
189
179
190
/* BUG: If DDR bit is set here, there should be no
180
191
* interrupt. But a spurious IRQ call by the user
0 commit comments