Monday, 23 December 2013

Sainsonic arduino mega touchscreen bmp Image viewer example

Hey,
Here's the demo file I've promised, Hope you enjoy.

Allows the user to scroll between bmp images on a SD card using SD Class and Custom event handlers to suit the non genuine chip on the Sainsonic Screen.

Works with the 3.2" Touchscreen Provided by sainsonic with the


/*
Arduino Mega Sainsmart 3.2 TFT Touchscreen Demo
Written & Adaption of demo Source from Sainsmart
By BJ Smith
http://technomungo.blogspot.com.au
If this Helped you, donate me a few feathercoins @

6tCqWb5C65BfXXEw6yrKBHP8uMx8imW68Y

Explanation:

Cycle through all bitmap images in /images on flash card
Images must be even in dimensions and have 24bit colour

Will explore this glitch at some point.

Demonstrates seeking to data bits to display Bitmap display.

Was written due to the limitation of SDFAT Not allowing me to
load images out of the root directory.

Known Issues:
Images must be even in dimensions.
Doesn't white out the screen before displaying next image,
so if next image is smaller it'll leave some portion of the old image.
Will cover over the menu if the image is too big.

If you need consultation or help on your project I am available
at reasonable rates.
*/

#include "UTFT.h"
#include "SD.h"

//TOUCH SCREEN PINS
#define DCLK     6
#define CS       5 
#define DIN      4
#define DOUT     3
#define IRQ      2


#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240

#define SD_PIN 53 

extern uint8_t SmallFont[];
extern uint8_t BigFont[];

int Image_Current = 0;
File root;
boolean isloading = false;
boolean backwards = false;
int lastfile = -1;
volatile boolean screenpressed = false;
unsigned int TP_X,TP_Y;

UTFT myGLCD(GEEE32, 38, 39, 40, 41);

void ShowMessage(const char* msg1, const char* msg2 = 0)
{
    myGLCD.setColor(255, 0, 0);
    myGLCD.fillRoundRect(55, 190, 265, 230);
    myGLCD.setColor(255, 255, 255);
    myGLCD.setBackColor(255, 0, 0);
    myGLCD.print(msg1, CENTER, 196);
    if (msg2) myGLCD.print(msg2, CENTER, 210);
}

void LoadImage(File& file)   //This does have a glitch, you need to have images with even dimensions.
{
    
      //READ THE HEADER
      int header  = file.read();
      int header2  = file.read();
      int xoff = 0;
      int yoff = 0;
      if (header == 66 && header2 == 77) //Check if header = BM
      {
          file.seek(0x1C); //OFFSET FOR COLOR BITS
          word  BPP = read32(file); 
          if ( BPP ==0x18) //CHECK IF 24bit for TFT
          {
                file.seek(0x12); //OFFSET TO DIMENSIONS
                word  height = read32(file);
                word  width = read32(file);
                xoff = SCREEN_WIDTH/2-(int)width/2; //USED TO CENTER THE IMAGE
                yoff = SCREEN_HEIGHT/2-(int)height/2;
                file.seek(0xA); //OFFSET TO DATA OFFSET
                word bitmapOffset =  read32(file);
                file.seek(bitmapOffset); //SEEK TO READ POSITION
                for (int y = (int)width; y > 0 ; y--)
                    {
                        for (int x = 0; x < (int)height ; x++)
                        {
                            byte b = file.read();
                            byte g = file.read();
                            byte r = file.read();
                            myGLCD.setColor(r,g,b);
                            myGLCD.drawPixel(x+xoff,y+yoff);
                        }
                     }
                    
           
          }
        
      }
      else
      {
         if (backwards)
         {
             previmage();
         }
         else
         {
             nextimg();
         }
      }
  }
   



void WalkDirectory(File dir)
{
        File entry = dir.openNextFile();
        if (! entry) {
            // no more files
            lastfile = Image_Current;
           
        }
        if (entry.isDirectory()) {
            WalkDirectory(entry);
        }
        else {
           
            if (lastfile != Image_Current)
            {
                ShowMessage(entry.name());
            }
           
            LoadImage(entry);
        }
        entry.close();
 
}

void spistar()                                     //SPI Start
{
  digitalWrite(CS,HIGH);
  digitalWrite(DCLK,HIGH);
  digitalWrite(DIN,HIGH);
  digitalWrite(DCLK,HIGH);

}
//**********************************************************
void WriteCharTo7843(unsigned char num)          //SPI Write Data
{
  unsigned char count=0;
  unsigned char temp;
  unsigned nop;
  temp=num;
  digitalWrite(DCLK,LOW);
  for(count=0;count<8;count++)
  {
    if(temp&0x80)
      digitalWrite(DIN,HIGH);
    else
      digitalWrite(DIN,LOW);

    temp=temp<<1;

    digitalWrite(DCLK,LOW);               
    nop++;
    nop++;
    digitalWrite(DCLK,HIGH);
    nop++;
    nop++;
  }
}

