Update | Update | ||||
------ | ------ | ||||
2015/05/05 Added keymaps for 107-key, 77-key and 50-key. Thanks, orihalcon @ geekhack! | 2015/05/05 Added keymaps for 107-key, 77-key and 50-key. Thanks, orihalcon @ geekhack! | ||||
2015/05/19 Fixed a protocol handling bug. | |||||
/* Pin interrupt on rising edge of clock */ | /* Pin interrupt on rising edge of clock */ | ||||
#define IBM4704_INT_INIT() do { EICRA |= ((1<<ISC11)|(1<<ISC10)); } while (0) | #define IBM4704_INT_INIT() do { EICRA |= ((1<<ISC11)|(1<<ISC10)); } while (0) | ||||
#define IBM4704_INT_ON() do { EIMSK |= (1<<INT1); } while (0) | |||||
#define IBM4704_INT_ON() do { EIFR |= (1<<INTF1); EIMSK |= (1<<INT1); } while (0) | |||||
#define IBM4704_INT_OFF() do { EIMSK &= ~(1<<INT1); } while (0) | #define IBM4704_INT_OFF() do { EIMSK &= ~(1<<INT1); } while (0) | ||||
#define IBM4704_INT_VECT INT1_vect | #define IBM4704_INT_VECT INT1_vect | ||||
| `-----`--- scan code | | `-----`--- scan code | ||||
`------------- enable bit(0: enable repeat, 1: enable break) | `------------- enable bit(0: enable repeat, 1: enable break) | ||||
00-77 Enable repeat(78-7F: invalid scancode) | |||||
80-F7 Enable break(F8-FF: invalid scancode) | |||||
00-79 Enable repeat | |||||
80-F9 Enable break(FA-FF are used as other commands, see above.) | |||||
FE Resend(011ah) no need to use | FE Resend(011ah) no need to use | ||||
FF End(0114h) exits FC command mode. | FF End(0114h) exits FC command mode. | ||||
Response from keyboard: | Response from keyboard: | ||||
FD Out of bound - Invalid scancode | FD Out of bound - Invalid scancode | ||||
-- OK - No response means that command is accepted. | |||||
Examples: | Examples: | ||||
To enable break code of all keys. | To enable break code of all keys. |
static void enable_break(void) | static void enable_break(void) | ||||
{ | { | ||||
uint8_t ret; | |||||
print("Enable break: "); | print("Enable break: "); | ||||
// valid scancode: 00-79h | // valid scancode: 00-79h | ||||
for (uint8_t code = 0; code < 0x7A; code++) { | for (uint8_t code = 0; code < 0x7A; code++) { | ||||
while (ibm4704_send(0x80|code)) _delay_ms(1); | |||||
// get none when ok, get FD when out of bound | |||||
_delay_ms(5); | |||||
if ((ret = ibm4704_recv()) != 0xff) { | |||||
xprintf("c%02X:r%02X ", code, ret); | |||||
} | |||||
_delay_ms(1); | |||||
while (ibm4704_send(0x80|code)) _delay_ms(10); | |||||
_delay_ms(5); // wait for response | |||||
// No response(FF) when ok, FD when out of bound | |||||
xprintf("s%02X:r%02X ", code, ibm4704_recv()); | |||||
} | } | ||||
_delay_us(1000); | |||||
while (ibm4704_send(0xFF)) { _delay_ms(1); } // End | |||||
while (ibm4704_send(0xFF)) { _delay_ms(10); } // End | |||||
print("End\n"); | print("End\n"); | ||||
} | } | ||||
void matrix_init(void) | |||||
{ | |||||
debug_enable = true; | |||||
void matrix_setup(void) | |||||
{ | |||||
ibm4704_init(); | ibm4704_init(); | ||||
matrix_clear(); | |||||
} | |||||
_delay_ms(2000); // wait for starting up debug console | |||||
void matrix_init(void) | |||||
{ | |||||
debug_enable = true; | |||||
print("IBM 4704 converter\n"); | print("IBM 4704 converter\n"); | ||||
while (ibm4704_send(0xFE)) _delay_ms(1); // resend | |||||
_delay_ms(5); | |||||
matrix_clear(); | |||||
_delay_ms(2000); // wait for keyboard starting up | |||||
xprintf("Keyboard ID: %02X\n", ibm4704_recv()); | xprintf("Keyboard ID: %02X\n", ibm4704_recv()); | ||||
enable_break(); | enable_break(); | ||||
} | } |
void ibm4704_init(void) | void ibm4704_init(void) | ||||
{ | { | ||||
inhibit(); // keep keyboard from sending | |||||
IBM4704_INT_INIT(); | IBM4704_INT_INIT(); | ||||
IBM4704_INT_ON(); | IBM4704_INT_ON(); | ||||
idle(); | |||||
idle(); // allow keyboard sending | |||||
} | } | ||||
/* | /* | ||||
ISR(IBM4704_INT_VECT) | ISR(IBM4704_INT_VECT) | ||||
{ | { | ||||
static enum { | static enum { | ||||
STOP, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY | |||||
} state = STOP; | |||||
BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP | |||||
} state = BIT0; | |||||
// LSB first | // LSB first | ||||
static uint8_t data = 0; | static uint8_t data = 0; | ||||
// Odd parity | // Odd parity | ||||
ibm4704_error = 0; | ibm4704_error = 0; | ||||
switch (state++) { | |||||
case STOP: | |||||
// Data:Low | |||||
WAIT(data_lo, 10, state); | |||||
break; | |||||
switch (state) { | |||||
case BIT0: | case BIT0: | ||||
case BIT1: | case BIT1: | ||||
case BIT2: | case BIT2: | ||||
} | } | ||||
if (!parity) | if (!parity) | ||||
goto ERROR; | goto ERROR; | ||||
break; | |||||
case STOP: | |||||
// Data:Low | |||||
WAIT(data_lo, 100, state); | |||||
rbuf_enqueue(data); | rbuf_enqueue(data); | ||||
ibm4704_error = IBM4704_ERR_NONE; | ibm4704_error = IBM4704_ERR_NONE; | ||||
goto DONE; | goto DONE; | ||||
default: | default: | ||||
goto ERROR; | goto ERROR; | ||||
} | } | ||||
state++; | |||||
goto RETURN; | goto RETURN; | ||||
ERROR: | ERROR: | ||||
ibm4704_error = state; | ibm4704_error = state; | ||||
while (ibm4704_send(0xFE)) _delay_ms(1); // resend | while (ibm4704_send(0xFE)) _delay_ms(1); // resend | ||||
xprintf("R:%02X%02X\n", state, data); | xprintf("R:%02X%02X\n", state, data); | ||||
DONE: | DONE: | ||||
state = STOP; | |||||
state = BIT0; | |||||
data = 0; | data = 0; | ||||
parity = false; | parity = false; | ||||
RETURN: | RETURN: |