Last active
July 18, 2020 19:49
-
-
Save Lukelectro/29857324e392116e9f2726e1025e3ae2 to your computer and use it in GitHub Desktop.
E-Ink ED060SC7 differs from ...SC4 (Swap X & Y). STM32F103 has less RAM, so only Proof of Concept.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[empty file, added to change gist title] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
EPD DRIVER FOR STM32F2/4 w/ FSMC | |
By ZephRay(zephray@outlook.com) | |
*******************************************************************************/ | |
#include "epd.h" | |
#include <stdlib.h> // otherwise abs() not defined. | |
/******************************************************************************* | |
*******************************************************************************/ | |
//unsigned char EPD_FB[60000]; //1bpp Framebuffer /* TODO: this won' t fit in STM32F103 RAM. */ | |
#define BUFFERSIZE 18000 | |
unsigned char EPD_FB[BUFFERSIZE]; | |
#ifdef BGIMG /* To save memory / to simplyfy making-it-work */ | |
#ifdef __USE_FIXED_BG__ | |
#include <bg.h> | |
#else | |
unsigned char EPD_BG[240000] @ 0x08020000; //fixed address of image | |
#endif | |
#endif | |
#define MIN(a,b) (((a)<(b))?(a):(b)) | |
#define MAX(a,b) (((a)>(b))?(a):(b)) | |
extern const unsigned char Font_Ascii_8X16E[]; | |
extern const unsigned char Font_Ascii_24X48E[]; | |
extern const unsigned char Font_Ascii_12X24E[]; | |
//extern const unsigned char WQY_ASCII_24[]; | |
#ifndef USE_H_SCREEN | |
//Init waveform, basiclly alternating between black and white | |
#define FRAME_INIT_LEN 33 | |
const unsigned char wave_init[FRAME_INIT_LEN]= | |
{ | |
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, | |
0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, | |
0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55, | |
0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, | |
0, | |
}; | |
//line delay for different shades of grey | |
//note that delay is accumulative | |
//it means that if it's the level 4 grey | |
//the total line delay is 90+90+90+90=360 | |
//this could be used as a method of rough gamma correction | |
//these settings only affect 4bpp mode | |
const unsigned char timA[16] = | |
{ | |
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
90,90,90,90,90,90,90,90,90,90,120,120,120,120,200 | |
}; | |
#define timB 20 | |
//this only affect 1bpp mode | |
#define clearCount 4 | |
#define setCount 4 | |
#else | |
#define FRAME_INIT_LEN 21 | |
const unsigned char wave_init[FRAME_INIT_LEN]= | |
{ | |
0x55,0x55,0x55,0x55,0x55, | |
0xaa,0xaa,0xaa,0xaa,0xaa, | |
0x55,0x55,0x55,0x55,0x55, | |
0xaa,0xaa,0xaa,0xaa,0xaa, | |
0, | |
}; | |
const unsigned char timA[16] = | |
{ | |
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
30,20,20,15,15,15,15,15,20,20,20,20,20,40,50 | |
}; | |
#define timB 40 | |
#define clearCount 2 | |
#define setCount 2 | |
#endif | |
unsigned char g_dest_data[200];//Line data buffer | |
void DelayCycle(unsigned long x) | |
{ | |
while (x--) | |
{ | |
asm("nop"); | |
} | |
} | |
//Us delay that is not accurate | |
void Delay_Us(unsigned long x) | |
{ | |
unsigned long a; | |
while (x--) | |
{ | |
a = 17;// on the original 120 MHz | |
a=8; /* TODO: verify this works on the 60 MHz f103*/ | |
while (a--) | |
{ | |
asm ("nop"); | |
} | |
} | |
} | |
void EPD_GPIO_Init() | |
{ | |
/* with all pins in different places, this is changed too. Initialisation of GPIO is done by STM32HAL*/ | |
} | |
void EPD_Power_Off(void) | |
{ | |
/* power down sequence as per Petteri Aimonen / datasheet*/ | |
VPOS_CTRL_GPIO_Port->BRR = VPOS_CTRL_Pin; | |
VNEG_CTRL_GPIO_Port->BRR = VNEG_CTRL_Pin; | |
Delay_Us(100); | |
EPD_LE_L(); | |
EPD_CL_L(); | |
EPD_OE_L(); | |
EPD_SPH_L(); | |
EPD_SPV_L(); | |
EPD_CKV_L(); | |
EPD_GMODE1_L(); | |
PWR_CTRL_GPIO_Port->BRR = PWR_CTRL_Pin; | |
} | |
void EPD_Init(void) | |
{ | |
unsigned long i; | |
EPD_GPIO_Init(); | |
//EPD_SHR_L(); | |
EPD_GMODE1_H(); | |
//EPD_GMODE2_H(); | |
//EPD_XRL_H(); | |
EPD_Power_Off(); | |
EPD_LE_L(); | |
EPD_CL_L(); | |
EPD_OE_L(); | |
EPD_SPH_H(); | |
EPD_SPV_H(); | |
EPD_CKV_L(); | |
// for (i=0;i<60000;i++) | |
for (i=0;i<BUFFERSIZE;i++) | |
{ | |
EPD_FB[i]=0; | |
} | |
} | |
void EPD_Send_Row_Data(u8 *pArray) | |
{ | |
unsigned char i; | |
unsigned short a; | |
a = GPIOA->IDR & 0x00FF; | |
EPD_LE_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_LE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_OE_H(); | |
EPD_SPH_L(); | |
for (i=0;i<200;i++) | |
{ | |
// GPIOA->ODR = pArray[i]; /* this wont work considering that port is shared with other things now.. */ | |
D0_GPIO_Port->ODR = (D0_GPIO_Port->ODR & 0xFF00) | pArray[i]; /* do this instead */ | |
EPD_CL_H(); | |
//DelayCycle(1); | |
EPD_CL_L(); | |
} | |
EPD_SPH_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CKV_L(); | |
EPD_OE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CKV_H(); | |
} | |
void EPD_SkipRow(void) | |
{ | |
unsigned char i; | |
unsigned short a; | |
a = GPIOA->IDR & 0x00FF; | |
EPD_LE_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_LE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_OE_H(); | |
EPD_SPH_L(); | |
for (i=0;i<200;i++) | |
{ | |
GPIOA->ODR = a; | |
EPD_CL_H(); | |
//DelayCycle(1); | |
EPD_CL_L(); | |
} | |
EPD_SPH_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CKV_L(); | |
EPD_OE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CKV_H(); | |
} | |
void EPD_Send_Row_Data_Slow(u8 *pArray,unsigned char timingA,unsigned char timingB) | |
{ | |
unsigned char i; | |
unsigned short a; | |
a = GPIOA->IDR & 0x00FF; | |
EPD_OE_H(); | |
EPD_SPH_L(); | |
for (i=0;i<200;i++) | |
{ | |
// GPIOA->ODR = pArray[i]; /* this wont work considering that port is shared with other things now.. */ | |
D0_GPIO_Port->ODR = (D0_GPIO_Port->ODR & 0xFF00) |pArray[i]; /* do this instead */ | |
EPD_CL_H(); | |
//DelayCycle(1); | |
EPD_CL_L(); | |
} | |
EPD_SPH_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_LE_H(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_LE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CKV_H(); | |
DelayCycle(timingA); | |
EPD_CKV_L(); | |
DelayCycle(timingB); | |
EPD_OE_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
EPD_CL_H(); | |
EPD_CL_L(); | |
} | |
void EPD_Vclock_Quick(void) | |
{ | |
unsigned char i; | |
for (i=0;i<2;i++) | |
{ | |
EPD_CKV_L(); | |
DelayCycle(20); | |
EPD_CKV_H(); | |
DelayCycle(20); | |
} | |
} | |
void EPD_Start_Scan(void) | |
{ | |
EPD_SPV_H(); | |
EPD_Vclock_Quick(); | |
EPD_SPV_L(); | |
EPD_Vclock_Quick(); | |
EPD_SPV_H(); | |
EPD_Vclock_Quick(); | |
} | |
void EPD_Power_On(void) | |
{ | |
PWR_CTRL_GPIO_Port->BSRR = PWR_CTRL_Pin; | |
/* power up sequence as per Petteri Aimonen / datasheet*/ | |
Delay_Us(100); | |
VNEG_CTRL_GPIO_Port->BSRR = VNEG_CTRL_Pin; | |
Delay_Us(1000); | |
VPOS_CTRL_GPIO_Port->BSRR = VPOS_CTRL_Pin; | |
} | |
void EPD_Clear(void) | |
{ | |
unsigned short line,frame,i; | |
for(frame=0; frame<FRAME_INIT_LEN; frame++) | |
{ | |
EPD_Start_Scan(); | |
for(line=0; line<600; line++) | |
{ | |
for(i=0;i<200;i++) g_dest_data[i]=wave_init[frame]; | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
} | |
#ifdef BGIMG | |
void EPD_EncodeLine_Pic(u8 *new_pic, u8 frame)//Encode data for grayscale image | |
{ | |
int i,j; | |
unsigned char k,d; | |
j=0; | |
for(i=0; i<200; i++) | |
{ | |
d = 0; | |
k = new_pic[j++]; | |
if ((k&0x0F)>frame) d |= 0x10; | |
if ((k>>4)>frame) d |= 0x40; | |
k = new_pic[j++]; | |
if ((k&0x0F)>frame) d |= 0x01; | |
if ((k>>4)>frame) d |= 0x04; | |
g_dest_data[i] = d; | |
} | |
} | |
void EPD_DispPic()//Display image in grayscale mode | |
{ | |
unsigned short frame; | |
signed long line; | |
unsigned long i; | |
unsigned char *ptr; | |
ptr = (unsigned char *)EPD_BG; | |
for(frame=0; frame<15; frame++) | |
{ | |
EPD_Start_Scan(); | |
for (i=0;i<200;i++) g_dest_data[i]=0x00; | |
for(line=0; line<70; line++) | |
{ | |
EPD_Send_Row_Data_Slow(g_dest_data,timA[frame],timB); | |
} | |
for(line=(530-1); line>=0; line--) | |
{ | |
EPD_EncodeLine_Pic(ptr + line*400, frame); | |
EPD_Send_Row_Data_Slow(g_dest_data,timA[frame],timB); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
} | |
#endif | |
//Encode data for monochrome image | |
//From white to image | |
void EPD_EncodeLine_To(u8 *new_pic) | |
{ | |
int i,j; | |
unsigned char k,d; | |
j=0; | |
for(i=0; i<100; i++) | |
{ | |
k = new_pic[i]; | |
d = 0; | |
if (k&0x01) d |= 0x40; | |
if (k&0x02) d |= 0x10; | |
if (k&0x04) d |= 0x04; | |
if (k&0x08) d |= 0x01; | |
g_dest_data[j++] = d; | |
d = 0; | |
if (k&0x10) d |= 0x40; | |
if (k&0x20) d |= 0x10; | |
if (k&0x40) d |= 0x04; | |
if (k&0x80) d |= 0x01; | |
g_dest_data[j++] = d; | |
} | |
} | |
//Encode data for clearing a monochrome image | |
//From image to black | |
void EPD_EncodeLine_From(u8 *new_pic) | |
{ | |
int i,j; | |
unsigned char k,d; | |
j=0; | |
for(i=0; i<100; i++) | |
{ | |
k = ~new_pic[i]; | |
d = 0; | |
if (k&0x01) d |= 0x40; | |
if (k&0x02) d |= 0x10; | |
if (k&0x04) d |= 0x04; | |
if (k&0x08) d |= 0x01; | |
g_dest_data[j++] = d; | |
d = 0; | |
if (k&0x10) d |= 0x40; | |
if (k&0x20) d |= 0x10; | |
if (k&0x40) d |= 0x04; | |
if (k&0x80) d |= 0x01; | |
g_dest_data[j++] = d; | |
} | |
} | |
//Display image in monochrome mode | |
/* TODO: this needs the large buffer it originaly had but wont fit in ram on f103*/ | |
void EPD_DispScr(unsigned int startLine, unsigned int lineCount) | |
{ | |
unsigned short frame; | |
signed short line; | |
unsigned long i; | |
unsigned char *ptr; | |
unsigned long skipBefore,skipAfter; | |
ptr = EPD_FB; | |
skipBefore = 600-startLine-lineCount; | |
skipAfter = startLine; | |
for(frame=0; frame<setCount; frame++) | |
{ | |
EPD_Start_Scan(); | |
for(line=0;line<skipBefore;line++) | |
{ | |
EPD_EncodeLine_To(ptr); | |
EPD_SkipRow(); | |
} | |
for(line=(lineCount-1); line>=0; line--) | |
{ | |
EPD_EncodeLine_To(ptr + (line+startLine)*100); | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
for(line=0;line<skipAfter;line++) | |
{ | |
EPD_EncodeLine_To(ptr); | |
EPD_SkipRow(); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
} | |
//Clear image in monochrome mode | |
/* TODO: this needs the large buffer it originaly had but wont fit in ram on f103*/ | |
void EPD_ClearScr(unsigned int startLine, unsigned int lineCount) | |
{ | |
unsigned short frame; | |
signed short line; | |
unsigned long i; | |
unsigned char *ptr; | |
unsigned long skipBefore,skipAfter; | |
ptr = EPD_FB; | |
skipBefore = 600-startLine-lineCount; | |
skipAfter = startLine; | |
for(frame=0; frame<clearCount; frame++) | |
{ | |
EPD_Start_Scan(); | |
for(line=0;line<skipBefore;line++) | |
{ | |
EPD_EncodeLine_From(ptr); | |
EPD_SkipRow(); | |
} | |
for(line=(lineCount-1); line>=0; line--) | |
{ | |
EPD_EncodeLine_From(ptr + (line+startLine)*100); | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
for(line=0;line<skipAfter;line++) | |
{ | |
EPD_EncodeLine_From(ptr); | |
EPD_SkipRow(); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
for(frame=0; frame<4; frame++) | |
{ | |
EPD_Start_Scan(); | |
for(line=0;line<skipBefore;line++) | |
{ | |
EPD_SkipRow(); | |
} | |
for(line=(lineCount-1); line>=0; line--) | |
{ | |
for(i=0;i<200;i++) g_dest_data[i]=0xaa; | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
for(line=0;line<skipAfter;line++) | |
{; | |
EPD_SkipRow(); | |
} | |
EPD_Send_Row_Data( g_dest_data ); | |
} | |
} | |
void EPD_ClearFB(unsigned char c) | |
{ | |
unsigned long i; | |
// for (i=0;i<60000;i++) | |
for (i=0;i<BUFFERSIZE;i++) /* TODO: made to fit ram*/ | |
EPD_FB[i]=c; | |
} | |
#ifndef ROTATE | |
void EPD_SetPixel(unsigned short x,unsigned short y,unsigned char color) | |
{ | |
unsigned short x_bit; | |
unsigned long x_byte; | |
//if ((x<800)&&(y<600)) /* TODO: this would go wrong with the smaller buffer, so...*/ | |
if((x<600)&&(y<240)) | |
{ | |
x_byte=x/8+y*100; | |
x_bit=x%8; | |
EPD_FB[x_byte] &= ~(1 << x_bit); | |
EPD_FB[x_byte] |= (color << x_bit); | |
} | |
} | |
#else | |
void EPD_SetPixel(unsigned short x,unsigned short y,unsigned char color) | |
{ | |
/* rotated 90 degrees */ | |
unsigned short y_bit; | |
unsigned long y_byte; | |
//if ((x<800)&&(y<600)) /* TODO: this would go wrong with the smaller buffer, so...*/ | |
/* besides, the ed060SC7 is 600x800, not 800x600*/ | |
if((x<600)&&(y<240)) | |
{ | |
y_byte=y/8+x*100; | |
y_bit=y%8; | |
EPD_FB[y_byte] &= ~(1 << y_bit); | |
EPD_FB[y_byte] |= (color << y_bit); | |
} | |
} | |
#endif | |
void EPD_XLine(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short color) | |
{ | |
unsigned short i,xx0,xx1; | |
xx0=MIN(x0,x1); | |
xx1=MAX(x0,x1); | |
for (i=xx0;i<=xx1;i++) | |
{ | |
EPD_SetPixel(i,y0,color); | |
} | |
} | |
void EPD_YLine(unsigned short x0,unsigned short y0,unsigned short y1,unsigned short color) | |
{ | |
unsigned short i,yy0,yy1; | |
yy0=MIN(y0,y1); | |
yy1=MAX(y0,y1); | |
for (i=yy0;i<=yy1;i++) | |
{ | |
EPD_SetPixel(x0,yy1,color); | |
} | |
} | |
void EPD_Line(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned short color) | |
{ | |
int temp; | |
int dx,dy; //������㵽�յ�ĺᡢ����������ֵ | |
int s1,s2,status,i; | |
int Dx,Dy,sub; | |
dx=x1-x0; | |
if(dx>=0) //X�ķ��������ӵ� | |
s1=1; | |
else //X�ķ����ǽ��͵� | |
s1=-1; | |
dy=y1-y0; //�ж�Y�ķ��������ӻ��ǽ����� | |
if(dy>=0) | |
s2=1; | |
else | |
s2=-1; | |
Dx=abs(x1-x0); //����ᡢ�ݱ�־����ֵ�ľ���ֵ | |
Dy=abs(y1-y0); | |
if(Dy>Dx) // | |
{ //��45�Ƚ�Ϊ�ֽ��ߣ�����Y����status=1,����X����status=0 | |
temp=Dx; | |
Dx=Dy; | |
Dy=temp; | |
status=1; | |
} | |
else | |
status=0; | |
/********�жϴ�ֱ�ߺ�ˮƽ��********/ | |
if(dx==0) //������û����������һ��ˮƽ�� | |
EPD_YLine(x0,y0,y1,color); | |
if(dy==0) //������û����������һ����ֱ�� | |
EPD_XLine(x0,y0,x1,color); | |
/*********Bresenham�㷨������������ֱ��********/ | |
sub=2*Dy-Dx; //��1���ж��¸����λ�� | |
for(i=0;i<Dx;i++) | |
{ | |
EPD_SetPixel(x0,y0,color); //���� | |
if(sub>=0) | |
{ | |
if(status==1) //�ڿ���Y������xֵ��1 | |
x0+=s1; | |
else //�ڿ���X������yֵ��1 | |
y0+=s2; | |
sub-=2*Dx; //�ж����¸����λ�� | |
} | |
if(status==1) | |
y0+=s2; | |
else | |
x0+=s1; | |
sub+=2*Dy; | |
} | |
} | |
void EPD_PutChar_16(unsigned short x, unsigned short y, unsigned short chr, unsigned char color) | |
{ | |
unsigned short x1,y1; | |
unsigned short ptr; | |
ptr=(chr-0x20)*16; | |
for (y1=0;y1<16;y1++) | |
{ | |
for (x1=0;x1<8;x1++) | |
{ | |
if ((Font_Ascii_8X16E[ptr]>>x1)&0x01) | |
EPD_SetPixel(x+x1,y+y1,color); | |
else | |
EPD_SetPixel(x+x1,y+y1,1-color); | |
} | |
ptr++; | |
} | |
} | |
void EPD_PutChar_24(unsigned short x, unsigned short y, unsigned short chr, unsigned char color) | |
{ | |
unsigned short x1,y1,b; | |
unsigned short ptr; | |
ptr=(chr-0x20)*48; | |
for (y1=0;y1<24;y1++) | |
{ | |
for (b=0;b<8;b++) | |
if ((Font_Ascii_12X24E[ptr]<<b)&0x80) | |
EPD_SetPixel(x+b,y+y1,color); | |
else | |
EPD_SetPixel(x+b,y+y1,1-color); | |
ptr++; | |
for (b=0;b<4;b++) | |
if ((Font_Ascii_12X24E[ptr]<<b)&0x80) | |
EPD_SetPixel(x+8+b,y+y1,color); | |
else | |
EPD_SetPixel(x+8+b,y+y1,1-color); | |
ptr++; | |
} | |
} | |
void EPD_PutChar_48(unsigned short x, unsigned short y, unsigned short chr, unsigned char color) | |
{ | |
unsigned short x1,y1,b; | |
unsigned short ptr; | |
ptr=(chr-0x20)*144; | |
for (y1=0;y1<48;y1++) | |
{ | |
for (x1=0;x1<24;x1+=8) | |
{ | |
for (b=0;b<8;b++) | |
if ((Font_Ascii_24X48E[ptr]>>b)&0x01) | |
EPD_SetPixel(x+x1+b,y+y1,color); | |
else | |
EPD_SetPixel(x+x1+b,y+y1,1-color); | |
ptr++; | |
} | |
} | |
} | |
void EPD_String_16(unsigned short x,unsigned short y,unsigned char *s,unsigned char color) | |
{ | |
unsigned short x1; | |
x1=0; | |
while(*s) | |
{ | |
if (*s<128) | |
{ | |
EPD_PutChar_16(x+x1,y,*s++,color); | |
x+=8; | |
} | |
} | |
} | |
void EPD_String_24(unsigned short x,unsigned short y,unsigned char *s,unsigned char color) | |
{ | |
unsigned short x1; | |
x1=0; | |
while(*s) | |
{ | |
if (*s<128) | |
{ | |
EPD_PutChar_24(x+x1,y,*s++,color); | |
x+=12; | |
} | |
} | |
} | |
void EPD_FillRect(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned char color) | |
{ | |
unsigned short x,y; | |
for (x=x1;x<x2;x++) | |
for (y=y1;y<y2;y++) | |
EPD_SetPixel(x,y,color); | |
} | |
/*void EPD_FastFillRect(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned char color) | |
{ | |
unsigned short x,x1a,x2a,y; | |
unsigned char c; | |
c = (color << 6) | (color << 4) | (color << 2) | color; | |
for (y=y1;y<y2;y++) | |
{ | |
x1a = (x1+3)/ 4; | |
x2a = x2/ 4; | |
for (x=x1a;x<x2a;x++) | |
EPD_InfoView[y*200+x]=c; | |
if ((x1a*4)>x1) | |
for (x=x1;x<(x1a*4);x++) | |
EPD_SetPixel(x,y,color); | |
if ((x2a*4)<x2) | |
for (x=(x2a*4);x<x2;x++) | |
EPD_SetPixel(x,y,color); | |
} | |
}*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
EPD DRIVER FOR STM32F2/4 w/ FSMC | |
By ZephRay(zephray@outlook.com) | |
*******************************************************************************/ | |
#ifndef __EPD_H__ | |
#define __EPD_H__ | |
#include "main.h" | |
//Use new ED060SC4 H1/H2 screens | |
//if you are using ED060SC4 without any postfix, comment this | |
//#define USE_H_SCREEN | |
//extern unsigned char EPD_FB[60000]; | |
extern unsigned char EPD_FB[]; | |
#define PulseDelay() {} | |
#if original | |
//SOURCE DRIVER | |
#define EPD_CL_L() {GPIOA->BSRRH = GPIO_Pin_1; PulseDelay();} | |
#define EPD_CL_H() {GPIOA->BSRRL = GPIO_Pin_1; PulseDelay();} | |
#define EPD_LE_L() {GPIOA->BSRRH = GPIO_Pin_2; PulseDelay();} | |
#define EPD_LE_H() {GPIOA->BSRRL = GPIO_Pin_2; PulseDelay();} | |
#define EPD_OE_L() {GPIOA->BSRRH = GPIO_Pin_3; PulseDelay();} | |
#define EPD_OE_H() {GPIOA->BSRRL = GPIO_Pin_3; PulseDelay();} | |
#define EPD_SHR_L() {GPIOA->BSRRH = GPIO_Pin_4; PulseDelay();} | |
#define EPD_SHR_H() {GPIOA->BSRRL = GPIO_Pin_4; PulseDelay();} | |
#define EPD_SPH_L() {GPIOA->BSRRH = GPIO_Pin_5; PulseDelay();} | |
#define EPD_SPH_H() {GPIOA->BSRRL = GPIO_Pin_5; PulseDelay();} | |
//GATE DRIVER | |
#define EPD_GMODE1_L() {GPIOE->BSRRH = GPIO_Pin_3; PulseDelay();} | |
#define EPD_GMODE1_H() {GPIOE->BSRRL = GPIO_Pin_3; PulseDelay();} | |
#define EPD_GMODE2_L() {GPIOE->BSRRH = GPIO_Pin_2; PulseDelay();} | |
#define EPD_GMODE2_H() {GPIOE->BSRRL = GPIO_Pin_2; PulseDelay();} | |
#define EPD_XRL_L() {GPIOE->BSRRH = GPIO_Pin_4; PulseDelay();} | |
#define EPD_XRL_H() {GPIOE->BSRRL = GPIO_Pin_4; PulseDelay();} | |
#define EPD_SPV_L() {GPIOA->BSRRH = GPIO_Pin_6; PulseDelay();} | |
#define EPD_SPV_H() {GPIOA->BSRRL = GPIO_Pin_6; PulseDelay();} | |
#define EPD_CKV_L() {GPIOA->BSRRH = GPIO_Pin_7; PulseDelay();} | |
#define EPD_CKV_H() {GPIOA->BSRRL = GPIO_Pin_7; PulseDelay();} | |
#else | |
//SOURCE DRIVER | |
#define EPD_CL_L() {GPIOA->BRR = GPIO_PIN_8; PulseDelay();} | |
#define EPD_CL_H() {GPIOA->BSRR = GPIO_PIN_8; PulseDelay();} | |
#define EPD_LE_L() {GPIOA->BRR = GPIO_PIN_10; PulseDelay();} | |
#define EPD_LE_H() {GPIOA->BSRR = GPIO_PIN_10; PulseDelay();} | |
#define EPD_OE_L() {GPIOA->BRR = GPIO_PIN_9; PulseDelay();} | |
#define EPD_OE_H() {GPIOA->BSRR = GPIO_PIN_9; PulseDelay();} | |
//no shr | |
#define EPD_SPH_L() {GPIOA->BRR = GPIO_PIN_11; PulseDelay();} | |
#define EPD_SPH_H() {GPIOA->BSRR = GPIO_PIN_11; PulseDelay();} | |
//GATE DRIVER | |
#define EPD_GMODE1_L() {GPIOB->BRR = GPIO_PIN_10; PulseDelay();} | |
#define EPD_GMODE1_H() {GPIOB->BSRR = GPIO_PIN_10; PulseDelay();} | |
// no gmode2, no XRL | |
#define EPD_SPV_L() {GPIOB->BRR = GPIO_PIN_12; PulseDelay();} | |
#define EPD_SPV_H() {GPIOB->BSRR = GPIO_PIN_12; PulseDelay();} | |
#define EPD_CKV_L() {GPIOB->BRR = GPIO_PIN_11; PulseDelay();} | |
#define EPD_CKV_H() {GPIOB->BSRR = GPIO_PIN_11; PulseDelay();} | |
/* and because u8 seems undefined:*/ | |
typedef unsigned char u8; | |
#define ROTATE /* to swap X an Y */ | |
#endif | |
void EPD_Init(void); | |
void EPD_Power_Off(void); | |
void EPD_Power_On(void); | |
void EPD_Clear(void); | |
void EPD_PrepareWaveform(void); | |
void EPD_DispPic(); | |
void EPD_DispScr(unsigned int startLine, unsigned int lineCount); | |
void EPD_ClearFB(unsigned char c); | |
void EPD_SetPixel(unsigned short x,unsigned short y,unsigned char color); | |
void EPD_Line(unsigned short x0,unsigned short y0,unsigned short x1,unsigned short y1,unsigned short color); | |
void EPD_PutChar_16(unsigned short x, unsigned short y, unsigned short chr, unsigned char color); | |
void EPD_PutChar_Legacy(unsigned short x, unsigned short y, unsigned short chr, unsigned char color); | |
void EPD_String_16(unsigned short x,unsigned short y,unsigned char *s,unsigned char color); | |
void EPD_String_24(unsigned short x,unsigned short y,unsigned char *s,unsigned char color); | |
void EPD_FillRect(unsigned short x1,unsigned short y1,unsigned short x2,unsigned short y2,unsigned char color); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* USER CODE BEGIN Header */ | |
/** | |
****************************************************************************** | |
* @file : main.c | |
* @brief : Main program body | |
****************************************************************************** | |
* @attention | |
* | |
* <h2><center>© Copyright (c) 2020 STMicroelectronics. | |
* All rights reserved.</center></h2> | |
* | |
* This software component is licensed by ST under BSD 3-Clause license, | |
* the "License"; You may not use this file except in compliance with the | |
* License. You may obtain a copy of the License at: | |
* opensource.org/licenses/BSD-3-Clause | |
* | |
****************************************************************************** | |
*/ | |
/* USER CODE END Header */ | |
/* Includes ------------------------------------------------------------------*/ | |
#include "main.h" | |
/* Private includes ----------------------------------------------------------*/ | |
/* USER CODE BEGIN Includes */ | |
#include "epd.h" | |
#include "font.h" | |
/* USER CODE END Includes */ | |
/* Private typedef -----------------------------------------------------------*/ | |
/* USER CODE BEGIN PTD */ | |
/* USER CODE END PTD */ | |
/* Private define ------------------------------------------------------------*/ | |
/* USER CODE BEGIN PD */ | |
/* USER CODE END PD */ | |
/* Private macro -------------------------------------------------------------*/ | |
/* USER CODE BEGIN PM */ | |
/* USER CODE END PM */ | |
/* Private variables ---------------------------------------------------------*/ | |
ADC_HandleTypeDef hadc1; | |
TIM_HandleTypeDef htim1; | |
/* USER CODE BEGIN PV */ | |
/* USER CODE END PV */ | |
/* Private function prototypes -----------------------------------------------*/ | |
void SystemClock_Config(void); | |
static void MX_GPIO_Init(void); | |
static void MX_ADC1_Init(void); | |
static void MX_TIM1_Init(void); | |
/* USER CODE BEGIN PFP */ | |
/* USER CODE END PFP */ | |
/* Private user code ---------------------------------------------------------*/ | |
/* USER CODE BEGIN 0 */ | |
/* USER CODE END 0 */ | |
/** | |
* @brief The application entry point. | |
* @retval int | |
*/ | |
int main(void) | |
{ | |
/* USER CODE BEGIN 1 */ | |
/* USER CODE END 1 */ | |
/* MCU Configuration--------------------------------------------------------*/ | |
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */ | |
HAL_Init(); | |
/* USER CODE BEGIN Init */ | |
/* USER CODE END Init */ | |
/* Configure the system clock */ | |
SystemClock_Config(); | |
/* USER CODE BEGIN SysInit */ | |
/* USER CODE END SysInit */ | |
/* Initialize all configured peripherals */ | |
MX_GPIO_Init(); | |
MX_ADC1_Init(); | |
MX_TIM1_Init(); | |
/* USER CODE BEGIN 2 */ | |
/* USER CODE END 2 */ | |
/* Infinite loop */ | |
/* USER CODE BEGIN WHILE */ | |
EPD_Init(); | |
EPD_Power_On(); | |
EPD_Clear(); | |
EPD_String_24(0,0,"Hallo Wereld!",1); | |
EPD_String_24(0,30,"Hallo Lucas!",1); | |
EPD_DispScr(0,180);/* TODO: can not DispScr over the full screen yet due to lack of either more ram or a smarter buffer*/ | |
EPD_Power_Off(); | |
while (1) | |
{ | |
/* USER CODE END WHILE */ | |
/* USER CODE BEGIN 3 */ | |
// EPD_Power_On(); | |
// EPD_Clear(); | |
//EPD_Power_Off(); | |
} | |
while(0){ | |
static unsigned int x=0,y=50; | |
EPD_Power_On(); | |
EPD_SetPixel(x,y,1); | |
EPD_DispScr(0,200); | |
//HAL_Delay(1); | |
if(x<600) x++; else {x=0; y++;} | |
if(y>800) y=0; | |
} | |
/* USER CODE END 3 */ | |
} | |
/** | |
* @brief System Clock Configuration | |
* @retval None | |
*/ | |
void SystemClock_Config(void) | |
{ | |
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; | |
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; | |
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; | |
/** Initializes the CPU, AHB and APB busses clocks | |
*/ | |
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; | |
RCC_OscInitStruct.HSIState = RCC_HSI_ON; | |
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; | |
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; | |
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI_DIV2; | |
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL15; | |
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
/** Initializes the CPU, AHB and APB busses clocks | |
*/ | |
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK | |
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; | |
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; | |
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; | |
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; | |
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; | |
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; | |
PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; | |
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
} | |
/** | |
* @brief ADC1 Initialization Function | |
* @param None | |
* @retval None | |
*/ | |
static void MX_ADC1_Init(void) | |
{ | |
/* USER CODE BEGIN ADC1_Init 0 */ | |
/* USER CODE END ADC1_Init 0 */ | |
ADC_ChannelConfTypeDef sConfig = {0}; | |
/* USER CODE BEGIN ADC1_Init 1 */ | |
/* USER CODE END ADC1_Init 1 */ | |
/** Common config | |
*/ | |
hadc1.Instance = ADC1; | |
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; | |
hadc1.Init.ContinuousConvMode = DISABLE; | |
hadc1.Init.DiscontinuousConvMode = DISABLE; | |
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; | |
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; | |
hadc1.Init.NbrOfConversion = 1; | |
if (HAL_ADC_Init(&hadc1) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
/** Configure Regular Channel | |
*/ | |
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; | |
sConfig.Rank = ADC_REGULAR_RANK_1; | |
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5; | |
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
/* USER CODE BEGIN ADC1_Init 2 */ | |
/* USER CODE END ADC1_Init 2 */ | |
} | |
/** | |
* @brief TIM1 Initialization Function | |
* @param None | |
* @retval None | |
*/ | |
static void MX_TIM1_Init(void) | |
{ | |
/* USER CODE BEGIN TIM1_Init 0 */ | |
/* USER CODE END TIM1_Init 0 */ | |
TIM_ClockConfigTypeDef sClockSourceConfig = {0}; | |
TIM_MasterConfigTypeDef sMasterConfig = {0}; | |
/* USER CODE BEGIN TIM1_Init 1 */ | |
/* USER CODE END TIM1_Init 1 */ | |
htim1.Instance = TIM1; | |
htim1.Init.Prescaler = 35; | |
htim1.Init.CounterMode = TIM_COUNTERMODE_UP; | |
htim1.Init.Period = 0xFFFF; | |
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; | |
htim1.Init.RepetitionCounter = 0; | |
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; | |
if (HAL_TIM_Base_Init(&htim1) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; | |
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; | |
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; | |
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) | |
{ | |
Error_Handler(); | |
} | |
/* USER CODE BEGIN TIM1_Init 2 */ | |
/* USER CODE END TIM1_Init 2 */ | |
} | |
/** | |
* @brief GPIO Initialization Function | |
* @param None | |
* @retval None | |
*/ | |
static void MX_GPIO_Init(void) | |
{ | |
GPIO_InitTypeDef GPIO_InitStruct = {0}; | |
/* GPIO Ports Clock Enable */ | |
__HAL_RCC_GPIOC_CLK_ENABLE(); | |
__HAL_RCC_GPIOD_CLK_ENABLE(); | |
__HAL_RCC_GPIOA_CLK_ENABLE(); | |
__HAL_RCC_GPIOB_CLK_ENABLE(); | |
/*Configure GPIO pin Output Level */ | |
HAL_GPIO_WritePin(led_GPIO_Port, led_Pin, GPIO_PIN_RESET); | |
/*Configure GPIO pin Output Level */ | |
HAL_GPIO_WritePin(GPIOA, D0_Pin|D1_Pin|D2_Pin|D3_Pin | |
|D4_Pin|D5_Pin|D6_Pin|D7_Pin | |
|CL_Pin|OE_Pin|LE_Pin|SPH_Pin, GPIO_PIN_RESET); | |
/*Configure GPIO pin Output Level */ | |
HAL_GPIO_WritePin(GPIOB, VPOS_CTRL_Pin|VNEG_CTRL_Pin|GMODE_Pin|CKV_Pin | |
|SPV_Pin|PWR_CTRL_Pin, GPIO_PIN_RESET); | |
/*Configure GPIO pin : led_Pin */ | |
GPIO_InitStruct.Pin = led_Pin; | |
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; | |
GPIO_InitStruct.Pull = GPIO_NOPULL; | |
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
HAL_GPIO_Init(led_GPIO_Port, &GPIO_InitStruct); | |
/*Configure GPIO pins : PC14 PC15 */ | |
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_15; | |
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; | |
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); | |
/*Configure GPIO pins : PD0 PD1 */ | |
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; | |
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; | |
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); | |
/*Configure GPIO pins : D0_Pin D1_Pin D2_Pin D3_Pin | |
D4_Pin D5_Pin D6_Pin D7_Pin | |
CL_Pin OE_Pin LE_Pin SPH_Pin */ | |
GPIO_InitStruct.Pin = D0_Pin|D1_Pin|D2_Pin|D3_Pin | |
|D4_Pin|D5_Pin|D6_Pin|D7_Pin | |
|CL_Pin|OE_Pin|LE_Pin|SPH_Pin; | |
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; | |
GPIO_InitStruct.Pull = GPIO_NOPULL; | |
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); | |
/*Configure GPIO pins : VPOS_CTRL_Pin VNEG_CTRL_Pin GMODE_Pin CKV_Pin | |
SPV_Pin PWR_CTRL_Pin */ | |
GPIO_InitStruct.Pin = VPOS_CTRL_Pin|VNEG_CTRL_Pin|GMODE_Pin|CKV_Pin | |
|SPV_Pin|PWR_CTRL_Pin; | |
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; | |
GPIO_InitStruct.Pull = GPIO_NOPULL; | |
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; | |
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); | |
/*Configure GPIO pins : PB2 PB14 PB15 PB3 | |
PB4 PB5 PB6 PB7 | |
PB8 PB9 */ | |
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_3 | |
|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7 | |
|GPIO_PIN_8|GPIO_PIN_9; | |
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; | |
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); | |
/*Configure GPIO pins : PA12 PA15 */ | |
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_15; | |
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; | |
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); | |
/*Configure peripheral I/O remapping */ | |
__HAL_AFIO_REMAP_PD01_ENABLE(); | |
} | |
/* USER CODE BEGIN 4 */ | |
/* USER CODE END 4 */ | |
/** | |
* @brief This function is executed in case of error occurrence. | |
* @retval None | |
*/ | |
void Error_Handler(void) | |
{ | |
/* USER CODE BEGIN Error_Handler_Debug */ | |
/* User can add his own implementation to report the HAL error return state */ | |
/* USER CODE END Error_Handler_Debug */ | |
} | |
#ifdef USE_FULL_ASSERT | |
/** | |
* @brief Reports the name of the source file and the source line number | |
* where the assert_param error has occurred. | |
* @param file: pointer to the source file name | |
* @param line: assert_param error line source number | |
* @retval None | |
*/ | |
void assert_failed(uint8_t *file, uint32_t line) | |
{ | |
/* USER CODE BEGIN 6 */ | |
/* User can add his own implementation to report the file name and line number, | |
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ | |
/* USER CODE END 6 */ | |
} | |
#endif /* USE_FULL_ASSERT */ | |
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment