EPD

Dependencies:   mbed-STM32F103C8T6 mbed

main.cpp

Committer:
spin7ion
Date:
2017-12-29
Revision:
0:1d2c0afef43c

File content as of revision 0:1d2c0afef43c:

#include "stm32f103c8t6.h"
#include "mbed.h"
#include "epd.h"
 
DigitalOut  myled1(LED1);

DigitalOut  edp_reset(PB_0);
DigitalOut  edp_dataCommand(PB_10);
DigitalOut  edp_chipSelect(PA_4);
DigitalIn   edp_busy(PB_11);
SPI spi(PA_7,PA_6,PA_5); // mosi, miso, sclk, ss
//DigitalOut eink(PB_0);
/*
EaEpaper epaper(NC,             // PWR_CTRL
                NC,            // BORDER
                PB_10,            // DISCHARGE
                PB_0,            // RESET_DISP
                PB_11,            // BUSY
                PA_4,             // SSEL
                NC,            // PWM
                PA_7,PA_6,PA_5,       // MOSI,MISO,SCLK
                "eink");       // SDA,SCL */
 
void EPD_SendCommand(unsigned char data) {
    edp_chipSelect=0;
    edp_dataCommand=0;
    spi.write(data);
    edp_chipSelect=1;
}

void EPD_SendData(unsigned char data) {
    edp_chipSelect=0;
    edp_dataCommand=1;
    spi.write(data);
    edp_chipSelect=1;
}
 
void EPD_Reset() {
  edp_reset=0;
  wait_ms(200);
  edp_reset=1;
  wait_ms(200);
}
 
void EPD_WaitUntilIdle() {
  while(edp_busy == 1) {      //0: busy, 1: idle
    wait_ms(100);
  }      
} 

/**
 *  @brief: private function to specify the memory area for data R/W
 */
static void EPD_SetMemoryArea(int x_start, int y_start, int x_end, int y_end) {
  EPD_SendCommand(SET_RAM_X_ADDRESS_START_END_POSITION);
  /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  EPD_SendData((x_start >> 3) & 0xFF);
  EPD_SendData((x_end >> 3) & 0xFF);
  EPD_SendCommand(SET_RAM_Y_ADDRESS_START_END_POSITION);
  EPD_SendData(y_start & 0xFF);
  EPD_SendData((y_start >> 8) & 0xFF);
  EPD_SendData(y_end & 0xFF);
  EPD_SendData((y_end >> 8) & 0xFF);
}

/**
 *  @brief: private function to specify the start point for data R/W
 */
static void EPD_SetMemoryPointer(int x, int y) {
  EPD_SendCommand(SET_RAM_X_ADDRESS_COUNTER);
  /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  EPD_SendData((x >> 3) & 0xFF);
  EPD_SendCommand(SET_RAM_Y_ADDRESS_COUNTER);
  EPD_SendData(y & 0xFF);
  EPD_SendData((y >> 8) & 0xFF);
  EPD_WaitUntilIdle();
}

void EPD_SetLut(const unsigned char* lut) {
  EPD_SendCommand(WRITE_LUT_REGISTER);
  /* the length of look-up table is 30 bytes */
  for (int i = 0; i < 30; i++) {
    EPD_SendData(lut[i]);
  } 
}
 
int EPD_Init() {
  EPD_Reset();
  EPD_SendCommand(DRIVER_OUTPUT_CONTROL);
  EPD_SendData((EPD_HEIGHT - 1) & 0xFF);
  EPD_SendData(((EPD_HEIGHT - 1) >> 8) & 0xFF);
  EPD_SendData(0x00);                     // GD = 0; SM = 0; TB = 0;
  EPD_SendCommand(BOOSTER_SOFT_START_CONTROL);
  EPD_SendData(0xD7);
  EPD_SendData(0xD6);
  EPD_SendData(0x9D);
  EPD_SendCommand(WRITE_VCOM_REGISTER);
  EPD_SendData(0xA8);                     // VCOM 7C
  EPD_SendCommand(SET_DUMMY_LINE_PERIOD);
  EPD_SendData(0x1A);                     // 4 dummy lines per gate
  EPD_SendCommand(SET_GATE_TIME);
  EPD_SendData(0x08);                     // 2us per line
  EPD_SendCommand(DATA_ENTRY_MODE_SETTING);
  EPD_SendData(0x03);                     // X increment; Y increment
  EPD_SetLut(lut_full_update);
  //EPD_SetLut(lut_partial_update);
  /* EPD hardware init end */
  return 0;
}

/**
 *  @brief: put an image buffer to the frame memory.
 *          this won't update the display.
 */
void EPD_SetFrameMemory(
  const unsigned char* image_buffer,
  int x,
  int y,
  int image_width,
  int image_height
) {
  int x_end;
  int y_end;

  if (
    image_buffer == NULL ||
    x < 0 || image_width < 0 ||
    y < 0 || image_height < 0
  ) {
    return;
  }
  /* x point must be the multiple of 8 or the last 3 bits will be ignored */
  x &= 0xF8;
  image_width &= 0xF8;
  if (x + image_width >= EPD_WIDTH) {
    x_end = EPD_WIDTH - 1;
  } else {
    x_end = x + image_width - 1;
  }
  if (y + image_height >= EPD_HEIGHT) {
    y_end = EPD_HEIGHT - 1;
  } else {
    y_end = y + image_height - 1;
  }
  EPD_SetMemoryArea(x, y, x_end, y_end);
  EPD_SetMemoryPointer(x, y);
  EPD_SendCommand(WRITE_RAM);
  /* send the image data */
  for (int j = 0; j < y_end - y + 1; j++) {
    for (int i = 0; i < (x_end - x + 1) / 8; i++) {
      EPD_SendData(image_buffer[i + j * (image_width / 8)]);
    }
  }
}

/**
*  @brief: clear the frame memory with the specified color.
*          this won't update the display.
*/
void EPD_ClearFrameMemory(unsigned char color) {
  EPD_SetMemoryArea(0, 0, EPD_WIDTH - 1, EPD_HEIGHT - 1);
  EPD_SetMemoryPointer(0, 0);
  EPD_SendCommand(WRITE_RAM);
  /* send the color data */
  for (int i = 0; i < EPD_WIDTH / 8 * EPD_HEIGHT; i++) {
    EPD_SendData(color);
  }
}

/**
*  @brief: update the display
*          there are 2 memory areas embedded in the e-paper display
*          but once this function is called,
*          the the next action of SetFrameMemory or ClearFrame will 
*          set the other memory area.
*/
void EPD_DisplayFrame() {
  EPD_SendCommand(DISPLAY_UPDATE_CONTROL_2);
  EPD_SendData(0xC4);
  EPD_SendCommand(MASTER_ACTIVATION);
  EPD_SendCommand(TERMINATE_FRAME_READ_WRITE);
  EPD_WaitUntilIdle();
}

/**
 *  @brief: After this command is transmitted, the chip would enter the 
 *          deep-sleep mode to save power. 
 *          The deep sleep mode would return to standby by hardware reset. 
 *          You can use EPD_Init() to awaken
 */
void EPD_Sleep() {
  EPD_SendCommand(DEEP_SLEEP_MODE);
  EPD_WaitUntilIdle();
}

void setChar(char chr, int x, int y, unsigned char color){
  unsigned char arr[8];
  memcpy(arr, (unsigned char*)&(FONT8x8[chr - 0x1F][0]), 8);
  
  if(color==0){
    for(int i=0;i<8;i++){
        arr[i]=~arr[i];
    }    
  }
  
  EPD_SetFrameMemory(arr,x,y,8,8);
}

void setString(char *str, int len, int x, int y, unsigned char color){
    for (int i=0;i<len;i++) {
        if(str[i]=='\n' && i<len-1){y+=8;i++;x-=i*8;}
        setChar(str[i], x+i*8, y, color);
    }
}
 
int main() {
    confSysClock(); 
    spi.format(8,0);
    spi.frequency(4000000);         
    
    EPD_Init();
    
    //EPD_ClearFrameMemory(BACKGROUND_WHITE);
    //EPD_DisplayFrame();
    setString("Alexander\nSemion",16,0,0,0);
    EPD_DisplayFrame();
    /*unsigned char arr[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['S' - 0x1F][0]),0,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['P' - 0x1F][0]),8,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['I' - 0x1F][0]),16,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['N' - 0x1F][0]),24,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['7' - 0x1F][0]),32,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['I' - 0x1F][0]),40,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['O' - 0x1F][0]),48,0,8,8);
    EPD_SetFrameMemory((unsigned char*)&(FONT8x8['N' - 0x1F][0]),56,0,8,8);
    EPD_DisplayFrame();*/
    /*
    while(1){ 
        myled1 = 1;
        wait_ms(1000);
        myled1 = 0;
        wait_ms(1000);
    }*/
}