OSDN Git Service

706b63fc0e06605da069c06cd632674b20551b48
[csp-qt/common_source_project-fm7.git] / source / src / vm / jx / keyboard.cpp
1 /*
2         IBM Japan Ltd PC/JX Emulator 'eJX'
3
4         Author : Takeda.Toshiya
5         Date   : 2011.05.10-
6
7         [ keyboard ]
8 */
9
10 #include "keyboard.h"
11 #include "../i8253.h"
12 #include "../i8255.h"
13 #include "../../fifo.h"
14
15 static const int key_table[256] = {
16         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
17         0x2a, 0x1d, 0x38, 0x46, 0x3a, 0x6f, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x01, 0x6d, 0x6c, 0x00, 0x00,
18         0x39, 0x4f, 0x5e, 0x54, 0x47, 0x4b, 0x48, 0x4d, 0x50, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x00,
19         0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
20         0x00, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
21         0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
22         0x70, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x4e, 0x00, 0x4a, 0x71, 0x7c,
23         0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x6e, 0x6f, 0x00, 0x00, 0x00, 0x00,
24         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
25         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
26         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
27         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x27, 0x33, 0x0c, 0x34, 0x35,
28         0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x6A, 0x29, 0x0d, 0x00,
30         0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
32 };
33
34 #define EVENT_SEND      0
35 #define EVENT_TIMER     1
36
37 void KEYBOARD::initialize()
38 {
39         key_buf = new FIFO(8);
40         
41 #ifdef KEYBOARD_HACK
42         register_event(this, EVENT_SEND, 440 * 21, true, NULL);
43 #else
44         register_event(this, EVENT_SEND, 220, true, NULL);
45 #endif
46 #ifndef TIMER_HACK
47         register_event_by_clock(this, EVENT_TIMER, 4, true, NULL);
48 #endif
49 }
50
51 void KEYBOARD::release()
52 {
53         key_buf->release();
54         delete key_buf;
55 }
56
57 void KEYBOARD::reset()
58 {
59         key_buf->clear();
60 #ifndef KEYBOARD_HACK
61         send_count = 0;
62 #endif
63         key_latched = false;
64         
65         d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x01); // clear keyboard latched
66         d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x40); // set stop bit
67         
68         nmi_reg = 0;
69 }
70
71 void KEYBOARD::write_io8(uint32_t addr, uint32_t data)
72 {
73         switch(addr) {
74         case 0xa0:
75                 nmi_reg = data;
76                 break;
77         }
78 }
79
80 uint32_t KEYBOARD::read_io8(uint32_t addr)
81 {
82         switch(addr) {
83         case 0xa0:
84                 d_pio->write_signal(SIG_I8255_PORT_C, 0x00, 0x01);
85                 key_latched = false;
86                 return nmi_reg; // ???
87 #ifdef KEYBOARD_HACK
88         case 0xa1:
89                 if(!key_buf->empty()) {
90                         return key_buf->read();
91                 }
92                 break;
93 #endif
94         }
95         return 0xff;
96 }
97
98 void KEYBOARD::event_callback(int id, int err)
99 {
100         if(id == EVENT_SEND) {
101 #ifdef KEYBOARD_HACK
102                 if(!key_buf->empty()) {
103                         // rising edge
104                         if(nmi_reg & 0x80) {
105                                 d_cpu->write_signal(SIG_CPU_NMI, 1, 1);
106                         }
107                         d_pio->write_signal(SIG_I8255_PORT_C, 0x01, 0x01);
108                         key_latched = true;
109                 }
110 #else
111                 if(send_count == 0 && !key_buf->empty()) {
112                         int code = key_buf->read();
113                         int parity = 1;
114                         uint64_t bit = 1;
115                         
116                         for(int i = 0; i < 8; i++) {
117                                 if(code & (1 << i)) {
118                                         parity++;
119                                 }
120                         }
121                         send_data = 0;
122                         
123                         #define SET_HALF_BIT(v) { \
124                                 if(v) { \
125                                         send_data |= bit; \
126                                 } \
127                                 bit <<= 1; \
128                         }
129                         #define SET_BIT(v) { \
130                                 if(v) { \
131                                         SET_HALF_BIT(1); \
132                                         SET_HALF_BIT(0); \
133                                 } else { \
134                                         SET_HALF_BIT(0); \
135                                         SET_HALF_BIT(1); \
136                                 } \
137                         }
138                         
139                         SET_BIT(1);     // start bit
140                         for(int i = 0; i < 8; i++) {
141                                 SET_BIT(code & (1 << i));
142                         }
143                         SET_BIT(parity & 1);
144                         send_count = 42;
145                 }
146                 if(send_count) {
147                         if(send_count == 42 && !key_latched) {
148                                 // rising edge
149                                 if(nmi_reg & 0x80) {
150                                         d_cpu->write_signal(SIG_CPU_NMI, 1, 1);
151                                 }
152                                 d_pio->write_signal(SIG_I8255_PORT_C, 0x01, 0x01);
153                                 key_latched = true;
154                         }
155                         d_pio->write_signal(SIG_I8255_PORT_C, (send_data & 1) ? 0x40 : 0, 0x40);
156                         send_data >>= 1;
157                         send_count--;
158                 }
159 #endif
160 #ifndef TIMER_HACK
161         } else if(id == EVENT_TIMER) {
162                 if(!(nmi_reg & 0x20)) {
163                         d_pit->write_signal(SIG_I8253_CLOCK_1, 1, 1);
164                         d_pit->write_signal(SIG_I8253_CLOCK_1, 0, 0);
165                 }
166 #endif
167         }
168 }
169
170 void KEYBOARD::write_signal(int id, uint32_t data, uint32_t mask)
171 {
172 #ifndef TIMER_HACK
173         if(id == SIG_KEYBOARD_TIMER) {
174                 if(nmi_reg & 0x20) {
175                         d_pit->write_signal(SIG_I8253_CLOCK_1, data, mask);
176                 }
177         }
178 #endif
179 }
180
181 void KEYBOARD::key_down(int code)
182 {
183         if(key_table[code]) {
184                 key_buf->write(key_table[code]);
185         }
186 }
187
188 void KEYBOARD::key_up(int code)
189 {
190         if(key_table[code]) {
191                 key_buf->write(key_table[code] | 0x80);
192         }
193 }
194