diff --git a/README.md b/README.md index b76b7fb9..a561b38e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di * [pc98_usb](converter/pc98_usb/) - [PC98] to USB * [usb_usb](converter/usb_usb/) - USB to USB(experimental) * [ascii_usb](converter/ascii_usb/) - ASCII(Serial console terminal) to USB +* [ibm4704_usb](converter/ibm4704_usb) - [IBM 4704 keyboard Converter][GH_ibm4704] ### keyboard * [hhkb](keyboard/hhkb/) - [Happy Hacking Keyboard pro][GH_hhkb] **my main board** @@ -62,6 +63,7 @@ You can find some keyboard specific projects under `converter` and `keyboard` di [GH_terminal]: http://geekhack.org/showwiki.php?title=Island:27272 [GH_x68k]: http://geekhack.org/showwiki.php?title=Island:29060 [GH_hbkb]: http://geekhack.org/showwiki.php?title=Island:29483 +[GH_ibm4704]: http://geekhack.org/index.php?topic=54706.0 [HID_liber]: http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions [Phantom]: http://geekhack.org/index.php?topic=26742 [GH60]: http://geekhack.org/index.php?topic=34959 diff --git a/protocol/ibm4704.c b/protocol/ibm4704.c new file mode 100644 index 00000000..10e229fd --- /dev/null +++ b/protocol/ibm4704.c @@ -0,0 +1,169 @@ +/* +Copyright 2010,2011,2012,2013 Jun WAKO +*/ +#include +#include +#include "debug.h" +#include "ibm4704.h" + + +#define WAIT(stat, us, err) do { \ + if (!wait_##stat(us)) { \ + ibm4704_error = err; \ + goto ERROR; \ + } \ +} while (0) + + +uint8_t ibm4704_error = 0; + + +void ibm4704_init(void) +{ + inhibit(); +} + +/* +Host to Keyboard +---------------- +Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. + + ____ __ __ __ __ __ __ __ __ __ ________ +Clock \______/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ + ^ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___ +Data ____|__/ X____X____X____X____X____X____X____X____X____X \___ + | Start 0 1 2 3 4 5 6 7 P Stop + Request by host + +Start bit: can be long as 300-350us. +Request: Host pulls Clock line down to request to send a command. +Timing: After Request keyboard pull up Data and down Clock line to low for start bit. + After request host release Clock line once Data line becomes hi. + Host writes a bit while Clock is hi and Keyboard reads while low. +Stop bit: Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo. +*/ +uint8_t ibm4704_send(uint8_t data) +{ + bool parity = true; // odd parity + ibm4704_error = 0; + + /* Request to send */ + idle(); + clock_lo(); + + /* wait for Start bit(Clock:lo/Data:hi) */ + WAIT(data_hi, 300, 0x30); + + /* Data bit */ + for (uint8_t i = 0; i < 8; i++) { + WAIT(clock_hi, 100, 0x40+i); + //_delay_us(5); + if (data&(1<= 0x30) { + xprintf("x%02X ", ibm4704_error); + } + _delay_us(200); // wait to recover clock to hi + return -1; +} + +/* receive data when host want else inhibit communication */ +uint8_t ibm4704_recv_response(void) +{ + // 250 * 100us(wait start bit in ibm4704_recv) + uint8_t data = 0; + uint8_t try = 250; + do { + data = ibm4704_recv(); + } while (try-- && ibm4704_error); + return data; +} + +/* +Keyboard to Host +---------------- +Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. + + ____ __ __ __ __ __ __ __ __ __ ________ +Clock \____/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ + ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ +Data ____/ X____X____X____X____X____X____X____X____X____X________ + Start 0 1 2 3 4 5 6 7 P Stop + +Start bit: can be long as 300-350us. +Inhibit: Pull Data line down to inhibit keyboard to send. +Timing: Host reads bit while Clock is hi. +Stop bit: Keyboard pulls down Data line to lo after 9th clock. +*/ +uint8_t ibm4704_recv(void) +{ + uint8_t data = 0; + bool parity = true; // odd parity + ibm4704_error = IBM4704_ERR_NONE; + + idle(); + _delay_us(5); // wait for line settles + + /* start bit */ + WAIT(clock_lo, 100, 0x11); // wait for keyboard to send + WAIT(data_hi, 100, 0x12); // can be delayed that long + + WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer + /* data */ + for (uint8_t i = 0; i < 8; i++) { + WAIT(clock_hi, 100, 0x20+i); + //_delay_us(5); + if (data_in()) { + parity = !parity; + data |= (1< 0x12) { + xprintf("x%02X ", ibm4704_error); + } + inhibit(); + _delay_us(200); // wait to recover clock to hi + return -1; +} diff --git a/protocol/ibm4704.h b/protocol/ibm4704.h new file mode 100644 index 00000000..618cce6b --- /dev/null +++ b/protocol/ibm4704.h @@ -0,0 +1,110 @@ +/* +Copyright 2014 Jun WAKO +*/ +#ifndef IBM4704_H +#define IBM4704_H + +#define IBM4704_ERR_NONE 0 +#define IBM4704_ERR_PARITY 0x70 + + +void ibm4704_init(void); +uint8_t ibm4704_send(uint8_t data); +uint8_t ibm4704_recv_response(void); +uint8_t ibm4704_recv(void); + + +/* Check pin configuration */ +#if !(defined(IBM4704_CLOCK_PORT) && \ + defined(IBM4704_CLOCK_PIN) && \ + defined(IBM4704_CLOCK_DDR) && \ + defined(IBM4704_CLOCK_BIT)) +# error "ibm4704 clock pin configuration is required in config.h" +#endif + +#if !(defined(IBM4704_DATA_PORT) && \ + defined(IBM4704_DATA_PIN) && \ + defined(IBM4704_DATA_DDR) && \ + defined(IBM4704_DATA_BIT)) +# error "ibm4704 data pin configuration is required in config.h" +#endif + + +/*-------------------------------------------------------------------- + * static functions + *------------------------------------------------------------------*/ +static inline void clock_lo(void) +{ + IBM4704_CLOCK_PORT &= ~(1<