Hello, I currently am working with a SNES controller that I have tied into my Arduino; and for those unfamiliar with the SNES architecture, all of the buttons are inputs to a 16-bit PISO shift register.
I am putting the data obtained from pulsing the shift register into a 16bit integer and returning it in the function below:
uint16_t readNesController()
{
uint16_t tempData = 0xFFFF;
//B Button
digitalWrite(NES_LATCH, HIGH);
digitalWrite(NES_LATCH, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, B_BUTTON);
// Y Button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, Y_BUTTON);
// Select button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, SELECT_BUTTON);
// Start button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, START_BUTTON);
// Up button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, UP_BUTTON);
// Down button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, DOWN_BUTTON);
// Left button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, LEFT_BUTTON);
// Right button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, RIGHT_BUTTON);
// A button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, A_BUTTON);
// X button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, X_BUTTON);
// L button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, L_BUTTON);
// R button
digitalWrite(NES_CLOCK, HIGH);
digitalWrite(NES_CLOCK, LOW);
if (digitalRead(NES_DATA) == LOW)
bitClear(tempData, R_BUTTON)
int count = 0;
for (int i = 0; i <= 16; i++) {
if(bitRead(tempData, i) == 0) {
count++;
}
}
Serial.println(tempData, BIN);
if (count < 4) {
return tempData;
} else {
return 0xFFFF;
}
}
Note that each button is given an index value within each call to bitClear that corresponds to the order they are read in. Each bit in the tempData output represents the state of each button, 0 being closed and 1 being open.
This functions, however the tempData variable every other call to this function contains a large number of 0's, alternating like so:
1111000000000011
1111111111111111
1111000000000011
1111111111111111
...
And if a button is pressed, say B:
1111000000000011
1111111111111110
1111000000000011
1111111111111110
...
So in other words, every second call to readNesController produces incorrect data in the tempData variable. I was (rather inelegantly) filtering these out outputting 0xFFFF (no buttons pressed) when there are more then 3 zeroes in the tempData variable using a counting loop, which has been working for now but now I am wanting to have rising edge detection in other parts of the project which becomes impossible when every second call to this function will always see all buttons as not being pressed. In other words holding down a button will act as if it is being very rapidly spammed by sending out 0xFFFF every second call.
What are my options here or is there something about my code that is causing this that can be fixed?
Before it is suggested I did try pulsing the clock pin 4 more times as a part of read NesController to get the data from the pins that arent used by the controller - this still occurs - pulsing latch resets the shift register to read data line 0.
---------UPDATE---------
I very quickly realized after posting I could call the function recursively like so, so I am not outputting 0xFFFF for a data error, like so:
int count = 0;
for (int i = 0; i <= 16; i++) {
if(bitRead(tempData, i) == 0) {
count++;
}
}
if (count < 4) {
Serial.println(tempData, BIN);
return tempData;
} else {
readNesController();
}
but I am still wondering if there is something else I am doing incorrectly that is causing the button states to be read like this.