Serial Controller for KS0108B GLCD

hippy

Technical Support
Staff member
You need to subtract from 'executebyte' rather than add. For example, if it's not < 32 but is < 64 then it holds value 32..63, the LOOKUP index starts at 0, so subtract 32 giving 0 to 31.
 

nick12ab

Senior Member
You need to subtract from 'executebyte' rather than add. For example, if it's not < 32 but is < 64 then it holds value 32..63, the LOOKUP index starts at 0, so subtract 32 giving 0 to 31.
It also had problems with the way the hex numbers were divided between the lookup commands as the end ones were duplicated causing some problems but that was fixed and your fix also applied and it now takes 0.6 seconds to print the entire character set on-screen.

I kept the old code and saved updates as seperate files so that I could go back to an old version and see how far it has come with the speed improvements. The earliest file I have is a test version which doesn't use the serial at all and only prints its character set. It took 1.4 seconds to do so and that old version actually took up more program memory despite it lacking every feature that the latest version has except the small text. Will attach that version and the latest version for comparison.

Newest code segment for small character lookup tables:
Code:
if executebyte < 32 then
	lookup executebyte,(0,$1020,$4444,$1474,$1D15,$1515,$1516,$1038,$FE83,$2214,$0808,$7F10,$4E71,$0002,$0808,$0000,$0808,$0000,$0000,$0808,$0808,$0808,$0000,$0808,$0808,$FFFF,$3E41,$3E41,$7F7F,$7F41,$7F00,$487E),cw1
	lookup executebyte,(0,$7F01,$5F44,$1C17,$1700,$1F00,$7C16,$5410,$8183,$0814,$2A08,$100F,$0171,$0502,$0808,$FF00,$FF08,$F808,$0F08,$0F00,$F800,$FF00,$FF08,$0F08,$F808,$FFFF,$7549,$5D49,$7F7F,$4141,$7F00,$4949),cw2
	lookup executebyte,(0,$0100,$4400,$1400,$0000,$0000,$1500,$1F00,$FE00,$2200,$0800,$1000,$4E00,$0000,$0808,$0000,$0808,$0808,$0808,$0000,$0000,$0000,$0808,$0808,$0808,$FFFF,$3E00,$3E00,$7F00,$7F00,$7F00,$4200),cw3
elseif executebyte < 64 then
	executebyte = executebyte - 32
	lookup executebyte,($0000,$0000,$0003,$147F,$242A,$2313,$3649,$0005,$001C,$0041,$1408,$0808,$0050,$0808,$0060,$2010,$7F41,$0000,$7949,$4149,$0F08,$4F49,$7F49,$0101,$7F49,$0F09,$0036,$0056,$0814,$1414,$0041,$0201),cw1
	lookup executebyte,($0000,$4F00,$0003,$147F,$7F2A,$0864,$5522,$0300,$2241,$221C,$3E08,$3E08,$3000,$0808,$6000,$0804,$4141,$0000,$4949,$4949,$0808,$4949,$4949,$0101,$4949,$0909,$3600,$3600,$2241,$1414,$2214,$5109),cw2
	lookup executebyte,($0000,$0000,$0000,$1400,$1200,$6200,$5000,$0000,$0000,$0000,$1400,$0800,$0000,$0800,$0000,$0200,$7F00,$7F00,$4F00,$7F00,$7F00,$7900,$7900,$7F00,$7F00,$7F00,$0000,$0000,$0000,$1400,$0800,$0600),cw3
elseif executebyte < 96 then
	executebyte = executebyte - 64
	lookup executebyte,($3E41,$7C12,$7F49,$3E41,$7F41,$7F49,$7F09,$3E41,$7F08,$0041,$2040,$7F08,$7F40,$7F02,$7F04,$3E41,$7F09,$3E41,$7F09,$4649,$0101,$3F40,$1F20,$3F40,$6314,$0304,$6151,$007F,$0204,$0041,$0402,$4040),cw1
	lookup executebyte,($5D55,$1112,$4949,$4141,$4122,$4949,$0909,$4949,$0808,$7F41,$413F,$1422,$4040,$0C02,$0810,$4141,$0909,$5121,$1929,$4949,$7F01,$4040,$4020,$3840,$0814,$7804,$4945,$4141,$0810,$417F,$0102,$4040),cw2
	lookup executebyte,($1E00,$7C00,$3600,$2200,$1C00,$4100,$0100,$7A00,$7F00,$0000,$0100,$4100,$4000,$7F00,$7F00,$3E00,$0600,$5E00,$4600,$3100,$0100,$3F00,$1F00,$3F00,$6300,$0300,$4300,$0000,$2000,$0000,$0400,$4000),cw3
