19
19
#include "esp32-hal-ledc.h"
20
20
#include "driver/ledc.h"
21
21
#include "esp32-hal-periman.h"
22
+ #include "soc/gpio_sig_map.h"
23
+ #include "esp_rom_gpio.h"
22
24
23
25
#ifdef SOC_LEDC_SUPPORT_HS_MODE
24
26
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM<<1)
@@ -40,7 +42,7 @@ typedef struct {
40
42
int used_channels : LEDC_CHANNELS ; // Used channels as a bits
41
43
} ledc_periph_t ;
42
44
43
- ledc_periph_t ledc_handle ;
45
+ ledc_periph_t ledc_handle = { 0 } ;
44
46
45
47
static bool fade_initialized = false;
46
48
@@ -58,15 +60,25 @@ static bool ledcDetachBus(void * bus){
58
60
59
61
bool ledcAttachChannel (uint8_t pin , uint32_t freq , uint8_t resolution , uint8_t channel )
60
62
{
61
- if (channel >= LEDC_CHANNELS || resolution > LEDC_MAX_BIT_WIDTH )
62
- {
63
- log_e ("Channel %u is not available! (maximum %u) or bit width too big (maximum %u)" , channel , LEDC_CHANNELS , LEDC_MAX_BIT_WIDTH );
63
+ if (channel >= LEDC_CHANNELS || ledc_handle .used_channels & (1UL << channel )){
64
+ log_e ("Channel %u is not available (maximum %u) or already used!" , channel , LEDC_CHANNELS );
65
+ return false;
66
+ }
67
+
68
+ if (resolution > LEDC_MAX_BIT_WIDTH ){
69
+ log_e ("LEDC resolution too big (maximum %u)" , LEDC_MAX_BIT_WIDTH );
64
70
return false;
65
71
}
66
72
67
73
perimanSetBusDeinit (ESP32_BUS_TYPE_LEDC , ledcDetachBus );
68
74
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
69
- if (bus != NULL && !perimanClearPinBus (pin )){
75
+ if (bus != NULL ){
76
+ log_e ("Pin %u is already attached to LEDC (channel %u, resolution %u)" , pin , bus -> channel , bus -> channel_resolution );
77
+ return false;
78
+ }
79
+
80
+ if (!perimanClearPinBus (pin )){
81
+ log_e ("Pin %u is already attached to another bus and failed to detach" , pin );
70
82
return false;
71
83
}
72
84
@@ -120,11 +132,11 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
120
132
bool ledcAttach (uint8_t pin , uint32_t freq , uint8_t resolution )
121
133
{
122
134
uint8_t free_channel = ~ledc_handle .used_channels & (ledc_handle .used_channels + 1 );
123
- if (free_channel == 0 || resolution > LEDC_MAX_BIT_WIDTH ){
124
- log_e ("No more LEDC channels available! (maximum %u) or bit width too big (maximum %u )" , LEDC_CHANNELS , LEDC_MAX_BIT_WIDTH );
135
+ if (free_channel == 0 ){
136
+ log_e ("No more LEDC channels available! (maximum is %u channels )" , LEDC_CHANNELS );
125
137
return false;
126
138
}
127
- int channel = log2 (free_channel & - free_channel );
139
+ uint8_t channel = log2 (free_channel & - free_channel );
128
140
129
141
return ledcAttachChannel (pin , freq , resolution , channel );
130
142
}
@@ -265,6 +277,21 @@ uint32_t ledcChangeFrequency(uint8_t pin, uint32_t freq, uint8_t resolution)
265
277
return 0 ;
266
278
}
267
279
280
+ bool ledcOutputInvert (uint8_t pin , bool out_invert )
281
+ {
282
+ ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
283
+ if (bus != NULL ){
284
+ gpio_set_level (pin , out_invert );
285
+ #ifdef SOC_LEDC_SUPPORT_HS_MODE
286
+ 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 );
287
+ #else
288
+ esp_rom_gpio_connect_out_signal (pin , LEDC_LS_SIG_OUT0_IDX + ((bus -> channel )%8 ), out_invert , 0 );
289
+ #endif
290
+ return true;
291
+ }
292
+ return false;
293
+ }
294
+
268
295
static IRAM_ATTR bool ledcFnWrapper (const ledc_cb_param_t * param , void * user_arg )
269
296
{
270
297
if (param -> event == LEDC_FADE_END_EVT ) {
@@ -373,7 +400,7 @@ void analogWrite(uint8_t pin, int value) {
373
400
if (pin < SOC_GPIO_PIN_COUNT ) {
374
401
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
375
402
if (bus == NULL && perimanClearPinBus (pin )){
376
- if (ledcAttach (pin , analog_frequency , analog_resolution ) == 0 ){
403
+ if (ledcAttach (pin , analog_frequency , analog_resolution , LEDC_CHANNEL_AUTO ) == 0 ){
377
404
log_e ("analogWrite setup failed (freq = %u, resolution = %u). Try setting different resolution or frequency" );
378
405
return ;
379
406
}
0 commit comments