It is currently Tue Oct 16, 2018 9:01 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next
Author Message
PostPosted: Mon Oct 01, 2018 4:26 pm 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
I started a long overnight test on each PPU address, should take many hours. When getting that test running, I found that as I changed things here and there, it took different numbers of PPU /RD toggles to set the status bit and different numbers of M2 toggles to clear the status bit. It didn't seem random - things were very repeatable. For the purpose of this test (i.e. identify all addresses that do and do not cause the status to set), I toggled each of those a bunch of times. There is definitely some counter business going on here. Will be interesting to poke more at it and to see if anything in this test indicates a connection between particular addresses and numbers of toggles.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 7:52 am 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
Results from the test:

"In Frame" status bit is able to be set in the PPU address range $2000 - $3000.

Additional observations:
  • As expected, PPU address $0000 did trigger the status bit to be set, based on prior knowledge that the first falling edge of PPU /RD always sets status regardless of PPU address.
  • PPU address $3000 IS included. $3001 is the first one not to set the status bit in this test.
  • Theory: It could be that after clearing in test $2FFF, the MMC5 has returned to it's "don't care about PPU address, just look for any PPU /RD falling edge" state. (Will test that.)
  • PPU Address $2000 set the status on the 4th falling edge of PPU /RD
  • All other addresses ($2001 - $3000 (including $3000)) set the status on the first falling edge of PPU /RD
  • In this test, clearing of status always occurred on the 3rd falling edge of M2.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 9:01 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 394
Location: Poland
Yeah, there is some more complexity behind that, because not always three PPU read cycles set the bit (sometimes, one is just enough and sometimes four).

Now I can confirm that only $2000-$3fff adresses (when comes to three-cycle-read) are able to set the bit.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 9:50 am 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
You were able to get the status bit to set with PPU address range $3001 - $3FFF? I tested each and every PPU address and gave 10 falling edges on PPU /RD, and nothing in that address range set the status bit for me.

My chip is marked MMC5A, is that what yours is marked?


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 10:41 am 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
Did a quick test, running PPU address range limited to just $2FF0 through $3003. Was able to repeat the status being set from beginning up to $3000 and then not set on $3001/2/3. I then made the test skip address $3000, so it tested $2FFE, $2FFF, [skipped], $3001. And the status did get set on $3001 this way and not on $3002. So it looks like it always is accepting the next one regardless of PPU address in this situation.

I am trying to keep in mind that this strange counter-type handling might be related to the difference between one scanline to the next vs. starting a whole new frame after v-blank. I might need to learn more about the PPU and how it accesses memory for different purposes.


Last edited by Ben Boldt on Tue Oct 02, 2018 10:46 am, edited 1 time in total.

Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 10:43 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7648
Location: Seattle
That does smell like there's something off with your test. Try testing addresses randomly?


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 10:48 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 394
Location: Poland
I have MMC5A from Just Breed.
Actually, the scanline counter is quite simple - at start of each PPU read cycle it just looks for the last three 3 PPU read addresses and whenever it sees three from same address, it increments its value.

What is also interesting is that even if the $5204.7 is set, /IRQ is asserted only if M2 toggles (if M2 stops toggling, it it deasserted) - same goes for the /IRQ asserted from $5209.


Attachments:
mmc5_2.PNG
mmc5_2.PNG [ 50.65 KiB | Viewed 254 times ]


Last edited by krzysiobal on Tue Oct 02, 2018 11:35 am, edited 2 times in total.
Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 11:34 am 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
I just ran the same test except with random PPU address instead of sequential PPU address. I tested 10,000 random PPU addresses. The address range does correlate - the status bit could only get set in address range $2000 through $2FFF for me.

I noticed that in all cases after clearing the status, the next falling edge of PPU /RD always set the status again regardless of address, on the first falling edge. Will review the data more closely this evening.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 12:03 pm 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
Here is my data. I put some conditional formatting colors to make it easier to see. Some clear patterns emerge in this test.


Attachments:
Set Status Random Address.xlsx [1.23 MiB]
Downloaded 4 times
Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 2:24 pm 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
I have found that the M2 counter for clearing status, resets its count any time PPU /RD has a falling edge, regardless of PPU address staying the same or changing. I found this by inserting PPU /RD toggles between each M2 toggle. It could never clear the status in this test.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 3:03 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 394
Location: Poland
Yes, that's how it works - there must be three or more CPU cycles without PPU read between to clear the in-frame bit.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 3:18 pm 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
Okay, my findings agree with that. You said 3 or more cycles -- not sure how literally you mean that. Have you seen it take more than 3 M2 falling edges to clear the status? I have only ever seen it take exactly 3 that I am aware of.

I still see a very persistent range of PPU addresses that can set the status which is different that yours:

$0000
-> Doesn't set
$1FFF