else
	executebyte = executebyte - 96
	lookup executebyte,($0000,$2054,$7F48,$3844,$3844,$3854,$087E,$0C52,$7F08,$0044,$2040,$7F10,$0041,$7C04,$7C08,$3844,$7C14,$0814,$7C08,$4854,$043F,$3C40,$1C20,$3C40,$4428,$0C50,$4464,$081C,$0402,$0808,$0804,$1020),cw1
	lookup executebyte,($0305,$5454,$4444,$4444,$4448,$5454,$0901,$5252,$0404,$7D40,$443D,$2844,$7F40,$1804,$0404,$4444,$1414,$1418,$0404,$5454,$4440,$4020,$4020,$3040,$1028,$5050,$544C,$2A08,$7F02,$2A1C,$0810,$7F20),cw2
	lookup executebyte,($0000,$7800,$3800,$2000,$7F00,$1800,$0200,$3E00,$7800,$0000,$0000,$0000,$0000,$7800,$7800,$3800,$0800,$7C00,$0800,$2000,$2000,$7C00,$1C00,$3C00,$4400,$3C00,$4400,$0800,$0400,$0800,$0800,$1000),cw3
end if
Also, would using the 'disconnect' command increase the speed or does whatever scanning for the download does not have enough overhead for it to slow down the program whatsoever?
 

Attachments

Last edited:

rigidigital

Senior Member
I need help for getting text onto a KS1080B 128x64 GLCD as sold by Techsupplies at a decent speed. The trouble is - this controller doesn't seem to have a built-in capability for text. Putting text onto the display takes up much of the PICAXE (40X2) memory just for the numbers to define which pixels need to be set for which letters.

I decided that to overcome this I could use a serial driver chip for the display which is capable of putting text on it. I checked out the FGC thing offered on Techsupplies but it has flaws and is expensive. Its flaws are slow serial, and only allowing 7 lines of text when the display is capable of 8. I started producing my own version on the PICAXE-20X2 which lacks the circle-drawing and other features of the GLIC-K1 but has text on 8 lines, a PWM pin used for controlling the backlight (command: 249, byte for level), and allows direct control of the LCD as well through the high speed serial interface.

Only problem - it is very slow at printing the characters on screen... well not very slow for human standards but slow to computer standards. When the serial connection is disconnected, it continues printing the text which shows that all the data has already been received through hardware serial.

The code is attached as it is too big to show here. I'm thinking I may need to go for a lookup table with the command of the same name but typing that out will take an eternity so I'm looking for advice first. I have also included a video to demonstrate it. Those who own a GLIC-K1 may be able to tell me whether it provides a faster speed or not. Either way, I want this to look more professional.

The latest version of the code can be found at the end of this thread. The video has a PDF extension so that it can be uploaded here but you must change the extension back to 3gp to watch it.
I triednto play that pdf you attached but i could not play it, either unsupported or the file was corrupt ?
 

nick12ab

Senior Member
I triednto play that pdf you attached but i could not play it, either unsupported or the file was corrupt ?
Have you changed the file extension to 3gp ? PICAXE Forum does not support video uploads so I changed the extension to pdf so that I could upload it here.
 

hippy

Technical Support
Staff member
Also, would using the 'disconnect' command increase the speed or does whatever scanning for the download does not have enough overhead for it to slow down the program whatsoever?
You might eek out an extra microsecond per instruction performance but it probably wouldn't be noticeable.

You'd gain more by optimising out the ^invertbyte when not required; two sets of code for when invertbyte is zero and when it isn't, turning some of the LOOKUP into READ and READTABLE. You've still got a BINTOASCII and a divide by 20 which will will slow things down.
 

nick12ab

Senior Member
You'd gain more by optimising out the ^invertbyte when not required; two sets of code for when invertbyte is zero and when it isn't, turning some of the LOOKUP into READ and READTABLE. You've still got a BINTOASCII and a divide by 20 which will will slow things down.
Using seperate inverted and non-inverted character sets probably wouldn't fit into program memory and the IF statement to determine which to use would probably take longer to execute. Couldn't find a bintoascii anywhere in the code. Do you mean bintobcd?

Ran the experiment from Post 13 but using the number 54 and with these operations instead of the DIG operations:

divide by 20
divide by 4
shift right by 2
xor with 255
bintobcd


and the results are, again with each one executing 65535 times...
In first place, shift right by 2, which took 10.69 seconds. Not surprised.
In a close second place is xor with 255, which took 10.75 seconds. It is afterall, a bitwise operation so should be quick.
In third place, comes divide by 20, which took 14.06 seconds. It is closely followed by divide by 4, which took 14.25 seconds.
In last place, comes bintobcd which took 17.88 seconds.

Using disconnect caused some commands to run a little bit faster but also caused others to run slower. Why could that be? Anyway, the table only supports bytes and not words so would the support code required to put the correct bytes from the table into the correct bytes in RAM end up taking up more time than LOOKUP?
 
Last edited:

hippy

Technical Support
Staff member
The suggestions are the things I personally would consider if I were doing it. There seems plenty of space left and, while TABLE and EEPROM can only hold bytes, the gains in shortening the LOOKUP is probably greater than any overhead.

It's a good question of is the IF faster than all the ^invertByte; best way to tell is to try it.

One thing I forgot to mention is moving the 'cw' and 'cb' variables into w0, w1, b0-b3, as that could shave some more time off the case without ^invertbyte, for example ...

