808

Dependents:   Chromatograph_Mobile

src/FT_Hal_Utils.cpp

Committer:
nikmaos
Date:
2020-09-01
Revision:
13:5959af2ac87a
Parent:
10:6a81aeca25e3

File content as of revision 13:5959af2ac87a:

#include "FT_Platform.h"
#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 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);
//}

//int FT813::Load_raw(char* filename)
//{
//    ft_uint8_t imbuff[8192];
//    ft_uint16_t filesize;
//    ft_uint16_t blocklen;
////    ft_uint16_t ram_start = 0x00;
//    
////    sd.mount();  
//    FILE *fp = fopen(filename, "rb");   //  open file
////    if(fp == NULL) return (-1);       //  connot open file         
//    fseek(fp, 0, SEEK_END);             //  set file position to end of file
//    filesize= ftell(fp);                //  determine file size
//    fseek(fp, 2, SEEK_SET);             //  return to beginning of file       
//
//    while(filesize > 0)
//    {
//        //copy the .raw file data to imbuff[8192] in 8k block
//        blocklen = filesize>8192?8192:filesize;
//        fread(imbuff,1,blocklen,fp);
//        filesize-= blocklen;
//        //write imbuff contents to graphics RAM at address ram_start = 0x00
//        WrCmdBuf(imbuff, blocklen); //alignment is already taken care by this api
////        ram_start += 8192;   
//    }
//    fclose(fp);
////    sd.unmount();
//    
//    return 0;
//}

/* calibrate touch */
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 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 FT813::fadeout()
{
    ft_int32_t i;
    
    for (i = 100; i >= 0; i -= 3) 
    {
        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 FT813::fadein()
{
    ft_int32_t i;
    
    for (i = 0; i <=100 ; i += 3) 
    {
        Wr8(REG_PWM_DUTY,i);
        Sleep(2);//sleep for 2 ms
    }
    /* Finally make the PWM 100% */
    i = 128;
    Wr8(REG_PWM_DUTY,i);
}

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 < 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));
}

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;
}

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_SCREEN_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;
}

uint32_t FT813::GetTouchTagXY(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.
    return Rd32(REG_TOUCH_SCREEN_XY);       // check if one of the tracking fields is touched     
}

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);
    
//    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);
}