Loading JPG to FT800 screen
Test program to load a JPG to a FT800 controlled lcd screen. First the graphics data have to be load to the FT800 buffer. The FT800 will decode the JPG data into a bitmap. In the second step this bitmap will displayed on the LCD.
main.cpp@1:c603024cbd1d, 2015-02-09 (annotated)
- Committer:
- dreschpe
- Date:
- Mon Feb 09 20:46:41 2015 +0000
- Revision:
- 1:c603024cbd1d
- Parent:
- 0:a6545392ca42
Add some doku
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dreschpe | 0:a6545392ca42 | 1 | /* Demo for mbed Library for FTDI FT800 Enbedded Video Engine "EVE" |
dreschpe | 0:a6545392ca42 | 2 | * to show jpg file handling |
dreschpe | 0:a6545392ca42 | 3 | * c by Peter Drescher, DC2PD 2014 |
dreschpe | 0:a6545392ca42 | 4 | * Released under the MIT License: http://mbed.org/license/mit */ |
dreschpe | 0:a6545392ca42 | 5 | |
dreschpe | 0:a6545392ca42 | 6 | #include "mbed.h" |
dreschpe | 0:a6545392ca42 | 7 | #include "FT_Platform.h" |
dreschpe | 0:a6545392ca42 | 8 | |
dreschpe | 0:a6545392ca42 | 9 | Serial pc(USBTX, USBRX); // tx, rx |
dreschpe | 0:a6545392ca42 | 10 | DigitalOut myled(LED1); |
dreschpe | 0:a6545392ca42 | 11 | FT800 TFT(p11,p12,p13,p14,p15,p16); // the FT800 is connected to SPI 11-13 |
dreschpe | 0:a6545392ca42 | 12 | |
dreschpe | 0:a6545392ca42 | 13 | LocalFileSystem local("local"); // filesystem to load jpg |
dreschpe | 0:a6545392ca42 | 14 | |
dreschpe | 0:a6545392ca42 | 15 | |
dreschpe | 0:a6545392ca42 | 16 | /* function to load jpg file from internal filesystem */ |
dreschpe | 1:c603024cbd1d | 17 | /* into FT800 buffer and decode JPG to bitmap */ |
dreschpe | 0:a6545392ca42 | 18 | /* return 0 if jpg is ok */ |
dreschpe | 0:a6545392ca42 | 19 | /* return x_size and y_size of jpg */ |
dreschpe | 0:a6545392ca42 | 20 | |
dreschpe | 0:a6545392ca42 | 21 | int load_jpg(char* filename, ft_int16_t* x_size, ft_int16_t* y_size) |
dreschpe | 0:a6545392ca42 | 22 | { |
dreschpe | 0:a6545392ca42 | 23 | unsigned char pbuff[8291]; |
dreschpe | 0:a6545392ca42 | 24 | unsigned short marker; |
dreschpe | 0:a6545392ca42 | 25 | unsigned short length; |
dreschpe | 0:a6545392ca42 | 26 | unsigned char data[4]; |
dreschpe | 0:a6545392ca42 | 27 | |
dreschpe | 0:a6545392ca42 | 28 | |
dreschpe | 0:a6545392ca42 | 29 | ft_uint16_t blocklen; |
dreschpe | 0:a6545392ca42 | 30 | |
dreschpe | 0:a6545392ca42 | 31 | FILE *fp = fopen(filename, "r"); |
dreschpe | 0:a6545392ca42 | 32 | if(fp == NULL) return (-1); // connot open file |
dreschpe | 0:a6545392ca42 | 33 | |
dreschpe | 0:a6545392ca42 | 34 | // search for 0xFFC0 marker |
dreschpe | 0:a6545392ca42 | 35 | fseek(fp, 0, SEEK_END); |
dreschpe | 0:a6545392ca42 | 36 | unsigned int Fsize = ftell(fp); |
dreschpe | 0:a6545392ca42 | 37 | fseek(fp, 2, SEEK_SET); |
dreschpe | 0:a6545392ca42 | 38 | fread(data,4,1,fp); |
dreschpe | 0:a6545392ca42 | 39 | marker = data[0] << 8 | data[1]; |
dreschpe | 0:a6545392ca42 | 40 | length = data[2] << 8 | data[3]; |
dreschpe | 0:a6545392ca42 | 41 | do { |
dreschpe | 0:a6545392ca42 | 42 | if(marker == 0xFFC0) break; |
dreschpe | 0:a6545392ca42 | 43 | if(marker & 0xFF00 != 0xFF00) break; |
dreschpe | 0:a6545392ca42 | 44 | if (fseek(fp, length - 2,SEEK_CUR) != 0) break; |
dreschpe | 0:a6545392ca42 | 45 | fread(data,4,1,fp); |
dreschpe | 0:a6545392ca42 | 46 | marker = data[0] << 8 | data[1]; |
dreschpe | 0:a6545392ca42 | 47 | length = data[2] << 8 | data[3]; |
dreschpe | 0:a6545392ca42 | 48 | } while(1); |
dreschpe | 0:a6545392ca42 | 49 | if(marker != 0xFFC0) return (-2); // no FFC0 Marker, wrong format no baseline DCT-based JPEG |
dreschpe | 0:a6545392ca42 | 50 | fseek(fp, 1,SEEK_CUR); |
dreschpe | 0:a6545392ca42 | 51 | fread(data,4,1,fp); |
dreschpe | 0:a6545392ca42 | 52 | *y_size = (data[0] << 8 | data[1]); |
dreschpe | 0:a6545392ca42 | 53 | *x_size = (data[2] << 8 | data[3]); |
dreschpe | 0:a6545392ca42 | 54 | |
dreschpe | 0:a6545392ca42 | 55 | if(*x_size > TFT.FT_DispWidth || *y_size > TFT.FT_DispHeight) return (-3); // to big to fit on screen |
dreschpe | 0:a6545392ca42 | 56 | |
dreschpe | 0:a6545392ca42 | 57 | fseek(fp, 0, SEEK_SET); |
dreschpe | 0:a6545392ca42 | 58 | TFT.Ft_Gpu_Hal_WrCmd32(CMD_LOADIMAGE); |
dreschpe | 0:a6545392ca42 | 59 | TFT.Ft_Gpu_Hal_WrCmd32(0);//destination address of jpg decode |
dreschpe | 0:a6545392ca42 | 60 | TFT.Ft_Gpu_Hal_WrCmd32(0);//output format of the bitmap - default is rgb565 |
dreschpe | 0:a6545392ca42 | 61 | while(Fsize > 0) { |
dreschpe | 0:a6545392ca42 | 62 | /* download the data into the command buffer by 8kb one shot */ |
dreschpe | 0:a6545392ca42 | 63 | blocklen = Fsize>8192?8192:Fsize; |
dreschpe | 0:a6545392ca42 | 64 | /* copy the data into pbuff and then transfter it to command buffer */ |
dreschpe | 0:a6545392ca42 | 65 | fread(pbuff,1,blocklen,fp); |
dreschpe | 0:a6545392ca42 | 66 | Fsize -= blocklen; |
dreschpe | 0:a6545392ca42 | 67 | /* copy data continuously into command memory */ |
dreschpe | 0:a6545392ca42 | 68 | TFT.Ft_Gpu_Hal_WrCmdBuf(pbuff, blocklen); //alignment is already taken care by this api |
dreschpe | 0:a6545392ca42 | 69 | } |
dreschpe | 0:a6545392ca42 | 70 | fclose(fp); |
dreschpe | 0:a6545392ca42 | 71 | |
dreschpe | 0:a6545392ca42 | 72 | return(0); |
dreschpe | 0:a6545392ca42 | 73 | } |
dreschpe | 0:a6545392ca42 | 74 | |
dreschpe | 0:a6545392ca42 | 75 | int main() |
dreschpe | 0:a6545392ca42 | 76 | { |
dreschpe | 0:a6545392ca42 | 77 | ft_int16_t x_size,y_size; |
dreschpe | 0:a6545392ca42 | 78 | int err; |
dreschpe | 0:a6545392ca42 | 79 | |
dreschpe | 0:a6545392ca42 | 80 | TFT.Ft_Gpu_CoCmd_Dlstart(); // start a new display command list |
dreschpe | 0:a6545392ca42 | 81 | TFT.Ft_App_WrCoCmd_Buffer(CLEAR_COLOR_RGB(255,255,255)); // set the clear color to white |
dreschpe | 0:a6545392ca42 | 82 | TFT.Ft_App_WrCoCmd_Buffer(CLEAR(1,1,1)); // clear buffers -> color buffer,stencil buffer, tag buffer |
dreschpe | 0:a6545392ca42 | 83 | TFT.Ft_App_WrCoCmd_Buffer(COLOR_RGB(255,255,255)); // set current color |
dreschpe | 0:a6545392ca42 | 84 | |
dreschpe | 0:a6545392ca42 | 85 | |
dreschpe | 1:c603024cbd1d | 86 | err = load_jpg("/local/ARML2.jpg",& x_size,& y_size); // load graphic data into buffer and decode jpg to bitmap |
dreschpe | 1:c603024cbd1d | 87 | if(err != 0) { // something is wrong - display error |
dreschpe | 0:a6545392ca42 | 88 | TFT.Ft_App_WrCoCmd_Buffer(COLOR_RGB(0,0,0)); // set current color |
dreschpe | 0:a6545392ca42 | 89 | TFT.Ft_Gpu_CoCmd_Text((TFT.FT_DispWidth/2), TFT.FT_DispHeight/2, 25, OPT_CENTERX, "Error"); // draw Text with font 31 |
dreschpe | 0:a6545392ca42 | 90 | TFT.Ft_Gpu_CoCmd_Number(50,50,25,OPT_SIGNED,err); |
dreschpe | 0:a6545392ca42 | 91 | |
dreschpe | 1:c603024cbd1d | 92 | } else { // jpg is loaded and decoded into bitmap |
dreschpe | 0:a6545392ca42 | 93 | |
dreschpe | 0:a6545392ca42 | 94 | TFT.Ft_App_WrCoCmd_Buffer(BEGIN(BITMAPS)); |
dreschpe | 0:a6545392ca42 | 95 | TFT.Ft_Gpu_CoCmd_LoadIdentity(); |
dreschpe | 0:a6545392ca42 | 96 | //TFT.Ft_Gpu_CoCmd_Rotate((45*65536/360));//rotate by 45 degrees anticlock wise |
dreschpe | 0:a6545392ca42 | 97 | //TFT.Ft_Gpu_CoCmd_Scale(32768,32768);//scale by 2x2 |
dreschpe | 0:a6545392ca42 | 98 | TFT.Ft_Gpu_CoCmd_SetMatrix(); |
dreschpe | 0:a6545392ca42 | 99 | TFT.Ft_App_WrCoCmd_Buffer(VERTEX2F(0,0)); |
dreschpe | 0:a6545392ca42 | 100 | |
dreschpe | 0:a6545392ca42 | 101 | TFT.Ft_App_WrCoCmd_Buffer(DISPLAY()); // Display the image |
dreschpe | 0:a6545392ca42 | 102 | TFT.Ft_Gpu_CoCmd_Swap(); // Swap the current display list |
dreschpe | 0:a6545392ca42 | 103 | |
dreschpe | 0:a6545392ca42 | 104 | TFT.Ft_App_Flush_Co_Buffer(); // Download the commands into fifo |
dreschpe | 0:a6545392ca42 | 105 | TFT.Ft_Gpu_Hal_WaitCmdfifo_empty(); // Wait till coprocessor completes the operation |
dreschpe | 0:a6545392ca42 | 106 | |
dreschpe | 0:a6545392ca42 | 107 | wait(2); |
dreschpe | 0:a6545392ca42 | 108 | TFT.Ft_Gpu_CoCmd_Dlstart(); |
dreschpe | 0:a6545392ca42 | 109 | TFT.Ft_App_WrCoCmd_Buffer(BEGIN(BITMAPS)); |
dreschpe | 0:a6545392ca42 | 110 | TFT.Ft_Gpu_CoCmd_LoadIdentity(); |
dreschpe | 0:a6545392ca42 | 111 | //TFT.Ft_Gpu_CoCmd_Scale(32768,32768);//scale by 0.5 |
dreschpe | 0:a6545392ca42 | 112 | //TFT.Ft_Gpu_CoCmd_Translate(50,50); |
dreschpe | 0:a6545392ca42 | 113 | //TFT.Ft_Gpu_CoCmd_Rotate((45*65536/360));//rotate by 45 degrees anticlock wise |
dreschpe | 0:a6545392ca42 | 114 | //TFT.Ft_Gpu_CoCmd_Scale(32768,32768);//scale by 2x2 |
dreschpe | 0:a6545392ca42 | 115 | TFT.Ft_Gpu_CoCmd_SetMatrix(); |
dreschpe | 0:a6545392ca42 | 116 | TFT.Ft_App_WrCoCmd_Buffer(VERTEX2F(50,50)); |
dreschpe | 0:a6545392ca42 | 117 | } |
dreschpe | 0:a6545392ca42 | 118 | TFT.Ft_App_WrCoCmd_Buffer(DISPLAY()); // Display the image |
dreschpe | 0:a6545392ca42 | 119 | TFT.Ft_Gpu_CoCmd_Swap(); // Swap the current display list |
dreschpe | 0:a6545392ca42 | 120 | |
dreschpe | 0:a6545392ca42 | 121 | TFT.Ft_App_Flush_Co_Buffer(); // Download the commands into fifo |
dreschpe | 0:a6545392ca42 | 122 | TFT.Ft_Gpu_Hal_WaitCmdfifo_empty(); // Wait till coprocessor completes the operation |
dreschpe | 0:a6545392ca42 | 123 | |
dreschpe | 0:a6545392ca42 | 124 | |
dreschpe | 0:a6545392ca42 | 125 | } |
dreschpe | 0:a6545392ca42 | 126 | |
dreschpe | 0:a6545392ca42 | 127 | |
dreschpe | 0:a6545392ca42 | 128 |