OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [fb.c] - Blame information for rev 1773

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 645 markom
/* fb.c -- Simple frame buffer
2 1748 jeremybenn
 
3 645 markom
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
4 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
5 645 markom
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 645 markom
 
8 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9 645 markom
 
10 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14 645 markom
 
15 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19 645 markom
 
20 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22 1350 nogj
 
23 1748 jeremybenn
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28 1350 nogj
#include "config.h"
29 1748 jeremybenn
#include "port.h"
30 1350 nogj
 
31 1748 jeremybenn
/* System includes */
32
#include <stdlib.h>
33
#include <stdio.h>
34 1350 nogj
 
35 1748 jeremybenn
/* Package includes */
36 1350 nogj
#include "arch.h"
37 645 markom
#include "sim-config.h"
38
#include "abstract.h"
39 805 markom
#include "sched.h"
40 1748 jeremybenn
#include "toplevel-support.h"
41 645 markom
 
42 1748 jeremybenn
 
43
#define FB_SIZEX           640
44
#define FB_SIZEY           480
45
 
46
#define CAM_SIZEX          352
47
#define CAM_SIZEY          288
48
 
49
/*! Relative amount of time spent in refresh */
50
#define REFRESH_DIVIDER     20
51
 
52
#define FB_CTRL            0x0000
53
#define FB_BUFADDR         0x0004
54
#define FB_CAMBUFADDR      0x0008
55
#define FB_CAMPOSADDR      0x000c
56
#define FB_PAL             0x0400
57
 
58 799 simons
#define FB_WRAP (512*1024)
59
 
60 1748 jeremybenn
struct fb_state
61
{
62 1461 nogj
  int enabled;
63 1369 nogj
  unsigned long pal[256];
64
  int ctrl;
65
  int pic;
66
  int in_refresh;
67
  int refresh_count;
68
  oraddr_t addr;
69
  oraddr_t cam_addr;
70
  int camerax;
71
  int cameray;
72
  int camera_pos;
73
  oraddr_t baseaddr;
74
  int refresh;
75
  int refresh_rate;
76
  char *filename;
77
};
78 645 markom
 
79 1748 jeremybenn
static void
80
change_buf_addr (struct fb_state *fb, oraddr_t addr)
81 647 markom
{
82 1369 nogj
  fb->addr = addr;
83 647 markom
}
84
 
85
/* Write a register */
86 1748 jeremybenn
static void
87
fb_write32 (oraddr_t addr, uint32_t value, void *dat)
88 647 markom
{
89 1369 nogj
  struct fb_state *fb = dat;
90
 
91 1748 jeremybenn
  switch (addr)
92
    {
93
    case FB_CTRL:
94
      fb->ctrl = value;
95
      break;
96
    case FB_BUFADDR:
97
      change_buf_addr (fb, value);
98
      break;
99
    case FB_CAMBUFADDR:
100
      fb->cam_addr = value;
101
      break;
102
    case FB_CAMPOSADDR:
103
      fb->camera_pos = value;
104
      fb->camerax = value % FB_SIZEX;
105
      fb->cameray = value / FB_SIZEX;
106
      break;
107 647 markom
    default:
108 1486 nogj
      addr -= FB_PAL;
109
      addr /= 4;
110 1748 jeremybenn
      if (addr < 0 || addr >= 256)
111
        {
112
          fprintf (stderr, "Write out of palette buffer (0x%" PRIxADDR ")!\n",
113
                   addr);
114
        }
115
      else
116
        fb->pal[addr] = value;
117 647 markom
      break;
118 1748 jeremybenn
    }
119 647 markom
}
120
 
121 645 markom
/* Read a register */
122 1748 jeremybenn
static oraddr_t
123
fb_read32 (oraddr_t addr, void *dat)
124 645 markom
{
125 1369 nogj
  struct fb_state *fb = dat;
126
 
127 1748 jeremybenn
  switch (addr)
128
    {
129 845 markom
    case FB_CTRL:
130 1748 jeremybenn
      return (fb->ctrl & ~0xff000000) | (fb->
131
                                         in_refresh ? 0x80000000 : 0) |
132
        ((unsigned long) (fb->refresh_count & 0x7f) << 24);
133 845 markom
      break;
134 1748 jeremybenn
    case FB_BUFADDR:
135
      return fb->addr;
136
      break;
137
    case FB_CAMBUFADDR:
138
      return fb->cam_addr;
139
      break;
140
    case FB_CAMPOSADDR:
141
      return fb->camera_pos;
142
      break;
143 647 markom
    default:
144 1486 nogj
      addr -= FB_PAL;
145
      addr /= 4;
146 1748 jeremybenn
      if (addr < 0 || addr >= 256)
147
        {
148
          fprintf (stderr, "Read out of palette buffer (0x%" PRIxADDR ")!\n",
149
                   addr);
150
          return 0;
151
        }
152
      else
153
        return fb->pal[addr];
154
    }
155 645 markom
}
156
 
