⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga_support.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================
//
//        vga_support.c
//
//        NMI picasso - VGA support
//
//==========================================================================
//####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 <gary@mind.be>
//
// 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 VGA 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/vga_support.h>
#include <cyg/hal/hal_cache.h>

#include <cyg/hal/plx.h>          // Localbus I/O

#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 VGA_WIDTH  640
#define VGA_HEIGHT 480
#define VGA_DEPTH    8

static int bg = 0;
static int fg = 1;

static struct vga_info vga;

struct VGA_ctlr {
    unsigned short rev;
    unsigned char  enable;
    unsigned char  _fill1[13];
    struct ADV471 {
        unsigned short write_addr;
        unsigned short data;
        unsigned short pixel_read_mask;
        unsigned short read_addr;
        unsigned short overlay_data;
        unsigned short _fill2[2];
        unsigned short overlay_read_addr;
    } clut;
    unsigned char _fill3[0x100000-0x20];
    unsigned char fb[1];
};

// Compute the location for a pixel within the framebuffer
static cyg_uint8 *
vga_fb(int row, int col)
{
    cyg_uint8 *res = (cyg_uint8 *)((char *)vga.fb+(row*vga.rlen)+(col*vga.stride));
    return res;
}

void
vga_on(bool enable)
{
    static bool on = false;
    volatile struct VGA_ctlr *ctlr = vga.ctlr;

    if (enable) {
        if (!on) {
            ctlr->enable = 1;
        }
        on = true;
    } else {
        ctlr->enable = 0;
        on = false;
    }
}

// Initialize VGA hardware

static void
vga_set_cmap(volatile struct VGA_ctlr *ctlr, int index, 
             int red, int green, int blue)
{
    if (index > 255) {
        // Invalid index
        return;
    }
    ctlr->clut.write_addr = index;  // Select
    ctlr->clut.data = red>>2;
    ctlr->clut.data = green>>2;
    ctlr->clut.data = blue>>2;
}

void
vga_init(cyg_uint32 *addr)
{
    volatile struct VGA_ctlr *ctlr;

    vga.ctlr = (struct VGA_ctlr *)ctlr = (struct VGA_ctlr *)addr;
    vga.fb = ctlr->fb;
    vga.bpp = VGA_DEPTH;
    vga.height = VGA_HEIGHT;
    vga.width = VGA_WIDTH;
    vga.rlen = VGA_WIDTH;
    vga.stride = 1;
    vga.access_size = 1;
    vga_set_cmap(ctlr, 0, 0x00, 0x00, 0x00);  // 0 -> black
    vga_set_cmap(ctlr, 1, 0xFF, 0xFF, 0xFF);  // 1 -> white
//    diag_printf("VGA init at %p/%p\n", vga.ctlr, vga.fb);
    ctlr->enable = 1;
}

// Get information about the frame buffer
int
vga_getinfo(struct vga_info *info)
{
    if (vga.bpp == 0) {
        return 0;  // VGA not initialized
    }
    *info = vga;
    return 1; // Information valid
}

// Clear screen
void
vga_clear(void)
{
#if 0
    cyg_uint32 *fb_row0, *fb_rown;
    cyg_uint32 _bg = (bg<<16)|bg;

    fb_row0 = vga_fb(0, 0);
    fb_rown = vga_fb(vga_height, 0);
    while (fb_row0 != fb_rown) {
        *fb_row0++ = _bg;
    }
#endif
}

#ifdef CYGSEM_UE250_VGA_COMM

//
// Additional support for VGA/Keyboard as 'console' device
//

#ifdef CYGOPT_UE250_VGA_COMM_LOGO
#include "banner.xpm"
#endif
#include "font.h"

// Virtual screen info
static int curX = 0;  // Last used position
static int curY = 0;
//static int width = VGA_WIDTH / (FONT_WIDTH*NIBBLES_PER_PIXEL);
//static int height = VGA_HEIGHT / (FONT_HEIGHT*SCREEN_SCALE);

#define SCREEN_PAN            20
#define SCREEN_WIDTH          80
#define SCREEN_HEIGHT         (VGA_HEIGHT/FONT_HEIGHT)
#define VISIBLE_SCREEN_WIDTH  (VGA_WIDTH/FONT_WIDTH)
#define VISIBLE_SCREEN_HEIGHT (VGA_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 = VGA_HEIGHT/FONT_HEIGHT;

static bool cursor_enable = true;

// Functions
static void vga_drawc(cyg_uint8 c, int x, int y);

static __inline__ void
set_pixel(int row, int col, unsigned char val)
{
    unsigned char *pix = (unsigned char *)vga_fb(row, col);
    *pix = val;
}

#ifdef CYGOPT_UE250_VGA_COMM_LOGO
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 void
parse_color(char *cp, int *red, int *green, int *blue)
{
    *red = *green = *blue = 0xFF;
    while (*cp && (*cp != 'c')) cp++;
    if (cp) {
        cp += 2;
        if (*cp == '#') {
            *red = _hex(cp+1);
            *green = _hex(cp+3);
            *blue = _hex(cp+5);
        }
    }
}

#ifndef CYGINT_ISO_STDIO_FORMATTED_IO
static int
get_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

static int
show_xpm(char *xpm[], int screen_pos)
{
    int i, row, col, offset;
    unsigned char *cp;
    int nrows, ncols, nclrs, cwid;
    short color_index;
    int red, green, blue;
//#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++) {
#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
        parse_color(cp+cwid, &red, &green, &blue);        
//        diag_printf("Color[%d] = %02x/%02x/%02x\n", color_index, red, green, blue);
        vga_set_cmap(vga.ctlr, color_index+2, red, green, blue);
        color_index++;
    }

#ifdef CYGOPT_UE250_VGA_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, color_index+2);
            cp += cwid;
        }
    }
#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP
    screen_start = (nrows + (FONT_HEIGHT-1))/FONT_HEIGHT;
    screen_end = VGA_HEIGHT/FONT_HEIGHT;
    return offset+nrows;
#else    
    screen_start = 0;
    screen_height = offset / FONT_HEIGHT;
    screen_end = screen_height;
    return offset;
#endif
}
#endif

void
vga_screen_clear(void)
{
    int row, col;
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
    int pos;
#endif

    for (row = 0;  row < screen_height;  row++) {
        for (col = 0;  col < screen_width;  col++) {
            screen[row][col] = ' ';
            vga_drawc(' ', col, row);
        }
    }
#ifdef CYGOPT_UE250_VGA_COMM_LOGO
    // Note: Row 0 seems to wrap incorrectly
#ifdef CYGOPT_UE250_VGA_COMM_LOGO_TOP
    pos = 0;
#else
    pos = (VGA_HEIGHT-1);
#endif
    show_xpm(banner_xpm, pos);
#endif // CYGOPT_UE250_VGA_COMM_LOGO
    curX = 0;  curY = screen_start;
    if (cursor_enable) {
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
    }
}

// Position cursor
void
vga_moveto(int X, int Y)
{
    if (cursor_enable) {
        vga_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) {
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
    }
}

static unsigned long _bitmap[] = {
#ifdef FONT_LEFT_TO_RIGHT
    0x00000000, 0x01000000, 0x00010000, 0x01010000,
    0x00000100, 0x01000100, 0x00010100, 0x01010100,
    0x00000001, 0x01000001, 0x00010001, 0x01010001,
    0x00000101, 0x01000101, 0x00010101, 0x01010101,
#else
    0x00000000, 0x00000001, 0x00000100, 0x00000101,
    0x00010000, 0x00010001, 0x00010100, 0x00010101,
    0x01000000, 0x01000001, 0x01000100, 0x01000101,
    0x01010000, 0x01010001, 0x01010100, 0x01010101
#endif
};

// Render a character at position (X,Y) with current background/foreground
static void
vga_drawc(cyg_uint8 c, int x, int y)
{
    cyg_uint8 bits;
    int l, p;
    int xoff, yoff;

⌨️ 快捷键说明

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