PDA

View Full Version : My "Library" for ST7920 Graphical displays, works fine, but...



CuriousOne
- 16th May 2022, 06:37
Hello.
There are LCD modules, based on ST7920 controller, which are pin and command compatible with HD44780 controllers, so they can be used with PBP, by using LCDOUT statement. This saves a lot of time, can be run on almost any PIC, no need for includes and so on. Also, with these, any existing project can be easily updated, since no need to change PCB or hardware layouts. At the current stage, I'm using a 1602 compatible module, which has same physical outline, but has resolution of 144x32 pixels, instead of 80x16 of standard 1602. This allows to have 4 lines of 18 character text on screen, instead of 2 lines x 16 character, with better looking 7x7 font. If 5x7 font will be used, it will be possible to display 24 characters per line. The attached picture shows my ASCII 7x7 font for that display. The code is here.



LCDOUT $FE,$2E 'enable graphic mode
pause 1
gosub gpt 'clear screen after switching to graphics mode
topline var byte [18]
arraywrite topline, ["0123456789:;<=>?@ "]
C=0 'line number multiplied by 8
gosub GCODER
arraywrite topline, ["ABCDEFGHIJKLMNOPQR"]
c=8
gosub gcoder
arraywrite topline, ["STUVXYZ[\]&_`abcde"]
c=16
gosub gcoder
C=24
arraywrite topline, ["fghijklmnopqrstuvw"]
GOSUB GCODER
stop
GCODER:
FOR X=0 TO 17 step 2 'READ ARRAY INTO VARIABLE, ARRAY MEMBER CHAR=EEPROM OFFSET
Y=(topline[x])*8-264
Z=(topline[x+1])*8-264 'READ INTO VARIABLE AS TWINS
FOR I=0 TO 7 'HELPER LOOP FOR CHARACTER READING
i2cread sda, scl, adr, y+i, [a]
i2cread sda, scl, adr, z+i, [b]
LCDOUT $FE,$80+i+c 'UPDATE Y POSITION
LCDOUT $FE,$80+x/2 'UPDATE X POSITION
if topline[x]=32 then a=0
if topline[x+1]=32 then b=0 'blanker to display space (32)
LCDOUT a
LCDOUT b 'WRITE TO SCREEN
NEXT I
NEXT X
return
GPT: 'clear screen
z=0
for y=0 to 32
LCDOUT $FE,$80+y
LCDOUT $FE,$80
FOR x=1 TO 18
LCDOUT z
NEXT
next
return


At initial state, I was using on chip eeprom for storing font data, and using READ statement to read it. The speed was very fast - fast enough that I can do smooth scrolling, and some old school jumping lines/letters, parallax scrolling effects. But since in most PICs, on-chip eeprom is limited to 128 or 256 bytes, that amount is not enough to store complete ASCII character set. So I decided to use an external, I2C eeprom for font data storage. In this particular case, I'm using 24C256 chip. It works fine, but there's an issue with speed. Now, to re-read characters needed for complete screen display (576 bytes), it needs approximately 1 second, which makes smooth scrolling and other, "realtime" effects impossible.

So the question is following: This slowdown is definitely happens over I2C, because with on chip eeprom, everything is very fast. Is this caused by PBP limitation of I2C implementation, or the 24C256 is slow by it's nature and can't be read that fast? So what are ways of solving this? Use hardware I2C? (how?) use faster eeprom chip (which?)

Thanks!

9222

HenrikOlsson
- 16th May 2022, 14:59
Store the font data in program memory instead.

CuriousOne
- 16th May 2022, 17:06
I'm using 24C256 for a good reason - due to amount of data being used :)
Also, when using program memory, it won't be that easy to form the letters, as I do in the example above.

tumbleweed
- 16th May 2022, 19:17
But since in most PICs, on-chip eeprom is limited to 128 or 256 bytes
Would 1K of EEPROM be enough for what you're doing?

If so, switch to a pic18, like an 18F26K22. It'll be MUCH faster than trying to read from an I2C EEPROM.

CuriousOne
- 16th May 2022, 19:52
24C256 is 32KB EEPROM.
So I'm using it, because I need that much amount of font/graphics data :)

tumbleweed
- 16th May 2022, 23:25
In that case, if you're looking for speed then an I2C EEPROM isn't the best of choices.

I have no idea how slow the bit-banged I2CREAD is (probably pretty slow).
A 24C256 isn't all that slow, but you're going to be limited to about 400KHz using the pic's MSSP hardware.
That means a random read operation works out to something like 120us/byte @ 400KHz.

A faster choice would be an SPI EEPROM like a 25LC512. There you'll probably be able to get the MSSP to run at 8MHz,
which would speed up the random read to about 5-10us/byte.

If you can read more than 1 byte at a time then the operations are a bit faster, but Henrik's suggestion of using program memory would be faster.

