//  Only Runs on Mega. Uses 6k Ram
//  BMP Must be 154x220
//  BMP Must be 16 Bit 565 Color
//


#include <SPI.h>                                 // SPI Library
#include <SdFat.h>                               // SD Card Library

#include <LCDWIKI_GUI.h>                         // Core graphics library
#include <LCDWIKI_KBV.h>                         // Hardware-specific library
#include <XPT2046_Touchscreen.h>                 // Hardware SPI touch library


LCDWIKI_KBV my_lcd(NT35510, 40, 38, 39, 43, 41); // model,cs,cd,wr,rd,reset  4" 800x480 16 Bit Mega
XPT2046_Touchscreen ts(53);                      // Touch Library  CS Pin
SdFat SD;

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define FILE_NUMBER 53
#define FILE_NAME_SIZE_MAX 20



typedef struct button_push
{
  int16_t posx1;
  int16_t posy1;
  int16_t posx2;
  int16_t posy2;
};

button_push button[11]={                   // Button Calibration Data

{141, 1769, 863, 3146},                    // Button1
{896, 1724, 1667, 3148},                   // Button2
{1690, 1730, 2432, 3101},                  // Button3
{2458, 1727, 3197, 3094},                  // Button4
{3239, 1725, 3957, 3103},                  // Button5
{146, 1387, 877, 1743},                    // Button6
{889, 1362, 1666, 1730},                   // Button7
{1702, 1359, 2431, 1724},                  // Button8
{2468, 1375, 3214, 1688},                  // Button9
{3239, 1338, 3942, 1691},                  // Button10
{2770, 3421, 3958, 3811},                  // Button11

};



char file_name[FILE_NUMBER][FILE_NAME_SIZE_MAX];
uint32_t bmp_offset;
uint8_t pushed;
uint16_t start = 5;
uint8_t cards[53];
uint8_t card_face[5];
char card_suit[5];
uint8_t hold[5];
String winner;
uint8_t bet = 5;                                      // Starting bet
uint8_t demo = 0;                                     // Demo mode
int16_t credit = 100;
uint16_t won;
uint16_t x1;
uint16_t y1;
uint16_t x2;
uint16_t y2;
uint8_t z;


void setup()
{
  Serial.begin(9600);

  my_lcd.reset();
  my_lcd.Init_LCD();
  my_lcd.Set_Rotation(1);
  ts.begin();
  ts.setRotation(3);

//  calib();                                         // Calibrate Touch Screen
//  test_buttons();                                  // Test Button Calibration
  
  my_lcd.Fill_Screen(RED);
  my_lcd.Fill_Rect(5, 5, 790, 190, BLUE);
  my_lcd.Fill_Rect(318, 0, 5, 195, WHITE);
  my_lcd.Fill_Rect(636, 0, 5, 195, WHITE);
  my_lcd.Fill_Rect(0, 425, 800, 55, BLUE);
  my_lcd.Fill_Rect(0, 150, 800, 5, WHITE);
  my_lcd.Fill_Rect(0, 0, 800, 5, WHITE);
  my_lcd.Fill_Rect(0, 0, 5, 195, WHITE);
  my_lcd.Fill_Rect(795, 0, 800, 195, WHITE);
  my_lcd.Fill_Rect(0, 155, 800, 40, BLACK);

  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Back_colour(BLUE);
  my_lcd.Set_Text_Size(2);
  my_lcd.Print_String("ROYAL FLUSH........", 10, 10);
  my_lcd.Print_String("STRAIGHT FLUSH.....", 10, 40);
  my_lcd.Print_String("FOUR OF A KIND.....", 10, 70);
  my_lcd.Print_String("FULL HOUSE.........", 10, 100);
  my_lcd.Print_String("FLUSH..............", 10, 130);
  my_lcd.Print_String("STRAIGHT...........", 328, 10);
  my_lcd.Print_String("THREE OF A KIND....", 328, 40);
  my_lcd.Print_String("TWO PAIR...........", 328, 70);
  my_lcd.Print_String("JACKS OR BETTER....", 328, 100);
  my_lcd.Set_Text_Size(3);
  my_lcd.Print_String("BET 1", 685, 15);
  my_lcd.Print_String("CREDIT", 670, 70);
  my_lcd.Print_Number_Int(credit, 680, 110, 6, 32, 10);
  my_lcd.Print_Number_Int(bet, 760, 15, 2, 32, 10);

  showbet();

  randomSeed(analogRead(0));
  for ( int a = 1; a < 53; a++) { cards[a] = a; }

  {
    strcpy(file_name[0], "back.bmp");
    strcpy(file_name[1], "14H.bmp");
    strcpy(file_name[2], "14D.bmp");
    strcpy(file_name[3], "14C.bmp");
    strcpy(file_name[4], "14S.bmp");
    strcpy(file_name[5], "13H.bmp");
    strcpy(file_name[6], "13D.bmp");
    strcpy(file_name[7], "13C.bmp");
    strcpy(file_name[8], "13S.bmp");
    strcpy(file_name[9], "12H.bmp");
    strcpy(file_name[10], "12D.bmp");
    strcpy(file_name[11], "12C.bmp");
    strcpy(file_name[12], "12S.bmp");
    strcpy(file_name[13], "11H.bmp");
    strcpy(file_name[14], "11D.bmp");
    strcpy(file_name[15], "11C.bmp");
    strcpy(file_name[16], "11S.bmp");
    strcpy(file_name[17], "10H.bmp");
    strcpy(file_name[18], "10D.bmp");
    strcpy(file_name[19], "10C.bmp");
    strcpy(file_name[20], "10S.bmp");
    strcpy(file_name[21], "09H.bmp");
    strcpy(file_name[22], "09D.bmp");
    strcpy(file_name[23], "09C.bmp");
    strcpy(file_name[24], "09S.bmp");
    strcpy(file_name[25], "08H.bmp");
    strcpy(file_name[26], "08D.bmp");
    strcpy(file_name[27], "08C.bmp");
    strcpy(file_name[28], "08S.bmp");
    strcpy(file_name[29], "07H.bmp");
    strcpy(file_name[30], "07D.bmp");
    strcpy(file_name[31], "07C.bmp");
    strcpy(file_name[32], "07S.bmp");
    strcpy(file_name[33], "06H.bmp");
    strcpy(file_name[34], "06D.bmp");
    strcpy(file_name[35], "06C.bmp");
    strcpy(file_name[36], "06S.bmp");
    strcpy(file_name[37], "05H.bmp");
    strcpy(file_name[38], "05D.bmp");
    strcpy(file_name[39], "05C.bmp");
    strcpy(file_name[40], "05S.bmp");
    strcpy(file_name[41], "04H.bmp");
    strcpy(file_name[42], "04D.bmp");
    strcpy(file_name[43], "04C.bmp");
    strcpy(file_name[44], "04S.bmp");
    strcpy(file_name[45], "03H.bmp");
    strcpy(file_name[46], "03D.bmp");
    strcpy(file_name[47], "03C.bmp");
    strcpy(file_name[48], "03S.bmp");
    strcpy(file_name[49], "02H.bmp");
    strcpy(file_name[50], "02D.bmp");
    strcpy(file_name[51], "02C.bmp");
    strcpy(file_name[52], "02S.bmp");
  }
  
  if (!SD.begin(48)) {
    my_lcd.Set_Text_Back_colour(BLUE);
    my_lcd.Set_Text_colour(WHITE);
    my_lcd.Set_Text_Size(2);
    my_lcd.Print_String("SD Card Init fail!", 0, 300);
  }
}


void loop()
{
  uint8_t c;
  shuffle();

  showcard(0, 5);
  showcard(0, 164);
  showcard(0, 323);
  showcard(0, 482);
  showcard(0, 641);
  dodeal();

  showcard(cards[1], 5); card_face[0] = atoi(file_name[cards[1]]); card_suit[0] = file_name[cards[1]][2];
  showcard(cards[2], 164); card_face[1] = atoi(file_name[cards[2]]); card_suit[1] = file_name[cards[2]][2];
  showcard(cards[3], 323); card_face[2] = atoi(file_name[cards[3]]); card_suit[2] = file_name[cards[3]][2];
  showcard(cards[4], 482); card_face[3] = atoi(file_name[cards[4]]); card_suit[3] = file_name[cards[4]][2];
  showcard(cards[5], 641); card_face[4] = atoi(file_name[cards[5]]); card_suit[4] = file_name[cards[5]][2];
  c = 6;
  dohold();

  if (hold[0] == 0) { showcard(0, 5); }
  if (hold[1] == 0) { showcard(0, 164); }
  if (hold[2] == 0) { showcard(0, 323); }
  if (hold[3] == 0) { showcard(0, 482); }
  if (hold[4] == 0) { showcard(0, 641); }
  
  if (hold[0] == 0) { showcard(cards[c], 5); 
    card_face[0] = atoi(file_name[cards[c]]);
    card_suit[0] = file_name[cards[c]][2];
    c = c + 1;
  }
  if (hold[1] == 0) { showcard(cards[c], 164);
    card_face[1] = atoi(file_name[cards[c]]);
    card_suit[1] = file_name[cards[c]][2];
    c = c + 1;
  }
  if (hold[2] == 0) { showcard(cards[c], 323);
    card_face[2] = atoi(file_name[cards[c]]);
    card_suit[2] = file_name[cards[c]][2];
    c = c + 1;
  }
  if (hold[3] == 0) { showcard(cards[c], 482);
    card_face[3] = atoi(file_name[cards[c]]);
    card_suit[3] = file_name[cards[c]][2];
    c = c + 1;
  }
  if (hold[4] == 0) { showcard(cards[c], 641);
    card_face[4] = atoi(file_name[cards[c]]);
    card_suit[4] = file_name[cards[c]][2];
    c = c + 1;
  }

  dosort();
  checkcards();
  dowin();

}


void showbet()
{
  my_lcd.Set_Text_Size(2);
  if (bet < 5) { my_lcd.Print_Number_Int(250 * bet, 250, 10, 5, 32, 10); }
  if (bet == 5) { my_lcd.Print_Number_Int(4000, 250, 10, 5, 32, 10); }
  my_lcd.Print_Number_Int(50 * bet, 250, 40, 5, 32, 10);
  my_lcd.Print_Number_Int(25 * bet, 250, 70, 5, 32, 10);
  my_lcd.Print_Number_Int(9 * bet, 250, 100, 5, 32, 10);
  my_lcd.Print_Number_Int(6 * bet, 250, 130, 5, 32, 10);
  my_lcd.Print_Number_Int(4 * bet, 550, 10, 5, 32, 10);
  my_lcd.Print_Number_Int(3 * bet, 550, 40, 5, 32, 10);
  my_lcd.Print_Number_Int(2 * bet, 550, 70, 5, 32, 10);
  my_lcd.Print_Number_Int(1 * bet, 550, 100, 5, 32, 10);
  my_lcd.Set_Text_Size(3);
}


