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 CCS Technical Support

GLCD 128x64 driver and glcd_update

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



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

GLCD 128x64 driver and glcd_update
PostPosted: Fri Jan 03, 2014 4:20 pm     Reply with quote

Hi to all,

As my last post of some days ago I'm trying to use GLCD 128x64 display in FAST_GLCD mode because I use shift register instead parallel port. This because I haven't enough I/O. I can't change PIC at the moment.
The problem is time used from glcd_update() function to write all display every time I change something. Really, I write just some areas of display not all pixel every time.
At the moment I have 40% of ram used, so I think to work in ram and write only byte changed into GLCD.

In your opinion, does it possible ? any other solution to suggest me ?

Thanks,
Fabri
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jan 03, 2014 4:43 pm     Reply with quote

comment: You'll need to do a study and a lot of math to see if it's worth the effort. Yes, it could be done if you have sufficient RAM available and speed. You would need 2 RAM buffers.One with the new data and the other with 'flags' to tell the PIC which bytes to update. Once your 'newdata' buffer is complete, the PIC would have to read the 'flagbuffer' to select and transfer the 'newdata' buffer data to the GLCD. Depending on the size of buffers, PIC speed, algoritms for deciding what's new, what to move, etc. the PIC could be spending MORE time than just re-writing the entire buffer to the GLCD. Obviously if only certain small areas of the GLCD need 'updating', it should be faster to use RAM buffering but if enough pixels need to change then do them all. Another factor would be the 'screen update' or data refresh rate. The faster or more frequent the rate, the more data probably has to be moved.
A possible alternative is to have a 'smart screen PIC/ GLCD' module. PICs are inexpensive! It may be cheaper to have a midsized, fast PIC just do screen interface and connect to the 'brains' or 'controller' PIC via SPI ? This offloading of GLCD to another PIC would free up the 'controller' PIC. You've said you're already 'PINned' out, so this might be an option. Also consider the time factor to get code 'up and running'. This option might be faster, easier to implement than a dual RAM buffer solution especially if you find out you really do NOT have enough RAM for the application!


hth
jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 4:06 am     Reply with quote

The problem is how to know what parts of the screen need to update....

You end up either having to hold two copies of the screen in memory, one the 'before changes', and the other the 'after', and then sending just the bytes that are different, or you have to send the whole screen.

You could do it my having a limited 'change buffer' list, and storing details of which bytes changed in this, but again storage becomes the limiting factor.
It's made worse for you, because if I remember your earlier post, you are using multiplexed drive to the display, which slows the transactions, making the full screen update less acceptable.

Best Wishes
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 7:47 am     Reply with quote

Thanks for suggestions.

Actually my product has two kind of display, led 7 segments and LCD 16x2. Based on same production I want to introduce graphic display. Really it's just a restyling of display waiting a TFT touch screen. It will arrive soon based on PIC32. I already develope displays based on I2C bus, RS232 and RS485 comunications some years ago. They are in production and work fine. Anyway I'll work on before decide to introduce one second PIC dedicate to GLCD.

Regards,
Fabri
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 9:12 am     Reply with quote

I changed in this way glcd_update() but don't work very well and I don't understand where's problem. It doesn't write in the correct position...

I created second structure with copy of data written to display.

Code:

struct
{
   unsigned int8 left[512];
   unsigned int8 right[512];
} displayData;

struct
{
   unsigned int8 left[512];
   unsigned int8 right[512];
} displayData_GLCD_copy;




void glcd_update()
{
   unsigned int8 i, j,data_check;
   unsigned int8 *p1, *p2, *p1_s, *p2_s;

   p1 = displayData.left;
   p2 = displayData.right;
   p1_s= displayData_GLCD_copy.left;   
   p2_s= displayData_GLCD_copy.right;   



   // Loop through the vertical pages
   for(i = 0; i < 8; ++i)
   {
      output_low(GLCD_DI);                      // Set for instruction
      glcd_writeByte(GLCD_LEFT, 0x40);          // Set horizontal address to 0
      glcd_writeByte(GLCD_RIGHT, 0x40);
      glcd_writeByte(GLCD_LEFT, i | 0xB8);      // Set page address
      glcd_writeByte(GLCD_RIGHT, i | 0xB8);
      output_high(GLCD_DI);                     // Set for data

// Controllo
     for(j = 0; j < 64; ++j)
      {
      if(*p1 != *p1_s){
         *p1_s=*p1;
         glcd_writeByte(GLCD_LEFT, *p1);      // Turn pixels on or off
      }
      *p1++;
      *p1_s++;

      if(*p2 != *p2_s){
         *p2_s=*p2;
         glcd_writeByte(GLCD_RIGHT, *p2);     // Turn pixels on or off
      }
      *p2++;
      *p2_s++;
      }
   }
}


Thanks for help,
Fabri
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 9:38 am     Reply with quote

comment: "It doesn't write in the correct position... " isn't really too useful

Please tell us where it 'should' write and 'where' it does write. it's difficult to decide what the problem is if we don't know the data.

could be you're updating a variable before you should, mismatch of counters,pointing to the wrong data,etc.

we need a few examples before we can accuratly diagnose.

