
Frame buffer의 구조 및 그래픽의 기본적인 각도 계산 및 재귀호출, 베지어곡선의 수학개념을 이해하기 위해서 만들어 본겁니다.
lilo.conf 에 "vga=0x0317" 이라는 옵션을 주고 해보세요.
| 코드: |
/* Copyright (C) Information Equipment co.,LTD All rights reserved. Code by JaeHyuk Cho <mailto:minzkn@infoeq.com> CVSTAG="$Header$" */ #include <sys/types.h> #include <sys/select.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <math.h> #include <signal.h> #include <linux/fb.h> #define DEF_2PI (2.0 * 3.14159265358) static int g_FB_Handle, g_FB_Cx, g_FB_Cy, g_FB_ScreenSize; static struct fb_fix_screeninfo g_FB_FIX; static struct fb_var_screeninfo g_FB_VAR; static void *g_FB_Map; static void (*DrawPixel)(int, int, int); volatile int g_break_clock = 0; static void clock_signal(int s_signal) { g_break_clock = 1; (void)signal(s_signal, clock_signal); } static void (clock_load_balance)(void) { #if 1 struct timeval s_timeval = {0l, 1000000l / 100l /* hz */}; (void)select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, (struct timeval *)(&s_timeval)); #endif } static void DrawPixel8(int s_Color, int s_x, int s_y) { *(((unsigned char *)g_FB_Map) + (s_y * g_FB_FIX.line_length) + s_x) = (unsigned char)s_Color; } static void DrawPixel16(int s_Color, int s_x, int s_y) { *((unsigned short *)(((unsigned char *)g_FB_Map) + (s_y * g_FB_FIX.line_length) + (s_x << 1))) = (unsigned short)s_Color; } static void DrawPixel24(int s_Color, int s_x, int s_y) { unsigned char *s_FB_Ptr = ((unsigned char *)g_FB_Map) + (s_y * g_FB_FIX.line_length) + ((s_x << 1) + s_x); *((unsigned short *)s_FB_Ptr) = (unsigned short)s_Color; *(s_FB_Ptr + sizeof(unsigned short)) = (unsigned char)(s_Color >> 16); } static void DrawPixel32(int s_Color, int s_x, int s_y) { *((unsigned long *)(((unsigned char *)g_FB_Map) + (s_y * g_FB_FIX.line_length) + (s_x << 2))) = (unsigned long)s_Color; } static void PinXY(int s_Angle, int *s_x, int *s_y, int s_r) { /* s_To(Grid) : X = s_From(Grid) : s_Current */ double s_Value = ((DEF_2PI * (double)(s_Angle % 360)) / 360.0); *(s_x) = (int)(sin(s_Value) * s_r); *(s_y) = (int)(-cos(s_Value) * s_r); } static void __DrawLine__(int s_Color, float s_x1, float s_y1, float s_x2, float s_y2, int s_Level) { /* Call by call level 16 optimize draw line : JaeHyuk algorithm ^^ */ float s_cx = (s_x1 + s_x2) / 2.0, s_cy = (s_y1 + s_y2) / 2.0; if(((int)s_x1 == (int)s_x2 && (int)s_y1 == (int)s_y2) || s_Level > 16)DrawPixel(s_Color, (int)s_cx, (int)s_cy); else { s_Level++; __DrawLine__(s_Color, s_x1, s_y1, s_cx, s_cy, s_Level); __DrawLine__(s_Color, s_cx, s_cy, s_x2, s_y2, s_Level); } } static void DrawLine(int s_Color, int s_x1, int s_y1, int s_x2, int s_y2) { __DrawLine__(s_Color, (float)s_x1, (float)s_y1, (float)s_x2, (float)s_y2, 0); } static void DrawCircle(int s_Color, int s_x, int s_y, int s_r) { double s_Pi, s_Grid = 1.0 / ((double)s_r), s_sinX, s_cosY; for(s_Pi = 0.0;s_Pi < (DEF_2PI / 4.0);s_Pi += s_Grid) { s_sinX = sin(s_Pi) * (double)s_r; s_cosY = -cos(s_Pi) * (double)s_r; DrawPixel(s_Color, (int)(s_x + s_sinX), (int)(s_y + s_cosY)); DrawPixel(s_Color, (int)(s_x - s_sinX), (int)(s_y + s_cosY)); DrawPixel(s_Color, (int)(s_x + s_sinX), (int)(s_y - s_cosY)); DrawPixel(s_Color, (int)(s_x - s_sinX), (int)(s_y - s_cosY)); } } static void Pin(int s_Color, int s_Angle, int s_Type) { int s_x1, s_y1, s_x2, s_y2, s_x3, s_y3; int s_Size; s_Size = g_FB_ScreenSize >> 1; if(s_Type == 0) s_Size -= ((g_FB_ScreenSize >> 1) >> 3); else if(s_Type == 10) s_Size -= ((g_FB_ScreenSize >> 1) >> 3); else if(s_Type == 20) s_Size -= ((g_FB_ScreenSize >> 1) >> 2); PinXY(s_Angle, &s_x1, &s_y1, s_Size >> 2); PinXY(s_Angle, &s_x2, &s_y2, s_Size); DrawLine(s_Color, g_FB_Cx - s_x1, g_FB_Cy - s_y1, g_FB_Cx + s_x2, g_FB_Cy + s_y2); if(s_Type > 0) { PinXY(s_Angle + 90, &s_x3, &s_y3, s_Type); DrawLine(s_Color, g_FB_Cx - s_x1, g_FB_Cy - s_y1, g_FB_Cx + s_x3, g_FB_Cy + s_y3); DrawLine(s_Color, g_FB_Cx + s_x2, g_FB_Cy + s_y2, g_FB_Cx + s_x3, g_FB_Cy + s_y3); DrawLine(s_Color, g_FB_Cx - s_x1, g_FB_Cy - s_y1, g_FB_Cx - s_x3, g_FB_Cy - s_y3); DrawLine(s_Color, g_FB_Cx + s_x2, g_FB_Cy + s_y2, g_FB_Cx - s_x3, g_FB_Cy - s_y3); } } int main(int s_argc, char **s_argv) { (void)signal(SIGINT, clock_signal); printf("fbclock v1.0.1 - Code by JaeHyuk Cho <minzkn@infoeq.co.kr>\n\n"); g_FB_Handle = open(s_argc >= 2 ? s_argv[1] : "/dev/fb0", O_RDWR); if(g_FB_Handle >= 0) { if(ioctl(g_FB_Handle, FBIOGET_FSCREENINFO, &g_FB_FIX) == 0) { if(ioctl(g_FB_Handle, FBIOGET_VSCREENINFO, &g_FB_VAR) == 0) { g_FB_Map = mmap((void *)0, g_FB_FIX.line_length * g_FB_VAR.yres, PROT_READ | PROT_WRITE, MAP_SHARED, g_FB_Handle, 0); if(g_FB_Map != (void *)(-1)) { switch(g_FB_VAR.bits_per_pixel) { case 8: DrawPixel = DrawPixel8; break; case 16: DrawPixel = DrawPixel16; break; case 24: DrawPixel = DrawPixel24; break; case 32: DrawPixel = DrawPixel32; break; default: DrawPixel = (void *)0; break; } g_FB_Cx = g_FB_VAR.xres >> 1; g_FB_Cy = g_FB_VAR.yres >> 1; g_FB_ScreenSize = g_FB_VAR.xres < g_FB_VAR.yres ? g_FB_VAR.xres : g_FB_VAR.yres; if(DrawPixel) { int s_PreSecond = 0, s_PreMinute = 0, s_PreHour = 0, s_Count, s_Index, s_x, s_y; time_t s_UTC; struct tm *s_LocalTime; s_Count = 0; do { s_UTC = time((time_t *)0); s_LocalTime = localtime(&s_UTC); if(s_LocalTime->tm_sec != s_PreSecond) { if(s_LocalTime->tm_min != s_PreMinute) { if(s_LocalTime->tm_hour != s_PreHour) { Pin(0, s_PreHour * 30, 20); s_PreHour = s_LocalTime->tm_hour; } Pin(0, s_PreMinute * 6, 10); s_PreMinute = s_LocalTime->tm_min; } Pin(0, s_PreSecond * 6, 0); Pin(0xf00f, s_LocalTime->tm_hour * 30, 20); Pin(0x0ff0, s_LocalTime->tm_min * 6, 10); Pin(0xffff, s_LocalTime->tm_sec * 6, 0); DrawCircle(0x0fff, g_FB_Cx, g_FB_Cy, 5); s_PreSecond = s_LocalTime->tm_sec; } do { int s_tick; for(s_tick = 0;s_tick < 10;s_tick++)clock_load_balance(); }while(0); PinXY(s_Count, &s_x, &s_y, (g_FB_ScreenSize >> 1) - (g_FB_ScreenSize >> 5)); s_Index = (s_Count % 30) ? 5 : 10; DrawCircle(0xffff, g_FB_Cx + s_x, g_FB_Cy + s_y, s_Index); DrawCircle(0xffff, g_FB_Cx - s_x, g_FB_Cy + s_y, s_Index); DrawCircle(0xffff, g_FB_Cx + s_x, g_FB_Cy - s_y, s_Index); DrawCircle(0xffff, g_FB_Cx - s_x, g_FB_Cy - s_y, s_Index); s_Count+=6; if(s_Count > 90)s_Count = 0; }while(g_break_clock == 0); } else fprintf(stderr, "Err: %d\n", __LINE__); munmap(g_FB_Map, g_FB_FIX.line_length * g_FB_VAR.yres); } else fprintf(stderr, "Err: %d\n", __LINE__); } else fprintf(stderr, "Err: %d\n", __LINE__); } else fprintf(stderr, "Err: %d\n", __LINE__); close(g_FB_Handle); } else fprintf(stderr, "Err: %d\n", __LINE__); (void)fprintf(stdout, "End of clock\n"); return(0); } /* vim: set expandtab: */ /* End of source */ |
Marius Konitzer 씨가 예전에 만들었던 fbclock을 개선하였다고 패치된 내용을 보내왔습니다. 외국인이 직접 제 소스를 패치해준것은 공식적으로 처음이군요.
잘 알지도 못하는 외국인으로부터 몇번 다른 여러 소스들에 대해서 개선점을 Mail 로 받아본적은 있지만 이렇게 패치로 보내준것은 처음인것 같네요.
Marius Konitzer 씨 에게 감사(Thanks)의 마음을 이자리를 빌어서 전합니다.
다음은 Marius Konitzer 씨가 저에게 보내준 Mail의 원문내용입니다.
| 인용: |
| Hello! I recently needed a analog clock for fb output. It seemed that there was none - except from your fbclock. I liked it's charming simplicity and decided to improve it somewhat. So here is what I did: * hour and minute hands are drawn on "in-between" positions, too * added some commandline options for colour switching * using default colours depending on the fb's bitdepth I thought this could be of interest for you, if you like to implement it in the upstream version of your fbclock!? (perhaps even mentioning me in the source... ;-)) Nice greetings from Germany, Marius Konitzer |
아래의 패치가 patch명령으로 일부 적용되지 않을수 있습니다. 그래서 직접 손으로 해주어야 할지도 모릅니다. 원인은 제가 개념없이 버젼관리를 해서입니다. 버젼이 한가지라라면 문제가 없겠지만 비슷한 버젼이 꽤 많거든요...
| 코드: |
| --- fbclock.orig.c 2005-11-25 00:44:09.000000000 +0100 +++ fbclock.c 2005-11-26 14:21:43.000000000 +0100 @@ -8,6 +8,8 @@ */ #include <stdio.h> +#include <stdlib.h> +#include <string.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> @@ -25,6 +27,10 @@ static struct fb_var_screeninfo g_FB_VAR; static void *g_FB_Map; static void (*DrawPixel)(int, int, int); +static char *g_Progname; +static int g_Col8[4] = {0x04, 0x01, 0x0e, 0x07}; /* red, blue, green, grey */ +static int g_Col16[4] = {0xf000, 0x00f0, 0xff00, 0x8410}; /* rgb565 */ +static int g_Col24[4] = {0xdd0000, 0x0000ff, 0xffff00, 0x808080}; /* rgb888 */ static void DrawPixel8(int s_Color, int s_x, int s_y) { @@ -103,11 +109,50 @@ } } +void Usage() { + printf("Usage: %s [-h] [-d fbdev] [-hc col] [-mc col] [-sc col] [-bc col]\n", g_Progname); + printf(" -h show this help page\n"); + printf(" -d fbdev use fbdev as framebuffer device\n"); + printf(" -hc col specifies colour for hour hand\n"); + printf(" -mc col specifies colour for minute hand\n"); + printf(" -sc col specifies colour for second hand\n"); + printf(" -bc col specifies border colour\n"); + printf("col is a hexadecimal colour code, that depends on your framebuffer's\n"); + printf("colour depth, e.g. \"-hc 0xf0f0\" for 16 bit\n"); + exit(1); +} + int main(int s_Argc, char *s_Argv[]) { + int i, s_Colour[4], s_isColSet[4]={0,0,0,0}; char *s_Device = "/dev/fb0"; - if(s_Argc > 1)s_Device = s_Argv[1]; + g_Progname = s_Argv[0]; printf("fbclock v1.0.1 - Code by JaeHyuk Cho <minzkn@infoeq.co.kr>\n\n"); + while(--s_Argc) { + s_Argv++; + if (s_Argc<=1) Usage(); + if (!strcmp(s_Argv[0], "-d")) + s_Device = s_Argv[1]; + else if (!strcmp(s_Argv[0], "-hc")) { + if (sscanf(s_Argv[1], "0x%x", &s_Colour[0])!=1) + Usage(); + s_isColSet[0]=1; + } else if (!strcmp(s_Argv[0], "-mc")) { + if (sscanf(s_Argv[1], "0x%x", &s_Colour[1])!=1) + Usage(); + s_isColSet[1]=1; + } else if (!strcmp(s_Argv[0], "-sc")) { + if (sscanf(s_Argv[1], "0x%x", &s_Colour[2])!=1) + Usage(); + s_isColSet[2]=1; + } else if (!strcmp(s_Argv[0], "-bc")) { + if (sscanf(s_Argv[1], "0x%x", &s_Colour[3])!=1) + Usage(); + s_isColSet[3]=1; + } else + Usage(); + s_Argc--; s_Argv++; + } g_FB_Handle = open(s_Device, O_RDWR); if(g_FB_Handle >= 0) { @@ -130,40 +175,49 @@ g_FB_ScreenSize = g_FB_VAR.xres < g_FB_VAR.yres ? g_FB_VAR.xres : g_FB_VAR.yres; if(DrawPixel) { - int s_PreSecond = 0, s_PreMinute = 0, s_PreHour = 0, s_Count, s_Index, s_x, s_y; + int s_Count, s_Index, s_x, s_y; + int s_PreAngleSecond = 0, s_PreAngleMinute = 0, s_PreAngleHour = 0; + int s_AngleSecond = 0, s_AngleMinute = 0, s_AngleHour = 0; time_t s_UTC; struct tm *s_LocalTime; s_Count = 0; + for (i=0; i<4; i++) { + if (!s_isColSet[i]) + s_Colour[i]=(DrawPixel==DrawPixel8?g_Col8[i]:(DrawPixel==DrawPixel16?g_Col16[i]:g_Col24[i])); + } do { s_UTC = time((time_t *)0); s_LocalTime = localtime(&s_UTC); - if(s_LocalTime->tm_sec != s_PreSecond) + s_AngleSecond = s_LocalTime->tm_sec * 6; + s_AngleMinute = s_LocalTime->tm_min * 6 + ((float)s_LocalTime->tm_sec / 10); + s_AngleHour = s_LocalTime->tm_hour * 30 + ((float)s_LocalTime->tm_min / 2); + if(s_AngleSecond != s_PreAngleSecond) { - if(s_LocalTime->tm_min != s_PreMinute) + if(s_AngleMinute != s_PreAngleMinute) { - if(s_LocalTime->tm_hour != s_PreHour) + if(s_AngleHour != s_PreAngleHour) { - Pin(0, s_PreHour * 30, 20); - s_PreHour = s_LocalTime->tm_hour; + Pin(0, s_PreAngleHour, 20); + s_PreAngleHour = s_AngleHour; } - Pin(0, s_PreMinute * 6, 10); - s_PreMinute = s_LocalTime->tm_min; + Pin(0, s_PreAngleMinute, 10); + s_PreAngleMinute = s_AngleMinute; } - Pin(0, s_PreSecond * 6, 0); - Pin(0xf00f, s_LocalTime->tm_hour * 30, 20); - Pin(0x0ff0, s_LocalTime->tm_min * 6, 10); - Pin(0xffff, s_LocalTime->tm_sec * 6, 0); - DrawCircle(0x0fff, g_FB_Cx, g_FB_Cy, 5); - s_PreSecond = s_LocalTime->tm_sec; + Pin(0, s_PreAngleSecond, 0); + s_PreAngleSecond = s_AngleSecond; + Pin(s_Colour[0], s_AngleHour, 20); + Pin(s_Colour[1], s_AngleMinute, 10); + Pin(s_Colour[2], s_AngleSecond, 0); + DrawCircle(s_Colour[3], g_FB_Cx, g_FB_Cy, 5); } usleep(DEF_HEAT_CPU); PinXY(s_Count, &s_x, &s_y, (g_FB_ScreenSize >> 1) - (g_FB_ScreenSize >> 5)); s_Index = (s_Count % 30) ? 5 : 10; - DrawCircle(0xffff, g_FB_Cx + s_x, g_FB_Cy + s_y, s_Index); - DrawCircle(0xffff, g_FB_Cx - s_x, g_FB_Cy + s_y, s_Index); - DrawCircle(0xffff, g_FB_Cx + s_x, g_FB_Cy - s_y, s_Index); - DrawCircle(0xffff, g_FB_Cx - s_x, g_FB_Cy - s_y, s_Index); + DrawCircle(s_Colour[3], g_FB_Cx + s_x, g_FB_Cy + s_y, s_Index); + DrawCircle(s_Colour[3], g_FB_Cx - s_x, g_FB_Cy + s_y, s_Index); + DrawCircle(s_Colour[3], g_FB_Cx + s_x, g_FB_Cy - s_y, s_Index); + DrawCircle(s_Colour[3], g_FB_Cx - s_x, g_FB_Cy - s_y, s_Index); s_Count+=6; if(s_Count > 90)s_Count = 0; }while(1); |




댓글을 달아 주세요