2.8 tft capacitive touch display

Adafruit Ethernet, Motor, Proto, Wave, Datalogger, GPS Shields - etc!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
JJAAWW
 
Posts: 15
Joined: Fri Mar 11, 2022 5:26 pm

2.8 tft capacitive touch display

Post by JJAAWW »

I've come across a program to display bmp to the display. I'm not able to get it to work
I've displayed the code below

Code: Select all

#include <SD.h>

#include "TFTv2.h"

#define MAX_BMP         25      // Maximum number of BMP files
#define FILENAME_LEN    16      // Maximum file name length

#define SKETCH "TFT_Mod1 / Rev2"

// Determine how a file will be displayed, sweeping the screen vertically:
#define DOWN 0           // display from top to bottom
#define UP   1           // display from bottom to top
#define IN   2           // display from top/bottom in to center
#define OUT  3           // display from center out to top/bottom

const int PIN_SD_CS = 4;           // pin of sd card

// Display pixel size, as defined in TFTv2.h
uint32_t DspHeight = MAX_Y + 1;
uint32_t DspWidth  = MAX_X + 1;
float    DspAr = (float)DspHeight / (float)DspWidth; // Aspect Ratio

// Specify the BMP file read buffer
#define BUFFPIXEL 400
uint8_t  SdBuffer[BUFFPIXEL * 3];  // Allow for color depth of 3 bytes/pixel
uint16_t PixelColor[MAX_X + 1];

// BMP File specifcations
uint16_t NumBmpFiles = 0;              // Number of BMP files
char BmpFiles[MAX_BMP][FILENAME_LEN];  // List of image files
char* fileName;                        // Current file on display
uint32_t fileSize;
uint32_t BmpImageOffset  = 0;          // Offset of image in the BMP file
uint32_t BmpHeight;                    // BMP image pixel height
uint32_t BmpWidth;                     // BMP image pixel width
uint8_t  BmpDepth;
File BmpFile;

// search root to find bmp file
void searchDirectory() {
    File root = SD.open("/");                       // root

    while (NumBmpFiles < MAX_BMP) {
        File entry =  root.openNextFile();
        if (!entry) {
            break;
        }

        if (!entry.isDirectory()) {
            String name = entry.name();
            int len = name.length();

            if (len >= 5 && len <= 12) {
                strcpy(BmpFiles[NumBmpFiles], name.c_str());
                name.toUpperCase();
                if (name.endsWith(".BMP")) {
                    NumBmpFiles++;
                }
            }
        }

        entry.close();
    }

    Serial.print("get ");
    Serial.print(NumBmpFiles);
    Serial.println(" files: ");

    for (int i = 0; i < NumBmpFiles; i++) {
        Serial.println(BmpFiles[i]);
    }

    Serial.println();
}

void setup() {
    Serial.begin(115200);
    Serial.println(F(SKETCH));

    pinMode(PIN_SD_CS, OUTPUT);

    Tft.TFTinit();

    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS);

    if (!SD.begin(PIN_SD_CS)) {
        Serial.println("SD failed!");
        while (1);                              // init fail, die here
    }

    Serial.println("SD OK!");

    searchDirectory();

    TFT_BL_ON;
}

void loop() {
    static int dirCtrl = UP;

    for (unsigned char i = 0; i < NumBmpFiles; i++) {
        fileName = BmpFiles[i];
        BmpFile = SD.open(fileName);

        if (!BmpFile) {
            Serial.print("didnt find image: ");
            Serial.println(fileName);
            break;
        }

        if (!bmpReadHeader(BmpFile)) {
            Serial.println("bad bmp");
            break;
        }

        bmpdraw(BmpFile, dirCtrl);
        BmpFile.close();
        dirCtrl = (dirCtrl + 1) % 4;
    }
}

/*********************************************/
// This procedure reads a bitmap and draws it to the screen
// its sped up by reading many pixels worth of data at a time
// instead of just one pixel at a time. Increasing the buffer takes
// more RAM but makes the drawing a little faster. 20 pixels' worth
// is probably a good place

// dir - DOWN: sweep top to bottom
// dir - UP:   sweep bottom to top
// dir - IN:   sweep from edge to center
// dir - OUT:  sweep from center to edge

