Monday, June 25, 2012

Flickering LED Matrix

Running s simple sample driving a LED matrix, goes without any problem. But when you get more ambitious the LED matrix flickers regularly. I know that a digitalWrite can replaced by editing the registers directly, but hey I just don't like to rewrite all the code...

After some slight optimizations ordering the code a bit, I found a discussion on the Arduino forum that handles this topic.

In this discussion the digitalWrite and shiftOut are optimized. The regular shiftOut takes 110us to output a byte, but with the optimizations it performs 6 times better. Now thats a nice gain. That definitely should solve the flicker...

But wait, there's more! The compile optimization can really make a difference, when the compiler knows all values.

Quote:
The compiler will produce code that will do port I/O in a single instruction (65 nanoseconds) if it knows the port, pin and state at compile time.

So, when you define a hardcoded pin in your sketch, there's a real difference in the way you define it. A regular integer variable containing the pin number.
int OUTPUT_PIN = 5;
or a define statement:
#define OUTPUT_PIN  5
The #define is the way to go. This way, every occurrence of "OUTPUT_PIN" is replaced by the number 5 directly and the compiler can optimize the code. When using the first option, using a integer variable, the compiles should always retrieve the value from the variable first and the compiler does not know which value to expect. You probably never want to change a pin at runtime... and if you do, you can go for the "int" option anyway.

From now on, I'll code my pins using a #define statement, instead of regular variables!!!


Well, actually you can also use the following:
const int OUTPUT_PIN = 5;
This also tells the compiler that OUTPUT_PIN is never going to be changed, so the compiler can choose the most efficient way to use the value of OUTPUT_PIN.

So let us look at the following code:
void f(int);

void g()
{
  f(OUTPUT_PIN);
}
When using "#define OUTPUT_PIN 5" or "const int OUTPUT_PIN = 5;", the resulting instructions are in both cases:
push 5
call f
add esp, 4
To the compiler it is better to have the number 5 everywhere in the resulting binary, than having to fetch the number 5 from the variable, if you know that the number has not changed.

Okay, to summarize... use the "const" keyword for defining your pins and every other value that you know will not change.

From my rusty C++ guidelines I vaguely remember: "Use const wherever possible."


Extra:

No comments:

Post a Comment