Skip to content

Commit 895ffce

Browse files
Fix analogWrite scaling issues (#962)
The PWM internals on the RP2040 are based on 8 slices with independent clocking. Make sure that we init the PWM slice being used only once per change of frequency/range. Only init the scaling values one time, because we also adjust the input scale/frequency values when calculating them. If we ran this twice (i.e. writing to two slices), it would overwrite the pseudo scale/slow scale values with 1 causing the wrong PWM values to be set. Fixes #955
1 parent 40855c9 commit 895ffce

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

cores/rp2040/wiring_analog.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
static uint32_t analogScale = 255;
3030
static uint32_t analogFreq = 1000;
3131
static uint32_t pwmInitted = 0;
32+
static bool scaleInitted = false;
3233
static bool adcInitted = false;
3334
static uint16_t analogWritePseudoScale = 1;
3435
static uint16_t analogWriteSlowScale = 1;
@@ -49,6 +50,7 @@ extern "C" void analogWriteFreq(uint32_t freq) {
4950
analogFreq = freq;
5051
}
5152
pwmInitted = 0;
53+
scaleInitted = false;
5254
}
5355

5456
extern "C" void analogWriteRange(uint32_t range) {
@@ -58,6 +60,7 @@ extern "C" void analogWriteRange(uint32_t range) {
5860
if ((range >= 3) && (range <= 65535)) {
5961
analogScale = range;
6062
pwmInitted = 0;
63+
scaleInitted = false;
6164
} else {
6265
DEBUGCORE("ERROR: analogWriteRange out of range (%d)\n", range);
6366
}
@@ -78,7 +81,7 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
7881
DEBUGCORE("ERROR: Illegal analogWrite pin (%d)\n", pin);
7982
return;
8083
}
81-
if (!(pwmInitted & (1 << pin))) {
84+
if (!scaleInitted) {
8285
// For low frequencies, we need to scale the output max value up to achieve lower periods
8386
analogWritePseudoScale = 1;
8487
while (((clock_get_hz(clk_sys) / ((float)analogScale * analogFreq)) > 255.0) && (analogScale < 32678)) {
@@ -93,11 +96,14 @@ extern "C" void analogWrite(pin_size_t pin, int val) {
9396
analogScale /= 2;
9497
DEBUGCORE("Adjusting analogWrite values SS=%d, scale=%d\n", analogWriteSlowScale, analogScale);
9598
}
99+
scaleInitted = true;
100+
}
101+
if (!(pwmInitted & (1 << pwm_gpio_to_slice_num(pin)))) {
96102
pwm_config c = pwm_get_default_config();
97103
pwm_config_set_clkdiv(&c, clock_get_hz(clk_sys) / ((float)analogScale * analogFreq));
98104
pwm_config_set_wrap(&c, analogScale - 1);
99105
pwm_init(pwm_gpio_to_slice_num(pin), &c, true);
100-
pwmInitted |= 1 << pin;
106+
pwmInitted |= 1 << pwm_gpio_to_slice_num(pin);
101107
}
102108

103109
val <<= analogWritePseudoScale;

0 commit comments

Comments
 (0)