LookUp .... , cw1
:
let lcddata = cb1
let pinsB = lcddata
let pinC.1 = bit30
pulsout enablepin,1
let lcddata = cb2
let pinsB = lcddata
let pinC.1 = bit30
pulsout enablepin,1

Could then become ...

Symbol cw1 = w0
Symbol cb1 = b0
Symbol cb2 = b1
:
LookUp .... , cw1
:
let pinsB = cb1
let pinC.1 = bit6
pulsout enablepin,1
let pinsB = cb2
let pinC.1 = bit14
pulsout enablepin,1

That's two assignments which become redundant and have been removed, plus the LOOKUP into cw1 can be replaced in the fast case by

Read ... , cb1
ReadTable ... , cb2

So you get the same result and no additional assignments needed no matter which way it's done.

Of course the real question is; is it fast enough already ? If so it's not worth struggling to save a few microseconds or milliseconds.
 

nick12ab

Senior Member
The suggestions are the things I personally would consider if I were doing it. There seems plenty of space left and, while TABLE and EEPROM can only hold bytes, the gains in shortening the LOOKUP is probably greater than any overhead.

It's a good question of is the IF faster than all the ^invertByte; best way to tell is to try it.

One thing I forgot to mention is moving the 'cw' and 'cb' variables into w0, w1, b0-b3, as that could shave some more time off the case without ^invertbyte, for example ...

LookUp .... , cw1
:
let lcddata = cb1
let pinsB = lcddata
let pinC.1 = bit30
pulsout enablepin,1
let lcddata = cb2
let pinsB = lcddata
let pinC.1 = bit30
pulsout enablepin,1

Could then become ...

Symbol cw1 = w0
Symbol cb1 = b0
Symbol cb2 = b1
:
LookUp .... , cw1
:
let pinsB = cb1
let pinC.1 = bit6
pulsout enablepin,1
let pinsB = cb2
let pinC.1 = bit14
pulsout enablepin,1

That's two assignments which become redundant and have been removed, plus the LOOKUP into cw1 can be replaced in the fast case by

Read ... , cb1
ReadTable ... , cb2

So you get the same result and no additional assignments needed no matter which way it's done.

Of course the real question is; is it fast enough already ? If so it's not worth struggling to save a few microseconds or milliseconds.
For your code example to work, multiple IF statements would have to be used on the short LOOKUPs as there is only one remaining word that can have its bits accessed with bit#. The time taken for those extra IF statements would probably exceed the time gained by removing a line from each enable sequence as microcontrollers are best at doing simple maths and an IF statement would probably use a lot more instructions than a let something equal something else statement.

On the previous post where I said that:
nick12ab said:
Using disconnect caused some commands to run a little bit faster but also caused others to run faster.
, I actually meant to say "Using disconnect caused some commands to run a little bit faster but also caused others to run slower." so I will edit that in, but why would using Disconnect have strange effects like that?

Also, I don't understand how others have managed to get theirs much faster than mine. But I will definately run the tester on an IF statement.
 

hippy

Technical Support
Staff member
For your code example to work, multiple IF statements would have to be used on the short LOOKUPs as there is only one remaining word that can have its bits accessed with bit#.
Sometimes code optimisation means having to move things around, reassigning variables and dealing with the consequences of that. It's not uncommon to develop in stages, create a prototype which works, analyse how it could be better, rip it up entirely and restart with a blank canvas using knowledge gained.

It's all a matter of balancing what one can gain against what one loses so making something faster in one place may slow something else down or make that less convenient but as long as there's a gain that's a win. Something slow but rarely executed has less impact than something frequently executed which is slow.


I actually meant to say "Using disconnect caused some commands to run a little bit faster but also caused others to run slower." so I will edit that in, but why would using Disconnect have strange effects like that?
The check for download mainly occurs between commands ( and, for a few, within them ) so I would not have expected there to have been any appreciable increase or decrease in any commands you are using. Can you give examples of those commands which slow down ?


Also, I don't understand how others have managed to get theirs much faster than mine.
I'm not sure who the others are and what you are comparing with, is it truly like for like ?

They may not have used the same hardware, nor be controlling the same display or doing exactly what you are doing, and probably not using the same techniques.

Choice of hardware will impose limitations and thus affect performance but so too will technique and working out tricks which can be used; such as not sending position commands if the hardware auto-increments to the next address anyway.

As mentioned previously, code development for high-speed processing can often be upside down to other development and it takes a different way to approach it than usual. This is the direction I'm coming from, make the writes to the LCD as fast and as efficient as possible, choose hardware, allocate I/O lines and place variables to make that so, and then build backwards from there. Hence -

Code:
If invertByte = 0 Then
  PinsB = b0
  PinC.1 = bit6
  PinsB = b1
  PinC.1 = bit14
Else
  b0 = b0 ^ invertByte
  PinsB = b0 
  PinC.1 = bit6 
  b1 = b1 ^ invertByte
  PinsB = b1
  PinC.1 = bit14
End If
Does the IF cost less than two ( or more ) ^invertbyte ? I suspect so but one has to measure it. One could gain even more by optimising higher up ...

Code:
If invertByte = 0 Then
  LookUp ... , b0
  LookUp ... , b1
