Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Esp32Ledc.hxx
Go to the documentation of this file.
1
35#ifndef _DRIVERS_ESP32LEDC_HXX_
36#define _DRIVERS_ESP32LEDC_HXX_
37
39#include "utils/logging.h"
40#include "utils/macros.h"
42
43#include <driver/ledc.h>
44
45namespace openmrn_arduino
46{
47
83{
84public:
102 Esp32Ledc(const std::initializer_list<uint8_t> &pins,
103 const ledc_channel_t first_channel = LEDC_CHANNEL_0,
104 const ledc_timer_bit_t timer_resolution = LEDC_TIMER_12_BIT,
105 const uint32_t timer_hz = 5000,
106 const ledc_timer_t timer_num = LEDC_TIMER_0,
107 const ledc_mode_t timer_mode = LEDC_LOW_SPEED_MODE,
108 const ledc_clk_cfg_t timer_clock = LEDC_AUTO_CLK)
109 : firstChannel_(first_channel)
110 , pins_(pins)
111 {
112 // Ensure the pin count is valid and within range of usable channels.
113 HASSERT(pins_.size() > 0 &&
114 pins_.size() <= (LEDC_CHANNEL_MAX - first_channel));
115 memset(&timerConfig_, 0, sizeof(ledc_timer_config_t));
116 // timerConfig_.speed_mode will be assigned the SOC default mode, which
117 // is either HIGH speed or LOW speed depending on the hardware support.
118 timerConfig_.duty_resolution = timer_resolution;
119 timerConfig_.freq_hz = timer_hz;
120 timerConfig_.speed_mode = timer_mode;
121 timerConfig_.timer_num = timer_num;
122 timerConfig_.clk_cfg = timer_clock;
123 }
124
132 void hw_init()
133 {
134 LOG(INFO,
135 "[Esp32Ledc:%d] Configuring timer (resolution:%d, frequency:%"
136 PRIu32 ")",
137 timerConfig_.timer_num,
138 (1 << (uint8_t)timerConfig_.duty_resolution) - 1,
139 timerConfig_.freq_hz);
140 ESP_ERROR_CHECK(ledc_timer_config(&timerConfig_));
141 size_t count = 0;
142 for (uint8_t pin : pins_)
143 {
144 HASSERT(GPIO_IS_VALID_OUTPUT_GPIO(pin));
145
146 ledc_channel_t led_channel =
147 static_cast<ledc_channel_t>(firstChannel_ + count);
148 LOG(INFO, "[Esp32Ledc:%d] Configuring LEDC channel %d on GPIO %d",
149 timerConfig_.timer_num, led_channel, pin);
150 ledc_channel_config_t config;
151 memset(&config, 0, sizeof(ledc_channel_config_t));
152 config.gpio_num = pin;
153 config.speed_mode = timerConfig_.speed_mode;
154 config.channel = led_channel;
155 config.timer_sel = timerConfig_.timer_num;
156 ESP_ERROR_CHECK(ledc_channel_config(&config));
157 channels_[count].emplace(this, led_channel, pin);
158 count++;
159 }
160 }
161
165 PWM *get_channel(unsigned id)
166 {
167 HASSERT(id <= (LEDC_CHANNEL_MAX - firstChannel_));
168 return &*channels_[id];
169 }
170
185 void fade_channel_over_time(unsigned id, uint32_t target_duty = 0,
186 uint32_t fade_period = 1000,
187 ledc_fade_mode_t fade_mode = LEDC_FADE_NO_WAIT)
188 {
189 HASSERT(id <= (LEDC_CHANNEL_MAX - firstChannel_));
190 ledc_channel_t channel =
191 static_cast<ledc_channel_t>(firstChannel_ + id);
192 HASSERT(0 == pthread_once(&ledcFadeOnce_, &Esp32Ledc::ledc_fade_setup));
193 ESP_ERROR_CHECK(
194 ledc_set_fade_time_and_start(timerConfig_.speed_mode, channel,
195 target_duty, fade_period, fade_mode));
196 }
197
203 static void ledc_fade_setup()
204 {
205 // allocate the interrupt as low/medium priority (C code supported) and
206 // the interrupt can be shared with other usages (if necessary).
207 const int INTR_MODE_FLAGS =
208 ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED;
209 LOG(VERBOSE, "[Esp32Ledc] Initializing LED Fade ISR");
210 ESP_ERROR_CHECK(ledc_fade_func_install(INTR_MODE_FLAGS));
211 }
212private:
213 class Channel : public PWM
214 {
215 public:
216 Channel(Esp32Ledc *parent, ledc_channel_t channel, uint8_t pin)
217 : parent_(parent)
218 , channel_(channel)
219 {
220 }
221
222 void set_period(uint32_t counts) override
223 {
224 parent_->set_period(counts);
225 }
226
227 uint32_t get_period() override
228 {
229 return parent_->get_period();
230 }
231
232 void set_duty(uint32_t counts) override
233 {
234 parent_->set_duty(channel_, counts);
235 }
236
237 uint32_t get_duty() override
238 {
239 return parent_->get_duty(channel_);
240 }
241
242 uint32_t get_period_max() override
243 {
244 return parent_->get_period_max();
245 }
246
247 uint32_t get_period_min() override
248 {
249 return parent_->get_period_min();
250 }
251 private:
252 Esp32Ledc *parent_;
253 ledc_channel_t channel_;
254 };
255
260 void set_period(uint32_t counts)
261 {
262 ESP_ERROR_CHECK(
263 ledc_set_freq(timerConfig_.speed_mode, timerConfig_.timer_num,
264 counts));
265 }
266
269 uint32_t get_period()
270 {
271 return ledc_get_freq(timerConfig_.speed_mode, timerConfig_.timer_num);
272 }
273
277 void set_duty(ledc_channel_t channel, uint32_t counts)
278 {
279 ESP_ERROR_CHECK(
280 ledc_set_duty(timerConfig_.speed_mode, channel, counts));
281 ESP_ERROR_CHECK(ledc_update_duty(timerConfig_.speed_mode, channel));
282 }
283
287 uint32_t get_duty(ledc_channel_t channel)
288 {
289 return ledc_get_duty(timerConfig_.speed_mode, channel);
290 }
291
294 uint32_t get_period_max()
295 {
296 return ((1 << (uint8_t)timerConfig_.duty_resolution) - 1);
297 }
298
301 uint32_t get_period_min()
302 {
303 return 0;
304 }
305
307 const ledc_channel_t firstChannel_;
308
310 ledc_timer_config_t timerConfig_;
311
313 static pthread_once_t ledcFadeOnce_;
314
317
319 std::vector<uint8_t> pins_;
320
322};
323
324} // namespace openmrn_arduino
325
327
328#endif // _DRIVERS_ESP32LEDC_HXX_
Abstract interface for a PWM driver.
Definition PWM.hxx:43
void set_duty(uint32_t counts) override
Sets the duty cycle.
uint32_t get_period_max() override
Get max period supported.
uint32_t get_period() override
Get PWM period.
uint32_t get_period_min() override
Get min period supported.
void set_period(uint32_t counts) override
Set PWM period.
uint32_t get_duty() override
Gets the duty cycle.
ESP32 LEDC provider for PWM like output on GPIO pins.
Definition Esp32Ledc.hxx:83
void set_period(uint32_t counts)
Set PWM period.
PWM * get_channel(unsigned id)
ledc_timer_config_t timerConfig_
LEDC Timer configuration settings.
uint32_t get_period()
Get PWM period.
Esp32Ledc(const std::initializer_list< uint8_t > &pins, const ledc_channel_t first_channel=LEDC_CHANNEL_0, const ledc_timer_bit_t timer_resolution=LEDC_TIMER_12_BIT, const uint32_t timer_hz=5000, const ledc_timer_t timer_num=LEDC_TIMER_0, const ledc_mode_t timer_mode=LEDC_LOW_SPEED_MODE, const ledc_clk_cfg_t timer_clock=LEDC_AUTO_CLK)
Constructor.
std::vector< uint8_t > pins_
Collection of GPIO pins in use by this Esp32Ledc.
static void ledc_fade_setup()
Static entry point for configuring the LEDC hardware fade controller.
const ledc_channel_t firstChannel_
First LEDC Channel for this Esp32Ledc.
void set_duty(ledc_channel_t channel, uint32_t counts)
Sets the duty cycle.
static pthread_once_t ledcFadeOnce_
Protects the initialization of LEDC Fade ISR hook.
uint32_t get_duty(ledc_channel_t channel)
Gets the duty cycle.
uninitialized< Channel > channels_[LEDC_CHANNEL_MAX]
PWM instances connected to LEDC channels.
uint32_t get_period_max()
Get max period supported by the underlying LEDC timer.
uint32_t get_period_min()
Get min period supported by the underlying LEDC timer.
void fade_channel_over_time(unsigned id, uint32_t target_duty=0, uint32_t fade_period=1000, ledc_fade_mode_t fade_mode=LEDC_FADE_NO_WAIT)
Transitions a PWM output from the current duty to the target duty over the provided time period.
void hw_init()
Initializes the LEDC peripheral.
Template class that allows allocating storage for an object but not calling its constructor.
#define LOG(level, message...)
Conditionally write a message to the logging output.
Definition logging.h:99
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
Definition logging.h:59
static const int INFO
Loglevel that is printed by default, reporting some status information.
Definition logging.h:57
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171