157
/* define these also for big endian */
158 859 markom
#if __BIG_ENDIAN__
159 1244 hpanther
#define CNV32(x) (\
160 859 markom
     ((((x) >> 24) & 0xff) << 0)\
161
   | ((((x) >> 16) & 0xff) << 8)\
162
   | ((((x) >> 8) & 0xff) << 16)\
163
   | ((((x) >> 0) & 0xff) << 24))
164 1244 hpanther
#define CNV16(x) (\
165
     ((((x) >> 8) & 0xff) << 0)\
166 859 markom
   | ((((x) >> 0) & 0xff) << 8))
167
#else
168 645 markom
#define CNV16(x) (x)
169
#define CNV32(x) (x)
170 859 markom
#endif
171 645 markom
 
172
/* Dumps a bmp file, based on current image */
173 1748 jeremybenn
static int
174
fb_dump_image8 (struct fb_state *fb, char *filename)
175 645 markom
{
176
  int sx = FB_SIZEX;
177
  int sy = FB_SIZEY;
178 1557 nogj
  int i, x = 0, y = 0;
179 645 markom
  FILE *fo;
180
 
181
  unsigned short int u16;
182
  unsigned long int u32;
183 1748 jeremybenn
 
184
  if (config.sim.verbose)
185
    PRINTF ("Creating %s...", filename);
186 645 markom
  fo = fopen (filename, "wb+");
187 1748 jeremybenn
  u16 = CNV16 (19778);          /* BM */
188
  if (!fwrite (&u16, 2, 1, fo))
189
    return 1;
190
  u32 = CNV32 (14 + 40 + sx * sy + 1024);       /* size */
191
  if (!fwrite (&u32, 4, 1, fo))
192
    return 1;
193
  u32 = CNV32 (0);               /* reserved */
194
  if (!fwrite (&u32, 4, 1, fo))
195
    return 1;
196
  u32 = 14 + 40 + 1024;         /* offset */
197
  if (!fwrite (&u32, 4, 1, fo))
198
    return 1;
199 645 markom
 
200 1748 jeremybenn
  u32 = CNV32 (40);             /* header size */
201
  if (!fwrite (&u32, 4, 1, fo))
202
    return 1;
203
  u32 = CNV32 (sx);             /* width */
204
  if (!fwrite (&u32, 4, 1, fo))
205
    return 1;
206
  u32 = CNV32 (sy);             /* height */
207
  if (!fwrite (&u32, 4, 1, fo))
208
    return 1;
209
  u16 = CNV16 (1);              /* planes */
210
  if (!fwrite (&u16, 2, 1, fo))
211
    return 1;
212
  u16 = CNV16 (8);              /* bits */
213
  if (!fwrite (&u16, 2, 1, fo))
214
    return 1;
215
  u32 = CNV32 (0);               /* compression */
216
  if (!fwrite (&u32, 4, 1, fo))
217
    return 1;
218
  u32 = CNV32 (x * y);          /* image size */
219
  if (!fwrite (&u32, 4, 1, fo))
220
    return 1;
221
  u32 = CNV32 (2835);           /* x resolution */
222
  if (!fwrite (&u32, 4, 1, fo))
223
    return 1;
224
  u32 = CNV32 (2835);           /* y resolution */
225
  if (!fwrite (&u32, 4, 1, fo))
226
    return 1;
227
  u32 = CNV32 (0);               /* ncolours = 0; should be generated */
228
  if (!fwrite (&u32, 4, 1, fo))
229
    return 1;
230
  u32 = CNV32 (0);               /* important colours; all are important */
231
  if (!fwrite (&u32, 4, 1, fo))
232
    return 1;
233
 
234
  for (i = 0; i < 256; i++)
235
    {
236
      unsigned long val, d;
237
      d = fb->pal[i];
238 766 simons
#if 1
239 1748 jeremybenn
      val = ((d >> 0) & 0x1f) << 3;      /* Blue */
240
      val |= ((d >> 5) & 0x3f) << 10;   /* Green */
241
      val |= ((d >> 11) & 0x1f) << 19;  /* Red */
242
#else
243
      val = CNV32 (pal[i]);
244 766 simons
#endif
245 1748 jeremybenn
      if (!fwrite (&val, 4, 1, fo))
246
        return 1;
247
    }
248 645 markom
 
249 1748 jeremybenn
  if (config.sim.verbose)
250
    PRINTF ("(%i,%i)", sx, sy);
251 645 markom
  /* Data is stored upside down */
252 1748 jeremybenn
  for (y = sy - 1; y >= 0; y--)
253
    {
254
      int align = (4 - sx) % 4;
255
      int zero = CNV32 (0);
256
      int add;
257
      while (align < 0)
258
        align += 4;
259
      for (x = 0; x < sx; x++)
260
        {
261
          add =
262
            (fb->
263
             addr & ~(FB_WRAP - 1)) | ((fb->addr + y * sx + x) & (FB_WRAP -
264
                                                                  1));
265
          fputc (eval_direct8 (add, 0, 0), fo);
266
        }
267
      if (align && !fwrite (&zero, align, 1, fo))
268
        return 1;
269 799 simons
    }
270 645 markom
 
271 1748 jeremybenn
  if (config.sim.verbose)
272
    PRINTF ("DONE\n");
273 645 markom
  fclose (fo);
274
  return 0;
275
}
276
 
277 859 markom
/* Dumps a bmp file, based on current image */
278 1748 jeremybenn
static int
279
fb_dump_image24 (struct fb_state *fb, char *filename)
280 859 markom
{
281
  int sx = FB_SIZEX;
282
  int sy = FB_SIZEY;
283 1557 nogj
  int x = 0, y = 0;
284 859 markom
  FILE *fo;
285
 
286
  unsigned short int u16;
287
  unsigned long int u32;
288 1484 nogj
 
289 1748 jeremybenn
  if (config.sim.verbose)
290
    PRINTF ("Creating %s...", filename);
291 859 markom
  fo = fopen (filename, "wb+");
292 1748 jeremybenn
  u16 = CNV16 (19778);          /* BM */
293
  if (!fwrite (&u16, 2, 1, fo))
294
    return 1;
295
  u32 = CNV32 (14 + 40 + sx * sy * 3);  /* size */
296
  if (!fwrite (&u32, 4, 1, fo))
297
    return 1;
298
  u32 = CNV32 (0);               /* reserved */
299
  if (!fwrite (&u32, 4, 1, fo))
300
    return 1;
301
  u32 = 14 + 40;                /* offset */
302
  if (!fwrite (&u32, 4, 1, fo))
303
    return 1;
304 859 markom
 
305 1748 jeremybenn
  u32 = CNV32 (40);             /* header size */
306
  if (!fwrite (&u32, 4, 1, fo))
307
    return 1;
308
  u32 = CNV32 (sx);             /* width */
309
  if (!fwrite (&u32, 4, 1, fo))
310
    return 1;
311
  u32 = CNV32 (sy);             /* height */
312
  if (!fwrite (&u32, 4, 1, fo))
313
    return 1;
314
  u16 = CNV16 (1);              /* planes */
315
  if (!fwrite (&u16, 2, 1, fo))
316
    return 1;
317
  u16 = CNV16 (24);             /* bits */
318
  if (!fwrite (&u16, 2, 1, fo))
319
    return 1;
320
  u32 = CNV32 (0);               /* compression */
321
  if (!fwrite (&u32, 4, 1, fo))
322
    return 1;
323
  u32 = CNV32 (x * y * 3);      /* image size */
324
  if (!fwrite (&u32, 4, 1, fo))
325
    return 1;
326
  u32 = CNV32 (2835);           /* x resolution */
327
  if (!fwrite (&u32, 4, 1, fo))
328
    return 1;
329
  u32 = CNV32 (2835);           /* y resolution */
330
  if (!fwrite (&u32, 4, 1, fo))
331
    return 1;
332
  u32 = CNV32 (0);               /* ncolours = 0; should be generated */
333
  if (!fwrite (&u32, 4, 1, fo))
334
    return 1;
335
  u32 = CNV32 (0);               /* important colours; all are important */
336
  if (!fwrite (&u32, 4, 1, fo))
337
    return 1;
338
 
339
  if (config.sim.verbose)
340
    PRINTF ("(%i,%i)", sx, sy);
341 859 markom
  /* Data is stored upside down */
342 1748 jeremybenn
  for (y = sy - 1; y >= 0; y--)
343
    {
344
      unsigned char line[FB_SIZEX][3];
345
      for (x = 0; x < sx; x++)
346
        if (y >= fb->cameray && x >= fb->camerax
347
            && y < fb->cameray + CAM_SIZEY && x < fb->camerax + CAM_SIZEX)
348
          {
349
            int add =
350
              (fb->cam_addr +
351
               (x - fb->camerax + (y - fb->cameray) * CAM_SIZEX) * 2) ^ 2;
352
            unsigned short d = eval_direct16 (add, 0, 0);
353
            line[x][0] = ((d >> 0) & 0x1f) << 3;  /* Blue */
354
            line[x][1] = ((d >> 5) & 0x3f) << 2;        /* Green */
355
            line[x][2] = ((d >> 11) & 0x1f) << 3;       /* Red */
356
          }
357
        else
358
          {
359
            int add =
360
              (fb->
361
               addr & ~(FB_WRAP - 1)) | ((fb->addr + y * sx + x) & (FB_WRAP -
362
                                                                    1));
363
            unsigned short d = fb->pal[eval_direct8 (add, 0, 0)];
364
            line[x][0] = ((d >> 0) & 0x1f) << 3;  /* Blue */
365
            line[x][1] = ((d >> 5) & 0x3f) << 2;        /* Green */
366
            line[x][2] = ((d >> 11) & 0x1f) << 3;       /* Red */
367
          }
368
      if (!fwrite (line, sizeof (line), 1, fo))
369
        return 1;
370
    }
371 859 markom
 
372 1748 jeremybenn
  if (config.sim.verbose)
373
    PRINTF ("DONE\n");
374 859 markom
  fclose (fo);
375
  return 0;
376
}
377
 
