Hardware components | ||||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
Software apps and online services | ||||||
|
When I bought a 800 x 480 IPS Touchscreen shield (Model MAR4018) for the Mega I was amazed at the Quality of the Screen. I was showing Pics in a slideshow at first and the Image quality was fantastic. I eventually decided I wanted to make a Full on Graphical Poker game for it. I used Very detailed Playing cards and used the Micro SD card on the Touchscreen to store them. All the BMP's are Converted to 16 Bit 565 Color to reduce the loading times.
The game should be easy to get running if you use the same hardware. You need to use a Mega as the game needs the extra ram. (Used for fast BMP loading.) You need an 800x480 screen as the game has been written for that resolution.
Just copy the 53 BMP's to a Micro SD Card and insert it into the Screens SD Slot. Compile the sketch and program the Mega. It should run.
The Game is very simple to use. It prompts the User for what to do. Deal, Hold, Shuffle etc. It's all Touch driven.
One thing I found out when writing this project. The LCDWIKI_Touch driver does NOT work with the Micro SD card in use. The SD card driver uses Hardware SPI but the LCDWIKI_Touch driver uses Software SPI. The Touch won't work after the SD card driver is initialised. I did however find a Touchscreen driver that does use Hardware SPI. You do need to use this driver. Thanks to Paul Stoffregen for releasing it. It's available on Github at
I am using the LCDWIKI NT35510 Screen driver. The model of the Touchscreen is MAR4018. It's exceptional value for money. It's a true IPS screen unlike the others in this size range which are TFT.
Link to the Library for the 4 Inch Screen on the LCDWIKI Web Page.
I have updated the code to use the SdFat Library to access the SD Card. That Library is about double the reading speed of the old SD Library. You will need to install the SdFat Library from the Library Manager in IDE.
I did have some issues with SdFat as it's not fully compatible with the SD Library. It is working now though. It display all 5 cards in about 1.5 Seconds.
17th November 2022: Major Update
The MAR4018 is a Very nice IPS screen. The Colours are vibrant and the contrast is great. HOWEVER, The Touch panel they have used is VERY Poor quality. The Screen on mine has noticeable Rotation Errors and "Severe" Linearity Errors. The Linearity was so bad I had to calibrate every button position manually. The standard Touch Screen Calibration methods do not work.
I have added Calibration code to the Sketch as well as a Test Calibration code. See the Read_Me file on Calibration etc.
// 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);
}
}
}
}
}
No preview (download only).
Instructions to get the Touch Screen Calibrated and Confirm the calibration is accurate.
The first Step is to Calibrate the Touch Screen Button Positions.
Under the void setup() section of the code you will find two calls to Sub routenes.
// calib();
// test_buttons();
calib() is used to calibrate the Touch Screen Button positions.
test_buttons() is used to test the Calibration is correct.
First, Uncomment the calib() then compile the sketch and program your Mega.
Open the Serial Port Monitor and you will get instructions on what to do.
After all 22 points are done you can either edit the data points in the sketch
or copy and paste the whole data table. The Data Table format is laid out in
the Serial Port Monitor screen the way the Sketch needs it.
Next, Comment the calib() agan and uncomment the test_buttons() call. Compile
the sketch and program your Mega. When you touch inside the boxes they should
change to Red colour to show where you are touching.
Now Comment the test_buttons() again and compile and program your Mega. The Game is now
ready to run.
Note: There is sample calibration data in the sketch that is accurate for my Touch
Screen. It may or maynot be accurate for yours.
This is a sample of what the Button Calibration Data Table looks like in the Sketch.
{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
Their is a Demo mode in the code. Just change the Demo declaration to a 1. Compile
and program. The Game will play Automatically. To go back to normal mode change the
demo value back to 0.
uint8_t demo = 0; // Normal Mode
uint8_t demo = 1; // Demo Mode
Enjoy.
Comments