richard
- 17th May 2022, 02:47
9x2x8 lcd "command delays" per text line is probably the worst delay
your snippet lacks that exact detail


the st7920 chip has a spi i/f that's a little faster and uses less pins too

there are better methods, at least use a graphics row buffer

even unpacking a "DA" packed font from flash is fasted than bit banged i2c by a large margin


this example uses 16 byte row data transfers for either i/f [way more efficient]
http://www.picbasic.co.uk/forum/showthread.php?t=24218
post# 26/27

CuriousOne
- 17th May 2022, 05:34
Thanks everyone.
So let's answer step by step.
There are no significant delays with ST7920 itself nor SPI should be used for it. I'm looking for best compatibility, and with LCDOUT it works like charm. When reading data from built-in eeprom of PIC16F886, I can update whole, 144x32 pixels screen at 20 fps. That's fully enough.
Regarding the SPI flash, I tried to use 25xx series, but was not able to connect to it via PBP. And by the way, as I know, there is no direct support for hardware MSSP in PBP, so it will be slow as I2C, or I have to use some large inserts on ASM or whatsoever, which will be again limitation in available hardware, like need for PIC18 series, while my code above can be used even on 16F628A.
Maybe I should use some old style, parallel eeprom, like ones used in old motherboards?

HenrikOlsson
- 17th May 2022, 06:01
Oh, you don't want to limit yourself to the hundreds of available 18F series devices so your contemplating using old parallell I/F EEPROMs instead, needing so many I/O-lines that you'll probably have less PICs to choose from than if you went with an 18F series device in the first place. And of those devices that DO have enough pins 75% probably are 18F series anyway.

Also, a cheap 32k x 8 parallell EEPROM is like €14 while a cheap SPI FLASH with less than €1 (and has 4 times the amount of space).

You don't need assembly to use the MSSP module.

HenrikOlsson
- 17th May 2022, 06:02
Oh, you don't want to limit yourself to the hundreds of available 18F series devices so your contemplating using old parallell I/F EEPROMs instead, needing so many I/O-lines that you'll probably have less PICs to choose from than if you went with an 18F series device in the first place. And of those devices that DO have enough pins 75% probably are 18F series anyway.

Also, a cheap 32k x 8 parallell EEPROM is like €14 while a cheap SPI FLASH is less than €1 (and has 4 times the amount of space).

You don't need assembly to use the MSSP module.

CuriousOne
- 17th May 2022, 06:26
The main difference between us is the sourcing capabilities :)
I'm buying everything from china, so I'm paying about 3 cents for 24C256 and parallel eeprom is somewhere around 40 cents. I guess, I can tolerate the difference :) But for PICs, 2nd hand 16F886 is about 70 cents, and 2nd hand 18F4550 is about $4, that is already a difference
and regarding the pin count, what you're trying to say, that 40 pin or 64 pin PICs aren't available in 16F series? For sure they are.
So if you have simple, clean to understand code for working with MSSP in PBP, I'd like to have a look...

tumbleweed
- 17th May 2022, 12:48
If you're trying to write something totally generic that can be used with all the 8-bit PIC's then the most generic solution is to use the bit-banged I2C routines.

If you want a faster method then using the MSSP hardware is the solution, but-
a) not all PIC's have an MSSP module
b) even if they do, they all don't work quite the same, so there may be some slight differences in programming

SPI is simpler and faster than I2C but will take 4 pins instead of 2.
Either way, you will be limited as to which pins can be used... bit-banged can use pretty much any pins but the MSSP uses fixed pins.

If somebody required me to use a parallel EEPROM for something like this I'd laugh and say "no thanks".

CuriousOne
- 17th May 2022, 17:28
Well I tried software SPI with MAX7219 and was not impressed at all - updating 32x8 pixels led display was quite slow....

HenrikOlsson
- 17th May 2022, 19:57
So if you have simple, clean to understand code for working with MSSP in PBP, I'd like to have a look...
I'll just point to MELABS: https://melabs.com/samples/PBP-mixed/spimast.htm That example is what I used as a basis when I first used the MSSP module for SPI (for interfacing the W5100 (search the forum for that code if you want)). See, not a single line of assembly.

CuriousOne
- 17th May 2022, 21:06
Thanks, but that code is missing SSPBUF declaration?

HenrikOlsson
- 17th May 2022, 21:28
No.
SSPBUF is the Synchronous Serial Port Receive Buffer/Transmit Register. It's the name of register to/from which you write/read whatever gets shifted out.

CuriousOne
- 18th May 2022, 04:43
Good.
So I have to "learn" to use SPI eeprom 1st, and then use MSSP :)
By the way, if I leave current setup as is - using I2C, but use PIC running at say 32mhz (instead of current 8mhz), will this result 4x times faster reading speed or not?

HenrikOlsson
- 18th May 2022, 05:29
Have you measure what clock speed you're getting?
Standard "high speed" I2C clock is 400kHz, maximum clock speed of a Microchip 24C256 when run at >2.5V is 1MHz.
SPI-interface flash chips usually has a maximum clock frequency of at least 33MHz.

