Marc Bax / Mbed 2 deprecated Flexbook180111a

Dependencies:   SDFileSystem app epson mbed msp430 pl tests

Revision:
0:c643d398cdb6
diff -r 000000000000 -r c643d398cdb6 eink.cpp
--- /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