views:

136

answers:

2

I am working on an embedded C project. I have an LCD display and for each character there is a 5x7 dot matrix. To display a specific character you have to shift in 5 bytes that correlate with the dots to turn on. So I need to make some kind of look-up table with a key where I can pass in an ASCII character, and get an array of 5 bytes returned... For example, a call to this function like this,

GetDisplayBytes('A');

should return `an array like this...

C[0] = 0x7E : C[1] = 0x90 : C[2] = 0x90 : C[3] = 0x90 : C[4] = 0x7E

What would be the best way to do this in C?

+10  A: 

I would make arrays for the contiguous ASCII blocks you want to use. data. Something like this:

uint8_t displayBytesLetters[] = 
{
  0x73, 0x90, 0x90, 0x90, 0x73, // 'A'
  .
  .
  .
};

uint8_t displayBytesDigits[] = 
{
  0x12, 0x15, 0x25, 0x58, 0x80, // '0'
  .
  .
  .
};

Then your GetDisplayBytes() is something like:

uint8_t *GetDisplayBytes(char c)
{
  if (isdigit(c))
    return &displayBytes[5*(c - '0')];
  else if (isupper(c))
    return &displayBytes[5*(c - 'A')];
  else
    return NULL;
}

Pass the returned pointer to whatever function outputs the data:

void DoDisplay(uint8_t *displayBytes)
{
  int i;
  for (i = 0; i < 5; i++) 
  {
     SendOutput(displayBytes[i]);
  }
}
Carl Norum
This is good but what if I don't want to make EVERY ASCII value available for printing. Say I only want the upper case letters, the numbers and a couple symbols (<,>,!,?). In that case wouldn't your approach require me to use unnecessary memory space.
Jordan S
Sorry, I should have specified that in the question to begin with...
Jordan S
@Jordan S, just use a different lookup table for each non-contiguous ascii block then. I'll edit my answer with an example.
Carl Norum
Then, in lieu of `(c - 'A')`, write a function/macro that will take as input an ASCII character that you support, and return as output an index number (sort of like a mini hash function). You'd probably want to handle illegal character input, too.
Santa
+1 @Santa, also a good solution.
Carl Norum
Would you mind also adding an example of how to make a call to GetDisplayBytes showing how to iterate through the 5 bytes.
Jordan S
@Jordan S, `GetDisplayBytes()` doesn't need to iterate the bytes, does it? I would think the routine that does the display would need that. I added an example of what I think you're asking about.
Carl Norum
Yeah that looks good. I was thinking a function that did this... `value = GetDisplayBytes(c);``PutU1(*value);``value++;``PutU1(*value);`, etc
Jordan S
@Jordan S, that would work too.
Carl Norum
+3  A: 
typedef char LCDDATA[5];   

LCDDATA lcdTable[256] = { {0,0,0,0,0},  // char 0
                          {.....},       // char 1

LCDDATA GetDisplayBytes(char chr)
{
     return lcdTable[chr];
}

This is basically making an array of arrays.

James Curran
There no reason this method can't be ranged as Carl's is.
James Curran
+1 for doing proper typing and not playing games with arithmetic. Some minor things though: your prototype should be `LCDDATA GetDisplayBytes(unsigned char chr)` and also it is unusual to use all caps for type names, conventionally these are reserved for macros.
Jens Gustedt
@Jens: I once did this using macros, and the habit sticked.
James Curran