A library with drivers for different peripherals on the LPC4088 QuickStart Board or related add-on boards.

Dependencies:   FATFileSystem

Fork of EALib by EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers EaLcdBoard.cpp Source File

EaLcdBoard.cpp

00001 /*
00002  *  Copyright 2013 Embedded Artists AB
00003  *
00004  *  Licensed under the Apache License, Version 2.0 (the "License");
00005  *  you may not use this file except in compliance with the License.
00006  *  You may obtain a copy of the License at
00007  *
00008  *    http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  *  Unless required by applicable law or agreed to in writing, software
00011  *  distributed under the License is distributed on an "AS IS" BASIS,
00012  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *  See the License for the specific language governing permissions and
00014  *  limitations under the License.
00015  */
00016 
00017 /******************************************************************************
00018  * Includes
00019  *****************************************************************************/
00020 
00021 #include "mbed.h"
00022 #include "EaLcdBoard.h"
00023 
00024 /******************************************************************************
00025  * Defines and typedefs
00026  *****************************************************************************/
00027 
00028 #define PORT_PIN_BUG_IN_MBED_SDK
00029 
00030 #define LCDB_MAGIC 0xEA01CDAE
00031 
00032 
00033 #define LCDB_PCA9532_I2C_ADDR    (0x64 << 1)
00034 
00035 /* PCA9532 registers*/
00036 #define LCDB_PCA9532_INPUT0   0x00
00037 #define LCDB_PCA9532_INPUT1   0x01
00038 #define LCDB_PCA9532_PSC0     0x02
00039 #define LCDB_PCA9532_PWM0     0x03
00040 #define LCDB_PCA9532_PSC1     0x04
00041 #define LCDB_PCA9532_PWM1     0x05
00042 #define LCDB_PCA9532_LS0      0x06
00043 #define LCDB_PCA9532_LS1      0x07
00044 #define LCDB_PCA9532_LS2      0x08
00045 #define LCDB_PCA9532_LS3      0x09
00046 #define LCDB_PCA9532_AUTO_INC 0x10
00047 
00048 #define LCDB_LS_MODE_ON     0x01
00049 #define LCDB_LS_MODE_BLINK0 0x02
00050 #define LCDB_LS_MODE_BLINK1 0x03
00051 
00052 #define LCDB_CTRL_3V3     0x0001
00053 #define LCDB_CTRL_5V      0x0002
00054 #define LCDB_CTRL_DISP_EN 0x0010
00055 #define LCDB_CTRL_BL_EN   0x0080
00056 #define LCDB_CTRL_BL_C    0x0100
00057 #define LCDB_EEPROM_WP    0x8000
00058 
00059 #define LCDB_EEPROM_I2C_ADDR  (0x56 << 1)
00060 #define LCDB_EEPROM_PAGE_SIZE     32
00061 #define LCDB_EEPROM_TOTAL_SIZE  8192
00062 
00063 /*
00064  * Set which sequence string version that is supported
00065  */
00066 #define LCDB_SEQ_VER 2
00067 
00068 #ifndef MIN
00069 #define MIN(x, y) (((x)<(y))?(x):(y))
00070 #endif
00071 
00072 #define EA_LCD_TMP_BUFFER_SZ 256
00073 static char* eaLcdTmpBuffer[EA_LCD_TMP_BUFFER_SZ];
00074 
00075 
00076 /* Structure containing the parameters for the LCD panel as stored on LCD Board */
00077 
00078 /* LCD display types */
00079 typedef enum {
00080     TFT = 0,   /* standard TFT */
00081     ADTFT,     /* advanced TFT */
00082     HRTFT,     /* highly reflective TFT */
00083     MONO_4BIT, /* 4-bit mono */
00084     MONO_8BIT, /* 8-bit mono */
00085     CSTN       /* color STN */
00086 } nxp_lcd_panel_t;
00087 
00088 typedef struct {
00089     uint8_t         h_back_porch;         /* Horizontal back porch in clocks */
00090     uint8_t         h_front_porch;        /* Horizontal front porch in clocks */
00091     uint8_t         h_sync_pulse_width;   /* HSYNC pulse width in clocks */
00092     uint16_t        pixels_per_line;      /* Pixels per line (horizontal resolution) */
00093     uint8_t         v_back_porch;         /* Vertical back porch in clocks */
00094     uint8_t         v_front_porch;        /* Vertical front porch in clocks */
00095     uint8_t         v_sync_pulse_width;   /* VSYNC pulse width in clocks */
00096     uint16_t        lines_per_panel;      /* Lines per panel (vertical resolution) */
00097     uint8_t         invert_output_enable; /* Invert output enable, 1 = invert*/
00098     uint8_t         invert_panel_clock;   /* Invert panel clock, 1 = invert*/
00099     uint8_t         invert_hsync;         /* Invert HSYNC, 1 = invert */
00100     uint8_t         invert_vsync;         /* Invert VSYNC, 1 = invert */
00101     uint8_t         ac_bias_frequency;    /* AC bias frequency in clocks */
00102     uint8_t         bits_per_pixel;       /* Maximum bits per pixel the display supports */
00103     uint32_t        optimal_clock;        /* Optimal clock rate (Hz) */
00104     nxp_lcd_panel_t lcd_panel_type;       /* LCD panel type */
00105     uint8_t         dual_panel;           /* Dual panel, 1 = dual panel display */
00106 } nxp_lcd_param_t;
00107 
00108 static uint32_t str_to_uint(char* str, uint32_t len);
00109 
00110 EaLcdBoard::EaLcdBoard(PinName sda, PinName scl) : _i2c(sda, scl) {
00111     _blink0Shadow = 0;
00112     _blink1Shadow = 0;
00113     _ledStateShadow = 0;
00114     _lcdPwrOn = false;
00115 }
00116 
00117 EaLcdBoard::Result EaLcdBoard::open(LcdController::Config* cfg, char* initSeq) {
00118 
00119     EaLcdBoard::Result result = Ok;
00120 
00121     // load LCD configuration from storage
00122     if (cfg == NULL) {
00123         result = getLcdConfig(&_cfg);
00124         cfg = &_cfg;
00125     }
00126 
00127     // load init sequence from storage
00128     if (result == Ok && initSeq == NULL) {
00129         result = getInitSeq((char*)eaLcdTmpBuffer, EA_LCD_TMP_BUFFER_SZ);
00130         initSeq = (char*)eaLcdTmpBuffer;
00131     }
00132 
00133     if (result != Ok) {
00134         return result;
00135     }
00136 
00137     return parseInitString(initSeq, cfg);
00138 }
00139 
00140 EaLcdBoard::Result EaLcdBoard::close() {
00141     int r = 0;
00142 
00143     do {
00144         r = lcdCtrl.setPower(false);
00145         if (r != 0) break;
00146 
00147         _lcdPwrOn = false;
00148 
00149         r = lcdCtrl.close();
00150     } while(0);
00151 
00152     if (r != 0) {
00153         return LcdAccessError;
00154     }
00155 
00156     return Ok;
00157 }
00158 
00159 EaLcdBoard::Result EaLcdBoard::setFrameBuffer(uint32_t address) {
00160     int r = 0;
00161 
00162     do {
00163 
00164         // begin by powering on the display
00165         if (!_lcdPwrOn) {
00166             r = lcdCtrl.setPower(true);
00167             if (r != 0) break;
00168 
00169             _lcdPwrOn = true;
00170         }
00171 
00172         // activate specified frame buffer
00173         r = lcdCtrl.setFrameBuffer(address);
00174         if (r != 0) break;
00175 
00176     } while(0);
00177 
00178     if (r != 0) {
00179         return LcdAccessError;
00180     }
00181 
00182 
00183     return Ok;
00184 }
00185 
00186 EaLcdBoard::Result EaLcdBoard::getLcdConfig(LcdController::Config* cfg) {
00187     store_t h;
00188 
00189     nxp_lcd_param_t lcdParam;
00190 
00191     if (cfg == NULL) {
00192         return InvalidArgument;
00193     }
00194 
00195     getStore(&h);
00196 
00197     if (h.magic != LCDB_MAGIC) {
00198         return InvalidStorage;
00199     }
00200 
00201     eepromRead((uint8_t*)&lcdParam, h.lcdParamOff,
00202             (h.initOff-h.lcdParamOff));
00203 
00204     cfg->horizontalBackPorch  = lcdParam.h_back_porch;
00205     cfg->horizontalFrontPorch = lcdParam.h_front_porch;
00206     cfg->hsync                = lcdParam.h_sync_pulse_width;
00207     cfg->width                = lcdParam.pixels_per_line;
00208     cfg->verticalBackPorch    = lcdParam.v_back_porch;
00209     cfg->verticalFrontPorch   = lcdParam.v_front_porch;
00210     cfg->vsync                = lcdParam.v_sync_pulse_width;
00211     cfg->height               = lcdParam.lines_per_panel;
00212     cfg->invertOutputEnable   = (lcdParam.invert_output_enable == 1);
00213     cfg->invertPanelClock     = (lcdParam.invert_panel_clock == 1);
00214     cfg->invertHsync          = (lcdParam.invert_hsync == 1);
00215     cfg->invertVsync          = (lcdParam.invert_vsync == 1);
00216     cfg->acBias               = lcdParam.ac_bias_frequency;
00217     cfg->bpp = LcdController::Bpp_16_565;
00218     cfg->optimalClock         = lcdParam.optimal_clock;
00219     cfg->panelType            = (LcdController::LcdPanel)lcdParam.lcd_panel_type;
00220     cfg->dualPanel            = (lcdParam.dual_panel == 1);
00221 
00222     return Ok;
00223 }
00224 
00225 EaLcdBoard::Result EaLcdBoard::getDisplayName(char* buf, int len) {
00226     store_t h;
00227 
00228     if (buf == NULL) {
00229         return InvalidArgument;
00230     }
00231 
00232     getStore(&h);
00233 
00234     if (h.magic != LCDB_MAGIC) {
00235         return InvalidStorage;
00236     }
00237 
00238     if (len < NameBufferSize) {
00239         return BufferTooSmall;
00240     }
00241 
00242     strncpy(buf, (char*)h.lcd_name, NameBufferSize);
00243 
00244     return Ok;
00245 }
00246 
00247 EaLcdBoard::Result EaLcdBoard::getDisplayMfg(char* buf, int len) {
00248     store_t h;
00249 
00250     if (buf == NULL) {
00251         return InvalidArgument;
00252     }
00253 
00254     getStore(&h);
00255 
00256     if (h.magic != LCDB_MAGIC) {
00257         return InvalidStorage;
00258     }
00259 
00260     if (len < NameBufferSize) {
00261         return BufferTooSmall;
00262     }
00263 
00264     strncpy(buf, (char*)h.lcd_mfg, NameBufferSize);
00265 
00266     return Ok;
00267 }
00268 
00269 EaLcdBoard::Result EaLcdBoard::getInitSeq(char* buf, int len) {
00270     store_t h;
00271 
00272     if (buf == NULL) {
00273         return InvalidArgument;
00274     }
00275 
00276     getStore(&h);
00277 
00278     if (h.magic != LCDB_MAGIC) {
00279         return InvalidStorage;
00280     }
00281 
00282     if ((h.pdOff-h.initOff) > len) {
00283         return BufferTooSmall;
00284     }
00285 
00286     eepromRead((uint8_t*)buf, h.initOff,
00287             (h.pdOff-h.initOff));
00288 
00289     return Ok;
00290 }
00291 
00292 EaLcdBoard::Result EaLcdBoard::getPowerDownSeq(char* buf, int len) {
00293     store_t h;
00294 
00295     if (buf == NULL) {
00296         return InvalidArgument;
00297     }
00298 
00299     getStore(&h);
00300 
00301     if (h.magic != LCDB_MAGIC) {
00302         return InvalidStorage;
00303     }
00304 
00305     if ((h.tsOff-h.pdOff) > len) {
00306         return BufferTooSmall;
00307     }
00308 
00309     eepromRead((uint8_t*)buf, h.pdOff,
00310             (h.tsOff-h.pdOff));
00311 
00312     return Ok;
00313 }
00314 
00315 EaLcdBoard::Result EaLcdBoard::getTouchParameters(TouchParams_t* params) {
00316     store_t h;
00317 
00318     if (params == NULL) {
00319         return InvalidArgument;
00320     }
00321 
00322     getStore(&h);
00323 
00324     if (h.magic != LCDB_MAGIC) {
00325         return InvalidStorage;
00326     }
00327 
00328 
00329     if (eepromRead((uint8_t*)params, h.tsOff,
00330             (h.end-h.tsOff)) == -1) {
00331         return InvalidStorage;
00332     }
00333 
00334 
00335     if (params->panelId <= TouchPanelInvalidFirst
00336             || params->panelId >= TouchPanelInvalidLast) {
00337         params->panelId = TouchPanelUnknown;
00338     }
00339 
00340 
00341     return Ok;
00342 }
00343 
00344 EaLcdBoard::Result EaLcdBoard::storeParameters(
00345   const char* lcdName,
00346   const char* lcdMfg,
00347   LcdController::Config* cfg,
00348   const char* initSeqStr,
00349   const char* pdSeqStr,
00350   TouchParams_t* touch,
00351   bool controlWp)
00352 {
00353     store_t h;
00354     nxp_lcd_param_t lcdParam;
00355 
00356     if (lcdName == NULL || lcdMfg == NULL || cfg == NULL
00357             || initSeqStr == NULL || pdSeqStr == NULL) {
00358         return InvalidArgument;
00359 
00360     }
00361 
00362 
00363     lcdParam.h_back_porch         = cfg->horizontalBackPorch;
00364     lcdParam.h_front_porch        = cfg->horizontalFrontPorch;
00365     lcdParam.h_sync_pulse_width   = cfg->hsync;
00366     lcdParam.pixels_per_line      = cfg->width;
00367     lcdParam.v_back_porch         = cfg->verticalBackPorch;
00368     lcdParam.v_front_porch        = cfg->verticalFrontPorch;
00369     lcdParam.v_sync_pulse_width   = cfg->vsync;
00370     lcdParam.lines_per_panel      = cfg->height;
00371     lcdParam.invert_output_enable = (cfg->invertOutputEnable ? 1 : 0);
00372     lcdParam.invert_panel_clock   = (cfg->invertPanelClock ? 1 : 0);
00373     lcdParam.invert_hsync         = (cfg->invertHsync ? 1 : 0);
00374     lcdParam.invert_vsync         = (cfg->invertVsync ? 1 : 0);
00375     lcdParam.ac_bias_frequency    = cfg->acBias;
00376     lcdParam.optimal_clock        = cfg->optimalClock;
00377     lcdParam.lcd_panel_type       = (nxp_lcd_panel_t)cfg->panelType;
00378     lcdParam.dual_panel           = (cfg->dualPanel ? 1 : 0);
00379 
00380 
00381     h.magic = LCDB_MAGIC;
00382     strncpy((char*)h.lcd_name, lcdName, 30);
00383     strncpy((char*)h.lcd_mfg, lcdMfg, 30);
00384 
00385     h.lcdParamOff = sizeof(store_t);
00386     h.initOff     = h.lcdParamOff + sizeof(nxp_lcd_param_t);
00387     h.pdOff       = h.initOff + strlen(initSeqStr)+1;
00388     h.tsOff       = h.pdOff + strlen(pdSeqStr)+1;
00389     h.end         = h.tsOff + sizeof(TouchParams_t);
00390 
00391     if (controlWp) setWriteProtect(false);
00392     eepromWrite((uint8_t*)&h,         0,             h.lcdParamOff);
00393     eepromWrite((uint8_t*)&lcdParam,  h.lcdParamOff, (h.initOff-h.lcdParamOff));
00394     eepromWrite((uint8_t*)initSeqStr, h.initOff,     (h.pdOff-h.initOff));
00395     eepromWrite((uint8_t*)pdSeqStr,   h.pdOff,       (h.tsOff-h.pdOff));
00396     eepromWrite((uint8_t*)touch,      h.tsOff,       (h.end-h.tsOff));
00397     if (controlWp) setWriteProtect(true);
00398 
00399     return Ok;
00400 }
00401 
00402 EaLcdBoard::Result EaLcdBoard::getStore(store_t* store) {
00403     int num = 0;
00404 
00405     if (store == NULL) return InvalidArgument;
00406 
00407     num = eepromRead((uint8_t*)store, 0, sizeof(store_t));
00408     if (num < (int)sizeof(store_t)) {
00409         return InvalidStorage;
00410     }
00411 
00412     return Ok;
00413 }
00414 
00415 // ###########################
00416 // An EEPROM is used for persistent storage
00417 // ###########################
00418 
00419 int EaLcdBoard::eepromRead(uint8_t* buf, uint16_t offset, uint16_t len) {
00420     int i = 0;
00421     char off[2];
00422     uint16_t retLen = 0;
00423 
00424     if (len > LCDB_EEPROM_TOTAL_SIZE || offset+len > LCDB_EEPROM_TOTAL_SIZE) {
00425         return -1;
00426     }
00427 
00428     wait_ms(10);
00429 
00430     off[0] = ((offset >> 8) & 0xff);
00431     off[1] = (offset & 0xff);
00432 
00433     do {
00434         if (_i2c.write(LCDB_EEPROM_I2C_ADDR, (char*)off, 2) != 0) break;
00435         for ( i = 0; i < 0x2000; i++);
00436         if (_i2c.read(LCDB_EEPROM_I2C_ADDR, (char*)buf, len) != 0) break;
00437 
00438         retLen = len;
00439     } while(0);
00440 
00441     return retLen;
00442 }
00443 
00444 int EaLcdBoard::eepromWrite(uint8_t* buf, uint16_t offset, uint16_t len) {
00445     int16_t written = 0;
00446     uint16_t wLen = 0;
00447     uint16_t off = offset;
00448     uint8_t tmp[LCDB_EEPROM_PAGE_SIZE+2];
00449 
00450     if (len > LCDB_EEPROM_TOTAL_SIZE || offset+len > LCDB_EEPROM_TOTAL_SIZE) {
00451         return -1;
00452     }
00453 
00454     wait_ms(1);
00455 
00456     wLen = LCDB_EEPROM_PAGE_SIZE - (off % LCDB_EEPROM_PAGE_SIZE);
00457     wLen = MIN(wLen, len);
00458 
00459     while (len) {
00460         tmp[0] = ((off >> 8) & 0xff);
00461         tmp[1] = (off & 0xff);
00462         memcpy(&tmp[2], (void*)&buf[written], wLen);
00463         if (_i2c.write(LCDB_EEPROM_I2C_ADDR, (char*)tmp, wLen+2) != 0) break;
00464 
00465         // delay to wait for a write cycle
00466         //eepromDelay();
00467         wait_ms(10);
00468 
00469         len     -= wLen;
00470         written += wLen;
00471         off     += wLen;
00472 
00473         wLen = MIN(LCDB_EEPROM_PAGE_SIZE, len);
00474     }
00475 
00476     return written;
00477 }
00478 
00479 // ###########################
00480 // string parsing (initialization and power down strings)
00481 // ###########################
00482 
00483 EaLcdBoard::Result EaLcdBoard::parseInitString(char* str, LcdController::Config* cfg) {
00484     char* c = NULL;
00485     uint32_t len = 0;
00486     Result result = Ok;
00487 
00488     if (str == NULL) {
00489         return InvalidCommandString;
00490     }
00491 
00492     while(*str != '\0') {
00493 
00494         // skip whitespaces
00495         while(*str == ' ') {
00496             str++;
00497         }
00498 
00499         c = str;
00500 
00501         // find end of command
00502         while(*str != ',' && *str != '\0') {
00503             str++;
00504         }
00505 
00506         len = (str-c);
00507 
00508         if (*str == ',') {
00509             str++;
00510         }
00511 
00512         switch (*c++) {
00513 
00514         case 'v':
00515             result = checkVersion(c, len-1);
00516             break;
00517 
00518             // sequence control command (pca9532)
00519         case 'c':
00520             execSeqCtrl(c, len-1);
00521             break;
00522 
00523             // delay
00524         case 'd':
00525             execDelay(c, len-1);
00526             break;
00527 
00528             // open lcd (init LCD controller)
00529         case 'o':
00530 
00531             if (cfg != NULL) {
00532 
00533                 if (lcdCtrl.open(cfg) != 0) {
00534                     result = LcdAccessError;
00535                 }
00536             }
00537 
00538             else {
00539                 result = InvalidArgument;
00540             }
00541 
00542             break;
00543 
00544             // exec pin set
00545         case 'p':
00546             execPinSet(c, len-1);
00547             break;
00548 
00549         }
00550 
00551         if (result != Ok) {
00552             break;
00553         }
00554 
00555 
00556     }
00557 
00558 
00559     return result;
00560 }
00561 
00562 EaLcdBoard::Result EaLcdBoard::checkVersion(char* v, uint32_t len) {
00563     uint32_t ver = str_to_uint(v, len);
00564 
00565     if (ver > LCDB_SEQ_VER) {
00566         return VersionNotSupported;
00567     }
00568 
00569     return Ok;
00570 }
00571 
00572 EaLcdBoard::Result EaLcdBoard::execDelay(char* del, uint32_t len) {
00573     wait_ms(str_to_uint(del, len));
00574 
00575     return Ok;
00576 }
00577 
00578 EaLcdBoard::Result EaLcdBoard::execSeqCtrl(char* cmd, uint32_t len) {
00579 
00580     switch (*cmd++) {
00581 
00582     // display enable
00583     case 'd':
00584         setDisplayEnableSignal(*cmd == '1');
00585         break;
00586 
00587         // backlight contrast
00588     case 'c':
00589         setBacklightContrast(str_to_uint(cmd, len));
00590         break;
00591 
00592         // 3v3 enable
00593     case '3':
00594         set3V3Signal(*cmd == '1');
00595         break;
00596 
00597         // 5v enable
00598     case '5':
00599         set5VSignal(*cmd == '1');
00600         break;
00601     }
00602 
00603     return Ok;
00604 }
00605 
00606 #ifdef PORT_PIN_BUG_IN_MBED_SDK
00607 static PinName port_pin2(PortName port, int pin_n) {
00608     return (PinName)(((port << 5) | pin_n));
00609 }
00610 #endif
00611 
00612 
00613 EaLcdBoard::Result EaLcdBoard::execPinSet(char* cmd, uint32_t len) {
00614 
00615     PortName port;
00616 
00617     do {
00618         // cmd: 0_02=1 means p0.2 = 1
00619         if (len < 6) break;
00620         if (cmd[1] != '_' || cmd[4] != '=') break;
00621 
00622         // port
00623         int portnum  = cmd[0] - '0';
00624         if (portnum < 0 || portnum > 5) break;
00625         port = (PortName)portnum;
00626 
00627         // pin
00628         int pinnum = (10*(cmd[2]-'0'))+ cmd[3]-'0';
00629         if (pinnum < 0 || pinnum > 31) break;
00630 
00631         // value
00632         int value = cmd[5]-'0';
00633         if (!(value == 0 || value == 1)) break;
00634 
00635 #ifdef PORT_PIN_BUG_IN_MBED_SDK
00636         PinName pin = port_pin2(port, pinnum);
00637 #else
00638         PinName pin = port_pin(port, pinnum);
00639 #endif
00640 
00641         gpio_t gp;
00642         gpio_init(&gp, pin);
00643         gpio_dir(&gp, PIN_OUTPUT);
00644         gpio_mode(&gp, PullNone);
00645         gpio_write(&gp, value);
00646 
00647         return Ok;
00648 
00649     } while (false);
00650 
00651 
00652     return InvalidCommandString;
00653 }
00654 
00655 
00656 // ###########################
00657 // PCA9532 is used as a control inteface to the display.
00658 // voltages can be turned on/off and backlight can be controlled.
00659 // ###########################
00660 
00661 // Helper function to set LED states
00662 void EaLcdBoard::setLsStates(uint16_t states, uint8_t* ls, uint8_t mode)
00663 {
00664 #define IS_LED_SET(bit, x) ( ( ((x) & (bit)) != 0 ) ? 1 : 0 )
00665 
00666     int i = 0;
00667 
00668     for (i = 0; i < 4; i++) {
00669 
00670         ls[i] |= ( (IS_LED_SET(0x0001, states)*mode << 0)
00671                 | (IS_LED_SET(0x0002, states)*mode << 2)
00672                 | (IS_LED_SET(0x0004, states)*mode << 4)
00673                 | (IS_LED_SET(0x0008, states)*mode << 6) );
00674 
00675         states >>= 4;
00676     }
00677 }
00678 
00679 void EaLcdBoard::setLeds(void)
00680 {
00681     uint8_t buf[5];
00682     uint8_t ls[4] = {0,0,0,0};
00683     uint16_t states = _ledStateShadow;
00684 
00685     // LEDs in On/Off state
00686     setLsStates(states, ls, LCDB_LS_MODE_ON);
00687 
00688     // set the LEDs that should blink
00689     setLsStates(_blink0Shadow, ls, LCDB_LS_MODE_BLINK0);
00690     setLsStates(_blink1Shadow, ls, LCDB_LS_MODE_BLINK1);
00691 
00692     buf[0] = LCDB_PCA9532_LS0 | LCDB_PCA9532_AUTO_INC;
00693     buf[1] = ls[0];
00694     buf[2] = ls[1];
00695     buf[3] = ls[2];
00696     buf[4] = ls[3];
00697 
00698     _i2c.write(LCDB_PCA9532_I2C_ADDR, (char*)buf, 5);
00699 }
00700 
00701 void EaLcdBoard::pca9532_setLeds (uint16_t ledOnMask, uint16_t ledOffMask)
00702 {
00703     // turn off leds
00704     _ledStateShadow &= (~(ledOffMask) & 0xffff);
00705 
00706     // ledOnMask has priority over ledOffMask
00707     _ledStateShadow |= ledOnMask;
00708 
00709     // turn off blinking
00710     _blink0Shadow &= (~(ledOffMask) & 0xffff);
00711     _blink1Shadow &= (~(ledOffMask) & 0xffff);
00712 
00713     setLeds();
00714 }
00715 
00716 void EaLcdBoard::pca9532_setBlink0Period(uint8_t period)
00717 {
00718     uint8_t buf[2];
00719 
00720     buf[0] = LCDB_PCA9532_PSC0;
00721     buf[1] = period;
00722 
00723     _i2c.write(LCDB_PCA9532_I2C_ADDR, (char*)buf, 2);
00724 }
00725 
00726 void EaLcdBoard::pca9532_setBlink0Duty(uint8_t duty)
00727 {
00728     uint8_t buf[2];
00729     uint32_t tmp = duty;
00730     if (tmp > 100) {
00731         tmp = 100;
00732     }
00733 
00734     tmp = (255 * tmp)/100;
00735 
00736     buf[0] = LCDB_PCA9532_PWM0;
00737     buf[1] = tmp;
00738 
00739     _i2c.write(LCDB_PCA9532_I2C_ADDR, (char*)buf, 2);
00740 }
00741 
00742 void EaLcdBoard::pca9532_setBlink0Leds(uint16_t ledMask)
00743 {
00744     _blink0Shadow |= ledMask;
00745     setLeds();
00746 }
00747 
00748 void EaLcdBoard::setWriteProtect(bool enable)
00749 {
00750     if (enable) {
00751         pca9532_setLeds(0, LCDB_EEPROM_WP);
00752     } else {
00753         pca9532_setLeds(LCDB_EEPROM_WP, 0);
00754     }
00755 }
00756 
00757 void EaLcdBoard::set3V3Signal(bool enabled) {
00758     if (enabled) {
00759         pca9532_setLeds(LCDB_CTRL_3V3, 0);
00760     } else {
00761         pca9532_setLeds(0, LCDB_CTRL_3V3);
00762     }
00763 }
00764 
00765 void EaLcdBoard::set5VSignal(bool enabled) {
00766     if (enabled) {
00767         pca9532_setLeds(LCDB_CTRL_5V, 0);
00768     } else {
00769         pca9532_setLeds(0, LCDB_CTRL_5V);
00770     }
00771 }
00772 
00773 void EaLcdBoard::setDisplayEnableSignal(bool enabled) {
00774     if (!enabled) {
00775         pca9532_setLeds(LCDB_CTRL_DISP_EN, 0);
00776     } else {
00777         pca9532_setLeds(0, LCDB_CTRL_DISP_EN);
00778     }
00779 }
00780 
00781 void EaLcdBoard::setBacklightContrast(uint32_t value) {
00782 
00783     if (value > 100) return;
00784 
00785     pca9532_setBlink0Duty(100-value);
00786     pca9532_setBlink0Period(0);
00787     pca9532_setBlink0Leds(LCDB_CTRL_BL_C);
00788 }
00789 
00790 
00791 // convert string to integer
00792 static uint32_t str_to_uint(char* str, uint32_t len)
00793 {
00794     uint32_t val = 0;
00795 
00796     while(len > 0 && *str <= '9' && *str >= '0') {
00797         val = (val * 10) + (*str - '0');
00798         str++;
00799         len--;
00800     }
00801 
00802     return val;
00803 }
00804 
00805