thickline and gradientline

This commit is contained in:
nitko12 2020-07-30 09:24:30 +02:00
parent 536fe7928b
commit 42f43d4b26
2 changed files with 217 additions and 423 deletions

View File

@ -1,9 +1,8 @@
#include "Inkplate.h"
#include <stdlib.h> #include <stdlib.h>
#include "Adafruit_GFX.h" #include "Adafruit_GFX.h"
#include "WiFi.h"
#include "HTTPClient.h"
#include "Inkplate.h"
Adafruit_MCP23017 mcp; Adafruit_MCP23017 mcp;
SPIClass spi2(HSPI); SPIClass spi2(HSPI);
SdFat sd(&spi2); SdFat sd(&spi2);
@ -330,13 +329,13 @@ uint8_t Inkplate::getDisplayMode() {
return _displayMode; return _displayMode;
} }
int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y, bool invert) { int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y) {
if(sdCardOk == 0) return 0; if(sdCardOk == 0) return 0;
struct bitmapHeader bmpHeader; struct bitmapHeader bmpHeader;
readBmpHeaderSd(p, &bmpHeader); readBmpHeader(p, &bmpHeader);
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24)) return 0; if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 24)) return 0;
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) { if ((bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) {
selectDisplayMode(INKPLATE_3BIT); selectDisplayMode(INKPLATE_3BIT);
} }
@ -344,71 +343,68 @@ int Inkplate::drawBitmapFromSD(SdFile* p, int x, int y, bool invert) {
selectDisplayMode(INKPLATE_1BIT); selectDisplayMode(INKPLATE_1BIT);
} }
if (bmpHeader.color == 1) drawMonochromeBitmapSd(p, bmpHeader, x, y, invert); if (bmpHeader.color == 1) drawMonochromeBitmap(p, bmpHeader, x, y);
if (bmpHeader.color == 4) drawGrayscaleBitmap4Sd(p, bmpHeader, x, y, invert); if (bmpHeader.color == 24) drawGrayscaleBitmap24(p, bmpHeader, x, y);
if (bmpHeader.color == 8) drawGrayscaleBitmap8Sd(p, bmpHeader, x, y, invert);
if (bmpHeader.color == 24) drawGrayscaleBitmap24Sd(p, bmpHeader, x, y, invert);
return 1; return 1;
} }
int Inkplate::drawBitmapFromSD(char* fileName, int x, int y, bool invert) { int Inkplate::drawBitmapFromSD(char* fileName, int x, int y) {
if(sdCardOk == 0) return 0; if(sdCardOk == 0) return 0;
SdFile dat; SdFile dat;
if (dat.open(fileName, O_RDONLY)) { if (dat.open(fileName, O_RDONLY)) {
return drawBitmapFromSD(&dat, x, y, invert); return drawBitmapFromSD(&dat, x, y);
} else { } else {
return 0; return 0;
} }
} }
int Inkplate::drawBitmapFromWeb(WiFiClient* s, int x, int y, int len, bool invert) { void Inkplate::drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness)
struct bitmapHeader bmpHeader; {
readBmpHeaderWeb(s, &bmpHeader); float deg = atan2f((float)(y2 - y1), (float)(x2 - x1));
if (bmpHeader.signature != 0x4D42 || bmpHeader.compression != 0 || !(bmpHeader.color == 1 || bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24)) return 0;
if ((bmpHeader.color == 4 || bmpHeader.color == 8 || bmpHeader.color == 24 || bmpHeader.color == 32) && getDisplayMode() != INKPLATE_3BIT) { float l1 = tan(deg);
selectDisplayMode(INKPLATE_3BIT); float k1 = (float)y1 - l1 * (float)x1;
}
if (bmpHeader.color == 1 && getDisplayMode() != INKPLATE_1BIT) { float degShift = (l1 < 0 ? M_PI_2 : -M_PI_2);
selectDisplayMode(INKPLATE_1BIT);
}
if (bmpHeader.color == 1) drawMonochromeBitmapWeb(s, bmpHeader, x, y, len, invert); int x3 = (int)round((float)x1 + thickness / 2.0 * cos(deg + degShift));
if (bmpHeader.color == 4) drawGrayscaleBitmap4Web(s, bmpHeader, x, y, len, invert); int y3 = (int)round((float)y1 + thickness / 2.0 * sin(deg + degShift));
if (bmpHeader.color == 8) drawGrayscaleBitmap8Web(s, bmpHeader, x, y, len, invert);
if (bmpHeader.color == 24) drawGrayscaleBitmap24Web(s, bmpHeader, x, y, len, invert);
return 1; int x4 = (int)round((float)x2 + thickness / 2.0 * cos(deg + degShift));
int y4 = (int)round((float)y2 + thickness / 2.0 * sin(deg + degShift));
x1 = (int)round((float)x1 + thickness / 2.0 * cos(deg - degShift));
y1 = (int)round((float)y1 + thickness / 2.0 * sin(deg - degShift));
x2 = (int)round((float)x2 + thickness / 2.0 * cos(deg - degShift));
y2 = (int)round((float)y2 + thickness / 2.0 * sin(deg - degShift));
fillTriangle(x1, y1, x2, y2, x3, y3, color);
fillTriangle(x2, y2, x4, y4, x3, y3, color);
} }
int Inkplate::drawBitmapFromWeb(char* url, int x, int y, bool invert) { void Inkplate::drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness) {
if (WiFi.status() != WL_CONNECTED) return 0; int n = color2 - color1;
int ret = 0;
bool sleep = WiFi.getSleep(); float px = (float)(x2 - x1) / (float)n;
WiFi.setSleep(false); float py = (float)(y2 - y1) / (float)n;
HTTPClient http; for (int i = 0; i < n; ++i)
http.getStream().setNoDelay(true); {
http.getStream().setTimeout(1); if (abs(thickness + 1) < 0.1)
http.begin(url); drawLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
(int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py),
int httpCode = http.GET(); color1 + i);
if (httpCode == 200) { else
int32_t len = http.getSize(); drawThickLine((int)((float)x1 + (float)i * px), (int)((float)y1 + (float)i * py),
if (len > 0) { (int)((float)x1 + (float)(i + 1) * px), (int)((float)y1 + (float)(i + 1) * py),
WiFiClient * dat = http.getStreamPtr(); color1 + i,
ret = drawBitmapFromWeb(dat, x, y, len, invert); thickness);
} }
}
http.end();
WiFi.setSleep(sleep);
return ret;
} }
int Inkplate::sdCardInit() { int Inkplate::sdCardInit() {
spi2.begin(14, 12, 13, 15); spi2.begin(14, 12, 13, 15);
sdCardOk = sd.begin(15, SD_SCK_MHZ(25)); sdCardOk = sd.begin(15, SD_SCK_MHZ(25));
@ -819,7 +815,7 @@ uint16_t Inkplate::read16(uint8_t* c) {
return (*(c) | (*(c + 1) << 8)); return (*(c) | (*(c + 1) << 8));
} }
void Inkplate::readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h) { void Inkplate::readBmpHeader(SdFile *_f, struct bitmapHeader *_h) {
uint8_t header[100]; uint8_t header[100];
_f->rewind(); _f->rewind();
_f->read(header, 100); _f->read(header, 100);
@ -834,21 +830,7 @@ void Inkplate::readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h) {
return; return;
} }
void Inkplate::readBmpHeaderWeb(WiFiClient *_s, struct bitmapHeader *_h) { int Inkplate::drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
uint8_t header[34];
_s->read(header, 34);
_h->signature = read16(header + 0);
_h->fileSize = read32(header + 2);
_h->startRAW = read32(header + 10);
_h->dibHeaderSize = read32(header + 14);
_h->width = read32(header + 18);
_h->height = read32(header + 22);
_h->color = read16(header + 28);
_h->compression = read32(header + 30);
return;
}
int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
int w = bmpHeader.width; int w = bmpHeader.width;
int h = bmpHeader.height; int h = bmpHeader.height;
uint8_t paddingBits = w % 32; uint8_t paddingBits = w % 32;
@ -859,18 +841,14 @@ int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, i
for (j = 0; j < h; j++) { for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) { for (i = 0; i < w; i++) {
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read(); uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < 32; n++) { for (int n = 0; n < 32; n++) {
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n)))); drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
} }
} }
if (paddingBits) { if (paddingBits) {
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read(); uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < paddingBits; n++) { for (int n = 0; n < paddingBits; n++) {
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n)))); drawPixel((i * 32) + n + x, h - j + y, !(pixelRow & (1ULL << (31 - n))));
} }
} }
} }
@ -878,62 +856,7 @@ int Inkplate::drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, i
return 1; return 1;
} }
int Inkplate::drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) { int Inkplate::drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, int x, int y) {
int w = bmpHeader.width;
int h = bmpHeader.height;
uint8_t paddingBits = w % 8;
w /= 8;
f->seekSet(bmpHeader.startRAW);
int i, j;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < 8; n++) {
drawPixel((i * 8) + n + x, h - 1 - j + y, (pixelRow & (0xFULL << (28 - n*4))) >> (28 - n*4 + 1));
}
}
if (paddingBits) {
uint32_t pixelRow = f->read() << 24 | f->read() << 16 | f->read() << 8 | f->read();
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < paddingBits; n++) {
drawPixel((i * 8) + n + x, h - 1 - j + y, ((pixelRow & (0xFULL << (28 - n*4)))) >> (28 - n*4 + 1));
}
}
}
f->close();
return 1;
}
int Inkplate::drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
int w = bmpHeader.width;
int h = bmpHeader.height;
char padding = w % 4;
f->seekSet(bmpHeader.startRAW);
int i, j;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint8_t px = 0;
if (invert)
px = 255-f->read();
else
px = f->read();
drawPixel(i + x, h - 1 - j + y, px>>5);
}
if (padding) {
for (int p = 0; p < 4-padding; p++) {
f->read();
}
}
}
f->close();
return 1;
}
int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert) {
int w = bmpHeader.width; int w = bmpHeader.width;
int h = bmpHeader.height; int h = bmpHeader.height;
char padding = w % 4; char padding = w % 4;
@ -947,14 +870,10 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader,
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7)); //display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method. //So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
uint8_t px = 0; uint8_t px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000);
if (invert)
px = ((255-f->read()) * 2126 / 10000) + ((255-f->read()) * 7152 / 10000) + ((255-f->read()) * 722 / 10000);
else
px = (f->read() * 2126 / 10000) + (f->read() * 7152 / 10000) + (f->read() * 722 / 10000);
//drawPixel(i + x, h - j + y, gammaLUT[px]); //drawPixel(i + x, h - j + y, gammaLUT[px]);
drawPixel(i + x, h - 1 - j + y, px>>5); drawPixel(i + x, h - j + y, px>>5);
//drawPixel(i + x, h - j + y, px/32); //drawPixel(i + x, h - j + y, px/32);
} }
if (padding) { if (padding) {
for (int p = 0; p < padding; p++) { for (int p = 0; p < padding; p++) {
@ -966,190 +885,6 @@ int Inkplate::drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader,
return 1; return 1;
} }
int Inkplate::drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
int w = bmpHeader.width;
int h = bmpHeader.height;
uint8_t paddingBits = w % 32;
int total = len - 34;
w /= 32;
uint8_t* buf = (uint8_t*) ps_malloc(total);
if (buf == NULL)
return 0;
int pnt = 0;
while (pnt < total) {
int toread = s->available();
if (toread > 0) {
int read = s->read(buf+pnt, toread);
if (read > 0)
pnt += read;
}
}
int i, j, k = bmpHeader.startRAW - 34;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < 32; n++) {
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
}
}
if (paddingBits) {
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < paddingBits; n++) {
drawPixel((i * 32) + n + x, h - 1 - j + y, !(pixelRow & (1ULL << (31 - n))));
}
}
}
free(buf);
return 1;
}
int Inkplate::drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
int w = bmpHeader.width;
int h = bmpHeader.height;
char paddingBits = w % 8;
int total = len - 34;
w /= 8;
uint8_t* buf = (uint8_t*) ps_malloc(total);
if (buf == NULL)
return 0;
int pnt = 0;
while (pnt < total) {
int toread = s->available();
if (toread > 0) {
int read = s->read(buf+pnt, toread);
if (read > 0)
pnt += read;
}
}
int i, j, k = bmpHeader.startRAW - 34;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < 8; n++) {
drawPixel((i * 8) + n + x, h - 1 - j + y, (pixelRow & (0xFULL << (28 - n*4))) >> (28 - n*4 + 1));
}
}
if (paddingBits) {
uint32_t pixelRow = buf[k++] << 24 | buf[k++] << 16 | buf[k++] << 8 | buf[k++];
if (invert)
pixelRow = ~pixelRow;
for (int n = 0; n < paddingBits; n++) {
drawPixel((i * 8) + n + x, h - 1 - j + y, ((pixelRow & (0xFULL << (28 - n*4)))) >> (28 - n*4 + 1));
}
}
}
free(buf);
return 1;
}
int Inkplate::drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
int w = bmpHeader.width;
int h = bmpHeader.height;
char padding = w % 4;
int total = len - 34;
uint8_t* buf = (uint8_t*) ps_malloc(total);
if (buf == NULL)
return 0;
int pnt = 0;
while (pnt < total) {
int toread = s->available();
if (toread > 0) {
int read = s->read(buf+pnt, toread);
if (read > 0)
pnt += read;
}
}
int i, j, k = bmpHeader.startRAW - 34;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
uint8_t px = 0;
if (invert)
px = 255-buf[k++];
else
px = buf[k++];
drawPixel(i + x, h - 1 - j + y, px>>5);
}
if (padding) {
for (int p = 0; p < 4-padding; p++) {
k++;
}
}
}
free(buf);
return 1;
}
int Inkplate::drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert) {
int w = bmpHeader.width;
int h = bmpHeader.height;
char padding = w % 4;
int total = len - 34;
uint8_t* buf = (uint8_t*) ps_malloc(total);
if (buf == NULL)
return 0;
int pnt = 0;
while (pnt < total) {
int toread = s->available();
if (toread > 0) {
int read = s->read(buf+pnt, toread);
if (read > 0)
pnt += read;
}
}
int i, j, k = bmpHeader.startRAW - 34;
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
//This is the proper way of converting True Color (24 Bit RGB) bitmap file into grayscale, but it takes waaay too much time (full size picture takes about 17s to decode!)
//float px = (0.2126 * (readByteFromSD(&file) / 255.0)) + (0.7152 * (readByteFromSD(&file) / 255.0)) + (0.0722 * (readByteFromSD(&file) / 255.0));
//px = pow(px, 1.5);
//display.drawPixel(i + x, h - j + y, (uint8_t)(px*7));
//So then, we are convertng it to grayscale using good old average and gamma correction (from LUT). With this metod, it is still slow (full size image takes 4 seconds), but much beter than prev mentioned method.
uint8_t px = 0;
if (invert)
px = ((255-buf[k++]) * 2126 / 10000) + ((255-buf[k++]) * 7152 / 10000) + ((255-buf[k++]) * 722 / 10000);
else
px = (buf[k++] * 2126 / 10000) + (buf[k++] * 7152 / 10000) + (buf[k++] * 722 / 10000);
//drawPixel(i + x, h - j + y, gammaLUT[px]);
drawPixel(i + x, h - 1 - j + y, px>>5);
//drawPixel(i + x, h - j + y, px/32);
}
if (padding) {
for (int p = 0; p < padding; p++) {
k++;
}
}
}
free(buf);
return 1;
}
void Inkplate::precalculateGamma(uint8_t* c, float gamma) { void Inkplate::precalculateGamma(uint8_t* c, float gamma) {
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
c[i] = int(round((pow(i / 255.0, gamma)) * 15)); c[i] = int(round((pow(i / 255.0, gamma)) * 15));

View File

@ -11,75 +11,139 @@
#endif #endif
#include "Adafruit_GFX.h" #include "Adafruit_GFX.h"
#include "Wire.h"
#include "SPI.h"
#include "Adafruit_MCP23017.h" #include "Adafruit_MCP23017.h"
#include "SPI.h"
#include "SdFat.h" #include "SdFat.h"
#include "WiFiClient.h" #include "Wire.h"
#define INKPLATE_GAMMA 1.45 #define INKPLATE_GAMMA 1.45
#define E_INK_WIDTH 800 #define E_INK_WIDTH 800
#define E_INK_HEIGHT 600 #define E_INK_HEIGHT 600
#define BLACK 1 #define BLACK 1
#define WHITE 0 #define WHITE 0
#define GPIO0_ENABLE 8 #define GPIO0_ENABLE 8
#define INKPLATE_1BIT 0 #define INKPLATE_1BIT 0
#define INKPLATE_3BIT 1 #define INKPLATE_3BIT 1
#define PAD1 0 #define PAD1 0
#define PAD2 1 #define PAD2 1
#define PAD3 2 #define PAD3 2
#define DATA 0x0E8C0030 //D0-D7 = GPIO4 GPIO5 GPIO18 GPIO19 GPIO23 GPIO25 GPIO26 GPIO27 #define DATA 0x0E8C0030 //D0-D7 = GPIO4 GPIO5 GPIO18 GPIO19 GPIO23 GPIO25 GPIO26 GPIO27
#define CL 0x01 //GPIO0 #define CL 0x01 //GPIO0
#define CL_SET {GPIO.out_w1ts = CL;} #define CL_SET \
#define CL_CLEAR {GPIO.out_w1tc = CL;} { \
GPIO.out_w1ts = CL; \
}
#define CL_CLEAR \
{ \
GPIO.out_w1tc = CL; \
}
#define LE 0x04 //GPIO2 #define LE 0x04 //GPIO2
#define LE_SET {GPIO.out_w1ts = LE;} #define LE_SET \
#define LE_CLEAR {GPIO.out_w1tc = LE;} { \
GPIO.out_w1ts = LE; \
}
#define LE_CLEAR \
{ \
GPIO.out_w1tc = LE; \
}
#define CKV 0x01 //GPIO32 #define CKV 0x01 //GPIO32
#define CKV_SET {GPIO.out1_w1ts.val = CKV;} #define CKV_SET \
#define CKV_CLEAR {GPIO.out1_w1tc.val = CKV;} { \
GPIO.out1_w1ts.val = CKV; \
}
#define CKV_CLEAR \
{ \
GPIO.out1_w1tc.val = CKV; \
}
#define SPH 0x02 //GPIO33 #define SPH 0x02 //GPIO33
#define SPH_SET {GPIO.out1_w1ts.val = SPH;} #define SPH_SET \
#define SPH_CLEAR {GPIO.out1_w1tc.val = SPH;} { \
GPIO.out1_w1ts.val = SPH; \
}
#define SPH_CLEAR \
{ \
GPIO.out1_w1tc.val = SPH; \
}
//#define SPV 15 //GPIO15 //#define SPV 15 //GPIO15
//#define SPV_SET {digitalWrite(SPV, HIGH);} //#define SPV_SET {digitalWrite(SPV, HIGH);}
//#define SPV_CLEAR {digitalWrite(SPV, LOW);} //#define SPV_CLEAR {digitalWrite(SPV, LOW);}
//I/O Expander - A Channel //I/O Expander - A Channel
#define GMOD 1 //GPIOA1 #define GMOD 1 //GPIOA1
#define GMOD_SET {mcp.digitalWrite(GMOD, HIGH);} #define GMOD_SET \
#define GMOD_CLEAR {mcp.digitalWrite(GMOD, LOW);} { \
mcp.digitalWrite(GMOD, HIGH); \
}
#define GMOD_CLEAR \
{ \
mcp.digitalWrite(GMOD, LOW); \
}
#define OE 0 //GPIOA0 #define OE 0 //GPIOA0
#define OE_SET {mcp.digitalWrite(OE, HIGH);} #define OE_SET \
#define OE_CLEAR {mcp.digitalWrite(OE, LOW);} { \
mcp.digitalWrite(OE, HIGH); \
}
#define OE_CLEAR \
{ \
mcp.digitalWrite(OE, LOW); \
}
#define SPV 2 //GPIOA5 #define SPV 2 //GPIOA5
#define SPV_SET {mcp.digitalWrite(SPV, HIGH);} #define SPV_SET \
#define SPV_CLEAR {mcp.digitalWrite(SPV, LOW);} { \
mcp.digitalWrite(SPV, HIGH); \
}
#define SPV_CLEAR \
{ \
mcp.digitalWrite(SPV, LOW); \
}
#define WAKEUP 3 //GPIOA3 #define WAKEUP 3 //GPIOA3
#define WAKEUP_SET {mcp.digitalWrite(WAKEUP, HIGH);} #define WAKEUP_SET \
#define WAKEUP_CLEAR {mcp.digitalWrite(WAKEUP, LOW);} { \
mcp.digitalWrite(WAKEUP, HIGH); \
}
#define WAKEUP_CLEAR \
{ \
mcp.digitalWrite(WAKEUP, LOW); \
}
#define PWRUP 4 //GPIOA4 #define PWRUP 4 //GPIOA4
#define PWRUP_SET {mcp.digitalWrite(PWRUP, HIGH);} #define PWRUP_SET \
#define PWRUP_CLEAR {mcp.digitalWrite(PWRUP, LOW);} { \
mcp.digitalWrite(PWRUP, HIGH); \
}
#define PWRUP_CLEAR \
{ \
mcp.digitalWrite(PWRUP, LOW); \
}
#define VCOM 5 //GPIOA6 #define VCOM 5 //GPIOA6
#define VCOM_SET {mcp.digitalWrite(VCOM, HIGH);} #define VCOM_SET \
#define VCOM_CLEAR {mcp.digitalWrite(VCOM, LOW);} { \
mcp.digitalWrite(VCOM, HIGH); \
}
#define VCOM_CLEAR \
{ \
mcp.digitalWrite(VCOM, LOW); \
}
#define CKV_CLOCK ckvClock(); #define CKV_CLOCK ckvClock();
#ifndef _swap_int16_t #ifndef _swap_int16_t
#define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } #define _swap_int16_t(a, b) \
{ \
int16_t t = a; \
a = b; \
b = t; \
}
#endif #endif
extern Adafruit_MCP23017 mcp; extern Adafruit_MCP23017 mcp;
@ -88,27 +152,29 @@ extern SdFat sd;
static void ckvClock(); static void ckvClock();
static void usleep1(); static void usleep1();
class Inkplate : public Adafruit_GFX { class Inkplate : public Adafruit_GFX
public: {
uint8_t* D_memory_new; public:
uint8_t* _partial; uint8_t *D_memory_new;
uint8_t* D_memory4Bit; uint8_t *_partial;
uint8_t * _pBuffer; uint8_t *D_memory4Bit;
const uint8_t LUT2[16] = {B10101010, B10101001, B10100110, B10100101, B10011010, B10011001, B10010110, B10010101, B01101010, B01101001, B01100110, B01100101, B01011010, B01011001, B01010110, B01010101}; uint8_t *_pBuffer;
const uint8_t LUTW[16] = {B11111111, B11111110, B11111011, B11111010, B11101111, B11101110, B11101011, B11101010, B10111111, B10111110, B10111011, B10111010, B10101111, B10101110, B10101011, B10101010}; const uint8_t LUT2[16] = {B10101010, B10101001, B10100110, B10100101, B10011010, B10011001, B10010110, B10010101, B01101010, B01101001, B01100110, B01100101, B01011010, B01011001, B01010110, B01010101};
const uint8_t LUTB[16] = {B11111111, B11111101, B11110111, B11110101, B11011111, B11011101, B11010111, B11010101, B01111111, B01111101, B01110111, B01110101, B01011111, B01011101, B01010111, B01010101}; const uint8_t LUTW[16] = {B11111111, B11111110, B11111011, B11111010, B11101111, B11101110, B11101011, B11101010, B10111111, B10111110, B10111011, B10111010, B10101111, B10101110, B10101011, B10101010};
const uint8_t pixelMaskLUT[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000}; const uint8_t LUTB[16] = {B11111111, B11111101, B11110111, B11110101, B11011111, B11011101, B11010111, B11010101, B01111111, B01111101, B01110111, B01110101, B01011111, B01011101, B01010111, B01010101};
const uint8_t pixelMaskGLUT[2] = {B00001111, B11110000}; const uint8_t pixelMaskLUT[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000};
const uint8_t discharge[16] = {B11111111, B11111100, B11110011, B11110000, B11001111, B11001100, B11000011, B11000000, B00111111, B00111100, B00110011, B00110000, B00001111, B00001100, B00000011, B00000000}; const uint8_t pixelMaskGLUT[2] = {B00001111, B11110000};
//BLACK->WHITE const uint8_t discharge[16] = {B11111111, B11111100, B11110011, B11110000, B11001111, B11001100, B11000011, B11000000, B00111111, B00111100, B00110011, B00110000, B00001111, B00001100, B00000011, B00000000};
//BLACK->WHITE
//THIS IS OKAYISH WAVEFORM FOR GRAYSCALE. IT CAN BE MUCH BETTER. //THIS IS OKAYISH WAVEFORM FOR GRAYSCALE. IT CAN BE MUCH BETTER.
const uint8_t waveform3Bit[8][7] = {{0, 0, 0, 0, 1, 1, 1}, {0, 0, 1, 1, 1, 2, 1}, {0, 1, 1, 2, 1, 2, 1}, {0, 0, 1, 1, 2, 1, 2}, {1, 1, 1, 2, 2, 1, 2}, {0, 0, 1, 1, 1, 2, 2}, {0, 1, 1, 2, 1, 2, 2}, {0, 0, 0, 0, 0, 0, 2}}; const uint8_t waveform3Bit[8][7] = {{0, 0, 0, 0, 1, 1, 1}, {0, 0, 1, 1, 1, 2, 1}, {0, 1, 1, 2, 1, 2, 1}, {0, 0, 1, 1, 2, 1, 2}, {1, 1, 1, 2, 2, 1, 2}, {0, 0, 1, 1, 1, 2, 2}, {0, 1, 1, 2, 1, 2, 2}, {0, 0, 0, 0, 0, 0, 2}};
//const uint8_t waveform3Bit[8][12] = {{3,3,3,1,1,1,1,1,1,1,2,0}, {3,3,3,3,1,1,1,1,1,1,2,0}, {3,3,3,3,3,1,1,1,1,1,2,0}, {3,3,3,3,3,3,1,1,1,1,2,0}, {3,3,3,3,3,3,3,1,1,1,2,0}, {3,3,3,3,3,3,3,2,1,1,2,0}, {3,3,3,3,3,3,3,3,3,1,2,0}, {3,3,3,3,3,3,3,3,3,3,2,0}}; //const uint8_t waveform3Bit[8][12] = {{3,3,3,1,1,1,1,1,1,1,2,0}, {3,3,3,3,1,1,1,1,1,1,2,0}, {3,3,3,3,3,1,1,1,1,1,2,0}, {3,3,3,3,3,3,1,1,1,1,2,0}, {3,3,3,3,3,3,3,1,1,1,2,0}, {3,3,3,3,3,3,3,2,1,1,2,0}, {3,3,3,3,3,3,3,3,3,1,2,0}, {3,3,3,3,3,3,3,3,3,3,2,0}};
//const uint8_t waveform3Bit[16][12] = {{0,0,0,0,0,0,1,2,1,1,0,3},{0,0,1,1,1,2,2,2,1,1,0,3},{0,0,0,1,1,2,2,2,1,1,0,3}, {0,0,0,1,2,1,2,1,2,1,3}, {0,0,2,1,2,1,2,1,2,1,3}, {0,0,1,2,2,1,1,1,1,2,0,3}, {0,0,0,2,1,1,1,1,0,2,0,3}, {0,0,2,1,2,2,1,1,1,2,0,3}, {0,0,0,2,2,2,1,1,1,2,0,3}, {0,0,0,0,0,0,2,1,1,2,0,3}, {0,0,0,0,0,2,2,1,1,2,0,3}, {0,0,0,0,0,1,1,1,2,2,0,3}, {0,0,0,0,1,2,1,2,1,2,0,3}, {0,0,0,0,1,1,2,2,1,2,0,3},{0,0,0,0,1,1,1,2,2,2,0,3}, {0,0,0,0,0,0,0,0,0,2,0,3}}; //const uint8_t waveform3Bit[16][12] = {{0,0,0,0,0,0,1,2,1,1,0,3},{0,0,1,1,1,2,2,2,1,1,0,3},{0,0,0,1,1,2,2,2,1,1,0,3}, {0,0,0,1,2,1,2,1,2,1,3}, {0,0,2,1,2,1,2,1,2,1,3}, {0,0,1,2,2,1,1,1,1,2,0,3}, {0,0,0,2,1,1,1,1,0,2,0,3}, {0,0,2,1,2,2,1,1,1,2,0,3}, {0,0,0,2,2,2,1,1,1,2,0,3}, {0,0,0,0,0,0,2,1,1,2,0,3}, {0,0,0,0,0,2,2,1,1,2,0,3}, {0,0,0,0,0,1,1,1,2,2,0,3}, {0,0,0,0,1,2,1,2,1,2,0,3}, {0,0,0,0,1,1,2,2,1,2,0,3},{0,0,0,0,1,1,1,2,2,2,0,3}, {0,0,0,0,0,0,0,0,0,2,0,3}};
//PVI waveform for cleaning screen, not sure if it is correct, but it cleans screen properly. //PVI waveform for cleaning screen, not sure if it is correct, but it cleans screen properly.
const uint32_t waveform[50] = {0x00000008, 0x00000008, 0x00200408, 0x80281888, 0x60a81898, 0x60a8a8a8, 0x60a8a8a8, 0x6068a868, 0x6868a868, 0x6868a868, 0x68686868, 0x6a686868, 0x5a686868, 0x5a686868, 0x5a586a68, 0x5a5a6a68, 0x5a5a6a68, 0x55566a68, 0x55565a64, 0x55555654, 0x55555556, 0x55555556, 0x55555556, 0x55555516, 0x55555596, 0x15555595, 0x95955595, 0x95959595, 0x95949495, 0x94949495, 0x94949495, 0xa4949494, 0x9494a4a4, 0x84a49494, 0x84948484, 0x84848484, 0x84848484, 0x84848484, 0xa5a48484, 0xa9a4a4a8, 0xa9a8a8a8, 0xa5a9a9a4, 0xa5a5a5a4, 0xa1a5a5a1, 0xa9a9a9a9, 0xa9a9a9a9, 0xa9a9a9a9, 0xa9a9a9a9, 0x15151515, 0x11111111}; const uint32_t waveform[50] = {0x00000008, 0x00000008, 0x00200408, 0x80281888, 0x60a81898, 0x60a8a8a8, 0x60a8a8a8, 0x6068a868, 0x6868a868, 0x6868a868, 0x68686868, 0x6a686868, 0x5a686868, 0x5a686868, 0x5a586a68, 0x5a5a6a68, 0x5a5a6a68, 0x55566a68, 0x55565a64, 0x55555654, 0x55555556, 0x55555556, 0x55555556, 0x55555516, 0x55555596, 0x15555595, 0x95955595, 0x95959595, 0x95949495, 0x94949495, 0x94949495, 0xa4949494, 0x9494a4a4, 0x84a49494, 0x84948484, 0x84848484, 0x84848484, 0x84848484, 0xa5a48484, 0xa9a4a4a8, 0xa9a8a8a8, 0xa5a9a9a4, 0xa5a5a5a4, 0xa1a5a5a1, 0xa9a9a9a9, 0xa9a9a9a9, 0xa9a9a9a9, 0xa9a9a9a9, 0x15151515, 0x11111111};
struct bitmapHeader { struct bitmapHeader
{
uint16_t signature; uint16_t signature;
uint32_t fileSize; uint32_t fileSize;
uint32_t startRAW; uint32_t startRAW;
@ -119,64 +185,57 @@ class Inkplate : public Adafruit_GFX {
uint32_t compression; uint32_t compression;
}; };
Inkplate(uint8_t _mode); Inkplate(uint8_t _mode);
void begin(void); void begin(void);
void drawPixel(int16_t x0, int16_t y0, uint16_t color); void drawPixel(int16_t x0, int16_t y0, uint16_t color);
void clearDisplay(); void clearDisplay();
void display(); void display();
void partialUpdate(); void partialUpdate();
void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char* _p, int16_t _w, int16_t _h); void drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char *_p, int16_t _w, int16_t _h);
void setRotation(uint8_t); void setRotation(uint8_t);
void einkOff(void); void einkOff(void);
void einkOn(void); void einkOn(void);
void selectDisplayMode(uint8_t _mode); void selectDisplayMode(uint8_t _mode);
uint8_t getDisplayMode(); uint8_t getDisplayMode();
int drawBitmapFromSD(SdFile* p, int x, int y, bool invert = false); int drawBitmapFromSD(SdFile *p, int x, int y);
int drawBitmapFromSD(char* fileName, int x, int y, bool invert = false); int drawBitmapFromSD(char *fileName, int x, int y);
int drawBitmapFromWeb(WiFiClient* s, int x, int y, int len, bool invert = false); void drawThickLine(int x1, int y1, int x2, int y2, int color, float thickness);
int drawBitmapFromWeb(char* url, int x, int y, bool invert = false); void drawGradientLine(int x1, int y1, int x2, int y2, int color1, int color2, float thickness = -1);
int sdCardInit(); int sdCardInit();
SdFat getSdFat(); SdFat getSdFat();
SPIClass getSPI(); SPIClass getSPI();
uint8_t getPanelState(); uint8_t getPanelState();
uint8_t readTouchpad(uint8_t); uint8_t readTouchpad(uint8_t);
int8_t readTemperature(); int8_t readTemperature();
double readBattery(); double readBattery();
void vscan_start(); void vscan_start();
void vscan_write(); void vscan_write();
void hscan_start(uint32_t _d = 0); void hscan_start(uint32_t _d = 0);
void vscan_end(); void vscan_end();
void clean(); void clean();
void cleanFast(uint8_t c, uint8_t rep); void cleanFast(uint8_t c, uint8_t rep);
void cleanFast2(uint8_t c, uint8_t n, uint16_t d); void cleanFast2(uint8_t c, uint8_t n, uint16_t d);
void pinsZstate(); void pinsZstate();
void pinsAsOutputs(); void pinsAsOutputs();
private: private:
uint8_t gammaLUT[256]; uint8_t gammaLUT[256];
int8_t _temperature; int8_t _temperature;
uint8_t _panelOn = 0; uint8_t _panelOn = 0;
uint8_t _rotation = 0; uint8_t _rotation = 0;
uint8_t _displayMode = 0; //By default, 1 bit mode is used uint8_t _displayMode = 0; //By default, 1 bit mode is used
int sdCardOk = 0; int sdCardOk = 0;
uint8_t _blockPartial = 1; uint8_t _blockPartial = 1;
uint8_t _beginDone = 0; uint8_t _beginDone = 0;
void display1b(); void display1b();
void display3b(); void display3b();
uint32_t read32(uint8_t* c); uint32_t read32(uint8_t *c);
uint16_t read16(uint8_t* c); uint16_t read16(uint8_t *c);
void readBmpHeaderSd(SdFile *_f, struct bitmapHeader *_h); void readBmpHeader(SdFile *_f, struct bitmapHeader *_h);
void readBmpHeaderWeb(WiFiClient *_s, struct bitmapHeader *_h); int drawMonochromeBitmap(SdFile *f, struct bitmapHeader bmpHeader, int x, int y);
int drawMonochromeBitmapSd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert); int drawGrayscaleBitmap24(SdFile *f, struct bitmapHeader bmpHeader, int x, int y);
int drawGrayscaleBitmap4Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert); void precalculateGamma(uint8_t *c, float gamma);
int drawGrayscaleBitmap8Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
int drawGrayscaleBitmap24Sd(SdFile *f, struct bitmapHeader bmpHeader, int x, int y, bool invert);
int drawMonochromeBitmapWeb(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
int drawGrayscaleBitmap4Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
int drawGrayscaleBitmap8Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
int drawGrayscaleBitmap24Web(WiFiClient *s, struct bitmapHeader bmpHeader, int x, int y, int len, bool invert);
void precalculateGamma(uint8_t* c, float gamma);
}; };
#endif #endif