Else
  LookUp ... , b0
  LookUp ... , b1
End If
PinsB = b0
PinC.1 = bit6
PinsB = b1
PinC.1 = bit14
Then, improving the LOOKUP ...

Code:
If invertByte = 0 Then
  If index < 128 Then
    Read index, b0
    ReadTable index, b1
  Else
    index = index - 128
    LookUp ... , b0
    LookUp ... , b1
  End If
Else
  If index < 128 Then
    Read index, b0
    ReadTable index, b1
    b0 = b0 ^ invertByte 
    b1 = b1 ^ invertByte 
  Else
    index = index - 128
    LookUp ... , b0
    LookUp ... , b1
  End If  
End If
PinsB = b0
PinC.1 = bit6
PinsB = b1
PinC.1 = bit14
There are a whole load of potential possibilities and it's just a matter of working out which is most efficient and which fit within the constraints one has. Sometimes an expected gain isn't delivered so it's a case of try it, test it, continue or revert as you go, thinking about other potential choices and the opportunities and costs.

Added : And it's a matter of continually looking to see where improvements can be made. I've just realised the two -

b0 = b0 ^ invertByte
b1 = b1 ^ invertByte

can be replaced by a single -

w0 = w0 ^ invertWord

Again one has to set 'invertWord' to use it so it's a matter of trying each as a whole and seeing which is fastest.
 
Last edited:

nick12ab

Senior Member
I'm not sure who the others are and what you are comparing with, is it truly like for like ?

They may not have used the same hardware, nor be controlling the same display or doing exactly what you are doing, and probably not using the same techniques.
Posts 32 and 34 show Dippy's GLCD and he says that it only took 200ms. For the amount of characters, it is about the same as mine is now for the amount of text but as he's using variable-width, fixed-width should be faster. His GLCD is completely identical to mine.

Hippy said:
The check for download mainly occurs between commands ( and, for a few, within them ) so I would not have expected there to have been any appreciable increase or decrease in any commands you are using. Can you give examples of those commands which slow down ?
I will re-test them soon and post results.
 

MartinM57

Moderator
Posts 32 and 34 show Dippy's GLCD and he says that it only took 200ms.
I think you'll find that Dippy's controller was related to, but not a PICAXE :) (and was probably written using a BASIC compiler as opposed to running as interpreted basic)
 

Dippy

Moderator
Ha, yes you are nearly right Martin, I was having a practice run :)
I think Nick has done a great job doing the text at the speed he has achieved.

The main part that slows mine down is the coding technique I used to work as a general purpose drop of code which could work on many PICs.
E.G. Drawing a line. The accepted GP technique is to read a byte from the GLCD memory then logical bitwise add your dot and then rewrite. You do this because there may be already a dot occupying that byte. If you didn't then you would overwrite the byte and obliterate anything already there.
The other method (which I used for an OLED) is to store the GLCD memory 'mapped' on the PIC.
You then do your bitwise in PIC RAM and send the whole screen (or the relevant section of screen). This is much faster as there is only one-way traffic and RAM operations are many times faster than I/O.
My tests with an OLED (modern driver) shows a 20x speed improvement even sending the whole screen.


In my code the character (text) write is a simple write (no logical ops) and that takes around 100mS. I store my Font data as literal in Flash (programme space).


Notes.
One of the main issues with GLCDs is the pixel reresh speed.
They simply cannot keep up with there own drive electronics.
I have tried animation and even at the equiv of 6 frames per second they just look a messy blurr.
And, with a compiler, their drive elctronics can't keep up with compiled code, in fact I have to put pauses in the pin-twiddling routine.
With an OLED animations are very possible. I'm experimenting with a high-speed link from (my own) SD controller to (hopefully) get > 10fps. Albeit in mono 1-bit.

In summary Nick, you should be really pleased with what you've done but I'm afraid you'll probably never get it going much faster. I think what you have achieved is really good.
 

nick12ab

Senior Member
Here's the results for the experimentation on using DISCONNECT:


Ha, yes you are nearly right Martin, I was having a practice run :)
I think Nick has done a great job doing the text at the speed he has achieved.

The main part that slows mine down is the coding technique I used to work as a general purpose drop of code which could work on many PICs.
E.G. Drawing a line. The accepted GP technique is to read a byte from the GLCD memory then logical bitwise add your dot and then rewrite. You do this because there may be already a dot occupying that byte. If you didn't then you would overwrite the byte and obliterate anything already there.
The other method (which I used for an OLED) is to store the GLCD memory 'mapped' on the PIC.
You then do your bitwise in PIC RAM and send the whole screen (or the relevant section of screen). This is much faster as there is only one-way traffic and RAM operations are many times faster than I/O.
My tests with an OLED (modern driver) shows a 20x speed improvement even sending the whole screen.


In my code the character (text) write is a simple write (no logical ops) and that takes around 100mS. I store my Font data as literal in Flash (programme space).