$2000
-> Does set after counting PPU /RD falling edges
$2FFF

$3000
-> Doesn't set for me, does set for you.
$3FFF

How can yours set in range $3000 - 3FFF but not mine? Do you write to any registers or drive any other inputs low at the beginning of your test?


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 3:34 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 394
Location: Poland
Quote:
Okay, my findings agree with that. You said 3 or more cycles -- not sure how literally you mean that. Have you seen it take more than 3 M2 falling edges to clear the status? I have only ever seen it take exactly 3 that I am aware of.

I mean 3.

Quote:
How can yours set in range $3000 - 3FFF but not mine? Do you write to any registers or drive any other inputs low at the beginning of your test?

No, you are right, only $2000-$2fff can set it. I haven't checked that before with so many datails.


Top
 Profile  
 
PostPosted: Tue Oct 02, 2018 4:49 pm 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
Okay. I am trying to think of this from the perspective of FPGA or CPLD, that is why I am so paranoid about edges and what latches and what happens asynchronously, etc.

Do you agree that the in-frame status bit works like this?:

Code:
// Declaration / initial values:
UInt16 prev_ppu_address = ? / don't care
bool always_set_in_frame_status_next_ppu_read = true;  // Default true: first falling edge of PPU /RD always sets in_frame_status regardless of PPU address and set counter.
int set_counter = 0;  // counts PPU /RD falling edges
int clear_counter = 0;  //  counts M2 falling edges

void on_ppu_rd_falling_edge( void )
{
    clear_counter = 0;  // Observation: Always resets M2 counter regardless if PPU address stayed the same or changed.

    if(prev_ppu_addr != ppu_addr)
    {
        set_counter = 0;
        prev_ppu_addr = ppu_addr;
    }
   
    if( true == always_set_in_frame_status_next_ppu_read )
    {
        in_frame_status = 1;
        always_set_in_frame_status_next_ppu_read = false;
    }
    else if( ppu address is in range $2000 to 2FFF )  // Observed this range.
    {
        set_counter++;
        if(set_counter >= 4)
        {
            in_frame_status = 1;
        }
    }
}

void on_m2_falling_edge (void)
{
    if(in_frame_status = 1)
    {
        if(PPU /RD is high)  // Observation: with PPU /RD held low, status can not clear with M2 toggles.
        {
            clear_counter++;
            if(clear_counter >= 3)  // Observation: always clears on the 3rd falling edge of M2, considering /RD had not reset the counter.
            {
                always_set_in_frame_status_next_ppu_read = true;
                in_frame_status = 0
            }
        }
    }
}

void combinational_logic (void)
{
    'and' these:
        M2, !(/ROMSEL), CPU A14,13,12,11,10,9,8,7,6,5,4,3,!2,1,in_frame_status
    result 1 -> always_set_in_frame_status_next_ppu_read = true, in_frame_status = 0
   
    // Observation: this part does not care about PPU /RD even if it is held low.
}


I am wondering if there is some way to simplify this - maybe the counters can be combined into 1 counter and the status bit is one of the bits of the counter, etc. I will think about it some more.

Edit:
Oops, nothing ever clears always_set_in_frame_status_next_ppu_read. hmmm...

Edit 2: fixed I think


Top
 Profile  
 
PostPosted: Wed Oct 03, 2018 11:08 am 
Offline
User avatar

Joined: Tue Mar 22, 2016 8:27 pm
Posts: 75
Location: Minnesota
I made a state diagram of how we think it works. I think this is a better approach than pseudo-code. I would like to try to verify each arrow in the diagram. If everything checks out, then I think we can feel pretty confident that we nailed down M2 and /RD interaction with the in frame status bit. Reading from CPU address $FFFA/B is not shown in this diagram.

Attachment:
in_frame_bit_states.PNG
in_frame_bit_states.PNG [ 66.14 KiB | Viewed 159 times ]


Edit: Something isn't right here because I know that you can loop through just the top 4 boxes if you keep reading PPU addresses in range 2000-2fff. This diagram shows the 4x /RD every other read even when PPU addresses remain in this range. Will think about how to fix the diagram.

Edit 2: This is better:

Attachment:
in_frame_bit_states_2.PNG
in_frame_bit_states_2.PNG [ 80.42 KiB | Viewed 146 times ]


Edit 3: This still isn't right because it alternates between caring and not caring about the PPU address when the address is always in range... I will get this, probably a few more revisions...

Edit 4: More improvements:

Attachment:
in_frame_bit_states_3.PNG
in_frame_bit_states_3.PNG [ 82.18 KiB | Viewed 140 times ]


Edit 5: I have looked at the diagram in edit 4 a fair bit now and I am feeling pretty good about it now. I think I will print it and start testing each arrow and checking them off.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 65 posts ]  Go to page Previous  1, 2, 3, 4, 5  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group