trunk/src/mess/drivers/ie15.c
| r29635 | r29636 | |
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | | 15IE-00-013 Terminal |
| 3 | 15IE-00-013 Terminal |
| 4 | 4 | |
| 5 | | board images : http://asvcorp.ru/darch/hardware/pdp/fryazin-display/index.html |
| 5 | A serial (RS232 or current loop) green-screen terminal, mostly VT52 |
| 6 | compatible (no Hold Screen mode and no graphics character set). |
| 6 | 7 | |
| 7 | | 29/06/2012 Skeleton driver. |
| 8 | Alternate character set (selected by SO/SI chars) is Cyrillic. |
| 8 | 9 | |
| 9 | | A serial (RS232 or current loop) green-screen terminal, mostly VT52 compatible |
| 10 | | (no Hold Screen mode and no graphics character set, but has Cyrillic characters). |
| 11 | | The top line is a status line. |
| 12 | | |
| 13 | 10 | ****************************************************************************/ |
| 14 | 11 | |
| 12 | |
| 15 | 13 | #include "emu.h" |
| 14 | |
| 15 | #include "bus/rs232/rs232.h" |
| 16 | 16 | #include "cpu/ie15/ie15.h" |
| 17 | 17 | #include "imagedev/bitbngr.h" |
| 18 | | #include "machine/keyboard.h" |
| 18 | #include "machine/ie15_kbd.h" |
| 19 | 19 | #include "sound/beep.h" |
| 20 | #include "ie15.lh" |
| 20 | 21 | |
| 21 | 22 | #define SCREEN_PAGE (80*48) |
| 22 | 23 | |
| 23 | | #define IE_1 0x80 |
| 24 | | #define IE_KB_ACK 1 |
| 24 | #define IE_TRUE 0x80 |
| 25 | #define IE_FALSE 0 |
| 25 | 26 | |
| 26 | 27 | #define IE15_TOTAL_HORZ 1000 |
| 27 | | #define IE15_TOTAL_VERT 28*11 |
| 28 | | |
| 29 | 28 | #define IE15_DISP_HORZ 800 |
| 30 | | #define IE15_DISP_VERT 25*11 |
| 29 | #define IE15_HORZ_START 200 |
| 31 | 30 | |
| 32 | | #define IE15_HORZ_START 100 |
| 31 | #define IE15_TOTAL_VERT 28*11 |
| 32 | #define IE15_DISP_VERT 25*11 |
| 33 | 33 | #define IE15_VERT_START 2*11 |
| 34 | #define IE15_STATUSLINE 11 |
| 34 | 35 | |
| 36 | |
| 35 | 37 | #define VERBOSE_DBG 1 /* general debug messages */ |
| 36 | 38 | |
| 37 | 39 | #define DBG_LOG(N,M,A) \ |
| r29635 | r29636 | |
| 44 | 46 | } \ |
| 45 | 47 | } while (0) |
| 46 | 48 | |
| 47 | | #if VERBOSE_DBG > 0 |
| 48 | | #define LOOPBACK (m_io_keyboard->read() & 0x20) |
| 49 | | #else |
| 50 | | #define LOOPBACK (0) |
| 51 | | #endif |
| 52 | 49 | |
| 53 | | #define BITBANGER_TAG "bitbanger" |
| 54 | | #define KEYBOARD_TAG "keyboard" |
| 55 | | |
| 56 | | class ie15_state : public driver_device |
| 50 | class ie15_state : public driver_device, |
| 51 | public device_serial_interface |
| 57 | 52 | { |
| 58 | 53 | public: |
| 59 | | ie15_state(const machine_config &mconfig, device_type type, const char *tag) |
| 60 | | : driver_device(mconfig, type, tag), |
| 54 | ie15_state(const machine_config &mconfig, device_type type, const char *tag) : |
| 55 | driver_device(mconfig, type, tag), |
| 56 | device_serial_interface(mconfig, *this), |
| 61 | 57 | m_maincpu(*this, "maincpu"), |
| 62 | 58 | m_beeper(*this, "beeper"), |
| 63 | | m_bitbanger(*this, BITBANGER_TAG), |
| 64 | | m_io_keyboard(*this, KEYBOARD_TAG) |
| 59 | m_rs232(*this, "rs232"), |
| 60 | m_io_keyboard(*this, "keyboard") |
| 65 | 61 | { } |
| 66 | 62 | |
| 67 | 63 | virtual void machine_reset(); |
| 68 | 64 | virtual void video_start(); |
| 69 | | DECLARE_PALETTE_INIT(ie15); |
| 70 | 65 | UINT32 screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 71 | 66 | UINT32 screen_update_hle(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); |
| 72 | | TIMER_DEVICE_CALLBACK_MEMBER(scanline_callback); |
| 73 | | DECLARE_WRITE8_MEMBER(kbd_put); |
| 74 | | static const bitbanger_config ie15_bitbanger_config; |
| 75 | | TIMER_CALLBACK_MEMBER(serial_tx_callback); |
| 76 | | emu_timer *m_serial_tx_timer; |
| 67 | TIMER_DEVICE_CALLBACK_MEMBER( scanline_callback ); |
| 68 | DECLARE_WRITE16_MEMBER( kbd_put ); |
| 77 | 69 | |
| 70 | DECLARE_WRITE_LINE_MEMBER( serial_rx_callback ); |
| 71 | virtual void rcv_complete(); |
| 72 | virtual void tra_callback(); |
| 73 | virtual void tra_complete(); |
| 74 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 75 | |
| 78 | 76 | DECLARE_WRITE8_MEMBER( mem_w ); |
| 79 | 77 | DECLARE_READ8_MEMBER( mem_r ); |
| 80 | 78 | DECLARE_WRITE8_MEMBER( mem_addr_lo_w ); |
| r29635 | r29636 | |
| 96 | 94 | DECLARE_WRITE8_MEMBER( serial_w ); |
| 97 | 95 | DECLARE_READ8_MEMBER( serial_rx_ready_r ); |
| 98 | 96 | DECLARE_READ8_MEMBER( serial_r ); |
| 99 | | #if 0 |
| 100 | 97 | DECLARE_WRITE8_MEMBER( serial_speed_w ); |
| 101 | | #endif |
| 102 | 98 | |
| 103 | 99 | private: |
| 104 | 100 | TIMER_CALLBACK_MEMBER(ie15_beepoff); |
| 105 | | UINT32 draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y); |
| 101 | void update_leds(); |
| 102 | UINT32 draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline); |
| 103 | rectangle m_tmpclip; |
| 106 | 104 | bitmap_ind16 m_tmpbmp; |
| 105 | bitmap_ind16 m_offbmp; |
| 107 | 106 | |
| 108 | 107 | const UINT8 *m_p_chargen; |
| 109 | 108 | UINT8 *m_p_videoram; |
| 110 | | UINT8 m_beep; |
| 111 | | UINT8 m_cursor; |
| 109 | UINT8 m_long_beep; |
| 110 | UINT8 m_kb_control; |
| 112 | 111 | UINT8 m_kb_data; |
| 113 | | UINT8 m_kb_flag; |
| 114 | 112 | UINT8 m_kb_flag0; |
| 113 | UINT8 m_kb_flag; |
| 114 | UINT8 m_kb_ruslat; |
| 115 | 115 | UINT8 m_latch; |
| 116 | | UINT8 m_ruslat; |
| 117 | | UINT8 m_serial_rx_bits; |
| 118 | | UINT8 m_serial_rx_buffer; |
| 119 | | UINT8 m_serial_rx_data; |
| 120 | | UINT8 m_serial_tx_bits; |
| 121 | | UINT8 m_serial_tx_data; |
| 122 | | UINT8 m_statusline; |
| 123 | | UINT8 m_video; |
| 124 | | UINT32 m_videoptr; |
| 125 | | UINT32 m_videoptr_2; |
| 116 | struct { |
| 117 | UINT8 cursor; |
| 118 | UINT8 enable; |
| 119 | UINT8 line25; |
| 120 | UINT32 ptr1; |
| 121 | UINT32 ptr2; |
| 122 | } m_video; |
| 126 | 123 | |
| 127 | | static void bitbanger_callback(running_machine &machine, UINT8 bit); |
| 128 | | DECLARE_WRITE_LINE_MEMBER( serial_rx_callback ); |
| 124 | UINT8 m_serial_rx_ready; |
| 125 | UINT8 m_serial_tx_ready; |
| 129 | 126 | |
| 130 | 127 | protected: |
| 131 | 128 | required_device<cpu_device> m_maincpu; |
| 132 | 129 | required_device<beep_device> m_beeper; |
| 133 | | required_device<bitbanger_device> m_bitbanger; |
| 130 | required_device<rs232_port_device> m_rs232; |
| 134 | 131 | required_ioport m_io_keyboard; |
| 135 | 132 | }; |
| 136 | 133 | |
| 137 | 134 | READ8_MEMBER( ie15_state::mem_r ) { |
| 138 | 135 | UINT8 ret; |
| 139 | 136 | |
| 140 | | ret = m_p_videoram[m_videoptr]; |
| 141 | | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE) |
| 137 | ret = m_p_videoram[m_video.ptr1]; |
| 138 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_video.ptr1 >= SCREEN_PAGE) |
| 142 | 139 | { |
| 143 | | DBG_LOG(2,"memory",("R @ %03x == %02x\n", m_videoptr, ret)); |
| 140 | DBG_LOG(2,"memory",("R @ %03x == %02x\n", m_video.ptr1, ret)); |
| 144 | 141 | } |
| 145 | | m_videoptr++; |
| 146 | | m_videoptr &= 0xfff; |
| 142 | m_video.ptr1++; |
| 143 | m_video.ptr1 &= 0xfff; |
| 147 | 144 | m_latch = 0; |
| 148 | 145 | return ret; |
| 149 | 146 | } |
| 150 | 147 | |
| 151 | 148 | WRITE8_MEMBER( ie15_state::mem_w ) { |
| 152 | 149 | if ((m_latch ^= 1) == 0) { |
| 153 | | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_videoptr >= SCREEN_PAGE) |
| 150 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && m_video.ptr1 >= SCREEN_PAGE) |
| 154 | 151 | { |
| 155 | | DBG_LOG(2,"memory",("W @ %03x <- %02x\n", m_videoptr, data)); |
| 152 | DBG_LOG(2,"memory",("W @ %03x <- %02x\n", m_video.ptr1, data)); |
| 156 | 153 | } |
| 157 | | m_p_videoram[m_videoptr++] = data; |
| 158 | | m_videoptr &= 0xfff; |
| 154 | m_p_videoram[m_video.ptr1++] = data; |
| 155 | m_video.ptr1 &= 0xfff; |
| 159 | 156 | } |
| 160 | 157 | } |
| 161 | 158 | |
| 162 | 159 | WRITE8_MEMBER( ie15_state::mem_addr_inc_w ) { |
| 163 | 160 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 164 | 161 | { |
| 165 | | DBG_LOG(2,"memory",("++ %03x\n", m_videoptr)); |
| 162 | DBG_LOG(2,"memory",("++ %03x\n", m_video.ptr1)); |
| 166 | 163 | } |
| 167 | | m_videoptr++; |
| 168 | | m_videoptr &= 0xfff; |
| 169 | | if (m_video) |
| 170 | | m_videoptr_2 = m_videoptr; |
| 164 | m_video.ptr1++; |
| 165 | m_video.ptr1 &= 0xfff; |
| 166 | if (m_video.enable) |
| 167 | m_video.ptr2 = m_video.ptr1; |
| 171 | 168 | } |
| 172 | 169 | |
| 173 | 170 | WRITE8_MEMBER( ie15_state::mem_addr_dec_w ) { |
| 174 | 171 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 175 | 172 | { |
| 176 | | DBG_LOG(2,"memory",("-- %03x\n", m_videoptr)); |
| 173 | DBG_LOG(2,"memory",("-- %03x\n", m_video.ptr1)); |
| 177 | 174 | } |
| 178 | | m_videoptr--; |
| 179 | | m_videoptr &= 0xfff; |
| 180 | | if (m_video) |
| 181 | | m_videoptr_2 = m_videoptr; |
| 175 | m_video.ptr1--; |
| 176 | m_video.ptr1 &= 0xfff; |
| 177 | if (m_video.enable) |
| 178 | m_video.ptr2 = m_video.ptr1; |
| 182 | 179 | } |
| 183 | 180 | |
| 184 | 181 | WRITE8_MEMBER( ie15_state::mem_addr_lo_w ) { |
| 185 | | UINT16 tmp = m_videoptr; |
| 182 | UINT16 tmp = m_video.ptr1; |
| 186 | 183 | |
| 187 | 184 | tmp &= 0xff0; |
| 188 | 185 | tmp |= ((data >> 4) & 0xf); |
| 189 | 186 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 190 | 187 | { |
| 191 | | DBG_LOG(2,"memory",("lo %03x <- %02x = %03x\n", m_videoptr, data, tmp)); |
| 188 | DBG_LOG(2,"memory",("lo %03x <- %02x = %03x\n", m_video.ptr1, data, tmp)); |
| 192 | 189 | } |
| 193 | | m_videoptr = tmp; |
| 194 | | if (m_video) |
| 195 | | m_videoptr_2 = tmp; |
| 190 | m_video.ptr1 = tmp; |
| 191 | if (m_video.enable) |
| 192 | m_video.ptr2 = tmp; |
| 196 | 193 | } |
| 197 | 194 | |
| 198 | 195 | WRITE8_MEMBER( ie15_state::mem_addr_hi_w ) { |
| 199 | | UINT16 tmp = m_videoptr; |
| 196 | UINT16 tmp = m_video.ptr1; |
| 200 | 197 | |
| 201 | 198 | tmp &= 0xf; |
| 202 | 199 | tmp |= (data << 4); |
| 203 | 200 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 204 | 201 | { |
| 205 | | DBG_LOG(2,"memory",("hi %03x <- %02x = %03x\n", m_videoptr, data, tmp)); |
| 202 | DBG_LOG(2,"memory",("hi %03x <- %02x = %03x\n", m_video.ptr1, data, tmp)); |
| 206 | 203 | } |
| 207 | | m_videoptr = tmp; |
| 208 | | if (m_video) |
| 209 | | m_videoptr_2 = tmp; |
| 204 | m_video.ptr1 = tmp; |
| 205 | if (m_video.enable) |
| 206 | m_video.ptr2 = tmp; |
| 210 | 207 | } |
| 211 | 208 | |
| 212 | 209 | TIMER_CALLBACK_MEMBER(ie15_state::ie15_beepoff) |
| r29635 | r29636 | |
| 215 | 212 | } |
| 216 | 213 | |
| 217 | 214 | WRITE8_MEMBER( ie15_state::beep_w ) { |
| 218 | | UINT16 length = (m_beep&128)?150:400; |
| 215 | UINT16 length = (m_long_beep & IE_TRUE) ? 150 : 400; |
| 219 | 216 | |
| 220 | 217 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 221 | 218 | { |
| 222 | | DBG_LOG(1,"beep",("(%s)\n", m_beep?"short":"long")); |
| 219 | DBG_LOG(1,"beep",("(%s)\n", m_long_beep ? "short" : "long")); |
| 223 | 220 | } |
| 224 | 221 | machine().scheduler().timer_set(attotime::from_msec(length), timer_expired_delegate(FUNC(ie15_state::ie15_beepoff),this)); |
| 225 | 222 | machine().device<beep_device>("beeper")->set_state(1); |
| 226 | 223 | } |
| 227 | 224 | |
| 225 | /* keyboard */ |
| 226 | |
| 228 | 227 | // active high |
| 229 | 228 | READ8_MEMBER( ie15_state::kb_r ) { |
| 230 | | DBG_LOG(2,"keyboard",("R %02X '%c'\n", m_kb_data, m_kb_data < 0x20?' ':m_kb_data)); |
| 229 | DBG_LOG(2,"keyboard",("R %02X '%c'\n", m_kb_data, m_kb_data < 0x20 ? ' ' : m_kb_data)); |
| 231 | 230 | return m_kb_data; |
| 232 | 231 | } |
| 233 | 232 | |
| 234 | 233 | // active low |
| 235 | 234 | READ8_MEMBER( ie15_state::kb_ready_r ) { |
| 236 | | m_kb_flag &= IE_1; |
| 235 | m_kb_flag &= IE_TRUE; |
| 237 | 236 | if (m_kb_flag != m_kb_flag0) { |
| 238 | | DBG_LOG(2,"keyboard",("? %c\n", m_kb_flag?'n':'y')); |
| 237 | DBG_LOG(2,"keyboard",("? %c\n", m_kb_flag ? 'n' : 'y')); |
| 239 | 238 | m_kb_flag0 = m_kb_flag; |
| 240 | 239 | } |
| 241 | 240 | return m_kb_flag; |
| r29635 | r29636 | |
| 244 | 243 | // active low |
| 245 | 244 | WRITE8_MEMBER( ie15_state::kb_ready_w ) { |
| 246 | 245 | DBG_LOG(2,"keyboard",("clear ready\n")); |
| 247 | | m_kb_flag = IE_1 | IE_KB_ACK; |
| 246 | m_kb_flag = IE_TRUE | IE_KB_ACK; |
| 248 | 247 | } |
| 249 | 248 | |
| 250 | 249 | |
| 251 | 250 | // active high; active = interpret controls, inactive = display controls |
| 252 | 251 | READ8_MEMBER( ie15_state::kb_s_red_r ) { |
| 253 | | return m_io_keyboard->read() & 0x01 ? IE_1 : 0; |
| 252 | return m_io_keyboard->read() & IE_KB_RED ? IE_TRUE : 0; |
| 254 | 253 | } |
| 255 | 254 | |
| 256 | 255 | // active high; active = setup mode |
| 257 | 256 | READ8_MEMBER( ie15_state::kb_s_sdv_r ) { |
| 258 | | return m_io_keyboard->read() & 0x02 ? IE_1 : 0; |
| 257 | return m_kb_control & IE_KB_SDV ? IE_TRUE : 0; |
| 259 | 258 | } |
| 260 | 259 | |
| 261 | | // active high, XXX stub |
| 260 | // active high; active = keypress detected on aux keypad |
| 262 | 261 | READ8_MEMBER( ie15_state::kb_s_dk_r ) { |
| 263 | | return 0; |
| 262 | return m_kb_control & IE_KB_DK ? IE_TRUE : 0; |
| 264 | 263 | } |
| 265 | 264 | |
| 266 | 265 | // active low; active = full duplex, inactive = half duplex |
| 267 | 266 | READ8_MEMBER( ie15_state::kb_s_dupl_r ) { |
| 268 | | return m_io_keyboard->read() & 0x08 ? IE_1 : 0; |
| 267 | return m_io_keyboard->read() & IE_KB_DUP ? IE_TRUE : 0; |
| 269 | 268 | } |
| 270 | 269 | |
| 271 | 270 | // active high; active = on-line, inactive = local editing |
| 272 | 271 | READ8_MEMBER( ie15_state::kb_s_lin_r ) { |
| 273 | | return m_io_keyboard->read() & 0x10 ? IE_1 : 0; |
| 272 | return m_io_keyboard->read() & IE_KB_LIN ? IE_TRUE : 0; |
| 274 | 273 | } |
| 275 | 274 | |
| 276 | | // active low |
| 277 | | READ8_MEMBER( ie15_state::serial_rx_ready_r ) { |
| 278 | | if (LOOPBACK) |
| 279 | | return m_serial_tx_data ? 0 : IE_1; |
| 280 | | else |
| 281 | | return m_serial_rx_data ? 0 : IE_1; |
| 282 | | } |
| 275 | /* serial port */ |
| 283 | 276 | |
| 284 | | // not called unless data is ready |
| 285 | | READ8_MEMBER( ie15_state::serial_r ) { |
| 286 | | UINT8 tmp; |
| 287 | | |
| 288 | | if (LOOPBACK) { |
| 289 | | tmp = m_serial_tx_data; |
| 290 | | m_serial_tx_data = 0; |
| 291 | | } else { |
| 292 | | tmp = m_serial_rx_data; |
| 293 | | m_serial_rx_data = 0; |
| 294 | | } |
| 295 | | DBG_LOG(2,"serial",("R %02X '%c'\n", tmp, tmp < 0x20?' ':tmp)); |
| 296 | | return tmp; |
| 277 | void ie15_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 278 | { |
| 279 | device_serial_interface::device_timer(timer, id, param, ptr); |
| 297 | 280 | } |
| 298 | 281 | |
| 299 | | /* |
| 300 | | m_serial_rx_buffer incoming bits. |
| 301 | | m_serial_rx_bits number of bits in _buffer. |
| 302 | | m_serial_rx_data complete byte, ready to be read by host, or 0 if no data. |
| 303 | | */ |
| 304 | | |
| 305 | 282 | WRITE_LINE_MEMBER( ie15_state::serial_rx_callback ) |
| 306 | 283 | { |
| 307 | | UINT8 tmp = m_serial_rx_bits; |
| 284 | device_serial_interface::rx_w(state); |
| 285 | } |
| 308 | 286 | |
| 309 | | switch (m_serial_rx_bits) { |
| 310 | | // wait for start bit (0) |
| 311 | | case 10: |
| 312 | | m_serial_rx_bits = 0; |
| 313 | | case 0: |
| 314 | | if (!state) { |
| 315 | | m_serial_rx_bits++; |
| 316 | | m_serial_rx_buffer = 0; |
| 317 | | } |
| 318 | | break; |
| 319 | | // stuff incoming bits into byte buffer |
| 320 | | case 1: case 2: case 3: case 4: |
| 321 | | case 5: case 6: case 7: case 8: |
| 322 | | m_serial_rx_buffer |= state << (m_serial_rx_bits-1); |
| 323 | | m_serial_rx_bits++; |
| 324 | | break; |
| 325 | | // expecting stop bit (1) |
| 326 | | case 9: |
| 327 | | if (state && !m_serial_rx_data) { |
| 328 | | m_serial_rx_data = m_serial_rx_buffer; |
| 329 | | m_serial_rx_bits++; |
| 330 | | } else |
| 331 | | m_serial_rx_bits = 0; |
| 332 | | break; |
| 333 | | default: |
| 334 | | // overflow |
| 335 | | break; |
| 336 | | } |
| 337 | | DBG_LOG(2,"serial",("r %d bits %02d->%02d buffer %02X data %02X\n", |
| 338 | | state, tmp, m_serial_rx_bits, m_serial_rx_buffer, m_serial_rx_data)); |
| 287 | void ie15_state::rcv_complete() |
| 288 | { |
| 289 | receive_register_extract(); |
| 290 | m_serial_rx_ready = IE_FALSE; |
| 339 | 291 | } |
| 340 | 292 | |
| 341 | | const bitbanger_config ie15_state::ie15_bitbanger_config = |
| 293 | void ie15_state::tra_callback() |
| 342 | 294 | { |
| 343 | | DEVCB_DRIVER_LINE_MEMBER(ie15_state, serial_rx_callback), /* callback */ |
| 344 | | BITBANGER_PRINTER, /* default mode */ |
| 345 | | BITBANGER_9600, /* default output baud */ |
| 346 | | BITBANGER_0PERCENT /* default fine tune adjustment */ |
| 347 | | }; |
| 295 | UINT8 bit = transmit_register_get_data_bit(); |
| 296 | m_rs232->write_txd(bit); |
| 297 | } |
| 348 | 298 | |
| 299 | void ie15_state::tra_complete() |
| 300 | { |
| 301 | m_serial_tx_ready = IE_TRUE; |
| 302 | } |
| 303 | |
| 304 | // active low |
| 305 | READ8_MEMBER( ie15_state::serial_rx_ready_r ) { |
| 306 | return m_serial_rx_ready; |
| 307 | } |
| 308 | |
| 349 | 309 | // active high |
| 350 | 310 | READ8_MEMBER( ie15_state::serial_tx_ready_r ) { |
| 351 | | return m_serial_tx_data ? 0 : IE_1; |
| 311 | return m_serial_tx_ready; |
| 352 | 312 | } |
| 353 | 313 | |
| 314 | // not called unless data are ready |
| 315 | READ8_MEMBER( ie15_state::serial_r ) { |
| 316 | UINT8 data; |
| 317 | |
| 318 | data = get_received_char(); |
| 319 | m_serial_rx_ready = IE_TRUE; |
| 320 | DBG_LOG(1,"serial",("R %02X '%c'\n", data, data < 0x20?' ':data)); |
| 321 | return data; |
| 322 | } |
| 323 | |
| 354 | 324 | WRITE8_MEMBER( ie15_state::serial_w ) { |
| 355 | | DBG_LOG(2,"serial",("W %02X '%c'\n", data, data < 0x20?' ':data)); |
| 356 | | if (LOOPBACK) { |
| 357 | | if (!m_serial_tx_data) |
| 358 | | m_serial_tx_data = data; |
| 359 | | } else { |
| 360 | | /* 1 start bit */ |
| 361 | | m_bitbanger->output(0); |
| 362 | | /* 8 data bits, 1 stop bit, no parity */ |
| 363 | | m_serial_tx_bits = 8; |
| 364 | | m_serial_tx_data = data; |
| 365 | | m_serial_tx_timer->adjust(attotime::from_hz(9600)); |
| 366 | | } |
| 325 | DBG_LOG(1,"serial",("W %02X '%c'\n", data, data < 0x20?' ':data)); |
| 326 | |
| 327 | m_serial_tx_ready = IE_FALSE; |
| 328 | transmit_register_setup(data); |
| 367 | 329 | } |
| 368 | 330 | |
| 369 | | TIMER_CALLBACK_MEMBER(ie15_state::serial_tx_callback) { |
| 370 | | if (!m_serial_tx_bits) { |
| 371 | | m_bitbanger->output(1); |
| 372 | | m_serial_tx_data = 0; |
| 373 | | } else { |
| 374 | | m_bitbanger->output(BIT(m_serial_tx_data, 8-(m_serial_tx_bits--))); |
| 375 | | m_serial_tx_timer->adjust(attotime::from_hz(9600)); |
| 376 | | } |
| 331 | WRITE8_MEMBER( ie15_state::serial_speed_w ) { |
| 332 | return; |
| 377 | 333 | } |
| 378 | 334 | |
| 379 | 335 | READ8_MEMBER( ie15_state::flag_r ) { |
| r29635 | r29636 | |
| 391 | 347 | ret = !machine().first_screen()->vblank(); |
| 392 | 348 | break; |
| 393 | 349 | case 4: |
| 394 | | ret = m_ruslat; |
| 350 | ret = m_kb_ruslat; |
| 395 | 351 | break; |
| 396 | 352 | default: |
| 397 | 353 | break; |
| r29635 | r29636 | |
| 407 | 363 | switch (offset) |
| 408 | 364 | { |
| 409 | 365 | case 0: |
| 410 | | m_video = data; |
| 366 | m_video.enable = data; |
| 411 | 367 | break; |
| 412 | 368 | case 1: |
| 413 | | m_cursor = data; |
| 369 | m_video.cursor = data; |
| 414 | 370 | break; |
| 415 | 371 | case 2: |
| 416 | | m_beep = data; |
| 372 | m_long_beep = data; |
| 417 | 373 | break; |
| 418 | 374 | case 3: |
| 419 | | m_statusline = data; |
| 375 | m_video.line25 = data; |
| 420 | 376 | break; |
| 421 | 377 | case 4: |
| 422 | | m_ruslat = data; |
| 378 | m_kb_ruslat = data; |
| 423 | 379 | break; |
| 424 | 380 | default: |
| 425 | 381 | break; |
| 426 | 382 | } |
| 427 | | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) |
| 383 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0 && !offset) |
| 428 | 384 | { |
| 429 | 385 | DBG_LOG(2,"flag",("%sset %d\n", data?"":"re", offset)); |
| 430 | 386 | } |
| r29635 | r29636 | |
| 449 | 405 | AM_RANGE(011, 011) AM_READ(kb_r) // 09h R: keyboard data [6.1.5.2] |
| 450 | 406 | AM_RANGE(012, 012) AM_READ(kb_s_red_r) // 0Ah I: keyboard mode "RED" [6.1.5.2] |
| 451 | 407 | AM_RANGE(013, 013) AM_READ(kb_ready_r) // 0Bh R: keyboard data ready [6.1.5.2] |
| 452 | | AM_RANGE(014, 014) AM_READ(kb_s_sdv_r) AM_WRITENOP // 0Ch W: serial port speed [6.1.3.1], R: keyboard mode "SDV" [6.1.5.2] |
| 408 | AM_RANGE(014, 014) AM_READ(kb_s_sdv_r) AM_WRITE(serial_speed_w) // 0Ch W: serial port speed [6.1.3.1], R: keyboard mode "SDV" [6.1.5.2] |
| 453 | 409 | AM_RANGE(015, 015) AM_READ(kb_s_dk_r) AM_WRITE(kb_ready_w) // 0Dh I: keyboard mode "DK" [6.1.5.2] |
| 454 | 410 | AM_RANGE(016, 016) AM_READ(kb_s_dupl_r) // 0Eh I: keyboard mode "DUPL" [6.1.5.2] |
| 455 | 411 | AM_RANGE(017, 017) AM_READ(kb_s_lin_r) // 0Fh I: keyboard mode "LIN" [6.1.5.2] |
| r29635 | r29636 | |
| 460 | 416 | /* Input ports */ |
| 461 | 417 | static INPUT_PORTS_START( ie15 ) |
| 462 | 418 | PORT_START("keyboard") |
| 463 | | PORT_DIPNAME(0x01, 0x00, "RED mode") |
| 464 | | PORT_DIPSETTING(0x00, "Off" ) |
| 465 | | PORT_DIPSETTING(0x01, "On" ) |
| 466 | | PORT_DIPNAME(0x02, 0x00, "SDV mode (Setup)") |
| 467 | | PORT_DIPSETTING(0x00, "Off" ) |
| 468 | | PORT_DIPSETTING(0x02, "On" ) |
| 469 | | PORT_DIPNAME(0x08, 0x00, "DUPL mode") |
| 470 | | PORT_DIPSETTING(0x00, "Off" ) |
| 471 | | PORT_DIPSETTING(0x08, "On" ) |
| 472 | | PORT_DIPNAME(0x10, 0x00, "LIN mode") |
| 473 | | PORT_DIPSETTING(0x00, "Off" ) |
| 474 | | PORT_DIPSETTING(0x10, "On" ) |
| 475 | | PORT_DIPNAME(0x20, 0x00, "digital loopback") |
| 476 | | PORT_DIPSETTING(0x00, "Off" ) |
| 477 | | PORT_DIPSETTING(0x20, "On" ) |
| 419 | PORT_DIPNAME(IE_KB_RED, IE_KB_RED, "RED (Interpret controls)") |
| 420 | PORT_DIPSETTING(0x00, "Off") |
| 421 | PORT_DIPSETTING(IE_KB_RED, "On") |
| 422 | PORT_DIPNAME(IE_KB_DUP, IE_KB_DUP, "DUP (Full duplex)") |
| 423 | PORT_DIPSETTING(0x00, "Off") |
| 424 | PORT_DIPSETTING(IE_KB_DUP, "On") |
| 425 | PORT_DIPNAME(IE_KB_LIN, IE_KB_LIN, "LIN (Online)") |
| 426 | PORT_DIPSETTING(0x00, "Off") |
| 427 | PORT_DIPSETTING(IE_KB_LIN, "On") |
| 478 | 428 | INPUT_PORTS_END |
| 479 | 429 | |
| 480 | | WRITE8_MEMBER( ie15_state::kbd_put ) |
| 430 | WRITE16_MEMBER( ie15_state::kbd_put ) |
| 481 | 431 | { |
| 482 | | DBG_LOG(2,"keyboard",("W %02X<-%02X '%c' %c\n", m_kb_data, data, data < 0x20?' ':data, m_kb_flag?'n':'y')); |
| 483 | | if (m_kb_flag == IE_1) { |
| 484 | | m_kb_data = data; |
| 432 | DBG_LOG(2,"keyboard",("W %02X<-%02X '%c' %02X (%c)\n", m_kb_data, data, 'x' /* data < 0x20 ? ' ' : (data & 255) */, |
| 433 | m_kb_flag, m_kb_flag ? 'n' : 'y')); |
| 434 | m_kb_control = (data >> 8) & 255; |
| 435 | // send new key only when firmware has processed previous one |
| 436 | if (m_kb_flag == IE_TRUE) { |
| 437 | m_kb_data = data & 255; |
| 485 | 438 | m_kb_flag = 0; |
| 486 | 439 | } |
| 487 | 440 | } |
| 488 | 441 | |
| 442 | static IE15_KEYBOARD_INTERFACE( keyboard_intf ) |
| 443 | { |
| 444 | DEVCB_DRIVER_MEMBER16(ie15_state, kbd_put) |
| 445 | }; |
| 446 | |
| 489 | 447 | void ie15_state::machine_reset() |
| 490 | 448 | { |
| 491 | | m_ruslat = m_beep = m_statusline = m_cursor = m_video = m_kb_data = m_kb_flag0 = 0; |
| 492 | | m_serial_tx_data = m_serial_tx_bits = m_serial_rx_buffer = m_serial_rx_data = m_serial_rx_bits = 0; |
| 493 | | m_kb_flag = IE_1; |
| 449 | memset(&m_video, 0, sizeof(m_video)); |
| 450 | m_kb_ruslat = m_long_beep = m_kb_control = m_kb_data = m_kb_flag0 = 0; |
| 451 | m_kb_flag = IE_TRUE; |
| 494 | 452 | |
| 495 | 453 | machine().device<beep_device>("beeper")->set_frequency(2400); |
| 496 | 454 | machine().device<beep_device>("beeper")->set_state(0); |
| 497 | 455 | |
| 498 | | m_serial_tx_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ie15_state::serial_tx_callback),this)); |
| 456 | m_serial_tx_ready = m_serial_rx_ready = IE_TRUE; |
| 457 | set_data_frame(1 /* start bits */, 8 /* data bits */, PARITY_NONE, STOP_BITS_1); |
| 458 | // device supports rates from 150 to 9600 baud but null_modem has hardcoded 9600 |
| 459 | set_tra_rate(9600); |
| 460 | set_rcv_rate(9600); |
| 499 | 461 | } |
| 500 | 462 | |
| 501 | 463 | void ie15_state::video_start() |
| 502 | 464 | { |
| 503 | | m_p_chargen = machine().root_device().memregion("chargen")->base(); |
| 465 | m_p_chargen = memregion("chargen")->base(); |
| 504 | 466 | m_p_videoram = memregion("video")->base(); |
| 505 | | m_videoptr = m_videoptr_2 = m_latch = 0; |
| 467 | m_video.ptr1 = m_video.ptr2 = m_latch = 0; |
| 506 | 468 | |
| 469 | m_tmpclip = rectangle(0, IE15_DISP_HORZ-1, 0, IE15_DISP_VERT-1); |
| 507 | 470 | m_tmpbmp.allocate(IE15_DISP_HORZ, IE15_DISP_VERT); |
| 471 | m_offbmp.allocate(IE15_DISP_HORZ, 1); |
| 472 | if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { |
| 473 | m_offbmp.fill(0); |
| 474 | } |
| 508 | 475 | } |
| 509 | 476 | |
| 510 | | UINT32 ie15_state::draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline, UINT8 y) |
| 477 | /* |
| 478 | Usable raster is 800 x 275 pixels (80 x 25 characters). 24 lines are |
| 479 | available to the user and 25th (topmost) line is the status line. |
| 480 | Status line, if enabled, displays current serial port speed, 16 setup |
| 481 | bits, and clock. There is no NVRAM, so setup bits are always 0 after |
| 482 | reset and clock starts counting at 0 XXX. |
| 483 | |
| 484 | No character attributes are available, but in 'display controls' mode |
| 485 | control characters stored in memory are shown as blinking chars. |
| 486 | |
| 487 | Character cell is 10 x 11; character generator provides 7 x 8 of that. |
| 488 | 3 extra horizontal pixels are always blank. Blinking cursor may be |
| 489 | displayed on 3 extra scan lines. |
| 490 | |
| 491 | On each scan line, video board draws 80 characters from any location |
| 492 | in video memory; this is used by firmware to provide instant scroll |
| 493 | and cursor, which is a character with code 0x7F stored in XXX. |
| 494 | |
| 495 | Video board output is controlled by |
| 496 | - control flag 0 "disable video": 0 == disable |
| 497 | - control flag 1 "cursor": 0 == if this scan line is one of extra 3, |
| 498 | enable video every 5 frames. |
| 499 | - control flag 3 "status line": 0 == current scan line is part of status line |
| 500 | - keyboard mode 'RED' ('display controls'): if character code is |
| 501 | less than 0x20 and RED is set, enable video every 5 frames; if RED is |
| 502 | unset, disable video. |
| 503 | |
| 504 | XXX 'dotted look' is caused by strobe at 2x pixel clock -- use HLSL for this. |
| 505 | */ |
| 506 | |
| 507 | UINT32 ie15_state::draw_scanline(UINT16 *p, UINT16 offset, UINT8 scanline) |
| 511 | 508 | { |
| 512 | | UINT8 gfx,fg,bg,ra,blink,red; |
| 513 | | UINT16 x,chr; |
| 509 | UINT8 gfx, fg, bg, ra, blink, red; |
| 510 | UINT16 x, chr; |
| 514 | 511 | |
| 515 | 512 | bg = 0; fg = 1; ra = scanline % 8; |
| 516 | | blink = (machine().first_screen()->frame_number() % 10) >= 5; |
| 517 | | red = m_io_keyboard->read() & 0x01; |
| 513 | blink = (machine().first_screen()->frame_number() % 10) > 4; |
| 514 | red = m_io_keyboard->read() & IE_KB_RED; |
| 518 | 515 | |
| 519 | | DBG_LOG(2,"draw_scanline", |
| 520 | | ("addr %03x row %d-%d video %d\n", offset, y, scanline, m_video)); |
| 521 | | |
| 522 | 516 | for (x = offset; x < offset + 80; x++) |
| 523 | 517 | { |
| 524 | | if (m_video) { |
| 525 | | chr = m_p_videoram[x] << 3; |
| 526 | | gfx = m_p_chargen[chr | ra]; |
| 518 | chr = m_p_videoram[x] << 3; |
| 519 | gfx = m_p_chargen[chr | ra]; |
| 527 | 520 | |
| 528 | | /* |
| 529 | | Cursor is a character with only 3 scan lines, and is |
| 530 | | not shown if flag 1 is not active on this scan line. |
| 531 | | It always blinks if shown. |
| 532 | | |
| 533 | | Control characters blink if RED mode is on and they |
| 534 | | are not on status line; else they are blanked out. |
| 535 | | */ |
| 536 | | |
| 537 | | if (scanline > 7 && (!m_cursor || blink)) |
| 521 | if (scanline > 7 && (!m_video.cursor || blink)) |
| 522 | gfx = 0; |
| 523 | else if (chr < (0x20<<3)) { |
| 524 | if (red && blink && m_video.line25) |
| 525 | gfx = m_p_chargen[chr | 0x200 | ra]; |
| 526 | else |
| 538 | 527 | gfx = 0; |
| 539 | | if (chr < (0x20<<3)) { |
| 540 | | if (!y || !red || blink) |
| 541 | | gfx = 0; |
| 542 | | else |
| 543 | | gfx = m_p_chargen[chr | 0x200 | ra]; |
| 544 | | } |
| 545 | | /* Display a scanline of a character */ |
| 546 | | *p++ = BIT(gfx, 7) ? fg : bg; |
| 547 | | *p++ = BIT(gfx, 6) ? fg : bg; |
| 548 | | *p++ = BIT(gfx, 5) ? fg : bg; |
| 549 | | *p++ = BIT(gfx, 4) ? fg : bg; |
| 550 | | *p++ = BIT(gfx, 3) ? fg : bg; |
| 551 | | *p++ = BIT(gfx, 2) ? fg : bg; |
| 552 | | *p++ = BIT(gfx, 1) ? fg : bg; |
| 553 | | *p++ = bg; |
| 554 | | *p++ = bg; |
| 555 | | *p++ = bg; |
| 556 | | } else { |
| 557 | | *p++ = bg; |
| 558 | | *p++ = bg; |
| 559 | | *p++ = bg; |
| 560 | | *p++ = bg; |
| 561 | | *p++ = bg; |
| 562 | | *p++ = bg; |
| 563 | | *p++ = bg; |
| 564 | | *p++ = bg; |
| 565 | | *p++ = bg; |
| 566 | | *p++ = bg; |
| 567 | 528 | } |
| 529 | |
| 530 | *p++ = BIT(gfx, 7) ? fg : bg; |
| 531 | *p++ = BIT(gfx, 6) ? fg : bg; |
| 532 | *p++ = BIT(gfx, 5) ? fg : bg; |
| 533 | *p++ = BIT(gfx, 4) ? fg : bg; |
| 534 | *p++ = BIT(gfx, 3) ? fg : bg; |
| 535 | *p++ = BIT(gfx, 2) ? fg : bg; |
| 536 | *p++ = BIT(gfx, 1) ? fg : bg; |
| 537 | *p++ = bg; |
| 538 | *p++ = bg; |
| 539 | *p++ = bg; |
| 568 | 540 | } |
| 569 | 541 | return 0; |
| 570 | 542 | } |
| 571 | 543 | |
| 544 | void ie15_state::update_leds() |
| 545 | { |
| 546 | UINT8 data = m_io_keyboard->read(); |
| 547 | output_set_value("lat_led", m_kb_ruslat ^ 1); |
| 548 | output_set_value("nr_led", BIT(m_kb_control, IE_KB_NR_BIT) ^ 1); |
| 549 | output_set_value("pch_led", BIT(data, IE_KB_PCH_BIT) ^ 1); |
| 550 | output_set_value("dup_led", BIT(data, IE_KB_DUP_BIT) ^ 1); |
| 551 | output_set_value("lin_led", BIT(data, IE_KB_LIN_BIT) ^ 1); |
| 552 | output_set_value("red_led", BIT(data, IE_KB_RED_BIT) ^ 1); |
| 553 | output_set_value("sdv_led", BIT(m_kb_control, IE_KB_SDV_BIT) ^ 1); |
| 554 | output_set_value("prd_led", 1); // XXX |
| 555 | } |
| 556 | |
| 557 | /* |
| 558 | VBlank is active for 3 topmost on-screen rows and 1 at the bottom; however, control flag 3 overrides VBlank, |
| 559 | allowing status line to be switched on and off. |
| 560 | */ |
| 572 | 561 | TIMER_DEVICE_CALLBACK_MEMBER(ie15_state::scanline_callback) |
| 573 | 562 | { |
| 574 | 563 | UINT16 y = machine().first_screen()->vpos(); |
| 575 | | // DBG_LOG(2,"scanline", |
| 576 | | // ("addr %03x frame %lld x %04d y %03d\n", m_videoptr_2, machine().first_screen()->frame_number(), machine().first_screen()->hpos(), y)); |
| 577 | | if (y>=IE15_VERT_START) { |
| 578 | | y -= IE15_VERT_START; |
| 579 | | if (y < IE15_DISP_VERT) { |
| 580 | | draw_scanline(&m_tmpbmp.pix16(y), m_videoptr_2, y%11, y/11); |
| 581 | | } |
| 564 | |
| 565 | DBG_LOG(3,"scanline_cb", |
| 566 | ("addr %03x frame %" I64FMT "d x %.4d y %.3d row %.2d e:c:s %d:%d:%d\n", |
| 567 | m_video.ptr2, machine().first_screen()->frame_number(), machine().first_screen()->hpos(), y, |
| 568 | y%11, m_video.enable, m_video.cursor, m_video.line25)); |
| 569 | |
| 570 | if (y < IE15_VERT_START) return; |
| 571 | y -= IE15_VERT_START; |
| 572 | if (y >= IE15_DISP_VERT) return; |
| 573 | |
| 574 | if (!m_video.enable || (y < IE15_STATUSLINE && m_video.line25)) { |
| 575 | copybitmap( m_tmpbmp, m_offbmp, 0, 0, 0, y, m_tmpclip ); |
| 576 | } else { |
| 577 | draw_scanline( &m_tmpbmp.pix16(y), m_video.ptr2, y%11 ); |
| 582 | 578 | } |
| 583 | 579 | } |
| 584 | 580 | |
| 585 | 581 | UINT32 ie15_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) |
| 586 | 582 | { |
| 587 | | copybitmap( bitmap, m_tmpbmp, 0, 0, IE15_HORZ_START, IE15_VERT_START, cliprect ); |
| 583 | update_leds(); |
| 584 | copybitmap(bitmap, m_tmpbmp, 0, 0, IE15_HORZ_START, IE15_VERT_START, cliprect); |
| 588 | 585 | return 0; |
| 589 | 586 | } |
| 590 | 587 | |
| r29635 | r29636 | |
| 604 | 601 | }; |
| 605 | 602 | |
| 606 | 603 | static GFXDECODE_START( ie15 ) |
| 607 | | GFXDECODE_ENTRY( "chargen", 0x0000, ie15_charlayout, 0, 1 ) |
| 604 | GFXDECODE_ENTRY("chargen", 0x0000, ie15_charlayout, 0, 1) |
| 608 | 605 | GFXDECODE_END |
| 609 | 606 | |
| 610 | | PALETTE_INIT_MEMBER(ie15_state, ie15) |
| 611 | | { |
| 612 | | palette.set_pen_color(0, rgb_t::black); // black |
| 613 | | palette.set_pen_color(1, 0x00, 0xc0, 0x00); // green |
| 614 | | } |
| 615 | | |
| 616 | 607 | static MACHINE_CONFIG_START( ie15, ie15_state ) |
| 617 | 608 | /* Basic machine hardware */ |
| 618 | 609 | MCFG_CPU_ADD("maincpu", IE15, XTAL_30_8MHz / 10) |
| r29635 | r29636 | |
| 630 | 621 | MCFG_SCREEN_PALETTE("palette") |
| 631 | 622 | |
| 632 | 623 | MCFG_GFXDECODE_ADD("gfxdecode", "palette", ie15) |
| 633 | | MCFG_PALETTE_ADD("palette", 2) |
| 634 | | MCFG_PALETTE_INIT_OWNER(ie15_state, ie15) |
| 624 | MCFG_PALETTE_ADD_MONOCHROME_GREEN("palette") |
| 635 | 625 | |
| 626 | MCFG_DEFAULT_LAYOUT( layout_ie15 ) |
| 627 | |
| 636 | 628 | /* Devices */ |
| 637 | | MCFG_DEVICE_ADD(KEYBOARD_TAG, GENERIC_KEYBOARD, 0) |
| 638 | | MCFG_GENERIC_KEYBOARD_CB(WRITE8(ie15_state, kbd_put)) |
| 639 | | MCFG_BITBANGER_ADD(BITBANGER_TAG, ie15_state::ie15_bitbanger_config) |
| 629 | MCFG_IE15_KEYBOARD_ADD("keyboard", keyboard_intf) |
| 640 | 630 | |
| 631 | MCFG_RS232_PORT_ADD("rs232", default_rs232_devices, NULL) |
| 632 | MCFG_RS232_RXD_HANDLER(WRITELINE(ie15_state, serial_rx_callback)) |
| 633 | MCFG_DEVICE_MODIFY("rs232") |
| 634 | MCFG_SLOT_DEFAULT_OPTION("null_modem") |
| 635 | |
| 641 | 636 | MCFG_SPEAKER_STANDARD_MONO("mono") |
| 642 | 637 | MCFG_SOUND_ADD("beeper", BEEP, 0) |
| 643 | 638 | MCFG_SOUND_ROUTE(ALL_OUTPUTS,"mono",0.15) |
trunk/src/mess/machine/ie15_kbd.c
| r0 | r29636 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | 15WWW-97-006 keyboard, normally used with 15IE-00-013. |
| 4 | Irisha can use it too. |
| 5 | |
| 6 | ***************************************************************************/ |
| 7 | |
| 8 | #include "machine/ie15_kbd.h" |
| 9 | |
| 10 | /*************************************************************************** |
| 11 | IMPLEMENTATION |
| 12 | ***************************************************************************/ |
| 13 | |
| 14 | |
| 15 | ie15_keyboard_device::ie15_keyboard_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) |
| 16 | : device_t(mconfig, type, name, tag, owner, clock, shortname, source) |
| 17 | , m_io_kbd0(*this, "TERM_LINE0") |
| 18 | , m_io_kbd1(*this, "TERM_LINE1") |
| 19 | , m_io_kbd2(*this, "TERM_LINE2") |
| 20 | , m_io_kbd3(*this, "TERM_LINE3") |
| 21 | , m_io_kbdc(*this, "TERM_LINEC") |
| 22 | { |
| 23 | } |
| 24 | |
| 25 | ie15_keyboard_device::ie15_keyboard_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 26 | : device_t(mconfig, IE15_KEYBOARD, "15WWW-97-006 Keyboard", tag, owner, clock, "ie15_keyboard", __FILE__) |
| 27 | , m_io_kbd0(*this, "TERM_LINE0") |
| 28 | , m_io_kbd1(*this, "TERM_LINE1") |
| 29 | , m_io_kbd2(*this, "TERM_LINE2") |
| 30 | , m_io_kbd3(*this, "TERM_LINE3") |
| 31 | , m_io_kbdc(*this, "TERM_LINEC") |
| 32 | { |
| 33 | } |
| 34 | |
| 35 | UINT8 ie15_keyboard_device::row_number(UINT32 code) |
| 36 | { |
| 37 | if BIT(code,0) return 0; |
| 38 | if BIT(code,1) return 1; |
| 39 | if BIT(code,2) return 2; |
| 40 | if BIT(code,3) return 3; |
| 41 | if BIT(code,4) return 4; |
| 42 | if BIT(code,5) return 5; |
| 43 | if BIT(code,6) return 6; |
| 44 | if BIT(code,7) return 7; |
| 45 | if BIT(code,8) return 8; |
| 46 | if BIT(code,9) return 9; |
| 47 | if BIT(code,10) return 10; |
| 48 | if BIT(code,11) return 11; |
| 49 | if BIT(code,12) return 12; |
| 50 | if BIT(code,13) return 13; |
| 51 | if BIT(code,14) return 14; |
| 52 | if BIT(code,15) return 15; |
| 53 | return 0; |
| 54 | } |
| 55 | |
| 56 | UINT16 ie15_keyboard_device::keyboard_handler(UINT16 last_code, UINT8 *scan_line) |
| 57 | { |
| 58 | int i; |
| 59 | UINT32 code = 0; |
| 60 | UINT16 key_code = 0; |
| 61 | UINT16 retVal = 0; |
| 62 | UINT8 ctrl = BIT(m_io_kbdc->read(), 0); |
| 63 | UINT8 shift = BIT(m_io_kbdc->read(), 1); |
| 64 | |
| 65 | i = *scan_line; |
| 66 | { |
| 67 | if (i == 0) code = m_io_kbd0->read(); |
| 68 | else |
| 69 | if (i == 1) code = m_io_kbd1->read(); |
| 70 | else |
| 71 | if (i == 2) code = m_io_kbd2->read(); |
| 72 | else |
| 73 | if (i == 3) code = m_io_kbd3->read(); |
| 74 | |
| 75 | if (code != 0) |
| 76 | { |
| 77 | if (!m_ruslat) |
| 78 | i += 4; |
| 79 | if (shift) |
| 80 | i += 8; |
| 81 | i <<= 4; |
| 82 | if (code < 0x10000) { |
| 83 | key_code = m_rom [i + row_number(code)]; |
| 84 | } else { |
| 85 | key_code = m_rom [i + row_number(code >> 16)*2 + 256]; |
| 86 | } |
| 87 | if (ctrl) { |
| 88 | key_code &= 0x1f; |
| 89 | } |
| 90 | retVal = key_code; |
| 91 | } else { |
| 92 | *scan_line += 1; |
| 93 | if (*scan_line==4) { |
| 94 | *scan_line = 0; |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | // setup mode toggle |
| 100 | if (BIT(m_io_kbdc->read(), 2)) { |
| 101 | retVal |= (IE_KB_SDV << 8); |
| 102 | } |
| 103 | // aux keyboard flag |
| 104 | if (code & 0xe0e000) { |
| 105 | retVal |= (IE_KB_DK << 8); |
| 106 | } |
| 107 | // shift |
| 108 | if (shift) { |
| 109 | retVal |= (IE_KB_NR << 8); |
| 110 | } |
| 111 | // SI/SO handling |
| 112 | if ((key_code & 127) == IE_KB_SI) { |
| 113 | m_ruslat = 0; |
| 114 | } |
| 115 | if ((key_code & 127) == IE_KB_SO) { |
| 116 | m_ruslat = 1; |
| 117 | } |
| 118 | |
| 119 | return retVal; |
| 120 | } |
| 121 | |
| 122 | void ie15_keyboard_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 123 | { |
| 124 | UINT16 new_code; |
| 125 | new_code = keyboard_handler(m_last_code, &m_scan_line); |
| 126 | if ((m_last_code != new_code) /* && (new_code) */) |
| 127 | send_key(new_code); |
| 128 | m_last_code = new_code; |
| 129 | } |
| 130 | |
| 131 | /*************************************************************************** |
| 132 | VIDEO HARDWARE |
| 133 | ***************************************************************************/ |
| 134 | |
| 135 | ROM_START( ie15_keyboard ) |
| 136 | ROM_REGION( 0x200, "ie15kbd", 0 ) |
| 137 | ROM_LOAD( "15bbb.rt5", 0x000, 0x200, CRC(e6a4226e) SHA1(0ee46f5be1b01fa917a6d483bb51463106ae441f) ) |
| 138 | ROM_END |
| 139 | |
| 140 | const rom_entry *ie15_keyboard_device::device_rom_region() const |
| 141 | { |
| 142 | return ROM_NAME( ie15_keyboard ); |
| 143 | } |
| 144 | |
| 145 | static MACHINE_CONFIG_FRAGMENT( ie15_keyboard ) |
| 146 | MACHINE_CONFIG_END |
| 147 | |
| 148 | machine_config_constructor ie15_keyboard_device::device_mconfig_additions() const |
| 149 | { |
| 150 | return MACHINE_CONFIG_NAME(ie15_keyboard); |
| 151 | } |
| 152 | |
| 153 | void ie15_keyboard_device::device_start() |
| 154 | { |
| 155 | m_keyboard_func.resolve(m_keyboard_cb, *this); |
| 156 | m_timer = timer_alloc(); |
| 157 | m_rom = (UINT8*)memregion("ie15kbd")->base(); |
| 158 | } |
| 159 | |
| 160 | void ie15_keyboard_device::device_config_complete() |
| 161 | { |
| 162 | const ie15_keyboard_interface *intf = reinterpret_cast<const ie15_keyboard_interface *>(static_config()); |
| 163 | if(intf != NULL) |
| 164 | { |
| 165 | *static_cast<ie15_keyboard_interface *>(this) = *intf; |
| 166 | } |
| 167 | else |
| 168 | { |
| 169 | memset(&m_keyboard_cb, 0, sizeof(m_keyboard_cb)); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | void ie15_keyboard_device::device_reset() |
| 174 | { |
| 175 | m_last_code = 0; |
| 176 | m_scan_line = 0; |
| 177 | m_ruslat = 0; |
| 178 | m_timer->adjust(attotime::from_hz(10000), 0, attotime::from_hz(10000)); |
| 179 | } |
| 180 | |
| 181 | /* |
| 182 | Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y10 Y11 Y12 Y13 Y14 Y15 Y16 Y17 Y18 Y19 Y20 Y21 Y22 Y23 Y24 |
| 183 | -- |
| 184 | ;+ 1! 2" 3# 4$ 5% 6& 7' 8( 9) 0 -= 7 8 9 ??? ?? ??? ??? ??? f1 f2 f3 |
| 185 | ?J ?C ?U ?K ?E ?N ?G ?[ ?] ?Z ?H :* 4 5 6 ?? ?? ??1 ?1 ??2 f4 f5 f6 |
| 186 | ?F ?Y ?W ?A ?P ?R ?O ?L ?D ?V ?\ .> ?? 1 2 3 ??? ??? ??? f7 f8 f9 |
| 187 | ?Q ?^ ?S ?M ?I ?T ?X ?B ?@ ,< /? _ SPC 0 , fA fB fC |
| 188 | |
| 189 | rom: |
| 190 | |
| 191 | 00000000 3b 31 32 33 34 35 36 37 38 39 30 2d 00 37 38 39 |;1234567890-.789| rus + upper |
| 192 | 00000010 6a 63 75 6b 65 6e 67 7b 7d 7a 68 3a 00 34 35 36 |jcukeng{}zh:.456| |
| 193 | 00000020 66 79 77 61 70 72 6f 6c 64 76 7c 2e 7f 31 32 33 |fywaproldv|..123| |
| 194 | 00000030 71 7e 73 6d 69 74 78 62 60 2c 2f 7f 20 30 30 2c |q~smitxb`,/. 00,| |
| 195 | |
| 196 | 00000040 3b 31 32 33 34 35 36 37 38 39 30 2d 00 37 38 39 |;1234567890-.789| lat + upper |
| 197 | 00000050 4a 43 55 4b 45 4e 47 5b 5d 5a 48 3a 00 34 35 36 |JCUKENG[]ZH:.456| |
| 198 | 00000060 46 59 57 41 50 52 4f 4c 44 56 5c 2e 7f 31 32 33 |FYWAPROLDV\..123| |
| 199 | 00000070 51 5e 53 4d 49 54 58 42 40 2c 2f 5f 20 30 30 2c |Q^SMITXB@,/_ 00,| |
| 200 | |
| 201 | 00000080 2b 21 22 23 24 25 26 27 28 29 30 3d 00 37 38 39 |+!"#$%&'()0=.789| rus + lower |
| 202 | 00000090 4a 43 55 4b 45 4e 47 5b 5d 5a 48 2a 00 34 35 36 |JCUKENG[]ZH*.456| |
| 203 | 000000a0 46 59 57 41 50 52 4f 4c 44 56 5c 3e 7f 31 32 33 |FYWAPROLDV\>.123| |
| 204 | 000000b0 51 5e 53 4d 49 54 58 42 40 3c 3f 5f 20 30 30 2c |Q^SMITXB@<?_ 00,| |
| 205 | |
| 206 | 000000c0 2b 21 22 23 24 25 26 27 28 29 30 3d 00 37 38 39 |+!"#$%&'()0=.789| lat + lower |
| 207 | 000000d0 6a 63 75 6b 65 6e 67 7b 7d 7a 68 2a 00 34 35 36 |jcukeng{}zh*.456| |
| 208 | 000000e0 66 79 77 61 70 72 6f 6c 64 76 7c 3e 7f 31 32 33 |fywaproldv|>.123| |
| 209 | 000000f0 71 7e 73 6d 69 74 78 62 60 3c 3f 7f 20 30 30 2c |q~smitxb`<?. 00,| |
| 210 | |
| 211 | 00000100 18 18 09 09 0c 0c 1f 1f 0b 0b 15 15 1c 1c 0d 0d |................| |
| 212 | 00000110 0a 0a 0d 0d 10 10 01 01 1b 1b 1a 1a 08 08 19 19 |................| |
| 213 | 00000120 7f 7f 7f 7f 1e 1e 11 11 06 06 14 14 1d 1d 13 13 |................| |
| 214 | 00000130 0e 0e 0f 0f 7f 7f 7f 7f 7f 7f 16 16 02 02 12 12 |................| |
| 215 | */ |
| 216 | |
| 217 | static INPUT_PORTS_START( ie15_keyboard ) |
| 218 | PORT_START("TERM_LINE0") |
| 219 | PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COLON) PORT_CHAR(';') PORT_CHAR('+') |
| 220 | PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_1) PORT_CHAR('1') PORT_CHAR('!') |
| 221 | PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_2) PORT_CHAR('2') PORT_CHAR('"') |
| 222 | PORT_BIT(0x000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_3) PORT_CHAR('3') PORT_CHAR('#') |
| 223 | PORT_BIT(0x000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_4) PORT_CHAR('4') PORT_CHAR('$') |
| 224 | PORT_BIT(0x000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_5) PORT_CHAR('5') PORT_CHAR('%') |
| 225 | PORT_BIT(0x000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_6) PORT_CHAR('6') PORT_CHAR('&') |
| 226 | PORT_BIT(0x000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_7) PORT_CHAR('7') PORT_CHAR('\'') |
| 227 | PORT_BIT(0x000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_8) PORT_CHAR('8') PORT_CHAR('(') |
| 228 | PORT_BIT(0x000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_9) PORT_CHAR('9') PORT_CHAR(')') |
| 229 | PORT_BIT(0x000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_0) PORT_CHAR('0') |
| 230 | PORT_BIT(0x000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-') // PORT_CHAR('=') |
| 231 | PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 232 | PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 7") PORT_CODE(KEYCODE_7_PAD) |
| 233 | PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 8") PORT_CODE(KEYCODE_8_PAD) |
| 234 | PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 9") PORT_CODE(KEYCODE_9_PAD) |
| 235 | PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("TAB (VT)") PORT_CODE(KEYCODE_F11) PORT_CHAR(UCHAR_MAMEKEY(F11)) // Vertical Tab |
| 236 | PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TAB) PORT_CHAR(9) |
| 237 | PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SBR") PORT_CODE(KEYCODE_F1) PORT_CHAR(UCHAR_MAMEKEY(F1)) |
| 238 | PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("STR") PORT_CODE(KEYCODE_F2) PORT_CHAR(UCHAR_MAMEKEY(F2)) |
| 239 | PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("STS") PORT_CODE(KEYCODE_F3) PORT_CHAR(UCHAR_MAMEKEY(F3)) |
| 240 | PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER_PAD) PORT_CHAR(UCHAR_MAMEKEY(ENTER_PAD)) // 'f1' |
| 241 | PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Up") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP)) // 'f2' |
| 242 | PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Home") PORT_CODE(KEYCODE_HOME) PORT_CHAR(UCHAR_MAMEKEY(HOME)) // 'f3' |
| 243 | |
| 244 | PORT_START("TERM_LINE1") |
| 245 | PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_J) PORT_CHAR('j') PORT_CHAR('J') |
| 246 | PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_C) PORT_CHAR('c') PORT_CHAR('C') |
| 247 | PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_U) PORT_CHAR('u') PORT_CHAR('U') |
| 248 | PORT_BIT(0x000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_K) PORT_CHAR('k') PORT_CHAR('K') |
| 249 | PORT_BIT(0x000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_E) PORT_CHAR('e') PORT_CHAR('E') |
| 250 | PORT_BIT(0x000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_N) PORT_CHAR('n') PORT_CHAR('N') |
| 251 | PORT_BIT(0x000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_G) PORT_CHAR('g') PORT_CHAR('G') |
| 252 | PORT_BIT(0x000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('[') PORT_CHAR('{') |
| 253 | PORT_BIT(0x000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR(']') PORT_CHAR('}') |
| 254 | PORT_BIT(0x000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Z) PORT_CHAR('z') PORT_CHAR('Z') |
| 255 | PORT_BIT(0x000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_H) PORT_CHAR('h') PORT_CHAR('H') |
| 256 | PORT_BIT(0x000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_QUOTE) PORT_CHAR(':') PORT_CHAR('*') |
| 257 | PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 258 | PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 4") PORT_CODE(KEYCODE_4_PAD) |
| 259 | PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 5") PORT_CODE(KEYCODE_5_PAD) |
| 260 | PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 6") PORT_CODE(KEYCODE_6_PAD) |
| 261 | PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PS (LF)") PORT_CODE(KEYCODE_F12) PORT_CHAR(UCHAR_MAMEKEY(F12)) // Line Feed |
| 262 | PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_ENTER) PORT_CHAR(13) |
| 263 | PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("AR1") PORT_CODE(KEYCODE_F4) PORT_CHAR(UCHAR_MAMEKEY(F4)) |
| 264 | PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("S1") PORT_CODE(KEYCODE_F5) PORT_CHAR(UCHAR_MAMEKEY(F5)) |
| 265 | PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("AR2 (Escape)") PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 266 | PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Left") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT)) |
| 267 | PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Begin") PORT_CODE(KEYCODE_END) PORT_CHAR(UCHAR_MAMEKEY(END)) |
| 268 | PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Right") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT)) |
| 269 | |
| 270 | PORT_START("TERM_LINE2") |
| 271 | PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_F) PORT_CHAR('f') PORT_CHAR('F') |
| 272 | PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Y) PORT_CHAR('y') PORT_CHAR('Y') |
| 273 | PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_W) PORT_CHAR('w') PORT_CHAR('W') |
| 274 | PORT_BIT(0x000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_A) PORT_CHAR('a') PORT_CHAR('A') |
| 275 | PORT_BIT(0x000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_P) PORT_CHAR('p') PORT_CHAR('P') |
| 276 | PORT_BIT(0x000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_R) PORT_CHAR('r') PORT_CHAR('R') |
| 277 | PORT_BIT(0x000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_O) PORT_CHAR('o') PORT_CHAR('O') |
| 278 | PORT_BIT(0x000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_L) PORT_CHAR('l') PORT_CHAR('L') |
| 279 | PORT_BIT(0x000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_D) PORT_CHAR('d') PORT_CHAR('D') |
| 280 | PORT_BIT(0x000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_V) PORT_CHAR('v') PORT_CHAR('V') |
| 281 | PORT_BIT(0x000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR('\\') PORT_CHAR('|') |
| 282 | PORT_BIT(0x000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') PORT_CHAR('>') |
| 283 | PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8) |
| 284 | PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 1") PORT_CODE(KEYCODE_1_PAD) |
| 285 | PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 2") PORT_CODE(KEYCODE_2_PAD) |
| 286 | PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 3") PORT_CODE(KEYCODE_3_PAD) |
| 287 | PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 288 | PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 289 | PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRD") PORT_CODE(KEYCODE_F6) PORT_CHAR(UCHAR_MAMEKEY(F6)) |
| 290 | PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRM") PORT_CODE(KEYCODE_F7) PORT_CHAR(UCHAR_MAMEKEY(F7)) |
| 291 | PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PRS") PORT_CODE(KEYCODE_F8) PORT_CHAR(UCHAR_MAMEKEY(F8)) |
| 292 | PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Del") PORT_CODE(KEYCODE_DEL) PORT_CHAR(UCHAR_MAMEKEY(DEL)) |
| 293 | PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Down") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN)) |
| 294 | PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ins") PORT_CODE(KEYCODE_INSERT) PORT_CHAR(UCHAR_MAMEKEY(INSERT)) |
| 295 | |
| 296 | PORT_START("TERM_LINE3") |
| 297 | PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_Q) PORT_CHAR('q') PORT_CHAR('Q') |
| 298 | PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_TILDE) PORT_CHAR('^') PORT_CHAR('~') |
| 299 | PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_S) PORT_CHAR('s') PORT_CHAR('S') |
| 300 | PORT_BIT(0x000008, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_M) PORT_CHAR('m') PORT_CHAR('M') |
| 301 | PORT_BIT(0x000010, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_I) PORT_CHAR('i') PORT_CHAR('I') |
| 302 | PORT_BIT(0x000020, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_T) PORT_CHAR('t') PORT_CHAR('T') |
| 303 | PORT_BIT(0x000040, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_X) PORT_CHAR('x') PORT_CHAR('X') |
| 304 | PORT_BIT(0x000080, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_B) PORT_CHAR('b') PORT_CHAR('B') |
| 305 | PORT_BIT(0x000100, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH_PAD) PORT_CHAR(UCHAR_MAMEKEY(SLASH_PAD)) // PORT_CHAR('`') PORT_CHAR('@') // XXX |
| 306 | PORT_BIT(0x000200, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') PORT_CHAR('<') |
| 307 | PORT_BIT(0x000400, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') PORT_CHAR('?') |
| 308 | PORT_BIT(0x000800, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('=') PORT_CHAR('_') // XXX |
| 309 | PORT_BIT(0x001000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ') |
| 310 | PORT_BIT(0x002000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad 0") PORT_CODE(KEYCODE_0_PAD) |
| 311 | PORT_BIT(0x004000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 312 | PORT_BIT(0x008000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Keypad ,") PORT_CODE(KEYCODE_DEL_PAD) PORT_CHAR(UCHAR_MAMEKEY(DEL_PAD)) |
| 313 | PORT_BIT(0x010000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Lat (SO)") PORT_CODE(KEYCODE_LALT) |
| 314 | PORT_BIT(0x020000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Rus (SI)") PORT_CODE(KEYCODE_RALT) |
| 315 | PORT_BIT(0x040000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 316 | PORT_BIT(0x080000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 317 | PORT_BIT(0x100000, IP_ACTIVE_HIGH, IPT_UNUSED) |
| 318 | PORT_BIT(0x200000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PgDn") PORT_CODE(KEYCODE_PGDN) PORT_CHAR(UCHAR_MAMEKEY(PGDN)) |
| 319 | PORT_BIT(0x400000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Next SetUp") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR(UCHAR_MAMEKEY(ASTERISK)) |
| 320 | PORT_BIT(0x800000, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("PgUp") PORT_CODE(KEYCODE_PGUP) PORT_CHAR(UCHAR_MAMEKEY(PGUP)) |
| 321 | |
| 322 | PORT_START("TERM_LINEC") |
| 323 | PORT_BIT(0x000001, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Ctrl") PORT_CODE(KEYCODE_LCONTROL) PORT_CODE(KEYCODE_RCONTROL) |
| 324 | // PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("Shift") PORT_CODE(KEYCODE_LSHIFT) PORT_CODE(KEYCODE_RSHIFT) PORT_CHAR(UCHAR_SHIFT_1) |
| 325 | PORT_BIT(0x000002, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SetUp") PORT_CODE(KEYCODE_RSHIFT) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(RSHIFT)) |
| 326 | PORT_BIT(0x000004, IP_ACTIVE_HIGH, IPT_KEYBOARD) PORT_NAME("SetUp") PORT_CODE(KEYCODE_PRTSCR) PORT_TOGGLE PORT_CHAR(UCHAR_MAMEKEY(PRTSCR)) |
| 327 | INPUT_PORTS_END |
| 328 | |
| 329 | ioport_constructor ie15_keyboard_device::device_input_ports() const |
| 330 | { |
| 331 | return INPUT_PORTS_NAME(ie15_keyboard); |
| 332 | } |
| 333 | |
| 334 | const device_type IE15_KEYBOARD = &device_creator<ie15_keyboard_device>; |