1#ifndef _DRIVERS_ESP8266_TIMERBASEDPWM_HXX_
2#define _DRIVERS_ESP8266_TIMERBASEDPWM_HXX_
13#define FRC1_LOAD READ_PERI_REG(PERIPHS_TIMER_BASEDDR + FRC1_LOAD_ADDRESS)
14#define FRC1_COUNT READ_PERI_REG(PERIPHS_TIMER_BASEDDR + FRC1_COUNT_ADDRESS)
15#define FRC1_CTRL READ_PERI_REG(PERIPHS_TIMER_BASEDDR + FRC1_CTRL_ADDRESS)
16#define FRC1_INTCLR READ_PERI_REG(PERIPHS_TIMER_BASEDDR + FRC1_INT_ADDRESS)
18#define FRC_CTL_INT_ACTIVE 0x100
20#define FRC_CTL_ENABLE 0x80
21#define FRC_CTL_AUTORELOAD 0x40
22#define FRC_CTL_DIV_1 0x00
23#define FRC_CTL_DIV_16 0x04
24#define FRC_CTL_DIV_256 0x0C
25#define FRC_CTL_INT_EDGE 0x00
26#define FRC_CTL_INT_LEVEL 0x01
28#define FRC2_LOAD READ_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x20)
29#define FRC2_COUNT READ_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x24)
30#define FRC2_CTRL READ_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x28)
31#define FRC2_INTCLR READ_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x2C)
32#define FRC2_ALARM READ_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30)
35#define GPIO_OUT_CLR GPIO_REG_READ(GPIO_OUT_W1TC_ADDRESS)
36#define GPIO_OUT_SET GPIO_REG_READ(GPIO_OUT_W1TS_ADDRESS)
52 void __attribute__((noinline))
enable() {
53 ETS_FRC1_INTR_DISABLE();
54#pragma GCC diagnostic push
55#pragma GCC diagnostic ignored "-Wpmf-conversions"
58#pragma GCC diagnostic pop
84 ETS_FRC1_INTR_DISABLE();
98 ETS_FRC1_INTR_DISABLE();
101 GPIO_OUTPUT_SET(pin, 0);
104 if (nsec_on >= nsec_period) {
105 GPIO_OUTPUT_SET(pin, 1);
110 long long nsec_off = nsec_period - nsec_on;
114 GPIO_OUTPUT_SET(pin, 0);
116 FRC1_CTRL = FRC_CTL_ENABLE | FRC_CTL_DIV_1 | FRC_CTL_INT_EDGE;
118 ETS_FRC1_INTR_ENABLE();
119 TM1_EDGE_INT_ENABLE();
121 TM1_EDGE_INT_ENABLE();
136 ETS_FRC1_INTR_DISABLE();
137 unsigned clock_pause = (nsec_pause * 2) / 25;
138 HASSERT(clock_pause < (1<<23));
140 ETS_FRC1_INTR_ENABLE();
141 TM1_EDGE_INT_ENABLE();
142 FRC1_LOAD = std::max(clock_pause, 1U);
168 void set_state(
int pin,
long long nsec_period,
long long nsec_on)
174 long long nsec_off = nsec_period - nsec_on;
181 ETS_FRC1_INTR_ENABLE();
183 FRC1_CTRL = FRC_CTL_ENABLE | FRC_CTL_DIV_1 | FRC_CTL_INT_EDGE;
186 TM1_EDGE_INT_ENABLE();
Single-channel PWM implementation for the ESP8266 that uses the hardware timer resource.
void ICACHE_RAM_ATTR owned_isr_handler()
interrupt handler (to be called with a this pointer externally stored).
static uint32_t clockOn_
How many clock cycles we should wait after switching ON before swithing OFF.
void enable()
Turns on the PWM.
void pause(long long nsec_pause)
Pauses updating the PWM for a certain amount of time.
void set_off()
Turns off the previous output that may have been running.
static void ICACHE_RAM_ATTR new_isr_handler(void *)
New implementation of the interrupt handler.
static uint32_t clockOff_
How many clock cycles we should wait after switching OFF before swithing ON.
void set_state(int pin, long long nsec_period, long long nsec_on)
Sets the PWM parameters.
static uint32_t gpioValue_
Bit-shifted value to send to the GPIO output port.
void old_set_state(int pin, long long nsec_period, long long nsec_on)
Enables the PWM on a specific pin.
static void ICACHE_RAM_ATTR isr_handler(void *)
Interrupt handler.
static bool isOn_
1 if output is currently on, 0 if it is off.
#define ICACHE_RAM_ATTR
Declares (on the ESP8266) that the current function is executed often and should be placed in the ins...
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.