The Teensy uses the USB connection for programing, so we don't need a seperate AVR programmer. We will use the Teensyduino IDE, which is a patch to the Arduino IDE.
If you don't have it yet, download & install the Arduino IDE software
Next, download the Teensyduino installer for your OS and run it, patching the Arduino IDE
Finally, be sure to also grab Teensyloader which is a helper that talks to the Teensy for you.
One Button Test
We'll start with the 'one button test' sketch, which will only listen for the 'Up' D-Pad button and output the letter 'u'
Understanding this code now will make it a lot easier to understand the later sketches that are much more complex!
You can also grab this code (which may be updated!) at GitHub
// SPDX-FileCopyrightText: 2019 Limor Fried/ladyada for Adafruit Industries // // SPDX-License-Identifier: MIT const int pinBtnUp = 0; const int pinLEDOutput = 11; //Variables for the states of the SNES buttons boolean boolBtnUp; void setup() { //Setup the pin modes. pinMode( pinLEDOutput, OUTPUT ); //Special for the Teensy is the INPUT_PULLUP //It enables a pullup resitor on the pin. pinMode( pinBtnUp, INPUT_PULLUP ); //Zero the SNES controller button keys: boolBtnUp = false; } void loop() { // //debugging the start button... digitalWrite ( pinLEDOutput, digitalRead(pinBtnUp)); //Progess the SNES controller buttons to send keystrokes. fcnProcessButtons(); } //Function to process the buttons from the SNES controller void fcnProcessButtons() { //Assign temporary values for the buttons. //Remember, the SNES buttons are read as active LOW. //Capture their status here: boolean boolBtnUp = !digitalRead(pinBtnUp); if ( boolBtnUp ) { //Set key1 to the U key Keyboard.set_key1( KEY_U ); } else { Keyboard.set_key1( 0 ); } //Send all of the set keys. Keyboard.send_now(); }
All Button Test
Next we can upload the sketch that uses all the buttons so you can test each connection. It is much longer. Download it from GitHub.
// SPDX-FileCopyrightText: 2019 Limor Fried/ladyada for Adafruit Industries // // SPDX-License-Identifier: MIT #define REPEATRATE 100 // milliseconds const int pinBtnUp = 0; const int pinBtnRight = 1; const int pinBtnDown = 2; const int pinBtnLeft = 3; const int pinBtnSelect = 4; const int pinBtnStart = 5; const int pinBtnB = 7; const int pinBtnA = 8; const int pinBtnY = 10; const int pinBtnX = 9; const int pinBtnTrigLeft = 6; const int pinBtnTrigRight = 23; const int pinLEDOutput = 11; //Variables for the states of the SNES buttons byte buttons[] = { pinBtnUp, pinBtnRight, pinBtnDown, pinBtnLeft, pinBtnSelect, pinBtnStart, pinBtnB, pinBtnA, pinBtnY, pinBtnX, pinBtnTrigLeft, pinBtnTrigRight }; uint16_t keys[] = {KEY_U, KEY_R, KEY_D, KEY_L, KEY_ENTER, KEY_TAB, KEY_B, KEY_A, KEY_Y, KEY_X, KEY_P, KEY_Q}; void myset_key1(uint16_t c); void myset_key2(uint16_t c); void myset_key3(uint16_t c); void myset_key4(uint16_t c); void myset_key5(uint16_t c); void myset_key6(uint16_t c); #define NUMBUTTONS sizeof(buttons) typedef void KeyFunction_t(uint16_t c); KeyFunction_t* buttonActive[NUMBUTTONS]; KeyFunction_t* keyList[] = {myset_key6, myset_key5, myset_key4, myset_key3, myset_key2, myset_key1}; int keySlot = sizeof(keyList) / sizeof(KeyFunction_t*); void setup() { //Setup the pin modes. pinMode( pinLEDOutput, OUTPUT ); //Special for the Teensy is the INPUT_PULLUP //It enables a pullup resitor on the pin. for (byte i=0; i< NUMBUTTONS; i++) { pinMode(buttons[i], INPUT_PULLUP); } //Uncomment this line to debug the acceleromter values: // Serial.begin(); for (int i=0; i < NUMBUTTONS; i++) { buttonActive[i] = 0; } } void loop() { // //debugging the start button... digitalWrite ( pinLEDOutput, digitalRead(pinBtnStart)); //Progess the SNES controller buttons to send keystrokes. fcnProcessButtons(); } //Function to process the buttons from the SNES controller void fcnProcessButtons() { bool keysPressed = false; bool keysReleased = false; // run through all the buttons for (byte i = 0; i < NUMBUTTONS; i++) { // are any of them pressed? if (! digitalRead(buttons[i])) { //this button is pressed keysPressed = true; if (!buttonActive[i]) //was it pressed before? activateButton(i); //no - activate the keypress } else { //this button is not pressed if (buttonActive[i]) { //was it pressed before? releaseButton(i); //yes - release the keypress keysReleased = true; } } } if (keysPressed || keysReleased) Keyboard.send_now(); //update all the keypresses } void activateButton(byte index) { if (keySlot) //any key slots left? { keySlot--; //Push the keySlot stack buttonActive[index] = keyList[keySlot]; //Associate the keySlot function pointer with the button (*keyList[keySlot])(keys[index]); //Call the key slot function to set the key value } } void releaseButton(byte index) { keyList[keySlot] = buttonActive[index]; //retrieve the keySlot function pointer buttonActive[index] = 0; //mark the button as no longer pressed (*keyList[keySlot])(0); //release the key slot keySlot++; //pop the keySlot stack } void myset_key1(uint16_t c) { Keyboard.set_key1(c); } void myset_key2(uint16_t c) { Keyboard.set_key2(c); } void myset_key3(uint16_t c) { Keyboard.set_key3(c); } void myset_key4(uint16_t c) { Keyboard.set_key4(c); } void myset_key5(uint16_t c) { Keyboard.set_key5(c); } void myset_key6(uint16_t c) { Keyboard.set_key6(c); }
You should test all the buttons, to make sure they all output characters.
This code is more involved since it has to listen to 12 buttons. You can see at the top where we define an array of all the buttons, and then the keys that correspond to the presses. In this case, we're using a simple one-to-one correspondence for keypresses, such as Up being 'u'. To adapt this code to allow for things like "Alt-F3" would be a little more complex.
The code supports up to 6 simultaneous keypresses.
Page last edited January 22, 2025
Text editor powered by tinymce.