Skip to content

Commit fe632cd

Browse files
authored
Increase analogWrite frequency range, bugfixes (#918)
* analogWrite: fix overflow and wrap value (#917) -avoid overflow when calculating analogScale * analogFreq, perform the multiplication in floating point. -use analogScale - 1 to set the PWM wrap value. Wrap is the highest value the counter reaches, not the counter period. * analogWrite: increase frequency range (#917) - increase frequency range to 10 MHz - decrease the lowest allowed resolution to 2 bits, and the minimal analogRange value to 3. This makes 10 MHz output possible with system clock frequencies down to 50 MHz. - allow clkdiv values >= 1.0, was 2.0. This makes it possible to manually set frequency and analogRange so that frequency * analogRange = system clock frequency. This gives the best possible frequency accuracy and resolution.
1 parent 10090b6 commit fe632cd

File tree

1 file changed

+8
-9
lines changed

1 file changed

+8
-9
lines changed

cores/rp2040/wiring_analog.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ extern "C" void analogWriteFreq(uint32_t freq) {
4242
if (freq < 100) {
4343
DEBUGCORE("ERROR: analogWriteFreq too low (%d)\n", freq);
4444
analogFreq = 100;
45-
} else if (freq > 1'000'000) {
45+
} else if (freq > 10'000'000) {
4646
DEBUGCORE("ERROR: analogWriteFreq too high (%d)\n", freq);
47-
analogFreq = 1'000'000;
47+
analogFreq = 10'000'000;
4848
} else {
4949
analogFreq = freq;
5050
}
@@ -55,7 +55,7 @@ extern "C" void analogWriteRange(uint32_t range) {
5555
if (range == analogScale) {
5656
return;
5757
}
58-
if ((range >= 15) && (range <= 65535)) {
58+
if ((range >= 3) && (range <= 65535)) {
5959
analogScale = range;
6060
pwmInitted = false;
6161
} else {
@@ -64,7 +64,7 @@ extern "C" void analogWriteRange(uint32_t range) {
6464
}
6565

6666
extern "C" void analogWriteResolution(int res) {
67-
if ((res >= 4) && (res <= 16)) {
67+
if ((res >= 2) && (res <= 16)) {
6868
analogWriteRange((1 << res) - 1);
6969
} else {
7070
DEBUGCORE("ERROR: analogWriteResolution out of range (%d)\n", res);
@@ -81,22 +81,21 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
8181
if (!pwmInitted) {
8282
// For low frequencies, we need to scale the output max value up to achieve lower periods
8383
analogWritePseudoScale = 1;
84-
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
84+
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
8585
analogWritePseudoScale++;
8686
analogScale *= 2;
8787
DEBUGCORE("Adjusting analogWrite values PS=%d, scale=%d\n", analogWritePseudoScale, analogScale);
8888
}
8989
// For high frequencies, we need to scale the output max value down to actually hit the frequency target
9090
analogWriteSlowScale = 1;
91-
while (((clock_get_hz(clk_sys) / (float)(analogScale * analogFreq)) < 2.0) && (analogScale > 32)) {
91+
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) < 1.0) && (analogScale >= 6)) {
9292
analogWriteSlowScale++;
9393
analogScale /= 2;
9494
DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%d\n", analogWriteSlowScale, analogScale);
9595
}
96-
9796
pwm_config c = pwm_get_default_config();
98-
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / (float)(analogScale * analogFreq));
99-
pwm_config_set_wrap(&c, analogScale);
97+
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq));
98+
pwm_config_set_wrap(&c, analogScale - 1);
10099
for (int i = 0; i < 30; i++) {
101100
pwm_init(pwm_gpio_to_slice_num(i), &c, true);
102101
}

0 commit comments

Comments
 (0)