main.c
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <stdint.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <linux/fb.h> #include <linux/omapfb.h> #define FB_MAP_SIZE (800 * 480 * 2 * 2) static int fbdev[2] = {0}; static void* fbpixels[2] = {0}; static uint32_t get_ticks(void) { struct timeval tv = {0}; static struct timeval init_tv = {0}; gettimeofday(&tv, 0); if (init_tv.tv_sec == 0) { init_tv = tv; } return ((tv.tv_sec - init_tv.tv_sec) * 1000000) + tv.tv_usec - init_tv.tv_usec; } static void init_fb(void) { int arg = 0; struct omapfb_mem_info mi = {0}; struct omapfb_plane_info pi = {0}; struct fb_var_screeninfo vinfo = {0}; struct fb_fix_screeninfo finfo = {0}; fbdev[0] = open("/dev/fb0", O_RDWR); fbdev[1] = open("/dev/fb1", O_RDWR); ioctl(fbdev[1], OMAPFB_QUERY_PLANE, &pi); ioctl(fbdev[1], OMAPFB_QUERY_MEM, &mi); if (pi.enabled) { pi.enabled = 0; ioctl(fbdev[1], OMAPFB_SETUP_PLANE, &pi); } mi.size = FB_MAP_SIZE; ioctl(fbdev[1], OMAPFB_SETUP_MEM, &mi); pi.pos_x = 0; pi.pos_y = 0; pi.out_width = 800; pi.out_height = 480; pi.enabled = 1; ioctl(fbdev[1], OMAPFB_SETUP_PLANE, &pi); ioctl(fbdev[0], FBIOGET_VSCREENINFO, &vinfo); ioctl(fbdev[0], FBIOGET_FSCREENINFO, &finfo); fbpixels[0] = (uint16_t *)mmap(0, FB_MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fbdev[0], 0); memset(fbpixels[0], 0, FB_MAP_SIZE); printf("fb0: fd:0x%08lx name:\"%s\" @ 0x%08lx (mmap: 0x%08lx)\n", fbdev[0], finfo.id, finfo.smem_start, fbpixels[0]); ioctl(fbdev[1], FBIOGET_VSCREENINFO, &vinfo); ioctl(fbdev[1], FBIOGET_FSCREENINFO, &finfo); fbpixels[1] = (uint16_t *)mmap(0, FB_MAP_SIZE, PROT_WRITE | PROT_READ, MAP_SHARED, fbdev[1], 0); memset(fbpixels[1], 0, FB_MAP_SIZE); printf("fb1: fd:0x%08lx name:\"%s\" @ 0x%08lx (mmap: 0x%08lx)\n", fbdev[1], finfo.id, finfo.smem_start, fbpixels[1]); } static void deinit_fb(void) { struct omapfb_plane_info pi = {0}; if (fbpixels[0]) { munmap(fbpixels[0], FB_MAP_SIZE); } if (fbpixels[1]) { munmap(fbpixels[1], FB_MAP_SIZE); } if (fbdev[0] > 0) { close(fbdev[0]); } if (fbdev[1] > 0) { ioctl(fbdev[1], OMAPFB_QUERY_PLANE, &pi); pi.enabled = 0; ioctl(fbdev[1], OMAPFB_SETUP_PLANE, &pi); close(fbdev[1]); } } int main(int argc, char *args[]) { int x = 0; int y = 0; int arg = 0; int off = 0; int cnt = 600; int index = 0; uint16_t col = 0; uint16_t *p = NULL; uint32_t frame = 0; uint32_t speed_target = 0; uint32_t speed_next = 1000000 / 60; struct fb_var_screeninfo vinfo = {0}; init_fb(); ioctl(fbdev[1], FBIOGET_VSCREENINFO, &vinfo); speed_target = get_ticks(); while (cnt--) { if (off == 0) { p = fbpixels[1]; } else { p = (uint16_t*)fbpixels[1] + (480 * 800); } for (y = 0; y < 480; y++) { for (x = 0; x < 800; x++) { *p++ = col; } } vinfo.yoffset = off; ioctl(fbdev[1], FBIOPAN_DISPLAY, &vinfo); ioctl(fbdev[1], FBIO_WAITFORVSYNC, &arg); off = off ? 0 : 480; switch(index) { case 0: index = 1; col = 0xf800; break; case 1: index = 2; col = 0x7e0; break; default: index = 0; col = 0x1f; break; } frame += 1; speed_target += speed_next; while (get_ticks() < speed_target) { usleep(5); } } deinit_fb(); return 0; }