forked from xuos/xiuos
				
			
		
			
				
	
	
		
			500 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			500 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
| /*
 | |
| * Copyright (c) 2020 AIIT XUOS Lab
 | |
| * XiUOS is licensed under Mulan PSL v2.
 | |
| * You can use this software according to the terms and conditions of the Mulan PSL v2.
 | |
| * You may obtain a copy of Mulan PSL v2 at:
 | |
| *        http://license.coscl.org.cn/MulanPSL2
 | |
| * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
| * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
| * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
| * See the Mulan PSL v2 for more details.
 | |
| */
 | |
| 
 | |
| /**
 | |
| * @file:    test_lcd.c
 | |
| * @brief:   a application of dac function
 | |
| * @version: 2.0
 | |
| * @author:  AIIT XUOS Lab
 | |
| * @date:    2022/1/11
 | |
| */
 | |
| 
 | |
| #include <transform.h>
 | |
| 
 | |
| #ifdef ADD_NUTTX_FEATURES
 | |
| 
 | |
| #ifdef CONFIG_K210_LCD
 | |
| void LcdDemo(void)
 | |
| {
 | |
|     int lcd_fd = PrivOpen("/dev/lcd_dev",O_RDWR);
 | |
|     LcdWriteParam disp_info;
 | |
| 
 | |
|     disp_info.type = 0;
 | |
|     disp_info.string_info.x_pos = 80;
 | |
|     disp_info.string_info.y_pos = 80;
 | |
|     disp_info.string_info.width = 250;
 | |
|     disp_info.string_info.height = 24;
 | |
|     disp_info.string_info.font_size = 24;
 | |
|     disp_info.string_info.addr = "wecome test lcd";
 | |
|     disp_info.string_info.font_color = GREEN;
 | |
|     disp_info.string_info.back_color = BLUE;
 | |
|     PrivWrite(lcd_fd, &disp_info, sizeof(LcdWriteParam));
 | |
|     PrivTaskDelay(2000);
 | |
| 
 | |
|     disp_info.type = 1;
 | |
|     lv_color_t redcolor = {
 | |
|         .ch = {
 | |
|             .red   = 0b11111,
 | |
|             .green = 0,
 | |
|             .blue  = 0
 | |
|         }
 | |
|     };
 | |
|     disp_info.pixel_info.x_startpos =  0;
 | |
|     disp_info.pixel_info.x_endpos =  50;
 | |
|     disp_info.pixel_info.y_startpos = 0;
 | |
|     disp_info.pixel_info.y_endpos = 50;
 | |
|     disp_info.pixel_info.pixel_color = &redcolor;
 | |
|     PrivWrite(lcd_fd, &disp_info, sizeof(LcdWriteParam));
 | |
|     PrivTaskDelay(2000);
 | |
|     
 | |
|     disp_info.type = SHOW_TRIANGLE;
 | |
|     PrivWrite(lcd_fd, &disp_info, sizeof(LcdWriteParam));
 | |
| }
 | |
| 
 | |
| #else
 | |
| /****************************************************************************
 | |
|  * Preprocessor Definitions
 | |
|  ****************************************************************************/
 | |
| 
 | |
| #define NCOLORS 6
 | |
| #define TEST_FB_DEV "/dev/fb0"
 | |
| 
 | |
| /****************************************************************************
 | |
|  * Private Types
 | |
|  ****************************************************************************/
 | |
| 
 | |
| struct fb_state_s
 | |
| {
 | |
|   int fd;
 | |
|   struct fb_videoinfo_s vinfo;
 | |
|   struct fb_planeinfo_s pinfo;
 | |
| #ifdef CONFIG_FB_OVERLAY
 | |
|   struct fb_overlayinfo_s oinfo;
 | |
| #endif
 | |
|   FAR void *fbmem;
 | |
| };
 | |
| 
 | |
| /****************************************************************************
 | |
|  * Private Data
 | |
|  ****************************************************************************/
 | |
