Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /* 00002 * This is a simple mbed program for driving 00003 * an Acorn Electron keyboard from a KL25Z mbed 00004 * board. 00005 * 00006 * It is placed in the public domain by its author, 00007 * Ian Harvey. Note that there is NO WARRANTY. 00008 */ 00009 00010 /* About the Electron keyboard ----------------- 00011 00012 The keyboard itself has 14 'columns' and 4 'rows'. 00013 The column being scanned is driven low and four row 00014 bits are read out. The keyboard has diodes on the columns 00015 and pull-ups on the rows, so there's no need to tri-state 00016 un-driven columns or activate pullups. The break key 00017 is wired separately and connects directly to ground 00018 when preseed. Connections are as follows: 00019 00020 1. Break key PTE5 00021 2. Caps lock LED PTE4 00022 3. Ground 00023 4. V+ for LED 00024 5. Row 3 PTE3 00025 6. Row 2 PTE2 00026 7. Row 1 PTB11 00027 8. Row 0 PTB10 00028 9. Col 13 PTA1 00029 10. Col 12 PTC7 00030 11. Col 11 PTA2 00031 12. Col 10 PTC0 00032 13. Col 9 PTD4 00033 14. Col 8 PTC3 00034 15. Col 7 PTA12 00035 16. Col 6 PTC4 00036 17. Col 5 PTA4 00037 18. Col 4 PTC5 00038 19. Col 3 PTA5 00039 20. Col 2 PTC6 00040 21. Col 1 PTC8 00041 22. Col 0 PTC10 00042 00043 Pin "1" (my numbering) is closest to the corner 00044 of the board, and pin "22" is next to the space 00045 bar. The connections of the keys follow the 00046 layout in 'hid_keys' below, so KEY_PERIOD is 00047 col 0 row 0, KEY_L is col 0 row 1, and so on. 00048 We're using the following modifications: 00049 00050 "CAPS LK" -> KEY_TAB 00051 "[ ] COPY" -> KEY_OPEN_SQUARE 00052 "DELETE" -> KEY_LEFT_ALT 00053 ": *" -> KEY_SINGLE_QUOTE 00054 00055 The firmware also treats the 'break' key as 00056 'row 4' all on its own (mapped to KEY_BACKSPACE). 00057 00058 When 'DELETE' (the LEFT_ALT key) is pressed, 00059 the keyboard map in 'alt_keys' is used, so 00060 e.g. KEY_MINUS becomes KEY_EQUALS. 00061 00062 Keyboard layout 00063 --------------- 00064 00065 Note that the keycaps on the Electron keyboard 00066 are considerably different to those on a regular 00067 PC-style one: shift-6 is labelled '&' not '^', 00068 shift-';' is labelled '+' not ':', and so on. 00069 The code here *doesn't* change which key code 00070 is sent when shift is pressed, so the characters 00071 you get are those you'd get on a PC keyboard - 00072 after some experimentation I personally preferred 00073 this. If this isn't to your taste, creating a 00074 custom keyboard layout on the PC/Pi may be the best 00075 way to fix this. 00076 00077 I tend to use a 'US' keyboard layout with this 00078 keyboard, so shift-3 generates a '#', not a 00079 UK pound sign, and the single/double quotes are 00080 next to the ';' key (labelled ': *' on the Electron). 00081 00082 ---------------------------------------------- */ 00083 00084 #include "mbed.h" 00085 #include "USBKeyboard.h" 00086 #include "hid_keys.h" 00087 00088 #define MAX_ROWS 5 00089 #define MAX_COLS 14 00090 #define REPORT_LEN 9 00091 #define REPORT_ID_KEYBOARD 1 00092 00093 const uint8_t hid_keys[MAX_ROWS * MAX_COLS] = 00094 { 00095 KEY_PERIOD, KEY_L, KEY_O, KEY_9, KEY_BACKSPACE, 00096 KEY_SLASH, KEY_SEMICOLON, KEY_P, KEY_0, KEY_NONE, 00097 KEY_NONE, KEY_SINGLE_QUOTE,KEY_UP_ARROW, KEY_MINUS, KEY_NONE, 00098 KEY_LEFT_ALT, KEY_ENTER, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_NONE, 00099 00100 KEY_SPACE, KEY_NONE, KEY_OPEN_SQUARE, KEY_RIGHT_ARROW, KEY_NONE, 00101 KEY_COMMA, KEY_K, KEY_I, KEY_8, KEY_NONE, 00102 KEY_M, KEY_J, KEY_U, KEY_7, KEY_NONE, 00103 KEY_N, KEY_H, KEY_Y, KEY_6, KEY_NONE, 00104 00105 KEY_B, KEY_G, KEY_T, KEY_5, KEY_NONE, 00106 KEY_V, KEY_F, KEY_R, KEY_4, KEY_NONE, 00107 KEY_C, KEY_D, KEY_E, KEY_3, KEY_NONE, 00108 KEY_X, KEY_S, KEY_W, KEY_2, KEY_NONE, 00109 00110 KEY_Z, KEY_A, KEY_Q, KEY_1, KEY_NONE, 00111 KEY_LEFT_SHIFT, KEY_LEFT_CTRL, KEY_TAB, KEY_ESC, KEY_NONE, 00112 }; 00113 00114 const uint8_t alt_keys[MAX_ROWS * MAX_COLS] = 00115 { 00116 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00117 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00118 KEY_NONE, KEY_NONE, KEY_HASH_TILDE, KEY_EQUALS, KEY_NONE, 00119 KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKTICK_TILDE, KEY_NONE, 00120 00121 KEY_NONE, KEY_NONE, KEY_CLOSE_SQUARE, KEY_BACKSLASH, KEY_NONE, 00122 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00123 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00124 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00125 00126 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00127 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00128 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00129 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00130 00131 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00132 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, 00133 00134 }; 00135 00136 00137 BusOut leds(LED1, LED2, LED3); 00138 00139 BusOut scanCols( 00140 PTC10,PTC8, 00141 PTC6, PTA5, 00142 PTC5, PTA4, 00143 PTC4, PTA12, 00144 PTC3, PTD4, 00145 PTC0, PTA2, 00146 PTC7, PTA1 00147 ); 00148 00149 BusIn inRows( 00150 PTB10, 00151 PTB11, 00152 PTE2, 00153 PTE3, 00154 PTE5 ); 00155 00156 DigitalOut extLed(PTE4); 00157 00158 USBKeyboard kbd; 00159 00160 static int scanColumn(int col) 00161 { 00162 int rowBits; 00163 // Drive output low to scan 00164 scanCols.write(0x3FFF ^ (1 << col)); 00165 leds.write(col >> 1); 00166 wait(0.001); 00167 rowBits = inRows.read(); 00168 scanCols.write(0x3FFF); 00169 // Inputs also active-low 00170 return rowBits ^ 0x1F; 00171 } 00172 00173 static const uint8_t altKeys = 00174 MODIFIER_BIT(KEY_LEFT_ALT) | MODIFIER_BIT(KEY_RIGHT_ALT); 00175 00176 00177 int main() 00178 { 00179 // Setup 00180 inRows.mode(PullUp); 00181 extLed = 1; 00182 00183 // Run loop 00184 while(1) 00185 { 00186 int col, ocount; 00187 HID_REPORT report; 00188 uint8_t keyIfAlt = KEY_NONE; 00189 00190 report.data[0] = REPORT_ID_KEYBOARD; 00191 report.data[1] = 0; // modifiers 00192 report.data[2] = 0; 00193 ocount = 3; 00194 00195 for (col=0; col < MAX_COLS; col++) 00196 { 00197 int row; 00198 int rowBits = scanColumn(col); 00199 if ( !rowBits ) 00200 continue; 00201 00202 for (row=0; row < MAX_ROWS; row++) 00203 { 00204 if ( rowBits & (1 << row) ) 00205 { 00206 uint8_t key = hid_keys[col * MAX_ROWS + row]; 00207 if ( IS_MODIFIER(key) ) 00208 report.data[1] |= MODIFIER_BIT(key); 00209 else if ( key != KEY_NONE ) 00210 { 00211 if ( ocount < REPORT_LEN ) 00212 report.data[ocount++] = key; 00213 } 00214 00215 key = alt_keys[col * MAX_ROWS + row]; 00216 if ( key != KEY_NONE ) 00217 keyIfAlt = key; 00218 //kbd.printf("c%dr%d ", col, row); 00219 } 00220 } 00221 } 00222 00223 if ( (report.data[1] & altKeys) != 0 && 00224 keyIfAlt != KEY_NONE 00225 ) 00226 { 00227 report.data[3] = keyIfAlt; 00228 ocount = 4; // Zero out the rest 00229 report.data[1] &= ~altKeys; // And put alt key up 00230 } 00231 00232 while( ocount < REPORT_LEN ) 00233 report.data[ocount++] = KEY_NONE; 00234 00235 report.length = REPORT_LEN; 00236 kbd.send(&report); 00237 } 00238 }
Generated on Fri Aug 19 2022 00:54:31 by
1.7.2