diff --git a/Tools/ILIScreenshotViewer licence information.txt b/Tools/ILIScreenshotViewer licence information.txt deleted file mode 100644 index 2c9f877..0000000 --- a/Tools/ILIScreenshotViewer licence information.txt +++ /dev/null @@ -1,23 +0,0 @@ - -This ILIScreenshotViewer.exe file is part of the Arduino ILI9341_due library. - -A set of compatible functions is included in the "ESP8266_uncannyEyes" example. - -The original library licence conditions that apply to the software in this folder are: - -Copyright (c) 2014 Marek Buriak - -Sources can be found at https://github.com/marekburiak/ILI9341_Due. - -ILI9341_due is free software you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 2.1 of the License, or -(at your option) any later version. - -ILI9341_due is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with ILI9341_due. If not, see . diff --git a/Tools/ILIScreenshotViewer.exe b/Tools/ILIScreenshotViewer.exe deleted file mode 100644 index d9f4ed9..0000000 Binary files a/Tools/ILIScreenshotViewer.exe and /dev/null differ diff --git a/Tools/Screenshot_client/Screenshot_client.pde b/Tools/Screenshot_client/Screenshot_client.pde new file mode 100644 index 0000000..22f6afd --- /dev/null +++ b/Tools/Screenshot_client/Screenshot_client.pde @@ -0,0 +1,285 @@ +// This is a Processing sketch, see https://processing.org/ to download the IDE + +// The sketch is a client that requests TFT screenshots from an Arduino board. +// The arduino must call a screenshot server function to respond with pixels. + +// It has been created to work with the TFT_eSPI library here: +// https://github.com/Bodmer/TFT_eSPI + +// The library provides a member function that reads the RGB values of screen pixels +// and an example TFT_Screen_Capture + +// Captured images are stored in the sketch folder, use "Sketch" menu option +// "Show Sketch Folder" or press Ctrl+K + +// Created by: Bodmer 27/1/17 + +// MIT licence applies, all text above must be included in derivative works + +import processing.serial.*; + +Serial serial; // Create an instance called serial + +// ########################################################################################### +// # These are the values to change for a particular setup # +// # +int serial_port = 1; // Use enumerated value from list provided when sketch is run # +int serial_baud_rate = 921600; // Maximum tested is 921600 # +// # +int tft_width = 240; // TFT width in portrait orientation # +int tft_height = 320; // TFT height # +//int tft_width = 320; // TFT width in landscape orientation # +//int tft_height = 240; // TFT height # +// # +// Change the image file type saved here, comment out all but one # +//String image_type = ".jpg"; // # +String image_type = ".png"; // # +//String image_type = ".bmp"; // # +//String image_type = ".tif"; // # +// # +boolean save_border = true; // Save the image with a border # +int border = 5; // Border pixel width # +boolean fade = false; // Fade out image after saving # +// # +int max_images = 10; // Maximum of numbered saved images before over-writing files # +// # +// # End of the values to change for a particular setup # +// ########################################################################################### + +int serialCount = 0; // Count of colour bytes arriving + +int bgcolor = 255; // Background color + +PImage img, tft_img; + +color light_blue = color(50, 128, 255); + +int[] rgb = new int[6]; // Buffer for the RGB colour bytes + +int indexRed = 0; // Colour byte index in the array +int indexGreen = 1; +int indexBlue = 2; + +long end = 10; // Whether we've heard from the microcontroller + +int n = 0; // Whether we've heard from the microcontroller + +boolean got_image = false; + +int x_offset = (500 - tft_width) /2; // Image offsets in the window +int y_offset = 20; // +int xpos, ypos; // Pixel position + +int beginTime = 0; +int pixelWaitTime = 100; // Wait a maximum of 100ms gap for image pixels to arrive +int lastPixelTime = 0; // Time that "image send" command was sent + +int state = 0; // State machine current state + +int progress_bar = 0; +int pixel_count = 0; +float percentage = 0; + +int drawLoopCount = 0; + +void setup() { + + size(500, 540); // Stage size, could handle 480 pixel scrren + noStroke(); // No border on the next thing drawn + + img = createImage(500, 540, ARGB); + for (int i = 0; i < img.pixels.length; i++) { + float a = map(i, 0, img.pixels.length, 255, 0); + img.pixels[i] = color(0, 153, 204, a); + } + + tft_img = createImage(tft_width, tft_height, ARGB); + for (int i = 0; i < tft_img.pixels.length; i++) { + tft_img.pixels[i] = color(0, 0, 0, 255); + } + + frameRate(5000); // High frame rate so draw() loops fast + + xpos = 0; + ypos = 0; + + // Print a list of the available serial ports + println("-----------------------"); + println("Available Serial Ports:"); + println("-----------------------"); + printArray(Serial.list()); + println("-----------------------"); + + print("Port currently used: ["); + print(serial_port); + println("]"); + + String portName = Serial.list()[serial_port]; + + delay(1000); + + serial = new Serial(this, portName, serial_baud_rate); + + state = 99; +} + +void draw() { + drawLoopCount++; + switch(state) { + + case 0: // Init varaibles, send start request + tint(255, 255); + textAlign(CENTER); + textSize(20); + + println(""); + //println("Clearing pipe..."); + beginTime = millis() + 200; + while ( millis() < beginTime ) + { + serial.read(); + } + println("Ready to receive image"); + serial.write("S"); + xpos = 0; + ypos = 0; + serialCount = 0; + progress_bar = 0; + pixel_count = 0; + percentage = 0; + drawLoopCount = 0; + lastPixelTime = millis() + 1000; + state = 1; + break; + + case 1: // Console message, give server some time + println("Requesting image"); + delay(10); + state = 2; + break; + + case 2: // Get size and set start time for render time report + // To do: Read image size info, currently hard coded + beginTime = millis(); + state = 3; + break; + + case 3: // Request pixels and reder them + if ( serial.available() > 0 ) { + + // Add the latest byte from the serial port to array: + while (serial.available()>0) + { + rgb[serialCount] = serial.read(); + serialCount++; + + // If we have 3 colour bytes: + if (serialCount >= 3 ) { + serialCount = 0; + pixel_count++; + stroke(rgb[indexRed], rgb[indexGreen], rgb[indexBlue]); + point(xpos + x_offset, ypos + y_offset); + lastPixelTime = millis(); + xpos++; + if (xpos >= tft_width) { + xpos = 0; + print("."); + progress_bar++; + if (progress_bar >31) + { + progress_bar = 0; + percentage = 0.5 + 100 * pixel_count/(0.001 + tft_width * tft_height); + if (percentage > 100) percentage = 100; + println(" [ " + (int)percentage + "% ]"); + } + ypos++; + if (ypos>=tft_height) { + ypos = 0; + println("Image fetch time = " + (millis()-beginTime)/1000.0 + " s"); + state = 5; + } + } + } + } + } else + { + + if (millis() > (lastPixelTime + pixelWaitTime)) + { + println(""); + System.err.println("No response, trying again..."); + state = 4; + } else + { + // Request 64 more pixels (ESP8266 buffer size) + serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); + serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); + } + } + break; + + case 4: // Time-out, flush serial buffer + println(); + //println("Clearing serial pipe after a time-out"); + int clearTime = millis() + 50; + while ( millis() < clearTime ) + { + serial.read(); + } + state = 0; + break; + + case 5: // Save the image tot he sketch folder + println(); + String filename = "tft_screen_" + n + image_type; + println("Saving image as \"" + filename); // Does not execute + if (save_border) + { + PImage partialSave = get(x_offset - border, y_offset - border, tft_width + 2*border, tft_height + 2*border); + partialSave.save(filename); + } else { + PImage partialSave = get(x_offset, y_offset, tft_width, tft_height); + partialSave.save(filename); + } + + n = n + 1; + if (n>9) n = 0; + drawLoopCount = 0; // Reset value ready for counting in step 6 + state = 6; + break; + + case 6: // Fade the old image if enabled + delay(10); + if (fade) + { + tint(255, drawLoopCount); + image(tft_img, x_offset, y_offset); + } + if (drawLoopCount > 50) state = 0; // Wait for fade to end + break; + + case 99: // Draw image viewer window + textAlign(CENTER); + textSize(20); + background(bgcolor); + image(img, 0, 0); + + fill(0); + text("Bodmer's TFT image viewer", width/2, height-10); + + stroke(0, 0, 0); + + rect(x_offset - border, y_offset - border, tft_width - 1 + 2*border, tft_height - 1 + 2*border); + + fill(100); + rect(x_offset, y_offset, tft_width-1, tft_height-1); + + state = 0; + break; + + default: + println(""); + System.err.println("Error state reached - check sketch!"); + break; + } +} \ No newline at end of file diff --git a/examples/ILI9341/TFT_Screen_Capture/TFT_Screen_Capture.ino b/examples/ILI9341/TFT_Screen_Capture/TFT_Screen_Capture.ino new file mode 100644 index 0000000..ceed295 --- /dev/null +++ b/examples/ILI9341/TFT_Screen_Capture/TFT_Screen_Capture.ino @@ -0,0 +1,165 @@ +/* + This example draws rainbow colours on the screen, adds text in various + fast rendering fonts and then sends the TFT screen to a PC over the serial + port to a processing sketch. + + This sketch uses the GLCD, 2, 4, 6 fonts. + + Make sure all the display driver and pin comnenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +#include // Hardware-specific library +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height + +//TFT_eSPI tft = TFT_eSPI(240, 320); // Could invoke custom library declaring width and height + +unsigned long targetTime = 0; +byte red = 31; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each + +void setup(void) { + Serial.begin(921600); + + tft.init(); + tft.setRotation(0); + tft.fillScreen(TFT_BLACK); + + targetTime = millis() + 1000; +} + +void loop() { + + if (targetTime < millis()) { + targetTime = millis() + 4000; + + rainbow_fill(); // Fill the screen with rainbow colours + + // The standard AdaFruit font still works as before + tft.setTextColor(TFT_BLACK); // Background is not defined so it is transparent + + tft.setCursor (60, 5); + tft.setTextFont(0); // Select font 0 which is the Adafruit font + tft.print("Original Adafruit font!"); + + //tft.drawString("Original Adafruit font!",60,5,1); + + // The new larger fonts do not need to use the .setCursor call, coords are embedded + tft.setTextColor(TFT_BLACK); // Do not plot the background colour + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + tft.drawCentreString("Font size 2", 120, 14, 2); // Draw text centre at position 120, 14 using font 2 + tft.drawCentreString("Font size 4", 120, 30, 4); // Draw text centre at position 120, 30 using font 4 + tft.drawCentreString("12.34", 120, 54, 6); // Draw text centre at position 120, 54 using font 6 + + tft.drawCentreString("12.34 is in font size 6", 120, 92, 2); // Draw text centre at position 120, 92 using font 2 + // Note the x position is the top of the font! + + // draw a floating point number + float pi = 3.14159; // Value to print + int precision = 3; // Number of digits after decimal point + int xpos = 90; // x position + int ypos = 110; // y position + int font = 2; // font number 2 + xpos += tft.drawFloat(pi, precision, xpos, ypos, font); // Draw rounded number and return new xpos delta for next print position + tft.drawString(" is pi", xpos, ypos, font); // Continue printing from new x position + + tft.setTextSize(1); // We are using a size multiplier of 1 + + tft.setTextColor(TFT_BLACK); // Set text colour to black, no background (so transparent) + + tft.setCursor(36, 150, 4); // Set cursor to x = 36, y = 150 and use font 4 + tft.println("Transparent..."); // As we use println, the cursor moves to the next line + + tft.setCursor(30, 175); // Set cursor to x = 30, y = 175 + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text colour to white and background to black + tft.println(" White on black "); + + tft.setTextFont(4); // Select font 4 without moving cursor + tft.setCursor(50, 210); // Set cursor to x = 50, y = 210 without changing the font + tft.setTextColor(TFT_WHITE); + // By using #TFT print we can use all the formatting features like printing HEX + tft.print(57005, HEX); // Cursor does no move to next line + tft.println(48879, HEX); // print and move cursor to next line + + tft.setTextColor(TFT_GREEN, TFT_BLACK); // This time we will use green text on a black background + tft.setTextFont(2); // Select font 2 + + // An easier way to position text and blank old text is to set the datum and use width padding + tft.setTextDatum(BC_DATUM); // Bottom centre for text datum + tft.setTextPadding(241); // Pad text to full screen wdth (240 pixels + 1 spare for +/-1 position rounding) + tft.drawString("Ode to a Small Lump of Green Putty", 120, 300 - 32); + tft.drawString("I Found in My Armpit One Midsummer", 120, 300 - 16); + tft.drawString("Morning", 120, 300); + tft.setTextDatum(TL_DATUM); // Reset to top left for text datum + screenServer(); + } +} + +// Fill screen with a rainbow pattern +void rainbow_fill() +{ + // The colours and state are not initialised so the start colour changes each time the funtion is called + + for (int i = 319; i >= 0; i--) { + // This is a "state machine" that ramps up/down the colour brightnesses in sequence + switch (state) { + case 0: + green ++; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green --; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + // Draw a line 1 pixel wide in the selected colour + tft.drawFastHLine(0, i, tft.width(), colour); // in this example tft.width() returns the pixel width of the display + } +} + + + diff --git a/examples/ILI9341/TFT_Screen_Capture/processing_sketch.ino b/examples/ILI9341/TFT_Screen_Capture/processing_sketch.ino new file mode 100644 index 0000000..4fafcbd --- /dev/null +++ b/examples/ILI9341/TFT_Screen_Capture/processing_sketch.ino @@ -0,0 +1,304 @@ +// Below is a copy of the processing sketch that can be used to capture the images +// The sketch beow is NOT and Arduino IDE sketch! + +// Copy the sketch content below and remove the /* and */ at the beginning and end. +// The sketch runs in Processing version 3.3, it can be downloaded here: +// https://processing.org/download/ + +// When the sketch is loaded in Processing, save it as "Screenshot_Client", and click +// the run triangle. Then check the serial port list in the console report, edit the +// Processing sketch to use the right port by changing the port number allocated in +// "int serial_port = X;" at line 26 (see line 43 below) + +// The Arduino IDE and Processing will share a serial port, make sure only one +// program tries to use the port at any time. Processing may "freeze" otherwise. + +/* <<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS LINE <<<<<<<<<<<<<<<<<<<<<<<<< + +// This is a Processing sketch, see https://processing.org/ to download the IDE + +// The sketch is a client that requests TFT screenshots from an Arduino board. +// The arduino must call a screenshot server function to respond with pixels. + +// It has been created to work with the TFT_eSPI library here: +// https://github.com/Bodmer/TFT_eSPI + +// The library provides a member function that reads the RGB values of screen pixels +// and an example TFT_Screen_Capture + +// Captured images are stored in the Processing sketch folder, use "Sketch" menu option +// "Show Sketch Folder" or press Ctrl+K in the Processing IDE. + +// Created by: Bodmer 27/1/17 + +// MIT licence applies, all text above must be included in derivative works + +import processing.serial.*; + +Serial serial; // Create an instance called serial + +// ########################################################################################### +// # These are the values to change for a particular setup # +// # +int serial_port = 0; // Use enumerated value from list provided when sketch is run # +int serial_baud_rate = 921600; // Maximum tested is 921600 # +// # +int tft_width = 240; // TFT width in portrait orientation # +int tft_height = 320; // TFT height # +//int tft_width = 320; // TFT width in landscape orientation # +//int tft_height = 240; // TFT height # +// # +// Change the image file type saved here, comment out all but one # +//String image_type = ".jpg"; // # +String image_type = ".png"; // # +//String image_type = ".bmp"; // # +//String image_type = ".tif"; // # +// # +boolean save_border = true; // Save the image with a border # +int border = 5; // Border pixel width # +boolean fade = false; // Fade out image after saving # +// # +int max_images = 10; // Maximum of numbered saved images before over-writing files # +// # +// # End of the values to change for a particular setup # +// ########################################################################################### + +int serialCount = 0; // Count of colour bytes arriving + +int bgcolor = 255; // Background color + +PImage img, tft_img; + +color light_blue = color(50, 128, 255); + +int[] rgb = new int[6]; // Buffer for the RGB colour bytes + +int indexRed = 0; // Colour byte index in the array +int indexGreen = 1; +int indexBlue = 2; + +long end = 10; // Whether we've heard from the microcontroller + +int n = 0; // Whether we've heard from the microcontroller + +boolean got_image = false; + +int x_offset = (500 - tft_width) /2; // Image offsets in the window +int y_offset = 20; // +int xpos, ypos; // Pixel position + +int beginTime = 0; +int pixelWaitTime = 100; // Wait a maximum of 100ms gap for image pixels to arrive +int lastPixelTime = 0; // Time that "image send" command was sent + +int state = 0; // State machine current state + +int progress_bar = 0; +int pixel_count = 0; +float percentage = 0; + +int drawLoopCount = 0; + +void setup() { + + size(500, 540); // Stage size, could handle 480 pixel scrren + noStroke(); // No border on the next thing drawn + + img = createImage(500, 540, ARGB); + for (int i = 0; i < img.pixels.length; i++) { + float a = map(i, 0, img.pixels.length, 255, 0); + img.pixels[i] = color(0, 153, 204, a); + } + + tft_img = createImage(tft_width, tft_height, ARGB); + for (int i = 0; i < tft_img.pixels.length; i++) { + tft_img.pixels[i] = color(0, 0, 0, 255); + } + + frameRate(5000); // High frame rate so draw() loops fast + + xpos = 0; + ypos = 0; + + // Print a list of the available serial ports + println("-----------------------"); + println("Available Serial Ports:"); + println("-----------------------"); + printArray(Serial.list()); + println("-----------------------"); + + print("Port currently used: ["); + print(serial_port); + println("]"); + + String portName = Serial.list()[serial_port]; + + delay(1000); + + serial = new Serial(this, portName, serial_baud_rate); + + state = 99; +} + +void draw() { + drawLoopCount++; + switch(state) { + + case 0: // Init varaibles, send start request + tint(255, 255); + textAlign(CENTER); + textSize(20); + + println(""); + //println("Clearing pipe..."); + beginTime = millis() + 200; + while ( millis() < beginTime ) + { + serial.read(); + } + println("Ready to receive image"); + serial.write("S"); + xpos = 0; + ypos = 0; + serialCount = 0; + progress_bar = 0; + pixel_count = 0; + percentage = 0; + drawLoopCount = 0; + lastPixelTime = millis() + 1000; + state = 1; + break; + + case 1: // Console message, give server some time + println("Requesting image"); + delay(10); + state = 2; + break; + + case 2: // Get size and set start time for render time report + // To do: Read image size info, currently hard coded + beginTime = millis(); + state = 3; + break; + + case 3: // Request pixels and reder them + if ( serial.available() > 0 ) { + + // Add the latest byte from the serial port to array: + while (serial.available()>0) + { + rgb[serialCount] = serial.read(); + serialCount++; + + // If we have 3 colour bytes: + if (serialCount >= 3 ) { + serialCount = 0; + pixel_count++; + stroke(rgb[indexRed], rgb[indexGreen], rgb[indexBlue]); + point(xpos + x_offset, ypos + y_offset); + lastPixelTime = millis(); + xpos++; + if (xpos >= tft_width) { + xpos = 0; + print("."); + progress_bar++; + if (progress_bar >31) + { + progress_bar = 0; + percentage = 0.5 + 100 * pixel_count/(0.001 + tft_width * tft_height); + if (percentage > 100) percentage = 100; + println(" [ " + (int)percentage + "% ]"); + } + ypos++; + if (ypos>=tft_height) { + ypos = 0; + println("Image fetch time = " + (millis()-beginTime)/1000.0 + " s"); + state = 5; + } + } + } + } + } else + { + + if (millis() > (lastPixelTime + pixelWaitTime)) + { + println(""); + System.err.println("No response, trying again..."); + state = 4; + } else + { + // Request 64 more pixels (ESP8266 buffer size) + serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); + serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); + } + } + break; + + case 4: // Time-out, flush serial buffer + println(); + //println("Clearing serial pipe after a time-out"); + int clearTime = millis() + 50; + while ( millis() < clearTime ) + { + serial.read(); + } + state = 0; + break; + + case 5: // Save the image tot he sketch folder + println(); + String filename = "tft_screen_" + n + image_type; + println("Saving image as \"" + filename); // Does not execute + if (save_border) + { + PImage partialSave = get(x_offset - border, y_offset - border, tft_width + 2*border, tft_height + 2*border); + partialSave.save(filename); + } else { + PImage partialSave = get(x_offset, y_offset, tft_width, tft_height); + partialSave.save(filename); + } + + n = n + 1; + if (n>9) n = 0; + drawLoopCount = 0; // Reset value ready for counting in step 6 + state = 6; + break; + + case 6: // Fade the old image if enabled + delay(10); + if (fade) + { + tint(255, drawLoopCount); + image(tft_img, x_offset, y_offset); + } + if (drawLoopCount > 50) state = 0; // Wait for fade to end + break; + + case 99: // Draw image viewer window + textAlign(CENTER); + textSize(20); + background(bgcolor); + image(img, 0, 0); + + fill(0); + text("Bodmer's TFT image viewer", width/2, height-10); + + stroke(0, 0, 0); + + rect(x_offset - border, y_offset - border, tft_width - 1 + 2*border, tft_height - 1 + 2*border); + + fill(100); + rect(x_offset, y_offset, tft_width-1, tft_height-1); + + state = 0; + break; + + default: + println(""); + System.err.println("Error state reached - check sketch!"); + break; + } +} + +*/ // <<<<<<<<<<<<<<<<<<<<<<<<< REMOVE THIS LINE <<<<<<<<<<<<<<<<<<<<<<<<< diff --git a/examples/ILI9341/TFT_Screen_Capture/screenServer.ino b/examples/ILI9341/TFT_Screen_Capture/screenServer.ino new file mode 100644 index 0000000..53a8dc0 --- /dev/null +++ b/examples/ILI9341/TFT_Screen_Capture/screenServer.ino @@ -0,0 +1,152 @@ +// TFT screenshot server + +// This is a sketch support tab containing function calls to read a screen image +// off a TFT and send it to a processing client sketch over the serial port. + +// See the processing_sketch tab, it contains a capy of the processing sketch. + +// Use a high baud rate, for an ESP8266: +/* + Serial.begin(921600); +*/ +// 240 x 320 images take about 3.5s to transfer at 921600 baud(minimum is ~2.5s) + +// This sketch has been created to work with the TFT_eSPI library here: +// https://github.com/Bodmer/TFT_eSPI + +// Created by: Bodmer 27/1/17 + +// The MIT permissive free software license applies, include all text above in +// derivatives. + +#define BAUD_RATE 250000 // Maximum Arduino IDE Serial Monitor rate +#define DUMP_BAUD_RATE 921600 // Rate used for screen dumps by ESP8266 + +#define PIXEL_TIMEOUT 100 // 100ms Time-out between pixel requests +#define START_TIMEOUT 10000 // 10s Maximum time to wait at start transfer + +// Start a screen dump server (serial or network) +boolean screenServer(void) +{ + Serial.end(); // Stop the serial port (clears buffers too) + Serial.begin(DUMP_BAUD_RATE); // Force baud rate to be high + yield(); + + boolean result = serialScreenServer(); // Screenshot serial port server + //boolean result = wifiDump(); // Screenshot WiFi UDP port server (WIP) + + Serial.end(); // Stop the serial port (clears buffers too) + Serial.begin(BAUD_RATE); // Return baud rate to normal + yield(); + + //Serial.println(); + //if (result) Serial.println(F("Screen dump passed :-)")); + //else Serial.println(F("Screen dump failed :-(")); + + return result; +} + +// Screenshot serial port server (Processing sketch acts as client) +boolean serialScreenServer(void) +{ + // Serial commands from client: + // 'S' to start the transfer process (To do: reply with width + height) + // 'R' or any character except 'X' to request pixel + // 'X' to abort and return immediately to caller + // Returned boolean values: + // true = image despatched OK + // false = time-out or abort command received + + // Precautionary receive buffer garbage flush for 50ms + uint32_t clearTime = millis() + 50; + while ( millis() < clearTime ) { + Serial.read(); + yield(); + } + + boolean wait = true; + uint32_t lastCmdTime = millis(); // Initialise start of command time-out + + // Wait for the starting flag with a start time-out + while (wait) + { + yield(); + // Check serial buffer + if (Serial.available() > 0) { + // Read the command byte + uint8_t cmd = Serial.read(); + // If it is 'S' (start command) then clear the serial buffer for 100ms and stop waiting + if ( cmd == 'S' ) { + // Precautionary receive buffer garbage flush for 50ms + clearTime = millis() + 50; + while ( millis() < clearTime ) { + Serial.read(); + yield(); + } + wait = false; // No need to wait anymore + lastCmdTime = millis(); // Set last received command time + + // Send screen size, not supported by processing sketch yet + //Serial.write('W'); + //Serial.write(tft.width() >> 8); + //Serial.write(tft.width() & 0xFF); + //Serial.write('H'); + //Serial.write(tft.height() >> 8); + //Serial.write(tft.height() & 0xFF); + //Serial.write('Y'); + } + } + else + { + // Check for time-out + if ( millis() > lastCmdTime + START_TIMEOUT) return false; + } + } + + uint8_t color[3]; // RGB color buffer for 1 pixel + + // Send all the pixels on the whole screen (typically 5 seconds at 921600 baud) + for ( uint32_t y = 0; y < tft.height(); y++) + { + // Increment x by 2 as we send 2 pixels for every byte received + for ( uint32_t x = 0; x < tft.width(); x += 1) + { + yield(); + + // Wait here for serial data to arrive or a time-out elapses + while ( Serial.available() == 0 ) + { + yield; + if ( millis() > lastCmdTime + PIXEL_TIMEOUT) return false; + } + + // Serial data must be available to get here, read 1 byte and + // respond with N pixels, i.e. N x 3 RGB bytes + if ( Serial.read() == 'X' ) { + // X command byte means abort, so clear the buffer and return + clearTime = millis() + 50; + while ( millis() < clearTime ) Serial.read(); + return false; + } + // Save arrival time of the read command (for later time-out check) + lastCmdTime = millis(); + + // Fetch data for N pixels starting at x,y + tft.readRectRGB(x, y, 1, 1, color); + // Send values to client + Serial.write(color[0]); // Pixel 1 red + Serial.write(color[1]); // Pixel 1 green + Serial.write(color[2]); // Pixel 1 blue + //Serial.write(color[3]); // Pixel 2 red + //Serial.write(color[4]); // Pixel 2 green + //Serial.write(color[5]); // Pixel 2 blue + } + } + + // Receive buffer excess command flush for 50ms + clearTime = millis() + 50; + while ( millis() < clearTime ) Serial.read(); + + return true; +} +