Skip to content

Commit d2401a2

Browse files
authored
Merge pull request wled#4082 from PaoloTK/fix_esp32c3_pwm_bit_depth
Fix incorrect PWM bit depth on Esp32 with XTAL clock
2 parents ef8f23c + 5254854 commit d2401a2

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

wled00/bus_manager.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -378,30 +378,48 @@ void BusDigital::cleanup() {
378378
}
379379

380380

381+
#ifdef ESP8266
382+
// 1 MHz clock
383+
#define CLOCK_FREQUENCY 1000000UL
384+
#else
385+
// Use XTAL clock if possible to avoid timer frequency error when setting APB clock < 80 Mhz
386+
// https://github.com/espressif/arduino-esp32/blob/2.0.2/cores/esp32/esp32-hal-ledc.c
387+
#ifdef SOC_LEDC_SUPPORT_XTAL_CLOCK
388+
#define CLOCK_FREQUENCY 40000000UL
389+
#else
390+
#define CLOCK_FREQUENCY 80000000UL
391+
#endif
392+
#endif
393+
394+
#ifdef ESP8266
395+
#define MAX_BIT_WIDTH 10
396+
#else
397+
#ifdef SOC_LEDC_TIMER_BIT_WIDE_NUM
398+
// C6/H2/P4: 20 bit, S2/S3/C2/C3: 14 bit
399+
#define MAX_BIT_WIDTH SOC_LEDC_TIMER_BIT_WIDE_NUM
400+
#else
401+
// ESP32: 20 bit (but in reality we would never go beyond 16 bit as the frequency would be to low)
402+
#define MAX_BIT_WIDTH 20
403+
#endif
404+
#endif
405+
381406
BusPwm::BusPwm(BusConfig &bc)
382407
: Bus(bc.type, bc.start, bc.autoWhite, 1, bc.reversed)
383408
{
384409
if (!IS_PWM(bc.type)) return;
385410
unsigned numPins = NUM_PWM_PINS(bc.type);
386411
_frequency = bc.frequency ? bc.frequency : WLED_PWM_FREQ;
412+
// duty cycle resolution (_depth) can be extracted from this formula: CLOCK_FREQUENCY > _frequency * 2^_depth
413+
for (_depth = MAX_BIT_WIDTH; _depth > 8; _depth--) if (((CLOCK_FREQUENCY/_frequency) >> _depth) > 0) break;
387414

388415
#ifdef ESP8266
389-
// duty cycle resolution (_depth) can be extracted from this formula: 1MHz > _frequency * 2^_depth
390-
if (_frequency > 1760) _depth = 8;
391-
else if (_frequency > 880) _depth = 9;
392-
else _depth = 10; // WLED_PWM_FREQ <= 880Hz
393416
analogWriteRange((1<<_depth)-1);
394417
analogWriteFreq(_frequency);
395418
#else
396419
_ledcStart = pinManager.allocateLedc(numPins);
397420
if (_ledcStart == 255) { //no more free LEDC channels
398421
deallocatePins(); return;
399422
}
400-
// duty cycle resolution (_depth) can be extracted from this formula: 80MHz > _frequency * 2^_depth
401-
if (_frequency > 78124) _depth = 9;
402-
else if (_frequency > 39062) _depth = 10;
403-
else if (_frequency > 19531) _depth = 11;
404-
else _depth = 12; // WLED_PWM_FREQ <= 19531Hz
405423
#endif
406424

407425
for (unsigned i = 0; i < numPins; i++) {
@@ -419,7 +437,7 @@ BusPwm::BusPwm(BusConfig &bc)
419437
}
420438
_data = _pwmdata; // avoid malloc() and use stack
421439
_valid = true;
422-
DEBUG_PRINTF_P(PSTR("%successfully inited PWM strip with type %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
440+
DEBUG_PRINTF_P(PSTR("%successfully inited PWM strip with type %u, frequency %u, bit depth %u and pins %u,%u,%u,%u,%u\n"), _valid?"S":"Uns", bc.type, _frequency, _depth, _pins[0], _pins[1], _pins[2], _pins[3], _pins[4]);
423441
}
424442

425443
void BusPwm::setPixelColor(uint16_t pix, uint32_t c) {

0 commit comments

Comments
 (0)