Here's the updated code - a toggle switch connected to pin 12 will select between MIDI or Joypad mode:

EDIT: updated again...

#include <MIDI.h>

int unmappedBend;
byte mappedBend;
static byte bitMask[] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup()
{  
  pinMode(0, INPUT); // MIDI IN

  pinMode(11, OUTPUT); // 4021 D7 (A Button)
  pinMode(10, OUTPUT); // 4021 D6 (B Button)
  pinMode(9, OUTPUT); // 4021 D5 (Select)
  pinMode(8, OUTPUT); // 4021 D4 (Start)

  pinMode(A3, OUTPUT); // 4021 D3 (Up)
  pinMode(A2, OUTPUT); // 4021 D2 (Down)
  pinMode(A1, OUTPUT); // 4021 D1 (Left)
  pinMode(A0, OUTPUT); // 4021 D0 (Right)

  pinMode(A5, INPUT); // A Button
  pinMode(A4, INPUT); // B Button
  pinMode(2, INPUT); // Select
  pinMode(3, INPUT); // Start
  pinMode(4, INPUT); // Up
  pinMode(5, INPUT); // Down
  pinMode(6, INPUT); // Left
  pinMode(7, INPUT); // Right

  pinMode(12, INPUT); // Toggle Switch

  // set OUTPUT pins HIGH
  PORTB |= B00001111; // pins 8, 9, 10 and 11
  PORTC |= B00001111; // pins A0, A1, A2 and A3
  
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop()
{
  if (PINB & bitMask[4])
  {
    if (MIDI.read() && (MIDI.getType() < B11110000))
    {
      if (MIDI.getType() == NoteOn && MIDI.getData2() > 0)
      {
        if (MIDI.getData1() == 60) // C4
          PORTB &= ~bitMask[3]; // A
        else if (MIDI.getData1() == 62) // D4
          PORTB &= ~bitMask[2]; // B
        else if (MIDI.getData1() == 64) // E4
          PORTB &= ~bitMask[1]; // Select
        else if (MIDI.getData1() == 65) // F4
          PORTB &= ~bitMask[0]; // Start
        else if (MIDI.getData1() == 67) // G4
          PORTC &= ~bitMask[3]; // Up
        else if (MIDI.getData1() == 69) // A4
          PORTC &= ~bitMask[2]; // Down
        else if (MIDI.getData1() == 71) // B4
          PORTC &= ~bitMask[1]; // Left
        else if (MIDI.getData1() == 72) // C5
          PORTC &= ~bitMask[0]; // Right
      }

      else if (MIDI.getType() == NoteOff || (MIDI.getType() == NoteOn && MIDI.getData2() == 0))
      {
        if (MIDI.getData1() == 60) // C4
          PORTB |= bitMask[3]; // A
        else if (MIDI.getData1() == 62) // D4
          PORTB |= bitMask[2]; // B
        else if (MIDI.getData1() == 64) // E4
          PORTB |= bitMask[1]; // Select
        else if (MIDI.getData1() == 65) // F4
          PORTB |= bitMask[0]; // Start
        else if (MIDI.getData1() == 67) // G4
          PORTC |= bitMask[3]; // Up
        else if (MIDI.getData1() == 69) // A4
          PORTC |= bitMask[2]; // Down
        else if (MIDI.getData1() == 71) // B4
          PORTC |= bitMask[1]; // Left
        else if (MIDI.getData1() == 72) // C5
          PORTC |= bitMask[0]; // Right
      }

      else if (MIDI.getType() == PitchBend)
      {
        unmappedBend = (int)((MIDI.getData1() & B01111111) | ((MIDI.getData2() & B01111111) << 7));
        mappedBend = map(unmappedBend, 0, 16383, 165, 5); // Arkanoid Paddle range, centered at 170 (+/-80)

        // Paddle Position
        if (mappedBend & bitMask[7]) // A
          PORTB &= ~bitMask[3];
        else
          PORTB |= bitMask[3];
        if (mappedBend & bitMask[6]) // B
          PORTB &= ~bitMask[2];
        else
          PORTB |= bitMask[2];
        if (mappedBend & bitMask[5]) // Select
          PORTB &= ~bitMask[1];
        else
          PORTB |= bitMask[1];
        if (mappedBend & bitMask[4]) // Start
          PORTB &= ~bitMask[0];
        else
          PORTB |= bitMask[0];
        if (mappedBend & bitMask[3]) // Up
          PORTC &= ~bitMask[3];
        else
          PORTC |= bitMask[3];
        if (mappedBend & bitMask[2]) // Down
          PORTC &= ~bitMask[2];
        else
          PORTC |= bitMask[2];
        if (mappedBend & bitMask[1]) // Left
          PORTC &= ~bitMask[1];
        else
          PORTC |= bitMask[1];
        if (mappedBend & bitMask[0]) // Right
          PORTC &= ~bitMask[0];
        else
          PORTC |= bitMask[0];
      }      
    }
  }

  else
  {
    delay(1);

    // read Joypad buttons directly
    if (PINC & bitMask[5]) // A
      PORTB |= bitMask[3];
    else
      PORTB &= ~bitMask[3];
    if (PINC & bitMask[4]) // B
      PORTB |= bitMask[2];
    else
      PORTB &= ~bitMask[2];
    if (PIND & bitMask[2]) // Select
      PORTB |= bitMask[1];
    else
      PORTB &= ~bitMask[1];
    if (PIND & bitMask[3]) // Start
      PORTB |= bitMask[0];
    else
      PORTB &= ~bitMask[0];
    if (PIND & bitMask[4]) // Up
      PORTC |= bitMask[3];
    else
      PORTC &= ~bitMask[3];
    if (PIND & bitMask[5]) // Down
      PORTC |= bitMask[2];
    else
      PORTC &= ~bitMask[2];
    if (PIND & bitMask[6]) // Left
      PORTC |= bitMask[1];
    else
      PORTC &= ~bitMask[1];
    if (PIND & bitMask[7]) // Right
      PORTC |= bitMask[0];
    else
      PORTC &= ~bitMask[0];
  }
}
yogi wrote:

A brute force approach could be adding a second 4021, with the arduino in the middle-reading the KB 4021 and outputting a parallel byte to the second NES 4021.

Another alternative would be to go ahead and cut the shift register input pins from their original connections to the joypad, wire them up to the Arduino for MIDI control, and then make connections directly to the pads on the controller PCB for detecting button presses - read them into the Arduino directly and bypass the shift register! Simple on / off, like how an Atari joystick works - just wire eight Arduino pins to the pads highlighted here in blue, the pins should be held high by the joypad's pull-ups and then when the buttons are pressed those pins should be pulled low:

yogi wrote:

Understand. Still seems doable without too much pain. Will think this through a bit.
A brute force approach could be adding a second 4021, with the arduino in the middle-reading the KB 4021 and outputting a parallel byte to the second  NES 4021.

That sounds workable, yes!

yogi wrote:

Remeber seeing code somewhere of a AVR Gamepad, but this will complicate your code a bit.

This would be a good starting point:

http://code.google.com/p/nespad/

yogi wrote:

Thanks for the code!

You're welcome!

yogi wrote:

Got a couple of ProMicro Leonardo clones coming from HK (for another project) so if things workout, you got it!

heart

yogi wrote:
uXe wrote:

Just occurred to me though - not sure if the buttons on the joypad itself could still be functional or if you would need to cut the pins from their previous connections before you wire them to the Arduino... wondering what would happen if you are trying to pull a pin low with the Arduino if it is still being held high by the joypad's built-in pull-ups, or try to pull a pin low by pressing a button on the joypad when it is being held high by the Arduino?

Well you may have a point, will look into this. Off the top of my head, a work-around would be letting the Arduino sacn the KB and then interleave button presses with Midi messages to send to the NES. Haven't looked thru your code, but you are simulating the Game pad with the Arduino? If so, adding a key scan may be possible?
Yogi

No, the Arduino is not simulating a joypad. The FamiiDI shield does have connections to Clock and Latch, but it also has a 4021 shift register onboard - and it is much quicker and easier to just feed the shift register with button presses and let it do its thing than to try and make the Arduino pretend to be a shift register, and be able to keep up with something that is so timing-dependant while it is doing several other things at the same time!

And in the case of the code I have provided for a 'quick and dirty' solution without the FamiiDI shield, the joypad's 4021 is just taking the place of the 4021 on the shield.

You could just as easily buy a shift register IC from any electronics supplier, wire that to the Arduino, and then wire it up internally directly to the NES Expansion Port pins without having to sacrifice a joypad. It is just that a joypad happens to be a quick and dirty way of getting hold of both a 4021 shift register and a cable that lets you communicate with the NES! smile

117

(1 replies, posted in Nintendo Handhelds)

Here's a similar thread:

http://chipmusic.org/forums/topic/9505/ … ge-to-dmg/

and kitsch was working on a converter board at one point:

http://chipmusic.org/forums/post/155783/#p155783

uXe wrote:

and then open up a NES joypad and connect the 8 input pins on the joypad's shift register to 8 pins on the Arduino and you'd have yourself a MIDI controlled NES joypad! smile You would even have enough spare pins to connect another 8 to a second joypad if you really wanted to...

...or connect 12 pins to a SNES joypad instead and you'd have yourself a MIDI controlled SNES joypad! smile

Just occurred to me though - not sure if the buttons on the joypad itself could still be functional or if you would need to cut the pins from their previous connections before you wire them to the Arduino... wondering what would happen if you are trying to pull a pin low with the Arduino if it is still being held high by the joypad's built-in pull-ups, or try to pull a pin low by pressing a button on the joypad when it is being held high by the Arduino?

...if anybody does decide to build this into a joypad and wants to make an extra one for me (I would pay for parts / postage of course) then nothing would make me happier! smile

Enjoy!

Here's the code, you'll need to have the MIDI library installed in your Arduino IDE:

http://playground.arduino.cc/Main/MIDILibrary

and you can safely set 'COMPILE_MIDI_OUT' 'COMPILE_MIDI_THRU' and 'USE_CALLBACKS' to 0 in the MIDI.h file to reduce the size of your compiled sketch. Connect the Arduino pins to the NES joypad's 4021 shift register inputs as they are labelled in the setup routine and you should be good to go! smile

This will map the eight buttons to MIDI notes C4 D4 E4 F4 G4 A4 B4 and C5, but you can change this to whatever notes you want, or experiment with MIDI Continuous Controller values or whatever...

PS. if you want to play with the Arkanoid paddle stuff let me know your E-Mail address and I'll send you an Arkanoid ROM that's modified to read input at $4017.0 - although you won't have a paddle button unless you wire up some kind of 'on / off' value separately to $4016.1 on the NES Expansion Port!

#include <MIDI.h>

int unmappedBend;
byte mappedBend;
static byte bitMask[] = {1, 2, 4, 8, 16, 32, 64, 128};

void setup()
{  
  pinMode(0, INPUT); // MIDI IN

  pinMode(11, OUTPUT); // 4021 D7 (A Button)
  pinMode(10, OUTPUT); // 4021 D6 (B Button)
  pinMode(9, OUTPUT); // 4021 D5 (Select)
  pinMode(8, OUTPUT); // 4021 D4 (Start)

  pinMode(A3, OUTPUT); // 4021 D3 (Up)
  pinMode(A2, OUTPUT); // 4021 D2 (Down)
  pinMode(A1, OUTPUT); // 4021 D1 (Left)
  pinMode(A0, OUTPUT); // 4021 D0 (Right)

  // set OUTPUT pins HIGH
  PORTB |= B00001111; // pins 8, 9, 10 and 11
  PORTC |= B00001111; // pins A0, A1, A2 and A3
  
  MIDI.begin(MIDI_CHANNEL_OMNI);
}

void loop()
{
  if (MIDI.read() && (MIDI.getType() < B11110000))
  {
    if (MIDI.getType() == NoteOn && MIDI.getData2() > 0)
    {
      if (MIDI.getData1() == 60) // C4
        PORTB &= ~bitMask[3]; // A
      else if (MIDI.getData1() == 62) // D4
        PORTB &= ~bitMask[2]; // B
      else if (MIDI.getData1() == 64) // E4
        PORTB &= ~bitMask[1]; // Select
      else if (MIDI.getData1() == 65) // F4
        PORTB &= ~bitMask[0]; // Start
      else if (MIDI.getData1() == 67) // G4
        PORTC &= ~bitMask[3]; // Up
      else if (MIDI.getData1() == 69) // A4
        PORTC &= ~bitMask[2]; // Down
      else if (MIDI.getData1() == 71) // B4
        PORTC &= ~bitMask[1]; // Left
      else if (MIDI.getData1() == 72) // C5
        PORTC &= ~bitMask[0]; // Right
    }

    else if (MIDI.getType() == NoteOff || (MIDI.getType() == NoteOn && MIDI.getData2() == 0))
    {
      if (MIDI.getData1() == 60) // C4
        PORTB |= bitMask[3]; // A
      else if (MIDI.getData1() == 62) // D4
        PORTB |= bitMask[2]; // B
      else if (MIDI.getData1() == 64) // E4
        PORTB |= bitMask[1]; // Select
      else if (MIDI.getData1() == 65) // F4
        PORTB |= bitMask[0]; // Start
      else if (MIDI.getData1() == 67) // G4
        PORTC |= bitMask[3]; // Up
      else if (MIDI.getData1() == 69) // A4
        PORTC |= bitMask[2]; // Down
      else if (MIDI.getData1() == 71) // B4
        PORTC |= bitMask[1]; // Left
      else if (MIDI.getData1() == 72) // C5
        PORTC |= bitMask[0]; // Right
    }

    else if (MIDI.getType() == PitchBend)
    {
      unmappedBend = (int)((MIDI.getData1() & B01111111) | ((MIDI.getData2() & B01111111) << 7));
      mappedBend = map(unmappedBend, 0, 16383, 165, 5); // Arkanoid Paddle range, centered at 170 (+/-80)

      // Paddle Position
      if (mappedBend & bitMask[7]) // A
        PORTB &= ~bitMask[3];
      else
        PORTB |= bitMask[3];
      if (mappedBend & bitMask[6]) // B
        PORTB &= ~bitMask[2];
      else
        PORTB |= bitMask[2];
      if (mappedBend & bitMask[5]) // Select
        PORTB &= ~bitMask[1];
      else
        PORTB |= bitMask[1];
      if (mappedBend & bitMask[4]) // Start
        PORTB &= ~bitMask[0];
      else
        PORTB |= bitMask[0];
      if (mappedBend & bitMask[3]) // Up
        PORTC &= ~bitMask[3];
      else
        PORTC |= bitMask[3];
      if (mappedBend & bitMask[2]) // Down
        PORTC &= ~bitMask[2];
      else
        PORTC |= bitMask[2];
      if (mappedBend & bitMask[1]) // Left
        PORTC &= ~bitMask[1];
      else
        PORTC |= bitMask[1];
      if (mappedBend & bitMask[0]) // Right
        PORTC &= ~bitMask[0];
      else
        PORTC |= bitMask[0];
    }      
  }
}

I would be happy to have a batch of these shields made if there is enough interest - I'll keep a list of interested people, and if the list gets long enough then we can go ahead and put in an order! From what I've been told they should only cost about $8 each to produce...

The 5V and Ground connections in that circuit I linked to could just be connected to the Arduino's 5V and Ground pins, but yes the Arduino would need a power supply. I'm using a Duemilanove (ATmega328) because I already had a couple of them around - the recommended input voltage range for the Duemilanove is 7 to 12 volts. Also, I stuck with the Duemilanove because I know the operating voltage on the Duemilanove's pins are 5V, like the NES. I think some newer Arduino boards are 3.3V?

Note: the Nunchuk will work at 5V, but is supposed to operate at 3.3V, so the FamiiDI shield includes the same circuit used in the Video Game Shield to translate the levels:

I haven't had any reason to look at what else is on offer to be able to give any recommendations for Arduino-shopping, but I'm sure there are others here who can! smile

When I get the time I'll work on cutting-down the source to that quick and dirty version...

stargazer wrote:

Awesome dude! Any immediate plans to release the source?

Thanks! The source is pretty straight-forward, but it is written to work specifically with the shield - if you are just interested in the MIDI side of the project, and wanted to build it yourself quick and dirty, I could send you a cut-down version of the source and you would just need to build the standard Arduino 'MIDI IN' circuit, like this:

and then open up a NES joypad and connect the 8 input pins on the joypad's shift register to 8 pins on the Arduino and you'd have yourself a MIDI controlled NES joypad! smile You would even have enough spare pins to connect another 8 to a second joypad if you really wanted to...

I should mention, with the Arkanoid Paddle emulation stuff it is either / or, you can't be using the Arduino to emulate paddle position and a joypad on the same shift register at the same time because they both want to be in control of the shift register!

TylerBarnes wrote:

This looks so cool. So it is essentially converting midi data into button-press data?

Yep! (that is not all it can do though)

MCTRL does the same thing:

http://www.ninstrument.com/?page_id=783

I mentioned this here:

http://chipmusic.org/forums/post/189085/#p189085

And now I've finally gotten around to writing the code to get it off the ground, so here is some information and some demonstration:

FamiiDI: MIDI Input & Wii Nunchuk arduino shield for the NES / Famicom


FamiiDI (Famicom / Wii Nunchuk / MIDI) is an Arduino shield that reads in data from a MIDI serial connection, or a Wii Nunchuk controller, and translates that data to the 15-pin 'Famicom Expansion Port' standard.

All of the 15-pin Famicom Expansion Port signals are also present on the 48-pin NES Expansion Port that lurks hidden on the console's underside - and there is a great little device called the 'ENIO EXP Board' that acts as a 48-pin to 15-pin converter if you don't like the idea of soldering directly to the NES motherboard (or cutting the cable off a joypad to build your own 15-pin to 7-pin cable to connect directly to the NES Controller Port).

The FamiiDI shield appears to the NES as a joypad connected to Controller Port 2, so you can still have a regular joypad connected to Controller Port 1 without any conflicts. Demonstration # 1 in the video shows a MIDI sequence being played from a laptop into the FamiiDI board. The Arduino then maps the MIDI Note On / Off data received (note numbers 59-66, or B3-F#4) to each of the eight joypad buttons (A, B, Select, Start, Up, Down, Left, Right) the NES is running a Controller Test ROM which plays a different musical pitch for each button pressed.

The video also demonstrates sending a proportional analog input (rather than just digital on / off button presses) to emulate an Arkanoid Paddle by taking an 8-bit value (0-255) and mapping each of the 8 bits to the eight button presses read in by the NES input register at $4017.0 (a separate on / off value for the Paddle Button is sent to input register $4016.1).

PS. The 15-pin Expansion Port standard also means there is the potential to map another four Note On / Off signals, so rather than just eight notes (only the white piano keys) you could send a full twelve notes (both the black and white keys). The four additional pins present on the FamiiDI shield are:

$4016.1 (traditionally used for the Arkanoid Paddle Button)
$4017.1
$4017.3 (traditionally used for the Zapper Gun Light Sensor)
$4017.4 (traditionally used for the Zapper Gun Trigger)

PPS. Because of the potential for so many 'modes' I've also put 3 dip switches on board to allow for code that reads the state of the switches and changes mode accordingly, and there is also an RGB LED on board wired directly to the dip switches for quick and easy representation of the selected mode by color:

(0. 000, Off)
1. 001, Green
2. 010, Blue
3. 011, Blue + Green = Cyan
4. 100, Red
5. 101, Red + Green = Yellow
6. 110, Red + Blue = Pink
7. 111, Red + Blue + Green = White

bitjacker wrote:

in soviet russia computer tracks you.

big_smile

I have a 'Primo': http://primo.homeserver.hu/html/inenglish.html

BGB has 'TCP/IP game link support'!

http://bgb.bircd.org/

I have a couple of 07's and twenty-something 08's and they all have the blobs - the other thing I noticed is that all of the blobbed-boys say "Made in China" rather than "Made in Japan".

I also have thirteen 02's and four 03's that have the 'A' revision of the CPU if they are of interest to anybody?

(and an 06 with a 'C' revision CPU - but I'm keeping that one!)

...another etsy shop - is this kitsch? or just someone selling kitsch's stuff?

http://www.etsy.com/shop/HighClassRetro