element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Arduino Forum How to convert code for Driver IC IL0373 to Driver ID SSD1680
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Forum Thread Details
  • Replies 7 replies
  • Subscribers 388 subscribers
  • Views 1758 views
  • Users 0 members are here
  • driver
  • epaper
  • adafruit feather
  • nrf
  • segger embedded studio
Related

How to convert code for Driver IC IL0373 to Driver ID SSD1680

KKaushik
KKaushik over 2 years ago

I'm working on epaper display (based on SSD1680) with the nRF52840DK board.

I have a code sample from this link, but this code uses paper based on IL0373 IC.

Below is the code for paper.c 

#include "paper.h"

#include <string.h>

#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "nrf_drv_spi.h"

#define PAPER_RST_PIN 13
#define PAPER_DC_PIN  14

#define PAPER_SPI_INSTANCE 0
#define PAPER_SPI_SS_PIN   29
#define PAPER_SPI_MOSI_PIN 4
#define PAPER_SPI_SCK_PIN  3

#define PAPER_BYTE_WIDTH ((PAPER_PIXEL_WIDTH % 8 == 0) ? PAPER_PIXEL_WIDTH / 8 : PAPER_PIXEL_WIDTH / 8 + 1)
#define PAPER_BYTE_HEIGHT PAPER_PIXEL_HEIGHT
#define PAPER_BUFLEN PAPER_BYTE_WIDTH * PAPER_BYTE_HEIGHT

#define PAPER_CMD_PWR  0x01
#define PAPER_CMD_BTST 0x06
#define PAPER_CMD_PON  0x04
#define PAPER_CMD_PSR  0x00
#define PAPER_CMD_PLL  0x30
#define PAPER_CMD_TRES 0x61
#define PAPER_CMD_VDCD 0x82
#define PAPER_CMD_VCOM 0x50
#define PAPER_CMD_LUT_VCDC 0x20
#define PAPER_CMD_LUT_WW 0x21
#define PAPER_CMD_LUT_BW 0x22
#define PAPER_CMD_LUT_WB 0x23
#define PAPER_CMD_LUT_BB 0x24
#define PAPER_CMD_DISP 0x12

static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(PAPER_SPI_INSTANCE);

static uint8_t paper_cmd_pwr[] = {
  PAPER_CMD_PWR,
  0x03, 0x00, 0x2b, 0x2b, 0x03,
};

static uint8_t paper_cmd_btst[] = {
  PAPER_CMD_BTST,
  0x17, 0x17, 0x17,
};

static uint8_t paper_cmd_pon[] = {
  PAPER_CMD_PON,
};

static uint8_t paper_cmd_psr[] = {
  PAPER_CMD_PSR,
  0xbf, 0x0d,
};

static uint8_t paper_cmd_pll[] = {
  PAPER_CMD_PLL,
  0x3a,
};

static uint8_t paper_cmd_tres[] = {
  PAPER_CMD_TRES,
  PAPER_PIXEL_WIDTH,
  (PAPER_PIXEL_HEIGHT >> 8) & 0xff,
  PAPER_PIXEL_HEIGHT & 0xff,
};

static uint8_t paper_cmd_vdcd[] = {
  PAPER_CMD_VDCD,
  0x28,
};

static uint8_t paper_cmd_vcom[] = {
  PAPER_CMD_VCOM,
  0x97
};

static uint8_t paper_cmd_lut_vcdc[] = {
  PAPER_CMD_LUT_VCDC,
  0x00, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x60, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x00, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x00, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00,
};

static uint8_t paper_cmd_lut_ww[] = {
  PAPER_CMD_LUT_WW,
  0x40, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x40, 0x14, 0x00, 0x00, 0x00, 0x01,
  0xA0, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_bw[] = {
  PAPER_CMD_LUT_BW,
  0x40, 0x17, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x0F, 0x0F, 0x00, 0x00, 0x03,
  0x40, 0x0A, 0x01, 0x00, 0x00, 0x01,
  0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_wb[] = {
  PAPER_CMD_LUT_WB,
  0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_lut_bb[] = {
  PAPER_CMD_LUT_BB,
  0x80, 0x08, 0x00, 0x00, 0x00, 0x02,
  0x90, 0x28, 0x28, 0x00, 0x00, 0x01,
  0x80, 0x14, 0x00, 0x00, 0x00, 0x01,
  0x50, 0x12, 0x12, 0x00, 0x00, 0x01,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

static uint8_t paper_cmd_disp[] = {
  PAPER_CMD_DISP,
};

static uint8_t paper_buffer[PAPER_BUFLEN];
static uint8_t paper_prev_buffer[PAPER_BUFLEN];

static void paper_begin_command(void) {
  nrf_gpio_pin_clear(PAPER_DC_PIN);
}

static void paper_begin_data(void) {
  nrf_gpio_pin_set(PAPER_DC_PIN);
}

static ret_code_t paper_tx_cmd(uint8_t *cmd, uint8_t length) {
  ret_code_t ret;

  paper_begin_command();
  ret = nrf_drv_spi_transfer(&spi, cmd, 1, NULL, 0);
  if (ret != NRF_SUCCESS) return ret;

  if (length - 1 > 0) {
    paper_begin_data();
    ret = nrf_drv_spi_transfer(&spi, cmd + 1, length - 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  return ret;
}

static void paper_reset(void) {
  nrf_gpio_pin_clear(PAPER_RST_PIN);
  nrf_delay_ms(200);
  nrf_gpio_pin_set(PAPER_RST_PIN);
  nrf_delay_ms(200);
}

static ret_code_t paper_tx_lut(void) {
  ret_code_t ret;

  ret = paper_tx_cmd(paper_cmd_vcom, sizeof(paper_cmd_vcom));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_vcdc, sizeof(paper_cmd_lut_vcdc));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_ww, sizeof(paper_cmd_lut_ww));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_bw, sizeof(paper_cmd_lut_bw));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_wb, sizeof(paper_cmd_lut_wb));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_lut_bb, sizeof(paper_cmd_lut_bb));
  if (ret != NRF_SUCCESS) return ret;

  return ret;
}

static ret_code_t _paper_display(void) {
  ret_code_t ret;

  /*
   * TODO transfer chunks of 256 bytes rather than calling nrf_drv_spi_transfer
   * for each byte.
   */

  uint8_t command[1];

  command[0] = 0x10;
  ret = paper_tx_cmd(command, 1);
  if (ret != NRF_SUCCESS) return ret;

  paper_begin_data();
  for (int i = 0; i < PAPER_BUFLEN; i++) {
    ret = nrf_drv_spi_transfer(&spi, paper_prev_buffer + i, 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  nrf_delay_ms(10);

  /*
   * TODO i'm not yet sure about the purpose of sending the previous buffer too.
   * just sending 0x00s works pretty good. when sending the actual previous
   * image buffer, it looks like sections that have not changed become kinda
   * dirty / greyish (which could be useful because one can use three colors).
   */

  // memcpy(paper_prev_buffer, paper_buffer, PAPER_BUFLEN);

  command[0] = 0x13;
  ret = paper_tx_cmd(command, 1);
  if (ret != NRF_SUCCESS) return ret;

  paper_begin_data();
  for (int i = 0; i < PAPER_BUFLEN; i++) {
    ret = nrf_drv_spi_transfer(&spi, paper_buffer + i, 1, NULL, 0);
    if (ret != NRF_SUCCESS) return ret;
  }

  nrf_delay_ms(10);

  ret = paper_tx_lut();
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_disp, sizeof(paper_cmd_disp));
  if (ret != NRF_SUCCESS) return ret;

  nrf_delay_ms(100); // TODO use busy pin rather than arbitrary delays

  return ret;
}

ret_code_t paper_init(void) {
  ret_code_t ret;

  nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
  spi_config.ss_pin   = PAPER_SPI_SS_PIN;
  spi_config.mosi_pin = PAPER_SPI_MOSI_PIN;
  spi_config.sck_pin  = PAPER_SPI_SCK_PIN;

  ret = nrf_drv_spi_init(&spi, &spi_config, NULL, NULL);
  if (ret != NRF_SUCCESS) return ret;

  nrf_gpio_cfg_output(PAPER_RST_PIN);
  nrf_gpio_cfg_output(PAPER_DC_PIN);

  paper_reset();

  ret = paper_tx_cmd(paper_cmd_pwr, sizeof(paper_cmd_pwr));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_btst, sizeof(paper_cmd_btst));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_pon, sizeof(paper_cmd_pon));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_psr, sizeof(paper_cmd_psr));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_pll, sizeof(paper_cmd_pll));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_tres, sizeof(paper_cmd_tres));
  if (ret != NRF_SUCCESS) return ret;

  ret = paper_tx_cmd(paper_cmd_vdcd, sizeof(paper_cmd_vdcd));
  if (ret != NRF_SUCCESS) return ret;

  memset(paper_buffer, 0xff, PAPER_BUFLEN);
  memset(paper_prev_buffer, 0x00, PAPER_BUFLEN);

  return ret;
}

void paper_uninit(void) {
  // TODO uninit spi and free buffers
}

void paper_pixel_draw(uint16_t x, uint16_t y, uint32_t color) {
  ASSERT(x < PAPER_PIXEL_WIDTH);
  ASSERT(y < PAPER_PIXEL_HEIGHT);

  int bitn = y * PAPER_PIXEL_WIDTH + x;
  int byten = bitn / 8;
  bitn = 8 - bitn % 8 - 1;

  if (color == 0) paper_buffer[byten] |= 1UL << (bitn);
  else paper_buffer[byten] &= ~(1UL << (bitn));
}

