3
\$\begingroup\$

How can I create a lookup table in a microcontroller using C? I have one input and one output and want to implement a lookup table in C.

\$\endgroup\$
13
\$\begingroup\$

I'll give a general answer since the question lacks information:

Suppose you have an uint8_t as input and a uint8_t as output and you want to create a full lookup table (i.e. every input has an output). You'd need 256 values, as the input can have 256 different values. You can now create a table with:

const uint8_t the_table[256] = { ... }

The const keyword is to store the table in the flash memory, not in the RAM. This is because RAM is scarce in microcontrollers, as jippie points out in the comments.

In the curly brackets, the values should go. You can now easily lookup an input value with the_table[input_value].


Generally, we could say a lookup table would look as follows:

const OutputType the_table[CountOfInputValues] = { ... };

A small example for a lookup table to do this conversion (from the Gray code, thanks to Anindo Ghosh):

input -> output
0b000    0b000
0b001    0b001
0b010    0b011
0b011    0b010
0b100    0b110
0b101    0b111
0b110    0b101
0b111    0b100

Might be implemented as follows, using uint8_t, or a byte, as the output type:

const uint8_t gray_code[8] = {0b000, 0b001, 0b011, 0b010, 0b110, 0b111, 0b101, 0b100};

You can lookup a value with:

some_var = gray_code[input];
\$\endgroup\$
  • 1
    \$\begingroup\$ I like this explanation clear and simple :). \$\endgroup\$ – Dean May 3 '13 at 12:08
  • 2
    \$\begingroup\$ uint32_t gray( uint32_t number ) { return number ^= ( number >> 1 ); } Don't need a table for that. \$\endgroup\$ – jippie May 3 '13 at 17:50
  • 1
    \$\begingroup\$ On an ARM processor that takes only 1 clock cycle! EOR Rn,Rn,Rn,LSR 1, no way a lookup table can beat that. \$\endgroup\$ – jippie May 3 '13 at 17:58
  • 1
    \$\begingroup\$ While it's usually desirable to avoid having constant initializers copied from flash to limited ram on startup (thus proper use of "const" and pragmas or linker configuration), there is an exception: many of these processors are comparably slow at fetching data from flash "program" memory, so if there is RAM available for it, a table in RAM initialized only once from the flash at startup may be faster. \$\endgroup\$ – Chris Stratton May 3 '13 at 19:19
  • 1
    \$\begingroup\$ @PrabinKumar I'm sorry, but your responses come across as send-me-teh-codez. Perhaps if you demonstrated effort in working with the guidelines provided, and came back with any specific issues you could not resolve, you would get the help you actually need. \$\endgroup\$ – Anindo Ghosh May 4 '13 at 9:59
4
\$\begingroup\$

Here's an example of how I would create a lookup table for some precomputed values. I will use an example of swapping bits front-to-back within a byte. This is sometimes useful for FFT algorithms or SPI peripherals that want the wrong order.

First I create a program that creates the table. Maintaining the table by hand is drudgery and error-prone, so this job should be given to the computer.

#!/usr/bin/python

def swapbits(x):
    ret=0
    for i in range(8):
        if x&(1<<i): ret |= 1<<(7-i)
    return ret

print "const uint8_t bitswap[] = {",
print ", ".join("0x%02x"%swapbits(x) for x in range(256)),
print "}"

I call this file "bitend.py". Notice I used a scripting language instead of a C program for this. Generating the table is fundamentally a string-processing problem, and C is a pain to do string processing in. Because the table is only needed at compile-time, I can use a caveman-simple algorithm that is more obviously correct than an optimized one.

Now to integrate this into the build. In my Makefile, I put a section like this:

generated_swapbits.c: bitend.py
       echo "/* generated by bitend.py, do not edit */" > generated_swapbits.c
       python bitend.py >> generated_swapbits.c

Here I made a dependency on the python script, so that if I edit the script, the C file will be regenerated automatically.

In my main C code, I just include the generated file:

#include <stdio.h>
#include "generated_swapbits.c"

int main(void) { 
   printf("Swapped 0x0f is %0x\n", swapbits[0x0f]); 
}

Now in my Makefile, I have to include the generated file as a dependency of the C code:

a.out: main.c generated_swapbits.c
     $(CC) $(CFLAGS) main.c

And the last thing is to add "generated_swapbits.c" to the Makefile's "clean" target, so the file will be removed upon "make clean".

If you use an IDE instead of make, you will need to consult its documentation about running scripts to satisfy dependencies. (If the IDE doesn't support this, choose a different IDE.)

\$\endgroup\$

protected by clabacchio Jun 9 '13 at 1:18

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.