Programming the Teensy

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

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();


}
Now we'll upload this sketch to the Teensy. Make a new sketch and copy the code in. Select the Teensy 2.0 (USB Keyboard/Mouse) item from the Board menu.
Make sure the Loader is running, if you see this:
Press the tiny button to start the bootloader, so that it looks like this:
Upload the sketch! You should see it sucessfully program the Teensy, and reboot. The OS will then alert you that it found an HID device.
And the device manager will now have an extra Keyboard and Mouse called "HID Keyboard Device" and "HID-compliant mouse"
You should now be able to open up a text editor and carefully push the 'up' D-pad to generate 'u's!

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.

#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
                 }; 
short 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};

#define NUMBUTTONS sizeof(buttons)

typedef void KeyFunction_t(uint8_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(uint8_t c)
{
  Keyboard.set_key1(c);
}

void myset_key2(uint8_t c)
{
  Keyboard.set_key2(c);
}

void myset_key3(uint8_t c)
{
  Keyboard.set_key3(c);
}

void myset_key4(uint8_t c)
{
  Keyboard.set_key4(c);
}

void myset_key5(uint8_t c)
{
  Keyboard.set_key5(c);
}

void myset_key6(uint8_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.

This guide was first published on Jul 29, 2012. It was last updated on Jul 29, 2012. This page (Programming the Teensy) was last updated on Aug 17, 2019.