inkplate-6-arduino-library/Inkplate.cpp

877 lines
21 KiB
C++
Raw Normal View History

2019-12-16 08:54:40 +01:00
#include <stdlib.h>
#include "Adafruit_GFX.h"
#include "Inkplate.h"
Adafruit_MCP23017 mcp;
Inkplate::Inkplate(uint8_t _mode) : Adafruit_GFX(E_INK_WIDTH, E_INK_HEIGHT) {
_displayMode = _mode;
}
Inkplate::Inkplate() : Adafruit_GFX(E_INK_WIDTH, E_INK_HEIGHT) {
}
void Inkplate::begin(void) {
Wire.begin();
mcp.begin(0);
mcp.pinMode(VCOM, OUTPUT);
mcp.pinMode(PWRUP, OUTPUT);
mcp.pinMode(WAKEUP, OUTPUT);
mcp.pinMode(GPIO0_ENABLE, OUTPUT);
mcp.digitalWrite(GPIO0_ENABLE, HIGH);
//CONTROL PINS
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
pinMode(32, OUTPUT);
pinMode(33, OUTPUT);
mcp.pinMode(OE, OUTPUT);
mcp.pinMode(GMOD, OUTPUT);
mcp.pinMode(SPV, OUTPUT);
//DATA PINS
pinMode(4, OUTPUT); //D0
pinMode(5, OUTPUT);
pinMode(18, OUTPUT);
pinMode(19, OUTPUT);
pinMode(23, OUTPUT);
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
pinMode(27, OUTPUT); //D7
//TOUCHPAD PINS
mcp.pinMode(10, INPUT);
mcp.pinMode(11, INPUT);
mcp.pinMode(12, INPUT);
//Battery voltage Switch MOSFET
mcp.pinMode(9, OUTPUT);
//1 bit per pixel mode (monochrome mode)
if (_displayMode == 0) {
D_memory_new = (uint8_t*)ps_malloc(600 * 100);
_partial = (uint8_t*)ps_malloc(600*100);
_pBuffer = (uint8_t*) ps_malloc(120000);
if (D_memory_new == NULL || _partial == NULL || _pBuffer == NULL) {
2019-12-16 08:54:40 +01:00
do {
delay(100);
} while (true);
}
memset(D_memory_new, 0, 60000);
memset(_partial, 0, 60000);
2019-12-16 08:54:40 +01:00
}
//3 bit per pixel mode (8 level grayscale mode)
if (_displayMode == 1) {
D_memory4Bit = (uint8_t*)ps_malloc(240000);
2019-12-16 08:54:40 +01:00
if (D_memory4Bit == NULL ) {
do {
delay(100);
} while (true);
}
memset(D_memory4Bit, 255, 240000);
2019-12-16 08:54:40 +01:00
}
}
void Inkplate::clearDisplay() {
//Clear 1 bit per pixel display buffer
if (_displayMode == 0) memset(_partial, 0, 60000);
2019-12-16 08:54:40 +01:00
//Clear 3 bit per pixel display buffer
if (_displayMode == 1) memset(D_memory4Bit, 255, 240000);
2019-12-16 08:54:40 +01:00
}
void Inkplate::draw_mode_on() {
einkOn();
SPH_SET;
SPV_SET;
delay(1);
OE_SET;
delay(1);
GMOD_SET;
CKV_SET;
delay(5);
2019-12-16 08:54:40 +01:00
}
void Inkplate::draw_mode_off() {
CKV_CLOCK;
GMOD_CLEAR;
CKV_CLOCK;
GPIO.out &= ~DATA;
CL_CLEAR;
LE_CLEAR;
OE_CLEAR;
SPV_CLEAR;
CKV_CLEAR;
SPH_CLEAR;
einkOff();
}
void Inkplate::advance_line() {
CKV_CLEAR;
usleep1();
CKV_SET;
usleep1();
}
void Inkplate::begin_frame() {
2019-12-16 08:54:40 +01:00
SPV_SET;
delayMicroseconds(100); //usleep(500);
2019-12-16 08:54:40 +01:00
SPV_CLEAR;
//usleep1();
CKV_CLEAR;
usleep1();
//delayMicroseconds(20); //usleep(25);
2019-12-16 08:54:40 +01:00
CKV_SET
usleep1();
SPV_SET;
usleep1();
//delayMicroseconds(20); //usleep(25);
//SPV_SET; //STV=1
//int loop = 2;
//while(loop--)
//{
// CKV_CLEAR; //CPV=0
// usleep1();
// CKV_SET; //CPV=1
// usleep1();
//}
//SPV_CLEAR; //STV=0
//loop = 2;
//while(loop--)
//{
// CKV_CLEAR; //CPV=0
// usleep1();
// CKV_SET; //CPV=1
// usleep1();
//}
//SPV_SET; //STV=1
//loop = 2;
//while(loop--)
//{
// CKV_CLEAR; //CPV=0
// usleep1();
// CKV_SET; //CPV=1
// usleep1();
//}
2019-12-16 08:54:40 +01:00
//Skip three lines to get to the start of the screen
advance_line();
advance_line();
advance_line();
}
void Inkplate::end_frame() {
}
void Inkplate::begin_line() {
SPH_CLEAR;
usleep1();
// LE_SET; //LE =1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//LE_CLEAR; //LE=0
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//EPD_OE_H; //OE =1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//SPH_CLEAR; //SPH=0
2019-12-16 08:54:40 +01:00
}
void Inkplate::end_line() {
2019-12-16 08:54:40 +01:00
SPH_SET;
//usleep1();
2019-12-16 08:54:40 +01:00
CKV_CLEAR;
//CL_SET;
usleep1();
CL_CLEAR;
//usleep1();
CKV_SET;
usleep1();
LE_SET;
//usleep1();
LE_CLEAR;
//usleep1();
// SPH_SET; //STH=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CKV_CLEAR; //CPV=0 zegar taktujacy bufor GATE
//EPD_OE_L; //OE =0
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CL_CLEAR; //CL=0
//CL_SET; //CL=1
//CKV_SET; //CPV=1
2019-12-16 08:54:40 +01:00
}
void Inkplate::end_line_slow() {
SPH_SET;
//usleep1();
CKV_CLEAR;
CL_SET;
delayMicroseconds(20);
//usleep1();
CL_CLEAR;
CKV_SET;
delayMicroseconds(4);
LE_SET;
//usleep1();
LE_CLEAR;
//usleep1();
}
//For precise 1uS timing, we cannot use delayMicroseconds(), instead we use ASM with nop command. Initial Z value will be difeerent on different CPU speeds! (for 240 MHz CPU Clock z = 25)
void usleep1() {
int z = 27;
2019-12-16 08:54:40 +01:00
while (z--) {
asm("NOP");
};
}
//Draw function, used by Adafruit GFX.
void Inkplate::drawPixel(int16_t x0, int16_t y0, uint16_t color) {
if (x0 > 799 || y0 > 599 || x0 < 0 || y0 < 0) return;
switch (_rotation) {
case 1:
_swap_int16_t(x0, y0);
x0 = _width - x0 - 1;
break;
case 2:
x0 = _width - x0 - 1;
y0 = _height - y0 - 1;
break;
case 3:
_swap_int16_t(x0, y0);
y0 = _width - y0 - 1;
break;
}
if (_displayMode == 0) {
int x = x0 / 8;
int x_sub = x0 % 8;
uint8_t temp = *(_partial + 100 * y0 + x); //D_memory_new[99 * y0 + x]; //-->> Doesn't work with index
//D_memory_new[100 * y0 + x] = ~pixelMaskLUT[x_sub] & temp | (color ? pixelMaskLUT[x_sub] : 0); //-->> Doesn't work with index
*(_partial + 100 * y0 + x) = ~pixelMaskLUT[x_sub] & temp | (color ? pixelMaskLUT[x_sub] : 0);
2019-12-16 08:54:40 +01:00
} else {
color &= 7;
int x = x0 / 2;
int x_sub = x0 % 2;
uint8_t temp;
temp = *(D_memory4Bit + 400 * y0 + x);
*(D_memory4Bit + 400 * y0 + x) = pixelMaskGLUT[x_sub] & temp | (x_sub ? color : color << 4);
}
}
//Function that displays content from RAM to screen
void Inkplate::display() {
if (_displayMode == 0) display1b();
if (_displayMode == 1) display3b();
}
//Display content from RAM to display (1 bit per pixel,. monochrome picture).
void Inkplate::display1b() {
for(int i = 0; i<60000; i++) {
*(D_memory_new+i) &= *(_partial+i);
*(D_memory_new+i) |= (*(_partial+i));
}
2019-12-16 08:54:40 +01:00
uint16_t _pos;
uint32_t _send;
uint8_t data;
draw_mode_on();
SPV_SET;
delayMicroseconds(500);
//cleanFast(2);
cleanFast(2);
for(int i = 0; i<8; i++) {
cleanFast(0);
delayMicroseconds(500);
}
for(int i = 0; i<8; i++) {
cleanFast(1);
delayMicroseconds(500);
}
for(int i = 0; i<8; i++) {
cleanFast(0);
delayMicroseconds(500);
}
//for(int i = 0; i<2; i++) {
//cleanFast(2);
//}
2019-12-16 08:54:40 +01:00
//for (int i = 0; i < 6; i++) {
// cleanFast(1);
// delayMicroseconds(500);
//}
//for (int i = 0; i < 6; i++) {
// cleanFast(0);
// delayMicroseconds(500);
//}
//for (int i = 0; i < 1; i++) {
// cleanFast(1);
2019-12-16 08:54:40 +01:00
//delayMicroseconds(500);
//}
for (int k = 0; k < 6; k++) {
begin_frame();
_pos = 59999;
for (int i = 0; i < 600; i++) {
//data = 10101010;
//_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA;
//GPIO.out_w1ts = _send;
//CL_SET;
CL_CLEAR;
begin_line();
for (int j = 0; j < 100; j++) {
data = LUTB[(*(D_memory_new + _pos) >> 4)];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
data = LUTB[*(D_memory_new + _pos) & 0x0F];
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
_pos--;
}
end_line();
}
end_frame();
delayMicroseconds(500);
2019-12-16 08:54:40 +01:00
}
cleanFast(2);
cleanFast(2);
delayMicroseconds(500);
draw_mode_off();
}
2019-12-16 08:54:40 +01:00
void Inkplate::partialUpdate() {
if(_displayMode == 1) return;
uint16_t _pos = 59999;
uint32_t _send;
uint8_t data;
uint8_t diffw, diffb;
uint32_t n = 119999;
draw_mode_on();
SPV_SET;
delayMicroseconds(500);
for (int i = 0; i < 600; i++) {
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)));
_pos--;
*(_pBuffer+n) = LUTW[diffw>>4] & (LUTB[diffb>>4]);
n--;
*(_pBuffer+n) = LUTW[diffw&0x0F] & (LUTB[diffb&0x0F]);
n--;
}
}
for (int k = 0; k < 7; k++) {
2019-12-16 08:54:40 +01:00
begin_frame();
n = 119999;
for (int i = 0; i < 600; i++) {
2019-12-16 08:54:40 +01:00
//data = 10101010;
//_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA;
//GPIO.out_w1ts = _send;
//CL_SET;
CL_CLEAR;
begin_line();
for (int j = 0; j < 200; j++) {
//_pos = i * 200 + j;
////diffw = ((*(D_memory_new+_pos))^(*(_partial+_pos)))&(~(*(_partial+_pos)));
////diffb = ((*(D_memory_new+_pos))^(*(_partial+_pos)))&((*(_partial+_pos)));
////data = LUTW[diffw>>4] & (LUTB[diffb>>4]);
//data = LUT2[(*(D_memory_new + _pos) >> 4)];
data = *(_pBuffer + n);
2019-12-16 08:54:40 +01:00
_send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
//data = LUT2[*(D_memory_new + _pos) & 0x0F];
////data = LUTW[diffw&0x0F] & (LUTB[diffb&0x0F]);
////_send = ((_pBuffer & B00000011) << 4) | (((_pBuffer & B00001100) >> 2) << 18) | (((_pBuffer & B00010000) >> 4) << 23) | (((_pBuffer & B11100000) >> 5) << 25);
////GPIO.out_w1tc = DATA | CL;
////GPIO.out_w1ts = _send;
////GPIO.out_w1ts = CL;
n--;
2019-12-16 08:54:40 +01:00
}
end_line();
}
end_frame();
delayMicroseconds(500);
}
for(int i = 0; i<60000; i++) {
*(D_memory_new+i) &= *(_partial+i);
*(D_memory_new+i) |= (*(_partial+i));
2019-12-16 08:54:40 +01:00
}
cleanFast(2);
delayMicroseconds(500);
draw_mode_off();
}
//Display content from RAM to display (3 bit per pixel,. 8 level of grayscale, STILL IN PROGRESSS, we need correct wavefrom to get good picture, use it only for pictures not for GFX).
void Inkplate::display3b() {
draw_mode_on();
SPV_SET;
delayMicroseconds(500);
cleanFast(2);
//cleanFast(2);
//for(int i = 0; i<5; i++) {
// cleanFast(0);
//}
for(int i = 0; i<5; i++) {
cleanFast(0);
//delay(1);
}
delay(5);
for(int i = 0; i<5; i++) {
cleanFast(0);
//delay(1);
}
delay(5);
for(int i = 0; i<7; i++) {
cleanFast(1);
//delay(1);
}
delay(5);
for(int i = 0; i<7; i++) {
cleanFast(0);
//delay(1);
}
delay(5);
//cleanFast(1);
cleanFast(2);
//cleanFast(0);
//for(int i = 0; i<3; i++) {
// cleanFast(2);
//}
for (int k = 0; k < 12; k++) {
//for (int k = 0; k < sz_contrast_cycles; ++k) {
//for (int contrast_cnt = 0; contrast_cnt < contrast_cycles[k]; ++contrast_cnt) {
2019-12-16 08:54:40 +01:00
begin_frame();
uint8_t *dp = D_memory4Bit + 239999;
uint32_t _send;
uint8_t pix1;
uint8_t pix2;
uint8_t pix3;
uint8_t pix4;
for (int i = 0; i < 600; i++) {
//CL_SET;
//GPIO.out_w1tc = DATA;
//CL_CLEAR;
2019-12-16 08:54:40 +01:00
begin_line();
//portDISABLE_INTERRUPTS();
2019-12-16 08:54:40 +01:00
for (int j = 0; j < 100; j++) {
uint8_t pixel = 0B00000000;
uint8_t pixel2 = 0B00000000;
2019-12-16 08:54:40 +01:00
//4 bit mode (non-reversed bits)
//pix1 = (*(dp) >> k) & 1; //4, 5, 6, 7
//pix2 = (*(dp--) >> k + 4) & 1; //0, 1, 2, 3
//pix3 = (*(dp) >> k) & 1;
//pix4 = (*(dp--) >> k + 4) & 1;
//pix1 = (*(dp)) & 0x07; //4, 5, 6, 7
//pix2 = (*(dp--) >> 4)& 0x07; //0, 1, 2, 3
//pix3 = (*(dp)) & 0x07;
//pix4 = (*(dp--) >> 4)& 0x07;
pix1 = *(dp--);
pix2 = *(dp--);
pix3 = *(dp--);
pix4 = *(dp--);
//pixel |= ( pixel_to_epd_cmd[pix1] << 6) | ( pixel_to_epd_cmd[pix2] << 4) | ( pixel_to_epd_cmd[pix3] << 2) | ( pixel_to_epd_cmd[pix4] << 0);
//pixel |= ( waveform3Bit[pix1][k] << 6) | ( waveform3Bit[pix2][k] << 4) | ( waveform3Bit[pix3][k] << 2) | ( waveform3Bit[pix4][k] << 0);
pixel |= ( waveform3Bit[pix1&0x07][k] << 6) | ( waveform3Bit[(pix1>>4)&0x07][k] << 4) | ( waveform3Bit[pix2&0x07][k] << 2) | ( waveform3Bit[(pix2>>4)&0x07][k] << 0);
pixel2 |= ( waveform3Bit[pix3&0x07][k] << 6) | ( waveform3Bit[(pix3>>4)&0x07][k] << 4) | ( waveform3Bit[pix4&0x07][k] << 2) | ( waveform3Bit[(pix4>>4)&0x07][k] << 0);
2019-12-16 08:54:40 +01:00
_send = ((pixel & B00000011) << 4) | (((pixel & B00001100) >> 2) << 18) | (((pixel & B00010000) >> 4) << 23) | (((pixel & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
//4 bit mode (non-reversed bits)
//pix1 = (*(dp) >> k) & 1; //4, 5, 6, 7
//pix2 = (*(dp--) >> k + 4) & 1; //0, 1, 2, 3
//pix3 = (*(dp) >> k) & 1;
//pix4 = (*(dp--) >> k + 4) & 1;
//pixel2 |= ( pixel_to_epd_cmd[pix1] << 6);
//pixel2 |= ( pixel_to_epd_cmd[pix2] << 4);
//pixel2 |= ( pixel_to_epd_cmd[pix3] << 2);
//pixel2 |= ( pixel_to_epd_cmd[pix4] << 0);
//pix1 = (*(dp)) & 0x07; //4, 5, 6, 7
//pix2 = (*(dp--) >> 4)& 0x07; //0, 1, 2, 3
//pix3 = (*(dp)) & 0x07;
//pix4 = (*(dp--) >> 4)& 0x07;
//pixel |= ( pixel_to_epd_cmd[pix1] << 6) | ( pixel_to_epd_cmd[pix2] << 4) | ( pixel_to_epd_cmd[pix3] << 2) | ( pixel_to_epd_cmd[pix4] << 0);
//pixel2 |= ( waveform3Bit[pix1][k] << 6) | ( waveform3Bit[pix2][k] << 4) | ( waveform3Bit[pix3][k] << 2) | ( waveform3Bit[pix4][k] << 0);
2019-12-16 08:54:40 +01:00
_send = ((pixel2 & B00000011) << 4) | (((pixel2 & B00001100) >> 2) << 18) | (((pixel2 & B00010000) >> 4) << 23) | (((pixel2 & B11100000) >> 5) << 25);
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
}
//portENABLE_INTERRUPTS();
2019-12-16 08:54:40 +01:00
end_line();
}
end_frame();
//}
2019-12-16 08:54:40 +01:00
}
2019-12-16 08:54:40 +01:00
cleanFast(2);
delayMicroseconds(500);
draw_mode_off();
}
void ckvClock() {
CKV_CLEAR;
usleep1();
CKV_SET;
usleep1();
}
void Inkplate::drawBitmap3Bit(int16_t _x, int16_t _y, const unsigned char* _p, int16_t _w, int16_t _h) {
if (_displayMode != INKPLATE_3BIT) return;
uint8_t _rem = _w % 2;
int i, j;
int xSize = _w / 2 + _rem;
//if (_shiftX == 0) {
// for (int i = _y; i < _y + _h; i++) {
// memcpy(D_memory4Bit + (400 * i) + _x/2, _p + _w/2 * (i-_y), _w / 2);
// }
//}
2019-12-16 08:54:40 +01:00
for (i = 0; i < _h; i++) {
for (j = 0; j < xSize - 1; j++) {
drawPixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4)>>1);
drawPixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff)>>1);
}
drawPixel((j * 2) + _x, i + _y, (*(_p + xSize * (i) + j) >> 4)>>1);
if (_rem == 0) drawPixel((j * 2) + 1 + _x, i + _y, (*(_p + xSize * (i) + j) & 0xff)>>1);
}
}
//Clears contenst from display (slower, some epaper panels needs slower cleaning process from others).
void Inkplate::fillScreen(uint8_t c) {
uint8_t data = c == 0 ? B10101010 : B01010101;
uint32_t _send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
draw_mode_on();
SPV_SET;
delayMicroseconds(500); //usleep(500);
for (int k = 0; k < REF_RATE; k++) {
begin_frame();
for (int i = 0; i < 600; i++) {
begin_line();
for (int j = 0; j < 100; j++) {
GPIO.out &= ~DATA;
GPIO.out |= _send;
CL_SET;
CL_CLEAR;
GPIO.out &= ~DATA;
GPIO.out |= _send;
CL_SET;
CL_CLEAR;
}
end_line();
}
end_frame();
}
draw_mode_off();
}
//Clear screan before new screen update using waveform
void Inkplate::clean() {
draw_mode_on();
SPV_SET; //dspv_gpio::set::set(1 << DSPV_BIT);
delayMicroseconds(500); //usleep(500);
int m = 0;
cleanFast(0); //white
m++;
for (int i = 0; i < 8; i++) {
cleanFast((waveform[m] >> 30) & 3); //White to white
m++;
delay(1);
2019-12-16 08:54:40 +01:00
}
//cleanFast(0);
2019-12-16 08:54:40 +01:00
cleanFast((waveform[m] >> 24) & 3); //white to black
m++;
for (int i = 0; i < 8; i++) {
cleanFast((waveform[m]) & 3); //Black to black
m++;
delay(1);
2019-12-16 08:54:40 +01:00
}
cleanFast((waveform[m] >> 6) & 3); //Black to white
m++;
for (int i = 0; i < 8; i++) {
cleanFast((waveform[m] >> 30) & 3); //White to white
m++;
delay(1);
2019-12-16 08:54:40 +01:00
}
//cleanFast(2);
//delay(1);
2019-12-16 08:54:40 +01:00
draw_mode_off();
}
//Clears content from epaper diplay as fast as ESP32 can.
void Inkplate::cleanFast(uint8_t c) {
uint8_t data;
if (c == 0) {
data = B10101010; //White
} else if (c == 1) {
data = B01010101; //Black
} else if (c == 2) {
data = B00000000; //Discharge
}
uint32_t _send = ((data & B00000011) << 4) | (((data & B00001100) >> 2) << 18) | (((data & B00010000) >> 4) << 23) | (((data & B11100000) >> 5) << 25);
begin_frame();
for (int i = 0; i < 600; i++) {
begin_line();
for (int j = 0; j < 100; j++) {
2019-12-16 08:54:40 +01:00
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
GPIO.out_w1tc = DATA | CL;
GPIO.out_w1ts = (_send) | CL;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
}
end_line();
}
end_frame();
}
//Turn on supply for epaper display (TPS65186) [+15 VDC, -15VDC, +22VDC, -20VDC, +3.3VDC, VCOM]
void Inkplate::einkOn() {
_panelOn = 1;
2019-12-16 08:54:40 +01:00
pinsAsOutputs();
WAKEUP_SET;
PWRUP_SET;
2019-12-16 08:54:40 +01:00
//Enable all rails
Wire.beginTransmission(0x48);
Wire.write(0x01);
Wire.write(B00111111);
Wire.endTransmission();
//Set out voltage on LDO outputs
Wire.beginTransmission(0x48);
Wire.write(0x02);
Wire.write(B00100011);
Wire.endTransmission();
//Set VCOM Voltage
Wire.beginTransmission(0x48);
Wire.write(0x03);
Wire.write(150);
2019-12-16 08:54:40 +01:00
Wire.endTransmission();
//Set power up times (all on 3mS)
Wire.beginTransmission(0x48);
Wire.write(0x0A);
Wire.write(0);
Wire.endTransmission();
//Set Power Down Seq.
Wire.beginTransmission(0x48);
Wire.write(0x0B);
Wire.write(B00011011);
Wire.endTransmission();
//Set Power Down Times (all on 6mS)
Wire.beginTransmission(0x48);
Wire.write(0x0C);
Wire.write(0);
Wire.endTransmission();
delay(20);
2019-12-16 08:54:40 +01:00
VCOM_SET;
2019-12-16 08:54:40 +01:00
Wire.beginTransmission(0x48);
Wire.write(0x0D);
Wire.write(B10000000);
Wire.endTransmission();
delay(2);
Wire.beginTransmission(0x48);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x48, 1);
_temperature = Wire.read();
2019-12-16 08:54:40 +01:00
}
//Turn off epapewr supply and put all digital IO pins in high Z state
void Inkplate::einkOff() {
_panelOn = 0;
GPIO.out &= ~(DATA | CL | LE);
SPH_CLEAR;
OE_CLEAR;
GMOD_CLEAR;
SPV_CLEAR;
PWRUP_CLEAR;
//Enable all rails
2019-12-16 08:54:40 +01:00
Wire.beginTransmission(0x48);
Wire.write(0x01);
Wire.write(B00000000);
Wire.endTransmission();
//delay(250);
WAKEUP_CLEAR;
VCOM_CLEAR;
2019-12-16 08:54:40 +01:00
pinsZstate();
}
void Inkplate::setRotation(uint8_t r) {
_rotation = r % 4;
switch (rotation) {
case 0:
_width = E_INK_WIDTH;
_height = E_INK_HEIGHT;
break;
case 1:
_width = E_INK_HEIGHT;
_height = E_INK_WIDTH;
break;
case 2:
_width = E_INK_WIDTH;
_height = E_INK_HEIGHT;
break;
case 3:
_width = E_INK_HEIGHT;
_height = E_INK_WIDTH;
break;
}
}
uint8_t Inkplate::getPanelState() {
return _panelOn;
}
void Inkplate::pinsZstate() {
//CONTROL PINS
pinMode(0, INPUT);
pinMode(2, INPUT);
pinMode(32, INPUT);
pinMode(33, INPUT);
mcp.pinMode(OE, INPUT);
mcp.pinMode(GMOD, INPUT);
mcp.pinMode(SPV, INPUT);
//DATA PINS
pinMode(4, INPUT); //D0
pinMode(5, INPUT);
pinMode(18, INPUT);
pinMode(19, INPUT);
pinMode(23, INPUT);
pinMode(25, INPUT);
pinMode(26, INPUT);
pinMode(27, INPUT); //D7
}
void Inkplate::pinsAsOutputs() {
//CONTROL PINS
pinMode(0, OUTPUT);
pinMode(2, OUTPUT);
pinMode(32, OUTPUT);
pinMode(33, OUTPUT);
mcp.pinMode(OE, OUTPUT);
mcp.pinMode(GMOD, OUTPUT);
mcp.pinMode(SPV, OUTPUT);
//DATA PINS
pinMode(4, OUTPUT); //D0
pinMode(5, OUTPUT);
pinMode(18, OUTPUT);
pinMode(19, OUTPUT);
pinMode(23, OUTPUT);
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
pinMode(27, OUTPUT); //D7
}
void Inkplate::selectDisplayMode(uint8_t _mode) {
if (_mode == INKPLATE_1BIT) {
if (D_memory_new != NULL) return;
2019-12-16 08:54:40 +01:00
if (D_memory4Bit != NULL) free(D_memory4Bit);
//1 bit per pixel mode (monochrome mode)
D_memory_new = (uint8_t*)ps_malloc(600 * 100);
_partial = (uint8_t*)ps_malloc(600 * 100);
_pBuffer = (uint8_t*) ps_malloc(120000);
if (D_memory_new == NULL || _partial == NULL || _pBuffer == NULL) {
2019-12-16 08:54:40 +01:00
do {
delay(100);
} while (true);
}
memset(D_memory_new, 0, 60000);
_displayMode = INKPLATE_1BIT;
}
if (_mode == INKPLATE_3BIT) {
if (D_memory4Bit != NULL) return;
if (D_memory_new != NULL) {
free(D_memory_new);
free(_partial);
free(_pBuffer);
}
//3 bit per pixel mode (8 level grayscale mode)
2019-12-16 08:54:40 +01:00
D_memory4Bit = (uint8_t*)ps_malloc(240000);
if (D_memory4Bit == NULL ) {
do {
delay(100);
} while (true);
}
memset(D_memory4Bit, 255, 240000);
2019-12-16 08:54:40 +01:00
_displayMode = INKPLATE_3BIT;
}
}
uint8_t Inkplate::getDisplayMode() {
return _displayMode;
}
uint8_t Inkplate::readTouchpad(uint8_t _pad) {
return mcp.digitalRead((_pad&3)+10);
}
int8_t Inkplate::readTemperature() {
return _temperature;
}
double Inkplate::readBattery() {
mcp.digitalWrite(9, HIGH);
delay(1);
int adc = analogRead(35);
mcp.digitalWrite(9, LOW);
return (double(adc) / 4095 * 3.3 * 2);
}