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