void bmpdraw(File f, int my_dir) {
    /*
        Display the BMP file.

        If the image is narrower than the screen (BmpWidth < DspWidth),
        then center the display on the width.

        If the image is shorter than the display (BmpHeight < DspHeight),
        then center the image on the display height.

        If the image is wider than the screen (BmpWidth > DspWidth),
        then crop the image width from both sides.

        If the image is taller than the display (BmpHeight > DspHeight),
        then crop the image width from both top and bottom
    */
    int dir = my_dir == IN || my_dir == OUT ? UP : my_dir;

    // Compute scanline padding
    uint8_t padding = 0;
    uint16_t scanlinebytes = BmpWidth * BmpDepth;
    while ((scanlinebytes + padding) % 4 != 0) {
        padding++;
    }

    uint32_t time = millis();    // Milliseconds taken to display the image

    uint16_t offset_x = 0,       // Display Width Margin
             offset_y = 0;       // Display Height Margin

    float    skip = 1.0;         // Image Shrink Factor

    float    BmpAr = (float)BmpHeight / (float)BmpWidth; // Image Aspect Ratio
    bool     done_y = false;

    // First check to see if the image needs to shrink to fit onto the display:
    if (BmpWidth > DspWidth || BmpHeight > DspHeight) {
        if (BmpAr >= DspAr) {
            skip = (float)BmpHeight / (float)DspHeight;
            offset_x = (uint32_t)((float)DspWidth - (float)DspHeight / BmpAr) / 2;
        } else {
            skip = (float)BmpWidth / (float)DspWidth;
            offset_y = (uint32_t)((float)DspHeight - (float)DspWidth * BmpAr) / 2;
        }
    } else {
        if (BmpWidth < DspWidth) {
            offset_x = (DspWidth - BmpWidth) / 2;
        }
        if (BmpHeight < DspHeight) {
            offset_y = (DspHeight - BmpHeight) / 2;
        }
    }

    #if(1)
    Serial.print(F("\nFile: "));
    Serial.println(fileName);
    Serial.print(F("Size: "));
    Serial.println(fileSize);
    Serial.print(F("dir = "));
    switch (my_dir) {
        case UP:   {
                Serial.println(F("UP"));
                break;
            }
        case DOWN: {
                Serial.println(F("DOWN"));
                break;
            }
        case IN:   {
                Serial.println(F("IN"));
                break;
            }
        case OUT:  {
                Serial.println(F("OUT"));
                break;
            }
    }
    #endif

    #if(1)
    Serial.print(F("padding: "));
    Serial.println(padding);

    Serial.print(F("DspWidth, DspHeight = "));
    Serial.print(DspWidth);
    Serial.print(F(", "));
    Serial.println(DspHeight);

    Serial.print(F("BmpDepth = "));
    Serial.println(BmpDepth);

    Serial.print(F("BmpWidth, BmpHeight = "));
    Serial.print(BmpWidth);
    Serial.print(F(", "));
    Serial.println(BmpHeight);

    Serial.print(F("BmpAr, DspAr = "));
    Serial.print(BmpAr);
    Serial.print(F(", "));
    Serial.println(DspAr);

    Serial.print(F("skip = "));
    Serial.println(skip);

    Serial.print(F("offset_x, offset_y = "));
    Serial.print(offset_x);
    Serial.print(F(", "));
    Serial.println(offset_y);
    #endif

    uint16_t ydn = DspHeight - 1,
             yup = 0;

    float    fx = 0.0,
             fyup = 0.0,
             fydn = (float)BmpHeight - 1;

    if (my_dir == OUT) {
        yup = ydn = DspHeight / 2;
        fyup = fydn = (float)BmpHeight / 2;
    }

    // Sweep the display vertically (up or down)
    for (uint16_t y = 0; y <= DspHeight; y++) {
        if (my_dir == IN || my_dir == OUT) {
            dir = 1 - dir;
        }

        // Prefill the pixel colors with the background color (black in this case):
        memset(PixelColor, 0, DspWidth * sizeof(*PixelColor)); // Fill background black

        // Display_image is true if the vertical sweep is withing the image boundaries:
        bool display_image;

        switch (my_dir) {
            case UP:
            case DOWN:
                display_image = y >= offset_y && y <= DspHeight - 1 - offset_y;
                break;
            case IN:
                display_image = yup >= offset_y && ydn <= DspHeight - 1 - offset_y;
                break;
            case OUT:
                display_image = ydn >= offset_y && yup <= DspHeight - 1 - offset_y;
        }

        // Don't gather image pixels if we're not within the image boundaries.
        if (display_image) {
            bool done_x = false;
            uint32_t i = (dir == UP ? (uint32_t)(fyup + 0.5) : (uint32_t)(fydn - 0.5));
            uint32_t r = BmpImageOffset + (BmpHeight - i - 1) * (BmpWidth * BmpDepth + padding);
  // Sweep the image horizontally
            BmpFile.seek(r);

            for (uint16_t h = 0, i = 0; !done_x; h += BUFFPIXEL) {
                uint16_t size = BUFFPIXEL;
                fx = 0.0;

                if (h + size >= BmpWidth) {
                    size = BmpWidth - h;
                    done_x = true;
                }

                BmpFile.read(SdBuffer, size * BmpDepth);

                for (uint16_t p = 0; p < size && fx + skip < (float)size; i++, p++) {
                    fx += skip;
                    uint16_t buffidx = BmpDepth * ((uint16_t)fx);
                    uint16_t x = i + offset_x;

                    switch (BmpDepth) {
                        case 1:
                            PixelColor[x] = SdBuffer[buffidx] >> 3;                     // red
                            PixelColor[x] = PixelColor[x] << 6 | (SdBuffer[buffidx] >> 2); // green
                            PixelColor[x] = PixelColor[x] << 5 | (SdBuffer[buffidx] >> 3); // blue
                            break;
                        case 3:
                            PixelColor[x] = SdBuffer[buffidx + 2] >> 3;                   // red
                            PixelColor[x] = PixelColor[x] << 6 | (SdBuffer[buffidx + 1] >> 2); // green
                            PixelColor[x] = PixelColor[x] << 5 | (SdBuffer[buffidx + 0] >> 3); // blue
                            break;
                    }
                }
            }

            if (dir == DOWN) {
                fydn -= skip;
            } else {
                fyup += skip;
            }
        }

        Tft.setCol(0, DspWidth);

        if (dir == UP) {
            Tft.setPage(yup, yup);
            yup++;
        } else {
            Tft.setPage(ydn, ydn);
            ydn--;
        }

        Tft.sendCMD(0x2c);

        TFT_DC_HIGH;
        TFT_CS_LOW;

        for (int m = 0; m < DspWidth; m++) {
            SPI.transfer(PixelColor[m] >> 8);
            SPI.transfer(PixelColor[m]);
        }

        TFT_CS_HIGH;
    }

    float time_sec = (millis() - time) / 1000.0;
    Serial.print(time_sec);
    Serial.println(F(" seconds"));
}

