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

4.104.115
Last change on this file since e7bde492 was e7bde492, checked in by Joel Sherrill <joel.sherrill@…>, on 06/02/09 at 22:19:44

2009-06-02 Joel Sherrill <joel.sherrill@…>

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