Need help with an NES controller code

Hey ho everyone. I need some help trying to get this code to read two different NES controller presses. But the code I found is giving me a hard time about it. I found the code that someone made here:

https://docs.google.com/a/acidbabies.com/folder/d/0B8X8TmxLLUQiS28wcjBIQXJJaFk/edit

The original code can be found here:

http://www.thehelloworld.info/

I can upload it to the arduino and read one controller like a dream. But I want to be able to run two controllers on the same arduino. I can wire the two controllers easily. But the code is giving me trouble in trying to achieve this. Here is the code that I had altered:

#include <MeetAndroid.h>

MeetAndroid meetAndroid;
int latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int data = 4; // set the data pin
int controllerData[16]; // array to store data from 16 clock cycles

/* SETUP */
void setup()
{

  // set baud rate to 57.6k
  Serial.begin(57600);
 
  // set output/input pins
  pinMode(latch,OUTPUT);
  pinMode(clock,OUTPUT);
  pinMode(data,INPUT);
 
  // set latch and clock high
  digitalWrite(latch,HIGH);
  digitalWrite(clock,HIGH);
}

/* THIS READS DATA FROM THE CONTROLLER */
void controllerRead()
{
  // set latch and clock low
  digitalWrite(latch,LOW);
  digitalWrite(clock,LOW);
 
  // set latch high to trigger controller data send
  digitalWrite(latch,HIGH);
  delayMicroseconds(4);
  digitalWrite(latch,LOW);
  delayMicroseconds(2);
 
  // Clock Cycle 1
  controllerData[0] = digitalRead(data);
 
  // Clock Cycles 2-16
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock,LOW);
    delayMicroseconds(4);
    controllerData[i] = digitalRead(data);
  }
}

// NES Button Reference
// 01111111 - A [0]
// 10111111 - B [1]
// 11011111 - SELECT [2]
// 11101111 - START [3]
// 11110111 - UP [4]
// 11111011 - DOWN [5]
// 11111101 - LEFT [6]
// 11111110 - RIGHT [7]
// UP+RIGHT
// UP+LEFT
// DOWN+RIGHT
// DOWN+LEFT

/* MAIN LOOP */
void loop()
{
  controllerRead();
  String Out = "";
  int length = 1;
 
 
  // A
  if (controllerData[0] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "QZ";
    length = length + 2;
  }
 
  // B
  if (controllerData[1] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "WL";
    length = length + 2;
  }

  // SELECT
  if (controllerData[2] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "EK";
    length = length + 2;
  }
 
  // START
  if (controllerData[3] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "UJ";
    length = length + 2;
  }
 
  // UP
  if (controllerData[4] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "I1";
    length = length + 2;
  }
 
  // DOWN
  else if (controllerData[5] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "AS";
    length = length + 2;
  }
 
  // LEFT
  else if (controllerData[6] == 0)
  {

    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "DA";
    length = length + 2;
  }
 
  // RIGHT
  else if (controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "SI";
    length = length + 2;
  }

  // UP+RIGHT
  if (controllerData[4] == 0 && controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "KU";
    length = length + 2;
  }
 
  // UP+LEFT
  else if (controllerData[4] == 0 && controllerData[6] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "JE";
    length = length + 2;
  }
 
  // DOWN+RIGHT
  else if (controllerData[5] == 0 && controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "LQ";
    length = length + 2;
  }
 
  // DOWN+LEFT
  else if (controllerData[5] == 0 && controllerData[6] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "ZW";
    length = length + 2;
  }
     
  char outData[length];
  Out.toCharArray(outData, length);
 
  meetAndroid.send(outData);
  Serial.println(outData);
  delay(16);
}

