source: rtems/c/src/lib/libbsp/arm/csb337/console/sed1356.c @ 884730c

4.104.11
Last change on this file since 884730c was 884730c, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 8, 2009 at 7:34:48 PM

2009-12-08 Fernando Nicodemos <fgnicodemos@…>

  • console/font8x16.h, console/sed1356.c: Fix typos.
  • Property mode set to 100644
File size: 15.5 KB
Line 
1/*
2 *  SED1356 Support for KIT637_V6 (CSB637)
3 *
4 *  Based upon code from MicroMonitor 1.17 from http://www.umonfw.com/
5 *  which includes this notice:
6 *
7 **************************************************************************
8 *  General notice:
9 *  This code is part of a boot-monitor package developed as a generic base
10 *  platform for embedded system designs.  As such, it is likely to be
11 *  distributed to various projects beyond the control of the original
12 *  author.  Please notify the author of any enhancements made or bugs found
13 *  so that all may benefit from the changes.  In addition, notification back
14 *  to the author will allow the new user to pick up changes that may have
15 *  been made by other users after this version of the code was distributed.
16 *
17 *  Note1: the majority of this code was edited with 4-space tabs.
18 *  Note2: as more and more contributions are accepted, the term "author"
19 *         is becoming a mis-representation of credit.
20 *
21 *  Original author:    Ed Sutter
22 *  Email:              esutter@alcatel-lucent.com
23 *  Phone:              908-582-2351
24 **************************************************************************
25 *
26 *  Ed Sutter has been informed that this code is being used in RTEMS.
27 *
28 *  This code was reformatted by Joel Sherrill from OAR Corporation and
29 *  Fernando Nicodemos <fgnicodemos@terra.com.br> from NCB - Sistemas
30 *  Embarcados Ltda. (Brazil) to be more compliant with RTEMS coding
31 *  standards and to eliminate C++ style comments.
32 *
33 *  $Id$
34 */
35
36#include <bsp.h>
37
38#include <stdlib.h>
39#include <stdio.h>
40#include "sed1356.h"
41#include "font8x16.h"
42
43int mode900lq;
44long PIXELS_PER_ROW;
45long PIXELS_PER_COL;
46long COLS_PER_SCREEN;
47long ROWS_PER_SCREEN;
48long SED_HOR_PULSE_WIDTH_LCD;
49long SED_VER_PULSE_START_LCD;
50long SED_HOR_PULSE_START_LCD;
51long SED_HOR_NONDISP_LCD;
52long SED_VER_NONDISP_LCD;
53long SED_VER_PULSE_WIDTH_LCD;
54
55/* globals to keep track of foreground, background colors and x,y position */
56int sed_color_depth;    /* 4, 8 or 16 */
57int sed_fg_color;      /* 0 to 15, used as lookup into VGA color table */
58int sed_bg_color;      /* 0 to 15, used as lookup into VGA color table */
59int sed_col;        /* current column, 0 to COLS_PER_SCREEN - 1 */
60int sed_row;        /* current row, 0 to (ROWS_PER_SCREEN * 2) - 1 */
61int sed_disp_mode_crt;       /* CRT=1, LCD=0 */
62int sed135x_ok;
63int sed135x_tst;
64uint32_t sed_fb_offset;       /* current offset into frame buffer for sed_putchar */
65
66void sed_writechar(uint8_t c);
67void sed_scroll(void);
68
69#define SED_REG_BASE      0x30000000  /* *CS2 */
70#define SED_MEM_BASE      (SED_REG_BASE + 0x00200000)
71#define SED_STEP          1      /* 16-bit port on 16-bit boundry */
72
73#define SED_REG16(_x_)       *(volatile uint16_t *)((uint32_t)SED_REG_BASE + (((uint32_t)_x_ * SED_STEP) ^ 0))  /* Control/Status Registers, 16-bit mode */
74#define RD_FB16(_reg_,_val_)   ((_val_) = *((volatile uint16_t *)(((uint32_t)SED_MEM_BASE + ((uint32_t)(_reg_ * SED_STEP) ^ 0)))))
75#define WR_FB16(_reg_,_val_)   (*((volatile uint16_t *)(((uint32_t)SED_MEM_BASE + ((uint32_t)(_reg_ * SED_STEP)  ^ 0)))) = (_val_))
76
77#if 0
78#define SED1356_REG_LCD_HOR_DISP                 SED_REG16(0x32)
79#define SED1356_REG_LCD_HOR_NONDISP_and_START    SED_REG16(0x34)
80#define SED1356_REG_LCD_HOR_PULSE               SED_REG16(0x36)
81#define SED1356_REG_LCD_VER_DISP_HT_LO_and_HI      SED_REG16(0x38)
82#define SED1356_REG_LCD_VER_NONDISP_and_START      SED_REG16(0x3a)
83#define SED1356_REG_LCD_VER_PULSE                SED_REG16(0x3c)
84#define SED1356_REG_LCD_DISP_MODE_and_MISC      SED_REG16(0x40)
85#define SED1356_REG_LCD_DISP_START_LO_and_MID    SED_REG16(0x42)
86#define SED1356_REG_LCD_DISP_START_HI           SED_REG16(0x44)
87#define SED1356_REG_LCD_ADD_OFFSET_LO_and_HI    SED_REG16(0x46)
88#define SED1356_REG_LCD_PIXEL_PAN             SED_REG16(0x48)
89#define SED1356_REG_LCD_FIFO_THRESH_LO_and_HI    SED_REG16(0x4a)
90#endif
91
92
93#define H2SED(_x_)        (_x_)
94
95#define FB_SIZE (640 * 480)
96#define SED_ROW_SIZE(_depth_)        ((PIXELS_PER_ROW * _depth_) / 8)
97#define SED_FB_SIZE(_depth_)         (((PIXELS_PER_COL * PIXELS_PER_ROW) * _depth_) / 8)
98
99#define FONT_WIDTH    8
100#define FONT_HEIGHT   16
101
102#define SED_GET_ADD(_row_, _col_, _depth_) \
103    (((((_row_ * PIXELS_PER_ROW) * FONT_HEIGHT) \
104                                                                                          + (_col_ * FONT_WIDTH)) \
105                                                                                          * _depth_) / 8)
106
107
108#define SED_GET_PHYS_ADD(_reg_) \
109  (volatile unsigned long)(SED_MEM_BASE + ((_reg_ * SED_STEP) ^ 0))
110
111
112#include "sed1356_16bit.h"
113
114/* #define SED_DBG */
115int sed135x_tst = 0;
116
117void sed_write_frame_buffer(
118  uint32_t i,
119  uint16_t wr16
120)
121{
122  WR_FB16(i, wr16);
123}
124
125int sed_frame_buffer_size(void)
126{
127  return SED_FB_SIZE(sed_color_depth);
128}
129
130void sed_clr_row(int char_row)
131{
132  unsigned long sed_mem_add;
133  int i;
134  uint16_t wr16;
135
136  /* clear the desired row */
137  sed_mem_add = SED_GET_ADD(char_row, 0, sed_color_depth);
138
139#ifdef SED_DBG
140  sed135x_tst = 1;
141  printf("SED Clear Row %d, FB Add 0x%08lx, CPU Add 0x%08lx.\n ", char_row, sed_mem_add, SED_GET_PHYS_ADD(sed_mem_add));
142  sed135x_tst = 0;
143#endif
144
145  switch (sed_color_depth)
146  {
147    case 4:
148      wr16 = ((sed_bg_color << 12) | (sed_bg_color << 8) | (sed_bg_color << 4) | (sed_bg_color << 0));
149#ifdef SED_DBG
150  sed135x_tst = 1;
151  printf("SED Clear Row %d, FB Add 0x%08lx to 0x%08lx.\n ", char_row, sed_mem_add, sed_mem_add + ((PIXELS_PER_ROW * FONT_HEIGHT) / 2));
152  sed135x_tst = 0;
153#endif
154      for (i = 0; i < ((PIXELS_PER_ROW * FONT_HEIGHT) / 2); i += 2){
155        WR_FB16(sed_mem_add, wr16);
156        sed_mem_add += 2;
157      } /* for font_row */
158      break;
159    case 8:
160      wr16 = ((sed_bg_color << 8) | (sed_bg_color << 0));
161      for (i = 0; i < (PIXELS_PER_ROW * FONT_HEIGHT); i += 2){
162        WR_FB16(sed_mem_add, wr16);
163        sed_mem_add += 2;
164      } /* for font_row */
165      break;
166    case 16:
167      wr16 = ((vga_lookup[sed_bg_color]));
168      for (i = 0; i < ((PIXELS_PER_ROW * FONT_HEIGHT) * 2); i += 2){
169        WR_FB16(sed_mem_add, wr16);
170        sed_mem_add += 2;
171      } /* for font_row */
172      break;
173  } /* switch sed_color_depth */
174} /* sed_clr_row */
175
176void sed_init(void)
177{
178  mode900lq = 0;
179  PIXELS_PER_ROW = 640;
180  PIXELS_PER_COL = 480;
181  COLS_PER_SCREEN = 80;
182  ROWS_PER_SCREEN = 30;
183  SED_HOR_PULSE_WIDTH_LCD = 0x0b;
184  SED_HOR_NONDISP_LCD = 0x13;
185  SED_VER_PULSE_WIDTH_LCD = 0x01;
186  SED_VER_PULSE_START_LCD = 0x09;
187  SED_VER_NONDISP_LCD = 0x2c;
188
189  sed_color_depth = 16;          /* 16 => vga lookup */
190  sed_fg_color = 14;             /* Bright Yellow */
191  sed_bg_color = 1;              /* Blue */
192  sed_disp_mode_crt = 0;         /* default to LCD */
193  sed_fb_offset = 0x00;
194  sed_row = 0;
195  sed_col = 0;
196
197  sed135x_ok = 1;
198  sed135x_tst = 0;
199  sed_clearscreen();
200}
201
202/*
203 * sed_putchar()
204 *
205 * This routine parses the character and calls sed_writechar if it is a
206 * printable character
207 */
208void sed_putchar(char c)
209{
210
211  if ((sed135x_ok == 0) || (sed135x_tst == 1)) return;
212
213  /* First parse the character to see if it printable or an
214   * acceptable control character.
215   */
216  switch (c) {
217    case '\r':
218      sed_col = 0;
219      return;
220    case '\n':
221      sed_col = 0;
222      sed_scroll();
223      return;
224    case '\b':
225      sed_col--;
226      if (sed_col < 0) {
227        sed_row--;
228        if (sed_row < 0)
229          sed_row = 0;
230        sed_col = COLS_PER_SCREEN - 1;
231      }
232      c = 0;    /* erase the character */
233      sed_writechar(c);
234      break;
235    default:
236      if (((uint8_t)c < FIRST_CHAR) || ((uint8_t)c > LAST_CHAR))
237        return; /* drop anything we can't print */
238      c -= FIRST_CHAR;  /* get aligned to the first printable character */
239      sed_writechar(c);
240      /* advance to next column */
241      sed_col++;
242      if (sed_col == COLS_PER_SCREEN) {
243        sed_col = 0;
244        sed_scroll();
245      }
246      break;
247  }
248
249} /* sed_putchar() */
250
251/*
252 * sed_writechar()
253 *
254 * This routine writes the character to the screen at the current cursor
255 * location.
256 */
257void sed_writechar(uint8_t c)
258{
259  uint32_t sed_mem_add;
260  int font_row, font_col;
261  uint8_t font_data8;
262  uint16_t wr16;
263
264  /* Convert the current row,col and color depth values
265   * into an address
266   */
267  sed_mem_add = SED_GET_ADD(sed_row, sed_col, sed_color_depth);
268
269#ifdef SED_DBG
270  sed135x_tst = 1;
271  printf("SED writechar at row %d, col %d, FB Add 0x%08lx, CPU Add 0x%08lx.\n ",    sed_row, sed_col, sed_mem_add, SED_GET_PHYS_ADD(sed_mem_add));
272  sed135x_tst = 0;
273#endif
274
275  if (FONT_WIDTH == 8) {
276    switch (sed_color_depth) {
277      case 4:
278        /* Now render the font by painting one font row at a time */
279        for (font_row = 0; font_row < FONT_HEIGHT; font_row++) {
280          /* get the font row of data */
281          font_data8 = font8x16[(c * FONT_HEIGHT) + font_row];
282
283
284          for (font_col = 0; font_col < 8; font_col += 4)
285          {
286            /* get a words worth of pixels */
287            wr16 = (((font_data8 & 0x80) ? sed_fg_color << 12 : sed_bg_color << 12)
288                | ((font_data8 & 0x40) ? sed_fg_color << 8 : sed_bg_color << 8)
289                | ((font_data8 & 0x20) ? sed_fg_color << 4 : sed_bg_color << 4)
290                | ((font_data8 & 0x10) ? sed_fg_color << 0 : sed_bg_color << 0));
291            font_data8 = font_data8 << 4;
292            WR_FB16(sed_mem_add, wr16);
293            /* if we are in the 2nd frame buffer, write to the 1st
294             * frame buffer also
295             */
296            if (sed_row > (ROWS_PER_SCREEN - 1)) {
297              WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16);
298            }
299            sed_mem_add += 2;
300          } /* for font_col */
301          /* go to the next pixel row */
302          sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8));
303        } /* for font_row */
304        break;
305
306      case 8:
307        /* Now render the font by painting one font row at a time */
308        for (font_row = 0; font_row < FONT_HEIGHT; font_row++) {
309          /* get the font row of data */
310          font_data8 = font8x16[(c * FONT_HEIGHT) + font_row];
311          for (font_col = 0; font_col < 8; font_col += 2)
312          {
313            /* get a words worth of pixels */
314            wr16 = (((font_data8 & 0x80) ? sed_fg_color << 8 : sed_bg_color << 8)
315                | ((font_data8 & 0x40) ? sed_fg_color << 0 : sed_bg_color << 0));
316            font_data8 = font_data8 << 2;
317            WR_FB16(sed_mem_add, wr16);
318            /* if we are in the 2nd frame buffer, write to the 1st
319             * frame buffer also
320             */
321            if (sed_row > (ROWS_PER_SCREEN - 1)) {
322              WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16);
323            }
324            sed_mem_add += 2;
325          } /* for font_col */
326          /* go to the next pixel row */
327          sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8));
328        } /* for font_row */
329        break;
330
331      case 16:
332        /* Now render the font by painting one font row at a time */
333        for (font_row = 0; font_row < FONT_HEIGHT; font_row++) {
334          /* get the font row of data */
335          font_data8 = font8x16[(c * FONT_HEIGHT) + font_row];
336          for (font_col = 0; font_col < 8; font_col++)
337          {
338            /* get a words worth of pixels */
339            wr16 = ((font_data8 & 0x80) ?
340                     vga_lookup[sed_fg_color] : vga_lookup[sed_bg_color]);
341            font_data8 = font_data8 << 1;
342            WR_FB16(sed_mem_add, wr16);
343            /* if we are in the 2nd frame buffer, write to the 1st
344             * frame buffer also.
345             */
346            if (sed_row > (ROWS_PER_SCREEN - 1)) {
347              WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16);
348            }
349            sed_mem_add += 2;
350          } /* for font_col */
351          /* go to the next pixel row */
352          sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8));
353        } /* for font_row */
354        break;
355
356    } /* switch sed_color depth */
357  } /* FONT_WIDTH == 8 */
358  else
359  {
360    return;
361  }
362} /* sed_writechar() */
363
364void sed_update_fb_offset(void)
365{
366  /* write the new sed_fb_offset value */
367  if (sed_disp_mode_crt) {
368  /* before we change the address offset, wait for the display to
369   * go from active to non-active, unless the display is not enabled
370   */
371  if (SED1356_REG_DISP_MODE & H2SED(SED1356_DISP_MODE_CRT)) {  /* CRT is on */
372    while ((SED1356_REG_CRT_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 0) {}
373    while ((SED1356_REG_CRT_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 1) {}
374    }
375    SED1356_REG_CRT_DISP_START_LO_and_MID  = H2SED(((sed_fb_offset & 0x00ffff) >> 0));
376    SED1356_REG_CRT_DISP_START_HI  = H2SED(((sed_fb_offset & 0x070000) >> 16));
377  }
378  else /* LCD */
379  {
380    if (SED1356_REG_DISP_MODE & H2SED(SED1356_DISP_MODE_LCD)) {  /* LCD is on */
381      while ((SED1356_REG_LCD_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 0) {}
382      while ((SED1356_REG_LCD_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 1) {}
383    }
384    SED1356_REG_LCD_DISP_START_LO_and_MID  = H2SED(((sed_fb_offset & 0x00ffff) >> 0));
385    SED1356_REG_LCD_DISP_START_HI  = H2SED(((sed_fb_offset & 0x070000) >> 16));
386  }
387}
388
389/* sed_scroll()
390 *
391 * Because we are most likely running out of FLASH and probably also with
392 * cache disabled, a brute force memcpy of the whole screen would be very
393 * slow, even with reduced color depths.  Instead, we define a frame buffer
394 * that is twice the size of our actual display.  This does limit us to a
395 * 1Mbyte active display size, but 640 x 480 @ 16-bits/pixel = 614K so it
396 * works just fine.  800 x 600 can be had by reducing the color depth to
397 * 8-bits/pixel and using the look up tables.
398 *
399 * With the double buffering, we always write to the first buffer, even
400 * when the second buffer is active.  This allows us to scroll by adjusting
401 * the starting and ending addresses in the SED135x by one row.  When we
402 * reach the end of our virtual buffer, we reset the starting and ending
403 * addresses to the first buffer.  Note that we can not adjust the SED135x
404 * registers until it is in vertical retrace.  That means we have to wait
405 * until it is in active display, then goes to non-display, unless the
406 * screen is blanked, in which case we can update immediately.
407 */
408void sed_scroll(void)
409{
410  sed_row++;
411
412  /* clear the new row(s) */
413  sed_clr_row(sed_row);
414  if (sed_row > (ROWS_PER_SCREEN - 1)) {
415    sed_clr_row(sed_row - ROWS_PER_SCREEN);
416  }
417  /* when sed_y_pos is greater than ROWS_PER_SCREEN we just adjust the
418   * start and end addresses in the SED135x.  If it is equal to 2 *
419   * ROWS_PER_SCREEN, we reset the start and end addresses to SED_MEM_BASE.
420   */
421  if (sed_row > (ROWS_PER_SCREEN - 1)) {
422    if (sed_row > ((ROWS_PER_SCREEN * 2) - 1)) {
423      sed_fb_offset = 0x00;
424      sed_row = 0;
425      sed_clearscreen();
426    } else {
427      /* calculate the new offset address of the frame buffer in words */
428      sed_fb_offset += (SED_GET_ADD(1, 0, sed_color_depth) / 2);
429    }
430    sed_update_fb_offset();
431  } /* if (sed_row > (ROWS_PER_SCREEN - 1)) */
432}
433
434void sed_putstring(char *s)
435{
436  char *p = s;
437  while (*p)
438    sed_putchar(*p++);
439}
440
441void sed_clearscreen(void)
442{
443  int i;
444  uint16_t wr16;
445  int bg = sed_bg_color;
446  int fbsize = sed_frame_buffer_size();
447
448  /* we double buffer so clear ALL of memory */
449  fbsize *= 2;
450
451  /* fill the frame buffer with incrementing color values */
452  switch (sed_color_depth){
453    case 4:  wr16 = bg | bg << 4 | bg << 8 | bg << 12; break;
454    case 8:  wr16 = bg | bg << 8; break;
455    /* 16-bits bypasses the lookup table */
456    default: wr16 = vga_lookup[bg]; break;
457  }
458  for (i = 0; i < fbsize; i += 2){
459    sed_write_frame_buffer(i, wr16);
460  }
461}
Note: See TracBrowser for help on using the repository browser.