Notes.
One of the main issues with GLCDs is the pixel reresh speed.
They simply cannot keep up with there own drive electronics.
I have tried animation and even at the equiv of 6 frames per second they just look a messy blurr.
And, with a compiler, their drive elctronics can't keep up with compiled code, in fact I have to put pauses in the pin-twiddling routine.
With an OLED animations are very possible. I'm experimenting with a high-speed link from (my own) SD controller to (hopefully) get > 10fps. Albeit in mono 1-bit.

In summary Nick, you should be really pleased with what you've done but I'm afraid you'll probably never get it going much faster. I think what you have achieved is really good.
Thanks for the praise, but it would have been impossible without the help of all the forum members who have posted stuff here.

Since you're on the topic of flaws in the GLCDs, do you know of any mod that can improve the awful contrast characteristics of the GLCD compared to a character LCD (where datasheets show a little graph of contrast of on pixel vs contrast of off pixel, on a GLCD those lines are really close together) as this problem only seems to show on GLCDs as used here and not old phone screens etc. I tried using different value resistors on a character LCD and 'it went funny' if the values differed or had no change if the values were all the same. I seem to have a desire to modify everything!

MartinM57 said:
I think you'll find that Dippy's controller was related to, but not a PICAXE (and was probably written using a BASIC compiler as opposed to running as interpreted basic)
Dippy said that Martin was nearly right so was Dippy's code compiled rather than interpreted?
 

hippy

Technical Support
Staff member
Here's the results for the experimentation on using DISCONNECT.
Interesting with the BINTOBCD. At 64K loops that 80ms difference works out at 1us per command. I would guess that's an instruction cycle delay which depends on whether a skip is taken or not, or more compound code behaving in a similar way. It does demonstrate though how even a very small difference can add up over a long enough time.
 

Dippy

Moderator
GLCD contrast quality varies quite a lot but none that I have seen are as good as modern cellphone etc. display quality. Your only safe 'controls' are supply voltage and the 'contrast' voltage setting.
Yes, it is compiled.
 

nick12ab

Senior Member
GLCD contrast quality varies quite a lot but none that I have seen are as good as modern cellphone etc. display quality. Your only safe 'controls' are supply voltage and the 'contrast' voltage setting.
Yes, it is compiled.
One thing that vaguely makes up for the awful contrast is that you can safely remove the LCD panel from the PCB and put it back in upside down to change the viewing angle. It works with any LCD, character or graphic, which has connectors at both the top and the bottom of the panel. Rev-Ed's GLCD comes designed to be viewed from below making it unsuitable for any application which is viewed from above without modification as above.

Anyway, I have applied the IF statements used to divide the LOOKUPs to the large character set. The speed gain wasn't so significant for that because the LOOKUP statements were much smaller than the ones for the small character set.

I have attached the latest code and a 'datasheet' for the driver explaining its features, showing code examples, a table giving a brief overview, a circuit diagram, pinouts for the driver and the GLCD, plus the character set tables. I will buy some 28X2s (not 20X2s) soon.

EDIT: What compiler did you use?

EDIT 2: I have uploaded another new version of the code due to a minor additional change. I swapped around the initialisation commands so that the DISPLAY ON command is the last one so that the garbled rubbish which often occupies the display data RAM after it it powered up is not seen until something can be done about it. Still going to work out clearing the screen on startup as it is no longer a simple gosub. The file name is the same as it was only a minor change.
 

Attachments

Last edited:

nick12ab

Senior Member
IF vs LOOKUP test

Tested the execution times of IF vs XOR. The XOR statement is simply 54 ^ b55 where b55 has nothing in it but we can pretend it's invertbyte and 54 is just a potential number (not b54). The IF statement is: IF b55 = 0 then : else : end if.

The IF statement, again executed 65535 times like all the experiments so far, took 11.75 seconds without DISCONNECT being used and it took 11.69 seconds with DISCONNECT being used.

The XOR statement took 10.81 seconds without DISCONNECT and 10.69 seconds without.

EDIT: Also, here's the results for DISCONNECT and RECONNECT:
Disconnect: 7.81 seconds
Reconnect: 7.69 seconds
 
Last edited:

nick12ab

Senior Member
As I don't have any 28X2s yet, I've decided to try it out on a 40X2 instead as they should both function the same. I have made the necessary conversions (I think) to operate on pins B without the extra port C pin and changed the other pins (RS, Enable, CS1, CS2, Backlight) because the hserin pin on 40X2 is C.7. Unfortunately, it doesn't work properly. Sending it the clear screen command, for example, instead sends some random number to the LCD as data.

The code is uploaded as an attachment.

Don't dismiss baud rate as a potential thing wrong as it could be a bad resonator or even a bad 40X2.
 

Attachments

MartinM57

Moderator
Code:
	setfreq [B][I]em40[/I][/B]						'Use [B][I]64MHz[/I][/B] as operating speed
	pwmout backlightpin,64,backlight			'Set backlight to saved value
	invert = 1							'Set default inversion setting: Not Inverted
x000:	hsersetup B38400_[B][I]64[/I][/B],%00111				'Initialise hardware serial input
What's the rationale for the inconsistency?
 

nick12ab