378 1748 jeremybenn
static void
379
fb_job (void *dat)
380 805 markom
{
381 1369 nogj
  struct fb_state *fb = dat;
382
 
383 1748 jeremybenn
  if (fb->refresh)
384
    {
385
      /* dump the image? */
386
      if (fb->ctrl & 1)
387
        {
388
          char temp[STR_SIZE];
389
          sprintf (temp, "%s%04i.bmp", fb->filename, fb->pic);
390
          if (fb->ctrl & 2)
391
            fb_dump_image24 (fb, temp);
392
          else
393
            fb_dump_image8 (fb, temp);
394
          fb->pic++;
395
        }
396
      SCHED_ADD (fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER);
397
      fb->in_refresh = 0;
398
      fb->refresh = 0;
399 845 markom
    }
400 1748 jeremybenn
  else
401
    {
402
      fb->refresh_count++;
403
      fb->refresh = 1;
404
      SCHED_ADD (fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER);
405
    }
406 805 markom
}
407
 
408 1446 nogj
/* Reset all FBs */
409 1748 jeremybenn
static void
410
fb_reset (void *dat)
411 645 markom
{
412 1369 nogj
  struct fb_state *fb = dat;
413 645 markom
  int i;
414 647 markom
 
415 1369 nogj
  fb->pic = 0;
416
  fb->addr = 0;
417
  fb->ctrl = 0;
418 645 markom
 
419 1369 nogj
  for (i = 0; i < 256; i++)
420
    fb->pal[i] = (i << 16) | (i << 8) | (i << 0);
421 647 markom
 
422 1748 jeremybenn
  SCHED_ADD (fb_job, dat, fb->refresh_rate);
423 1369 nogj
  fb->refresh = 0;
424 645 markom
}
425 1358 nogj
 
426
/*-----------------------------------------------------[ FB configuration ]---*/
427 1748 jeremybenn
static void
428
fb_enabled (union param_val val, void *dat)
429 1358 nogj
{
430 1369 nogj
  struct fb_state *fb = dat;
431 1748 jeremybenn
  fb->enabled = val.int_val;
432 1358 nogj
}
433
 
434 1748 jeremybenn
 
435
static void
436
fb_baseaddr (union param_val val, void *dat)
437 1358 nogj
{
438 1369 nogj
  struct fb_state *fb = dat;
439 1748 jeremybenn
  fb->baseaddr = val.addr_val;
440 1358 nogj
}
441
 
