CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Question on KS0108 graphics display character update

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

Question on KS0108 graphics display character update
PostPosted: Wed Jan 14, 2015 4:19 pm     Reply with quote

Hi, i am doing some work for myself using the KS0108 128X64 GLD display and so far I have been able to do quite a bit with it in terms of graphics and character display on a GPS based application using a modified version of CCS GLCD prog example but I seem to have a problem with the flickering when updating the screen. I am using a PIC18F45K22 running at 16 MHz and unfortunately I do not have enough RAM available to use the FAST_GLCD update where you write the entire screen to a RAM page. I tried going to faster clock rates on the PIC but anything >16 MHz gives me crap all over the display and things just don't seem to work (although this may have to do with some other serial process between the GPS receiver and the PIC).
So what I am looking for is a simple method to just update a particular range of characters on a given line location and not have to update the entire screen this would make for a much smoother view. I figure the way to do this is to just write a 5X7 pixel fill in its complementary value (so all pixels are off) to each of the characters I want to update and then update the new value characters. I guess this is probably something that some have already done and I did not want to re-invent the wheel or perhaps there is abetter method. In any event I searched throughout this forum and did not see such answer. Perhaps someone could help me with such.
Thank you
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Thu Jan 15, 2015 8:07 am     Reply with quote

Hi,

The 'stock' 5x7 character display routine provided by CCS in 'GLCD.c' will turn ON pixels only based on the character data. This means that the display
area must be cleared before each update, which can cause an annoying ' 'flicker' depending on the update rate. I suppose that is what you are
observing?

I solved this issue by explicitly controlling the state (OFF or ON) of each pixel in the character, so I can simply write whenever necessary without
having to clear anything first. I generally also keep track of any values that I'm displaying, and only update the text when there is a change.

Here is the relevant change to glcd_text57:

Code:

      for(j=0; j<5; ++j, x++)         // Loop through character byte data
      {
         for(k=0; k<7; ++k)          // Loop through the vertical pixels
         {
            if(bit_test(pixelData[j], k)) // Check if the pixel should be set
               glcd_pixel(x, y+k, ON); // Draws the pixel
            else
            glcd_pixel(x, y+k, OFF); // Clears the pixel
         }
      }


Hope this helps!

John
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Thu Jan 15, 2015 9:47 am     Reply with quote

John,
Thank you for your help on this and YES that is exactly the problem I have the characters get written one over the other and if there is any change in any of them you just see the sum of all the previous pixels light up and it is basically unreadable, so I do a total display clear and re-write the screen, now everything is ok but you get the annoying page flicker. For sure, I though your code would definitely work as it seems to me that is exactly what I wanted to do. However, I still have the same problem with the characters overlapping if I don't do a page clear. Perhaps I have not placed your suggested code in the right place.

See excerpt of code where I placed your suggested lines.
Code:

#ifdef LARGE_LCD
void glcd_text57(int16 x, int16 y, char* textptr, int8 size, int1 color)
#else
void glcd_text57(int8 x, int8 y, char* textptr, int8 size, int1 color)
#endif
{
   int8 j, k, l, m;                       // Loop counters
   int8 pixelData[5];                     // Stores character data

   for(; *textptr != '\0'; ++textptr, ++x)// Loop through the passed string
   {
      if(*textptr < 'S') // Checks if the letter is in the first font array
         memcpy(pixelData, FONT[*textptr - ' '], 5);
      else if(*textptr <= '~') // Check if the letter is in the second font array
         memcpy(pixelData, FONT2[*textptr - 'S'], 5);
      else
         memcpy(pixelData, FONT[0], 5);   // Default to space

      // Handles newline and carriage returns
      switch(*textptr)
      {
         case '\n':
            y += 7*size + 1;
            continue;
         case '\r':
            x = 0;
            continue;
      }

      if(x+5*size >= GLCD_WIDTH)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 7*size + 1;                 // Set y at next position down
      }
      for(j=0; j<5; ++j, x+=size)         // Loop through character byte data
      {
         for(k=0; k < 7; ++k)             // Loop through the vertical pixels
         {
         
           // if(bit_test(pixelData[j], k)) // Check if the pixel should be set
           
         
         
         
            if(bit_test(pixelData[j], k)) // Check if the pixel should be set
            {
               glcd_pixel(x, y+k, ON); // Draws the pixel /////////////////////////////////////////
               else                                      /////////////////////////////////////////
               glcd_pixel(x, y+k, OFF); // Clears the pixel ///////////////////////////////////////////
           
               for(l=0; l < size; ++l)    // These two loops change the
               {                          // character's size
                  for(m=0; m < size; ++m)
                  {
                     glcd_pixel(x+m, y+k*size+l, color); // Draws the pixel
                  }
               }
            }
         }
      }
   }
}