//**********************************************************
unsigned int ReadFromCharFrom7843()             //SPI Read Data
{
  unsigned nop;
  unsigned char count=0;
  unsigned int Num=0;
  for(count=0;count<12;count++)
  {
    Num<<=1;
    digitalWrite(DCLK,HIGH);//DCLK=1; _nop_();_nop_();_nop_();               
    nop++;
    digitalWrite(DCLK,LOW);//DCLK=0; _nop_();_nop_();_nop_();
    nop++;
    if(digitalRead(DOUT)) Num++;
  }
  return(Num);
}

void AD7843(void)             
{
  digitalWrite(CS,LOW);                   
  WriteCharTo7843(0x90);
  digitalWrite(DCLK,HIGH);
  digitalWrite(DCLK,LOW);
  TP_Y=ReadFromCharFrom7843();
  WriteCharTo7843(0xD0);  
  digitalWrite(DCLK,HIGH);
  digitalWrite(DCLK,LOW);
  TP_X=ReadFromCharFrom7843();
  digitalWrite(CS,HIGH);
}

void setup()
{
  Serial.begin(9600);
  for(int p=22;p<42;p++)
  {
    pinMode(p,OUTPUT);
  }
  for(int p=2; p<7;p++)
      pinMode(p,OUTPUT);
  pinMode(DOUT,INPUT);
  pinMode(IRQ,INPUT);
 
    // Setup the LCD
    myGLCD.InitLCD();
  
    myGLCD.setFont(BigFont);
    myGLCD.fillScr(255, 255, 255);
    //BACK BUTTON
    myGLCD.setColor(255, 0, 0);
    myGLCD.fillRoundRect(10, 190, 50, 230);
    myGLCD.setColor(255, 255, 255);
    myGLCD.setBackColor(255, 0, 0);
    myGLCD.print("<", 25, 202);
    //FORWARD BUTTON
    myGLCD.setColor(255, 0, 0);
    myGLCD.fillRoundRect(270, 190, 310, 230);
    myGLCD.setColor(255, 255, 255);
    myGLCD.setBackColor(255, 0, 0);
    myGLCD.print(">", 285, 202);
   
    spistar(); //setup the Touchscreen
    pinMode(SD_PIN, OUTPUT);
    if (!SD.begin(SD_PIN))
    {
        ShowMessage("SD not ready");
        return;
    }
    attachInterrupt(0, screentouched, FALLING);
    root = SD.open("/images");
    WalkDirectory(root);

}
void screentouched()  //TOUCH SCREEN EVENT HANDLER
{
      noInterrupts();
      if (!screenpressed)
      {
         screenpressed = true;
        
      }
      interrupts();
}
void checkscreen()
{
         
     unsigned int lx,ly;
     int runningy =0; //Cumlative total
     int ycount =0; //Divisor
     int runningx =0; //Cumlative total
     int xcount=0; //Divisor
     int dud = 0; // Count of out of range data

     while (xcount <10 ||ycount <10)  //This performorms multpile measurements, throws out the duds and
     {
           if (dud >5) break; //bail if press is glitchy
           AD7843();
           int yavg =((TP_X-340)*10/144)+2;  //Landscape, so the Vals are swapped
           int xavg =((TP_Y-320)/11);
           if  (yavg >=0&& yavg <=240)
           {
                 runningy+=yavg;
                 ycount++;
                 
           }
           else
           {
                 dud++;
           }
            if  (xavg >=0&& xavg <= 320)
           {
                 runningx+=xavg;
                 xcount++;
           }
            else
           {
                 dud++;
           }
     }
     ly = (int)runningy/ycount;
     lx = (int)runningx/xcount;
    
     Serial.print("X,Y:");
     Serial.print(lx);
     Serial.print(",");
     Serial.println(ly);

     if (lx >= 270 && lx <= 310 && ly >= 190 && ly <= 230)  //IF NEXT BUTTON 270, 190, 310, 230
     {
            backwards =false;
            nextimg();
     }
     else
     {
          if (lx >= 10 && lx <= 50 && ly >= 190 && ly <= 230)  //IF BACK BUTTON 10, 190, 50, 230
            {
                backwards = true;
                previmage();
            } 
                 
     
     }


}
void loop()
{

   if (screenpressed)
         {
            checkscreen();
            delay(100);  //Wait to remove double press in some circumstances (not on this example)
            screenpressed= false;
         }
}

void nextimg()
{
    myGLCD.setColor(24, 0, 255);
    myGLCD.print(">", 285, 202);
    WalkDirectory(root);
    if (lastfile >0)  //Don't overrun the bounds of folder.
    {
        if (lastfile != Image_Current)
        {
            Image_Current++;
        }
      
    }
    else
    {
        Image_Current++;
    }

    myGLCD.setColor(255, 255, 255);
    myGLCD.print(">", 285, 202);

}
void previmage()
{
   if (Image_Current >0/*&&!isloading*/)
    {
         Image_Current--;
         myGLCD.setColor(24, 0, 255);
         myGLCD.print("<", 25, 202);
        
         root.rewindDirectory();
         for (int i = 0; i <Image_Current; i++)
         {
             root.openNextFile();
         }
         WalkDirectory(root);
         myGLCD.setColor(255, 255, 255);
         myGLCD.print("<", 25, 202);
     }
 
}

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

2 comments:

  1. What does it mean when the screen appears white with two red buttons and does nothing else?

    ReplyDelete
  2. What board are you using? This is very specific code to the sainsonic.

    ReplyDelete