|
|
View previous topic :: View next topic |
Author |
Message |
Fabri
Joined: 22 Aug 2005 Posts: 275
|
GLCD 128x64 driver and glcd_update |
Posted: Fri Jan 03, 2014 4:20 pm |
|
|
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
|
|
Posted: Fri Jan 03, 2014 4:43 pm |
|
|
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
|
|
Posted: Sat Jan 04, 2014 4:06 am |
|
|
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
|
|
Posted: Sat Jan 04, 2014 7:47 am |
|
|
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
|
|
Posted: Sat Jan 04, 2014 9:12 am |
|
|
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
|
|
Posted: Sat Jan 04, 2014 9:38 am |
|
|
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
|
|
Posted: Sat Jan 04, 2014 9:50 am |
|
|
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
|
|
Posted: Sat Jan 04, 2014 1:40 pm |
|
|
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
|
|
Posted: Sat Jan 04, 2014 3:09 pm |
|
|
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
Regards,
Fabri |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19541
|
|
Posted: Sun Jan 05, 2014 3:27 am |
|
|
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
|
|
Posted: Sun Jan 05, 2014 5:01 am |
|
|
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 |
|
|
|
|
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
|