robtillaart:
Could not resist
Simple if then ladder, no constrain needed as it is build in.
Max 8 compares, on average ~2.45 (if numbers are divided equally)
uint8_t n = 0;
if (div >= 192) n = 8;
else if (div >= 96) n = 7;
else if (div >= 48) n = 6;
else if (div >= 24) n = 5;
else if (div >= 12) n = 4;
else if (div >= 6) n = 3;
else if (div >= 3) n = 2;
else if (div >= 2) n = 1;
If you really want to squeeze performance you might consider a binary search tree...
Performance is not an issue at all. This function is only called once or twice in the entire lifetime of the program using it.
By the way, as I thought about it, I realized that what I wanted was a logarithmic curve, so I just generated a small data file (like this):
[tt][b]384, 8
192, 7
96, 6
...
6, 2
3, 1
1, 0[/b]
[/tt]then curve fit it, then used the equation and coefficients to generate all the points. Lastly, I took the first and last of each value that generated "8" and put them into one case statement, all the ones that generated "7", etc... so now I get a perfectly centered result based on the input value.
Here's the final, finished code:
//
// clockDivide.cpp
//
#include "wiring_private.h" // for uint8_t and CLKPCE
uint8_t clockDivide (int div)
{
uint8_t n;
uint8_t oldSREG;
div = div < 1 ? 1 : div > 256 ? 256 : div; // constrain value to legal
switch (div) {
case 192 ... 256: {
n = 8;
break;
}
case 100 ... 191: {
n = 7;
break;
}
case 52 ... 99: {
n = 6;
break;
}
case 27 ... 51: {
n = 5;
break;
}
case 14 ... 26: {
n = 4;
break;
}
case 8 ... 13: {
n = 3;
break;
}
case 4 ... 7: {
n = 2;
break;
}
case 2 ... 3: {
n = 1;
break;
}
case 1: {
n = 0;
break;
}
default: {
n = 0;
break;
}
}
oldSREG = SREG; // save status register state
__asm__ __volatile__ (" cli\n"); // interrupts off
CLKPR = _BV (CLKPCE); // enable prescaler change
CLKPR = n; // set clock divider
SREG = oldSREG; // restore SREG state
return n; // return divider number for other possible uses
}
See what it does? It allows changing the AVR clock divider on the fly within a sketch (I'm sure someone will ask me "why would you want to do that?") 