Switching images with 2.8" TFTLCD

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
MikeCohen
 
Posts: 2
Joined: Fri May 04, 2012 2:24 pm

Switching images with 2.8" TFTLCD

Post by MikeCohen »

So I'm using the 2.8" TFT LCD Shield. What I'm trying to do is change which BMP is displayed on the screen based on serial input. The first image is displayed on screen fine in the setup() method, but the next time I try to draw the BMP (ie: serialEvent), it seems to hang on the SD.open(fName). Code below. Any ideas?
#include <SD.h>
#include <Adafruit_TFTLCD.h>
#include <Adafruit_GFX.h>
#include <SPI.h>

#if not defined USE_ADAFRUIT_SHIELD_PINOUT 
#error "For use with the shield, make sure to #define USE_ADAFRUIT_SHIELD_PINOUT in the TFTLCD.h library file"
#endif

// These are the pins as connected in the shield
#define LCD_CS A3    // Chip Select goes to Analog 3
#define LCD_CD A2    // Command/Data goes to Analog 2
#define LCD_WR A1    // LCD Write goes to Analog 1
#define LCD_RD A0    // LCD Read goes to Analog 0

// The chip select pin for the SD card on the shield
#define SD_CS 5 
// In the SD card, place 24 bit color BMP files (be sure they are 24-bit!)
// There are examples in the sketch folder

#define NUMBER_OF_IMAGES 5

// our TFT wiring
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, 0);

String bmpFiles[5];


int bmpWidth, bmpHeight;
uint8_t bmpDepth, bmpImageoffset;

/************* HARDWARE SPI ENABLE/DISABLE */
// we want to reuse the pins for the SD card and the TFT - to save 2 pins. this means we have to
// enable the SPI hardware interface whenever accessing the SD card and then disable it when done
int8_t saved_spimode;

void disableSPI(void) {
  saved_spimode = SPCR;
  SPCR = 0;
}

void enableSPI(void) {
  SPCR = saved_spimode; 
}

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

  tft.reset();

  // find the TFT display
  uint16_t identifier = tft.readRegister(0x0);
  if (identifier == 0x9325) {
    Serial.println("Found ILI9325");
  } 
  else if (identifier == 0x9328) {
    Serial.println("Found ILI9328");
  } 
  else {
    Serial.print("Unknown driver chip ");
    Serial.println(identifier, HEX);
    while (1);
  }  

  tft.begin();
  // the image is a landscape, so get into landscape mode
  tft.setRotation(1);

  Serial.print("Initializing SD card...");

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

  for(int i=0; i < 5; i++){
    int idx = i+1;
    char buffer [12];
    sprintf(buffer, "%d_EN-US.BMP", idx);
    //buffer[11] = '\0';
    Serial.println(buffer);
    bmpFiles = buffer; 
  }

  drawToScreen(bmpFiles[0]);
}

void drawToScreen(String fileName){
  
  File bmpFile;
    
  char fName[20];
  fileName.toCharArray(fName, 12);
  fName[12] = '\0';
  Serial.print("Opening ");
  Serial.print(fName);
  
  bmpFile = SD.open(fName);
  if(bmpFile){
    Serial.println("Got it!");
  }
  
  Serial.println("Opened File");
  
  if(!bmpFile){
    Serial.print("didn't find image");
    Serial.println(fileName);
    while(1);
  }
  
  if(!bmpReadHeader(bmpFile)){
    Serial.println("bad bmp");
    return;
  }
  
  disableSPI();    // release SPI so we can use those pins to draw

  bmpdraw(bmpFile, 0, 0);

  // disable the SD card interface after we are done!
  disableSPI(); 
  
  bmpFile.close();
}

void serialEvent(){
  int serialAvail = Serial.available() > 0;
  Serial.print("Serial available: ");
  Serial.println(serialAvail);
  if(serialAvail){
    Serial.println("line 1");
    int input = (int)Serial.read();
    Serial.println("line 2");
    Serial.println(input);
    disableSPI();
    switch(input){
    case 49:
      Serial.print("Got 1: ");
      Serial.println(bmpFiles[0]);
      drawToScreen(bmpFiles[0]);
      break;
    case 50:
      Serial.print("Got 2: ");
      Serial.println(bmpFiles[1]);
      drawToScreen(bmpFiles[1]);
      break;
    case 51:
      Serial.print("Got 3: ");
      Serial.println(bmpFiles[2]);
      drawToScreen(bmpFiles[2]);
      break;
    case 52:
      Serial.print("Got 4: ");
      Serial.println(bmpFiles[3]);
      drawToScreen(bmpFiles[3]);
      break;
    case 53:
      Serial.print("Got 5: ");
      Serial.println(bmpFiles[4]);
      drawToScreen(bmpFiles[4]);
      break;
    }
    
    delay(500);
  } 
}

