Go Down

Topic: [Bug?] read an image from SD card and draw it on TFT (Read 843 times) previous topic - next topic

NSmit

Hello Forum,

I have developed a code to read an image stored on my SD Card and display it on a TFT. I can read the image from the SD Card successfully but I cannot draw it on the TFT. I dunno where is the bug.
Could you please guys help me figure it out?

Board: Arduino DUE

Code: [Select]

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

#include "ascii_data.h"

#define SERIAL_PORT 9600

#define PIN_SCE 10
#define PIN_RESET 6
#define PIN_DC 5
// #define PIN_SDIN
// #define PIN_SCLK
#define PIN_LED 2

#define LCD_COMMAND LOW
#define LCD_DATA HIGH
#define CHAR_WIDTH 6
#define CHAR_HEIGHT 8
#define LCD_WIDTH 84
#define LCD_HEIGHT 48
#define CHARS_PER_ROW (LCD_WIDTH / CHAR_WIDTH)
#define CHARS_PER_COL (LCD_HEIGHT / CHAR_HEIGHT)

#define PIN_SCSD 4

void draw();
void reset();
void cls();
void lcdMode(int mode);
void lcdInitialize();
void printString(int y, const char *value);
void printString(int x, int y, const char *value);
int printChar(int x, int y, char value);
void setPixel(int x, int y, int value);
void lcdWrite(int value);

byte data[84][6] = {0};

String input = "";
bool complete = false;

// ----------------------------------------------------------------------------

void setup()
{
  // Enable I/O stream
  Serial.begin(SERIAL_PORT);
  Serial.println("Serial Init..");

  // pin modes
  pinMode(PIN_SCE, OUTPUT);
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_SCSD, OUTPUT);

  // SD stuff
  SD.begin(PIN_SCSD);

  // display stuff
  reset();

  SPI.begin(PIN_SCE);
  SPI.setClockDivider(PIN_SCE, SPI_CLOCK_DIV16);

  lcdInitialize();

  input.reserve(200);

  printChar(0, 0, 'a');
}

void loop()
{
  while (Serial.available() > 0) {
    char ch = (char)Serial.read();
    //Serial.print(ch);
    if (isprint(ch) && ch != '\n') {
      input += ch;
      //Serial.println(input);
    }
    else {
      complete = true;
    }
  }

  if (complete) {
    Serial.print("Command: ");
    Serial.println(input);

    //Serial.println(input.startsWith("exists(") && input.endsWith(")"));

    if (input.startsWith("exists(") && input.endsWith(")")) {
      String file = input.substring(7, input.length() - 1);

      Serial.print("File: ");
      Serial.println(file);

      File f = SD.open(file);
      if (f) {
        Serial.println("File does exists");
        f.close();
      } else {
        Serial.println("File does not exist");
      }

    } else if (input.startsWith("print(") && input.endsWith(".img)")) {
      String file = input.substring(6, input.length() - 1);
      File f = SD.open(file);
      if (f) {
        cls();

        Serial.print("Printing image: ");
        // Dimensionen auslesen
        int width = 0;
        int height = 0;

        char ch = '\0';
        String dim = "";

        while (f.available()) {
          ch = (char)f.read();

          if (ch != ',' && ch != '\n')
            dim += ch;
          else {
            if (width == 0) {
              width = dim.toInt();
              dim = "";
            } else if (height == 0) {
              height = dim.toInt();
            }

            if (ch == '\n') {
              break;
            }
          }
        }

        Serial.print("Dimensions of image: ");
        Serial.print(width);
        Serial.print(" x ");
        Serial.println(height);

        for (int i = 0; i < height; ++i) {
          for (int x = 0; x < width; ++x){
            char ch = '\0';
            while (ch != '\n') {
              ch = f.read();
              if (ch == ','){
                continue;
              }else (ch == '0' || ch == '1') {
                int pix = ch - '0';
                setPixel(x, i, pix);
              }
            }
          }
        }
      }

    } else if (input.startsWith("print(") && input.endsWith(")")) {
      String file = input.substring(6, input.length() - 1);
      File f = SD.open(file);
      if (f) {
        cls();

        int x = 0;
        int y = 0;
        Serial.print("Printing: ");
        while (f.available()) {
          char ch = (char)f.read();
          Serial.print(ch);
          if (-1 == printChar(x, y, ch));

          draw();

          x = (x + 6) % 84;
          if (x == 0) {
            y = (y + 8) % 48;
          }
        }
        Serial.println();



      } else {
        Serial.println("Error: File does not exist");
      }


    } else {
      Serial.println("Unknown command");
    }

    complete = false;
    input = "";
  }

  draw();

  delay(10);

}

