Creating a Built in 4 Score device

Started by lifewithmatthew, September 14, 2021, 11:57:14 am

Previous topic - Next topic

P

Yeah, that's what I thought too. 4016.D1 and 4017.D1 are available in the NES expansion port (pin 12 and 20) so it's just a matter of switching to those pins and swap the two signature bytes (the one for 4016.D0 goes to 4017.D1 and vice versa) for the Hori multitap method to work.
For the "simple" method I guess you could just send first two controllers to the two D0s and the other two to the two D1s, and send no signature to either.

You could also add a microphone (or just a pushbutton) to 4016.D2 (pin 33) and shout on bunnies. ;D

emerson

Quote from: lifewithmatthew on September 27, 2021, 09:35:52 am3 ICs and you could have a very basic solutions using just ICs.

I admit my 10-12 chip solution quote is pretty generous, but I disagree with this for three reasons:
- One, if a three chip solution were possible Nintendo would not have paid to have a custom chip made.
- Two, if two of the three chips hold the signatures, that means your third chip would be a dual 3-1 multiplexer that counts clocks and automatically changes multiplexer input every 8 clocks. In other words, an FPA-92-S01 minus some 8-bit shift registers.
- Three, if it were really that easy you would likely find schematics for it throughout the internet as you do NES/Famicom controllers.

ASICs are used when you want to cram a lot of circuitry into a relatively small enclosure. Therefore, if you see an ASIC it's safe to assume that the logical equivalent is at least somewhat complex and worth the cost of manufacturing it. Now I am curious what the lowest chip count solution is for a pure logic four-score...

Quote from: lifewithmatthew on September 27, 2021, 09:59:21 amAs for the way the diodes are connected... I mean your drawing isn't wrong.

Thank you for the images. I know my drawing isn't wrong but as I suspected your schematic is. I didn't want to assume before in case there was some weird hardware recall and you happened to have one that got through. I understand that physically some parts are in parallel and some aren't but physical orientation has little to do with how they are actually connected in circuit. You detailed the solution perfectly in the image with the highlighted diodes and resistors, now compare that to your schematic.

Do you plan to use the zener diodes in your end design? I am unaware of any specific design considerations when it comes to zener diodes aside from max current capability. I would think as long as it can handle the current any 6.2v zener diode should work fine.

I am glad to hear you have a microcontroller solution working!

emerson

September 27, 2021, 06:11:33 pm #17 Last Edit: September 27, 2021, 07:25:27 pm by emerson
After fooling around in Kicad for a while the best solution I can get is 8 chips and two transistors. This does not include turbo.

Edit: You don't need the transistors, logic chips only can do it.

emerson

I think I have it down to 6 chips and 2 transistors but I'm not certain without building/simulating it.

Also, after all my talk about U1 being an ASIC, it hit me this morning that "FPA" could possibly stand for "Field Programmable Array".

lifewithmatthew

Quote from: P on September 18, 2021, 03:22:28 pmIf you build a Four-Score you need to make sure the signature is wired or games won't detect it as connected.

On that program you wrote, can you confirm the signature it's looking for for the four score?

I've worked out my program such that it sees all four controllers in the program, but using the FDS program you sent, only controller 1 and 2 data are being seen at the NES.  However, the FDS program does recognize my actual Four Score when I plug it in.

Right now I have a 16 bit variable that holds the values for the 2 controllers (1 and 3 or 2 and 4), and then an 8 bit variable that holds the signature.  After 15 pulses have been read it swaps out the controller data with the signature and sends that.  For controllers 1 and 3 I have the signature set to 8 (which would be binary 00001000) and for controllers 2 and 4 I have the the signature set to 4 (which would be binary 00000100).

P

September 30, 2021, 10:03:02 am #20 Last Edit: September 30, 2021, 10:08:17 am by P
You seem to have the signature backwards. It should be 16 and 32 respectively in decimal, not 8 and 4 (this is of course assuming that bits are rolling in from right to left like in my program). Check the @nes_multitap_id routine in my source and you should see this piece of code:

@loop_nmid2:
  lda $4016
  lsr a
  rol temp+0
  lda $4017
  lsr a
  rol temp+1           ;save ID in RAM
  dex
  bne @loop_nmid2
  lda temp+0
  cmp #%00010000
  bne @nm_off
  lda temp+1
  cmp #%00100000
  bne @nm_off
The 16-byte Four Score ID is saved in RAM registers temp+0 and temp+1, which are then compared with the expected values and branches off if either is incorrect.

lifewithmatthew