hth
jay
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 9:50 am     Reply with quote

you are right but It's difficult to explain you. Anyway seems I write in different page of controller. I think I have to study routine, it isn't easy as I thought.
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 1:40 pm     Reply with quote

Addresses....

The bulk loader is taking advantage of not having to address every byte.
When you write a byte the write address automatically increments by one. So the standard transfer becomes 'set the address to the start of the line', then 'send all the bytes for the line'.
With the 'only send the bytes that have changed' driver, you have to send the address for each byte before you send it.

Best Wishes
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sat Jan 04, 2014 3:09 pm     Reply with quote

now it's clear... I'm wondering about....

Anyway at the moment I don't know how do that.
I have all night to study and solve Very Happy

Regards,
Fabri
Ttelmah



Joined: 11 Mar 2010
Posts: 19541

View user's profile Send private message

PostPosted: Sun Jan 05, 2014 3:27 am     Reply with quote

The code is already in the driver (with some fiddling!...).
Key is that the 'slow mode' driver has to address the bytes individually like this.
It functions by selecting the address, reading the byte, modifying the bit required, and writing back.
If you look at the section:
Code:

   int1 side = GLCD_LEFT;  // Stores which chip to use on the LCD
   if(x > 63)              // Check for first or second display area
   {
      x -= 64;
      side = GLCD_RIGHT;
   }

   output_low(GLCD_DI);                         // Set for instruction
   bit_clear(x,7);                              // Clear the MSB. Part of an instruction code
   bit_set(x,6);                                // Set bit 6. Also part of an instruction code
   glcd_writeByte(side, x);                     // Set the horizontal address
   glcd_writeByte(side, (y/8 & 0xBF) | 0xB8);   // Set the vertical page address
   output_high(GLCD_DI);                        // Set for data

This is the routine to set the address to write/read.
Now in the slow routine it then reads the data, resets the horizontal address, and writes, but you should just be able to write the byte required.

However I'd expect it to be possible to save writes, by selecting the page once, and then doing all the horizontal addresses needed in one page, by just updating this part of the address.

The key though is that the extra writes needed are 'why' the fast routine doesn't bother. With the standard 'non multiplexed' connections, it only takes about 10uSec to send a byte. The entire screen can be written in only just over 1/10th second.....

Best Wishes
Fabri



Joined: 22 Aug 2005
Posts: 275

View user's profile Send private message

PostPosted: Sun Jan 05, 2014 5:01 am     Reply with quote

Ok Ttelmah, this is my routine. It's work quite well. I don't understand why it don't delete pixel on display.
Code:

struct
{
   unsigned int8 left[512];
   unsigned int8 right[512];
} displayData;

struct
{
   unsigned int8 left[512];
   unsigned int8 right[512];
} displayData_GLCD_copy;


void glcd_update_sel()
{
   int *p_adr;
   int *p_adr_s;
   int page;
   int adr_hor;
   int16 p_ram;
   int16 j;

   p_adr=displayData.left;
   p_adr_s=displayData_GLCD_copy.left;

// Check RAM left side controller
   for (p_ram=0;p_ram<512;p_ram++){
      if(p_adr_s[p_ram]!=p_adr[p_ram]){
         p_adr_s[p_ram]=p_adr[p_ram];

// get adr and page of changed byte
         j=p_ram;
          page=0;
          while (j>64){
            page++;
            j-=64;
          }   
// Now I write address and data of byte changed
         adr_hor=(int)j;
          output_low(GLCD_DI);                                  // Set for instruction
          glcd_writeByte(GLCD_LEFT, adr_hor | 0b01000000);    // Set horizontal address to 0
          glcd_writeByte(GLCD_LEFT, page | 0b10111000);// Set page address
          output_high(GLCD_DI);                                    // Set for data
          glcd_writeByte(GLCD_LEFT,p_adr[p_ram]);
      
      }
   }
// Check RAM right side controller
   p_adr=displayData.right;
   p_adr_s=displayData_GLCD_copy.right;

   for (p_ram=0;p_ram<512;p_ram++){
      if(p_adr[p_ram]!=p_adr_s[p_ram]){
         p_adr_s[p_ram]=p_adr[p_ram];

// get adr and page of changed byte
         j=p_ram;
          page=0;
          while (j>64){
            page++;
            j-=64;
          }
   
// Now I write address and data of byte changed
         adr_hor=(int)j;
          output_low(GLCD_DI);                                  // Set for instruction
          glcd_writeByte(GLCD_RIGHT, adr_hor | 0b01000000);    // Set horizontal address to 0
          glcd_writeByte(GLCD_RIGHT, page | 0b10111000);         // Set page address
          output_high(GLCD_DI);                                    // Set for data
          glcd_writeByte(GLCD_RIGHT,p_adr[p_ram]);
      }
   }
}   


Standard glcd_update() function take 80ms. After this routine will work fine I must understand if this way is correct or introduce one pic for LCD. LCD is connected by flat 1,5 m long. I can provide it on PCB and decide in second time. I think to use I2C bus anyway because it's present on flat.

Regarding uncleared pixel have you something to suggest me ?

By the way, I'm sorry. My English is not very good.

Fabri
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