Only thing that I did was remove all LED code since I don't have any, tightened the sensitivity of the button presses, and I added two keystrokes to each button press. I had to look at it for a long time, but the code that allows me to do that is right below the keystroke mapping "length = length + 2;" You can set that number to as many keystrokes as you want, which is great. You just set each controller in the emulator to read only one key. The problem is that the code only seems to recognise only certain keystokes. It will recongnise keys like "QWEU" but not keys like "OPH" can anyone look at this code and tell me why that is? The only thing that I can think of is that this code was designed for an SNES controller, therefore can only recgonise 16 keystrokes. But I can't find anywhere what specifies that or how I can change that. Anyone might have an idea? I know very little of arduino coding only but from tutorials I have watched online, so your help would be gratefully appreciated. Thanks guys, later.

So it looks like it reads from one controller connected to pins 2, 3, and 4. Do you have another controller connected to a different set of three pins? I don't see any code for reading a second controller.

Did you mean that when you press Down (5) and Right (7) together you are getting only Down ("AS") and not Right ("SI") or Down-Right ("LQ")? That's because the big chain of IF-ELSE will only execute the first matching option it finds. Since Down will match
"if (controllerData[5] == 0)" it will not go on to check "if (controllerData[5] == 0 && controllerData[6] == 0)" or" if (controllerData[5] == 0 && controllerData[7] == 0)".

johnwasser:
So it looks like it reads from one controller connected to pins 2, 3, and 4. Do you have another controller connected to a different set of three pins? I don't see any code for reading a second controller.

No, I will simply expose a portion of the three wires (2,3,4) and wrap an striped wire around it so it can split off the connection. The reason I have to wire it like that is that If I try to add extra int pins like below:

latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int data = 4; // set the data pin
latch = 5; // set the latch pin
int clock = 6; // set the clock pin
int data = 7; // set the data pin

The sketch would give me an error in the upload. I can't seem to get extra pin inputs to upload properly (although it would be ideal), so I will simply wire it as explained above. I had to do something similar to wire the controller 3.5v and the bluesmirf 3.5v together so I can get it to talk to my android (which is the ultimate goal).

johnwasser:
Did you mean that when you press Down (5) and Right (7) together you are getting only Down ("AS") and not Right ("SI") or Down-Right ("LQ")? That's because the big chain of IF-ELSE will only execute the first matching option it finds. Since Down will match
"if (controllerData[5] == 0)" it will not go on to check "if (controllerData[5] == 0 && controllerData[6] == 0)" or" if (controllerData[5] == 0 && controllerData[7] == 0)".

Hum, I think you might be onto something there. You picked out a bug with the d-pad that I have been experiencing but didn't mention in the post above. Its kind of hard for me to explain, but when I press Down (5) to Down+Right (57), when I press Right (7), it doesn't read it as being pressed. I have to lift my thumb and press it again for it to read. It basically doesn't let me roll the dpad at all. Does this symptom sound like the issue you addressed? If you think so, what would you suggest I change it to? This was something I was going to ask about later on, but it seems like you may have found the problem without me even mentioning it. Good job, and thanks!

No, where my problem lies is why I can't use every key on the keyboard. When I press Down, I get "AS" (but in actuality I really get "LS" the amarino program reads certain keys but types them as something else. Thats something else I would like to mention, but we can get back to that later). And when I press Down+Right I get "ASLQ" I can recieve all four letters because of changing that "length = length + 2;" line. But I can't, for example, change Down "AS" to Down "PS" It will only read the letter "S" and I have no idea why. Is there anything that I'm not explaining (considering I know little about this stuff)?

No, I will simply expose a portion of the three wires (2,3,4) and wrap an striped wire around it so it can split off the connection.

That will not work.

The reason I have to wire it like that is that If I try to add extra int pins like below:

latch = 2; // set the latch pin
int clock = 3; // set the clock pin
int data = 4; // set the data pin
latch = 5; // set the latch pin
int clock = 6; // set the clock pin
int data = 7; // set the data pin

The sketch would give me an error in the upload.

Well, of course it will. You could study the message, and see that it is telling you that you can't have two variables of the same name.

Hint:

int latch1 = 2;
int latch2 = 5;

Technically, the error is not in the upload. That happens after the compiler gets done and the linker does its job. You are causing a failure far earlier that the uploader.

PaulS:
Well, of course it will. You could study the message, and see that it is telling you that you can't have two variables of the same name.

Hint:

int latch1 = 2;

int latch2 = 5;




Technically, the error is not in the upload. That happens after the compiler gets done and the linker does its job. You are causing a failure far earlier that the uploader.

Yeah your right, I should have said compiler. I always upload because it compiles for me before it shoots it out over the USB. So your saying that if I specify different latches and clocks in the code that I can divide it? I just typed that into my code and made doubles off all the "void setup" code. But by the time I got done with that, the compiler gave me an error that I don't understand. Heres my new code I just entered.

#include <MeetAndroid.h>

MeetAndroid meetAndroid;
int latch1 = 2; // set the latch pin
int clock1 = 3; // set the clock pin
int data1 = 4; // set the data pin
int latch2 = 5; // set the latch pin
int clock2 = 6; // set the clock pin
int data2 = 7; // set the data pin
int controllerData1[16]; // array to store data from 16 clock cycles
int controllerData2[16]; // array to store data from 16 clock cycles

/* SETUP */
void setup()
{

  // set baud rate to 57.6k
  Serial.begin(57600);
 
  // set output/input pins
  pinMode(latch1,OUTPUT);
  pinMode(clock1,OUTPUT);
  pinMode(data1,INPUT);
  pinMode(latch2,OUTPUT);
  pinMode(clock2,OUTPUT);
  pinMode(data2,INPUT);
 
  // set latch and clock high
  digitalWrite(latch1,HIGH);
  digitalWrite(clock1,HIGH);
  digitalWrite(latch2,HIGH);
  digitalWrite(clock2,HIGH);

}

/* THIS READS DATA FROM THE CONTROLLER */
void controllerRead()
{
  // set latch and clock low
  digitalWrite(latch1,LOW);
  digitalWrite(clock1,LOW);
  digitalWrite(latch2,LOW);
  digitalWrite(clock2,LOW);
 
  // set latch high to trigger controller data send
  digitalWrite(latch1,HIGH);
  delayMicroseconds(4);
  digitalWrite(latch1,LOW);
  delayMicroseconds(2);
  digitalWrite(latch2,HIGH);
  delayMicroseconds(4);
  digitalWrite(latch2,LOW);
  delayMicroseconds(2);
 
  // Clock Cycle 1
  controllerData1[0] = digitalRead(data1);
  controllerData2[0] = digitalRead(data2);
 
  // Clock Cycles 2-16
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock1,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock1,LOW);
    delayMicroseconds(4);
    controllerData1[i] = digitalRead(data1);
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock2,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock2,LOW);
    delayMicroseconds(4);
    controllerData2[i] = digitalRead(data2);
  }
}

// NES Button Reference
// 01111111 - A [0]
// 10111111 - B [1]
// 11011111 - SELECT [2]
// 11101111 - START [3]
// 11110111 - UP [4]
// 11111011 - DOWN [5]
// 11111101 - LEFT [6]
// 11111110 - RIGHT [7]
// UP+RIGHT
// UP+LEFT
// DOWN+RIGHT
// DOWN+LEFT

/* MAIN LOOP */
void loop()
{
  controllerRead();
  String Out = "";
  int length = 1;
 
 
  // A
  if (controllerData[0] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "QZ";
    length = length + 2;
  }
 
  // B
  if (controllerData[1] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "WL";
    length = length + 2;
  }

  // SELECT
  if (controllerData[2] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "EK";
    length = length + 2;
  }
 
  // START
  if (controllerData[3] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "UJ";
    length = length + 2;
  }
 
  // UP
  if (controllerData[4] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "I1";
    length = length + 2;
  }
 
  // DOWN
  else if (controllerData[5] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "AS";
    length = length + 2;
  }
 
  // LEFT
  else if (controllerData[6] == 0)
  {

    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "DA";
    length = length + 2;
  }
 
  // RIGHT
  else if (controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "SI";
    length = length + 2;
  }

  // UP+RIGHT
  if (controllerData[4] == 0 && controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "KU";
    length = length + 2;
  }
 
  // UP+LEFT
  else if (controllerData[4] == 0 && controllerData[6] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "JE";
    length = length + 2;
  }
 
  // DOWN+RIGHT
  else if (controllerData[5] == 0 && controllerData[7] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "LQ";
    length = length + 2;
  }
 
  // DOWN+LEFT
  else if (controllerData[5] == 0 && controllerData[6] == 0)
  {
    if (Out != "")
    {
      Out = Out + ",";
      length = length + 2;
    }
    Out = Out + "ZW";
    length = length + 2;
  }
     
  char outData[length];
  Out.toCharArray(outData, length);
 
  meetAndroid.send(outData);
  Serial.println(outData);
  delay(16);
}

And heres the error it gave me.

NES_2_Controllers.cpp: In function 'void controllerRead()':
NES_2_Controllers:92: error: a function-definition is not allowed here before '{' token
NES_2_Controllers:249: error: expected `}' at end of input

The error is at the "{" below the "void loop" code line. Whats that about? Thanks again for your guys help. Later.

Sowden:
And heres the error it gave me.

NES_2_Controllers.cpp: In function 'void controllerRead()':
NES_2_Controllers:92: error: a function-definition is not allowed here before '{' token
NES_2_Controllers:249: error: expected `}' at end of input

The error is at the "{" below the "void loop" code line. Whats that about? Thanks again for your guys help. Later.

You left out a '}' at the end of the first FOR loop in controllerRead().

So where do I put it?

/* MAIN LOOP */
void loop()}

{
  controllerRead();
  String Out = "";
  int length = 1;
 
 
  // A
  if (controllerData1[0] == 0)
  {
    if (Out != "")
    {

That doesn't seem to work. Sorry for being a noob on this guys.

Oh wait, I just got it, I had to add it here:

  // Clock Cycles 2-16
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock1,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock1,LOW);
    delayMicroseconds(4);
    controllerData1[i] = digitalRead(data1);
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock2,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock2,LOW);
    delayMicroseconds(4);
    controllerData2[i] = digitalRead(data2);
  }
}
}
// NES Button Reference
// 01111111 - A [0]
// 10111111 - B [1]
// 11011111 - SELECT [2]
// 11101111 - START [3]
// 11110111 - UP [4]
// 11111011 - DOWN [5]
// 11111101 - LEFT [6]
// 11111110 - RIGHT [7]
// UP+RIGHT
// UP+LEFT
// DOWN+RIGHT
// DOWN+LEFT

/* MAIN LOOP */
void loop()
{
  controllerRead();
  String Out = "";
  int length = 1;

That will get a second controller plugged in to the arduino thanks to you guys. I will start expirmenting with that to make that work properly. But I am still stuck with the limitation of only having 16 keystrokes to work with. Any ideas? Thanks guys, you all are awesome.

Are you sure you want to execute the second loop 15 times? o.0

I'd have guessed you wanted this instead:

  // Clock Cycles 2-16
  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock1,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock1,LOW);
    delayMicroseconds(4);
    controllerData1[i] = digitalRead(data1);
  }

  for (int i = 1; i <= 15; i++)
  {
    digitalWrite(clock2,HIGH);
    delayMicroseconds(4);
    digitalWrite(clock2,LOW);
    delayMicroseconds(4);
    controllerData2[i] = digitalRead(data2);
  }
}

Ah ha! You found my error. Good eye dude. This code compiles and uploads. But when its all hooked up, it doesn't work correctly. Controller one only reads one button as a keystroke and nothing else works. I am starting to think that I can't make two controllers work on one arduino. Unless anyone has experience working with this or can find what I have wrong in my code. I appreciate all of your help guys.