Quote from: P on September 30, 2021, 10:03:02 amYou seem to have the signature backwards. It should be 16 and 32 respectively in decimal, not 8 and 4 (this is of course assuming that bits are rolling in from right to left like in my program).

Just to make sure, when it gets to your program do you consider a "0" to indicate the button is pressed or not pressed?

I changed the way I processed my code to improve speed and it's working REALLY well except the signature bit.  At this point I have three 8-bit variables for each controller pair.  When I get the latch I reset back to the first bit of the first controller, after 8 clock pulses I swap to the next controller, 8 pulses later I swap to the signature bits.

I've put in some debug code and can confirm it makes it all the way to the signature bits, and I've tried all kinds of signatures for the controllers but I can't get it to work :(  At this point I wish I had an oscilloscope that I could connect to a four score so I could compare it to my setup to see what it is I'm missing!

lifewithmatthew

YYYYYEEEEESSSSS!!!!  That was the secret!  The signature bits are reported as seen by the NES, but that's the opposite values that are ELECTRICALLY SENT!  For my needs a 1 represents an unpressed button and a zero represents a pressed button.




Also, the bits are stored opposite as to how you receive them apparently.  So for controllers 1/3 the signature bits were 11110111 and for controllers 2/4 the signature bits were 11111011 (or 247 for controller 1/3 and 251 for controllers 2/4).

Thanks for helping me work this out, I am beyond thrilled with it!

I do have a couple of lingering issues:
1) I'm currently having to use 2 boards since I didn't have enough interrupts on one.  I hope to be able to replace this with a single board.
2) I'm getting some flashing on controllers 3 and 4.  I think for some reason the "multitap" (MatthewTap, lol) is occasionally getting the latch prior to finishing sending the signature.  I'll test it out with RC-PRO AM 2 and see how well it works for players 3 and 4 later.

emerson

I have never programmed Arduino before but I do mess with PIC microcontrollers. Something like the example code below should allow you to handle all incoming signals within the interrupt routine. Is something like this possible with the Arduino?

//This example assumes that $4016.LATCH, $4016.CLK and $4017.CLK are on PORTB bits 0, 1 and 2 respectively. The interrupt is triggered by a PORTB pin state change irq.


void interrupt __FourScoreIRQ();
x = PORTB and 0x07; //isolate latch and clock lines
switch (x) {
case 0x07: //latch high pulse detected

//latch all controllers here
       
case 0x04: //$4016.CLK low pulse detected

//$4016 read routine here

case 0x02: //$4017.CLK low pulse detected

//$4017 read routine here
     }

     while 0x06 != PORTB and 0x06 //loop until default state is returned to avoid false triggers
     wend
     retfie     //return from interrupt

lifewithmatthew

The Arduino does have interrupts (without using them, I'm convinced it would be impossible to make this code work), but depending on which ATMega you're using there are a limited number of interrupts.  The most prolific ATMega only provides 2 interrupts.  Now that I've worked out the correct way to do things, I'm going to try some of the other boards that have more interrupts to see if I can get it working.

P

The game always sees 1 as pressed and 0 unpressed, and my program does nothing to change that. I know that the controllers are using reverse logic for buttons so that 0 means pressed. I'm guessing the I/O hardware in the console is inverting the controller data before the game sees it.

Pretty cool that you almost got it to work though! :)

emerson

I think with some well structured code you could pull this off with no interrupts whatsoever, or a maximum of one if absolutely necessary. All you need is a state machine that tests the latch and two clock pulse inputs and executes only the necessary code based on the active input signal. The code would need to complete all computations and return to the input polling loop before the next signal is expected, and because your design successfully communicates with real hardware means you're already half way there.

If you want some help with a one or no interrupt solution I'd be happy to take a look at your code and give some ideas (either here or PM). With that being said, you are doing what makes sense to you and getting successful results and that's what it's all about. Good work!

P

I'm just worried the microcontroller is fast enough. And since Arduino is used, that means C++ instead of assembly, introducing some overhead.

emerson

Quote from: P on October 02, 2021, 12:06:42 pmI'm just worried the microcontroller is fast enough. And since Arduino is used, that means C++ instead of assembly, introducing some overhead.

I agree. All the more reason for well structured code. In my PS/2 keyboard + mouse to NES adapter I only used one interrupt to reset a timer. This design required the PIC being a middle-man between three separate devices that all provide their own clock signals for data transfer. Certainly more complicated then polling four shift registers. This was done at only 4 MHz and written in XC8 which is a C variant for PIC microcontrollers. If I were to write it again today I would use assembly for sure.

If I could accomplish this with basic specs then the OP should be able to accomplish reading four shift registers using similar specs.

P

Yeah well, no use in dismissing it before it has been tried.