Senior Member
Code:
	setfreq [B][I]em40[/I][/B]						'Use [B][I]64MHz[/I][/B] as operating speed
	pwmout backlightpin,64,backlight			'Set backlight to saved value
	invert = 1							'Set default inversion setting: Not Inverted
x000:	hsersetup B38400_[B][I]64[/I][/B],%00111				'Initialise hardware serial input
What's the rationale for the inconsistency?
Oops! Failed to change that to B38400_40 for the 40MHz permitted by the 40X2-5v which I'm using.

It works better now but the large text is not functioning properly. The left side of the display doesn't work properly with the big text. It fails to put on the top half or bottom half of a large character on the left side of the display only and which part of the character alternates each time.

EDIT: Forget that, I had to add an OR %01000000 for setting the Y address because previously i relied on the high c.6 command for that.

So everything works fine now and until I get some 28X2s which can run on 64MHz, I still have an experimentation platform on which I can add extra hardware features (like a Contrast PWM pin and an image-storage EEPROM).
 
Last edited:

nick12ab

Senior Member
New feature: Contrast PWM pin. This is my current circuit for generating the negative voltage required by the GLCD from a PWM pin.


When the GLCD is attached, the lowest voltage it can produce is -3.5 volts which is just below the optimal voltage for room temperature so if the temperature changed, the optimal contrast may not be accessable. Does anyone have a better suggestion for a negative voltage generator that doesn't require an IC except for the one provided on the GLCD.

I have tried connecting the PWM to the power pin of the negative voltage generator chip but only the first few duty cycle values give a variety of contrast settings and then all the ones afterwards make the contrast far too high.

EDIT: The 'optimal voltage' mentioned here only refers to when there is very little text on the screen. The optimal voltage changes as more text is put on the screen.

EDIT 2: Connecting the PWM pin to the power pin of the voltage inverter through a diode using a small capacitor across the power pins of the inverter now works well.
 
Last edited:

nick12ab

Senior Member
A complete 28x2 implementation for driving GLCD may be found at glcd.svejklabs.cz.cc.

The application includes dot, line, box, circle, image and customizable fonts. Have a look.
I have tried to use Svejk's implementation to see if I can learn any code enhancements from that. It doesn't seem to work very well, unless I'm missing something that makes it dead-important that it runs on a 28X2 and not a 40X2, and the mammoth-themed software from his website won't download the data (I have downloaded both programs onto the chip) and the sample code which runs on the 08M gets it to fill the screen with whiteness and then does some other things until it gets to this:

It then restarts again. I'd assume the filling the screen with whiteness would normally load the sample shown on his webpage but it takes forever to turn the screen white so there may not be anything to learn from it when it comes to speed enhancements.

Because there are pictures of it working on his website, I must have done something wrong.

I better just go back to making development on my own.
 

nick12ab

Senior Member
nick12ab said:
It doesn't seem to work very well, unless I'm missing something
...Sounds likely.
Has anybody apart from Svejk managed to get his GLCD driver to work? That'll confirm whether I've built it correctly. I cannot see how it would do that due to an electrical error and is probably because the software doesn't work. I have no idea how to convert the bitmap into anything else using Visual Studio like Svejk does so the software could possibly be used if I decide to add an EEPROM to mine, so hopefully it's a problem with the PICAXE program he wrote.
 

Svejk

Senior Member
if I decide to add an EEPROM to mine
My implementation uses an eeprom to store all fonts and bitmap images. If you don't have one isn't likely to work. I never aimed for speed.

For a speedy sample see this little video and this. That code isn't available yet due to the messy programming style used.
 

nick12ab

Senior Member
My implementation uses an eeprom to store all fonts and bitmap images. If you don't have one isn't likely to work. I never aimed for speed.

For a speedy sample see this little video and this. That code isn't available yet due to the messy programming style used.
I do have an EEPROM and it was attached but the software from your website won't see the PICAXE. It is still the normal programming pins used by the software, right?
 

nick12ab

Senior Member
New Code and Datasheet

I have completed changing the code for the 28X2/40X2 from the 20X2. I will attach the new code and a new 'datasheet' with the circuit diagram and functions list.

EDIT: Forget about these - I will upload new code and datasheet very shortly to correct errors in datasheet and change of character set.
 

Attachments

Last edited:

nick12ab

Senior Member
New Code and Datasheet

I have modified the small character set so that the numbers look more like the proper LCD numbers rather than the ones that were there previously which I did just to save effort at the time. The new code is attached.

Also, in the datasheet, I forgot to connect the 'Serial In' label in the schematic to the Hardware Serial Pin on the Picaxe, so I have updated that and the character set in the datasheet, which is also uploaded.

But I am experiencing a bit of a problem with serial data being corrupted and if it is being used a lot, over time the backlight can change brightness and other funnies like that can happen so I reduced the baud rate of the serial input. It had little effect. I'm guessing it could be the resonator which could be why the AXE033 uses such a slow serial speed but as reducing the baud rate didn't seem to have an effect, it may not be that. I'll try a different resonator anyway.
 

Attachments

nick12ab