| 
 | |
| static const char g_default_fbdev[] = TEST_FB_DEV;
 | |
| 
 | |
| /* Violet-Blue-Green-Yellow-Orange-Red */
 | |
| 
 | |
| static const uint32_t g_rgb24[NCOLORS] =
 | |
| {
 | |
|   RGB24_VIOLET, RGB24_BLUE, RGB24_GREEN,
 | |
|   RGB24_YELLOW, RGB24_ORANGE, RGB24_RED
 | |
| };
 | |
| 
 | |
| static const uint16_t g_rgb16[NCOLORS] =
 | |
| {
 | |
|   RGB16_VIOLET, RGB16_BLUE, RGB16_GREEN,
 | |
|   RGB16_YELLOW, RGB16_ORANGE, RGB16_RED
 | |
| };
 | |
| 
 | |
| static const uint8_t g_rgb8[NCOLORS] =
 | |
| {
 | |
|   RGB8_VIOLET, RGB8_BLUE, RGB8_GREEN,
 | |
|   RGB8_YELLOW, RGB8_ORANGE, RGB8_RED
 | |
| };
 | |
| 
 | |
| /****************************************************************************
 | |
|  * Private Functions
 | |
|  ****************************************************************************/
 | |
| 
 | |
| /****************************************************************************
 | |
|  * draw_rect
 | |
|  ****************************************************************************/
 | |
| 
 | |
| static void draw_rect32(FAR struct fb_state_s *state,
 | |
|                         FAR struct fb_area_s *area, int color)
 | |
