NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Trying to uncomplicate my head, Building an EEPROM, Shift Register, Display Schema

August 18, 2011
by Ralphxyz
Ralphxyz's Avatar

I thought I should ask this in Noter's great I2C EEPROM thread but there should be a lot of general interest programming tips, so I started a new thread.

Please contribute I need everybody's ideas as this isn't going to be so simple to do.

Specifically this will be for my Water Curtain.

I have 4 Shift Registers working thanks to Rick's and Noter's postings now I have to combine the shift registers with the EEPROM pattern storage to get the display session.

I am picturing (please jump in here if you have a good idea) storing patterns in external I2C EEPROMs.

First thing is what is a pattern?

Well a pattern is composed of a series of 32 bit numbers (my water curtain is 32 bits wide).

Sorry this will make the thread kinda long but I think I have to illustrate.

The letter "A":

A1

00000000000000111000000000000000
00000000000001111100000000000000
00000000000011000110000000000000
00000000000110000011000000000000
00000000001100000001100000000000
00000000001111111111100000000000
00000000011111111111110000000000
00000000110000000000011000000000
00000001100000000000001100000000
00000011000000000000000110000000
00000110000000000000000011000000
00001100000000000000000001100000

and of course the inverse:

A2

11111111111111000111111111111111
11111111111110000011111111111111
11111111111100111001111111111111
11111111111001111100111111111111
11111111110011111110011111111111
11111111110000000000011111111111
11111111100000000000001111111111
11111111001111111111100111111111
11111110011111111111110011111111
11111100111111111111111001111111
11111001111111111111111100111111
11110011111111111111111110011111

There easily will be hundreds of patterns!

The A2 pattern above makes a 4kb text file, using Unix (LF) line breaks and Unicode (UTF-8) encoding.

Now I am proposing populating the I2C EEPROM from my pc.

I have a DevSys USB-I2C board.

I'll need to come up with a Python or PEARL script to build the patterns on the pc and then to populate the EEPROM.

Anybody want to help?

Now how am I going to store these patterns on the EEPROM?

Do I store them as 32bit patterns? Or as 8bit components:

Sorry but again for illustration:

A1
00000000
00000011
10000000
00000000
00000000
00000111
11000000
00000000
00000000
00001100
01100000
00000000
00000000
00011000
00110000
00000000
00000000
00110000
00011000
00000000
00000000
00111111
11111000
00000000
00000000
01111111
11111100
00000000
00000000
11000000
00000110
00000000
00000001
10000000
00000011
00000000
00000011
00000000
00000001
10000000
00000110
00000000
00000000
11000000
00001100
00000000
00000000
01100000

This also is a 4kb text file!

I do not have any timing parameters so that will add another dimension!

I am thinking that I will need a lookup table in say the first 10 or 20 kb of the EEPROM.

Or what other method might I use?

Then what would this "look up" table look like?

There has to be a method of condensing the look up code.

So if I have the A1 letter at position 100000 - 104000 (assuming 4kb) how would I reference that?

It would be nice to use a multidimension array Location[A1][100000][104000]

maybe that structure might work, as you can see I really need your help.

Then how do I pull a pattern from the EEPROM?

Should I use a Dynamic Array?

Then how do I display it? Rick had a suggestion to carlhako in my shift register daisy chain thread that I need him to elaborate on or if any one has any other schema I sure would be interested.

Again sorry about the length of this post but it is a little slow in the forum so this gives you all something to think about.

I'll take any thoughts.

So what do you think, it has to be possible but what might be the most efficient method?

Or any method for that matter lets get something to work.

Keep in mind my "limited" programing abilities, I put things together better than creating from scratch.

Ralph

August 18, 2011
by bretm
bretm's Avatar

You're not going to store text '1' and '0' characters in the EEPROM, you're going to store bits. The 24LC256 EEPROM is 32k x 8 bits, so you're going to be reading and writing bytes. That's 8 bits.

So you'll need 4 bytes for each pattern row, plus, let's say one more byte for the row "on" duration. That's 5 bytes per pattern row. A pattern consists of multiple rows, so a pattern could be one byte to indicate the number of rows, then the 5 bytes per row.

You'll need two bytes to identify the address of a pattern (since the EEPROM is 32k bytes). So a complete "script" could just be a two-byte count of pattern offsets (number of patterns) followed by two byte pattern address for each pattern than you want to display.

I wouldn't mess with complicated C data structures. It's total overkill. I would just do something like this:

  1. Read EEPROM bytes from location 0 and 1. Combine these into an int. This tells you the number of patterns to play.

  2. for i=0 to number of patterns minus 1, read two bytes from location i * 2 + 2 and i * 2 + 3. Combine these into an int. This tells you the address of the pattern.

  3. Read one byte from that address. That tells you how many rows in the pattern.

  4. for j=0 to number of rows minus 1, increment address, read byte from that address, do that five times. First four bytes are the pattern, fifth byte is the duration.

  5. Display the pattern. Pause for the duration.

  6. Continue loops.

August 18, 2011
by bretm
bretm's Avatar

Step 5 should be "Display the pattern row. Pause for the duration."

August 18, 2011
by bretm
bretm's Avatar
int address = 0;
byte loCount = read_byte_at(address++);
byte hiCount = read_byte_at(address++);
int count = loCount + 256 * hiCount;

while (count-- > 0)
{
    byte loLookup = read_byte_at(address++);
    byte hiLookup = read_byte_at(address++);
    int lookup = loLookup + 256 * hiLookup;
    int rowCount = read_byte_at(lookup++);

    while (rowCount-- > 0)
    {
        byte duration = read_byte_at(lookup++);
        byte pattern0 = read_byte_at(lookup++);
        byte pattern1 = read_byte_at(lookup++);
        byte pattern2 = read_byte_at(lookup++);
        byte pattern3 = read_byte_at(lookup++);
        display_pattern_row(pattern0, pattern1, pattern2, pattern3);
        wait_a_little_white(duration);
    }
}
August 18, 2011
by bretm
bretm's Avatar

Using this scheme, pattern A2 is 60 bytes, plus 2 bytes for each time you use it.

August 18, 2011
by Ralphxyz
Ralphxyz's Avatar

Thanks bretm, I will be trying your methods.

I suppose a lot of this question is outside the realm of microprocessor programming.

Maybe I'll break up the question in other threads.

Ralph

August 18, 2011
by BobaMosfet
BobaMosfet's Avatar

Ralph,

The simplest way to store this, knowing that it is 48-bytes per character, is as a consecutive string of bytes, and then use simple pointer arithmetic to access the start of each letter in a variable when you need to access it. 26 letters only take a little over 1200 bytes.

unsigned char alphabet[48 * 26];                /* 26 letters */
unsigned char *letterPtr;

letterPtr = &alphabet[0] + (13 * 48);           /* Letter M */
letterPtr = &alphabet[0] + (0 * 48);            /* Letter A */

Then mask to extract each bit you want and go from there. It can be cleaner/tighter; I wrote it this way for educational purposes.

Hope this helps.

BM

August 19, 2011
by Ralphxyz
Ralphxyz's Avatar

Thanks BM, this will work for this font but there will be images also like a diving dolphin or other shapes,

I am trying to do some math modeling to see how big a pattern might be.

The 32 x 12 A1 and A2 letters were just random selections for illustration.

I like your schema, and what bretm has suggested so far, I will try to incorporate it all.

This was just my preliminary question I am just starting to think about how I am going to do this so wanted to start to get some feed back.

I am probable going to get the pc talking to the EEPROM first before I do much on the mcu/display side.

Ralph

August 19, 2011
by BobaMosfet
BobaMosfet's Avatar

Ralph,

Step back, think about your answer, look at what I've provided. This is a learning exercise :P . Can you not see that it would be useful for you to make commonalities between your blocks? letters of a certain dimension, figures of a certain dimension, and so forth, and then just change the values in the algorithm depending on what you're trying to access?

Balance man. Balance. Resource .v. Performance- THAT is the name of the game. I've given you a the most important rudiments of an algorithm that uses the least resources while offering significantly high performance.

BM

August 19, 2011
by BobaMosfet
BobaMosfet's Avatar

Did I really say that.... :: hand to forehead ::

sheesh BM

Ralph, yeah, you're on the right track; just find commonalities; it'll help you write more useful, algorithms. Thank God it's Friday.

August 20, 2011
by Ralphxyz
Ralphxyz's Avatar

Thanks BM, saying this is a [quote] " learning exercise" [/quote] is a true understatement.

I understand your method of modularizing the commonalities.

Believe me once I start on this I am gong to need lots of help.

I am encouraged as so far I can follow bretm's and your methods.

Now to see if I can apply them.

I just got my newest solenoid valves and in laying it out it looks like I will have 80 columns eventually.

I am working with 32 for now just to see if I can make some recognizable patterns.

The same code "should" be able to expand to 80 columns.

This is so challenging but a lot of fun.

Ralph

August 21, 2011
by BobaMosfet
BobaMosfet's Avatar

Ralph,

I think mostly, you just need a few 'Aha!' moments where things that are murky with how RAM works, how you access it, and what a compiler is actually doing to get you where you want to go, become clear. I think once you start understanding the mechanics of how things work, you'll start realizing just how powerful C is, and why (realistically) it is the most powerful programming language to date. It's the one language that doesn't get in your way, no matter what you're trying to do-- and know almost all of them.

For purposes of 'growth', set your column width as a constant (use a define), that way, when you are ready to change it, you can just change a number.

BM

Post a Reply

Please log in to post a reply.

Did you know that interrupts can cause problems if you're not careful about timing and memory access? Learn more...