diff --git a/.gitignore b/.gitignore index 94f1119..dbfbd18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .DS_Store .vscode + diff --git a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino index acfdab2..b7dd563 100644 --- a/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino +++ b/SmartyKit 1 basic drivers/SmartyKit1_KeyboardDriverBasic/SmartyKit1_KeyboardDriverBasic.ino @@ -16,7 +16,8 @@ */ #include -#include + +//#define _SMARTY_DEBUG_ // Keyboard Driver pins connections: // D0 & D1 – reserved for Serial connection @@ -45,8 +46,700 @@ static boolean autoCommandSent = false; // run pre-set command only once after r //10 milliseconds = 100 times per second (100 Hz) #define LORATE_CLOCK_PERIOD_MILLIS 100 + +// Uncomment any of following defines to include those mappings +// or comment to exclude +//#define GERMAN +//#define FRENCH +//#define SPANISH +//#define ITALIAN +//#define SPECIAL + +/* UTF-8 single byte LATIN encodings + 128 to 159 (0x80 to 0x9F) are control characters application generated + 160 to 255 (0xA0 to 0XFF) are used depending on keymap tables + These defines are used to insert them into correct tables */ + +/**************************************************************** + IMPORTANT NOTE EURO currency Symbol is NOT supported in UTF-8 single + byte codings, as EURO symbol came after UTF-8 single byte codings +****************************************************************/ +#define PS2_NO_BREAK_SPACE 160 // nbsp +#define PS2_INVERTED_EXCLAMATION 161 // ¡ +#define PS2_CENT_SIGN 162 // ¢ +#define PS2_POUND_SIGN 163 // £ +#define PS2_CURRENCY_SIGN 164 // ¤ +#define PS2_YEN_SIGN 165 // ¥ +#define PS2_BROKEN_BAR 166 // ¦ +#define PS2_SECTION_SIGN 167 // § +#define PS2_DIAERESIS 168 // ¨ +#define PS2_COPYRIGHT_SIGN 169 // © +#define PS2_FEMININE_ORDINAL 170 // ª +#define PS2_LEFT_DOUBLE_ANGLE_QUOTE 171 // « +#define PS2_NOT_SIGN 172 // ¬ +#define PS2_HYPHEN 173 +#define PS2_REGISTERED_SIGN 174 // ® +#define PS2_MACRON 175 // ¯ +#define PS2_DEGREE_SIGN 176 // ° +#define PS2_PLUS_MINUS_SIGN 177 // ± +#define PS2_SUPERSCRIPT_TWO 178 // ² +#define PS2_SUPERSCRIPT_THREE 179 // ³ +#define PS2_ACUTE_ACCENT 180 // ´ +#define PS2_MICRO_SIGN 181 // µ +#define PS2_PILCROW_SIGN 182 // ¶ +#define PS2_MIDDLE_DOT 183 // · +#define PS2_CEDILLA 184 // ¸ +#define PS2_SUPERSCRIPT_ONE 185 // ¹ +#define PS2_MASCULINE_ORDINAL 186 // º +#define PS2_RIGHT_DOUBLE_ANGLE_QUOTE 187 // » +#define PS2_FRACTION_ONE_QUARTER 188 // ¼ +#define PS2_FRACTION_ONE_HALF 189 // ½ +#define PS2_FRACTION_THREE_QUARTERS 190 // ¾ +#define PS2_INVERTED_QUESTION_MARK 191 // ¿ +#define PS2_A_GRAVE 192 // À +#define PS2_A_ACUTE 193 // Á +#define PS2_A_CIRCUMFLEX 194 // Â +#define PS2_A_TILDE 195 // Ã +#define PS2_A_DIAERESIS 196 // Ä +#define PS2_A_RING_ABOVE 197 // Å +#define PS2_AE 198 // Æ +#define PS2_C_CEDILLA 199 // Ç +#define PS2_E_GRAVE 200 // È +#define PS2_E_ACUTE 201 // É +#define PS2_E_CIRCUMFLEX 202 // Ê +#define PS2_E_DIAERESIS 203 // Ë +#define PS2_I_GRAVE 204 // Ì +#define PS2_I_ACUTE 205 // Í +#define PS2_I_CIRCUMFLEX 206 // Î +#define PS2_I_DIAERESIS 207 // Ï +#define PS2_ETH 208 // Ð +#define PS2_N_TILDE 209 // Ñ +#define PS2_O_GRAVE 210 // Ò +#define PS2_O_ACUTE 211 // Ó +#define PS2_O_CIRCUMFLEX 212 // Ô +#define PS2_O_TILDE 213 // Õ +#define PS2_O_DIAERESIS 214 // Ö +#define PS2_MULTIPLICATION 215 // × +#define PS2_O_STROKE 216 // Ø +#define PS2_U_GRAVE 217 // Ù +#define PS2_U_ACUTE 218 // Ú +#define PS2_U_CIRCUMFLEX 219 // Û +#define PS2_U_DIAERESIS 220 // Ü +#define PS2_Y_ACUTE 221 // Ý +#define PS2_THORN 222 // Þ +#define PS2_SHARP_S 223 // ß +#define PS2_a_GRAVE 224 // à +#define PS2_a_ACUTE 225 // á +#define PS2_a_CIRCUMFLEX 226 // â +#define PS2_a_TILDE 227 // ã +#define PS2_a_DIAERESIS 228 // ä +#define PS2_a_RING_ABOVE 229 // å +#define PS2_ae 230 // æ +#define PS2_c_CEDILLA 231 // ç +#define PS2_e_GRAVE 232 // è +#define PS2_e_ACUTE 233 // é +#define PS2_e_CIRCUMFLEX 234 // ê +#define PS2_e_DIAERESIS 235 // ë +#define PS2_i_GRAVE 236 // ì +#define PS2_i_ACUTE 237 // í +#define PS2_i_CIRCUMFLEX 238 // î +#define PS2_i_DIAERESIS 239 // ï +#define PS2_eth 240 // ð +#define PS2_n_TILDE 241 // ñ +#define PS2_o_GRAVE 242 // ò +#define PS2_o_ACUTE 243 // ó +#define PS2_o_CIRCUMFLEX 244 // ô +#define PS2_o_TILDE 245 // õ +#define PS2_o_DIAERESIS 246 // ö +#define PS2_DIVISION 247 // ÷ +#define PS2_o_STROKE 248 // ø +#define PS2_u_GRAVE 249 // ù +#define PS2_u_ACUTE 250 // ú +#define PS2_u_CIRCUMFLEX 251 // û +#define PS2_u_DIAERESIS 252 // ü +#define PS2_y_ACUTE 253 // ý +#define PS2_thorn 254 // þ +#define PS2_y_DIAERESIS 255 // ÿ + + +/* Public class definition */ +class SmartyPS2KeyMap { + public: + /** + * This constructor just sets the default key mapping to US. */ + SmartyPS2KeyMap(); + + /** + Pass in 2 character string for the ISO 2 letter country code in use + For UK "UK" or "GB" are valid + "US" is built-in default + Returns 1 for done or 0 for not found. + */ + uint8_t selectMap( char * ); + + /** + Return selected map as a string pointer (2 chars and terminator) */ + const char *getMap( void ); + + /** + Pass in unsigned int returned from PS2KeyAdvanced + Returns 0 for error + uint16_t for valid code + */ + uint16_t remapKey( uint16_t ); + + /** + Returns uint8_t version of remapKey ONLY for standard ASCII/UTF-8 codes + Invalid codes returned as 0 + */ + uint8_t remapKeyByte( uint16_t ); +}; + +/* Standard ASCII/UTF-8 control Characters */ +#define PS2_BACKSPACE 0x08 +#define PS2_TAB 0x09 +#define PS2_ENTER 0x0D +#define PS2_ESC 0x1B +#define PS2_DELETE 0x7F +#define PS2_SPACE 0x20 + + +/* Standard ASCII control characters array */ +/* in order of PS2_KEY_* values order is important */ +const uint8_t _control_codes[] = { + PS2_DELETE, PS2_ESC, PS2_BACKSPACE, + PS2_TAB, PS2_ENTER, PS2_SPACE + }; + +// convert codes based on SHIFT and not SHIFT only for base US-ASCII +const uint16_t _US_ASCII[][ 2 ] = { + { PS2_SHIFT + PS2_KEY_1, '!' }, + { PS2_SHIFT + PS2_KEY_2, '@' }, + { PS2_SHIFT + PS2_KEY_3, '#' }, + { PS2_SHIFT + PS2_KEY_4, '$' }, + { PS2_SHIFT + PS2_KEY_5, '%' }, + { PS2_SHIFT + PS2_KEY_6, '^' }, + { PS2_SHIFT + PS2_KEY_7, '&' }, + { PS2_SHIFT + PS2_KEY_8, '*' }, + { PS2_SHIFT + PS2_KEY_9, '(' }, + { PS2_SHIFT + PS2_KEY_0, ')' }, + { PS2_KEY_KP_DOT, '.' }, + { PS2_KEY_KP_ENTER, PS2_ENTER }, + { PS2_KEY_KP_PLUS, '+' }, + { PS2_KEY_KP_MINUS, '-' }, + { PS2_KEY_KP_TIMES, '*' }, + { PS2_KEY_KP_DIV, '/' }, + { PS2_KEY_KP_COMMA, ',' }, + { PS2_KEY_KP_EQUAL, '=' }, + { PS2_KEY_APOS, '\'' }, + { PS2_SHIFT + PS2_KEY_APOS, '"' }, + { PS2_KEY_COMMA, ',' }, + { PS2_SHIFT + PS2_KEY_COMMA, '<' }, + { PS2_KEY_MINUS, '-' }, + { PS2_SHIFT + PS2_KEY_MINUS, '_' }, + { PS2_KEY_DOT, '.' }, + { PS2_SHIFT + PS2_KEY_DOT, '>' }, + { PS2_KEY_DIV, '/' }, + { PS2_SHIFT + PS2_KEY_DIV, '?' }, + { PS2_KEY_SINGLE, '`' }, + { PS2_SHIFT + PS2_KEY_SINGLE, '~' }, + { PS2_KEY_SEMI, ';' }, + { PS2_SHIFT + PS2_KEY_SEMI, ':' }, + { PS2_KEY_BACK, '\\' }, + { PS2_SHIFT + PS2_KEY_BACK, '|' }, + { PS2_KEY_OPEN_SQ, '[' }, + { PS2_SHIFT + PS2_KEY_OPEN_SQ, '{' }, + { PS2_KEY_CLOSE_SQ, ']' }, + { PS2_SHIFT + PS2_KEY_CLOSE_SQ, '}' }, + { PS2_KEY_EQUAL, '=' }, + { PS2_SHIFT + PS2_KEY_EQUAL, '+' } + }; + +const uint16_t _UKmap[][ 2 ] = { + { PS2_SHIFT + '@', '"' }, + { PS2_SHIFT + '"', '@' }, + { PS2_ALT_GR + '`', PS2_BROKEN_BAR }, + { PS2_SHIFT + '`', PS2_NOT_SIGN }, + { PS2_SHIFT + '#', PS2_POUND_SIGN }, + { '\\', '#' }, + { PS2_SHIFT + '|', '~' }, + { PS2_KEY_EUROPE2, '\\' }, + { PS2_SHIFT + PS2_KEY_EUROPE2, '|' }, + }; +#ifdef FRENCH +const uint16_t _FRmap[][ 2 ] = { + { '`', PS2_SUPERSCRIPT_TWO }, + { PS2_SHIFT + '~', PS2_SUPERSCRIPT_TWO }, + { 'q', 'a' }, + { 'Q', 'A' }, + { '1', '&' }, + { PS2_SHIFT + '!', '1' }, + { PS2_ALT_GR + '1', 0 }, + { PS2_ALT_GR + PS2_SHIFT + '!', 0 }, + { 'z', 'w' }, + { 'Z', 'W' }, + { 'a', 'q' }, + { 'A', 'Q' }, + { 'w', 'z' }, + { 'W', 'Z' }, + { PS2_ALT_GR + '2', '~' }, + { PS2_SHIFT + PS2_ALT_GR + '@', '~' }, + { '2', PS2_e_ACUTE }, + { PS2_SHIFT + '@', '2' }, + { PS2_ALT_GR + '3', PS2_CENT_SIGN }, + { PS2_SHIFT + PS2_ALT_GR + '#', PS2_CENT_SIGN }, + { '3', '"' }, + { PS2_SHIFT + '#', '3' }, + { PS2_ALT_GR + '4', '{' }, + { PS2_SHIFT + PS2_ALT_GR + '$', '{' }, + { '4', '\'' }, + { PS2_SHIFT + '$', '4' }, + { PS2_ALT_GR + '5', '[' }, + { PS2_SHIFT + PS2_ALT_GR + '%', '[' }, + { '5', '(' }, + { PS2_SHIFT + '%', '5' }, + { PS2_ALT_GR + '6', '|' }, + { PS2_SHIFT + PS2_ALT_GR + '^', '|' }, + { '6', '-' }, + { PS2_SHIFT + '^', '6' }, + { 'm', ',' }, + { 'M', '?' }, + { PS2_ALT_GR + '7', '`' }, + { PS2_SHIFT + PS2_ALT_GR + '&', '`' }, + { '7', PS2_e_GRAVE }, + { PS2_SHIFT + '&', '7' }, + { PS2_ALT_GR + '8', '\\' }, + { PS2_SHIFT + PS2_ALT_GR + '*', '\\' }, + { '8', '_' }, + { PS2_SHIFT + '*', '8' }, + { ',', ';' }, + { PS2_SHIFT + '<', '.' }, + { PS2_ALT_GR + '9', '^' }, + { PS2_SHIFT + PS2_ALT_GR + '(', '^' }, + { '9', PS2_c_CEDILLA }, + { PS2_SHIFT + '(', '9' }, + { PS2_ALT_GR + '0', '@' }, + { PS2_ALT_GR + ')', '@' }, + { '0', PS2_a_GRAVE }, + { PS2_SHIFT + ')', '0' }, + { '.', ':' }, + { PS2_SHIFT + '>', '/' }, + { '/', '!' }, + { PS2_SHIFT + '?', PS2_SECTION_SIGN }, + { ';', 'm' }, + { PS2_SHIFT + ':', 'M' }, + { PS2_ALT_GR + '-', ']' }, + { PS2_SHIFT + PS2_ALT_GR + '_', ']' }, + { '-', ')' }, + { PS2_SHIFT + '_', PS2_DEGREE_SIGN }, + { '\'', PS2_u_GRAVE }, + { PS2_SHIFT + '"', '%' }, + { PS2_ALT_GR + '\'', 0 }, + { PS2_SHIFT + PS2_ALT_GR + '"', 0 }, + { '[', '^' }, + { PS2_SHIFT + '{', PS2_DIAERESIS }, + { PS2_ALT_GR + '=', '}' }, + { PS2_SHIFT + PS2_ALT_GR + '+', '}' }, + { PS2_ALT_GR + ']', PS2_CURRENCY_SIGN }, + { PS2_SHIFT + PS2_ALT_GR + '}', 0 }, + { ']', '$' }, + { PS2_SHIFT + '}', PS2_POUND_SIGN }, + { '\\', '*' }, + { PS2_SHIFT + '|', PS2_MICRO_SIGN }, + { PS2_SHIFT + PS2_ALT_GR +'|', 0 }, + { PS2_ALT_GR +'\\', 0 }, + { PS2_KEY_EUROPE2 + PS2_SHIFT + PS2_ALT_GR, '|' }, + { PS2_KEY_EUROPE2 + PS2_ALT_GR, '|' }, + { PS2_SHIFT + PS2_KEY_EUROPE2, '>' }, + { PS2_KEY_EUROPE2, '<' } + }; +#endif +#ifdef GERMAN +const uint16_t _DEmap[][ 2 ] = { + { '`', '^' }, + { PS2_SHIFT + '~', PS2_DEGREE_SIGN }, + { PS2_ALT_GR + 'q', '@' }, + { PS2_ALT_GR + 'Q', '@' }, + { 'y', 'z' }, + { 'Y', 'Z' }, + { PS2_ALT_GR + '2', PS2_SUPERSCRIPT_TWO }, + { PS2_SHIFT + PS2_ALT_GR + '@', PS2_SUPERSCRIPT_TWO }, + { PS2_SHIFT + '@', '"' }, + { PS2_ALT_GR + 'e', PS2_CURRENCY_SIGN }, + { PS2_ALT_GR + 'E', PS2_CURRENCY_SIGN }, + { PS2_ALT_GR + '3', PS2_SUPERSCRIPT_THREE }, + { PS2_SHIFT + PS2_ALT_GR + '#', PS2_SUPERSCRIPT_THREE }, + { PS2_SHIFT + '#', PS2_SECTION_SIGN }, + { 'z', 'y' }, + { 'Z', 'Y' }, + { PS2_SHIFT + '^', '&' }, + { PS2_ALT_GR + 'm', PS2_MICRO_SIGN }, + { PS2_ALT_GR + 'M', PS2_MICRO_SIGN }, + { PS2_SHIFT + '&', '/' }, + { PS2_ALT_GR + '7', '{' }, + { PS2_SHIFT + PS2_ALT_GR + '&', '{' }, + { PS2_SHIFT + '*', '(' }, + { PS2_ALT_GR + '8', '[' }, + { PS2_SHIFT + PS2_ALT_GR + '*', '[' }, + { PS2_SHIFT + '<', ';' }, + { PS2_SHIFT + ')', '=' }, + { PS2_ALT_GR + '0', '}' }, + { PS2_SHIFT + PS2_ALT_GR + ')', '}' }, + { PS2_SHIFT + '(', ')' }, + { PS2_ALT_GR + '9', ']' }, + { PS2_SHIFT + PS2_ALT_GR + '(', ']' }, + { PS2_SHIFT + '>', ':' }, + { ';', PS2_o_DIAERESIS }, + { PS2_SHIFT + ':', PS2_O_DIAERESIS }, + { PS2_ALT_GR + '-', '\\' }, + { PS2_SHIFT + PS2_ALT_GR + '_', '\\' }, + { '-', PS2_SHARP_S }, + { PS2_SHIFT + '_', '?' }, + { '\'', PS2_a_DIAERESIS }, + { PS2_SHIFT + '"', PS2_A_DIAERESIS }, + { '[', PS2_u_DIAERESIS }, + { PS2_SHIFT + '{', PS2_U_DIAERESIS }, + { '=', '\'' }, + { PS2_SHIFT + '+', '`' }, + { ']' + PS2_ALT_GR, '~' }, + { PS2_SHIFT + '}' + PS2_ALT_GR, '~' }, + { ']', '+' }, + { PS2_SHIFT + '}', '*' }, + { '\\', '#' }, + { PS2_SHIFT + '|', '\'' }, + { PS2_KEY_EUROPE2 + PS2_SHIFT + PS2_ALT_GR, '|' }, + { PS2_KEY_EUROPE2 + PS2_ALT_GR, '|' }, + { PS2_SHIFT + PS2_KEY_EUROPE2, '>' }, + { PS2_KEY_EUROPE2, '<' } + }; +#endif +#ifdef SPANISH +const uint16_t _ESmap[][ 2 ] = { + { PS2_KEY_SINGLE, PS2_MASCULINE_ORDINAL }, + { PS2_SHIFT + PS2_KEY_SINGLE, PS2_FEMININE_ORDINAL }, + { PS2_KEY_SINGLE + PS2_ALT_GR, '\\' }, + { '1' + PS2_ALT_GR, '|' }, + { PS2_SHIFT + '@', '"' }, + { '2' + PS2_ALT_GR, '@' }, + { PS2_SHIFT + '#', PS2_MIDDLE_DOT }, + { '3' + PS2_ALT_GR, '#' }, + { '4' + PS2_ALT_GR, '~' }, + { PS2_SHIFT + '^', '&' }, + { '6' + PS2_ALT_GR, PS2_NOT_SIGN }, + { PS2_SHIFT + '&', '/' }, + { PS2_SHIFT + '*', '(' }, + { PS2_SHIFT + '(', ')' }, + { PS2_SHIFT + ')', '=' }, + { '-', '\'' }, + { PS2_SHIFT + '_', '?' }, + { '=', PS2_INVERTED_EXCLAMATION }, + { PS2_SHIFT + '+', PS2_INVERTED_QUESTION_MARK }, + { '[', '`' }, + { PS2_SHIFT + '{', '^' }, + { '[' + PS2_ALT_GR, '[' }, + { ']', '+' }, + { PS2_SHIFT + '}', '*' }, + { ']' + PS2_ALT_GR, ']' }, + { ';', PS2_n_TILDE }, + { PS2_SHIFT + ':', PS2_N_TILDE }, + { '\'', PS2_ACUTE_ACCENT }, + { PS2_SHIFT + '"', PS2_DIAERESIS }, + { '\'' + PS2_ALT_GR, '{' }, + { '\\', PS2_c_CEDILLA }, + { PS2_SHIFT + '|', PS2_C_CEDILLA }, + { '\\' + PS2_ALT_GR, '}' }, + { PS2_SHIFT + PS2_KEY_EUROPE2, '>' }, + { PS2_KEY_EUROPE2, '<' }, + { PS2_SHIFT + '<', ';' }, + { PS2_SHIFT + '>', ':' }, + { PS2_KEY_DIV, '-' }, + { PS2_SHIFT + PS2_KEY_DIV, '+' } + }; +#endif +#ifdef ITALIAN +const uint16_t _ITmap[][ 2 ] = { + { PS2_KEY_SINGLE, '\\' }, + { PS2_SHIFT + PS2_KEY_SINGLE, '|' }, + { '@', '"' }, + { PS2_SHIFT + '#', PS2_POUND_SIGN }, + { '3' + PS2_ALT_GR, '#' }, + { PS2_SHIFT + '^', '&' }, + { PS2_SHIFT + '&', '/' }, + { '7' + PS2_ALT_GR, '{' }, + { PS2_SHIFT + '*', '(' }, + { '8' + PS2_ALT_GR, '[' }, + { PS2_SHIFT + '(', ')' }, + { '9' + PS2_ALT_GR, ']' }, + { PS2_SHIFT + ')', '=' }, + { '0' + PS2_ALT_GR, '}' }, + { '-', '\'' }, + { PS2_SHIFT + '_', '?' }, + { '=', PS2_i_GRAVE }, + { PS2_SHIFT + '+', '^' }, + { 'q' + PS2_ALT_GR, '@' }, + { '[', PS2_e_GRAVE }, + { PS2_SHIFT + '{', PS2_e_ACUTE }, + { ']', '+' }, + { PS2_SHIFT + '}', '*' }, + { ']' + PS2_ALT_GR, '~' }, + { ';', PS2_o_GRAVE }, + { PS2_SHIFT + ':', PS2_c_CEDILLA }, + { '\'', PS2_a_GRAVE }, + { PS2_SHIFT + '"', PS2_DEGREE_SIGN }, + { '\\', PS2_u_GRAVE }, + { PS2_SHIFT + '|', PS2_SECTION_SIGN }, + { PS2_SHIFT + PS2_KEY_EUROPE2, '>' }, + { PS2_KEY_EUROPE2, '<' }, + { PS2_SHIFT + '<', ';' }, + { PS2_SHIFT + '>', ':' }, + { PS2_KEY_DIV, '-' }, + { PS2_SHIFT + PS2_KEY_DIV, '+' } + }; +#endif +#ifdef SPECIAL +const uint16_t _SpecialMap[][ 2 ] = { +// Insert your Special mapping DIFFERENCES from US-ASCII here + }; +#endif + +// The following structures define the key maps available +typedef struct { + char *name; // 2 Character ISO country code + uint8_t size; // Number of entries in map array + uint16_t *map; // Map array pointer + } PS2Advmap; + +// Actual map structure array ( 2 entries for GB and UK for same map +// Because many people don't know ISO code for UK is GB ) +const PS2Advmap _KeyMaps[ ] = { + { "US", sizeof( _US_ASCII ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_US_ASCII }, +#ifdef FRENCH + { "FR", sizeof( _FRmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_FRmap }, +#endif +#ifdef GERMAN + { "DE", sizeof( _DEmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_DEmap }, +#endif +#ifdef SPANISH + { "ES", sizeof( _ESmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_ESmap }, +#endif +#ifdef ITALIAN + { "IT", sizeof( _ITmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_ITmap }, +#endif +#ifdef SPECIAL + { "--", sizeof( _SpecialMap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t* )_SpecialMap }, +#endif + { "UK", sizeof( _UKmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_UKmap }, + { "GB", sizeof( _UKmap ) / ( 2 * sizeof( uint16_t ) ), (uint16_t *)_UKmap } + }; + + +uint8_t _selected_map; + +// Private country code strings +const char *_USStr[] = { "US" }; + + +/* Common function to scan a Look up table table and + return a value or 0 for not found + + Checks using default mask of keycode plus ALT_GR and SHIFT + To add in match other modifiers set mask to combination of + PS2_CTRL match either Control key as well + PS2_ALT match left ALT as well + PS2_GUI match either GUI key as well + + Assumes map table has 2 dimensions of type prog_uint16_t (in Flash memory) + i.e. an array like test[ ][ 2 ] + First entry (test[][ 0 ]) is item to match + Second entry (test[][ 1 ]) is item to return + + Parameters are + data unsigned int 16 from PS2KeyAdvanced library + index index of mapping table to use +*/ +uint16_t scan_map( uint16_t data, uint8_t index ) +{ +uint16_t idx, result, size; +uint16_t *maparray; + +// Convert entries count to number of ints +size = ( _KeyMaps[ index ].size ) << 1; +maparray = ( uint16_t *)_KeyMaps[ index ].map; + +//for (int i = 0 ; i < 10 ; i+=2) +//{ +// Serial.print("maparray: "); Serial.print(i); +// Serial.print(" 0x"); Serial.println(pgm_read_word(maparray + i), HEX); +//} + +// Leave only required bits for checking against +result = data & ( PS2_ALT_GR + PS2_SHIFT + 0xFF ); + +// scan Lookup Table (array) jumping 2 integers at a time +for( idx = 0; idx < size; idx += 2 ) +{ + if( result == *( maparray + idx ) ) + { // second integer is the replacement value + result = *( maparray + idx + 1 ); + data &= ~0xFF; // clear old bits retaining CTRL etc + data |= result; // Make new code + break; + } +} +return data; +} + + +/* + Pass in 2 character string for the ISO 2 letter country code in use + For UK "UK" or "GB" are valid + "US" is built-in default + + Returns 1 for done + or 0 for not found. +*/ +uint8_t SmartyPS2KeyMap::selectMap( char *ISO = (char *)_USStr ) +{ +uint8_t outer, idx, end; + +end = sizeof( _KeyMaps ) / sizeof( PS2Advmap ); + +//for (int i; i < end; i++) +//{ +// Serial.print("MMap "); +// Serial.print(i); Serial.print(" "); +// Serial.print(_KeyMaps[i].name[0]); Serial.print(_KeyMaps[i].name[1]); Serial.print(" "); +// Serial.println(_KeyMaps[i].size); +//} + +for( outer = 0; outer < end; outer++ ) + { +// Serial.print("Map "); Serial.print(outer); + for( idx = 0; idx < 3; idx++ ) + { +// Serial.print(" _KeyMap[].name[i] "); +// Serial.write(_KeyMaps[ outer ].name[ idx ]); +// Serial.print(" ISO[ idx ] "); +// Serial.write(ISO[ idx ]); +// Serial.print(" "); + if( _KeyMaps[ outer ].name[ idx ] != ISO[ idx ] ) + break; // No match + } +// Serial.println(); + if( idx == 3 ) // done whole match + break; + } +if( outer < end ) // found entry + { + _selected_map = outer; // Copy over to selected + return 1; + } +return 0; +} + + +/* + Return selected map as a string pointer (2 chars and terminator) +*/ +const char *SmartyPS2KeyMap::getMap( void ) +{ +return ( _KeyMaps[ _selected_map ].name ); +} + + +/* Pass in unsigned int returned from PS2KeyAdvanced + Returns 0 for error + uint16_t for valid code + Converts code to US-ASCII first (honouring SHIFT ONLY) + then if additional map defined scan and remap those keys +*/ +uint16_t SmartyPS2KeyMap::remapKey( uint16_t code ) +{ +uint8_t temp; + +// for bottom byte checks +temp = code & 0xFF; + +// Sort standard ASCII control codes +if( temp >= PS2_KEY_DELETE && temp <= PS2_KEY_SPACE ) + { + code &= ~( PS2_FUNCTION + 0xFF ); // convert to ASCII code not function + temp = _control_codes[ temp - PS2_KEY_DELETE ]; + code |= temp; + } +else + // Remainder convert printable to US-ASCII + if( !( code & PS2_FUNCTION ) ) + { // Some codes are straight return values We deal with ones that need work + // When A-Z not shifted create lower case a - z + if( temp >= PS2_KEY_A && temp <= PS2_KEY_Z ) + { + // Deal with Caps Lock by inverting PS2_SHIFT and remove caps lock + if( ( code & PS2_CAPS ) ) + code ^= ( PS2_SHIFT + PS2_CAPS ); + if( !( code & PS2_SHIFT ) ) + code |= 0x20; + // When shifted pass through code as received as the codes are A - Z + else + code &= ~PS2_SHIFT; + } + else + // Convert KeyPad 0-9 to number codes + if( temp >= PS2_KEY_KP0 && temp <= PS2_KEY_KP9 ) + { + code |= 0x10; + code &= ~( PS2_SHIFT + PS2_ALT + PS2_ALT_GR + PS2_CTRL + PS2_GUI + PS2_CAPS ); + } + else + { + // Some keys ignore shift, the extra keys on numeric keypad + if( ( temp >= PS2_KEY_KP_DOT && temp <= PS2_KEY_KP_DIV ) + || temp == PS2_KEY_KP_EQUAL || temp == PS2_KEY_KP_COMMA ) + code &= ~PS2_SHIFT; + // Do default US-ASCII mapping of remainders excluding (CTRL, ALT, GUI) + code = (code & PS2_ALT_GR ) + scan_map( code & ~PS2_ALT_GR, 0 ); + } + //Now do remap if necessary for all modifiers + if( code > 0 && _selected_map > 0 ) + code = scan_map( code, _selected_map ); + else // For USASCII ignore extra key in case + if( ( temp == PS2_KEY_EUROPE2 ) ) + code = 0; + code &= ~( PS2_SHIFT + PS2_ALT_GR ); // Now clear shift status + } + else + code = 0; +return code; +} + + +/* + Returns uint8_t version of remapKey ONLY for standard ASCII/UTF-8 codes + Invalid codes returned as 0 + Also any key with BREAK condition are returned as 0 +*/ +uint8_t SmartyPS2KeyMap::remapKeyByte( uint16_t code ) +{ +uint16_t data; + +// Invalid codes returned as 0 +if( code & ( PS2_FUNCTION + PS2_BREAK ) ) + return 0; +data = remapKey( code ); +return ( uint8_t )( data & 0xFF ); +} + + +/* Class constructor + At construction ensure default map selected +*/ +SmartyPS2KeyMap::SmartyPS2KeyMap() +{ +_selected_map = 0; +} + PS2KeyAdvanced keyboard; -PS2KeyMap keymap; +SmartyPS2KeyMap keymap; void setup() { @@ -62,7 +755,7 @@ void setup() digitalWrite(KEYBOARD_BIT7_PIN, LOW); Serial.begin(9600); - Serial.println("SmartyKit 1 PS2 Keyboard is ready..."); + Serial.println(F("SmartyKit 1 PS2 Keyboard is ready...")); if (autoMode) delay(7500); //for start without Keyboard connected @@ -74,22 +767,32 @@ void setup() delay( 6 ); uint16_t scan_code = keyboard.read(); +#ifdef _SMARTY_DEBUG_ + Serial.print(F("0.scan_code: 0x")); + Serial.print(scan_code, HEX); + Serial.println(); + if( (scan_code & 0xff) == PS2_KEY_ECHO || (scan_code & 0xff) == PS2_KEY_BAT || (scan_code & 0xff) == 0xe8 ) - Serial.println( "Keyboard OK.." ); // Response was Echo or power up + Serial.println(F("Keyboard OK..")); // Response was Echo or power up else if ((scan_code & 0xff) == 0) { - Serial.println( "Keyboard Not Found" ); + Serial.println(F("Keyboard Not Found") ); } else { - Serial.print( "Invalid Code received of 0x" ); + Serial.print(F("Invalid Code received of 0x")); Serial.println(scan_code, HEX); } +#endif keyboard.setNoBreak(1); keyboard.setNoRepeat(1); - keymap.selectMap((char *)"UK"); +// keymap.selectMap((char *)"UK"); +// keymap.selectMap((char *)"FR"); +// keymap.selectMap((char *)"DE"); +// keymap.selectMap((char *)"IT"); +// keymap.selectMap((char *)"ES"); attachInterrupt(digitalPinToInterrupt(KEYBOARD_RD_PIN), cpuReadsKeyboard, FALLING); } @@ -100,11 +803,6 @@ void cpuReadsKeyboard(void) void sendCharToKeyboardPort(char c) { - if (c == '\r') - Serial.println(); - else - Serial.print(c); - for (int bit = 0; bit < 8 ; bit++) { if (c & (1 << (bit))) @@ -130,36 +828,59 @@ void loop() if (!digitalRead(KEYBOARD_BIT7_PIN) && keyboard.available()) { uint16_t scan_code = keymap.remapKey(keyboard.read()); - char c = scan_code & 0xff; + uint8_t c = scan_code & 0xff; - Serial.print(":0x"); - Serial.print(scan_code, HEX); - Serial.print(":"); - - //process Backspace, Left Arrow, Delete as Apple I backspace '_' - switch (c) + if (scan_code > 0) { - case PS2_KEY_TAB: - runCommand(); - break; - case PS2_KEY_BS: - case PS2_KEY_DELETE: - case PS2_KEY_L_ARROW: - c = '_'; - break; - case PS2_KEY_ENTER: - c = '\r'; - break; - case PS2_KEY_SPACE: - c = ' '; - break; - } +#ifdef _SMARTY_DEBUG_ + Serial.print(F("1.scan_code: 0x")); + Serial.print(scan_code, HEX); + Serial.print(F(", c: 0x")); + Serial.print(c, HEX); + Serial.print(F(", ASCII ")); + Serial.write(c); + Serial.println(); +#endif + //process Backspace, Left Arrow, Delete as Apple I backspace '_' + switch (c) + { + case PS2_TAB: + case PS2_KEY_TAB: + runCommand(); + break; + case PS2_BACKSPACE: + case PS2_DELETE: + case PS2_KEY_L_ARROW: + c = '_'; + break; + } - //make all symbols uppercase (from 'a' (ASCII code 0x61) to 'z' (ASCII code 0x7A)) - //as in original Apple-1 - c = toupper(c); - //print c to Keyboard Port to be read by CPU - sendCharToKeyboardPort(c); +#ifdef _SMARTY_DEBUG_ + Serial.print("2.scan_code: 0x"); + Serial.print(scan_code, HEX); + Serial.print(", c: 0x"); + Serial.print(c, HEX); + Serial.print(", ASCII "); + Serial.write(c); + Serial.println(); +#endif + + //make all symbols uppercase (from 'a' (ASCII code 0x61) to 'z' (ASCII code 0x7A)) + //as in original Apple-1 + c = toupper(c); + //print c to Keyboard Port to be read by CPU + +#ifdef _SMARTY_DEBUG_ + Serial.print("3.scan_code: 0x"); + Serial.print(scan_code, HEX); + Serial.print(", c: 0x"); + Serial.print(c, HEX); + Serial.print(", ASCII "); + Serial.write(c); + Serial.println(); +#endif + sendCharToKeyboardPort(c); + } } //low-rate clock diff --git a/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino index 97fca0b..deffa56 100644 --- a/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino +++ b/SmartyKit 1 basic drivers/SmartyKit1_VideoDriverBasic_TFT2.8_TV/SmartyKit1_VideoDriverBasic_TFT2.8_TV.ino @@ -19,12 +19,11 @@ #include - -#include #undef _TERMINAL_ //turn off Terminal //#define _TERMINAL_ //turn on Terminal #ifdef _TERMINAL_ +#include // Create a terminal in TWI mode Terminal term; //uses A4 (SDA) and A5 (SCL) that conflict with other usage of A4-A5 //so we need to put CS on low, RST = A0, DC = A1, MOSI = A2, SCK = A3, MISO = not connected (NC) @@ -601,7 +600,7 @@ void SmartyKit_DisplayDriver::initSPI(void) spiClass = &SPI; #if defined(_SMARTY_DEBUG_) - Serial.print(F("SmartyKit SPI freq = "));Serial.println(DEFAULT_SPI_FREQ, DEC); + Serial.print(F("SmartyKit TFT_HARD_SPI freq = "));Serial.println(DEFAULT_SPI_FREQ, DEC); #endif spiSettings = SPISettings(DEFAULT_SPI_FREQ, MSBFIRST, SPI_MODE0); @@ -611,6 +610,9 @@ void SmartyKit_DisplayDriver::initSPI(void) } else if (connection == TFT_SOFT_SPI) { + #if defined(_SMARTY_DEBUG_) + Serial.println(F("SmartyKit TFT_SOFT_SPI")); + #endif pinMode(_mosi, OUTPUT); digitalWrite(_mosi, LOW); pinMode(_sck, OUTPUT); @@ -1471,7 +1473,11 @@ const int VideoBIT7pin = 5; int DataBus[8] = {6, 7, 8, 9, 10, 11, 12, 13}; byte scan_code=0; -void setup() { +void setup() +{ + Serial.begin(9600); + Serial.println("setup()"); + pinMode(VideoBIT7pin, OUTPUT); digitalWrite(VideoBIT7pin, HIGH); //wait until video setup is ready @@ -1508,7 +1514,8 @@ void setup() { digitalWrite(VideoBIT7pin, LOW); //default state after restart = 0 (ready to print) } -void loop() { +void loop() +{ //intentionally left blank }