The code below is written in C++ to create a lookup table for the grains for 1V/oct tracking
based on a linear PWM frequency of 31.25KHz, 32.70 is choosen as lowest frequency (C), 65536=2^16 is max pulsewidth on 31.25KHz, pow(x,y) is x^y pow(2,f) creates the exponential value of 0V to 5V in 1024 steps pow(2,0) = 1 generates a value of 32.50Hz pow(2,1) = 2 generates 32.50 * 2 = 65 Hz etc. Math.floor (x) rounds off the value
// I divide 5 volts in 1024 steps
int main()
{
for (int c=0; c<1024; c++)
{
float f=5 * c /1024.0;
std::cout << floor((65536 * 32.70 * pow (2.0, f)) / 31250 + 0.5f)<< ",";
}
return 0;
}