components/tft/tft.c

changeset 18
5d4a40fe9967
parent 0
b74b0e4902c3
child 20
3fd5e0fc075f
equal deleted inserted replaced
17:f3451031d6c6 18:5d4a40fe9967
2262 dispWin.x2 = dispWinTemp.x2; 2262 dispWin.x2 = dispWinTemp.x2;
2263 dispWin.y2 = dispWinTemp.y2; 2263 dispWin.y2 = dispWinTemp.y2;
2264 } 2264 }
2265 2265
2266 2266
2267 // ================ JPG SUPPORT ================================================
2268 // User defined device identifier
2269 typedef struct {
2270 FILE *fhndl; // File handler for input function
2271 int x; // image top left point X position
2272 int y; // image top left point Y position
2273 uint8_t *membuff; // memory buffer containing the image
2274 uint32_t bufsize; // size of the memory buffer
2275 uint32_t bufptr; // memory buffer current position
2276 color_t *linbuf[2]; // memory buffer used for display output
2277 uint8_t linbuf_idx;
2278 } JPGIODEV;
2279
2280
2281 // User defined call-back function to input JPEG data from file
2282 //---------------------
2283 static UINT tjd_input (
2284 JDEC* jd, // Decompression object
2285 BYTE* buff, // Pointer to the read buffer (NULL:skip)
2286 UINT nd // Number of bytes to read/skip from input stream
2287 )
2288 {
2289 int rb = 0;
2290 // Device identifier for the session (5th argument of jd_prepare function)
2291 JPGIODEV *dev = (JPGIODEV*)jd->device;
2292
2293 if (buff) { // Read nd bytes from the input strem
2294 rb = fread(buff, 1, nd, dev->fhndl);
2295 return rb; // Returns actual number of bytes read
2296 }
2297 else { // Remove nd bytes from the input stream
2298 if (fseek(dev->fhndl, nd, SEEK_CUR) >= 0) return nd;
2299 else return 0;
2300 }
2301 }
2302
2303 // User defined call-back function to input JPEG data from memory buffer
2304 //-------------------------
2305 static UINT tjd_buf_input (
2306 JDEC* jd, // Decompression object
2307 BYTE* buff, // Pointer to the read buffer (NULL:skip)
2308 UINT nd // Number of bytes to read/skip from input stream
2309 )
2310 {
2311 // Device identifier for the session (5th argument of jd_prepare function)
2312 JPGIODEV *dev = (JPGIODEV*)jd->device;
2313 if (!dev->membuff) return 0;
2314 if (dev->bufptr >= (dev->bufsize + 2)) return 0; // end of stream
2315
2316 if ((dev->bufptr + nd) > (dev->bufsize + 2)) nd = (dev->bufsize + 2) - dev->bufptr;
2317
2318 if (buff) { // Read nd bytes from the input strem
2319 memcpy(buff, dev->membuff + dev->bufptr, nd);
2320 dev->bufptr += nd;
2321 return nd; // Returns number of bytes read
2322 }
2323 else { // Remove nd bytes from the input stream
2324 dev->bufptr += nd;
2325 return nd;
2326 }
2327 }
2328
2329 // User defined call-back function to output RGB bitmap to display device
2330 //----------------------
2331 static UINT tjd_output (
2332 JDEC* jd, // Decompression object of current session
2333 void* bitmap, // Bitmap data to be output
2334 JRECT* rect // Rectangular region to output
2335 )
2336 {
2337 // Device identifier for the session (5th argument of jd_prepare function)
2338 JPGIODEV *dev = (JPGIODEV*)jd->device;
2339
2340 // ** Put the rectangular into the display device **
2341 int x;
2342 int y;
2343 int dleft, dtop, dright, dbottom;
2344 BYTE *src = (BYTE*)bitmap;
2345
2346 int left = rect->left + dev->x;
2347 int top = rect->top + dev->y;
2348 int right = rect->right + dev->x;
2349 int bottom = rect->bottom + dev->y;
2350
2351 if ((left > dispWin.x2) || (top > dispWin.y2)) return 1; // out of screen area, return
2352 if ((right < dispWin.x1) || (bottom < dispWin.y1)) return 1;// out of screen area, return
2353
2354 if (left < dispWin.x1) dleft = dispWin.x1;
2355 else dleft = left;
2356 if (top < dispWin.y1) dtop = dispWin.y1;
2357 else dtop = top;
2358 if (right > dispWin.x2) dright = dispWin.x2;
2359 else dright = right;
2360 if (bottom > dispWin.y2) dbottom = dispWin.y2;
2361 else dbottom = bottom;
2362
2363 if ((dleft > dispWin.x2) || (dtop > dispWin.y2)) return 1; // out of screen area, return
2364 if ((dright < dispWin.x1) || (dbottom < dispWin.y1)) return 1; // out of screen area, return
2365
2366 uint32_t len = ((dright-dleft+1) * (dbottom-dtop+1)); // calculate length of data
2367
2368
2369 if ((len > 0) && (len <= JPG_IMAGE_LINE_BUF_SIZE)) {
2370 uint8_t *dest = (uint8_t *)(dev->linbuf[dev->linbuf_idx]);
2371
2372 for (y = top; y <= bottom; y++) {
2373 for (x = left; x <= right; x++) {
2374 // Clip to display area
2375 if ((x >= dleft) && (y >= dtop) && (x <= dright) && (y <= dbottom)) {
2376 *dest++ = (*src++) & 0xFC;
2377 *dest++ = (*src++) & 0xFC;
2378 *dest++ = (*src++) & 0xFC;
2379 }
2380 else src += 3; // skip
2381 }
2382 }
2383 wait_trans_finish(1);
2384 send_data(dleft, dtop, dright, dbottom, len, dev->linbuf[dev->linbuf_idx]);
2385 dev->linbuf_idx = ((dev->linbuf_idx + 1) & 1);
2386 }
2387 else {
2388 wait_trans_finish(1);
2389 printf("Data size error: %d jpg: (%d,%d,%d,%d) disp: (%d,%d,%d,%d)\r\n", len, left,top,right,bottom, dleft,dtop,dright,dbottom);
2390 return 0; // stop decompression
2391 }
2392
2393 return 1; // Continue to decompression
2394 }
2395
2396 // tft.jpgimage(X, Y, scale, file_name, buf, size]
2397 // X & Y can be < 0 !
2398 //==================================================================================
2399 void TFT_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int size)
2400 {
2401 JPGIODEV dev;
2402 struct stat sb;
2403 char *work = NULL; // Pointer to the working buffer (must be 4-byte aligned)
2404 UINT sz_work = 3800; // Size of the working buffer (must be power of 2)
2405 JDEC jd; // Decompression object (70 bytes)
2406 JRESULT rc;
2407
2408 dev.linbuf[0] = NULL;
2409 dev.linbuf[1] = NULL;
2410 dev.linbuf_idx = 0;
2411
2412 dev.fhndl = NULL;
2413 if (fname == NULL) {
2414 // image from buffer
2415 dev.membuff = buf;
2416 dev.bufsize = size;
2417 dev.bufptr = 0;
2418 }
2419 else {
2420 // image from file
2421 dev.membuff = NULL;
2422 dev.bufsize = 0;
2423 dev.bufptr = 0;
2424
2425 if (stat(fname, &sb) != 0) {
2426 if (image_debug) printf("File error: %ss\r\n", strerror(errno));
2427 goto exit;
2428 }
2429
2430 dev.fhndl = fopen(fname, "r");
2431 if (!dev.fhndl) {
2432 if (image_debug) printf("Error opening file: %s\r\n", strerror(errno));
2433 goto exit;
2434 }
2435 }
2436
2437 if (scale > 3) scale = 3;
2438
2439 work = malloc(sz_work);
2440 if (work) {
2441 if (dev.membuff) rc = jd_prepare(&jd, tjd_buf_input, (void *)work, sz_work, &dev);
2442 else rc = jd_prepare(&jd, tjd_input, (void *)work, sz_work, &dev);
2443 if (rc == JDR_OK) {
2444 if (x == CENTER) x = ((dispWin.x2 - dispWin.x1 + 1 - (int)(jd.width >> scale)) / 2) + dispWin.x1;
2445 else if (x == RIGHT) x = dispWin.x2 + 1 - (int)(jd.width >> scale);
2446
2447 if (y == CENTER) y = ((dispWin.y2 - dispWin.y1 + 1 - (int)(jd.height >> scale)) / 2) + dispWin.y1;
2448 else if (y == BOTTOM) y = dispWin.y2 + 1 - (int)(jd.height >> scale);
2449
2450 if (x < ((dispWin.x2-1) * -1)) x = (dispWin.x2-1) * -1;
2451 if (y < ((dispWin.y2-1)) * -1) y = (dispWin.y2-1) * -1;
2452 if (x > (dispWin.x2-1)) x = dispWin.x2 - 1;
2453 if (y > (dispWin.y2-1)) y = dispWin.y2-1;
2454
2455 dev.x = x;
2456 dev.y = y;
2457
2458 dev.linbuf[0] = heap_caps_malloc(JPG_IMAGE_LINE_BUF_SIZE*3, MALLOC_CAP_DMA);
2459 if (dev.linbuf[0] == NULL) {
2460 if (image_debug) printf("Error allocating line buffer #0\r\n");
2461 goto exit;
2462 }
2463 dev.linbuf[1] = heap_caps_malloc(JPG_IMAGE_LINE_BUF_SIZE*3, MALLOC_CAP_DMA);
2464 if (dev.linbuf[1] == NULL) {
2465 if (image_debug) printf("Error allocating line buffer #1\r\n");
2466 goto exit;
2467 }
2468
2469 // Start to decode the JPEG file
2470 disp_select();
2471 rc = jd_decomp(&jd, tjd_output, scale);
2472 disp_deselect();
2473
2474 if (rc != JDR_OK) {
2475 if (image_debug) printf("jpg decompression error %d\r\n", rc);
2476 }
2477 if (image_debug) printf("Jpg size: %dx%d, position; %d,%d, scale: %d, bytes used: %d\r\n", jd.width, jd.height, x, y, scale, jd.sz_pool);
2478 }
2479 else {
2480 if (image_debug) printf("jpg prepare error %d\r\n", rc);
2481 }
2482 }
2483 else {
2484 if (image_debug) printf("work buffer allocation error\r\n");
2485 }
2486
2487 exit:
2488 if (work) free(work); // free work buffer
2489 if (dev.linbuf[0]) free(dev.linbuf[0]);
2490 if (dev.linbuf[1]) free(dev.linbuf[1]);
2491 if (dev.fhndl) fclose(dev.fhndl); // close input file
2492 }
2493
2494
2495 //====================================================================================
2496 int TFT_bmp_image(int x, int y, uint8_t scale, char *fname, uint8_t *imgbuf, int size)
2497 {
2498 FILE *fhndl = NULL;
2499 struct stat sb;
2500 int i, err=0;
2501 int img_xsize, img_ysize, img_xstart, img_xlen, img_ystart, img_ylen;
2502 int img_pos, img_pix_pos, scan_lines, rd_len;
2503 uint8_t tmpc;
2504 uint16_t wtemp;
2505 uint32_t temp;
2506 int disp_xstart, disp_xend, disp_ystart, disp_yend;
2507 uint8_t buf[56];
2508 char err_buf[64];
2509 uint8_t *line_buf[2] = {NULL,NULL};
2510 uint8_t lb_idx = 0;
2511 uint8_t *scale_buf = NULL;
2512 uint8_t scale_pix;
2513 uint16_t co[3] = {0,0,0}; // RGB sum
2514 uint8_t npix;
2515
2516 if (scale > 7) scale = 7;
2517 scale_pix = scale+1; // scale factor ( 1~8 )
2518
2519 if (fname) {
2520 // * File name is given, reading image from file
2521 if (stat(fname, &sb) != 0) {
2522 sprintf(err_buf, "opening file");
2523 err = -1;
2524 goto exit;
2525 }
2526 size = sb.st_size;
2527 fhndl = fopen(fname, "r");
2528 if (!fhndl) {
2529 sprintf(err_buf, "opening file");
2530 err = -2;
2531 goto exit;
2532 }
2533
2534 i = fread(buf, 1, 54, fhndl); // read header
2535 }
2536 else {
2537 // * Reading image from buffer
2538 if ((imgbuf) && (size > 54)) {
2539 memcpy(buf, imgbuf, 54);
2540 i = 54;
2541 }
2542 else i = 0;
2543 }
2544
2545 sprintf(err_buf, "reading header");
2546 if (i != 54) {err = -3; goto exit;}
2547
2548 // ** Check image header and get image properties
2549 if ((buf[0] != 'B') || (buf[1] != 'M')) {err=-4; goto exit;} // accept only images with 'BM' id
2550
2551 memcpy(&temp, buf+2, 4); // file size
2552 if (temp != size) {err=-5; goto exit;}
2553
2554 memcpy(&img_pos, buf+10, 4); // start of pixel data
2555
2556 memcpy(&temp, buf+14, 4); // BMP header size
2557 if (temp != 40) {err=-6; goto exit;}
2558
2559 memcpy(&wtemp, buf+26, 2); // the number of color planes
2560 if (wtemp != 1) {err=-7; goto exit;}
2561
2562 memcpy(&wtemp, buf+28, 2); // the number of bits per pixel
2563 if (wtemp != 24) {err=-8; goto exit;}
2564
2565 memcpy(&temp, buf+30, 4); // the compression method being used
2566 if (temp != 0) {err=-9; goto exit;}
2567
2568 memcpy(&img_xsize, buf+18, 4); // the bitmap width in pixels
2569 memcpy(&img_ysize, buf+22, 4); // the bitmap height in pixels
2570
2571
2572 // * scale image dimensions
2573
2574 img_xlen = img_xsize / scale_pix; // image display horizontal size
2575 img_ylen = img_ysize / scale_pix; // image display vertical size
2576
2577 if (x == CENTER) x = ((dispWin.x2 - dispWin.x1 + 1 - img_xlen) / 2) + dispWin.x1;
2578 else if (x == RIGHT) x = dispWin.x2 + 1 - img_xlen;
2579
2580 if (y == CENTER) y = ((dispWin.y2 - dispWin.y1 + 1 - img_ylen) / 2) + dispWin.y1;
2581 else if (y == BOTTOM) y = dispWin.y2 + 1 - img_ylen;
2582
2583 if ((x < ((dispWin.x2 + 1) * -1)) || (x > (dispWin.x2 + 1)) || (y < ((dispWin.y2 + 1) * -1)) || (y > (dispWin.y2 + 1))) {
2584 sprintf(err_buf, "out of display area (%d,%d", x, y);
2585 err = -10;
2586 goto exit;
2587 }
2588
2589 // ** set display and image areas
2590 if (x < dispWin.x1) {
2591 disp_xstart = dispWin.x1;
2592 img_xstart = -x; // image pixel line X offset
2593 img_xlen += x;
2594 }
2595 else {
2596 disp_xstart = x;
2597 img_xstart = 0;
2598 }
2599 if (y < dispWin.y1) {
2600 disp_ystart = dispWin.y1;
2601 img_ystart = -y; // image pixel line Y offset
2602 img_ylen += y;
2603 }
2604 else {
2605 disp_ystart = y;
2606 img_ystart = 0;
2607 }
2608 disp_xend = disp_xstart + img_xlen - 1;
2609 disp_yend = disp_ystart + img_ylen - 1;
2610 if (disp_xend > dispWin.x2) {
2611 disp_xend = dispWin.x2;
2612 img_xlen = disp_xend - disp_xstart + 1;
2613 }
2614 if (disp_yend > dispWin.y2) {
2615 disp_yend = dispWin.y2;
2616 img_ylen = disp_yend - disp_ystart + 1;
2617 }
2618
2619 if ((img_xlen < 8) || (img_ylen < 8) || (img_xstart >= (img_xsize-2)) || ((img_ysize - img_ystart) < 2)) {
2620 sprintf(err_buf, "image too small");
2621 err = -11;
2622 goto exit;
2623 }
2624
2625 // ** Allocate memory for 2 lines of image pixels
2626 line_buf[0] = heap_caps_malloc(img_xsize*3, MALLOC_CAP_DMA);
2627 if (line_buf[0] == NULL) {
2628 sprintf(err_buf, "allocating line buffer #1");
2629 err=-12;
2630 goto exit;
2631 }
2632
2633 line_buf[1] = heap_caps_malloc(img_xsize*3, MALLOC_CAP_DMA);
2634 if (line_buf[1] == NULL) {
2635 sprintf(err_buf, "allocating line buffer #2");
2636 err=-13;
2637 goto exit;
2638 }
2639
2640 if (scale) {
2641 // Allocate memory for scale buffer
2642 rd_len = img_xlen * 3 * scale_pix;
2643 scale_buf = malloc(rd_len*scale_pix);
2644 if (scale_buf == NULL) {
2645 sprintf(err_buf, "allocating scale buffer");
2646 err=-14;
2647 goto exit;
2648 }
2649 }
2650 else rd_len = img_xlen * 3;
2651
2652 // ** ***************************************************** **
2653 // ** BMP images are stored in file from LAST to FIRST line **
2654 // ** ***************************************************** **
2655
2656 /* Used variables:
2657 img_xsize horizontal image size in pixels
2658 img_ysize number of image lines
2659 img_xlen image display horizontal scaled size in pixels
2660 img_ylen image display vertical scaled size in pixels
2661 img_xstart first pixel in line to be displayed
2662 img_ystart first image line to be displayed
2663 img_xlen number of pixels in image line to be displayed, starting with 'img_xstart'
2664 img_ylen number of lines in image to be displayed, starting with 'img_ystart'
2665 rd_len length of color data which are read from image line in bytes
2666 */
2667
2668 // Set position in image to the first color data (beginning of the LAST line)
2669 img_pos += (img_ystart * (img_xsize*3));
2670 if (fhndl) {
2671 if (fseek(fhndl, img_pos, SEEK_SET) != 0) {
2672 sprintf(err_buf, "file seek at %d", img_pos);
2673 err = -15;
2674 goto exit;
2675 }
2676 }
2677
2678 if (image_debug) printf("BMP: image size: (%d,%d) scale: %d disp size: (%d,%d) img xofs: %d img yofs: %d at: %d,%d; line buf: 2* %d scale buf: %d\r\n",
2679 img_xsize, img_ysize, scale_pix, img_xlen, img_ylen, img_xstart, img_ystart, disp_xstart, disp_ystart, img_xsize*3, ((scale) ? (rd_len*scale_pix) : 0));
2680
2681 // * Select the display
2682 disp_select();
2683
2684 while ((disp_yend >= disp_ystart) && ((img_pos + (img_xsize*3)) <= size)) {
2685 if (img_pos > size) {
2686 sprintf(err_buf, "EOF reached: %d > %d", img_pos, size);
2687 err = -16;
2688 goto exit1;
2689 }
2690 if (scale == 0) {
2691 // Read the line of color data into color buffer
2692 if (fhndl) {
2693 i = fread(line_buf[lb_idx], 1, img_xsize*3, fhndl); // read line from file
2694 if (i != (img_xsize*3)) {
2695 sprintf(err_buf, "file read at %d (%d<>%d)", img_pos, i, img_xsize*3);
2696 err = -16;
2697 goto exit1;
2698 }
2699 }
2700 else memcpy(line_buf[lb_idx], imgbuf+img_pos, img_xsize*3);
2701
2702 if (img_xstart > 0) memmove(line_buf[lb_idx], line_buf[lb_idx]+(img_xstart*3), rd_len);
2703 // Convert colors BGR-888 (BMP) -> RGB-888 (DISPLAY) ===
2704 for (i=0; i < rd_len; i += 3) {
2705 tmpc = line_buf[lb_idx][i+2] & 0xfc; // save R
2706 line_buf[lb_idx][i+2] = line_buf[lb_idx][i] & 0xfc; // B -> R
2707 line_buf[lb_idx][i] = tmpc; // R -> B
2708 line_buf[lb_idx][i+1] &= 0xfc; // G
2709 }
2710 img_pos += (img_xsize*3);
2711 }
2712 else {
2713 // scale image, read 'scale_pix' lines and find the average color
2714 for (scan_lines=0; scan_lines<scale_pix; scan_lines++) {
2715 if (img_pos > size) break;
2716 if (fhndl) {
2717 i = fread(line_buf[lb_idx], 1, img_xsize*3, fhndl); // read line from file
2718 if (i != (img_xsize*3)) {
2719 sprintf(err_buf, "file read at %d (%d<>%d)", img_pos, i, img_xsize*3);
2720 err = -17;
2721 goto exit1;
2722 }
2723 }
2724 else memcpy(line_buf[lb_idx], imgbuf+img_pos, img_xsize*3);
2725 img_pos += (img_xsize*3);
2726
2727 // copy only data which are displayed to scale buffer
2728 memcpy(scale_buf + (rd_len * scan_lines), line_buf[lb_idx]+img_xstart, rd_len);
2729 }
2730
2731 // Populate display line buffer
2732 for (int n=0;n<(img_xlen*3);n += 3) {
2733 memset(co, 0, sizeof(co)); // initialize color sum
2734 npix = 0; // initialize number of pixels in scale rectangle
2735
2736 // sum all pixels in scale rectangle
2737 for (int sc_line=0; sc_line<scan_lines; sc_line++) {
2738 // Get colors position in scale buffer
2739 img_pix_pos = (rd_len * sc_line) + (n * scale_pix);
2740
2741 for (int sc_col=0; sc_col<scale_pix; sc_col++) {
2742 co[0] += scale_buf[img_pix_pos];
2743 co[1] += scale_buf[img_pix_pos + 1];
2744 co[2] += scale_buf[img_pix_pos + 2];
2745 npix++;
2746 }
2747 }
2748 // Place the average in display buffer, convert BGR-888 (BMP) -> RGB-888 (DISPLAY)
2749 line_buf[lb_idx][n+2] = (uint8_t)(co[0] / npix); // B
2750 line_buf[lb_idx][n+1] = (uint8_t)(co[1] / npix); // G
2751 line_buf[lb_idx][n] = (uint8_t)(co[2] / npix); // R
2752 }
2753 }
2754
2755 wait_trans_finish(1);
2756 send_data(disp_xstart, disp_yend, disp_xend, disp_yend, img_xlen, (color_t *)line_buf[lb_idx]);
2757 lb_idx = (lb_idx + 1) & 1; // change buffer
2758
2759 disp_yend--;
2760 }
2761 err = 0;
2762 exit1:
2763 disp_deselect();
2764 exit:
2765 if (scale_buf) free(scale_buf);
2766 if (line_buf[0]) free(line_buf[0]);
2767 if (line_buf[1]) free(line_buf[1]);
2768 if (fhndl) fclose(fhndl);
2769 if ((err) && (image_debug)) printf("Error: %d [%s]\r\n", err, err_buf);
2770
2771 return err;
2772 }
2773
2774
2775 // ============= Touch panel functions ========================================= 2267 // ============= Touch panel functions =========================================
2776 2268
2777 #if USE_TOUCH == TOUCH_TYPE_XPT2046 2269 #if USE_TOUCH == TOUCH_TYPE_XPT2046
2778 //------------------------------------------------------- 2270 //-------------------------------------------------------
2779 static int tp_get_data_xpt2046(uint8_t type, int samples) 2271 static int tp_get_data_xpt2046(uint8_t type, int samples)

mercurial