void paper_rect_draw(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t color) {
  ASSERT(x + width < PAPER_PIXEL_WIDTH);
  ASSERT(y + height < PAPER_PIXEL_HEIGHT);

  for (uint16_t _x = x; _x < x + width; _x++)
    for (uint16_t _y = y; _y < y + height; _y++)
      paper_pixel_draw(_x, _y, color);
}

void paper_display(void) {
  APP_ERROR_CHECK(_paper_display());
}

void paper_rotation_set(nrf_lcd_rotation_t rotation) {
  UNUSED_PARAMETER(rotation);

  // TODO
}

void paper_display_invert(bool invert) {
  UNUSED_PARAMETER(invert);

  // TODO
}

I have used adafruit library from this link and successfully worked using SSD1680

I want to know how can I convert the paper.c code to use SSD1680 from the adafruit library instead of IL0373 driver

  • Sign in to reply
  • Cancel

Top Replies

  • shabaz
    shabaz over 2 years ago +3
    Hi, I think you wish to use an Adafruit library on a non-Adafruit board, is that correct? If so, the approach that you mention (converting the paper.c driver) is not needed. Adafruit libraries are already…
  • shabaz
    shabaz over 2 years ago in reply to KKaushik +1
    Hi Kaushik, Replying here because others may be able to help if they can see it: Regarding the message: Hello, I have been following your given code, for the paper display. I have changed only…
  • shabaz
    shabaz over 2 years ago in reply to KKaushik +1
    Hi, The code definitely works (it was confirmed by several people in the comments at Experimenting with E-Paper Displays: Building a Clock! ) so if it is not functioning for you, it may be one of these…
Parents
  • shabaz
    shabaz over 2 years ago

    Hi,

    I think you wish to use an Adafruit library on a non-Adafruit board, is that correct? If so, the approach that you mention (converting the paper.c driver) is not needed. Adafruit libraries are already C code, that can be used with any microcontroller (pretty much). You don't need the paper.c code at all (well, you could use the line or rectangle drawing routines from it if desired, but nothing much else).

    If you wish to use as much of the Adafruit code as possible, then the thing that needs to be done is to _port_ the Adafruit library, rather than try to convert the driver for a completely different chip (i.e. your paper.c file is effectively a driver of sorts, just visually examining it). There's no special technique however. The Adafruit code will need to be manually inspected, and modified to suit your new microcontroller environment. 

    Personally, if it were me (I have done this for a different e-paper display, so I know it is feasible), I'd take the constant arrays from the known working code (i.e. the Adafruit code), and then just write the rest of the code from scratch, following both the datasheet (if available) as well as the Adafruit code. There's not a lot of code to write, since the controllers inside these displays do not expect much communication. They do however expect the correct initializing data, hence the need to use the constant arrays from the known working code.

    Finally, one other approach is to simply google around for a driver that will suit your microcontroller. For example, my code might work for you:  Experimenting with E-Paper Displays: Building a Clock! 

    I believe it is for a display that uses the same chip, i.e. SSD1680 (but I'm only 90% sure). It was specifically written in C (not C++) without any reliance on other libraries, so that it would be easy to port to any microcontroller. However it is a 6-year-old blog post, so I can't recall much.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • Cancel
  • KKaushik
    KKaushik over 2 years ago in reply to shabaz

    Thanks a lot for your reply, I'll try the code you have given. But one more thing I wanted to confirm

    shabaz said:
    Adafruit libraries are already C code, that can be used with any microcontroller (pretty much). You don't need the paper.c code at all

    When I checked the libraries used in SSD1680.c, I ended up with Arduino.h and SPI.h. So I thought those are related to Arduino-compatible boards.

    And SPI.h is used in SSD1680.c are related to Arduino too not the nRF52840DK board.

    Adafruit_SSD1680.c  > Adafruit_EPD.h > Adafruit_GFX.h > Arduino.h

    So I am not sure if I can use Arduino.h to nRF52840Dk Projects, as I going to need to include all these sub-libraries to include the folder of the project.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
  • shabaz
    shabaz over 2 years ago in reply to KKaushik

    This is part of the porting exercise, i.e. visually inspecting any included files content (doesn't matter if it is called Arduino.h or not, you still need to inspect what gets included from it). Otherwise, you could try to use code (e.g. the code I wrote) that isn't dependent on other libraries or header files, if you have difficulty porting the Arduino version.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • shabaz
    shabaz over 2 years ago in reply to KKaushik

    This is part of the porting exercise, i.e. visually inspecting any included files content (doesn't matter if it is called Arduino.h or not, you still need to inspect what gets included from it). Otherwise, you could try to use code (e.g. the code I wrote) that isn't dependent on other libraries or header files, if you have difficulty porting the Arduino version.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Cancel
Children
No Data
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube