@@ -87,6 +87,7 @@ export const PCINT2 = {
8787} ;
8888
8989export type GPIOListener = ( value : u8 , oldValue : u8 ) => void ;
90+ export type ExternalClockListener = ( pinValue : boolean ) => void ;
9091
9192export const portAConfig : AVRPortConfig = {
9293 PIN : 0x20 ,
@@ -198,6 +199,8 @@ enum InterruptMode {
198199}
199200
200201export class AVRIOPort {
202+ readonly externalClockListeners : ( ExternalClockListener | null ) [ ] = [ ] ;
203+
201204 private readonly externalInts : ( AVRInterruptConfig | null ) [ ] ;
202205 private readonly PCINT : AVRInterruptConfig | null ;
203206 private listeners : GPIOListener [ ] = [ ] ;
@@ -208,8 +211,10 @@ export class AVRIOPort {
208211 private lastDdr : u8 = 0 ;
209212 private lastPin : u8 = 0 ;
210213
211- constructor ( private cpu : CPU , private portConfig : AVRPortConfig ) {
214+ constructor ( private cpu : CPU , readonly portConfig : Readonly < AVRPortConfig > ) {
212215 cpu . gpioPorts . add ( this ) ;
216+ cpu . gpioByPort [ portConfig . PORT ] = this ;
217+
213218 cpu . writeHooks [ portConfig . DDR ] = ( value : u8 ) => {
214219 const portValue = cpu . data [ portConfig . PORT ] ;
215220 cpu . data [ portConfig . DDR ] = value ;
@@ -234,34 +239,6 @@ export class AVRIOPort {
234239 this . updatePinRegister ( ddrMask ) ;
235240 return true ;
236241 } ;
237- // The following hook is used by the timer compare output to override GPIO pins:
238- cpu . gpioTimerHooks [ portConfig . PORT ] = ( pin : u8 , mode : PinOverrideMode ) => {
239- const pinMask = 1 << pin ;
240- if ( mode === PinOverrideMode . None ) {
241- this . overrideMask |= pinMask ;
242- this . overrideValue &= ~ pinMask ;
243- } else {
244- this . overrideMask &= ~ pinMask ;
245- switch ( mode ) {
246- case PinOverrideMode . Enable :
247- this . overrideValue &= ~ pinMask ;
248- this . overrideValue |= cpu . data [ portConfig . PORT ] & pinMask ;
249- break ;
250- case PinOverrideMode . Set :
251- this . overrideValue |= pinMask ;
252- break ;
253- case PinOverrideMode . Clear :
254- this . overrideValue &= ~ pinMask ;
255- break ;
256- case PinOverrideMode . Toggle :
257- this . overrideValue ^= pinMask ;
258- break ;
259- }
260- }
261- const ddrMask = cpu . data [ portConfig . DDR ] ;
262- this . writeGpio ( cpu . data [ portConfig . PORT ] , ddrMask ) ;
263- this . updatePinRegister ( ddrMask ) ;
264- } ;
265242
266243 // External interrupts
267244 const { externalInterrupts } = portConfig ;
@@ -360,13 +337,48 @@ export class AVRIOPort {
360337 this . updatePinRegister ( this . cpu . data [ this . portConfig . DDR ] ) ;
361338 }
362339
340+ /**
341+ * Internal method - do not call this directly!
342+ * Used by the timer compare output units to override GPIO pins.
343+ */
344+ timerOverridePin ( pin : u8 , mode : PinOverrideMode ) {
345+ const { cpu, portConfig } = this ;
346+ const pinMask = 1 << pin ;
347+ if ( mode === PinOverrideMode . None ) {
348+ this . overrideMask |= pinMask ;
349+ this . overrideValue &= ~ pinMask ;
350+ } else {
351+ this . overrideMask &= ~ pinMask ;
352+ switch ( mode ) {
353+ case PinOverrideMode . Enable :
354+ this . overrideValue &= ~ pinMask ;
355+ this . overrideValue |= cpu . data [ portConfig . PORT ] & pinMask ;
356+ break ;
357+ case PinOverrideMode . Set :
358+ this . overrideValue |= pinMask ;
359+ break ;
360+ case PinOverrideMode . Clear :
361+ this . overrideValue &= ~ pinMask ;
362+ break ;
363+ case PinOverrideMode . Toggle :
364+ this . overrideValue ^= pinMask ;
365+ break ;
366+ }
367+ }
368+ const ddrMask = cpu . data [ portConfig . DDR ] ;
369+ this . writeGpio ( cpu . data [ portConfig . PORT ] , ddrMask ) ;
370+ this . updatePinRegister ( ddrMask ) ;
371+ }
372+
363373 private updatePinRegister ( ddr : u8 ) {
364374 const newPin = ( this . pinValue & ~ ddr ) | ( this . lastValue & ddr ) ;
365375 this . cpu . data [ this . portConfig . PIN ] = newPin ;
366376 if ( this . lastPin !== newPin ) {
367377 for ( let index = 0 ; index < 8 ; index ++ ) {
368378 if ( ( newPin & ( 1 << index ) ) !== ( this . lastPin & ( 1 << index ) ) ) {
369- this . toggleInterrupt ( index , ! ! ( newPin & ( 1 << index ) ) ) ;
379+ const value = ! ! ( newPin & ( 1 << index ) ) ;
380+ this . toggleInterrupt ( index , value ) ;
381+ this . externalClockListeners [ index ] ?.( value ) ;
370382 }
371383 }
372384 this . lastPin = newPin ;
0 commit comments