@@ -56,7 +56,7 @@ static bool find_matching_timer(uint8_t speed_mode, uint32_t freq, uint8_t resol
56
56
peripheral_bus_type_t type = perimanGetPinBusType (i );
57
57
if (type == ESP32_BUS_TYPE_LEDC ) {
58
58
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (i , ESP32_BUS_TYPE_LEDC );
59
- if (bus != NULL && (bus -> channel / 8 ) == speed_mode && bus -> freq_hz == freq && bus -> channel_resolution == resolution ) {
59
+ if (bus != NULL && (bus -> channel / SOC_LEDC_CHANNEL_NUM ) == speed_mode && bus -> freq_hz == freq && bus -> channel_resolution == resolution ) {
60
60
log_d ("Found matching timer %u for freq=%u, resolution=%u" , bus -> timer_num , freq , resolution );
61
61
* timer_num = bus -> timer_num ;
62
62
return true;
@@ -78,7 +78,7 @@ static bool find_free_timer(uint8_t speed_mode, uint8_t *timer_num) {
78
78
peripheral_bus_type_t type = perimanGetPinBusType (i );
79
79
if (type == ESP32_BUS_TYPE_LEDC ) {
80
80
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (i , ESP32_BUS_TYPE_LEDC );
81
- if (bus != NULL && (bus -> channel / 8 ) == speed_mode ) {
81
+ if (bus != NULL && (bus -> channel / SOC_LEDC_CHANNEL_NUM ) == speed_mode ) {
82
82
log_d ("Timer %u is in use by channel %u" , bus -> timer_num , bus -> channel );
83
83
used_timers |= (1 << bus -> timer_num );
84
84
}
@@ -110,7 +110,7 @@ static void remove_channel_from_timer(uint8_t speed_mode, uint8_t timer_num, uin
110
110
peripheral_bus_type_t type = perimanGetPinBusType (i );
111
111
if (type == ESP32_BUS_TYPE_LEDC ) {
112
112
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (i , ESP32_BUS_TYPE_LEDC );
113
- if (bus != NULL && (bus -> channel / 8 ) == speed_mode && bus -> timer_num == timer_num && bus -> channel != channel ) {
113
+ if (bus != NULL && (bus -> channel / SOC_LEDC_CHANNEL_NUM ) == speed_mode && bus -> timer_num == timer_num && bus -> channel != channel ) {
114
114
log_d ("Timer %u is still in use by channel %u" , timer_num , bus -> channel );
115
115
timer_in_use = true;
116
116
break ;
@@ -168,8 +168,8 @@ static bool ledcDetachBus(void *bus) {
168
168
}
169
169
pinMatrixOutDetach (handle -> pin , false, false);
170
170
if (!channel_found ) {
171
- uint8_t group = (handle -> channel / 8 );
172
- remove_channel_from_timer (group , handle -> timer_num , handle -> channel % 8 );
171
+ uint8_t group = (handle -> channel / SOC_LEDC_CHANNEL_NUM );
172
+ remove_channel_from_timer (group , handle -> timer_num , handle -> channel % SOC_LEDC_CHANNEL_NUM );
173
173
ledc_handle .used_channels &= ~(1UL << handle -> channel );
174
174
}
175
175
free (handle );
@@ -206,21 +206,21 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
206
206
return false;
207
207
}
208
208
209
- uint8_t group = (channel / 8 );
209
+ uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM );
210
210
uint8_t timer = 0 ;
211
211
bool channel_used = ledc_handle .used_channels & (1UL << channel );
212
212
213
213
if (channel_used ) {
214
214
log_i ("Channel %u is already set up, given frequency and resolution will be ignored" , channel );
215
- if (ledc_set_pin (pin , group , channel % 8 ) != ESP_OK ) {
215
+ if (ledc_set_pin (pin , group , channel % SOC_LEDC_CHANNEL_NUM ) != ESP_OK ) {
216
216
log_e ("Attaching pin to already used channel failed!" );
217
217
return false;
218
218
}
219
219
} else {
220
220
// Find a timer with matching frequency and resolution, or a free timer
221
221
if (!find_matching_timer (group , freq , resolution , & timer )) {
222
222
if (!find_free_timer (group , & timer )) {
223
- log_e ("No free timers available for speed mode %u" , group );
223
+ log_w ("No free timers available for speed mode %u" , group );
224
224
return false;
225
225
}
226
226
@@ -239,12 +239,12 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
239
239
}
240
240
}
241
241
242
- uint32_t duty = ledc_get_duty (group , (channel % 8 ));
242
+ uint32_t duty = ledc_get_duty (group , (channel % SOC_LEDC_CHANNEL_NUM ));
243
243
244
244
ledc_channel_config_t ledc_channel ;
245
245
memset ((void * )& ledc_channel , 0 , sizeof (ledc_channel_config_t ));
246
246
ledc_channel .speed_mode = group ;
247
- ledc_channel .channel = (channel % 8 );
247
+ ledc_channel .channel = (channel % SOC_LEDC_CHANNEL_NUM );
248
248
ledc_channel .timer_sel = timer ;
249
249
ledc_channel .intr_type = LEDC_INTR_DISABLE ;
250
250
ledc_channel .gpio_num = pin ;
@@ -291,14 +291,36 @@ bool ledcAttach(uint8_t pin, uint32_t freq, uint8_t resolution) {
291
291
}
292
292
uint8_t channel = __builtin_ctz (free_channel ); // Convert the free_channel bit to channel number
293
293
294
- return ledcAttachChannel (pin , freq , resolution , channel );
294
+ // Try the first available channel
295
+ if (ledcAttachChannel (pin , freq , resolution , channel )) {
296
+ return true;
297
+ }
298
+
299
+ #ifdef SOC_LEDC_SUPPORT_HS_MODE
300
+ // If first attempt failed and HS mode is supported, try to find a free channel in group 1
301
+ if ((channel / SOC_LEDC_CHANNEL_NUM ) == 0 ) { // First attempt was in group 0
302
+ log_d ("LEDC: Group 0 channel %u failed, trying to find a free channel in group 1" , channel );
303
+ // Find free channels specifically in group 1
304
+ uint32_t group1_mask = ((1UL << SOC_LEDC_CHANNEL_NUM ) - 1 ) << SOC_LEDC_CHANNEL_NUM ;
305
+ int group1_free_channel = (~ledc_handle .used_channels ) & group1_mask ;
306
+ if (group1_free_channel != 0 ) {
307
+ uint8_t group1_channel = __builtin_ctz (group1_free_channel );
308
+ if (ledcAttachChannel (pin , freq , resolution , group1_channel )) {
309
+ return true;
310
+ }
311
+ }
312
+ }
313
+ #endif
314
+
315
+ log_e ("No free timers available for freq=%u, resolution=%u. To attach a new channel, use the same frequency and resolution as an already attached channel to share its timer." , freq , resolution );
316
+ return false;
295
317
}
296
318
297
319
bool ledcWrite (uint8_t pin , uint32_t duty ) {
298
320
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
299
321
if (bus != NULL ) {
300
322
301
- uint8_t group = (bus -> channel / 8 ), channel = (bus -> channel % 8 );
323
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM ), channel = (bus -> channel % SOC_LEDC_CHANNEL_NUM );
302
324
303
325
//Fixing if all bits in resolution is set = LEDC FULL ON
304
326
uint32_t max_duty = (1 << bus -> channel_resolution ) - 1 ;
@@ -307,8 +329,14 @@ bool ledcWrite(uint8_t pin, uint32_t duty) {
307
329
duty = max_duty + 1 ;
308
330
}
309
331
310
- ledc_set_duty (group , channel , duty );
311
- ledc_update_duty (group , channel );
332
+ if (ledc_set_duty (group , channel , duty ) != ESP_OK ) {
333
+ log_e ("ledc_set_duty failed" );
334
+ return false;
335
+ }
336
+ if (ledc_update_duty (group , channel ) != ESP_OK ) {
337
+ log_e ("ledc_update_duty failed" );
338
+ return false;
339
+ }
312
340
313
341
return true;
314
342
}
@@ -321,7 +349,11 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
321
349
log_e ("Channel %u is not available (maximum %u) or not used!" , channel , LEDC_CHANNELS );
322
350
return false;
323
351
}
324
- uint8_t group = (channel / 8 ), timer = ((channel / 2 ) % 4 );
352
+ uint8_t group = (channel / SOC_LEDC_CHANNEL_NUM );
353
+ ledc_timer_t timer ;
354
+
355
+ // Get the actual timer being used by this channel
356
+ ledc_ll_get_channel_timer (LEDC_LL_GET_HW (), group , (channel % SOC_LEDC_CHANNEL_NUM ), & timer );
325
357
326
358
//Fixing if all bits in resolution is set = LEDC FULL ON
327
359
uint32_t resolution = 0 ;
@@ -333,8 +365,14 @@ bool ledcWriteChannel(uint8_t channel, uint32_t duty) {
333
365
duty = max_duty + 1 ;
334
366
}
335
367
336
- ledc_set_duty (group , channel , duty );
337
- ledc_update_duty (group , channel );
368
+ if (ledc_set_duty (group , channel , duty ) != ESP_OK ) {
369
+ log_e ("ledc_set_duty failed" );
370
+ return false;
371
+ }
372
+ if (ledc_update_duty (group , channel ) != ESP_OK ) {
373
+ log_e ("ledc_update_duty failed" );
374
+ return false;
375
+ }
338
376
339
377
return true;
340
378
}
@@ -343,7 +381,7 @@ uint32_t ledcRead(uint8_t pin) {
343
381
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
344
382
if (bus != NULL ) {
345
383
346
- uint8_t group = (bus -> channel / 8 ), channel = (bus -> channel % 8 );
384
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM ), channel = (bus -> channel % SOC_LEDC_CHANNEL_NUM );
347
385
return ledc_get_duty (group , channel );
348
386
}
349
387
return 0 ;
@@ -355,8 +393,8 @@ uint32_t ledcReadFreq(uint8_t pin) {
355
393
if (!ledcRead (pin )) {
356
394
return 0 ;
357
395
}
358
- uint8_t group = (bus -> channel / 8 ), timer = (( bus -> channel / 2 ) % 4 );
359
- return ledc_get_freq (group , timer );
396
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM );
397
+ return ledc_get_freq (group , bus -> timer_num );
360
398
}
361
399
return 0 ;
362
400
}
@@ -370,12 +408,12 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
370
408
return 0 ;
371
409
}
372
410
373
- uint8_t group = (bus -> channel / 8 ), timer = (( bus -> channel / 2 ) % 4 );
411
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM );
374
412
375
413
ledc_timer_config_t ledc_timer ;
376
414
memset ((void * )& ledc_timer , 0 , sizeof (ledc_timer_config_t ));
377
415
ledc_timer .speed_mode = group ;
378
- ledc_timer .timer_num = timer ;
416
+ ledc_timer .timer_num = bus -> timer_num ;
379
417
ledc_timer .duty_resolution = 10 ;
380
418
ledc_timer .freq_hz = freq ;
381
419
ledc_timer .clk_cfg = clock_source ;
@@ -386,7 +424,7 @@ uint32_t ledcWriteTone(uint8_t pin, uint32_t freq) {
386
424
}
387
425
bus -> channel_resolution = 10 ;
388
426
389
- uint32_t res_freq = ledc_get_freq (group , timer );
427
+ uint32_t res_freq = ledc_get_freq (group , bus -> timer_num );
390
428
ledcWrite (pin , 0x1FF );
391
429
return res_freq ;
392
430
}
@@ -427,12 +465,12 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution) {
427
465
log_e ("LEDC pin %u - resolution is zero or it is too big (maximum %u)" , pin , LEDC_MAX_BIT_WIDTH );
428
466
return 0 ;
429
467
}
430
- uint8_t group = (bus -> channel / 8 ), timer = (( bus -> channel / 2 ) % 4 );
468
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM );
431
469
432
470
ledc_timer_config_t ledc_timer ;
433
471
memset ((void * )& ledc_timer , 0 , sizeof (ledc_timer_config_t ));
434
472
ledc_timer .speed_mode = group ;
435
- ledc_timer .timer_num = timer ;
473
+ ledc_timer .timer_num = bus -> timer_num ;
436
474
ledc_timer .duty_resolution = resolution ;
437
475
ledc_timer .freq_hz = freq ;
438
476
ledc_timer .clk_cfg = clock_source ;
@@ -442,7 +480,7 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution) {
442
480
return 0 ;
443
481
}
444
482
bus -> channel_resolution = resolution ;
445
- return ledc_get_freq (group , timer );
483
+ return ledc_get_freq (group , bus -> timer_num );
446
484
}
447
485
return 0 ;
448
486
}
@@ -453,12 +491,12 @@ bool ledcOutputInvert(uint8_t pin, bool out_invert) {
453
491
gpio_set_level (pin , out_invert );
454
492
455
493
#ifdef CONFIG_IDF_TARGET_ESP32P4
456
- esp_rom_gpio_connect_out_signal (pin , LEDC_LS_SIG_OUT_PAD_OUT0_IDX + ((bus -> channel ) % 8 ), out_invert , 0 );
494
+ esp_rom_gpio_connect_out_signal (pin , LEDC_LS_SIG_OUT_PAD_OUT0_IDX + ((bus -> channel ) % SOC_LEDC_CHANNEL_NUM ), out_invert , 0 );
457
495
#else
458
496
#ifdef SOC_LEDC_SUPPORT_HS_MODE
459
- esp_rom_gpio_connect_out_signal (pin , ((bus -> channel / 8 == 0 ) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX ) + ((bus -> channel ) % 8 ), out_invert , 0 );
497
+ esp_rom_gpio_connect_out_signal (pin , ((bus -> channel / SOC_LEDC_CHANNEL_NUM == 0 ) ? LEDC_HS_SIG_OUT0_IDX : LEDC_LS_SIG_OUT0_IDX ) + ((bus -> channel ) % SOC_LEDC_CHANNEL_NUM ), out_invert , 0 );
460
498
#else
461
- esp_rom_gpio_connect_out_signal (pin , LEDC_LS_SIG_OUT0_IDX + ((bus -> channel ) % 8 ), out_invert , 0 );
499
+ esp_rom_gpio_connect_out_signal (pin , LEDC_LS_SIG_OUT0_IDX + ((bus -> channel ) % SOC_LEDC_CHANNEL_NUM ), out_invert , 0 );
462
500
#endif
463
501
#endif // ifdef CONFIG_IDF_TARGET_ESP32P4
464
502
return true;
@@ -505,7 +543,7 @@ static bool ledcFadeConfig(uint8_t pin, uint32_t start_duty, uint32_t target_dut
505
543
}
506
544
#endif
507
545
#endif
508
- uint8_t group = (bus -> channel / 8 ), channel = (bus -> channel % 8 );
546
+ uint8_t group = (bus -> channel / SOC_LEDC_CHANNEL_NUM ), channel = (bus -> channel % SOC_LEDC_CHANNEL_NUM );
509
547
510
548
// Initialize fade service.
511
549
if (!fade_initialized ) {
0 commit comments