////////////////////////////////////////////////////////////////////////////// // Product: Direct Video (VGA) screen output // Last Updated for Version: 4.1.01 // Date of the Last Update: Nov 04, 2009 // // Q u a n t u m L e a P s // --------------------------- // innovating embedded systems // // Copyright (C) 2002-2009 Quantum Leaps, LLC. All rights reserved. // // This software may be distributed and modified under the terms of the GNU // General Public License version 2 (GPL) as published by the Free Software // Foundation and appearing in the file GPL.TXT included in the packaging of // this file. Please note that GPL Section 2[b] requires that all works based // on this software must also be made publicly available under the terms of // the GPL ("Copyleft"). // // Alternatively, this software may be distributed and modified under the // terms of Quantum Leaps commercial licenses, which expressly supersede // the GPL and are specifically designed for licensees interested in // retaining the proprietary status of their code. // // Contact information: // Quantum Leaps Web site: http://www.quantum-leaps.com // e-mail: info@quantum-leaps.com ////////////////////////////////////////////////////////////////////////////// #include "qp_port.h" #include "video.h" #include #include Q_DEFINE_THIS_FILE #define VIDEO_BASE 0xB800 #define VIDEO_WIDTH 80 #define VIDEO_HEIGHT 25 #define OFF(x_, y_) ((((y_) * VIDEO_WIDTH) + (x_)) * 2) //............................................................................ void Video::clearScreen(uint8_t bgColor) { system("CLS"); clearRect(0, 0, VIDEO_WIDTH, VIDEO_HEIGHT, bgColor); } //............................................................................ void Video::clearRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t bgColor) { for ( ; y1 < y2; ++y1) { uint8_t x; uint8_t far *pscr = (uint8_t far *)MK_FP(VIDEO_BASE, (uint16_t)(((y1 * VIDEO_WIDTH) + x1) * 2)); for (x = x1; x < x2; ++x) { pscr[0] = ' '; // Put space in video RAM pscr[1] = bgColor; // Put video attribute in video RAM pscr += 2; } } } //............................................................................ void Video::drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t fgColor, uint8_t line) { static uint8_t const line_char[][6] = { { ' ', ' ', ' ', ' ', ' ', ' ' }, { 0xDA, 0xBF, 0xC0, 0xD9, 0xC4, 0xB3 }, { 0xC9, 0xBB, 0xC8, 0xBC, 0xCD, 0xBA } }; enum { UL_CORNER, UR_CORNER, LL_CORNER, LR_CORNER, HOR_LINE, VER_LINE }; Q_REQUIRE(line < Q_DIM(line_char)); // calculate position on the video RAM (VGA) uint8_t far *pscr = (uint8_t far *)MK_FP(VIDEO_BASE, 0); uint16_t off; uint8_t xy; off = OFF(x1, y1); pscr[off] = line_char[line][UL_CORNER]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM off = OFF(x2 - 1, y1); pscr[off] = line_char[line][UR_CORNER]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM off = OFF(x1, y2 - 1); pscr[off] = line_char[line][LL_CORNER]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM off = OFF(x2 - 1, y2 - 1); pscr[off] = line_char[line][LR_CORNER]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM for (xy = x1 + 1; xy < x2 - 1; ++xy) { off = OFF(xy, y1); pscr[off] = line_char[line][HOR_LINE]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM off = OFF(xy, y2 - 1); pscr[off] = line_char[line][HOR_LINE]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM } for (xy = y1 + 1; xy < y2 - 1; ++xy) { off = OFF(x1, xy); pscr[off] = line_char[line][VER_LINE]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM off = OFF(x2 - 1, xy); pscr[off] = line_char[line][VER_LINE]; pscr[off + 1] &= ~0x0F; // clear the foreground color pscr[off + 1] |= fgColor; // Put video attribute in video RAM } } //............................................................................ void Video::printStrAt(uint8_t x, uint8_t y, uint8_t color, char const *str) { // calculate position on the video RAM (VGA) uint8_t far *pscr = (uint8_t far *)MK_FP(VIDEO_BASE, (uint16_t)(((y * VIDEO_WIDTH) + x) * 2)); while (*str != (uint8_t)0) { pscr[0] = *str++; // Put character in video RAM pscr[1] &= ~0x0F; // clear the foreground color pscr[1] |= color; // Put video attribute in video RAM pscr += 2; } } //............................................................................ void Video::printNumAt(uint8_t x, uint8_t y, uint8_t color, uint32_t num) { char buf[4]; buf[3] = (char)0; buf[2] = (char)('0' + num % 10); num /= 10; buf[1] = (char)('0' + num % 10); num /= 10; buf[0] = (char)('0' + num % 10); if (buf[0] == '0') { buf[0] = ' '; } printStrAt(x, y, color, buf); } //............................................................................ void Video::drawBitmapAt(uint8_t x, uint8_t y, uint8_t const *bitmap, uint8_t width, uint8_t height) { uint8_t far *pscrX = (uint8_t far *)MK_FP(VIDEO_BASE, (uint16_t)(((y * VIDEO_WIDTH) + x) << 1)); uint8_t ix, iy; uint8_t w = width; uint8_t h = height; // perform the clipping if (x > VIDEO_WIDTH) { x = VIDEO_WIDTH; } if (y > VIDEO_HEIGHT) { y = VIDEO_HEIGHT; } if (w > VIDEO_WIDTH - x) { w = VIDEO_WIDTH - x; } if (h > VIDEO_HEIGHT - y) { h = VIDEO_HEIGHT - y; } for (ix = 0; ix < w; ++ix, pscrX += 2) { // loop over x uint8_t far *pscrXY = pscrX; for (iy = 0; iy < h; ++iy, pscrXY += 2*VIDEO_WIDTH) { static uint8_t const pixel[2] = { 0x20, 0xDB }; uint8_t byte = bitmap[ix + (iy >> 3)*width]; *pscrXY = pixel[(byte >> (iy & 0x7)) & 1]; } } } //............................................................................ void Video::drawStringAt(uint8_t x, uint8_t y, char const *str) { static uint8_t const font5x7[95][5] = { { 0x00, 0x00, 0x00, 0x00, 0x00 }, // ' ' { 0x00, 0x00, 0x4F, 0x00, 0x00 }, // ! { 0x00, 0x07, 0x00, 0x07, 0x00 }, // " { 0x14, 0x7F, 0x14, 0x7F, 0x14 }, // # { 0x24, 0x2A, 0x7F, 0x2A, 0x12 }, // $ { 0x23, 0x13, 0x08, 0x64, 0x62 }, // % { 0x36, 0x49, 0x55, 0x22, 0x50 }, // & { 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' { 0x00, 0x1C, 0x22, 0x41, 0x00 }, // ( { 0x00, 0x41, 0x22, 0x1C, 0x00 }, // ) { 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * { 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + { 0x00, 0x50, 0x30, 0x00, 0x00 }, // , { 0x08, 0x08, 0x08, 0x08, 0x08 }, // - { 0x00, 0x60, 0x60, 0x00, 0x00 }, // . { 0x20, 0x10, 0x08, 0x04, 0x02 }, // / { 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 { 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 { 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 { 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 { 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 { 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 { 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 { 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 { 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 { 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 { 0x00, 0x36, 0x36, 0x00, 0x00 }, // : { 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; { 0x08, 0x14, 0x22, 0x41, 0x00 }, // < { 0x14, 0x14, 0x14, 0x14, 0x14 }, // = { 0x00, 0x41, 0x22, 0x14, 0x08 }, // > { 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? { 0x32, 0x49, 0x79, 0x41, 0x3E }, // @ { 0x7E, 0x11, 0x11, 0x11, 0x7E }, // A { 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B { 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C { 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D { 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E { 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F { 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G { 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H { 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I { 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J { 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K { 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L { 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M { 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N { 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O { 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P { 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q { 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R { 0x46, 0x49, 0x49, 0x49, 0x31 }, // S { 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T { 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U { 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V { 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W { 0x63, 0x14, 0x08, 0x14, 0x63 }, // X { 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y { 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z { 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ { 0x02, 0x04, 0x08, 0x10, 0x20 }, /* \ */ { 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] { 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ { 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ { 0x00, 0x01, 0x02, 0x04, 0x00 }, // ` { 0x20, 0x54, 0x54, 0x54, 0x78 }, // a { 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b { 0x38, 0x44, 0x44, 0x44, 0x20 }, // c { 0x38, 0x44, 0x44, 0x48, 0x7F }, // d { 0x38, 0x54, 0x54, 0x54, 0x18 }, // e { 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f { 0x0C, 0x52, 0x52, 0x52, 0x3E }, // g { 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h { 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i { 0x20, 0x40, 0x44, 0x3D, 0x00 }, // j { 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k { 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l { 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m { 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n { 0x38, 0x44, 0x44, 0x44, 0x38 }, // o { 0x7C, 0x14, 0x14, 0x14, 0x08 }, // p { 0x08, 0x14, 0x14, 0x18, 0x7C }, // q { 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r { 0x48, 0x54, 0x54, 0x54, 0x20 }, // s { 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t { 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u { 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v { 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w { 0x44, 0x28, 0x10, 0x28, 0x44 }, // x { 0x0C, 0x50, 0x50, 0x50, 0x3C }, // y { 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z { 0x00, 0x08, 0x36, 0x41, 0x00 }, // { { 0x00, 0x00, 0x7F, 0x00, 0x00 }, // | { 0x00, 0x41, 0x36, 0x08, 0x00 }, // } { 0x02, 0x01, 0x02, 0x04, 0x02 }, // ~ }; while (*str != '\0') { drawBitmapAt(x, y, font5x7[*str - ' '], 5, 8); ++str; x += 6; } }