- 01-06-2006 changed: All gui settings to lower case only.
[xbmc:xbmc-antiquated.git] / xbmc / lib / smartXX / smartxxlcd.cpp
1
2 #include "../../stdafx.h"
3 #include "smartxxlcd.h"
4 #include "conio.h"
5 #include "../../Util.h"
6 #include "../../utils/SystemInfo.h"
7
8 /*
9 HD44780 or equivalent
10 Character located  1   2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 
11 DDRAM address      00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13
12 DDRAM address      40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53
13 DDRAM address      14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27
14 DDRAM address      54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 64 65 66 67
15 */
16
17 #define SCROLL_SPEED_IN_MSEC 250
18 #define DISP_O                          0xF700          // Display Port
19 #define DISP_O_LIGHT                      0xF701                // Display Port brightness control
20 #define DISP_O_CONTRAST                 0xF703          // Display Port contrast control
21 #define DISP_CTR_TIME               2                 // Controll Timing for Display routine
22
23 #define DISPCON_RS                    0x02                // some Display definitions
24 #define DISPCON_E                       0x04
25
26 #define INI                                 0x01
27 #define CMD                                 0x00
28 #define DAT                                 0x02
29
30 #define DISP_CLEAR                    0x01 // cmd: clear display command
31 #define DISP_HOME                       0x02 // cmd: return cursor to home
32 #define DISP_ENTRY_MODE_SET     0x04 // cmd: enable cursor moving direction and enable the shift of entire display
33 #define DISP_S_FLAG                   0x01
34 #define DISP_ID_FLAG                0x02
35
36 #define DISP_CONTROL                0x08        //cmd: display ON/OFF
37 #define DISP_D_FLAG                   0x04      // display on
38 #define DISP_C_FLAG                   0x02      // cursor on
39 #define DISP_B_FLAG                   0x01      // blinking on
40
41 #define DISP_EXT_CONTROL          0x08  //RE_FLAG = 1
42 #define DISP_FW_FLAG                0x04        //RE_FLAG = 1
43 #define DISP_BW_FLAG                0x02        //RE_FLAG = 1
44 #define DISP_NW_FLAG                0x01        //RE_FLAG = 1
45
46 #define DISP_SHIFT                    0x10  //cmd: set cursor moving and display shift control bit, and the direction without changing of ddram data
47 #define DISP_SC_FLAG                0x08
48 #define DISP_RL_FLAG                0x04
49
50 #define DISP_FUNCTION_SET         0x20 // cmd: set interface data length
51 #define DISP_DL_FLAG                0x10  // set interface data length: 8bit/4bit
52 #define DISP_N_FLAG                   0x08  // number of display lines:2-line / 1-line
53 #define DISP_F_FLAG                   0x04  // display font type 5x11 dots or 5x8 dots
54 #define DISP_RE_FLAG                0x04
55
56 #define DISP_CGRAM_SET            0x40 // cmd: set CGRAM address in address counter
57 #define DISP_SEGRAM_SET           0x40  //RE_FLAG = 1
58
59 #define DISP_DDRAM_SET            0x80 // cmd: set DDRAM address in address counter
60
61 char AnimIndex=0;
62
63 //*************************************************************************************************************
64 static void outb(unsigned short port, unsigned char data)
65 {
66   __asm
67   {
68     nop
69     mov dx, port
70     nop
71     mov al, data
72     nop
73     out dx,al
74     nop
75     nop
76   }
77 }
78
79 //*************************************************************************************************************
80 static unsigned char inb(unsigned short port)
81 {
82   unsigned char data;
83   __asm
84   {
85     mov dx, port
86     in al, dx
87     mov data,al
88   }
89   return data;
90 }
91
92 //*************************************************************************************************************
93 CSmartXXLCD::CSmartXXLCD()
94 {
95   m_iActualpos=0;
96   m_iRows    = 4;
97   m_iColumns = 20;                              // display rows each line
98   m_iRow1adr = 0x00;
99   m_iRow2adr = 0x20;
100   m_iRow3adr = 0x40;
101   m_iRow4adr = 0x60;
102
103   m_iRow1adr = 0x00;
104   m_iRow2adr = 0x40;
105   m_iRow3adr = 0x14;
106   m_iRow4adr = 0x54;
107   m_iBackLight=32;
108 }
109
110 //*************************************************************************************************************
111 CSmartXXLCD::~CSmartXXLCD()
112 {
113 }
114
115 //*************************************************************************************************************
116 void CSmartXXLCD::Initialize()
117 {
118   StopThread();
119   if (g_guiSettings.GetInt("lcd.type") == LCD_TYPE_NONE) 
120   {
121     CLog::Log(LOGINFO, "lcd not used");
122     return;
123   }
124   ILCD::Initialize();
125   Create();
126   
127 }
128 void CSmartXXLCD::SetBackLight(int iLight)
129 {
130   m_iBackLight=iLight;
131 }
132
133 void CSmartXXLCD::SetContrast(int iContrast)
134 {
135   m_iContrast=iContrast;
136 }
137
138 //*************************************************************************************************************
139 void CSmartXXLCD::Stop()
140 {
141   if (g_guiSettings.GetInt("lcd.type") == LCD_TYPE_NONE) return;
142   StopThread();
143 }
144
145 //*************************************************************************************************************
146 void CSmartXXLCD::SetLine(int iLine, const CStdString& strLine)
147 {
148   if (g_guiSettings.GetInt("lcd.type") == LCD_TYPE_NONE) return;
149   if (iLine < 0 || iLine >= (int)m_iRows) return;
150   
151   CStdString strLineLong=strLine;
152   strLineLong.Trim();
153         StringToLCDCharSet(strLineLong);
154
155   while (strLineLong.size() < m_iColumns) strLineLong+=" ";
156   if (strLineLong != m_strLine[iLine])
157   {
158 //    CLog::Log(LOGINFO, "set line:%i [%s]", iLine,strLineLong.c_str());
159     m_bUpdate[iLine]=true;
160     m_strLine[iLine]=strLineLong;
161     m_event.Set();
162   }
163 }
164
165
166 //************************************************************************************************************************
167 // wait_us: delay routine
168 // Input: (wait in ~us)
169 //************************************************************************************************************************
170 void CSmartXXLCD::wait_us(unsigned int value) 
171 {
172   // 1 us = 1000msec
173   int iValue=value/30;
174   if (iValue>10) iValue=10;
175   if (iValue) Sleep(iValue);
176 }
177
178
179 //************************************************************************************************************************
180 // DisplayOut: writes command or datas to display
181 // Input: (Value to write, token as CMD = Command / DAT = DATAs / INI for switching to 4 bit mode)
182 //************************************************************************************************************************
183 void CSmartXXLCD::DisplayOut(unsigned char data, unsigned char command) 
184 {
185         unsigned char odathigh;
186         unsigned char odatlow;
187   static DWORD dwTick=0;
188
189   if ((GetTickCount()-dwTick) < 3)
190   {
191     Sleep(1);
192   }
193   dwTick=GetTickCount();
194
195         // Data bit's mapping for higher nibble outbut
196         odathigh  = (data >> 2) & 0x28;         // outD7 => PortD5 => DisplayD7  //outD5 => PortD3 => DisplayD5
197         odathigh |= (data >> 0) & 0x50;         // outD6 => PortD6 => DisplayD6  //outD4 => PortD4 => DisplayD4         
198         
199   // Data bit's mapping for lower nibble outbut
200         odatlow  = (data << 2) & 0x28;   // outD3 => PortD5 => DisplayD7  //outD1 => PortD3 => DisplayD5
201         odatlow |= (data << 4) & 0x50;   // outD2 => PortD6 => DisplayD6  //outD0 => PortD4 => DisplayD4
202         
203         //outbut higher nibble
204         outb(DISP_O, (command & DISPCON_RS) | odathigh);                                            // set the RS if needed
205         outb(DISP_O,((command & DISPCON_RS) | DISPCON_E | odathigh));   // set E
206         outb(DISP_O,((command & DISPCON_RS) | odathigh));                               // reset E
207
208
209         if ((command & INI) == 0) 
210   {                                                     
211     // if it's not the init command, do second nibble
212                 //wait_us(DISP_CTR_TIME * 21);
213                 //outbut lower nibble
214                 outb(DISP_O,((command & DISPCON_RS) | odatlow));                          // set E
215                 outb(DISP_O,((command & DISPCON_RS) | DISPCON_E | odatlow));    // set Data
216                 outb(DISP_O,((command & DISPCON_RS) | odatlow));                          // reset E
217                 if ((data & 0xFC) == 0) 
218     {                                                                     
219       // if command was a Clear Display
220       // or Cursor Home, wait at least 1.5 ms more
221                         m_iActualpos = 0;
222                         Sleep(2);                                                                                          
223                 }
224                 if ((command & DISPCON_RS) == 0x02) m_iActualpos++;
225         }
226         else 
227   {                                                                             
228                 m_iActualpos = 0;
229     
230                 //wait_us(2500);                // wait 2.5 msec        
231         }
232         usleep(50);
233  }
234
235 //************************************************************************************************************************
236 //DisplayBuildCustomChars: load customized characters to character ram of display, resets cursor to pos 0
237 //************************************************************************************************************************
238 void CSmartXXLCD::DisplayBuildCustomChars() 
239 {
240         int I;
241         
242         static char Bar0[] ={0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10};
243         static char Bar1[] ={0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
244         static char Bar2[] ={0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c};
245         static char Bar3[] ={0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e};   //4pixel
246         static char REW[8][8]=
247         {
248                 {0x00, 0x05, 0x0a, 0x14, 0x0a, 0x05, 0x00, 0x00},
249                 {0x00, 0x0a, 0x14, 0x08, 0x14, 0x0a, 0x00, 0x00},
250                 {0x00, 0x14, 0x08, 0x10, 0x08, 0x14, 0x00, 0x00},
251                 {0x00, 0x08, 0x10, 0x00, 0x10, 0x08, 0x00, 0x00},
252                 {0x00, 0x10, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00},
253                 {0x00, 0x00, 0x01, 0x02, 0x01, 0x00, 0x00, 0x00},
254                 {0x00, 0x01, 0x02, 0x05, 0x02, 0x01, 0x00, 0x00},
255                 {0x00, 0x02, 0x05, 0x0a, 0x05, 0x02, 0x00, 0x00}
256
257         };
258         static char FF[8][8]=
259         {
260                 {0x00, 0x14, 0x0a, 0x05, 0x0a, 0x14, 0x00, 0x00},
261                 {0x00, 0x0a, 0x05, 0x02, 0x05, 0x0a, 0x00, 0x00},
262                 {0x00, 0x05, 0x02, 0x01, 0x02, 0x05, 0x00, 0x00},
263                 {0x00, 0x02, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00},
264                 {0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00},
265                 {0x00, 0x00, 0x10, 0x08, 0x10, 0x00, 0x00, 0x00},
266                 {0x00, 0x10, 0x08, 0x14, 0x08, 0x10, 0x00, 0x00},
267                 {0x00, 0x08, 0x14, 0x0a, 0x14, 0x08, 0x00, 0x00}
268         };
269         static char Play[] ={0x00, 0x04, 0x06, 0x07, 0x07, 0x06, 0x04, 0x00};
270         static char Stop[] ={0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00};
271         static char Pause[]={0x00, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00};
272         
273         DisplayOut(DISP_CGRAM_SET, CMD);
274          for(I=0;I<8;I++) DisplayOut(Bar0[I], DAT);  // Bar0
275          for(I=0;I<8;I++) DisplayOut(Bar1[I], DAT);  // Bar1
276          for(I=0;I<8;I++) DisplayOut(Bar2[I], DAT);  // Bar2
277          for(I=0;I<8;I++) DisplayOut(REW[AnimIndex][I], DAT);   // REW
278          for(I=0;I<8;I++) DisplayOut(FF[AnimIndex][I], DAT);    // FF
279          for(I=0;I<8;I++) DisplayOut(Play[I], DAT);  // Play
280          //for(I=0;I<8;I++) DisplayOut(Stop[I], DAT);                   // Stop
281          for(I=0;I<8;I++) DisplayOut(Bar3[I], DAT);
282          for(I=0;I<8;I++) DisplayOut(Pause[I], DAT); // Pause
283         DisplayOut(DISP_DDRAM_SET, CMD);
284     AnimIndex=(AnimIndex+1) & 0x7;
285 }
286
287
288 //************************************************************************************************************************
289 // DisplaySetPos: sets cursor position
290 // Input: (row position, line number from 0 to 3)
291 //************************************************************************************************************************
292 void CSmartXXLCD::DisplaySetPos(unsigned char pos, unsigned char line) 
293 {
294         
295         unsigned int cursorpointer;
296         
297         cursorpointer = pos % m_iColumns;
298
299         if (line == 0) {
300                 cursorpointer += m_iRow1adr;
301         }
302         if (line == 1) {
303                 cursorpointer += m_iRow2adr;
304         }
305         if (line == 2) {
306                 cursorpointer += m_iRow3adr;
307         }
308         if (line == 3) {
309                 cursorpointer += m_iRow4adr;
310         }
311         DisplayOut(DISP_DDRAM_SET | cursorpointer, CMD);
312         m_iActualpos = cursorpointer;
313 }
314
315 //************************************************************************************************************************
316 // DisplayWriteFixText: write a fixed text to actual cursor position
317 // Input: ("fixed text like")
318 //************************************************************************************************************************
319 void CSmartXXLCD::DisplayWriteFixtext(const char *textstring)
320 {
321         unsigned char  c;
322         while (c = *textstring++) {
323                 DisplayOut(c,DAT);
324         }
325 }
326
327
328 //************************************************************************************************************************
329 // DisplayWriteString: write a string to acutal cursor position 
330 // Input: (pointer to a 0x00 terminated string)
331 //************************************************************************************************************************
332
333 void CSmartXXLCD::DisplayWriteString(char *pointer) 
334 {
335         /* display a normal 0x00 terminated string on the LCD display */
336         unsigned char c;
337         do {
338                 c = *pointer;
339                 if (c == 0x00) 
340                         break;
341     
342                 DisplayOut(c, DAT);
343                 *pointer++;
344         } while(1);
345  
346 }               
347
348
349 //************************************************************************************************************************
350 // DisplayClearChars:  clears a number of chars in a line and resets cursor position to it's startposition
351 // Input: (Startposition of clear in row, row number, number of chars to clear)
352 //************************************************************************************************************************
353 void CSmartXXLCD::DisplayClearChars(unsigned char startpos , unsigned char line, unsigned char lenght) 
354 {
355         int i;
356         
357         DisplaySetPos(startpos,line);
358         for (i=0;i<lenght; i++){
359                 DisplayOut(0x20,DAT);
360         }
361         DisplaySetPos(startpos,line);
362   
363 }
364
365
366 //************************************************************************************************************************
367 // DisplayProgressBar: shows a grafic bar staring at actual cursor position
368 // Input: (percent of bar to display, lenght of whole bar in chars when 100 %)
369 //************************************************************************************************************************
370 void CSmartXXLCD::DisplayProgressBar(unsigned char percent, unsigned char charcnt) 
371 {
372                 
373         unsigned int barcnt100;
374         
375         barcnt100 = charcnt * 5 * percent / 100;
376
377         int i;  
378         for (i=1; i<=charcnt; i++) {
379                 if (i<=(int)(barcnt100 / 5)){
380                         DisplayOut(4,DAT);
381                 }
382                 else 
383                 {
384                         if ( (i == (barcnt100 /5)+1) && (barcnt100 % 5 != 0) ){
385                                 DisplayOut((barcnt100 % 5)-1,DAT);
386                         }
387                         else{
388                                 DisplayOut(0x20,DAT);
389                         }
390                 }
391         }
392 }
393 //************************************************************************************************************************
394 //Set brightness level 
395 //************************************************************************************************************************
396 void CSmartXXLCD::DisplaySetBacklight(unsigned char level) 
397 {
398   if (g_guiSettings.GetInt("lcd.type")==LCD_TYPE_VFD)
399   {
400     //VFD:(value 0 to 3 = 100%, 75%, 50%, 25%)
401     if (level<0) level=0;
402     if (level>99) level=99;
403           level = (99-level);
404     level/=25;
405           DisplayOut(DISP_FUNCTION_SET | DISP_N_FLAG | level,CMD);
406   }
407   else //if (g_guiSettings.GetInt("lcd.type")==LCD_TYPE_LCD_HD44780)
408   {
409     if (SYSINFO::SmartXXModCHIP()== "SmartXX V3")
410     {
411       float fBackLight=((float)level)/100.0f;
412       fBackLight*=127.0f;
413       int iNewLevel=(int)fBackLight;
414       if (iNewLevel==63) iNewLevel=64;
415       outb(DISP_O_LIGHT, iNewLevel&127);
416     }
417     else if (SYSINFO::SmartXXModCHIP()== "SmartXX OPX")
418     {
419       float fBackLight=((float)level)/100.0f;
420       fBackLight*=127.0f;
421       int iNewLevel=(int)fBackLight;
422       if (iNewLevel==63) iNewLevel=64;
423       outb(DISP_O_LIGHT, iNewLevel&127);
424     }
425     else
426     {
427       float fBackLight=((float)level)/100.0f;
428       fBackLight*=63.0f;
429       int iNewLevel=(int)fBackLight;
430       if (iNewLevel==31) iNewLevel=32;
431       outb(DISP_O_LIGHT, iNewLevel&63);
432     }
433   }
434 }
435 //************************************************************************************************************************
436 //Set brightness level 
437 //************************************************************************************************************************
438 void CSmartXXLCD::DisplaySetContrast(unsigned char level) 
439 {
440   // can't do this with a VFD
441   if (g_guiSettings.GetInt("lcd.type")==LCD_TYPE_VFD) 
442     return;
443
444   float fBackLight=((float)level)/100.0f;
445   
446   if (SYSINFO::SmartXXModCHIP() == "SmartXX V3") // Smartxx V3 
447   {   
448       fBackLight*=127.0f;
449       int iNewLevel=(int)fBackLight;
450       if (iNewLevel==63) iNewLevel=64;
451       int itemp = iNewLevel;
452       outb(0xF701, itemp&127|128);
453         }
454   else if ( SYSINFO::SmartXXModCHIP() == "SmartXX OPX" )
455   {
456     fBackLight*=127.0f;
457     int iNewLevel=(int)fBackLight;
458     if (iNewLevel==63) iNewLevel=64;
459     
460     outb(DISP_O_CONTRAST, iNewLevel&127|128);
461   }
462   else 
463   {
464     fBackLight*=63.0f;
465     int iNewLevel=(int)fBackLight;
466     if (iNewLevel==31) iNewLevel=32;
467     
468     outb(DISP_O_CONTRAST, iNewLevel&63);
469   }
470   
471 }
472
473 //************************************************************************************************************************
474 void CSmartXXLCD::DisplayInit()
475 {
476         outb(DISP_O,0);
477         DisplayOut(DISP_FUNCTION_SET | DISP_DL_FLAG, INI);                    // 8-Bit Datalenght if display is already initialized to 4 bit
478         Sleep(5);
479   DisplayOut(DISP_FUNCTION_SET | DISP_DL_FLAG, INI);                  // 8-Bit Datalenght if display is already initialized to 4 bit
480         Sleep(5);
481   DisplayOut(DISP_FUNCTION_SET | DISP_DL_FLAG, INI);                  // 8-Bit Datalenght if display is already initialized to 4 bit
482         Sleep(5);
483         DisplayOut(DISP_FUNCTION_SET,INI);                                                // 4-Bit Datalenght
484         Sleep(5);
485         DisplayOut(DISP_FUNCTION_SET | DISP_N_FLAG | DISP_RE_FLAG ,CMD);        // 4-Bit Datalenght, 2 Lines, Font 5x7, and set RE Flag
486         Sleep(5);
487         DisplayOut(DISP_SEGRAM_SET, CMD);                                                   // set SEGRAM to 0x00 (RE = 1)
488         Sleep(5);
489         DisplayOut(DISP_EXT_CONTROL | DISP_NW_FLAG ,CMD);                       // set Display to 2 lines (RE = 1)
490         Sleep(5);
491         DisplayOut(DISP_FUNCTION_SET | DISP_N_FLAG ,CMD);                       // 4-Bit Datalenght, 2 Lines, Font 5x7, clear RE Flag
492         Sleep(5);
493         DisplayOut(DISP_CONTROL | DISP_D_FLAG ,CMD);                              // Display on
494         Sleep(5);
495         DisplayOut(DISP_CLEAR,CMD);                                                             // Display clear
496         Sleep(5);
497         DisplayOut(DISP_ENTRY_MODE_SET | DISP_ID_FLAG,CMD);                   // Cursor autoincrement
498         Sleep(5);
499
500   DisplayBuildCustomChars();                            
501   DisplaySetPos(0,0);
502 }
503
504 //************************************************************************************************************************
505 void CSmartXXLCD::Process()
506 {
507   int iOldLight=-1;
508   int iOldContrast=-1;
509
510   
511   m_iColumns = g_advancedSettings.m_lcdColumns;
512   m_iRows    = g_advancedSettings.m_lcdRows;
513   m_iRow1adr = g_advancedSettings.m_lcdAddress1;
514   m_iRow2adr = g_advancedSettings.m_lcdAddress2;
515   m_iRow3adr = g_advancedSettings.m_lcdAddress3;
516   m_iRow4adr = g_advancedSettings.m_lcdAddress4;
517   m_iBackLight= g_guiSettings.GetInt("lcd.backlight");
518   m_iContrast = g_guiSettings.GetInt("lcd.contrast");
519   if (m_iRows >= MAX_ROWS) m_iRows=MAX_ROWS-1;
520
521   DisplayInit();
522   while (!m_bStop)
523   {
524     Sleep(SCROLL_SPEED_IN_MSEC);  
525     if (m_iBackLight != iOldLight)
526     {
527       // backlight setting changed
528       iOldLight=m_iBackLight;
529       DisplaySetBacklight(m_iBackLight);
530     }
531     if (m_iContrast != iOldContrast)
532     {
533       // contrast setting changed
534       iOldContrast=m_iContrast;
535       DisplaySetContrast(m_iContrast);
536     }
537           DisplayBuildCustomChars();
538           for (int iLine=0; iLine < (int)m_iRows; ++iLine)
539     {
540             if (m_bUpdate[iLine])
541                         {
542         CStdString strTmp=m_strLine[iLine];
543         if (strTmp.size() > m_iColumns)
544         {
545           strTmp=m_strLine[iLine].Left(m_iColumns);
546         }
547         m_iPos[iLine]=0;
548         DisplaySetPos(0,iLine);
549         DisplayWriteFixtext(strTmp.c_str());
550         m_bUpdate[iLine]=false;
551         m_dwSleep[iLine]=GetTickCount();
552       }
553       else if ( (GetTickCount()-m_dwSleep[iLine]) > 1000)
554       {
555         int iSize=m_strLine[iLine].size();
556         if (iSize > (int)m_iColumns)
557         {
558           //scroll line
559           CStdString strRow=m_strLine[iLine]+"   -   ";
560           int iSize=strRow.size();
561           m_iPos[iLine]++;
562           if (m_iPos[iLine]>=iSize) m_iPos[iLine]=0;
563           int iPos=m_iPos[iLine];
564           CStdString strLine="";
565           for (int iCol=0; iCol < (int)m_iColumns;++iCol)
566           {
567             strLine +=strRow.GetAt(iPos);
568             iPos++;
569             if (iPos >= iSize) iPos=0;
570           }
571           DisplaySetPos(0,iLine);
572           DisplayWriteFixtext(strLine.c_str());
573         }
574       }
575     }
576   }
577   for (int i=0; i < (int)m_iRows; i++)
578   {
579           DisplayClearChars(0,i,m_iColumns);
580   } 
581   DisplayOut(DISP_CONTROL ,CMD);                                  // Display off
582 }