Keyboards

C code for Teensy: USB Keyboard

This code implements a USB keyboard, which you can use to control almost any PC or Mac software.

Download Source Files

Example Application

The example program configures all Port B and Port D pins as inputs with pullup resistors. When any of these 16 pins is shorted to ground, 2 keystrokes are sent to the PC naming that pin.

An idle timeout is also implemented which send a spacebar keystroke after 8 seconds of inactivity.


USB Keyboard Example, 16 keys on Port B and Port D

Operating System Setup

All modern operating systems support USB keyboards. No special drivers need to be loaded.

This code also supports the keyboard “boot protocol” for compatability with the BIOS before an operating system has loaded.

Simple Keypress Function

#include

usb_keyboard_press(key, modifier)

This simple function sends a single keypress. The following table lists definitions for the standard keys and modifiers. If no modifier is needed, use 0.

key modifier
KEY_A KEY_B KEY_C KEY_D KEY_CTRL
KEY_E KEY_F KEY_G KEY_H KEY_SHIFT
KEY_I KEY_J KEY_K KEY_L KEY_ALT
KEY_M KEY_N KEY_O KEY_P KEY_GUI
KEY_Q KEY_R KEY_S KEY_T KEY_LEFT_CTRL
KEY_U KEY_V KEY_W KEY_X KEY_LEFT_SHIFT
KEY_Y KEY_Z KEY_1 KEY_2 KEY_LEFT_ALT
KEY_3 KEY_4 KEY_5 KEY_6 KEY_LEFT_GUI
KEY_7 KEY_8 KEY_9 KEY_0 KEY_RIGHT_CTRL
KEY_ENTER KEY_ESC KEY_BACKSPACE KEY_TAB KEY_RIGHT_SHIFT
KEY_SPACE KEY_MINUS KEY_EQUAL KEY_LEFT_BRACE KEY_RIGHT_ALT
KEY_RIGHT_BRACE KEY_BACKSLASH KEY_NUMBER KEY_SEMICOLON KEY_RIGHT_GUI
KEY_QUOTE KEY_TILDE KEY_COMMA KEY_PERIOD
KEY_SLASH KEY_CAPS_LOCK KEY_F1 KEY_F2
KEY_F3 KEY_F4 KEY_F5 KEY_F6
KEY_F7 KEY_F8 KEY_F9 KEY_F10
KEY_F11 KEY_F12 KEY_PRINTSCREEN KEY_SCROLL_LOCK
KEY_PAUSE KEY_INSERT KEY_HOME KEY_PAGE_UP
KEY_DELETE KEY_END KEY_PAGE_DOWN KEY_RIGHT
KEY_LEFT KEY_DOWN KEY_UP KEY_NUM_LOCK
KEYPAD_SLASH KEYPAD_ASTERIX KEYPAD_MINUS KEYPAD_PLUS
KEYPAD_ENTER KEYPAD_1 KEYPAD_2 KEYPAD_3
KEYPAD_4 KEYPAD_5 KEYPAD_6 KEYPAD_7
KEYPAD_8 KEYPAD_9 KEYPAD_0 KEYPAD_PERIOD

Complex Keyboard Functionality

Most applications only require the single press function above, which rapidly presses and releases a single key (plus modifiers) at a time. However, for multiple simultaneous keys pressed, holding keys down for periods of time, and complex sequences, the raw USB key code data may be accessed.

For example, to copy from the clipboard in Windows, some programs may require the CTRL key to be held for a period of time before the C key is pressed. Using usb_keyboard_press() presses and quickly releases the C and CTRL keys together at exactly the same instant. To send a timed sequence, you must set the keyboard state variables and use usb_keyboard_send() to transmit each state change.

keyboard_keys[6]

This 6 byte array represents the non-modifier keys that are currently pressed. You can only press 6 of the non-modifier keys at once. Set these to zero when not pressing a key.

keyboard_modifier_keys

This variable represents the modifier keys currently pressed. Set this to a bitwise OR of all modifier keys pressed, or zero if none are pressed.

usb_keyboard_send()

After setting the varibles above, call this function to transmit the key state to the PC. The PC automatically implements auto-repeat when you send a key state that has a non-modifier key pressed, and you allow a long delay before sending a zero to release the key. // first, press the CTRL key keyboard_modifier_keys = KEY_CTRL; keyboard_keys[0] = 0; keyboard_keys[1] = 0; keyboard_keys[2] = 0; keyboard_keys[3] = 0; keyboard_keys[4] = 0; keyboard_keys[5] = 0; usb_keyboard_send(); _delay_ms(50); // next, press ALT while still holding CTRL keyboard_modifier_keys = KEY_CTRL | KEY_ALT; usb_keyboard_send(); _delay_ms(50); // now press DELETE, while still keeping CTRL and ALT keyboard_keys[0] = KEY_DELETE; usb_keyboard_send(); _delay_ms(150); // release DELETE, while still keeping CTRL and ALT keyboard_keys[0] = 0; usb_keyboard_send(); _delay_ms(50); // release both CTRL and ALT at exactly the same moment keyboard_modifier_keys = 0; usb_keyboard_send();

keyboard_leds

This variable is updated with the current keyboard LED setting.

USB Connection Management Functions

usb_init()

Initialize the USB controller. This must be called before any others, typically as your program initializes everything. This function always returns immediately and never waits for any USB communication.

usb_configured()

Is the USB controller configured?

Returns 0 (false) if the host has not enumerated (auto-detected) and configured the USB controller. Returns non-zero (true) if configuration is complete.

Many PC and Macintosh drivers are not immediately ready to transfer data, even after configuration is complete. An additional delay of 1 second is generally a good idea to allow drivers to load on the PC before initiating data transfers.

USB Debug Message Functions

The debug version includes all the debug message functions, which may be used indepentently from the keyboard functions for display in HID Listen.

About USB Keyboard Bandwidth

The USB keyboard protocol is not designed for high bandwidth data transfer. Each change of keyboard state is transmitted as a packet. Because the USB interrupt transfer type is used, a maximum of 1000 packets per second can be sent.

Using usb_keyboard_press(), two packets are sent for every keystroke, the first to press the key (and modifier keys) and the second to release. This results in a maximum of 500 keystrokes per second. Using usb_keyboard_send(), a single packet is sent with the contents of the keyboard_keys[6] and keyboard_modifier_keys.

Software on the PC may spend considerable CPU time processing each keystroke, with the assumption that no human could possibly press more than several keys per second. Even 500 keys per second may overwhelm such software.

Source

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *