lcd_support.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,400 行 · 第 1/3 页
C
1,400 行
//==========================================================================//// Lcd_support.c//// Cogent CSB281 - LCD/CRT support routines////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2003 Gary Thomas//// eCos 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 or (at your option) any later version.//// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): gthomas// Contributors: gthomas// Date: 2001-11-03// Description: Simple LCD support//####DESCRIPTIONEND#####include <pkgconf/hal.h>#include <cyg/infra/diag.h>#include <cyg/hal/hal_io.h> // IO macros#include <cyg/hal/hal_if.h> // Virtual vector support#include <cyg/hal/hal_arch.h> // Register state info#include <cyg/hal/hal_intr.h> // HAL interrupt macros#include <cyg/hal/lcd_support.h>#include <cyg/hal/hal_cache.h>#include <string.h>#ifdef CYGPKG_ISOINFRA# include <pkgconf/isoinfra.h># ifdef CYGINT_ISO_STDIO_FORMATTED_IO# include <stdio.h> // sscanf# endif#endif#ifndef FALSE#define FALSE 0#define TRUE 1#endif// Logical layout#define LCD_WIDTH 640#define LCD_HEIGHT 480#define LCD_DEPTH 16#define RGB_RED(x) (((x)&0x1F)<<11)#define RGB_GREEN(x) (((x)&0x3F)<<5)#define RGB_BLUE(x) (((x)&0x1F)<<0)// Black on light bluestatic int bg = RGB_RED(0x1F) | RGB_GREEN(0x3F) | RGB_BLUE(0x1F);static int fg = RGB_RED(0) | RGB_GREEN(0) | RGB_BLUE(0);static struct lcd_info lcd;int sed135x_init(int depth, struct lcd_info *info);// Compute the location for a pixel within the framebufferstatic cyg_uint16 *lcd_fb(int row, int col){ cyg_uint16 *res = (cyg_uint16 *)((char *)lcd.fb+(row*lcd.rlen)+(col*lcd.stride)); return res;}voidlcd_on(bool enable){#if 0 // The on/off code is not stable static bool on = false; if (enable) { if (!on) { (*lcd.on)(); } on = true; } else { (*lcd.off)(); on = false; }#endif}// Initialize LCD hardwarevoidlcd_init(int depth){ sed135x_init(depth, &lcd);}// Get information about the frame bufferintlcd_getinfo(struct lcd_info *info){ if (lcd.bpp == 0) { return 0; // LCD not initialized } *info = lcd; return 1; // Information valid}// Clear screenvoidlcd_clear(void){#if 0 cyg_uint32 *fb_row0, *fb_rown; cyg_uint32 _bg = (bg<<16)|bg; fb_row0 = lcd_fb(0, 0); fb_rown = lcd_fb(lcd_height, 0); while (fb_row0 != fb_rown) { *fb_row0++ = _bg; }#endif}#ifdef CYGSEM_CSB281_LCD_COMM//// Additional support for LCD/Keyboard as 'console' device//#ifdef CYGOPT_CSB281_LCD_COMM_LOGO#include "banner.xpm"#endif#include "font.h"// Virtual screen infostatic int curX = 0; // Last used positionstatic int curY = 0;//static int width = LCD_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);//static int height = LCD_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);#define SCREEN_PAN 20#define SCREEN_WIDTH 80#define SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)#define VISIBLE_SCREEN_WIDTH (LCD_WIDTH/FONT_WIDTH)#define VISIBLE_SCREEN_HEIGHT (LCD_HEIGHT/FONT_HEIGHT)static char screen[SCREEN_HEIGHT][SCREEN_WIDTH];static int screen_height = SCREEN_HEIGHT;static int screen_width = SCREEN_WIDTH;static int screen_pan = 0;// Usable area on screen [logical pixel rows]static int screen_start = 0; static int screen_end = LCD_HEIGHT/FONT_HEIGHT;static bool cursor_enable = true;// Functionsstatic void lcd_drawc(cyg_int8 c, int x, int y);// Note: val is a 16 bit, RGB555 value which must be mapped// onto a 12 bit value.#define RED(v) ((v>>12) & 0x0F)#define GREEN(v) ((v>>7) & 0x0F)#define BLUE(v) ((v>>1) & 0x0F)static voidset_pixel(int row, int col, unsigned short val){ unsigned short *pix = (unsigned short *)lcd_fb(row, col); *pix = _le16(val);}static int_hexdigit(char c){ if ((c >= '0') && (c <= '9')) { return c - '0'; } else { if ((c >= 'A') && (c <= 'F')) { return (c - 'A') + 0x0A; } else { if ((c >= 'a') && (c <= 'f')) { return (c - 'a') + 0x0a; } } } return 0;}static int_hex(char *cp){ return (_hexdigit(*cp)<<4) | _hexdigit(*(cp+1));}static unsigned shortparse_color(char *cp){ int red, green, blue; while (*cp && (*cp != 'c')) cp++; if (cp) { cp += 2; if (*cp == '#') { red = _hex(cp+1); green = _hex(cp+3); blue = _hex(cp+5);#define USE_RGB565#ifdef USE_RGB565 return RGB_RED(red>>3) | RGB_GREEN(green>>2) | RGB_BLUE(blue>>3);#else return RGB_RED(red>>3) | RGB_GREEN(green>>3) | RGB_BLUE(blue>>3);#endif } else { // Should be "None" return 0xFFFF; } } else { return 0xFFFF; }}#ifndef CYGINT_ISO_STDIO_FORMATTED_IOstatic intget_int(unsigned char **_cp){ char *cp = *_cp; char c; int val = 0; while ((c = *cp++) && (c != ' ')) { if ((c >= '0') && (c <= '9')) { val = val * 10 + (c - '0'); } else { return -1; } } *_cp = cp; return val;}#endif#ifdef CYGOPT_CSB281_LCD_COMM_LOGOstatic intshow_xpm(char *xpm[], int screen_pos){ int i, row, col, offset; unsigned char *cp; int nrows, ncols, nclrs, cwid; unsigned short colors[256]; // Mapped by character index short color_value, color_index;//#define HORRIBLY_SLOW_COLOR_MAPPING#ifdef HORRIBLY_SLOW_COLOR_MAPPING bool color_match; short cmap[256][2]; int j;#else // Caution - this is very GIMP specific short cmap[256][3]; // Enough room for 256 colors short cmap_col, cmap_row; unsigned char std_cmap[] = " .+";#endif cp = xpm[0];#ifdef CYGINT_ISO_STDIO_FORMATTED_IO if (sscanf(cp, "%d %d %d %d", &ncols, &nrows, &nclrs, &cwid) != 4) {#else if (((ncols = get_int(&cp)) < 0) || ((nrows = get_int(&cp)) < 0) || ((nclrs = get_int(&cp)) < 0) || ((cwid = get_int(&cp)) < 0)) {#endif diag_printf("Can't parse XPM data, sorry\n"); return 0; }// diag_printf("%d rows, %d cols, %d colors %d chars/pixel\n", nrows, ncols, nclrs, cwid); if (cwid > 2) { diag_printf("Color map is too wide - %d\n", cwid); return 0; } for (i = 0; i < 256; i++) { colors[i] = 0x0000;#ifdef HORRIBLY_SLOW_COLOR_MAPPING cmap[i][0] = 0; cmap[i][1] = 0;#else cmap[i][0] = 0; cmap[i][1] = 0; cmap[i][2] = 0;#endif } color_index = 0; for (i = 0; i < nclrs; i++) { cp = xpm[i+1];#ifdef HORRIBLY_SLOW_COLOR_MAPPING for (j = 0; j < cwid; j++) { cmap[color_index][j] = cp[j]; }#else if (cwid == 1) { cmap_col = 0; } else { for (cmap_col = 0; cmap_col < 3; cmap_col++) { if (cp[1] == std_cmap[cmap_col]) { break; } } } cmap_row = *cp; cmap[cmap_row][cmap_col] = color_index;#endif color_value = parse_color(cp+cwid); colors[color_index++] = color_value;// diag_printf("Color[%d] = %04x\n", color_index-1, colors[color_index-1]); }#ifdef CYGOPT_CSB281_LCD_COMM_LOGO_TOP offset = screen_pos;#else offset = screen_pos-nrows;#endif for (row = 0; row < nrows; row++) { cp = xpm[nclrs+1+row]; for (col = 0; col < ncols; col++) {#ifdef HORRIBLY_SLOW_COLOR_MAPPING // Horrible, but portable, way to map colors for (color_index = 0; color_index < nclrs; color_index++) { color_match = true; for (j = 0; j < cwid; j++) { if (cmap[color_index][j] != cp[j]) { color_match = false; } } if (color_match) { break; } }#else if (cwid == 1) { cmap_col = 0; } else { for (cmap_col = 0; cmap_col < 3; cmap_col++) { if (cp[1] == std_cmap[cmap_col]) { break; } } } cmap_row = *cp; color_index = cmap[cmap_row][cmap_col];#endif set_pixel(row+offset, col, colors[color_index]); cp += cwid; } }#ifdef CYGOPT_CSB281_LCD_COMM_LOGO_TOP screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT; screen_end = LCD_HEIGHT/FONT_HEIGHT; return offset+nrows;#else screen_start = 0; screen_height = offset / FONT_HEIGHT; screen_end = screen_height; return offset;#endif}#endifvoidlcd_screen_clear(void){ int row, col, pos; for (row = 0; row < screen_height; row++) { for (col = 0; col < screen_width; col++) { screen[row][col] = ' '; lcd_drawc(' ', col, row); } }#ifdef CYGOPT_CSB281_LCD_COMM_LOGO // Note: Row 0 seems to wrap incorrectly#ifdef CYGOPT_CSB281_LCD_COMM_LOGO_TOP pos = 0;#else pos = (LCD_HEIGHT-1);#endif show_xpm(banner_xpm, pos);#endif // CYGOPT_CSB281_LCD_COMM_LOGO curX = 0; curY = screen_start; if (cursor_enable) { lcd_drawc(CURSOR_ON, curX-screen_pan, curY); }}// Position cursorvoidlcd_moveto(int X, int Y){ if (cursor_enable) { lcd_drawc(screen[curY][curX], curX-screen_pan, curY); } if (X < 0) X = 0; if (X >= screen_width) X = screen_width-1; curX = X; if (Y < screen_start) Y = screen_start; if (Y >= screen_height) Y = screen_height-1; curY = Y; if (cursor_enable) { lcd_drawc(CURSOR_ON, curX-screen_pan, curY); }}// Render a character at position (X,Y) with current background/foregroundstatic voidlcd_drawc(cyg_int8 c, int x, int y){ cyg_uint8 bits; int l, p; int xoff, yoff; if ((x < 0) || (x >= VISIBLE_SCREEN_WIDTH) || (y < 0) || (y >= screen_height)) return; for (l = 0; l < FONT_HEIGHT; l++) { bits = font_table[c-FIRST_CHAR][l]; yoff = y*FONT_HEIGHT + l; xoff = x*FONT_HEIGHT; for (p = 0; p < FONT_WIDTH; p++) { set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg); bits >>= 1; } }}static voidlcd_refresh(void){ int row, col; for (row = screen_start; row < screen_height; row++) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?