Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: SDFileSystem app epson mbed msp430 pl tests
Diff: eink.cpp
- Revision:
- 0:c643d398cdb6
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/eink.cpp Thu Jan 11 13:42:27 2018 +0000
@@ -0,0 +1,684 @@
+//
+// Filename: eink.cpp
+//
+// Flexbook eInk display driver.
+//
+
+#include "eink.h"
+
+#include "mbed.h"
+
+#include "ChaN/ff.h"
+
+#include "log.h"
+#include "page.h"
+
+#include "pmic-tps65185.h"
+#include "vcom.h"
+
+#include <sstream>
+
+const int MAX_INIT_FAILS = 3;
+
+SPI *spi = 0;
+
+#define I2C_PMIC_ADDR_TPS65185 0x68
+
+struct tps65185_info pmic_info;
+
+const char *g_wflib_fatfs_path = "/waveform.dat";
+
+extern "C"
+{
+ // EPSON drivers.
+ #include "epson/epson-epdc.h"
+ #include "epson/epson-s1d135xx.h"
+
+ // Plastic Logic drivers.
+ #include "pl/epdc.h"
+ #include "pl/dispinfo.h"
+ #include "pl/platform.h"
+ #include "pl/types.h"
+
+ #include "wflib.h"
+
+void mdelay(uint16_t ms)
+{
+ wait_ms(ms);
+}
+
+void msleep(uint16_t ms)
+{
+ mdelay(ms);
+}
+
+#define EPSON_RESET p16
+#define EPSON_CS_0 p14
+#define EPSON_HIRQ p15
+#define EPSON_HRDY ~0U
+#define EPSON_HDC p24
+#define EPSON_CLK_EN 1002
+#define EPSON_VCC_EN 1003
+
+enum
+{
+ HVSW_CTRL = p17, /* VCOM switch enable */
+ PMIC_EN = p18, /* HV-PMIC enable */
+ PMIC_POK = p23, /* HV-PMIC power OK */
+ PMIC_FLT = 1006 /* HV-PMIC fault condition */
+};
+
+static const struct s1d135xx_data g_s1d135xx_data =
+{
+ EPSON_RESET,
+ EPSON_CS_0,
+ EPSON_HIRQ,
+ EPSON_HRDY,
+ EPSON_HDC,
+ EPSON_CLK_EN,
+ EPSON_VCC_EN
+};
+
+void printgpio(unsigned int gpio)
+{
+ switch(gpio)
+ {
+ case EPSON_RESET:
+ printf("EPSON_RESET");
+ break;
+
+ case EPSON_CS_0:
+ printf("EPSON_CS_0");
+ break;
+
+ case EPSON_HIRQ:
+ printf("EPSON_HIRQ");
+ break;
+
+ case EPSON_HRDY:
+ printf("EPSON_HRDY");
+ break;
+
+ case EPSON_HDC:
+ printf("EPSON_HDC");
+ break;
+
+ case EPSON_CLK_EN:
+ printf("EPSON_CLK_EN");
+ break;
+
+ case EPSON_VCC_EN:
+ printf("EPSON_VCC_EN");
+ break;
+
+ case HVSW_CTRL:
+ printf("HVSW_CTRL");
+ break;
+
+ case PMIC_EN:
+ printf("PMIC_EN");
+ break;
+
+ case PMIC_POK:
+ printf("PMIC_POK");
+ break;
+
+ default:
+ printf("Unknown GPIO: %u", gpio);
+ break;
+ }
+}
+
+//#define LOG_GPIO
+
+extern int msp430_gpio_get(unsigned gpio)
+{
+#ifdef LOG_GPIO
+ printf("msp430_gpio_get(");
+ printgpio(gpio);
+ printf(")\n");
+#endif // LOG_GPIO
+
+ int value = 0;
+ if(gpio != EPSON_CLK_EN && gpio != EPSON_VCC_EN)
+ {
+ DigitalIn gpiopin((PinName) gpio);
+ value = gpiopin;
+ } else {
+#ifdef LOG_GPIO
+ printf("unused GPIO, ignored\n");
+#endif // LOG_GPIO
+ }
+
+ return value;
+}
+
+extern void msp430_gpio_set(unsigned gpio, int value)
+{
+#ifdef LOG_GPIO
+ printf("msp430_gpio_set(");
+ printgpio(gpio);
+ printf(", %d)\n", value);
+#endif // LOG_GPIO
+
+ if(gpio != EPSON_CLK_EN && gpio != EPSON_VCC_EN)
+ {
+ DigitalOut gpiopin((PinName) gpio);
+ gpiopin = value;
+ } else {
+#ifdef LOG_GPIO
+ printf("unused GPIO, ignored\n");
+#endif // LOG_GPIO
+ }
+}
+
+int _swap_bytes(int bytes)
+{
+ uint16_t ubytes = bytes;
+ ubytes = (ubytes << 8) + (ubytes >> 8);
+ return ubytes;
+}
+
+int parser_read_file_line(FIL *f, char *buffer, int max_length)
+{
+ Log("parser_read_file_line not implemented, returning FR_OK");
+ return 0;
+}
+
+int parser_read_word(const char *str, const char *sep, unsigned int *out)
+{
+ Log("parser_read_word not implemented, returning 0");
+ return 0;
+}
+
+//#define LOG_SPI
+
+void spi_read_bytes(uint8_t *buff, size_t size)
+{
+#ifdef LOG_SPI
+ printf("spi_read_bytes(");
+#endif // LOG_SPI
+ for(size_t i = 0; i < size; i++)
+ {
+ buff[i] = spi->write(0);
+
+#ifdef LOG_SPI
+ int buffint = buff[i];
+ printf("%02x", buffint);
+#endif // LOG_SPI
+ }
+
+#ifdef LOG_SPI
+ int sizeint = size;
+ printf(", %02x)\n", sizeint);
+#endif // LOG_SPI
+}
+
+void spi_write_bytes(uint8_t *buff, size_t size)
+{
+#ifdef LOG_SPI
+ int sizeint = size;
+ printf("spi_write_bytes(");
+ for(size_t i = 0; i < size; i++)
+ {
+ int buffint = buff[i];
+ printf("%02x", buffint);
+ }
+ printf(", %02x)\n", sizeint);
+#endif // LOG_SPI
+
+ if(spi)
+ {
+ for(size_t i = 0; i < size; i++)
+ {
+ spi->write(buff[i]);
+ }
+
+ } else {
+
+ printf("ERROR: SPI not set!!!\n");
+ }
+}
+
+} // End '"C" linking.
+
+struct pl_platform g_plat;
+
+struct pl_dispinfo g_dispinfo;
+
+void WriteColour(pl_epdc &epdc, uint8_t colour)
+{
+ if(epdc.fill(&epdc, NULL, colour))
+ Log("fill failed");
+
+ if(epdc.clear_init(&epdc))
+ Log("clear_init fail");
+
+ if(g_plat.psu.on(&g_plat.psu))
+ Log("PSU on fail");
+
+ int wfid = pl_epdc_get_wfid(&epdc, wf_refresh);
+ if (wfid < 0)
+ Log("Bad wfid");
+
+ if(epdc.update(&epdc, wfid, NULL))
+ Log("update failed");
+
+ if(epdc.wait_update_end(&epdc))
+ Log("wait update end failed");
+
+ if(g_plat.psu.off(&g_plat.psu))
+ Log("PSU off fail");
+}
+
+void WritePicture(pl_epdc &epdc, const char *file)
+{
+//#ifdef VERBOSE
+ Log("WritePicture");
+//#endif
+
+ if(g_plat.epdc.load_image(&g_plat.epdc, file, NULL, 0, 0))
+ Log("Image load failed");
+ else Log("Image loaded");
+ if(g_plat.psu.on(&g_plat.psu))
+ Log("PSU on fail");
+ else Log ("PSU on");
+ int wfid = pl_epdc_get_wfid(&epdc, wf_refresh);
+ if (wfid < 0)
+ Log("Bad wfid");
+ else Log("Good wfid");
+
+ if(g_plat.epdc.update(&g_plat.epdc, wfid, NULL))
+ Log("update failed");
+ else Log("update succeeded");
+
+ if(epdc.wait_update_end(&epdc))
+ Log("wait update end failed");
+ else Log("wait update end succeeded");
+
+ if(g_plat.psu.off(&g_plat.psu))
+ Log("PSU off fail");
+ else Log("PSU off");
+}
+
+void WriteImage(const char *file)
+{
+#ifdef VERBOSE
+ Log("WritePicture");
+#endif
+
+ if(g_plat.epdc.load_image(&g_plat.epdc, file, NULL, 0, 0))
+ Log("Image load failed");
+}
+
+void WritePartImage(const char *file, int xd, int yd, int xi, int yi, int w, int h)
+{
+#ifdef VERBOSE
+ Log("WritePartImage");
+#endif
+
+ pl_area area;
+
+ area.left = xd;
+ area.top = yd;
+ area.width = w;
+ area.height = h;
+
+ if(g_plat.epdc.load_image(&g_plat.epdc, file, &area, xi, yi))
+ Log("Image load failed");
+}
+
+void UpdateDisplay()
+{
+#ifdef VERBOSE
+ Log("UpdateDisplay");
+#endif
+
+ if(g_plat.psu.on(&g_plat.psu))
+ Log("PSU on fail");
+
+ int wfid = pl_epdc_get_wfid(&g_plat.epdc, wf_refresh);
+ if (wfid < 0)
+ Log("Bad wfid");
+
+ if(g_plat.epdc.update(&g_plat.epdc, wfid, NULL))
+ Log("update failed");
+
+ if(g_plat.epdc.wait_update_end(&g_plat.epdc))
+ Log("wait update end failed");
+
+ if(g_plat.psu.off(&g_plat.psu))
+ Log("PSU off fail");
+}
+
+int pl_i2c_reg_read_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg, uint8_t *data);
+
+int pl_i2c_reg_write_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg, uint8_t data);
+
+void pl_hwinfo_log(const struct pl_hwinfo *info)
+{
+#if VERBOSE
+ const struct pl_hw_vcom_info *vcom = &info->vcom;
+#endif
+ const struct pl_hw_board_info *board = &info->board;
+
+#if VERBOSE
+ printf("Version: %d\n", info->version);
+ printf("VCOM DAC info: dac[%d]=%d, dac[%d]=%d\n",
+ vcom->dac_x1, vcom->dac_y1, vcom->dac_x2, vcom->dac_y2);
+ printf("Gate PSU info: VGPOS=%ld, VGNEG=%ld, swing=%ld\n",
+ vcom->vgpos_mv, vcom->vgneg_mv, vcom->swing_ideal);
+#endif
+ printf("Board type: %s, version: %d.%d\n",
+ board->board_type, board->board_ver_maj, board->board_ver_min);
+#if VERBOSE
+ printf("vcom_mode=%d, hv_pmic=%d, vcom_dac=%d, vcom_adc=%d\n",
+ board->vcom_mode, board->hv_pmic, board->vcom_dac, board->vcom_adc);
+ printf("io_config=%d, i2c_mode=%d, temp_sensor=%d, frame_buffer=%d\n",
+ board->io_config, board->i2c_mode, board->temp_sensor,
+ board->frame_buffer);
+ printf("epdc_ref=%d, adc_scale_1=%d, adc_scale_2=%d\n",
+ board->epdc_ref, board->adc_scale_1, board->adc_scale_2);
+ printf("CRC16: %04X\n", info->crc);
+#endif
+}
+
+#define CONFIG_DEFAULT_I2C_MODE I2C_MODE_HOST
+#define BOARD_MAJ 6
+#define BOARD_MIN 3
+
+static const struct pl_hwinfo g_hwinfo_default = {
+ /* version */
+ PL_HWINFO_VERSION,
+ /* vcom */
+ { 127, 4172, 381, 12490, 25080, -32300, 56886 },
+ /* board */
+ { "HB", BOARD_MAJ, BOARD_MIN, 0, HV_PMIC_TPS65185, 0, 0, 0,
+ CONFIG_DEFAULT_I2C_MODE, TEMP_SENSOR_NONE, 0, EPDC_S1D13541, 1, 1 },
+ /* CRC16 (not used when not reading from actual EEPROM) */
+ 0xFFFF,
+};
+
+FIL g_wflib_fatfs_file;
+
+static struct pl_epdpsu_gpio g_epdpsu_gpio = {
+ &g_plat.gpio, PMIC_EN, HVSW_CTRL, PMIC_POK, PMIC_FLT, 300, 5, 100
+};
+
+struct vcom_cal vcom_cal;
+
+pl_epdc &Get_epdc()
+{
+ return g_plat.epdc;
+}
+
+std::ostream &operator<<(std::ostream &s, pl_gpio &gpio)
+{
+ s << "pl_gpio\n";
+
+ s << gpio.config << "\n";
+ s << gpio.get << "\n";
+ s << gpio.set << "\n";
+
+ return s;
+}
+
+std::ostream &operator<<(std::ostream &s, pl_epdpsu &epdpsu)
+{
+ s << "pl_epdpsu\n";
+
+ s << epdpsu.on << "\n";
+ s << epdpsu.off << "\n";
+ s << epdpsu.state << "\n";
+ s << epdpsu.data << "\n";
+
+ return s;
+};
+
+std::ostream &operator<<(std::ostream &s, pl_epdc &epdc)
+{
+ s << "pl_epdc\n";
+
+ s << epdc.clear_init << "\n";
+ s << epdc.load_wflib << "\n";
+ s << epdc.update << "\n";
+ s << epdc.wait_update_end << "\n";
+ s << epdc.set_power << "\n";
+ s << epdc.set_temp_mode << "\n";
+ s << epdc.update_temp << "\n";
+ s << epdc.fill << "\n";
+ s << epdc.pattern_check << "\n";
+ s << epdc.load_image << "\n";
+ s << epdc.set_epd_power << "\n";
+
+ s << epdc.wf_table << "\n";
+ s << epdc.dispinfo << "\n";
+ //struct pl_wflib wflib << "\n";
+ s << epdc.power_state << "\n";
+ s << epdc.temp_mode << "\n";
+ s << epdc.manual_temp << "\n";
+ s << epdc.xres << "\n";
+ s << epdc.yres << "\n";
+ s << epdc.data << "\n";
+
+ return s;
+};
+
+std::ostream &operator<<(std::ostream &s, pl_platform &g_plat)
+{
+ s << "pl_platform\n";
+
+ s << g_plat.gpio << "\n";
+ s << g_plat.psu << "\n";
+ s << g_plat.epdc << "\n";
+ s << g_plat.i2c << "\n";
+ s << g_plat.sys_gpio << "\n";
+ s << g_plat.hwinfo << "\n";
+ s << g_plat.dispinfo << "\n";
+
+ return s;
+}
+
+void DisplayHardwareSettings()
+{
+ pl_hwinfo_log(g_plat.hwinfo);
+
+#ifdef VERBOSE
+ printf("Hardware information start\n"):
+ std::ostringstream info;
+ info << g_plat << "\n";
+ printf(info.str().c_str());
+
+ printf("Hardware information end\n");
+#endif // VERBOSE
+}
+
+// Configure the EPSON controller settings.
+s1d135xx driver = { &g_s1d135xx_data, NULL };
+
+
+void InitDisplay(I2C &i2c, SPI &spi_in, DigitalOut &spics, DigitalOut &hven, DigitalOut &rst, DigitalIn &hvpok)
+{
+ spi = &spi_in;
+
+ spi->frequency(1000000);
+ spi->format(8, 0);
+
+ rst = 0;
+ hven = 0;
+ spics = 1;
+
+ // Initialise the platform settings.
+ g_plat.i2c = NULL;
+ g_plat.sys_gpio = NULL;
+ g_plat.hwinfo = &g_hwinfo_default;
+ g_plat.dispinfo = &g_dispinfo;
+
+ g_plat.psu.on = NULL;
+ g_plat.psu.off = NULL;
+ g_plat.psu.state = 0;
+ g_plat.psu.data = NULL;
+
+ // Use a 100Khz I2c clock (the PMIC limits are 100-400KHz).
+ i2c.frequency(100000);
+
+ // COnfigure the VCOM settings.
+ g_dispinfo.info.vcom = 5124; // Note hardcoded VCOM
+
+ int fails = 0;
+ int initfailed = -1;
+ while(initfailed && fails < MAX_INIT_FAILS)
+ {
+ // Enable the TPS65185 PMIC.
+ // The I2C is now enabled.
+ hven = 1;
+ wait(0.2);
+
+ // Hard reset the Epson controller.
+ rst = 0;
+ mdelay(4);
+ rst = 1;
+ mdelay(10);
+
+ // Load the display information.
+ initfailed = pl_wflib_init_fatfs(&g_plat.epdc.wflib, (int *) &g_wflib_fatfs_file, g_wflib_fatfs_path);
+ if(initfailed != 0)
+ {
+ Log("Failed to load display info");
+ fails++;
+
+ } else {
+
+ pl_epdpsu_gpio_init(&g_plat.psu, &g_epdpsu_gpio);
+ vcom_init(&vcom_cal, &g_plat.hwinfo->vcom);
+ initfailed = tps65185_init(&pmic_info, i2c, I2C_PMIC_ADDR_TPS65185, &vcom_cal);
+ if(initfailed != 0)
+ {
+ Log("Error initalizing TPS65185");
+ fails++;
+
+ } else {
+
+ initfailed = tps65185_set_vcom_voltage(&pmic_info, g_plat.dispinfo->info.vcom);
+ if(initfailed != 0)
+ {
+ Log("Error initalizing VCOM");
+ fails++;
+
+ } else {
+
+ if(epson_epdc_init(&g_plat.epdc, g_plat.dispinfo, EPSON_EPDC_S1D13541, &driver) != 0)
+ {
+ Log("Error initalizing EPDC");
+
+ } else {
+
+ // Display the hardware settings.
+ DisplayHardwareSettings();
+
+ Log("White screen");
+ WriteColour(g_plat.epdc, PL_WHITE);
+
+ //wait(4);
+
+ Log("Black screen");
+ WriteColour(g_plat.epdc, PL_BLACK);
+
+ /*wait(4);
+
+ Log("White screen");
+ WriteColour(g_plat.epdc, PL_WHITE);
+
+ wait(4);
+ Log("Picture");
+ WritePicture(g_plat.epdc, "/myfile.pgm");*/
+
+ /*WriteColour(g_plat.epdc, PL_WHITE);
+ Log("Picture");
+ wait(1);
+ WritePicture(g_plat.epdc, "/logos2.pgm");
+ wait(5);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang00.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang01.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang02.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang03.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang04.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang05.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang06.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang07.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang08.pgm");
+ wait(2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang09.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang10.pgm");
+ wait (2);
+ //ShortBeep();
+ WritePicture(g_plat.epdc, "/hang11.pgm");
+ wait (2);*/
+ }
+ }
+ }
+ }
+ }
+
+ if(fails < MAX_INIT_FAILS)
+ printf("Init done, %d retries\n", fails);
+ else
+ printf("Init aborted, retry limit of %d exceeded\n", fails);
+}
+
+void WriteImage ( const int number)
+{
+ printf("WriteImage in eink.cpp\n");
+ switch (number)
+ {
+ case 0:
+ WritePicture(g_plat.epdc, "/hang00.pgm");
+ break;
+ case 1:
+ WritePicture(g_plat.epdc, "/hang01.pgm");
+ break;
+ case 2:
+ WritePicture(g_plat.epdc, "/hang02.pgm");
+ break;
+ case 3:
+ WritePicture(g_plat.epdc, "/hang03.pgm");
+ break;
+ case 4:
+ WritePicture(g_plat.epdc, "/hang04.pgm");
+ break;
+ case 5:
+ WritePicture(g_plat.epdc, "/hang05.pgm");
+ break;
+ case 6:
+ WritePicture(g_plat.epdc, "/hang06.pgm");
+ break;
+ case 7:
+ WritePicture(g_plat.epdc, "/hang07.pgm");
+ break;
+ case 8:
+ WritePicture(g_plat.epdc, "/hang08.pgm");
+ break;
+ default:
+ break;
+ }
+}
\ No newline at end of file