/*********************************************/
// 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. increading the buffer takes
// more RAM but makes the drawing a little faster. 20 pixels' worth
// is probably a good place

#define BUFFPIXEL 20

void bmpdraw(File f, int x, int y) {

  Serial.println("enable SPI");
  enableSPI();     // enable the hardware SPI to talk to the SD card
  f.seek(bmpImageoffset);
  disableSPI();    // release it so we can use those pins

  uint32_t time = millis();
  uint16_t p;
  uint8_t g, b;
  int i, j;

  uint8_t sdbuffer[3 * BUFFPIXEL];  // 3 * pixels to buffer
  uint8_t buffidx = 3*BUFFPIXEL;

  Serial.print("rotation = ");
  Serial.println(tft.getRotation(), DEC);

  for (i=0; i< bmpHeight; i++) {
    // bitmaps are stored with the BOTTOM line first so we have to move 'up'

    if (tft.getRotation() == 3) {
      tft.writeRegister16(ILI932X_ENTRY_MOD, 0x1028);
      tft.goTo(x+i, y); 
    } 
    else if (tft.getRotation() == 2) {
      tft.writeRegister16(ILI932X_ENTRY_MOD, 0x1020);
      tft.goTo(x+bmpWidth, y+i); 
    } 
    else if (tft.getRotation() == 1) {
      tft.writeRegister16(ILI932X_ENTRY_MOD, 0x1018);
      tft.goTo(x+bmpHeight-1-i, y); 
    } 
    else if (tft.getRotation() == 0) {
      tft.writeRegister16(ILI932X_ENTRY_MOD, 0x1030);
      tft.goTo(x, y+bmpHeight-i); 
    }

    for (j=0; j<bmpWidth; j++) {
      // read more pixels
      if (buffidx >= 3*BUFFPIXEL) {
        enableSPI();     // enable the hardware SPI to talk to the SD card
        f.read(sdbuffer, 3*BUFFPIXEL);
        disableSPI();    // release it so we can use those pins
        buffidx = 0;
      }

      // convert pixel from 888 to 565
      b = sdbuffer[buffidx++];     // blue
      g = sdbuffer[buffidx++];     // green
      p = sdbuffer[buffidx++];     // red

      p >>= 3;
      p <<= 6;

      g >>= 2;
      p |= g;
      p <<= 5;

      b >>= 3;
      p |= b;

      // write out the 16 bits of color
      tft.writeData(p);
    }
  }
  tft.writeRegister16(ILI932X_ENTRY_MOD, 0x1030);
  Serial.print(millis() - time, DEC);
  Serial.println(" ms");
}

boolean bmpReadHeader(File f) {
  // read header
  uint32_t tmp;
  Serial.println("read16 in Read Header");
  uint16_t r16 = read16(f);
  if (r16 != 0x4D42) {
    Serial.println(r16);
    // magic bytes missing
    return false;
  }
  
  Serial.println("read32 in Read Header");
  // read file size
  tmp = read32(f);  
  Serial.print("size 0x");
  Serial.println(tmp, HEX);

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

  bmpImageoffset = read32(f);  
  Serial.print("offset ");
  Serial.println(bmpImageoffset, DEC);

  // read DIB header
  tmp = read32(f);
  Serial.print("header size ");
  Serial.println(tmp, DEC);
  bmpWidth = read32(f);
  bmpHeight = read32(f);

  r16 = read16(f);
  if (r16 != 1){
    Serial.println(r16);
    return false;
  }
  
  bmpDepth = read16(f);
  Serial.print("bitdepth ");
  Serial.println(bmpDepth, DEC);

  if (read32(f) != 0) {
    // compression not supported!
    return false;
  }

  Serial.print("compression ");
  Serial.println(tmp, DEC);

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

void loop(){
  
}

MikeCohen
 
Posts: 2
Joined: Fri May 04, 2012 2:24 pm

Re: Switching images with 2.8" TFTLCD

Post by MikeCohen »

got it...needed to enableSPI after the drawToScreen method, not disableSPI.

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

Return to “Arduino Shields from Adafruit”