Guest User

Untitled

a guest
Aug 2nd, 2020
1,377
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 13.09 KB | None | 0 0
  1. #include <ESPAsyncWebServer.h>
  2. #include "FS.h"
  3. #include "SD_MMC.h"
  4. #include "lcdgfx.h"
  5. #include "esp_camera.h"
  6. #include "camera_index.h"
  7. #include <TJpg_Decoder.h>
  8. #include <TFT_eSPI.h>
  9. TFT_eSPI tft = TFT_eSPI();
  10.  
  11. AsyncWebServer webserver(80);
  12. AsyncWebSocket ws("/ws");
  13.  
  14. const char* ssid = "NSA HONEYPOT";
  15. const char* password = "only4andrew";
  16.  
  17. const int trigger_button_pin = 12;
  18. const int left_button_pin = 1;
  19. const int right_button_pin = 3;
  20. int visible_image_id;
  21. long trigger_button_millis = 0;
  22. long direction_button_millis = 0;
  23.  
  24. int x = 160;
  25. int y = 120;
  26. byte  gray_array [161][121];
  27. byte  resize_array [161][121];
  28. uint8_t display_array [10][128] {};
  29. int bitmap_row = 0;
  30. int bitmap_column = 0;
  31.  
  32. #define SD_CS 5
  33.  
  34. DisplaySSD1306_128x64_I2C display(-1, { -1, 0x3C, 13, 16, 0}); // 16 when psram off
  35.  
  36. camera_fb_t *fb = NULL;
  37. static esp_err_t cam_err;
  38. static esp_err_t card_err;
  39. int file_number = 0;
  40.  
  41. #define PWDN_GPIO_NUM     32
  42. #define RESET_GPIO_NUM    -1
  43. #define XCLK_GPIO_NUM      0
  44. #define SIOD_GPIO_NUM     26
  45. #define SIOC_GPIO_NUM     27
  46. #define Y9_GPIO_NUM       35
  47. #define Y8_GPIO_NUM       34
  48. #define Y7_GPIO_NUM       39
  49. #define Y6_GPIO_NUM       36
  50. #define Y5_GPIO_NUM       21
  51. #define Y4_GPIO_NUM       19
  52. #define Y3_GPIO_NUM       18
  53. #define Y2_GPIO_NUM        5
  54. #define VSYNC_GPIO_NUM    25
  55. #define HREF_GPIO_NUM     23
  56. #define PCLK_GPIO_NUM     22
  57.  
  58. void setup()
  59. {
  60.   Serial.begin(115200);
  61.  
  62.   pinMode(4, OUTPUT);// initialize io4 as an output for LED flash.
  63.   digitalWrite(4, LOW); // flash off
  64.  
  65.   display.begin();
  66.   delay(2000); // just in case pinmode below stops serial comms
  67.  
  68.   init_wifi();
  69.  
  70.   pinMode(trigger_button_pin, INPUT);
  71.   pinMode(left_button_pin, INPUT);
  72.   pinMode(right_button_pin, INPUT);
  73.  
  74.   display.setFixedFont( ssd1306xled_font6x8 );
  75.   display.clear();
  76.   display.printFixed(0,  8, "IP ADDRESS", STYLE_NORMAL);
  77.   display.printFixed(0,  16, WiFi.localIP().toString().c_str(), STYLE_NORMAL);
  78.   delay(4000);
  79.   display.clear();
  80.  
  81.   TJpgDec.setCallback(tft_output);
  82.  
  83.   camera_config_t config;
  84.   config.ledc_channel = LEDC_CHANNEL_0;
  85.   config.ledc_timer = LEDC_TIMER_0;
  86.   config.pin_d0 = Y2_GPIO_NUM;
  87.   config.pin_d1 = Y3_GPIO_NUM;
  88.   config.pin_d2 = Y4_GPIO_NUM;
  89.   config.pin_d3 = Y5_GPIO_NUM;
  90.   config.pin_d4 = Y6_GPIO_NUM;
  91.   config.pin_d5 = Y7_GPIO_NUM;
  92.   config.pin_d6 = Y8_GPIO_NUM;
  93.   config.pin_d7 = Y9_GPIO_NUM;
  94.   config.pin_xclk = XCLK_GPIO_NUM;
  95.   config.pin_pclk = PCLK_GPIO_NUM;
  96.   config.pin_vsync = VSYNC_GPIO_NUM;
  97.   config.pin_href = HREF_GPIO_NUM;
  98.   config.pin_sscb_sda = SIOD_GPIO_NUM;
  99.   config.pin_sscb_scl = SIOC_GPIO_NUM;
  100.   config.pin_pwdn = PWDN_GPIO_NUM;
  101.   config.pin_reset = RESET_GPIO_NUM;
  102.   config.xclk_freq_hz = 20000000;
  103.   config.pixel_format = PIXFORMAT_JPEG;
  104.   //init with high specs to pre-allocate larger buffers
  105.   if (psramFound()) {
  106.     config.frame_size = FRAMESIZE_UXGA;
  107.     config.jpeg_quality = 10;
  108.     config.fb_count = 2;
  109.   } else {
  110.     config.frame_size = FRAMESIZE_SVGA;
  111.     config.jpeg_quality = 12;
  112.     config.fb_count = 1;
  113.   }
  114.  
  115.   // camera init
  116.   cam_err = esp_camera_init(&config);
  117.   if (cam_err != ESP_OK) {
  118.     Serial.printf("Camera init failed with error 0x%x", cam_err);
  119.     return;
  120.   }
  121.  
  122.   sensor_t * s = esp_camera_sensor_get();
  123.   s->set_framesize(s, FRAMESIZE_QQVGA);
  124.   s->set_hmirror(s, 1);
  125.   s->set_vflip(s, 1);
  126.   init_sdcard_arduino_stylie();
  127.  
  128.   ws.onEvent(onEvent);
  129.   webserver.addHandler(&ws);
  130.  
  131.   webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
  132.     Serial.print("wtf here");
  133.     AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_ov2640_html_gz, sizeof(index_ov2640_html_gz));
  134.     response->addHeader("Content-Encoding", "gzip");
  135.     request->send(response);
  136.   });
  137.  
  138.   webserver.on("/image", HTTP_GET, [](AsyncWebServerRequest * request) {
  139.     Serial.println("requesting image from SD");
  140.     if (request->hasParam("id")) {
  141.       AsyncWebParameter* p = request->getParam("id");
  142.       Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
  143.       String imagefile = p->value();
  144.       imagefile = imagefile.substring(4); // remove img_
  145.       imagefile = "full_" + imagefile + ".jpg";
  146.       request->send(SD_MMC, "/" + imagefile, "image/jpeg");
  147.     }
  148.   });
  149.  
  150.   webserver.begin();
  151.  
  152.   file_number = latest_file_number(SD_MMC, "/", 0);
  153.  
  154. }
  155. bool init_wifi()
  156. {
  157.   WiFi.begin(ssid, password);
  158.   while (WiFi.status() != WL_CONNECTED) {
  159.     delay(500);
  160.     Serial.print(".");
  161.   }
  162.   Serial.print("Ready! Use 'http://");
  163.   Serial.print(WiFi.localIP());
  164.   Serial.println("' to connect");
  165.   return true;
  166. }
  167.  
  168. void init_sdcard_arduino_stylie()
  169. {
  170.   if (!SD_MMC.begin("/sd", true)) {
  171.     Serial.println("Card Mount Failed");
  172.     return;
  173.   }
  174.   uint8_t cardType = SD_MMC.cardType();
  175.  
  176.   if (cardType == CARD_NONE) {
  177.     Serial.println("No SD_MMC card attached");
  178.     return;
  179.   }
  180.  
  181.   Serial.print("SD_MMC Card Type: ");
  182.   if (cardType == CARD_MMC) {
  183.     Serial.println("MMC");
  184.   } else if (cardType == CARD_SD) {
  185.     Serial.println("SDSC");
  186.   } else if (cardType == CARD_SDHC) {
  187.     Serial.println("SDHC");
  188.   } else {
  189.     Serial.println("UNKNOWN");
  190.   }
  191.  
  192.   uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
  193.   Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
  194.  
  195.   Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
  196.   Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));
  197. }
  198.  
  199. void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len)
  200. {
  201.   // String incoming = String((char *)data); No idea why.. gave extra characters in data for short names.
  202.   // so ....
  203.  
  204.   // websocket events
  205. }
  206.  
  207. int latest_file_number(fs::FS &fs, const char * dirname, uint8_t levels)
  208. {
  209.   String file_name, file_id;
  210.   int until_dot, from_underscore;
  211.   File root = fs.open(dirname);
  212.  
  213.   File file = root.openNextFile();
  214.   while (file) {
  215.     file_name = file.name();
  216.     // Serial.println(file_name);
  217.     from_underscore = file_name.lastIndexOf('_') + 1;
  218.     until_dot = file_name.lastIndexOf('.');
  219.     file_id = file_name.substring(from_underscore, until_dot);
  220.     // Serial.println(file_id);
  221.     file = root.openNextFile();
  222.   }
  223.   return file_id.toInt();
  224. }
  225.  
  226. static bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
  227. {
  228.   if ( y >= 120 ) return 0;
  229.   //  Serial.print("x"); Serial.print(" "); Serial.println(x);
  230.   //  Serial.print("y"); Serial.print(" "); Serial.println(y);
  231.   for (int p = 0; p < w * h; p++) { //pixels in current tile
  232.     uint16_t R = (((bitmap[p]) >> 11) & 0x1F) << 3; // extract R component
  233.     uint16_t G = (((bitmap[p]) >> 5) & 0x3F) << 2; // extract G component
  234.     uint16_t B = ((bitmap[p]) & 0x1F) << 3; // extract B component
  235.     uint16_t gray = (R * 30 + G * 59 + B * 11) / 100; // formula from the link above
  236.  
  237.     if (p % 16 == 0 && p > 0) { // 16 x 16 tile
  238.       bitmap_row++ ;
  239.     }
  240.  
  241.     bitmap_column = p - (bitmap_row * 16);
  242.  
  243.     gray_array[x + bitmap_column][y + bitmap_row] = gray;
  244.  
  245.     // if (y <= 96 && p == 255) { // 16x16 tile
  246.     //  bitmap_row = 0;
  247.     // }
  248.     if (p == 127) {  // 16x8 tile
  249.       bitmap_row = 0;
  250.     }
  251.   }
  252.   return 1;
  253. }
  254.  
  255. esp_err_t display_image_from_sd(int fileno)
  256. {
  257.   fs::FS &fs = SD_MMC;
  258.   char *filename = (char*)malloc(11 + sizeof(fileno));
  259.   sprintf(filename, "/thumb_%d.jpg", fileno);
  260.   Serial.println(filename);
  261.   File file = fs.open(filename);
  262.   if (!file) {
  263.     ESP_LOGE(TAG, "file open failed");
  264.     return ESP_FAIL;
  265.   }
  266.   TJpgDec.drawSdJpg(0, 0, file);
  267.   file.close();
  268.   Serial.println("Start dithering");
  269.   resize_dither_display(160);
  270.   char *id4html = (char*)malloc(10 + sizeof(fileno));
  271.   sprintf(id4html, "viewid:%d", fileno);
  272.   ws.textAll((char*)id4html);// image id for slide
  273. }
  274.  
  275. esp_err_t resize_dither_display(int res) {
  276.   // resize
  277.   int new_x = 0;
  278.   int new_y = 0;
  279.   //  if (res = 800) {
  280.   //    for (int y = 0; y < 800; y++) {
  281.   //      if (y % 7 == 0  && x > 0) {
  282.   //        y++;
  283.   //      }
  284.   //
  285.   //      for (int x = 0; x < 600; x++) {
  286.   //        if (x % 10 == 0  && x > 0) {
  287.   //          x++;
  288.   //        }
  289.   //        if (x == 0) {
  290.   //          new_x = 0;
  291.   //        }
  292.   //        resize_array[new_x][new_y] = gray_array[x][y];
  293.   //        new_x++;
  294.   //      }
  295.   //      new_y++;
  296.   //    }
  297.   //  } else {
  298.   for (int y = 0; y < 120; y++) {
  299.     if (y != 14 && y != 29 && y != 42 && y != 57 && y != 60 && y != 75 && y != 88 && y != 103) {
  300.       y++;
  301.     }
  302.  
  303.     for (int x = 0; x < 160; x++) {
  304.       if (x % 4 == 0  && x > 0) {
  305.         x++;
  306.       }
  307.       if (x == 0) {
  308.         new_x = 0;
  309.       }
  310.       resize_array[new_x][new_y] = gray_array[x][y];
  311.       new_x++;
  312.     }
  313.     new_y++;
  314.   }
  315.   //  }
  316.  
  317.   // dither
  318.   for (int j = 0; j < new_y; j++) {
  319.     for (int i = 0; i < new_x; i++) {
  320.  
  321.       int oldpixel = resize_array[i][j];
  322.       int newpixel  = (oldpixel > 128) ? 255 : 0;
  323.       resize_array[i][j] = newpixel;
  324.       int quant_error   = oldpixel - newpixel;
  325.  
  326.       resize_array[i + 1][j    ] = resize_array[i + 1][j    ] + (quant_error * 7 / 16);
  327.       resize_array[i - 1][j + 1] = resize_array[i - 1][j + 1] + (quant_error * 3 / 16);
  328.       resize_array[i    ][j + 1] = resize_array[i    ][j + 1] + (quant_error * 5 / 16);
  329.       resize_array[i + 1][j + 1] = resize_array[i + 1][j + 1] + (quant_error * 1 / 16);
  330.  
  331.     }
  332.   }
  333.  
  334.   //display
  335.   for (int x = 0; x < new_x; x++) {
  336.     for (int y = 0; y < new_y; y++) {
  337.       int black_white = 128 < resize_array[x][y] ? 1 : 0;
  338.       display_array[y / 8][x] |= black_white ? (1 << (y & 7)) : 0;
  339.     }
  340.   }
  341.  
  342.   display.drawBuffer1(10, 0, 128, 64, &display_array[0][0]);
  343.  
  344.   memset(gray_array, 0, sizeof(gray_array));
  345.   memset(resize_array, 0, sizeof(resize_array));
  346.   memset(display_array, 0, sizeof(display_array));
  347.   return ESP_OK;
  348. }
  349.  
  350. esp_err_t display_stream()
  351. {
  352.   camera_fb_t * fb = esp_camera_fb_get();
  353.   if (!fb) {
  354.     ESP_LOGE(TAG, "Camera Capture Failed");
  355.     return ESP_FAIL;
  356.   }
  357.  
  358.   TJpgDec.drawJpg(0, 0, (const uint8_t*)fb->buf, (uint32_t)fb->len);
  359.   resize_dither_display(160);
  360.   esp_camera_fb_return(fb);
  361.   fb = NULL;
  362.   return ESP_OK;
  363. }
  364.  
  365. esp_err_t frame_capture()
  366. {
  367.   fs::FS &fs = SD_MMC;
  368.   file_number++;
  369.   digitalWrite(4, HIGH); // flash on
  370.   sensor_t * s = esp_camera_sensor_get();
  371.   s->set_framesize(s, FRAMESIZE_SVGA);
  372.   delay(300);
  373.   camera_fb_t * fb = esp_camera_fb_get();
  374.   digitalWrite(4, LOW);
  375.   char *full_filename = (char*)malloc(10 + sizeof(file_number));
  376.   sprintf(full_filename, "/full_%d.jpg", file_number);
  377.   Serial.println(full_filename);
  378.   File file = fs.open(full_filename, FILE_WRITE);
  379.   if (file != NULL)  {
  380.     file.write(fb->buf, fb->len);
  381.     Serial.println("saved file");
  382.   }  else  {
  383.     Serial.println("Could not open file");
  384.   }
  385.   file.close();
  386.   free(full_filename);
  387.   esp_camera_fb_return(fb);
  388.  
  389.  
  390.   s->set_framesize(s, FRAMESIZE_QQVGA);
  391.   delay(300);
  392.   fb = esp_camera_fb_get();
  393.  
  394.   char *thumb_filename  = (char*)malloc(13 + sizeof(file_number));
  395.   sprintf(thumb_filename , "/thumb_%d.jpg", file_number);
  396.   Serial.println(thumb_filename);
  397.   file = fs.open(thumb_filename , FILE_WRITE);
  398.   if (file != NULL)  {
  399.     file.write(fb->buf, fb->len);
  400.     Serial.println("saved file");
  401.   }  else  {
  402.     Serial.println("Could not open file");
  403.   }
  404.   file.close();
  405.   free(thumb_filename);
  406.   esp_camera_fb_return(fb);
  407. }
  408.  
  409. void loop()
  410. {
  411.   display_stream();
  412.  
  413.   // add in a delay to avoid repeat presses
  414.   if (digitalRead(trigger_button_pin) == HIGH && millis() - trigger_button_millis > 1000) {
  415.     trigger_button_millis = millis();
  416.     frame_capture();
  417.     display_image_from_sd(file_number);
  418.     delay(2000); // Hold image on OLED
  419.   }
  420.  
  421.   if (millis() - direction_button_millis > 2000) { // after two seconds of no directions, reset visible to current
  422.     visible_image_id = file_number;
  423.   }
  424.  
  425.   while (digitalRead(left_button_pin) == HIGH) {
  426.     visible_image_id--;
  427.     display_image_from_sd(visible_image_id);
  428.     delay(1000); // allow browser to catch up
  429.   }
  430.  
  431.   while (digitalRead(right_button_pin) == HIGH) {
  432.     visible_image_id++;
  433.     display_image_from_sd(visible_image_id);
  434.     delay(1000); // allow browser to catch up
  435.   }
  436.  
  437.   //  display.clear();
  438.   //    display_image_from_sd(file_number);
  439.   //    delay(4000);
  440.   //    display_image_from_sd(file_number-1);
  441.   //    delay(4000);
  442.   //    display_image_from_sd(file_number-2);
  443.   //    delay(4000);
  444.   //    display_image_from_sd(file_number-3);
  445.   //    delay(4000);
  446.   //    display_image_from_sd(file_number-4);
  447.   //    delay(4000);
  448.   //    display_image_from_sd(file_number-5);
  449.   //    delay(4000);
  450.   //    display_image_from_sd(file_number-4);
  451.   //    delay(4000);
  452.   //    display_image_from_sd(file_number-3);
  453.   //    delay(4000);
  454.   //    display_image_from_sd(file_number-2);
  455.   //    delay(4000);
  456.   //   display_image_from_sd(file_number-1);
  457.   //    //    delay(2000);
  458.   //    //    display_image_from_sd(file_number - 4);
  459.   //    //    delay(2000);
  460.   //    //    display_image_from_sd(file_number - 3);
  461.   //    //    delay(2000);
  462.   //    //    display_image_from_sd(file_number - 2);
  463.   //    delay(10000);
  464.  
  465. }
Add Comment
Please, Sign In to add comment