E-Ink ED060SC7 differs from ...SC4 (Swap X & Y). STM32F103 has less RAM, so only Proof of Concept.
[empty file, added to change gist title] |
/******************************************************************************* | |
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); | |
} | |
}*/ |
/******************************************************************************* | |
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 |
/* 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