src/mess/video/upd7220.c
| r4447 | r4448 | |
| 2 | 2 | #include "upd7220.h"
|
| 3 | 3 | |
| 4 | 4 | /***************************************************************************
|
| 5 | PARAMETERS
|
| 6 | ***************************************************************************/
|
| 7 | |
| 8 | #define UPD7220_COMMAND_RESET 0x00
|
| 9 | #define UPD7220_COMMAND_SYNC 0x0e // & 0xfe
|
| 10 | #define UPD7220_COMMAND_VSYNC 0x6e // & 0xfe
|
| 11 | #define UPD7220_COMMAND_CCHAR 0x4b
|
| 12 | #define UPD7220_COMMAND_START 0x6b
|
| 13 | #define UPD7220_COMMAND_BCTRL 0x0c // & 0xfe
|
| 14 | #define UPD7220_COMMAND_ZOOM 0x46
|
| 15 | #define UPD7220_COMMAND_CURS 0x49
|
| 16 | #define UPD7220_COMMAND_PRAM 0x70 // & 0xf0
|
| 17 | #define UPD7220_COMMAND_PITCH 0x47
|
| 18 | #define UPD7220_COMMAND_WDAT 0x20 // & 0xe4
|
| 19 | #define UPD7220_COMMAND_MASK 0x4a
|
| 20 | #define UPD7220_COMMAND_FIGS 0x4c
|
| 21 | #define UPD7220_COMMAND_FIGD 0x6c
|
| 22 | #define UPD7220_COMMAND_GCHRD 0x68
|
| 23 | #define UPD7220_COMMAND_RDAT 0xa0 // & 0xe4
|
| 24 | #define UPD7220_COMMAND_CURD 0xe0
|
| 25 | #define UPD7220_COMMAND_LPRD 0xc0
|
| 26 | #define UPD7220_COMMAND_DMAR 0xa4 // & 0xe4
|
| 27 | #define UPD7220_COMMAND_DMAW 0x24 // & 0xe4
|
| 28 | |
| 29 | #define UPD7220_SR_DATA_READY 0x01
|
| 30 | #define UPD7220_SR_FIFO_FULL 0x02
|
| 31 | #define UPD7220_SR_FIFO_EMPTY 0x04
|
| 32 | #define UPD7220_SR_DRAWING_IN_PROGRESS 0x08
|
| 33 | #define UPD7220_SR_DMA_EXECUTE 0x10
|
| 34 | #define UPD7220_SR_VSYNC_ACTIVE 0x20
|
| 35 | #define UPD7220_SR_HBLANK_ACTIVE 0x40
|
| 36 | #define UPD7220_SR_LIGHT_PEN_DETECT 0x80
|
| 37 | |
| 38 | /***************************************************************************
|
| 5 | 39 | TYPE DEFINITIONS
|
| 6 | 40 | ***************************************************************************/
|
| 7 | 41 | |
| 8 | 42 | typedef struct _upd7220_t upd7220_t;
|
| 9 | 43 | struct _upd7220_t
|
| 10 | 44 | {
|
| 45 | devcb_resolved_read8 in_data_func;
|
| 46 | devcb_resolved_write8 out_data_func;
|
| 11 | 47 | devcb_resolved_write_line out_drq_func;
|
| 12 | 48 | devcb_resolved_write_line out_hsync_func;
|
| 13 | 49 | devcb_resolved_write_line out_vsync_func;
|
| 50 | devcb_resolved_write_line out_blank_func;
|
| 14 | 51 | |
| 52 | int clock; |
| 53 | |
| 54 | UINT8 ra[16]; /* parameter RAM */
|
| 55 | |
| 56 | UINT8 sr; /* status register */
|
| 57 | UINT8 mode; /* mode of operation */
|
| 58 | |
| 59 | int de; /* display enabled */
|
| 60 | int aw; /* active display words per line - 2 (must be even number with bit 0 = 0) */
|
| 61 | int al; /* active display lines per video field */
|
| 62 | int vs; /* vertical sync width - 1 */
|
| 63 | int vfp; /* vertical front porch width - 1 */
|
| 64 | int vbp; /* vertical back porch width - 1 */
|
| 65 | int hs; /* horizontal sync width - 1 */
|
| 66 | int hfp; /* horizontal front porch width - 1 */
|
| 67 | int hbp; /* horizontal back porch width - 1 */
|
| 68 | int m; /* 0 = accept external vertical sync (slave mode) / 1 = generate & output vertical sync (master mode) */
|
| 69 | |
| 70 | int dc; /* display cursor */
|
| 71 | int sc; /* 0 = blinking cursor / 1 = steady cursor */
|
| 72 | int br; /* blink rate */
|
| 73 | int lr; /* lines per character row - 1 */
|
| 74 | int ctop; /* cursor top line number in the row */
|
| 75 | int cbot; /* cursor bottom line number in the row (CBOT < LR) */
|
| 76 | UINT32 ead; /* execute word address */
|
| 77 | UINT16 dad; /* dot address within the word */
|
| 78 | UINT32 lad; /* light pen address */
|
| 79 |
|
| 80 | int disp; /* display zoom factor */
|
| 81 | int gchr; /* zoom factor for graphics character writing and area filling */
|
| 82 | UINT16 mask; /* mask register */
|
| 83 | UINT8 pitch; /* number of word addresses in display memory in the horizontal direction */
|
| 84 | |
| 85 | /* timers */
|
| 86 | emu_timer *vsync_timer; /* vertical sync timer */
|
| 87 | emu_timer *hsync_timer; /* horizontal sync timer */
|
| 88 | emu_timer *blank_timer; /* CRT blanking timer */
|
| 89 | |
| 15 | 90 | const device_config *screen; /* screen */
|
| 16 | 91 | };
|
| 17 | 92 | |
| r4447 | r4448 | |
| 23 | 98 | {
|
| 24 | 99 | assert(device != NULL);
|
| 25 | 100 | assert(device->token != NULL);
|
| 26 | | |
| 27 | 101 | return (upd7220_t *)device->token;
|
| 28 | 102 | }
|
| 29 | 103 | |
| r4447 | r4448 | |
| 34 | 108 | return (const upd7220_interface *) device->static_config;
|
| 35 | 109 | }
|
| 36 | 110 | |
| 111 | INLINE void queue(upd7220_t *upd7220, UINT8 data, int command)
|
| 112 | {
|
| 113 | }
|
| 114 | |
| 115 | INLINE UINT16 dequeue(upd7220_t *upd7220)
|
| 116 | {
|
| 117 | return 0;
|
| 118 | }
|
| 119 | |
| 37 | 120 | /***************************************************************************
|
| 38 | 121 | IMPLEMENTATION
|
| 39 | 122 | ***************************************************************************/
|
| 40 | 123 | |
| 41 | 124 | /*-------------------------------------------------
|
| 125 | recompute_parameters - |
| 126 | -------------------------------------------------*/
|
| 127 | #ifdef UNUSED_FUNCTION
|
| 128 | static void recompute_parameters(upd7220_t *upd7220)
|
| 129 | {
|
| 130 | rectangle visarea;
|
| 131 | |
| 132 | int horiz_pix_total;
|
| 133 | int vert_pix_total;
|
| 134 | |
| 135 | attoseconds_t refresh = HZ_TO_ATTOSECONDS(upd7220->clock) * (upd7220->aw + 2) * upd7220->al;
|
| 136 | |
| 137 | visarea.min_x = upd7220->hs + upd7220->hbp + 1;
|
| 138 | visarea.min_y = upd7220->vs + upd7220->vbp + 1;
|
| 139 | visarea.max_x = 0;
|
| 140 | visarea.max_y = upd7220->al + 2 - upd7220->vfp;
|
| 141 | |
| 142 | video_screen_configure(upd7220->screen, horiz_pix_total, vert_pix_total, &visarea, refresh);
|
| 143 | }
|
| 144 | #endif
|
| 145 | /*-------------------------------------------------
|
| 146 | update_vsync_timer - |
| 147 | -------------------------------------------------*/
|
| 148 | |
| 149 | static void update_vsync_timer(upd7220_t *upd7220, int state)
|
| 150 | {
|
| 151 | int next_y = state ? (upd7220->vs + 1) : 0;
|
| 152 | |
| 153 | attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, 0);
|
| 154 | |
| 155 | timer_adjust_oneshot(upd7220->vsync_timer, duration, !state);
|
| 156 | }
|
| 157 | |
| 158 | /*-------------------------------------------------
|
| 159 | TIMER_CALLBACK( vsync_tick )
|
| 160 | -------------------------------------------------*/
|
| 161 | |
| 162 | static TIMER_CALLBACK( vsync_tick )
|
| 163 | {
|
| 164 | const device_config *device = ptr;
|
| 165 | upd7220_t *upd7220 = get_safe_token(device);
|
| 166 | |
| 167 | devcb_call_write_line(&upd7220->out_vsync_func, param);
|
| 168 | |
| 169 | update_vsync_timer(upd7220, param);
|
| 170 | }
|
| 171 | |
| 172 | /*-------------------------------------------------
|
| 173 | update_hsync_timer - |
| 174 | -------------------------------------------------*/
|
| 175 | |
| 176 | static void update_hsync_timer(upd7220_t *upd7220, int state)
|
| 177 | {
|
| 178 | int y = video_screen_get_vpos(upd7220->screen);
|
| 179 | |
| 180 | int next_x = state ? upd7220->hs : 0;
|
| 181 | int next_y = state ? y : ((y + 1) % upd7220->al);
|
| 182 | |
| 183 | attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
|
| 184 | |
| 185 | timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
|
| 186 | }
|
| 187 | |
| 188 | /*-------------------------------------------------
|
| 189 | TIMER_CALLBACK( hsync_tick )
|
| 190 | -------------------------------------------------*/
|
| 191 | |
| 192 | static TIMER_CALLBACK( hsync_tick )
|
| 193 | {
|
| 194 | const device_config *device = ptr;
|
| 195 | upd7220_t *upd7220 = get_safe_token(device);
|
| 196 | |
| 197 | devcb_call_write_line(&upd7220->out_hsync_func, param);
|
| 198 | |
| 199 | update_hsync_timer(upd7220, param);
|
| 200 | }
|
| 201 | |
| 202 | /*-------------------------------------------------
|
| 203 | update_blank_timer - |
| 204 | -------------------------------------------------*/
|
| 205 | |
| 206 | static void update_blank_timer(upd7220_t *upd7220, int state)
|
| 207 | {
|
| 208 | int y = video_screen_get_vpos(upd7220->screen);
|
| 209 | |
| 210 | int next_x = state ? (upd7220->hs + upd7220->hbp + 1) : 0;
|
| 211 | int next_y = state ? y : ((y + 1) % upd7220->al);
|
| 212 | |
| 213 | attotime duration = video_screen_get_time_until_pos(upd7220->screen, next_y, next_x);
|
| 214 | |
| 215 | timer_adjust_oneshot(upd7220->hsync_timer, duration, !state);
|
| 216 | }
|
| 217 | |
| 218 | /*-------------------------------------------------
|
| 219 | TIMER_CALLBACK( blank_tick )
|
| 220 | -------------------------------------------------*/
|
| 221 | |
| 222 | static TIMER_CALLBACK( blank_tick )
|
| 223 | {
|
| 224 | const device_config *device = ptr;
|
| 225 | upd7220_t *upd7220 = get_safe_token(device);
|
| 226 | |
| 227 | devcb_call_write_line(&upd7220->out_blank_func, param);
|
| 228 | |
| 229 | update_blank_timer(upd7220, param);
|
| 230 | }
|
| 231 | |
| 232 | /*-------------------------------------------------
|
| 233 | process_command - process command
|
| 234 | -------------------------------------------------*/
|
| 235 | |
| 236 | #ifdef UNUSED_CODE
|
| 237 | static void process_command(upd7220_t *upd7220, UINT8 data)
|
| 238 | {
|
| 239 | switch (data)
|
| 240 | {
|
| 241 | case UPD7220_COMMAND_RESET:
|
| 242 | break;
|
| 243 | case UPD7220_COMMAND_CCHAR:
|
| 244 | break;
|
| 245 | case UPD7220_COMMAND_START:
|
| 246 | break;
|
| 247 | case UPD7220_COMMAND_ZOOM:
|
| 248 | break;
|
| 249 | case UPD7220_COMMAND_CURS:
|
| 250 | break;
|
| 251 | case UPD7220_COMMAND_PITCH:
|
| 252 | break;
|
| 253 | case UPD7220_COMMAND_MASK:
|
| 254 | break;
|
| 255 | case UPD7220_COMMAND_FIGS:
|
| 256 | break;
|
| 257 | case UPD7220_COMMAND_FIGD:
|
| 258 | break;
|
| 259 | case UPD7220_COMMAND_CURD:
|
| 260 | break;
|
| 261 | case UPD7220_COMMAND_LPRD:
|
| 262 | break;
|
| 263 | default:
|
| 264 | switch (data & 0xfe)
|
| 265 | {
|
| 266 | case UPD7220_COMMAND_SYNC:
|
| 267 | break;
|
| 268 | case UPD7220_COMMAND_VSYNC:
|
| 269 | break;
|
| 270 | case UPD7220_COMMAND_BCTRL:
|
| 271 | break;
|
| 272 | default:
|
| 273 | switch (data & 0xf0)
|
| 274 | {
|
| 275 | case UPD7220_COMMAND_PRAM:
|
| 276 | default:
|
| 277 | switch (data & 0xe4)
|
| 278 | {
|
| 279 | case UPD7220_COMMAND_WDAT:
|
| 280 | break;
|
| 281 | case UPD7220_COMMAND_RDAT:
|
| 282 | break;
|
| 283 | case UPD7220_COMMAND_DMAR:
|
| 284 | break;
|
| 285 | case UPD7220_COMMAND_DMAW:
|
| 286 | break;
|
| 287 | default:
|
| 288 | logerror("Invalid command %02x\n", data);
|
| 289 | }
|
| 290 | }
|
| 291 | }
|
| 292 | }
|
| 293 | }
|
| 294 | #endif
|
| 295 | |
| 296 | /*-------------------------------------------------
|
| 42 | 297 | upd7220_r - register read
|
| 43 | 298 | -------------------------------------------------*/
|
| 44 | 299 | |
| 45 | 300 | READ8_DEVICE_HANDLER( upd7220_r )
|
| 46 | 301 | {
|
| 47 | | return 0;
|
| 302 | upd7220_t *upd7220 = get_safe_token(device);
|
| 303 | |
| 304 | UINT8 data;
|
| 305 | |
| 306 | if (offset & 1)
|
| 307 | {
|
| 308 | /* FIFO read */
|
| 309 | data = dequeue(upd7220);
|
| 310 | }
|
| 311 | else
|
| 312 | {
|
| 313 | /* status register */
|
| 314 | data = upd7220->sr;
|
| 315 | }
|
| 316 | |
| 317 | return data;
|
| 48 | 318 | }
|
| 49 | 319 | |
| 50 | 320 | /*-------------------------------------------------
|
| r4447 | r4448 | |
| 53 | 323 | |
| 54 | 324 | WRITE8_DEVICE_HANDLER( upd7220_w )
|
| 55 | 325 | {
|
| 326 | upd7220_t *upd7220 = get_safe_token(device);
|
| 327 | |
| 328 | if (offset & 1)
|
| 329 | {
|
| 330 | /* command into FIFO */
|
| 331 | queue(upd7220, data, 1);
|
| 332 | }
|
| 333 | else
|
| 334 | {
|
| 335 | /* parameter into FIFO */
|
| 336 | queue(upd7220, data, 0);
|
| 337 | }
|
| 56 | 338 | }
|
| 57 | 339 | |
| 58 | 340 | /*-------------------------------------------------
|
| r4447 | r4448 | |
| 64 | 346 | }
|
| 65 | 347 | |
| 66 | 348 | /*-------------------------------------------------
|
| 349 | upd7220_lpen_w - light pen strobe
|
| 350 | -------------------------------------------------*/
|
| 351 | |
| 352 | void upd7220_lpen_w(const device_config *device, int state)
|
| 353 | {
|
| 354 | }
|
| 355 | |
| 356 | /*-------------------------------------------------
|
| 357 | ROM( upd7220 )
|
| 358 | -------------------------------------------------*/
|
| 359 | |
| 360 | ROM_START( upd7220 )
|
| 361 | ROM_REGION( 0x100, "upd7220", ROMREGION_LOADBYNAME )
|
| 362 | ROM_LOAD( "upd7220.bin", 0x000, 0x100, NO_DUMP ) /* internal 128x14 control ROM */
|
| 363 | ROM_END
|
| 364 | |
| 365 | /*-------------------------------------------------
|
| 67 | 366 | DEVICE_START( upd7220 )
|
| 68 | 367 | -------------------------------------------------*/
|
| 69 | 368 | |
| r4447 | r4448 | |
| 73 | 372 | const upd7220_interface *intf = get_interface(device);
|
| 74 | 373 | |
| 75 | 374 | /* resolve callbacks */
|
| 375 | devcb_resolve_read8(&upd7220->in_data_func, &intf->in_data_func, device);
|
| 376 | devcb_resolve_write8(&upd7220->out_data_func, &intf->out_data_func, device);
|
| 76 | 377 | devcb_resolve_write_line(&upd7220->out_drq_func, &intf->out_drq_func, device);
|
| 77 | 378 | devcb_resolve_write_line(&upd7220->out_hsync_func, &intf->out_hsync_func, device);
|
| 78 | 379 | devcb_resolve_write_line(&upd7220->out_vsync_func, &intf->out_vsync_func, device);
|
| r4447 | r4448 | |
| 80 | 381 | /* get the screen device */
|
| 81 | 382 | upd7220->screen = devtag_get_device(device->machine, intf->screen_tag);
|
| 82 | 383 | assert(upd7220->screen != NULL);
|
| 384 | |
| 385 | /* create the timers */
|
| 386 | upd7220->vsync_timer = timer_alloc(device->machine, vsync_tick, (void *)device);
|
| 387 | upd7220->hsync_timer = timer_alloc(device->machine, hsync_tick, (void *)device);
|
| 388 | upd7220->blank_timer = timer_alloc(device->machine, blank_tick, (void *)device);
|
| 389 | |
| 390 | /* register for state saving */
|
| 391 | state_save_register_device_item_array(device, 0, upd7220->ra);
|
| 392 | state_save_register_device_item(device, 0, upd7220->sr);
|
| 393 | state_save_register_device_item(device, 0, upd7220->mode);
|
| 394 | state_save_register_device_item(device, 0, upd7220->de);
|
| 395 | state_save_register_device_item(device, 0, upd7220->aw);
|
| 396 | state_save_register_device_item(device, 0, upd7220->al);
|
| 397 | state_save_register_device_item(device, 0, upd7220->vs);
|
| 398 | state_save_register_device_item(device, 0, upd7220->vfp);
|
| 399 | state_save_register_device_item(device, 0, upd7220->vbp);
|
| 400 | state_save_register_device_item(device, 0, upd7220->hs);
|
| 401 | state_save_register_device_item(device, 0, upd7220->hfp);
|
| 402 | state_save_register_device_item(device, 0, upd7220->hbp);
|
| 403 | state_save_register_device_item(device, 0, upd7220->m);
|
| 404 | state_save_register_device_item(device, 0, upd7220->dc);
|
| 405 | state_save_register_device_item(device, 0, upd7220->sc);
|
| 406 | state_save_register_device_item(device, 0, upd7220->br);
|
| 407 | state_save_register_device_item(device, 0, upd7220->lr);
|
| 408 | state_save_register_device_item(device, 0, upd7220->ctop);
|
| 409 | state_save_register_device_item(device, 0, upd7220->cbot);
|
| 410 | state_save_register_device_item(device, 0, upd7220->ead);
|
| 411 | state_save_register_device_item(device, 0, upd7220->dad);
|
| 412 | state_save_register_device_item(device, 0, upd7220->lad);
|
| 413 | state_save_register_device_item(device, 0, upd7220->disp);
|
| 414 | state_save_register_device_item(device, 0, upd7220->gchr);
|
| 415 | state_save_register_device_item(device, 0, upd7220->mask);
|
| 416 | state_save_register_device_item(device, 0, upd7220->pitch);
|
| 83 | 417 | }
|
| 84 | 418 | |
| 85 | 419 | /*-------------------------------------------------
|
| r4447 | r4448 | |
| 118 | 452 | case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
|
| 119 | 453 | case DEVINFO_INT_CLASS: info->i = DEVICE_CLASS_PERIPHERAL; break;
|
| 120 | 454 | |
| 455 | /* --- the following bits of info are returned as pointers --- */
|
| 456 | case DEVINFO_PTR_ROM_REGION: info->romregion = ROM_NAME(upd7220); break;
|
| 457 | |
| 121 | 458 | /* --- the following bits of info are returned as pointers to data or functions --- */
|
| 122 | 459 | case DEVINFO_FCT_SET_INFO: info->set_info = DEVICE_SET_INFO_NAME(upd7220); break;
|
| 123 | 460 | case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(upd7220); break;
|