lcd_support.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,456 行 · 第 1/3 页

C
1,456
字号
//==========================================================================////        lcd_support.c////        SA1110/iPAQ - LCD 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) 2002 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//                Richard Panton <richard.panton@3glab.com>// Date:          2001-02-24// 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/hal_sa11x0.h>   // Board definitions#include <cyg/hal/ipaq.h>#include <cyg/hal/lcd_support.h>#include <cyg/hal/atmel_support.h>#include <cyg/hal/hal_cache.h>#ifdef CYGPKG_ISOINFRA# include <pkgconf/isoinfra.h># ifdef CYGINT_ISO_STDIO_FORMATTED_IO#  include <stdio.h>  // sscanf# endif#endif// Gross hack to force use of simple internal functions.// Using libc sscanf fails (as far as I could tell from a quick look)// when assertions are enabled because some of the C++ contructors have// not been run yet.   jskov#undef CYGINT_ISO_STDIO_FORMATTED_IO#ifndef FALSE#define FALSE 0#define TRUE  1#endif#define PORTRAIT_MODE//#define LOGO_AT_TOP#include "banner.xpm"#include "font.h"// Physical dimensions of LCD display#define DISPLAY_WIDTH  320#define DISPLAY_HEIGHT 240// Logical layout#ifdef PORTRAIT_MODE#define LCD_WIDTH  240#define LCD_HEIGHT 320#else#define LCD_WIDTH  320#define LCD_HEIGHT 240#endif#define LCD_DEPTH   16static struct lcd_frame {    unsigned short palette[16];    unsigned short pixels[DISPLAY_HEIGHT][DISPLAY_WIDTH];    unsigned char  pad[256];} *lcd_frame_buffer = (struct lcd_frame *)0x01FC0000;  // Actually just 0x26000 bytes, but...#define USE_RGB565#ifdef USE_RGB565#define RGB_RED(x)   (((x)&0x1F)<<11)#define RGB_GREEN(x) (((x)&0x3F)<<5)#define RGB_BLUE(x)  ((x)&0x1F)#else#define RGB_RED(x)   (((x)&0x0F)<<12)#define RGB_GREEN(x) (((x)&0x0F)<<7)#define RGB_BLUE(x)  (((x)&0x0F)<<1)#endifstatic volatile struct lcd_frame *fp;// Physical screen info//static int lcd_depth  = LCD_DEPTH;  // Should be 1, 2, or 4static int lcd_bpp;static int lcd_width  = LCD_WIDTH;static int lcd_height = LCD_HEIGHT;// 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);static int fg = RGB_RED(15) | RGB_GREEN(63) | RGB_BLUE(8);static int bg = RGB_RED(0) | RGB_GREEN(0) | RGB_BLUE(15/*31*/);#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_start = 0;static int screen_height = SCREEN_HEIGHT;static int screen_width = SCREEN_WIDTH;static int screen_pan = 0;static bool cursor_enable = true;static int kbd_pos;// Functionsstatic void lcd_drawc(cyg_int8 c, int x, int y);#ifdef PORTRAIT_MODE// Translate coordinates, rotating clockwise 90 degreesstatic voidset_pixel(int row, int col, unsigned short val){    fp->pixels[col][(DISPLAY_WIDTH-1)-row] = val;}#elsestatic voidset_pixel(int row, int col, unsigned short val){    fp->pixels[row][col] = val;}#endifstatic 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);#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(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;}#endifintshow_xpm(char *xpm[], int screen_pos){    int i, row, col, offset;    char *cp;    int nrows, ncols, nclrs;    unsigned short colors[256];  // Mapped by character index    cp = xpm[0];#ifdef CYGINT_ISO_STDIO_FORMATTED_IO    if (sscanf(cp, "%d %d %d", &ncols, &nrows, &nclrs) != 3) {#else    if (((ncols = get_int(&cp)) < 0) ||        ((nrows = get_int(&cp)) < 0) ||        ((nclrs = get_int(&cp)) < 0)) {#endif        diag_printf("Can't parse XPM data, sorry\n");        return 0;    }    // printf("%d rows, %d cols, %d colors\n", nrows, ncols, nclrs);    for (i = 0;  i < 256;  i++) {        colors[i] = 0x0000;    }    for (i = 0;  i < nclrs;  i++) {        cp = xpm[i+1];        colors[(unsigned int)*cp] = parse_color(&cp[1]);        // printf("Color[%c] = %x\n", *cp, colors[(unsigned int)*cp]);    }#ifdef LOGO_AT_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++) {            set_pixel(row+offset, col, colors[(unsigned int)*cp++]);        }    }#ifdef LOGO_AT_TOP    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;    return offset+nrows;#else        screen_height = offset / FONT_HEIGHT;    return offset;#endif}voidlcd_init(int depth){    // Currently only color/16bpp supported    if (depth != 16) {        return;    }    lcd_bpp = depth;    fp = (struct lcd_frame *)hal_virt_to_phys_address((cyg_uint32)lcd_frame_buffer);    // Enable LCD in 320x240 16bpp    *SA1110_DBAR1 = (unsigned long)&(fp->palette);    *SA1110_LCCR1 = 0x0b100800 + DISPLAY_WIDTH - 16;    *SA1110_LCCR2 = 0x0a010400 + DISPLAY_HEIGHT - 1;    *SA1110_LCCR3 = 0x00300010;    fp->palette[0] = 0x2000;  // Tell controller true color / 16 bits    *SA1110_LCCR0 = 0xB9;     // Color    ipaq_EGPIO(SA1110_EIO_LCD_3V3|SA1110_EIO_LCD_CTRL|SA1110_EIO_LCD_5V|SA1110_EIO_LCD_VDD,	    SA1110_EIO_LCD_3V3_ON|SA1110_EIO_LCD_CTRL_ON|SA1110_EIO_LCD_5V_ON|SA1110_EIO_LCD_VDD_ON);    lcd_clear();    lcd_brightness(31);}// Get information about the frame bufferintlcd_getinfo(struct lcd_info *info){    if (lcd_bpp == 0) {        return 0;  // LCD not initialized    }    info->width = DISPLAY_WIDTH;    info->height = DISPLAY_HEIGHT;    info->bpp = lcd_bpp;    info->fb = (void *)lcd_frame_buffer->pixels;  // Note: this is cached    info->rlen = DISPLAY_WIDTH * 2;    info->type = FB_TRUE_RGB565;    return 1; // Information valid}// Control screen light [brightness]static voidlcd_brightness_ack(atmel_pkt *pkt){}static int _lcd_brightness;voidlcd_brightness(int level){    unsigned char cmd[3];    atmel_register(ATMEL_CMD_LIGHT, lcd_brightness_ack);    cmd[0] = 1;  // LCD magic    cmd[1] = (level > 0) ? 1 : 0;  // Turn light on    cmd[2] = level;    if (level) _lcd_brightness = level;    atmel_send(ATMEL_CMD_LIGHT, cmd, 3);}// Clear screenvoidlcd_clear(void){    int row, col;    int pos;#ifndef USE_RGB565    int val;    for (row = 0;  row < lcd_height;  row++) {        for (col = 0;  col < lcd_width;  col++) {            set_pixel(row, col, RGB_RED(31));        }    }    CYGACC_CALL_IF_DELAY_US(100000);    for (row = 0;  row < lcd_height;  row++) {        for (col = 0;  col < lcd_width;  col++) {            set_pixel(row, col, RGB_GREEN(31));        }    }    CYGACC_CALL_IF_DELAY_US(100000);    val = 0;    for (pos = 0;  pos < 16;  pos++) {        val = (1<<pos);        diag_printf("Set pixel to 0x%04x\n", val);        for (row = 0;  row < lcd_height;  row++) {            for (col = 0;  col < lcd_width;  col++) {                set_pixel(row, col, val);            }        }        CYGACC_CALL_IF_DELAY_US(100000);    }    val = 0;    for (pos = 8;  pos < 16;  pos++) {        val |= (1<<pos);        diag_printf("Set pixel to 0x%04x\n", val);        for (row = 0;  row < lcd_height;  row++) {            for (col = 0;  col < lcd_width;  col++) {                set_pixel(row, col, val);            }        }        CYGACC_CALL_IF_DELAY_US(100000);    }    for (row = 0;  row < lcd_height;  row++) {        for (col = 0;  col < lcd_width;  col++) {            set_pixel(row, col, RGB_BLUE(31));        }    }    CYGACC_CALL_IF_DELAY_US(100000);#endif // RGB565    for (row = 0;  row < lcd_height;  row++) {        for (col = 0;  col < lcd_width;  col++) {            set_pixel(row, col, bg);        }    }    for (row = 0;  row < screen_height;  row++) {        for (col = 0;  col < screen_width;  col++) {            screen[row][col] = ' ';        }    }    // Note: Row 0 seems to wrap incorrectly#ifdef LOGO_AT_TOP    pos = 0;#else    pos = (LCD_HEIGHT-1);#endif    kbd_pos = show_xpm(banner_xpm, pos);    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;    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];         for (p = 0;  p < FONT_WIDTH;  p++) {            if (bits & 0x01) {                set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, fg);            } else {                set_pixel(y*FONT_HEIGHT+l, x*FONT_WIDTH + p, bg);            }            bits >>= 1;        }    }}static voidlcd_refresh(void){    int row, col;#ifdef PORTRAIT_MODE    for (row = screen_start;  row < screen_height;  row++) {        for (col = 0;  col < VISIBLE_SCREEN_WIDTH;  col++) {            if ((col+screen_pan) < screen_width) {                lcd_drawc(screen[row][col+screen_pan], col, row);            } else {                lcd_drawc(' ', col, row);            }        }    }#else    cyg_uint16 *p1, *p2;    // Now the physical screen    for (row = FONT_HEIGHT*(screen_start+1);  row < LCD_HEIGHT;  row++) {                p1 = &fp->pixels[row-FONT_HEIGHT][0];        p2 = &fp->pixels[row][0];        for (col = 0;  col < LCD_WIDTH;  col++) {            *p1++ = *p2++;        }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?