Mercurial > louis > kiibohd-controller
changeset 21:c14f9ac8420f
Reorganization for use with the CMake "Modules"
- Include option is currently "hacked" and needs to be fixed
- Builds on Linux, but Mac and Windows needs to be tested
- Loader script generation isn't complete
author | Jacob Alexander <triplehaata@gmail.com> |
---|---|
date | Wed, 28 Sep 2011 23:25:51 -0700 |
parents | 0bd94a5cac31 |
children | 7e2217378d23 |
files | CMakeLists.txt Debug/basic/print.c Debug/basic/print.h Debug/basic/setup.cmake Keymap/keymap.h Keymap/usb_keys.h LoadFile/load Macro/basic/setup.cmake Scan/matrix/matrix.c Scan/matrix/matrix.h Scan/matrix/scan_loop.c Scan/matrix/scan_loop.h Scan/matrix/setup.cmake USB/pjrc/setup.cmake USB/pjrc/usb_keyboard.c USB/pjrc/usb_keyboard.h USB/pjrc/usb_keyboard_debug.c USB/pjrc/usb_keyboard_debug.h setup.cmake |
diffstat | 19 files changed, 2910 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Wed Sep 28 20:37:19 2011 -0700 +++ b/CMakeLists.txt Wed Sep 28 23:25:51 2011 -0700 @@ -33,13 +33,13 @@ # Source Defines # -#| Sources -set( SRCS - ./main.c - ./print.c - ./usb_keyboard_debug.c - ./scan_loop.c -) +#| Sources (see setup.h for configuring in/away code blocks or other complete modules) +#| XXX Not set here in this project, see setup.cmake +#set( SRCS ./main.c ) + +#| Instead, include the module source selector +include( setup.cmake ) +set( SRCS main.c ${SCAN_SRCS} ${MACRO_SRCS} ${USB_SRCS} ${DEBUG_SRCS} )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Debug/basic/print.c Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,190 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Compiler Includes +#include <stdarg.h> + +// AVR Includes +#include <avr/io.h> +#include <avr/pgmspace.h> + +// Project Includes +#include "print.h" + +// Defines + + +// USB HID String Output +void usb_debug_putstr( char* s ) +{ + while ( *s != '\0' ) + usb_debug_putchar( *s++ ); +} + +// Multiple string Output +void usb_debug_putstrs( char* first, ... ) +{ + // Initialize the variadic function parameter list + va_list ap; + + // Get the first parameter + va_start( ap, first ); + char *cur = first; + + // Loop through the variadic list until "\0\0\0" is found + while ( !( cur[0] == '\0' && cur[1] == '\0' && cur[2] == '\0' ) ) + { + // Print out the given string + usb_debug_putstr( cur ); + + // Get the next argument ready + cur = va_arg( ap, char* ); + } + + va_end( ap ); // Not required, but good practice +} + +// Print a constant string +void _print(const char *s) +{ + char c; + + // Acquire the character from flash, and print it, as long as it's not NULL + // Also, if a newline is found, print a carrige return as well + while ( ( c = pgm_read_byte(s++) ) != '\0' ) + { + if ( c == '\n' ) + usb_debug_putchar('\r'); + usb_debug_putchar(c); + } +} + + + + +// String Functions +void int8ToStr( uint8_t in, char* out ) +{ + // Position and sign containers + uint8_t pos; + pos = 0; + + // Evaluate through digits as decimal + do + { + out[pos++] = in % 10 + '0'; + } + while ( (in /= 10) > 0 ); + + // Append null + out[pos] = '\0'; + + // Reverse the string to the correct order + revsStr(out); +} + + +void int16ToStr( uint16_t in, char* out ) +{ + // Position and sign containers + uint16_t pos; + pos = 0; + + // Evaluate through digits as decimal + do + { + out[pos++] = in % 10 + '0'; + } + while ( (in /= 10) > 0 ); + + // Append null + out[pos] = '\0'; + + // Reverse the string to the correct order + revsStr(out); +} + + +void hexToStr_op( uint16_t in, char* out, uint8_t op ) +{ + // Position container + uint16_t pos = 0; + + // Evaluate through digits as hex + do + { + uint16_t cur = in % 16; + out[pos++] = cur + (( cur < 10 ) ? '0' : 'A' - 10); + } + while ( (in /= 16) > 0 ); + + // Output formatting options + switch ( op ) + { + case 1: // Add 0x + out[pos++] = 'x'; + out[pos++] = '0'; + break; + case 2: // 8-bit padding + case 4: // 16-bit padding + while ( pos < op ) + out[pos++] = '0'; + break; + } + + // Append null + out[pos] = '\0'; + + // Reverse the string to the correct order + revsStr(out); +} + + +void revsStr( char* in ) +{ + // Iterators + int i, j; + + // Temp storage + char c; + + // Loop through the string, and reverse the order of the characters + for ( i = 0, j = lenStr( in ) - 1; i < j; i++, j-- ) + { + c = in[i]; + in[i] = in[j]; + in[j] = c; + } +} + + +uint16_t lenStr( char* in ) +{ + // Iterator + char *pos; + + // Loop until null is found + for ( pos = in; *pos; pos++ ); + + // Return the difference between the pointers of in and pos (which is the string length) + return (pos - in); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Debug/basic/print.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,87 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef print_h__ +#define print_h__ + +// AVR Includes +#include <avr/pgmspace.h> + +// Project Includes +#include "usb_keyboard_debug.h" + +// Defines +#define NL "\r\n" + + +/* XXX + * Note that all the variadic functions below, take comma separated string lists, they are purposely not printf style (simplicity) + */ + +// Function Aliases +#define dPrint(c) usb_debug_putchar(c) +#define dPrintStr(c) usb_debug_putstr (c) +#define dPrintStrs(...) usb_debug_putstrs(__VA_ARGS__, "\0\0\0") // Convenience Variadic Macro +#define dPrintStrNL(c) dPrintStrs (c, NL) // Appends New Line Macro +#define dPrintStrsNL(...) usb_debug_putstrs(__VA_ARGS__, NL, "\0\0\0") // Appends New Line Macro + +// Special Msg Constructs (Uses VT100 tags) +#define dPrintMsg(colour_code_str,msg,...) \ + usb_debug_putstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") +#define printMsg(colour_code_str,msg,str) \ + print("\033[" colour_code_str "m" msg "\033[0m - " str NL) + +// Info Messages +#define info_dPrint(...) dPrintMsg ("1;32", "INFO", __VA_ARGS__) // Info Msg +#define info_print(str) printMsg ("1;32", "INFO", str) // Info Msg + +// Warning Messages +#define warn_dPrint(...) dPrintMsg ("1;33", "WARNING", __VA_ARGS__) // Warning Msg +#define warn_print(str) printMsg ("1;33", "WARNING", str) // Warning Msg + +// Error Messages +#define erro_dPrint(...) dPrintMsg ("1;5;31", "ERROR", __VA_ARGS__) // Error Msg +#define erro_print(str) printMsg ("1;5;31", "ERROR", str) // Error Msg + +// Debug Messages +#define dbug_dPrint(...) dPrintMsg ("1;35", "DEBUG", __VA_ARGS__) // Debug Msg +#define dbug_print(str) printMsg ("1;35", "DEBUG", str) // Debug Msg + +// Static String Printing +#define print(s) _print(PSTR(s)) + +void _print(const char *s); +void usb_debug_putstr( char* s ); +void usb_debug_putstrs( char* first, ... ); + + + +// String Functions +#define hexToStr(hex, out) hexToStr_op(hex, out, 1) + +void int8ToStr ( uint8_t in, char* out ); +void int16ToStr ( uint16_t in, char* out ); +void hexToStr_op( uint16_t in, char* out, uint8_t op ); +void revsStr ( char* in ); +uint16_t lenStr ( char* in ); + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Debug/basic/setup.cmake Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,22 @@ +###| CMake Kiibohd Controller Debug Module |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( DEBUG_SRCS + print.c +) + + +### +# Module Specific Options +# +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Keymap/keymap.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,228 @@ +#ifndef __KEYMAP_h +#define __KEYMAP_h + +#include "usb_keys.h" + +// Modifier Mask +#define MODIFIERS_KEYPAD 0 +#define MODIFIERS_KEYBOARD 4 +static uint8_t keypad_modifierMask[] = {}; +static uint8_t keyboard_modifierMask[] = { 1, 17, 33, 49 }; +static uint8_t alternate_modifierMask[] = { 1, 17, 33, 49, 62 }; + +// Default 1-indexed key mappings +static uint8_t keypadDefaultMap[] = { 0, + KEYPAD_7, + KEYPAD_8, + KEYPAD_9, + KEYPAD_SLASH, + KEYPAD_4, + KEYPAD_5, + KEYPAD_6, + KEYPAD_ASTERIX, + KEYPAD_1, + KEYPAD_2, + KEYPAD_3, + KEYPAD_MINUS, + KEYPAD_ENTER, + KEYPAD_0, + KEYPAD_PERIOD, + KEYPAD_PLUS }; + +static uint8_t defaultMap[] = { 0, + KEY_GUI, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + KEY_MINUS, + KEY_EQUAL, + KEY_BACKSLASH, + KEY_TILDE, + KEY_BACKSPACE, + KEY_ALT, + KEY_TAB, + KEY_Q, + KEY_W, + KEY_E, + KEY_R, + KEY_T, + KEY_Y, + KEY_U, + KEY_I, + KEY_O, + KEY_P, + KEY_LEFT_BRACE, + KEY_RIGHT_BRACE, + KEY_DELETE, + KEY_UP, + KEY_CTRL, + KEY_CAPS_LLOCK, + KEY_A, + KEY_S, + KEY_D, + KEY_F, + KEY_G, + KEY_H, + KEY_J, + KEY_K, + KEY_L, + KEY_SEMICOLON, + KEY_QUOTE, + KEY_ENTER, + KEY_DOWN, + KEY_ESC, + KEY_LEFT_SHIFT, + KEY_Z, + KEY_X, + KEY_C, + KEY_V, + KEY_B, + KEY_N, + KEY_M, + KEY_COMMA, + KEY_PERIOD, + KEY_SLASH, + KEY_RIGHT_SHIFT, + KEY_LEFT, + KEY_RIGHT, + KEY_SPACE }; + +static uint8_t navigationMap[] = { 0, + KEY_GUI, + 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_INSERT, + KEY_DELETE, + KEY_BACKSPACE, + KEY_ALT, + KEY_CAPS_LOCK, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + KEY_SYSREQ_ATT, + KEY_SCROLL_LOCK, + KEY_PAUSE, + KEY_UP, + 0, + 0, + 0, + KEY_CTRL, + KEY_CAPS_LLOCK, + 0, + 0, + 0, + 0, + 0, + KEYPAD_ASTERIX, + KEYPAD_SLASH, + KEY_HOME, + KEY_PAGE_UP, + KEY_LEFT, + KEY_RIGHT, + KEY_ENTER, + 0, + KEY_ESC, + KEY_LEFT_SHIFT, + 0, + 0, + 0, + 0, + 0, + KEYPAD_PLUS, + KEYPAD_MINUS, + KEY_END, + KEY_PAGE_DOWN, + KEY_DOWN, + KEY_RIGHT_SHIFT, + 165, + KEY_RIGHT_ALT, + KEY_SPACE }; + +static uint8_t colemakMap[] = { 0, + KEY_GUI, + KEY_1, + KEY_2, + KEY_3, + KEY_4, + KEY_5, + KEY_6, + KEY_7, + KEY_8, + KEY_9, + KEY_0, + KEY_MINUS, + KEY_EQUAL, + KEY_BACKSLASH, + KEY_TILDE, + KEY_BACKSPACE, + KEY_ALT, + KEY_TAB, + KEY_Q, + KEY_W, + KEY_F, + KEY_P, + KEY_G, + KEY_J, + KEY_L, + KEY_U, + KEY_Y, + KEY_SEMICOLON, + KEY_LEFT_BRACE, + KEY_RIGHT_BRACE, + KEY_DELETE, + KEY_PAGE_UP, + KEY_CTRL, + KEY_CAPS_LLOCK, + KEY_A, + KEY_R, + KEY_S, + KEY_T, + KEY_D, + KEY_H, + KEY_N, + KEY_E, + KEY_I, + KEY_O, + KEY_QUOTE, + KEY_ENTER, + KEY_PAGE_DOWN, + KEY_ESC, + KEY_LEFT_SHIFT, + KEY_Z, + KEY_X, + KEY_C, + KEY_V, + KEY_B, + KEY_K, + KEY_M, + KEY_COMMA, + KEY_PERIOD, + KEY_SLASH, + KEY_RIGHT_SHIFT, + 165, + KEY_RIGHT_ALT, + KEY_SPACE }; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Keymap/usb_keys.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,244 @@ +#ifndef __usb_keys_h +#define __usb_keys_h + + +// List of Modifiers +#define KEY_CTRL 0x01 +#define KEY_SHIFT 0x02 +#define KEY_ALT 0x04 +#define KEY_GUI 0x08 +#define KEY_LEFT_CTRL 0x01 +#define KEY_LEFT_SHIFT 0x02 +#define KEY_LEFT_ALT 0x04 +#define KEY_LEFT_GUI 0x08 +#define KEY_RIGHT_CTRL 0x10 +#define KEY_RIGHT_SHIFT 0x20 +#define KEY_RIGHT_ALT 0x40 +#define KEY_RIGHT_GUI 0x80 + +// List of Keycodes +#define KEY_A 4 +#define KEY_B 5 +#define KEY_C 6 +#define KEY_D 7 +#define KEY_E 8 +#define KEY_F 9 +#define KEY_G 10 +#define KEY_H 11 +#define KEY_I 12 +#define KEY_J 13 +#define KEY_K 14 +#define KEY_L 15 +#define KEY_M 16 +#define KEY_N 17 +#define KEY_O 18 +#define KEY_P 19 +#define KEY_Q 20 +#define KEY_R 21 +#define KEY_S 22 +#define KEY_T 23 +#define KEY_U 24 +#define KEY_V 25 +#define KEY_W 26 +#define KEY_X 27 +#define KEY_Y 28 +#define KEY_Z 29 +#define KEY_1 30 +#define KEY_2 31 +#define KEY_3 32 +#define KEY_4 33 +#define KEY_5 34 +#define KEY_6 35 +#define KEY_7 36 +#define KEY_8 37 +#define KEY_9 38 +#define KEY_0 39 +#define KEY_ENTER 40 +#define KEY_ESC 41 +#define KEY_BACKSPACE 42 +#define KEY_TAB 43 +#define KEY_SPACE 44 +#define KEY_MINUS 45 +#define KEY_EQUAL 46 +#define KEY_LEFT_BRACE 47 +#define KEY_RIGHT_BRACE 48 +#define KEY_BACKSLASH 49 +#define KEY_NUMBER 50 +#define KEY_SEMICOLON 51 +#define KEY_QUOTE 52 +#define KEY_TILDE 53 +#define KEY_COMMA 54 +#define KEY_PERIOD 55 +#define KEY_SLASH 56 +#define KEY_CAPS_LOCK 57 +#define KEY_F1 58 +#define KEY_F2 59 +#define KEY_F3 60 +#define KEY_F4 61 +#define KEY_F5 62 +#define KEY_F6 63 +#define KEY_F7 64 +#define KEY_F8 65 +#define KEY_F9 66 +#define KEY_F10 67 +#define KEY_F11 68 +#define KEY_F12 69 +#define KEY_PRINTSCREEN 70 +#define KEY_SCROLL_LOCK 71 +#define KEY_PAUSE 72 +#define KEY_INSERT 73 +#define KEY_HOME 74 +#define KEY_PAGE_UP 75 +#define KEY_DELETE 76 +#define KEY_END 77 +#define KEY_PAGE_DOWN 78 +#define KEY_RIGHT 79 +#define KEY_LEFT 80 +#define KEY_DOWN 81 +#define KEY_UP 82 +#define KEY_NUM_LOCK 83 +#define KEYPAD_SLASH 84 +#define KEYPAD_ASTERIX 85 +#define KEYPAD_MINUS 86 +#define KEYPAD_PLUS 87 +#define KEYPAD_ENTER 88 +#define KEYPAD_1 89 +#define KEYPAD_2 90 +#define KEYPAD_3 91 +#define KEYPAD_4 92 +#define KEYPAD_5 93 +#define KEYPAD_6 94 +#define KEYPAD_7 95 +#define KEYPAD_8 96 +#define KEYPAD_9 97 +#define KEYPAD_0 98 +#define KEYPAD_PERIOD 99 +#define KEY_ISO_BACKSLASH 100 +#define KEY_APP 101 +#define KEYBOARD_ERROR 102 // See spec +#define KEYPAD_EQUAL 103 +#define KEY_F13 104 +#define KEY_F14 105 +#define KEY_F15 106 +#define KEY_F16 107 +#define KEY_F17 108 +#define KEY_F18 109 +#define KEY_F19 110 +#define KEY_F20 111 +#define KEY_F21 112 +#define KEY_F22 113 +#define KEY_F23 114 +#define KEY_F24 115 +#define KEY_EXEC 116 +#define KEY_HELP 117 +#define KEY_MENU 118 +#define KEY_SELECT 119 +#define KEY_STOP 120 +#define KEY_AGAIN 121 +#define KEY_UNDO 122 +#define KEY_CUT 123 +#define KEY_COPY 124 +#define KEY_PASTE 125 +#define KEY_FIND 126 +#define KEY_MUTE 127 +#define KEY_VOL_UP 128 +#define KEY_VOL_DOWN 129 +#define KEY_CAPS_LLOCK 130 // "Locking" Scroll Lock (Old keyboards with Locking Caps Lock) +#define KEY_NUM_LLOCK 131 +#define KEY_SCROLL_LLOCK 132 +#define KEYPAD_COMMA 133 // Brazillian (See spec) +#define KEYPAD_EQUAL_AS 134 // AS/400 Keyboard (See spec) +#define KEY_INTER1 135 // Brazillian and Japanese "Ru" +#define KEY_INTER2 136 // Japanese Katakana/Hiragana +#define KEY_INTER3 137 // Japanese Yen +#define KEY_INTER4 138 // Japanese Henkan +#define KEY_INTER5 139 // Japanese Muhenkan +#define KEY_INTER6 140 // PC98 Comma (Ka-m-ma) +#define KEY_INTER7 141 // Double-Byte/Single-Byte Toggle +#define KEY_INTER8 142 // Undefined +#define KEY_INTER9 143 // Undefined +#define KEY_LANG1 144 // Korean Hangul/English Toggle +#define KEY_LANG2 145 // Korean Hanja Conversion +#define KEY_LANG3 146 // Japanese Katakana Key (USB) +#define KEY_LANG4 147 // Japanese Hiragana Key (USB) +#define KEY_LANG5 148 // Japanese Zenkaku/Hankaku Key (USB) +#define KEY_LANG6 149 // Reserved (Application Specific) +#define KEY_LANG7 150 // Reserved (Application Specific) +#define KEY_LANG8 151 // Reserved (Application Specific) +#define KEY_LANG9 152 // Reserved (Application Specific) +#define KEY_ALT_ERASE 153 // Special Erase (See Spec) +#define KEY_SYSREQ_ATT 154 // Modifier Type +#define KEY_CANCEL 155 +#define KEY_CLEAR 156 +#define KEY_PRIOR 157 +#define KEY_RETURN 158 +#define KEY_SEPARATOR 159 +#define KEY_OUT 160 +#define KEY_OPER 161 +#define KEY_CLEAR_AGAIN 162 +#define KEY_CRSEL_PROPS 163 +#define KEY_EXSEL 164 +// 165 - 175 Reserved +#define KEYPAD_00 176 +#define KEYPAD_000 177 +#define KEY_1000_SEP 178 +#define KEY_DECIMAL_SEP 179 +#define KEY_CURRENCY_MAIN 180 +#define KEY_CURRENCY_SUB 181 +#define KEYPAD_LPAREN 182 +#define KEYPAD_RPAREN 183 +#define KEYPAD_LBRACE 184 +#define KEYPAD_RBRACE 185 +#define KEYPAD_TAB 186 +#define KEYPAD_BACKSPACE 187 +#define KEYPAD_A 188 +#define KEYPAD_B 189 +#define KEYPAD_C 190 +#define KEYPAD_D 191 +#define KEYPAD_E 192 +#define KEYPAD_F 193 +#define KEYPAD_XOR 194 +#define KEYPAD_CHEVRON 195 +#define KEYPAD_PERCENT 196 +#define KEYPAD_LTHAN 197 +#define KEYPAD_GTHAN 198 +#define KEYPAD_AND 199 +#define KEYPAD_AND_AND 200 +#define KEYPAD_OR 201 +#define KEYPAD_OR_OR 202 +#define KEYPAD_COLON 203 +#define KEYPAD_POUND 204 +#define KEYPAD_SPACE 205 +#define KEYPAD_AT 206 +#define KEYPAD_EXCLAIM 207 +#define KEYPAD_MEM_STORE 208 +#define KEYPAD_MEM_RECALL 209 +#define KEYPAD_MEM_CLEAR 210 +#define KEYPAD_MEM_ADD 211 +#define KEYPAD_MEM_SUB 212 +#define KEYPAD_MEM_MULT 213 +#define KEYPAD_MEM_DIV 214 +#define KEYPAD_PLUS_MINUS 215 +#define KEYPAD_CLEAR 216 +#define KEYPAD_CLEAR_ENTRY 217 +#define KEYPAD_BINARY 218 +#define KEYPAD_OCTAL 219 +#define KEYPAD_DECIMAL 220 +#define KEYPAD_HEX 221 +// 222 - 223 Reserved +#define KEYS_LCTRL 224 +#define KEYS_LSHIFT 225 +#define KEYS_LALT 226 +#define KEYS_LGUI 227 +#define KEYS_RCTRL 228 +#define KEYS_RSHIFT 229 +#define KEYS_RALT 230 +#define KEYS_RGUI 231 +// 232 - 65535 Reserved + + + + + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LoadFile/load Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,8 @@ +#!/bin/bash + +#| Loads the hex file onto the teensy++ 2.0 + +sudo teensy-loader-cli -mmcu=at90usb1286 -w Build/main.hex + +exit 0 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Macro/basic/setup.cmake Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,21 @@ +###| CMake Kiibohd Controller Macro Module |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( MACRO_SRCS +) + + +### +# Module Specific Options +# +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/matrix/matrix.c Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,181 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "matrix.h" + +#define REG_SET(reg) reg |= (1 << ( matrix[row][col] % 10 ) ) + +#define PIN_SET_COL(pin) \ + switch ( scanMode ) { \ + case scanCol: \ + case scanCol_powrRow: \ + case scanDual: \ + REG_SET(port##pin); break; \ + case scanRow_powrCol: REG_SET(ddr##pin); REG_SET(port##pin); break; \ + } \ + break + +#define PIN_SET_ROW(pin) \ + switch ( scanMode ) { \ + case scanRow: \ + case scanRow_powrCol: \ + case scanDual: \ + REG_SET(port##pin); break; \ + case scanCol_powrRow: REG_SET(ddr##pin); REG_SET(port##pin); break; \ + } \ + break + +#define PIN_CASE(pinLetter) \ + case pin##pinLetter##0: \ + case pin##pinLetter##1: \ + case pin##pinLetter##2: \ + case pin##pinLetter##3: \ + case pin##pinLetter##4: \ + case pin##pinLetter##5: \ + case pin##pinLetter##6: \ + case pin##pinLetter##7 + +#define PIN_TEST_COL(pin) \ + if ( !( pin & ( 1 << ( matrix[0][col] % 10 ) ) \ + detectArray[matrix[row][col]]++; \ + break + + +void matrix_pinSetup( uint8_t *matrix ) +{ + // Setup the variables + uint8_t portA = 0x00; + uint8_t portB = 0x00; + uint8_t portC = 0x00; + uint8_t portD = 0x00; + uint8_t portE = 0x00; + uint8_t portF = 0x00; + + uint8_t ddrA = 0x00; + uint8_t ddrB = 0x00; + uint8_t ddrC = 0x00; + uint8_t ddrD = 0x00; + uint8_t ddrE = 0x00; + uint8_t ddrF = 0x00; + + // Loop through all the pin assignments, for the initial pin settings + int row, col; + + // Rows + for ( row = 1; row < sizeof(matrix); row++ ) { + switch ( matrix[row][col] ) { + PIN_CASE(A): + PIN_SET_ROW(A); + PIN_CASE(B): + PIN_SET_ROW(B); + PIN_CASE(C): + PIN_SET_ROW(C); + PIN_CASE(D): + PIN_SET_ROW(D); + PIN_CASE(E): + PIN_SET_ROW(E); + PIN_CASE(F): + PIN_SET_ROW(F); + + default: + continue; + } + } + + // Columns + for ( col = 1; col < sizeof(matrix[0]); row++ ) { + switch ( matrix[row][col] ) { + PIN_CASE(A): + PIN_SET_COL(A); + PIN_CASE(B): + PIN_SET_COL(B); + PIN_CASE(C): + PIN_SET_COL(C); + PIN_CASE(D): + PIN_SET_COL(D); + PIN_CASE(E): + PIN_SET_COL(E); + PIN_CASE(F): + PIN_SET_COL(F); + + default: + continue; + } + } + + // Setting the pins + DDRA = ddrA; + DDRB = ddrB; + DDRC = ddrC; + DDRD = ddrD; + DDRE = ddrE; + DDRF = ddrF; + + PORTA = portA; + PORTB = portB; + PORTC = portC; + PORTD = portD; + PORTE = portE; + PORTF = portF; +} + +// TODO Proper matrix scanning +void matrix_scan( uint8_t *matrix, uint8_t *detectArray ) +{ + // Column Scan +#if scanMode == scanCol + uint8_t col = 1; + uint8_t row = 1; + for ( ; col < sizeof(matrix[1]); col++ ) { + switch ( matrix[0][col] / 10 ) { + case 0: // PINA + PIN_TEST_COL(PINA); + case 1: // PINB + PIN_TEST_COL(PINB); + case 2: // PINC + PIN_TEST_COL(PINC); + case 3: // PIND + PIN_TEST_COL(PIND); + case 4: // PINE + PIN_TEST_COL(PINE); + case 5: // PINF + PIN_TEST_COL(PINF); + } + } +#endif + + // Row Scan +#if scanMode == scanRow +#endif + + // Column Scan, Power Row +#if scanMode == scanCol_powrRow +#endif + + // Row Scan, Power Column +#if scanMode == scanRow_powrCol +#endif + + // Dual Scan +#if scanMode == scanDual +#endif +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/matrix/matrix.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,151 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MATRIX_H +#define __MATRIX_H + +// ----- Quick Map (don't change) ----- +#define pinA0 0 +#define pinA1 1 +#define pinA2 2 +#define pinA3 3 +#define pinA4 4 +#define pinA5 5 +#define pinA6 6 +#define pinA7 7 + +#define pinB0 10 +#define pinB1 11 +#define pinB2 12 +#define pinB3 13 +#define pinB4 14 +#define pinB5 15 +#define pinB6 16 +#define pinB7 17 + +#define pinC0 20 +#define pinC1 21 +#define pinC2 22 +#define pinC3 23 +#define pinC4 24 +#define pinC5 25 +#define pinC6 26 +#define pinC7 27 + +#define pinD0 30 +#define pinD1 31 +#define pinD2 32 +#define pinD3 33 +#define pinD4 34 +#define pinD5 35 +#define pinD6 36 +#define pinD7 37 + +#define pinE0 40 +#define pinE1 41 +#define pinE2 42 +#define pinE3 43 +#define pinE4 44 +#define pinE5 45 +#define pinE6 46 +#define pinE7 47 + +#define pinF0 50 +#define pinF1 51 +#define pinF2 52 +#define pinF3 53 +#define pinF4 54 +#define pinF5 55 +#define pinF6 56 +#define pinF7 57 + +#define pinNULL 128 + + + +// ----- Scan Mode (usually dual-scan) ----- +// Ordered by increasing memory/CPU usage +#define scanRow 0 // Needed for powered switches (Hall-Effect) +#define scanCol 1 // Opposite of scanRow +#define scanRow_powrCol 2 // NKRO supported (simple detection) +#define scanCol_powrRow 3 // Opposite of scanRow_powrCol +#define scanDual 4 // Typical ~2KRO matrix + + + +// ----- Scan Mode Setting ----- +#define scanMode scanCol + + + +// ----- Key Settings ----- +#define keyboardSize 16 // # of keys + + + +// ----- Matrix Configuration ----- +static uint8_t matrix_pinout[][] = { + + + +// Just layout the matrix by rows and columns +// Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol +// The mode allows for optimization in the kind of scanning algorithms that are done +// +// The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0). +// See the keymap.h file for the various preconfigured arrays. + +// Scan Mode | Col 1 | Col 2 | Col 3 | Col 4 | Col 4 | ... +// ------------------------------------------------------- +// Row 1 | Key 1 Key 7 Key32 ... +// Row 2 | Key 3 Key92 ... +// Row 3 | Key23 ... +// Row 4 | ... +// Row 5 | +// ... | + + + { scanMode, pinF4, pinA6, pinA1, pinA3, pinF5, pinA5, pinA2, pinF0, pinF6, pinA7, pinA0, pinF1, pinF3, pinF7, pinA4, pinF2 }, + { pinNULL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, + + +// Example Rows +//{ pinE0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, +//{ pinE1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, }, + + +}; + + +// ----- Variables ----- + +// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) +// Other Bits: Pressed state sample counter +uint8_t keyboardDetectArray[keyboardSize + 1]; + + + +// ----- Functions ----- + + +#endif // __MATRIX_H + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/matrix/scan_loop.c Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,137 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#include <stdint.h> +#include <usb_keyboard_debug.h> +#include <keymap.h> +// Debouncing Defines +#define SAMPLE_THRESHOLD 110 +#define MAX_SAMPLES 127 // Max is 127, reaching 128 is very bad +// Loop over all of the sampled keys of the given array +// If the number of samples is higher than the sample threshold, flag the high bit, clear otherwise +// This should be resetting VERY quickly, cutting off a potentially valid keypress is not an issue +#define DEBOUNCE_ASSESS(table,size) \ + for ( uint8_t key = 1; key < size + 1; key++ ) {\ + table[key] = ( table[key] & ~(1 << 7) ) > SAMPLE_THRESHOLD ? (1 << 7) : 0x00; \ + } \ + +// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) +// Other Bits: Pressed state sample counter +#define KEYBOARD_SIZE 23 +uint8_t keyboardDetectArray[KEYBOARD_SIZE + 1]; + +// Interrupt Variable +volatile uint8_t sendKeypresses = 0; + +// USB Data Send +void usb_send( uint8_t validKeys ) +{ + // TODO undo potentially old keys + for ( uint8_t c = validKeys; c < 6; c++ ) + keyboard_keys[c] = 0; + + // Send keypresses + usb_keyboard_send(); + + // Clear sendKeypresses Flag + sendKeypresses = 0; + + // Clear modifiers + keyboard_modifier_keys = 0; +} + + +// Given a sampling array, and the current number of detected keypress +// Add as many keypresses from the sampling array to the USB key send array as possible. +void keyPressDetection( uint8_t *keys, uint8_t *validKeys, uint8_t numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) { + for ( uint8_t key = 0; key < numberOfKeys + 1; key++ ) { + if ( keys[key] & (1 << 7) ) { + pint8( key ); + //print(" "); + uint8_t modFound = 0; + + // Determine if the key is a modifier + for ( uint8_t mod = 0; mod < numberOfModifiers; mod++ ) { + // Modifier found + if ( modifiers[mod] == key ) { + keyboard_modifier_keys |= map[key]; + modFound = 1; + break; + } + } + if ( modFound ) + continue; + + // Too many keys + if ( *validKeys == 6 ) + break; + + // Allow ignoring keys with 0's + if ( map[key] != 0 ) + keyboard_keys[(*validKeys)++] = map[key]; + } + } +} + + +// Main Detection Loop +void scan_loop( void ) +{ + //matrix_pinSetup( matrix_pinout ); + uint8_t count = 0; + + for ( ;; ) { + //matrix_scan( matrix_pinout, keyboardDetectArray ); + + // Check count to see if the sample threshold may have been reached, otherwise collect more data + if ( count++ < MAX_SAMPLES ) + continue; + + // Reset Sample Counter + count = 0; + + // Assess debouncing sample table + //DEBOUNCE_ASSESS(keyDetectArray,KEYBOARD_SIZE) + + // Send keypresses over USB if the ISR has signalled that it's time + if ( !sendKeypresses ) + continue; + + // Layout Setup + uint8_t validKeys = 0; + + uint8_t *keyboard_MODMASK = keyboard_modifierMask; + uint8_t keyboard_NUMMODS = MODIFIERS_KEYBOARD; + uint8_t *keyboard_MAP = defaultMap; + + // TODO Layout Switching + + // TODO Macro Processing + + // Debounce Sampling Array to USB Data Array + keyPressDetection( keyboardDetectArray, &validKeys, KEYBOARD_SIZE, keyboard_MODMASK, keyboard_NUMMODS, keyboard_MAP ); + + // Send USB Data + usb_send( validKeys ); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/matrix/scan_loop.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,31 @@ +/* Copyright (C) 2011 by Jacob Alexander + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __SCAN_LOOP_H +#define __SCAN_LOOP_H + +//extern uint8_t keyboardDetectArray[KEYBOARDZ +extern volatile uint8_t sendKeypresses; + +void scan_loop( void ); + +#endif // __SCAN_LOOP_H +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Scan/matrix/setup.cmake Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,23 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( SCAN_SRCS + scan_loop.c +) + + +### +# Module Specific Options TODO Fixme!! (../) +# +add_definitions( -I../Keymap ) +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USB/pjrc/setup.cmake Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,22 @@ +###| CMake Kiibohd Controller USB Module |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( USB_SRCS + usb_keyboard_debug.c +) + + +### +# Module Specific Options +# +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USB/pjrc/usb_keyboard.c Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,592 @@ +/* USB Keyboard Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/usb_keyboard.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release +// Version 1.1: Add support for Teensy 2.0 + +#define USB_SERIAL_PRIVATE_INCLUDE +#include "usb_keyboard.h" + +/************************************************************************** + * + * Configurable Options + * + **************************************************************************/ + +// You can change these to give your code its own name. +#define STR_MANUFACTURER L"MfgName" +#define STR_PRODUCT L"Keyboard" + + +// Mac OS-X and Linux automatically load the correct drivers. On +// Windows, even though the driver is supplied by Microsoft, an +// INF file is needed to load the driver. These numbers need to +// match the INF file. +#define VENDOR_ID 0x16C0 +#define PRODUCT_ID 0x047C + + +// USB devices are supposed to implment a halt feature, which is +// rarely (if ever) used. If you comment this line out, the halt +// code will be removed, saving 102 bytes of space (gcc 4.3.0). +// This is not strictly USB compliant, but works with all major +// operating systems. +#define SUPPORT_ENDPOINT_HALT + + + +/************************************************************************** + * + * Endpoint Buffer Configuration + * + **************************************************************************/ + +#define ENDPOINT0_SIZE 32 + +#define KEYBOARD_INTERFACE 0 +#define KEYBOARD_ENDPOINT 3 +#define KEYBOARD_SIZE 8 +#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER + +static const uint8_t PROGMEM endpoint_config_table[] = { + 0, + 0, + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, + 0 +}; + + +/************************************************************************** + * + * Descriptor Data + * + **************************************************************************/ + +// Descriptors are the data that your computer reads when it auto-detects +// this USB device (called "enumeration" in USB lingo). The most commonly +// changed items are editable at the top of this file. Changing things +// in here should only be done by those who've read chapter 9 of the USB +// spec and relevant portions of any USB class specifications! + + +static uint8_t PROGMEM device_descriptor[] = { + 18, // bLength + 1, // bDescriptorType + 0x00, 0x02, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + ENDPOINT0_SIZE, // bMaxPacketSize0 + LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor + LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct + 0x00, 0x01, // bcdDevice + 1, // iManufacturer + 2, // iProduct + 0, // iSerialNumber + 1 // bNumConfigurations +}; + +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static uint8_t PROGMEM keyboard_hid_report_desc[] = { + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte + 0x95, 0x01, // Report Count (1), + 0x75, 0x08, // Report Size (8), + 0x81, 0x03, // Input (Constant), ;Reserved byte + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), ;LED report padding + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x68, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x68, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + 0xc0 // End Collection +}; + +#define CONFIG1_DESC_SIZE (9+9+9+7) +#define KEYBOARD_HID_DESC_OFFSET (9+9) +static uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { + // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 + 9, // bLength; + 2, // bDescriptorType; + LSB(CONFIG1_DESC_SIZE), // wTotalLength + MSB(CONFIG1_DESC_SIZE), + 1, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0xC0, // bmAttributes + 50, // bMaxPower + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + KEYBOARD_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x01, // bInterfaceSubClass (0x01 = Boot) + 0x01, // bInterfaceProtocol (0x01 = Keyboard) + 0, // iInterface + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(keyboard_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + KEYBOARD_SIZE, 0, // wMaxPacketSize + 1 // bInterval +}; + +// If you're desperate for a little extra code memory, these strings +// can be completely removed if iManufacturer, iProduct, iSerialNumber +// in the device desciptor are changed to zeros. +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + int16_t wString[]; +}; +static struct usb_string_descriptor_struct PROGMEM string0 = { + 4, + 3, + {0x0409} +}; +static struct usb_string_descriptor_struct PROGMEM string1 = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +static struct usb_string_descriptor_struct PROGMEM string2 = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +static struct descriptor_list_struct { + uint16_t wValue; + uint16_t wIndex; + const uint8_t *addr; + uint8_t length; +} PROGMEM descriptor_list[] = { + {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, + {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, + {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, + {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, + {0x0300, 0x0000, (const uint8_t *)&string0, 4}, + {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, + {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)} +}; +#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) + + +/************************************************************************** + * + * Variables - these are the only non-stack RAM usage + * + **************************************************************************/ + +// zero when we are not configured, non-zero when enumerated +static volatile uint8_t usb_configuration=0; + +// which modifier keys are currently pressed +// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui +// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui +uint8_t keyboard_modifier_keys=0; + +// which keys are currently pressed, up to 6 keys may be down at once +uint8_t keyboard_keys[6]={0,0,0,0,0,0}; + +// protocol setting from the host. We use exactly the same report +// either way, so this variable only stores the setting since we +// are required to be able to report which setting is in use. +static uint8_t keyboard_protocol=1; + +// the idle configuration, how often we send the report to the +// host (ms * 4) even when it hasn't changed +static uint8_t keyboard_idle_config=125; + +// count until idle timeout +static uint8_t keyboard_idle_count=0; + +// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana +volatile uint8_t keyboard_leds=0; + + +/************************************************************************** + * + * Public Functions - these are the API intended for the user + * + **************************************************************************/ + + +// initialize USB +void usb_init(void) +{ + HW_CONFIG(); + USB_FREEZE(); // enable USB + PLL_CONFIG(); // config PLL + while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock + USB_CONFIG(); // start USB clock + UDCON = 0; // enable attach resistor + usb_configuration = 0; + UDIEN = (1<<EORSTE)|(1<<SOFE); + sei(); +} + +// return 0 if the USB is not configured, or the configuration +// number selected by the HOST +uint8_t usb_configured(void) +{ + return usb_configuration; +} + + +// perform a single keystroke +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier) +{ + int8_t r; + + keyboard_modifier_keys = modifier; + keyboard_keys[0] = key; + r = usb_keyboard_send(); + if (r) return r; + keyboard_modifier_keys = 0; + keyboard_keys[0] = 0; + return usb_keyboard_send(); +} + +// send the contents of keyboard_keys and keyboard_modifier_keys +int8_t usb_keyboard_send(void) +{ + uint8_t i, intr_state, timeout; + + if (!usb_configuration) return -1; + intr_state = SREG; + cli(); + UENUM = KEYBOARD_ENDPOINT; + timeout = UDFNUML + 50; + while (1) { + // are we ready to transmit? + if (UEINTX & (1<<RWAL)) break; + SREG = intr_state; + // has the USB gone offline? + if (!usb_configuration) return -1; + // have we waited too long? + if (UDFNUML == timeout) return -1; + // get ready to try checking again + intr_state = SREG; + cli(); + UENUM = KEYBOARD_ENDPOINT; + } + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + UEINTX = 0x3A; + keyboard_idle_count = 0; + SREG = intr_state; + return 0; +} + +/************************************************************************** + * + * Private Functions - not intended for general user consumption.... + * + **************************************************************************/ + + + +// USB Device Interrupt - handle all device-level events +// the transmit buffer flushing is triggered by the start of frame +// +ISR(USB_GEN_vect) +{ + uint8_t intbits, t, i; + static uint8_t div4=0; + + intbits = UDINT; + UDINT = 0; + if (intbits & (1<<EORSTI)) { + UENUM = 0; + UECONX = 1; + UECFG0X = EP_TYPE_CONTROL; + UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER; + UEIENX = (1<<RXSTPE); + usb_configuration = 0; + } + if ((intbits & (1<<SOFI)) && usb_configuration) { + if (keyboard_idle_config && (++div4 & 3) == 0) { + UENUM = KEYBOARD_ENDPOINT; + if (UEINTX & (1<<RWAL)) { + keyboard_idle_count++; + if (keyboard_idle_count == keyboard_idle_config) { + keyboard_idle_count = 0; + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + UEINTX = 0x3A; + } + } + } + } +} + + + +// Misc functions to wait for ready and send/receive packets +static inline void usb_wait_in_ready(void) +{ + while (!(UEINTX & (1<<TXINI))) ; +} +static inline void usb_send_in(void) +{ + UEINTX = ~(1<<TXINI); +} +static inline void usb_wait_receive_out(void) +{ + while (!(UEINTX & (1<<RXOUTI))) ; +} +static inline void usb_ack_out(void) +{ + UEINTX = ~(1<<RXOUTI); +} + + + +// USB Endpoint Interrupt - endpoint 0 is handled here. The +// other endpoints are manipulated by the user-callable +// functions, and the start-of-frame interrupt. +// +ISR(USB_COM_vect) +{ + uint8_t intbits; + const uint8_t *list; + const uint8_t *cfg; + uint8_t i, n, len, en; + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint16_t desc_val; + const uint8_t *desc_addr; + uint8_t desc_length; + + UENUM = 0; + intbits = UEINTX; + if (intbits & (1<<RXSTPI)) { + bmRequestType = UEDATX; + bRequest = UEDATX; + wValue = UEDATX; + wValue |= (UEDATX << 8); + wIndex = UEDATX; + wIndex |= (UEDATX << 8); + wLength = UEDATX; + wLength |= (UEDATX << 8); + UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); + if (bRequest == GET_DESCRIPTOR) { + list = (const uint8_t *)descriptor_list; + for (i=0; ; i++) { + if (i >= NUM_DESC_LIST) { + UECONX = (1<<STALLRQ)|(1<<EPEN); //stall + return; + } + desc_val = pgm_read_word(list); + if (desc_val != wValue) { + list += sizeof(struct descriptor_list_struct); + continue; + } + list += 2; + desc_val = pgm_read_word(list); + if (desc_val != wIndex) { + list += sizeof(struct descriptor_list_struct)-2; + continue; + } + list += 2; + desc_addr = (const uint8_t *)pgm_read_word(list); + list += 2; + desc_length = pgm_read_byte(list); + break; + } + len = (wLength < 256) ? wLength : 255; + if (len > desc_length) len = desc_length; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); + if (i & (1<<RXOUTI)) return; // abort + // send IN packet + n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; + for (i = n; i; i--) { + UEDATX = pgm_read_byte(desc_addr++); + } + len -= n; + usb_send_in(); + } while (len || n == ENDPOINT0_SIZE); + return; + } + if (bRequest == SET_ADDRESS) { + usb_send_in(); + usb_wait_in_ready(); + UDADDR = wValue | (1<<ADDEN); + return; + } + if (bRequest == SET_CONFIGURATION && bmRequestType == 0) { + usb_configuration = wValue; + usb_send_in(); + cfg = endpoint_config_table; + for (i=1; i<5; i++) { + UENUM = i; + en = pgm_read_byte(cfg++); + UECONX = en; + if (en) { + UECFG0X = pgm_read_byte(cfg++); + UECFG1X = pgm_read_byte(cfg++); + } + } + UERST = 0x1E; + UERST = 0; + return; + } + if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) { + usb_wait_in_ready(); + UEDATX = usb_configuration; + usb_send_in(); + return; + } + + if (bRequest == GET_STATUS) { + usb_wait_in_ready(); + i = 0; + #ifdef SUPPORT_ENDPOINT_HALT + if (bmRequestType == 0x82) { + UENUM = wIndex; + if (UECONX & (1<<STALLRQ)) i = 1; + UENUM = 0; + } + #endif + UEDATX = i; + UEDATX = 0; + usb_send_in(); + return; + } + #ifdef SUPPORT_ENDPOINT_HALT + if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) + && bmRequestType == 0x02 && wValue == 0) { + i = wIndex & 0x7F; + if (i >= 1 && i <= MAX_ENDPOINT) { + usb_send_in(); + UENUM = i; + if (bRequest == SET_FEATURE) { + UECONX = (1<<STALLRQ)|(1<<EPEN); + } else { + UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN); + UERST = (1 << i); + UERST = 0; + } + return; + } + } + #endif + if (wIndex == KEYBOARD_INTERFACE) { + if (bmRequestType == 0xA1) { + if (bRequest == HID_GET_REPORT) { + usb_wait_in_ready(); + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + usb_send_in(); + return; + } + if (bRequest == HID_GET_IDLE) { + usb_wait_in_ready(); + UEDATX = keyboard_idle_config; + usb_send_in(); + return; + } + if (bRequest == HID_GET_PROTOCOL) { + usb_wait_in_ready(); + UEDATX = keyboard_protocol; + usb_send_in(); + return; + } + } + if (bmRequestType == 0x21) { + if (bRequest == HID_SET_REPORT) { + usb_wait_receive_out(); + keyboard_leds = UEDATX; + usb_ack_out(); + usb_send_in(); + return; + } + if (bRequest == HID_SET_IDLE) { + keyboard_idle_config = (wValue >> 8); + keyboard_idle_count = 0; + usb_send_in(); + return; + } + if (bRequest == HID_SET_PROTOCOL) { + keyboard_protocol = wValue; + usb_send_in(); + return; + } + } + } + } + UECONX = (1<<STALLRQ) | (1<<EPEN); // stall +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USB/pjrc/usb_keyboard.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,16 @@ +#ifndef usb_serial_h__ +#define usb_serial_h__ + +#include <stdint.h> + +void usb_init(void); // initialize everything +uint8_t usb_configured(void); // is the USB port configured + +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier); +int8_t usb_keyboard_send(void); +extern uint8_t keyboard_modifier_keys; +extern uint8_t keyboard_keys[6]; +extern volatile uint8_t keyboard_leds; + +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USB/pjrc/usb_keyboard_debug.c Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,750 @@ +/* USB Keyboard Plus Debug Channel Example for Teensy USB Development Board + * http://www.pjrc.com/teensy/usb_keyboard.html + * Copyright (c) 2009 PJRC.COM, LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Version 1.0: Initial Release +// Version 1.1: Add support for Teensy 2.0 + +#define USB_SERIAL_PRIVATE_INCLUDE +#include "usb_keyboard_debug.h" + +/************************************************************************** + * + * Configurable Options + * + **************************************************************************/ + +// You can change these to give your code its own name. +#define STR_MANUFACTURER L"MfgName" +#define STR_PRODUCT L"Keyboard" + + +// Mac OS-X and Linux automatically load the correct drivers. On +// Windows, even though the driver is supplied by Microsoft, an +// INF file is needed to load the driver. These numbers need to +// match the INF file. +#define VENDOR_ID 0x16C0 +#define PRODUCT_ID 0x047D + + +// USB devices are supposed to implment a halt feature, which is +// rarely (if ever) used. If you comment this line out, the halt +// code will be removed, saving 102 bytes of space (gcc 4.3.0). +// This is not strictly USB compliant, but works with all major +// operating systems. +#define SUPPORT_ENDPOINT_HALT + + + +/************************************************************************** + * + * Endpoint Buffer Configuration + * + **************************************************************************/ + +#define ENDPOINT0_SIZE 32 + +#define KEYBOARD_INTERFACE 0 +#define KEYBOARD_ENDPOINT 3 +#define KEYBOARD_SIZE 8 +#define KEYBOARD_BUFFER EP_DOUBLE_BUFFER + +#define DEBUG_INTERFACE 1 +#define DEBUG_TX_ENDPOINT 4 +#define DEBUG_TX_SIZE 32 +#define DEBUG_TX_BUFFER EP_DOUBLE_BUFFER + +static const uint8_t PROGMEM endpoint_config_table[] = { + 0, + 0, + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER, + 1, EP_TYPE_INTERRUPT_IN, EP_SIZE(DEBUG_TX_SIZE) | DEBUG_TX_BUFFER +}; + + +/************************************************************************** + * + * Descriptor Data + * + **************************************************************************/ + +// Descriptors are the data that your computer reads when it auto-detects +// this USB device (called "enumeration" in USB lingo). The most commonly +// changed items are editable at the top of this file. Changing things +// in here should only be done by those who've read chapter 9 of the USB +// spec and relevant portions of any USB class specifications! + + +static const uint8_t PROGMEM device_descriptor[] = { + 18, // bLength + 1, // bDescriptorType + 0x00, 0x02, // bcdUSB + 0, // bDeviceClass + 0, // bDeviceSubClass + 0, // bDeviceProtocol + ENDPOINT0_SIZE, // bMaxPacketSize0 + LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor + LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct + 0x00, 0x01, // bcdDevice + 1, // iManufacturer + 2, // iProduct + 0, // iSerialNumber + 1 // bNumConfigurations +}; + +// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 +static const uint8_t PROGMEM keyboard_hid_report_desc[] = { + 0x05, 0x01, // Usage Page (Generic Desktop), + 0x09, 0x06, // Usage (Keyboard), + 0xA1, 0x01, // Collection (Application), + 0x75, 0x01, // Report Size (1), + 0x95, 0x08, // Report Count (8), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0xE0, // Usage Minimum (224), + 0x29, 0xE7, // Usage Maximum (231), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x01, // Logical Maximum (1), + 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte + 0x95, 0x01, // Report Count (1), + 0x75, 0x08, // Report Size (8), + 0x81, 0x03, // Input (Constant), ;Reserved byte + 0x95, 0x05, // Report Count (5), + 0x75, 0x01, // Report Size (1), + 0x05, 0x08, // Usage Page (LEDs), + 0x19, 0x01, // Usage Minimum (1), + 0x29, 0x05, // Usage Maximum (5), + 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report + 0x95, 0x01, // Report Count (1), + 0x75, 0x03, // Report Size (3), + 0x91, 0x03, // Output (Constant), ;LED report padding + 0x95, 0x06, // Report Count (6), + 0x75, 0x08, // Report Size (8), + 0x15, 0x00, // Logical Minimum (0), + 0x25, 0x68, // Logical Maximum(104), + 0x05, 0x07, // Usage Page (Key Codes), + 0x19, 0x00, // Usage Minimum (0), + 0x29, 0x68, // Usage Maximum (104), + 0x81, 0x00, // Input (Data, Array), + 0xc0 // End Collection +}; + +static const uint8_t PROGMEM debug_hid_report_desc[] = { + 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) + 0x09, 0x74, // Usage 0x74 + 0xA1, 0x53, // Collection 0x53 + 0x75, 0x08, // report size = 8 bits + 0x15, 0x00, // logical minimum = 0 + 0x26, 0xFF, 0x00, // logical maximum = 255 + 0x95, DEBUG_TX_SIZE, // report count + 0x09, 0x75, // usage + 0x81, 0x02, // Input (array) + 0xC0 // end collection +}; + +#define CONFIG1_DESC_SIZE (9+9+9+7+9+9+7) +#define KEYBOARD_HID_DESC_OFFSET (9+9) +#define DEBUG_HID_DESC_OFFSET (9+9+9+7+9) +static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = { + // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 + 9, // bLength; + 2, // bDescriptorType; + LSB(CONFIG1_DESC_SIZE), // wTotalLength + MSB(CONFIG1_DESC_SIZE), + 2, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0xC0, // bmAttributes + 50, // bMaxPower + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + KEYBOARD_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x01, // bInterfaceSubClass (0x01 = Boot) + 0x01, // bInterfaceProtocol (0x01 = Keyboard) + 0, // iInterface + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(keyboard_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + KEYBOARD_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + KEYBOARD_SIZE, 0, // wMaxPacketSize + 1, // bInterval + // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 + 9, // bLength + 4, // bDescriptorType + DEBUG_INTERFACE, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + 0x03, // bInterfaceClass (0x03 = HID) + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0, // iInterface + // HID interface descriptor, HID 1.11 spec, section 6.2.1 + 9, // bLength + 0x21, // bDescriptorType + 0x11, 0x01, // bcdHID + 0, // bCountryCode + 1, // bNumDescriptors + 0x22, // bDescriptorType + sizeof(debug_hid_report_desc), // wDescriptorLength + 0, + // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 + 7, // bLength + 5, // bDescriptorType + DEBUG_TX_ENDPOINT | 0x80, // bEndpointAddress + 0x03, // bmAttributes (0x03=intr) + DEBUG_TX_SIZE, 0, // wMaxPacketSize + 1 // bInterval +}; + +// If you're desperate for a little extra code memory, these strings +// can be completely removed if iManufacturer, iProduct, iSerialNumber +// in the device desciptor are changed to zeros. +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + int16_t wString[]; +}; +static const struct usb_string_descriptor_struct PROGMEM string0 = { + 4, + 3, + {0x0409} +}; +static const struct usb_string_descriptor_struct PROGMEM string1 = { + sizeof(STR_MANUFACTURER), + 3, + STR_MANUFACTURER +}; +static const struct usb_string_descriptor_struct PROGMEM string2 = { + sizeof(STR_PRODUCT), + 3, + STR_PRODUCT +}; + +// This table defines which descriptor data is sent for each specific +// request from the host (in wValue and wIndex). +static const struct descriptor_list_struct { + uint16_t wValue; + uint16_t wIndex; + const uint8_t *addr; + uint8_t length; +} PROGMEM descriptor_list[] = { + {0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)}, + {0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)}, + {0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)}, + {0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9}, + {0x2200, DEBUG_INTERFACE, debug_hid_report_desc, sizeof(debug_hid_report_desc)}, + {0x2100, DEBUG_INTERFACE, config1_descriptor+DEBUG_HID_DESC_OFFSET, 9}, + {0x0300, 0x0000, (const uint8_t *)&string0, 4}, + {0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)}, + {0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)} +}; +#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct)) + + +/************************************************************************** + * + * Variables - these are the only non-stack RAM usage + * + **************************************************************************/ + +// zero when we are not configured, non-zero when enumerated +static volatile uint8_t usb_configuration=0; + +// the time remaining before we transmit any partially full +// packet, or send a zero length packet. +static volatile uint8_t debug_flush_timer=0; + +// which modifier keys are currently pressed +// 1=left ctrl, 2=left shift, 4=left alt, 8=left gui +// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui +uint8_t keyboard_modifier_keys=0; + +// which keys are currently pressed, up to 6 keys may be down at once +uint8_t keyboard_keys[6]={0,0,0,0,0,0}; + +// protocol setting from the host. We use exactly the same report +// either way, so this variable only stores the setting since we +// are required to be able to report which setting is in use. +static uint8_t keyboard_protocol=1; + +// the idle configuration, how often we send the report to the +// host (ms * 4) even when it hasn't changed +static uint8_t keyboard_idle_config=125; + +// count until idle timeout +static uint8_t keyboard_idle_count=0; + +// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana +volatile uint8_t keyboard_leds=0; + + +/************************************************************************** + * + * Public Functions - these are the API intended for the user + * + **************************************************************************/ + + +// initialize USB +void usb_init(void) +{ + HW_CONFIG(); + USB_FREEZE(); // enable USB + PLL_CONFIG(); // config PLL + while (!(PLLCSR & (1<<PLOCK))) ; // wait for PLL lock + USB_CONFIG(); // start USB clock + UDCON = 0; // enable attach resistor + usb_configuration = 0; + UDIEN = (1<<EORSTE)|(1<<SOFE); + sei(); +} + +// return 0 if the USB is not configured, or the configuration +// number selected by the HOST +uint8_t usb_configured(void) +{ + return usb_configuration; +} + + +// perform a single keystroke +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier) +{ + int8_t r; + + keyboard_modifier_keys = modifier; + keyboard_keys[0] = key; + r = usb_keyboard_send(); + if (r) return r; + keyboard_modifier_keys = 0; + keyboard_keys[0] = 0; + return usb_keyboard_send(); +} + +// send the contents of keyboard_keys and keyboard_modifier_keys +int8_t usb_keyboard_send(void) +{ + uint8_t i, intr_state, timeout; + + if (!usb_configuration) return -1; + intr_state = SREG; + cli(); + UENUM = KEYBOARD_ENDPOINT; + timeout = UDFNUML + 50; + while (1) { + // are we ready to transmit? + if (UEINTX & (1<<RWAL)) break; + SREG = intr_state; + // has the USB gone offline? + if (!usb_configuration) return -1; + // have we waited too long? + if (UDFNUML == timeout) return -1; + // get ready to try checking again + intr_state = SREG; + cli(); + UENUM = KEYBOARD_ENDPOINT; + } + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + UEINTX = 0x3A; + keyboard_idle_count = 0; + SREG = intr_state; + return 0; +} + +// transmit a character. 0 returned on success, -1 on error +int8_t usb_debug_putchar(uint8_t c) +{ + static uint8_t previous_timeout=0; + uint8_t timeout, intr_state; + + // if we're not online (enumerated and configured), error + if (!usb_configuration) return -1; + // interrupts are disabled so these functions can be + // used from the main program or interrupt context, + // even both in the same program! + intr_state = SREG; + cli(); + UENUM = DEBUG_TX_ENDPOINT; + // if we gave up due to timeout before, don't wait again + if (previous_timeout) { + if (!(UEINTX & (1<<RWAL))) { + SREG = intr_state; + return -1; + } + previous_timeout = 0; + } + // wait for the FIFO to be ready to accept data + timeout = UDFNUML + 4; + while (1) { + // are we ready to transmit? + if (UEINTX & (1<<RWAL)) break; + SREG = intr_state; + // have we waited too long? + if (UDFNUML == timeout) { + previous_timeout = 1; + return -1; + } + // has the USB gone offline? + if (!usb_configuration) return -1; + // get ready to try checking again + intr_state = SREG; + cli(); + UENUM = DEBUG_TX_ENDPOINT; + } + // actually write the byte into the FIFO + UEDATX = c; + // if this completed a packet, transmit it now! + if (!(UEINTX & (1<<RWAL))) { + UEINTX = 0x3A; + debug_flush_timer = 0; + } else { + debug_flush_timer = 2; + } + SREG = intr_state; + return 0; +} + + +// immediately transmit any buffered output. +void usb_debug_flush_output(void) +{ + uint8_t intr_state; + + intr_state = SREG; + cli(); + if (debug_flush_timer) { + UENUM = DEBUG_TX_ENDPOINT; + while ((UEINTX & (1<<RWAL))) { + UEDATX = 0; + } + UEINTX = 0x3A; + debug_flush_timer = 0; + } + SREG = intr_state; +} + + + +/************************************************************************** + * + * Private Functions - not intended for general user consumption.... + * + **************************************************************************/ + + + +// USB Device Interrupt - handle all device-level events +// the transmit buffer flushing is triggered by the start of frame +// +ISR(USB_GEN_vect) +{ + uint8_t intbits, t, i; + static uint8_t div4=0; + + intbits = UDINT; + UDINT = 0; + if (intbits & (1<<EORSTI)) { + UENUM = 0; + UECONX = 1; + UECFG0X = EP_TYPE_CONTROL; + UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER; + UEIENX = (1<<RXSTPE); + usb_configuration = 0; + } + if ((intbits & (1<<SOFI)) && usb_configuration) { + t = debug_flush_timer; + if (t) { + debug_flush_timer = -- t; + if (!t) { + UENUM = DEBUG_TX_ENDPOINT; + while ((UEINTX & (1<<RWAL))) { + UEDATX = 0; + } + UEINTX = 0x3A; + } + } + if (keyboard_idle_config && (++div4 & 3) == 0) { + UENUM = KEYBOARD_ENDPOINT; + if (UEINTX & (1<<RWAL)) { + keyboard_idle_count++; + if (keyboard_idle_count == keyboard_idle_config) { + keyboard_idle_count = 0; + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + UEINTX = 0x3A; + } + } + } + } +} + + + +// Misc functions to wait for ready and send/receive packets +static inline void usb_wait_in_ready(void) +{ + while (!(UEINTX & (1<<TXINI))) ; +} +static inline void usb_send_in(void) +{ + UEINTX = ~(1<<TXINI); +} +static inline void usb_wait_receive_out(void) +{ + while (!(UEINTX & (1<<RXOUTI))) ; +} +static inline void usb_ack_out(void) +{ + UEINTX = ~(1<<RXOUTI); +} + + + +// USB Endpoint Interrupt - endpoint 0 is handled here. The +// other endpoints are manipulated by the user-callable +// functions, and the start-of-frame interrupt. +// +ISR(USB_COM_vect) +{ + uint8_t intbits; + const uint8_t *list; + const uint8_t *cfg; + uint8_t i, n, len, en; + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; + uint16_t desc_val; + const uint8_t *desc_addr; + uint8_t desc_length; + + UENUM = 0; + intbits = UEINTX; + if (intbits & (1<<RXSTPI)) { + bmRequestType = UEDATX; + bRequest = UEDATX; + wValue = UEDATX; + wValue |= (UEDATX << 8); + wIndex = UEDATX; + wIndex |= (UEDATX << 8); + wLength = UEDATX; + wLength |= (UEDATX << 8); + UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI)); + if (bRequest == GET_DESCRIPTOR) { + list = (const uint8_t *)descriptor_list; + for (i=0; ; i++) { + if (i >= NUM_DESC_LIST) { + UECONX = (1<<STALLRQ)|(1<<EPEN); //stall + return; + } + desc_val = pgm_read_word(list); + if (desc_val != wValue) { + list += sizeof(struct descriptor_list_struct); + continue; + } + list += 2; + desc_val = pgm_read_word(list); + if (desc_val != wIndex) { + list += sizeof(struct descriptor_list_struct)-2; + continue; + } + list += 2; + desc_addr = (const uint8_t *)pgm_read_word(list); + list += 2; + desc_length = pgm_read_byte(list); + break; + } + len = (wLength < 256) ? wLength : 255; + if (len > desc_length) len = desc_length; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); + if (i & (1<<RXOUTI)) return; // abort + // send IN packet + n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; + for (i = n; i; i--) { + UEDATX = pgm_read_byte(desc_addr++); + } + len -= n; + usb_send_in(); + } while (len || n == ENDPOINT0_SIZE); + return; + } + if (bRequest == SET_ADDRESS) { + usb_send_in(); + usb_wait_in_ready(); + UDADDR = wValue | (1<<ADDEN); + return; + } + if (bRequest == SET_CONFIGURATION && bmRequestType == 0) { + usb_configuration = wValue; + usb_send_in(); + cfg = endpoint_config_table; + for (i=1; i<5; i++) { + UENUM = i; + en = pgm_read_byte(cfg++); + UECONX = en; + if (en) { + UECFG0X = pgm_read_byte(cfg++); + UECFG1X = pgm_read_byte(cfg++); + } + } + UERST = 0x1E; + UERST = 0; + return; + } + if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) { + usb_wait_in_ready(); + UEDATX = usb_configuration; + usb_send_in(); + return; + } + + if (bRequest == GET_STATUS) { + usb_wait_in_ready(); + i = 0; + #ifdef SUPPORT_ENDPOINT_HALT + if (bmRequestType == 0x82) { + UENUM = wIndex; + if (UECONX & (1<<STALLRQ)) i = 1; + UENUM = 0; + } + #endif + UEDATX = i; + UEDATX = 0; + usb_send_in(); + return; + } + #ifdef SUPPORT_ENDPOINT_HALT + if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE) + && bmRequestType == 0x02 && wValue == 0) { + i = wIndex & 0x7F; + if (i >= 1 && i <= MAX_ENDPOINT) { + usb_send_in(); + UENUM = i; + if (bRequest == SET_FEATURE) { + UECONX = (1<<STALLRQ)|(1<<EPEN); + } else { + UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN); + UERST = (1 << i); + UERST = 0; + } + return; + } + } + #endif + if (wIndex == KEYBOARD_INTERFACE) { + if (bmRequestType == 0xA1) { + if (bRequest == HID_GET_REPORT) { + usb_wait_in_ready(); + UEDATX = keyboard_modifier_keys; + UEDATX = 0; + for (i=0; i<6; i++) { + UEDATX = keyboard_keys[i]; + } + usb_send_in(); + return; + } + if (bRequest == HID_GET_IDLE) { + usb_wait_in_ready(); + UEDATX = keyboard_idle_config; + usb_send_in(); + return; + } + if (bRequest == HID_GET_PROTOCOL) { + usb_wait_in_ready(); + UEDATX = keyboard_protocol; + usb_send_in(); + return; + } + } + if (bmRequestType == 0x21) { + if (bRequest == HID_SET_REPORT) { + usb_wait_receive_out(); + keyboard_leds = UEDATX; + usb_ack_out(); + usb_send_in(); + return; + } + if (bRequest == HID_SET_IDLE) { + keyboard_idle_config = (wValue >> 8); + keyboard_idle_count = 0; + //usb_wait_in_ready(); + usb_send_in(); + return; + } + if (bRequest == HID_SET_PROTOCOL) { + keyboard_protocol = wValue; + //usb_wait_in_ready(); + usb_send_in(); + return; + } + } + } + if (wIndex == DEBUG_INTERFACE) { + if (bRequest == HID_GET_REPORT && bmRequestType == 0xA1) { + len = wLength; + do { + // wait for host ready for IN packet + do { + i = UEINTX; + } while (!(i & ((1<<TXINI)|(1<<RXOUTI)))); + if (i & (1<<RXOUTI)) return; // abort + // send IN packet + n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE; + for (i = n; i; i--) { + UEDATX = 0; + } + len -= n; + usb_send_in(); + } while (len || n == ENDPOINT0_SIZE); + return; + } + } + } + UECONX = (1<<STALLRQ) | (1<<EPEN); // stall +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USB/pjrc/usb_keyboard_debug.h Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,91 @@ +#ifndef usb_serial_h__ +#define usb_serial_h__ + +#include <stdint.h> + +void usb_init(void); // initialize everything +uint8_t usb_configured(void); // is the USB port configured + +int8_t usb_keyboard_press(uint8_t key, uint8_t modifier); +int8_t usb_keyboard_send(void); +extern uint8_t keyboard_modifier_keys; +extern uint8_t keyboard_keys[6]; +extern volatile uint8_t keyboard_leds; + +int8_t usb_debug_putchar(uint8_t c); // transmit a character +void usb_debug_flush_output(void); // immediately transmit any buffered output +#define USB_DEBUG_HID + + +// Everything below this point is only intended for usb_serial.c +#ifdef USB_SERIAL_PRIVATE_INCLUDE +#include <avr/io.h> +#include <avr/pgmspace.h> +#include <avr/interrupt.h> + +#define EP_TYPE_CONTROL 0x00 +#define EP_TYPE_BULK_IN 0x81 +#define EP_TYPE_BULK_OUT 0x80 +#define EP_TYPE_INTERRUPT_IN 0xC1 +#define EP_TYPE_INTERRUPT_OUT 0xC0 +#define EP_TYPE_ISOCHRONOUS_IN 0x41 +#define EP_TYPE_ISOCHRONOUS_OUT 0x40 + +#define EP_SINGLE_BUFFER 0x02 +#define EP_DOUBLE_BUFFER 0x06 + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +#define MAX_ENDPOINT 4 + +#define LSB(n) (n & 255) +#define MSB(n) ((n >> 8) & 255) + +#if defined(__AVR_AT90USB162__) +#define HW_CONFIG() +#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0))) +#define USB_CONFIG() (USBCON = (1<<USBE)) +#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) +#elif defined(__AVR_ATmega32U4__) +#define HW_CONFIG() (UHWCON = 0x01) +#define PLL_CONFIG() (PLLCSR = 0x12) +#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) +#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) +#elif defined(__AVR_AT90USB646__) +#define HW_CONFIG() (UHWCON = 0x81) +#define PLL_CONFIG() (PLLCSR = 0x1A) +#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) +#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) +#elif defined(__AVR_AT90USB1286__) +#define HW_CONFIG() (UHWCON = 0x81) +#define PLL_CONFIG() (PLLCSR = 0x16) +#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE))) +#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK))) +#endif + +// standard control endpoint request types +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define SET_ADDRESS 5 +#define GET_DESCRIPTOR 6 +#define GET_CONFIGURATION 8 +#define SET_CONFIGURATION 9 +#define GET_INTERFACE 10 +#define SET_INTERFACE 11 +// HID (human interface device) +#define HID_GET_REPORT 1 +#define HID_GET_IDLE 2 +#define HID_GET_PROTOCOL 3 +#define HID_SET_REPORT 9 +#define HID_SET_IDLE 10 +#define HID_SET_PROTOCOL 11 +// CDC (communication class device) +#define CDC_SET_LINE_CODING 0x20 +#define CDC_GET_LINE_CODING 0x21 +#define CDC_SET_CONTROL_LINE_STATE 0x22 +#endif +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/setup.cmake Wed Sep 28 23:25:51 2011 -0700 @@ -0,0 +1,109 @@ +###| CMAKE Kiibohd Controller Source Configurator |### +# +# Written by Jacob Alexander in 2011 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + + +### +# Project Modules +# + +#| Each module is defined by it's own folder (e.g. Scan/Matrix represents the "Matrix" module) +#| All of the modules must be specified, as they generate the sources list of files to compile +#| Any modifications to this file will cause a complete rebuild of the project + +#| Please the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones + +##| Deals with acquiring the keypress information and turning it into a key index +set( ScanModule "matrix" ) + +##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code +set( MacroModule "basic" ) + +##| Sends the current list of usb key codes through USB HID +set( USBModule "pjrc" ) + +##| Debugging source to use, each module has it's own set of defines that it sets +set( DebugModule "basic" ) + + + +### +# Path Setup +# +set( ScanModulePath "Scan/${ScanModule}" ) +set( MacroModulePath "Macro/${MacroModule}" ) +set( USBModulePath "USB/${USBModule}" ) +set( DebugModulePath "Debug/${DebugModule}" ) + + + + +### +# Module Configuration +# + +#| Additional options, usually define settings +add_definitions() + +#| Include path for each of the modules TODO Fixme!! (../) +add_definitions(" + -I../${ScanModulePath} + -I../${MacroModulePath} + -I../${USBModulePath} + -I../${DebugModulePath} +") + + + +### +# Module Processing +# + +#| Go through lists of sources and append paths +#| Usage: +#| PathPrepend( OutputListOfSources <Prepend Path> <InputListOfSources> ) +macro( PathPrepend Output SourcesPath ) + unset( tmpSource ) + + # Loop through items + foreach( item ${ARGN} ) + set( tmpSource ${tmpSource} "${SourcesPath}/${item}" ) + endforeach( item ) + + # Finalize by writing the new list back over the old one + set( ${Output} ${tmpSource} ) +endmacro( PathPrepend ) + + +#| Scan Module +include( "${ScanModulePath}/setup.cmake" ) +PathPrepend( SCAN_SRCS ${ScanModulePath} ${SCAN_SRCS} ) + +#| Macro Module +include( "${MacroModulePath}/setup.cmake" ) +PathPrepend( MACRO_SRCS ${MacroModulePath} ${MACRO_SRCS} ) + +#| USB Module +include( "${USBModulePath}/setup.cmake" ) +PathPrepend( USB_SRCS ${USBModulePath} ${USB_SRCS} ) + +#| Debugging Module +include( "${DebugModulePath}/setup.cmake" ) +PathPrepend( DEBUG_SRCS ${DebugModulePath} ${DEBUG_SRCS} ) + + +#| Print list of all module sources +message( STATUS "Detected Scan Module Source Files: +${SCAN_SRCS}") +message( STATUS "Detected Macro Module Source Files: +${MACRO_SRCS}") +message( STATUS "Detected USB Module Source Files: +${USB_SRCS}") +message( STATUS "Detected Debug Module Source Files: +${DEBUG_SRCS}") +