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 ) ;
2020-03-12 14:28:34 +01:00
_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 ) ;
2020-03-12 14:28:34 +01:00
memset ( _partial , 0 , 60000 ) ;
2019-12-16 08:54:40 +01:00
}
//3 bit per pixel mode (8 level grayscale mode)
if ( _displayMode = = 1 ) {
2020-03-12 14:28:34 +01:00
D_memory4Bit = ( uint8_t * ) ps_malloc ( 240000 ) ;
2019-12-16 08:54:40 +01:00
if ( D_memory4Bit = = NULL ) {
do {
delay ( 100 ) ;
} while ( true ) ;
}
2020-03-12 14:28:34 +01:00
memset ( D_memory4Bit , 255 , 240000 ) ;
2019-12-16 08:54:40 +01:00
}
}
void Inkplate : : clearDisplay ( ) {
//Clear 1 bit per pixel display buffer
2020-03-12 14:28:34 +01:00
if ( _displayMode = = 0 ) memset ( _partial , 0 , 60000 ) ;
2019-12-16 08:54:40 +01:00
//Clear 3 bit per pixel display buffer
2020-03-12 14:28:34 +01:00
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 ;
2020-03-12 14:28:34 +01:00
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 ( ) {
2020-03-12 14:28:34 +01:00
2019-12-16 08:54:40 +01:00
SPV_SET ;
2020-03-12 14:28:34 +01:00
delayMicroseconds ( 100 ) ; //usleep(500);
2019-12-16 08:54:40 +01:00
SPV_CLEAR ;
//usleep1();
CKV_CLEAR ;
2020-03-12 14:28:34 +01:00
usleep1 ( ) ;
//delayMicroseconds(20); //usleep(25);
2019-12-16 08:54:40 +01:00
CKV_SET
usleep1 ( ) ;
SPV_SET ;
2020-03-12 14:28:34 +01:00
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 ;
2020-03-12 14:28:34 +01:00
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 ( ) {
2020-03-12 14:28:34 +01:00
2019-12-16 08:54:40 +01:00
SPH_SET ;
2020-03-12 14:28:34 +01:00
//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();
2020-03-12 14:28:34 +01:00
// 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 ( ) {
2020-03-12 14:28:34 +01:00
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 ;
2020-03-12 14:28:34 +01:00
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 ( ) {
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
//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);
//}
2020-03-12 14:28:34 +01:00
//for (int i = 0; i < 1; i++) {
// cleanFast(1);
2019-12-16 08:54:40 +01:00
//delayMicroseconds(500);
2020-03-12 14:28:34 +01:00
//}
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
}
2020-03-12 14:28:34 +01:00
cleanFast ( 2 ) ;
cleanFast ( 2 ) ;
delayMicroseconds ( 500 ) ;
draw_mode_off ( ) ;
}
2019-12-16 08:54:40 +01:00
2020-03-12 14:28:34 +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 ( ) ;
2020-03-12 14:28:34 +01:00
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 ( ) ;
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
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 ( ) ;
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
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 + + ) {
2020-03-12 14:28:34 +01:00
//CL_SET;
//GPIO.out_w1tc = DATA;
//CL_CLEAR;
2019-12-16 08:54:40 +01:00
begin_line ( ) ;
2020-03-12 14:28:34 +01:00
//portDISABLE_INTERRUPTS();
2019-12-16 08:54:40 +01:00
for ( int j = 0 ; j < 100 ; j + + ) {
2020-03-12 14:28:34 +01:00
uint8_t pixel = 0B00000000 ;
uint8_t pixel2 = 0B00000000 ;
2019-12-16 08:54:40 +01:00
//4 bit mode (non-reversed bits)
2020-03-12 14:28:34 +01:00
//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 ;
2020-03-12 14:28:34 +01:00
GPIO . out_w1ts = ( _send ) | CL ;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
//4 bit mode (non-reversed bits)
2020-03-12 14:28:34 +01:00
//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 ;
2020-03-12 14:28:34 +01:00
GPIO . out_w1ts = ( _send ) | CL ;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
}
2020-03-12 14:28:34 +01:00
//portENABLE_INTERRUPTS();
2019-12-16 08:54:40 +01:00
end_line ( ) ;
}
end_frame ( ) ;
2020-03-12 14:28:34 +01:00
//}
2019-12-16 08:54:40 +01:00
}
2020-03-12 14:28:34 +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 ;
2020-03-12 14:28:34 +01:00
//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 + + ;
2020-03-12 14:28:34 +01:00
delay ( 1 ) ;
2019-12-16 08:54:40 +01:00
}
2020-03-12 14:28:34 +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 + + ;
2020-03-12 14:28:34 +01:00
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 + + ;
2020-03-12 14:28:34 +01:00
delay ( 1 ) ;
2019-12-16 08:54:40 +01:00
}
2020-03-12 14:28:34 +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 ( ) ;
2020-03-12 14:28:34 +01:00
for ( int j = 0 ; j < 100 ; j + + ) {
2019-12-16 08:54:40 +01:00
GPIO . out_w1tc = DATA | CL ;
2020-03-12 14:28:34 +01:00
GPIO . out_w1ts = ( _send ) | CL ;
//GPIO.out_w1ts = CL;
2019-12-16 08:54:40 +01:00
GPIO . out_w1tc = DATA | CL ;
2020-03-12 14:28:34 +01:00
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 ( ) {
2020-03-12 14:28:34 +01:00
_panelOn = 1 ;
2019-12-16 08:54:40 +01:00
pinsAsOutputs ( ) ;
WAKEUP_SET ;
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
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 ( ) ;
2020-03-12 14:28:34 +01:00
delay ( 20 ) ;
2019-12-16 08:54:40 +01:00
2020-03-12 14:28:34 +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 ( ) ;
2020-03-12 14:28:34 +01:00
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 ;
2020-03-12 14:28:34 +01:00
//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 ;
2020-03-12 14:28:34 +01:00
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 ) {
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
_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 ) {
2020-03-12 14:28:34 +01:00
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 ) ;
}
2020-03-12 14:28:34 +01:00
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 ) ;
2020-03-12 14:28:34 +01:00
}