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

📄 vga_support.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 3 页
字号:
    unsigned long *pix;

    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_WIDTH;
#if 0  // Render font characters one bit at a time
        for (p = 0;  p < FONT_WIDTH;  p++) {
#ifdef FONT_LEFT_TO_RIGHT
            set_pixel(yoff, xoff + p, (bits & 0x80) ? fg : bg);
            bits <<= 1;
#else
            set_pixel(yoff, xoff + p, (bits & 0x01) ? fg : bg);
            bits >>= 1;
#endif
        }
#else  // Render characters 4 bits at a time
        pix = (unsigned long *)vga_fb(yoff, xoff);
#ifdef FONT_LEFT_TO_RIGHT
        *pix++ = _bitmap[(bits & 0xF0) >> 4];
        *pix++ = _bitmap[(bits & 0x0F)];
#else
        *pix++ = _bitmap[(bits & 0x0F)];
        *pix++ = _bitmap[(bits & 0xF0) >> 4];
#endif
#endif
    }
}

static void
vga_refresh(void)
{
    int row, col;

    for (row = screen_start;  row < screen_height;  row++) {
        for (col = 0;  col < VISIBLE_SCREEN_WIDTH;  col++) {
            if ((col+screen_pan) < screen_width) {
                vga_drawc(screen[row][col+screen_pan], col, row);
            } else {
                vga_drawc(' ', col, row);
            }
        }
    }
    if (cursor_enable) {
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
    }
}

static void
vga_scroll(void)
{
    int col;
    cyg_uint8 *c1;
    cyg_uint32 *lc0, *lc1, *lcn;
    cyg_uint32 *fb_row0, *fb_row1, *fb_rown;

    // First scroll up the virtual screen
#if ((SCREEN_WIDTH%4) != 0)
#error Scroll code optimized for screen with multiple of 4 columns
#endif
    lc0 = (cyg_uint32 *)&screen[0][0];
    lc1 = (cyg_uint32 *)&screen[1][0];
    lcn = (cyg_uint32 *)&screen[screen_height][0];
    while (lc1 != lcn) {
        *lc0++ = *lc1++;
    }
    c1 = &screen[screen_height-1][0];
    for (col = 0;  col < screen_width;  col++) {
        *c1++ = 0x20;
    }
#if 0  // Scrolling like this is *relly* slow
    fb_row0 = (cyg_uint32 *)vga_fb(screen_start*FONT_HEIGHT, 0);
    fb_row1 = (cyg_uint32 *)vga_fb((screen_start+1)*FONT_HEIGHT, 0);
    fb_rown = (cyg_uint32 *)vga_fb(screen_end*FONT_HEIGHT, 0);
#if 0
    while (fb_row1 != fb_rown) {
        *fb_row0++ = *fb_row1++;
    }
#else
    // Optimized ARM assembly "move" code
    asm __volatile(
        "mov r0,%0;"
        "mov r1,%1;"
        "mov r2,%2;"
        "10: ldmia r1!,{r3-r6};"
        "stmia r0!,{r3-r6};"
        "ldmia r1!,{r3-r6};"
        "stmia r0!,{r3-r6};"
        "cmp r1,r2;"
        "bne 10b"
        :
        : "r"(fb_row0), "r"(fb_row1), "r"(fb_rown)
        : "r0","r1","r2","r3","r4","r5","r6"
        );
#endif
    // Erase bottom line
    for (col = 0;  col < screen_width;  col++) {
        vga_drawc(' ', col, screen_end-1);
    }
#else  // Clear & redraw is faster!
    vga_refresh();
#endif
}

// Draw one character at the current position
void
vga_putc(cyg_uint8 c)
{
    if (cursor_enable) {
        vga_drawc(screen[curY][curX], curX-screen_pan, curY);
    }
    switch (c) {
    case '\r':
        curX = 0;
        break;
    case '\n':
        curY++;
        break;
    case '\b':
        curX--;
        if (curX < 0) {
            curY--;
            if (curY < 0) curY = 0;
            curX = screen_width-1;
        }
        break;
    default:
        if (((int)c < FIRST_CHAR) || ((int)c > LAST_CHAR)) c = '.';
        screen[curY][curX] = c;
        vga_drawc(c, curX-screen_pan, curY);
        curX++;
        if (curX == screen_width) {
            curY++;
            curX = 0;
        }
    } 
    if (curY >= screen_height) {
        vga_scroll();
        curY = (screen_height-1);
    }
    if (cursor_enable) {
        vga_drawc(CURSOR_ON, curX-screen_pan, curY);
    }
}

// Basic VGA 'printf()' support

#include <stdarg.h>

#define is_digit(c) ((c >= '0') && (c <= '9'))

static int
_cvt(unsigned long val, char *buf, long radix, char *digits)
{
    char temp[80];
    char *cp = temp;
    int length = 0;

    if (val == 0) {
        /* Special case */
        *cp++ = '0';
    } else {
        while (val) {
            *cp++ = digits[val % radix];
            val /= radix;
        }
    }
    while (cp != temp) {
        *buf++ = *--cp;
        length++;
    }
    *buf = '\0';
    return (length);
}

static int
vga_vprintf(void (*putc)(cyg_uint8), const char *fmt0, va_list ap)
{
    char c, sign, *cp;
    int left_prec, right_prec, zero_fill, length, pad, pad_on_right;
    char buf[32];
    long val;

    while ((c = *fmt0++)) {
        cp = buf;
        length = 0;
        if (c == '%') {
            c = *fmt0++;
            left_prec = right_prec = pad_on_right = 0;
            if (c == '-') {
                c = *fmt0++;
                pad_on_right++;
            }
            if (c == '0') {
                zero_fill = TRUE;
                c = *fmt0++;
            } else {
                zero_fill = FALSE;
            }
            while (is_digit(c)) {
                left_prec = (left_prec * 10) + (c - '0');
                c = *fmt0++;
            }
            if (c == '.') {
                c = *fmt0++;
                zero_fill++;
                while (is_digit(c)) {
                    right_prec = (right_prec * 10) + (c - '0');
                    c = *fmt0++;
                }
            } else {
                right_prec = left_prec;
            }
            sign = '\0';
            switch (c) {
            case 'd':
            case 'x':
            case 'X':
                val = va_arg(ap, long);
                switch (c) {
                case 'd':
                    if (val < 0) {
                        sign = '-';
                        val = -val;
                    }
                    length = _cvt(val, buf, 10, "0123456789");
                    break;
                case 'x':
                    length = _cvt(val, buf, 16, "0123456789abcdef");
                    break;
                case 'X':
                    length = _cvt(val, buf, 16, "0123456789ABCDEF");
                    break;
                }
                break;
            case 's':
                cp = va_arg(ap, char *);
                length = strlen(cp);
                break;
            case 'c':
                c = va_arg(ap, long /*char*/);
                (*putc)(c);
                continue;
            default:
                (*putc)('?');
            }
            pad = left_prec - length;
            if (sign != '\0') {
                pad--;
            }
            if (zero_fill) {
                c = '0';
                if (sign != '\0') {
                    (*putc)(sign);
                    sign = '\0';
                }
            } else {
                c = ' ';
            }
            if (!pad_on_right) {
                while (pad-- > 0) {
                    (*putc)(c);
                }
            }
            if (sign != '\0') {
                (*putc)(sign);
            }
            while (length-- > 0) {
                (*putc)(c = *cp++);
                if (c == '\n') {
                    (*putc)('\r');
                }
            }
            if (pad_on_right) {
                while (pad-- > 0) {
                    (*putc)(' ');
                }
            }
        } else {
            (*putc)(c);
            if (c == '\n') {
                (*putc)('\r');
            }
        }
    }

    // FIXME
    return 0;
}

int
_vga_printf(char const *fmt, ...)
{
    int ret;
    va_list ap;

    va_start(ap, fmt);
    ret = vga_vprintf(vga_putc, fmt, ap);
    va_end(ap);
    return (ret);
}

//
// Support VGA/keyboard (PS2) as a virtual I/O channel
//   Adapted from i386/pcmb_screen.c
//


//-----------------------------------------------------------------------------
// Keyboard definitions

#define	KBDATAPORT	0x0060		// data I/O port
#define	KBCMDPORT	0x0064		// command port (write)
#define	KBSTATPORT	0x0064		// status port	(read)

#define KBINRDY         0x01
#define KBOUTRDY        0x02
#define KBTXTO          0x40          // Transmit timeout - nothing there
#define KBTEST          0xAB

// Scan codes

#define LSHIFT    0x2a
#define RSHIFT    0x36
#define CTRL      0x1d
#define ALT       0x38
#define CAPS      0x3a
#define NUMS      0x45

#define BREAK     0x80

// Bits for KBFlags

#define KBNormal  0x0000
#define KBShift   0x0001
#define KBCtrl    0x0002
#define KBAlt     0x0004
#define KBIndex   0x0007  // mask for the above

#define KBExtend   0x0010
#define KBAck      0x0020
#define KBResend   0x0040
#define KBShiftL   (0x0080 | KBShift)
#define KBShiftR   (0x0100 | KBShift)
#define KBCtrlL    (0x0200 | KBCtrl)
#define KBCtrlR    (0x0400 | KBCtrl)
#define KBAltL     (0x0800 | KBAlt)
#define KBAltR     (0x1000 | KBAlt)
#define KBCapsLock 0x2000
#define KBNumLock  0x4000

#define KBArrowUp       0x48
#define KBArrowRight    0x4D
#define KBArrowLeft     0x4B
#define KBArrowDown     0x50

//-----------------------------------------------------------------------------
// Keyboard Variables

static  int  KBFlags = 0;

static  CYG_BYTE  KBPending = 0xFF;

static  CYG_BYTE  KBScanTable[128][4] = {
//  Normal    Shift    Control    Alt
// 0x00
    {  0xFF,    0xFF,    0xFF,    0xFF,   },
    {  0x1b,    0x1b,    0x1b,    0xFF,  },
    {  '1',    '!',    0xFF,    0xFF,  },
    {  '2',    '"',    0xFF,    0xFF,  },
    {  '3',    '#',    0xFF,    0xFF,  },
    {  '4',    '$',    0xFF,    0xFF,  },
    {  '5',    '%',    0xFF,    0xFF,  },
    {  '6',    '^',    0xFF,    0xFF,  },
    {  '7',    '&',    0xFF,    0xFF,  },
    {  '8',    '*',    0xFF,    0xFF,  },
    {  '9',    '(',    0xFF,    0xFF,  },
    {  '0',    ')',    0xFF,    0xFF,  },
    {  '-',    '_',    0xFF,    0xFF,  },
    {  '=',    '+',    0xFF,    0xFF,  },
    {  '\b',    '\b',    0xFF,    0xFF,  },
    {  '\t',    '\t',    0xFF,    0xFF,  },
// 0x10
    {  'q',    'Q',    0x11,    0xFF,  },
    {  'w',    'W',    0x17,    0xFF,  },
    {  'e',    'E',    0x05,    0xFF,  },
    {  'r',    'R',    0x12,    0xFF,  },
    {  't',    'T',    0x14,    0xFF,  },
    {  'y',    'Y',    0x19,    0xFF,  },
    {  'u',    'U',    0x15,    0xFF,  },
    {  'i',    'I',    0x09,    0xFF,  },
    {  'o',    'O',    0x0F,    0xFF,  },
    {  'p',    'P',    0x10,    0xFF,  },
    {  '[',    '{',    0x1b,    0xFF,  },
    {  ']',    '}',    0x1d,    0xFF,  },
    {  '\r',    '\r',    '\n',    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  'a',    'A',    0x01,    0xFF,  },
    {  's',    'S',    0x13,    0xFF,  },
// 0x20
    {  'd',    'D',    0x04,    0xFF,  },
    {  'f',    'F',    0x06,    0xFF,  },
    {  'g',    'G',    0x07,    0xFF,  },
    {  'h',    'H',    0x08,    0xFF,  },
    {  'j',    'J',    0x0a,    0xFF,  },
    {  'k',    'K',    0x0b,    0xFF,  },
    {  'l',    'L',    0x0c,    0xFF,  },
    {  ';',    ':',    0xFF,    0xFF,  },
    {  0x27,    '@',    0xFF,    0xFF,  },
    {  '#',    '~',    0xFF,    0xFF,  },
    {  '`',    '~',    0xFF,    0xFF,  },
    {  '\\',    '|',    0x1C,    0xFF,  },
    {  'z',    'Z',    0x1A,    0xFF,  },
    {  'x',    'X',    0x18,    0xFF,  },
    {  'c',    'C',    0x03,    0xFF,  },
    {  'v',    'V',    0x16,    0xFF,  },
// 0x30
    {  'b',    'B',    0x02,    0xFF,  },
    {  'n',    'N',    0x0E,    0xFF,  },
    {  'm',    'M',    0x0D,    0xFF,  },
    {  ',',    '<',    0xFF,    0xFF,  },
    {  '.',    '>',    0xFF,    0xFF,  },
    {  '/',    '?',    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  ' ',    ' ',    ' ',    ' ',  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xF1,    0xE1,    0xFF,    0xFF,  },
    {  0xF2,    0xE2,    0xFF,    0xFF,  },
    {  0xF3,    0xE3,    0xFF,    0xFF,  },
    {  0xF4,    0xE4,    0xFF,    0xFF,  },
    {  0xF5,    0xE5,    0xFF,    0xFF,  },
// 0x40
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },

    {  0x15,    0x15,    0x15,    0x15,  },
    {  0x10,    0x10,    0x10,    0x10,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
// 0x50
    {  0x04,    0x04,    0x04,    0x04,  },
    {  0x0e,    0x0e,    0x0e,    0x0e,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
// 0x60
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },
    {  0xFF,    0xFF,    0xFF,    0xFF,  },

⌨️ 快捷键说明

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