void checkcards()
{
  if ( card_face[4] == 14 && card_face[3] == 13 && card_face[2] == 12 && card_face[1] == 11 && card_face[0] == 10
       && card_suit[4] == card_suit[3] && card_suit[3] == card_suit[2] && card_suit[2] == card_suit[1] && card_suit[1] == card_suit[0]) {
    winner = "ROYAL FLUSH";
    won = 250 * bet;
    if (bet == 5) { won = 4000; }
    credit += won;
    return (1); }

  if (card_face[4] == card_face[3] + 1 && card_face[3] + 1 == card_face[2] + 2 && card_face[2] + 2 == card_face[1] + 3 && card_face[1] + 3 == card_face[0] + 4 && card_suit[4] == card_suit[3] && card_suit[3] == card_suit[2] && card_suit[2] == card_suit[1] && card_suit[1] == card_suit[0]) {
    winner = "STRAIGHT FLUSH";
    won = 50 * bet;
    credit += won;
    return (1);
  }

  if (card_face[4] == 14 && card_face[0] == 2 && card_face[1] == 3 && card_face[2] == 4 && card_face[3] == 5 && card_suit[4] == card_suit[3] && card_suit[3] == card_suit[2] && card_suit[2] == card_suit[1] && card_suit[1] == card_suit[0]) {
    winner = "STRAIGHT FLUSH";
    won = 50 * bet;
    credit += won;
    return (1);
  }

  if ((card_face[0] == card_face[1] && card_face[1] == card_face[2] && card_face[2] == card_face[3]) ||
      (card_face[1] == card_face[2] && card_face[2] == card_face[3] && card_face[3] == card_face[4])) {
    winner = "FOUR OF A KIND";
    won = 25 * bet;
    credit += won;
    return (1);
  }

  if ((card_face[0] == card_face[1] && card_face[1] == card_face[2] && card_face[3] == card_face[4]) ||
      (card_face[0] == card_face[1] && card_face[2] == card_face[3] && card_face[3] == card_face[4])) {
    winner = "FULL HOUSE";
    won = 9 * bet;
    credit += won;
    return (1);
  }

  if (card_suit[0] == card_suit[1] && card_suit[1] == card_suit[2] && card_suit[2] == card_suit[3] && card_suit[3] == card_suit[4]) {
    winner = "FLUSH";
    won = 6 * bet;
    credit += won;
    return (1);
  }

  if (card_face[4] == card_face[3] + 1 && card_face[3] + 1 == card_face[2] + 2 && card_face[2] + 2 == card_face[1] + 3 && card_face[1] + 3 == card_face[0] + 4) {
    winner = "STRAIGHT";
    won = 4 * bet;
    credit += won;
    return (1);
  }

  if (card_face[4] == 14 && card_face[0] == 2 && card_face[1] == 3 && card_face[2] == 4 && card_face[3]) {
    winner = "STRAIGHT";
    won = 4 * bet;
    credit += won;
    return (1);
  }

  for (int i = 0; i < 3; ++i)
  {
    if ((card_face[i] == card_face[i + 1]) && (card_face[i + 1] == card_face[i + 2])) {
      winner = "THREE OF A KIND";
      won = 3 * bet;
      credit += won;
      return (1);
    }
  }

  if ((card_face[0] == card_face[1] && card_face[2] == card_face[3]) ||
      (card_face[1] == card_face[2] && card_face[3] == card_face[4]) ||
      (card_face[0] == card_face[1] && card_face[3] == card_face[4])) {
    winner = "TWO PAIR";
    won = 2 * bet;
    credit += won;
    return (1);
  }

  for (int i = 0; i < 4; i++)
  {
    if (card_face[i] == card_face[i + 1] && card_face[i] > 10) {
      winner = "JACKS OR BETTER";
      won = 1 * bet;
      credit += won;
      return (1);
    }
  }
  won = 0;
  winner = "";
}


void dosort()
{
  uint8_t c = 0;
  uint8_t a;
  char b;

  while (c == 0) {
    c = 1;
    if (card_face[0] > card_face[1]) {
      a = card_face[1]; card_face[1] = card_face[0]; card_face[0] = a;
      b = card_suit[1]; card_suit[1] = card_suit[0]; card_suit[0] = b;
      c = 0;
    }

    if (card_face[1] > card_face[2]) {
      a = card_face[2]; card_face[2] = card_face[1]; card_face[1] = a;
      b = card_suit[2]; card_suit[2] = card_suit[1]; card_suit[1] = b;
      c = 0;
    }

    if (card_face[2] > card_face[3]) {
      a = card_face[3]; card_face[3] = card_face[2]; card_face[2] = a;
      b = card_suit[3]; card_suit[3] = card_suit[2]; card_suit[2] = b;
      c = 0;
    }

    if (card_face[3] > card_face[4]) {
      a = card_face[4]; card_face[4] = card_face[3]; card_face[3] = a;
      b = card_suit[4]; card_suit[4] = card_suit[3]; card_suit[3] = b;
      c = 0;
    }
  }
}