boolean bmpReadHeader(File f) {
    // read header
    uint32_t tmp;

    if (read16(f) != 0x4D42) {
        Serial.println(F("Incorrect BMP file signature"));
        return false;
    }

    // read file size
    fileSize = read32(f);

    // read and ignore creator bytes
    read16(f);
    read16(f);

    BmpImageOffset = read32(f);

    // read DIB header
    tmp = read32(f);
    BmpWidth  = read32(f);
    BmpHeight = read32(f);

    if (read16(f) != 1) {
        Serial.println("Planes != 1");
        return false;
    }

    BmpDepth = read16(f) / 8; // Bytes / Pixel
    if (BmpDepth != 1 && BmpDepth != 3) {
        Serial.println(F("Unsupported color depth"));
        return false;
    }

    if (read32(f) != 0) {
        Serial.println(F("compression not supported!"));
        return false;
    }

    return true;
}

/*********************************************/
// These read data from the SD card file and convert them to big endian
// (the data is stored in little endian format!)

// LITTLE ENDIAN!
uint16_t read16(File f) {
    uint16_t d;
    uint8_t b;
    b = f.read();
    d = f.read();
    d <<= 8;
    d |= b;
    return d;
}

// LITTLE ENDIAN!
uint32_t read32(File f) {
    uint32_t d;
    uint16_t b;
    b = read16(f);
    d = read16(f);
    d <<= 16;
    d |= b;
    return d;
}
Last edited by adafruit_support_carter on Thu Mar 24, 2022 3:29 pm, edited 1 time in total.
Reason: added [code] tags

User avatar
adafruit_support_carter
 
Posts: 29168
Joined: Tue Nov 29, 2016 2:45 pm

Re: 2.8 tft capacitive touch display

Post by adafruit_support_carter »

Is this the TFT display you are using?
https://www.adafruit.com/product/2090

Where did that code example come from?

User avatar
JJAAWW
 
Posts: 15
Joined: Fri Mar 11, 2022 5:26 pm

Re: 2.8 tft capacitive touch display

Post by JJAAWW »

no i'm not using that touchscreen and the code came from i think adafruit or arduino

User avatar
adafruit_support_carter
 
Posts: 29168
Joined: Tue Nov 29, 2016 2:45 pm

Re: 2.8 tft capacitive touch display

Post by adafruit_support_carter »

Which display are you using? Can you link to the product page.

User avatar
JJAAWW
 
Posts: 15
Joined: Fri Mar 11, 2022 5:26 pm

Re: 2.8 tft capacitive touch display

Post by JJAAWW »

here is the link to the display that i am using

https://learn.adafruit.com/adafruit-2-8 ... 2/overview

User avatar
adafruit_support_carter
 
Posts: 29168
Joined: Tue Nov 29, 2016 2:45 pm

Re: 2.8 tft capacitive touch display

Post by adafruit_support_carter »

Does the bitmap example from that guide work?
https://learn.adafruit.com/adafruit-2-8 ... ng-bitmaps

User avatar
JJAAWW
 
Posts: 15
Joined: Fri Mar 11, 2022 5:26 pm

Re: 2.8 tft capacitive touch display

Post by JJAAWW »

the graphictest works but i cant display more than 2 bmp

User avatar
adafruit_support_carter
 
Posts: 29168
Joined: Tue Nov 29, 2016 2:45 pm

Re: 2.8 tft capacitive touch display

Post by adafruit_support_carter »

If you want to do that with this library:

Code: Select all

#include "TFTv2.h"
you'll need to contact the maintainers of that library.

For the ImageReader library:
https://github.com/adafruit/Adafruit_ImageReader
you can call drawBMP() for each BMP file you want to display. For example, see how four copies of the parrot.bmp are being shown here:
https://github.com/adafruit/Adafruit_Im ... 1.ino#L127
It doesn't have to be four copies of the same file. Can call it separately for each BMP file.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino Shields from Adafruit”