Skip to content

Instantly share code, notes, and snippets.

@Lukelectro
Last active July 18, 2020 19:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lukelectro/29857324e392116e9f2726e1025e3ae2 to your computer and use it in GitHub Desktop.
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.
[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>&copy; 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