Senior Member
Going back temporarily to the GLCD contrast issues (post 55), I did a little experiment using different coloured LEDs as the LCD backlight and when I used blue LEDs, the colours were inverted, and the contrast characteristics improved slightly for orange (the only one bright enough to see) so from that I can conclude that it is the cool white backlighting LEDs that are causing the problem of contrast and I could probably improve the contrast by replacing them with warm white LEDs. This wouldn't cause any electrical problems like changing the clock speed and resistors etc. would.

Back to the serial corruption, I tried three different resonators and it dodn't change a thing. I didn't have any 'mint condition' 40X2s to use so it had to come out of my selection of faulty 40X2s - i chose the one with a dead pinD.7 as that pin isn't used by this but I can't imagine this corrupting only some bytes of the serial input. I couldn't use any of my other damaged 40X2s as they all had problems that made them unusable for this application (runs at around 2/3 speed on external osc, A.0 dead & no external osc, if B.7 = 1 then B.0 = 0 always).

I'm still waiting for Rapid Electronics to resume selling their range of dirt-cheap Winstar LCDs and OLEDs before I buy but they seem to be unable to make their mind up whether they are selling them or not and they keep disappearing and reappearing over time here. Strangely, in the saved basket my chosen ones are in, it still mentions the LCDs instead of 'invalid code'. Speaking of which, OLEDs would fix the contrast problem.

Until then, I'll remove a good 40X2 from a working project to check whether it's a bad 40X2 causing the serial problem.
 

nick12ab

Senior Member
Serial Corruption

Until then, I'll remove a good 40X2 from a working project to check whether it's a bad 40X2 causing the serial problem.
A different 40X2 made no difference at 40MHz. But as this other 40X2 was the universal voltage version, I could safely use a 16MHz resonator instead of 10MHz and change the hsersetup command in the code accordingly and it now works without any corruption.

I used the formula in the manual to calculate the constant used for B19200_40, and it was 519.8333333333333333. Because the PICAXE can't do decimals, the number should be 520 so I did a little test:
Code:
#picaxe 40x2
#terminal 9600
w0 = B19200_40
sertxd (w0,13,10)
reset
and it revealed that the number IS 520. I did the calculation for B19200_64 and that is 832.33333333333333, which isn't an exact integer either, and in fact, the 519.8333333 was closer to an integer than 832.33333333. But the number itself is much bigger so the decimal points probably lose enough significance to not cause corruption.

I left an experiment running for around half an hour before... THE CORRUPTION STARTED AGAIN!!! This time to a much lesser extent, but still happening. I can only assume that this is being caused by the resonator being warmed slightly by the neighbouring PICAXE and GLCD. So I replace the resonator with a different one - no difference!

All I can assume now is that the master PICAXE sending the test commands (a PICAXE-20X2) is suffering from internal oscillator drift because it's getting normally warm through operation. But when I briefly remove power in order to reset it, the corruption stops. I used a soldering iron to heat up the PICAXE-20X2 but that didn't cause corruption so it can't be a temperature-related issue. The corruption starts when the test application, which is a simplistic EEPROM tester, gets to around byte 10,000 (at 40MHz, it starts immediately). So I use a different 20X2 - same thing happens.

I then change the test program to work on the PICAXE-18M2 and... it does the same thing.

Anybody have any ideas why this is happening?
 

MartinM57

Moderator
You aren't the first, and won't be the last, person to discover that some PICAXEs without external resonators (eg 18M2, 20X2 etc), in some situations (temperature, external circuitry, length of wires, bodgit wiring/decent wiring, non-common grounds, phase of moon etc), after some time (straight away, after 30 mins, after 2 days) don't do perfect serial comms...

...and neither will most (all?) 8-bit PICs or AVRs operating on their internal oscillators.

If you want reliable comms use a crystal plus two caps (preferred if you want ultimate accuracy - a few tens of parts per million frequency accuracy) or a resonator (maybe around 0.5% frequency accuracy).

I can't explain why a resonator based PICAXE drifts sufficiently to corrupt serial comms though - it's certainly not normal and there is probably some external effect. I doubt you've uncovered a fundamental error in any PICAXE firmware. What EEPROM test program?
 

nick12ab

Senior Member
, in some situations (temperature, external circuitry, length of wires, bodgit wiring/decent wiring, non-common grounds, phase of moon etc), after some time (straight away, after 30 mins, after 2 days) don't do perfect serial comms...

...and neither will most (all?) 8-bit PICs or AVRs operating on their internal oscillators.

If you want reliable comms use a crystal plus two caps (preferred if you want ultimate accuracy - a few tens of parts per million frequency accuracy) or a resonator (maybe around 0.5% frequency accuracy).
Will the phase of moon really affect it or is that just a joke?

Anyway, to reduce the length of the wires, I could solder the resonator (soon-to-be crystal) straight to the pins of the microcontroller. I will get the crystals when I get the 28X2s. As the corruption problem can also happen when using the computer to send the data, the problem must lie in the resonator for the 40X2. I will relocate it as I am using wires 3 inches long to connect it currently to optimise the board space, but it is really strange that the problem gets corrected after the driving PICAXE is reset, so it is possible that voltage surges etc. are causing it to go back to normal when restarting the controlling PICAXE.

