Commit ada678d7 authored by Bodmer's avatar Bodmer

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.
parent d5f0812b
......@@ -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<h; yp++)
{
for (int32_t xp = 0; xp<ww; xp+=8)
{
uint8_t pbyte = *pdata++;
for (uint8_t xc = 0; xc < 8; xc++)
{
if (xp+xc<w) drawPixel(x+xp+xc, y+yp, (pbyte<<xc) & 0x80);
}
}
}
}
}
......@@ -329,6 +364,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
}
}
}
else if (_bpp == 8)
{
for (uint32_t yp = y; yp < y + h; yp++)
......@@ -341,7 +377,42 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const
}
}
}
// 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;
}
const uint8_t* pdata = (const uint8_t* ) data;
uint32_t ww = (w+7) & 0xFFF8;
for (int32_t yp = 0; yp<h; yp++)
{
for (int32_t xp = 0; xp<ww; xp+=8)
{
uint8_t pbyte = pgm_read_byte(pdata++);
for (uint8_t xc = 0; xc < 8; xc++)
{
if (xp+xc<w) drawPixel(x+xp+xc, y+yp, (pbyte<<xc) & 0x80);
}
}
}
}
}
......
......@@ -28,7 +28,6 @@
// If it is a 16bit serial display we must transfer 16 bits every time
#ifdef RPI_ILI9486_DRIVER
#define SEND_16_BITS
#define CMD_BITS 16-1
#else
#define CMD_BITS 8-1
......
......@@ -14,7 +14,7 @@
// Customised User_Setup files are stored in the "User_Setups" folder.
#ifndef USER_SETUP_LOADED // Lets PlatformIO users define user settings in
#ifndef USER_SETUP_LOADED // Lets PlatformIO users define settings in
// platformio.ini, see notes in "Tools" folder.
// Only ONE line below should be uncommented. Add extra lines and files as needed.
......@@ -30,17 +30,16 @@
//#include <User_Setups/Setup7_ST7735_128x128.h> // Setup file configured for my ST7735 128x128 display
//#include <User_Setups/Setup8_ILI9163_128x128.h> // Setup file configured for my ILI9163 128x128 display
//#include <User_Setups/Setup9_ST7735_Overlap.h> // Setup file configured for my ST7735
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
//#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for ESP8266 and RPi TFT with touch
//#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for ESP32 and RPi TFT with touch
//#include <User_Setups/Setup12_M5Stack.h> // Setup file for the ESP32 based M5Stack
//#include <User_Setups/Setup13_ILI9481_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup14_ILI9341_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup15_HX8357D.h> // Setup file configured for HX8357D (untested)
//#include <User_Setups/Setup16_ILI9488_Parallel.h> // Setup file for the ESP32 with parallel bus TFT
//#include <User_Setups/Setup17_ePaper.h> // Setup file for any Waveshare ePaper display
//#include <User_Setups/Setup99.h>
// ePaper #include <User_Setups/SetupX_Template.h> // Setup file template for copying/editting
//#include <User_Setups/SetupX_Template.h>
#endif // USER_SETUP_LOADED
......@@ -70,7 +69,7 @@
#define TFT_DRIVER 0x6D02
#elif defined (RPI_ILI9486_DRIVER)
#include <TFT_Drivers/RPI_ILI9486_Defines.h>
#define TFT_DRIVER 0x9481
#define TFT_DRIVER 0x9486
#elif defined (ILI9481_DRIVER)
#include <TFT_Drivers/ILI9481_Defines.h>
#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
......
// 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
//
// ##################################################################################
/* 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
}
// 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 <epd?in?.h> where ?.?? is screen size in inches
#include <epd2in7.h> // Screen specific library
Epd ePaper; // Create an instance ePaper
#include <TFT_eSPI.h> // 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
}
/*
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
// Call up the SPIFFS FLASH filing system
#define FS_NO_GLOBALS
#include <FS.h>
#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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment