2020-05-25 04:56:48 +03:00

380 lines
12 KiB
C++

/* ===============================================
* - THIS IS TAKEONE 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
*/
// Include Library
#include <FS.h>
#include <SD.h>
#include <SPI.h>
#include <Wire.h>
#include <Button.h>
#include <ArduinoJson.h>
#include <BluetoothSerial.h>
#include <Adafruit_NeoPixel.h>
//----------------------------------------------------------------
// Communication Models
//----------------------------------------------------------------
// Serial Port As Terminal
#define terminal Serial
// Clearing Terminal Remainning
#define flush_terminal while(terminal.available()) { terminal.read(); }
// Bluetooth Object
BluetoothSerial bluetooth;
// Bluetooth Connection Status
bool bluetooth_conn = false;
// Clearing Bluetooth Remainning
#define flush_bluetooth while(bluetooth.available()) { bluetooth.read(); }
// Fixed JSON Strings
#define POWERUP "{\"status\":\"POWER UP\"}"
#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\"}"
// JSON CAPACITY
#define capacity 250
//----------------------------------------------------------------
// TAKEONE BOARD HARDWARE DEFINITIONS
//----------------------------------------------------------------
// On Board MPU9250 I2C Address
#define MPU_ADD 0x69
// Connected I2C OLED Address
#define OLED_ADD 0x3C
// Connected I2C LCD Address
#define LCD_ADD 0x2C
// Define Impact Sensor
#define PIEZO analogRead(34)
#define VOLTS mapf(PIEZO, 0, 4095, 0, 3.3)
// Panel Push Buttons Pin Assignment Sections
Button TLB(32); // Top Left Button
Button BLB(15); // Bottom Left Button
Button CB(33); // Center Button
Button BRB(27); // Bottom Right Button
Button TRB(12); // Top Right Button 33
// Panel Push Buttons Command Assignment
#define PrvMenu TLB.pressed()
#define NxtMenu TRB.pressed()
#define SelMenu CB.pressed()
#define IncBtn BLB.pressed()
#define DecBtn BRB.pressed()
// NEO Pixel Strip Section
#define NEOPIXEL 26 // Define Pin Number
#define NUMPIXELS 22 // Define Number Of LED's
// Battery Level Monitoring
#define BATTERY (float)(((analogRead(35) * (3.3 / 4096)) * 2) + 0.31)
#define CHARGE mapf(BATTERY, 3.27, 4.31, 0, 100)
// Power Latch Holder Pin
#define POWER_PIN 14
#define POWER_SETUP pinMode(POWER_PIN, OUTPUT)
#define POWER_ON digitalWrite(POWER_PIN, HIGH)
#define POWER_OFF digitalWrite(POWER_PIN, LOW)
// Battery To 5V Level Booster Setup & Control
#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)
// On Board LED Setup & Control
#define LED_PIN 13
#define LED_SETUP pinMode(LED_PIN, OUTPUT)
#define LED_ON digitalWrite(LED_PIN, HIGH)
#define LED_OFF digitalWrite(LED_PIN, LOW)
// For Timming
unsigned long timetick = 0;
unsigned long prevtick = 0;
/* Display Change Flag Explaination
* This flag is used to prevent continous writing to the oled display
* once a change has happened we drive the display_changed to false this will tell
* the micro controller that a need to write new data is needed, after writing the new data to display
* then we drive the display_changed to true that means the nessary changes has been written
*/
bool display_changed = false;
uint8_t menu_count = 0;
//--------------------------------------------------------------------
// Bluetooth Connection Status Call Back
//--------------------------------------------------------------------
void callback(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
if(event == ESP_SPP_SRV_OPEN_EVT){
//Serial.println("Client Connected");
bluetooth_conn = true;
}
if(event == ESP_SPP_CLOSE_EVT ){
//Serial.println("Client disconnected");
bluetooth_conn = false;
}
}
//--------------------------------------------------------------------
// CHIP MAIN SETUP
//--------------------------------------------------------------------
void setup()
{
// Starting Serial Communications
terminal.begin(115200); // Starting Main USB UART Communication Interface
terminal.println(); // New Line Seperator 1
terminal.println(); // New Line Seperator 2
// Starting The Bluetooth Module
if(!bluetooth.begin("KICKER")) {
terminal.println("An error occurred initializing Bluetooth");
} else {
terminal.println("Bluetooth initialized");
}
// Checking The Connection Status
bluetooth.register_callback(callback);
// Pin Assignments
BOOST_SETUP; // Boost Converter Pin Setup
LED_SETUP; // OnBoard LED Pin Setup
// Turn Off The Pins
BOOST_OFF; // Turn Off The Booster
LED_OFF; // Turn Off The LED
// The Five Panel Buttons
TLB.begin(); // Setup The Top Left Panel Button
BLB.begin(); // Setup The Bottom Left Panel Button
BRB.begin(); // Setup The Bottom Right Panel Button
TRB.begin(); // Setup The Top Right Panel Button
CB.begin(); // Setup The Center Panel Button
// I2C Section
Wire.begin(); // Starting I2C Communication Interface
scanI2C(); // Starting I2C Communicatable Devices Detection
oled_init(); // Starting OLED Display I2C Communications
kicker_logo(); // Display Kicker Main Logo Display
// Starting SDCARD Interface
sdcard_init(); // Starting SDCARD Reader Communication Protocol
// Neo Pixel Section
neo_init(); // Starting Neo Pixel
neo_color(0, 0, 0); // Clear All LED's
delay(10); // Delay 10 Milli Seconds
neo_color(255, 0, 0); // Display RED LED Strip
delay(1000); // Delay 1 Second
neo_color(0, 255, 0); // Display GREEN LED Strip
delay(1000); // Delay 1 Second
neo_color(0, 0, 255); // Display BLUE LED Strip
delay(1000); // Delay 1 Second
neo_turnoff(); // Power Off Neo Pixels & Their Power
// THE PROGRAM STATE = MENU
display_changed = false; // Allow Display Change
}
//--------------------------------------------------------------------
// CHIP MAIN PROGRAM
//--------------------------------------------------------------------
void loop()
{
// Checking The Bluetooth Connection
bluetooth.register_callback(callback);
// Condition The Preiority Is For The Bluetooth
if(bluetooth_conn == true)
{
// Wait For Game JSON String
read_game_json();
}
// Condition To Stand Alone Mode - Manual Mode
else
{
// Previous Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(TLB.pressed()) {
if(menu_count == 0) {
menu_count = 4;
} else {
menu_count--;
}
display_changed = false;
}
// Next Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(TRB.pressed()) {
if(menu_count == 4) {
menu_count = 0;
} else {
menu_count++;
}
display_changed = false;
}
// Select A Game ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(CB.pressed()) {
select_game();
}
// Increase Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(BLB.pressed()) {
}
// Decrease Power ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if(BRB.pressed()) {
}
// Display Target Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~
switch_menu();
}
}
//======================================================
// Read Game JSON String Command From Mobile
//======================================================
void read_game_json()
{
// Reading From Bluetooth
if(bluetooth.available())
{
// Reading Message From Bluetooth
String msg = bluetooth.readStringUntil('\n');
// Clearing The Receive Buffer
flush_bluetooth;
// Clean The Message
msg.trim();
// Display On Sertial
terminal.println(msg);
// Parsing Objects Message Objects
DynamicJsonDocument root(capacity);
// Deserialize the JSON document
DeserializationError error = deserializeJson(root, msg);
// If The System Understood The Message Clearly
if(!error)
{
// Sending Status Message
terminal.println(UNDERSTOOD);
bluetooth.println(UNDERSTOOD);
// Reading Game Name & Settings
String game = root["gm"];
String settings = root["set"];
// Clearing JSON Document Buffer
root.clear();
// Entering To Game Selector
game_selector(game, settings);
}
else
{
// Display On Serial
terminal.println(JSON_ERROR);
}
// Bluetooth Serial RXD Flush
flush_bluetooth;
}
}
//======================================================
// Game Selector Function
//======================================================
void game_selector(String game, String settings)
{
// Kick Counter Game
if(game == "ct") {
terminal.println(GM_COUNTER);
//game_counter(settings);
return;
}
// Time Attack Game
else if(game == "ta") {
terminal.println(GM_TATTACK);
//game_timeAttack(settings);
return;
}
// Time Attack Game
else if(game == "ra") {
terminal.println(GM_REACTION);
//game_reaction(settings);
return;
}
// Unknown Game
else {
terminal.println(UNKNOWN_GAME);
bluetooth.println(UNKNOWN_GAME);
return;
}
}