| {
 | |
|   FAR uint32_t *dest;
 | |
|   FAR uint8_t *row;
 | |
|   int x;
 | |
|   int y;
 | |
| 
 | |
|   row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
 | |
|   for (y = 0; y < area->h; y++)
 | |
|     {
 | |
|       dest = ((FAR uint32_t *)row) + area->x;
 | |
|       for (x = 0; x < area->w; x++)
 | |
|         {
 | |
|           *dest++ = g_rgb24[color];
 | |
|         }
 | |
| 
 | |
|       row += state->pinfo.stride;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void draw_rect16(FAR struct fb_state_s *state,
 | |
|                         FAR struct fb_area_s *area, int color)
 | |
| {
 | |
|   FAR uint16_t *dest;
 | |
|   FAR uint8_t *row;
 | |
|   int x;
 | |
|   int y;
 | |
| 
 | |
|   row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
 | |
|   for (y = 0; y < area->h; y++)
 | |
|     {
 | |
|       dest = ((FAR uint16_t *)row) + area->x;
 | |
|       for (x = 0; x < area->w; x++)
 | |
|         {
 | |
|           *dest++ = g_rgb16[color];
 | |
|         }
 | |
| 
 | |
|       row += state->pinfo.stride;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void draw_rect8(FAR struct fb_state_s *state,
 | |
|                        FAR struct fb_area_s *area, int color)
 | |
| {
 | |
|   FAR uint8_t *dest;
 | |
|   FAR uint8_t *row;
 | |
|   int x;
 | |
|   int y;
 | |
| 
 | |
|   row = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
 | |
|   for (y = 0; y < area->h; y++)
 | |
|     {
 | |
|       dest = row + area->x;
 | |
|       for (x = 0; x < area->w; x++)
 | |
|         {
 | |
|           *dest++ = g_rgb8[color];
 | |
|         }
 | |
| 
 | |
|       row += state->pinfo.stride;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void draw_rect1(FAR struct fb_state_s *state,
 | |
|                        FAR struct fb_area_s *area, int color)
 | |
| {
 | |
|   FAR uint8_t *pixel;
 | |
|   FAR uint8_t *row;
 | |
|   uint8_t color8 = (color & 1) == 0 ? 0 : 0xff;
 | |
|   uint8_t lmask;
 | |
|   uint8_t rmask;
 | |
|   int startx;
 | |
|   int endx;
 | |
|   int x;
 | |
|   int y;
 | |
| 
 | |
|   /* Calculate the framebuffer address of the first row to draw on */
 | |
| 
 | |
|   row    = (FAR uint8_t *)state->fbmem + state->pinfo.stride * area->y;
 | |
| 
 | |
|   /* Calculate the start byte position rounding down so that we get the
 | |
|    * first byte containing any part of the pixel sequence.  Then calculate
 | |
|    * the last byte position with a ceil() operation so it includes any final
 | |
|    * final pixels of the sequence.
 | |
|    */
 | |
| 
 | |
|   startx = (area->x >> 3);
 | |
|   endx   = ((area->x + area->w + 6) >> 3);
 | |
| 
 | |
|   /* Calculate a mask on the first and last bytes of the sequence that may
 | |
|    * not be completely filled with pixel.
 | |
|    */
 | |
| 
 | |
|   lmask  = 0xff << (8 - (area->x & 7));
 | |
|   rmask  = 0xff >> ((area->x + area->w - 1) & 7);
 | |
| 
 | |
|   /* Now draw each row, one-at-a-time */
 | |
| 
 | |
|   for (y = 0; y < area->h; y++)
 | |
|     {
 | |
|       /* 'pixel' points to the 1st pixel the next row */
 | |
| 
 | |
|       pixel = row + startx;
 | |
| 
 | |
|       /* Special case: The row is less no more than one byte wide */
 | |
| 
 | |
|       if (startx == endx)
 | |
|         {
 | |
|           uint8_t mask = lmask | rmask;
 | |
| 
 | |
|           *pixel = (*pixel & mask) | (color8 & ~mask);
 | |
|         }
 | |
|       else
 | |
|         {
 | |
|           /* Special case the first byte of the row */
 | |
| 
 | |
|           *pixel = (*pixel & lmask) | (color8 & ~lmask);
 | |
|           pixel++;
 | |
| 
 | |
|           /* Handle all middle bytes in the row */
 | |
| 
 | |
|           for (x = startx + 1; x < endx; x++)
 | |
|             {
 | |
|               *pixel++ = color8;
 | |
|             }
 | |
| 
 | |
|           /* Handle the final byte of the row */
 | |
| 
 | |
|           *pixel = (*pixel & rmask) | (color8 & ~rmask);
 | |
|         }
 | |
| 
 | |
|       row += state->pinfo.stride;
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void draw_rect(FAR struct fb_state_s *state,
 | |
|                       FAR struct fb_area_s *area, int color)
 | |
| {
 | |
| #ifdef CONFIG_FB_UPDATE
 | |
|   int ret;
 | |
| #endif
 | |
| 
 | |
|   switch (state->pinfo.bpp)
 | |
|     {
 | |
|       case 32:
 | |
|         draw_rect32(state, area, color);
 | |
|         break;
 | |
| 
 | |
|       case 16:
 | |
|         draw_rect16(state, area, color);
 | |
|         break;
 | |
| 
 | |
|       case 8:
 | |
|       default:
 | |
|         draw_rect8(state, area, color);
 | |
|         break;
 | |
| 
 | |
|       case 1:
 | |
|         draw_rect1(state, area, color);
 | |
|         break;
 | |
|     }
 | |
| 
 | |
| #ifdef CONFIG_FB_UPDATE
 | |
|   ret = ioctl(state->fd, FBIO_UPDATE,
 | |
|               (unsigned long)((uintptr_t)area));
 | |
|   if (ret < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIO_UPDATE) failed: %d\n",
 | |
|               errcode);
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
|  * Public Functions
 | |
|  ****************************************************************************/
 | |
| 
 | |
| /****************************************************************************
 | |
|  * fb_main
 | |
|  ****************************************************************************/
 | |
| 
 | |
| int test_lcd(int argc, FAR char *argv[])
 | |
| {
 | |
|   FAR const char *fbdev = g_default_fbdev;
 | |
|   struct fb_state_s state;
 | |
|   struct fb_area_s area;
 | |
|   int nsteps;
 | |
|   int xstep;
 | |
|   int ystep;
 | |
|   int width;
 | |
|   int height;
 | |
|   int color;
 | |
|   int x;
 | |
|   int y;
 | |
|   int ret;
 | |
| 
 | |
|   /* There is a single required argument:  The path to the framebuffer
 | |
|    * driver.
 | |
|    */
 | |
| 
 | |
|   if (argc == 2)
 | |
|     {
 | |
|       fbdev = argv[1];
 | |
|     }
 | |
|   else if (argc != 1)
 | |
|     {
 | |
|       fprintf(stderr, "ERROR: Single argument required\n");
 | |
|       fprintf(stderr, "USAGE: %s [<fb-driver-path>]\n", argv[0]);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   /* Open the framebuffer driver */
 | |
| 
 | |
|   state.fd = open(fbdev, O_RDWR);
 | |
|   if (state.fd < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: Failed to open %s: %d\n", fbdev, errcode);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   /* Get the characteristics of the framebuffer */
 | |
| 
 | |
|   ret = ioctl(state.fd, FBIOGET_VIDEOINFO,
 | |
|               (unsigned long)((uintptr_t)&state.vinfo));
 | |
|   if (ret < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIOGET_VIDEOINFO) failed: %d\n",
 | |
|               errcode);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
|   printf("2022-10-14 Mr. Wang commit LCD\n");
 | |
|   printf("VideoInfo:\n");
 | |
|   printf("      fmt: %u\n", state.vinfo.fmt);
 | |
|   printf("     xres: %u\n", state.vinfo.xres);
 | |
|   printf("     yres: %u\n", state.vinfo.yres);
 | |
|   printf("  nplanes: %u\n", state.vinfo.nplanes);
 | |
| 
 | |
| #ifdef CONFIG_FB_OVERLAY
 | |
|   printf("noverlays: %u\n", state.vinfo.noverlays);
 | |
| 
 | |
|   /* Select the first overlay, which should be the composed framebuffer */
 | |
| 
 | |
|   ret = ioctl(state.fd, FBIO_SELECT_OVERLAY, 0);
 | |
|   if (ret < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIO_SELECT_OVERLAY) failed: %d\n",
 | |
|               errcode);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   /* Get the first overlay information */
 | |
| 
 | |
|   state.oinfo.overlay = 0;
 | |
|   ret = ioctl(state.fd, FBIOGET_OVERLAYINFO,
 | |
|                         (unsigned long)((uintptr_t)&state.oinfo));
 | |
|   if (ret < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIOGET_OVERLAYINFO) failed: %d\n",
 | |
|               errcode);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   printf("OverlayInfo (overlay 0):\n");
 | |
|   printf("    fbmem: %p\n", state.oinfo.fbmem);
 | |
|   printf("    fblen: %lu\n", (unsigned long)state.oinfo.fblen);
 | |
|   printf("   stride: %u\n", state.oinfo.stride);
 | |
|   printf("  overlay: %u\n", state.oinfo.overlay);
 | |
|   printf("      bpp: %u\n", state.oinfo.bpp);
 | |
|   printf("    blank: %u\n", state.oinfo.blank);
 | |
|   printf("chromakey: 0x%08" PRIx32 "\n", state.oinfo.chromakey);
 | |
|   printf("    color: 0x%08" PRIx32 "\n", state.oinfo.color);
 | |
|   printf("   transp: 0x%02x\n", state.oinfo.transp.transp);
 | |
|   printf("     mode: %u\n", state.oinfo.transp.transp_mode);
 | |
|   printf("     area: (%u,%u) => (%u,%u)\n",
 | |
|                       state.oinfo.sarea.x, state.oinfo.sarea.y,
 | |
|                       state.oinfo.sarea.w, state.oinfo.sarea.h);
 | |
|   printf("     accl: %" PRIu32 "\n", state.oinfo.accl);
 | |
| 
 | |
| #endif
 | |
| 
 | |
|   ret = ioctl(state.fd, FBIOGET_PLANEINFO,
 | |
|               (unsigned long)((uintptr_t)&state.pinfo));
 | |
|   if (ret < 0)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n",
 | |
|               errcode);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   printf("PlaneInfo (plane 0):\n");
 | |
|   printf("    fbmem: %p\n", state.pinfo.fbmem);
 | |
|   printf("    fblen: %lu\n", (unsigned long)state.pinfo.fblen);
 | |
|   printf("   stride: %u\n", state.pinfo.stride);
 | |
|   printf("  display: %u\n", state.pinfo.display);
 | |
|   printf("      bpp: %u\n", state.pinfo.bpp);
 | |
| 
 | |
|   /* Only these pixel depths are supported.  viinfo.fmt is ignored, only
 | |
|    * certain color formats are supported.
 | |
|    */
 | |
| 
 | |
|   if (state.pinfo.bpp != 32 && state.pinfo.bpp != 16 &&
 | |
|       state.pinfo.bpp != 8  && state.pinfo.bpp != 1)
 | |
|     {
 | |
|       fprintf(stderr, "ERROR: bpp=%u not supported\n", state.pinfo.bpp);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   /* mmap() the framebuffer.
 | |
|    *
 | |
|    * NOTE: In the FLAT build the frame buffer address returned by the
 | |
|    * FBIOGET_PLANEINFO IOCTL command will be the same as the framebuffer
 | |
|    * address.  mmap(), however, is the preferred way to get the framebuffer
 | |
|    * address because in the KERNEL build, it will perform the necessary
 | |
|    * address mapping to make the memory accessible to the application.
 | |
|    */
 | |
| 
 | |
|   state.fbmem = mmap(NULL, state.pinfo.fblen, PROT_READ | PROT_WRITE,
 | |
|                      MAP_SHARED | MAP_FILE, state.fd, 0);
 | |
|   if (state.fbmem == MAP_FAILED)
 | |
|     {
 | |
|       int errcode = errno;
 | |
|       fprintf(stderr, "ERROR: ioctl(FBIOGET_PLANEINFO) failed: %d\n",
 | |
|               errcode);
 | |
|       close(state.fd);
 | |
|       return EXIT_FAILURE;
 | |
|     }
 | |
| 
 | |
|   printf("Mapped FB: %p\n", state.fbmem);
 | |
| 
 | |
|   /* Draw some rectangles */
 | |
| 
 | |
|   nsteps = 2 * (NCOLORS - 1) + 1;
 | |
|   xstep  = state.vinfo.xres / nsteps;
 | |
|   ystep  = state.vinfo.yres / nsteps;
 | |
|   width  = state.vinfo.xres;
 | |
|   height = state.vinfo.yres;
 | |
| 
 | |
|   for (x = 0, y = 0, color = 0;
 | |
|        color < NCOLORS;
 | |
|        x += xstep, y += ystep, color++)
 | |
|     {
 | |
|       area.x = x;
 | |
|       area.y = y;
 | |
|       area.w = width;
 | |
|       area.h = height;
 | |
| 
 | |
|       printf("%2d: (%3d,%3d) (%3d,%3d)\n",
 | |
|              color, area.x, area.y, area.w, area.h);
 | |
| 
 | |
|       draw_rect(&state, &area, color);
 | |
|       usleep(500 * 1000);
 | |
| 
 | |
|       width  -= (2 * xstep);
 | |
|       height -= (2 * ystep);
 | |
|     }
 | |
| 
 | |
|   printf("Test finished\n");
 | |
|   munmap(state.fbmem, state.pinfo.fblen);
 | |
|   close(state.fd);
 | |
|   return EXIT_SUCCESS;
 | |
| }
 | |
| 
 | |
| void LcdDemo(void)
 | |
| {
 | |
|     test_lcd(1, NULL);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| #endif
 |