CuriousOne
- 18th May 2022, 05:32
Not yet, but will do. Measure what, I2C clock frequency?
Tried modifying code in a way, that only that part of screen is redrawn, which is being updated. For some uses it does helps, but not always.

tumbleweed
- 18th May 2022, 11:58
using I2C, but use PIC running at say 32mhz (instead of current 8mhz), will this result 4x times faster reading speed or not?
If you're running at 8MHz then no wonder everything is slow.

32MHz (or 64MHz for something like an 18F26K22) would definitely be faster, way faster.
The I2C won't necessarily be a lot faster on its own (that depends on how I2CREAD is written), but you can almost bet that it will be.
One thing is for sure, everything else will be much faster.

Getting the pic I2C to run at much more than 400KHz depends on the chip and your hdw.
I2CREAD probably won't do it even running at 32MHz, but the MSSP can if you have pullups with a low enough value.
You won't get 1MHz out of it, but it's possible to get about 800KHz or so given the right setup.

The SPI on a pic tops out at about 8-10MHz, but the selection of available clocks depends on the chip.
I've been able to get 16MHz on a few select 18F devices but that's about the max that the IO pins can do.

There are a lot of benefits to switching to a more modern chip, esp a PIC18F.
I usually like to use a K22, K40, or Q10 for general stuff.
The more recent the chip the cheaper it will be (but I don't buy 2nd hand chips from china).


Measure what, I2C clock frequency?
That's where I always start. That'll let you know the max performance you're getting, and rules out a bunch of other stuff that can mask it.
A few poorly placed delay calls can ruin everything, no matter what speed you're running at.

For example, that SPI code has a totally unnecessary delay call in the read portion that does absolutely nothing but slow down the program (I think it was a 25us delay???).

CuriousOne
- 18th May 2022, 20:22
Well, I don't see anything to be slow at 8mhz, except I2C :D
Had no time today, will measure I2C frequency tomorrow and post back....

CuriousOne
- 19th May 2022, 19:26
Ok, measured I2C CLK speed. it is about 48khz. So I guess, this is the main issue, right?

tumbleweed
- 20th May 2022, 11:34
Well, that's going to make I2C operations about ten times slower than what it could be running at.

A while back you mentioned using software SPI and complained about it being slow too.
You'd probably find the same sort of issue.

The builtin high-level commands make things easy to use, but you pay a price for that.

CuriousOne
- 20th May 2022, 16:40
So only one way to get the speed, is to use SPI, but with MSSP?

CuriousOne
- 20th May 2022, 17:35
By the way, as PIC16F886 datasheet says:

Master Synchronous Serial Port (MSSP) Module
supporting 3-wire SPI (all 4 modes) and I2C™
Master and Slave Modes with I2C Address Mask

This means, I can use MSSP for I2C too, via PBP?

tumbleweed
- 20th May 2022, 18:13
Yes, the MSSP does both.

CuriousOne
- 20th May 2022, 20:06
Yes, found some sample code for hardware I2C listed here. Reading thru them slowly....

CuriousOne
- 9th June 2022, 18:05
Added "giant" size, 16x24 pixels font to the charset. But some letters need fine tuning. Once completed, will make this font .hex file free for everyone.

9237

CuriousOne
- 15th June 2022, 20:57
Bought larger version, which has 128x64 pixels arrangement.
But the issue is, that above code can write only to upper 32 lines of display.

https://blog.projectryu.com/using-digole-12864zw-lcd-with-pic18f/

This appears to be quite similar, but not exactly, to my module. And by sending some wild bits, I found out two things:

1. it is somehow possible to adjust contrast via software, but I guess, I'm sending wrong bytes, since display hangs after this (but remaining picture has high contrast)

LCDOUT $FE, $80
LCDOUT $FE, 10

above mentioned code mentions some X variable, which seems to be the "divider" between upper and lower parts of the screen, based on this pic: https://blog.projectryu.com/wp-content/uploads/2013/12/Digole-12864-Address-Map.jpg

But I can't get idea, where to write it?

CuriousOne
- 16th June 2022, 09:16
Solved issue with writing to lower lines.
These screens are actually divided into 64x32 blocks, which are addressed as 256x32, but physically located as
AB
CD
So this is it.

CuriousOne
- 29th June 2022, 07:40
Will post "Upgraded" version soon - it now supports individual attributes for all chars, like language, inversion, underline, striketrough. Working on variable width character support too.

9246

CuriousOne
- 19th July 2022, 19:53
Ordered 128x64 display from the different manufacturer.
It has proper dimensions - the screen above is almost square, as you can see, and the new one has proper proportions.
But it also has 20 pin connector, instead of standard 16 pin, and while it works, seems that addressing mode is different in graphic mode, haven't figured it yet. Will post update once "solved".