Ok, I think this is the way to go if you want a software pwm (or square wave frequency generator).
3-channel example:
C:
/* set up counters */
uint16_t f1_counter = 0;
uint16_t f2_counter = 0;
uint16_t f3_counter = 0;
uint16_t f1_increment = calculate correct increment to get the frequency you want;
uint16_t f2_increment = calculate correct increment to get the frequency you want;
uint16_t f3_increment = calculate correct increment to get the frequency you want;
interrupt routine that is executed at constant interval {
(f1_counter & 0x8000) ? (PIN1_HIGH) : (PIN1_LOW);
(f2_counter & 0x8000) ? (PIN2_HIGH) : (PIN2_LOW);
(f3_counter & 0x8000) ? (PIN3_HIGH) : (PIN3_LOW);
f1_counter += f1_increment;
f2_counter += f2_increment;
f3_counter += f3_increment;
}
The
fx_counter variable is tested if the last bit is set or not and the output is set high or low accordingly. The frequency is controlled by the amount of the
fx_increment and the loop (interrupt) frequency. You can play with the values.
8bit counters gives you more speed, but less resolution (accuracy) etc. Loop frequency sets the resolution.
This scheme also lets you to go higher and higher.. I mean from 220 Hz to 440 Hz.
Instead of testing the last bit (bit 15).. test the bit before that (bit 14) and you double the frequency. Is that the same as going one octave up? sorry I'm really bad in music theory.
Anyway, if that is true, then you get that kind of control almost free.
Actually you have nice control of the accuracy of the frequency if you play with the increment value and what bit you are testing. I can't do the math now.. too drunk.
The math is:
Not sure if this is correct:
loopf / ((2^n)*increment)
loopf: the loop frequency that you execute the thing.
n: the bit you are testing if it is 1 or 0
increment: the counter increment
You want the loop frequency to be as fast as possible and then you have two variables to play with.