This commit is contained in:
ghassan committed 2020-05-25 04:56:48 +03:00
1 parent 6b0cd678c1
commit ecbffd73dd
37 files changed
+74 -2002

No files matched your search

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -10,8 +10,8 @@
//====================================================== //======================================================
// HARDWARE SETUP & SELECTION // HARDWARE SETUP & SELECTION
//====================================================== //======================================================
// Arduino Uno Or Nano Was The Hardware // Arduino MEGA
#ifdef ARDUINO_AVR_UNO || ARDUINO_AVR_NANO #ifdef ARDUINO_AVR_MEGA2560
//------------------------------------------------------ //------------------------------------------------------
// Library Nessesary // Library Nessesary
@@ -19,7 +19,41 @@
#include <avr/power.h> #include <avr/power.h>
#endif #endif
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE // Serial Terminal
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
// Bluetooth Terminal
#define Bluetooth Serial1 // We will Connect The HC-05 To Hardware Serial1 In Arduino Mega
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
// JSON Object & Memory
#define CAPACITY 100
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// LED Strip
#define LED_STRIP 53 // LED STRIP PIN NUMBER
#define NUM_PIXELS 14 // NUMBER OF LED'S IN NEO PIXEL STRIP
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_PIXELS, LED_STRIP, NEO_GRB + NEO_KHZ800);
// Impact Detection
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN A0 // IMPACT SENSOR
#define RANDOM_SOURCE A7 // RANDOM NUMBER GENERATOR SOURCE
//------------------------------------------------------
// Arduino Uno / Nano
#elif ARDUINO_AVR_UNO || ARDUINO_AVR_NANO
//------------------------------------------------------
// Library Nessesary
#ifdef __AVR__
#include <avr/power.h>
#endif
/* ARDUINO NANO DOESNOT HAVE A SECOND NATIVE
SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */ SERIAL PORT SO WE USE SOFTWARE SERIAL LIBRARY */
#include <SoftwareSerial.h> #include <SoftwareSerial.h>
@@ -67,7 +101,7 @@
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL) * SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND) * BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL) * LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG) * BATTERY MONITOR PIN : 35 (ANALOG)
*/ */
/* ESP32 HAVE A NATIVE BLUETOOTH MODULE /* ESP32 HAVE A NATIVE BLUETOOTH MODULE
@@ -102,7 +136,7 @@
#define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR #define VTH 14 // THRESHOLD VOLTAGE FOR ZERO POSITIONNING KICKING POWER SENSOR
#define SENSOR_PIN 39 // IMPACT SENSOR #define SENSOR_PIN 39 // IMPACT SENSOR
#define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE #define RANDOM_SOURCE 34 // RANDOM NUMBER GENERATOR SOURCE
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Exclusive Features Of TAKEONE BOARD // Exclusive Features Of TAKEONE BOARD
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -110,7 +144,7 @@
/* ESP32 TAKEONE Board has some unique hardware features /* ESP32 TAKEONE Board has some unique hardware features
* 1. Battery Voltage Level Monitoring Via Analog Pin 35 * 1. Battery Voltage Level Monitoring Via Analog Pin 35
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery * 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom * 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
* 4. SPI : SDCARD Reader */ * 4. SPI : SDCARD Reader */
// Boost Converter // Boost Converter
@@ -171,7 +205,7 @@
//====================================================== //======================================================
// READING THE IMPACT // READING THE IMPACT
int readImpact() int readImpact()
{ {
int value = analogRead(SENSOR_PIN); int value = analogRead(SENSOR_PIN);
return value; return value;
@@ -181,7 +215,7 @@
// MAIN HARDWARE SETUP // MAIN HARDWARE SETUP
//====================================================== //======================================================
void setup() void setup()
{ {
// Communications // Communications
Terminal.begin(9600); Terminal.begin(9600);
@@ -217,10 +251,10 @@
// MAIN PROGRAM LOOP // MAIN PROGRAM LOOP
//====================================================== //======================================================
void loop() void loop()
{ {
// Reading From Bluetooth // Reading From Bluetooth
if(isBluetooth) if(isBluetooth)
{ {
// Reading Message From Bluetooth // Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n'); String msg = Bluetooth.readStringUntil('\n');
@@ -229,7 +263,7 @@
// Display On Serial Monitor For Debuging // Display On Serial Monitor For Debuging
terminal(msg); terminal(msg);
// Deserialize the JSON document // Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg); DeserializationError error = deserializeJson(JSON, msg);
@@ -245,7 +279,7 @@
// Clearing JSON Buffer // Clearing JSON Buffer
JSON.clear(); JSON.clear();
// Entering To Game Selector // Entering To Game Selector
game_selector(game, settings); game_selector(game, settings);
} }
@@ -2,17 +2,17 @@
// TERMINAL WINDOW - NATIVE USB // TERMINAL WINDOW - NATIVE USB
//====================================================== //======================================================
void terminal(String msg) void terminal(String msg)
{ {
msg += "\n"; msg += "\n";
Terminal.print(msg); Terminal.print(msg);
} }
//====================================================== //======================================================
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB // BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//====================================================== //======================================================
void bluetooth(String msg) void bluetooth(String msg)
{ {
msg += "\n"; msg += "\n";
Bluetooth.print(msg); Bluetooth.print(msg);
@@ -22,7 +22,7 @@
// BLUETOOTH WINDOW - NATIVE/VERTUAL USB // BLUETOOTH WINDOW - NATIVE/VERTUAL USB
//====================================================== //======================================================
void dualcomm(String msg) void dualcomm(String msg)
{ {
terminal(msg); terminal(msg);
bluetooth(msg); bluetooth(msg);
File renamed without changes.
File renamed without changes.
@@ -3,7 +3,7 @@
//====================================================== //======================================================
/* game selector is the main function that tell the game groutine /* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters * which game to be JSONed and at what parameters
*/ */
void game_selector(String game, String settings) void game_selector(String game, String settings)
@@ -18,7 +18,7 @@
// Time Attack Game // Time Attack Game
else if(game == "ta") { else if(game == "ta") {
terminal(GM_TATTACK); terminal(GM_TATTACK);
time_attack_bluetooth(settings); game_reaction_bluetooth(settings);
return; return;
} }
@@ -2,17 +2,17 @@
// TIME ATTACK GAME MAIN ROUTINE // TIME ATTACK GAME MAIN ROUTINE
//====================================================== //======================================================
/* This Game Can Be Called From /* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection * Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but * The primary mode is the standalone but
* if the bluetooth is connected it has the priority * if the bluetooth is connected it has the priority
* so it will take over the control of the device * so it will take over the control of the device
* *
* If you want to control the game via bluetooth * If you want to control the game via bluetooth
* you need to call : time_attack_bluetooth(JSON String) * you need to call : time_attack_bluetooth(JSON String)
* If you want to use the stand alone mode * If you want to use the stand alone mode
* you need to call : time_attack_standalone() * you need to call : time_attack_standalone()
* *
* the game returns a float point number which is * the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react * in seconds. so the athlete know how long he takes to react
*/ */
@@ -24,11 +24,11 @@
void time_attack_standalone() void time_attack_standalone()
{ {
// Variables // Variables
uint16_t time = 0; uint16_t time = 0;
uint16_t timer = 0; uint16_t timer = 0;
uint16_t limit = 0; uint16_t limit = 0;
bool limitEnable = 0; bool limitEnable = 0;
// Display Screen Menu And Button Actions // Display Screen Menu And Button Actions
// If The Menu Number 1 -> We Set The Value Of Min Delay // 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 2 -> We Set The Value Of Max Delay
@@ -44,7 +44,7 @@
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE: /* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------ * ------------------------------------------
* *
* FORMAT : * FORMAT :
* -------- * --------
* {"tm": 10, "le": false, "lm": 10} * {"tm": 10, "le": false, "lm": 10}
@@ -52,22 +52,22 @@
* tm : count down timer starting value * tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet * le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks * lm : targeted amount of kicks
* *
* THINGS THAT ENDS THE GAME : * THINGS THAT ENDS THE GAME :
* --------------------------- * ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO * 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH" * 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE" * 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
* *
* CALCULATING RESULTS : * CALCULATING RESULTS :
* --------------------- * ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec * Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick * Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
* *
* RETURNNING JSON FORMAT : * RETURNNING JSON FORMAT :
* ------------------------ * ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585} * {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
* *
* tm : timer count in Sec * tm : timer count in Sec
* ct : strike counter (number of kicks) * ct : strike counter (number of kicks)
* dl : delay between strikes * dl : delay between strikes
@@ -75,7 +75,7 @@
*/ */
void time_attack_bluetooth(String settings) void time_attack_bluetooth(String settings)
{ {
// Deserialize the JSON document // Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
@@ -102,7 +102,7 @@
// Play Time Atack Game // 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 timer, uint16_t limit, bool limitEnable)
{ {
// Building Timers 1000mSec -> 1Sec // Building Timers 1000mSec -> 1Sec
TimeTrigger sec_tick(1000); TimeTrigger sec_tick(1000);
@@ -122,7 +122,7 @@
// staring Of time stamp // staring Of time stamp
unsigned long startStamp = millis(); unsigned long startStamp = millis();
// store the time of the previous kick // store the time of the previous kick
unsigned long lastStamp = 0; unsigned long lastStamp = 0;
@@ -141,7 +141,7 @@
String msg = Bluetooth.readStringUntil('\n'); String msg = Bluetooth.readStringUntil('\n');
flushBluetooth; flushBluetooth;
msg.trim(); msg.trim();
if(msg == CM_STOP) if(msg == CM_STOP)
{ {
dualcomm(GAME_OVER); dualcomm(GAME_OVER);
// Grean Light In // Grean Light In
@@ -161,9 +161,8 @@
LED_SIGNAL_RESET(); LED_SIGNAL_RESET();
} }
} }
// Every Kick ---------------------------->>> // Every Kick ---------------------------->>>
if(readImpact() > VTH) if(readImpact() > VTH)
{ {
counter++; counter++;
@@ -173,13 +172,12 @@
} }
// Every Second ---------------------------->>> // Every Second ---------------------------->>>
if(sec_tick.Trigger()) if(sec_tick.Trigger())
{ {
timer--; timer--;
dualcomm(timeAttack_JSON_json(timer, counter, 0, 0)); dualcomm(timeAttack_JSON_json(timer, counter, 0, 0));
} }
// If Limits Are Enabled And Meet // If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit) if(limitEnable == true && counter == limit)
{ {
@@ -207,25 +205,25 @@
//====================================================== //======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp) String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{ {
// Building The Buffer // Building The Buffer
JSON["tm"] = RunningTime; JSON["tm"] = RunningTime;
JSON["ct"] = KickCount; JSON["ct"] = KickCount;
// Calculations // Calculations
if(TimeStamp > 0) if(TimeStamp > 0)
{ {
// Calculate Time Stamp In Seconds // Calculate Time Stamp In Seconds
float st = TimeStamp; float st = TimeStamp;
st /= 1000; st /= 1000;
JSON["st"] = String(st, 3).toFloat(); JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds // Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp; float dl = TimeStamp - LastStamp;
dl /= 1000; dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat(); JSON["dl"] = String(dl, 3).toFloat();
} }
String output; String output;
serializeJson(JSON, output); serializeJson(JSON, output);
JSON.clear(); JSON.clear();
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -9,7 +9,6 @@
* NEOPIXEL LED STRIP : A0/GPIO 26 * NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT * PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT * RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* https://www.aliexpress.com/item/32813561581.html?spm=a2g0s.9042311.0.0.48644c4dfH5L8o
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12) * BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
* I2C PIN : SDA 21, SCL 22 (DIGITAL) * I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL) * SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-40
View File
@@ -1,40 +0,0 @@
//======================================================
// COMMUNICATION PORTS FUNCTIONS
//======================================================
// TERMINAL WINDOW - NATIVE USB
//------------------------------------------------------
void terminal(String msg)
{
msg += "\n";
Terminal.print(msg);
}
//------------------------------------------------------
// BLUETOOTH WINDOW - NATIVE
//------------------------------------------------------
void bluetooth(String msg)
{
msg += "\n";
Bluetooth.print(msg);
}
//------------------------------------------------------
// BLUETOOTH CONNECTION STATUS
//------------------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if(event == ESP_SPP_SRV_OPEN_EVT) {
BLUETOOTH_STATUS = true;
terminal(BLUETOOTH_CONNECTED);
}
if(event == ESP_SPP_CLOSE_EVT ) {
BLUETOOTH_STATUS = false;
terminal(STAND_ALONE_MODE);
}
}
//------------------------------------------------------
// TERMINAL & BLUETOOTH WINDOW - NATIVE
//------------------------------------------------------
void dualcomm(String msg)
{
terminal(msg);
bluetooth(msg);
}
-22
View File
@@ -1,22 +0,0 @@
//======================================================
// THIS PAGE IS FOR GENERAL FUNCTIONS AND METHODES
//======================================================
// Floting Point Mapping
//------------------------------------------------------
double mapf(double val, double in_min, double in_max, double out_min, double out_max) {
return (val - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
//------------------------------------------------------
// MONITOR THE CENTER BUTTON RELEASE STATE
//------------------------------------------------------
void DETECT_LONG_PRESS() {
// Resetting The Timer For Long Press
POWER_PRESS.Reset();
// Loop If the Person Didnt Release The Button
while(!BTN_CENTER.released()) {
if(POWER_PRESS.Trigger()) {
OLED_POWERING_DOWN();
}
}
}
-264
View File
@@ -1,264 +0,0 @@
//======================================================
// MAIN COUNTER GAME LOOP
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_counter_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_counter_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// THIS IS THE STAND ALONE CALL FOR THE GAME
//======================================================
void game_counter_standalone()
{
// Variables Of The Game
uint16_t limit = 10;
bool limitEnable = true;
// Play The Game
game_counter(limit, limitEnable);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//======================================================
// THIS IS THE BLUETOOTH CALL FOR THE GAME
//======================================================
/* COUNTER GAME SETTINGS PARAMETERS NOTE:
* --------------------------------------
*
* FORMAT :
* --------
* {"le": false, "lm": 10}
*
* MEANNING :
* ----------
* ct : count
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 2. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* WHAT JSON TO BE COLLECTED :
* ---------------------------
* 1. FOR EVERY KICK YOU RECEIVE THE COUNTER DISJSON AND TIMESTAMP
* WE NEED TO COLLECT TIMESTAMPS AS AN ARRAY IN JSON FORMAT
*
* CALCULATING RESULTS :
* ---------------------
* No calculation required, Its directly the count
*/
void game_counter_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint16_t limit = JSON["lm"]; // Kick Target Limit
bool limitEnable = JSON["le"]; // Enable Kick Target Limit
// Clearing Buffer
JSON.clear();
// Play The Game
game_counter(limit, limitEnable);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//======================================================
// COUNTER JSON JSON -> To Send Back To Server
//======================================================
void game_counter(uint16_t limit, bool limitEnable)
{
// Kick Counter
uint16_t counter = 0;
// Game Start Lights
//LED_SIGNAL_START();
// Display On OLED
GAME_COUNTER_DISPLAY(0, limit);
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// staring Of time stamp
unsigned long startStamp = millis();
while(1)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
//LED_SIGNAL_END();
// RESET
return;
}
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) {
// END GAME
dualcomm(GAME_OVER);
// Celebration
//LED_SIGNAL_CELEBRATION();
// Display On OLED
GAME_RESULT_DISPLAY(counter, limit);
// RESET
return;
}
// Read Impact
if(PIEZO_MAP >= VTH)
{
counter++;
GAME_COUNTER_DISPLAY(counter, limit);
dualcomm(counter_JSON_json(counter, timeStamp));
delay(100);
}
}
}
//======================================================
// COUNTER JSON -> To Send Back To Mobile
//======================================================
String counter_JSON_json(unsigned int ct, unsigned int st)
{
// Convert Int To Float
float stamp = st;
stamp /= 1000;
// Assignning JSONset
JSON["ct"] = ct;
JSON["st"] = String(stamp, 3).toFloat();
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//------------------------------------------------------
// OLED - GAME COUNTER PLAY
//------------------------------------------------------
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) + "/" + 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;
}
}
}
-346
View File
@@ -1,346 +0,0 @@
//======================================================
// REACTION GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : game_reaction_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : game_reaction_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//------------------------------------------------------
// Request From Stand Alone Buttons
//------------------------------------------------------
void game_reaction_standalone()
{
// Variables
uint8_t minDelay = 1;
uint8_t maxDelay = 3;
uint8_t trials = 10;
// Call the Game Play
play_reaction(minDelay, maxDelay, trials);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//------------------------------------------------------
// Request From Bluetooth Via JSON
//------------------------------------------------------
/* REACTION GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tr": 10, "mn": 1, "mx": 2}
*
* MEANNING :
* ----------
* tr : trials pre counter
* mn : minimum delay, between trials
* mx : maximum delay, between trials
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tr" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
*/
void game_reaction_bluetooth(String settings)
{
//------------------------------------------------------
// START OF READING THE SETTINGS
//------------------------------------------------------
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings);
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
uint8_t minDelay = JSON["mn"];
uint8_t maxDelay = JSON["mx"];
uint16_t trials = JSON["lm"];
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
// Play The Game
play_reaction(minDelay, maxDelay, trials);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//------------------------------------------------------
// Play The Game
//------------------------------------------------------
void play_reaction(uint8_t minDelay, uint8_t maxDelay, uint16_t trials)
{
// PUBLIC VARIABLES
double totalRes = 0.0;
// Fix Random Error
maxDelay += 1;
// Clearing Buffer
JSON.clear();
//------------------------------------------------------
// PREPARE FOR GAME START
//------------------------------------------------------
// DisJSON Welcome Message
terminal("");
terminal("trials : " + String(trials) + " Strikes");
terminal("minDelay : " + String(minDelay) + " Seconds");
terminal("maxDelay : " + String(maxDelay) + " Seconds");
terminal("2 Seconds To Start Get Ready & Good Luck !!");
terminal("");
// Main Variables
uint16_t sdelay = 0;
uint16_t power = 0;
uint16_t response = 0;
unsigned long startTime = 0;
unsigned long stopTime = 0;
// Ready Signal
//LED_SIGNAL_REACTION_START();
// Display On OLED
GAME_REACTION_DISPLAY(0, 0);
//-------------------------
// PREPARE FOR GAME START
//-------------------------
// Processing Results
for(int i=0; i<trials; i++)
{
// Reading Kick JSON
terminal(" ------ Trial Number (" + String(i + 1) + ") ------");
terminal(" -> Get Ready !!");
// Set Random Delay Time
sdelay = random(minDelay, maxDelay);
sdelay *= 1000;
delay(sdelay);
// Light Up Green
//LED_SET_COLOR(0, 255, 0, 255);
// Start Timer
startTime = millis();
// Sensing Strike Power
while(power < VTH)
{
// Reading The Strike
power = PIEZO_MAP;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP) {
dualcomm(GAME_OVER);
// LightUp
//LED_SIGNAL_END();
// RESET
return;
}
else if(msg == CM_RESET) {
//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);
//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
stopTime = millis();
// Stop Light
//LED_SET_COLOR(255, 0, 0, 255);
// 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);
// Clear All
sdelay = 0;
power = 0;
response = 0;
}
// Red Light Delay
delay(500);
// END GAME
dualcomm(GAME_OVER);
// Blink Red
//LED_SIGNAL_CELEBRATION();
// Display Result
GAME_REACTION_RESULT(trials, totalRes);
// Return To Game Selector
return;
}
//------------------------------------------------------
// REACTION JSON -> To Send Back To Mobile Device
//------------------------------------------------------
String reaction_JSON_json(unsigned int count, unsigned int power, unsigned int response, unsigned int startDelay)
{
// Convert To Seconds Unit
float re = response;
re /= 1000;
// Asignning Values
JSON["ct"] = count; // Strike Number
JSON["pw"] = power; // Strike Power In Analog Read
JSON["sd"] = startDelay/1000; // LED Strip Start Delay in Seconds
JSON["re"] = String(re, 3).toFloat(); // Strike Reaction Time In Milli Sec
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//------------------------------------------------------
// REACTION GAME START LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_REACTION_START()
{
// Cross fade the white signal to get ready
//LED_CROSS_FADE(255, 255, 255, 3);
// Set the LED strip color to red
//LED_SET_COLOR(255, 0, 0, 255);
}
//------------------------------------------------------
// REACTION GAME RESET LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_REACTION_RESET()
{
// Light Bright Blue
//LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
//delay(250);
// Fade Out The Blue
//LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// OLED GAME PLAY REACTION
//------------------------------------------------------
void GAME_REACTION_DISPLAY(uint16_t count, float reatime)
{
OLED_CLEAR();
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;
}
}
}
-70
View File
@@ -1,70 +0,0 @@
//======================================================
// MAIN PROGRAM LOOP
//======================================================
/* game selector is the main function that tell the game groutine
* which game to be JSONed and at what parameters
*/
void bluetooth_game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal(GM_COUNTER);
game_counter_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal(GM_TATTACK);
time_attack_bluetooth(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal(GM_REACTION);
game_reaction_bluetooth(settings);
return;
}
// Unknown Game
else {
dualcomm(UNKNOWN_GAME);
return;
}
}
//======================================================
// GAME SELECTOR CODE
//======================================================
// SELECTOR ROUTINE
//------------------------------------------------------
void standalone_game_selector()
{
// Check Bluetooth
if(isBluetooth)
{
// Reading The Message From Bluetooth
String message = Bluetooth.readStringUntil('\n');
// Cleaning Bluetooth Receive Buffer
flushBluetooth;
// Cleaning The Message
message.trim();
// Cleaning JSON Document
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, "GAME #" + String(Number));
drawTextCenter(128/2, 22, 2, " - " + Title + " - ");
drawTextCenter(128/2, 43, 1, "<< SELECT >>");
OLED_SHOW();
DISPLAY_CHANGED = true;
}
-316
View File
@@ -1,316 +0,0 @@
//======================================================
// TIME ATTACK GAME MAIN ROUTINE
//======================================================
/* This Game Can Be Called From
* Stand Alone Mode / Bluetooth Connection
* The primary mode is the standalone but
* if the bluetooth is connected it has the priority
* so it will take over the control of the device
*
* If you want to control the game via bluetooth
* you need to call : time_attack_bluetooth(JSON String)
* If you want to use the stand alone mode
* you need to call : time_attack_standalone()
*
* the game returns a float point number which is
* in seconds. so the athlete know how long he takes to react
*/
//======================================================
// Request From Stand Alone Buttons
//======================================================
void time_attack_standalone()
{
// Variables
uint16_t time = 30;
uint16_t limit = 10;
bool limitEnable = true;
// Call the Game Play
game_timeAttack(time, limit, limitEnable);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//======================================================
// Request From Bluetooth Via JSON
//======================================================
/* TIME ATTACK GAME SETTINGS PARAMETERS NOTE:
* ------------------------------------------
*
* FORMAT :
* --------
* {"tm": 10, "le": false, "lm": 10}
*
* tm : count down timer starting value
* le : stands for limit enable, if is TRUE the game end if target value is meet
* lm : targeted amount of kicks
*
* THINGS THAT ENDS THE GAME :
* ---------------------------
* 1. BY COUNT DOWN "tm" REACH TO ZERO
* 2. BY A COMMAND "FROM APP VIA BLUETOOTH"
* 3. BY LIMITS MEET "WHEN NUMBER OF YOUR KICKS REACH TO lm VALUE"
*
* CALCULATING RESULTS :
* ---------------------
* Rapid Kick Speed = Number Of Kickes Made / Elasped Time In Sec
* Delay Between Kicks = Time Of Current Kick - Time Of Last Kick
*
* RETURNNING JSON FORMAT :
* ------------------------
* {"tm" : 82, "ct" : 10, "dl" : 1234, "st" : 585}
*
* tm : timer count in Sec
* ct : strike counter (number of kicks)
* dl : delay between strikes
* st : time stampe of the strike in milli Seconds
*/
void time_attack_bluetooth(String settings)
{
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, settings); // the main JSON body container
// JSON ERROR
if(error) {
dualcomm(JSON_ERROR);
return;
}
// PUBLIC VARIABLES
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, limit, limitEnable);
// Give Permision To Change Display
DISPLAY_CHANGED = false;
}
//======================================================
// Play Time Atack Game
//======================================================
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; // This is what counts your kicks
uint16_t timer = time; // This is what your running timer
// Start LED Signal
//LED_SIGNAL_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();
// store the time of the previous kick
unsigned long lastStamp = 0;
// reseting time ticker
sec_tick.Reset();
// While The Game Is Still On
while(timer != 0)
{
// Time Stamp
unsigned long timeStamp = millis() - startStamp;
// If Stop Command Came From Smart Phone
if(isBluetooth)
{
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
if(msg == CM_STOP)
{
dualcomm(GAME_OVER);
// Grean Light In
//LED_SIGNAL_END();
// Return
return;
}
else if(msg == CM_RESET)
{
timer = time;
counter = 0;
startStamp = millis();
timeStamp = startStamp;
lastStamp = timeStamp;
sec_tick.Reset();
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));
}
// If Limits Are Enabled And Meet
if(limitEnable == true && counter == limit)
{
// 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;
}
}
// 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
//LED_CLEAR(); // CLEAR OFF
// Return
return;
}
//======================================================
// TIME ATTACK KICK JSON -> To Send Back To Mobile
//======================================================
String timeAttack_JSON_json(unsigned int RunningTime, unsigned int KickCount, unsigned int LastStamp, unsigned int TimeStamp)
{
// Building The Buffer
JSON["tm"] = RunningTime;
JSON["ct"] = KickCount;
// Calculations
if(TimeStamp > 0)
{
// Calculate Time Stamp In Seconds
float st = TimeStamp;
st /= 1000;
JSON["st"] = String(st, 3).toFloat();
// Calculate Strike Delay In Seconds
float dl = TimeStamp - LastStamp;
dl /= 1000;
JSON["dl"] = String(dl, 3).toFloat();
}
String output;
serializeJson(JSON, output);
JSON.clear();
return output;
}
//------------------------------------------------------
// OLED - GAME TIMEATTACK PLAY
//------------------------------------------------------
void GAME_TIMEATTACK_DISPLAY(uint16_t count, uint16_t time)
{
OLED_CLEAR();
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;
}
}
}
-382
View File
@@ -1,382 +0,0 @@
/* ===============================================
* - THIS IS TAKEONE ESP32 BOARD -
* ===============================================
* MPU9250 Address : 0X69 (ADDRESS)
* OLED 128x64 Address : 0X3C (ADDRESS)
* -----------------------------------------------
* Description : PIN GPIO#
* -----------------------------------------------
* NEOPIXEL LED STRIP : A0/GPIO 26
* PIEZO SENSOR : A2/GPIO 34 - ANALOG ONLY INPUT
* RANDOM SEED : A3/GPIO 39 - ANALOG ONLY INPUT
* BUTTONS : TLB (35), BLB (15), CB (33), BRB (27), TRB(12)
* I2C PIN : SDA 21, SCL 22 (DIGITAL)
* SPI PIN : CS 5, SCK 18, MISO 19, MOSI 23 (DIGITAL)
* BOOST CONTROL PIN : 14 (DIGITAL) OUTPUT ON PADS (TP1 +5V, TP2 GND)
* LED PIN : 13 (DIGITAL)
* BATTERY MONITOR PIN : 35 (ANALOG)
* -----------------------------------------------
* BUTTONS PINOUTS : PIN GPIO
* -----------------------------------------------
* TOP LEFT BUTTON : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
* TOP RIGHT BUTTON : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
* BOTTOM LEFT BUTTON : 32 - POWER INC & BACK & INC PARAMETER
* BOTTOM RIGHT BUTTON : 27 - POWER DEC & SAVE & DEC PARAMETER
* CENTER BUTTON : 33 - POWER ON & SELECT
* -----------------------------------------------
* Exclusive Features Of TAKEONE BOARD
* -----------------------------------------------
* ESP32 TAKEONE Board has some unique hardware features
* 1. Battery Voltage Level Monitoring Via Analog Pin 35
* 2. Boost Converter In Case We Need 5V Supply From Li-Ion Battery
* 3. I2C : Motion Sensor IMU/MPU9250 9 Degrees Of Fredom
* 4. SPI : SDCARD Reader */
//======================================================
// LIBRARIES
//======================================================
#include <Wire.h>
#include <EEPROM.h>
#include <Button.h>
#include <TimeTrigger.h>
#include <ArduinoJson.h>
#include <BluetoothSerial.h>
#include <Adafruit_NeoPixel.h>
//======================================================
// OVER THE AIR PROGRAMMING
//======================================================
// #include <WiFi.h>
// #include <ESPmDNS.h>
// #include <WiFiUdp.h>
// #include <ArduinoOTA.h>
//======================================================
// PUBLIC VARIABLES
//======================================================
uint8_t MENU_COUNT = 1;
bool BLUETOOTH_STATUS = false;
bool CHARGE_STATE = false;
bool DISPLAY_CHANGED = false;
//======================================================
// HARDWARE DEFINITIONS
//======================================================
// Nessesary Definition For Bluetooth Library
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
//------------------------------------------------------
// Serial Terminal
//------------------------------------------------------
#define Terminal Serial // SERIAL PORT USED AS TERMINAL WINDO FOR DEBUG
#define isTerminal Terminal.available() // Terminal Serial Buffer Available
#define flushTerminal while(isTerminal) { Terminal.read(); }
//------------------------------------------------------
// Bluetooth Terminal
//------------------------------------------------------
BluetoothSerial Bluetooth; // Here We Use the Native Bluetooth In The ESP32
#define isBluetooth Bluetooth.available() // Bluetooth Serial Buffer Available
#define flushBluetooth while(isBluetooth) { Bluetooth.read(); }
//------------------------------------------------------
// Buttons
//------------------------------------------------------
Button BTN_PREVIOUS(15); // TL : 15 - SWITCH PREVIOUS MENU / CHANGE PARAMETER
Button BTN_NEXT(12); // TR : 12 - SWITCH NEXT MENU / CHANGE PARAMETER
Button BTN_CENTER(33); // CT : 33 - POWER INC & BACK & INC PARAMETER
Button BTN_INCREASE(32); // BL : 32 - POWER DEC & SAVE & DEC PARAMETER
Button BTN_DECREASE(27); // BR : 27 - POWER ON & SELECT
//------------------------------------------------------
// Boost 3V3 To 5V
//------------------------------------------------------
#define BOOST_PIN 14
#define BOOST_SETUP pinMode(BOOST_PIN, OUTPUT)
#define BOOST_ON digitalWrite(BOOST_PIN, HIGH)
#define BOOST_OFF digitalWrite(BOOST_PIN, LOW)
#define BOOST_STU digitalRead(BOOST_PIN)
//------------------------------------------------------
// Keep Power On
//------------------------------------------------------
#define POWER_PIN 13
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
TimeTrigger POWER_PRESS(4000); // The Interval In mSeconds
//------------------------------------------------------
// Piezo Transducer
//------------------------------------------------------
#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)
#define PIEZO_MAP map(PIEZO_READ, VTH, 4095, 0, 100)
//------------------------------------------------------
// Battery Level Monitoring
//------------------------------------------------------
#define BATTERY_PIN 35
#define BATTERY (float)(((analogRead(BATTERY_PIN) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE round(mapf(BATTERY, 3.27, 4.31, 0, 100), 1)
//------------------------------------------------------
// Power Charging Status
//------------------------------------------------------
#define STAT_PIN 25
#define STAT_SETUP pinMode(STAT_PIN, INPUT)
#define STAT_READ digitalRead(STAT_PIN)
//------------------------------------------------------
// Neo Pixel LED Strip
//------------------------------------------------------
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define PIN 6 // On Trinket or Gemma, suggest changing this to 1
#define NUMPIXELS 16 // Number Of LED's
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
//------------------------------------------------------
// JSON Object & Memory
//------------------------------------------------------
#define CAPACITY 200
DynamicJsonDocument JSON(CAPACITY); // Building JSON Buffer
// FIXED OPERATION MODE MESSAGES ~~~~~~~~~~~~~~~~~~~~~~
#define BLUETOOTH_START "{\"status\":\"BLUETOOTH STARTED\"}"
#define BLUETOOTH_FAIL "{\"status\":\"BLUETOOTH FAILED\"}"
#define BLUETOOTH_CONNECTED "{\"status\":\"BLUETOOTH CONNECTED\"}"
#define BLUETOOTH_DISCONNECTED "{\"status\":\"BLUETOOTH DISCONNECTED\"}"
#define STAND_ALONE_MODE "{\"status\":\"STAND ALONE MODE\"}"
// FIXED MESSAGES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define POWERUP "{\"status\":\"POWER UP\"}"
#define POWEROFF "{\"status\":\"POWER OFF\"}"
#define UNDERSTOOD "{\"status\":\"OK\"}"
#define JSON_ERROR "{\"status\":\"ERROR JSON\"}"
#define TARGET_MET "{\"status\":\"TARGET MEET\"}"
#define GAME_OVER "{\"status\":\"GAME OVER\"}"
#define TIME_OVER "{\"status\":\"TIME OVER\"}"
#define UNKNOWN_GAME "{\"status\":\"UNKNOWN GAME\"}"
// GAME NAMES ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define GM_COUNTER "{\"gm\":\"COUNTER\"}"
#define GM_TATTACK "{\"gm\":\"TIME ATTACK\"}"
#define GM_REACTION "{\"gm\":\"REACTION\"}"
#define GM_DECISION "{\"gm\":\"DECISION\"}"
#define GM_STAMINA "{\"gm\":\"STAMINA\"}"
// COMMAND LIST ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define CM_START "{\"cm\":\"START\"}"
#define CM_RESET "{\"cm\":\"RESET\"}"
#define CM_STOP "{\"cm\":\"STOP\"}"
#define CM_EXIT "{\"cm\":\"EXIT\"}"
//======================================================
// MAIN SETUP
//======================================================
void setup()
{
// Power Hold
POWER_SETUP;
POWER_ON;
// Charging Status Pin Setup
STAT_SETUP;
// I2C Module & OLED
Wire.begin();
delay(5);
OLED_INIT();
OLED_CLEAR();
OLED_SHOW();
// IF Charger Connected Dont Allow Any One To Play
// Turn On Booster
BOOST_SETUP;
BOOST_ON;
// Start Buttons Function
BTN_PREVIOUS.begin();
BTN_NEXT.begin();
BTN_CENTER.begin();
BTN_INCREASE.begin();
BTN_DECREASE.begin();
// Communication Ports
Terminal.begin(9600); Terminal.println();
// To Detect Connection / Disconnection Event
Bluetooth.register_callback(callback);
// Starting Bluetooth Wireless With Name (KICKER)
if(!Bluetooth.begin("KICKER")) {
terminal(POWERUP);
terminal(BLUETOOTH_FAIL);
} else {
dualcomm(POWERUP);
dualcomm(BLUETOOTH_START);
}
// The Random Number Source
randomSeed(analogRead(RANDOM_SOURCE));
// Display Welcome Screen
KICKER_LOGO();
delay(2000);
}
//======================================================
// MAIN PROGRAM LOOP
//======================================================
void loop()
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This Is For Bluetooth Mode
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(BLUETOOTH_STATUS == true) {
// 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
}
// Give Permition To Change The Content
DISPLAY_CHANGED = false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This Is For Stand Alone Mode
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
else {
// 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(); // Enter Listen To Stand Alone Buttons
}
// Once The Stand Alone Mode Is Over
DISPLAY_CHANGED = false; // Give Permition To Change The Display
}
}
//------------------------------------------------------
// LISTEN TO BLUETOOTH
//------------------------------------------------------
void ListenToBluetooth()
{
if(isBluetooth)
{
// Reading Message From Bluetooth
String msg = Bluetooth.readStringUntil('\n');
flushBluetooth;
msg.trim();
// Display On Serial Monitor For Debuging
terminal(msg);
// If It Was A Command To Power OFf
if(msg == POWEROFF) {
OLED_POWERING_DOWN();
}
// Deserialize the JSON document
DeserializationError error = deserializeJson(JSON, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
dualcomm(UNDERSTOOD);
// Reading Game Name & Settings
String game = JSON["gm"];
String settings = JSON["set"];
// Clearing JSON Buffer
JSON.clear();
// Entering To Game Selector
bluetooth_game_selector(game, settings);
}
else
{
terminal(JSON_ERROR);
}
}
}
//------------------------------------------------------
// LISTEN TO STAND ALONE
//------------------------------------------------------
void ListenToStandAlone()
{
// SHIFT TO PREVIOUS GAME MENU
if(BTN_PREVIOUS.pressed())
{
// Checking The Condition Of Order Number
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;
}
// SHIFT TO NEXT GAME MENU
else if(BTN_NEXT.pressed())
{
// Checking The Condition Of Order Number
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;
}
// SELECT CURRENT DISPLAYED MENU
else if(BTN_CENTER.pressed())
{
// 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 Pages
if(DISPLAY_CHANGED == false)
{
// IF Previous / Next Buttons Are Pressed -> Display Menu Selection On Terminal
switch(MENU_COUNT)
{
case 1: // Play Counter Game
//Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME COUNTER");
GAME_TITLE_DISPLAY(MENU_COUNT, "COUNTER");
break;
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: // Play Reaction Game
//Terminal.println("MENU #" + String(MENU_COUNT) + " - " + "GAME REACTION");
GAME_TITLE_DISPLAY(MENU_COUNT, "REACTION");
break;
}
}
}
-247
View File
@@ -1,247 +0,0 @@
//======================================================
// NEO PIXEL LED STRIP
//======================================================
// PUBLIC DEFINITIONS
//------------------------------------------------------
#define BETWEEN_FADE 15
#define FADE_RATE 15
#define BLINK_RATE 250
#define ColorSaturation 128
//------------------------------------------------------
// Clearing The LED Strip
//------------------------------------------------------
void LED_CLEAR()
{
// Clear The Strip Color
PIXEL_STRIP.clear();
// Show On LED Strip
LED_SHOW();
}
//------------------------------------------------------
// DISPLAY ON STRIP
//------------------------------------------------------
void LED_SHOW()
{
// Pass It To The LED Strip
PIXEL_STRIP.show();
}
//------------------------------------------------------
// Set LED Brightness
//------------------------------------------------------
void LED_SET_BRIGHTNESS(uint8_t Value)
{
// Set The Brightness
PIXEL_STRIP.setBrightness(Value);
}
//------------------------------------------------------
// Set LED Color
//------------------------------------------------------
void LED_SET_COLOR(uint8_t R, uint8_t G, uint8_t B, uint8_t Intensity)
{
// Set Intensity
LED_SET_BRIGHTNESS(Intensity);
// Loop
for(int i=0; i<NUM_PIXELS; i++) {
PIXEL_STRIP.setPixelColor(i, PIXEL_STRIP.Color(R, G, B));
}
// Show The Colors On LED Strip
LED_SHOW();
}
//------------------------------------------------------
// BLINK
//------------------------------------------------------
void LED_BLINK(uint8_t R, uint8_t G, uint8_t B, int Times)
{
for(int i=0; i<Times; i++)
{
LED_SET_COLOR(R, G, B, 255);
delay(BLINK_RATE);
LED_CLEAR();
delay(BLINK_RATE);
}
}
//------------------------------------------------------
// COLOR WHIPE
//------------------------------------------------------
// Fill the dots one after the other with a color
void LED_COLOR_WIPE(uint32_t c, uint8_t wait)
{
// Work Loop
for(uint16_t i=0; i<NUM_PIXELS; i++)
{
PIXEL_STRIP.setPixelColor(i, c);
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Slightly different, this makes the rainbow equally distributed throughout
void LED_RAINBOW_CYCLE(uint8_t wait)
{
// Loop Variables
uint16_t i, j;
// The Loop
for(j=0; j<256*5; j++)
{
// 5 cycles of all colors on WHEEL
for(i=0; i< PIXEL_STRIP.numPixels(); i++)
{
PIXEL_STRIP.setPixelColor(i, LED_COLOR_WHEEL(((i * 256 / PIXEL_STRIP.numPixels()) + j) & 255));
}
LED_SHOW();
delay(wait);
}
}
//------------------------------------------------------
// END GAME LIGHTING SIGNAL
//------------------------------------------------------
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t LED_COLOR_WHEEL(byte WHEELPos)
{
// Wheel Sequance
WHEELPos = 255 - WHEELPos;
if(WHEELPos < 85)
{
return PIXEL_STRIP.Color(255 - WHEELPos * 3, 0, WHEELPos * 3);
}
if(WHEELPos < 170)
{
WHEELPos -= 85;
return PIXEL_STRIP.Color(0, WHEELPos * 3, 255 - WHEELPos * 3);
}
WHEELPos -= 170;
return PIXEL_STRIP.Color(WHEELPos * 3, 255 - WHEELPos * 3, 0);
}
//------------------------------------------------------
// Set Color Fade In
//------------------------------------------------------
void LED_FADEIN(uint8_t R, uint8_t G, uint8_t B)
{
// Loop For Fade
for(int i=0; i<=255; i++)
{
PIXEL_STRIP.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set Color Fade Out
//------------------------------------------------------
void LED_FADEOUT(uint8_t R, uint8_t G, uint8_t B)
{
// Loop For Fade Out
for(int i=255; i>=0; i--)
{
PIXEL_STRIP.setBrightness(i);
for(int j=0; j<NUM_PIXELS; j++)
{
PIXEL_STRIP.setPixelColor(j, PIXEL_STRIP.Color(R, G, B));
}
LED_SHOW();
delay(4);
}
}
//------------------------------------------------------
// Set LED Color Cross Fade
//------------------------------------------------------
void LED_CROSS_FADE(uint8_t R, uint8_t G, uint8_t B, unsigned int Times)
{
for(int i=0; i<Times; i++)
{
LED_FADEIN(R, G, B);
LED_FADEOUT(R, G, B);
delay(BETWEEN_FADE);
}
}
//------------------------------------------------------
// REACTION GAME START LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_START()
{
// Cross Fade White Color To Get ready 3 Times
LED_CROSS_FADE(255, 255, 255, 3);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// REACTION GAME END SINGNAL LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_END()
{
// Blink Red Twice
LED_BLINK(255, 0, 0, 2);
// Fade The Red Color To Nothing
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// REACTION GAME START LED CELEBRATION
//------------------------------------------------------
void LED_SIGNAL_CELEBRATION()
{
// Display Rainbow Twice
LED_RAINBOW_CYCLE(2);
// Grean Light OUT
LED_FADEOUT(0, 255, 0);
}
//------------------------------------------------------
// REACTION GAME RESET LED SIGNAL
//------------------------------------------------------
void LED_SIGNAL_RESET()
{
// Light Bright Blue
LED_BLINK(0, 0, 255, 2);
// Wait For 1/4 Second
delay(250);
// Fade Out The Blue
LED_SET_COLOR(0, 255, 0, 255);
// Set Strip Color Green
LED_SET_COLOR(0, 255, 0, 255);
}
//------------------------------------------------------
// DISPLAY BAHRAIN FLAG
//------------------------------------------------------
void LED_BAHRAIN_FLAG()
{
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 255), 30); // White
delay(250);
LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
//------------------------------------------------------
// DISPLAY COLOMBIA FLAG
//------------------------------------------------------
void LED_COLOMBIA_FLAG()
{
LED_SET_BRIGHTNESS(255);
LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 255, 0), 30); // Yellow
delay(250);
LED_COLOR_WIPE(PIXEL_STRIP.Color(0, 0, 255), 30); // Blue
delay(250);
LED_COLOR_WIPE(PIXEL_STRIP.Color(255, 0, 0), 30); // Red
delay(250);
LED_FADEOUT(255, 0, 0);
}
-272
View File
@@ -1,272 +0,0 @@
//======================================================
// OLED DISPLAY
//======================================================
// LIBRARY INCLUDE
//------------------------------------------------------
// Include Libraries
#include <Wire.h>
#include <SSD1306Wire.h>
// Display Instance
SSD1306Wire display(0x3c, 21, 22);
//------------------------------------------------------
// OLED INITIALIZATION
//------------------------------------------------------
void OLED_INIT() {
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
}
//------------------------------------------------------
// OLED CLEAR DISPLAY
//------------------------------------------------------
void OLED_CLEAR() {
display.clear();
}
//------------------------------------------------------
// OLED CLEAN DISPLAY
//------------------------------------------------------
void OLED_CLEAN() {
OLED_CLEAR();
OLED_SHOW();
}
//------------------------------------------------------
// OLED SHOW NEW DATA
//------------------------------------------------------
void OLED_SHOW() {
display.display();
}
//------------------------------------------------------
// OLED DISPLAY KICKER WELCOME MESSAGE
//------------------------------------------------------
void KICKER_LOGO() {
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "TAKEONE");
drawTextCenter(128/2, 30, 1, " - T E C H N O L O G Y - ");
drawTextCenter(128/2, 43, 2, "<< KICKER >>");
OLED_SHOW();
}
//------------------------------------------------------
// OLED DISPLAY KICKER POWERING OFF MESSAGE
//------------------------------------------------------
void OLED_POWERING_DOWN() {
dualcomm(POWEROFF);
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "POWER");
drawTextCenter(128/2, 30, 1, "- T U R N I N G O F F -");
drawTextCenter(128/2, 43, 2, "SEE YOU AGAIN");
OLED_SHOW();
BOOST_OFF;
delay(2000);
OLED_CLEAN();
delay(250);
POWER_OFF;
}
//------------------------------------------------------
// OLED Display Text
//------------------------------------------------------
void drawTextFlowDemo(String Text) {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawStringMaxWidth(0, 0, 128, Text);
}
//------------------------------------------------------
// OLED LEFT TEXT Display
//------------------------------------------------------
void drawTextLeft() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
display.drawString(0, 10, "Left aligned (0,10)");
}
//------------------------------------------------------
// OLED CENTER TEXT Display
//------------------------------------------------------
void drawTextCenter(int X, int Y, int Size, String Text) {
//display.setFont(ArialMT_Plain_10);
if(Size == 1) {
display.setFont(ArialMT_Plain_10);
} else if(Size == 2) {
display.setFont(ArialMT_Plain_16);
} else if(Size == 3) {
display.setFont(ArialMT_Plain_24);
} else {
display.setFont(ArialMT_Plain_10);
}
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(X, Y, Text);
}
//------------------------------------------------------
// OLED RIGHT TEXT DISPLAY
//------------------------------------------------------
// OLED Display
void drawTextRight() {
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 33, "Right aligned (128,33)");
}
//------------------------------------------------------
// OLED DRAW RECTANGLE
//------------------------------------------------------
void drawRectDemo() {
// Draw a pixel at given position
for (int i = 0; i < 10; i++) {
display.setPixel(i, i);
display.setPixel(10 - i, i);
}
display.drawRect(12, 12, 20, 20);
// Fill the rectangle
display.fillRect(14, 14, 17, 17);
// Draw a line horizontally
display.drawHorizontalLine(0, 40, 20);
// Draw a line horizontally
display.drawVerticalLine(40, 0, 20);
}
//------------------------------------------------------
// OLED DRAW CIRCLE
//------------------------------------------------------
void drawCircleDemo() {
for (int i=1; i < 8; i++) {
display.setColor(WHITE);
display.drawCircle(32, 32, i*3);
if (i % 2 == 0) {
display.setColor(BLACK);
}
display.fillCircle(96, 32, 32 - i* 3);
}
}
//------------------------------------------------------
// OLED DRAW PROGRESS BAR
//------------------------------------------------------
void drawProgressBarDemo(int Value) {
int progress = Value;
// draw the progress bar
display.drawProgressBar(0, 50, 120, 10, progress);
// draw the percentage as String
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 35, String(progress) + "%");
}
//------------------------------------------------------
// I2C DECIVES SCANNER
//------------------------------------------------------
void scanI2C()
{
byte error, address;
int nDevices;
Serial.println(" -> Scanning I2C Devices ...");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print(" --> Device Found At Address 0x");
if (address<16)
Serial.print("0");
Serial.print(address,HEX);
Serial.println(" !");
nDevices++;
}
else if (error==4)
{
Serial.print(" --> Unknown error at address 0x");
if (address<16)
Serial.print("0");
Serial.println(address,HEX);
}
}
if (nDevices == 0)
Serial.println(" --> No I2C devices found\n");
else
Serial.println(" --> done");
}
//------------------------------------------------------
// WAITING FOR BLUETOOTH CONNECTION
//------------------------------------------------------
void OLED_BLUETOOTH_MODE()
{
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "KICKER");
drawTextCenter(128/2, 30, 1, " - B L U E T O O T H - ");
if(BLUETOOTH_STATUS == true) {
drawTextCenter(128/2, 43, 2, "< CONNECTED >");
} else {
drawTextCenter(128/2, 43, 2, "< WAITING >");
}
OLED_SHOW();
}
//------------------------------------------------------
// WAITING FOR BLUETOOTH CONNECTION
//------------------------------------------------------
void OLED_STANDALONE_MODE()
{
// Starting The First Code
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "KICKER");
drawTextCenter(128/2, 30, 1, " - S T A N D A L O N E - ");
drawTextCenter(128/2, 43, 2, "< MODE >");
OLED_SHOW();
}
//------------------------------------------------------
// GAME SLIDER SELECTOR
//------------------------------------------------------
void GAME_PAGE(uint8_t MenuNumber, String Title) {
if(DISPLAY_CHANGED == false) {
OLED_CLEAR();
drawTextCenter(128/2, 5, 3, "< GAME #" + String(MenuNumber) + " >");
drawTextCenter(128/2, 30, 1, " - " + Title + " - ");
drawTextCenter(128/2, 43, 2, "<< SELECT >>");
OLED_SHOW();
DISPLAY_CHANGED = true;
}
}