· 5 years ago · Jul 28, 2020, 09:02 PM
1#include <Keyboard.h>
2
3/*
4================================================================================
5
6 File........... NES Controller Test Code
7 Purpose........ To demonstrate how to interface to an NES controller
8 Author......... Joseph Corleto
9 E-mail......... corleto.joseph @ gmail.com
10 Started........ 04/13/2016
11 Finished....... 04/14/2016
12 Updated........ --/--/----
13
14================================================================================
15 Notes
16================================================================================
17- The NES controller contains one 8-bit 4021 shift register inside.
18
19- This register takes parallel inputs and converts them into a serial output.
20
21- This code first latches the data and then shifts in the first bit on the data line.
22 Then it clocks and shifts in on the data line until all bits are received.
23
24- What is debugged are the button states of the NES controller.
25
26- A logical "1" means the button is not pressed. A logical "0" means the button is
27 pressed.
28
29- This code shifts the first bit of data into the LSB.
30
31- The order of shifting for the buttons is shown in the table below:
32
33 Bit# | Button
34 --------------
35 0 | A
36 --------------
37 1 | B
38 --------------
39 2 | Select
40 --------------
41 3 | Start
42 --------------
43 4 | Up
44 --------------
45 5 | Down
46 --------------
47 6 | Left
48 --------------
49 7 | Right
50 --------------
51
52- The NES controller pinout is shown below (looking into controllers
53 connector end):
54 __________
55 / |
56 / O 1 | 1 - Ground
57 | | 2 - Clock
58 | 7 O O 2 | 3 - Latch
59 | | 4 - Data Out
60 | 6 O O 3 | 5 - No Connection
61 | | 6 - No Connection
62 | 5 O O 4 | 7 - +5V
63 |___________|
64
65- Please visit www.allaboutcircuits.com to search for complete article!
66
67================================================================================
68 Updates
69================================================================================
70*/
71
72//===============================================================================
73// Header Files
74//===============================================================================
75
76//===============================================================================
77// Constants
78//===============================================================================
79// Here we have a bunch of constants that will become clearer when we look at the
80// readNesController() function. Basically, we will use these contents to clear
81// a bit. These are chosen according to the table above.
82const int A_BUTTON = 0;
83const int B_BUTTON = 1;
84const int SELECT_BUTTON = 2;
85const int START_BUTTON = 3;
86const int UP_BUTTON = 4;
87const int DOWN_BUTTON = 5;
88const int LEFT_BUTTON = 6;
89const int RIGHT_BUTTON = 7;
90
91//===============================================================================
92// Variables
93//===============================================================================
94byte nesRegister = 0; // We will use this to hold current button states
95
96//===============================================================================
97// Pin Declarations
98//===============================================================================
99//Inputs:
100int nesData = 4; // The data pin for the NES controller
101
102//Outputs:
103int nesClock = 2; // The clock pin for the NES controller
104int nesLatch = 3; // The latch pin for the NES controller
105
106//===============================================================================
107// Initialization
108//===============================================================================
109void setup()
110{
111 // Initialize serial port speed for the serial terminal
112 //Serial.begin(9600);
113
114 // Set appropriate pins to inputs
115 pinMode(nesData, INPUT);
116
117 // Set appropriate pins to outputs
118 pinMode(nesClock, OUTPUT);
119 pinMode(nesLatch, OUTPUT);
120
121 // Set initial states
122 digitalWrite(nesClock, LOW);
123 digitalWrite(nesLatch, LOW);
124
125 pinMode(LED_BUILTIN, OUTPUT);
126}
127
128//===============================================================================
129// Main
130//===============================================================================
131void loop()
132{
133 // This function call will return the states of all NES controller's register
134 // in a nice 8 bit variable format. Remember to refer to the table and
135 // constants above for which button maps where!
136 nesRegister = readNesController();
137
138 digitalWrite(LED_BUILTIN, HIGH);
139
140 // Slight delay before we debug what was pressed so we don't spam the
141 // serial monitor.
142 delay(50);
143
144 // To give you an idea on how to use this data to control things for your
145 // next project, look through the serial terminal code below. Basically,
146 // just choose a bit to look at and decide what to do whether HIGH (not pushed)
147 // or LOW (pushed). What is nice about this test code is that we mapped all
148 // of the bits to the actual button name so no useless memorizing!
149 if (bitRead(nesRegister, A_BUTTON) == 0) {
150 Keyboard.press(KEY_LEFT_CTRL); Keyboard.release(KEY_LEFT_CTRL);
151 //Serial.println("JUMP!");
152 }
153
154 if (bitRead(nesRegister, B_BUTTON) == 0) {
155 Keyboard.press(KEY_RIGHT_CTRL); Keyboard.release(KEY_RIGHT_CTRL);
156 //Serial.println("PUNCH!");
157 }
158
159 if (bitRead(nesRegister, START_BUTTON) == 0) {
160 // ignore
161 //Serial.println("START");
162 }
163
164 if (bitRead(nesRegister, SELECT_BUTTON) == 0) {
165 // ignore
166 //Serial.println("SELECT");
167 }
168
169 if (bitRead(nesRegister, UP_BUTTON) == 0) {
170 Keyboard.press('w');Keyboard.release('w');
171 //Serial.println("UP");
172 }
173
174 if (bitRead(nesRegister, DOWN_BUTTON) == 0) {
175 Keyboard.press('s');Keyboard.release('s');
176 //Serial.println("DOWN!");
177 }
178
179 if (bitRead(nesRegister, LEFT_BUTTON) == 0) {
180 Keyboard.press('a');Keyboard.release('a');
181 //Serial.println("LEFT!");
182 }
183
184
185 if (bitRead(nesRegister, RIGHT_BUTTON) == 0) {
186 Keyboard.press('d');Keyboard.release('d');
187 //Serial.println("RIGHT");
188 }
189
190 digitalWrite(LED_BUILTIN, LOW);
191}
192
193//===============================================================================
194// Functions
195//===============================================================================
196///////////////////////
197// readNesController //
198///////////////////////
199byte readNesController()
200{
201 // Pre-load a variable with all 1's which assumes all buttons are not
202 // pressed. But while we cycle through the bits, if we detect a LOW, which is
203 // a 0, we clear that bit. In the end, we find all the buttons states at once.
204 int tempData = 255;
205
206 // Quickly pulse the nesLatch pin so that the register grab what it see on
207 // its parallel data pins.
208 digitalWrite(nesLatch, HIGH);
209 digitalWrite(nesLatch, LOW);
210
211 // Upon latching, the first bit is available to look at, which is the state
212 // of the A button. We see if it is low, and if it is, we clear out variable's
213 // first bit to indicate this is so.
214 if (digitalRead(nesData) == LOW)
215 bitClear(tempData, A_BUTTON);
216
217 // Clock the next bit which is the B button and determine its state just like
218 // we did above.
219 digitalWrite(nesClock, HIGH);
220 digitalWrite(nesClock, LOW);
221 if (digitalRead(nesData) == LOW)
222 bitClear(tempData, B_BUTTON);
223
224 // Now do this for the rest of them!
225
226 // Select button
227 digitalWrite(nesClock, HIGH);
228 digitalWrite(nesClock, LOW);
229 if (digitalRead(nesData) == LOW)
230 bitClear(tempData, SELECT_BUTTON);
231
232 // Start button
233 digitalWrite(nesClock, HIGH);
234 digitalWrite(nesClock, LOW);
235 if (digitalRead(nesData) == LOW)
236 bitClear(tempData, START_BUTTON);
237
238 // Up button
239 digitalWrite(nesClock, HIGH);
240 digitalWrite(nesClock, LOW);
241 if (digitalRead(nesData) == LOW)
242 bitClear(tempData, UP_BUTTON);
243
244 // Down button
245 digitalWrite(nesClock, HIGH);
246 digitalWrite(nesClock, LOW);
247 if (digitalRead(nesData) == LOW)
248 bitClear(tempData, DOWN_BUTTON);
249
250 // Left button
251 digitalWrite(nesClock, HIGH);
252 digitalWrite(nesClock, LOW);
253 if (digitalRead(nesData) == LOW)
254 bitClear(tempData, LEFT_BUTTON);
255
256 // Right button
257 digitalWrite(nesClock, HIGH);
258 digitalWrite(nesClock, LOW);
259 if (digitalRead(nesData) == LOW)
260 bitClear(tempData, RIGHT_BUTTON);
261
262 // After all of this, we now have our variable all bundled up
263 // with all of the NES button states.*/
264 return tempData;
265}