URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [peripheral/] [fb.c] - Rev 1358
Go to most recent revision | Compare with Previous | Blame | View Log
/* fb.c -- Simple frame buffer 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 "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #endif #include "port.h" #include "arch.h" #include "sim-config.h" #include "abstract.h" #include "fb.h" #include "sched.h" #define FB_WRAP (512*1024) static unsigned long pal[256]; static int fb_ctrl = 0; static int fb_pic = 0; static int fb_in_refresh = 1; static int fb_refresh_count = 0; static oraddr_t fb_addr = 0; static oraddr_t cam_addr = 0; static int camerax = 0, cameray = 0, camera_pos = 0; static void change_buf_addr (oraddr_t addr) { fb_addr = addr; } /* Write a register */ void fb_write32 (oraddr_t addr, uint32_t value) { int a = (addr - config.fb.baseaddr); switch (a) { case FB_CTRL: fb_ctrl = value; break; case FB_BUFADDR: change_buf_addr (value); break; case FB_CAMBUFADDR: cam_addr = value; break; case FB_CAMPOSADDR: camera_pos = value; camerax = value % FB_SIZEX; cameray = value / FB_SIZEX; break; default: a -= FB_PAL; a /= 4; if (a < 0 || a >= 256) { fprintf (stderr, "Write out of palette buffer (0x%"PRIxADDR")!\n", addr); runtime.sim.cont_run = 0; } else pal[a] = value; break; } } /* Read a register */ oraddr_t fb_read32 (oraddr_t addr) { int a = (addr - config.fb.baseaddr); switch (a) { case FB_CTRL: return fb_ctrl & ~0xff000000| (fb_in_refresh ? 0x80000000 : 0) | ((unsigned long)(fb_refresh_count & 0x7f) << 24); break; case FB_BUFADDR: return fb_addr; break; case FB_CAMBUFADDR: return cam_addr; break; case FB_CAMPOSADDR: return camera_pos; break; default: a -= FB_PAL; a /= 4; if (a < 0 || a >= 256) { fprintf (stderr, "Read out of palette buffer (0x%"PRIxADDR")!\n", addr); runtime.sim.cont_run = 0; return 0; } else return pal[a]; } } /* define these also for big endian */ #if __BIG_ENDIAN__ #define CNV32(x) (\ ((((x) >> 24) & 0xff) << 0)\ | ((((x) >> 16) & 0xff) << 8)\ | ((((x) >> 8) & 0xff) << 16)\ | ((((x) >> 0) & 0xff) << 24)) #define CNV16(x) (\ ((((x) >> 8) & 0xff) << 0)\ | ((((x) >> 0) & 0xff) << 8)) #else #define CNV16(x) (x) #define CNV32(x) (x) #endif /* Dumps a bmp file, based on current image */ static int fb_dump_image8 (char *filename) { int sx = FB_SIZEX; int sy = FB_SIZEY; int i, x, y; FILE *fo; unsigned short int u16; unsigned long int u32; if (config.sim.verbose) PRINTF ("Creating %s...", filename); fo = fopen (filename, "wb+"); u16 = CNV16(19778); /* BM */ if (!fwrite (&u16, 2, 1, fo)) return 1; u32 = CNV32(14 + 40 + sx * sy + 1024); /* size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* reserved */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = 14 + 40 + 1024; /* offset */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(40); /* header size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(sx); /* width */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(sy); /* height */ if (!fwrite (&u32, 4, 1, fo)) return 1; u16 = CNV16(1); /* planes */ if (!fwrite (&u16, 2, 1, fo)) return 1; u16 = CNV16(8); /* bits */ if (!fwrite (&u16, 2, 1, fo)) return 1; u32 = CNV32(0); /* compression */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(x * y); /* image size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(2835); /* x resolution */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(2835); /* y resolution */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* ncolours = 0; should be generated */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* important colours; all are important */ if (!fwrite (&u32, 4, 1, fo)) return 1; for (i = 0; i < 256; i++) { unsigned long val, d; d = pal[i]; #if 1 val = ((d >> 0) & 0x1f) << 3; /* Blue */ val |= ((d >> 5) & 0x3f) << 10; /* Green */ val |= ((d >> 11) & 0x1f) << 19; /* Red */ #else val = CNV32(pal[i]); #endif if (!fwrite (&val, 4, 1, fo)) return 1; } if (config.sim.verbose) PRINTF ("(%i,%i)", sx, sy); /* Data is stored upside down */ for (y = sy - 1; y >= 0; y--) { int align = (4 - sx) % 4; int zero = CNV32(0); int add; while (align < 0) align += 4; for (x = 0; x < sx; x++) { add = (fb_addr & ~(FB_WRAP - 1)) | ((fb_addr + y * sx + x) & (FB_WRAP - 1)); fputc (evalsim_mem8 (add), fo); } if (align && !fwrite (&zero, align, 1, fo)) return 1; } if (config.sim.verbose) PRINTF ("DONE\n"); fclose (fo); return 0; } /* Dumps a bmp file, based on current image */ static int fb_dump_image24 (char *filename) { int sx = FB_SIZEX; int sy = FB_SIZEY; int x, y; FILE *fo; unsigned short int u16; unsigned long int u32; if (config.sim.verbose) PRINTF ("Creating %s...", filename); fo = fopen (filename, "wb+"); u16 = CNV16(19778); /* BM */ if (!fwrite (&u16, 2, 1, fo)) return 1; u32 = CNV32(14 + 40 + sx * sy * 3); /* size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* reserved */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = 14 + 40; /* offset */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(40); /* header size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(sx); /* width */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(sy); /* height */ if (!fwrite (&u32, 4, 1, fo)) return 1; u16 = CNV16(1); /* planes */ if (!fwrite (&u16, 2, 1, fo)) return 1; u16 = CNV16(24); /* bits */ if (!fwrite (&u16, 2, 1, fo)) return 1; u32 = CNV32(0); /* compression */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(x * y * 3); /* image size */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(2835); /* x resolution */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(2835); /* y resolution */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* ncolours = 0; should be generated */ if (!fwrite (&u32, 4, 1, fo)) return 1; u32 = CNV32(0); /* important colours; all are important */ if (!fwrite (&u32, 4, 1, fo)) return 1; if (config.sim.verbose) PRINTF ("(%i,%i)", sx, sy); /* Data is stored upside down */ for (y = sy - 1; y >= 0; y--) { unsigned char line[FB_SIZEX][3]; for (x = 0; x < sx; x++) if (y >= cameray && x >= camerax && y < cameray + CAM_SIZEY && x < camerax + CAM_SIZEX) { int add = (cam_addr + (x - camerax + (y - cameray) * CAM_SIZEX) * 2) ^ 2; unsigned short d = evalsim_mem16 (add); line[x][0] = ((d >> 0) & 0x1f) << 3; /* Blue */ line[x][1] = ((d >> 5) & 0x3f) << 2; /* Green */ line[x][2] = ((d >> 11) & 0x1f) << 3; /* Red */ } else { int add = (fb_addr & ~(FB_WRAP - 1)) | ((fb_addr + y * sx + x) & (FB_WRAP - 1)); unsigned short d = pal[evalsim_mem8 (add)]; line[x][0] = ((d >> 0) & 0x1f) << 3; /* Blue */ line[x][1] = ((d >> 5) & 0x3f) << 2; /* Green */ line[x][2] = ((d >> 11) & 0x1f) << 3; /* Red */ } if(!fwrite (line, sizeof(line), 1, fo)) return 1; } if (config.sim.verbose) PRINTF ("DONE\n"); fclose (fo); return 0; } void fb_job (int param) { if (param) { /* dump the image? */ if (fb_ctrl & 1) { char temp[STR_SIZE]; sprintf (temp, "%s%04i.bmp", &config.fb.filename[0], fb_pic); if (fb_ctrl & 2) fb_dump_image24 (temp); else fb_dump_image8 (temp); fb_pic++; } SCHED_ADD(fb_job, 0, runtime.sim.cycles + config.fb.refresh_rate - config.fb.refresh_rate / REFRESH_DIVIDER); fb_in_refresh = 0; } else { fb_refresh_count++; SCHED_ADD(fb_job, 1, runtime.sim.cycles + config.fb.refresh_rate / REFRESH_DIVIDER); } } /* Reset all VGAs */ void fb_reset () { int i; if (config.fb.enabled) { fb_pic = 0; fb_addr = 0; fb_ctrl = 0; for (i = 0; i < 256; i++) pal[i] = (i << 16) | (i << 8) | (i << 0); if (config.fb.baseaddr) register_memoryarea(config.fb.baseaddr, FB_PAL + 256*4, 4, 0, fb_read32, fb_write32); SCHED_ADD(fb_job, 0, runtime.sim.cycles + config.fb.refresh_rate); } } /*-----------------------------------------------------[ FB configuration ]---*/ void fb_enabled(union param_val val, void *dat) { config.fb.enabled = val.int_val; } void fb_baseaddr(union param_val val, void *dat) { config.fb.baseaddr = val.addr_val; } void fb_refresh_rate(union param_val val, void *dat) { config.fb.refresh_rate = val.int_val; } void fb_filename(union param_val val, void *dat) { strcpy(config.fb.filename, val.str_val); } void reg_fb_sec(void) { struct config_section *sec = reg_config_sec("fb", NULL, NULL); reg_config_param(sec, "enabled", paramt_int, fb_enabled); reg_config_param(sec, "baseaddr", paramt_addr, fb_baseaddr); reg_config_param(sec, "refresh_rate", paramt_int, fb_refresh_rate); reg_config_param(sec, "filename", paramt_str, fb_filename); }
Go to most recent revision | Compare with Previous | Blame | View Log