Apu and Interrupts

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Apu and Interrupts
by on (#132041)
Im confused with apu and interrupts.
There are a couple of Blarrg's test that don't pass in my emu so im looking for help.

Please tell me if what i think is right:

1 - There are two flags: irq_inhibit flag and frame_interrupt flag
2 - When 0x40 is written to $4017 inihibit_flag is set to "1" and flrame_interrupt is cleared to "0". Otherwise inihibit_flag is cleared, but frame_interrupt flag is unchanged.
3 - On step 4 more or less of the 0x80 = 0 mode IF inihibit_flag is "0" frame_interrupt is set to "1" and IRQ line is asserted (irq_collector = 0)
4 - When $4015 is read it returns the state of frame_interrupt. IF SET -> data_to_return |= 0x40. AFTERWARDS it clears the frame_interrupt flag. AND AFTERWARDS all that IRQ is acknowledged (irq_collector = 1).
5 - On Power Up, according to the wiki $00 is written to $4017 so interrupt_inhibit is clear allowing IRQs.

What is wrong??
Re: Apu and Interrupts
by on (#132335)
no help?? C'mon!!
Re: Apu and Interrupts
by on (#132338)
What's the test ROM name?
Maybe it's more clear if you report the name and that fail number.
Re: Apu and Interrupts
by on (#132339)
Well, it's not that easy and... so boolean. I remember of having a lot of trouble and hours of tracing my APU code in order to get the things working right. I had to add a cycle counter in order to clock the quarter/half frames correctly, thanks to the help of Q below.

7456 cycles after init, triggers quarter frame
14912 cycles after init, triggers quarter+half frames
22370 cycles after init, triggers quarter frame
mode 0 - 29828 cycles after init, triggers quarter+half frames, checks IRQ
29829 and 30 - checks IRQ
37280 cycles after init, triggers quarter+half frames


There's more on the wiki regarding $4017 register.
Re: Apu and Interrupts
by on (#132348)
Zepper wrote:
7456 cycles after init, triggers quarter frame
14912 cycles after init, triggers quarter+half frames
22370 cycles after init, triggers quarter frame
mode 0 - 29828 cycles after init, triggers quarter+half frames, checks IRQ
29829 and 30 - checks IRQ
37280 cycles after init, triggers quarter+half frames


What do you mean with "29829 and 30" Zepper? I understand the other ones, but not that. Also i have read the wiki, but sometimes gets not to much understandable for me.

Boolean: The rom name is Blarrg's apu_reset set.
Re: Apu and Interrupts
by on (#132350)
It means
29829 - checks IRQ
29830 - checks IRQ
Re: Apu and Interrupts
by on (#132387)
Good info Zepper and Tepples. I could pass test "4017 timming".
I cannot pass $4017 re-written. I don't know what's wrong here, it seems a lame test to pass. Anyway this Blarrg's test ask me to reset 2 times and then the error "should me wrtten with last value written".
My ResetApu() routhine is very simple: it writes $0 to $4015 and the previous value in $4017 wich was stored in a variable.

My WriteApu() and $4017 write looks like this:

Code:
   case 0x4017:
      
      Apu.reg4017 = data;     //this stores the previos value
      Apu.seq_divider = 0;     // reset sequencer divider as Blarrg's doc says
      Apu.sequence = 0;       // reset Frame Sequence again as Blarrg's says
      
      if (Apu.reg4017 & 0x40)
      {
         Apu.irq_disable = 1;     //irq inhibit flag set
      }
      else
      {
         Apu.irq_disable= 0;     //irq inhibit flag clean
      }

      Apu.frame_interrupt = 0;     //IM NOT SURE THIS OK

      Apu.mode = Apu.reg4017  & 0x80;     //Sets the mode
      
      if (Apu.mode)    If mode = 0x80 Clocks inmediatly quarter and half frames
      {
         ClockEnvelope(&Apu.Square.Env);
         ClockEnvelope(&Apu.Square2.Env);
         ClockEnvelope(&Apu.Noise.Env);
         ClockLinearCounter();
         ClockLenCounter(&Apu.Square.Len);
         ClockLenCounter(&Apu.Square2.Len);
         ClockLenCounter(&Apu.Triangle.Len);
         ClockLenCounter(&Apu.Noise.Len);
         ClockSweep(&Apu.Square.Sweep, &Apu.Square.PTimer, 0);
         ClockSweep(&Apu.Square2.Sweep, &Apu.Square2.PTimer, 1);
      }

      break;
   }


Something wrong there must be in this...
Re: Apu and Interrupts
by on (#132393)
Use a log file! Your first line of $4017 must be: fprintf(fp, "$4017 value: %02X (old_value: %02X)\n", value_written, old_value).

Log it and check what's up. Be sure the value is the same after the reset.