Non CG Ram Custom characters?

Hey all,
I am running up on a wall again. I have been using some code I saw in a post by Anachrocomputer for the creation and use of custom characters. This has been working great, but you are limited to the 8 chars held in the LCD CG RAM. I have been trying to make a custom graphic that is 2 rows high an 5 columns long (10 chars). You can redefine characters after the initial set up so you can change out character sets which is cool, but if you change them out while characters from the original set are still on screen, they too get changed.

So,
I am trying to understand how

static unsigned char angryDog[8] = { 0x10,0x1C,0x17,0x1C,0x1C,0x1F,0x18,0x10 };

gets converted to the actual character. I understand the graphic and how to create the graphic. I understand that it is an array of 8 words that stack up to make the graphic. I have had no problems with this, but as to the creation within the program space, I do not understand why Anachrocomputer’s code works the way it does (just being honest here folks). So, trying to munch through this the best I can…

In the set up for the custom character I see this line

  if (( asc < 0 ) || ( asc > 7 )) // if asc is greater than 0 OR less than 7
    return;

which I believe to be the CG RAM locater for positions 0-7. Since variables mean something to someone, (at least I know why I name things the way I name them) I am curious what asc means to Anachrocomputer.

  thelcd.command ( 0x40 | ( asc << 3 )); // Row select 2 - bitwise OR - bitshift left 3

I pulled this appart to try to get a handle on it, but nope, honestly, I don’t have a clue.
But then there is this…

  for ( i = 0; i < 8; i++ )
    thelcd.write ( row [ i ] );

I think that this is the sectret sauce, which I believe to be a device to stack the rows into the characters, but how can I use this in a non CG RAM setting. Say, PROGMEM or something. I would like to make a stack of like 15 or so characters so I can make a pseudo animation. Once this is pulled from the program space, I assume that it will be “lcd.print(angryDog);” not “lcd.write(0x00);” right?

Assuming you’re using a HD44780 based LCD…

Firstly, as you’ve observed, if you make changes to the CGRAM while your custom characters are being displayed, they update. This is because the HD44780 constantly refreshes the screen. You are never going to be able to display a 10 character “graphic”.

  if (( asc < 0 ) || ( asc > 7 )) // if asc is greater than 0 OR less than 7
    return;

I’m not familiar with the code you’re referring to but I’m guessing asc is short for the ASCII code for the character.

The controller has 64 continuous bytes of CGRAM for custom characters. To write to it you must tell the controller where to move the address pointer too. (The address pointer points to the memory location that will be written too next time you write to the display).

To tell the controller you’re going to write to CGRAM you send it B01AAAAA. (B01000000==0x40). The high bit6 tells the controller to go to CGRAM, the AAAAA then tells it where abouts in the CGRAM to go to. Remember that the CGRAM is 64 bytes, so this AAAAA value points somewhere within those bytes.

Because the characters are stored contiguously, the lower three AAAs point to the byte within a character. This is why we shift the ASCII code three bits left, because the lower three bits are within a character. So for example, to write to character 4, we shift 4 three bits over, which gives us 32, which is the beginning of the fifth character (don’t forget character codes begin at zero!).

Once we’ve told the controller to go to CGRAM, and which byte to go to, we then write the character data to the display, the address pointer auto-increments once you write to the display, so when we write the 8 bytes of character, those bytes are being put in CGRAM location

AAA000 (0)
AAA001 (1)
AAA010 (2)

AAA110 (6)
AAA111 (7)

(Where AAA is your character ASCII code)

It isn’t possible to make the controller read the custom characters from anywhere but its own 64bytes, so you can’t use the arduinos RAM to extend the CGRAM, you’re still limited to only 8 custom chars.

I’m not sure if this is what you’re after, if not I can try to explain it differently…

That was a great explanation, and it does clear up several things.

I knew we were limited on the LCD it's self. Where I was going was the idea of being able to use the same coding format, held but locally. So, I create a character live in the arduino (program space) and send it to the lcd at the time of need, not as a previously stored character in LCD CG RAM. So, therefore it would only be in the current working RAM and would not replace anything in CG RAM. I guess similar to a string sent to Serial.print. Although, I don't think you can send your own goofy pictures to the serial port, was said for the concept.

I am curious what asc means to Anachrocomputer

‘asc’ is short for ASCII, which is what the variable holds, an ASCII code.

I pulled this appart to try to get a handle on it, but nope, honestly, I don’t have a clue.

The command code to send to the LCD is made up of the bits 0x40 combined with the ASCII code of the character multiplied by eight. Now, multiplying by eight is the same as left shifting by three, so that accounts for the ‘<<’ left shift operator.

how can I use this in a non CG RAM setting. Say, PROGMEM or something

You can’t – all user-defined characters must be held in CGRAM in the LCD, not in memory in the AVR chip in the Arduino. You can only ever define eight characters in an HD44780-type LCD. There’s no way to enlarge that number to ten, as you want to do; it’s a limitation of the hardware in the LCD.

therefore it would only be in the current working RAM and would not replace anything in CG RAM.

If the character patterns are only in working RAM in the Arduino, then they cannot appear on the LCD. The patterns must be in CGRAM in the LCD chip.

If your LCD is graphics capable you should use that, otherwise you'll have to shrink your "graphic" to fit in the available custom chars.