📄 lcd.c
字号:
/* * lcd.c --- Primary C source file for * LCD Device Driver with Framebuffer * (C)opyright 2004 Bit 920 Labs * * Written by: Ye Nan <bye200009123@163.com> * Created on: Sat. Mar 6 22:03:45 GMT +8:00 2004 */#ifndef __FB_LCD_C#define __FB_LCD_C#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <string.h>#include <linux/fb.h>#include <linux/kd.h>#include <sys/mman.h>#include <sys/types.h>#include <sys/stat.h>#include <termios.h>#include <sys/time.h>#include <sys/ioctl.h>#include "lcd.h"int current_vt;struct termios term;
// Framebuffer device routine
int fb_con = 0; /* framebuffer device handle */void * frame_base = 0; /* lcd framebuffer base address */// Framebuffer initialization.// Failed return -1, succeed return 0.int fb_Init(void){ struct fb_fix_screeninfo finfo; /* fixed screen information */ struct fb_var_screeninfo vinfo; /* variable screen information */ struct termios current; unsigned short red[256], green[256], blue[256]; struct fb_cmap new_map = {0, 256, red, green, blue, NULL}; /* new system palette */
tcgetattr(0, &term); current = term; current.c_lflag &= ~ICANON; current.c_lflag &= ~ECHO; current.c_cc[VMIN] = 1; current.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, ¤t); // Open vitual terminal current_vt = open("/dev/tty", O_RDWR); ioctl(current_vt, KDSETMODE, KD_GRAPHICS); // Open framebuffer device fb_con = open("/dev/fb0", O_RDWR, 0); if (fb_con < 0) { printf("Can't open /dev/fb0.\n"); return -1; } // Get fixed screen information if (ioctl(fb_con, FBIOGET_FSCREENINFO, &finfo) < 0) { printf("Can't get FSCREENINFO.\n"); close(fb_con); return -1; } // Get variable screen information if (ioctl(fb_con, FBIOGET_VSCREENINFO, &vinfo) < 0) { printf("Can't get VSCREENINFO.\n"); close(fb_con); return -1; } // Palette opertion srand(time(0)); // Make up a new palette fb_MakePalette(&new_map); // Apply new framebuffer palette if (finfo.visual == FB_VISUAL_DIRECTCOLOR || vinfo.bits_per_pixel == 8) { if (ioctl(fb_con, FBIOPUTCMAP, &new_map) < 0) { printf("Error putting Colormap.\n"); return -1; } } // Configure framebuffer color settings switch (vinfo.bits_per_pixel) { case 8: fb_pixel_size = 1; break; case 16: fb_pixel_size = 2; vinfo.red.offset = 11; vinfo.red.length = 5; vinfo.green.offset = 5;
vinfo.green.length = 6;
vinfo.blue.offset = 0;
vinfo.blue.length = 5;
break;
default:
fprintf(stderr, "Current color depth is NOT surpported.\n");
fb_pixel_size = 1;
break;
}
// Apply new settings to the framebuffer
if (ioctl(fb_con, FBIOPUT_VSCREENINFO, &vinfo) < 0)
{
fprintf(stderr, "Couldn't set ideal mode at FBIOPUT_VSCREENINFO");
return -1;
}
// Retrieve screen size information
if (ioctl(fb_con, FBIOGET_VSCREENINFO, &vinfo) < 0)
{
fprintf(stderr, "ioctl FBIOGET_VSCREENINFO");
return -1;
}
fb_width = vinfo.xres_virtual;
fb_height = vinfo.yres_virtual;
fb_bpp = vinfo.bits_per_pixel;
fb_line_size = finfo.line_length;
fb_buffer_size = finfo.smem_len;
// Map frame buffer to a vitual memory area
frame_base = mmap(NULL, BUFFER_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fb_con, 0); if (frame_base == MAP_FAILED) { fprintf(stderr, "Can't mmap.\n"); close(fb_con); return -1; } printf("\nVideo memory address = 0x%x\n",frame_base); printf("Video visible resolution: x_res = %ld, y_res = %ld\n", SCREEN_WIDTH, SCREEN_HEIGHT);
// Clear screen
fb_Clear(SYS_BLACK);
return 0;}
// Framebuffer releasevoid fb_Release(void){
fb_AssertDevice(fb_con); // release the vitual memeory area of frame buffer munmap(frame_base, BUFFER_SIZE);
// close framebuffer device if(fb_con) close(fb_con); tcsetattr(0, TCSANOW, &term); return;}// Assert device is openedint fb_AssertDevice(int dev){ if (dev == 0) { printf("Device is NOT opened.\n"); return -1; } return 0;}// Make up System Palettevoid fb_MakePalette(struct fb_cmap *map){ int rs, gs, bs, i; int r = 8, g = 8, b = 4; if (map == NULL) return; rs = 256 / (r - 1); gs = 256 / (g - 1); bs = 256 / (b - 1); for (i = 0; i < 256; i++) { map->red[i] = (rs * ((i / (g * b)) % r)) * 255; map->green[i] = (gs * ((i / b) % g)) * 255; map->blue[i] = (bs * ((i) % b)) * 255; } return;}// Save System Paletteint fb_SavePalette(struct fb_cmap * map){ fb_AssertDevice(fb_con); if (BPP == 8) { if (ioctl(fb_con, FBIOGETCMAP, map) < 0) { printf("Save system palette failed.\n"); return -1; } } return 0;}// Update System Paletteint fb_UpdatePalette(struct fb_cmap map){ fb_AssertDevice(fb_con); if (BPP == 8) { if(ioctl(fb_con, FBIOPUTCMAP, &map) < 0) { printf("Update system palette failed.\n"); return -1; } } return 0;}// Make up a color fits for 8-bit display according to RGB factors specified
ColorType fb_MakeColor_8(ByteType red, ByteType green, ByteType blue)
{
ColorType color;
// Adjust RGB factors to fit 16 bit display red >>= 5; green >>= 5; blue >>=6; red &= 7; green &= 7; blue &= 3; // Use RGB factors to make up the display color color = (red << 5 | green << 2 | blue); return color;
}
// Make up a color fits for 16-bit display according to RGB factors specified
ColorType fb_MakeColor_16(ByteType red, ByteType green, ByteType blue)
{
ColorType color;
// Adjust RGB factors to fit 16 bit display red >>= 3; green >>= 2; blue >>= 3; // Use RGB factors to make up the display color color = (red << 11 | green << 5 | blue); return color;
}
// Retrieve base address of frame buffer
void * fb_GetFrameAddr(){ return frame_base;}
// Retrieve screen widthunsigned int fb_GetScreenWidth(){ return SCREEN_WIDTH;}
// Retrieve screen heightunsigned int fb_GetScreenHeight(){ return SCREEN_HEIGHT;}
// Retrieve screen bpp(bits per pixel)
unsigned int fb_GetScreenBpp()
{
return BPP;
}
// Retrieve screen colors
unsigned int fb_GetScreenColors()
{
return (1 << BPP);
}
// Clear screen with specified color
void fb_Clear(ColorType color)
{
switch (BPP)
{
case 8:
memset((ByteType *)frame_base, (color & 0xff), BUFFER_SIZE);
break;
case 16:
memset((WordType *)frame_base, (color & 0xffff), BUFFER_SIZE);
}
}
// Put a color pixel on the screenvoid fb_PutPixel(short x, short y, ColorType color/*, int xorm */){ void * currPoint;
if (x < 0 || x >= SCREEN_WIDTH ||
y < 0 || y >= SCREEN_HEIGHT)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x = %d, y = %d\n", x, y);
#endif
return;
}
// Calculate address of specified point
currPoint = (ByteType *)frame_base + y * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y= %d, currPoint = 0x%x\n", x, y, currPoint);
#endif
switch (BPP)
{
case 8:
*((ByteType *)currPoint) = (color & 0xff);
break;
case 16:
*((WordType *)currPoint) = (color & 0xffff);
break;
}
return;}
// Retrieve the color of specified pixel
ColorType fb_GetPixel(short x, short y){ void * currPoint;
ColorType color;
if (x < 0 || x >= SCREEN_WIDTH ||
y < 0 || y >= SCREEN_HEIGHT)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x = %d, y = %d\n", x, y);
#endif
return;
}
// Calculate address of specified point
currPoint = (ByteType *)frame_base + y * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y= %d, currPoint = 0x%x\n", x, y, currPoint);
#endif
switch (BPP)
{
case 8:
color = *((ByteType *)currPoint);
break;
case 16:
color = *((WordType *)currPoint);
break;
}
return color;}
// Draw a horizontal line on the screen
void fb_DrawLine_H(short x1, short x2, short y, ColorType color/*, int xorm */){ long startOffset = 0;
x1 = (x1 < 0) ? 0 : x1;
x2 = (x2 < 0) ? 0 : x2;
x1 = (x1 >= SCREEN_WIDTH) ? SCREEN_WIDTH - 1 : x1;
x2 = (x2 >= SCREEN_WIDTH) ? SCREEN_WIDTH - 1 : x2;
if (y < 0 || y >= SCREEN_HEIGHT)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x1 = %d, x2 = %d, y = %d\n", x1, x2, y);
#endif
return;
}
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line startOffset = y * LINE_SIZE + x1 * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x1 = %d, x2 = %d, y = %d, startOffset = 0x%x\n", x1, x2, y, startOffset);
#endif
switch (BPP)
{
case 8:
memset((ByteType *)((ByteType *)frame_base + startOffset), (color & 0xff), (x2 - x1 + 1) * PIXEL_SIZE);
break;
case 16:
memset((WordType *)((ByteType *)frame_base + startOffset), (color & 0xffff), (x2 - x1 + 1) * PIXEL_SIZE);
break;
}
return;
}// Draw a vertical line on the screen
void fb_DrawLine_V(short x, short y1, short y2, ColorType color/*, int xorm */){ short currLine;
void * currPoint;
y1 = (y1 < 0) ? 0 : y1;
y2 = (y2 < 0) ? 0 : y2;
y1 = (y1 >= SCREEN_HEIGHT) ? SCREEN_HEIGHT - 1 : y1;
y2 = (y2 >= SCREEN_HEIGHT) ? SCREEN_HEIGHT - 1 : y2;
if (x < 0 || x >= SCREEN_WIDTH)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x = %d, y1 = %d, y2 = %d\n", x, y1, y2);
#endif
return;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
currPoint = (ByteType *)frame_base + y1 * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y1 = %d, y2 = %d, currPoint = 0x%x\n", x, y1, y2, currPoint);
#endif
for (currLine = y1; currLine <= y2; currLine++) {
switch (BPP)
{
case 8:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -