From b9f58ca614736df5fc26dd14343da2a0216d9efb Mon Sep 17 00:00:00 2001 From: GhassanYusuf Date: Sun, 13 Jul 2025 16:10:06 +0300 Subject: [PATCH] first upload --- buttons.h | 41 +++++++ definitions.h | 13 +++ esp32c3-joystick.ino | 118 +++++++++++++++++++ functions.ino | 262 +++++++++++++++++++++++++++++++++++++++++++ oled.h | 147 ++++++++++++++++++++++++ time.h | 55 +++++++++ wireless.h | 241 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 877 insertions(+) create mode 100644 buttons.h create mode 100644 definitions.h create mode 100644 esp32c3-joystick.ino create mode 100644 functions.ino create mode 100644 oled.h create mode 100644 time.h create mode 100644 wireless.h diff --git a/buttons.h b/buttons.h new file mode 100644 index 0000000..ccf1da3 --- /dev/null +++ b/buttons.h @@ -0,0 +1,41 @@ +//=============================================== +// Buttons Library +//=============================================== + + // Library + #include "Button.h" + + // Making The Buttons + Button btnRedOne(_btn_red_one); + Button btnRedTwo(_btn_red_two); + Button btnBlueOne(_btn_blue_one); + Button btnBlueTwo(_btn_blue_two); + +//----------------------------------------------- +// Functions +//----------------------------------------------- + + void btn_start() { + #ifdef ENA_BTN + btnRedOne.begin(); + btnRedTwo.begin(); + btnBlueOne.begin(); + btnBlueTwo.begin(); + #endif + } + + void btn_test() { + #ifdef ENA_BTN + while(1) { + if(btnRedOne.pressed()) { Serial.println(" -> Red 1 Point"); } + if(btnRedTwo.pressed()) { Serial.println(" -> Red 2 Point"); } + if(btnBlueOne.pressed()) { Serial.println(" -> Blue 1 Point"); } + if(btnBlueTwo.pressed()) { Serial.println(" -> Blue 2 Point"); } + ESP.wdtFeed(); + } + #endif + } + +//=============================================== +// END +//=============================================== \ No newline at end of file diff --git a/definitions.h b/definitions.h new file mode 100644 index 0000000..c84f3ee --- /dev/null +++ b/definitions.h @@ -0,0 +1,13 @@ + + // Enable Functions + // #define ENA_DSP // Display + #define ENA_TRM // Terminal + #define ENA_BTN // Button + + // Pins Definitions + #define _led_pin 5 // On Board LED Pin + #define _btn_red_one 0 // Judge Button Red 1 Point + #define _btn_red_two 1 // Judge Button Red 2 Point + #define _btn_blue_one 2 // Judge Button Blue 1 Point + #define _btn_blue_two 3 // Judge Button Blue 2 Point + #define _motor_pin 4 // Motor Vibrator \ No newline at end of file diff --git a/esp32c3-joystick.ino b/esp32c3-joystick.ino new file mode 100644 index 0000000..a30f73f --- /dev/null +++ b/esp32c3-joystick.ino @@ -0,0 +1,118 @@ +//========================================================= +// Header +//========================================================= + + // Include Libraries And Headers + #include "WiFi.h" + #include "definitions.h" + #include "buttons.h" + #include "oled.h" + #include "wireless.h" + #include "time.h" + +//========================================================= +// Initialization +//========================================================= + + void setup() { + + // Serial Data + Serial.begin(115200); + Serial.println(); + + btn_start(); // Start Button Function + oled_start(); // Starting OLED + oled_clear(); // Clear OLED Display + + // btn_test(); // This Is For Test + // SPIFFS.format(); + + // Wait For Reset + wifi_wait_for_reset(); + + // Activate Buzzer Pin + pinMode(_motor_pin, OUTPUT); + + buzz(); + + oled_logo(); // Display LOGO + + // Print Seperator + Serial.println(MSG_SPACER); + + LED_START; // Starting LED + LED_OFF; // Turn Off + wifi_start(); // WiFi Start + LED_ON; // WiFi Connected + + // Print Seperator + Serial.println(MSG_SPACER); + + // ESP Chip ID + uint32_t chipId = ESP.getChipId(); + Serial.print("ESP Chip ID : "); Serial.println(chipId); + + // ESP Device Address + Serial.print("ESP IP Address : "); Serial.println(WiFi.localIP()); + + // ESP MAC Address + String macAddress = WiFi.macAddress(); + Serial.print("ESP MC Address : "); Serial.println(macAddress); + Serial.println(MSG_SPACER); + + // NTP Function + ntp_begin(); + ntp_update(); + syncedMillisOffset = timeClient.getEpochTime() * 1000 - startMillis; + + // Connected Server + oled_clear(); + oled_text(1, 0, 0, "Connect To Server"); + + // Connect To Server + server_connect(); + + // Display Connected + oled_text(1, 0, 10, "Connection Success"); + + // Wait On Sec + delay(1000); + + // Print Seperator + Serial.println(MSG_SPACER); + + // New Timming + timing = millis(); + + } + +//========================================================= +// Running Loop +//========================================================= + + void loop() { + + // Maintain Server Connection + server_connect(); + + // Update Time + ntp_update(); + // ntp_sync_millis(); + + // Read Buttons With Actions + read_buttons(); + + // Send VIA Serial + send_via_serial(); + + // Read TCP Data + read_tcp(); + + // Send Keep Alive + send_keep_alive(); + + } + +//========================================================= +// END +//========================================================= \ No newline at end of file diff --git a/functions.ino b/functions.ino new file mode 100644 index 0000000..089c627 --- /dev/null +++ b/functions.ino @@ -0,0 +1,262 @@ +//========================================================= +// Serial +//========================================================= +// Question +//--------------------------------------------------------- + + String serial_question(String msg) { + Serial.print(msg + " : "); + while(!Serial.available()); + msg = Serial.readStringUntil('\n'); + while(Serial.available()) { Serial.read(); } + msg.trim(); + Serial.println(msg); + return msg; + } + +//========================================================= +// Server +//========================================================= +// Connect To Server +//--------------------------------------------------------- + + void server_connect() { + + // If Connected Just Skip + if(tcpClient.connected()) { return; } + + // Try To Connect To Server + while(!tcpClient.connect(scoreboard_server, atoi(scoreboard_port))) { + LED_TOGGLE; + delay(200); + } + + // Stay On + LED_ON; + + // Connection Established + Serial.println(MSG_TCP_CONNECTED); + + } + +//--------------------------------------------------------- +// JSON Event Generator +//--------------------------------------------------------- + + String json_button_message(String buttonName) { + + // Empty Space + JSON.clear(); + + // Device Name + JSON["device"] = joypad_identifier; + JSON["type"] = "score"; + // JSON["cid"] = ESP.getChipId(); + // JSON["mac"] = WiFi.macAddress(); + // JSON["ipa"] = WiFi.localIP().toString(); + // JSON["battery"] = analogRead(A0); + // JSON["signal"] = WiFi.RSSI(); + JSON["button"] = buttonName; + // JSON["time"] = millis(); + // JSON["time"] = ntp_print_time(); + + // String Data Buffer + String ouput; + + // Print To Serial + serializeJson(JSON, ouput); + + // Save Memory + JSON.clear(); + + // Return The String + return ouput; + + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + String json_telemetry_message() { + + // Empty Space + JSON.clear(); + + // Device Name + JSON["device"] = joypad_identifier; + JSON["type"] = "telemetry"; + JSON["signal"] = WiFi.RSSI(); + JSON["battery"] = analogRead(A0); + JSON["mac"] = WiFi.macAddress(); + JSON["time"] = ntp_print_time(); + + // String Data Buffer + String ouput; + + // Print To Serial + serializeJson(JSON, ouput); + + // Save Memory + JSON.clear(); + + // Return The String + return ouput; + + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + void read_buttons() { + + // TopLeft - Send Message + if(btnRedOne.pressed()) { + String x = json_button_message("RED1"); + Serial.println(x); + tcpClient.print(x); + delay(150); + } + + // BottomLeft - Send Message + if(btnRedTwo.pressed()) { + String x = json_button_message("RED2"); + Serial.println(x); + tcpClient.print(x); + delay(150); + } + + // TopRight - Send Message + if(btnBlueOne.pressed()) { + String x = json_button_message("BLU1"); + Serial.println(x); + tcpClient.print(x); + delay(150); + } + + // TopRight - Send Message + if(btnBlueTwo.pressed()) { + String x = json_button_message("BLU2"); + Serial.println(x); + tcpClient.print(x); + delay(150); + } + + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + void buzz() { + digitalWrite(_motor_pin, HIGH); + delay(250); + digitalWrite(_motor_pin, LOW); + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + void send_via_serial() { + + // Sending TCP Data + if(Serial.available()) { + + String msg = Serial.readStringUntil('\n'); + while(Serial.available()) { Serial.read(); } + msg.trim(); + + // Create JSON Object + JSON["type"] = "cmd"; + JSON["header"] = "point"; + JSON["body"] = msg; + + // Move The Message To String Variable + serializeJson(JSON, msg); + + // Sending Data Out + Serial.println(MSG_TCP_SEND + String(" : ") + msg); + tcpClient.print(msg); + + // Empty Data + JSON.clear(); + + } + + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + void read_tcp() { + + // Received TCP Data + if(tcpClient.available()) { + + String x = tcpClient.readStringUntil('\n'); + while(tcpClient.available()) { tcpClient.read(); } + + x.trim(); + Serial.print(" -> tcp signal in : "); + Serial.println(x); + + // Clear JSON + JSON.clear(); + + // Deserialize the JSON document + DeserializationError error = deserializeJson(JSON, x); + + // Test if parsing succeeds + if (error) { + Serial.print(F("deserializeJson() failed: ")); + Serial.println(error.f_str()); + return; + } + + // Read Message Type + String mType = JSON["type"]; + + // Read Command + String command = JSON["command"]; + + // Read BuZZer + if(command == "buzz") { + buzz(); + } + + // Clear JSON + JSON.clear(); + + } + + } + +//--------------------------------------------------------- +// JSON Telemetry Generator +//--------------------------------------------------------- + + void send_keep_alive() { + + // Keep Sending To Avoid Disconnection + if(millis() - timing >= 15000) { + + // Buffer Data + String x = json_telemetry_message(); + + // Send Out Data + Serial.println(x); + tcpClient.print(x); + + // Update Time Snap Shot + timing = millis(); + + } + + } + +//========================================================= +// END +//========================================================= \ No newline at end of file diff --git a/oled.h b/oled.h new file mode 100644 index 0000000..08f4be6 --- /dev/null +++ b/oled.h @@ -0,0 +1,147 @@ +//=============================================== +// OLED +//=============================================== + + // OLED Library + #include + #include + #include + #include + + // OLED Declarations + #define SCREEN_WIDTH 128 + #define SCREEN_HEIGHT 64 + #define OLED_RESET -1 + #define SCREEN_ADDRESS 0x3C + Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); + + // For Reading Intervals + unsigned long displayReadPrv, serialReadPrv; + + #ifdef ENA_DSP + + // TAKEONE LOGO + static const unsigned char PROGMEM logo_bmp[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xce, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xfd, 0xe0, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf0, 0x3f, 0x00, 0x7c, 0x3f, 0x8f, 0xfc, 0x1f, 0xff, 0xfb, 0x60, 0x7c, 0x07, 0xc3, 0xff, + 0xff, 0xf0, 0x3f, 0x80, 0x7c, 0x7f, 0x8f, 0xfc, 0x1f, 0xff, 0xfe, 0x60, 0x7e, 0x07, 0xc3, 0xff, + 0xff, 0xf0, 0x7f, 0x80, 0x7c, 0xff, 0x0f, 0xfc, 0x1f, 0xff, 0xfc, 0xc0, 0x7f, 0x07, 0xc3, 0xff, + 0xff, 0xf0, 0x7f, 0xc0, 0x7c, 0xfe, 0x0f, 0xfc, 0x0f, 0xff, 0xf9, 0x80, 0x7f, 0x07, 0xc3, 0xff, + 0xff, 0xf0, 0x7f, 0xc0, 0x7d, 0xfc, 0x0f, 0x80, 0x07, 0xff, 0xfb, 0x00, 0x7f, 0x87, 0xc3, 0xe0, + 0x1f, 0x80, 0xff, 0xc0, 0x7f, 0xf8, 0x0f, 0x80, 0x07, 0xff, 0xf2, 0x00, 0x7f, 0xc7, 0xc3, 0xe0, + 0x1f, 0x80, 0xff, 0xe0, 0x7f, 0xf0, 0x0f, 0xfc, 0x07, 0xff, 0xf4, 0x00, 0x7f, 0xe7, 0xc3, 0xff, + 0x1f, 0x80, 0xfb, 0xe0, 0x7f, 0xe0, 0x0f, 0xfc, 0x07, 0xff, 0xf4, 0x00, 0x7f, 0xe7, 0xc3, 0xff, + 0x1f, 0x81, 0xfb, 0xe0, 0x7f, 0xc0, 0x0f, 0xfc, 0x3f, 0xff, 0xf4, 0x00, 0x7d, 0xf7, 0xc3, 0xff, + 0x1f, 0x81, 0xf1, 0xf0, 0x7f, 0xe0, 0x0f, 0xfc, 0x3f, 0xff, 0xf6, 0x00, 0x7c, 0xff, 0xc3, 0xff, + 0x1f, 0x83, 0xf1, 0xf0, 0x7f, 0xf0, 0x0f, 0xfc, 0x3f, 0xff, 0xf2, 0x00, 0x7c, 0x7f, 0xc3, 0xe0, + 0x1f, 0x83, 0xe0, 0xf8, 0x7f, 0xf8, 0x0f, 0x80, 0x3f, 0xff, 0xb9, 0x00, 0x7c, 0x7f, 0xc3, 0xe0, + 0x1f, 0x83, 0xff, 0xf8, 0x7d, 0xfc, 0x0f, 0x80, 0x3f, 0xff, 0x1c, 0x80, 0x7c, 0x3f, 0xc3, 0xe0, + 0x1f, 0x87, 0xff, 0xf8, 0x7c, 0xfe, 0x0f, 0xfc, 0x3f, 0xfe, 0x7e, 0x40, 0x7c, 0x1f, 0xc3, 0xff, + 0x1f, 0x87, 0xff, 0xfc, 0x7c, 0x7f, 0x0f, 0xfc, 0x1f, 0xfe, 0xf7, 0xe0, 0x7c, 0x0f, 0xc3, 0xff, + 0x1f, 0x8f, 0xc0, 0xfe, 0x7c, 0x3f, 0x8f, 0xfc, 0x1f, 0xff, 0xe7, 0xf0, 0x7c, 0x0f, 0xc3, 0xff, + 0x1f, 0x8f, 0xc0, 0xfe, 0x7c, 0x3f, 0x8f, 0xfc, 0x0f, 0xff, 0xcf, 0xf8, 0x7c, 0x07, 0xc1, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf9, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + #endif + +//----------------------------------------------- +// START OLED +//----------------------------------------------- + + void oled_start() { + #ifdef ENA_DSP + if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { + Serial.println(F("SSD1306 allocation failed")); + while(1); // Don't proceed, loop forever + } + #endif + } + +//----------------------------------------------- +// CLEAR DISPLAY +//----------------------------------------------- + + void oled_clear() { + #ifdef ENA_DSP + display.clearDisplay(); + #endif + } + +//----------------------------------------------- +// WRITE TEXT +//----------------------------------------------- + + void oled_text(uint8_t s, uint8_t x, uint8_t y, String msg) { + #ifdef ENA_DSP + display.setTextSize(s); + display.setTextColor(SSD1306_WHITE); + display.setCursor(x, y); + display.println(msg); + display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); + display.display(); + #endif + } + +//----------------------------------------------- +// Draw Logo +//----------------------------------------------- + + void oled_logo() { + #ifdef ENA_DSP + display.clearDisplay(); + display.drawBitmap(0, 0, logo_bmp, SCREEN_WIDTH, SCREEN_HEIGHT, 1); + oled_text(1, 110, 14, ".bh"); + oled_text(1, 1, 44, "sports-tech"); + delay(3000); + #endif + } + +//=============================================== +// END +//=============================================== \ No newline at end of file diff --git a/time.h b/time.h new file mode 100644 index 0000000..a030e06 --- /dev/null +++ b/time.h @@ -0,0 +1,55 @@ + #include + #include + + WiFiUDP ntpUDP; + NTPClient timeClient(ntpUDP, "pool.ntp.org", 10800, 60000); // Update every 60 seconds + unsigned long startMillis; + unsigned long syncedMillisOffset; + + void ntp_begin() { + timeClient.begin(); + timeClient.update(); + // startMillis = millis() - timeClient.getEpochTime() * 1000; + startMillis = millis(); + } + + void ntp_update() { + timeClient.update(); + } + + unsigned long ntp_sync_millis() { + return startMillis + millis(); + } + + String ntp_print_time() { + + // Calculate the time components + unsigned long currentMillis = millis(); + unsigned long syncedMillis = currentMillis + syncedMillisOffset; + + unsigned long totalSeconds = syncedMillis / 1000; + unsigned long hours = (totalSeconds % 86400) / 3600; + unsigned long minutes = (totalSeconds % 3600) / 60; + unsigned long seconds = totalSeconds % 60; + unsigned long milliseconds = syncedMillis % 1000; + + // Adjust for 12-hour format and determine AM/PM + String ampm = "AM"; + + if(hours >= 12) { + ampm = "PM"; + if(hours > 12) + hours -= 12; + } + + if(hours == 0) { + hours = 12; + } + + // Generate String + String x = String(hours) + ":" + String(minutes) + ":" + String(seconds) + ":" + String(milliseconds) + ":" + ampm; + + // Return String Value + return x; + + } \ No newline at end of file diff --git a/wireless.h b/wireless.h new file mode 100644 index 0000000..b71dd68 --- /dev/null +++ b/wireless.h @@ -0,0 +1,241 @@ +//========================================================= +// Header +//========================================================= + + // WiFi Libraries + #include // This needs to be first, or it all crashes and burns... + #include // https://github.com/tzapu/WiFiManager + #ifdef ESP32 + #include + #endif + #include // https://github.com/bblanchon/ArduinoJson + + // Variables + char joypad_identifier[40] = ""; // TCP Scoreboard IP Address + char scoreboard_server[40] = ""; // TCP Scoreboard IP Address + char scoreboard_port[6] = "8080"; // TCP Scoreboard Port + bool shouldSaveConfig = false; // Flag For Saving Data + unsigned long timing = 0; // For Keep Alive Signal + + // JSON Documents + JsonDocument JSON; + + // WiFi Manager Object + WiFiManager wifiManager; + + // WiFi Manager Web UI Parameters + WiFiManagerParameter custom_identifier("identifier", "Device Identifier", "", 40); // New Addition + WiFiManagerParameter custom_scoreboard("server", "ScoreBoard Server", "", 40); + WiFiManagerParameter custom_port("port", "ScoreBoard Port", "", 6); + +//========================================================= +// TCP Client +//========================================================= + + // TCP Object + WiFiClient tcpClient; + + // List Messages + #define MSG_SPACER "--------------------------------------------" + #define MSG_TCP_CONNECTED "TCP Server : Connected" + #define MSG_TCP_SEND "WHAT TO SEND ? " + +//========================================================= +// LED ON BOARD +//========================================================= + + // Defining Pin & Commands + #define LED_START pinMode(_led_pin, OUTPUT) + #define LED_ON digitalWrite(_led_pin, LOW) + #define LED_OFF digitalWrite(_led_pin, HIGH) + #define LED_TOGGLE digitalWrite(_led_pin, !digitalRead(_led_pin)) + +//========================================================= +// WIFI +//========================================================= +// Save Config Files Flag +//--------------------------------------------------------- + + void wifi_save_config_call_back () { + Serial.println("Should save config"); + shouldSaveConfig = true; + } + +//--------------------------------------------------------- +// Add Parameters +//--------------------------------------------------------- + + void wifi_add_parameter(WiFiManager& manager) { + // Set config save notify callback + manager.setSaveConfigCallback(wifi_save_config_call_back); + // Update The Values From Spiffs + custom_identifier.setValue(joypad_identifier, sizeof(joypad_identifier)); // New Addition + custom_scoreboard.setValue(scoreboard_server, sizeof(scoreboard_server)); + custom_port.setValue(scoreboard_port, sizeof(scoreboard_port)); + // Add All Parameters To WiFi Manager + manager.addParameter(&custom_identifier); // New Addition + manager.addParameter(&custom_scoreboard); + manager.addParameter(&custom_port); + } + +//--------------------------------------------------------- +// WiFi Connection +//--------------------------------------------------------- + + void wifi_start() { + + // Read configuration from FS json + Serial.println("mounting FS..."); + + // Working With File Systems + if(SPIFFS.begin()) { + + Serial.println("mounted file system"); + if(SPIFFS.exists("/config.json")) { + + Serial.println("reading config file"); + File configFile = SPIFFS.open("/config.json", "r"); + + if(configFile) { + Serial.println("opened config file"); + size_t size = configFile.size(); + std::unique_ptr buf(new char[size]); + configFile.readBytes(buf.get(), size); + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + DynamicJsonDocument json(1024); + auto deserializeError = deserializeJson(json, buf.get()); + serializeJson(json, Serial); + if(!deserializeError) { + #else + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.parseObject(buf.get()); + json.printTo(Serial); + if(json.success()) { + #endif + Serial.println("\nparsed json"); + strcpy(joypad_identifier, json["joypad_identifier"]); + strcpy(scoreboard_server, json["scoreboard_server"]); + strcpy(scoreboard_port, json["scoreboard_port"]); + } else { + Serial.println("failed to load json config"); + } + configFile.close(); + } + } + } else { + Serial.println("failed to mount FS"); + } + + // Add Parameters Settings + wifi_add_parameter(wifiManager); + + // Connecting To WiFi + oled_clear(); + oled_text(1, 0, 2, "Connecting WiFi"); + oled_text(1, 0, 14, "If It Takes Too Long"); + oled_text(1, 0, 24, "Connect To"); + oled_text(1, 0, 34, "TAKEONE JOYPADS"); + oled_text(1, 0, 44, "192.168.4.1"); + + // Fetches ssid and pass and tries to connect + if(!wifiManager.autoConnect("TAKEONE JOYPADS")) { + Serial.println("failed to connect and hit timeout"); + delay(3000); + //reset and try again, or maybe put it to deep sleep + ESP.restart(); + delay(5000); + } + + // Connecting To WiFi + oled_clear(); + oled_text(2, 0, 0, "WiFi Connected"); + + // Read updated parameters + strcpy(joypad_identifier, custom_identifier.getValue()); + strcpy(scoreboard_server, custom_scoreboard.getValue()); + strcpy(scoreboard_port, custom_port.getValue()); + Serial.println("The Values In The File Are : "); + Serial.println("\tjoypad_identifier : " + String(joypad_identifier)); + Serial.println("\tscoreboard_server : " + String(scoreboard_server)); + Serial.println("\tscoreboard_port : " + String(scoreboard_port)); + + // Save the custom parameters to FS + if(shouldSaveConfig) { + + Serial.println("saving config"); + + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + DynamicJsonDocument json(1024); + #else + DynamicJsonBuffer jsonBuffer; + JsonObject& json = jsonBuffer.createObject(); + #endif + + json["joypad_identifier"] = joypad_identifier; + json["scoreboard_server"] = scoreboard_server; + json["scoreboard_port"] = scoreboard_port; + + File configFile = SPIFFS.open("/config.json", "w"); + + if(!configFile) { + Serial.println("failed to open config file for writing"); + } + + #if defined(ARDUINOJSON_VERSION_MAJOR) && ARDUINOJSON_VERSION_MAJOR >= 6 + serializeJson(json, Serial); + serializeJson(json, configFile); + #else + json.printTo(Serial); + json.printTo(configFile); + #endif + Serial.println(); + configFile.close(); + + } + + } + +//--------------------------------------------------------- +// WiFi Reset +//--------------------------------------------------------- + + void wifi_reset() { + oled_clear(); + oled_text(1, 0, 2, "Reset WiFi Settings"); + wifiManager.resetSettings(); + delay(500); + oled_text(1, 0, 12, "Rebooting"); + delay(500); + oled_clear(); + oled_clear(); + ESP.restart(); + } + +//--------------------------------------------------------- +// WiFi Wait For Reset Button +//--------------------------------------------------------- + + void wifi_wait_for_reset() { + + // Clear Display + oled_clear(); + + // Draw Text For Reset Settings + oled_text(1, 0, 2, "Press Center Button"); + oled_text(1, 0, 12, "To Reset Config"); + + // Button Functions + for(int i=0; i<12; i++) { + if(btnRedOne.pressed() && btnBlueOne.pressed()) { + wifi_reset(); + break; + } + oled_text(1, i*5, 22, " . "); + delay(250); + } + + } + +//========================================================= +// Server +//========================================================= \ No newline at end of file