src/mess/drivers/a7000.c
| r8774 | r8775 | |
| 1 | 1 | /*************************************************************************** |
| 2 | 2 | |
| 3 | | Acorn Archimedes 7000/7000+ |
| 3 | Acorn Archimedes 7000/7000+ |
| 4 | 4 | |
| 5 | | 30/07/2010 Skeleton driver. |
| 5 | preliminary driver by Angelo Salese, |
| 6 | based on work by Tomasz Slanina and Tom Walker |
| 6 | 7 | |
| 8 | |
| 9 | bp (0382827C) (second trigger) |
| 10 | do R13 = SR13 |
| 11 | |
| 7 | 12 | ****************************************************************************/ |
| 8 | 13 | |
| 9 | 14 | #include "emu.h" |
| 10 | 15 | #include "cpu/arm7/arm7.h" |
| 16 | #include "cpu/arm7/arm7core.h" |
| 11 | 17 | |
| 18 | /* |
| 19 | * |
| 20 | * VIDC20 chip emulation |
| 21 | * |
| 22 | */ |
| 23 | |
| 24 | static const char *const vidc20_regnames[] = |
| 25 | { |
| 26 | "Video Palette", // 0 |
| 27 | "Video Palette Address", // 1 |
| 28 | "RESERVED", // 2 |
| 29 | "LCD offset", // 3 |
| 30 | "Border Colour", // 4 |
| 31 | "Cursor Palette Logical Colour 1", // 5 |
| 32 | "Cursor Palette Logical Colour 2", // 6 |
| 33 | "Cursor Palette Logical Colour 3", // 7 |
| 34 | "Horizontal", // 8 |
| 35 | "Vertical", // 9 |
| 36 | "Stereo Image", // A |
| 37 | "Sound", // B |
| 38 | "External", // C |
| 39 | "Frequency Synthesis", // D |
| 40 | "Control", // E |
| 41 | "Data Control" // F |
| 42 | }; |
| 43 | |
| 44 | |
| 45 | static WRITE32_HANDLER( a7000_vidc20_w ) |
| 46 | { |
| 47 | int reg = data >> 28; |
| 48 | int val = data & 0xffffff; |
| 49 | |
| 50 | switch(reg) |
| 51 | { |
| 52 | case 4: // Border Color |
| 53 | { |
| 54 | int r,g,b; |
| 55 | |
| 56 | r = (val & 0x0000ff) >> 0; |
| 57 | g = (val & 0x00ff00) >> 8; |
| 58 | b = (val & 0xff0000) >> 16; |
| 59 | |
| 60 | palette_set_color_rgb(space->machine,0x100,r,g,b); |
| 61 | } |
| 62 | break; |
| 63 | default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],val); |
| 64 | } |
| 65 | } |
| 66 | |
| 12 | 67 | static VIDEO_START( a7000 ) |
| 13 | 68 | { |
| 14 | 69 | } |
| 15 | 70 | |
| 16 | 71 | static VIDEO_UPDATE( a7000 ) |
| 17 | 72 | { |
| 73 | bitmap_fill(bitmap, cliprect, screen->machine->pens[0x100]); |
| 74 | |
| 18 | 75 | return 0; |
| 19 | 76 | } |
| 20 | 77 | |
| 78 | /* |
| 79 | * |
| 80 | * IOMD / ARM7500 / ARM7500FE chip emulation |
| 81 | * |
| 82 | */ |
| 83 | |
| 21 | 84 | /* TODO: some of these registers are actually ARM7500 specific */ |
| 22 | 85 | static const char *const iomd_regnames[] = |
| 23 | 86 | { |
| r8774 | r8775 | |
| 153 | 216 | |
| 154 | 217 | #define IOMD_IOCR 0x000/4 |
| 155 | 218 | #define IOMD_KBDDAT 0x004/4 |
| 219 | #define IOMD_KBDCR 0x008/4 |
| 156 | 220 | |
| 221 | #define IOMD_IRQSTA 0x010/4 |
| 222 | #define IOMD_IRQRQA 0x014/4 |
| 223 | #define IOMD_IRQMSKA 0x018/4 |
| 224 | |
| 225 | #define IOMD_T0LOW 0x040/4 |
| 226 | #define IOMD_T0HIGH 0x044/4 |
| 227 | #define IOMD_T0GO 0x048/4 |
| 228 | #define IOMD_T0LATCH 0x04c/4 |
| 229 | |
| 157 | 230 | #define IOMD_ID0 0x094/4 |
| 158 | 231 | #define IOMD_ID1 0x098/4 |
| 159 | 232 | |
| 160 | | static const char *const vidc20_regnames[] = |
| 233 | static UINT16 timer_in[2],timer_out[2]; |
| 234 | static int timer_counter[2]; |
| 235 | static emu_timer *IOMD_timer[2]; |
| 236 | static UINT8 IRQ_status_A,IRQ_mask_A; |
| 237 | static UINT8 IOMD_IO_ctrl,IOMD_keyb_ctrl; |
| 238 | |
| 239 | static UINT16 io_id; |
| 240 | |
| 241 | static void fire_iomd_timer(int timer, int timer_count) |
| 161 | 242 | { |
| 162 | | "Video Palette", // 0 |
| 163 | | "Video Palette Address", // 1 |
| 164 | | "RESERVED", // 2 |
| 165 | | "LCD offset", // 3 |
| 166 | | "Border Colour", // 4 |
| 167 | | "Cursor Palette Logical Colour 1", // 5 |
| 168 | | "Cursor Palette Logical Colour 2", // 6 |
| 169 | | "Cursor Palette Logical Colour 3", // 7 |
| 170 | | "Horizontal", // 8 |
| 171 | | "Vertical", // 9 |
| 172 | | "Stereo Image", // A |
| 173 | | "Sound", // B |
| 174 | | "External", // C |
| 175 | | "Frequency Synthesis", // D |
| 176 | | "Control", // E |
| 177 | | "Data Control" // F |
| 178 | | }; |
| 243 | int val = timer_count / 2; // correct? |
| 179 | 244 | |
| 245 | if(val==0) |
| 246 | timer_adjust_oneshot(IOMD_timer[timer], attotime_never, 0); |
| 247 | else |
| 248 | timer_adjust_periodic(IOMD_timer[timer], ATTOTIME_IN_USEC(val), 0, ATTOTIME_IN_USEC(val)); |
| 249 | } |
| 250 | |
| 251 | static TIMER_CALLBACK( IOMD_timer0_callback ) |
| 252 | { |
| 253 | IRQ_status_A|=0x20; |
| 254 | if(IRQ_mask_A&0x20) |
| 255 | { |
| 256 | generic_pulse_irq_line(machine->device("maincpu"), ARM7_IRQ_LINE); |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | static TIMER_CALLBACK( IOMD_timer1_callback ) |
| 261 | { |
| 262 | /* |
| 263 | PS7500_IO[IRQSTA]|=0x40; |
| 264 | if(PS7500_IO[IRQMSKA]&0x40) |
| 265 | { |
| 266 | generic_pulse_irq_line(machine->device("maincpu"), ARM7_IRQ_LINE); |
| 267 | } |
| 268 | */ |
| 269 | } |
| 270 | |
| 180 | 271 | static READ32_HANDLER( a7000_iomd_r ) |
| 181 | 272 | { |
| 273 | if(offset != IOMD_KBDCR) |
| 274 | logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); |
| 275 | |
| 276 | |
| 182 | 277 | switch(offset) |
| 183 | 278 | { |
| 184 | | case IOMD_ID0: return 0x000000e7; // IOMD ID low |
| 185 | | case IOMD_ID1: return 0x000000d4; // IOMD ID high |
| 186 | | default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break; |
| 279 | case IOMD_IOCR: |
| 280 | { |
| 281 | static UINT8 vblank = input_port_read(space->machine, "VBLANK") & 0x80; |
| 282 | |
| 283 | return IOMD_IO_ctrl | 0x34 | vblank; |
| 284 | } |
| 285 | case IOMD_KBDCR: return IOMD_keyb_ctrl | 0x80; //IOMD Keyb status |
| 286 | |
| 287 | /* |
| 288 | 1--- ---- always high |
| 289 | -x-- ---- Timer 1 |
| 290 | --x- ---- Timer 0 |
| 291 | ---x ---- Power On Reset |
| 292 | ---- x--- Flyback |
| 293 | ---- -x-- nINT1 |
| 294 | ---- --0- always low |
| 295 | ---- ---x INT2 |
| 296 | */ |
| 297 | case IOMD_IRQSTA: return (IRQ_status_A & ~2) | 0x80; |
| 298 | case IOMD_IRQRQA: return (IRQ_status_A & IRQ_mask_A) | 0x80; |
| 299 | case IOMD_IRQMSKA: return (IRQ_mask_A); |
| 300 | |
| 301 | case IOMD_T0LOW: return timer_out[0] & 0xff; |
| 302 | case IOMD_T0HIGH: return (timer_out[0] >> 8) & 0xff; |
| 303 | |
| 304 | case IOMD_ID0: return io_id & 0xff; // IOMD ID low |
| 305 | case IOMD_ID1: return (io_id >> 8) & 0xff; // IOMD ID high |
| 306 | // default: logerror("IOMD: %s Register (%04x) read\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4); break; |
| 187 | 307 | } |
| 188 | 308 | |
| 189 | 309 | return 0; |
| r8774 | r8775 | |
| 192 | 312 | static WRITE32_HANDLER( a7000_iomd_w ) |
| 193 | 313 | { |
| 194 | 314 | logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 195 | | } |
| 196 | 315 | |
| 316 | switch(offset) |
| 317 | { |
| 318 | case IOMD_IOCR: IOMD_IO_ctrl = data & ~0xf4; break; |
| 197 | 319 | |
| 198 | | static WRITE32_HANDLER( a7000_vidc20_w ) |
| 199 | | { |
| 200 | | int reg = data >> 28; |
| 201 | | int val = data & 0xffffff; |
| 320 | case IOMD_KBDCR: |
| 321 | IOMD_keyb_ctrl = data & ~0xf4; |
| 322 | //keyboard_ctrl_write(data & 0x08); |
| 323 | break; |
| 202 | 324 | |
| 203 | | switch(reg) |
| 204 | | { |
| 205 | | default: logerror("VIDC20: %s Register write = %08x\n",vidc20_regnames[reg],val); |
| 325 | case IOMD_IRQRQA: IRQ_status_A &= ~data; break; |
| 326 | case IOMD_IRQMSKA: IRQ_mask_A = (data & ~2) | 0x80; break; |
| 327 | |
| 328 | case IOMD_T0LOW: timer_in[0] = (timer_in[0] & 0xff00) | (data & 0xff); break; |
| 329 | case IOMD_T0HIGH: timer_in[0] = (timer_in[0] & 0x00ff) | ((data & 0xff) << 8); break; |
| 330 | case IOMD_T0GO: |
| 331 | timer_counter[0] = timer_in[0]; |
| 332 | fire_iomd_timer(0,timer_counter[0]); |
| 333 | break; |
| 334 | case IOMD_T0LATCH: |
| 335 | { |
| 336 | static UINT8 readinc; |
| 337 | readinc^=1; |
| 338 | timer_out[0] = timer_counter[0]; |
| 339 | if(readinc) |
| 340 | { |
| 341 | timer_counter[0]--; |
| 342 | if(timer_counter[0] < 0) |
| 343 | timer_counter[0]+= timer_in[0]; |
| 344 | } |
| 345 | } |
| 346 | break; |
| 347 | |
| 348 | //default: logerror("IOMD: %s Register (%04x) write = %08x\n",iomd_regnames[offset & (0x1ff >> 2)],offset*4,data); |
| 206 | 349 | } |
| 207 | 350 | } |
| 208 | 351 | |
| 209 | 352 | static ADDRESS_MAP_START( a7000_mem, ADDRESS_SPACE_PROGRAM, 32) |
| 210 | 353 | AM_RANGE(0x00000000, 0x007fffff) AM_MIRROR(0x00800000) AM_ROM AM_REGION("user1", 0x0) |
| 211 | | AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM |
| 212 | | AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM |
| 354 | // AM_RANGE(0x01000000, 0x01ffffff) AM_NOP //expansion ROM |
| 355 | // AM_RANGE(0x02000000, 0x02ffffff) AM_RAM //VRAM |
| 213 | 356 | // I/O 03000000 - 033fffff |
| 214 | 357 | AM_RANGE(0x03000000, 0x030001ff) AM_MIRROR(0x00200000) AM_READWRITE(a7000_iomd_r,a7000_iomd_w) //IOMD Registers |
| 215 | 358 | // AM_RANGE(0x03010000, 0x03011fff) //Super IO |
| r8774 | r8775 | |
| 220 | 363 | // AM_RANGE(0x03310000, 0x03310003) //Mouse Buttons |
| 221 | 364 | AM_RANGE(0x03400000, 0x037fffff) AM_WRITE(a7000_vidc20_w) |
| 222 | 365 | // AM_RANGE(0x08000000, 0x08ffffff) AM_MIRROR(0x07000000) //EASI space |
| 223 | | AM_RANGE(0x10000000, 0x10ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 0 bank 0 |
| 224 | | AM_RANGE(0x14000000, 0x14ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 0 bank 1 |
| 366 | AM_RANGE(0x10000000, 0x13ffffff) AM_RAM //SIMM 0 bank 0 |
| 367 | AM_RANGE(0x14000000, 0x17ffffff) AM_RAM //SIMM 0 bank 1 |
| 225 | 368 | // AM_RANGE(0x18000000, 0x18ffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 0 |
| 226 | 369 | // AM_RANGE(0x1c000000, 0x1cffffff) AM_MIRROR(0x03000000) AM_RAM //SIMM 1 bank 1 |
| 227 | 370 | ADDRESS_MAP_END |
| r8774 | r8775 | |
| 229 | 372 | |
| 230 | 373 | /* Input ports */ |
| 231 | 374 | static INPUT_PORTS_START( a7000 ) |
| 375 | PORT_START("VBLANK") |
| 376 | PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_VBLANK ) |
| 232 | 377 | INPUT_PORTS_END |
| 233 | 378 | |
| 379 | static MACHINE_START(a7000) |
| 380 | { |
| 381 | IOMD_timer[0] = timer_alloc(machine, IOMD_timer0_callback, NULL); |
| 382 | IOMD_timer[1] = timer_alloc(machine, IOMD_timer1_callback, NULL); |
| 234 | 383 | |
| 384 | io_id = 0xd4e7; |
| 385 | } |
| 386 | |
| 235 | 387 | static MACHINE_RESET(a7000) |
| 236 | 388 | { |
| 389 | IOMD_IO_ctrl = 0x0b | 0x34; //bit 0,1 and 3 set high on reset plus 2,4,5 always high |
| 390 | // IRQ_status_A = 0x10; // set POR bit ON |
| 391 | IRQ_mask_A = 0x00; |
| 392 | |
| 393 | IOMD_keyb_ctrl = 0x00; |
| 394 | |
| 395 | timer_adjust_oneshot( IOMD_timer[0], attotime_never, 0); |
| 396 | timer_adjust_oneshot( IOMD_timer[1], attotime_never, 0); |
| 237 | 397 | } |
| 238 | 398 | |
| 399 | static INTERRUPT_GEN( flyback_irq ) |
| 400 | { |
| 401 | IRQ_status_A|=0x08; |
| 402 | if(IRQ_mask_A&0x08) |
| 403 | { |
| 404 | generic_pulse_irq_line(device, ARM7_IRQ_LINE); |
| 405 | } |
| 406 | } |
| 239 | 407 | |
| 408 | |
| 240 | 409 | static MACHINE_DRIVER_START( a7000 ) |
| 241 | 410 | |
| 242 | 411 | /* Basic machine hardware */ |
| 243 | 412 | MDRV_CPU_ADD( "maincpu", ARM7, XTAL_32MHz ) |
| 244 | 413 | MDRV_CPU_PROGRAM_MAP( a7000_mem) |
| 414 | MDRV_CPU_VBLANK_INT( "screen", flyback_irq ) |
| 245 | 415 | |
| 416 | MDRV_MACHINE_START( a7000 ) |
| 246 | 417 | MDRV_MACHINE_RESET( a7000 ) |
| 247 | 418 | |
| 248 | | |
| 249 | 419 | /* video hardware */ |
| 250 | 420 | MDRV_SCREEN_ADD("screen", RASTER) |
| 251 | | MDRV_SCREEN_REFRESH_RATE(50) |
| 421 | MDRV_SCREEN_REFRESH_RATE(60) |
| 252 | 422 | MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ |
| 253 | 423 | MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) |
| 254 | 424 | MDRV_SCREEN_SIZE(640, 480) |
| 255 | 425 | MDRV_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1) |
| 256 | | MDRV_PALETTE_LENGTH(2) |
| 257 | | MDRV_PALETTE_INIT(black_and_white) |
| 426 | MDRV_PALETTE_LENGTH(0x200) |
| 427 | // MDRV_PALETTE_INIT(black_and_white) |
| 258 | 428 | |
| 259 | 429 | MDRV_VIDEO_START(a7000) |
| 260 | 430 | MDRV_VIDEO_UPDATE(a7000) |