--- /dev/null
+/*\r
+ IBM Japan Ltd PC/JX Emulator 'eJX'\r
+\r
+ Author : Takeda.Toshiya\r
+ Date : 2011.05.10-\r
+\r
+ [ keyboard ]\r
+*/\r
+\r
+#include "keyboard.h"\r
+#include "../i8253.h"\r
+#include "../i8255.h"\r
+#include "../../fifo.h"\r
+\r
+static const int key_table[256] = {\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,\r
+ 0x2a, 0x1d, 0x38, 0x46, 0x3a, 0x6f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x01, 0x6d, 0x6c, 0x00, 0x00,\r
+ 0x39, 0x4f, 0x5e, 0x54, 0x47, 0x4b, 0x48, 0x4d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x00,\r
+ 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,\r
+ 0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x70, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x4e, 0x00, 0x4a, 0x71, 0x7c,\r
+ 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x27, 0x33, 0x0c, 0x34, 0x35,\r
+ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x6A, 0x29, 0x0d, 0x00,\r
+ 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+};\r
+\r
+#define EVENT_SEND 0\r
+#define EVENT_TIMER 1\r
+\r
+void KEYBOARD::initialize()\r
+{\r
+ key_buf = new FIFO(8);\r
+ \r
+#ifdef KEYBOARD_HACK\r
+ register_event(this, EVENT_SEND, 440 * 21, true, NULL);\r
+#else\r
+ register_event(this, EVENT_SEND, 220, true, NULL);\r
+#endif\r
+#ifndef TIMER_HACK\r
+ register_event_by_clock(this, EVENT_TIMER, 4, true, NULL);\r
+#endif\r
+}\r
+\r
+void KEYBOARD::release()\r
+{\r
+ key_buf->release();\r
+ delete key_buf;\r
+}\r
+\r
+void KEYBOARD::reset()\r
+{\r
+ key_buf->clear();\r
+#ifndef KEYBOARD_HACK\r
+ send_count = 0;\r
+#endif\r
+ key_latched = false;\r
+ \r
+ d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x01); // clear keyboard latched\r
+ d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x40); // set stop bit\r
+ \r
+ nmi_reg = 0;\r
+}\r
+\r
+void KEYBOARD::write_io8(uint32 addr, uint32 data)\r
+{\r
+ switch(addr) {\r
+ case 0xa0:\r
+ nmi_reg = data;\r
+ break;\r
+ }\r
+}\r
+\r
+uint32 KEYBOARD::read_io8(uint32 addr)\r
+{\r
+ switch(addr) {\r
+ case 0xa0:\r
+ d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x01);\r
+ key_latched = false;\r
+ return nmi_reg; // ???\r
+#ifdef KEYBOARD_HACK\r
+ case 0xa1:\r
+ if(!key_buf->empty()) {\r
+ return key_buf->read();\r
+ }\r
+ break;\r
+#endif\r
+ }\r
+ return 0xff;\r
+}\r
+\r
+void KEYBOARD::event_callback(int id, int err)\r
+{\r
+ if(id == EVENT_SEND) {\r
+#ifdef KEYBOARD_HACK\r
+ if(!key_buf->empty()) {\r
+ // rising edge\r
+ if(nmi_reg & 0x80) {\r
+ d_cpu->write_signal(SIG_CPU_NMI, 1, 1);\r
+ }\r
+ d_pio->write_signal(SIG_I8255_PORT_C, 0x01, 0x01);\r
+ key_latched = true;\r
+ }\r
+#else\r
+ if(send_count == 0 && !key_buf->empty()) {\r
+ int code = key_buf->read();\r
+ int parity = 1;\r
+ uint64 bit = 1;\r
+ \r
+ for(int i = 0; i < 8; i++) {\r
+ if(code & (1 << i)) {\r
+ parity++;\r
+ }\r
+ }\r
+ send_data = 0;\r
+ \r
+ #define SET_HALF_BIT(v) { \\r
+ if(v) { \\r
+ send_data |= bit; \\r
+ } \\r
+ bit <<= 1; \\r
+ }\r
+ #define SET_BIT(v) { \\r
+ if(v) { \\r
+ SET_HALF_BIT(1); \\r
+ SET_HALF_BIT(0); \\r
+ } else { \\r
+ SET_HALF_BIT(0); \\r
+ SET_HALF_BIT(1); \\r
+ } \\r
+ }\r
+ \r
+ SET_BIT(1); // start bit\r
+ for(int i = 0; i < 8; i++) {\r
+ SET_BIT(code & (1 << i));\r
+ }\r
+ SET_BIT(parity & 1);\r
+ send_count = 42;\r
+ }\r
+ if(send_count) {\r
+ if(send_count == 42 && !key_latched) {\r
+ // rising edge\r
+ if(nmi_reg & 0x80) {\r
+ d_cpu->write_signal(SIG_CPU_NMI, 1, 1);\r
+ }\r
+ d_pio->write_signal(SIG_I8255_PORT_C, 0x01, 0x01);\r
+ key_latched = true;\r
+ }\r
+ d_pio->write_signal(SIG_I8255_PORT_C, (send_data & 1) ? 0x40 : 0, 0x40);\r
+ send_data >>= 1;\r
+ send_count--;\r
+ }\r
+#endif\r
+#ifndef TIMER_HACK\r
+ } else if(id == EVENT_TIMER) {\r
+ if(!(nmi_reg & 0x20)) {\r
+ d_pit->write_signal(SIG_I8253_CLOCK_1, 1, 1);\r
+ d_pit->write_signal(SIG_I8253_CLOCK_1, 0, 0);\r
+ }\r
+#endif\r
+ }\r
+}\r
+\r
+void KEYBOARD::write_signal(int id, uint32 data, uint32 mask)\r
+{\r
+#ifndef TIMER_HACK\r
+ if(id == SIG_KEYBOARD_TIMER) {\r
+ if(nmi_reg & 0x20) {\r
+ d_pit->write_signal(SIG_I8253_CLOCK_1, data, mask);\r
+ }\r
+ }\r
+#endif\r
+}\r
+\r
+void KEYBOARD::key_down(int code)\r
+{\r
+ if(key_table[code]) {\r
+ key_buf->write(key_table[code]);\r
+ }\r
+}\r
+\r
+void KEYBOARD::key_up(int code)\r
+{\r
+ if(key_table[code]) {\r
+ key_buf->write(key_table[code] | 0x80);\r
+ }\r
+}\r
+\r