textdisplay.c

Go to the documentation of this file.
00001 /***************************************************************************/
00017 #include <stdint.h>
00018 #include <stdbool.h>
00019 #include <stdlib.h>
00020 #include <stdio.h>
00021 #include <string.h>
00022 #include <ctype.h>
00023 
00024 #include "displayconfigall.h"
00025 #include "display.h"
00026 #include "textdisplay.h"
00027 
00028 #ifdef TEXTDISPLAY_FONT_8x8
00029 #include "displayfont8x8.h"
00030 #define FONT_ASCII_START  (' ')
00031 #define FONT_CHARACTERS   (100)
00032 #define FONT_BITS_MASK    (0x7)
00033 #define FONT_BITS_LOG2      (3)
00034 #define fontBits chars_8x8_bits
00035 #endif
00036 
00037 #ifdef TEXTDISPLAY_FONT_6x8
00038 #include "displayfont6x8.h"
00039 #define FONT_ASCII_START  (' ')
00040 #define FONT_CHARACTERS   (100)
00041 #define FONT_BITS_MASK    (0x7)
00042 #define FONT_BITS_LOG2      (3)
00043 #define fontBits chars_6x8_bits
00044 #endif
00045 
00046 #ifdef TEXTDISPLAY_NUMBER_FONT_16x20
00047 #include "displayfont16x20.h"
00048 #define FONT_ASCII_START  ('0')
00049 #define FONT_CHARACTERS    (12)
00050 #define FONT_BITS_MASK    (0xF)
00051 #define FONT_BITS_LOG2      (4)
00052 #define fontBits numbers_16x20_bits
00053 #endif
00054 
00055 
00058 /*******************************************************************************
00059  *******************************  TYPEDEFS   ***********************************
00060  ******************************************************************************/
00061 
00062 typedef enum TEXTDISPLAY_UpdateMode_t
00063 {
00064   TEXTDISPLAY_UPDATE_MODE_FULL,
00065   TEXTDISPLAY_UPDATE_MODE_LINE,
00066   TEXTDISPLAY_UPDATE_MODE_CHAR,
00067   TEXTDISPLAY_UPDATE_MODE_NONE
00068 } TEXTDISPLAY_UpdateMode_t;
00069 
00070 
00071 typedef struct TEXTDISPLAY_Device_t
00072 {
00073   int               displayDeviceNo;    /* Display device number to initialize
00074                                            test display on. */
00075   DISPLAY_Device_t  displayDevice;      /* Display properties. */
00076   
00077   unsigned int      columns;            /* Number of columns to use. */
00078   unsigned int      lines;              /* Number of lines to use. */
00079   
00080   bool              scrollEnable;       /* Enable/disable scrolling mode on the
00081                                            text display. Scrolling mode will
00082                                            consume more memory because the lines
00083                                            lines will have to be stored in
00084                                            memory. */
00085   
00086   bool                     lfToCrLf;    
00089   DISPLAY_PixelMatrix_t    lineBuffer;  
00092   char*                    charBuffer;  
00093   char**                   charArray;   
00095   uint8_t                  rgbColor[3]; 
00097   unsigned int             xpos;        
00098   unsigned int             ypos;        
00100   TEXTDISPLAY_UpdateMode_t updateMode;  
00102   bool                     initialized; 
00104 } TEXTDISPLAY_Device_t;
00105 
00106 
00107 typedef struct TEXTDISPLAY_CharBuffers_t
00108 {
00109   unsigned int    lines;         
00110   unsigned int    columns;       
00112   char*           charBuffer;    
00113   char**          charArray;     
00114 } TEXTDISPLAY_CharBuffers_t;
00115 
00116 
00117 /*******************************************************************************
00118  *******************************   STATICS   ***********************************
00119  ******************************************************************************/
00120 
00121 /* Table of text display device structures. */
00122 static TEXTDISPLAY_Device_t textdisplayTbl[TEXTDISPLAY_DEVICES_MAX];
00123 
00124 
00125 /* Static Character buffers */
00126 char  charBufferDevice0[TEXTDISPLAY_DEVICE_0_LINES * TEXTDISPLAY_DEVICE_0_COLUMNS];
00127 char* charArrayDevice0[TEXTDISPLAY_DEVICE_0_LINES];
00128 
00129 #if (TEXTDISPLAY_DEVICES_MAX == 2)
00130 char  charBufferDevice1[TEXTDISPLAY_DEVICE_1_LINES * TEXTDISPLAY_DEVICE_1_COLUMNS];
00131 char* charArrayDevice1[TEXTDISPLAY_DEVICE_1_LINES];
00132 #endif
00133 
00134 #if (TEXTDISPLAY_DEVICES_MAX == 3)
00135 char  charBufferDevice2[TEXTDISPLAY_DEVICE_2_LINES * TEXTDISPLAY_DEVICE_2_COLUMNS];
00136 char* charArrayDevice2[TEXTDISPLAY_DEVICE_2_LINES];
00137 #endif
00138 
00139 #if (TEXTDISPLAY_DEVICES_MAX == 4)
00140 char  charBufferDevice3[TEXTDISPLAY_DEVICE_3_LINES * TEXTDISPLAY_DEVICE_3_COLUMNS];
00141 char* charArrayDevice3[TEXTDISPLAY_DEVICE_3_LINES];
00142 #endif
00143 
00144 
00145 static TEXTDISPLAY_CharBuffers_t charBufferTbl[TEXTDISPLAY_DEVICES_MAX] =
00146   {
00147     {
00148       TEXTDISPLAY_DEVICE_0_LINES,
00149       TEXTDISPLAY_DEVICE_0_COLUMNS,
00150       charBufferDevice0,
00151       charArrayDevice0
00152     },
00153 #if (TEXTDISPLAY_DEVICES_MAX == 2)
00154     {
00155       TEXTDISPLAY_DEVICE_1_LINES,
00156       TEXTDISPLAY_DEVICE_1_COLUMNS,
00157       charBufferDevice1,
00158       charArrayDevice1
00159     },
00160 #endif
00161 #if (TEXTDISPLAY_DEVICES_MAX == 3)
00162     {
00163       TEXTDISPLAY_DEVICE_2_LINES,
00164       TEXTDISPLAY_DEVICE_2_COLUMNS,
00165       charBufferDevice2,
00166       charArrayDevice2
00167     },
00168 #endif    
00169 #if (TEXTDISPLAY_DEVICES_MAX == 4)
00170     {
00171       TEXTDISPLAY_DEVICE_3_LINES,
00172       TEXTDISPLAY_DEVICE_3_COLUMNS,
00173       charBufferDevice3,
00174       charArrayDevice3
00175     },
00176 #endif    
00177   };
00178 
00179 
00180 /*******************************************************************************
00181  ************************   STATIC FUNCTION PROTOTYPES   ***********************
00182  ******************************************************************************/
00183 
00184 /* Static functions: */
00185 static void TextdisplayClear    (TEXTDISPLAY_Device_t*  textdisplay);
00186 static void TextdisplayScrollUp (TEXTDISPLAY_Device_t*  textdisplay);
00187 static void TextdisplayCharAdd  (TEXTDISPLAY_Device_t*  textdisplay,
00188                                  int                    c);
00189 static EMSTATUS TextdisplayLineDraw (TEXTDISPLAY_Device_t*  textdisplay,
00190                                      unsigned int           y);
00191 static EMSTATUS TextdisplayUpdate   (TEXTDISPLAY_Device_t*  textdisplay);
00192 
00196 /*******************************************************************************
00197  **************************     GLOBAL FUNCTIONS      **************************
00198  ******************************************************************************/
00199 
00200 /**************************************************************************/
00210 EMSTATUS TEXTDISPLAY_New(TEXTDISPLAY_Config_t  *config,
00211                          TEXTDISPLAY_Handle_t  *handle)
00212 {
00213   TEXTDISPLAY_Device_t*    textdisplay;
00214   int                      deviceNo;
00215   unsigned int             i;
00216   EMSTATUS                 status;
00217 
00218   /* Find unused text display device structure. */
00219   for (textdisplay=NULL,
00220          deviceNo=0; deviceNo<TEXTDISPLAY_DEVICES_MAX; deviceNo++)
00221   {
00222     if (false == textdisplayTbl[deviceNo].initialized)
00223     {
00224       textdisplay = &textdisplayTbl[deviceNo];
00225       break;
00226     }
00227   }
00228   if (NULL == textdisplay)
00229   {
00230     return TEXTDISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY;
00231   }
00232 
00233   /* Retrieve the properties of the DISPLAY. */
00234   status =
00235     DISPLAY_DeviceGet(config->displayDeviceNo, &textdisplay->displayDevice);
00236   if (DISPLAY_EMSTATUS_OK != status)
00237     return status;
00238 
00239   /* If the display address mode is DISPLAY_ADDRESSING_BY_ROWS_ONLY we need
00240      a buffer to draw the current line with new characters as they arrive. */
00241   if (DISPLAY_ADDRESSING_BY_ROWS_ONLY == textdisplay->displayDevice.addressMode)
00242   {
00243     status =
00244       textdisplay->displayDevice.
00245       pPixelMatrixAllocate (&textdisplay->displayDevice,
00246                             textdisplay->displayDevice.geometry.width,
00247 #ifdef EMWIN_WORKAROUND
00248                             textdisplay->displayDevice.geometry.width,
00249 #endif
00250                             FONT_HEIGHT,
00251                             &textdisplay->lineBuffer);
00252     if (DISPLAY_EMSTATUS_OK != status)
00253       return status;
00254 
00255     status =
00256       textdisplay->displayDevice.
00257       pPixelMatrixClear (&textdisplay->displayDevice,
00258                          textdisplay->lineBuffer,
00259                          textdisplay->displayDevice.geometry.width,
00260                          FONT_HEIGHT);
00261                                                       
00262     if (DISPLAY_EMSTATUS_OK != status)
00263       return status;
00264   }
00265   else
00266   {
00267     textdisplay->lineBuffer = NULL;
00268   }
00269 
00270   /* Check that the requested number of text rows and columns fits inside the
00271      geometry of the display device. */
00272   if (charBufferTbl[deviceNo].lines >
00273       textdisplay->displayDevice.geometry.height / FONT_HEIGHT)
00274     return TEXTDISPLAY_EMSTATUS_OUT_OF_RANGE;
00275   if (charBufferTbl[deviceNo].columns >
00276       textdisplay->displayDevice.geometry.width / FONT_WIDTH)
00277     return TEXTDISPLAY_EMSTATUS_OUT_OF_RANGE;
00278 
00279   /* Remember the character buffer parameters. */
00280   textdisplay->lines      = charBufferTbl[deviceNo].lines;
00281   textdisplay->columns    = charBufferTbl[deviceNo].columns;
00282   textdisplay->charBuffer = charBufferTbl[deviceNo].charBuffer;
00283   textdisplay->charArray  = charBufferTbl[deviceNo].charArray;
00284 
00285   /* Store user configuration options */
00286   textdisplay->displayDeviceNo   = config->displayDeviceNo;
00287   textdisplay->scrollEnable      = config->scrollEnable;
00288   textdisplay->lfToCrLf          = config->lfToCrLf;
00289 
00290   /* Setup char pointer array */
00291   for (i=0; i<textdisplay->lines; i++)
00292     textdisplay->charArray[i] =
00293       textdisplay->charBuffer + textdisplay->columns * i;
00294   
00295   /* Initialize color for text */
00296   /* Use \b for red text (bell/warning) */
00297   textdisplay->rgbColor[0]       = 0xff;
00298   textdisplay->rgbColor[1]       = 0xff;
00299   textdisplay->rgbColor[2]       = 0xff;
00300   
00301   /* Clear character buffer */
00302   TextdisplayClear(textdisplay);
00303 
00304   textdisplay->initialized      = true;
00305 
00306   *handle = (TEXTDISPLAY_Handle_t*) textdisplay;
00307 
00308   return TEXTDISPLAY_EMSTATUS_OK;
00309 }
00310 
00311 
00312 /**************************************************************************/
00322 EMSTATUS TEXTDISPLAY_Delete(TEXTDISPLAY_Handle_t  handle)
00323 {
00324   TEXTDISPLAY_Device_t*  textdisplay = (TEXTDISPLAY_Device_t*) handle;
00325 
00326   if (textdisplay->initialized)
00327   {
00328     textdisplay->charBuffer = NULL;
00329     textdisplay->charArray = NULL;
00330 
00331     if (textdisplay->lineBuffer)
00332     {
00333       textdisplay->displayDevice.pPixelMatrixFree (&textdisplay->displayDevice,
00334                                                    textdisplay->lineBuffer);
00335       textdisplay->lineBuffer = NULL;
00336     }
00337 
00338     /* Clear display device number to allow reinitialization of this display.*/
00339     textdisplay->displayDeviceNo = -1;
00340 
00341     textdisplay->initialized = false;
00342    
00343     return TEXTDISPLAY_EMSTATUS_OK;
00344   }
00345 
00346   return TEXTDISPLAY_EMSTATUS_INVALID_PARAM;
00347 }
00348 
00349 
00350 /**************************************************************************/
00361 EMSTATUS TEXTDISPLAY_LfToCrLf(TEXTDISPLAY_Handle_t  handle,
00362                               bool                  on)
00363 {
00364   TEXTDISPLAY_Device_t*  textdisplay = (TEXTDISPLAY_Device_t*) handle;
00365   
00366   textdisplay->lfToCrLf = on;
00367   
00368   return TEXTDISPLAY_EMSTATUS_OK;
00369 }
00370 
00371 
00372 /**************************************************************************/
00381 EMSTATUS TEXTDISPLAY_WriteChar(TEXTDISPLAY_Handle_t  handle,
00382                                char                  c)
00383 {
00384   TEXTDISPLAY_Device_t*  textdisplay = (TEXTDISPLAY_Device_t*) handle;
00385 
00386   /* Check that we are initialized. */
00387   if (false == textdisplay->initialized)
00388   {
00389     return TEXTDISPLAY_EMSTATUS_NOT_INITIALIZED;
00390   }
00391 
00392   /* Determine initial display update mode. */
00393   if (DISPLAY_ADDRESSING_BY_ROWS_ONLY == textdisplay->displayDevice.addressMode)
00394   {
00395     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_LINE;
00396   }
00397   else
00398   {      
00399     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_CHAR;
00400   }
00401 
00402   if (textdisplay->scrollEnable)
00403   {
00404     /* Update the full screen (which has been scrolled up) if we start at the
00405        bottom left position and scroll is enabled. */
00406     if ((0==textdisplay->xpos) && (textdisplay->ypos == textdisplay->lines-1))
00407     {
00408       textdisplay->updateMode  = TEXTDISPLAY_UPDATE_MODE_FULL;
00409     }
00410   }
00411   else
00412   {
00413     /* Update the full screen (which is cleared) if we start at top left
00414        position and scroll is not enabled. */
00415     if ((0==textdisplay->xpos) && (0==textdisplay->ypos))
00416     {
00417       textdisplay->updateMode  = TEXTDISPLAY_UPDATE_MODE_FULL;
00418     }
00419   }
00420 
00421   /* Check for form feed - clear screen */
00422   if (c == '\f')
00423   {
00424     TextdisplayClear(textdisplay);
00425     /* Update the whole display and return. */
00426     textdisplay->updateMode  = TEXTDISPLAY_UPDATE_MODE_FULL;
00427     return TextdisplayUpdate(textdisplay);
00428   }
00429 
00430   /* Add CR or LF to CRLF if enabled */
00431   if (textdisplay->lfToCrLf && (c == '\n'))
00432   {
00433     TextdisplayCharAdd(textdisplay, '\r');
00434   }
00435   TextdisplayCharAdd(textdisplay, c);
00436 
00437   if (TEXTDISPLAY_UPDATE_MODE_NONE != textdisplay->updateMode)
00438     /* Update display and return. */
00439     return TextdisplayUpdate(textdisplay);
00440   else
00441     return TEXTDISPLAY_EMSTATUS_OK;
00442 }
00443 
00444 
00445 /**************************************************************************/
00454 EMSTATUS TEXTDISPLAY_WriteString(TEXTDISPLAY_Handle_t  handle,
00455                                  char*                 str)
00456 {
00457   TEXTDISPLAY_Device_t*  textdisplay = (TEXTDISPLAY_Device_t*) handle;
00458   EMSTATUS               status;
00459   char                   c;
00460   bool                   displayUpdated=false;
00461 
00462   /* Check that we are initialized. */
00463   if (false == textdisplay->initialized)
00464   {
00465     return TEXTDISPLAY_EMSTATUS_NOT_INITIALIZED;
00466   }
00467 
00468   /* Determine initial display update mode. */
00469   if (DISPLAY_ADDRESSING_BY_ROWS_ONLY == textdisplay->displayDevice.addressMode)
00470   {
00471     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_LINE;
00472   }
00473   else
00474   {      
00475     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_CHAR;
00476   }
00477 
00478   while (*str)
00479   {
00480     /* Mark display as NOT updated. */
00481     displayUpdated = false;
00482 
00483     /* Clear screen if we start at top left position and scroll is not
00484        enabled. */
00485     if ((0==textdisplay->xpos) && (0==textdisplay->ypos) &&
00486         (false == textdisplay->scrollEnable))
00487     {
00488       TextdisplayClear(textdisplay);
00489       textdisplay->updateMode  = TEXTDISPLAY_UPDATE_MODE_FULL;
00490     }
00491 
00492     c = *str;
00493 
00494     switch (c)
00495     {
00496     case '\f':
00497       /* Form feed - clear screen */
00498       TextdisplayClear(textdisplay);
00499       textdisplay->updateMode  = TEXTDISPLAY_UPDATE_MODE_FULL;
00500       break;
00501 
00502     case '\n':
00503       /* Update display before proceeding to the next line. */
00504       status = TextdisplayUpdate(textdisplay);
00505       if (status != TEXTDISPLAY_EMSTATUS_OK)
00506         return status;
00507 
00508       displayUpdated = true;
00509 
00510       /* Add CR or LF to CRLF if enabled */
00511       if (textdisplay->lfToCrLf)
00512       {
00513         TextdisplayCharAdd(textdisplay, '\r');
00514       }
00515 
00516       TextdisplayCharAdd(textdisplay, c);
00517       break;
00518 
00519     default:
00520       TextdisplayCharAdd(textdisplay, c);
00521       break;
00522     }
00523 
00524     /* Update display if we reach the end of the line or a full display update
00525        is required. */
00526     if ((textdisplay->xpos >= textdisplay->columns) ||
00527         (textdisplay->updateMode == TEXTDISPLAY_UPDATE_MODE_FULL))
00528     {
00529       status = TextdisplayUpdate(textdisplay);
00530       if (status != TEXTDISPLAY_EMSTATUS_OK)
00531         return status;
00532       displayUpdated = true;
00533     }
00534 
00535     str++;
00536   }
00537 
00538   /* Update display if not updated. */
00539   if (!displayUpdated)
00540     return TextdisplayUpdate(textdisplay);
00541   else
00542     return TEXTDISPLAY_EMSTATUS_OK;
00543 }
00544 
00545 
00548 /*******************************************************************************
00549  ****************************   STATIC FUNCTIONS   *****************************
00550  ******************************************************************************/
00551 
00552 /**************************************************************************/
00557 static void TextdisplayClear(TEXTDISPLAY_Device_t* textdisplay)
00558 {
00559   if (textdisplay->charArray)
00560   {
00561 
00562 #if (FONT_ASCII_START>' ') || (FONT_ASCII_START+FONT_CHARACTERS<' ')
00563     /* The font does not include the space character at the standard position
00564        according to the ascii table. Then the pace should be placed at the
00565        "end" of the font table. */
00566     memset(textdisplay->charBuffer, FONT_CHARACTERS - 1,
00567            textdisplay->lines * textdisplay->columns);
00568 #else
00569     memset(textdisplay->charBuffer, 0,
00570            textdisplay->lines * textdisplay->columns);
00571 #endif
00572 
00573     /* Set cursor position to upper left */
00574     textdisplay->xpos = 0;
00575     textdisplay->ypos = 0;
00576 
00577     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_FULL;
00578   }
00579 }
00580 
00581 
00582 /**************************************************************************/
00587 static void TextdisplayScrollUp(TEXTDISPLAY_Device_t*  textdisplay)
00588 {
00589   unsigned int y;
00590 
00591   /* copy all lines one line up */
00592   for (y = 0; y < (textdisplay->lines - 1); y++)
00593   {
00594     memcpy(textdisplay->charArray[y],
00595            textdisplay->charArray[y + 1],
00596            textdisplay->columns);
00597   }
00598 
00599   /* clear last line */
00600   memset(&textdisplay->charArray[textdisplay->lines - 1][0],
00601          0,
00602          textdisplay->columns);
00603 
00604   textdisplay->xpos       = 0;
00605   textdisplay->ypos       = textdisplay->lines - 1;
00606   textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_FULL;
00607 }
00608 
00609 
00610 #ifdef INCLUDE_VIDEO_TERMINAL_ESCAPE_SEQUENCE_SUPPORT
00611 /**************************************************************************/
00622 static bool TextdisplayEscapeSequence(TEXTDISPLAY_Device_t* textdisplay,
00623                                       int                   c)
00624 {
00625 #define ASCII_ESC                           (27)
00626 #define ESC_SEQ_SIZE_MAX                     (4)
00627 #define ESC_SEQ_MAX                          (6)
00628   static char escapeSequence[ESC_SEQ_SIZE_MAX]= {0,0,0,0};
00629   static const char escapeSequences[ESC_SEQ_MAX][ESC_SEQ_SIZE_MAX] =
00630   {
00631     /* Do not change the order of the escape sequences in the table below,
00632      and make sure they correspond to the TEXTDISPLAY_ESC_SEQNO_XXX contants
00633      below. */
00634     TEXTDISPLAY_ESC_SEQ_CURSOR_HOME_VT100,
00635     TEXTDISPLAY_ESC_SEQ_CURSOR_HOME_VT52,
00636     TEXTDISPLAY_ESC_SEQ_CURSOR_UP_ONE_LINE,
00637     TEXTDISPLAY_ESC_SEQ_CURSOR_DOWN_ONE_LINE,
00638     TEXTDISPLAY_ESC_SEQ_CURSOR_RIGHT_ONE_CHAR,
00639     TEXTDISPLAY_ESC_SEQ_CURSOR_LEFT_ONE_CHAR
00640   };
00641 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_HOME_VT100        (0)
00642 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_HOME_VT52         (1)
00643 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_UP_ONE_LINE       (2)
00644 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_DOWN_ONE_LINE     (3)
00645 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_RIGHT_ONE_CHAR    (4)
00646 #define TEXTDISPLAY_ESC_SEQNO_CURSOR_LEFT_ONE_CHAR     (5)
00647 
00648   char*       pChar;
00649   int         seqNo;
00650   bool        anyMatch = false;
00651 
00652   /* Handle escape sequence */
00653   if (ASCII_ESC == c)
00654   {
00655     /* Clear escape sequence, store the ESC character, update mode none and
00656        return true. */
00657     memset(escapeSequence, 0, ESC_SEQ_SIZE_MAX);
00658     escapeSequence[0]=c;
00659     textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_NONE;
00660     return true;
00661   }
00662 
00663   if (ASCII_ESC != escapeSequence[0])
00664   {
00665     /* We are not currently receiving an escape sequence. Just return false. */
00666     return false;
00667   }
00668   else
00669   {
00670     unsigned int len;
00671 
00672     /* We are currently receiving an escape sequence. Append the character to
00673        the end of the current escape sequence buffer and check if the sequence
00674        matches any of the supported sequences. */
00675 
00676     pChar = escapeSequence;
00677     while (*(++pChar));
00678     *pChar = c;
00679 
00680     len = strlen(escapeSequence);
00681 
00682     for (seqNo=0; seqNo<ESC_SEQ_MAX; seqNo++)
00683     {
00684       /* Check for supported escape sequences.*/
00685       if (0 == strncmp(escapeSequence, escapeSequences[seqNo], len))
00686       {
00687         /* We match part of the cursor home sequence. Set anyMatch and update
00688            mode to none. */
00689         anyMatch = true;
00690         textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_NONE;
00691       
00692         /* Full match? */
00693         if (len == strlen(escapeSequences[seqNo]))
00694         {
00695           switch (seqNo)
00696           {
00697           case TEXTDISPLAY_ESC_SEQNO_CURSOR_HOME_VT100:
00698           case TEXTDISPLAY_ESC_SEQNO_CURSOR_HOME_VT52:
00699             /* Move cursor to upper left corner, and set update mode to none. */
00700             textdisplay->ypos = 0;
00701             textdisplay->xpos = 0;
00702             break;
00703           case TEXTDISPLAY_ESC_SEQNO_CURSOR_UP_ONE_LINE:
00704             /* Move cursor up one line. */
00705             if (textdisplay->ypos)
00706               textdisplay->ypos--;
00707             break;
00708           case TEXTDISPLAY_ESC_SEQNO_CURSOR_DOWN_ONE_LINE:
00709             /* Move cursor down one line. */
00710             if (textdisplay->ypos < textdisplay->lines-1)
00711               textdisplay->ypos++;
00712             break;
00713           case TEXTDISPLAY_ESC_SEQNO_CURSOR_RIGHT_ONE_CHAR:
00714             /* Move cursor right one column. */
00715             if (textdisplay->xpos < textdisplay->columns-1)
00716               textdisplay->xpos++;
00717             break;
00718           case TEXTDISPLAY_ESC_SEQNO_CURSOR_LEFT_ONE_CHAR:
00719             /* Move cursor left one column. */
00720             if (textdisplay->xpos)
00721               textdisplay->xpos--;
00722             break;
00723           }
00724 
00725           /* Clear escape sequence, set no display update and return true. */
00726           memset(escapeSequence, 0, ESC_SEQ_SIZE_MAX);
00727           textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_NONE;
00728           return true;
00729         }
00730 
00731         /* We found a partial match. Break out of the loop and return in order
00732            to await the next character. */
00733         break;
00734       }
00735     }
00736     
00737     if (false == anyMatch)
00738     {
00739       /* No match found. Clear escape sequence and return false. */
00740       memset(escapeSequence, 0, ESC_SEQ_SIZE_MAX);
00741       return false;
00742     }
00743 
00744     if (ESC_SEQ_SIZE_MAX-1 == len)
00745     {
00746       /* The next character will overflow the escape sequence buffer.
00747          Clear the escape sequence buffer and return true. */
00748       memset(escapeSequence, 0, ESC_SEQ_SIZE_MAX);
00749       textdisplay->updateMode = TEXTDISPLAY_UPDATE_MODE_NONE;
00750       return true;
00751     }
00752     
00753     return anyMatch;
00754   }
00755 }
00756 
00757 #endif /* INCLUDE_VIDEO_TERMINAL_ESCAPE_SEQUENCE_SUPPORT */
00758 
00759 
00760 /**************************************************************************/
00773 static void TextdisplayCharAdd(TEXTDISPLAY_Device_t* textdisplay,
00774                                int                   c)
00775 {
00776   switch (c)
00777   {
00778   case '\r':  /* check for CR */
00779     textdisplay->xpos = 0;
00780     return;
00781     
00782   case '\n':  /* check for LF */
00783     textdisplay->ypos = textdisplay->ypos + 1;
00784     textdisplay->xpos = 0;
00785     if (textdisplay->ypos >= textdisplay->lines)
00786     {
00787       if (textdisplay->scrollEnable)
00788       {
00789         /* Scroll characters one line up */
00790         TextdisplayScrollUp(textdisplay);
00791         textdisplay->ypos = (textdisplay->lines - 1);
00792       }
00793       else
00794       {
00795         TextdisplayClear(textdisplay);
00796       }
00797     }
00798     return;
00799 
00800   case '\b':  /* check for bell character, changes color to red */
00801     if ( (DISPLAY_COLOUR_MODE_MONOCHROME !=
00802           textdisplay->displayDevice.colourMode) &&
00803          (DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE !=
00804           textdisplay->displayDevice.colourMode) )
00805     {
00806       if (textdisplay->rgbColor[1] == 0xff)
00807       {
00808         textdisplay->rgbColor[1] = 0x00;
00809         textdisplay->rgbColor[2] = 0x00;
00810       }
00811       else
00812       {
00813         textdisplay->rgbColor[1] = 0xff;
00814         textdisplay->rgbColor[2] = 0xff;
00815       }
00816       return;
00817     }
00818 
00819   }
00820 
00821 #ifdef INCLUDE_VIDEO_TERMINAL_ESCAPE_SEQUENCE_SUPPORT
00822   if (TextdisplayEscapeSequence(textdisplay, c))
00823   {
00824     /* We have detected an escape sequence. Return now. */
00825     return;
00826   }
00827 #endif
00828 
00829   /* Check for non-printable characters, and, if so, replace with space. */
00830   if (!isprint(c))
00831   {
00832     c = ' ';
00833   }
00834 
00835 #if 100 > FONT_CHARACTERS
00836   /* The font does not have all printable characters in the ASCII table.
00837      Check if character is supported. */
00838   if ( (FONT_ASCII_START>c) || (FONT_ASCII_START+FONT_CHARACTERS<=c) )
00839   {
00840 #if (FONT_ASCII_START>' ') || (FONT_ASCII_START+FONT_CHARACTERS<' ')
00841     /* Replace with an empty character (space) which should be placed at the
00842        "end" of the font table. */
00843     c = FONT_ASCII_START + FONT_CHARACTERS - 1;
00844 #else
00845     c = ' ';
00846 #endif
00847   }
00848 #endif
00849 
00850   if (textdisplay->xpos >= textdisplay->columns)
00851   {
00852     textdisplay->xpos = 0;
00853     textdisplay->ypos = textdisplay->ypos + 1;
00854   }
00855   if (textdisplay->ypos >= textdisplay->lines)
00856   {
00857     if (textdisplay->scrollEnable)
00858     {
00859       TextdisplayScrollUp(textdisplay);
00860       textdisplay->ypos = textdisplay->lines - 1;
00861     }
00862     else
00863     {
00864       TextdisplayClear(textdisplay);
00865     }
00866   }
00867   textdisplay->charArray[textdisplay->ypos][textdisplay->xpos] = 
00868     c - FONT_ASCII_START;
00869 
00870   textdisplay->xpos = textdisplay->xpos + 1;
00871 
00872   return;
00873 }
00874 
00875 
00876 /**************************************************************************/
00884 static EMSTATUS TextdisplayLineDraw(TEXTDISPLAY_Device_t*  textdisplay,
00885                                     unsigned int           y)
00886 {
00887   unsigned int x, i;
00888   uint8_t      c;
00889   FontBits_t*  rowPtr = (FontBits_t*) textdisplay->lineBuffer;
00890   FontBits_t   pixelBits;
00891 
00892   for (i = 0; i < FONT_HEIGHT; i++)
00893   {
00894     for (x = 0; x < textdisplay->columns; x++)
00895     {
00896       c = textdisplay->charArray[y][x];
00897 
00898       pixelBits = fontBits[c + FONT_CHARACTERS * i];
00899 
00900       switch (textdisplay->displayDevice.colourMode)
00901       {
00902 #if (8 == FONT_WIDTH) || (16 == FONT_WIDTH)
00903       case DISPLAY_COLOUR_MODE_MONOCHROME:
00904         rowPtr[x] = pixelBits;
00905         break;
00906     
00907       case DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE:
00908         rowPtr[x] = ~pixelBits;
00909         break;
00910 #elif (8 > FONT_WIDTH) || (16 > FONT_WIDTH)
00911       case DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE:
00912         pixelBits = ~pixelBits;
00913       case DISPLAY_COLOUR_MODE_MONOCHROME:
00914       {
00915         int startPixel = x * FONT_WIDTH;
00916         int pixelNo = startPixel;
00917         for (; pixelNo<startPixel+FONT_WIDTH; pixelBits>>=1, pixelNo++)
00918         {
00919           if (pixelBits & 0x1)
00920           {
00921             rowPtr[pixelNo>>FONT_BITS_LOG2] |= 1 << (pixelNo&FONT_BITS_MASK);
00922           }
00923           else
00924           {
00925             rowPtr[pixelNo>>FONT_BITS_LOG2] &= ~(1 << (pixelNo&FONT_BITS_MASK));
00926           }
00927         }
00928       }
00929       break;
00930 #endif
00931       }
00932     }
00933 
00934 #if (8 != FONT_WIDTH) || (16 != FONT_WIDTH)
00935     /* Set background colour at the end of the display line. */
00936     if (textdisplay->displayDevice.colourMode ==
00937         DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE)
00938     {
00939       int usedBits;
00940       int startPixel = x * FONT_WIDTH;
00941       /* Check if the startPixel is not aligned at an FontBits_t boundary,
00942          meaning that we need to adjust it to the next FontBits_t boundary. */
00943       usedBits = startPixel & FONT_BITS_MASK;
00944       if (usedBits)
00945       {
00946         /* First, clear the last bits in the FontBits_t word of the startPixel. */
00947         rowPtr[startPixel>>FONT_BITS_LOG2] &= (1<<usedBits)-1;
00948         /* Adjust the startPixel to the next FontBits_t boundary. */
00949         startPixel += (sizeof(FontBits_t)*8) - usedBits;
00950       }
00951       memset (&rowPtr[startPixel>>FONT_BITS_LOG2], 0xff,
00952               (textdisplay->displayDevice.geometry.width - startPixel)/8);
00953     }
00954 #endif
00955 
00956     rowPtr +=
00957       textdisplay->displayDevice.geometry.stride / (sizeof(FontBits_t) * 8) ;
00958   }
00959   
00960   return
00961     textdisplay->displayDevice.pPixelMatrixDraw(&textdisplay->displayDevice,
00962                                                 textdisplay->lineBuffer,
00963                                                 0,
00964                                                 textdisplay->columns*FONT_WIDTH,
00965 #ifdef EMWIN_WORKAROUND
00966                                                 textdisplay->columns*FONT_WIDTH,
00967 #endif
00968                                                 y * FONT_HEIGHT,
00969                                                 FONT_HEIGHT);
00970 }
00971 
00972 
00973 /**************************************************************************/
00980 static EMSTATUS TextdisplayUpdate(TEXTDISPLAY_Device_t*  textdisplay)
00981 {
00982   unsigned int  i;
00983   EMSTATUS      status;
00984 
00985   switch (textdisplay->updateMode)
00986   {
00987   case TEXTDISPLAY_UPDATE_MODE_NONE:
00988   default:
00989     break;
00990 
00991   case TEXTDISPLAY_UPDATE_MODE_FULL:
00992 
00993     /* Draw a full screen */
00994 
00995     switch (textdisplay->displayDevice.addressMode)
00996     {
00997     case DISPLAY_ADDRESSING_BY_ROWS_ONLY:
00998 
00999       /* Update all text lines. */
01000       for (i=0; i<textdisplay->lines; i++)
01001         /* Draw the current text line on the display. */
01002         TextdisplayLineDraw(textdisplay, i);
01003 
01004       /* Clear lowest and unused part of the screen. */
01005       if (textdisplay->lines * FONT_HEIGHT <
01006           textdisplay->displayDevice.geometry.height)
01007       {
01008         switch (textdisplay->displayDevice.colourMode)
01009         {
01010         case DISPLAY_COLOUR_MODE_MONOCHROME:
01011           memset (textdisplay->lineBuffer, 0x00,
01012                   textdisplay->displayDevice.geometry.width/8);
01013           break;
01014         case DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE:
01015           memset (textdisplay->lineBuffer, 0xff,
01016                   textdisplay->displayDevice.geometry.width/8);
01017           break;
01018         default:
01019           return TEXTDISPLAY_EMSTATUS_NOT_SUPPORTED;
01020         }
01021 
01022         for (i = textdisplay->lines * FONT_HEIGHT;
01023              i < textdisplay->displayDevice.geometry.height;
01024              i++)
01025         {
01026           status =
01027             textdisplay->displayDevice.pPixelMatrixDraw(&textdisplay->displayDevice,
01028                                                         textdisplay->lineBuffer,
01029                                                         0,
01030                                                         textdisplay->displayDevice.geometry.width,
01031 #ifdef EMWIN_WORKAROUND
01032                                                         textdisplay->displayDevice.geometry.width,
01033 #endif
01034                                                         i,
01035                                                         1);
01036           if (DISPLAY_EMSTATUS_OK != status)
01037             return status;
01038          }
01039       }
01040       break;
01041 
01042     default:
01043       return TEXTDISPLAY_EMSTATUS_NOT_SUPPORTED;
01044     }
01045 
01046   case TEXTDISPLAY_UPDATE_MODE_LINE:
01047 
01048     switch (textdisplay->displayDevice.addressMode)
01049     {
01050     case DISPLAY_ADDRESSING_BY_ROWS_ONLY:
01051 
01052       /* Draw the current text line on the display. */
01053       return TextdisplayLineDraw(textdisplay, textdisplay->ypos);
01054 
01055     default:
01056       return TEXTDISPLAY_EMSTATUS_NOT_SUPPORTED;
01057     }
01058 
01059   case TEXTDISPLAY_UPDATE_MODE_CHAR:
01060     return TEXTDISPLAY_EMSTATUS_NOT_SUPPORTED;
01061   }
01062   return TEXTDISPLAY_EMSTATUS_OK;
01063 }
01064 
01068 /***************  THE REST OF THE FILE IS DOCUMENTATION ONLY !  ***************/
01069 
01070 /*******************************************************************************
01071  **************************       DOCUMENTATION       **************************
01072  ******************************************************************************/
01073 
01074 /**************************************************************************/