Partial speed up.
This commit is contained in:
parent
82a082003a
commit
c7e0781d21
|
@ -20,42 +20,50 @@
|
|||
31 August 2020 by e-radionica.com
|
||||
*/
|
||||
|
||||
#include "Inkplate.h" //Include Inkplate library to the sketch
|
||||
#include "SdFat.h" //Include library for SD card
|
||||
Inkplate display(INKPLATE_1BIT); //Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
SdFile file; //Create SdFile object used for accessing files on SD card
|
||||
#include "Inkplate.h" //Include Inkplate library to the sketch
|
||||
#include "SdFat.h" //Include library for SD card
|
||||
Inkplate display(
|
||||
INKPLATE_1BIT); // Create an object on Inkplate library and also set library into 1 Bit mode (Monochrome)
|
||||
SdFile file; // Create SdFile object used for accessing files on SD card
|
||||
|
||||
void setup() {
|
||||
display.begin(); //Init Inkplate library (you should call this function ONLY ONCE)
|
||||
display.clearDisplay(); //Clear frame buffer of display
|
||||
display.display(); //Put clear image on display
|
||||
void setup()
|
||||
{
|
||||
display.begin(); // Init Inkplate library (you should call this function ONLY ONCE)
|
||||
display.clearDisplay(); // Clear frame buffer of display
|
||||
display.display(); // Put clear image on display
|
||||
|
||||
//Init SD card. Display if SD card is init propery or not.
|
||||
if (display.sdCardInit()) {
|
||||
// Init SD card. Display if SD card is init propery or not.
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
display.println("SD Card OK! Reading image...");
|
||||
display.partialUpdate();
|
||||
|
||||
//If card is properly init, try to load image and display it on e-paper at position X=100, Y=0
|
||||
//NOTE: These methods require you to pass a reference to the display object as first parameter.
|
||||
//NOTE: Both drawJpegFromSD methods allow for an optional sixth "invert" parameter. Setting this parameter to true
|
||||
//will flip all colors on the image, making black white and white black.
|
||||
//fifth parameter will dither the image.
|
||||
if (!display.drawJpegFromSD(&display, "pyramid.jpg", 100, 0, true, false)) {
|
||||
//If is something failed (wrong filename or wrong format), write error message on the screen.
|
||||
//You can turn off dithering for somewhat faster image load by changing the fifth parameter to false, or removing the parameter completely
|
||||
// If card is properly init, try to load image and display it on e-paper at position X=100, Y=0
|
||||
// NOTE: These methods require you to pass a reference to the display object as first parameter.
|
||||
// NOTE: Both drawJpegFromSd methods allow for an optional sixth "invert" parameter. Setting this parameter to
|
||||
// true will flip all colors on the image, making black white and white black. fifth parameter will dither the
|
||||
// image.
|
||||
if (!display.drawJpegFromSd(&display, "pyramid.jpg", 100, 0, true, false))
|
||||
{
|
||||
// If is something failed (wrong filename or wrong format), write error message on the screen.
|
||||
// You can turn off dithering for somewhat faster image load by changing the fifth parameter to false, or
|
||||
// removing the parameter completely
|
||||
display.println("Image open error");
|
||||
display.display();
|
||||
}
|
||||
display.display();
|
||||
}
|
||||
else {
|
||||
//If SD card init not success, display error on screen and stop the program (using infinite loop)
|
||||
else
|
||||
{
|
||||
// If SD card init not success, display error on screen and stop the program (using infinite loop)
|
||||
display.println("SD Card error!");
|
||||
display.partialUpdate();
|
||||
while (true);
|
||||
while (true)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//Nothing...
|
||||
void loop()
|
||||
{
|
||||
// Nothing...
|
||||
}
|
||||
|
|
126
src/Inkplate.cpp
126
src/Inkplate.cpp
|
@ -98,6 +98,9 @@
|
|||
Inkplate::Inkplate(uint8_t _mode) : GFX(E_INK_WIDTH, E_INK_HEIGHT)
|
||||
{
|
||||
setDisplayMode(_mode);
|
||||
for (uint32_t i = 0; i < 256; ++i)
|
||||
pinLUT[i] = ((i & B00000011) << 4) | (((i & B00001100) >> 2) << 18) | (((i & B00010000) >> 4) << 23) |
|
||||
(((i & B11100000) >> 5) << 25);
|
||||
}
|
||||
|
||||
void Inkplate::begin(void)
|
||||
|
@ -141,19 +144,19 @@ void Inkplate::begin(void)
|
|||
// Battery voltage Switch MOSFET
|
||||
pinModeMCP(9, OUTPUT);
|
||||
|
||||
D_memory_new = (uint8_t *)ps_malloc(600 * 100);
|
||||
DMemoryNew = (uint8_t *)ps_malloc(600 * 100);
|
||||
_partial = (uint8_t *)ps_malloc(600 * 100);
|
||||
_pBuffer = (uint8_t *)ps_malloc(120000);
|
||||
D_memory4Bit = (uint8_t *)ps_malloc(240000);
|
||||
|
||||
if (D_memory_new == NULL || _partial == NULL || _pBuffer == NULL || D_memory4Bit == NULL)
|
||||
if (DMemoryNew == NULL || _partial == NULL || _pBuffer == NULL || D_memory4Bit == NULL)
|
||||
{
|
||||
do
|
||||
{
|
||||
delay(100);
|
||||
} while (true);
|
||||
}
|
||||
memset(D_memory_new, 0, 60000);
|
||||
memset(DMemoryNew, 0, 60000);
|
||||
memset(_partial, 0, 60000);
|
||||
memset(_pBuffer, 0, 120000);
|
||||
memset(D_memory4Bit, 255, 240000);
|
||||
|
@ -189,11 +192,8 @@ void Inkplate::display()
|
|||
|
||||
void Inkplate::display1b()
|
||||
{
|
||||
for (int i = 0; i < 60000; i++)
|
||||
{
|
||||
*(D_memory_new + i) &= *(_partial + i);
|
||||
*(D_memory_new + i) |= (*(_partial + i));
|
||||
}
|
||||
memcpy(DMemoryNew, _partial, 60000);
|
||||
|
||||
uint16_t _pos;
|
||||
uint32_t _send;
|
||||
uint8_t data;
|
||||
|
@ -207,34 +207,30 @@ void Inkplate::display1b()
|
|||
cleanFast(1, 12);
|
||||
cleanFast(2, 1);
|
||||
cleanFast(0, 11);
|
||||
for (int k = 0; k < 3; k++)
|
||||
for (int k = 0; k < 3; ++k)
|
||||
{
|
||||
_pos = 59999;
|
||||
vscan_start();
|
||||
for (int i = 0; i < 600; i++)
|
||||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
dram = *(D_memory_new + _pos);
|
||||
dram = *(DMemoryNew + _pos);
|
||||
data = LUTB[(dram >> 4) & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
hscan_start(_send);
|
||||
data = LUTB[dram & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
_pos--;
|
||||
for (int j = 0; j < 99; j++)
|
||||
for (int j = 0; j < 99; ++j)
|
||||
{
|
||||
dram = *(D_memory_new + _pos);
|
||||
dram = *(DMemoryNew + _pos);
|
||||
data = LUTB[(dram >> 4) & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
|
||||
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
data = LUTB[dram & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
|
||||
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
_pos--;
|
||||
|
@ -248,30 +244,26 @@ void Inkplate::display1b()
|
|||
|
||||
_pos = 59999;
|
||||
vscan_start();
|
||||
for (int i = 0; i < 600; i++)
|
||||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
dram = *(D_memory_new + _pos);
|
||||
dram = *(DMemoryNew + _pos);
|
||||
data = LUT2[(dram >> 4) & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
hscan_start(_send);
|
||||
data = LUT2[dram & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
_pos--;
|
||||
for (int j = 0; j < 99; j++)
|
||||
for (int j = 0; j < 99; ++j)
|
||||
{
|
||||
dram = *(D_memory_new + _pos);
|
||||
dram = *(DMemoryNew + _pos);
|
||||
data = LUT2[(dram >> 4) & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
data = LUT2[dram & 0x0F];
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
_pos--;
|
||||
|
@ -283,18 +275,16 @@ void Inkplate::display1b()
|
|||
delayMicroseconds(230);
|
||||
|
||||
vscan_start();
|
||||
for (int i = 0; i < 600; i++)
|
||||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
dram = *(D_memory_new + _pos);
|
||||
dram = *(DMemoryNew + _pos);
|
||||
data = 0b00000000;
|
||||
;
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
hscan_start(_send);
|
||||
data = 0b00000000;
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
for (int j = 0; j < 99; j++)
|
||||
for (int j = 0; j < 99; ++j)
|
||||
{
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
|
@ -338,8 +328,8 @@ void Inkplate::display3b()
|
|||
vscan_start();
|
||||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
pixel = 0B00000000;
|
||||
pixel2 = 0B00000000;
|
||||
pixel = 0;
|
||||
pixel2 = 0;
|
||||
pix1 = *(dp--);
|
||||
pix2 = *(dp--);
|
||||
pix3 = *(dp--);
|
||||
|
@ -349,19 +339,16 @@ void Inkplate::display3b()
|
|||
pixel2 |= (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
|
||||
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
|
||||
|
||||
_send = ((pixel & B00000011) << 4) | (((pixel & B00001100) >> 2) << 18) |
|
||||
(((pixel & B00010000) >> 4) << 23) | (((pixel & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[pixel];
|
||||
hscan_start(_send);
|
||||
_send = ((pixel2 & B00000011) << 4) | (((pixel2 & B00001100) >> 2) << 18) |
|
||||
(((pixel2 & B00010000) >> 4) << 23) | (((pixel2 & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[pixel2];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
|
||||
for (int j = 0; j < 99; j++)
|
||||
for (int j = 0; j < 99; ++j)
|
||||
{
|
||||
|
||||
pixel = 0B00000000;
|
||||
pixel2 = 0B00000000;
|
||||
pixel = 0;
|
||||
pixel2 = 0;
|
||||
pix1 = *(dp--);
|
||||
pix2 = *(dp--);
|
||||
pix3 = *(dp--);
|
||||
|
@ -371,13 +358,11 @@ void Inkplate::display3b()
|
|||
pixel2 |= (waveform3Bit[pix3 & 0x07][k] << 6) | (waveform3Bit[(pix3 >> 4) & 0x07][k] << 4) |
|
||||
(waveform3Bit[pix4 & 0x07][k] << 2) | (waveform3Bit[(pix4 >> 4) & 0x07][k] << 0);
|
||||
|
||||
_send = ((pixel & B00000011) << 4) | (((pixel & B00001100) >> 2) << 18) |
|
||||
(((pixel & B00010000) >> 4) << 23) | (((pixel & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[pixel];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
|
||||
_send = ((pixel2 & B00000011) << 4) | (((pixel2 & B00001100) >> 2) << 18) |
|
||||
(((pixel2 & B00010000) >> 4) << 23) | (((pixel2 & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[pixel2];
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
}
|
||||
|
@ -399,6 +384,7 @@ void Inkplate::partialUpdate()
|
|||
return;
|
||||
if (_blockPartial == 1)
|
||||
display1b();
|
||||
|
||||
uint16_t _pos = 59999;
|
||||
uint32_t _send;
|
||||
uint8_t data;
|
||||
|
@ -410,8 +396,8 @@ void Inkplate::partialUpdate()
|
|||
{
|
||||
for (int j = 0; j < 100; ++j)
|
||||
{
|
||||
diffw = ((*(D_memory_new + _pos)) ^ (*(_partial + _pos))) & (~(*(_partial + _pos)));
|
||||
diffb = ((*(D_memory_new + _pos)) ^ (*(_partial + _pos))) & ((*(_partial + _pos)));
|
||||
diffw = *(DMemoryNew + _pos) & ~*(_partial + _pos);
|
||||
diffb = ~*(DMemoryNew + _pos) & *(_partial + _pos);
|
||||
_pos--;
|
||||
*(_pBuffer + n) = LUTW[diffw >> 4] & (LUTB[diffb >> 4]);
|
||||
n--;
|
||||
|
@ -428,20 +414,18 @@ void Inkplate::partialUpdate()
|
|||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
data = *(_pBuffer + n);
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
_send = pinLUT[data];
|
||||
hscan_start(_send);
|
||||
n--;
|
||||
for (int j = 0; j < 199; j++)
|
||||
for (int j = 0; j < 199; ++j)
|
||||
{
|
||||
data = *(_pBuffer + n);
|
||||
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) |
|
||||
(((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
_send = pinLUT[data];
|
||||
GPIO.out_w1ts = _send | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
n--;
|
||||
}
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1ts = _send | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
vscan_end();
|
||||
}
|
||||
|
@ -451,12 +435,8 @@ void Inkplate::partialUpdate()
|
|||
cleanFast(3, 1);
|
||||
vscan_start();
|
||||
einkOff();
|
||||
einkOff();
|
||||
for (int i = 0; i < 60000; ++i)
|
||||
{
|
||||
*(D_memory_new + i) &= *(_partial + i);
|
||||
*(D_memory_new + i) |= (*(_partial + i));
|
||||
}
|
||||
|
||||
memcpy(DMemoryNew, _partial, 60000);
|
||||
}
|
||||
|
||||
void Inkplate::clean()
|
||||
|
@ -489,18 +469,16 @@ void Inkplate::cleanFast(uint8_t c, uint8_t rep)
|
|||
else if (c == 3)
|
||||
data = B11111111;
|
||||
|
||||
uint32_t _send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) |
|
||||
(((data & B11100000) >> 5) << 25);
|
||||
;
|
||||
for (int k = 0; k < rep; k++)
|
||||
uint32_t _send = pinLUT[data];
|
||||
for (int k = 0; k < rep; ++k)
|
||||
{
|
||||
vscan_start();
|
||||
for (int i = 0; i < 600; i++)
|
||||
for (int i = 0; i < 600; ++i)
|
||||
{
|
||||
hscan_start(_send);
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
for (int j = 0; j < 99; j++)
|
||||
for (int j = 0; j < 99; ++j)
|
||||
{
|
||||
GPIO.out_w1ts = (_send) | CL;
|
||||
GPIO.out_w1tc = DATA | CL;
|
||||
|
|
|
@ -38,10 +38,6 @@ class Inkplate : public System, public GFX
|
|||
{
|
||||
return Network::isConnected();
|
||||
};
|
||||
uint8_t *downloadFile(const char *url, int32_t defaultLen)
|
||||
{
|
||||
return Network::downloadFile(url, defaultLen);
|
||||
};
|
||||
|
||||
private:
|
||||
void precalculateGamma(uint8_t *c, float gamma);
|
||||
|
@ -56,6 +52,7 @@ class Inkplate : public System, public GFX
|
|||
void pinsZstate();
|
||||
void pinsAsOutputs();
|
||||
|
||||
uint32_t pinLUT[256];
|
||||
|
||||
uint8_t _beginDone = 0;
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ void GFX::selectDisplayMode(uint8_t _mode)
|
|||
if (_mode != _displayMode)
|
||||
{
|
||||
_displayMode = _mode & 1;
|
||||
memset(D_memory_new, 0, 60000);
|
||||
memset(DMemoryNew, 0, 60000);
|
||||
memset(_partial, 0, 60000);
|
||||
memset(_pBuffer, 0, 120000);
|
||||
memset(D_memory4Bit, 255, 240000);
|
||||
|
|
|
@ -34,7 +34,7 @@ class GFX : public Shapes, public Image, public Font
|
|||
void setRotation(uint8_t r);
|
||||
uint8_t getRotation();
|
||||
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color) override;
|
||||
inline void drawPixel(int16_t x, int16_t y, uint16_t color) override;
|
||||
|
||||
void selectDisplayMode(uint8_t _mode);
|
||||
|
||||
|
@ -43,7 +43,7 @@ class GFX : public Shapes, public Image, public Font
|
|||
int16_t width() override;
|
||||
int16_t height() override;
|
||||
|
||||
uint8_t *D_memory_new;
|
||||
uint8_t *DMemoryNew;
|
||||
uint8_t *_partial;
|
||||
uint8_t *D_memory4Bit;
|
||||
uint8_t *_pBuffer;
|
||||
|
@ -65,7 +65,7 @@ class GFX : public Shapes, public Image, public Font
|
|||
|
||||
private:
|
||||
void startWrite(void) override;
|
||||
void writePixel(int16_t x, int16_t y, uint16_t color) override;
|
||||
inline void writePixel(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
|
|
|
@ -31,7 +31,7 @@ bool Image::drawImage(const char *path, int x, int y, bool dither, bool invert)
|
|||
if (strstr(path, ".bmp") != NULL)
|
||||
return drawBitmapFromSd(path, x, y, dither, invert);
|
||||
if (strstr(path, ".jpg") != NULL || strstr(path, ".jpeg") != NULL)
|
||||
return drawJpegFromSD(path, x, y, dither, invert);
|
||||
return drawJpegFromSd(path, x, y, dither, invert);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -28,17 +28,21 @@ class Image : virtual public Network
|
|||
uint16_t bg = 0xFFFF);
|
||||
void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h);
|
||||
|
||||
bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert);
|
||||
|
||||
bool drawBitmapFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
|
||||
bool drawBitmapFromWeb(WiFiClient *s, int x, int y, int len, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
|
||||
|
||||
bool drawJpegFromSD(const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawJpegFromSD(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawJpegFromBuffer(uint8_t *buf, int32_t len, int x, int y, bool dither, bool invert);
|
||||
|
||||
bool drawJpegFromSd(const char *fileName, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawJpegFromSd(SdFile *p, int x, int y, bool dither = 0, bool invert = 0);
|
||||
|
||||
bool drawJpegFromWeb(const char *url, int x, int y, bool dither = 0, bool invert = 0);
|
||||
bool drawJpegFromWeb(WiFiClient *s, int x, int y, int len, bool dither = 0, bool invert = 0);
|
||||
bool drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither = 0, bool invert = 0);
|
||||
|
||||
|
||||
private:
|
||||
|
@ -50,8 +54,7 @@ class Image : virtual public Network
|
|||
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color) = 0;
|
||||
virtual void endWrite(void) = 0;
|
||||
|
||||
static bool drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool _dither,
|
||||
bool _invert);
|
||||
static bool drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool dither, bool invert);
|
||||
|
||||
uint8_t pixelBuffer[800 * 4 + 5];
|
||||
uint8_t ditherBuffer[2][800 + 5];
|
||||
|
@ -60,9 +63,8 @@ class Image : virtual public Network
|
|||
|
||||
bool legalBmp(bitmapHeader *bmpHeader);
|
||||
|
||||
void ditherStart(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
|
||||
void ditherLoadNextLine(uint8_t *pixelBuffer, uint8_t *bufferPtr, int w, bool invert, uint8_t bits);
|
||||
uint8_t ditherGetPixel(uint8_t px, int i, int w, bool paletted);
|
||||
uint8_t ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted);
|
||||
uint8_t ditherGetPixelJpeg(uint8_t px, int x, int y, int w);
|
||||
void ditherSwap(int w);
|
||||
|
||||
void readBmpHeader(uint8_t *buf, bitmapHeader *_h);
|
||||
|
|
|
@ -92,14 +92,6 @@ bool Image::drawBitmapFromSd(SdFile *p, int x, int y, bool dither, bool invert)
|
|||
if (!legalBmp(&bmpHeader))
|
||||
return 0;
|
||||
|
||||
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT)
|
||||
selectDisplayMode(INKPLATE_1BIT);
|
||||
|
||||
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 || bmpHeader.color == 24 ||
|
||||
bmpHeader.color == 32) &&
|
||||
getDisplayMode() != INKPLATE_3BIT)
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
|
||||
int16_t w = bmpHeader.width, h = bmpHeader.height;
|
||||
int8_t c = bmpHeader.color;
|
||||
|
||||
|
@ -117,24 +109,38 @@ bool Image::drawBitmapFromSd(SdFile *p, int x, int y, bool dither, bool invert)
|
|||
|
||||
bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
uint8_t *buf = downloadFile(url, 800 * 600 * 4);
|
||||
bool ret = 0;
|
||||
int32_t defaultLen = 800 * 600 * 4;
|
||||
uint8_t *buf = downloadFile(url, &defaultLen);
|
||||
|
||||
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Image::drawBitmapFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
|
||||
{
|
||||
bool ret = 0;
|
||||
uint8_t *buf = downloadFile(s, len);
|
||||
|
||||
ret = drawBitmapFromBuffer(buf, x, y, dither, invert);
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Image::drawBitmapFromBuffer(uint8_t *buf, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
bitmapHeader bmpHeader;
|
||||
readBmpHeader(buf, &bmpHeader);
|
||||
|
||||
if (!legalBmp(&bmpHeader))
|
||||
return 0;
|
||||
|
||||
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT)
|
||||
selectDisplayMode(INKPLATE_1BIT);
|
||||
|
||||
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 16 || bmpHeader.color == 24 ||
|
||||
bmpHeader.color == 32) &&
|
||||
getDisplayMode() != INKPLATE_3BIT)
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
|
||||
if (dither)
|
||||
memset(ditherBuffer, 0, sizeof ditherBuffer);
|
||||
|
||||
uint8_t *bufferPtr = buf + bmpHeader.startRAW;
|
||||
for (int i = 0; i < bmpHeader.height; ++i)
|
||||
{
|
||||
|
@ -144,7 +150,6 @@ bool Image::drawBitmapFromWeb(const char *url, int x, int y, bool dither, bool i
|
|||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -167,14 +172,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
|
|||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(px, j, w, 1);
|
||||
val = ditherGetPixelBmp(px, j, w, 1);
|
||||
else
|
||||
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
val = 7 - val;
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 8: {
|
||||
|
@ -182,16 +188,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
|
|||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(px, j, w, 1);
|
||||
val = ditherGetPixelBmp(px, j, w, 1);
|
||||
else
|
||||
{
|
||||
val = palette[px >> 1] & (px & 1 ? 0x0F : 0xF0) >> (px & 1 ? 0 : 4);
|
||||
}
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
val = 7 - val;
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
|
@ -204,14 +209,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
|
|||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
val = 7 - val;
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 24: {
|
||||
|
@ -222,14 +228,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
|
|||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - val);
|
||||
else
|
||||
writePixel(x + j, y, val);
|
||||
val = 7 - val;
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
|
@ -240,14 +247,15 @@ void Image::displayBmpLine(int16_t x, int16_t y, bitmapHeader *bmpHeader, bool d
|
|||
uint8_t val;
|
||||
|
||||
if (dither)
|
||||
val = ditherGetPixel(RGB8BIT(r, g, b), j, w, 0);
|
||||
val = ditherGetPixelBmp(RGB8BIT(r, g, b), j, w, 0);
|
||||
else
|
||||
val = RGB3BIT(r, g, b);
|
||||
|
||||
if (invert)
|
||||
writePixel(x + j, y, 7 - RGB3BIT(r, g, b));
|
||||
else
|
||||
writePixel(x + j, y, RGB3BIT(r, g, b));
|
||||
val = 7 - val;
|
||||
if (getDisplayMode() == INKPLATE_1BIT)
|
||||
val = (~val >> 2) & 1;
|
||||
|
||||
writePixel(x + j, y, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#include "Image.h"
|
||||
|
||||
uint8_t Image::ditherGetPixel(uint8_t px, int i, int w, bool paletted)
|
||||
uint8_t Image::ditherGetPixelBmp(uint8_t px, int i, int w, bool paletted)
|
||||
{
|
||||
if (paletted)
|
||||
px = ditherPalette[px];
|
||||
|
||||
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][i] + px));
|
||||
|
||||
uint8_t newPixel = oldPixel & B11100000;
|
||||
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
|
||||
uint8_t quantError = oldPixel - newPixel;
|
||||
|
||||
ditherBuffer[1][i + 0] += (quantError * 5) >> 4;
|
||||
|
@ -22,6 +22,25 @@ uint8_t Image::ditherGetPixel(uint8_t px, int i, int w, bool paletted)
|
|||
return newPixel >> 5;
|
||||
}
|
||||
|
||||
uint8_t Image::ditherGetPixelJpeg(uint8_t px, int x, int y, int w)
|
||||
{
|
||||
uint8_t oldPixel = min((uint16_t)0xFF, (uint16_t)((uint16_t)ditherBuffer[0][x] + px));
|
||||
|
||||
uint8_t newPixel = oldPixel & (getDisplayMode() == INKPLATE_1BIT ? B10000000 : B11100000);
|
||||
uint8_t quantError = oldPixel - newPixel;
|
||||
|
||||
ditherBuffer[1][x + 0] += (quantError * 5) >> 4;
|
||||
if (x != w - 1)
|
||||
{
|
||||
ditherBuffer[0][x + 1] += (quantError * 7) >> 4;
|
||||
ditherBuffer[1][x + 1] += (quantError * 1) >> 4;
|
||||
}
|
||||
if (x != 0)
|
||||
ditherBuffer[1][x - 1] += (quantError * 3) >> 4;
|
||||
|
||||
return newPixel >> 5;
|
||||
}
|
||||
|
||||
void Image::ditherSwap(int w)
|
||||
{
|
||||
for (int i = 0; i < w; ++i)
|
||||
|
|
|
@ -8,7 +8,81 @@
|
|||
|
||||
extern Image *_imagePtrJpeg;
|
||||
|
||||
bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool _dither, bool _invert)
|
||||
bool Image::drawJpegFromSd(const char *fileName, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
SdFile dat;
|
||||
if (dat.open(fileName, O_RDONLY))
|
||||
return drawJpegFromSd(&dat, x, y, dither, invert);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromSd(SdFile *p, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
TJpgDec.setJpgScale(1);
|
||||
TJpgDec.setCallback(drawJpegChunk);
|
||||
|
||||
uint32_t pnt = 0;
|
||||
uint32_t total = p->fileSize();
|
||||
uint8_t *buff = (uint8_t *)ps_malloc(total);
|
||||
|
||||
if (buff == NULL)
|
||||
return 0;
|
||||
|
||||
while (pnt < total)
|
||||
{
|
||||
uint32_t toread = p->available();
|
||||
if (toread > 0)
|
||||
{
|
||||
int read = p->read(buff + pnt, toread);
|
||||
if (read > 0)
|
||||
pnt += read;
|
||||
}
|
||||
}
|
||||
p->close();
|
||||
|
||||
if (TJpgDec.drawJpg(x, y, buff, total, dither, invert) == 0)
|
||||
ret = 1;
|
||||
|
||||
free(buff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromWeb(const char *url, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
bool ret = 0;
|
||||
|
||||
int32_t defaultLen = 800 * 600 * 4;
|
||||
uint8_t *buff = downloadFile(url, &defaultLen);
|
||||
ret = drawJpegFromBuffer(buff, x, y, defaultLen, dither, invert);
|
||||
free(buff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromWeb(WiFiClient *s, int x, int y, int32_t len, bool dither, bool invert)
|
||||
{
|
||||
bool ret = 0;
|
||||
uint8_t *buff = downloadFile(s, len);
|
||||
ret = drawJpegFromBuffer(buff, x, y, len, dither, invert);
|
||||
free(buff);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromBuffer(uint8_t *buff, int32_t len, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
bool ret = 0;
|
||||
|
||||
if (TJpgDec.drawJpg(x, y, buff, len, dither, invert) == 0)
|
||||
ret = 1;
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t *bitmap, bool dither, bool invert)
|
||||
{
|
||||
if (!_imagePtrJpeg)
|
||||
return 0;
|
||||
|
@ -19,57 +93,15 @@ bool Image::drawJpegChunk(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t
|
|||
for (int i = 0; i < w; ++i)
|
||||
{
|
||||
uint16_t rgb = bitmap[j * w + i];
|
||||
if (_invert)
|
||||
_imagePtrJpeg->drawPixel(i + x, j + y, 7 - RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb)));
|
||||
else
|
||||
_imagePtrJpeg->drawPixel(i + x, j + y, RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb)));
|
||||
uint8_t val = RGB3BIT(RED(rgb), GREEN(rgb), BLUE(rgb));
|
||||
|
||||
if (invert)
|
||||
val = 7 - val;
|
||||
|
||||
_imagePtrJpeg->writePixel(x + i, y + j, val);
|
||||
}
|
||||
}
|
||||
_imagePtrJpeg->endWrite();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromSD(const char *fileName, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
SdFile dat;
|
||||
if (dat.open(fileName, O_RDONLY))
|
||||
return drawJpegFromSD(&dat, x, y, dither, invert);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Image::drawJpegFromSD(SdFile *p, int x, int y, bool dither, bool invert)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
|
||||
TJpgDec.setJpgScale(1);
|
||||
TJpgDec.setCallback(drawJpegChunk);
|
||||
|
||||
uint32_t pnt = 0;
|
||||
uint32_t total = p->fileSize();
|
||||
uint8_t *buf = (uint8_t *)ps_malloc(total);
|
||||
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
|
||||
while (pnt < total)
|
||||
{
|
||||
uint32_t toread = p->available();
|
||||
if (toread > 0)
|
||||
{
|
||||
int read = p->read(buf + pnt, toread);
|
||||
if (read > 0)
|
||||
pnt += read;
|
||||
}
|
||||
}
|
||||
p->close();
|
||||
|
||||
selectDisplayMode(INKPLATE_3BIT);
|
||||
|
||||
if (TJpgDec.drawJpg(x, y, buf, total, dither, invert) == 0)
|
||||
ret = 1;
|
||||
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -28,7 +28,7 @@ bool Network::isConnected()
|
|||
}
|
||||
|
||||
|
||||
uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
|
||||
uint8_t *Network::downloadFile(const char *url, int32_t *defaultLen)
|
||||
{
|
||||
if (!isConnected())
|
||||
return NULL;
|
||||
|
@ -45,7 +45,9 @@ uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
|
|||
|
||||
int32_t size = http.getSize();
|
||||
if (size == -1)
|
||||
size = defaultLen;
|
||||
size = *defaultLen;
|
||||
else
|
||||
*defaultLen = size;
|
||||
|
||||
uint8_t *buffer = (uint8_t *)ps_malloc(size);
|
||||
uint8_t *buffPtr = buffer;
|
||||
|
@ -79,3 +81,36 @@ uint8_t *Network::downloadFile(const char *url, int32_t defaultLen)
|
|||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
uint8_t *Network::downloadFile(WiFiClient *s, int32_t len)
|
||||
{
|
||||
if (!isConnected())
|
||||
return NULL;
|
||||
|
||||
bool sleep = WiFi.getSleep();
|
||||
WiFi.setSleep(false);
|
||||
|
||||
uint8_t *buffer = (uint8_t *)ps_malloc(len);
|
||||
uint8_t *buffPtr = buffer;
|
||||
|
||||
uint8_t buff[128] = {0};
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
size_t size = s->available();
|
||||
if (size)
|
||||
{
|
||||
int c = s->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
|
||||
memcpy(buffPtr, buff, c);
|
||||
|
||||
if (len > 0)
|
||||
len -= c;
|
||||
buffPtr += c;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
WiFi.setSleep(sleep);
|
||||
|
||||
return buffer;
|
||||
}
|
|
@ -25,7 +25,8 @@ class Network
|
|||
void disconnect();
|
||||
bool isConnected();
|
||||
|
||||
uint8_t *downloadFile(const char *url, int32_t defaultLen);
|
||||
uint8_t *downloadFile(const char *url, int32_t *defaultLen);
|
||||
uint8_t *downloadFile(WiFiClient *url, int32_t len);
|
||||
|
||||
private:
|
||||
};
|
||||
|
|
|
@ -14,11 +14,12 @@ void setup()
|
|||
|
||||
void loop()
|
||||
{
|
||||
int32_t t = millis();
|
||||
|
||||
display.drawBitmap(offSet, 0, (uint8_t *)bck_day, bck_day_w, bck_day_h, BLACK);
|
||||
int32_t t = millis();
|
||||
display.partialUpdate();
|
||||
display.clearDisplay();
|
||||
Serial.println(millis() - t);
|
||||
display.clearDisplay();
|
||||
offSet += 70;
|
||||
offSet %= 300;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#include "Inkplate.h"
|
||||
#include "SdFat.h"
|
||||
Inkplate display(INKPLATE_3BIT);
|
||||
Inkplate display(INKPLATE_1BIT);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
@ -30,9 +30,7 @@ void loop()
|
|||
|
||||
if (display.sdCardInit())
|
||||
{
|
||||
int16_t t = millis();
|
||||
Serial.println(display.drawBitmapFromSd("Lenna.bmp", 0, 0, 1, 0));
|
||||
Serial.println(millis() - t);
|
||||
}
|
||||
display.display();
|
||||
|
||||
|
|
Loading…
Reference in New Issue