void dohold()
{
  uint16_t x;
  uint16_t y;
  hold[0] = 0;
  hold[1] = 0;
  hold[2] = 0;
  hold[3] = 0;
  hold[4] = 0;

  my_lcd.Set_Text_Size(3);
  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Back_colour(BLACK);
  my_lcd.Fill_Rect(0, 425, 800, 75, BLACK);
  my_lcd.Print_String("SELECT CARDS TO HOLD THEN PUSH", 5, 450);
  my_lcd.Set_Text_colour(RED);
  my_lcd.Set_Text_Size(5);
  my_lcd.Print_String("  DEAL  ", 565, 439);
  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Size(3);

  if (demo == 1) { return (1); }

  while (1) {
  button_wait(); 

        if (pushed==0) {
            if (hold[0] == 0) {
            hold[0] = 1;
            my_lcd.Print_String("HELD ", 50, 165); }
          else {
            hold[0] = 0;
            my_lcd.Print_String("     ", 50, 165); }
        }
          if (pushed==1) {
            if (hold[1] == 0) {
            hold[1] = 1;
            my_lcd.Print_String("HELD ", 210, 165); }
          else {
            hold[1] = 0;
            my_lcd.Print_String("     ", 210, 165); }
        }
          if (pushed==2) {
            if (hold[2] == 0) {
            hold[2] = 1;
            my_lcd.Print_String("HELD ", 370, 165); }
          else {
            hold[2] = 0;
            my_lcd.Print_String("     ", 370, 165); }
        }
          if (pushed==3) {
          if (hold[3] == 0) {
            hold[3] = 1;
            my_lcd.Print_String("HELD ", 530, 165); }
          else {
            hold[3] = 0;
            my_lcd.Print_String("     ", 530, 165); }
        }
          if (pushed==4) {
          if (hold[4] == 0) {
            hold[4] = 1;
            my_lcd.Print_String("HELD ", 680, 165); }
          else {
            hold[4] = 0;
            my_lcd.Print_String("     ", 680, 165); }
        }
      
        if (pushed==10) {
        my_lcd.Fill_Rect(0, 425, 800, 55, BLACK);
        my_lcd.Fill_Rect(0, 155, 800, 40, BLACK);
        return (1); }
   delay(300);
  }
}


void dodeal()
{
  uint16_t x;
  uint16_t y;

  my_lcd.Set_Text_Size(3);
  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Back_colour(BLACK);
  my_lcd.Fill_Rect(0, 425, 800, 75, BLACK);
  my_lcd.Print_String("SELECT BET THEN PUSH DEAL", 5, 450);
  my_lcd.Set_Text_colour(RED);
  my_lcd.Set_Text_Size(5);
  my_lcd.Print_String("  DEAL  ", 565, 439);
  my_lcd.Set_Text_Back_colour(BLACK);
  my_lcd.Set_Text_Size(3);
  my_lcd.Set_Text_colour(RED);
  my_lcd.Print_String("BET 1", 40, 165);
  my_lcd.Print_String("BET 2", 200, 165);
  my_lcd.Print_String("BET 3", 360, 165);
  my_lcd.Print_String("BET 4", 510, 165);
  my_lcd.Print_String("BET 5", 670, 165);
  my_lcd.Set_Text_Back_colour(BLUE);
  my_lcd.Set_Text_colour(YELLOW);

  if (demo == 1) {
    credit -= bet;
    my_lcd.Print_Number_Int(credit, 680, 110, 6, 32, 10);
    return (1);
    }

  while (1) {
  button_wait(); 
  
      if (pushed==5) {
        my_lcd.Print_String("BET 1", 685, 15);
        bet = 1;
        showbet(); }

      if (pushed==6) {
        my_lcd.Print_String("BET 2", 685, 15);
        bet = 2;
        showbet(); }

      if (pushed==7) {
        my_lcd.Print_String("BET 3", 685, 15);
        bet = 3;
        showbet(); }

      if (pushed==8) {
        my_lcd.Print_String("BET 4", 685, 15);
        bet = 4;
        showbet(); }

      if (pushed==9) {
        my_lcd.Print_String("BET 5", 685, 15);
        bet = 5;
        showbet(); }
        
      if (pushed==10) {
        my_lcd.Fill_Rect(0, 425, 800, 55, BLACK);
        my_lcd.Fill_Rect(0, 155, 800, 40, BLACK);
        credit -= bet;
        my_lcd.Print_Number_Int(credit, 680, 110, 6, 32, 10);
        return (1); }
    }
}


void dowin()
{
  uint16_t x;
  uint16_t y;

  my_lcd.Set_Text_Size(3);
  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Back_colour(BLACK);
  my_lcd.Fill_Rect(0, 425, 800, 75, BLACK);
  my_lcd.Print_String(winner, 200, 450);
  my_lcd.Print_String("WIN", 5, 450);
  my_lcd.Print_Number_Int(won, 60, 450, 5, 32, 10);
  my_lcd.Set_Text_Back_colour(BLUE);
  my_lcd.Print_Number_Int(credit, 680, 110, 6, 32, 10);
  my_lcd.Set_Text_Back_colour(BLACK);
  my_lcd.Set_Text_colour(RED);
  my_lcd.Set_Text_Size(5);
  my_lcd.Print_String(" SHUFFLE ", 550, 439);
  my_lcd.Set_Text_colour(YELLOW);
  my_lcd.Set_Text_Back_colour(BLUE);
  my_lcd.Set_Text_Size(3);

  if (demo == 1) { return (1); }

  while (1) {
  button_wait();
  
      if (pushed==10) {
        my_lcd.Fill_Rect(0, 425, 800, 55, BLACK);
        my_lcd.Fill_Rect(0, 155, 800, 40, BLACK);
        return (1); }
   delay(300);
  }
}


void showcard(int a, int b)
{
  File bmp_file;
  start = b;

  bmp_file = SD.open(file_name[a]);
  if (bmp_file)
  {
    if (analysis_bpm_header(bmp_file))
    {
      draw_bmp_picture(bmp_file);
      bmp_file.close();
    }
    else
    {
      my_lcd.Set_Text_Back_colour(BLUE);
      my_lcd.Set_Text_colour(WHITE);
      my_lcd.Set_Text_Size(2);
      my_lcd.Print_String("Invalid BMPimage!", 0, 330);
    }
  }
  else {
    my_lcd.Set_Text_Back_colour(BLUE);
    my_lcd.Set_Text_colour(WHITE);
    my_lcd.Set_Text_Size(2);
    my_lcd.Print_String("Cant find BMPimage!", 0, 360);
  }
}


void shuffle()
{
  int a = 0;
  int b = 0;
  int c = 0;
  int d = 0;

  for (a = 0; a < 500; a++) {
    b = (random(52)) + 1;
    c = (random(52)) + 1;
    d = cards[b];
    cards[b] = cards[c];
    cards[c] = d;
  }
}


