Hello again !
I have managed to display a full image with all 4 colors !!!
I used a mix of your WiFi example and the example provided by GoodDisplay
I put the code bellow for reference.
Thanks for your help!
#include <SPI.h>
//EPD
#include "Display_EPD_W21_spi.h"
#include "Display_EPD_W21.h"
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiClientSecure.h>
#include "HTTPClient.h"
#define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
const char* ssid = "*******";
const char* password = "*******";
const int httpPort = 80;
const int httpsPort = 443;
const int sleepTime = 60; // min
const int wifiTimeout = 30; // seconds
const int serverTimeout = 60; // seconds
const int SCREEN_WIDTH = 960;
const int SCREEN_HEIGHT = 640;
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("=== WiFi TEST ===");
pinMode(A14, INPUT); //BUSY
pinMode(A15, OUTPUT); //RES
pinMode(A16, OUTPUT); //DC
pinMode(A17, OUTPUT); //CS
//SPI
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
SPI.begin ();
if (!WiFi.getAutoReconnect() || ( WiFi.getMode() != WIFI_STA) || ((WiFi.SSID() != ssid) && String(ssid) != "........"))
{
Serial.println();
Serial.print("WiFi.getAutoReconnect() = ");
Serial.println(WiFi.getAutoReconnect());
Serial.print("WiFi.SSID() = ");
Serial.println(WiFi.SSID());
WiFi.mode(WIFI_STA); // switch off AP
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
}
int ConnectTimeout = 60; // 30 seconds
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
Serial.print(WiFi.status());
if (--ConnectTimeout <= 0)
{
Serial.println();
Serial.println("WiFi connect timeout");
return;
}
}
Serial.println();
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
setClock();
// init screen
EPD_init();
int16_t x = 0;
int16_t y = 0;
showBitmapFrom_HTTP("example.com", "/images/", "image.bmp", x, y, true);
Serial.println("hibernate...");
delay(2000); // wait, so that all other components can calm down
esp_sleep_enable_timer_wakeup(sleepTime * 60 * uS_TO_S_FACTOR);
esp_deep_sleep_start();
}
//Tips//
/*
1.Flickering is normal when EPD is performing a full screen update to clear ghosting from the previous image so to ensure better clarity and legibility for the new image.
2.There will be no flicker when EPD performs a partial refresh.
3.Please make sue that EPD enters sleep mode when refresh is completed and always leave the sleep mode command. Otherwise, this may result in a reduced lifespan of EPD.
4.Please refrain from inserting EPD to the FPC socket or unplugging it when the MCU is being powered to prevent potential damage.)
5.Re-initialization is required for every full screen update.
6.When porting the program, set the BUSY pin to input mode and other pins to output mode.
*/
void loop() {
while(1); // The program stops here
}
static const uint16_t input_buffer_pixels = 960; // may affect performance
static const uint16_t max_row_width = 1872; // for up to 7.8" display 1872x1404
static const uint16_t max_palette_pixels = 256; // for depth <= 8
uint8_t input_buffer[3 * input_buffer_pixels]; // up to depth 24
void showBitmapFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y, bool with_color)
{
WiFiClient client;
bool connection_ok = false;
bool valid = false; // valid format to be handled
bool flip = false; // bitmap is stored bottom-to-top
uint32_t startTime = millis();
Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
Serial.print("connecting to "); Serial.println(host);
if (!client.connect(host, httpPort))
{
Serial.println("connection failed");
return;
}
Serial.print("requesting URL: ");
Serial.println(String("http://") + host + path + filename);
client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"User-Agent: GxEPD2_WiFi_Example\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
while (client.connected())
{
String line = client.readStringUntil('\n');
if (!connection_ok)
{
connection_ok = line.startsWith("HTTP/1.1 200 OK");
if (connection_ok) Serial.println(line);
//if (!connection_ok) Serial.println(line);
}
if (!connection_ok) Serial.println(line);
//Serial.println(line);
if (line == "\r")
{
Serial.println("headers received");
break;
}
}
if (!connection_ok) return;
// Parse BMP header
if (read16(client) == 0x4D42) // BMP signature
{
uint32_t fileSize = read32(client);
uint32_t creatorBytes = read32(client); (void)creatorBytes; //unused
uint32_t imageOffset = read32(client); // Start of image data
uint32_t headerSize = read32(client);
uint32_t width = read32(client);
int32_t height = (int32_t) read32(client);
uint16_t planes = read16(client);
uint16_t depth = read16(client); // bits per pixel
uint32_t format = read32(client);
uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
{
Serial.print("File size: "); Serial.println(fileSize);
Serial.print("Image Offset: "); Serial.println(imageOffset);
Serial.print("Header size: "); Serial.println(headerSize);
Serial.print("Bit Depth: "); Serial.println(depth);
Serial.print("Image size: ");
Serial.print(width);
Serial.print('x');
Serial.println(height);
// BMP rows are padded (if needed) to 4-byte boundary
uint32_t rowSize = (width * depth / 8 + 3) & ~3;
if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
if (height < 0)
{
height = -height;
flip = false;
}
uint16_t w = width;
uint16_t h = height;
if ((x + w - 1) >= SCREEN_WIDTH) w = SCREEN_WIDTH - x;
if ((y + h - 1) >= SCREEN_HEIGHT) h = SCREEN_HEIGHT - y;
if (w <= max_row_width) // handle with direct drawing
{
valid = true;
uint8_t bitmask = 0xFF;
uint8_t bitshift = 8 - depth;
uint16_t red, green, blue;
unsigned char color1,color2,color3,color4,data;
unsigned char pixel;
bool whitish = false;
bool reddish = false;
bool blackish = false;
bool yellowish = false;
//display.clearScreen();
EPD_W21_WriteCMD(0x10);
uint32_t rowPosition = flip ? imageOffset + (height - h) * rowSize : imageOffset;
//Serial.print("skip "); Serial.println(rowPosition - bytes_read);
bytes_read += skip(client, rowPosition - bytes_read);
for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
{
if (!connection_ok || !(client.connected() || client.available())) {
//Serial.println("break");
break;
}
delay(1); // yield() to avoid WDT
uint32_t in_remain = rowSize;
uint32_t in_idx = 0;
uint32_t in_bytes = 0;
uint8_t in_byte = 0; // for depth <= 8
uint8_t in_bits = 0; // for depth <= 8
uint8_t out_byte = 0xFF; // white (for w%8!=0 border)
uint8_t out_color_byte = 0xFF; // white (for w%8!=0 border)
uint32_t out_idx = 0;
uint8_t buff[SCREEN_WIDTH];
uint32_t pixel_idx = 0;
for (uint16_t col = 0; col < w; col++) // for each pixel
{
yield();
if (!connection_ok || !(client.connected() || client.available())) {
//Serial.println("break");
break;
}
// Time to read more pixel data?
if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
{
uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
uint32_t got = read8n(client, input_buffer, get);
while ((got < get) && connection_ok)
{
//Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
uint32_t gotmore = read8n(client, input_buffer + got, get - got);
got += gotmore;
connection_ok = gotmore > 0;
}
in_bytes = got;
in_remain -= got;
bytes_read += got;
}
if (!connection_ok)
{
Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
break;
}
blue = input_buffer[in_idx++];
green = input_buffer[in_idx++];
red = input_buffer[in_idx++];
whitish = ((red > 0xAA) && (green > 0xAA) && (blue > 0xAA)); // whitish
reddish = (red > 0xF0) || ((green > 0xF0) && (blue > 0xF0)); // reddish
yellowish = ((red > 0xAA) && (green > 0xAA) && (blue < 0x20)); // yellowish
//blackish = ((red < 0x20) && (green < 0x20) && (blue < 0x20)); // blackish
if (whitish)
{
pixel = WHITE;
}
else if(yellowish)
{
pixel = YELLOW;
}
else if (reddish)
{
pixel = RED;
}
else {
pixel = BLACK;
}
buff[pixel_idx] = pixel;
pixel_idx++;
} // end col
const int length = sizeof(buff);
for(size_t i = 0; i < length; i+=4) {
color1 = buff[i]<<6;
color2 = buff[i+1]<<4;
color3 = buff[i+2]<<2;
color4 = buff[i+3];
data = color1|color2|color3|color4;
EPD_W21_WriteDATA(data);
}
} // end row
Serial.print("downloaded in ");
Serial.print(millis() - startTime);
Serial.println(" ms");
EPD_refresh();
}
Serial.print("bytes read "); Serial.println(bytes_read);
}
}
client.stop();
if (!valid)
{
Serial.println("bitmap format not handled.");
}
}
uint16_t read16(WiFiClient& client)
{
// BMP data is stored little-endian, same as Arduino.
uint16_t result;
((uint8_t *)&result)[0] = client.read(); // LSB
((uint8_t *)&result)[1] = client.read(); // MSB
return result;
}
uint32_t read32(WiFiClient& client)
{
// BMP data is stored little-endian, same as Arduino.
uint32_t result;
((uint8_t *)&result)[0] = client.read(); // LSB
((uint8_t *)&result)[1] = client.read();
((uint8_t *)&result)[2] = client.read();
((uint8_t *)&result)[3] = client.read(); // MSB
return result;
}
uint32_t skip(WiFiClient& client, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while ((client.connected() || client.available()) && (remain > 0))
{
if (client.available())
{
client.read();
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
uint32_t read8n(WiFiClient& client, uint8_t* buffer, int32_t bytes)
{
int32_t remain = bytes;
uint32_t start = millis();
while ((client.connected() || client.available()) && (remain > 0))
{
if (client.available())
{
int16_t v = client.read();
*buffer++ = uint8_t(v);
remain--;
}
else delay(1);
if (millis() - start > 2000) break; // don't hang forever
}
return bytes - remain;
}
// Set time via NTP, as required for x.509 validation
void setClock()
{
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2)
{
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));
}
//////////////////////////////////END//////////////////////////////////////////////////