displayls013b7dh03.c

Go to the documentation of this file.
00001 /**************************************************************************/
00018 #include <stdint.h>
00019 #include <stdbool.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 /* DISPLAY driver inclustions */
00025 #include "displayconfigall.h"
00026 #include "displaypal.h"
00027 #include "displaybackend.h"
00028 #include "displayls013b7dh03.h"
00029 
00032 /*******************************************************************************
00033  ********************************  DEFINES  ************************************
00034  ******************************************************************************/
00035 
00036 /* LS013B7DH03 SPI commands */
00037 #define LS013B7DH03_CMD_UPDATE     (0x01)
00038 #define LS013B7DH03_CMD_ALL_CLEAR  (0x04)
00039 
00040 /* Frequency of LCD polarity inversion. */
00041 #ifndef LS013B7DH03_POLARITY_INVERSION_FREQUENCY
00042 #define LS013B7DH03_POLARITY_INVERSION_FREQUENCY (64)
00043 #endif
00044 
00045 #ifdef USE_CONTROL_BYTES
00046 #define LS013B7DH03_CONTROL_BYTES     (2)
00047 #else
00048 #define LS013B7DH03_CONTROL_BYTES     (0)
00049 #endif
00050 
00051 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00052 
00053   #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00054     /* Static pool has been chosen for pixelmatix allocation.
00055        Disable the use of malloc for allocation of pixel matrices. */
00056     #undef USE_MALLOC
00057   #endif
00058 
00059   #ifdef USE_MALLOC
00060     /* malloc has been chosen for pixelmatix allocation.
00061        Disable the use of static pool for allocation of pixel matrices. */
00062     #undef USE_STATIC_PIXEL_MATRIX_POOL
00063   #endif
00064 
00065 #endif /*  PIXEL_MATRIX_ALLOC_SUPPORT  */
00066 
00067 
00068 /*******************************************************************************
00069  *********************************  TYPEDEFS  **********************************
00070  ******************************************************************************/
00071 
00072 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00073 #ifndef PIXEL_MATRIX_ALIGNMENT
00074 typedef uint8_t PixelMatrixAlign_t;
00075 #else
00076   #if (1 == PIXEL_MATRIX_ALIGNMENT)
00077     typedef uint8_t PixelMatrixAlign_t;
00078   #elif (2 == PIXEL_MATRIX_ALIGNMENT)
00079     typedef uint16_t PixelMatrixAlign_t;
00080   #elif (4 == PIXEL_MATRIX_ALIGNMENT)
00081     typedef uint32_t PixelMatrixAlign_t;
00082   #else
00083     #error Unsupported PIXEL_MATRIX_ALIGNMENT.
00084   #endif
00085 #endif
00086 #endif
00087 
00088 
00089 /*******************************************************************************
00090  ********************************  STATICS  ************************************
00091  ******************************************************************************/
00092 
00093 /* Static variables: */
00094 static uint8_t        lcdPolarity = 0;
00095 
00096 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00097 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00098 #define PIXEL_MATRIX_POOL_ELEMENTS                                \
00099   (PIXEL_MATRIX_POOL_SIZE/sizeof(PixelMatrixAlign_t) +            \
00100    ((PIXEL_MATRIX_POOL_SIZE%sizeof(PixelMatrixAlign_t))? 1 : 0))
00101 static PixelMatrixAlign_t  pixelMatrixPoolBase[PIXEL_MATRIX_POOL_ELEMENTS];
00102 static PixelMatrixAlign_t* pixelMatrixPool = pixelMatrixPoolBase;
00103 #endif
00104 #endif
00105 
00106 
00107 /*******************************************************************************
00108  ************************   STATIC FUNCTION PROTOTYPES   ***********************
00109  ******************************************************************************/
00110 
00111 static EMSTATUS DisplayEnable(DISPLAY_Device_t*     device,
00112                               bool enable);
00113 static EMSTATUS DisplayClear(void);
00114 #ifndef POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE
00115 static EMSTATUS DisplayPolarityInverse (void);
00116 #endif
00117 
00118 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00119 static EMSTATUS PixelMatrixAllocate( DISPLAY_Device_t*     device,
00120                                      unsigned int           width,
00121 #ifdef EMWIN_WORKAROUND
00122                                      unsigned int           userStride,
00123 #endif
00124                                      unsigned int           height,
00125                                      DISPLAY_PixelMatrix_t *pixelMatrix);
00126 static EMSTATUS PixelMatrixFree( DISPLAY_Device_t*     device,
00127                                  DISPLAY_PixelMatrix_t pixelMatrix);
00128 #endif
00129 static EMSTATUS PixelMatrixDraw( DISPLAY_Device_t*     device,
00130                                  DISPLAY_PixelMatrix_t pixelMatrix,
00131                                  unsigned int          startColumn,
00132                                  unsigned int          width,
00133 #ifdef EMWIN_WORKAROUND
00134                                  unsigned int          userStride,
00135 #endif
00136                                  unsigned int          startRow,
00137                                  unsigned int          height );
00138 static EMSTATUS PixelMatrixClear( DISPLAY_Device_t*      device,
00139                                   DISPLAY_PixelMatrix_t  pixelMatrix,
00140                                   unsigned int           width,
00141                                   unsigned int           height);
00142 static EMSTATUS DriverRefresh (DISPLAY_Device_t* device);
00143 
00144 
00145 /*******************************************************************************
00146  **************************     GLOBAL FUNCTIONS      **************************
00147  ******************************************************************************/
00148 
00149 /**************************************************************************/
00154 EMSTATUS DISPLAY_Ls013b7dh03Init(void)
00155 {
00156   DISPLAY_Device_t      display;
00157   EMSTATUS              status;
00158 
00159   /* Initialize the Platform Abstraction Layer (PAL) interface.  */
00160   PAL_TimerInit();
00161   PAL_SpiInit();
00162   PAL_GpioInit();
00163 
00164   /* Setup GPIOs */
00165   PAL_GpioPinModeSet(LCD_PORT_SCLK,    LCD_PIN_SCLK,    palGpioModePushPull,0);
00166   PAL_GpioPinModeSet(LCD_PORT_SI,      LCD_PIN_SI,      palGpioModePushPull,0);
00167   PAL_GpioPinModeSet(LCD_PORT_SCS,     LCD_PIN_SCS,     palGpioModePushPull,0);
00168   PAL_GpioPinModeSet(LCD_PORT_DISP_SEL,LCD_PIN_DISP_SEL,palGpioModePushPull,0);
00169 
00170 #if defined( LCD_PORT_DISP_PWR )
00171   PAL_GpioPinModeSet(LCD_PORT_DISP_PWR,LCD_PIN_DISP_PWR,palGpioModePushPull,0);
00172 #endif
00173 
00174   PAL_GpioPinModeSet(LCD_PORT_EXTMODE, LCD_PIN_EXTMODE, palGpioModePushPull,0);
00175   PAL_GpioPinModeSet(LCD_PORT_EXTCOMIN,LCD_PIN_EXTCOMIN,palGpioModePushPull,0);
00176 
00177 #ifdef PAL_TIMER_REPEAT_FUNCTION
00178   /* If the platform specifies to use a timer repeat function we should
00179      register the DisplayPolarityInverse to be called every second in
00180      order to toggle the EXTCOMIN pin at 1Hz.
00181   */
00182   status =
00183     PAL_TimerRepeat((void(*)(void*)) DisplayPolarityInverse, 0,
00184                     LS013B7DH03_POLARITY_INVERSION_FREQUENCY);
00185 #elif defined POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE
00186   /* Setup system (via PAL) to toggle the EXTCOMIN pin every second. */
00187   status = PAL_GpioPinAutoToggle(LCD_PORT_EXTCOMIN, LCD_PIN_EXTCOMIN,
00188                                  LS013B7DH03_POLARITY_INVERSION_FREQUENCY);
00189 #else
00190   /* System does not support toggling the EXTCOMIN pin. Return error. */
00191   return DISPLAY_EMSTATUS_NOT_SUPPORTED;
00192 #endif
00193   if (PAL_EMSTATUS_OK != status)
00194   {
00195     return status;
00196   }
00197 
00198   /* Setup and register the LS013B7DH03 as a DISPLAY device now. */
00199   display.name                  = SHARP_MEMLCD_DEVICE_NAME;
00200   display.colourMode            = DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE;
00201   display.addressMode           = DISPLAY_ADDRESSING_BY_ROWS_ONLY;
00202   display.geometry.width        = LS013B7DH03_WIDTH;
00203   display.geometry.height       = LS013B7DH03_HEIGHT;
00204   /* stride = pixels + ctrl bytes */
00205   display.geometry.stride       =
00206     display.geometry.width + LS013B7DH03_CONTROL_BYTES*8;
00207 
00208   display.pDisplayPowerOn       = DisplayEnable;
00209 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00210   display.pPixelMatrixAllocate  = PixelMatrixAllocate;
00211   display.pPixelMatrixFree      = PixelMatrixFree;
00212 #else
00213   display.pPixelMatrixAllocate  = NULL;
00214   display.pPixelMatrixFree      = NULL;
00215 #endif
00216   display.pPixelMatrixDraw      = PixelMatrixDraw;
00217   display.pPixelMatrixClear     = PixelMatrixClear;
00218   display.pDriverRefresh        = DriverRefresh;
00219 
00220   status = DISPLAY_DeviceRegister (&display);
00221 
00222   if (DISPLAY_EMSTATUS_OK == status)
00223   {
00224     /* Turn on display. */
00225     DisplayEnable(&display, true);
00226 
00227     /* Clear display */
00228     DisplayClear();
00229   }
00230 
00231   return status;
00232 }
00233 
00234 
00235 /*******************************************************************************
00236  *****************************   STATIC FUNCTIONS   ****************************
00237  ******************************************************************************/
00238 
00239 /**************************************************************************/
00246 static EMSTATUS DriverRefresh(DISPLAY_Device_t* device)
00247 {
00248   EMSTATUS      status = DISPLAY_EMSTATUS_OK;
00249 
00250   (void) device; /* Suppress compiler warning: unused parameter. */
00251 
00252   /* Reinitialize the timer and SPI configuration.  */
00253   PAL_TimerInit();
00254   PAL_SpiInit();
00255 
00256   return status;
00257 }
00258 
00259 
00260 /**************************************************************************/
00273 static EMSTATUS DisplayEnable(DISPLAY_Device_t* device,
00274                               bool              enable)
00275 {
00276   (void) device; /* Suppress compiler warning: unused parameter. */
00277 
00278   if (enable)
00279   {
00280     /* Set EFM_DISP_SELECT pin. */
00281     PAL_GpioPinOutSet(LCD_PORT_DISP_SEL, LCD_PIN_DISP_SEL);
00282 
00283 #if defined( LCD_PORT_DISP_PWR )
00284     /* Drive voltage on EFM_DISP_PWR_EN pin. */
00285     PAL_GpioPinOutSet(LCD_PORT_DISP_PWR, LCD_PIN_DISP_PWR);
00286 #endif
00287   }
00288   else
00289   {
00290 #if defined( LCD_PORT_DISP_PWR )
00291     /* Stop driving voltage on EFM_DISP_PWR_EN pin. */
00292     PAL_GpioPinOutClear(LCD_PORT_DISP_PWR, LCD_PIN_DISP_PWR);
00293 #endif
00294 
00295     /* Clear EFM_DISP_SELECT pin. */
00296     PAL_GpioPinOutClear(LCD_PORT_DISP_SEL, LCD_PIN_DISP_SEL);
00297   }
00298 
00299   return DISPLAY_EMSTATUS_OK;
00300 }
00301 
00302 
00303 /**************************************************************************/
00310 static EMSTATUS DisplayClear ( void )
00311 {
00312   uint16_t cmd;
00313 
00314   /* Set SCS */
00315   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00316 
00317   /* SCS setup time: min 6us */
00318   PAL_TimerMicroSecondsDelay(6);
00319 
00320   /* Send command */
00321   cmd = LS013B7DH03_CMD_ALL_CLEAR | lcdPolarity;
00322   PAL_SpiTransmit ((uint8_t*) &cmd, 2 );
00323 
00324   /* SCS hold time: min 2us */
00325   PAL_TimerMicroSecondsDelay(2);
00326 
00327   /* Clear SCS */
00328   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00329 
00330   return DISPLAY_EMSTATUS_OK;
00331 }
00332 
00333 
00334 #ifdef PAL_TIMER_REPEAT_FUNCTION
00335 
00336 /**************************************************************************/
00344 static EMSTATUS DisplayPolarityInverse (void)
00345 {
00346 #ifdef POLARITY_INVERSION_EXTCOMIN
00347 
00348   /* Toggle extcomin gpio */
00349   PAL_GpioPinOutToggle( LCD_PORT_EXTCOMIN, LCD_PIN_EXTCOMIN );
00350 
00351 #else /* POLARITY_INVERSION_EXTCOMIN */
00352 
00353   /* Send a packet with inverted com */
00354   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00355 
00356   /* SCS setup time: min 6us */
00357   PAL_TimerMicroSecondsDelay(6);
00358 
00359   /* Send polarity command including dummy bits */
00360   PAL_SpiTransmit ((uint8_t*) &lcdPolarity, 2 );
00361 
00362   /* SCS hold time: min 2us */
00363   PAL_TimerMicroSecondsDelay(2);
00364 
00365   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00366 
00367   /* Invert com polarity */
00368   if (lcdPolarity == 0x00)
00369   {
00370     lcdPolarity = 0x02;
00371   }
00372   else
00373   {
00374     lcdPolarity = 0x00;
00375   }
00376 
00377 #endif /* POLARITY_INVERSION_EXTCOMIN */
00378 
00379   return DISPLAY_EMSTATUS_OK;
00380 }
00381 
00382 #endif /* POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE */
00383 
00384 
00385 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00386 /**************************************************************************/
00404 static EMSTATUS PixelMatrixAllocate( DISPLAY_Device_t*      device,
00405                                      unsigned int           width,
00406 #ifdef EMWIN_WORKAROUND
00407                                      unsigned int           userStride,
00408 #endif
00409                                      unsigned int           height,
00410                                      DISPLAY_PixelMatrix_t *pixelMatrix)
00411 {
00412 #ifdef EMWIN_WORKAROUND
00413   unsigned int allocSize = (userStride/8 + LS013B7DH03_CONTROL_BYTES) * height;
00414 #else
00415   unsigned int allocSize = (width/8 + LS013B7DH03_CONTROL_BYTES) * height;
00416 #endif
00417 
00418   (void) device; /* Suppress compiler warning: unused parameter. */
00419 
00420   if (width != LS013B7DH03_WIDTH)
00421     return DISPLAY_EMSTATUS_OUT_OF_RANGE;
00422 #ifdef EMWIN_WORKAROUND
00423   if (userStride < width)
00424     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00425 #endif
00426 
00427 #ifdef USE_MALLOC
00428 
00429   /* Allocate the pixel matrix buffer including 2 control bytes per line. */
00430   *pixelMatrix = (DISPLAY_PixelMatrix_t) malloc (allocSize);
00431 
00432   if (NULL == *pixelMatrix)
00433     return DISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY;
00434   else
00435     return DISPLAY_EMSTATUS_OK;
00436 
00437 #endif /* USE_MALLOC */
00438 
00439 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00440 
00441   if (((uint8_t*)pixelMatrixPool)     + allocSize >
00442       ((uint8_t*)pixelMatrixPoolBase) + PIXEL_MATRIX_POOL_SIZE)
00443   {
00444     *pixelMatrix     = NULL;
00445     return DISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY;
00446   }
00447   else
00448   {
00449     *pixelMatrix     = pixelMatrixPool;
00450     pixelMatrixPool += allocSize / sizeof(PixelMatrixAlign_t) +
00451       ((allocSize % sizeof(PixelMatrixAlign_t))? 1 : 0);
00452     return DISPLAY_EMSTATUS_OK;
00453   }
00454 
00455 #endif /* USE_STATIC_PIXEL_MATRIX_POOL */
00456 
00457 }
00458 #endif /* PIXEL_MATRIX_ALLOC_SUPPORT */
00459 
00460 
00461 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00462 /**************************************************************************/
00472 static EMSTATUS PixelMatrixFree( DISPLAY_Device_t*     device,
00473                                  DISPLAY_PixelMatrix_t pixelMatrix)
00474 {
00475   (void) device; /* Suppress compiler warning: unused parameter. */
00476 
00477 #ifdef USE_MALLOC
00478   free(pixelMatrix);
00479   return DISPLAY_EMSTATUS_OK;
00480 #endif /* USE_MALLOC */
00481 
00482 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00483   /* The non-malloc PixelMatrixAllocate function only allocates buffers
00484      consequtively from a pool. It is not possible to free the buffers.
00485      I.e. this allocator can only be used for one-shot allocations of
00486      buffers that will should never be freed and re-alloced.
00487   */
00488   (void) pixelMatrix;   /* Supress compiles warning: unused parameter. */
00489   return DISPLAY_EMSTATUS_NOT_SUPPORTED;
00490 #endif
00491 }
00492 #endif /* PIXEL_MATRIX_ALLOC_SUPPORT */
00493 
00494 
00495 /**************************************************************************/
00512 static EMSTATUS PixelMatrixClear( DISPLAY_Device_t*      device,
00513                                   DISPLAY_PixelMatrix_t  pixelMatrix,
00514                                   unsigned int           width,
00515                                   unsigned int           height)
00516 {
00517   uint8_t*       pByte = (uint8_t*) pixelMatrix;
00518   unsigned int   i;
00519 
00520   (void) device; /* Suppress compiler warning: unused parameter. */
00521   (void) width;  /* Suppress compiler warning: unused parameter. */
00522 
00523   for (i=0; i<height; i++)
00524   {
00525     /* Clear line */
00526     memset(pByte, 0, LS013B7DH03_WIDTH/8);
00527     pByte += LS013B7DH03_WIDTH/8;
00528 
00529 #ifdef USE_CONTROL_BYTES
00530     /* Set dummy byte. */
00531     *pByte++ = 0xff;
00532     /* Set address of next line */
00533     *pByte++ = i+1;
00534 #endif
00535   }
00536 
00537   return DISPLAY_EMSTATUS_OK;
00538 }
00539 
00540 
00541 #ifdef USE_CONTROL_BYTES
00542 /**************************************************************************/
00553 static EMSTATUS pixelMatrixSetup( DISPLAY_PixelMatrix_t  pixelMatrix,
00554                                   unsigned int           startRow,
00555                                   unsigned int           height
00556 #ifdef EMWIN_WORKAROUND
00557                                   ,
00558                                   unsigned int           userStride
00559 #endif
00560                                   )
00561 {
00562   int       i          = 0;
00563   uint8_t*  pByte      = (uint8_t*) pixelMatrix;
00564 #ifdef EMWIN_WORKAROUND
00565   int       strideGap  =
00566     (userStride-LS013B7DH03_WIDTH-(LS013B7DH03_CONTROL_BYTES*8)) /
00567     8 / sizeof(uint8_t);
00568   if ((userStride-LS013B7DH03_WIDTH) % sizeof(uint16_t))
00569     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00570 #endif
00571 
00572   while (i<height)
00573   {
00574     pByte += LS013B7DH03_WIDTH/8;
00575     /* Set dummy byte. */
00576     *pByte++ = 0xff;
00577 
00578     if (i == height-1)
00579     {
00580       /* Set dummy data at end of last line. */
00581       *pByte++ = 0xff;
00582       break;
00583     }
00584     else
00585       /* Set address of next line */
00586       *pByte++ = startRow + (++i);
00587 
00588 #ifdef EMWIN_WORKAROUND
00589     pByte += strideGap;
00590 #endif
00591   }
00592 
00593   return DISPLAY_EMSTATUS_OK;
00594 }
00595 
00596 #endif /* USE_CONTROL_BYTES */
00597 
00598 
00599 /**************************************************************************/
00616 static EMSTATUS PixelMatrixDraw( DISPLAY_Device_t*      device,
00617                                  DISPLAY_PixelMatrix_t  pixelMatrix,
00618                                  unsigned int           startColumn,
00619                                  unsigned int           width,
00620 #ifdef EMWIN_WORKAROUND
00621                                  unsigned int           userStride,
00622 #endif
00623                                  unsigned int           startRow,
00624                                  unsigned int           height )
00625 {
00626   unsigned int i;
00627   uint16_t*    p = (uint16_t *)pixelMatrix;
00628   uint16_t     cmd;
00629 #ifdef EMWIN_WORKAROUND
00630   int          strideGap =
00631     (userStride-width-(LS013B7DH03_CONTROL_BYTES*8)) / 8 / sizeof(uint16_t);
00632   if ((userStride-width) % sizeof(uint16_t))
00633     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00634 #else
00635   (void) width;  /* Suppress compiler warning: unused parameter. */
00636 #endif
00637   (void) startColumn;  /* Suppress compiler warning: unused parameter. */
00638   (void) device; /* Suppress compiler warning: unused parameter. */
00639 
00640   /* Need to adjust start row by one because LS013B7DH03 starts counting lines
00641      from 1, while the DISPLAY interface starts from 0. */
00642   startRow++;
00643 
00644 #ifdef USE_CONTROL_BYTES
00645   /* Setup line addressing in control words. */
00646   pixelMatrixSetup(pixelMatrix, startRow, height
00647 #ifdef EMWIN_WORKAROUND
00648                    , userStride
00649 #endif
00650                    );
00651 #endif
00652 
00653   /* Assert SCS */
00654   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00655 
00656   /* SCS setup time: min 6us */
00657   PAL_TimerMicroSecondsDelay(6);
00658 
00659   /* Send update command and first line address */
00660   cmd = LS013B7DH03_CMD_UPDATE | (startRow << 8);
00661   PAL_SpiTransmit((uint8_t*) &cmd, 2 );
00662 
00663   /* Get start address to draw from */
00664   for ( i=0; i<height; i++ ) {
00665 
00666     /* Send pixels for this line */
00667     PAL_SpiTransmit((uint8_t*) p,
00668                     LS013B7DH03_WIDTH/8 + LS013B7DH03_CONTROL_BYTES);
00669     p+=(LS013B7DH03_WIDTH/8 + LS013B7DH03_CONTROL_BYTES) / sizeof(uint16_t);
00670 
00671 #ifndef USE_CONTROL_BYTES
00672     if (i==height-1)
00673     {
00674       cmd = 0xffff;
00675     }
00676     else
00677     {
00678       cmd = 0xff | ((startRow+i+1) << 8);
00679     }
00680     PAL_SpiTransmit((uint8_t*) &cmd, 2 );
00681 #endif
00682 
00683 #ifdef EMWIN_WORKAROUND
00684     p += strideGap;
00685 #endif
00686 
00687   }
00688 
00689   /* SCS hold time: min 2us */
00690   PAL_TimerMicroSecondsDelay(2);
00691 
00692   /* De-assert SCS */
00693   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00694 
00695   return DISPLAY_EMSTATUS_OK;
00696 }
00697