bool analysis_bpm_header(File fp)
{
  uint8_t dat8[2];
  uint16_t dat16[2];
  uint32_t dat32;
  uint32_t bpm_heigh;
  uint32_t bpm_width;

  fp.read(dat8, 2);                            // Read BMP identifier
  dat16[0] = (dat8[1] << 8 | dat8[0]);
  if (dat16[0] != 0x4D42) {
    return false;
  }

  fp.read(dat8, 4);                            // Read BMP Size

  fp.read(dat8, 4);                            // Read Creator Information

  fp.read(dat8, 4);                            // Read Data offset
  dat16[1] = (dat8[1] << 8 | dat8[0]);
  dat16[0] = (dat8[3] << 8 | dat8[2]);
  bmp_offset = (dat16[0] << 16 | dat16[1]);

  fp.read(dat8, 4);                            // Read DIB Information

  fp.read(dat8, 4);                            // Read BMP Width
  dat16[1] = (dat8[1] << 8 | dat8[0]);
  dat16[0] = (dat8[3] << 8 | dat8[2]);
  bpm_width = (dat16[0] << 16 | dat16[1]);
  if (bpm_width != 154) {
    return false;
  }

  fp.read(dat8, 4);                            // Read BMP Height
  dat16[1] = (dat8[1] << 8 | dat8[0]);
  dat16[0] = (dat8[3] << 8 | dat8[2]);
  bpm_heigh = (dat16[0] << 16 | dat16[1]);
  if (bpm_heigh != 220) {
    return false;
  }

  fp.read(dat8, 2);                            // Read Colour Planes
  dat16[0] = (dat8[1] << 8 | dat8[0]);
  if (dat16[0] != 1) {
    return false;
  }

  fp.read(dat8, 2);                            // Read Bits per Pixel
  dat16[0] = (dat8[1] << 8 | dat8[0]);
  if (dat16[0] != 16) {
    return false;
  }

  fp.read(dat8, 4);                            // Read Compression
  dat16[1] = (dat8[1] << 8 | dat8[0]);
  dat16[0] = (dat8[3] << 8 | dat8[2]);
  dat32 = (dat16[0] << 16 | dat16[1]);
  if (dat32 != 0) {
    return false;
  }

  return true;
}


void draw_bmp_picture(File fp)
{
  uint16_t i;
  uint16_t bpm_color[616];

  fp.seek(bmp_offset);
  for (i = 0; i < 220; i += 4) {
    fp.read(bpm_color, 1232);
    my_lcd.Draw_Bit_Map((start), (i + 200), (154), 4, bpm_color, 1);
  }
}


void calib()
{
  Serial.println(" ");
  Serial.println("Touch the Red dots untill all of them are done");
  Serial.println("There are 22 Points to calibrate");
  Serial.println(" ");

  my_lcd.Fill_Screen(BLACK);
  my_lcd.Set_Draw_color (RED);
  my_lcd.Fill_Circle(5, 200, 5); get_touch();
  my_lcd.Fill_Circle(159, 380, 5); get_touch1();
  my_lcd.Fill_Circle(164, 200, 5); get_touch();
  my_lcd.Fill_Circle(319, 380, 5); get_touch1();
  my_lcd.Fill_Circle(323, 200, 5); get_touch();
  my_lcd.Fill_Circle(477, 380, 5); get_touch1();
  my_lcd.Fill_Circle(482, 200, 5); get_touch();
  my_lcd.Fill_Circle(636, 380, 5); get_touch1();
  my_lcd.Fill_Circle(641, 200, 5); get_touch();
  my_lcd.Fill_Circle(795, 380, 5); get_touch1();
  my_lcd.Fill_Circle(5, 151, 5); get_touch();
  my_lcd.Fill_Circle(159, 199, 5); get_touch1();
  my_lcd.Fill_Circle(164, 151, 5); get_touch();
  my_lcd.Fill_Circle(319, 199, 5); get_touch1();
  my_lcd.Fill_Circle(323, 151, 5); get_touch();
  my_lcd.Fill_Circle(477, 199, 5); get_touch1();
  my_lcd.Fill_Circle(482, 151, 5); get_touch();
  my_lcd.Fill_Circle(636, 199, 5); get_touch1();
  my_lcd.Fill_Circle(641, 151, 5); get_touch();
  my_lcd.Fill_Circle(795, 199, 5); get_touch1();
  my_lcd.Fill_Circle(550, 421, 5); get_touch();
  my_lcd.Fill_Circle(795, 475, 5); get_touch1();

  Serial.println(" ");
  Serial.println("Enter those values into the Sketch or Copy and Paste the whole lines");
  Serial.println("Then run the Test Calibration to confirm calibration is correct");

  while(1) {
  delay(100);}
 
}


