FlexBook / Mbed 2 deprecated FlexBook171204a

Dependencies:   SDFileSystem app epson mbed msp430 pl tests

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers eink.cpp Source File

eink.cpp

00001 //
00002 // Filename: eink.cpp
00003 //
00004 // Flexbook eInk display driver.
00005 //
00006 
00007 #include "eink.h"
00008 
00009 #include "mbed.h"
00010 
00011 #include "ChaN/ff.h"
00012 
00013 #include "log.h"
00014 #include "page.h"
00015 
00016 #include "pmic-tps65185.h"
00017 #include "vcom.h"
00018 
00019 #include <sstream>
00020 
00021 const int MAX_INIT_FAILS = 3;
00022 
00023 SPI *spi = 0;
00024 
00025 #define I2C_PMIC_ADDR_TPS65185 0x68
00026 
00027 struct tps65185_info pmic_info;
00028 
00029 const char *g_wflib_fatfs_path = "/waveform.dat";
00030 
00031 extern "C"
00032 {
00033     // EPSON drivers.
00034     #include "epson/epson-epdc.h"
00035     #include "epson/epson-s1d135xx.h"
00036 
00037     // Plastic Logic drivers.
00038     #include "pl/epdc.h"
00039     #include "pl/dispinfo.h"
00040     #include "pl/platform.h"
00041     #include "pl/types.h"
00042 
00043     #include "wflib.h"
00044 
00045 void mdelay(uint16_t ms)
00046 {
00047     wait_ms(ms);
00048 }
00049 
00050 void msleep(uint16_t ms)
00051 {
00052     mdelay(ms);
00053 }
00054 
00055 #define EPSON_RESET p16
00056 #define EPSON_CS_0 p14
00057 #define EPSON_HIRQ p15
00058 #define EPSON_HRDY ~0U
00059 #define EPSON_HDC p24
00060 #define EPSON_CLK_EN 1002
00061 #define EPSON_VCC_EN 1003
00062 
00063 enum
00064 {
00065     HVSW_CTRL = p17, /* VCOM switch enable */
00066     PMIC_EN =   p18, /* HV-PMIC enable */
00067     PMIC_POK =  p23, /* HV-PMIC power OK */
00068     PMIC_FLT =  1006 /* HV-PMIC fault condition */
00069 };
00070 
00071 static const struct s1d135xx_data g_s1d135xx_data =
00072 {
00073     EPSON_RESET,
00074     EPSON_CS_0,
00075     EPSON_HIRQ,
00076     EPSON_HRDY,
00077     EPSON_HDC,
00078     EPSON_CLK_EN,
00079     EPSON_VCC_EN
00080 };
00081 
00082 void printgpio(unsigned int gpio)
00083 {
00084     switch(gpio)
00085     {
00086         case EPSON_RESET:
00087             printf("EPSON_RESET");
00088             break;
00089 
00090         case EPSON_CS_0:
00091             printf("EPSON_CS_0");
00092             break;
00093 
00094         case EPSON_HIRQ:
00095             printf("EPSON_HIRQ");
00096             break;
00097 
00098         case EPSON_HRDY:
00099             printf("EPSON_HRDY");
00100             break;
00101 
00102         case EPSON_HDC:
00103             printf("EPSON_HDC");
00104             break;
00105 
00106         case EPSON_CLK_EN:
00107             printf("EPSON_CLK_EN");
00108             break;
00109 
00110         case EPSON_VCC_EN:
00111             printf("EPSON_VCC_EN");
00112             break;
00113 
00114         case HVSW_CTRL:
00115             printf("HVSW_CTRL");
00116             break;
00117 
00118         case PMIC_EN:
00119             printf("PMIC_EN");
00120             break;
00121 
00122         case PMIC_POK:
00123             printf("PMIC_POK");
00124             break;
00125 
00126         default:
00127             printf("Unknown GPIO: %u", gpio);
00128             break;
00129     }
00130 }
00131 
00132 //#define LOG_GPIO
00133 
00134 extern int msp430_gpio_get(unsigned gpio)
00135 {
00136 #ifdef LOG_GPIO
00137     printf("msp430_gpio_get(");
00138     printgpio(gpio);
00139     printf(")\n");
00140 #endif // LOG_GPIO
00141 
00142     int value = 0;
00143     if(gpio != EPSON_CLK_EN && gpio != EPSON_VCC_EN)
00144     {
00145         DigitalIn gpiopin((PinName) gpio);
00146         value = gpiopin;
00147     } else {
00148 #ifdef LOG_GPIO
00149         printf("unused GPIO, ignored\n");
00150 #endif // LOG_GPIO
00151     }
00152 
00153     return value;
00154 }
00155 
00156 extern void msp430_gpio_set(unsigned gpio, int value)
00157 {
00158 #ifdef LOG_GPIO
00159     printf("msp430_gpio_set(");
00160     printgpio(gpio);
00161     printf(", %d)\n", value);
00162 #endif // LOG_GPIO
00163 
00164     if(gpio != EPSON_CLK_EN && gpio != EPSON_VCC_EN)
00165     {
00166         DigitalOut gpiopin((PinName) gpio);
00167         gpiopin = value;
00168     } else {
00169 #ifdef LOG_GPIO
00170         printf("unused GPIO, ignored\n");
00171 #endif // LOG_GPIO
00172     }
00173 }
00174 
00175 int _swap_bytes(int bytes)
00176 {
00177     uint16_t ubytes = bytes;
00178     ubytes = (ubytes << 8) + (ubytes >> 8);
00179     return ubytes;
00180 }
00181 
00182 int parser_read_file_line(FIL *f, char *buffer, int max_length)
00183 {
00184     Log("parser_read_file_line not implemented, returning FR_OK");
00185     return 0;
00186 }
00187 
00188 int parser_read_word(const char *str, const char *sep, unsigned int *out)
00189 {
00190     Log("parser_read_word not implemented, returning 0");
00191     return 0;
00192 }
00193 
00194 //#define LOG_SPI
00195 
00196 void spi_read_bytes(uint8_t *buff, size_t size)
00197 {
00198 #ifdef LOG_SPI
00199     printf("spi_read_bytes(");
00200 #endif // LOG_SPI
00201     for(size_t i = 0; i < size; i++)
00202     {
00203         buff[i] = spi->write(0);
00204 
00205 #ifdef LOG_SPI
00206         int buffint = buff[i];
00207         printf("%02x", buffint);
00208 #endif // LOG_SPI
00209     }
00210 
00211 #ifdef LOG_SPI
00212     int sizeint = size;
00213     printf(", %02x)\n", sizeint);
00214 #endif // LOG_SPI
00215 }
00216 
00217 void spi_write_bytes(uint8_t *buff, size_t size)
00218 {
00219 #ifdef LOG_SPI
00220     int sizeint = size;
00221     printf("spi_write_bytes(");
00222     for(size_t i = 0; i < size; i++)
00223     {
00224         int buffint = buff[i];
00225         printf("%02x", buffint);
00226     }
00227     printf(", %02x)\n", sizeint);
00228 #endif // LOG_SPI
00229 
00230     if(spi)
00231     {
00232         for(size_t i = 0; i < size; i++)
00233         {
00234             spi->write(buff[i]);
00235         }
00236 
00237     } else {
00238 
00239         printf("ERROR: SPI not set!!!\n");
00240     }
00241 }
00242 
00243 } // End '"C" linking.
00244 
00245 struct pl_platform g_plat;
00246 
00247 struct pl_dispinfo g_dispinfo;
00248 
00249 void WriteColour(pl_epdc &epdc, uint8_t colour)
00250 {
00251     if(epdc.fill(&epdc, NULL, colour))
00252         Log("fill failed");
00253 
00254     if(epdc.clear_init(&epdc))
00255         Log("clear_init fail");
00256     
00257     if(g_plat.psu.on(&g_plat.psu))
00258         Log("PSU on fail");
00259 
00260     int wfid = pl_epdc_get_wfid(&epdc, wf_refresh);
00261     if (wfid < 0)
00262         Log("Bad wfid");
00263 
00264     if(epdc.update(&epdc, wfid, NULL))
00265         Log("update failed");
00266     
00267     if(epdc.wait_update_end(&epdc))
00268         Log("wait update end failed");
00269 
00270     if(g_plat.psu.off(&g_plat.psu))
00271         Log("PSU off fail");
00272 }
00273 
00274 void WritePicture(pl_epdc &epdc, const char *file)
00275 {
00276 //#ifdef VERBOSE
00277     Log("WritePicture");
00278 //#endif
00279 
00280     if(g_plat.epdc.load_image(&g_plat.epdc, file, NULL, 0, 0))
00281         Log("Image load failed");
00282     else Log("Image loaded");
00283     if(g_plat.psu.on(&g_plat.psu))
00284         Log("PSU on fail");
00285     else Log ("PSU on");
00286     int wfid = pl_epdc_get_wfid(&epdc, wf_refresh);
00287     if (wfid < 0)
00288         Log("Bad wfid");
00289     else Log("Good wfid");
00290 
00291     if(g_plat.epdc.update(&g_plat.epdc, wfid, NULL))
00292         Log("update failed");
00293     else Log("update succeeded");
00294     
00295     if(epdc.wait_update_end(&epdc))
00296         Log("wait update end failed");
00297     else Log("wait update end succeeded");
00298 
00299     if(g_plat.psu.off(&g_plat.psu))
00300         Log("PSU off fail");
00301     else Log("PSU off");
00302 }
00303 
00304 void WriteImage(const char *file)
00305 {
00306 #ifdef VERBOSE
00307     Log("WritePicture");
00308 #endif
00309 
00310     if(g_plat.epdc.load_image(&g_plat.epdc, file, NULL, 0, 0))
00311         Log("Image load failed");
00312 }
00313 
00314 void WritePartImage(const char *file, int xd, int yd, int xi, int yi, int w, int h)
00315 {
00316 #ifdef VERBOSE
00317     Log("WritePartImage");
00318 #endif
00319 
00320     pl_area area;
00321 
00322     area.left = xd;
00323     area.top = yd;
00324     area.width = w;
00325     area.height = h;
00326 
00327     if(g_plat.epdc.load_image(&g_plat.epdc, file, &area, xi, yi))
00328         Log("Image load failed");
00329 }
00330     
00331 void UpdateDisplay()
00332 {
00333 #ifdef VERBOSE
00334     Log("UpdateDisplay");
00335 #endif
00336 
00337     if(g_plat.psu.on(&g_plat.psu))
00338         Log("PSU on fail");
00339 
00340     int wfid = pl_epdc_get_wfid(&g_plat.epdc, wf_refresh);
00341     if (wfid < 0)
00342         Log("Bad wfid");
00343 
00344     if(g_plat.epdc.update(&g_plat.epdc, wfid, NULL))
00345         Log("update failed");
00346     
00347     if(g_plat.epdc.wait_update_end(&g_plat.epdc))
00348         Log("wait update end failed");
00349 
00350     if(g_plat.psu.off(&g_plat.psu))
00351         Log("PSU off fail");
00352 }
00353     
00354 int pl_i2c_reg_read_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg, uint8_t *data);
00355 
00356 int pl_i2c_reg_write_8(I2C &i2c, uint8_t i2c_addr, uint8_t reg, uint8_t data);
00357 
00358 void pl_hwinfo_log(const struct pl_hwinfo *info)
00359 {
00360 #if VERBOSE
00361     const struct pl_hw_vcom_info *vcom = &info->vcom;
00362 #endif
00363     const struct pl_hw_board_info *board = &info->board;
00364 
00365 #if VERBOSE
00366     printf("Version: %d\n", info->version);
00367     printf("VCOM DAC info: dac[%d]=%d, dac[%d]=%d\n",
00368         vcom->dac_x1, vcom->dac_y1, vcom->dac_x2, vcom->dac_y2);
00369     printf("Gate PSU info: VGPOS=%ld, VGNEG=%ld, swing=%ld\n",
00370         vcom->vgpos_mv, vcom->vgneg_mv, vcom->swing_ideal);
00371 #endif
00372     printf("Board type: %s, version: %d.%d\n",
00373         board->board_type, board->board_ver_maj, board->board_ver_min);
00374 #if VERBOSE
00375     printf("vcom_mode=%d, hv_pmic=%d, vcom_dac=%d, vcom_adc=%d\n",
00376         board->vcom_mode, board->hv_pmic, board->vcom_dac, board->vcom_adc);
00377     printf("io_config=%d, i2c_mode=%d, temp_sensor=%d, frame_buffer=%d\n",
00378         board->io_config, board->i2c_mode, board->temp_sensor,
00379         board->frame_buffer);
00380     printf("epdc_ref=%d, adc_scale_1=%d, adc_scale_2=%d\n",
00381         board->epdc_ref, board->adc_scale_1, board->adc_scale_2);
00382     printf("CRC16: %04X\n", info->crc);
00383 #endif
00384 }
00385 
00386 #define CONFIG_DEFAULT_I2C_MODE       I2C_MODE_HOST
00387 #define BOARD_MAJ 6
00388 #define BOARD_MIN 3
00389 
00390 static const struct pl_hwinfo g_hwinfo_default = {
00391     /* version */
00392     PL_HWINFO_VERSION,
00393     /* vcom */
00394     { 127, 4172, 381, 12490, 25080, -32300, 56886 },
00395     /* board */
00396     { "HB", BOARD_MAJ, BOARD_MIN, 0, HV_PMIC_TPS65185, 0, 0, 0,
00397       CONFIG_DEFAULT_I2C_MODE, TEMP_SENSOR_NONE, 0, EPDC_S1D13541, 1, 1 },
00398     /* CRC16 (not used when not reading from actual EEPROM) */
00399     0xFFFF,
00400 };
00401 
00402 FIL g_wflib_fatfs_file;
00403 
00404 static struct pl_epdpsu_gpio g_epdpsu_gpio = {
00405     &g_plat.gpio, PMIC_EN, HVSW_CTRL, PMIC_POK, PMIC_FLT, 300, 5, 100
00406 };
00407 
00408 struct vcom_cal vcom_cal;
00409 
00410 pl_epdc &Get_epdc()
00411 {
00412     return g_plat.epdc;
00413 }
00414 
00415 std::ostream &operator<<(std::ostream &s, pl_gpio &gpio)
00416 {
00417     s << "pl_gpio\n";
00418 
00419     s << gpio.config << "\n";
00420     s << gpio.get << "\n";
00421     s << gpio.set << "\n";
00422     
00423     return s;
00424 }
00425 
00426 std::ostream &operator<<(std::ostream &s, pl_epdpsu &epdpsu)
00427 {
00428     s << "pl_epdpsu\n";
00429 
00430     s << epdpsu.on << "\n";
00431     s << epdpsu.off << "\n";
00432     s << epdpsu.state << "\n";
00433     s << epdpsu.data << "\n";
00434     
00435     return s;
00436 };
00437 
00438 std::ostream &operator<<(std::ostream &s, pl_epdc &epdc)
00439 {
00440     s << "pl_epdc\n";
00441 
00442     s << epdc.clear_init << "\n";
00443     s << epdc.load_wflib << "\n";
00444     s << epdc.update << "\n";
00445     s << epdc.wait_update_end << "\n";
00446     s << epdc.set_power << "\n";
00447     s << epdc.set_temp_mode << "\n";
00448     s << epdc.update_temp << "\n";
00449     s << epdc.fill << "\n";
00450     s << epdc.pattern_check << "\n";
00451     s << epdc.load_image << "\n";
00452     s << epdc.set_epd_power << "\n";
00453 
00454     s << epdc.wf_table << "\n";
00455     s << epdc.dispinfo << "\n";
00456     //struct pl_wflib wflib << "\n";
00457     s << epdc.power_state << "\n";
00458     s << epdc.temp_mode << "\n";
00459     s << epdc.manual_temp << "\n";
00460     s << epdc.xres << "\n";
00461     s << epdc.yres << "\n";
00462     s << epdc.data << "\n";
00463     
00464     return s;
00465 };
00466 
00467 std::ostream &operator<<(std::ostream &s, pl_platform &g_plat)
00468 {
00469     s << "pl_platform\n";
00470 
00471     s << g_plat.gpio << "\n";
00472     s << g_plat.psu << "\n";
00473     s << g_plat.epdc << "\n";
00474     s << g_plat.i2c << "\n";
00475     s << g_plat.sys_gpio << "\n";
00476     s << g_plat.hwinfo << "\n";
00477     s << g_plat.dispinfo << "\n";
00478     
00479     return s;
00480 }
00481         
00482 void DisplayHardwareSettings()
00483 {
00484     pl_hwinfo_log(g_plat.hwinfo);
00485 
00486 #ifdef VERBOSE
00487     printf("Hardware information start\n"):
00488     std::ostringstream info;
00489     info << g_plat << "\n";
00490     printf(info.str().c_str());
00491 
00492     printf("Hardware information end\n");
00493 #endif // VERBOSE
00494 }
00495 
00496 // Configure the EPSON controller settings.
00497 s1d135xx driver = { &g_s1d135xx_data, NULL };
00498 
00499 
00500 void InitDisplay(I2C &i2c, SPI &spi_in, DigitalOut &spics, DigitalOut &hven, DigitalOut &rst, DigitalIn &hvpok)
00501 {
00502     spi = &spi_in;
00503 
00504     spi->frequency(1000000);
00505     spi->format(8, 0);
00506 
00507     rst = 0;
00508     hven = 0;
00509     spics = 1;
00510 
00511     // Initialise the platform settings.
00512     g_plat.i2c = NULL;
00513     g_plat.sys_gpio = NULL;
00514     g_plat.hwinfo = &g_hwinfo_default;
00515     g_plat.dispinfo = &g_dispinfo;
00516 
00517     g_plat.psu.on = NULL;
00518     g_plat.psu.off = NULL;
00519     g_plat.psu.state = 0;
00520     g_plat.psu.data = NULL;
00521 
00522     // Use a 100Khz I2c clock (the PMIC limits are 100-400KHz).
00523     i2c.frequency(100000);
00524 
00525     // COnfigure the VCOM settings.
00526     g_dispinfo.info.vcom = 5124; // Note hardcoded VCOM
00527 
00528     int fails = 0;
00529     int initfailed = -1;
00530     while(initfailed && fails < MAX_INIT_FAILS)
00531     {
00532         // Enable the TPS65185 PMIC.
00533         // The I2C is now enabled.
00534         hven = 1;
00535         wait(0.2);
00536         
00537         // Hard reset the Epson controller.
00538         rst = 0;
00539         mdelay(4);
00540         rst = 1;
00541         mdelay(10);
00542 
00543         // Load the display information.
00544         initfailed = pl_wflib_init_fatfs(&g_plat.epdc.wflib, (int *) &g_wflib_fatfs_file, g_wflib_fatfs_path);
00545         if(initfailed != 0)
00546         {
00547             Log("Failed to load display info");
00548             fails++;
00549 
00550         } else {
00551 
00552             pl_epdpsu_gpio_init(&g_plat.psu, &g_epdpsu_gpio);
00553             vcom_init(&vcom_cal, &g_plat.hwinfo->vcom);
00554             initfailed = tps65185_init(&pmic_info, i2c, I2C_PMIC_ADDR_TPS65185, &vcom_cal);
00555             if(initfailed != 0)
00556             {
00557                 Log("Error initalizing TPS65185");
00558                 fails++;
00559 
00560             } else {
00561             
00562                 initfailed = tps65185_set_vcom_voltage(&pmic_info, g_plat.dispinfo->info.vcom);
00563                 if(initfailed != 0)
00564                 {
00565                     Log("Error initalizing VCOM");
00566                     fails++;
00567 
00568                 } else {
00569 
00570                     if(epson_epdc_init(&g_plat.epdc, g_plat.dispinfo, EPSON_EPDC_S1D13541, &driver) != 0)
00571                     {
00572                         Log("Error initalizing EPDC");
00573 
00574                     } else {
00575 
00576                         // Display the hardware settings.
00577                         DisplayHardwareSettings();
00578 
00579                         Log("White screen");
00580                         WriteColour(g_plat.epdc, PL_WHITE);
00581 
00582                         //wait(4);
00583 
00584                         Log("Black screen");
00585                         WriteColour(g_plat.epdc, PL_BLACK);
00586 
00587                         /*wait(4);
00588 
00589                         Log("White screen");
00590                         WriteColour(g_plat.epdc, PL_WHITE);
00591 
00592                         wait(4);
00593                         Log("Picture");
00594                         WritePicture(g_plat.epdc, "/myfile.pgm");*/
00595 
00596                         /*WriteColour(g_plat.epdc, PL_WHITE);                        
00597                         Log("Picture");
00598                         wait(1);
00599                         WritePicture(g_plat.epdc, "/logos2.pgm");
00600                         wait(5);
00601                         //ShortBeep();
00602                         WritePicture(g_plat.epdc, "/hang00.pgm");
00603                         wait (2);
00604                         //ShortBeep();
00605                         WritePicture(g_plat.epdc, "/hang01.pgm");
00606                         wait (2);
00607                         //ShortBeep();
00608                         WritePicture(g_plat.epdc, "/hang02.pgm");
00609                         wait (2);
00610                         //ShortBeep();
00611                         WritePicture(g_plat.epdc, "/hang03.pgm");
00612                         wait (2);
00613                         //ShortBeep();
00614                         WritePicture(g_plat.epdc, "/hang04.pgm");
00615                         wait (2);
00616                         //ShortBeep();
00617                         WritePicture(g_plat.epdc, "/hang05.pgm");
00618                         wait (2);
00619                         //ShortBeep();
00620                         WritePicture(g_plat.epdc, "/hang06.pgm");
00621                         wait (2);
00622                         //ShortBeep();
00623                         WritePicture(g_plat.epdc, "/hang07.pgm");
00624                         wait (2);
00625                         //ShortBeep();
00626                         WritePicture(g_plat.epdc, "/hang08.pgm");
00627                         wait(2);
00628                         //ShortBeep();
00629                         WritePicture(g_plat.epdc, "/hang09.pgm");
00630                         wait (2);
00631                         //ShortBeep();
00632                         WritePicture(g_plat.epdc, "/hang10.pgm");
00633                         wait (2);
00634                         //ShortBeep();
00635                         WritePicture(g_plat.epdc, "/hang11.pgm");
00636                         wait (2);*/
00637                     }
00638                 }
00639             }
00640         }
00641     }
00642 
00643     if(fails < MAX_INIT_FAILS)
00644         printf("Init done, %d retries\n", fails);
00645     else
00646         printf("Init aborted, retry limit of %d exceeded\n", fails);
00647 }
00648 
00649 void WriteImage ( const int number)
00650 {
00651     printf("WriteImage in eink.cpp\n");
00652     switch (number)
00653     {
00654         case 0:
00655             WritePicture(g_plat.epdc, "/hang00.pgm");
00656             break;
00657         case 1:
00658             WritePicture(g_plat.epdc, "/hang01.pgm");
00659             break;
00660         case 2:
00661             WritePicture(g_plat.epdc, "/hang02.pgm");
00662             break;
00663         case 3:
00664             WritePicture(g_plat.epdc, "/hang03.pgm");
00665             break;
00666         case 4:
00667             WritePicture(g_plat.epdc, "/hang04.pgm");
00668             break;
00669         case 5:
00670             WritePicture(g_plat.epdc, "/hang05.pgm");
00671             break;
00672         case 6:
00673             WritePicture(g_plat.epdc, "/hang06.pgm");
00674             break;
00675         case 7:
00676             WritePicture(g_plat.epdc, "/hang07.pgm");
00677             break;
00678         case 8:
00679             WritePicture(g_plat.epdc, "/hang08.pgm");
00680             break;
00681         default:
00682             break;
00683     }
00684 }