Hi there, I am stuck again in another problem. This time I want to run a game and the catch is that I want the image to load only once. I am trying to develop a game with some RFID Tags. The game is that an image of the letter pops on the screen and the player has to show the correct RFID card. If the player shows a wrong card, the game stays on that letter only till the person does not tap the right card.
But, the problem is that I want the showBMP function to show the image once only. However, when the incorrect() function is executed, the image renders all over again. The problem is that the rendering is so slow that it becomes very boring to play again. I will attach the code for the game.
#define USE_SDFAT
#include <SdFat.h> // Use the SdFat library
SdFatSoftSpi<50, 51, 52> SD; //Bit-Bang on the Shield pins
#define SD_CS 53
#define NAMEMATCH "" // "" matches any name
//#define NAMEMATCH "tiger" // *tiger*.bmp
#define PALETTEDEPTH 8 // support 256-colour Palette
char namebuf[32] = "/"; //BMP files in root directory
//char namebuf[32] = "/bitmaps/"; //BMP directory e.g. files in /bitmaps/*.bmp
File root;
int pathlen;
uint8_t ret;
uint32_t start;
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <MCUFRIEND_kbv.h>
#include <Adafruit_GFX.h>
#include <Fonts/FreeMono12pt7b.h>
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
String id = "initial";
String A = "0B002453423E";
String B = "1E005BEEC962";
String C = "1E005BE8268B";
String D = "1D00ADC7E691";
String E = "1E005C32DEAE";
String F = "1E005C487F75";
String G = "1E005BC9BC30";
String H = "1D00AE8786B2";
String I = "1D00AF453CCB";
String J = "1D00AF6570A7";
String K = "1D00AE96A481";
String L = "1D00AE086FD4";
String M = "1D00AD74A96D";
String N = "1D00AF349016";
String O = "1D00AEA9B3A9";
String P = "1D00AE8FB38F";
String Q = "1D00AD835665";
String R = "1D00AD924664";
String S = "1D00AEC53C4A";
String T = "1D00AE44AC5B";
String U = "1D00AECCC0BF";
String V = "1E005CC4AD2B";
String W = "1E005CAF2EC3";
String X = "1E005CC8810B";
String Y = "1E005BC3B432";
String Z = "1E005CC038BA";
MCUFRIEND_kbv tft;
SoftwareSerial mySoftwareSerial(23, 22); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
int lcount = 1;
int LFlag = 1;
int LED1 = 47;
int LED2 = 46;
String re; //Crucial Declaration (As we have to hold the value in some place)
void setup() {
mySoftwareSerial.begin(9600);
Serial.begin(9600);
Serial1.begin(9600);
Serial2.begin(9600);
Serial3.begin(9600);
Serial.println("READY");
myDFPlayer.begin(Serial3);
//myDFPlayer.setTimeOut(500);
myDFPlayer.volume(25);
//myDFPlayer.play(4);
//pinMode(LedPin, OUTPUT);
delay(500);
uint16_t ID=tft.readID();
tft.begin(ID);
Serial.begin(9600);
Serial.print("Show BMP files on TFT with ID:0x");
ID = tft.readID();
Serial.println(ID, HEX);
if (ID == 0x0D3D3) ID = 0x9481;
tft.begin(ID);
tft.fillScreen(0x001F);
tft.setTextColor(0xFFFF, 0x0000);
bool good = SD.begin(SD_CS);
if (!good) {
Serial.print(F("cannot start SD"));
while (1);
}
root = SD.open(namebuf);
pathlen = strlen(namebuf);
}
void loop() {
//int t = 100; //Delay before starting the Audio module; Long Playback crashes in between
//int t1 = 10000; //Delay for the screen before tftFill()
int img_time = 5000;
int counter = 1;
id = "initial";
tft.fillScreen(WHITE);
Serial.println("Out of the Loop?");
Serial.println(lcount);
ret = showBMP("B.bmp",0,0);
//Printing letter 'B' //Do I need to add some kind of counter in the beginning?
if (lcount == 1) {
Serial.println("Entered the loop");
re = Serial1.readString();
ret = showBMP("B.bmp",0,0);
while (re == "") {
ret = showBMP("B.bmp", 0, 0);
re = Serial1.readString();
Serial.println("ABCD");
Serial.println(re); //How to get out of the while loop???
if (re == B) {
correct(); //Function has been formed!
}
else if (re != B && re != "") {
incorrect();
}
}
//Letter B Loading; Need to hold the image for a few seconds; While loop required?
}
//Printing Letter 'Z'
if (lcount == 2) {
Serial.println("Successfully Entered another loop");
re = Serial1.readString();
while(re == "") {
ret = showBMP("Z.bmp",0,0);
re = Serial1.readString();
Serial.println(re);
if (re == Z) {
correct(); //Function has been formed!
}
else if (re != Z && re != "") { //id == initial; I Need some kind of exception ; ReadString() has been specified not Read()
incorrect();
}
}
//Letter B Loading; Need to hold the image for a few seconds; While loop required?
}
//Printing Letter 'X'
if (lcount == 3) {
Serial.println("Looping Successfully!,3");
re = Serial1.readString();
while(re == "") {
ret = showBMP("X.bmp",5,5);
re = Serial1.readString();
Serial.println(re); //How to get out of the while loop???
//Letter B Loading; Need to hold the image for a few seconds; While loop required?
if (re == X) {
correct(); //Function has been formed!
}
else if (re != X && re != "") { //id == initial; I Need some kind of exception ; ReadString() has been specified not Read()
incorrect();
}
}
}
}
void correct() {
digitalWrite(LED1, HIGH);
Serial.println("CORRECT ANSWER");
myDFPlayer.play(1); //Audio --> This is the correct answer!
delay(2000);
digitalWrite(LED1, LOW);
LFlag = 1;
lcount += 1; //Incorrect Coding --> (lcount += lcount) does not increment by 1 except the first iteration [Lol!]
}
void incorrect() {
digitalWrite(LED2, HIGH);
Serial.println("INCORRECT ANSWER");
myDFPlayer.play(2); //Audio --> This is the incorrect answer!
delay(5000);
digitalWrite(LED2, LOW);
}
//LCD Screen Function
#define BMPIMAGEOFFSET 54
#define BUFFPIXEL 20
uint16_t read16(File& f) {
uint16_t result; // read little-endian
f.read(&result, sizeof(result));
return result;
}
uint32_t read32(File& f) {
uint32_t result;
f.read(&result, sizeof(result));
return result;
}
uint8_t showBMP(char *nm, int x, int y)
{
File bmpFile;
int bmpWidth, bmpHeight; // W+H in pixels
uint8_t bmpDepth; // Bit depth (currently must be 24, 16, 8, 4, 1)
uint32_t bmpImageoffset; // Start of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
uint16_t lcdbuffer[(1 << PALETTEDEPTH) + BUFFPIXEL], *palette = NULL;
uint8_t bitmask, bitshift;
boolean flip = true; // BMP is stored bottom-to-top
int w, h, row, col, lcdbufsiz = (1 << PALETTEDEPTH) + BUFFPIXEL, buffidx;
uint32_t pos; // seek position
boolean is565 = false; //
uint16_t bmpID;
uint16_t n; // blocks read
uint8_t ret;
if ((x >= tft.width()) || (y >= tft.height()))
return 1; // off screen
bmpFile = SD.open(nm); // Parse BMP header
bmpID = read16(bmpFile); // BMP signature
(void) read32(bmpFile); // Read & ignore file size
(void) read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
(void) read32(bmpFile); // Read & ignore DIB header size
bmpWidth = read32(bmpFile);
bmpHeight = read32(bmpFile);
n = read16(bmpFile); // # planes -- must be '1'
bmpDepth = read16(bmpFile); // bits per pixel
pos = read32(bmpFile); // format
if (bmpID != 0x4D42) ret = 2; // bad ID
else if (n != 1) ret = 3; // too many planes
else if (pos != 0 && pos != 3) ret = 4; // format: 0 = uncompressed, 3 = 565
else if (bmpDepth < 16 && bmpDepth > PALETTEDEPTH) ret = 5; // palette
else {
bool first = true;
is565 = (pos == 3); // ?already in 16-bit format
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * bmpDepth / 8 + 3) & ~3;
if (bmpHeight < 0) { // If negative, image is in top-down order.
bmpHeight = -bmpHeight;
flip = false;
}
w = bmpWidth;
h = bmpHeight;
if ((x + w) >= tft.width()) // Crop area to be loaded
w = tft.width() - x;
if ((y + h) >= tft.height()) //
h = tft.height() - y;
if (bmpDepth <= PALETTEDEPTH) { // these modes have separate palette
//bmpFile.seek(BMPIMAGEOFFSET); //palette is always @ 54
bmpFile.seek(bmpImageoffset - (4<<bmpDepth)); //54 for regular, diff for colorsimportant
bitmask = 0xFF;
if (bmpDepth < 8)
bitmask >>= bmpDepth;
bitshift = 8 - bmpDepth;
n = 1 << bmpDepth;
lcdbufsiz -= n;
palette = lcdbuffer + lcdbufsiz;
for (col = 0; col < n; col++) {
pos = read32(bmpFile); //map palette to 5-6-5
palette[col] = ((pos & 0x0000F8) >> 3) | ((pos & 0x00FC00) >> 5) | ((pos & 0xF80000) >> 8);
}
}
// Set TFT address window to clipped image bounds
tft.setAddrWindow(x, y, x + w - 1, y + h - 1);
for (row = 0; row < h; row++) { // For each scanline...
// Seek to start of scan line. It might seem labor-
// intensive to be doing this on every line, but this
// method covers a lot of gritty details like cropping
// and scanline padding. Also, the seek only takes
// place if the file position actually needs to change
// (avoids a lot of cluster math in SD library).
uint8_t r, g, b, *sdptr;
int lcdidx, lcdleft;
if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
else // Bitmap is stored top-to-bottom
pos = bmpImageoffset + row * rowSize;
if (bmpFile.position() != pos) { // Need seek?
bmpFile.seek(pos);
buffidx = sizeof(sdbuffer); // Force buffer reload
}
for (col = 0; col < w; ) { //pixels in row
lcdleft = w - col;
if (lcdleft > lcdbufsiz) lcdleft = lcdbufsiz;
for (lcdidx = 0; lcdidx < lcdleft; lcdidx++) { // buffer at a time
uint16_t color;
// Time to read more pixel data?
if (buffidx >= sizeof(sdbuffer)) { // Indeed
bmpFile.read(sdbuffer, sizeof(sdbuffer));
buffidx = 0; // Set index to beginning
r = 0;
}
switch (bmpDepth) { // Convert pixel from BMP to TFT format
case 24:
b = sdbuffer[buffidx++];
g = sdbuffer[buffidx++];
r = sdbuffer[buffidx++];
color = tft.color565(r, g, b);
break;
}
lcdbuffer[lcdidx] = color;
}
tft.pushColors(lcdbuffer, lcdidx, first);
first = false;
col += lcdidx;
} // end cols
} // end rows
tft.setAddrWindow(0, 0, tft.width() - 1, tft.height() - 1); //restore full screen
ret = 0; // good render
}
bmpFile.close();
return (ret);
}
type or paste code here