Or I could mount a heatsink on top of the PICAXE.

I can't explain why a resonator based PICAXE drifts sufficiently to corrupt serial comms though - it's certainly not normal and there is probably some external effect. I doubt you've uncovered a fundamental error in any PICAXE firmware. What EEPROM test program?
The EEPROM test program is one that I made myself. It isn't very good for testing EEPROMs as although it clears and sets all bits for each byte before restoring the original value, it doesn't check inbetween, so stuck bits would pass undetected and the EEPROM would have to fail during the test for it to be detected. It is still ideal as a test for sending lots of data to the GLCD. I'll upload the 20X2 and 18M2 versions.
 

Attachments

Dippy

Moderator
Absolutely.
Without delving into your code or your comms I can only assume it's drift.
I would NEVER use the INTOSC where timing (including Asynch serial) is important. You are asking for trouble.
As MArtin says: USE A CRYSTAL clock.

To test; just connect your 'scope and check the timings. You can calculate the exact timing easily. Try twidlling OSCTUNE to see if that improves things.
A 'scope will give you almost immediate confirmation as to whether it is a timing issue.

Bitmaps?
Yes, mine work fine.
Bitmap format goes in one direction and byte writing to your GLCD RAM is at right angles.
You have two basic options;
1. Use your PC and write some code to check and strip the header. Then reformat it and send it to EEPROM. That, I believe, is how Rev-Ed's GLIC works.
2. The method I use from SD is to read/check and strip the header. Then rejiggle the bytes so that the byte you send is perpendicular. It is easier to do this in a group of 8x8 cells.
Here is something I've knocked up for you in BASIC.

Code:
//
Sub PlotPictureNeg() ' Plots the image inverse (ie negative)
 
XPos = 0
YPos = 7
GWord = 2
GCommand = DByte(1)
For I = 7 To 0 Step -1 ' 64 lines = 8 charcater lines
For X2 = 0 To 15 ' Loop to get 8x8 cell . 15 is a linesworth.
For X1 = 0 To 7 ' Generate cell byte (a vertical byte)
CellByte.7 = GByte(GWord) <<X1 >>7 ' Pick out bit 7,6,5,4,3,2,1,0
CellByte.6 = GByte(GWord+16) <<X1 >>7
CellByte.5 = GByte(GWord+32) <<X1 >>7
CellByte.4 = GByte(GWord+48) <<X1 >>7
CellByte.3 = GByte(GWord+64) <<X1 >>7
CellByte.2 = GByte(GWord+80) <<X1 >>7
CellByte.1 = GByte(GWord+96) <<X1 >>7
CellByte.0 = GByte(GWord+112) <<X1 >>7 
Pos.x = XPos // GLCD x pos 
Pos.y = YPos // GLCD y pos 
Inc(XPos)
Next 'Vertical byte
Inc(GWord) ' Next group of image bytes 
Next 'X2
Dec(YPos)
XPos = 0 ' Set X back to start of line
Inc(GWord,112) ' Next block up
Next 
End Sub
//
Some compilers like MikroElektronika BASIC do a lot of the hard work for you. So you can write code and look really clever ;)
But as I don't like M.E. compilers I wrote my own.
From SD to screen takes about 0.5 seconds but that's mostly as my SD controller is a separate device and sends to serial to the GLCD controller.
Yes, my new graphics driver on an 18FK22 works flawlessly..... assuming the 'host' serial timing is good.:eek:
 

MartinM57

Moderator
Remember both ends of the comms link must be running at an accurate frequency - so if you have both ends running on inaccurate timing mechanisms you have double the trouble. What happens if you get your PICAXE to send everything to your PC for hours on end instead of the GLCD?

Phase of the moon affecting serial comms - what do you think? ;)
 

nick12ab

Senior Member
Remember both ends of the comms link must be running at an accurate frequency - so if you have both ends running on inaccurate timing mechanisms you have double the trouble. What happens if you get your PICAXE to send everything to your PC for hours on end instead of the GLCD?

Phase of the moon affecting serial comms - what do you think? ;)
I have started an experiment with the microcontroller sending lots of data to the PC instead of the GLCD. To make the test fair, I'm using the same EEPROM testing program so I'll report back when it's finished.

Phase of moon doesn't affect serial comms as otherwise PICAXE programs will only be downloadable on certain days of the month.
 

eclectic

Moderator
Phase of moon doesn't affect serial comms as otherwise PICAXE programs will only be downloadable on certain days of the month.
Hmm?

Look at what happened between your posts 61 and 62.
There was a full Moon in the UK. (15 06)

Mind though, you live in x
so perhaps the Moon doesn't reach you?

exits making Milligany "wwooo " noises.

e
 

nick12ab

Senior Member
Hmm?

Look at what happened between your posts 61 and 62.
There was a full Moon in the UK. (15 06)

Mind though, you live in x
so perhaps the Moon doesn't reach you?

exits making Milligany "wwooo " noises.

e
So far the test is running fine so it would appear the moon has no effect. I put location as x because I'm not giving away where I live unless I have to, but it's in the UK.
 
Top