STM32F103C8 & TFT (ili9325)

Working libraries, libraries being ported and related hardware
stevestrong
Posts: 1813
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: STM32F103C8 & TFT (ili9325)

Post by stevestrong » Thu Jul 20, 2017 9:29 pm

OK, so if graphicstest runs well, setAddressWndow() sould also be ok, then it most probably has to do with the BMP example.

Better said, a function involved by the BMP example, but not involved in graphicstest, is probably the reason.

golpesar132
Posts: 24
Joined: Mon Jul 10, 2017 1:42 pm

Re: STM32F103C8 & TFT (ili9325)

Post by golpesar132 » Thu Jul 20, 2017 9:34 pm

stevestrong wrote:
Thu Jul 20, 2017 9:29 pm
OK, so if graphicstest runs well, setAddressWndow() sould also be ok, then it most probably has to do with the BMP example.

Better said, a function involved by the BMP example, but not involved in graphicstest, is probably the reason.
which function for example???

david.prentice
Posts: 112
Joined: Wed Nov 16, 2016 8:52 am

Re: STM32F103C8 & TFT (ili9325)

Post by david.prentice » Thu Jul 20, 2017 11:11 pm

Adafruit_TFTLCD_STM is not installed with the Core. And is not available from the Library Manager.

Post a link to the actual library you are using. And either say which example you are using or attach your actual showBMP sketch.

The regular Adafruit graphicstest sketch does not test the pushColors() method. But it is easy enough to write your own test.
But the most important first step is: study the graphicstest sketch carefully. Make notes about any wrong colours or bad shapes.

It is important that Adafruit or any library author gets feedback when there is a problem. However small.
You may want other members to replicate your problem before contacting a big company. It is only polite and they will take more notice of a group of users.

David.

golpesar132
Posts: 24
Joined: Mon Jul 10, 2017 1:42 pm

Re: STM32F103C8 & TFT (ili9325)

Post by golpesar132 » Fri Jul 21, 2017 6:23 am

I use this library:
https://github.com/stevstrong/Adafruit_ ... 8bit_STM32

and this is my code:

Code: Select all

// BMP-loading example specifically for the TFTLCD breakout board.
// If using the Arduino shield, use the tftbmp_shield.pde sketch instead!
// If using an Arduino Mega make sure to use its hardware SPI pins, OR make
// sure the SD library is configured for 'soft' SPI in the file Sd2Card.h.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD_8bit_STM32.h> // Hardware-specific library



#include <SD.h>
#include <SPI.h>

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS PA3 // Chip Select goes to Analog 3
#define LCD_CD PA2 // Command/Data goes to Analog 2
#define LCD_WR PA1 // LCD Write goes to Analog 1
#define LCD_RD PA0 // LCD Read goes to Analog 0

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).

// For Arduino Uno/Duemilanove, etc
//  connect the SD card with DI going to pin 11, DO going to pin 12 and SCK going to pin 13 (standard)
//  Then pin 10 goes to CS (or whatever you have set up)
#define SD_CS PA4     // Set the chip select line to whatever you use (10 doesnt conflict with the library)

// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
// There are examples in the sketch folder

// our TFT wiring
/*
extern Adafruit_TFTLCD_8bit_STM32 TFT;
#define tft TFT
*/
Adafruit_TFTLCD_8bit_STM32 tft;


void setup()
{
  afio_cfg_debug_ports(AFIO_DEBUG_NONE);
  Serial.begin(115200);
  while ( !Serial.isConnected() ) ;
  tft.reset();

  uint16_t identifier = tft.readID();

  if(identifier == 0x9325) {
    Serial.println(F("Found ILI9325 LCD driver"));
  } else if(identifier == 0x9328) {
    Serial.println(F("Found ILI9328 LCD driver"));
  } else if(identifier == 0x7575) {
    Serial.println(F("Found HX8347G LCD driver"));
  } else if(identifier == 0x9341) {
    Serial.println(F("Found ILI9341 LCD driver"));
  } else if(identifier == 0x8357) {
    Serial.println(F("Found HX8357D LCD driver"));
  } else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    Serial.println(F("If using the Adafruit 2.8\" TFT Arduino shield, the line:"));
    Serial.println(F("  #define USE_ADAFRUIT_SHIELD_PINOUT"));
    Serial.println(F("should appear in the library header (Adafruit_TFT.h)."));
    Serial.println(F("If using the breakout board, it should NOT be #defined!"));
    Serial.println(F("Also if using the breakout, double-check that all wiring"));
    Serial.println(F("matches the tutorial."));
    return;
  }

  tft.begin(identifier);

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

  bmpDraw("normal.bmp", 0, 0);
  delay(1000);
}

void loop()
{
  for(int i = 0; i<4; i++) {
    tft.setRotation(i);
    tft.fillScreen(0);
    for(int j=0; j <= 200; j += 50) {
      bmpDraw("miniwoof.bmp", j, j);
    }
    delay(1000);
  }
}

