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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [fb.c] - Blame information for rev 37

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

Line No. Rev Author Line
1 19 jeremybenn
/* fb.c -- Simple frame buffer
2
 
3
   Copyright (C) 2001 Marko Mlinar, markom@opencores.org
4
   Copyright (C) 2008 Embecosm Limited
5
 
6
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7
 
8
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9
 
10
   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
 
15
   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
 
20
   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
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
 
27
/* Autoconf and/or portability configuration */
28
#include "config.h"
29
#include "port.h"
30
 
31
/* System includes */
32
#include <stdlib.h>
33
#include <stdio.h>
34
 
35
/* Package includes */
36
#include "arch.h"
37
#include "sim-config.h"
38
#include "abstract.h"
39
#include "sched.h"
40
#include "toplevel-support.h"
41
 
42
 
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
#define FB_WRAP (512*1024)
59
 
60
struct fb_state
61
{
62
  int enabled;
63
  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
 
79
static void
80
change_buf_addr (struct fb_state *fb, oraddr_t addr)
81
{
82
  fb->addr = addr;
83
}
84
 
85
/* Write a register */
86
static void
87
fb_write32 (oraddr_t addr, uint32_t value, void *dat)
88
{
89
  struct fb_state *fb = dat;
90
 
91
  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
    default:
108
      addr -= FB_PAL;
109
      addr /= 4;
110
      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
      break;
118
    }
119
}
120
 
121
/* Read a register */
122
static oraddr_t
123
fb_read32 (oraddr_t addr, void *dat)
124
{
125
  struct fb_state *fb = dat;
126
 
127
  switch (addr)
128
    {
129
    case FB_CTRL:
130
      return (fb->ctrl & ~0xff000000) | (fb->
131
                                         in_refresh ? 0x80000000 : 0) |
132
        ((unsigned long) (fb->refresh_count & 0x7f) << 24);
133
      break;
134
    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
    default:
144
      addr -= FB_PAL;
145
      addr /= 4;
146
      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
}
156
 
157
/* define these also for big endian */
158
#if __BIG_ENDIAN__
159
#define CNV32(x) (\
160
     ((((x) >> 24) & 0xff) << 0)\
161
   | ((((x) >> 16) & 0xff) << 8)\
162
   | ((((x) >> 8) & 0xff) << 16)\
163
   | ((((x) >> 0) & 0xff) << 24))
164
#define CNV16(x) (\
165
     ((((x) >> 8) & 0xff) << 0)\
166
   | ((((x) >> 0) & 0xff) << 8))
167
#else
168
#define CNV16(x) (x)
169
#define CNV32(x) (x)
170
#endif
171
 
172
/* Dumps a bmp file, based on current image */
173
static int
174
fb_dump_image8 (struct fb_state *fb, char *filename)
175
{
176
  int sx = FB_SIZEX;
177
  int sy = FB_SIZEY;
178
  int i, x = 0, y = 0;
179
  FILE *fo;
180
 
181
  unsigned short int u16;
182
  unsigned long int u32;
183
 
184
  if (config.sim.verbose)
185
    PRINTF ("Creating %s...", filename);
186
  fo = fopen (filename, "wb+");
187
  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
 
200
  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
#if 1
239
      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
#endif
245
      if (!fwrite (&val, 4, 1, fo))
246
        return 1;
247
    }
248
 
249
  if (config.sim.verbose)
250
    PRINTF ("(%i,%i)", sx, sy);
251
  /* Data is stored upside down */
252
  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
    }
270
 
271
  if (config.sim.verbose)
272
    PRINTF ("DONE\n");
273
  fclose (fo);
274
  return 0;
275
}
276
 
277
/* Dumps a bmp file, based on current image */
278
static int
279
fb_dump_image24 (struct fb_state *fb, char *filename)
280
{
281
  int sx = FB_SIZEX;
282
  int sy = FB_SIZEY;
283
  int x = 0, y = 0;
284
  FILE *fo;
285
 
286
  unsigned short int u16;
287
  unsigned long int u32;
288
 
289
  if (config.sim.verbose)
290
    PRINTF ("Creating %s...", filename);
291
  fo = fopen (filename, "wb+");
292
  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
 
305
  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
  /* Data is stored upside down */
342
  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
 
372
  if (config.sim.verbose)
373
    PRINTF ("DONE\n");
374
  fclose (fo);
375
  return 0;
376
}
377
 
378
static void
379
fb_job (void *dat)
380
{
381
  struct fb_state *fb = dat;
382
 
383
  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
    }
400
  else
401
    {
402
      fb->refresh_count++;
403
      fb->refresh = 1;
404
      SCHED_ADD (fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER);
405
    }
406
}
407
 
408
/* Reset all FBs */
409
static void
410
fb_reset (void *dat)
411
{
412
  struct fb_state *fb = dat;
413
  int i;
414
 
415
  fb->pic = 0;
416
  fb->addr = 0;
417
  fb->ctrl = 0;
418
 
419
  for (i = 0; i < 256; i++)
420
    fb->pal[i] = (i << 16) | (i << 8) | (i << 0);
421
 
422
  SCHED_ADD (fb_job, dat, fb->refresh_rate);
423
  fb->refresh = 0;
424
}
425
 
426
/*-----------------------------------------------------[ FB configuration ]---*/
427
static void
428
fb_enabled (union param_val val, void *dat)
429
{
430
  struct fb_state *fb = dat;
431
  fb->enabled = val.int_val;
432
}
433
 
434
 
435
static void
436
fb_baseaddr (union param_val val, void *dat)
437
{
438
  struct fb_state *fb = dat;
439
  fb->baseaddr = val.addr_val;
440
}
441
 
442
 
443
static void
444
fb_refresh_rate (union param_val val, void *dat)
445
{
446
  struct fb_state *fb = dat;
447
  fb->refresh_rate = val.int_val;
448
}
449
 
450
 
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
{
463
  struct fb_state *fb = dat;
464
 
465
  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
{
487
  struct fb_state *new = malloc (sizeof (struct fb_state));
488
 
489
  if (!new)
490
    {
491
      fprintf (stderr, "Peripheral FB: Run out of memory\n");
492
      exit (-1);
493
    }
494
 
495
  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
  new->refresh_count = 0;
504
  new->addr          = 0;
505
  new->cam_addr      = 0;
506
  new->camerax       = 0;
507
  new->cameray       = 0;
508
  new->camera_pos    = 0;
509
 
510
  return new;
511
 
512
}       /* fb_sec_start() */
513
 
514
 
515
static void
516
fb_sec_end (void *dat)
517
{
518
  struct fb_state *fb = dat;
519
  struct mem_ops ops;
520
 
521
  if (!fb->enabled)
522
    {
523
      free (fb->filename);
524
      free (fb);
525
      return;
526
    }
527
 
528
  memset (&ops, 0, sizeof (struct mem_ops));
529
 
530
  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
  reg_mem_area (fb->baseaddr, FB_PAL + 256 * 4, 0, &ops);
540
 
541
  reg_sim_reset (fb_reset, dat);
542
}
543
 
544
void
545
reg_fb_sec ()
546
{
547
  struct config_section *sec =
548
    reg_config_sec ("fb", fb_sec_start, fb_sec_end);
549
 
550
  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
}

powered by: WebSVN 2.1.0

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