From ada678d76e71207c0b10be1c65c2bb92ebfb1cfe Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 2 Apr 2018 02:53:42 +0100 Subject: [PATCH] Added Waveshare ePaper support Also added ability to push 1bpp bitmaps to a Sprite to support rendering images on an EPaper screen. Floyd-Steinberg dithering and basic graphics example added as first ePaper demo. --- Extensions/Sprite.cpp | 75 ++++++- TFT_eSPI.cpp | 1 - User_Setup_Select.h | 18 +- User_Setups/Setup17_ePaper.h | 94 +++++++++ examples/ePaper/Floyd_Steinberg/EPD_Support.h | 105 ++++++++++ .../Floyd_Steinberg/Floyd_Steinberg.ino | 187 +++++++++++++++++ .../Floyd_Steinberg/Floyd_Steinberg_BMP.ino | 198 ++++++++++++++++++ examples/ePaper/Floyd_Steinberg/SPIFFS.ino | 92 ++++++++ .../ePaper/Floyd_Steinberg/data/TestCard.bmp | Bin 0 -> 47542 bytes .../ePaper/Floyd_Steinberg/data/Tiger.bmp | Bin 0 -> 42262 bytes 10 files changed, 760 insertions(+), 10 deletions(-) create mode 100644 User_Setups/Setup17_ePaper.h create mode 100644 examples/ePaper/Floyd_Steinberg/EPD_Support.h create mode 100644 examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino create mode 100644 examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino create mode 100644 examples/ePaper/Floyd_Steinberg/SPIFFS.ino create mode 100644 examples/ePaper/Floyd_Steinberg/data/TestCard.bmp create mode 100644 examples/ePaper/Floyd_Steinberg/data/Tiger.bmp diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 90fadae..0ebca60 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -304,7 +304,42 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 } } } - // TODO Currently does nothing for 1 bpp + + else // 1bpp + { + // Move coordinate rotation to support fn + if (_rotation == 1) + { + int32_t tx = x; + x = _dwidth - y - 1; + y = tx; + } + else if (_rotation == 2) + { + x = _dwidth - x - 1; + y = _dheight - y - 1; + } + else if (_rotation == 3) + { + int32_t tx = x; + x = y; + y = _dheight - tx - 1; + } + + uint8_t* pdata = (uint8_t*) data; + uint32_t ww = (w+7) & 0xFFF8; + for (int32_t yp = 0; yp // Setup file configured for my ST7735 128x128 display //#include // Setup file configured for my ILI9163 128x128 display //#include // Setup file configured for my ST7735 -//#include // Setup file configured for my stock RPi TFT with touch -//#include // Setup file configured for my stock RPi TFT with touch +//#include // Setup file configured for ESP8266 and RPi TFT with touch +//#include // Setup file configured for ESP32 and RPi TFT with touch //#include // Setup file for the ESP32 based M5Stack //#include // Setup file for the ESP32 with parallel bus TFT //#include // Setup file for the ESP32 with parallel bus TFT //#include // Setup file configured for HX8357D (untested) //#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file for any Waveshare ePaper display -//#include - -// ePaper #include // Setup file template for copying/editting +//#include #endif // USER_SETUP_LOADED @@ -70,7 +69,7 @@ #define TFT_DRIVER 0x6D02 #elif defined (RPI_ILI9486_DRIVER) #include - #define TFT_DRIVER 0x9481 + #define TFT_DRIVER 0x9486 #elif defined (ILI9481_DRIVER) #include #define TFT_DRIVER 0x9481 @@ -83,6 +82,11 @@ #elif defined (EPD_DRIVER) #include "TFT_Drivers/EPD_Defines.h" #define TFT_DRIVER 0xE9D +#elif defined (XYZZY_DRIVER) // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE + #include "TFT_Drivers/XYZZY_Defines.h" + #define TFT_DRIVER 0x0000 +#else + #define TFT_DRIVER 0x0000 #endif // These are the pins for all ESP8266 boards diff --git a/User_Setups/Setup17_ePaper.h b/User_Setups/Setup17_ePaper.h new file mode 100644 index 0000000..3704cc5 --- /dev/null +++ b/User_Setups/Setup17_ePaper.h @@ -0,0 +1,94 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +#define EPD_DRIVER // ePaper driver + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + + +// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + +// Note: Pin allocations for the ePaper signals are defined in +// the ePaper library's epdif.h file. There follows the default +// pins already included in epdif.h file for the ESP8266: + +/////////////////////////////////////////////////////////////////// +// For ESP8266 connect as follows: // +// Display 3.3V to NodeMCU 3V3 // +// Display GND to NodeMCU GND // +// // +// Display GPIO NodeMCU pin // +// BUSY 5 D1 // +// RESET 4 D2 // +// DC 0 D3 // +// CS 2 D4 // +// CLK 14 D5 // +// D6 (MISO not connected to display) // +// DIN 13 D7 // +// // +/////////////////////////////////////////////////////////////////// + + +// ################################################################################## +// +// Section 2. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 below, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Not used +// +// ################################################################################## + diff --git a/examples/ePaper/Floyd_Steinberg/EPD_Support.h b/examples/ePaper/Floyd_Steinberg/EPD_Support.h new file mode 100644 index 0000000..ce3ce1d --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/EPD_Support.h @@ -0,0 +1,105 @@ +/* Support definitions and functions for ePaper examples + * These tailor the library and screen settings + * Must be a header file to ensure #defines are established first + * + * Created by Bodmer 30/3/18 for TFT_eSPI library: + * https://github.com/Bodmer/TFT_eSPI + */ + +/* + EPD_WIDTH and EPD_HEIGHT are automatically defined here based on the library selected + + For 2 colour ePaper displays create one frame pointer in sketch: + uint8_t* framePtr; + + For 3 colour ePaper displays create two frame pointers in sketch: + uint8_t* blackFramePtr; + uint8_t* redFramePtr; + + Call this function to update whole display: + updateDisplay(); +*/ +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + + +//------------------------------------------------------------------------------------ +// Define which colour values are paper and ink +//------------------------------------------------------------------------------------ +#if defined (EPD2IN7B_H) + #define COLORED 1 // EPD2IN7B is opposite to all others! + #define UNCOLORED 0 +#else + #define COLORED 0 + #define UNCOLORED 1 +#endif + + +//------------------------------------------------------------------------------------ +// Define the width and height of the different displays +//------------------------------------------------------------------------------------ +#if defined (EPD1IN54_H) || defined (EPD1IN54B_H) + #define EPD_WIDTH 200 // Frame buffer is 5000 bytes + #define EPD_HEIGHT 200 + +#elif defined (EPD1IN54C_H) + #define EPD_WIDTH 152 // 2 frame buffers of 2888 bytes each + #define EPD_HEIGHT 152 + +#elif defined (EPD2IN7_H) || defined (EPD2IN7B_H) + #define EPD_WIDTH 176 // Frame buffer is 5808 bytes + #define EPD_HEIGHT 264 + +#elif defined (EPD2IN9_H) || defined (EPD2IN9B_H) + #define EPD_WIDTH 128 // Frame buffer is 4736 bytes + #define EPD_HEIGHT 296 + +#elif defined (EPD2IN13_H) + #define EPD_WIDTH 122 // Frame buffer is 4000 bytes + #define EPD_HEIGHT 250 + +#elif defined (EPD2IN13B_H) + #define EPD_WIDTH 104 // 2 frame buffers of 2756 bytes each + #define EPD_HEIGHT 212 + +#elif defined (EPD4IN2_H) + #define EPD_WIDTH 400 // Frame buffer is 15000 bytes + #define EPD_HEIGHT 300 + +// ESP8266 has just enough RAM for a 2 color 7.5" display full screen buffer +// ESP32 has just enough RAM for 2 or 3 color 7.5" display +// (Without using partial screen updates) +#elif defined (EPD7IN5_H) || defined (EPD7IN5B_H) + #define EPD_WIDTH 640 // 2 colour frame buffer is 30720 bytes + #define EPD_HEIGHT 384 // 2 colour frame buffer is 61440 bytes + +#else + # error "Selected ePaper library is not supported" + +#endif + + +//------------------------------------------------------------------------------------ +// Update display - different displays have different function names in the default +// Waveshare libraries :-( +//------------------------------------------------------------------------------------ +#if defined (EPD1IN54B_H) || defined(EPD1IN54C_H) || defined(EPD2IN13B_H) || defined(EPD2IN7B_H) || defined(EPD2IN9B_H) || defined(EPD4IN2_H) + void updateDisplay(uint8_t* blackFrame = blackFramePtr, uint8_t* redFrame = redFramePtr) + { + ePaper.DisplayFrame(blackFrame, redFrame); // Update 3 colour display +#else + void updateDisplay(uint8_t* blackFrame = framePtr) + { + #if defined (EPD2IN7_H) || defined(EPD4IN2_H) + ePaper.DisplayFrame(blackFrame); // Update 2 color display + + #elif defined (EPD1IN54_H) || defined(EPD2IN13_H) || defined(EPD2IN9_H) + ePaper.SetFrameMemory(blackFrame); // Update 2 colour display + + #else + # error "Selected ePaper library is not supported" + #endif +#endif +} + diff --git a/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino new file mode 100644 index 0000000..1245a8d --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino @@ -0,0 +1,187 @@ +// Display grey-scale images on a Monchrome ePaper display using +// Floyd-Steinberg dithering +// https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering + +// Example created by Bodmer 31/3/18 for TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI +// Select the ePaper setup in library's "User_Setup_Select.h" file + +// This sketch supports Waveshare 2 colour ePaper displays +// https://www.waveshare.com/product/modules/oleds-lcds/e-paper.htm + +// Test images are in the Data folder with sketch (press Ctrl+k) +// Upload using the Tools menu "ESP8266 Sketch Data Upload" option + +/////////////////////////////////////////////////////////////////// +// For ESP8266 connect as follows: // +// Display 3.3V to NodeMCU 3V3 // +// Display GND to NodeMCU GND // +// // +// Display GPIO NodeMCU pin // +// BUSY 5 D1 // +// RESET 4 D2 // +// DC 0 D3 // +// CS 2 D4 // +// CLK 14 D5 // +// D6 (MISO not connected to display) // +// DIN 13 D7 // +// // +// Note: Pin allocations for the ePaper signals are defined in // +// ePaper library's epdif.h file, above are the default pins // +/////////////////////////////////////////////////////////////////// + +// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + +// The following is for the Waveshare 2.7" colour ePaper display +// include where ?.?? is screen size in inches + +#include // Screen specific library +Epd ePaper; // Create an instance ePaper + +#include // Graphics library and Sprite class + +TFT_eSPI glc = TFT_eSPI(); // Invoke the graphics library class +TFT_eSprite frame = TFT_eSprite(&glc); // Invoke the Sprite class for the image frame buffer + +#define INK COLORED // Black ink +#define PAPER UNCOLORED // 'paper' background colour + +uint16_t epd_width = EPD_WIDTH; // Set the initial values, these are swapped +uint16_t epd_height = EPD_HEIGHT; // in different landscape/portrait rotations + // so call frame.width() or frame.height() to get new values + +#define EPD_BUFFER 1 // Label for the black frame buffer 1 + +uint8_t* framePtr = NULL; // Pointer for the black frame buffer + +#include "EPD_Support.h" // Include sketch EPD support functions last! + +int8_t limit = 5; // Limit the number of loops before halting +//------------------------------------------------------------------------------------ +// Setup +//------------------------------------------------------------------------------------ +void setup() { + + Serial.begin(250000); // Used for messages + + // Initialise the ePaper library + if (ePaper.Init() != 0) { + Serial.print("ePaper init failed"); + while (1) yield(); // Wait here until re-boot + } + + Serial.println("\r\n ePaper initialisation OK"); + + // Initialise the SPIFFS filing system + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs + } + + Serial.println(" SPIFFS initialisation OK"); + + frame.setColorDepth(1); // Must set the bits per pixel to 1 for ePaper displays + // Set bit depth BEFORE creating Sprite, default is 16! + + // Create a frame buffer in RAM of defined size and save the pointer to it + // RAM needed is about (EPD_WIDTH * EPD_HEIGHT)/8 , ~5000 bytes for 200 x 200 pixels + // Note: always create the Sprite before setting the Sprite rotation + framePtr = (uint8_t*) frame.createSprite(EPD_WIDTH, EPD_HEIGHT); + + Serial.println("\r\nInitialisation done."); + + listFiles(); // List all the files in the SPIFFS +} + +//------------------------------------------------------------------------------------ +// Loop +//------------------------------------------------------------------------------------ +void loop() { + + frame.setRotation(random(4)); // Set the rotation to 0, 1, 2 or 3 ( 1 & 3 = landscape) + + frame.fillSprite(PAPER); + + // Draw 8 bit grey-scale bitmap using Floyd-Steinberg dithering at x,y + // /File name x y + //drawFSBmp("/TestCard.bmp", 0, 0); // 176 x 264 pixels + + drawFSBmp("/Tiger.bmp", (frame.width()-176)/2, (frame.height()-234)/2); // 176 x 234 pixels + + updateDisplay(); // Send image to display and refresh + + delay(5000); + + frame.fillSprite(PAPER); // Fill frame with white + + // Draw circle in frame buffer (x, y, r, color) in center of screen + frame.drawCircle(frame.width()/2, frame.height()/2, frame.width()/6, INK); + + // Draw diagonal lines + frame.drawLine(0 , 0, frame.width()-1, frame.height()-1, INK); + frame.drawLine(0 , frame.height()-1, frame.width()-1, 0, INK); + + updateDisplay(); // Send image to display and refresh + + delay(3000); + + // Run a rotation test + rotateTest(); + + // Put screen to sleep to save power (if wanted) + ePaper.Sleep(); + + if (--limit <= 0) while(1) yield(); // Wait here + + delay(20000); // Wait here for 20s + + // Wake up ePaper display so we can talk to it + Serial.println("Waking up!"); + ePaper.Init(); + +} // end of loop() + + +//------------------------------------------------------------------------------------ +// setRotation() actually rotates the drawing coordinates, not the whole display frame +// buffer so we can use this to draw text at right angles or upside down +//------------------------------------------------------------------------------------ +void rotateTest(void) +{ + //frame.fillSprite(PAPER); // Fill buffer with white to clear old graphics + + // Draw some text in frame buffer + frame.setTextFont(4); // Select font 4 + frame.setTextColor(INK); // Set colour to ink + frame.setTextDatum(TC_DATUM); // Middle centre text datum + + frame.setRotation(0); // Set the display rotation to 0, 1, 2 or 3 ( 1 & 3 = landscape) + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 0", epd_width / 2, 10); + + frame.setRotation(1); // Set the display rotation to 1 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 1", epd_width / 2, 10); + + frame.setRotation(2); // Set the display rotation to 2 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 2", epd_width / 2, 10); + + frame.setRotation(3); // Set the display rotation to 3 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 3", epd_width / 2, 10); + + Serial.println("Updating display"); + updateDisplay(); // Update display +} diff --git a/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino new file mode 100644 index 0000000..e78c741 --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino @@ -0,0 +1,198 @@ +/* + Support function for Floyd-Steinberg dithering of an 8bit grey-scale BMP image + on a Monochrome display: + https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering + + Bitmap format: + https://en.wikipedia.org/wiki/BMP_file_format + + Example for https://github.com/Bodmer/TFT_eSPI + + The MIT License (MIT) + Copyright (c) 2015 by Bodmer + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYBR_DATUM HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Note: drawFSBmp() is a simplified function and does not handle all possible + BMP file header variants. It works OK with 8 bit per pixel grey-scale images + generated by MS Paint and IrfanView. +*/ + +// https://github.com/Bodmer/TFT_eSPI + +//==================================================================================== +// Draw an 8 bit grey-scale bitmap (*.BMP) on a Monochrome display using dithering +//==================================================================================== +// Uses RAM for buffers (3 * width + 4) ( 532 bytes for 176 pixels) + +// Image must be stored in ESP8266 or ESP32 SPIFFS + +// Quantisation error distribution for pixel X +// (This is for bottum up drawing of the BMP) +// |-------|-------|-------| +// | +3/16 | +5/16 | +1/16 | +// |-------|-------|-------| +// | | X | +7/16 | +// |-------|-------|-------| +// + +void drawFSBmp(const char *filename, int16_t x, int16_t y) { + + if ((x >= frame.width()) || (y >= frame.height())) return; + + fs::File bmpFS; + + // Open requested file + bmpFS = SPIFFS.open( filename, "r"); + + if (!bmpFS) + { + Serial.print("File not found"); + return; + } + + uint32_t seekOffset, dib_size; + uint16_t w, h, row, col, num_colors; + uint8_t r, g, b; + + if (read16(bmpFS) == 0x4D42) // Check it is a valid bitmap header + { + read32(bmpFS); + read32(bmpFS); + seekOffset = read32(bmpFS); // Pointer to image start + dib_size = read32(bmpFS); // DIB header size, typically 40 bytes + + w = read32(bmpFS); // Get width and height of image + h = read32(bmpFS); + + // Check it is 1 plane and 8 bits per pixel and no compression + if ((read16(bmpFS) == 1) && (read16(bmpFS) == 8) && (read32(bmpFS) == 0)) + { + read32(bmpFS); // Throw away image size + read32(bmpFS); // Throw away x pixels per meter + read32(bmpFS); // Throw away y pixels per meter + + num_colors = read32(bmpFS); // Number of colours in colour table (usually 256) + + uint8_t pixel_color[num_colors]; // Lookup table for grey-scale + + bmpFS.seek(14 + dib_size); // Seek to start of colour table + + // Capture the colour lookup table + for (uint16_t i = 0; i < num_colors; i++) + { + uint32_t abgr = read32(bmpFS); // Assume 4 byte, RGB colours in LS 3 bytes + pixel_color[i] = (uint8_t) abgr; // For grey-scale R, G, B are same value + } + + bmpFS.seek(seekOffset); // Seek to start of image + + uint16_t padding = (4 - (w & 3)) & 3; // Calculate the BMP line padding + + // Create an zero an 8 bit pixel line buffer + uint8_t* lineBuffer = ( uint8_t*) calloc(w , sizeof(uint8_t)); + + // Create a 16 bit signed line buffer for the quantisation error + // Diffusion spreads to x-1 and x+1 so w + 2 avoids a bounds check + int16_t* qerrBuffer = ( int16_t*) calloc((w + 2)<<1, sizeof(uint8_t)); + + y += h - 1; // Start from bottom (assumes bottum up!) + + // Draw row by row from bottom up + for (row = 0; row < h; row++) { + + // Read a row of pixels + bmpFS.read(lineBuffer, w); + + // Prep variables + uint16_t dx = 0; + uint8_t* bptr = lineBuffer; + int16_t* qptr = qerrBuffer + 1; // + 1 because diffusion spreads to x-1 + + // Lookup color, add quantisation error, clip and clear error buffer + while(dx < w) + { + int16_t depixel = pixel_color[(uint8_t)*bptr] + *qptr; + if (depixel >255) depixel = 255; // Clip pixel to 0-255 + else if (depixel < 0) depixel = 0; + *bptr++ = (uint8_t) depixel; // Save new value, inc pointer + *qptr++ = 0; // Zero error, inc pointer + dx++; // Next pixel + } + + dx = 0; // Reset varaibles to start of line + bptr = lineBuffer; + qptr = qerrBuffer + 1; + int32_t qerr = 0; + int32_t qerr16 = 0; + + // Push the pixel row to screen + while(dx < w) + { + // Add 7/16 of error (error = 0 on first entry) + int16_t pixel = *bptr + (qerr>>1) - qerr16; + + // Do not clip here so quantisation error accumulates correctly? + // Draw pixel (black or white) and determine new error + if (pixel < 128) { frame.drawPixel(x + dx, y, INK); qerr = pixel; } + else qerr = pixel - 255; + + // Diffuse into error buffer for next pixel line + qerr16 = qerr>>4; // 1/16 of error + *(qptr - 1) += (qerr>>2) - qerr16; // Add 3/16 of error + *(qptr ) += (qerr>>2) + qerr16; // Add 5/16 of error + *(qptr + 1) += qerr16; // Add 1/16 of error + + *bptr++; // Move along pixel and error buffers + *qptr++; + dx++; // Move coordinate along + } + y--; + + // Read any line padding (saves a slow seek) + if (padding) bmpFS.read(lineBuffer, padding); + } + } + else Serial.println("BMP format not recognized."); + } + bmpFS.close(); +} + +//==================================================================================== +// Read a 16 bit value from the filing system +//==================================================================================== +uint16_t read16(fs::File &f) { + uint16_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); // MSB + return result; +} + +//==================================================================================== +// Read a 32 bit value from the filing system +//==================================================================================== +uint32_t read32(fs::File &f) { + uint32_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); + ((uint8_t *)&result)[2] = f.read(); + ((uint8_t *)&result)[3] = f.read(); // MSB + return result; +} + +// TODO: Add support for colour images by converting RGB to grey-scale +// grey = (R+G+B)/3 + diff --git a/examples/ePaper/Floyd_Steinberg/SPIFFS.ino b/examples/ePaper/Floyd_Steinberg/SPIFFS.ino new file mode 100644 index 0000000..ff35f61 --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/SPIFFS.ino @@ -0,0 +1,92 @@ + + // Call up the SPIFFS FLASH filing system + #define FS_NO_GLOBALS + #include + + #ifdef ESP32 + #include "SPIFFS.h" + #endif + + /*==================================================================================== + This sketch supports the ESP6266 and ESP32 SPIFFS filing system + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +//==================================================================================== +// Print a SPIFFS directory list (root directory) +//==================================================================================== + +void listFiles(void) { + Serial.println(); + Serial.println("SPIFFS files found:"); + +#ifdef ESP32 + listDir(SPIFFS, "/", true); +#else + fs::Dir dir = SPIFFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); +#endif + Serial.println(); + delay(1000); +} +//==================================================================================== + +#ifdef ESP32 +void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { + Serial.printf("Listing directory: %s\n", dirname); + + fs::File root = fs.open(dirname); + if (!root) { + Serial.println("Failed to open directory"); + return; + } + if (!root.isDirectory()) { + Serial.println("Not a directory"); + return; + } + + fs::File file = root.openNextFile(); + while (file) { + + if (file.isDirectory()) { + Serial.print("DIR : "); + String fileName = file.name(); + Serial.print(fileName); + if (levels) { + listDir(fs, file.name(), levels - 1); + } + } else { + String fileName = file.name(); + Serial.print(" " + fileName); + int spaces = 32 - fileName.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + String fileSize = (String) file.size(); + spaces = 8 - fileSize.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + Serial.println(fileSize + " bytes"); + } + + file = root.openNextFile(); + } +} +#endif diff --git a/examples/ePaper/Floyd_Steinberg/data/TestCard.bmp b/examples/ePaper/Floyd_Steinberg/data/TestCard.bmp new file mode 100644 index 0000000000000000000000000000000000000000..3a18f0cd57fc8ec887f26f63b177f6beeb7cc9db GIT binary patch literal 47542 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 literal 0 HcmV?d00001 diff --git a/examples/ePaper/Floyd_Steinberg/data/Tiger.bmp b/examples/ePaper/Floyd_Steinberg/data/Tiger.bmp new file mode 100644 index 0000000000000000000000000000000000000000..ef26eb18d6cf4b49bef1ccba605cd79b092eba06 GIT binary patch literal 42262 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 I;!+_1091?By#N3J literal 0 HcmV?d00001