diff --git a/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32CAM_Client_RGB565/ESP32CAM_Client_RGB565.ino b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32CAM_Client_RGB565/ESP32CAM_Client_RGB565.ino new file mode 100644 index 0000000..5ab4e0b --- /dev/null +++ b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32CAM_Client_RGB565/ESP32CAM_Client_RGB565.ino @@ -0,0 +1,105 @@ +#include "esp_camera.h" +#include +#include + +#define PWDN_GPIO_NUM 32 +#define RESET_GPIO_NUM -1 +#define XCLK_GPIO_NUM 0 +#define SIOD_GPIO_NUM 26 +#define SIOC_GPIO_NUM 27 + +#define Y9_GPIO_NUM 35 +#define Y8_GPIO_NUM 34 +#define Y7_GPIO_NUM 39 +#define Y6_GPIO_NUM 36 +#define Y5_GPIO_NUM 21 +#define Y4_GPIO_NUM 19 +#define Y3_GPIO_NUM 18 +#define Y2_GPIO_NUM 5 +#define VSYNC_GPIO_NUM 25 +#define HREF_GPIO_NUM 23 +#define PCLK_GPIO_NUM 22 + +const char* ssid = "ESP32-THAT-PROJECT"; +const char* password = "California"; + +const char* websockets_server_host = "192.168.4.1"; +const uint16_t websockets_server_port = 8888; + +using namespace websockets; +WebsocketsClient client; + +void setup() { + Serial.begin(115200); + Serial.setDebugOutput(true); + Serial.println(); + + camera_config_t config; + config.ledc_channel = LEDC_CHANNEL_0; + config.ledc_timer = LEDC_TIMER_0; + config.pin_d0 = Y2_GPIO_NUM; + config.pin_d1 = Y3_GPIO_NUM; + config.pin_d2 = Y4_GPIO_NUM; + config.pin_d3 = Y5_GPIO_NUM; + config.pin_d4 = Y6_GPIO_NUM; + config.pin_d5 = Y7_GPIO_NUM; + config.pin_d6 = Y8_GPIO_NUM; + config.pin_d7 = Y9_GPIO_NUM; + config.pin_xclk = XCLK_GPIO_NUM; + config.pin_pclk = PCLK_GPIO_NUM; + config.pin_vsync = VSYNC_GPIO_NUM; + config.pin_href = HREF_GPIO_NUM; + config.pin_sscb_sda = SIOD_GPIO_NUM; + config.pin_sscb_scl = SIOC_GPIO_NUM; + config.pin_pwdn = PWDN_GPIO_NUM; + config.pin_reset = RESET_GPIO_NUM; + config.xclk_freq_hz = 10000000; + config.pixel_format = PIXFORMAT_RGB565; + config.frame_size = FRAMESIZE_QQVGA; // 160x120 + config.jpeg_quality = 10; + config.fb_count = 1; + + // camera init + esp_err_t err = esp_camera_init(&config); + if (err != ESP_OK) { + Serial.printf("Camera init failed with error 0x%x", err); + return; + } + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + Serial.println(""); + Serial.println("WiFi connected"); + + Serial.println("Socket Connecting"); + + while(!client.connect(websockets_server_host, websockets_server_port, "/")){ + delay(500); + Serial.print("."); + } + + Serial.println("Socket Connected!"); +} + +void loop() { + camera_fb_t *fb = NULL; + esp_err_t res = ESP_OK; + fb = esp_camera_fb_get(); + if(!fb){ + Serial.println("Camera capture failed"); + esp_camera_fb_return(fb); + return; + } + + if(fb->format != PIXFORMAT_RGB565){ + Serial.println("PIXFORMAT_RGB565 not implemented"); + return; + } + + client.sendBinary((const char*) fb->buf, fb->len); + esp_camera_fb_return(fb); +} diff --git a/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_Dual_Core_JPEG/ESP32TTGO_Server_Dual_Core_JPEG.ino b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_Dual_Core_JPEG/ESP32TTGO_Server_Dual_Core_JPEG.ino new file mode 100644 index 0000000..1e08143 --- /dev/null +++ b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_Dual_Core_JPEG/ESP32TTGO_Server_Dual_Core_JPEG.ino @@ -0,0 +1,135 @@ +// Example from TJpg_Decoder library: +// https://github.com/Bodmer/TJpg_Decoder +// https://github.com/Bodmer/TJpg_Decoder/blob/master/examples/ESP32_Dual_Core_Flash_Jpg/ESP32_Dual_Core_Flash_Jpg.ino + +#include +#include +#include +#include +#include + +const char* ssid = "ESP32-THAT-PROJECT"; +const char* password = "California"; + +using namespace websockets; +WebsocketsServer server; +WebsocketsClient client; + +TFT_eSPI tft = TFT_eSPI(); + +TaskHandle_t Task1; // Global variables available to BOTH processors 0 and 1 +const uint8_t* arrayName; // Name of FLASH array containing Jpeg +uint16_t arrayLength; // Length of the Jpeg Image +bool doDecoding = false; // Mutex flag to start decoding +bool mcuReady = false; // Mutex flag to indicate an MCU block is ready for rendering +uint16_t mcuBuffer[16*16]; // Buffer to grab a snapshot of decoded MCU block +int32_t mcu_x, mcu_y, mcu_w, mcu_h; // Snapshot of the place to render the MCU + +void setup() { + Serial.begin(115200); + + tft.begin(); + tft.setRotation(1); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.fillScreen(TFT_BLACK); + tft.setSwapBytes(true); + tft.setTextFont(4); + TJpgDec.setJpgScale(1); + TJpgDec.setCallback(mcu_decoded); + + WiFi.softAP(ssid, password); + + tft.println("> Version.2 "); + tft.println("> w/ JPEG v2"); + tft.println("> Ready To Go!"); + tft.println("> Waiting For"); + tft.println("> ESP32CAM"); + + server.listen(8888); +} + +void loop() { + + if(server.poll()){ + xTaskCreate(decodeJpg, "decodeJpg", 10000, NULL, 0, &Task1); + client = server.accept(); + tft.fillScreen(TFT_BLACK); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.setCursor(163, 10, 2); + tft.print("File Size"); + tft.setCursor(163, 50, 2); + tft.print("Network ms"); + tft.setCursor(163, 90, 2); + tft.print("Drawing ms"); + } + + if(client.available()){ + client.poll(); + + uint32_t t = millis(); + WebsocketsMessage msg = client.readBlocking(); + drawingTimeText(msg.length(), 25); + drawingTimeText(millis() - t, 65); + + arrayName = (const uint8_t*)msg.c_str(); + arrayLength = msg.length(); + + mcuReady = false; // Flag which is set true when a MCU block is ready for display + doDecoding = true; // Flag to tell task to decode the image + + t = millis(); + + while(doDecoding || mcuReady) { + if (mcuReady) { + tft.pushImage(mcu_x, mcu_y, mcu_w, mcu_h, mcuBuffer); + mcuReady = false; + } + yield(); + } + + drawingTimeText(millis() - t, 105); + } +} + +// This next function will be called by the TJpg_Decoder library during decoding of the jpeg file +// A copy of the decoded MCU block is grabbed for rendering so decoding can then continue while +// the MCU block is rendered on the TFT. Note: This function is called by processor 0 +bool mcu_decoded(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) +{ + // Stop further decoding as image is running off bottom of screen + if ( y >= tft.height() ) return 0; + + while(mcuReady) yield(); // Wait here if rendering of last MCU block to TFT is still in progress + + memcpy(mcuBuffer, bitmap, 16*16*2); // Grab a copy of the MCU block image + mcu_x = x; // Grab postion and size of MCU block + mcu_y = y; + mcu_w = w; + mcu_h = h; + mcuReady = true; // Flag to tell processor 1 that rendering of MCU can start + + // Return 1 to decode next Jpeg MCU block + return 1; +} + +// This is the task that runs on processor 0 (Arduino sketch runs on processor 1) +// It decodes the Jpeg image +void decodeJpg(void* pvParameter) { + // This is an infinite loop, effectively the same as the normal sketch loop() + // but this function and loop is running on processor 0 + for(;;) { + // Decode the Jpeg image + if (doDecoding) { // Only start decoding if main sketch sets this flag + TJpgDec.drawJpg(0, 7, arrayName, arrayLength); // Runs until complete image decoded + doDecoding = false; // Set mutex false to indicate decoding has ended + } + yield(); // Must yield in this loop + } +} + +void drawingTimeText(uint32_t deltaT, int yPos){ + tft.setTextColor(TFT_GREEN,TFT_BLACK); + tft.fillRect(163, yPos, 77, 20,TFT_BLACK); + tft.setCursor(163, yPos, 4); + tft.print(deltaT); +} diff --git a/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_JPEG/ESP32TTGO_Server_JPEG.ino b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_JPEG/ESP32TTGO_Server_JPEG.ino new file mode 100644 index 0000000..4971bde --- /dev/null +++ b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_JPEG/ESP32TTGO_Server_JPEG.ino @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include + +#define FRAMESIZE_QQVGA_WIDTH 160 +#define FRAMESIZE_QQVGA_HEGIHT 120 + +const char* ssid = "ESP32-THAT-PROJECT"; +const char* password = "California"; + +using namespace websockets; +WebsocketsServer server; +WebsocketsClient client; + +TFT_eSPI tft = TFT_eSPI(); + +void setup() { + tft.begin(); + tft.setRotation(1); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.fillScreen(TFT_BLACK); + tft.setSwapBytes(true); + tft.setTextFont(4); + TJpgDec.setJpgScale(1); + TJpgDec.setCallback(tft_output); + WiFi.softAP(ssid, password); + + tft.println("> Version.2 "); + tft.println("> w/ JPEG"); + tft.println("> Ready To Go!"); + tft.println("> Waiting For"); + tft.println("> ESP32CAM"); + + server.listen(8888); +} + +void loop() { + if(server.poll()){ + client = server.accept(); + + tft.fillScreen(TFT_BLACK); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.setCursor(163, 10, 2); + tft.print("File Size"); + tft.setCursor(163, 50, 2); + tft.print("Network ms"); + tft.setCursor(163, 90, 2); + tft.print("Drawing ms"); + } + + if(client.available()){ + client.poll(); + + uint32_t t = millis(); + WebsocketsMessage msg = client.readBlocking(); + drawingTimeText(msg.length(), 25); + drawingTimeText(millis() - t, 65); + + t = millis(); + + TJpgDec.drawJpg(0, 7, (const uint8_t*)msg.c_str(), msg.length()); + + drawingTimeText(millis() - t, 105); + } +} + +void drawingTimeText(uint32_t deltaT, int yPos){ + tft.setTextColor(TFT_GREEN,TFT_BLACK); + tft.fillRect(163, yPos, 77, 20,TFT_BLACK); + tft.setCursor(163, yPos, 4); + tft.print(deltaT); +} + +bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap){ + if ( y >= tft.height() ) return 0; + tft.pushImage(x, y, w, h, bitmap); + return 1; +} diff --git a/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_RGB565/ESP32TTGO_Server_RGB565.ino b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_RGB565/ESP32TTGO_Server_RGB565.ino new file mode 100644 index 0000000..e40bf1a --- /dev/null +++ b/ESP32_TTGO/ESP32CAM_WiFi_Direct_v2_Faster/ESP32TTGO_Server_RGB565/ESP32TTGO_Server_RGB565.ino @@ -0,0 +1,72 @@ +#include +#include +#include +#include + +#define FRAMESIZE_QQVGA_WIDTH 160 +#define FRAMESIZE_QQVGA_HEGIHT 120 + +const char* ssid = "ESP32-THAT-PROJECT"; +const char* password = "California"; + +using namespace websockets; +WebsocketsServer server; +WebsocketsClient client; + +TFT_eSPI tft = TFT_eSPI(); + +void setup() { + tft.begin(); + tft.setRotation(1); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.fillScreen(TFT_BLACK); + tft.setSwapBytes(false); + tft.setTextFont(4); + + WiFi.softAP(ssid, password); + + tft.println("> Version.2 "); + tft.println("> w/ RGB565"); + tft.println("> Ready To Go!"); + tft.println("> Waiting For"); + tft.println("> ESP32CAM"); + + server.listen(8888); +} + +void loop() { + if(server.poll()){ + client = server.accept(); + + tft.fillScreen(TFT_BLACK); + tft.fillScreen(TFT_BLACK); + tft.setTextColor(TFT_WHITE,TFT_BLACK); + tft.setCursor(163, 10, 2); + tft.print("File Size"); + tft.setCursor(163, 50, 2); + tft.print("Network ms"); + tft.setCursor(163, 90, 2); + tft.print("Drawing ms"); + } + + if(client.available()){ + client.poll(); + + uint32_t t = millis(); + WebsocketsMessage msg = client.readBlocking(); + drawingTimeText(msg.length(), 25); + drawingTimeText(millis() - t, 65); + + t = millis(); + tft.pushImage(0, 7, FRAMESIZE_QQVGA_WIDTH, FRAMESIZE_QQVGA_HEGIHT, (uint16_t*) ((const uint8_t*)msg.c_str())); + + drawingTimeText(millis() - t, 105); + } +} + +void drawingTimeText(uint32_t deltaT, int yPos){ + tft.setTextColor(TFT_GREEN,TFT_BLACK); + tft.fillRect(163, yPos, 77, 20,TFT_BLACK); + tft.setCursor(163, yPos, 4); + tft.print(deltaT); +}