/////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////BRAIN GAME/////////////////////////////////////////// /////////////////////////////////ver 1.6 by Tomas C//////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// /* Brain game is a small game to pratice math. The game has an Oled display to show questions and Answers. You can choose from 8 different modes and 4 different levels using the select button and the Ok Button. From Main menu page 1 you can select Addition, Subtraction, Multiplication or Division. From Main menu page 2 you can choose from Bin or Hex conversion, practice analog clock reading and a random mode. The random mode will choose from the first four game at seleted level. Holding the back button for more then 1 sec vill toggle the sound on/off, holding the button for more then 3 sec will store the latest game, level and sound state before shutoff, (if AutoPower is def). If not pressing any button for more then 60Sec you will have a warning 5 Sec before the game stores it current states and shut down to save batteries. ///////////////////////////////////Connections///////////////////////////////////// The oled display is connected: Vcc 5V, GND-ground, SDA-Analog4, SCL-Analog5. Select Button Pin 10:use pullup 10K OK Button Pin 7:use pullup 10K Back Button Pin 9:Use pullup 10K Piezo Pin 6 Auto power off control pin 8 ////////////////////////////////////////////////////////////////////////////////////////7777 The Sketch uses the u8g2 lib for the display. see copyrigts and download info below. U8g2lib.h C++ Arduino wrapper for the u8g2 struct and c functions for the u8g2 library Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) Copyright (c) 2016, olikraus@gmail.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Note: U8x8lib.h is included for the declaration of the helper functions in U8x8lib.cpp. U8g2 class is based on the u8g2 struct from u8g2.h, the U8x8 class from U8x8lib.h is not used. */ #define AUTOPOWER //Exclude this line for standard version #include #include #ifdef AUTOPOWER #include #endif ////////////////Display//////////////// U8G2_SSD1306_128X64_NONAME_2_HW_I2C oled(U8G2_R0, /*reset=*/ U8X8_PIN_NONE); ////////////Buttons and Pins///////////////////////// #define SELECT 10 // selectbutton on Digital pin 10 #define OK 7 // ok Button on Digital pin 7 #define BACK 9 //Return button 9 #define SOUND_PIN 6 // Buzzer #ifdef AUTOPOWER #define AutoPower_PIN 8//PowerControl #endif boolean BUZZ = true; int debounce(150); ///////////////Calc Variables///////////////////////// int x; //Variable 1 Holds randomnumbers for calculation int y; //Variable 2 Holds randomnumbers for calculation int x2; //Variable to check if same equation is done two times in row int y2; int ANSWER; // Hold Aswer //////////Control variables/////////////////////////// boolean HOLD = false; boolean play = false; byte MENU = 1; byte SELECT_GAME = 1; byte SELECT_LEVEL = 1; byte Game; byte Level = 1; byte calcFlag; boolean Ready = true; #ifdef AUTOPOWER const byte startadress = 0; //EEPROM Startadress const byte EEPROM_ID = 0x98;//to track valid data in EEPROM #endif //////////////Timing///////////////////////// int stoptime [5] = {4000, 6000, 8000, 10000};//Time to think unsigned long beeptimer = millis(); unsigned long timeout = millis(); #ifdef AUTOPOWER const long warningTime = 60000; //AutoShutoff time #endif /////////Print Variables//////////////////// byte printy [9] = {25, 35, 45, 55, 25, 35, 45, 55}; //print y position variable byte POS_X = 20;//x for Menu char ARITHMETIC[5] = {'+', '-', '*', '/'}; String LEVELS [5] = {"LEVEL1", "LEVEL2", "LEVEL3", "LEVEL4"}; char PrintBuffer[20]; //sprintf Buffer //byte pos = 35; //print x pos for answer ///////////////////CLOCK///////////////////// byte clockCentreX = 84; byte clockCentreY = 32; byte circledia = 30; int minutes = 0; int hours = 0; byte rollMode = 1; /////////////Picture//////////////////////////// #define mute_width 10 #define mute_height 10 static const unsigned char mute_bits[]U8X8_PROGMEM = { 0x00, 0x00, 0x62, 0x00, 0x74, 0x00, 0x78, 0x00, 0x74, 0x00, 0x6c, 0x00, 0x5c, 0x00, 0xb0, 0x00, 0x60, 0x01, 0x00, 0x00 }; #ifdef AUTOPOWER #define Electricity_width 32 #define Electricity_height 32 static const unsigned char Electricity_bits[] U8X8_PROGMEM = { 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xcf, 0xf3, 0x0f, 0xf8, 0xcf, 0xf3, 0x1f, 0xf8, 0xdf, 0xf3, 0x1f, 0xfc, 0xcf, 0xf3, 0x3f, 0xfe, 0xcf, 0xf3, 0x7f, 0xfe, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0x01, 0x80, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x2f, 0xf4, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfc, 0xff, 0xfc, 0x3f, 0xfc, 0xff, 0xf8, 0x1f, 0xf8, 0xff, 0xf3, 0x1f, 0xf0, 0xff, 0xe3, 0x0f, 0xe0, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0xf0, 0x0f, 0x00 }; #endif #define brain_width 86 #define brain_height 64 static const unsigned char brain_bits[] U8X8_PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 0xf4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x01, 0x01, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x84, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0xa0, 0x20, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x40, 0x08, 0x40, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00, 0x86, 0x02, 0x04, 0x00, 0x80, 0x10, 0x0c, 0x00, 0x00, 0x00, 0xc0, 0x10, 0x00, 0x20, 0x02, 0x06, 0x8d, 0x11, 0x00, 0x00, 0x00, 0x30, 0x02, 0x01, 0x20, 0x80, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x44, 0x00, 0x05, 0x21, 0x40, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x12, 0x14, 0x86, 0x10, 0x21, 0x00, 0x32, 0x88, 0x00, 0x00, 0x80, 0x05, 0x11, 0x00, 0x08, 0x10, 0x04, 0x00, 0x04, 0x01, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x06, 0x00, 0x40, 0x20, 0x0c, 0x10, 0x44, 0x08, 0x08, 0x04, 0x02, 0x0c, 0x00, 0x40, 0x02, 0x00, 0x50, 0x01, 0x04, 0x00, 0x10, 0x80, 0x08, 0x00, 0x30, 0x10, 0x80, 0x0b, 0x20, 0x00, 0x00, 0x20, 0x42, 0x18, 0x00, 0x28, 0x24, 0x20, 0x04, 0x00, 0x02, 0x00, 0x80, 0x20, 0x20, 0x00, 0x24, 0x00, 0x08, 0x04, 0x08, 0x02, 0x00, 0x01, 0x09, 0x48, 0x00, 0x24, 0x00, 0x04, 0x40, 0x04, 0x00, 0x80, 0x00, 0x85, 0x40, 0x00, 0x04, 0x80, 0x00, 0x04, 0x04, 0x82, 0x40, 0x80, 0x00, 0x4a, 0x00, 0x02, 0x06, 0x02, 0x00, 0x00, 0x00, 0x42, 0x80, 0x00, 0x80, 0x00, 0x82, 0x08, 0x80, 0x04, 0x00, 0x02, 0x2c, 0x00, 0x00, 0x80, 0x01, 0x02, 0x00, 0x84, 0x04, 0x04, 0xc0, 0x15, 0x40, 0x08, 0x15, 0x01, 0x82, 0x20, 0x80, 0x00, 0x00, 0x34, 0x40, 0x22, 0x80, 0x20, 0x02, 0x42, 0x00, 0x00, 0x02, 0x01, 0x0c, 0x00, 0x18, 0x10, 0x08, 0x02, 0x22, 0x40, 0x00, 0x80, 0x00, 0x08, 0x00, 0x08, 0x30, 0x00, 0x05, 0x20, 0x80, 0x80, 0x00, 0x00, 0x04, 0x10, 0x04, 0x18, 0x88, 0x04, 0x22, 0x02, 0x80, 0x21, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x01, 0xdf, 0x01, 0x00, 0x22, 0x10, 0x00, 0x08, 0x04, 0x08, 0x00, 0xc1, 0x00, 0x00, 0x00, 0x80, 0x12, 0xe0, 0x08, 0x84, 0x00, 0x00, 0x30, 0x80, 0x00, 0x00, 0x03, 0x00, 0x0b, 0x12, 0x04, 0x04, 0x20, 0x09, 0x04, 0x00, 0xfc, 0x8c, 0x00, 0x00, 0x14, 0x04, 0x80, 0x12, 0x04, 0x04, 0x80, 0x02, 0x00, 0x00, 0x00, 0x09, 0x08, 0x08, 0x00, 0x03, 0x04, 0x40, 0x00, 0x00, 0x00, 0x20, 0x19, 0x08, 0x00, 0x80, 0x00, 0x00, 0x10, 0x10, 0x00, 0x08, 0x10, 0x10, 0x10, 0x00, 0x40, 0x00, 0x2e, 0x85, 0x20, 0x80, 0x00, 0x01, 0x11, 0x60, 0x00, 0x40, 0x80, 0x80, 0x00, 0x80, 0x3d, 0xb0, 0x00, 0x11, 0x40, 0x20, 0x20, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x80, 0x05, 0x11, 0x20, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x02, 0x10, 0x08, 0x00, 0x00, 0x06, 0x00, 0xfb, 0x43, 0x06, 0x00, 0x0c, 0x00, 0x08, 0x20, 0x00, 0x10, 0xe0, 0x94, 0x7e, 0x01, 0x00, 0xe0, 0x0f, 0x04, 0x00, 0x00, 0x00, 0x9c, 0xc6, 0x28, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x0a, 0xc0, 0xa7, 0x10, 0x26, 0x00, 0x00, 0x00, 0x08, 0x01, 0x50, 0x00, 0x78, 0x49, 0xfe, 0x29, 0x00, 0x00, 0x00, 0x88, 0x00, 0x04, 0xf0, 0x87, 0xaa, 0x04, 0x2b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x4c, 0x38, 0x45, 0x51, 0x1a, 0x00, 0x00, 0x00, 0x20, 0x80, 0x80, 0x81, 0x4a, 0x34, 0x6d, 0x15, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x55, 0x49, 0x9a, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x10, 0x81, 0x54, 0x25, 0xa5, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x80, 0x54, 0xaa, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x82, 0x00, 0x30, 0xed, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xea, 0x62, 0x51, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x52, 0xcd, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x94, 0x9d, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa9, 0x52, 0x4b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x2a, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc4, 0xa5, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void setup() { oled.setI2CAddress(0x3c * 2); //set display adress if needed (default 0x3Cx2 == 0x78) oled.begin(); //Serial.begin(9600); pinMode(OK, INPUT_PULLUP); pinMode(SELECT, INPUT_PULLUP); pinMode(BACK, INPUT_PULLUP); randomSeed(analogRead(A0)); #ifdef AUTOPOWER pinMode(AutoPower_PIN, OUTPUT); digitalWrite(AutoPower_PIN, HIGH); byte id = EEPROM.read(startadress); if (id == EEPROM_ID) { SELECT_GAME = EEPROM.read(startadress + 1); SELECT_LEVEL = EEPROM.read(startadress + 2); BUZZ = EEPROM.read(startadress + 3); } #endif tone(SOUND_PIN, 1000, 50); //////////DRAW INTRO PICTURE//////////////////////////////// oled.firstPage(); do { oled.drawXBMP(21, 0, brain_width, brain_height, brain_bits); oled.setFont(u8g_font_helvB10); oled.drawStr(25, 30, "Brain Game"); oled.setFont(u8g2_font_profont11_mf); oled.drawStr(10, 60, "ver1.6"); oled.drawStr(60, 60, " by Tomas C"); } while (oled.nextPage()); delay(5000); /////////////////////End Of Intro Picture/////////////////// if (BUZZ) { for (int i = 800; i < 1600; i = i + 200) { tone(SOUND_PIN, i, 200); delay(150); } } } void loop() { ////////////////Star Program Loop////////////////////////////// int x1;//Variable for Subtraktion to shift to avoid negativ numbers in equation int y1;//Variable for Subtraktion ////////////////////////////LEVELS Min Max RND NUMBERS///////////// int LevelAddx[4][4] = {{1, 5, 10, 10}, //Addition Range x {11, 21, 50, 100} }; int LevelAddy[4] [4] = {{1, 5, 10, 10},//Addition Range y {11, 21, 50, 100} }; int LevelSubx[4][4] = {{1, 5, 10, 10}, //Subtraction Range x {11, 21, 50, 100} }; int LevelSuby[4][4] = {{1, 5, 10, 10},//Subtraction Range y {11, 21, 50, 100} }; int LevelMulx[4][4] = {{1, 5, 5, 20}, //Multiplication Range x {11, 21, 50, 100} }; int LevelMuly[4][4] = {{1, 5, 5, 20},//Multiplication Range y {11, 21, 50, 100} }; int LevelDivx[4][4] = {{2, 2, 2, 2},// Division Range x {11, 21, 100, 500} }; int LevelDivy[4][4] = {{2, 2, 2, 2},// Division Range y {11, 21, 100, 500} }; int LevelBinx[4][4] = {{1, 16, 32, 54}, // Bin random range {16, 64, 128, 256} }; int LevelHexx[4][4] = {{8, 16, 32, 64}, // Hex random range {16, 32, 128, 256} }; ///////////////////////////////////////////////////////////////////// //////////////////////////Check Buttom//////////////////////////////// CheckSelect(); CheckOk(); CheckBack(); //////////////////////////Select MENUE////////////////////////////// DispMeny(); //////////////////////////////////////////////////////////////////// ////////////////////////////Select Game///////////////////////////// if (play == true) { Game = SELECT_GAME; if (SELECT_GAME == 8) { Game = random(1, 5); } switch (Game) { // switch to selected Arithmetic case 1: ///////////////////////////ADDITION/////////////////////////////// do { x = random(LevelAddx[0][SELECT_LEVEL - 1], (LevelAddx[1][SELECT_LEVEL - 1])); // Create random X number in randomrange from Addtion level Array X y = random(LevelAddy[0][SELECT_LEVEL - 1], (LevelAddy[1][SELECT_LEVEL - 1])); // Create random Y number in randomrange from Addtion level Array Y } while (x2 == x && y2 == y); x2 = x; y2 = y; printQ(); ANSWER = x + y; //calculate answer printA(); break; case 2: /////////////////////////////SUBTRAKTION//////////////////////////// do { x1 = random(LevelSubx[0][SELECT_LEVEL - 1], LevelSubx[1][SELECT_LEVEL - 1]); // Create random X number in randomrange from Subtraction level Array X y1 = random(LevelSuby[0][SELECT_LEVEL - 1], LevelSuby[1][SELECT_LEVEL - 1]); // Create random Y number in randomrange from Subtraction level Array Y x = max(x1, y1); //Convert random to avoid negativ equation y = min(x1, y1); //Convert random to avoid negativ equation } while (x2 == x && y2 == y); x2 = x; y2 = y; printQ(); ANSWER = x - y; //Calculate the answer printA(); break; case 3: //////////////////////////Multiplikation///////////////////////// do { x = random(LevelMulx[0][SELECT_LEVEL - 1], LevelMulx[1][SELECT_LEVEL - 1]); // Create random X number in randomrange from Multiplication level Array X y = random(LevelMuly[0][SELECT_LEVEL - 1], LevelMuly[1][SELECT_LEVEL - 1]); // Create random Y number in randomrange from Multiplication level Array y } while (x2 == x && y2 == y); x2 = x; y2 = y; printQ(); ANSWER = x * y; //Calculate the answer printA(); break; case 4: ///////////////////////////Division////////////////////////////////// //int x2; //Variable to check if same equation is done two times in row //int y2;// int CheckDiv; // Check division do { do { x1 = random(LevelDivx[0][SELECT_LEVEL - 1], LevelDivx[1][SELECT_LEVEL - 1]); // Create random X number in randomrange from Divison level Array X y1 = random(LevelDivy[0][SELECT_LEVEL - 1], LevelDivy[1][SELECT_LEVEL - 1]); // Create random Y number in randomrange from Divison level Array Y x = max(x1, y1); y = min(x1, y1); // convert numbers to avoid y is greater than x divission CheckDiv = x % y; //check if equation is even with no floting point numbers in the answer } while (CheckDiv != 0); //Runs while equation result not is even. } while (x2 == x && y2 == y); // Check to avoid the same equation second time x2 = x; y2 = y; printQ(); ANSWER = x / y; printA(); break; case 5: { /////////////////////BINARY /////////////////////////////////// do { x = random(LevelBinx[0][SELECT_LEVEL - 1], LevelBinx[1][SELECT_LEVEL - 1]); } while (x == x2); x2 = x; printBinQ(); printBinA(); break; } case 6: { ///////////////////HEXA DEC///////////////////////////////////// do { x = random(LevelHexx[0][SELECT_LEVEL - 1], LevelHexx[1][SELECT_LEVEL - 1]); } while (x == x2); x2 = x; printHexQ(); printHexA(); break; } case 7: { ///////////////////ANALOG CLOCK/////////////////////////////// HOLD = true; //hold clock Clock(); CheckOk(); if (HOLD == false) {// Scramble time rollMode = 0; randomGenerator(); Clock(); slow(); //time = millis(); rollMode = 2; Clock(); break; } } } //END OF SWITCH GAME// } //END OF GAME CONTROL// } //END MAIN PROGRAM LOOP/// /////////////////FUNCTIONS/////////////////////// //Check Select Button// void CheckSelect() { switch (MENU) { case (1): //Game Change// if (digitalRead(SELECT) == LOW) {//Check Select for game change delay(debounce); SELECT_GAME = (SELECT_GAME % 8) + 1; timeout = millis(); } break; case (2): //LEVEL Change// if (digitalRead(SELECT) == LOW) {//Ceck Select for Level Change delay(debounce); SELECT_LEVEL = (SELECT_LEVEL % 4) + 1; timeout = millis(); } break; } } //END OF Check Select Button// //Check OK Button// void CheckOk() { #ifdef AUTOPOWER Check_On_Time(); #endif if (digitalRead(OK) == LOW) { //Check OK Button delay(debounce); timeout = millis(); HOLD = false; if (MENU == 3) { play = true; } else play = false; if (MENU < 3) { MENU = MENU + 1; } if (SELECT_GAME == 7) { MENU = 3; } } } //END OF Check OK Button// //Check Back Button// void CheckBack() { if (digitalRead(BACK) == LOW) { //Check Back Button unsigned long longpress = millis(); timeout = millis(); while (digitalRead(BACK) == LOW) {} delay(debounce); if (millis() - longpress > 3000) { #ifdef AUTOPOWER store_data(); #endif } else if (millis() - longpress > 1000) {//Calculate long press BUZZ = !BUZZ; //Switch BUZZ ON/OFF if (BUZZ) { tone(SOUND_PIN, 800, 50); } } else { HOLD = false; play = false; rollMode = 1; if (MENU > 1) { MENU = MENU - 1; } if (SELECT_GAME == 7) { MENU = 1; } } } } //END OF Check Back Button// //Display Select// void DispMeny() { switch (MENU) {//Select meny to print case (1): selectgame(); break; case (2): if (SELECT_GAME != 7) { level(); } break; case (3): playgame(); break; } } //END of Display Select// //Draw Game Menue// void selectgame() { oled.firstPage(); do { if (!BUZZ) { oled.drawXBMP(112, 0, mute_width, mute_height, mute_bits); } oled.setFont(u8g_font_helvB10); oled.drawStr(10, 12, "Select Game"); if (SELECT_GAME < 5) { /////First Page //// oled.setFont(u8g2_font_profont11_mf); oled.drawStr(80, 60, "page1(2)"); oled.setCursor(POS_X, printy[0]); // first iteim oled.println("ADDITION"); oled.setCursor(POS_X, printy[1]); oled.println("SUBTRACTION"); oled.setCursor(POS_X, printy[2]); oled.println("MULTIPLICATION"); oled.setCursor(POS_X, printy[3]); oled.println("DIVISION"); } else if (SELECT_GAME > 4) { ////Second Page//// oled.setFont(u8g2_font_profont11_mf); oled.drawStr(80, 60, "page2(2)"); oled.setCursor(POS_X, printy[4]); oled.print("BIN"); oled.setCursor(POS_X, printy[5]); oled.print("HEX"); oled.setCursor(POS_X, printy[6]); oled.print("CLOCK"); oled.setCursor(POS_X, printy[7]); oled.print("RANDOM"); } oled.drawBox(POS_X - 10, (printy[SELECT_GAME - 1] - 5), 5, 5); } while (oled.nextPage()); delay(10); } //END OF DRAW GAME MENUE// //Draw Level Menue// void level() { oled.firstPage(); do { if (!BUZZ) { oled.drawXBMP(112, 0, mute_width, mute_height, mute_bits); } oled.setFont(u8g_font_helvB10); oled.drawStr(10, 12, "Select Level"); oled.setFont(u8g2_font_profont11_mf); oled.setCursor(POS_X, printy[0]); // first iteim oled.println(LEVELS[0]); oled.setCursor(POS_X, printy[1]); oled.println(LEVELS[1]); oled.setCursor(POS_X, printy[2]); oled.println(LEVELS[2]); oled.setCursor(POS_X, printy[3]); oled.println(LEVELS[3]); oled.drawBox(POS_X - 10, (printy[SELECT_LEVEL - 1] - 5), 5, 5);//draw box for selected level } while (oled.nextPage()); delay(10); } //END DRAW LEVEL MENUE// //Draw Play Game Menue// void playgame() { if (play == false) { oled.firstPage(); do { if (!BUZZ) { oled.drawXBMP(112, 0, mute_width, mute_height, mute_bits); } oled.drawFrame(15, 10, 90, 30); oled.setFont(u8g_font_helvB10); oled.drawStr(23, 30, "Play Game"); oled.setFont(u8g2_font_profont11_mf); oled.drawStr(10, 60, "Yes=OK"); oled.drawStr(80, 60, "No=BACK"); } while (oled.nextPage()); delay(10); } } //END DRAW PLAY GAME MENUE// //Print Question Menue// void printQ() { sprintf(PrintBuffer, "%d %c %d=?", x, ARITHMETIC[Game - 1], y);//Format print unsigned long gametime = millis();// Store play time before answer int i = 0; do { oled.firstPage(); do { oled.drawBox(64, 47, i, 5); // draw time bar oled.drawBox(64 - i, 47, i, 5); oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 10); oled.print("Calculate the Answer"); oled.drawLine(0, 12, 128, 12); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } oled.setFont(u8g_font_helvB10); oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); } while (oled.nextPage()); i = map(stoptime[SELECT_LEVEL - 1] - (millis() - gametime), 0, stoptime[SELECT_LEVEL - 1], 0, 64);// Map PlayTime Before Answer i = 64 - i; beepTimer(); } while (millis() - gametime < stoptime[SELECT_LEVEL - 1] && digitalRead(BACK) == HIGH); //Wait for time to run out if (BUZZ) { tone(SOUND_PIN, 600, 1000); } delay(10); } //END PRINT QUESTION// //Print Answer// void printA() { sprintf(PrintBuffer, "%d %c %d=%d", x, ARITHMETIC[Game - 1], y, ANSWER); //Format print do { HOLD = true; CheckOk(); CheckBack(); oled.firstPage(); do { oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); oled.setCursor(15, 11); oled.print("The Answer is"); oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer);//Print formated Answer oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } oled.drawStr(15, 60, "New Task press OK"); } while (oled.nextPage()); } while (HOLD == true && play == true); delay(10); } //END PRINT ANSWER// //Print Question BIN// void printBinQ() { delay(debounce); calcFlag = (random(0, 2)); do { HOLD = true; play = true; CheckOk(); CheckBack(); oled.firstPage(); do { oled.drawFrame(0, 25, 128, 25);//22,25 oled.setFont(u8g2_font_profont11_mf); oled.drawStr(5, 60, "Press When Ready"); if (Ready) { oled.setCursor( 38, 60); oled.print("OK"); } oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } if (calcFlag == 0) { oled.setCursor(10, 10); oled.print("Convert to Binary"); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); sprintf(PrintBuffer, "%d", x); oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); oled.setCursor(3, 46); oled.setFont(u8g2_font_profont11_mf); oled.print("dec"); } else { oled.setCursor(10, 10); oled.print("Convert to Decimal"); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); byte bits = 8; byte posx = 100; byte pos; if (x < 16) { pos = 45; posx = 90; bits = 4; } else pos = 30; oled.setCursor(pos, 43);//35 if (x == 0 || x == 1 || (x > 15 && x < 32)) { //Format Binary printout oled.print("000"); } if ((x > 1 && x < 4) || (x > 31 && x < 64)) {//Format Binary printout oled.print("00"); } if ((x > 3 && x < 8) || (x > 63 && x < 128)) {//Format Binary printout oled.print("0"); } oled.print(x, 2);//Print Binary oled.setCursor(posx, 46); oled.setFont(u8g2_font_profont11_mf); oled.print(bits); oled.print("bit"); } } while (oled.nextPage()); beepTimer(); } while (HOLD == true && play == true); delay(10); } ///End Print BIN Question// //Print Bin Answer// void printBinA() { do { HOLD = true; CheckOk(); CheckBack(); oled.firstPage(); do { oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); oled.setCursor(15, 11); oled.print("The Answer is"); oled.drawFrame(0, 25, 128, 25);//17,28 if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } if (calcFlag == 1) { sprintf(PrintBuffer, "%d", x);//Format print oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); oled.setFont(u8g2_font_profont11_mf); oled.setCursor(3, 46); oled.print("dec"); } else { byte bits = 8; byte pos; if (x < 16) { pos = 45; bits = 4; } else pos = 30; oled.setCursor(pos, 43); if (x == 0 || x == 1 || (x > 15 && x < 32)) { oled.print("000"); } if ((x > 1 && x < 4) || (x > 31 && x < 64)) { oled.print("00"); } if ((x > 3 && x < 8) || (x > 63 && x < 128)) { oled.print("0"); } oled.print(x, 2);//Print Binary oled.setCursor(100, 46); oled.setFont(u8g2_font_profont11_mf); oled.print(bits); oled.print("bit"); oled.setCursor(3, 46); oled.print("Bin"); } oled.setFont(u8g2_font_profont11_mf); oled.drawStr(15, 60, "New Task press OK"); } while (oled.nextPage()); } while (HOLD == true && play == true); delay(10); } void printHexQ() { delay(debounce); calcFlag = (random(0, 2)); do { HOLD = true; play = true; CheckOk(); CheckBack(); oled.firstPage(); do { oled.drawFrame(0, 25, 128, 25); oled.setFont(u8g2_font_profont11_mf); oled.drawStr(5, 60, "Press When Ready"); if (Ready) { oled.setCursor( 38, 60); oled.print("OK"); } oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } oled.drawLine(0, 12, 128, 12); if (calcFlag == 0) { oled.setCursor(20, 10); oled.print("Convert to Hex"); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); sprintf(PrintBuffer, "%d", x);//Format print oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); oled.setCursor(3, 46); oled.setFont(u8g2_font_profont11_mf); oled.print("dec"); } else { oled.setCursor(10, 10); oled.print("Convert to Decimal"); oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); sprintf(PrintBuffer, "0x %X", x);//Format Hex Print oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43);//Calculate print X oled.print(PrintBuffer); oled.setCursor(3, 46); oled.setFont(u8g2_font_profont11_mf); oled.print("Hex"); } } while (oled.nextPage()); beepTimer(); } while (HOLD == true && play == true); //Wait for Answer delay(10); } //END Print HEX Question// //Print HEX Answer// void printHexA() { do { HOLD = true; CheckOk(); CheckBack(); oled.firstPage(); do { oled.setFont(u8g2_font_profont11_mf); oled.setCursor(0, 22); oled.print(LEVELS[SELECT_LEVEL - 1]); if (!BUZZ) { oled.drawXBMP(110, 14, mute_width, mute_height, mute_bits); } oled.drawLine(0, 12, 128, 12); oled.setFont(u8g_font_helvB10); oled.setCursor(15, 11); oled.print("The Answer is"); oled.drawFrame(0, 25, 128, 25); if (calcFlag == 1) { sprintf(PrintBuffer, "%d", x); oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); oled.setFont(u8g2_font_profont11_mf); oled.setCursor(3, 46); oled.print("dec"); } else { sprintf(PrintBuffer, "0x %X", x); //Format Hex Printout oled.setCursor((oled.getWidth() - oled.getStrWidth(PrintBuffer)) / 2, 43); oled.print(PrintBuffer); oled.setFont(u8g2_font_profont11_mf); oled.setCursor(3, 46); oled.print("Hex"); } oled.drawStr(15, 60, "New Task press OK"); } while (oled.nextPage()); } while (HOLD == true && play == true); delay(10); } //END Print HEx Answer// //Draw Analog Clock// void Clock() { oled.firstPage(); do { oled.setFont(u8g2_font_profont11_mf); //Print instructions // if (rollMode == 1) { oled.drawStr(8, 12, "Press"); oled.drawStr(8, 22, "OK"); oled.drawStr(8, 32, "for");//40 oled.drawStr(8, 42, "new"); oled.drawStr(8, 52, "Time"); } else if (rollMode == 0) { oled.drawStr(8, 12, "Shuffle"); oled.drawStr(8, 22, "Time"); oled.drawStr(8, 32, "For"); oled.drawStr(8, 42, "You!"); } else if (rollMode == 2) { oled.drawStr(8, 12, "Do You"); oled.drawStr(8, 22, "know"); oled.drawStr(8, 32, "What"); oled.drawStr(8, 42, "Time"); oled.drawStr(8, 52, "it is ?"); } //Draw Clock// oled.setFont(u8g2_font_profont11_mn); oled.drawStr(clockCentreX + 18, clockCentreY + 3, "3"); //82Y35 oled.drawStr(clockCentreX - 21, clockCentreY + 3, "9"); //x43y35 oled.drawStr(clockCentreX - 2, clockCentreY + 23, "6"); //x62Y55 oled.drawStr(clockCentreX - 4, clockCentreY - 16, "12"); //X60Y16 //Draw The Clock Face// oled.drawCircle(clockCentreX, clockCentreY, circledia); //main outer circle oled.drawCircle(clockCentreX, clockCentreY, circledia + 1); // main outer circle2 oled.drawCircle(clockCentreX, clockCentreY, 2); // small inner circle oled.drawCircle(clockCentreX, clockCentreY, 2 + 1);// Small inner circle2 //Draw ClockMark// for ( int z = 0; z < 360; z = z + 30 ) { //Begin at 0° and stop at 360° float angle = z ; angle = (angle / 57.29577951) ; //Convert degrees to radians int x2 = (clockCentreX + (sin(angle) * circledia)); int y2 = (clockCentreY - (cos(angle) * circledia)); int x3 = (clockCentreX + (sin(angle) * (circledia - 5))); int y3 = (clockCentreY - (cos(angle) * (circledia - 5))); oled.drawLine(x2, y2, x3, y3); } //Draw Minute// float angle = minutes; angle = (angle / 57.29577951) ; //Convert degrees to radians int x3 = (clockCentreX + (sin(angle) * (circledia - 3))); int y3 = (clockCentreY - (cos(angle) * (circledia - 3))); oled.drawLine(clockCentreX, clockCentreY, x3, y3); //Draw Hour// angle = hours + (minutes / 12); angle = (angle / 57.29577951) ; //Convert degrees to radians x3 = (clockCentreX + (sin(angle) * (circledia - 11))); y3 = (clockCentreY - (cos(angle) * (circledia - 11))); oled.drawLine(clockCentreX, clockCentreY, x3, y3); if (!BUZZ) { oled.drawXBMP(112, 0, mute_width, mute_height, mute_bits); } } while (oled.nextPage()); delay(100); } //END DRAW ANALOG CLOCK// //Random For Clock// void randomGenerator () { minutes = random(0, 12) * 30; hours = random(0, 12) * 30; if (BUZZ) { tone(SOUND_PIN, 700, 80); } } //End Of Random// //Slow Down Clock Before Stop// void slow() { int d = 0; for (int i = 0; i < (random(7, 30)); i++) { randomGenerator(); Clock(); delay(d); d = d + 50; } if (BUZZ) { tone(SOUND_PIN, 800, 500); } } //End Slow Down// //Check On Time// #ifdef AUTOPOWER void Check_On_Time() { if (millis() - timeout > warningTime) { do { if (! digitalRead(OK) || !digitalRead(BACK) || !digitalRead(SELECT)) { timeout = millis(); delay(250); } oled.firstPage(); do { oled.setFont(u8g2_font_profont11_mf); oled.setCursor(20, 10); oled.print("Auto Power Off"); oled.setCursor(15, 60); oled.print("Press ok to reset"); beepTimer(); if (Ready) { oled.drawXBMP(48, 16, Electricity_width, Electricity_height, Electricity_bits); } } while (oled.nextPage()); delay(10); if (millis() - timeout > warningTime + 10000) { store_data(); } } while (millis() - timeout > warningTime) ; } } //END Check On Time// #endif //Beep Control// void beepTimer() { if (millis() - beeptimer > 750) { if (BUZZ) { tone(SOUND_PIN, 1000, 200); } beeptimer = millis(); Ready = !Ready; } } //End Beep Control// #ifdef AUTOPOWER void store_data() { oled.firstPage(); do { oled.setFont(u8g_font_helvB10); oled.setCursor(20, 30); oled.print("GoodBye!"); } while (oled.nextPage()); delay(1000); EEPROM.write(startadress, EEPROM_ID); EEPROM.write(startadress + 1, SELECT_GAME); EEPROM.write(startadress + 2, SELECT_LEVEL); EEPROM.write(startadress + 3, BUZZ); delay(50); digitalWrite(AutoPower_PIN, LOW); delay(10000);//Wait for power to drain } #endif