Acorn Electron keyboard scanner, turns an old Acorn Electron into a USB keyboard.

Dependencies:   USBDevice mbed

Committer:
IH
Date:
Mon May 12 20:15:52 2014 +0000
Revision:
1:84cd616cc684
Parent:
0:9fd3dad2dc25
Child:
2:9352b1232e6d
Add alt key translation;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
IH 0:9fd3dad2dc25 1 #include "mbed.h"
IH 0:9fd3dad2dc25 2 #include "USBKeyboard.h"
IH 0:9fd3dad2dc25 3 #include "hid_keys.h"
IH 0:9fd3dad2dc25 4
IH 0:9fd3dad2dc25 5 #define MAX_ROWS 5
IH 0:9fd3dad2dc25 6 #define MAX_COLS 14
IH 0:9fd3dad2dc25 7 #define REPORT_LEN 9
IH 0:9fd3dad2dc25 8 #define REPORT_ID_KEYBOARD 1
IH 0:9fd3dad2dc25 9
IH 0:9fd3dad2dc25 10 const uint8_t hid_keys[MAX_ROWS * MAX_COLS] =
IH 0:9fd3dad2dc25 11 {
IH 0:9fd3dad2dc25 12 KEY_PERIOD, KEY_L, KEY_O, KEY_9, KEY_BACKSPACE,
IH 0:9fd3dad2dc25 13 KEY_SLASH, KEY_SEMICOLON, KEY_P, KEY_0, KEY_NONE,
IH 1:84cd616cc684 14 KEY_NONE, KEY_SINGLE_QUOTE,KEY_UP_ARROW, KEY_MINUS, KEY_NONE,
IH 1:84cd616cc684 15 KEY_LEFT_ALT, KEY_ENTER, KEY_DOWN_ARROW, KEY_LEFT_ARROW, KEY_NONE,
IH 1:84cd616cc684 16
IH 0:9fd3dad2dc25 17 KEY_SPACE, KEY_NONE, KEY_OPEN_SQUARE, KEY_RIGHT_ARROW, KEY_NONE,
IH 0:9fd3dad2dc25 18 KEY_COMMA, KEY_K, KEY_I, KEY_8, KEY_NONE,
IH 0:9fd3dad2dc25 19 KEY_M, KEY_J, KEY_U, KEY_7, KEY_NONE,
IH 0:9fd3dad2dc25 20 KEY_N, KEY_H, KEY_Y, KEY_6, KEY_NONE,
IH 1:84cd616cc684 21
IH 0:9fd3dad2dc25 22 KEY_B, KEY_G, KEY_T, KEY_5, KEY_NONE,
IH 0:9fd3dad2dc25 23 KEY_V, KEY_F, KEY_R, KEY_4, KEY_NONE,
IH 0:9fd3dad2dc25 24 KEY_C, KEY_D, KEY_E, KEY_3, KEY_NONE,
IH 0:9fd3dad2dc25 25 KEY_X, KEY_S, KEY_W, KEY_2, KEY_NONE,
IH 1:84cd616cc684 26
IH 0:9fd3dad2dc25 27 KEY_Z, KEY_A, KEY_Q, KEY_1, KEY_NONE,
IH 0:9fd3dad2dc25 28 KEY_LEFT_SHIFT, KEY_LEFT_CTRL, KEY_TAB, KEY_ESC, KEY_NONE,
IH 0:9fd3dad2dc25 29 };
IH 0:9fd3dad2dc25 30
IH 1:84cd616cc684 31 const uint8_t alt_keys[MAX_ROWS * MAX_COLS] =
IH 1:84cd616cc684 32 {
IH 1:84cd616cc684 33 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 34 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 35 KEY_NONE, KEY_NONE, KEY_HASH_TILDE, KEY_EQUALS, KEY_NONE,
IH 1:84cd616cc684 36 KEY_NONE, KEY_NONE, KEY_NONE, KEY_BACKTICK_TILDE, KEY_NONE,
IH 1:84cd616cc684 37
IH 1:84cd616cc684 38 KEY_NONE, KEY_NONE, KEY_CLOSE_SQUARE, KEY_BACKSLASH, KEY_NONE,
IH 1:84cd616cc684 39 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 40 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 41 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 42
IH 1:84cd616cc684 43 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 44 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 45 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 46 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 47
IH 1:84cd616cc684 48 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 49 KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE, KEY_NONE,
IH 1:84cd616cc684 50
IH 1:84cd616cc684 51 };
IH 1:84cd616cc684 52
IH 0:9fd3dad2dc25 53
IH 0:9fd3dad2dc25 54 BusOut leds(LED1, LED2, LED3);
IH 0:9fd3dad2dc25 55
IH 0:9fd3dad2dc25 56 BusOut scanCols(
IH 0:9fd3dad2dc25 57 PTC10,PTC8,
IH 0:9fd3dad2dc25 58 PTC6, PTA5,
IH 0:9fd3dad2dc25 59 PTC5, PTA4,
IH 0:9fd3dad2dc25 60 PTC4, PTA12,
IH 0:9fd3dad2dc25 61 PTC3, PTD4,
IH 0:9fd3dad2dc25 62 PTC0, PTA2,
IH 0:9fd3dad2dc25 63 PTC7, PTA1
IH 0:9fd3dad2dc25 64 );
IH 0:9fd3dad2dc25 65
IH 0:9fd3dad2dc25 66 BusIn inRows(
IH 0:9fd3dad2dc25 67 PTB10,
IH 0:9fd3dad2dc25 68 PTB11,
IH 0:9fd3dad2dc25 69 PTE2,
IH 0:9fd3dad2dc25 70 PTE3,
IH 0:9fd3dad2dc25 71 PTE5 );
IH 0:9fd3dad2dc25 72
IH 0:9fd3dad2dc25 73 DigitalOut extLed(PTE4);
IH 0:9fd3dad2dc25 74
IH 0:9fd3dad2dc25 75 USBKeyboard kbd;
IH 0:9fd3dad2dc25 76
IH 0:9fd3dad2dc25 77 static int scanColumn(int col)
IH 0:9fd3dad2dc25 78 {
IH 0:9fd3dad2dc25 79 int rowBits;
IH 0:9fd3dad2dc25 80 // Drive output low to scan
IH 0:9fd3dad2dc25 81 scanCols.write(0x3FFF ^ (1 << col));
IH 0:9fd3dad2dc25 82 leds.write(col >> 1);
IH 1:84cd616cc684 83 wait(0.001);
IH 0:9fd3dad2dc25 84 rowBits = inRows.read();
IH 0:9fd3dad2dc25 85 scanCols.write(0x3FFF);
IH 0:9fd3dad2dc25 86 // Inputs also active-low
IH 0:9fd3dad2dc25 87 return rowBits ^ 0x1F;
IH 0:9fd3dad2dc25 88 }
IH 1:84cd616cc684 89
IH 1:84cd616cc684 90 static const uint8_t altKeys =
IH 1:84cd616cc684 91 MODIFIER_BIT(KEY_LEFT_ALT) | MODIFIER_BIT(KEY_RIGHT_ALT);
IH 1:84cd616cc684 92
IH 1:84cd616cc684 93
IH 0:9fd3dad2dc25 94 int main()
IH 0:9fd3dad2dc25 95 {
IH 0:9fd3dad2dc25 96 // Setup
IH 0:9fd3dad2dc25 97 inRows.mode(PullUp);
IH 0:9fd3dad2dc25 98 extLed = 1;
IH 0:9fd3dad2dc25 99
IH 0:9fd3dad2dc25 100 // Run loop
IH 0:9fd3dad2dc25 101 while(1)
IH 0:9fd3dad2dc25 102 {
IH 0:9fd3dad2dc25 103 int col, ocount;
IH 0:9fd3dad2dc25 104 HID_REPORT report;
IH 1:84cd616cc684 105 uint8_t keyIfAlt = KEY_NONE;
IH 0:9fd3dad2dc25 106
IH 0:9fd3dad2dc25 107 report.data[0] = REPORT_ID_KEYBOARD;
IH 0:9fd3dad2dc25 108 report.data[1] = 0; // modifiers
IH 0:9fd3dad2dc25 109 report.data[2] = 0;
IH 0:9fd3dad2dc25 110 ocount = 3;
IH 0:9fd3dad2dc25 111
IH 0:9fd3dad2dc25 112 for (col=0; col < MAX_COLS; col++)
IH 0:9fd3dad2dc25 113 {
IH 0:9fd3dad2dc25 114 int row;
IH 0:9fd3dad2dc25 115 int rowBits = scanColumn(col);
IH 0:9fd3dad2dc25 116 if ( !rowBits )
IH 0:9fd3dad2dc25 117 continue;
IH 0:9fd3dad2dc25 118
IH 0:9fd3dad2dc25 119 for (row=0; row < MAX_ROWS; row++)
IH 0:9fd3dad2dc25 120 {
IH 0:9fd3dad2dc25 121 if ( rowBits & (1 << row) )
IH 0:9fd3dad2dc25 122 {
IH 0:9fd3dad2dc25 123 uint8_t key = hid_keys[col * MAX_ROWS + row];
IH 0:9fd3dad2dc25 124 if ( IS_MODIFIER(key) )
IH 0:9fd3dad2dc25 125 report.data[1] |= MODIFIER_BIT(key);
IH 0:9fd3dad2dc25 126 else if ( key != KEY_NONE )
IH 0:9fd3dad2dc25 127 {
IH 0:9fd3dad2dc25 128 if ( ocount < REPORT_LEN )
IH 0:9fd3dad2dc25 129 report.data[ocount++] = key;
IH 0:9fd3dad2dc25 130 }
IH 1:84cd616cc684 131
IH 1:84cd616cc684 132 key = alt_keys[col * MAX_ROWS + row];
IH 1:84cd616cc684 133 if ( key != KEY_NONE )
IH 1:84cd616cc684 134 keyIfAlt = key;
IH 0:9fd3dad2dc25 135 //kbd.printf("c%dr%d ", col, row);
IH 0:9fd3dad2dc25 136 }
IH 0:9fd3dad2dc25 137 }
IH 0:9fd3dad2dc25 138 }
IH 0:9fd3dad2dc25 139
IH 1:84cd616cc684 140 if ( (report.data[1] & altKeys) != 0 &&
IH 1:84cd616cc684 141 keyIfAlt != KEY_NONE
IH 1:84cd616cc684 142 )
IH 1:84cd616cc684 143 {
IH 1:84cd616cc684 144 report.data[3] = keyIfAlt;
IH 1:84cd616cc684 145 ocount = 4; // Zero out the rest
IH 1:84cd616cc684 146 report.data[1] &= ~altKeys; // And put alt key up
IH 1:84cd616cc684 147 }
IH 1:84cd616cc684 148
IH 0:9fd3dad2dc25 149 while( ocount < REPORT_LEN )
IH 0:9fd3dad2dc25 150 report.data[ocount++] = KEY_NONE;
IH 0:9fd3dad2dc25 151
IH 0:9fd3dad2dc25 152 report.length = REPORT_LEN;
IH 0:9fd3dad2dc25 153 kbd.send(&report);
IH 0:9fd3dad2dc25 154 }
IH 0:9fd3dad2dc25 155 }