// ----------------------------------------------------------------------------

void draw()
{
  lcdMode(LCD_DATA);

  for (int b = 0; b < 6; ++b) {
    for (int x = 0; x < 84; ++x) {
      lcdWrite(data[x][b]);
    }
  }
}

void reset()
{
  digitalWrite(PIN_RESET, LOW);
  delay(500);
  digitalWrite(PIN_RESET, HIGH);
}

void cls()
{
  for (int x = 0; x < LCD_WIDTH; ++x) {
    for (int y = 0; y < LCD_HEIGHT; ++y) {
      setPixel(x, y, 0);
    }
  }
}

void lcdMode(int mode)
{
  digitalWrite(PIN_DC, mode);
}

void lcdInitialize()
{
  lcdMode(LCD_COMMAND);

  // FUNCTION SET (extended instruction set)
  lcdWrite(0x21);

  // SET BIAS
  lcdWrite(0x14);

  // SET TEMP COEFFICIENT
  lcdWrite(0x04);

  // SET CONTRAST
  lcdWrite(0xBF);

  // FUNCTION SET (normal instruction set)
  lcdWrite(0x20);

  // SET DISPLAY MODE (normal)
  lcdWrite(0x0C);

  // reset display
  lcdWrite(0x40);
  lcdWrite(0x80);
}

void printString(int y, const char *value)
{
  printString((84 - strlen(value) * 6) / 2, y, value);
}

void printString(int x, int y, const char *value)
{
  do
  {
    printChar(x, y, *value);
    x += 6;
  } while (*++value != '\0');
}

int printChar(int x, int y, char value)
{
  lcdMode(LCD_DATA);

  if (value < ' ') {
    return -1;
  }

  for (int dx = 0; dx < 6; ++dx) {
    for (int dy = 0; dy < 8; ++dy) {
      setPixel(x + dx, y + dy, !!(font[value - ' '][dx] & (1 << dy)));
    }
  }

  return 0;
}

void setPixel(int x, int y, int value)
{
  if (x >= 0 && x < 84 && y >= 0 && y < 48) {
    if (value) {
      data[x][y / 8] |= (1 << (y % 8));
    } else {
      data[x][y / 8] &= ~(1 << (y % 8));
    }
  }
}

void lcdWrite(int value)
{
  digitalWrite(PIN_SCE, LOW);
  SPI.transfer(PIN_SCE, value, SPI_CONTINUE);
  digitalWrite(PIN_SCE, HIGH);
}





chucktodd

#1
Sep 25, 2016, 07:21 pm Last Edit: Sep 25, 2016, 07:24 pm by chucktodd Reason: code error
Hello Forum,

I have developed a code to read an image stored on my SD Card and display it on a TFT. I can read the image from the SD Card successfully but I cannot draw it on the TFT. I dunno where is the bug.
Could you please guys help me figure it out?

Board: Arduino DUE

Code: [Select]

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

#include "ascii_data.h"

#define SERIAL_PORT 9600

#define PIN_SCE 10
#define PIN_RESET 6
#define PIN_DC 5
// #define PIN_SDIN
// #define PIN_SCLK
#define PIN_LED 2

#define LCD_COMMAND LOW
#define LCD_DATA HIGH
#define CHAR_WIDTH 6
#define CHAR_HEIGHT 8
#define LCD_WIDTH 84
#define LCD_HEIGHT 48
#define CHARS_PER_ROW (LCD_WIDTH / CHAR_WIDTH)
#define CHARS_PER_COL (LCD_HEIGHT / CHAR_HEIGHT)

#define PIN_SCSD 4

void draw();
void reset();
void cls();
void lcdMode(int mode);
void lcdInitialize();
void printString(int y, const char *value);
void printString(int x, int y, const char *value);
int printChar(int x, int y, char value);
void setPixel(int x, int y, int value);
void lcdWrite(int value);

byte data[84][6] = {0};

String input = "";
bool complete = false;

// ----------------------------------------------------------------------------

void setup()
{
  // Enable I/O stream
  Serial.begin(SERIAL_PORT);
  Serial.println("Serial Init..");

  // pin modes
  pinMode(PIN_SCE, OUTPUT);
  pinMode(PIN_RESET, OUTPUT);
  pinMode(PIN_DC, OUTPUT);
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_SCSD, OUTPUT);

  // SD stuff
  SD.begin(PIN_SCSD);

  // display stuff
  reset();

  SPI.begin(PIN_SCE);
  SPI.setClockDivider(PIN_SCE, SPI_CLOCK_DIV16);

  lcdInitialize();

  input.reserve(200);

  printChar(0, 0, 'a');
}

void loop()
{
  while (Serial.available() > 0) {
    char ch = (char)Serial.read();
    //Serial.print(ch);
    if (isprint(ch) && ch != '\n') {
      input += ch;
      //Serial.println(input);
    }
    else {
      complete = true;
    }
  }

  if (complete) {
    Serial.print("Command: ");
    Serial.println(input);

    //Serial.println(input.startsWith("exists(") && input.endsWith(")"));

    if (input.startsWith("exists(") && input.endsWith(")")) {
      String file = input.substring(7, input.length() - 1);

      Serial.print("File: ");
      Serial.println(file);

      File f = SD.open(file);
      if (f) {
        Serial.println("File does exists");
        f.close();
      } else {
        Serial.println("File does not exist");
      }

    } else if (input.startsWith("print(") && input.endsWith(".img)")) {
      String file = input.substring(6, input.length() - 1);
      File f = SD.open(file);
      if (f) {
        cls();

        Serial.print("Printing image: ");
        // Dimensionen auslesen
        int width = 0;
        int height = 0;

        char ch = '\0';
        String dim = "";

        while (f.available()) {
          ch = (char)f.read();

          if (ch != ',' && ch != '\n')
            dim += ch;
          else {
            if (width == 0) {
              width = dim.toInt();
              dim = "";
            } else if (height == 0) {
              height = dim.toInt();
            }

            if (ch == '\n') {
              break;
            }
          }
        }

        Serial.print("Dimensions of image: ");
        Serial.print(width);
        Serial.print(" x ");
        Serial.println(height);

        for (int i = 0; i < height; ++i) {
          for (int x = 0; x < width; ++x){
            char ch = '\0';
            while (ch != '\n') {
              ch = f.read();
              if (ch == ','){
                continue;
              }else (ch == '0' || ch == '1') {
                int pix = ch - '0';
                setPixel(x, i, pix);
              }
            }
          }
        }
      }

    } else if (input.startsWith("print(") && input.endsWith(")")) {
      String file = input.substring(6, input.length() - 1);
      File f = SD.open(file);
      if (f) {
        cls();

        int x = 0;
        int y = 0;
        Serial.print("Printing: ");
        while (f.available()) {
          char ch = (char)f.read();
          Serial.print(ch);
          if (-1 == printChar(x, y, ch));

          draw();

          x = (x + 6) % 84;
          if (x == 0) {
            y = (y + 8) % 48;
          }
        }
        Serial.println();



      } else {
        Serial.println("Error: File does not exist");
      }


    } else {
      Serial.println("Unknown command");
    }

    complete = false;
    input = "";
  }

  draw();

  delay(10);

}

// ----------------------------------------------------------------------------

void draw()
{
  lcdMode(LCD_DATA);

  for (int b = 0; b < 6; ++b) {
    for (int x = 0; x < 84; ++x) {
      lcdWrite(data[x][b]);
    }
  }
}

void reset()
{
  digitalWrite(PIN_RESET, LOW);
  delay(500);
  digitalWrite(PIN_RESET, HIGH);
}

void cls()
{
  for (int x = 0; x < LCD_WIDTH; ++x) {
    for (int y = 0; y < LCD_HEIGHT; ++y) {
      setPixel(x, y, 0);
    }
  }
}

void lcdMode(int mode)
{
  digitalWrite(PIN_DC, mode);
}

void lcdInitialize()
{
  lcdMode(LCD_COMMAND);

  // FUNCTION SET (extended instruction set)
  lcdWrite(0x21);

  // SET BIAS
  lcdWrite(0x14);

  // SET TEMP COEFFICIENT
  lcdWrite(0x04);

  // SET CONTRAST
  lcdWrite(0xBF);

  // FUNCTION SET (normal instruction set)
  lcdWrite(0x20);

  // SET DISPLAY MODE (normal)
  lcdWrite(0x0C);

  // reset display
  lcdWrite(0x40);
  lcdWrite(0x80);
}

void printString(int y, const char *value)
{
  printString((84 - strlen(value) * 6) / 2, y, value);
}

void printString(int x, int y, const char *value)
{
  do
  {
    printChar(x, y, *value);
    x += 6;
  } while (*++value != '\0');
}

int printChar(int x, int y, char value)
{
  lcdMode(LCD_DATA);

  if (value < ' ') {
    return -1;
  }

  for (int dx = 0; dx < 6; ++dx) {
    for (int dy = 0; dy < 8; ++dy) {
      setPixel(x + dx, y + dy, !!(font[value - ' '][dx] & (1 << dy)));
    }
  }

  return 0;
}

void setPixel(int x, int y, int value)
{
  if (x >= 0 && x < 84 && y >= 0 && y < 48) {
    if (value) {
      data[x][y / 8] |= (1 << (y % 8));
    } else {
      data[x][y / 8] &= ~(1 << (y % 8));
    }
  }
}

void lcdWrite(int value)
{
  digitalWrite(PIN_SCE, LOW);
  SPI.transfer(PIN_SCE, value, SPI_CONTINUE);
  digitalWrite(PIN_SCE, HIGH);
}


Read the reference manual for your LCD.

Normally, SPI connected devices are block devices.  Meaning they expect a formatted block of data, not single bytes.  I have no direct knowledge of your LCD, but I assume, your lcdWrite() function is totally confusing it.

Usually SPI devices are controlled in this manner:
Code: [Select]

void lcdTransaction(uint8_t command, char * inbuf, uint16_t inlen, char * outbuf){
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); // use the correct values for your device. Claim SPI bus, configure it for this device.
digitalWrite(CSpin,LOW); // wake up SPI device,
SPI.transfer(command); // first byte after wakeup is command
uint16_t index=0;
while(index<inlen){
  outbuf[index] = SPI.transfer(inbuf[index]); // transmit and Receive a byte, send data, accept response
  index++;
  }
digitalWrite(CSpin,HIGH); // end block transmission, allow SPI device to service requested command
SPI.endTransaction(); // release SPI bus for other device use (SdCard, etc..)
}


Normally every time you toggle the CSpin, the SPI device expects a new command sequence to start.

In my code example the SPI device expects a one byte command followed by an unknown number of data bytes.

If I tried to use your lcdWrite() function.  Every byte would be interpreted as a command with Zero bytes of data?

Chuck.
Currently built mega http server, Now converting it to ESP32.

NSmit

This is what I get in the serial monitor:

Code: [Select]

Serial Init..
Command: print(photo.img)
Printing image: Dimensions of image: 35 x 35


but there is not any thing drawn on the TFT. I have only "a" letter. Which I used to test the screen.

chucktodd

This is what I get in the serial monitor:

Code: [Select]

Serial Init..
Command: print(photo.img)
Printing image: Dimensions of image: 35 x 35


but there is not any thing drawn on the TFT. I have only "a" letter. Which I used to test the screen.

Step back a few paces, build, test, debug routines that control your TFT.  After you have the TFT functioning correctly, then integrate it with your SdCard images.

Based on your code, I do not believe you are in control of your TFT. You are just throwing bytes at the display.

I cannot offer any more help, I do not have any experience with TFT devices.

Chuck.
Currently built mega http server, Now converting it to ESP32.

Go Up