src/mess/machine/i8255a.c
| r0 | r5192 | |
| 1 | /********************************************************************** |
| 2 | |
| 3 | Intel 8255A Programmable Peripheral Interface emulation |
| 4 | |
| 5 | Copyright MESS Team. |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. |
| 7 | |
| 8 | **********************************************************************/ |
| 9 | |
| 10 | #include "driver.h" |
| 11 | #include "i8255a.h" |
| 12 | |
| 13 | /*************************************************************************** |
| 14 | PARAMETERS |
| 15 | ***************************************************************************/ |
| 16 | |
| 17 | #define LOG 0 |
| 18 | |
| 19 | enum |
| 20 | { |
| 21 | PORT_A = 0, |
| 22 | PORT_B, |
| 23 | PORT_C, |
| 24 | CONTROL |
| 25 | }; |
| 26 | |
| 27 | enum |
| 28 | { |
| 29 | GROUP_A = 0, |
| 30 | GROUP_B |
| 31 | }; |
| 32 | |
| 33 | enum |
| 34 | { |
| 35 | MODE_0 = 0, |
| 36 | MODE_1, |
| 37 | MODE_2 |
| 38 | }; |
| 39 | |
| 40 | enum |
| 41 | { |
| 42 | MODE_OUTPUT = 0, |
| 43 | MODE_INPUT, |
| 44 | }; |
| 45 | |
| 46 | #define I8255A_CONTROL_PORT_C_LOWER_INPUT 0x01 |
| 47 | #define I8255A_CONTROL_PORT_B_INPUT 0x02 |
| 48 | #define I8255A_CONTROL_GROUP_B_MODE_1 0x04 |
| 49 | #define I8255A_CONTROL_PORT_C_UPPER_INPUT 0x08 |
| 50 | #define I8255A_CONTROL_PORT_A_INPUT 0x10 |
| 51 | #define I8255A_CONTROL_GROUP_A_MODE_MASK 0x60 |
| 52 | #define I8255A_CONTROL_MODE_SET 0x80 |
| 53 | |
| 54 | /*************************************************************************** |
| 55 | TYPE DEFINITIONS |
| 56 | ***************************************************************************/ |
| 57 | |
| 58 | typedef struct _i8255a_t i8255a_t; |
| 59 | struct _i8255a_t |
| 60 | { |
| 61 | devcb_resolved_read8 in_port_func[3]; |
| 62 | devcb_resolved_write8 out_port_func[3]; |
| 63 | |
| 64 | UINT8 control; /* mode control word */ |
| 65 | UINT8 output[3]; /* output latch */ |
| 66 | UINT8 input[3]; /* input latch */ |
| 67 | |
| 68 | int ibf[2]; /* input buffer full flag */ |
| 69 | int obf[2]; /* output buffer full flag, negative logic */ |
| 70 | int inte[2]; /* interrupt enable */ |
| 71 | int inte1; /* interrupt enable */ |
| 72 | int inte2; /* interrupt enable */ |
| 73 | int intr[2]; /* interrupt */ |
| 74 | }; |
| 75 | |
| 76 | /*************************************************************************** |
| 77 | INLINE FUNCTIONS |
| 78 | ***************************************************************************/ |
| 79 | |
| 80 | INLINE i8255a_t *get_safe_token(const device_config *device) |
| 81 | { |
| 82 | assert(device != NULL); |
| 83 | assert(device->token != NULL); |
| 84 | |
| 85 | return (i8255a_t *)device->token; |
| 86 | } |
| 87 | |
| 88 | INLINE const i8255a_interface *get_interface(const device_config *device) |
| 89 | { |
| 90 | assert(device != NULL); |
| 91 | assert((device->type == I8255A)); |
| 92 | return (const i8255a_interface *) device->static_config; |
| 93 | } |
| 94 | |
| 95 | INLINE int group_mode(i8255a_t *i8255a, int group) |
| 96 | { |
| 97 | int mode = 0; |
| 98 | |
| 99 | switch (group) |
| 100 | { |
| 101 | case GROUP_A: |
| 102 | switch ((i8255a->control & I8255A_CONTROL_GROUP_A_MODE_MASK) >> 5) |
| 103 | { |
| 104 | case 0: mode = MODE_0; break; |
| 105 | case 1: mode = MODE_1; break; |
| 106 | case 2: case 3: mode = MODE_2; break; |
| 107 | } |
| 108 | break; |
| 109 | |
| 110 | case GROUP_B: |
| 111 | mode = i8255a->control & I8255A_CONTROL_GROUP_B_MODE_1 ? MODE_1 : MODE_0; |
| 112 | break; |
| 113 | } |
| 114 | |
| 115 | return mode; |
| 116 | } |
| 117 | |
| 118 | INLINE int port_mode(i8255a_t *i8255a, int port) |
| 119 | { |
| 120 | int mode = 0; |
| 121 | |
| 122 | switch (port) |
| 123 | { |
| 124 | case PORT_A: mode = i8255a->control & I8255A_CONTROL_PORT_A_INPUT ? MODE_INPUT : MODE_OUTPUT; break; |
| 125 | case PORT_B: mode = i8255a->control & I8255A_CONTROL_PORT_B_INPUT ? MODE_INPUT : MODE_OUTPUT; break; |
| 126 | } |
| 127 | |
| 128 | return mode; |
| 129 | } |
| 130 | |
| 131 | INLINE int port_c_lower_mode(i8255a_t *i8255a) |
| 132 | { |
| 133 | return i8255a->control & I8255A_CONTROL_PORT_C_LOWER_INPUT ? MODE_INPUT : MODE_OUTPUT; |
| 134 | } |
| 135 | |
| 136 | INLINE int port_c_upper_mode(i8255a_t *i8255a) |
| 137 | { |
| 138 | return i8255a->control & I8255A_CONTROL_PORT_C_UPPER_INPUT ? MODE_INPUT : MODE_OUTPUT; |
| 139 | } |
| 140 | |
| 141 | /*************************************************************************** |
| 142 | IMPLEMENTATION |
| 143 | ***************************************************************************/ |
| 144 | |
| 145 | static void output_pc(i8255a_t *i8255a) |
| 146 | { |
| 147 | UINT8 data = 0; |
| 148 | UINT8 mask = 0; |
| 149 | |
| 150 | /* PC upper */ |
| 151 | switch (group_mode(i8255a, GROUP_A)) |
| 152 | { |
| 153 | case MODE_0: |
| 154 | if (port_c_upper_mode(i8255a) == MODE_OUTPUT) |
| 155 | { |
| 156 | mask |= 0xf0; |
| 157 | } |
| 158 | break; |
| 159 | |
| 160 | case MODE_1: |
| 161 | data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; |
| 162 | |
| 163 | if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) |
| 164 | { |
| 165 | data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; |
| 166 | mask |= 0x30; |
| 167 | } |
| 168 | else |
| 169 | { |
| 170 | data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; |
| 171 | mask |= 0xc0; |
| 172 | } |
| 173 | break; |
| 174 | |
| 175 | case MODE_2: |
| 176 | data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; |
| 177 | data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; |
| 178 | data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; |
| 179 | break; |
| 180 | } |
| 181 | |
| 182 | /* PC lower */ |
| 183 | switch (group_mode(i8255a, GROUP_B)) |
| 184 | { |
| 185 | case MODE_0: |
| 186 | if (port_c_lower_mode(i8255a) == MODE_OUTPUT) |
| 187 | { |
| 188 | mask |= 0x0f; |
| 189 | } |
| 190 | break; |
| 191 | |
| 192 | case MODE_1: |
| 193 | data |= i8255a->intr[PORT_B] ? 0x01 : 0x00; |
| 194 | |
| 195 | if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) |
| 196 | { |
| 197 | data |= i8255a->obf[PORT_B] ? 0x02 : 0x00; |
| 198 | } |
| 199 | else |
| 200 | { |
| 201 | data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00; |
| 202 | } |
| 203 | } |
| 204 | |
| 205 | data |= i8255a->output[PORT_C] & mask; |
| 206 | |
| 207 | devcb_call_write8(&i8255a->out_port_func[PORT_C], 0, data); |
| 208 | } |
| 209 | |
| 210 | static void check_interrupt(i8255a_t *i8255a, int port) |
| 211 | { |
| 212 | switch (group_mode(i8255a, port)) |
| 213 | { |
| 214 | case MODE_1: |
| 215 | switch (port_mode(i8255a, port)) |
| 216 | { |
| 217 | case MODE_INPUT: |
| 218 | if (i8255a->inte[port] && i8255a->ibf[port]) |
| 219 | { |
| 220 | if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); |
| 221 | |
| 222 | i8255a->intr[port] = 1; |
| 223 | } |
| 224 | break; |
| 225 | |
| 226 | case MODE_OUTPUT: |
| 227 | if (i8255a->inte[port] && i8255a->obf[port]) |
| 228 | { |
| 229 | if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); |
| 230 | |
| 231 | i8255a->intr[port] = 1; |
| 232 | } |
| 233 | break; |
| 234 | } |
| 235 | break; |
| 236 | |
| 237 | case MODE_2: |
| 238 | if ((i8255a->inte1 && i8255a->obf[port]) || (i8255a->inte2 && i8255a->ibf[port])) |
| 239 | { |
| 240 | if (LOG) logerror("8255A Port %c INTR: 1\n", 'A' + port); |
| 241 | |
| 242 | i8255a->intr[port] = 1; |
| 243 | } |
| 244 | break; |
| 245 | } |
| 246 | |
| 247 | output_pc(i8255a); |
| 248 | } |
| 249 | |
| 250 | static void set_ibf(i8255a_t *i8255a, int port, int state) |
| 251 | { |
| 252 | if (LOG) logerror("8255A Port %c IBF: %u\n", 'A' + port, state); |
| 253 | |
| 254 | i8255a->ibf[port] = state; |
| 255 | |
| 256 | check_interrupt(i8255a, port); |
| 257 | } |
| 258 | |
| 259 | static void set_obf(i8255a_t *i8255a, int port, int state) |
| 260 | { |
| 261 | if (LOG) logerror("8255A Port %c OBF: %u\n", 'A' + port, state); |
| 262 | |
| 263 | i8255a->obf[port] = state; |
| 264 | |
| 265 | check_interrupt(i8255a, port); |
| 266 | } |
| 267 | |
| 268 | static void set_inte(i8255a_t *i8255a, int port, int state) |
| 269 | { |
| 270 | if (LOG) logerror("8255A Port %c INTE: %u\n", 'A' + port, state); |
| 271 | |
| 272 | i8255a->inte[port] = state; |
| 273 | |
| 274 | check_interrupt(i8255a, port); |
| 275 | } |
| 276 | |
| 277 | static void set_inte1(i8255a_t *i8255a, int state) |
| 278 | { |
| 279 | if (LOG) logerror("8255A Port A INTE1: %u\n", state); |
| 280 | |
| 281 | i8255a->inte1 = state; |
| 282 | |
| 283 | check_interrupt(i8255a, PORT_A); |
| 284 | } |
| 285 | |
| 286 | static void set_inte2(i8255a_t *i8255a, int state) |
| 287 | { |
| 288 | if (LOG) logerror("8255A Port A INTE2: %u\n", state); |
| 289 | |
| 290 | i8255a->inte2 = state; |
| 291 | |
| 292 | check_interrupt(i8255a, PORT_A); |
| 293 | } |
| 294 | |
| 295 | static void set_intr(i8255a_t *i8255a, int port, int state) |
| 296 | { |
| 297 | if (LOG) logerror("8255A Port %c INTR: %u\n", 'A' + port, state); |
| 298 | |
| 299 | i8255a->intr[port] = state; |
| 300 | |
| 301 | output_pc(i8255a); |
| 302 | } |
| 303 | |
| 304 | static UINT8 read_mode0(i8255a_t *i8255a, int port) |
| 305 | { |
| 306 | UINT8 data = 0; |
| 307 | |
| 308 | if (port_mode(i8255a, port) == MODE_OUTPUT) |
| 309 | { |
| 310 | /* read data from output latch */ |
| 311 | data = i8255a->output[port]; |
| 312 | } |
| 313 | else |
| 314 | { |
| 315 | /* read data from port */ |
| 316 | data = devcb_call_read8(&i8255a->in_port_func[port], 0); |
| 317 | } |
| 318 | |
| 319 | return data; |
| 320 | } |
| 321 | |
| 322 | static UINT8 read_mode1(i8255a_t *i8255a, int port) |
| 323 | { |
| 324 | UINT8 data = 0; |
| 325 | |
| 326 | if (port_mode(i8255a, port) == MODE_OUTPUT) |
| 327 | { |
| 328 | /* read data from output latch */ |
| 329 | data = i8255a->output[port]; |
| 330 | } |
| 331 | else |
| 332 | { |
| 333 | /* read data from input latch */ |
| 334 | data = i8255a->input[port]; |
| 335 | |
| 336 | /* clear input buffer full flag */ |
| 337 | set_ibf(i8255a, port, 0); |
| 338 | |
| 339 | /* clear interrupt */ |
| 340 | set_intr(i8255a, port, 0); |
| 341 | } |
| 342 | |
| 343 | return data; |
| 344 | } |
| 345 | |
| 346 | static UINT8 read_mode2(i8255a_t *i8255a) |
| 347 | { |
| 348 | UINT8 data = 0; |
| 349 | |
| 350 | /* read data from input latch */ |
| 351 | data = i8255a->input[PORT_A]; |
| 352 | |
| 353 | /* clear input buffer full flag */ |
| 354 | set_ibf(i8255a, PORT_A, 0); |
| 355 | |
| 356 | return data; |
| 357 | } |
| 358 | |
| 359 | static UINT8 read_pc(i8255a_t *i8255a) |
| 360 | { |
| 361 | UINT8 data = 0; |
| 362 | UINT8 mask = 0; |
| 363 | |
| 364 | /* PC upper */ |
| 365 | switch (group_mode(i8255a, GROUP_A)) |
| 366 | { |
| 367 | case MODE_0: |
| 368 | if (port_c_upper_mode(i8255a) == MODE_OUTPUT) |
| 369 | { |
| 370 | /* read data from output latch */ |
| 371 | data |= i8255a->output[PORT_C] & 0xf0; |
| 372 | } |
| 373 | else |
| 374 | { |
| 375 | /* read data from port */ |
| 376 | mask |= 0xf0; |
| 377 | } |
| 378 | break; |
| 379 | |
| 380 | case MODE_1: |
| 381 | data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; |
| 382 | |
| 383 | if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) |
| 384 | { |
| 385 | data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; |
| 386 | data |= i8255a->inte[PORT_A] ? 0x40 : 0x00; |
| 387 | mask |= 0x30; |
| 388 | } |
| 389 | else |
| 390 | { |
| 391 | data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; |
| 392 | data |= i8255a->inte[PORT_A] ? 0x10 : 0x00; |
| 393 | mask |= 0xc0; |
| 394 | } |
| 395 | break; |
| 396 | |
| 397 | case MODE_2: |
| 398 | data |= i8255a->intr[PORT_A] ? 0x08 : 0x00; |
| 399 | data |= i8255a->inte2 ? 0x10 : 0x00; |
| 400 | data |= i8255a->ibf[PORT_A] ? 0x20 : 0x00; |
| 401 | data |= i8255a->inte1 ? 0x40 : 0x00; |
| 402 | data |= i8255a->obf[PORT_A] ? 0x80 : 0x00; |
| 403 | break; |
| 404 | } |
| 405 | |
| 406 | /* PC lower */ |
| 407 | switch (group_mode(i8255a, GROUP_B)) |
| 408 | { |
| 409 | case MODE_0: |
| 410 | if (port_c_lower_mode(i8255a) == MODE_OUTPUT) |
| 411 | { |
| 412 | /* read data from output latch */ |
| 413 | data |= i8255a->output[PORT_C] & 0x0f; |
| 414 | } |
| 415 | else |
| 416 | { |
| 417 | /* read data from port */ |
| 418 | mask |= 0x0f; |
| 419 | } |
| 420 | break; |
| 421 | |
| 422 | case MODE_1: |
| 423 | data |= i8255a->inte[PORT_B] ? 0x04 : 0x00; |
| 424 | data |= i8255a->intr[PORT_B] ? 0x01 : 0x00; |
| 425 | |
| 426 | if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) |
| 427 | { |
| 428 | data |= i8255a->obf[PORT_B] ? 0x02 : 0x00; |
| 429 | } |
| 430 | else |
| 431 | { |
| 432 | data |= i8255a->ibf[PORT_B] ? 0x02 : 0x00; |
| 433 | } |
| 434 | } |
| 435 | |
| 436 | if (mask) |
| 437 | { |
| 438 | /* read data from port */ |
| 439 | data |= devcb_call_read8(&i8255a->in_port_func[PORT_C], 0) & mask; |
| 440 | } |
| 441 | |
| 442 | return data; |
| 443 | } |
| 444 | |
| 445 | READ8_DEVICE_HANDLER( i8255a_r ) |
| 446 | { |
| 447 | i8255a_t *i8255a = get_safe_token(device); |
| 448 | |
| 449 | UINT8 data = 0; |
| 450 | |
| 451 | switch (offset & 0x03) |
| 452 | { |
| 453 | case PORT_A: |
| 454 | switch (group_mode(i8255a, GROUP_A)) |
| 455 | { |
| 456 | case MODE_0: data = read_mode0(i8255a, PORT_A); break; |
| 457 | case MODE_1: data = read_mode1(i8255a, PORT_A); break; |
| 458 | case MODE_2: data = read_mode2(i8255a); break; |
| 459 | } |
| 460 | if (LOG) logerror("8255A '%s' Port A Read: %02x\n", device->tag, data); |
| 461 | break; |
| 462 | |
| 463 | case PORT_B: |
| 464 | switch (group_mode(i8255a, GROUP_B)) |
| 465 | { |
| 466 | case MODE_0: data = read_mode0(i8255a, PORT_B); break; |
| 467 | case MODE_1: data = read_mode1(i8255a, PORT_B); break; |
| 468 | } |
| 469 | if (LOG) logerror("8255A '%s' Port B Read: %02x\n", device->tag, data); |
| 470 | break; |
| 471 | |
| 472 | case PORT_C: |
| 473 | data = read_pc(i8255a); |
| 474 | //if (LOG) logerror("8255A '%s' Port C Read: %02x\n", device->tag, data); |
| 475 | break; |
| 476 | |
| 477 | case CONTROL: |
| 478 | data = i8255a->control; |
| 479 | if (LOG) logerror("8255A '%s' Mode Control Word Read: %02x\n", device->tag, data); |
| 480 | break; |
| 481 | } |
| 482 | |
| 483 | return data; |
| 484 | } |
| 485 | |
| 486 | static void write_mode0(i8255a_t *i8255a, int port, UINT8 data) |
| 487 | { |
| 488 | if (port_mode(i8255a, port) == MODE_OUTPUT) |
| 489 | { |
| 490 | /* latch output data */ |
| 491 | i8255a->output[port] = data; |
| 492 | |
| 493 | /* write data to port */ |
| 494 | devcb_call_write8(&i8255a->out_port_func[port], 0, data); |
| 495 | } |
| 496 | } |
| 497 | |
| 498 | static void write_mode1(i8255a_t *i8255a, int port, UINT8 data) |
| 499 | { |
| 500 | if (port_mode(i8255a, port) == MODE_OUTPUT) |
| 501 | { |
| 502 | /* latch output data */ |
| 503 | i8255a->output[port] = data; |
| 504 | |
| 505 | /* write data to port */ |
| 506 | devcb_call_write8(&i8255a->out_port_func[port], 0, data); |
| 507 | |
| 508 | /* set output buffer full flag */ |
| 509 | set_obf(i8255a, port, 0); |
| 510 | |
| 511 | /* clear interrupt */ |
| 512 | set_intr(i8255a, port, 0); |
| 513 | } |
| 514 | } |
| 515 | |
| 516 | static void write_mode2(i8255a_t *i8255a, UINT8 data) |
| 517 | { |
| 518 | /* latch output data */ |
| 519 | i8255a->output[PORT_A] = data; |
| 520 | |
| 521 | /* write data to port */ |
| 522 | devcb_call_write8(&i8255a->out_port_func[PORT_A], 0, data); |
| 523 | |
| 524 | /* set output buffer full flag */ |
| 525 | set_obf(i8255a, PORT_A, 0); |
| 526 | |
| 527 | /* clear interrupt */ |
| 528 | set_intr(i8255a, PORT_A, 0); |
| 529 | } |
| 530 | |
| 531 | static void write_pc(i8255a_t *i8255a, UINT8 data) |
| 532 | { |
| 533 | int changed = 0; |
| 534 | |
| 535 | if (group_mode(i8255a, GROUP_A) == MODE_0) |
| 536 | { |
| 537 | /* PC upper */ |
| 538 | if (port_c_upper_mode(i8255a) == MODE_OUTPUT) |
| 539 | { |
| 540 | i8255a->output[PORT_C] = (data & 0xf0) | (i8255a->output[PORT_C] & 0x0f); |
| 541 | changed = 1; |
| 542 | } |
| 543 | |
| 544 | /* PC lower */ |
| 545 | if (port_c_lower_mode(i8255a) == MODE_OUTPUT) |
| 546 | { |
| 547 | i8255a->output[PORT_C] = (i8255a->output[PORT_C] & 0xf0) | (data & 0x0f); |
| 548 | changed = 1; |
| 549 | } |
| 550 | } |
| 551 | |
| 552 | if (changed) |
| 553 | { |
| 554 | output_pc(i8255a); |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | static void set_mode(const device_config *device, UINT8 data) |
| 559 | { |
| 560 | i8255a_t *i8255a = get_safe_token(device); |
| 561 | |
| 562 | i8255a->control = data; |
| 563 | |
| 564 | /* group A */ |
| 565 | i8255a->output[PORT_A] = 0; |
| 566 | i8255a->input[PORT_A] = 0; |
| 567 | i8255a->ibf[PORT_A] = 0; |
| 568 | i8255a->obf[PORT_A] = 1; |
| 569 | i8255a->inte[PORT_A] = 0; |
| 570 | i8255a->inte1 = 0; |
| 571 | i8255a->inte2 = 0; |
| 572 | |
| 573 | if (LOG) logerror("8255A '%s' Group A Mode: %u\n", device->tag, group_mode(i8255a, GROUP_A)); |
| 574 | if (LOG) logerror("8255A '%s' Port A Mode: %s\n", device->tag, (port_mode(i8255a, PORT_A) == MODE_OUTPUT) ? "output" : "input"); |
| 575 | if (LOG) logerror("8255A '%s' Port C Upper Mode: %s\n", device->tag, (port_c_upper_mode(i8255a) == MODE_OUTPUT) ? "output" : "input"); |
| 576 | if (LOG) logerror("8255A '%s' Group B Mode: %u\n", device->tag, group_mode(i8255a, GROUP_B)); |
| 577 | if (LOG) logerror("8255A '%s' Port B Mode: %s\n", device->tag, (port_mode(i8255a, PORT_B) == MODE_OUTPUT) ? "output" : "input"); |
| 578 | if (LOG) logerror("8255A '%s' Port C Lower Mode: %s\n", device->tag, (port_c_lower_mode(i8255a) == MODE_OUTPUT) ? "output" : "input"); |
| 579 | |
| 580 | /* group B */ |
| 581 | i8255a->output[PORT_B] = 0; |
| 582 | i8255a->input[PORT_B] = 0; |
| 583 | i8255a->ibf[PORT_B] = 0; |
| 584 | i8255a->obf[PORT_B] = 1; |
| 585 | i8255a->inte[PORT_B] = 0; |
| 586 | |
| 587 | i8255a->output[PORT_C] = 0; |
| 588 | i8255a->input[PORT_C] = 0; |
| 589 | |
| 590 | output_pc(i8255a); |
| 591 | } |
| 592 | |
| 593 | static void set_pc_bit(const device_config *device, int bit, int state) |
| 594 | { |
| 595 | i8255a_t *i8255a = get_safe_token(device); |
| 596 | |
| 597 | /* set output latch bit */ |
| 598 | i8255a->output[PORT_C] &= ~(1 << bit); |
| 599 | i8255a->output[PORT_C] |= state << bit; |
| 600 | |
| 601 | switch (group_mode(i8255a, GROUP_A)) |
| 602 | { |
| 603 | case MODE_1: |
| 604 | if (port_mode(i8255a, PORT_A) == MODE_OUTPUT) |
| 605 | { |
| 606 | switch (bit) |
| 607 | { |
| 608 | case 3: set_intr(i8255a, PORT_A, state); break; |
| 609 | case 6: set_inte(i8255a, PORT_A, state); break; |
| 610 | case 7: set_obf(i8255a, PORT_A, state); break; |
| 611 | } |
| 612 | } |
| 613 | else |
| 614 | { |
| 615 | switch (bit) |
| 616 | { |
| 617 | case 3: set_intr(i8255a, PORT_A, state); break; |
| 618 | case 4: set_inte(i8255a, PORT_A, state); break; |
| 619 | case 5: set_ibf(i8255a, PORT_A, state); break; |
| 620 | } |
| 621 | } |
| 622 | break; |
| 623 | |
| 624 | case MODE_2: |
| 625 | switch (bit) |
| 626 | { |
| 627 | case 3: set_intr(i8255a, PORT_A, state); break; |
| 628 | case 4: set_inte2(i8255a, state); break; |
| 629 | case 5: set_ibf(i8255a, PORT_A, state); break; |
| 630 | case 6: set_inte1(i8255a, state); break; |
| 631 | case 7: set_obf(i8255a, PORT_A, state); break; |
| 632 | } |
| 633 | break; |
| 634 | } |
| 635 | |
| 636 | if (group_mode(i8255a, GROUP_B) == MODE_1) |
| 637 | { |
| 638 | switch (bit) |
| 639 | { |
| 640 | case 0: set_intr(i8255a, PORT_B, state); break; |
| 641 | case 1: |
| 642 | if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) |
| 643 | set_obf(i8255a, PORT_B, state); |
| 644 | else |
| 645 | set_ibf(i8255a, PORT_B, state); |
| 646 | break; |
| 647 | case 2: set_inte(i8255a, PORT_B, state); break; |
| 648 | } |
| 649 | } |
| 650 | |
| 651 | output_pc(i8255a); |
| 652 | } |
| 653 | |
| 654 | WRITE8_DEVICE_HANDLER( i8255a_w ) |
| 655 | { |
| 656 | i8255a_t *i8255a = get_safe_token(device); |
| 657 | |
| 658 | switch (offset & 0x03) |
| 659 | { |
| 660 | case PORT_A: |
| 661 | if (LOG) logerror("8255A '%s' Port A Write: %02x\n", device->tag, data); |
| 662 | |
| 663 | switch (group_mode(i8255a, GROUP_A)) |
| 664 | { |
| 665 | case MODE_0: write_mode0(i8255a, PORT_A, data); break; |
| 666 | case MODE_1: write_mode1(i8255a, PORT_A, data); break; |
| 667 | case MODE_2: write_mode2(i8255a, data); break; |
| 668 | } |
| 669 | break; |
| 670 | |
| 671 | case PORT_B: |
| 672 | if (LOG) logerror("8255A '%s' Port B Write: %02x\n", device->tag, data); |
| 673 | |
| 674 | switch (group_mode(i8255a, GROUP_B)) |
| 675 | { |
| 676 | case MODE_0: write_mode0(i8255a, PORT_B, data); break; |
| 677 | case MODE_1: write_mode1(i8255a, PORT_B, data); break; |
| 678 | } |
| 679 | break; |
| 680 | |
| 681 | case PORT_C: |
| 682 | if (LOG) logerror("8255A '%s' Port C Write: %02x\n", device->tag, data); |
| 683 | |
| 684 | write_pc(i8255a, data); |
| 685 | break; |
| 686 | |
| 687 | case CONTROL: |
| 688 | if (data & I8255A_CONTROL_MODE_SET) |
| 689 | { |
| 690 | if (LOG) logerror("8255A '%s' Mode Control Word: %02x\n", device->tag, data); |
| 691 | |
| 692 | set_mode(device, data); |
| 693 | } |
| 694 | else |
| 695 | { |
| 696 | int bit = (data >> 1) & 0x07; |
| 697 | int state = BIT(data, 0); |
| 698 | |
| 699 | if (LOG) logerror("8255A '%s' %s Bit %u\n", device->tag, state ? "Set" : "Reset", bit); |
| 700 | |
| 701 | set_pc_bit(device, bit, state); |
| 702 | } |
| 703 | break; |
| 704 | } |
| 705 | } |
| 706 | |
| 707 | READ8_DEVICE_HANDLER( i8255a_pa_r ) |
| 708 | { |
| 709 | i8255a_t *i8255a = get_safe_token(device); |
| 710 | |
| 711 | return i8255a->output[PORT_A]; |
| 712 | } |
| 713 | |
| 714 | READ8_DEVICE_HANDLER( i8255a_pb_r ) |
| 715 | { |
| 716 | i8255a_t *i8255a = get_safe_token(device); |
| 717 | |
| 718 | return i8255a->output[PORT_B]; |
| 719 | } |
| 720 | |
| 721 | WRITE_LINE_DEVICE_HANDLER( i8255a_pc2_w ) |
| 722 | { |
| 723 | i8255a_t *i8255a = get_safe_token(device); |
| 724 | |
| 725 | if (group_mode(i8255a, GROUP_B) == 1) |
| 726 | { |
| 727 | if (port_mode(i8255a, PORT_B) == MODE_OUTPUT) |
| 728 | { |
| 729 | /* port B acknowledge */ |
| 730 | if (!i8255a->obf[PORT_B] && !state) |
| 731 | { |
| 732 | if (LOG) logerror("8255A '%s' Port B Acknowledge\n", device->tag); |
| 733 | |
| 734 | /* clear output buffer flag */ |
| 735 | set_obf(i8255a, PORT_B, 1); |
| 736 | } |
| 737 | } |
| 738 | else |
| 739 | { |
| 740 | /* port B strobe */ |
| 741 | if (!i8255a->ibf[PORT_B] && !state) |
| 742 | { |
| 743 | if (LOG) logerror("8255A '%s' Port B Strobe\n", device->tag); |
| 744 | |
| 745 | /* read port into latch */ |
| 746 | i8255a->input[PORT_B] = devcb_call_read8(&i8255a->in_port_func[PORT_B], 0); |
| 747 | |
| 748 | /* set input buffer flag */ |
| 749 | set_ibf(i8255a, PORT_B, 1); |
| 750 | } |
| 751 | } |
| 752 | } |
| 753 | } |
| 754 | |
| 755 | WRITE_LINE_DEVICE_HANDLER( i8255a_pc4_w ) |
| 756 | { |
| 757 | i8255a_t *i8255a = get_safe_token(device); |
| 758 | |
| 759 | if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_INPUT))) |
| 760 | { |
| 761 | /* port A strobe */ |
| 762 | if (!i8255a->ibf[PORT_A] && !state) |
| 763 | { |
| 764 | if (LOG) logerror("8255A '%s' Port A Strobe\n", device->tag); |
| 765 | |
| 766 | /* read port into latch */ |
| 767 | i8255a->input[PORT_A] = devcb_call_read8(&i8255a->in_port_func[PORT_A], 0); |
| 768 | |
| 769 | /* set input buffer flag */ |
| 770 | set_ibf(i8255a, PORT_A, 1); |
| 771 | } |
| 772 | } |
| 773 | } |
| 774 | |
| 775 | WRITE_LINE_DEVICE_HANDLER( i8255a_pc6_w ) |
| 776 | { |
| 777 | i8255a_t *i8255a = get_safe_token(device); |
| 778 | |
| 779 | if ((group_mode(i8255a, GROUP_A) == 2) || ((group_mode(i8255a, GROUP_A) == 1) && (port_mode(i8255a, PORT_A) == MODE_OUTPUT))) |
| 780 | { |
| 781 | /* port A acknowledge */ |
| 782 | if (!i8255a->obf[PORT_A] && !state) |
| 783 | { |
| 784 | if (LOG) logerror("8255A '%s' Port A Acknowledge\n", device->tag); |
| 785 | |
| 786 | /* clear output buffer flag */ |
| 787 | set_obf(i8255a, PORT_A, 1); |
| 788 | } |
| 789 | } |
| 790 | } |
| 791 | |
| 792 | /*------------------------------------------------- |
| 793 | DEVICE_START( i8255a ) |
| 794 | -------------------------------------------------*/ |
| 795 | |
| 796 | static DEVICE_START( i8255a ) |
| 797 | { |
| 798 | i8255a_t *i8255a = get_safe_token(device); |
| 799 | const i8255a_interface *intf = get_interface(device); |
| 800 | |
| 801 | /* resolve callbacks */ |
| 802 | devcb_resolve_read8(&i8255a->in_port_func[PORT_A], &intf->in_pa_func, device); |
| 803 | devcb_resolve_read8(&i8255a->in_port_func[PORT_B], &intf->in_pb_func, device); |
| 804 | devcb_resolve_read8(&i8255a->in_port_func[PORT_C], &intf->in_pc_func, device); |
| 805 | devcb_resolve_write8(&i8255a->out_port_func[PORT_A], &intf->out_pa_func, device); |
| 806 | devcb_resolve_write8(&i8255a->out_port_func[PORT_B], &intf->out_pb_func, device); |
| 807 | devcb_resolve_write8(&i8255a->out_port_func[PORT_C], &intf->out_pc_func, device); |
| 808 | |
| 809 | /* register for state saving */ |
| 810 | state_save_register_device_item(device, 0, i8255a->control); |
| 811 | state_save_register_device_item_array(device, 0, i8255a->output); |
| 812 | state_save_register_device_item_array(device, 0, i8255a->input); |
| 813 | state_save_register_device_item_array(device, 0, i8255a->ibf); |
| 814 | state_save_register_device_item_array(device, 0, i8255a->obf); |
| 815 | state_save_register_device_item_array(device, 0, i8255a->inte); |
| 816 | state_save_register_device_item(device, 0, i8255a->inte1); |
| 817 | state_save_register_device_item(device, 0, i8255a->inte2); |
| 818 | state_save_register_device_item_array(device, 0, i8255a->intr); |
| 819 | } |
| 820 | |
| 821 | /*------------------------------------------------- |
| 822 | DEVICE_RESET( i8255a ) |
| 823 | -------------------------------------------------*/ |
| 824 | |
| 825 | static DEVICE_RESET( i8255a ) |
| 826 | { |
| 827 | i8255a_w(device, CONTROL, 0x9b); |
| 828 | } |
| 829 | |
| 830 | /*------------------------------------------------- |
| 831 | DEVICE_GET_INFO( i8255a ) |
| 832 | -------------------------------------------------*/ |
| 833 | |
| 834 | DEVICE_GET_INFO( i8255a ) |
| 835 | { |
| 836 | switch (state) |
| 837 | { |
| 838 | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 839 | case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(i8255a_t); break; |
| 840 | case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; |
| 841 | case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break; |
| 842 | |
| 843 | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 844 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(i8255a); break; |
| 845 | case DEVINFO_FCT_STOP: /* Nothing */ break; |
| 846 | case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(i8255a); break; |
| 847 | |
| 848 | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 849 | case DEVINFO_STR_NAME: strcpy(info->s, "Intel 8255A"); break; |
| 850 | case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8085"); break; |
| 851 | case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break; |
| 852 | case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 853 | case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break; |
| 854 | } |
| 855 | } |
src/mess/drivers/v1050.c
| r5191 | r5192 | |
| 13 | 13 | - video |
| 14 | 14 | - µPB8214 chip |
| 15 | 15 | - RTC58321 chip |
| 16 | | - floppy |
| 17 | 16 | - keyboard |
| 18 | | - centronics |
| 19 | 17 | - winchester |
| 20 | 18 | |
| 21 | 19 | */ |
| r5191 | r5192 | |
| 27 | 25 | #include "cpu/mcs48/mcs48.h" |
| 28 | 26 | #include "devices/basicdsk.h" |
| 29 | 27 | #include "machine/ctronics.h" |
| 30 | | #include "machine/8255ppi.h" |
| 28 | #include "machine/i8255a.h" |
| 31 | 29 | #include "machine/msm8251.h" |
| 32 | 30 | #include "machine/wd17xx.h" |
| 33 | 31 | #include "video/mc6845.h" |
| r5191 | r5192 | |
| 101 | 99 | |
| 102 | 100 | static ADDRESS_MAP_START( v1050_io, ADDRESS_SPACE_IO, 8 ) |
| 103 | 101 | ADDRESS_MAP_UNMAP_HIGH |
| 104 | | // AM_RANGE(0x84, 0x87) AM_DEVREADWRITE(CRT_Z80_PPI8255_TAG, ppi8255_r, ppi8255_w) |
| 105 | | // AM_RANGE(0x88, 0x88) AM_DEVREADWRITE(KB_MSM8251_TAG, msm8251_data_r, msm8251_data_w) |
| 106 | | // AM_RANGE(0x89, 0x89) AM_DEVREADWRITE(KB_MSM8251_TAG, msm8251_status_r, msm8251_control_w) |
| 107 | | // AM_RANGE(0x8c, 0x8c) AM_DEVREADWRITE(SIO_MSM8251_TAG, msm8251_data_r, msm8251_data_w) |
| 108 | | // AM_RANGE(0x8d, 0x8d) AM_DEVREADWRITE(SIO_MSM8251_TAG, msm8251_status_r, msm8251_control_w) |
| 109 | | // AM_RANGE(0x90, 0x93) AM_DEVREADWRITE(FDC_PPI8255_TAG, ppi8255_r, ppi8255_w) |
| 102 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 103 | AM_RANGE(0x84, 0x87) AM_DEVREADWRITE(I8255_DISP_TAG, i8255a_r, i8255a_w) |
| 104 | // AM_RANGE(0x88, 0x88) AM_DEVREADWRITE(I8251_KB_TAG, msm8251_data_r, msm8251_data_w) |
| 105 | // AM_RANGE(0x89, 0x89) AM_DEVREADWRITE(I8251_KB_TAG, msm8251_status_r, msm8251_control_w) |
| 106 | // AM_RANGE(0x8c, 0x8c) AM_DEVREADWRITE(I8251_SIO_TAG, msm8251_data_r, msm8251_data_w) |
| 107 | // AM_RANGE(0x8d, 0x8d) AM_DEVREADWRITE(I8251_SIO_TAG, msm8251_status_r, msm8251_control_w) |
| 108 | AM_RANGE(0x90, 0x93) AM_DEVREADWRITE(I8255_MISC_TAG, i8255a_r, i8255a_w) |
| 110 | 109 | AM_RANGE(0x94, 0x97) AM_DEVREADWRITE(MB8877_TAG, wd17xx_r, wd17xx_w) |
| 111 | | // AM_RANGE(0x9c, 0x9f) AM_DEVREADWRITE(RTC_PPI8255_TAG, ppi8255_r, ppi8255_w) |
| 110 | AM_RANGE(0x9c, 0x9f) AM_DEVREADWRITE(I8255_RTC_TAG, i8255a_r, i8255a_w) |
| 112 | 111 | // AM_RANGE(0xa0, 0xa0) AM_READWRITE(vint_clr_r, vint_clr_w) |
| 113 | 112 | // AM_RANGE(0xb0, 0xb0) AM_READWRITE(dint_clr_r, dint_clr_w) |
| 114 | 113 | // AM_RANGE(0xc0, 0xc0) AM_DEVREADWRITE(UPB8214_TAG, pic8214_r, pic8214_w) |
| r5191 | r5192 | |
| 121 | 120 | AM_RANGE(0x2000, 0x7fff) AM_RAM AM_READWRITE(v1050_videoram_r, v1050_videoram_w) AM_BASE_MEMBER(v1050_state, video_ram) |
| 122 | 121 | AM_RANGE(0x8000, 0x8000) AM_DEVWRITE(HD6845_TAG, mc6845_address_w) |
| 123 | 122 | AM_RANGE(0x8001, 0x8001) AM_DEVREADWRITE(HD6845_TAG, mc6845_register_r, mc6845_register_w) |
| 124 | | // AM_RANGE(0x9000, 0x9003) AM_DEVREADWRITE(CRT_M6502_PPI8255_TAG, ppi8255_r, ppi8255_w) |
| 123 | AM_RANGE(0x9000, 0x9003) AM_DEVREADWRITE(I8255_M6502_TAG, i8255a_r, i8255a_w) |
| 125 | 124 | AM_RANGE(0xa000, 0xa000) AM_READWRITE(v1050_attr_r, v1050_attr_w) |
| 126 | 125 | // AM_RANGE(0xb000, 0xb000) AM_WRITE(z80int_w) |
| 127 | 126 | AM_RANGE(0xc000, 0xc000) AM_WRITE(dvint_clr_w) |
| r5191 | r5192 | |
| 258 | 257 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) |
| 259 | 258 | INPUT_PORTS_END |
| 260 | 259 | |
| 260 | /* Display 8255A Interface */ |
| 261 | |
| 262 | static WRITE8_DEVICE_HANDLER( crt_z80_ppi8255_c_w ) |
| 263 | { |
| 264 | v1050_state *state = device->machine->driver_data; |
| 265 | |
| 266 | i8255a_pc2_w(state->i8255a_crt_m6502, BIT(data, 6)); |
| 267 | i8255a_pc4_w(state->i8255a_crt_m6502, BIT(data, 7)); |
| 268 | } |
| 269 | |
| 270 | static I8255A_INTERFACE( disp_8255_intf ) |
| 271 | { |
| 272 | DEVCB_DEVICE_HANDLER(I8255_M6502_TAG, i8255a_pb_r), // Port A read |
| 273 | DEVCB_NULL, // Port B read |
| 274 | DEVCB_NULL, // Port C read |
| 275 | DEVCB_NULL, // Port A write |
| 276 | DEVCB_NULL, // Port B write |
| 277 | DEVCB_HANDLER(crt_z80_ppi8255_c_w) // Port C write |
| 278 | }; |
| 279 | |
| 280 | static WRITE8_DEVICE_HANDLER( crt_m6502_ppi8255_c_w ) |
| 281 | { |
| 282 | v1050_state *state = device->machine->driver_data; |
| 283 | |
| 284 | i8255a_pc2_w(state->i8255a_crt_z80, BIT(data, 7)); |
| 285 | i8255a_pc4_w(state->i8255a_crt_z80, BIT(data, 6)); |
| 286 | } |
| 287 | |
| 288 | static I8255A_INTERFACE( m6502_8255_intf ) |
| 289 | { |
| 290 | DEVCB_DEVICE_HANDLER(I8255_DISP_TAG, i8255a_pb_r), // Port A read |
| 291 | DEVCB_NULL, // Port B read |
| 292 | DEVCB_NULL, // Port C read |
| 293 | DEVCB_NULL, // Port A write |
| 294 | DEVCB_NULL, // Port B write |
| 295 | DEVCB_HANDLER(crt_m6502_ppi8255_c_w) // Port C write |
| 296 | }; |
| 297 | |
| 261 | 298 | /* Miscellanous 8255A Interface */ |
| 262 | 299 | |
| 263 | | static WRITE8_DEVICE_HANDLER( misc_ppi8255_a_w ) |
| 300 | static WRITE8_DEVICE_HANDLER( misc_8255_a_w ) |
| 264 | 301 | { |
| 265 | 302 | /* |
| 266 | 303 | |
| r5191 | r5192 | |
| 284 | 321 | /* floppy drive select */ |
| 285 | 322 | if (BIT(data, 0)) wd17xx_set_drive(state->mb8877, 0); |
| 286 | 323 | if (BIT(data, 1)) wd17xx_set_drive(state->mb8877, 1); |
| 287 | | if (BIT(data, 2)) wd17xx_set_drive(state->mb8877, 2); |
| 288 | | if (BIT(data, 3)) wd17xx_set_drive(state->mb8877, 3); |
| 324 | // if (BIT(data, 2)) wd17xx_set_drive(state->mb8877, 2); |
| 325 | // if (BIT(data, 3)) wd17xx_set_drive(state->mb8877, 3); |
| 289 | 326 | |
| 290 | 327 | /* floppy side select */ |
| 291 | 328 | wd17xx_set_side(state->mb8877, BIT(data, 4)); |
| r5191 | r5192 | |
| 300 | 337 | wd17xx_set_density(state->mb8877, BIT(data, 7) ? DEN_FM_LO : DEN_FM_HI); |
| 301 | 338 | } |
| 302 | 339 | |
| 303 | | static READ8_DEVICE_HANDLER( misc_ppi8255_c_r ) |
| 340 | static READ8_DEVICE_HANDLER( misc_8255_c_r ) |
| 304 | 341 | { |
| 305 | 342 | /* |
| 306 | 343 | |
| r5191 | r5192 | |
| 327 | 364 | return data; |
| 328 | 365 | } |
| 329 | 366 | |
| 330 | | static WRITE8_DEVICE_HANDLER( misc_ppi8255_c_w ) |
| 367 | static WRITE8_DEVICE_HANDLER( misc_8255_c_w ) |
| 331 | 368 | { |
| 332 | 369 | /* |
| 333 | 370 | |
| r5191 | r5192 | |
| 353 | 390 | state->f_int_enb = BIT(data, 1); |
| 354 | 391 | } |
| 355 | 392 | |
| 356 | | static const ppi8255_interface misc_ppi8255_intf = |
| 393 | static I8255A_INTERFACE( misc_8255_intf ) |
| 357 | 394 | { |
| 358 | 395 | DEVCB_NULL, // Port A read |
| 359 | 396 | DEVCB_NULL, // Port B read |
| 360 | | DEVCB_HANDLER(misc_ppi8255_c_r), // Port C read |
| 361 | | DEVCB_HANDLER(misc_ppi8255_a_w), // Port A write |
| 397 | DEVCB_HANDLER(misc_8255_c_r), // Port C read |
| 398 | DEVCB_HANDLER(misc_8255_a_w), // Port A write |
| 362 | 399 | DEVCB_DEVICE_HANDLER(CENTRONICS_TAG, centronics_data_w),// Port B write |
| 363 | | DEVCB_HANDLER(misc_ppi8255_c_w) // Port C write |
| 400 | DEVCB_HANDLER(misc_8255_c_w) // Port C write |
| 364 | 401 | }; |
| 365 | 402 | |
| 403 | /* Real Time Clock 8255A Interface */ |
| 404 | |
| 405 | static WRITE8_DEVICE_HANDLER( rtc_8255_b_w ) |
| 406 | { |
| 407 | /* |
| 408 | |
| 409 | bit signal description |
| 410 | |
| 411 | PB0 RS-232 |
| 412 | PB1 Winchester |
| 413 | PB2 keyboard |
| 414 | PB3 floppy disk interrupt |
| 415 | PB4 vertical interrupt |
| 416 | PB5 display interrupt |
| 417 | PB6 expansion B |
| 418 | PB7 expansion A |
| 419 | |
| 420 | */ |
| 421 | |
| 422 | v1050_state *state = device->machine->driver_data; |
| 423 | |
| 424 | state->int_mask = data; |
| 425 | } |
| 426 | |
| 427 | static READ8_DEVICE_HANDLER( rtc_8255_c_r ) |
| 428 | { |
| 429 | /* |
| 430 | |
| 431 | bit signal description |
| 432 | |
| 433 | PC0 |
| 434 | PC1 |
| 435 | PC2 |
| 436 | PC3 clock busy |
| 437 | PC4 clock address write |
| 438 | PC5 clock data write |
| 439 | PC6 clock data read |
| 440 | PC7 clock device select |
| 441 | |
| 442 | */ |
| 443 | |
| 444 | return 0xff; |
| 445 | } |
| 446 | |
| 447 | static WRITE8_DEVICE_HANDLER( rtc_8255_c_w ) |
| 448 | { |
| 449 | /* |
| 450 | |
| 451 | bit signal description |
| 452 | |
| 453 | PC0 |
| 454 | PC1 |
| 455 | PC2 |
| 456 | PC3 clock busy |
| 457 | PC4 clock address write |
| 458 | PC5 clock data write |
| 459 | PC6 clock data read |
| 460 | PC7 clock device select |
| 461 | |
| 462 | */ |
| 463 | } |
| 464 | |
| 465 | static I8255A_INTERFACE( rtc_8255_intf ) |
| 466 | { |
| 467 | DEVCB_NULL, // Port A read (RTC data) |
| 468 | DEVCB_NULL, // Port B read |
| 469 | DEVCB_HANDLER(rtc_8255_c_r), // Port C read |
| 470 | DEVCB_NULL, // Port A write (RTC data) |
| 471 | DEVCB_HANDLER(rtc_8255_b_w), // Port B write |
| 472 | DEVCB_HANDLER(rtc_8255_c_w) // Port C write |
| 473 | }; |
| 474 | |
| 366 | 475 | /* MB8877 Interface */ |
| 367 | 476 | |
| 368 | 477 | static WD17XX_CALLBACK( v1050_mb8877_callback ) |
| r5191 | r5192 | |
| 403 | 512 | |
| 404 | 513 | /* find devices */ |
| 405 | 514 | state->upb8214 = devtag_get_device(machine, UPB8214_TAG); |
| 515 | state->i8255a_crt_z80 = devtag_get_device(machine, I8255_DISP_TAG); |
| 516 | state->i8255a_crt_m6502 = devtag_get_device(machine, I8255_M6502_TAG); |
| 406 | 517 | state->mb8877 = devtag_get_device(machine, MB8877_TAG); |
| 407 | 518 | state->centronics = devtag_get_device(machine, CENTRONICS_TAG); |
| 408 | 519 | |
| r5191 | r5192 | |
| 452 | 563 | MDRV_IMPORT_FROM(v1050_video) |
| 453 | 564 | |
| 454 | 565 | /* devices */ |
| 455 | | MDRV_PPI8255_ADD(FDC_PPI8255_TAG, misc_ppi8255_intf) |
| 566 | MDRV_I8255A_ADD(I8255_DISP_TAG, disp_8255_intf) |
| 567 | MDRV_I8255A_ADD(I8255_MISC_TAG, misc_8255_intf) |
| 568 | MDRV_I8255A_ADD(I8255_RTC_TAG, rtc_8255_intf) |
| 456 | 569 | MDRV_WD1793_ADD(MB8877_TAG, v1050_wd17xx_intf ) |
| 457 | 570 | |
| 571 | MDRV_I8255A_ADD(I8255_M6502_TAG, m6502_8255_intf) |
| 572 | |
| 458 | 573 | /* printer */ |
| 459 | 574 | MDRV_CENTRONICS_ADD(CENTRONICS_TAG, standard_centronics) |
| 460 | 575 | MACHINE_DRIVER_END |
| r5191 | r5192 | |
| 463 | 578 | |
| 464 | 579 | ROM_START( v1050 ) |
| 465 | 580 | ROM_REGION( 0x10000, Z80_TAG, 0 ) |
| 466 | | ROM_LOAD( "244-032.u86", 0x0000, 0x2000, CRC(46f847a7) SHA1(374db7a38a9e9230834ce015006e2f1996b9609a) ) |
| 581 | ROM_LOAD( "e244-032 rev 1.2.u86", 0x0000, 0x2000, CRC(46f847a7) SHA1(374db7a38a9e9230834ce015006e2f1996b9609a) ) |
| 467 | 582 | |
| 468 | 583 | ROM_REGION( 0x10000, M6502_TAG, 0 ) |
| 469 | | ROM_LOAD( "244-033.u77", 0xe000, 0x2000, CRC(c0502b66) SHA1(bc0015f5b14f98110e652eef9f7c57c614683be5) ) |
| 584 | ROM_LOAD( "e244-033 rev 1.1.u77", 0xe000, 0x2000, CRC(c0502b66) SHA1(bc0015f5b14f98110e652eef9f7c57c614683be5) ) |
| 470 | 585 | |
| 471 | 586 | ROM_REGION( 0x800, I8049_TAG, 0 ) |
| 472 | 587 | ROM_LOAD( "20-08049-410.z5", 0x0000, 0x0800, NO_DUMP ) |
| r5191 | r5192 | |
| 478 | 593 | static DEVICE_IMAGE_LOAD( v1050_floppy ) |
| 479 | 594 | { |
| 480 | 595 | if (image_has_been_created(image)) |
| 596 | { |
| 481 | 597 | return INIT_FAIL; |
| 598 | } |
| 482 | 599 | |
| 600 | if (DEVICE_IMAGE_LOAD_NAME(basicdsk_floppy)(image) == INIT_PASS) |
| 601 | { |
| 602 | switch (image_length(image)) |
| 603 | { |
| 604 | case 80*1*10*512: /* 400KB DSDD */ |
| 605 | basicdsk_set_geometry(image, 80, 1, 10, 512, 1, 0, FALSE); |
| 606 | break; |
| 607 | |
| 608 | default: |
| 609 | return INIT_FAIL; |
| 610 | } |
| 611 | |
| 612 | return INIT_PASS; |
| 613 | } |
| 614 | |
| 483 | 615 | return INIT_FAIL; |
| 484 | 616 | } |
| 485 | 617 | |