Added HangmanGame class, but does not work yet

Dependencies:   SDFileSystem app epson mbed msp430 pl tests

eink.cpp

Committer:
markpsymonds
Date:
2017-12-04
Revision:
1:a5ec6f9dcf0d
Parent:
0:fa7450a43b99

File content as of revision 1:a5ec6f9dcf0d:

//
// 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;
	}
}