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);
SNESController.h
- Committer:
- foolsday
- Date:
- 2015-01-14
- Revision:
- 0:7deb78c1c738
File content as of revision 0:7deb78c1c738:
/* 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__*/