# Bitmap tft 1.8 128\*160

**URL:** <https://community.particle.io/t/bitmap-tft-1-8-128-160/47598>\
**Category:** Troubleshooting\
**Tags:** photon\
**Created:** [February 6, 2019, 11:47pm UTC](https://community.particle.io/t/bitmap-tft-1-8-128-160/47598 "2019-02-06T23:47:52Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![utlaiotlabelectronic](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/utlaiotlabelectronic/32/18988_2.png) [@utlaiotlabelectronic](https://community.particle.io/u/utlaiotlabelectronic)\
**Post date:** [February 6, 2019, 11:47pm UTC](https://community.particle.io/t/bitmap-tft-1-8-128-160/47598/1 "2019-02-06T23:47:52Z")

</div>

hello, could anyone help me with a code to show images in bitmap ?, I'm working with a Chinese tft lcd 1.8 128x160 v1.1 , due to it has the ST7735 driver and it works very well for me when I use the Adafruit libraries in arduino  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/c/2/c25c3bcb21921296bcb944cd8e8477ae3c926ec4.jpg)

but when i was compiling the program I got the following error:  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/f/e/fe4ea967192058d43edcafe34f9a007c42005e59.png)

the code is:

```auto
// This #include statement was automatically added by the Particle IDE.
#include <sd-card-library.h>

// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_ST7735.h>
// This #include statement was automatically added by the Particle IDE.
#include <Adafruit_GFX.h>

// TFT display and SD card will share the hardware SPI interface.
// Hardware SPI pins are specific to the Arduino board type and
// cannot be remapped to alternate pins. For Arduino Uno,
// Duemilanove, etc., pin 11 = MOSI, pin 12 = MISO, pin 13 = SCK.
#define cs A2
#define dc A1
#define rst A0 

#define sdcs D4 // Chip select line for SD card

//Use this reset pin for the shield!
//#define TFT_RST 0 // you can also connect this to the Arduino reset!

Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst); // hardware spi

void setup(void) {
  Serial.begin(9600);

  // Use this initializer if you're using a 1.8" TFT
  tft.initR(INITR_BLACKTAB);

  // Use this initializer (uncomment) if you're using a 1.44" TFT
  //tft.initR(INITR_144GREENTAB);

  Serial.print("Initializing SD card...");
  if (!SD.begin(sdcs)) {
    Serial.println("failed!");
    return;
  }
  Serial.println("OK!");
  

  // change the name here!
  bmpDraw("Particle.bmp", 0, 0);
  // wait 5 seconds
  delay(5000);
 
}

void loop() {
// uncomment these lines to draw bitmaps in different locations/rotations!
/*
  tft.fillScreen(ST7735_BLACK); // Clear display
  for(uint8_t i=0; i<4; i++) // Draw 4 parrots
    bmpDraw("parrot.bmp", tft.width() / 4 * i, tft.height() / 4 * i);
  delay(1000);
  tft.setRotation(tft.getRotation() + 1); // Inc rotation 90 degrees
*/
 
// change the name here!
  bmpDraw("Photon.bmp", 0, 0);
  // wait 5 seconds
  delay(5000);  
  
// change the name here!
  bmpDraw("ruina.bmp", 0, 0);
  // wait 5 seconds
    delay(5000);
    
// change the name here!
  bmpDraw("yo.bmp", 0, 0);
  // wait 5 seconds
    delay(5000);
    
  // change the name here!
  bmpDraw("calendar.bmp", 0, 0);
  // wait 5 seconds
  delay(5000);
  
}

// This function opens a Windows Bitmap (BMP) file and
// displays it at the given coordinates. It's sped up
// by reading many pixels worth of data at a time
// (rather than pixel by pixel). Increasing the buffer
// size takes more of the Arduino's precious RAM but
// makes loading a little faster. 20 pixels seems a
// good balance.

#define BUFFPIXEL 20

void bmpDraw(char *filename, uint8_t x, uint8_t y) {

  File bmpFile;
  int bmpWidth, bmpHeight; // W+H in pixels
  uint8_t bmpDepth; // Bit depth (currently must be 24)
  uint32_t bmpImageoffset; // Start of image data in file
  uint32_t rowSize; // Not always = bmpWidth; may have padding
  uint8_t sdbuffer[3*BUFFPIXEL]; // pixel buffer (R+G+B per pixel)
  uint8_t buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean goodBmp = false; // Set to true on valid header parse
  boolean flip = true; // BMP is stored bottom-to-top
  int w, h, row, col;
  uint8_t r, g, b;
  uint32_t pos = 0, startTime = millis();

  if((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print("Loading image '");
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = SD.open(filename)) == NULL) {
    Serial.print("File not found");
    return;
  }

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.print("File size: "); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print("Image Offset: "); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print("Header size: "); Serial.println(read32(bmpFile));
    bmpWidth = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    if(read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print("Bit Depth: "); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print("Image size: ");
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if(bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if((x+w-1) >= tft.width()) w = tft.width() - x;
        if((y+h-1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds
        tft.setAddrWindow(x, y, x+w-1, y+h-1);

        for (row=0; row<h; row++) { // For each scanline...

          // Seek to start of scan line. It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding. Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if(flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if(bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col=0; col<w; col++) { // For each pixel...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format, push to display
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            tft.pushColor(tft.Color565(r,g,b));
          } // end pixel
        } // end scanline
        Serial.print("Loaded in ");
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println("BMP format not recognized.");
}

// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

```

I tried to modify the code in the link, however i have been the same error

> [@On-going problems with cheap ST7735 TFT displays](https://community.particle.io/t/on-going-problems-with-cheap-st7735-tft-displays/16317):
>
> Continuing the discussion from [[SOLVED] Getting the ST7735 to work with Spark](https://community.particle.io/t/solved-getting-the-st7735-to-work-with-spark/11392/33): I have to come back to this as this is frustrating the hell out of me and I think I have tried all the suggested things in the original thread. Like @apassemard in the original thread I purchased 3 1.8inch TFT SPI displays which use the ST7735 display controller. I had originally bought an adafruit 1.8 TFT with microSD card module and have experienced some intermittent issues (white screen). All had settled down an…

---

<div class="post-metadata">

**Author:** ![armor](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/armor/32/18398_2.png) [@armor](https://community.particle.io/u/armor)\
**Post date:** [February 7, 2019, 9:31am UTC](https://community.particle.io/t/bitmap-tft-1-8-128-160/47598/2 "2019-02-07T09:31:36Z")

</div>

The compile issue is the first to fix. You are missing a few things to make the SD card reading work.

Instead of sd-card-library I would use this library  
`#include <SdFat.h>` v1.0.16

You need to create the SdFat object  
`SdFat sd;`

Although you have a SD.begin() you have not specified the SPI bus speed. In my experience the SD.begin() is time critical after startup and needs to be put at the very start of setup(). The SPI\_HALF\_SPEED runs the SPI bus at half of 60MHz which is plenty for the small screen. You also need to ensure the TFT controller which is using the same SPI bus is set to run at SPI\_HALF\_SPEED. I use my own version of the Adafruit\_ST7735 library - you will need to check in the library code for the SPI.begin();

`sd.begin(sdcs, SPI_HALF_SPEED)`

I could suggest another couple of changes.

`void bmpDraw(const char * filename, uint16_t x, uint16_t y)`

And the test for file existing  
if (bmpFile.open(filename, O\_READ))

I haven’t had any display issues for the last couple of years. Good luck.

---

<div class="post-metadata">

**Author:** ![utlaiotlabelectronic](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/utlaiotlabelectronic/32/18988_2.png) [@utlaiotlabelectronic](https://community.particle.io/u/utlaiotlabelectronic)\
**Post date:** [February 7, 2019, 12:23pm UTC](https://community.particle.io/t/bitmap-tft-1-8-128-160/47598/3 "2019-02-07T12:23:02Z")

</div>

thank you I will try to make the suggested changes and then I will tell you
