unless RTL with a pulldown instead of a pull-up resistor was common place?

I feel like I remember seeing something to that effect somewhere in the RE thread ...?

There is a die shot of the 3193 on Visual6502, and it kinda looks like there's very strong drivers one way and very weak ones the other.

It's also possible it could be something like the 8051, which also lacks a DDR/TRIS register: it drives the output pins strongly for the first 2 instruction cycles (24 master clock cycles) after one of the output registers are written. I think. Something like that, anyway.

I realized another thing about the PICs with four CLCs, pertaining to MMC1 emulation...

They can emit a CLC output to more than one pin. And that lets us emulate a 74'32 or a 74'08, and that lets us get the UNROM/m180 banking styles of the MMC1.

To set up UNROM-style banking, we know that each PRG pin will either be always 1, or CPUA14, depending on the value written to the banking register.

In fact, this lets us get MMC1/VRC1 style CHR banking, too; we now need two CLCs to emit PPUA12 and NOT CPUA12, and the pin multiplexers let us control whether a given output is 0, 1, PPUA12, or NOT PPUA12.

Unfortunately, we now have overwhelmingly run out of CLCs: between needing to latch CPUA13, CPUA14, CPUD0, CPUD7 if PRG banking mode can change, buffer one of PPUA10/A11 for mirroring control, buffer CPUA14 for PRG banking control, and buffer both PPUA12 and NOT PPUA12 for CHR banking...

I think this is the last tangent I have on this specific topic. If I do write an MMC1 subset in a PIC it'll get its own thread.

Yeah that would certainly be possible. The stm8 has 128Bytes of eeprom, which could be made dedicated to the game. There would undoubtedly be some portion of the 8KB flash program memory left unused as well. Both eeprom and flash are single byte erasable/programmable to make things simple.

Having save data in the CIC has the benefit of being much easier to program save operations compared to putting save data in flash PRG-ROM. You don't need to copy and execute save routine from SRAM. The save routine wouldn't differ between mappers. It doesn't require added logic gates. One of biggest benefits is you don't have to erase in 4KB sector chunks, and give up PRG-ROM code space to save operations. The whole operation can be abstracted to r/w eeprom byte number commands.

This all of course requires not only a means for the NES CPU to both read and write from the CIC. Reads will probably be a bit more of a challenge.

One of my goals is to try and come up with an setup that's primarily mapper independent. Trying to come up with a specific (GNROM/MMC1/whatever) modeled mapper kind of dooms the idea to never being adopted IMO. If one comes up with a nonstandard mapper chances are slim that someone besides yourself will adopt the mapper. But if a mapper independent expansion like this were created, then someone could tack it onto the mapper of their choice whenever they decide to make use of it.

I like your ideas on the CLC solutions lidnariq. If you further investigate the CLC options I would be interested to see it in action. I need to spend more time investigating how they work exactly. It's nice to see low cost mcu offerering being made with available programmable logic finally. Hopefully the trend continues and maybe someday we'll get a hefty chunk of programmable logic on the order of 20-32 macrocells sub $1 someday.

For my own purposes I'm not married to the stm8, it just happens to have set the bar on minimum pricing I was able to find for CIC min specs. Beyond that I heavily value using one part for as many designs that I produce as possible. The fewer chips I have to maintain inventory of the better for both pricing and time. And the fewer footprints I need to support the simpler the PCB layout. These are some of the biggest reasons microchips CLC offerings are unappealing for me. That said, if someone had a game they needed help producing a PCB for that implemented CLCs I would entertain the idea.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

Within the available hardware, i.e. without adding a "real" port like Membler's squeedo, I can't think of anything less awful than "do/don't bankswitch depending on bit in EEPROM"

Quote:

One of my goals is to try and come up with an setup that's primarily mapper independent.

I suppose the value in taking something that starts as a simple-ish discrete logic mapper and adding mirroring control and/or and IRQ is that a subset can be tested in any emulator.

Quote:

I like your ideas on the CLC solutions lidnariq. If you further investigate the CLC options I would be interested to see it in action. I need to spend more time investigating how they work exactly. It's nice to see low cost mcu offerering being made with available programmable logic finally. Hopefully the trend continues and maybe someday we'll get a hefty chunk of programmable logic on the order of 20-32 macrocells sub $1 someday.

When my current projects are done I'll probably actually look into making a PIC-as-MMC1-subset...

Within the available hardware, i.e. without adding a "real" port like Membler's squeedo, I can't think of anything less awful than "do/don't bankswitch depending on bit in EEPROM"

Yeah something crazy like that would be one way to do it I suppose. Perhaps another unconventional way would be to come up with a specific sequence of IRQs to communicate data back to NES CPU.

If I can pull off a asynchronous CIC where the mcu is running off internal 16Mhz oscillator instead of 4Mhz CIC clock, I'm fairly confident I'll be able to decode and output data straight from mcu gpio to the databus.

One way to get around decoding would be to have an mcu interrupt on the '161/'377 mapper bit and be prepared to output data on the bus exactly N cycles afterwards. So the NES would be required to have LDA$5000 immediately after STA $8000 for example. If needed extra time in the mcu interrupt routine to retrieve data, maybe just require a specific number of NOPs between STA $8000, LDA $5000. Doing that might even allow the mcu to be running at 4MHz on the CIC clk.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

So been digging into the code and started implementing things with the stm8.

infiniteneslives wrote:

Quote:

It probably mostly depends on whether the hardware can manage all of the CIC timing without the CPU involvement, and the CPU "just" needs to calculate the next bit and next time.

Assuming my analysis of segher's disassembly holds true, my idea of simply outputting the next bit anytime during the 79usec between bit exchanges removes the CPU from time sensitive involvement.

I've found this plan to output data early won't work. Even though in segher's disassembly, the lock only verifies the Key's Data output once every 79usec, my console is checking it twice. I've shifted the key's output around to determine the thresholds. The Lock appears to check that the Key's data out is low 6cyc/usec prior to setting it's output (Lock Data in). This agrees with the tengen disassembly where data input is checked low 5/6cyc before setting Data out; if data in is high it dies/panics.

Segher doesn't seem to mention which of the two NTSC CIC's his disassembly is for perhaps it's a 6113, and the one in my console is probably a 3193. I haven't bothered to take a screwdriver to my console to confirm. One of the few posts that kevtris didn't delete from the RE thread reports that the only combo of 6113/3193 as lock/key that doesn't work is when 6113 is used as the lock, and the 3193 is used as the key. Perhaps this extra Data input check requiring data to be low has something do to with it.

Beyond that, since segher's disassembly is now fairly safe to assumed to not be the code running on my consoles; that may explain why I don't see the Lock setting Data out for ~9cyc immediately after reset as shown in segher's disassembly.

I was able to determine that there is a roughly 6.7usec window of when the key must transition from low to high when outputting a logic 1. Using the rising edge of Lock Dout as a reference:-Key Dout must be low 4.9usec beforehand.-Key Dout must be high 1.8usec afterwards for a logic 1 bit transfer.-After the transfer, the key is able to leave it's output high all the way up until ~5.5usec before the next bit transfer.

So that's not necessarily terrible news, as a 6.7usec time allowance equates to 26 mcu cycles when running at 4Mhz, and 107 cycles when running at 16Mhz. So there's some hope for servicing the CIC LOCK, and NES CPU both during a single 6usec window of time esp when running at higher frequencies.

While working on my stm8 implementation, I realized there is a rather vital feature that is necessary from a mcu being dual tasked by the CIC and NES CPU. It's a feature that's not available on most AVR's, I'm not sure about PICs as I'm not as familiar with them. If the CIC 4Mhz clock is to be used as a source for the mcu core, the mcu needs to have the ability to switch to it's internal oscillator in application. Because one can't count on there always being a 4Mhz cic clock on toploader and clone consoles. On most AVR's the clock is selected via fuse bits which can't be modified by the application code (an external programmer is needed). So in that situation you'd have no choice but to only run the mcu core off the internal oscillator to keep NES CPU services functional. Perhaps one method around this would be to use the 4Mhz CIC clock to feed a counter input instead.

The stm8 is rather flexible with it's clock source selection and will even switch itself back to the internal oscillator if the external clock source is to fail. It always starts up on the internal osc, and all clock selection modes are available to be programmed in application.

One thing I'm finding to be a bit of an annoyance with the stm8 is cycle counting the instructions with it's 3 stage pipeline isn't very straight forward. Extra cycles get added beyond the execution cycle count when the instruction prefetch buffer needs to be flushed, etc. It also seems alignment of my instructions also has an effect presumably due to the 32Byte prefetch buffer size. I've found the most practical means to ensure proper cycle counting is to verify my 'estimates' with actual measurements with the logic analzer. Then tweak as necessary and ensure that all conditional variances are verified as well before moving on to next operation. So that's a bit annoying but seems to be stable thus far after lots of tweaking and verification.

So far I've captured the stream ID, and output the first 15 transfer bits successfully. Now the challenge of properly timing the mangle calculation. If the cycle counting gets to be too much of a headache I might just switch over to running only on the internal 16Mhz oscillator and using timer counters and interrupts to handle all the timing as I envisioned for a dual tasked version. Shouldn't be too hard to correct for drift by sampling the Lock's output once per transaction.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

Last edited by infiniteneslives on Sat Apr 01, 2017 10:21 pm, edited 1 time in total.

Such a data logger has already been made by kevtris, and the data stream is extremely sparse - short bursts of '1' (each 3 clocks long) followed by huge spans of '0' (ranging from 76 to well over ten thousand).

Note that the CIC is clocked at 4MHz, but the clock is effectively divided by 4, resulting in two 1MHz data streams.

I'm not sure about PICs as I'm not as familiar with them. If the CIC 4Mhz clock is to be used as a source for the mcu core, the mcu needs to have the ability to switch to its internal oscillator in application. Because one can't count on there always being a 4Mhz cic clock on toploader and clone consoles. On most AVR's the clock is selected via fuse bits which can't be modified by the application code (an external programmer is needed). So in that situation you'd have no choice but to only run the mcu core off the internal oscillator to keep NES CPU services functional. Perhaps one method around this would be to use the 4Mhz CIC clock to feed a counter input instead.

PICs give you enough rope here. 1- There's the "Fail-Safe Clock Monitor" fuse setting, which will switch to an internal oscillator if the external one fails. It's handled automatically in hardware.2- In many models, you can switch clock as needed at run-time anyway, but there may be a significant delay if the target oscillator isn't already running3- In most models, you can measure the frequency of an external clock source (Capture every 16 rising edges), and-3b- In some models you can tune the frequency of the internal clock source (Roughly 0.1-0.3% precision)

Yeah I kinda forgot about that thread till lidnariq brought it up again. Read through it all again and still some useful info in there. It's really disappointing to see all the kevtris posts and a few others getting deleted.

I only assume bunnyboy asked that of kevtris as part of his terms to purchase his PIC implementation making it private, and hopes to make it more challenging for others. Was sad at the time to see a community project for everyone's benefit to try to be monopoloized and for their profit alone. Thankfully there was enough other documentation left around to allow others to make their own implementation. But now it's kinda sad just because we lost a bit of history that was contained in that thread. Suppose if I really cared I should reach out to bunnyboy/kevtris and see if the discussions were saved and can be revived now that the monopoly has been dead for a few years.

Quote:

PICs give you enough rope

That's good to hear. Was always annoyed with how easy it is to brick an AVR due to clock issues. Glad to see they're the outlier here. I suppose in their minds making clock selection nonselectable in application could help prevent the application from bricking itself, at the worthy cost of lack of flexibility.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

Yeah I kinda forgot about that thread till lidnariq brought it up again. Read through it all again and still some useful info in there. It's really disappointing to see all the kevtris posts and a few others getting deleted.

I only assume bunnyboy asked that of kevtris as part of his terms to purchase his PIC implementation making it private, and hopes to make it more challenging for others. Was sad at the time to see a community project for everyone's benefit to try to be monopoloized and for their profit alone. Thankfully there was enough other documentation left around to allow others to make their own implementation. But now it's kinda sad just because we lost a bit of history that was contained in that thread. Suppose if I really cared I should reach out to bunnyboy/kevtris and see if the discussions were saved and can be revived now that the monopoly has been dead for a few years.

Ugh. Yeah, that might be nice. (Not all of Kevtris's posts were blanked, though.)

I also wonder if phpbb was always at war with Eastasia has revision history of posts.

Well I got my synchronous implementation working with the STM8 core running on the 4Mhz CIC clock. Still have to implement region switching, and warm reset, but that'll be cake.

The cycle counting had me chasing my tail for quite awhile as SDCC kept relocating my code. The same exact source code was often time compiling to different cycle timing depending on how the wind blew at SDCC.. With the variance in cycles per instruction due to it's 3stage pipeline and prefetch buffer the compiler's relocation of my code was maddening. Eventually I figured out how to force the location of my code to remain constant. Then tweaking the exact cycles became rather easy when I started trading 2xNOP's (1Byte each), with an equivalent NOP such as "ADD A, #0" which is still 2 bytes, but only one execution cycle. That way I could adjust the cycle count without relocating the code that followed my delay.

After learning about the weak pulldowns on the original CIC's i/o, I started dual purposing the CIC RESET pin as a debug pin. Worked pretty well, to aid the timing analysis when my logic analyzer only had 3 channels working till I repaired it. This also means that one can practically get by with only dedicating 2-3 mcu i/o to CIC use. The reset pin is required, but after getting the reset sync from the lock during startup, the mcu can use it as a dedicated output pin. The mcu will be able to detect if the user hits reset on the console because the data in stream will stop, at which point the mcu can set the reset pin back to an input and wait for the reset sync from the lock again. So that's a nifty way to regain another mcu i/o pin.

There's only a couple i/o pins I had planned to dedicate to mcu outputs though. Perhaps SPI MOSI would be the best choice to dual purpose with CIC reset. However I think one might be able to get by tie the IRQ pin to CIC RESET assuming the console's IRQ pullup doesn't over power the CIC's pull-down. Better yet, just tie CIC DATA IN with CIC RESET, the resulting signal should be the ORing of the two signals. Doesn't get much more perfect than that! The sync from the RESET gets embedded directly into the LOCK's DATA OUT signal! When the stream stops coming from the LOCK you simply wait for the reset sync pulse.

I just did a quick check with my logic analyzer with CIC RESET tied to LOCK DATA OUT, and the resulting signal was ORed properly. So back down to only needing 3 CIC i/o pin for a synchronous cycle counted solution. That will only be 2 pins for an asynchronous setup where the mcu runs off it's own 16+Mhz oscillator cutting out CIC CLOCK.

I'll probably take a break for awhile and focus on some other projects for a bit. At some point I'll come back around and tinker with the timers trying out my async idea. Had a simple idea for a proof of concept to actually implement the discrete mapper flipflop in the STM8 while running the CIC at the same time. I'm not sure it can be pulled off, but looking at the timing requirements I think it's feasible. I don't think it would be a good idea or of much benefit to implement the mapper register in that way. But if that can be done with stability, then that would be a pretty good proving point for the hardware and underlying code.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

I don't have anything useful to add to the discussion, just wanted to say that I think this a pretty cool endeavor however it turns out. I would gladly consider licensing code that does something like this for some future mappers, assuming it didn't increase my unit cost weighed against the features provided (of course, it's utility greatly depends on what else ends up on the board).

Thanks Memblers, I'm not sure how far down this rabbit hole I'm going to go, but we'll see!

Today I accidentally stumbled on what might be my new favorite logic IC. Can't believe I didn't know or think to check if such an animal existed till now. The 74LVC1G97 basically like a micro-PLD with 'configurable' gate functions. Effectively a 5cent mux, which isn't that far off from what a switch costs in volume. Adding this guy to a discrete mapper would allow selectable H/V mirroring. Would take some sort of interface to be able to toggle mirroring on the fly during game play obviously. But at a minimum, I'm looking to make it so I can remove the mirroring switch from my discrete mapper design. Then the kazzo can have the ability to twiddle an eeprom bit in the STM8 CIC, and the CIC can set H/V mirroring at boot time. No need to open the case and toggle a switch anymore!

The fact it's also 5v tolerant, and can be configured as any number of gates is pretty legit. Means I only have to stock one IC for dozens of potential uses, and also simplifies the assembly process with only one part to pick from when it comes to a single gate.

_________________If you're gonna play the Game Boy, you gotta learn to play it right. -Kenny Rogers

Who is online

Users browsing this forum: No registered users and 3 guests

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