// 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, int x, int 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 in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixel out buffer (16-bit 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();
  uint8_t  lcdidx = 0;
  boolean  first = true;

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

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

  // Parse BMP header
  if(read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.println(F("File size: ")); Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: ")); Serial.println(bmpImageoffset, DEC);
    // Read DIB header
    Serial.print(F("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(F("Bit Depth: ")); Serial.println(bmpDepth);
      if((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed

        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("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 column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if(lcdidx > 0) {
                tft.pushColors(lcdbuffer, lcdidx, first);
                lcdidx = 0;
                first  = false;
              }
              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx++] = tft.color565(r,g,b);
          } // end pixel
        } // end scanline
        // Write any remaining data to LCD
        if(lcdidx > 0) {
          tft.pushColors(lcdbuffer, lcdidx, first);
        } 
        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");
      } // end goodBmp
    }
  }

  bmpFile.close();
  if(!goodBmp) Serial.println(F("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 don't have any problem with the graphicstest example functions.
The regular Adafruit graphicstest sketch does not test the pushColors() method. But it is easy enough to write your own test.
But the most important first step is: study the graphicstest sketch carefully. Make notes about any wrong colours or bad shapes.
how could I test it??

david.prentice
Posts: 112
Joined: Wed Nov 16, 2016 8:52 am

Re: STM32F103C8 & TFT (ili9325)

Post by david.prentice » Fri Jul 21, 2017 3:38 pm

I installed Steve's library and modified for my GPIO usage.

Steve's library only works with the Maple Core. Not with the ST Core.

Anyway, Steve's library code for pushColors() and setWindow() looks absolutely fine.
Here is a test sketch to prove it (tested on a BluePill):

Code: Select all

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD_8bit_STM32.h> // Hardware-specific library

Adafruit_TFTLCD_8bit_STM32 tft;

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

void setup(void) {
    afio_cfg_debug_ports(AFIO_DEBUG_NONE);
    Serial.begin(9600);
    while ( !Serial.isConnected() ) ;
    delay(1000);

    Serial.println(F("pushColors() test"));

    tft.reset();
    uint16_t ID = tft.readID();
    //  ID = 0x9325;
    Serial.print(F("ID = 0x"));
    Serial.println(ID, HEX);
    tft.begin(ID);
    tft.fillScreen(BLACK);
    tft.setTextColor(YELLOW, BLACK);
    tft.setTextSize(2);
}

uint16_t scrollbuf[320];    // Adafruit only does 240x320
// Adafruit can read a block by one pixel at a time
int16_t  READGRAM(int16_t x, int16_t y, uint16_t *block, int16_t w, int16_t h)
{
    uint16_t *p;
    for (int row = 0; row < h; row++) {
        p = block + row * w;
        for (int col = 0; col < w; col++) {
            *p++ = tft.readPixel(x + col, y + row);
        }
    }
}

void windowScroll(int16_t x, int16_t y, int16_t wid, int16_t ht, int16_t dx, int16_t dy, uint16_t *buf)
{
    if (dx) for (int16_t row = 0; row < ht; row++) {
            READGRAM(x, y + row, buf, wid, 1);
            tft.setAddrWindow(x, y + row, x + wid - 1, y + row);
            tft.pushColors(buf + dx, wid - dx, 1);
            tft.pushColors(buf + 0, dx, 0);
        }
    if (dy) for (int16_t col = 0; col < wid; col++) {
            READGRAM(x + col, y, buf, 1, ht);
            tft.setAddrWindow(x + col, y, x + col, y + ht - 1);
            tft.pushColors(buf + dy, ht - dy, 1);
            tft.pushColors(buf + 0, dy, 0);
        }
}

void loop()
{
    int wid = tft.width(), n;
    tft.setCursor(0, 200);
    tft.print("SOFTWARE SCROLL    ");
    // scroll a whole width of the screen
    n = (wid > 320) ? 320 : wid;
    for (int16_t i = n, dx = 4, dy = 0; i > 0; i -= dx) {
        windowScroll(0, 200, n, 16, dx, dy, scrollbuf);
    }
    delay(5000);
}
I ran your showBMP() sketch with MCUFRIEND_kbv on a Nucleo which works fine too.
Unfortunately, my wiring was not convenient for SD and Steve's library.

I suggest that you re-install Steve's library and try again. Perhaps Steve will run your showBMP sketch.

David.

golpesar132
Posts: 24
Joined: Mon Jul 10, 2017 1:42 pm

Re: STM32F103C8 & TFT (ili9325)

Post by golpesar132 » Fri Jul 21, 2017 4:42 pm

what must be the output of your code?? It is a text that change position and change color to yellow and blue??

How can I use MCUFRIEND_kbv library?? How is its wiring??

david.prentice
Posts: 112
Joined: Wed Nov 16, 2016 8:52 am

Re: STM32F103C8 & TFT (ili9325)

Post by david.prentice » Fri Jul 21, 2017 9:38 pm

You have a regular Uno Shield. Plug it into a Uno.
Install MCUFRIEND_kbv with the Library Manager. Run the examples.
You will see what "SOFTWARE SCROLL" does on the Uno.

The YELLOW text moves across the screen. There should not be any BLUE at all.

I am sure that Steve's library will work just fine on the STM32.
If Steve's examples work, so should any other sketches.

MCUFRIEND_kbv works out of the box on a NUCLEO-F103 or NUCLEO-L476
MCUFRIEND_kbv expects the data bus on PA0..PA7. Control signals on PB5..PB9 for a BLUEPILL

I could post you an MCUFRIEND_kbv SPECIAL that matches Steve's wiring, but I suggest that you continue with Steve's Library. e.g. re-install.

David.

golpesar132
Posts: 24
Joined: Mon Jul 10, 2017 1:42 pm

Re: STM32F103C8 & TFT (ili9325)

Post by golpesar132 » Sun Jul 23, 2017 2:58 pm

Thank you. I did it use Steve's library.

golpesar132
Posts: 24
Joined: Mon Jul 10, 2017 1:42 pm

Re: STM32F103C8 & TFT (ili9325)

Post by golpesar132 » Sun Jul 23, 2017 6:54 pm

If we use that bmp show example, the speed will be really low. is there any way to increase the speed. for example if we save the image in an array and use drawbitmap(), the image will be shown immediately. is there any way to show an image from SD card, fast like that???

stevestrong
Posts: 1813
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: STM32F103C8 & TFT (ili9325)

Post by stevestrong » Mon Jul 24, 2017 11:32 am

I am almost sure that I tested the BMP example reading a file from SD card, but I will check it again.

Post Reply