void test_buttons()
{
  z=1;
  my_lcd.Fill_Screen(BLACK);
  draw_box();
  while(1) {
    button_wait();
    my_lcd.Set_Draw_color (RED);
    if (pushed==0) { my_lcd.Draw_Rectangle(5,200,159,380); }
    if (pushed==1) { my_lcd.Draw_Rectangle(164,200,319,380); }
    if (pushed==2) { my_lcd.Draw_Rectangle(323,200,477,380); }
    if (pushed==3) { my_lcd.Draw_Rectangle(482,200,636,380); }
    if (pushed==4) { my_lcd.Draw_Rectangle(641,200,795,380); }
    if (pushed==5) { my_lcd.Draw_Rectangle(5,151,159,199); }
    if (pushed==6) { my_lcd.Draw_Rectangle(164,151,319,199); }
    if (pushed==7) { my_lcd.Draw_Rectangle(323,151,477,199); }
    if (pushed==8) { my_lcd.Draw_Rectangle(482,151,636,199); }
    if (pushed==9) { my_lcd.Draw_Rectangle(641,151,795,199); }
    if (pushed==10) { my_lcd.Draw_Rectangle(550,421,795,475); }
    delay(100);
    draw_box(); }
}


void draw_box()
{
  my_lcd.Set_Draw_color (GREEN);
  my_lcd.Draw_Rectangle(5,200,159,380);
  my_lcd.Draw_Rectangle(164,200,319,380);
  my_lcd.Draw_Rectangle(323,200,477,380);
  my_lcd.Draw_Rectangle(482,200,636,380);
  my_lcd.Draw_Rectangle(641,200,795,380);
  my_lcd.Draw_Rectangle(5,151,159,199);
  my_lcd.Draw_Rectangle(164,151,319,199);
  my_lcd.Draw_Rectangle(323,151,477,199);
  my_lcd.Draw_Rectangle(482,151,636,199);
  my_lcd.Draw_Rectangle(641,151,795,199);
  my_lcd.Draw_Rectangle(550,421,795,475);
}


void get_touch()
{
TS_Point p; 

  while (!ts.touched()) { delay(100); }
  p = ts.getPoint(); delay(50);
  p = ts.getPoint(); delay(50);
  p = ts.getPoint();
  x1 = p.x;
  y1 = p.y;
  delay(300);
  my_lcd.Fill_Screen(BLACK);
}


void get_touch1()
{
TS_Point p;

  while (!ts.touched()) { delay(100); }
  p = ts.getPoint(); delay(50);
  p = ts.getPoint(); delay(50);
  p = ts.getPoint();
  x2 = p.x;
  y2 = p.y;

  Serial.print("{ "); Serial.print(x1);
  Serial.print(", "); Serial.print(y1);
  Serial.print(", "); Serial.print(x2);
  Serial.print(", "); Serial.print(y2);
  Serial.print(" },         //Button"); Serial.println(z+1);
  
  z = z + 1;
  delay(300);
  my_lcd.Fill_Screen(BLACK);
}


void button_wait()
{
int8_t a;
TS_Point p;
   
   while (1) {
    if (ts.touched()) {
      p = ts.getPoint(); delay(50);
      p = ts.getPoint(); delay(50);
      p = ts.getPoint();

      for (a = 0; a < 11; a += 1) {
        x1=button[a].posx1;
        y1=button[a].posy1;
        x2=button[a].posx2;
        y2=button[a].posy2;
          if (p.x>x1 && p.x<x2 && p.y>y1 && p.y<y2) {
             pushed=a;
             return(1);
             }
        }
     }
   }   
}

 