442 1748 jeremybenn
 
443
static void
444
fb_refresh_rate (union param_val val, void *dat)
445 1358 nogj
{
446 1369 nogj
  struct fb_state *fb = dat;
447 1748 jeremybenn
  fb->refresh_rate = val.int_val;
448 1358 nogj
}
449
 
450 1748 jeremybenn
 
451
/*---------------------------------------------------------------------------*/
452
/*!Set the frame buffer output file
453
 
454
   Free any previously allocated value.
455
 
456
   @param[in] val  The value to use
457
   @param[in] dat  The config data structure                                 */
458
/*---------------------------------------------------------------------------*/
459
static void
460
fb_filename (union param_val  val,
461
             void            *dat)
462 1461 nogj
{
463
  struct fb_state *fb = dat;
464
 
465 1748 jeremybenn
  if (NULL != fb->filename)
466
    {
467
      free (fb->filename);
468
      fb->filename = NULL;
469
    }
470
 
471
  if (!(fb->filename = strdup (val.str_val)))
472
    {
473
      fprintf (stderr, "Peripheral FB: Run out of memory\n");
474
      exit (-1);
475
    }
476
}       /* fb_filename() */
477
 
478
 
479
/*---------------------------------------------------------------------------*/
480
/*!Initialize a new frame buffer configuration
481
 
482
   ALL parameters are set explicitly to default values.                      */
483
/*---------------------------------------------------------------------------*/
484
static void *
485
fb_sec_start ()
486 1369 nogj
{
487 1748 jeremybenn
  struct fb_state *new = malloc (sizeof (struct fb_state));
488 1369 nogj
 
489 1748 jeremybenn
  if (!new)
490
    {
491
      fprintf (stderr, "Peripheral FB: Run out of memory\n");
492
      exit (-1);
493
    }
494 1369 nogj
 
495 1748 jeremybenn
  new->enabled       = 1;
496
  new->baseaddr      = 0;
497
  new->refresh_rate  = 1000000000000ULL / 50ULL / config.sim.clkcycle_ps;
498
  new->filename      = strdup ("fb_out");
499
 
500
  new->ctrl          = 0;
501
  new->pic           = 0;
502
  new->in_refresh    = 1;
503 1369 nogj
  new->refresh_count = 0;
504 1748 jeremybenn
  new->addr          = 0;
505
  new->cam_addr      = 0;
506
  new->camerax       = 0;
507
  new->cameray       = 0;
508
  new->camera_pos    = 0;
509 1369 nogj
 
510
  return new;
511
 
512 1748 jeremybenn
}       /* fb_sec_start() */
513
 
514
 
515
static void
516
fb_sec_end (void *dat)
517 1369 nogj
{
518
  struct fb_state *fb = dat;
519 1486 nogj
  struct mem_ops ops;
520 1369 nogj
 
521 1748 jeremybenn
  if (!fb->enabled)
522
    {
523
      free (fb->filename);
524
      free (fb);
525
      return;
526
    }
527 1461 nogj
 
528 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
529 1369 nogj
 
530 1486 nogj
  ops.readfunc32 = fb_read32;
531
  ops.writefunc32 = fb_write32;
532
  ops.write_dat32 = dat;
533
  ops.read_dat32 = dat;
534
 
535
  /* FIXME: Correct delay? */
536
  ops.delayr = 2;
537
  ops.delayw = 2;
538
 
539 1748 jeremybenn
  reg_mem_area (fb->baseaddr, FB_PAL + 256 * 4, 0, &ops);
540 1486 nogj
 
541 1748 jeremybenn
  reg_sim_reset (fb_reset, dat);
542 1369 nogj
}
543
 
544 1748 jeremybenn
void
545
reg_fb_sec ()
546 1358 nogj
{
547 1748 jeremybenn
  struct config_section *sec =
548
    reg_config_sec ("fb", fb_sec_start, fb_sec_end);
549 1358 nogj
 
550 1748 jeremybenn
  reg_config_param (sec, "baseaddr", paramt_addr, fb_baseaddr);
551
  reg_config_param (sec, "enabled", paramt_int, fb_enabled);
552
  reg_config_param (sec, "refresh_rate", paramt_int, fb_refresh_rate);
553
  reg_config_param (sec, "txfile", paramt_str, fb_filename);
554
  reg_config_param (sec, "filename", paramt_str, fb_filename);
555 1358 nogj
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.