808

Dependents:   Chromatograph_Mobile

Revision:
10:6a81aeca25e3
Parent:
5:506e2de9a9e6
Child:
13:5959af2ac87a
diff -r ca6a7c6a2f4b -r 6a81aeca25e3 src/FT_Hal_Utils.cpp
--- a/src/FT_Hal_Utils.cpp	Thu Dec 22 20:19:22 2016 +0000
+++ b/src/FT_Hal_Utils.cpp	Mon Jul 23 12:22:23 2018 +0000
@@ -2,65 +2,891 @@
 #include "mbed.h"
 //#include "SDFileSystem.h"
 
+#define DEBUG
+
+/* meta-commands, sequences of several display-list entries condensed into simpler to use functions at the price of some overhead */
+
+ft_void_t FT813::Point(ft_int16_t x, ft_int16_t y, ft_uint16_t size)
+{
+    ft_uint32_t calc;
+
+    StartFunc(FT_CMD_SIZE*4);
+    SendCmd(DL_BEGIN | FT8_POINTS);
+    calc = POINT_SIZE(size*16);
+    SendCmd(calc);
+    calc = VERTEX2F(x * 16, y * 16);
+    SendCmd(calc);
+    SendCmd(DL_END);
+    EndFunc();
+}
+
+ft_void_t FT813::Line(ft_int16_t x0, ft_int16_t y0, ft_int16_t x1, ft_int16_t y1, ft_int16_t width)
+{
+    ft_uint32_t calc;
+
+    StartFunc(FT_CMD_SIZE*5);
+    SendCmd(DL_BEGIN | FT8_LINES);
+    calc = LINE_WIDTH(width * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x0 * 16, y0 * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x1 * 16, y1 * 16);
+    SendCmd(calc);
+    SendCmd(DL_END);
+    EndFunc();
+}
+
+ft_void_t FT813::Rect(ft_int16_t x0, ft_int16_t y0, ft_int16_t x1, ft_int16_t y1, ft_int16_t corner)
+{
+    ft_uint32_t calc;
+
+    StartFunc(FT_CMD_SIZE*5);
+    SendCmd(DL_BEGIN | FT8_RECTS);
+    calc = LINE_WIDTH(corner * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x0 * 16, y0 * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x1 * 16, y1 * 16);
+    SendCmd(calc);
+    SendCmd(DL_END);
+    EndFunc();
+}
+
+ft_void_t FT813::RectWH(ft_int16_t x0, ft_int16_t y0, ft_int16_t w, ft_int16_t h, ft_int16_t corner)
+{
+    ft_uint32_t calc;
+    x0 += corner;
+    y0 += corner;
+    w -= corner*2;
+    h -= corner*2;
+    ft_int16_t x1 = x0 + w;
+    ft_int16_t y1 = y0 + h;
+    StartFunc(FT_CMD_SIZE*5);
+    SendCmd(DL_BEGIN | FT8_RECTS);
+    calc = LINE_WIDTH(corner * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x0 * 16, y0 * 16);
+    SendCmd(calc);
+    calc = VERTEX2F(x1 * 16, y1 * 16);
+    SendCmd(calc);
+    SendCmd(DL_END);
+    EndFunc();
+}
+
+/* Function to load JPG file from the filesystem into the FT800 buffer. */
+/* First the graphics data have to be load into the FT800 buffer.       */
+/* The FT800 will decode the JPG data into a bitmap.                    */      
+/* In the second step this bitmap will displayed on the LCD.            */  
+/* return 0 if jpg is ok                                                */
+/* return x_size and y_size of jpg                                      */
+ft_uint8_t FT813::LoadJpg(char* filename, ft_int16_t* x_size, ft_int16_t* y_size)
+{
+//    unsigned char pbuff[8192];
+    int bufferSize = 8192;
+//    void* pbuff;
+    char* pbuff = (char*)malloc(bufferSize);
+//    char pbuff[BUFFER_SIZE] = {0};
+    unsigned short marker;
+    unsigned short length;
+    unsigned char data[4];
+  
+    ft_uint16_t blocklen;
+ 
+//    printf("LoadJpg: Open filename \"%s\".\n", filename);
+
+    FILE *fp = fopen(filename, "rb");
+    if(fp == NULL) {
+        free(pbuff);
+        printf("LoadJpg: Cannot open file \"%s\".\n", filename);
+        return (-1);         // cannot open file
+    }
+ 
+    // https://en.wikipedia.org/wiki/JPEG
+    // search for 0xFFC0 marker
+    fseek(fp, 0, SEEK_END);
+    unsigned int filesize = ftell(fp);
+    printf("LoadJpg: Size: %d.\n", filesize);
+
+    fseek(fp, 2, SEEK_SET); // Beginning of file
+    fread(data, 4, 1, fp); // Read first 4 bytes
+    marker = data[0] << 8 | data[1];
+    length = data[2] << 8 | data[3];
+    do {
+        if(marker == 0xFFC0)
+            break;
+        if(marker & 0xFF00 != 0xFF00)
+            break;
+        if (fseek(fp, length - 2,SEEK_CUR) != 0) // Skip marker
+            break;
+        fread(data, 4, 1, fp);
+        marker = data[0] << 8 | data[1];
+        length = data[2] << 8 | data[3];
+    } while(1);
+    
+    if(marker != 0xFFC0) {
+        free(pbuff);
+        printf("LoadJpg: marker != 0xFFC0\n");
+        return (-2);  // No FFC0 Marker, wrong format no baseline DCT-based JPEG
+    }
+    
+    fseek(fp, 1, SEEK_CUR); // Skip marker
+    fread(data, 8, 1, fp);  // Read next 8 bytes & extract height & width
+    *y_size = (data[0] << 8 | data[1]);
+    *x_size = (data[2] << 8 | data[3]);
+    uint16_t size_y = (data[0] << 8 | data[1]);
+    uint16_t size_x = (data[2] << 8 | data[3]);
+
+    uint16_t disp_x = DispWidth;
+    uint16_t disp_y = DispHeight;
+    if ((_orientation == FT8_DISPLAY_PORTRAIT_90CW) || (_orientation == FT8_DISPLAY_PORTRAIT_90CCW)) {
+        disp_x = DispHeight;
+        disp_y = DispWidth;
+    }
+  
+// http://www.ftdichip.com/Support/Documents/AppNotes/AN_339%20Using%20JPEGs%20with%20the%20FT800%20series.pdf, page 11
+//    if (marker_next_byte[0] == 0xC2){ //check if progressive JPEG
+//        error_code = 3;
+//    }
+
+//    if(*x_size > TFT.FT_DispWidth || *y_size > TFT.FT_DispHeight) return (-3);  // to big to fit on screen
+    if(*x_size > disp_x || *y_size > disp_y)
+    {
+        free(pbuff);
+        printf("LoadJpg: Too big to fit on screen\n");
+        printf("LoadJpg: JPG (%dx%d) does not fit on TFT (%dx%d)\n", *x_size, *y_size, DispWidth, DispHeight);
+        return (-3);  // Too big to fit on screen
+    }
+ 
+//    printf("LoadJpg: JPG (%dx%d) fits on TFT (%dx%d)\n", *x_size, *y_size, DispWidth, DispHeight);
+
+    fseek(fp, 0, SEEK_SET);
+    
+    
+    WrCmd32(CMD_LOADIMAGE);
+    WrCmd32(_address);             //destination address of jpg decode
+    
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+    _address += (uint32_t) (size_x * size_y * 2);
+    _addresses[_bitmap_count] = _address;
+    // 0 OPT_RGB565
+    // 1 OPT_MONO
+    // 2 OPT_NODL
+    // 256 OPT_FLAT
+    // 256 OPT_SIGNED
+    // 512 OPT_CENTERX
+    // 1024 OPT_CENTERY
+    // 1536 OPT_CENTER
+    // 2048 OPT_RIGHTX
+    // 4096 OPT_NOBACK
+    // 8192 OPT_NOTICKS
+    WrCmd32(0);             //output format of the bitmap - default is rgb565
+    while(filesize > 0) {
+        /* download the data into the command buffer by 8kb one shot */
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+//        printf("LoadJpg: blocklen: %d\n", blocklen);
+//        printf("LoadJpg: filesize: %d\n", filesize);
+
+        /* copy the data into pbuff and then transfter it to command buffer */
+//        int size = fread(&pbuff[0], 1, blocklen, fp);
+        int size = fread(pbuff, 1, blocklen, fp);
+//        printf("LoadJpg: fread: %d, %d\n", blocklen, size);
+        filesize -= blocklen;
+        /* copy data continuously into command memory */
+//        TFT.Ft_Gpu_Hal_WrCmdBuf(pbuff, blocklen); //alignment is already taken care by this api
+        WrCmdBuf((uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+    }
+    fclose(fp);
+    free(pbuff);
+ 
+    return(0);
+}
+
+ft_uint8_t FT813::LoadPng(char* filename, ft_int16_t* x_size, ft_int16_t* y_size)
+{
+    int bufferSize = 8192;
+    ft_uint32_t filesize = 0;
+    ft_uint16_t blocklen = 0;
+    uint32_t marker1;
+    uint32_t marker2;
+    unsigned short length;
+    unsigned char data[32];
+
+//    printf("------------------------------\n");
+    printf("LoadPng: Filename \"%s\".\n", filename);
+  
+    FILE *fp = fopen(filename, "rb");
+    if(fp == NULL) {
+        printf("LoadPng: Cannot open file \"%s\".\n", filename);
+        return (-1);         // cannot open file
+    }
+ 
+    // Get file size
+    fseek(fp, 0, SEEK_END); // End of file
+    filesize = ftell(fp);
+    fseek(fp, 0, SEEK_SET); // Beginning of file
+    printf("LoadPng: Filesize %d\n", filesize);
+
+    // search for 0x89504E47 and 0x0D0A1A0A markers "‰PNG...."
+    fread(data, 1, 32, fp); // Read first 32 bytes
+//    rewind(fp); // Beginning of file
+    fseek(fp, 0, SEEK_SET); // Beginning of file
+
+    // Check that this is indeed a PNG file
+    unsigned char png_header[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+    // Make sure you have an IHDR
+    unsigned char ihdr_name[] = "IHDR";
+    if ((memcmp(data, png_header, 8)) || (memcmp(data+8+4, ihdr_name, 4))) {
+        printf("LoadPng: Invalid PNG file.\n");
+        return (-2);  // No FFC0 Marker, wrong format no baseline DCT-based JPEG
+    }
+
+    // PNG actually stores integers in big-endian.
+    *x_size = ReadBigInt32(data, 24 - 8);
+    *y_size = ReadBigInt32(data, 24 - 4);
+    uint16_t size_x = ReadBigInt32(data, 24 - 8);
+    uint16_t size_y = ReadBigInt32(data, 24 - 4);
+  
+    uint16_t disp_x = DispWidth;
+    uint16_t disp_y = DispHeight;
+    if ((_orientation == FT8_DISPLAY_PORTRAIT_90CW) || (_orientation == FT8_DISPLAY_PORTRAIT_90CCW)) {
+        disp_x = DispHeight;
+        disp_y = DispWidth;
+    }
+
+    if(*x_size > disp_x || *y_size > disp_y)
+    {
+        printf("LoadPng: Too big to fit on screen\n");
+        printf("LoadPng: PNG (%dx%d) does not fit on TFT (%dx%d)\n", *x_size, *y_size, DispWidth, DispHeight);
+        return (-3);  // Too big to fit on screen
+    }
+
+//    printf("LoadPng: PNG (%dx%d) fits on TFT (%dx%d)\n", *x_size, *y_size, DispWidth, DispHeight);
+    
+    // http://www.ftdichip.com/Support/Documents/AppNotes/AN_339%20Using%20JPEGs%20with%20the%20FT800%20series.pdf
+    // CMD_LOADIMAGE: This function will decode the JPEG file, produce
+    // either RGB565 or L8 bitmap data and store this in graphics RAM.
+    // It also writes commands to the display list to set the source, layout and size of the
+    // image (BITMAP_SOURCE, BITMAP_LAYOUT and BITMAP_SIZE).
+    // Note that only a BEGIN and VERTEX2F (or VERTEX2II) display list commands are then
+    // required to complete the display list needed to render the image.
+    WrCmd32(CMD_LOADIMAGE); 
+    WrCmd32(_address);             //destination address of png decode
+    // 0 OPT_RGB565
+    // 1 OPT_MONO
+    // 2 OPT_NODL
+    // 256 OPT_FLAT
+    // 256 OPT_SIGNED
+    // 512 OPT_CENTERX
+    // 1024 OPT_CENTERY
+    // 1536 OPT_CENTER
+    // 2048 OPT_RIGHTX
+    // 4096 OPT_NOBACK
+    // 8192 OPT_NOTICKS
+    // By default, option OPT_RGB565 means the loaded bitmap is in RGB565 format.
+    
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+    _address += (uint32_t) (size_x * size_y * 2);
+    _addresses[_bitmap_count] = _address;
+    printf("LoadPng: Bitmap# %d, Res. %dx%d, Address %d-%d\n", _bitmap_count - 1, *x_size, *y_size, _addresses[_bitmap_count-1], _addresses[_bitmap_count]);
+
+    WrCmd32(OPT_RGB565);             // Output format of the bitmap OPT_RGB565
+//    unsigned int filesizeCounter = filesize;
+    char* pbuff = (char*)malloc(bufferSize);
+    while(filesize > 0) {
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+        int size = fread(pbuff, 1, blocklen, fp);
+        filesize -= blocklen;
+
+        WrCmdBuf((uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+    }
+    fclose(fp);
+    // If the number of bytes in the JPEG file to be written to the command buffer is not a multiple of
+    // four, then one, two or three bytes (of any value) should be added to ensure four-byte alignment of
+    // the next command.
+//    blocklen = filesize % 4;
+//    memset(pbuff, 0, blocklen);
+//    WrCmdBuf((uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+ 
+    free(pbuff);
+
+    printf("LoadPng: Done.\n");
+
+    return(0);
+}
+
+int FT813::LoadRaw(char* filename)
+{
+    ft_uint16_t filesize = 0;
+    ft_uint16_t blocklen;
+    ft_uint16_t ram_start = _address;
+    int bufferSize = 8192;
+
+    FILE *fp = fopen(filename, "rb");   //  open file
+    if (fp == NULL)
+    {
+        // Cannot open file  
+        printf("Unable to open: %s\n", filename);
+        return -1;
+    }
+    fseek(fp, 0, SEEK_END);             //  set file position to end of file
+    filesize = ftell(fp);               //  determine file size
+    fseek(fp, 0, SEEK_SET);             //  return to beginning of file    
+
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+    _address += (uint32_t) filesize;
+    _addresses[_bitmap_count] = _address;
+    printf("LoadRaw: Bitmap# %d, Address %d-%d\n", _bitmap_count - 1, _addresses[_bitmap_count-1], _addresses[_bitmap_count]);
+
+    char* pbuff = (char*)malloc(bufferSize);
+    while(filesize > 0)
+    {
+        //copy the .raw file data to pbuff[8192] in 8k block
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+        fread(pbuff, 1, blocklen, fp);
+        filesize -= blocklen;
+        //write pbuff contents to graphics RAM at address ram_start = 0x00
+        Wr8s(ram_start, (uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+        ram_start += blocklen;   
+    }
+    fclose(fp);
+    free(pbuff);
+    return 0;
+}
+
+int FT813::LoadRawFile(ft_uint32_t address, const char *filename)
+{
+    int bufferSize = 8192;
+    ft_uint32_t filesize = 0;
+    ft_uint16_t blocklen = 0;
+
+    _address = address;
+    ft_uint32_t addr = address;
+    
+    FILE *fp = fopen(filename, "rb");
+    if (fp == NULL)
+    {
+        printf("LoadRawFile: Cannot open file \"%s\".\n", filename);
+        return 0;
+    }
+    fseek(fp, 0, SEEK_END); // End of file
+    filesize = ftell(fp);
+    fseek(fp, 0, SEEK_SET); // Beginning of file
+
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+    _address += (uint32_t) filesize;
+    _addresses[_bitmap_count] = _address;
+    printf("LoadRawFile: Bitmap# %d, Address %d-%d\n", _bitmap_count - 1, _addresses[_bitmap_count-1], _addresses[_bitmap_count]);
+
+    char* pbuff = (char*)malloc(bufferSize);
+    while (filesize > 0)
+    {
+        blocklen = filesize >  bufferSize ? bufferSize : filesize;
+        fread(pbuff, 1, blocklen, fp);
+        filesize -= blocklen;
+        WrMem(addr, (ft_uint8_t *)pbuff, blocklen);
+        addr += blocklen;
+//        WrCmdBuf((ft_uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+    }
+    fclose(fp);
+    free(pbuff);
+
+    printf("LoadRawFile: Done.\n");
+    return 1;
+}
+
+int FT813::LoadInflateFile(ft_uint32_t address, const char *filename)
+{
+    int bufferSize = 8192;
+    ft_uint32_t filesize = 0;
+    ft_uint16_t blocklen = 0;
+    ft_uint32_t addr = address;
+    ft_uint32_t filesize_org = address;
+
+    _address = address;
+
+    FILE *fp = fopen(filename, "rb");      // read Binary (rb)
+    if (fp == NULL)
+    {
+        printf("LoadInflateFile: Cannot open file \"%s\".\n", filename);
+        return 0;
+    }
+    fseek(fp, 0, SEEK_END); // End of file
+    filesize = ftell(fp);
+    fseek(fp, 0, SEEK_SET); // Beginning of file
+
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+//    _address += (uint32_t) 0;
+    _addresses[_bitmap_count] = _address;
+//    printf("# %d, Addr %d\n", _bitmap_count - 1, _addresses[_bitmap_count-1]);
+
+    WrCmd32(CMD_INFLATE);
+    WrCmd32(address);             //destination address of bin decode
+
+    char* pbuff = (char*)malloc(bufferSize);
+    while (filesize > 0)
+    {
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+        int size = fread(pbuff, 1, blocklen, fp);   /* copy the data into pbuff and then transfter it to command buffer */
+        filesize -= blocklen;
+
+//        WrMem(addr, (ft_uint8_t *)pbuff, blocklen);
+//        addr += blocklen;
+
+        //Do not call "Ft_Gpu_Hal_WrCmdBuf_nowait" because it may cause emulator process hang. 
+        WrCmdBuf((ft_uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+//        WaitCmdfifo_empty();
+    }   
+    // If the number of bytes in the JPEG file to be written to the command buffer is not a multiple of
+    // four, then one, two or three bytes (of any value) should be added to ensure four-byte alignment of
+    // the next command.
+//    blocklen = filesize_org % 4;
+//    memset(pbuff, 0, blocklen);
+//    WrMem(addr, (ft_uint8_t *)pbuff, blocklen);
+//    WrCmdBuf((uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+
+//    WaitCmdfifo_empty();            
+
+    fclose(fp);                                              /* close the opened jpg file */
+    free(pbuff);
+    return 1;
+}
+
+int FT813::LoadImageFile(ft_uint32_t address, const char *filename)
+{
+    int bufferSize = 8192;
+    ft_uint32_t filesize = 0;
+    ft_uint16_t blocklen = 0;
+
+    _address = address;
+
+    FILE *fp = fopen(filename, "rb");      // read Binary (rb)
+    if (fp == NULL)
+    {
+        printf("LoadImageFile: Cannot open file \"%s\".\n", filename);
+        return 0;
+    }
+    // TODO: Let it write into the scratch display list handle, 
+    //  and read it out and write into the bitmapInfo the proper 
+    //  values to use. Replace compressed bool with uint8 enum to
+    //  specify the loading mechanism
+    fseek(fp, 0, SEEK_END); // End of file
+    filesize = ftell(fp);
+    fseek(fp, 0, SEEK_SET); // Beginning of file
+
+    // Keep track of of the start addresses of loaded images
+    // Increment _address
+    _addresses[_bitmap_count] = _address;
+    _bitmap_count++;
+    _address += (uint32_t) filesize;
+    _addresses[_bitmap_count] = _address;
+    printf("LoadImageFile: Bitmap# %d, Address %d-%d\n", _bitmap_count - 1, _addresses[_bitmap_count-1], _addresses[_bitmap_count]);
+
+    WrCmd32(CMD_LOADIMAGE);
+    WrCmd32(address);             //destination address of png decode
+    // 0 OPT_RGB565
+    // 1 OPT_MONO
+    // 2 OPT_NODL
+    // 256 OPT_FLAT
+    // 256 OPT_SIGNED
+    // 512 OPT_CENTERX
+    // 1024 OPT_CENTERY
+    // 1536 OPT_CENTER
+    // 2048 OPT_RIGHTX
+    // 4096 OPT_NOBACK
+    // 8192 OPT_NOTICKS
+    // By default, option OPT_RGB565 means the loaded bitmap is in RGB565 format.
+    WrCmd32(OPT_RGB565);             // Output format of the bitmap OPT_RGB565
+//    WrCmd32(OPT_NODL);
+    char* pbuff = (char*)malloc(bufferSize);
+    while (filesize > 0)
+    {
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+        int size = fread(pbuff, 1, blocklen, fp);   /* copy the data into pbuff and then transfter it to command buffer */
+        filesize -= blocklen;
+//        blocklen += 3;
+//        blocklen -= blocklen % 4;
+        
+        //Do not call "Ft_Gpu_Hal_WrCmdBuf_nowait" because it may cause emulator process hang. 
+        WrCmdBuf((ft_uint8_t *)pbuff, blocklen); //alignment is already taken care by this api
+    }   
+//    WaitCmdfifo_empty();
+    
+    fclose(fp);                                              /* close the opened jpg file */
+    free(pbuff);
+    return 1;
+}
+
+ft_void_t FT813::SetEndAddressForSize(ft_uint32_t addr)
+{
+    _addresses[_bitmap_count] = _addresses[_bitmap_count - 1] + addr;
+}
+
+ft_void_t FT813::Wr8s(ft_uint32_t addr, ft_uint8_t *buffer, ft_uint8_t length)
+{
+//    StartTransfer(FT_GPU_WRITE, addr);
+//    if (FT_GPU_READ == rw) {  // if (FT_GPU_READ == FT_GPU_WRITE)
+//        _ss = 0;       // cs low
+//        _spi.write(addr >> 16);
+//        _spi.write(addr >> 8);
+//        _spi.write(addr & 0xff);
+//        _spi.write(0); //Dummy Read Byte
+//        status = READING;
+//    } else {
+        _ss = 0;       // cs low
+        _spi.write(0x80 | (addr >> 16));
+        _spi.write(addr >> 8);
+        _spi.write(addr & 0xff);
+        status = WRITING;
+//    }
+
+//    Transfer8(v);
+//    _spi.write(v);
+
+    while (length--) {
+//            Transfer8(*buffer);
+        _spi.write(*buffer);
+        buffer++;
+//            SizeTransfered++;
+    }
+
+//    EndTransfer();
+    _ss = 1;
+    status = OPENED;
+}
+
+//{
+//ft_uint8_t imbuff[8192];
+//ft_uint16_t blocklen;
+////decompress the .bin file using CMD_INFLATE
+//WrCmd32(phost,CMD_INFLATE);
+////specify starting address in graphics RAM
+//WrCmd32(phost,0L);
+////check filesize and adjust number of bytes to multiple of 4
+//chdir("..\\..\\..\\Test"); //change directory to location (Test) of .bin file
+//pfile = fopen("lenaface40.bin","rb");
+//fseek(pfile,0,SEEK_END); //set file position to end of file
+//filesize = ftell(pfile); // determine file size
+//fseek(pfile,0,SEEK_SET); // return to beginning of file
+//while(filesize > 0)
+//{
+// //copy the .raw file data to imbuff[8192] in 8k blocks
+//blocklen = filesize>8192?8192:filesize;
+//fread(imbuff,1,blocklen,pfile);
+//filesize -= blocklen; //reduce filesize by blocklen
+////write imbuff contents to the FT800 FIFO command buffer
+//Ft_Gpu_Hal_WrCmdBuf(phost,imbuff,blocklen);
+//}
+//fclose(pfile); /* close the opened .bin file */
+//}
+
+int FT813::LoadRawFile(ft_uint32_t address, char* filename)
+{
+    ft_uint16_t filesize;
+    ft_uint16_t blocklen;
+    ft_uint32_t addr = address;
+    int bufferSize = 8192;
+
+    FILE *fp = fopen(filename, "rb");   //  open file
+    if (fp == NULL)
+    {
+        // Cannot open file  
+        printf("Unable to open: %s\n", filename);
+        return -1;
+    }
+    fseek(fp, 0, SEEK_END);             //  set file position to end of file
+    filesize = ftell(fp);               //  determine file size
+    fseek(fp, 0, SEEK_SET);             //  return to beginning of file
+#ifdef DEBUG
+    printf("LoadRawFile: %s %d @ %d\n", filename, filesize, address);
+#endif
+
+    char* pbuff = (char*)malloc(bufferSize);
+    while(filesize > 0)
+    {
+        //copy the .raw file data to pbuff[8192] in 8k block
+        blocklen = filesize > bufferSize ? bufferSize : filesize;
+        fread(pbuff, 1, blocklen, fp);
+        filesize -= blocklen;
+        //write pbuff contents to graphics RAM at addr
+        WrMem(addr, (ft_uint8_t *)pbuff, blocklen);
+        addr += blocklen;   
+    }
+    fclose(fp);
+    free(pbuff);
+    return 0;
+}
+
+void FT813::FillBitmap(ft_int16_t bitmap_number)
+{
+    int bufferSize = 8192;
+    uint8_t* pbuff = (uint8_t*)malloc(bufferSize);
+    // Clear buffer
+    memset(pbuff, 0, bufferSize);
+
+    ft_int32_t addr_start = _addresses[bitmap_number];
+    ft_int32_t addr_end = _addresses[bitmap_number+1];
+    printf("FillBitmap %d (%d - %d).\n", bitmap_number, addr_start, addr_end);
+//    ft_int32_t bufferSize = addr_end - addr_start;
+    ft_int32_t filesize = addr_end - addr_start;
+//    ft_int32_t addr = addr_start;
+    
+    WrCmd32(CMD_LOADIMAGE);
+    WrCmd32(addr_start);             //destination address of png decode
+    WrCmd32(0);             //output format of the bitmap - default is rgb565
+    printf("filesize = %d\n", filesize);
+    printf("while(filesize > 0)...\n");
+    while(filesize > 0) {
+        ft_uint16_t blocklen = filesize > bufferSize ? bufferSize : filesize;
+//    printf("WrCmdBuf %d.\n", bufferSize);
+        filesize -= blocklen;
+        printf("blocklen = %d\n", blocklen);
+        printf("WrCmdBuf...\n");
+        WrCmdBuf(pbuff, blocklen); //alignment is already taken care by this api
+        printf("Done.\n");
+    }
+    printf("free(pbuff)...\n");
+    free(pbuff);
+    printf("Done.\n");
+}
+
+void FT813::ClearBitmapCount(void)
+{
+    _bitmap_count = 0;
+}
+
+ft_uint32_t FT813::ReadBigInt32(unsigned char* data, ft_uint32_t offset)
+{
+    return (data[offset + 0] << 24 | data[24 - 4 + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]);
+}
+
+// Loads JPG at x, y on the screen
+ft_uint8_t FT813::Jpg(char *jpg_filename, int x, int y)
+{
+    ft_int16_t x_size,y_size;
+    int err;
+
+    err = LoadJpg(jpg_filename, & x_size, & y_size);      // load graphic data into buffer and decode jpg to bitmap
+    if(err != 0) {                                           // something is wrong - display error   
+        printf("LoadJpg: Error.\n");
+        return(-1);
+    }
+    DL(BEGIN(BITMAPS));                  
+//    LoadIdentity();
+//    SetMatrix();
+    DL(VERTEX2F(x * 16, y * 16));                  
+
+    // jpg is loaded and decoded into bitmap
+//    printf("jpg %s is loaded and decoded into bitmap (%dx%d)\n", jpg_filename, x_size, y_size);
+
+    return(0);
+}
+
+// Loads PNG at x, y on the screen
+ft_uint8_t FT813::Png(char *png_filename, int x, int y)
+{
+    ft_int16_t x_size,y_size;
+    int err;
+
+    err = LoadPng(png_filename, & x_size, & y_size);      // load graphic data into buffer and decode png to bitmap
+    if(err != 0) {                                           // something is wrong - display error   
+        printf("LoadPng: Error.\n");
+        return(-1);
+    }
+    DL(BEGIN(BITMAPS));                  
+//    LoadIdentity();
+//    SetMatrix();
+    DL(VERTEX2F(x * 16, y * 16));                  
+
+    // png is loaded and decoded into bitmap
+//    printf("png %s is loaded and decoded into bitmap (%dx%d)\n", png_filename, x_size, y_size);
+
+    return(0);
+}
+
+// Loads PNG at x, y on the screen at given address
+ft_uint8_t FT813::Png(char *png_filename, int x, int y, ft_int32_t address)
+{
+    ft_int16_t x_size,y_size;
+    int err;
+    _address = address;
+    err = LoadPng(png_filename, & x_size, & y_size);      // load graphic data into buffer and decode png to bitmap
+    if(err != 0) {                                           // something is wrong - display error   
+        printf("LoadPng: Error.\n");
+        return(-1);
+    }
+    DL(BEGIN(BITMAPS));                  
+//    LoadIdentity();
+//    SetMatrix();
+    DL(VERTEX2F(x * 16, y * 16));                  
+
+//    DL(DISPLAY()); //ends the display,commands after this ignored                 
+
+    // png is loaded and decoded into bitmap
+    printf("png %s is loaded and decoded into bitmap (%dx%d)\n", png_filename, x_size, y_size);
+
+    return(0);
+}
+
+// Loads JPG at the center of the screen (splash screen)
+// Background color specified
+ft_uint8_t FT813::JpgSplash(char *jpg_filename, ft_uint8_t r, ft_uint8_t g, ft_uint8_t b)
+{
+    ft_int16_t x_size,y_size;
+    int err;
+
+    DLstart();                              // start a new display command list
+    DL(CLEAR_COLOR_RGB(r, g, b));  // set the clear color to white
+    DL(CLEAR(1, 1, 1));                     // clear buffers -> color buffer,stencil buffer, tag buffer
+
+    err = LoadJpg(jpg_filename, & x_size, & y_size);      // load graphic data into buffer and decode jpg to bitmap
+    if(err != 0) {                                           // something is wrong - display error   
+        printf("LoadJpg: Error.\n");
+        return(-1);
+    }
+    
+    DL(BEGIN(BITMAPS));                  
+    LoadIdentity();
+    SetMatrix();
+    int x = (DispWidth - x_size) / 2;
+    int y = (DispHeight - y_size) / 2;
+    DL(VERTEX2F(x * 16, y * 16));                  
+
+    DL(DISPLAY());                          // Display the image
+    Swap();                                 // Swap the current display list
+    Flush_Co_Buffer();                      // Download the command list into fifo
+    WaitCmdfifo_empty();                    // Wait till coprocessor completes the operation
+    
+    return(0);
+}
+
+// ***************************************************************************************************************
+// *** Utility and helper functions ******************************************************************************
+// ***************************************************************************************************************
+
+// Find the space available in the GPU AKA CoProcessor AKA command buffer AKA FIFO
+ft_uint16_t FT813::CoProFIFO_FreeSpace(void)
+{
+    ft_uint16_t cmdBufferDiff, cmdBufferRd, cmdBufferWr, retval;
+    
+    cmdBufferRd = Rd16(REG_CMD_READ + RAM_REG);
+    cmdBufferWr = Rd16(REG_CMD_WRITE + RAM_REG);
+    
+    cmdBufferDiff = (cmdBufferWr-cmdBufferRd) % FT_CMD_FIFO_SIZE; // FT81x Programmers Guide 5.1.1
+    retval = (FT_CMD_FIFO_SIZE - 4) - cmdBufferDiff;
+    return (retval);
+}
+
+// Sit and wait until there are the specified number of bytes free in the <GPU/CoProcessor> incoming FIFO
+void FT813::Wait4CoProFIFO(ft_uint32_t room)
+{
+    ft_uint16_t getfreespace;
+    
+    do {
+        getfreespace = CoProFIFO_FreeSpace();
+    } while(getfreespace < room);
+}
+
+// Sit and wait until the CoPro FIFO is empty
+void FT813::Wait4CoProFIFOEmpty(void)
+{
+  while(Rd16(REG_CMD_READ + RAM_REG) != Rd16(REG_CMD_WRITE + RAM_REG));
+}
+
+// Check if the CoPro FIFO is empty
+// returns 1 if the CoPro FIFO is empty
+// returns 0 if the CoPro FIFO is not empty
+ft_uint8_t FT813::CheckIfCoProFIFOEmpty(void)
+{
+    return (Rd16(REG_CMD_READ + RAM_REG) == Rd16(REG_CMD_WRITE + RAM_REG)) ? 1 : 0;
+}
+
+// Write a block of data into Eve RAM space a byte at a time.
+// Return the last written address + 1 (The next available RAM address)
+ft_uint32_t FT813::WriteBlockRAM(ft_uint32_t Add, const ft_uint8_t *buff, ft_uint32_t count)
+{
+    ft_uint32_t index;
+    ft_uint32_t WriteAddress = Add;  // I want to return the value instead of modifying the variable in place
+    
+    for (index = 0; index < count; index++) {
+        Wr8(WriteAddress++, buff[index]);
+    }
+    return (WriteAddress);
+}
+
 /* function to load jpg file from filesystem */
 /* return 0 if jpg is ok                     */
 /* return x_size and y_size of jpg           */
 
-int FT800::Load_jpg(char* filename, ft_int16_t* x_size, ft_int16_t* y_size, ft_uint32_t address)
-{
-    unsigned char pbuff[8291];
-    unsigned short marker;
-    unsigned short length;
-    unsigned char data[4];
-
-    ft_uint16_t blocklen;
-//    sd.mount();
-    FILE *fp = fopen(filename, "r");
-    if(fp == NULL) return (-1);         // connot open file
+//int FT813::Load_jpg(char* filename, ft_int16_t* x_size, ft_int16_t* y_size, ft_uint32_t address)
+//{
+//    unsigned char pbuff[8192];
+//    unsigned short marker;
+//    unsigned short length;
+//    unsigned char data[4];
+//
+//    ft_uint16_t blocklen;
+////    sd.mount();
+//    FILE *fp = fopen(filename, "r");
+//    if(fp == NULL) return (-1);         // connot open file
+//
+//    // search for 0xFFC0 marker
+//    fseek(fp, 0, SEEK_END);
+//    unsigned int filesize = ftell(fp);
+//    fseek(fp, 2, SEEK_SET);
+//    fread(data,4,1,fp);
+//    marker = data[0] << 8 | data[1];
+//    length = data[2] << 8 | data[3];
+//    do {
+//        if(marker == 0xFFC0) break;
+//        if(marker & 0xFF00 != 0xFF00) break;
+//        if (fseek(fp, length - 2,SEEK_CUR) != 0) break;
+//        fread(data,4,1,fp);
+//        marker = data[0] << 8 | data[1];
+//        length = data[2] << 8 | data[3];
+//    } while(1);
+//    if(marker != 0xFFC0) return (-2);  // no FFC0 Marker, wrong format no baseline DCT-based JPEG
+//    fseek(fp, 1,SEEK_CUR);
+//    fread(data,4,1,fp);
+//    *y_size = (data[0] << 8 | data[1]);
+//    *x_size = (data[2] << 8 | data[3]);
+//
+//    //if(*x_size > DispWidth || *y_size > DispHeight) return (-3);  // to big to fit on screen
+//
+//    fseek(fp, 0, SEEK_SET);
+//    WrCmd32(CMD_LOADIMAGE);  // load a JPEG image
+//    WrCmd32(address);              //destination address of jpg decode
+//    WrCmd32(0);              //output format of the bitmap - default is rgb565
+//    while(filesize > 0) {
+//        /* download the data into the command buffer by 8kb one shot */
+//        blocklen = filesize>8192?8192:filesize;
+//        /* copy the data into pbuff and then transfter it to command buffer */
+//        fread(pbuff,1,blocklen,fp);
+//        filesize -= blocklen;
+//        /* copy data continuously into command memory */
+//        WrCmdBuf(pbuff, blocklen); //alignment is already taken care by this api
+//    }
+//    fclose(fp);
+////    sd.unmount();
+//
+//    return(0);
+//}
 
-    // search for 0xFFC0 marker
-    fseek(fp, 0, SEEK_END);
-    unsigned int Fsize = ftell(fp);
-    fseek(fp, 2, SEEK_SET);
-    fread(data,4,1,fp);
-    marker = data[0] << 8 | data[1];
-    length = data[2] << 8 | data[3];
-    do {
-        if(marker == 0xFFC0) break;
-        if(marker & 0xFF00 != 0xFF00) break;
-        if (fseek(fp, length - 2,SEEK_CUR) != 0) break;
-        fread(data,4,1,fp);
-        marker = data[0] << 8 | data[1];
-        length = data[2] << 8 | data[3];
-    } while(1);
-    if(marker != 0xFFC0) return (-2);  // no FFC0 Marker, wrong format no baseline DCT-based JPEG
-    fseek(fp, 1,SEEK_CUR);
-    fread(data,4,1,fp);
-    *y_size = (data[0] << 8 | data[1]);
-    *x_size = (data[2] << 8 | data[3]);
-
-    //if(*x_size > DispWidth || *y_size > DispHeight) return (-3);  // to big to fit on screen
-
-    fseek(fp, 0, SEEK_SET);
-    WrCmd32(CMD_LOADIMAGE);  // load a JPEG image
-    WrCmd32(address);              //destination address of jpg decode
-    WrCmd32(0);              //output format of the bitmap - default is rgb565
-    while(Fsize > 0) {
-        /* download the data into the command buffer by 8kb one shot */
-        blocklen = Fsize>8192?8192:Fsize;
-        /* copy the data into pbuff and then transfter it to command buffer */
-        fread(pbuff,1,blocklen,fp);
-        Fsize -= blocklen;
-        /* copy data continuously into command memory */
-        WrCmdBuf(pbuff, blocklen); //alignment is already taken care by this api
-    }
-    fclose(fp);
-//    sd.unmount();
-
-    return(0);
-}
-
-//int FT800::Load_raw(char* filename)
+//int FT813::Load_raw(char* filename)
 //{
 //    ft_uint8_t imbuff[8192];
 //    ft_uint16_t filesize;
@@ -90,47 +916,39 @@
 //    return 0;
 //}
 
-
-
-
-
-
 /* calibrate touch */
-ft_void_t FT800::Calibrate()
+ft_void_t FT813::Calibrate()
 {
     /*************************************************************************/
     /* Below code demonstrates the usage of calibrate function. Calibrate    */
     /* function will wait untill user presses all the three dots. Only way to*/
     /* come out of this api is to reset the coprocessor bit.                 */
     /*************************************************************************/
-    {
-
-        DLstart();                                       // start a new display command list
-        DL(CLEAR_COLOR_RGB(64,64,64));       // set the clear color R, G, B
-        DL(CLEAR(1,1,1));                    // clear buffers -> color buffer,stencil buffer, tag buffer
-        DL(COLOR_RGB(0xff,0xff,0xff));       // set the current color R, G, B
-        Text((DispWidth/2), (DispHeight/2), 27, OPT_CENTER, "Please Tap on the dot");  // draw Text at x,y, font 27, centered
-        Calibrate(0);                                    // start the calibration of touch screen
-        Flush_Co_Buffer();                               // download the commands into FT800 FIFO
-        WaitCmdfifo_empty();                             // Wait till coprocessor completes the operation
-    }
+    DLstart();                                       // start a new display command list
+    DL(CLEAR_COLOR_RGB(64,64,64));       // set the clear color R, G, B
+    DL(CLEAR(1,1,1));                    // clear buffers -> color buffer,stencil buffer, tag buffer
+    DL(COLOR_RGB(0xff,0xff,0xff));       // set the current color R, G, B
+    Text((DispWidth/2), (DispHeight/2), 27, OPT_CENTER, "Please tap on the dot");  // draw Text at x,y, font 27, centered
+    Calibrate(0);                                    // start the calibration of touch screen
+    Flush_Co_Buffer();                               // download the commands into FT813 FIFO
+    WaitCmdfifo_empty();                             // Wait till coprocessor completes the operation
 }
 
 
 /* API to give fadeout effect by changing the display PWM from 100 till 0 */
-ft_void_t FT800::fadeout()
+ft_void_t FT813::fadeout()
 {
-   ft_int32_t i;
+    ft_int32_t i;
     
     for (i = 100; i >= 0; i -= 3) 
     {
-        Wr8(REG_PWM_DUTY,i);
+        Wr8(REG_PWM_DUTY, i);
         Sleep(2);//sleep for 2 ms
     }
 }
 
 /* API to perform display fadein effect by changing the display PWM from 0 till 100 and finally 128 */
-ft_void_t FT800::fadein()
+ft_void_t FT813::fadein()
 {
     ft_int32_t i;
     
@@ -144,25 +962,516 @@
     Wr8(REG_PWM_DUTY,i);
 }
 
-ft_void_t FT800::read_calibrate(ft_uint8_t data[24]){
+ft_uint8_t FT813::read_calibrate_reg(ft_uint8_t i) {
+    return Rd8(REG_TOUCH_TRANSFORM_A + i);
+}
+
+ft_uint32_t FT813::read_calibrate_reg32(ft_uint8_t i) {
+    return (Rd8(REG_TOUCH_TRANSFORM_A + i)) +           // lsb
+           (Rd8(REG_TOUCH_TRANSFORM_A + i+1) << 8) + 
+           (Rd8(REG_TOUCH_TRANSFORM_A + i+2) << 16) + 
+           (Rd8(REG_TOUCH_TRANSFORM_A + i+3) << 24);    //  msb
+}
+
+ft_void_t FT813::read_calibrate(ft_uint8_t data[24]) {
+    unsigned int i;
+    for(i = 0; i < 24; i++) {
+        data[i] = Rd8(REG_TOUCH_TRANSFORM_A + i);
+    }
+}
+
+ft_void_t FT813::write_calibrate(ft_uint8_t data[24]) {
+    unsigned int i;
+    for(i = 0; i < 24; i++) {
+        Wr8(REG_TOUCH_TRANSFORM_A + i, data[i]);
+    }
+}
+
+ft_void_t FT813::write_calibrate32(ft_uint32_t data[6]) {
     unsigned int i;
-    for(i=0;i<24;i++){
-        data[i] = Rd8(REG_TOUCH_TRANSFORM_A + i);
-        }
+    for(i = 0; i < 6; i++) {
+        Wr8(REG_TOUCH_TRANSFORM_A + i*4, (data[i]) & 0xff);       // lsb
+        Wr8(REG_TOUCH_TRANSFORM_A + i*4 + 1, (data[i] >> 8) & 0xff);
+        Wr8(REG_TOUCH_TRANSFORM_A + i*4 + 2, (data[i] >> 16) & 0xff);
+        Wr8(REG_TOUCH_TRANSFORM_A + i*4 + 3, (data[i] >> 24) & 0xff);   // msb
+    }
+}
+
+ft_uint32_t FT813::color_rgb(ft_uint8_t red, ft_uint8_t green, ft_uint8_t blue){
+    return ((4UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0));
+}
+    
+ft_uint32_t FT813::clear_color_rgb(ft_uint8_t red, ft_uint8_t green, ft_uint8_t blue){
+    return ((2UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0));
+}    
+
+// Define the backlight PWM output duty cycle.
+void FT813::SetBacklight(ft_uint16_t brightness)
+{
+    brightness = brightness * brightness / 255;
+    if (brightness > 256)
+        brightness = 256;
+    if (brightness < 16)
+        brightness = 16;
+    Wr16(REG_PWM_DUTY, brightness); // Brightness
+}
+
+void FT813::Tag(ft_uint8_t tag)
+{
+    DL(TAG(tag)); 
+}
+
+void FT813::ClearTag(ft_uint8_t tag)
+{
+    DL(CLEAR_TAG(tag)); 
+}
+
+void FT813::TagMask(ft_uint8_t mask)
+{
+    DL(TAG_MASK(mask)); 
+}
+
+void FT813::BitmapLayoutH(ft_uint8_t linestride, ft_uint8_t height)
+{
+    DL((40 << 24) | (((linestride) & 3) << 2) | (((height) & 3) << 0));
+}
+
+void FT813::BitmapSizeH(ft_uint8_t width, ft_uint8_t height)
+{
+    DL((41UL << 24) | (((width) & 3) << 2) | (((height) & 3) << 0));
+}
+
+ft_void_t FT813::SetLoadAddress(ft_uint32_t address)
+{
+    _address = address;         // Old, try to get rid of this
+    _bitmapAddress = address;
+}
+
+ft_void_t FT813::SetBitmapCount(ft_uint8_t count)
+{
+    _bitmap_count = count;      // Old, try to get rid of this
+    _bitmapCount = count;
+}
+
+ft_uint32_t FT813::GetBitmapAddress(ft_uint8_t bitmap_number)
+{
+    return _addresses[bitmap_number];
+}
+
+void FT813::SetThemeDefaultColor(void)
+{
+    // Default
+    GradColor(COLOR_RGB(0xff, 0xff, 0xff)); // Default 0xffffff
+    FgColor(COLOR_RGB(0x00, 0x38, 0x70));   // Default 0x003870    (0, 56, 112)
+    BgColor(COLOR_RGB(0x00, 0x20, 0x40));   // Default 0x002040    (0, 32, 64)
+}
+
+void FT813::SetThemeColor(ft_uint32_t c)
+{
+    GradColor(COLOR_RGB(0xff, 0xff, 0xff)); // Default 0xffffff
+    ft_uint8_t r = (c >> 16) & 0xff;
+    ft_uint8_t g = (c >> 8) & 0xff;
+    ft_uint8_t b = c & 0xff;
+    ft_uint8_t rfg = r * 112 / 255;
+    ft_uint8_t gfg = g * 112 / 255;
+    ft_uint8_t bfg = b * 112 / 255;
+    ft_uint8_t rbg = r * 64 / 255;
+    ft_uint8_t gbg = g * 64 / 255;
+    ft_uint8_t bbg = b * 64 / 255;
+    FgColor(COLOR_RGB(rfg, gfg, bfg));   // Default 0x003870
+    BgColor(COLOR_RGB(rbg, gbg, bbg));   // Default 0x002040
+}
+
+// ShowCalibration
+void FT813::ShowCalibrationInCode(void)
+{
+    // Read calibrate registers
+    printf("// Calibration values:\n");
+    printf("    ft_uint32_t canned_calibration_data[] = {\n");
+    for(int i = 0; i < 24; i+=4) {
+        printf("        ");
+        printf("0x%08x", read_calibrate_reg32(i));
+        if (i < 20)
+            printf(",");
+        printf("\n");
+    }
+    printf("    };\n");
+    printf("    write_calibrate32(canned_calibration_data);\n");
+}
+
+// Set screen orientation and preload canned touch screen calibration values
+void FT813::SetOrientation(ft_uint8_t orientation)
+{
+//    TFT.SetRotate(0); // Standard landscape
+//    TFT.SetRotate(1); // Rotate 180 to landscape (upside down)
+//    TFT.SetRotate(2); // Rotate 90 CCW to portrait
+//    TFT.SetRotate(3); // Rotate 90 CW to portrait
+//    TFT.SetRotate(4); // Mirror over landscape X
+//    TFT.SetRotate(5); // Mirror over landscape Y
+//    TFT.SetRotate(6); // Rotate 90 CCW to portrait and mirror over portrait X
+//    TFT.SetRotate(7); // Rotate 90 CW to portrait and mirror over portrait X
+
+    _orientation = orientation;
+    
+    SetRotate(orientation); // Standard landscape
+    // Canned calibration for the orientation
+    
+    if (orientation == FT8_DISPLAY_LANDSCAPE_0)
+    {
+        // Landscape 0
+        ft_uint32_t canned_calibration_data[] = {
+            0x000109b0,   // 68016
+            0x0000023d,   // 573
+            0x0000fa64,   // 64100
+            0xffffffcf,   // -49
+            0xfffefc9a,   // -66406
+            0x01ee8754    // 32409428
+        };
+        write_calibrate32(canned_calibration_data);
+    }
+
+    if (orientation == FT8_DISPLAY_PORTRAIT_90CW)
+    {
+        ft_uint32_t canned_calibration_data[] = {
+            0xfffff994,
+            0xffff07d3,
+            0x01e4b85c,
+            0xfffef6f5,
+            0x000002ad,
+            0x032eb4d4
+        };
+        write_calibrate32(canned_calibration_data);
+    }
+
+    if (orientation == FT8_DISPLAY_PORTRAIT_90CCW)
+    {
+        // Calibration rotate 90 CCW to portrait 
+        ft_uint32_t canned_calibration_data[] = {
+            0x00000491,
+            0x0000fd0b,
+            0xfff6f84b,
+            0x00010503,
+            0x000006b7,
+            0xffeeb0b7
+        };
+        write_calibrate32(canned_calibration_data);
+    }
+}
+
+void FT813::ShowBitmap(ft_uint8_t bitmap, ft_int16_t fmt, ft_uint16_t x, ft_uint16_t y, ft_uint16_t width, ft_uint16_t height)
+{
+    ft_int32_t addr = GetBitmapAddress(bitmap);
+    DL(BITMAP_SOURCE(addr));
+//    ft_int16_t stride = width * 2;
+//     1-bits/p L1
+//    if (fmt == L1) {
+//        stride = width / 8;
+//    }
+//     2-bits/p L2
+//    if (fmt == L2) {
+//        stride = width / 4;
+//    }
+//     4-bits/p L4
+//    if (fmt == L4) {
+//        stride = width / 2;
+//    }
+//     8-bits/p L8 RGB332 ARGB2 PALETTED565 PALETTED4444 PALETTED8
+//    if ((fmt == L8) ||
+//        (fmt == RGB332) ||
+//        (fmt == ARGB2) ||
+//        (fmt == PALETTED565) ||
+//        (fmt == PALETTED4444) ||
+//        (fmt == PALETTED8)) {
+//        stride = width;
+//    }
+//     16-bits/p ARGB1555 ARGB4 RGB565
+//    if ((fmt == ARGB1555) ||
+//        (fmt == ARGB4) ||
+//        (fmt == RGB565)) {
+//        stride = width * 2;
+//    }
+//    DL(BITMAP_LAYOUT(fmt, stride, h));              // 10-bit linestride, 9-bit height
+//    DL(BITMAP_LAYOUT_H(stride >> 10, h >> 9));      // msb bits
+//    DL(BITMAP_SIZE(NEAREST, BORDER, BORDER, w, h)); // 9-bit width, 9-bit height
+//    DL(BITMAP_SIZE_H(w >> 9, h >> 9));              // msb bits
+
+    SetBitmap(addr, fmt, width, height);
+
+//    DL(VERTEX2II(x, y, 0, 0));
+    DL(VERTEX2F(x * 16, y * 16));
 }
 
-ft_void_t FT800::write_calibrate(ft_uint8_t data[24]){
-    unsigned int i;
-    for(i=0;i<24;i++) {
-        Wr8(REG_TOUCH_TRANSFORM_A + i,data[i]);
+void FT813::ShowBitmapAtAddress(ft_uint32_t addr, ft_int16_t fmt, ft_uint16_t x, ft_uint16_t y, ft_uint16_t width, ft_uint16_t height)
+{
+    DL(BITMAP_SOURCE(addr));
+//    ft_int16_t stride = width * 2;
+    // 1-bits/p L1
+//    if (fmt == L1) {
+//        stride = width / 8;
+//    }
+    // 2-bits/p L2
+//    if (fmt == L2) {
+//        stride = width / 4;
+//    }
+    // 4-bits/p L4
+//    if (fmt == L4) {
+//        stride = width / 2;
+//    }
+    // 8-bits/p L8 RGB332 ARGB2 PALETTED565 PALETTED4444 PALETTED8
+//    if ((fmt == L8) ||
+//        (fmt == RGB332) ||
+//        (fmt == ARGB2) ||
+//        (fmt == PALETTED565) ||
+//        (fmt == PALETTED4444) ||
+//        (fmt == PALETTED8)) {
+//        stride = width;
+//    }
+    // 16-bits/p ARGB1555 ARGB4 RGB565
+//    if ((fmt == ARGB1555) ||
+//        (fmt == ARGB4) ||
+//        (fmt == RGB565)) {
+//        stride = width * 2;
+//    }
+//    DL(BITMAP_LAYOUT(fmt, stride, h));              // 10-bit linestride, 9-bit height
+//    DL(BITMAP_LAYOUT_H(stride >> 10, h >> 9));      // msb bits
+//    DL(BITMAP_SIZE(NEAREST, BORDER, BORDER, w, h)); // 9-bit width, 9-bit height
+//    DL(BITMAP_SIZE_H(w >> 9, h >> 9));              // msb bits
+
+    SetBitmap(addr, fmt, width, height);
+    
+//    DL(VERTEX2II(x, y, 0, 0));
+    DL(VERTEX2F(x * 16, y * 16));
+}
+
+int FT813::GetImageIndexFromName(char *name)
+{
+    for (int i = 0; i < _bitmapCount; i++) {
+        if(strstr(_bitmaps[i].name, name) != NULL) {
+            return i;
         }
+    }
+    return -1;
+}
+
+int FT813::ResetInflateFileBitmap(void)
+{
+    _bitmapAddress = 0;
+    _bitmapCount = 0;
+}
+
+uint32_t FT813::GetRamUsage(void)
+{
+    return _bitmapAddress;
+}
+
+uint16_t FT813::GetRamNoOfBitmaps(void)
+{
+    return _bitmapCount;
+}
+
+int FT813::LoadInflateFileBitmap(char *name, uint16_t fmt, uint16_t w, uint16_t h)
+{
+    strcpy(_bitmaps[_bitmapCount].name, name);
+    _bitmaps[_bitmapCount].fmt = fmt;
+    _bitmaps[_bitmapCount].w = w;
+    _bitmaps[_bitmapCount].h = h;  
+    _bitmaps[_bitmapCount].addr = _bitmapAddress;
+    // 1-bits/p L1
+    if (_bitmaps[_bitmapCount].fmt == L1) {
+        _bitmaps[_bitmapCount].size = _bitmaps[_bitmapCount].w * _bitmaps[_bitmapCount].h / 8;
+    }
+    // 2-bits/p L2
+    if (_bitmaps[_bitmapCount].fmt == L2) {
+        _bitmaps[_bitmapCount].size = _bitmaps[_bitmapCount].w * _bitmaps[_bitmapCount].h / 4;
+    }
+    // 4-bits/p L4
+    if (_bitmaps[_bitmapCount].fmt == L4) {
+        _bitmaps[_bitmapCount].size = _bitmaps[_bitmapCount].w * _bitmaps[_bitmapCount].h / 2;
+    }
+    // 8-bits/p L8 RGB332 ARGB2 PALETTED565 PALETTED4444 PALETTED8
+    if ((_bitmaps[_bitmapCount].fmt == L8) ||
+        (_bitmaps[_bitmapCount].fmt == RGB332) || 
+        (_bitmaps[_bitmapCount].fmt == ARGB2) ||
+        (_bitmaps[_bitmapCount].fmt == PALETTED565) || 
+        (_bitmaps[_bitmapCount].fmt == PALETTED4444) || 
+        (_bitmaps[_bitmapCount].fmt == PALETTED8)) {
+        _bitmaps[_bitmapCount].size = _bitmaps[_bitmapCount].w * _bitmaps[_bitmapCount].h;
+    }
+    // 16-bits/p ARGB1555 ARGB4 RGB565
+    if ((_bitmaps[_bitmapCount].fmt == ARGB1555) || 
+        (_bitmaps[_bitmapCount].fmt == ARGB4) || 
+        (_bitmaps[_bitmapCount].fmt == RGB565)) {
+        _bitmaps[_bitmapCount].size = _bitmaps[_bitmapCount].w * _bitmaps[_bitmapCount].h * 2;
+    }
+    LoadInflateFile(_bitmaps[_bitmapCount].addr, _bitmaps[_bitmapCount].name); // x 0, y 0, w 32, h 32, size 1024
+    _bitmapAddress += _bitmaps[_bitmapCount].size;
+    _bitmapCount++;
+}
+
+int FT813::ShowBitmapByName(char *name, uint16_t x, uint16_t y)
+{
+    int index = GetImageIndexFromName(name);
+    ShowBitmapAtAddress(_bitmaps[index].addr, _bitmaps[index].fmt, x, y, _bitmaps[index].w, _bitmaps[index].h);
+}
+
+uint16_t FT813::GetTouchedTag(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TrackRegisterVal = Rd32(REG_TRACKER);       // check if one of the tracking fields is touched
+    return TrackRegisterVal & 0xffff;
 }
 
-ft_uint32_t FT800::color_rgb(ft_uint8_t red,ft_uint8_t green, ft_uint8_t blue){
-    return ((4UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0));
+uint16_t FT813::GetTouchedTag(uint8_t point_number)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    // check if one of the tracking fields is touched
+    uint32_t TrackRegisterVal = 0;
+    switch (point_number) {
+        case 0:
+            TrackRegisterVal = Rd32(REG_TRACKER);   // First point
+            break;
+        case 1:
+            TrackRegisterVal = Rd32(REG_TRACKER_1); // Second point
+            break;
+        case 2:
+            TrackRegisterVal = Rd32(REG_TRACKER_2); // Third point
+            break;
+        case 3:
+            TrackRegisterVal = Rd32(REG_TRACKER_3); // Fourth point
+            break;
+        case 4:
+            TrackRegisterVal = Rd32(REG_TRACKER_4); // Fift point
+            break;
     }
+    return TrackRegisterVal & 0xffff;
+}
+
+uint8_t FT813::GetTag(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TAG);       // check if one of the tracking fields is touched
+    return TagRegisterVal & 0xff;
+}
+
+uint16_t FT813::GetTagX(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TAG_X);       // check if one of the tracking fields is touched
+    return TagRegisterVal & 0x7ff;
+}
+
+uint16_t FT813::GetTagY(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TAG_Y);       // check if one of the tracking fields is touched
+    return TagRegisterVal & 0x7ff;
+}
+
+uint8_t FT813::GetTouchTag(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TOUCH_TAG);       // check if one of the tracking fields is touched
+    return TagRegisterVal & 0xff;
+}
+
+uint16_t FT813::GetTouchTagX(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TOUCH_TAG_XY);       // check if one of the tracking fields is touched
+    return (TagRegisterVal >> 16) & 0xffff;
+}
+
+uint16_t FT813::GetTouchTagY(void)
+{
+    // REG_TOUCH_TAG
+    // If the screen is being touched, the screen coordinates are looked up in the screen's tag buffer,
+    // delivering a final 8-bit tag value, in REG_TOUCH_TAG.
+    // REG_TOUCH_TAG_XY 
+    // Because the tag lookup takes a full frame, and touch coordinates change continuously,
+    // the original (x; y) used for the tag lookup is also available in REG_TOUCH_TAG_XY.
+    uint32_t TagRegisterVal = Rd32(REG_TOUCH_TAG_XY);       // check if one of the tracking fields is touched
+    return TagRegisterVal & 0xffff;
+}
+
+uint16_t FT813::GetTouchConfig(void)
+{
+    // Read 0x0381
+    // 0000 0011 1000 0001
+    // bit 15 0: capacitive, 1: resistive
+    // bit 10 - 4: I2C address of touch screen module: 0x011 1000 0x38
+    // bit 3: 0: FocalTech, 1: Azoteq
+    // bit 1 - 0: sampler clocks 0x01
+    uint32_t TouchConfigVal = Rd32(REG_TOUCH_CONFIG);       // check if one of the tracking fields is touched
+    return TouchConfigVal & 0xffff;
+}
+
+void FT813::SetTouchConfig(uint16_t TouchConfigVal = VAL_TOUCH_CONFIG)
+{
+    Wr32(REG_TOUCH_CONFIG, (uint32_t) TouchConfigVal);
+}
+
+
+
+
+
+void FT813::screenShot(void)
+{
+    int bufferSize = 800*480;
+    char* pbuff = (char*)malloc(bufferSize);
     
-ft_uint32_t FT800::clear_color_rgb(ft_uint8_t red,ft_uint8_t green, ft_uint8_t blue){
-    return ((2UL<<24)|(((red)&255UL)<<16)|(((green)&255UL)<<8)|(((blue)&255UL)<<0));
-    }    
-    
\ No newline at end of file
+//    wr8(REG_SCREENSHOT_EN, 1);
+//    for (int ly = 0; ly < SCREEN_HEIGHT; ly++) {
+//     wr16(REG_SCREENSHOT_Y, ly);
+//     wr8(REG_SCREENSHOT_START, 1);
+//    
+//     //Read 64 bit registers to see if it is busy
+//     while (rd32(REG_SCREENSHOT_BUSY) | rd32(REG_SCREENSHOT_BUSY + 4));
+//    
+//     wr8(REG_SCREENSHOT_READ , 1);
+//     for (int lx = 0; lx < SCREEN_WIDTH; lx ++) {
+//    //Read 32 bit pixel value from RAM_SCREENSHOT
+//    //The pixel format is BGRA: Blue is in lowest address and Alpha
+//    is in highest address
+//    screenshot[ly*SCREEN_HEIGHT + lx] = rd32(RAM_SCREENSHOT + lx*4);
+//     }
+//     wr8(REG_SCREENSHOT_READ, 0);
+//    }
+//    wr8(REG_SCREENSHOT_EN, 0);
+
+    free(pbuff);
+}
\ No newline at end of file