21
21
#include "esp32-hal-periman.h"
22
22
#include "soc/gpio_sig_map.h"
23
23
#include "esp_rom_gpio.h"
24
+ #include "hal/ledc_ll.h"
24
25
25
26
#ifdef SOC_LEDC_SUPPORT_HS_MODE
26
27
#define LEDC_CHANNELS (SOC_LEDC_CHANNEL_NUM << 1)
@@ -77,7 +78,7 @@ static bool ledcDetachBus(void *bus) {
77
78
78
79
bool ledcAttachChannel (uint8_t pin , uint32_t freq , uint8_t resolution , uint8_t channel ) {
79
80
if (channel >= LEDC_CHANNELS ) { //|| ledc_handle.used_channels & (1UL << channel)) {
80
- log_e ("Channel %u is not available (maximum %u) TODO: delete (or already used) !" , channel , LEDC_CHANNELS );
81
+ log_e ("Channel %u is not available (maximum %u)!" , channel , LEDC_CHANNELS );
81
82
return false;
82
83
}
83
84
if (freq == 0 ) {
@@ -102,29 +103,45 @@ bool ledcAttachChannel(uint8_t pin, uint32_t freq, uint8_t resolution, uint8_t c
102
103
}
103
104
104
105
uint8_t group = (channel / 8 ), timer = ((channel / 2 ) % 4 );
105
-
106
- ledc_timer_config_t ledc_timer = {.speed_mode = group , .timer_num = timer , .duty_resolution = resolution , .freq_hz = freq , .clk_cfg = LEDC_DEFAULT_CLK };
107
- if (ledc_timer_config (& ledc_timer ) != ESP_OK ) {
108
- log_e ("ledc setup failed!" );
109
- return false;
106
+ bool channel_used = ledc_handle .used_channels & (1UL << channel );
107
+ if (channel_used ) {
108
+ if (ledc_set_pin (pin , group , channel % 8 ) != ESP_OK ) {
109
+ log_e ("Attaching pin to already used channel failed!" );
110
+ return false;
111
+ }
110
112
}
113
+ else {
114
+ ledc_timer_config_t ledc_timer = {.speed_mode = group , .timer_num = timer , .duty_resolution = resolution , .freq_hz = freq , .clk_cfg = LEDC_DEFAULT_CLK };
115
+ if (ledc_timer_config (& ledc_timer ) != ESP_OK ) {
116
+ log_e ("ledc setup failed!" );
117
+ return false;
118
+ }
111
119
112
- uint32_t duty = ledc_get_duty (group , (channel % 8 ));
120
+ uint32_t duty = ledc_get_duty (group , (channel % 8 ));
113
121
114
- ledc_channel_config_t ledc_channel = {
115
- .speed_mode = group , .channel = (channel % 8 ), .timer_sel = timer , .intr_type = LEDC_INTR_DISABLE , .gpio_num = pin , .duty = duty , .hpoint = 0
116
- };
117
- ledc_channel_config (& ledc_channel );
122
+ ledc_channel_config_t ledc_channel = {
123
+ .speed_mode = group , .channel = (channel % 8 ), .timer_sel = timer , .intr_type = LEDC_INTR_DISABLE , .gpio_num = pin , .duty = duty , .hpoint = 0
124
+ };
125
+ ledc_channel_config (& ledc_channel );
126
+ }
118
127
119
128
ledc_channel_handle_t * handle = (ledc_channel_handle_t * )malloc (sizeof (ledc_channel_handle_t ));
120
-
121
129
handle -> pin = pin ;
122
130
handle -> channel = channel ;
123
- handle -> channel_resolution = resolution ;
124
131
#ifndef SOC_LEDC_SUPPORT_FADE_STOP
125
132
handle -> lock = NULL ;
126
133
#endif
127
- ledc_handle .used_channels |= 1UL << channel ;
134
+
135
+ //get resolution of selected channel when used
136
+ if (channel_used ) {
137
+ uint32_t channel_resolution = 0 ;
138
+ ledc_ll_get_duty_resolution (LEDC_LL_GET_HW (), group , timer , & channel_resolution );
139
+ handle -> channel_resolution = (uint8_t )channel_resolution ;
140
+ }
141
+ else {
142
+ handle -> channel_resolution = resolution ;
143
+ ledc_handle .used_channels |= 1UL << channel ;
144
+ }
128
145
129
146
if (!perimanSetPinBus (pin , ESP32_BUS_TYPE_LEDC , (void * )handle , group , channel )) {
130
147
ledcDetachBus ((void * )handle );
@@ -167,6 +184,30 @@ bool ledcWrite(uint8_t pin, uint32_t duty) {
167
184
return false;
168
185
}
169
186
187
+ bool ledcWriteChannel (uint8_t channel , uint32_t duty ){
188
+ //check if channel is valid and used
189
+ if (channel >= LEDC_CHANNELS || !(ledc_handle .used_channels & (1UL << channel ))) {
190
+ log_e ("Channel %u is not available (maximum %u) or not used!" , channel , LEDC_CHANNELS );
191
+ return false;
192
+ }
193
+ uint8_t group = (channel / 8 ), timer = ((channel / 2 ) % 4 );
194
+
195
+ //Fixing if all bits in resolution is set = LEDC FULL ON
196
+ uint32_t resolution = 0 ;
197
+ ledc_ll_get_duty_resolution (LEDC_LL_GET_HW (), group , timer , & resolution );
198
+
199
+ uint32_t max_duty = (1 << resolution ) - 1 ;
200
+
201
+ if ((duty == max_duty ) && (max_duty != 1 )) {
202
+ duty = max_duty + 1 ;
203
+ }
204
+
205
+ ledc_set_duty (group , channel , duty );
206
+ ledc_update_duty (group , channel );
207
+
208
+ return true;
209
+ }
210
+
170
211
uint32_t ledcRead (uint8_t pin ) {
171
212
ledc_channel_handle_t * bus = (ledc_channel_handle_t * )perimanGetPinBus (pin , ESP32_BUS_TYPE_LEDC );
172
213
if (bus != NULL ) {
0 commit comments