diff --git a/Firmware Code/KICKER_V2/COMM.ino b/Firmware Code/KICKER_V2/COMM.ino index 103a79c..ed0e1e9 100644 --- a/Firmware Code/KICKER_V2/COMM.ino +++ b/Firmware Code/KICKER_V2/COMM.ino @@ -27,7 +27,7 @@ } if(event == ESP_SPP_CLOSE_EVT ) { BLUETOOTH_STATUS = false; - terminal(BLUETOOTH_DISCONNECTED); + terminal(STAND_ALONE_MODE); } } //------------------------------------------------------ diff --git a/Firmware Code/KICKER_V2/GCNT.ino b/Firmware Code/KICKER_V2/GCNT.ino index 6fc4b44..71dd5cf 100644 --- a/Firmware Code/KICKER_V2/GCNT.ino +++ b/Firmware Code/KICKER_V2/GCNT.ino @@ -24,11 +24,14 @@ void game_counter_standalone() { // Variables Of The Game - uint16_t limit = 0; - bool limitEnable = 0; + uint16_t limit = 10; + bool limitEnable = true; // Play The Game game_counter(limit, limitEnable); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //====================================================== @@ -87,6 +90,9 @@ // Play The Game game_counter(limit, limitEnable); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //====================================================== @@ -101,6 +107,9 @@ // Game Start Lights //LED_SIGNAL_START(); + // Display On OLED + GAME_COUNTER_DISPLAY(0, limit); + //------------------------- // PREPARE FOR GAME START //------------------------- @@ -129,20 +138,51 @@ } else if(msg == CM_RESET) { + // Counter Reset To Zero counter = 0; + + // Starting Stamp From Now startStamp = millis(); + + // Time Stamp Is Now timeStamp = startStamp; + + // LED STRIP LED STRIP RESET SIGNAL //LED_SIGNAL_RESET(); } } + // Reset The Counter + if(BTN_INCREASE.pressed()) { + counter = 0; + startStamp = millis(); + timeStamp = startStamp; + GAME_COUNTER_DISPLAY(counter, limit); + } + + // Will Exit The Game + if(BTN_CENTER.pressed()) { + // Send Game Over JSON Signal + dualcomm(GAME_OVER); + + // Give Permition To Change OLED + DISPLAY_CHANGED = false; + + // Return To Main Menu + return; + } + // If Limits Are Enabled And Meet - if(limitEnable == true && counter == limit) - { + if(limitEnable == true && counter == limit) { // END GAME dualcomm(GAME_OVER); + // Celebration //LED_SIGNAL_CELEBRATION(); + + // Display On OLED + GAME_RESULT_DISPLAY(counter, limit); + // RESET return; } @@ -151,7 +191,7 @@ if(PIEZO_MAP >= VTH) { counter++; - GAME_COUNTER_DISPLAY(counter); + GAME_COUNTER_DISPLAY(counter, limit); dualcomm(counter_JSON_json(counter, timeStamp)); delay(100); } @@ -182,11 +222,43 @@ // OLED - GAME COUNTER PLAY //------------------------------------------------------ - void GAME_COUNTER_DISPLAY(uint16_t count) + void GAME_COUNTER_DISPLAY(uint16_t count, uint16_t limit) { OLED_CLEAR(); drawTextCenter(128/2, 0, 2, "KICKS"); - drawTextCenter(128/2, 20, 3, String(count)); - drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + drawTextCenter(128/2, 20, 3, String(count) + "/" + String(limit)); + + // Exit Button Command Only Via Stand Alone Mode + if(BLUETOOTH_STATUS == false) { + drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + } + OLED_SHOW(); } + +//------------------------------------------------------ +// OLED - GAME COUNTER RESULT +//------------------------------------------------------ + + void GAME_RESULT_DISPLAY(uint16_t count, uint16_t limit) + { + OLED_CLEAR(); + drawTextCenter(128/2, 0, 2, "FINISHED"); + drawTextCenter(128/2, 20, 3, String(count) + "/" + String(limit)); + + // Exit Button Command Only Via Stand Alone Mode + if(BLUETOOTH_STATUS == false) { + drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + } + + // Show Data On OLED + OLED_SHOW(); + + // Waiting For Center Button To Move On + while(1){ + if(BTN_CENTER.pressed()) { + break; + } + } + } + diff --git a/Firmware Code/KICKER_V2/GREA.ino b/Firmware Code/KICKER_V2/GREA.ino index 98766e6..7aaf426 100644 --- a/Firmware Code/KICKER_V2/GREA.ino +++ b/Firmware Code/KICKER_V2/GREA.ino @@ -17,13 +17,6 @@ * in seconds. so the athlete know how long he takes to react */ - // Game Reaction DataType - struct grdt { - uint8_t trials = 0; // Number Of Strike Trials - uint8_t minDelay = 0; // Minimum Seconds Delay Between Signals - uint8_t maxDelay = 0; // Maximum Seconds Delay Between Signals - }; - //------------------------------------------------------ // Request From Stand Alone Buttons //------------------------------------------------------ @@ -31,17 +24,15 @@ void game_reaction_standalone() { // Variables - uint8_t minDelay = 0; - uint8_t maxDelay = 0; - uint8_t trials = 0; + uint8_t minDelay = 1; + uint8_t maxDelay = 3; + uint8_t trials = 10; - // Display Screen Menu And Button Actions - // If The Menu Number 1 -> We Set The Value Of Min Delay - // If The Menu Number 2 -> We Set The Value Of Max Delay - // If The Menu Number 3 -> We Set The Number Of Trials - // Call the Game Play play_reaction(minDelay, maxDelay, trials); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //------------------------------------------------------ @@ -99,6 +90,9 @@ // Play The Game play_reaction(minDelay, maxDelay, trials); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //------------------------------------------------------ @@ -108,7 +102,7 @@ void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials) { // PUBLIC VARIABLES - uint16_t temp = trials; + double totalRes = 0.0; // Fix Random Error maxDelay += 1; @@ -138,6 +132,9 @@ // Ready Signal //LED_SIGNAL_REACTION_START(); + // Display On OLED + GAME_REACTION_DISPLAY(0, 0); + //------------------------- // PREPARE FOR GAME START //------------------------- @@ -161,7 +158,7 @@ startTime = millis(); // Sensing Strike Power - while(power < VTH) + while(power < VTH) { // Reading The Strike power = PIEZO_MAP; @@ -181,10 +178,39 @@ } else if(msg == CM_RESET) { //LED_SIGNAL_REACTION_RESET(); - trials = temp; - break; + i = 0; + sdelay = 0; + power = 0; + response = 0; + startTime = millis(); + stopTime = millis(); + totalRes = 0; + DISPLAY_CHANGED = false; + GAME_REACTION_DISPLAY(i, response); + //break; } } + + // Reset The Counter + if(BTN_INCREASE.pressed()) { + //LED_SIGNAL_REACTION_RESET(); + i = 0; + sdelay = 0; + power = 0; + response = 0; + startTime = millis(); + stopTime = millis(); + totalRes = 0; + DISPLAY_CHANGED = false; + GAME_REACTION_DISPLAY(i, response); + } + + // Will Exit The Game + if(BTN_CENTER.pressed()) { + dualcomm(GAME_OVER); + DISPLAY_CHANGED = false; + return; + } } // Stop Timer @@ -195,9 +221,13 @@ // Calculating Response Time response = stopTime - startTime - 1; + totalRes = totalRes + ((float)response/1000); // Create Json JSON String msg = reaction_JSON_json(i+1, power, response, sdelay); + + // Display On OLED + GAME_REACTION_DISPLAY(i+1, response); // Print To Terminal dualcomm(msg); @@ -217,6 +247,9 @@ // Blink Red //LED_SIGNAL_CELEBRATION(); + // Display Result + GAME_REACTION_RESULT(trials, totalRes); + // Return To Game Selector return; } @@ -276,11 +309,38 @@ // OLED GAME PLAY REACTION //------------------------------------------------------ - void GAME_REACTION_DISPLAY(uint16_t count) + void GAME_REACTION_DISPLAY(uint16_t count, float reatime) { OLED_CLEAR(); - drawTextCenter(128/2, 0, 2, "KICKS"); - drawTextCenter(128/2, 20, 3, String(count)); - drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + drawTextCenter(128/2, 0, 2, "KICK : " + String(count)); + drawTextCenter(128/2, 20, 3, "TIME : " + String(((float)reatime/1000), 2)); + + // Exit Button Command Only Via Stand Alone Mode + if(BLUETOOTH_STATUS == false) { + drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + } + OLED_SHOW(); } + +//------------------------------------------------------ +// OLED - GAME TIMEATTACK RESULT +//------------------------------------------------------ + + void GAME_REACTION_RESULT(uint16_t trials, uint16_t total_reaction) + { + OLED_CLEAR(); + float avgReaction = 0.0; + avgReaction = (float)total_reaction/trials; + drawTextCenter(128/2, 0, 2, "RESULT"); + drawTextCenter(128/2, 20, 2, String(avgReaction, 3) + " s"); + drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + OLED_SHOW(); + + // Waiting For Center Button To Move On + while(1){ + if(BTN_CENTER.pressed()) { + break; + } + } + } diff --git a/Firmware Code/KICKER_V2/GSEL.ino b/Firmware Code/KICKER_V2/GSEL.ino index 712968a..1b9f3a9 100644 --- a/Firmware Code/KICKER_V2/GSEL.ino +++ b/Firmware Code/KICKER_V2/GSEL.ino @@ -55,16 +55,14 @@ JSON.clear(); } } - //------------------------------------------------------ // DISPLAY MENU TITLE FUNCTION //------------------------------------------------------ - void GAME_TITLE_DISPLAY(uint8_t Number, String Title) { // Starting The First Code OLED_CLEAR(); - drawTextCenter(128/2, 5, 1, "MODE " + String(Number + 1)); + drawTextCenter(128/2, 5, 1, "GAME #" + String(Number)); drawTextCenter(128/2, 22, 2, " - " + Title + " - "); drawTextCenter(128/2, 43, 1, "<< SELECT >>"); OLED_SHOW(); diff --git a/Firmware Code/KICKER_V2/GTAT.ino b/Firmware Code/KICKER_V2/GTAT.ino index 2737fe5..6f59ea7 100644 --- a/Firmware Code/KICKER_V2/GTAT.ino +++ b/Firmware Code/KICKER_V2/GTAT.ino @@ -17,14 +17,6 @@ * in seconds. so the athlete know how long he takes to react */ - // Game Time Attack DataType - struct gtdt { - uint16_t time = 30; // Max Time Of The Game In Sec - uint16_t limit = 0; // Max Kick Count - bool limit_ena = false; // Enable End Game If Max Kicks Meet - float kicksPerSecond = 0; // Game Time Attack Result - }; - //====================================================== // Request From Stand Alone Buttons //====================================================== @@ -32,18 +24,15 @@ void time_attack_standalone() { // Variables - uint16_t time = 0; - uint16_t timer = 0; - uint16_t limit = 0; - bool limitEnable = 0; - - // Display Screen Menu And Button Actions - // If The Menu Number 1 -> We Set The Value Of Min Delay - // If The Menu Number 2 -> We Set The Value Of Max Delay - // If The Menu Number 3 -> We Set The Number Of Trials + uint16_t time = 30; + uint16_t limit = 10; + bool limitEnable = true; // Call the Game Play - game_timeAttack(time, timer, limit, limitEnable); + game_timeAttack(time, limit, limitEnable); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //====================================================== @@ -94,40 +83,46 @@ } // PUBLIC VARIABLES - uint16_t time = JSON["tm"]; // Time Window To JSON - uint16_t timer = time; - uint16_t limit = JSON["lm"]; // Kick Target Limit - bool limitEnable = JSON["le"]; // Enable Kick Target Limit + const uint16_t time = JSON["tm"]; // Time Window To JSON + uint16_t limit = JSON["lm"]; // Kick Target Limit + bool limitEnable = JSON["le"]; // Enable Kick Target Limit // Clearing Buffer JSON.clear(); // Play The Game - game_timeAttack(time, timer, limit, limitEnable); + game_timeAttack(time, limit, limitEnable); + + // Give Permision To Change Display + DISPLAY_CHANGED = false; } //====================================================== // Play Time Atack Game //====================================================== - void game_timeAttack(uint16_t time, uint16_t timer, uint16_t limit, bool limitEnable) - { + void game_timeAttack(uint16_t time, uint16_t limit, bool limitEnable) + { // Building Timers 1000mSec -> 1Sec TimeTrigger sec_tick(1000); // Kick Counter - uint16_t counter = 0; + uint16_t counter = 0; // This is what counts your kicks + uint16_t timer = time; // This is what your running timer // Start LED Signal //LED_SIGNAL_START(); - //------------------------- - // PREPARE FOR GAME START - //------------------------- + // Initial Display Of Game Data Before Start + GAME_TIMEATTACK_DISPLAY(timer, 0); // Send Initial DisJSON dualcomm(timeAttack_JSON_json(timer, counter, 0, 0)); + //------------------------- + // PREPARE FOR GAME START + //------------------------- + // staring Of time stamp unsigned long startStamp = millis(); @@ -165,24 +160,58 @@ timeStamp = startStamp; lastStamp = timeStamp; sec_tick.Reset(); - dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp)); + GAME_TIMEATTACK_DISPLAY(counter, timer); //LED_SIGNAL_RESET(); } } + + // Reset The Counter + if(BTN_INCREASE.pressed()) { + timer = time; + counter = 0; + startStamp = millis(); + timeStamp = startStamp; + lastStamp = timeStamp; + sec_tick.Reset(); + GAME_TIMEATTACK_DISPLAY(counter, timer); + } + + // Will Exit The Game + if(BTN_CENTER.pressed()) { + dualcomm(GAME_OVER); + DISPLAY_CHANGED = false; + return; + } // Every Kick ---------------------------->>> if(PIEZO_MAP > VTH) { + // Count As A Strike counter++; + + // Display On OLED + GAME_TIMEATTACK_DISPLAY(counter, timer); + + // Send JSON String Out dualcomm(timeAttack_JSON_json(timer, counter, lastStamp, timeStamp)); + + // Time Snap Shot lastStamp = timeStamp; + + // Wait For Analog Sampler To by pass the strike delay(100); } // Every Second ---------------------------->>> if(sec_tick.Trigger()) { + // Decrement Time After Every Second timer--; + + // Display Time And Count Every Second + GAME_TIMEATTACK_DISPLAY(counter, timer); + + // Send JSON String Out dualcomm(timeAttack_JSON_json(timer, counter, 0, 0)); } @@ -191,8 +220,16 @@ { // END GAME dualcomm(GAME_OVER); + + // Time Difference Between Start & Count Down Timer + const uint16_t diff = time - timer; + + // Display The Game Result + GAME_TIMEATTACK_RESULT(counter, diff); + // Celebrate //LED_SIGNAL_CELEBRATION(); + // Return return; } @@ -200,10 +237,15 @@ // Send End Game Signal To Smart Phone dualcomm(GAME_OVER); + + // Display The Result + GAME_TIMEATTACK_RESULT(counter, time); + // LightUp //LED_FADEIN(255, 0, 0); // RED Color - delay(2000); // Delay 2000 + //delay(2000); // Delay 2000 //LED_CLEAR(); // CLEAR OFF + // Return return; } @@ -242,11 +284,33 @@ // OLED - GAME TIMEATTACK PLAY //------------------------------------------------------ - void GAME_TIMEATTACK_DISPLAY(uint16_t count) + void GAME_TIMEATTACK_DISPLAY(uint16_t count, uint16_t time) { OLED_CLEAR(); - drawTextCenter(128/2, 0, 2, "KICKS"); - drawTextCenter(128/2, 20, 3, String(count)); + drawTextCenter(128/2, 0, 2, "TIME ( " + String(time) + " ) Sec"); + drawTextCenter(128/2, 20, 2, "KICKS ( " + String(count) + " )"); drawTextCenter(128/2, 50, 1, "<< EXIT >>"); OLED_SHOW(); } + +//------------------------------------------------------ +// OLED - GAME TIMEATTACK RESULT +//------------------------------------------------------ + + void GAME_TIMEATTACK_RESULT(uint16_t count, uint16_t time) + { + OLED_CLEAR(); + float avgSpeed = 0.0; + avgSpeed = (float)count/time; + drawTextCenter(128/2, 0, 2, "RESULT"); + drawTextCenter(128/2, 20, 2, String(avgSpeed, 2) + " K/s"); + drawTextCenter(128/2, 50, 1, "<< EXIT >>"); + OLED_SHOW(); + + // Waiting For Center Button To Move On + while(1){ + if(BTN_CENTER.pressed()) { + break; + } + } + } diff --git a/Firmware Code/KICKER_V2/KICKER_V2.ino b/Firmware Code/KICKER_V2/KICKER_V2.ino index f211989..2fdd699 100644 --- a/Firmware Code/KICKER_V2/KICKER_V2.ino +++ b/Firmware Code/KICKER_V2/KICKER_V2.ino @@ -44,7 +44,7 @@ //====================================================== // PUBLIC VARIABLES //====================================================== - uint8_t MENU_COUNT = 0; + uint8_t MENU_COUNT = 1; bool BLUETOOTH_STATUS = false; bool CHARGE_STATE = false; bool DISPLAY_CHANGED = false; @@ -94,7 +94,7 @@ //------------------------------------------------------ // Piezo Transducer //------------------------------------------------------ - #define VTH 5 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR + #define VTH 15 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR #define PIEZO_PIN 34 // IMPACT SENSOR #define RANDOM_SOURCE 39 // RANDOM NUMBER GENERATOR SOURCE #define PIEZO_READ analogRead(PIEZO_PIN) @@ -206,25 +206,42 @@ //====================================================== void loop() { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // This Is For Bluetooth Mode + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + if(BLUETOOTH_STATUS == true) { - OLED_BLUETOOTH_MODE(); + // Initialization Of Bluetooth Connected Mode + OLED_BLUETOOTH_MODE(); // Display Bluetooth Connected Mode + DISPLAY_CHANGED = false; // Give Permition To Change The Content + delay(3000); // Hold The Display Content For 3 Seconds + + // While You Are On Bluetooth Connected Mode while(BLUETOOTH_STATUS == true) { - ListenToBluetooth(); // Reading Only From Bluetooth + ListenToBluetooth(); // Reading Only From Bluetooth } - OLED_BLUETOOTH_MODE(); - delay(1000); - terminal(STAND_ALONE_MODE); + + // Give Permition To Change The Content + DISPLAY_CHANGED = false; } + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // This Is For Stand Alone Mode + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + else { - OLED_STANDALONE_MODE(); + // Initialization Of Stand Alone Mode + OLED_STANDALONE_MODE(); // Display Stand Alone Mode + DISPLAY_CHANGED = false; // Give Permition To Change The Content + delay(3000); // Hold The Display Content For 3 Seconds + + // While You Are On Stand Alone Mode while(BLUETOOTH_STATUS == false) { - ListenToStandAlone(); + ListenToStandAlone(); // Enter Listen To Stand Alone Buttons } - OLED_BLUETOOTH_MODE(); - delay(1000); + + // Once The Stand Alone Mode Is Over + DISPLAY_CHANGED = false; // Give Permition To Change The Display } } //------------------------------------------------------ @@ -281,11 +298,12 @@ if(BTN_PREVIOUS.pressed()) { // Checking The Condition Of Order Number - if(MENU_COUNT > 0) { - MENU_COUNT -= 1; - } else { + if(MENU_COUNT == 1 || MENU_COUNT < 1) { MENU_COUNT = 3; // If The Value Equals To Zero Then Roll Back To 4 + } else { + MENU_COUNT -= 1; } + // Give Permition To Change The Screen DISPLAY_CHANGED = false; } @@ -294,12 +312,13 @@ else if(BTN_NEXT.pressed()) { // Checking The Condition Of Order Number - if(MENU_COUNT > 3) + if(MENU_COUNT == 3 || MENU_COUNT > 3) { MENU_COUNT = 1; // If The Value Exceeds 4 Then Roll Back To 1 } else { MENU_COUNT += 1; } + // Give Permition To Change The Screen DISPLAY_CHANGED = false; } @@ -307,21 +326,43 @@ // SELECT CURRENT DISPLAYED MENU else if(BTN_CENTER.pressed()) { - DETECT_LONG_PRESS(); // IF LONG PRESS POWER OFF + // IF LONG PRESS -> POWER OFF KICKER + DETECT_LONG_PRESS(); + + // IF SHORT PRESS -> PLAY GAME CORESPONDING TO NUMBER + switch(MENU_COUNT) + { + case 1: // Play Counter Game + Terminal.println("SELECTED -> GAME COUNTER"); + game_counter_standalone(); + break; + case 2: // Play Time Attack Game + Terminal.println("SELECTED -> GAME TIME ATTACK"); + time_attack_standalone(); + break; + case 3: // Play Reaction Game + Terminal.println("SELECTED -> GAME REACTION"); + game_reaction_standalone(); + break; + } } - // Display The Game Page + // Display The Game Pages if(DISPLAY_CHANGED == false) { + // IF Previous / Next Buttons Are Pressed -> Display Menu Selection On Terminal switch(MENU_COUNT) { - case 1: + case 1: // Play Counter Game + //Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME COUNTER"); GAME_TITLE_DISPLAY(MENU_COUNT, "COUNTER"); break; - case 2: - GAME_TITLE_DISPLAY(MENU_COUNT, "TIMEATTACK"); + case 2: // Play Time Attack Game + //Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME TIME ATTACK"); + GAME_TITLE_DISPLAY(MENU_COUNT, "TIME ATTACK"); break; - case 3: + case 3: // Play Reaction Game + //Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME REACTION"); GAME_TITLE_DISPLAY(MENU_COUNT, "REACTION"); break; }