URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [peripheral/] [vga.c] - Rev 1358
Go to most recent revision | Compare with Previous | Blame | View Log
/* vga.c -- Definition of types and structures for VGA/LCD Copyright (C) 2001 Marko Mlinar, markom@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <string.h> #include "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "port.h" #include "arch.h" #include "sim-config.h" #include "vga.h" #include "abstract.h" #include "sched.h" /* When this counter reaches config.vgas[].refresh_rate, a screenshot is taken and outputted */ static struct { int pics; unsigned long ctrl, stat, htim, vtim; int vbindex; unsigned long vbar[2]; unsigned hlen, vlen; int pindex; unsigned long palette[2][256]; } vga[MAX_VGAS]; /* Write a register */ void vga_write32(oraddr_t addr, uint32_t value) { int i, found = -1; /* Find which controller this is */ for (i = 0; i < config.nvgas; i++ ) { if ((addr >= config.vgas[i].baseaddr) && (addr < config.vgas[i].baseaddr + VGA_ADDR_SPACE)) { found = i; break; } } if (found < 0) { fprintf( stderr, "vga_write32( 0x%"PRIxADDR" ): Out of range\n", addr); runtime.sim.cont_run = 0; return; } addr -= config.vgas[found].baseaddr; switch (addr) { case VGA_CTRL: vga[found].ctrl = value; break; case VGA_STAT: vga[found].stat = value; break; case VGA_HTIM: vga[found].htim = value; break; case VGA_VTIM: vga[found].vtim = value; break; case VGA_HVLEN: vga[found].hlen = (value >> 16) + 2; vga[found].hlen = (value & 0xffff) + 2; break; case VGA_VBARA: vga[found].vbar[0] = value; break; case VGA_VBARB: vga[found].vbar[1] = value; break; default: if (addr >= VGA_CLUTA && addr < VGA_CLUTB) { vga[found].palette[0][addr - VGA_CLUTA] = value & 0x00ffffff; } else if (addr >= VGA_CLUTB) { vga[found].palette[1][addr - VGA_CLUTB] = value & 0x00ffffff; } else { fprintf( stderr, "vga_write32( 0x%"PRIxADDR", 0x%08"PRIx32" ): Out of range\n", addr + config.vgas[found].baseaddr, value); runtime.sim.cont_run = 0; return; } break; } } /* Read a register */ uint32_t vga_read32(oraddr_t addr) { int i, found = -1; /* Find which controller this is */ for (i = 0; i < config.nvgas; i++ ) { if ((addr >= config.vgas[i].baseaddr) && (addr < config.vgas[i].baseaddr + VGA_ADDR_SPACE)) { found = i; break; } } if (found < 0) { fprintf( stderr, "vga_read32( 0x%"PRIxADDR" ): Out of range\n", addr); runtime.sim.cont_run = 0; return 0; } addr -= config.vgas[found].baseaddr; switch (addr) { case VGA_CTRL: return vga[found].ctrl; case VGA_STAT: return vga[found].stat; case VGA_HTIM: return vga[found].htim; case VGA_VTIM: return vga[found].vtim; case VGA_HVLEN: return ((vga[found].hlen - 2) << 16) | (vga[found].vlen - 2); case VGA_VBARA: return vga[found].vbar[0]; case VGA_VBARB: return vga[found].vbar[1]; default: if (addr >= VGA_CLUTA && addr < VGA_CLUTB) { return vga[found].palette[0][addr - VGA_CLUTA]; } else if (addr >= VGA_CLUTB) { return vga[found].palette[1][addr - VGA_CLUTB]; } else { fprintf( stderr, "vga_read32( 0x%"PRIxADDR" ): Out of range\n", addr); runtime.sim.cont_run = 0; return 0; } break; } return 0; } /* This code will only work on little endian machines */ #ifdef __BIG_ENDIAN__ #warning Image dump not supported on big endian machines static int vga_dump_image (char *filename, int v) { return 1; } #else typedef struct { unsigned short int type; /* Magic identifier */ unsigned int size; /* File size in bytes */ unsigned short int reserved1, reserved2; unsigned int offset; /* Offset to image data, bytes */ } BMP_HEADER; typedef struct { unsigned int size; /* Header size in bytes */ int width,height; /* Width and height of image */ unsigned short int planes; /* Number of colour planes */ unsigned short int bits; /* Bits per pixel */ unsigned int compression; /* Compression type */ unsigned int imagesize; /* Image size in bytes */ int xresolution,yresolution; /* Pixels per meter */ unsigned int ncolours; /* Number of colours */ unsigned int importantcolours; /* Important colours */ } INFOHEADER; /* Dumps a bmp file, based on current image */ static int vga_dump_image (char *filename, int v) { int sx = vga[v].hlen; int sy = vga[v].vlen; int i, x, y; int pc = vga[v].ctrl & VGA_CTRL_PC; int rbpp = vga[v].ctrl & VGA_CTRL_CD; int bpp = rbpp >> 8; BMP_HEADER bh; INFOHEADER ih; FILE *fo; if (!sx || !sy) return; /* 16bpp and 32 bpp will be converted to 24bpp */ if (bpp == 1 || bpp == 3) bpp = 2; bh.type = 19778; /* BM */ bh.size = sizeof (BMP_HEADER) + sizeof (INFOHEADER) + sx * sy * (bpp * 4 + 4) + (pc ? 1024 : 0); bh.reserved1 = bh.reserved2 = 0; bh.offset = sizeof (BMP_HEADER) + sizeof (INFOHEADER) + (pc ? 1024 : 0); ih.size = sizeof (INFOHEADER); ih.width = sx; ih.height = sy; ih.planes = 1; ih.bits = bpp * 4 + 4; ih.compression = 0; ih.imagesize = x * y * (bpp * 4 + 4); ih.xresolution = ih.yresolution = 0; ih.ncolours = 0; /* should be generated */ ih.importantcolours = 0; /* all are important */ fo = fopen (filename, "wb+"); if (!fwrite (&bh, sizeof (BMP_HEADER), 1, fo)) return 1; if (!fwrite (&ih, sizeof (INFOHEADER), 1, fo)) return 1; if (pc) { /* Write palette? */ for (i = 0; i < 256; i++) { unsigned long val, d; d = vga[v].palette[vga[v].pindex][i]; val = (d >> 0) & 0xff; /* Blue */ val |= (d >> 8) & 0xff; /* Green */ val |= (d >> 16) & 0xff; /* Red */ if (!fwrite (&val, sizeof (val), 1, fo)) return 1; } } /* Data is stored upside down */ for (y = sy - 1; y >= 0; y--) { int align = 4 - ((bpp + 1) * sx) % 4; int zero = 0; for (x = 0; x < sx; x++) { unsigned long pixel = evalsim_mem32 (vga[v].vbar[vga[v].vbindex] + (y * sx + x) * (bpp + 1)); if (!fwrite (&pixel, sizeof (pixel), 1, fo)) return 1; } if (!fwrite (&zero, align, 1, fo)) return 1; } fclose (fo); return 0; } #endif /* !__BIG_ENDIAN__ */ void vga_job (int param) { /* dump the image? */ char temp[STR_SIZE]; sprintf (temp, "%s%04i.bmp", config.vgas[param].filename, vga[param].pics++); vga_dump_image (temp, param); SCHED_ADD(vga_job, param, runtime.sim.cycles + config.vgas[param].refresh_rate); } /* Reset all VGAs */ void vga_reset () { int i, j; for (i = 0; i < config.nvgas; i++) { /* Init palette */ for (j = 0; j < 256; j++) vga[i].palette[0][j] = vga[i].palette[1][j] = 0; vga[i].ctrl = vga[i].stat = vga[i].htim = vga[i].vtim = 0; vga[i].hlen = vga[i].vlen = 0; vga[i].vbar[0] = vga[i].vbar[1] = 0; /* Init screen dumping machine */ vga[i].pics = 0; vga[i].pindex = 0; vga[i].vbindex = 0; if (config.vgas[i].baseaddr) register_memoryarea(config.vgas[i].baseaddr, VGA_ADDR_SPACE, 4, 0, vga_read32, vga_write32); SCHED_ADD(vga_job, i, runtime.sim.cycles + config.vgas[i].refresh_rate); } } /*----------------------------------------------------[ VGA Configuration ]---*/ void vga_nvgas(union param_val val, void *dat) { if (val.int_val >= 0 && val.int_val < MAX_VGAS) config.nvgas = val.int_val; else CONFIG_ERROR("invalid number of devices."); } void vga_baseaddr(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.nvgas) config.vgas[current_device].baseaddr = val.addr_val; else CONFIG_ERROR("invalid device number."); } void vga_irq(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.nvgas) config.vgas[current_device].irq = val.int_val; else CONFIG_ERROR("invalid device number."); } void vga_refresh_rate(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.nvgas) config.vgas[current_device].refresh_rate = val.int_val; else CONFIG_ERROR("invalid device number."); } void vga_filename(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.nvgas) strcpy (config.vgas[current_device].filename, val.str_val); else CONFIG_ERROR("invalid device number."); } void reg_vga_sec(void) { struct config_section *sec = reg_config_sec("vga", NULL, NULL); reg_config_param(sec, "nvgas", paramt_int, vga_nvgas); reg_config_param(sec, "device", paramt_int, change_device); reg_config_param(sec, "baseaddr", paramt_addr, vga_baseaddr); reg_config_param(sec, "irq", paramt_int, vga_irq); reg_config_param(sec, "refresh_rate", paramt_int, vga_refresh_rate); reg_config_param(sec, "filename", paramt_str, vga_filename); reg_config_param(sec, "enddevice", paramt_none, end_device); }
Go to most recent revision | Compare with Previous | Blame | View Log