#endif
Jerson



Joined: 31 Jul 2009
Posts: 122
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Thu Jan 15, 2015 7:11 pm     Reply with quote

The modification should go to the innermost for loop (m) which changes the font size.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Fri Jan 16, 2015 9:05 am     Reply with quote

I have tried moving these three lines of code inside the for(m) loop but still get the same results, so I am not sure that such method will ever work. The only thing I have been able to do is to write a bar that negates all previous pixels and then re-write once again to update that text field as shown below:
Code:

glcd_bar(10, 43, 125, 43, 7, OFF);
sprintf(LCDText"Lon:%u:%5.3g%c",Lon_Deg,Lon_Min,E_W);
glcd_text57(10,40, LCDText, 1, ON);

Although the above does work if you have more than one field you are updating it tends to give you a refresh flicker similar to the vertical sync on an old B&W TV set. I guess there is no other shortcut methods other than writing to a page of ram (which needs 1K of ram that I don't have here) and then using the FAST_GLCD update.
Maybe using a better display than the KS0108 may also help
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Fri Jan 16, 2015 7:50 pm     Reply with quote

Hi,

Sorry, I should have posted the entire routine originally. I should be able to get to it this weekend, but if not I'll post it Monday morning!

John
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Jan 19, 2015 8:00 am     Reply with quote

Hi,

Here is my complete, modified glcd_text57 routine. Note that I have removed the 'Size' parameter as I never found that produced satisfactory
results, so I created my own routine to deal with larger sized fonts!

Code:

// Purpose:       Write text on a graphic LCD
// Inputs:        (x,y) - The upper left coordinate of the first letter
//                textptr - A pointer to an array of text to display
//                color - ON or OFF
void glcd_text57(int x, int y, char* textptr, int1 color)
{
   int i, j, k, l, m;                     // Loop counters
   BYTE pixelData[5];                     // Stores character data

   for(i=0; textptr[i] != '\0'; ++i, ++x) // Loop through the passed string
   {
      if(textptr[i] < 'S') // Checks if the letter is in the first text array
         memcpy(pixelData, TEXT[textptr[i]-' '], 5);
      else if(textptr[i] <= '~') // Check if the letter is in the second array
         memcpy(pixelData, TEXT2[textptr[i]-'S'], 5);
      else
         memcpy(pixelData, TEXT[0], 5);   // Default to space

      if(x+5 >= GLCD_WIDTH)          // Performs character wrapping
      {
         x = 0;                           // Set x at far left position
         y += 7 + 1;                      // Set y at next position down
      }
      for(j=0; j<5; ++j, x++)         // Loop through character byte data
      {
         for(k=0; k<7; ++k)          // Loop through the vertical pixels
         {
            if(bit_test(pixelData[j], k)) // Check if the pixel should be set
               glcd_pixel(x, y+k, ON); // Draws the pixel
            else
            glcd_pixel(x, y+k, OFF); // Clears the pixel
         }
      }
   }
}


Hope this gets you up-and-running!!

John
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Jan 19, 2015 1:20 pm     Reply with quote

John,
I certainly appreciate your help with this. I substituted your code for the same routine that you have replaced and although it appears to work at first, the same thing happens when a new field value changes, it just writes over the previous pixels without clearing the past ones and after a couple of screen writes all you have is a mass of previously lit pixels compounded on one another and the entire text line is just totally unreadable. The only way to do this would be to clear the previous characters and then write the new ones. I am now doing this with a negated fill bar and then I write the new characters as I explained before, unfortunately that also gives you some level of field flicker. I am not sure there is a way around other than writing the screen to ram or getting a better display module like the T6963
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Mon Jan 19, 2015 3:31 pm     Reply with quote

Hi,

You undoubtedly have something else going on? Can you make a very small, compilable test program for us to look at? Just the absolute minimum
required to demonstrate the problem!

My hunch is that you are somehow shifting the text as you are writing it to the GLCD, which will give you the result that you appear to be seeing even
when using a text routine that clears/writes pixels explicitly.

John
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Mon Jan 19, 2015 5:33 pm     Reply with quote

Well it is a long program so I will just post the pertinent just to be brief.

.H file
Code:
#include <18F45K22.h>
#device ADC=10
#zero_ram

#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or
#use delay(internal=16000000)

void Init()  // initialization
{
set_tris_b(0x00);
set_tris_c(0x80);
set_tris_d(0x00);
setup_wdt(WDT_OFF);
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
glcd_init(ON);
}

RS232 interrupt and data from GPS
Code:

#INT_RDA
void  RDA_isr()
{  cbuff[next_in] = getc();
   last_in = next_in;
   if(cbuff[next_in] == '$' )             // this is the begining of the NMEA sentence 
        count =0;                         // we set the RecDatBuffer[count] so count is at the begining 0
       
//  if((cbuff[next_in] != '\r' )  || (cbuff[next_in] != '\n' )) // if we wanted to end the NMEA sentence at end of line
   if(cbuff[next_in] != '*' )             // keep storing in characters if we have not reached the end of the buffered sentence
   {RecDatBuffer[count] = cbuff[next_in];
    count++; }
                                          // here we look to see if we have the "$GPRMC" and the termination char available, meaning we have the whole sentence
   if((RMC) && (cbuff[next_in] == '*' ))  // we terminate at * the two byte checksum wich we discard this is the end of the buffered sentence
     {     BufferFlag= TRUE;               // now that we have the sentence we set the flag so we can parse the buffered sentence
           count++;
           RecDatBuffer[count]   = NULL; } // put in null delimiter to terminate NMEA sentence
   
   
    next_in++;
   if(next_in == BUFFER_SIZE)
      next_in = last_in;
}

Routine that actually writes GPS data to the display after parsing NMEA sentence.
Code:

 glcd_bar(10, 13, 125, 13, 7, OFF); ///// draw an invisible bar to erase entire text line
   sprintf(LCDText"Date:%u/%u/%lu",monthValue,dayValue,PresentYear);//  get the txt content for the line
   glcd_text57(10,10, LCDText, 1, ON); // write the entire text line
   
   glcd_bar(10, 23, 125, 23, 7, OFF); //glcd_bar(x1, y1, x2, y2, width, color)  glcd_bar(10, 23, 100, 23, 7, OFF);
   sprintf(LCDText"UTC:%sH:%sM:%sS",hour_nn,min_nn,sec_nnnnn);
   glcd_text57(10,20, LCDText, 1, ON);
 
   glcd_bar(10, 33, 125, 33, 7, OFF);
   sprintf(LCDText"Lat:%u:%5.3g%c",Lat_Deg,Lat_Min,N_S);
   glcd_text57(10,30, LCDText, 1, ON);
   
   glcd_bar(10, 43, 125, 43, 7, OFF);
   sprintf(LCDText"Lon:%u:%5.3g%c",Lon_Deg,Lon_Min,E_W);
   glcd_text57(10,40, LCDText, 1, ON);
   
   glcd_bar(10, 53, 125, 53, 7, OFF);
   sprintf(LCDText"Status:%s",Status);
   glcd_text57(10,50, LCDText, 1, ON);

main routine
Code:

void main()
{
 
char GPS_String[] = "$GPRMC,172958.00,A,2658.71175,N,08204.50983,W,0.036,,080115,,,D*6A"; // only used for parse testing
//int8 index;
   Init();
       
      glcd_init(ON);                               
      glcd_rect(0, 0, 126, 63, YES, ON);      // Outline the screen with a square but background is filled ************
      sprintf(LCDText"GPS Data\0");          // we use sprintf() to write to the string array LCDtext[]
      glcd_text57(22,15, LCDText, 2, OFF);    //we write this at 2 times the size of the normal font (1) we also use white background on black letter
      sprintf(LCDText"Using GPS click\0");   
      glcd_text57(20,40, LCDText, 1, OFF);     
         
      delay_ms(5000);
 
      glcd_init(ON);                               // Must initialize the LCD to clear screen
      glcd_rect(0, 0, 126, 63, NO, ON);
     
               
   //ParseNMEA();   // only for manual test of parsing
 
   
   while(TRUE)
   {
      if(BufferFlag)
         ParseNMEA();
         
   
     #ifdef FAST_GLCD
      glcd_update();
     #else
      delay_us(1);    // Reduces flicker by allowing pixels to be on
                        // much longer than off
     #endif
   
         restart_wdt();
   }

}

I did not include many of the parsing routines nor did I include the CFAG12864B.c and graphics.c which are CCS examples for the KS0108 that I just modied for my own use. The above program works just fine for the exception that I get the annoying update blinking. I have written this for the 16X2 LCD and it works flawlessly. When you say "you are somehow shifting the text as you are writing it to the GLCD" this may happen if I move the GPS antenna and I get longer strings like "Invalid Data" instead of "Valid Data" which will cause that problem. Perhaps there may be a shift due to loss of data or a longer or shorter data message been written to the screen.

Now for example if I was to continuosly write this data to the screen:
Code:

sprintf(LCDText"Hello cruel world!");
glcd_text57(10,20, LCDText, 1, ON);

I will only see: Hello cruel world! where i wrote to on the LCD without any blurring and everything looks fine!.

But if now I do the following:
Code:

sprintf(LCDText"the number is: \u",n++);
glcd_text57(10,20, LCDText, 1, ON);

The portion that says "the number is:" will look fine, but the actual number (n) printed on the LCD screen turns totally blurry from pixelation as it increments, because the actual character being written is changing and the previous pixels just stay ON which I think is my problem here.
Jerson



Joined: 31 Jul 2009
Posts: 122
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Mon Jan 19, 2015 10:55 pm     Reply with quote

can you try a simple exercise?

Change the statement to this
Code:

sprintf(LCDText,"the number is: %u     ",n++);
glcd_text57(10,20, LCDText, 1, ON);


By doing this, you are trailing the number with spaces that will erase any residue of longer numbers.
cbarberis



Joined: 01 Oct 2003
Posts: 172
Location: Punta Gorda, Florida USA

View user's profile Send private message Send e-mail

PostPosted: Tue Jan 20, 2015 7:04 pm     Reply with quote

Thank you Jerson, although I have not had the time to setup my breadboard and do further testing, what you imply I think is correct but unfortunately that blank space takes up valuable number of characters that would exceed my capacity for text on that row and most probably will wrap to the next line below.
Jerson



Joined: 31 Jul 2009
Posts: 122
Location: Bombay, India

View user's profile Send private message Visit poster's website

PostPosted: Tue Jan 20, 2015 10:28 pm     Reply with quote

It is just a suggestion to check if it resolves your problem.

What I do expands on this concept a little bit more

I have a printc routine that uses the character '\r' to trigger a clear to end of line. So printing something like
Code:

    printc("Number is %u\r",num);

will print the message with the number followed by as many spaces as will take the cursor to the end of the current row. It is not very fast, but, serves my purpose well.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group