A simple class for reading button presses from a Super Nintendo (SNES) controller. Requires access to the controller's latch, clock, and data pins.

ABOUT

A simple class for reading a Super Nintendo (SNES) controller's buttons.

HARDWARE

The library was developed using the Nordic mKIT and cheap controllers.

NOTE: This controller has a wide VCC tolerance and continues to operate even when the mKIT is running off of a coin cell battery.

            +-----------+           
            |           |           
            |    +-+    |           
            |    +-+--------+VCC    
            |           |           
            |    +-+    |           
            |    +-+--------+CLOCK  
            |           |           
            |    +-+    |           
            |    +-+--------+LATCH  
            |           |           
            |    +-+    |           
            |    +-+--------+DATA   
            |           |           
            +-----------+           
            |           |           
            |    +-+    |           
            |    +-+--------+N/C    
            |           |           
            |    +-+    |           
            |    +-+--------+N/C    
            |           |           
            |    +-+    |           
            X    +-+----+---+GND    
             X         X            
              ---------             
                                    
          Controller pinout         
(looking into the female connector) 

USAGE

After wiring up a controller:

Include the library

#include "SNESController.h"

Create a new object and specify the pins

SNESController snes(P0_20, P0_21, P0_22);

Read and decode the button presses

uint16_t state = snes.read();
if (snes.pressed(state, SNESController::SNES_BUTTON_RIGHT_ARROW)) {
    ...
}

Poll the controller periodically

Ticker ticker;
ticker.attach(periodicCallback, 0.05);

Files at this revision

API Documentation at this revision

Comitter:
foolsday
Date:
Wed Jan 14 20:00:17 2015 +0000
Commit message:
A simple class for reading button presses from a Super Nintendo (SNES) controller. Requires access to a controller's latch, clock, and data pins.

Changed in this revision

SNESController.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 7deb78c1c738 SNESController.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SNESController.h	Wed Jan 14 20:00:17 2015 +0000
@@ -0,0 +1,127 @@
+/* SNES Controller library
+ * Copyright (c) 2015 Daniel Veilleux
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+ 
+#ifndef __SNES_CONTROLLER_H__
+#define __SNES_CONTROLLER_H__
+
+#include "mbed.h"
+
+
+/**
+* @class SNESController
+* @brief Reads the state of an SNES controller and decodes the button presses.
+*/
+class SNESController {
+public:
+
+    /**
+     * @enum SNESButton_t
+     * @brief The masks of the individual buttons as read from the controller
+     */
+    enum SNESButton_t
+    {
+        SNES_BUTTON_B           = 0x0001,
+        SNES_BUTTON_Y           = 0x0002,
+        SNES_BUTTON_SEL         = 0x0004,
+        SNES_BUTTON_START       = 0x0008,
+        SNES_BUTTON_UP_ARROW    = 0x0010,
+        SNES_BUTTON_DOWN_ARROW  = 0x0020,
+        SNES_BUTTON_LEFT_ARROW  = 0x0040,
+        SNES_BUTTON_RIGHT_ARROW = 0x0080,
+        SNES_BUTTON_A           = 0x0100,
+        SNES_BUTTON_X           = 0x0200,
+        SNES_BUTTON_L           = 0x0400,
+        SNES_BUTTON_R           = 0x0800
+    };
+
+
+    /**
+     * @brief Constructs a new object for reading button presses
+     *
+     * @param  latch
+     *         A PinName specifying the latch pin (pin #3)
+     * @param  clock
+     *         A PinName specifying the clock pin (pin #2)
+     * @param  data
+     *         A PinName specifying the data pin (pin #4)
+     *
+     */
+    SNESController(PinName latch, PinName clock, PinName data):
+        latchPin(latch),
+        clockPin(clock),
+        dataPin(data) {
+            latchPin = 0;
+            clockPin = 1;
+        }
+
+
+    /**
+     * @brief Reads the current state of the controller and returns a button mask
+     *
+     * @return
+     *     A 16-bit mask containing the states of all of the buttons.
+     *     Pressed buttons will have their bits set to 1.
+     */
+    uint16_t read(void)
+    {
+        uint32_t mask;
+        uint16_t buttons = 0;
+
+        latchPin = 1;
+        wait_us(12);
+        latchPin = 0;
+
+        wait_us(6);
+
+        for (mask = 0x0001; mask < 0x10000; mask <<= 1)
+        {
+            clockPin = 0;
+            wait_us(6);
+    
+            // Data is active low.
+            if (!dataPin)
+            {
+                buttons |= mask;
+            }
+
+            clockPin = 1;
+            wait_us(6);
+        }
+
+        return buttons;
+    }
+
+
+    /**
+     * @brief Returns true if the specified button is pressed in the given buttonMask
+     *
+     * @return
+     *     True if the specified button is pressed in the mask
+     */
+    __inline bool pressed(uint16_t buttonMask, SNESButton_t button)
+    {
+        return (buttonMask & button);    
+    }
+
+
+private:
+    DigitalOut latchPin;
+    DigitalOut clockPin;
+    DigitalIn dataPin;
+};
+
+#endif /* #ifndef __SNES_CONTROLLER_H__*/