#include "ets_sys.h"
#include "gpio.h"
#define INTC_EDGE_EN (*(volatile uint32_t *)0x3FF00004)
#define TIMER_LOAD (*(volatile uint32_t *)0x60000600)
#define TIMER_COUNT (*(volatile uint32_t *)0x60000604)
#define TIMER_CTRL (*(volatile uint32_t *)0x60000608)
#define TIMER_INT (*(volatile uint32_t *)0x6000060c)
#define GPIO_OUT_W1TS (*(volatile uint32_t *)0x60000304)
#define GPIO_OUT_W1TC (*(volatile uint32_t *)0x60000308)
#define GPIO_OUTP (*(volatile uint32_t *)0x60000300)
#define GPIO_STATUS (*(volatile uint32_t *)0x6000031C)
#define GPIO_PIN2_CFG (*(volatile uint32_t *)0x60000330)
#define GPIO_STATUS_W1TC (*(volatile uint32_t *)0x60000324)
static const int GPIO_OUT = 2; // GPIO2 ?
static const int GPIO_IN = 0; // GPIO0 ?
uint32_t volatile pulse1_in_0us2 = 50 * 5; // in 0.2 us (0x007fffff max), min 12*5
uint32_t volatile pulse2_in_0us2 = 50 * 5; // in 0.2 us (0x007fffff max), min 12*5
void ICACHE_RAM_ATTR GPIOs_intr_handler(void *arg) {
(void)arg;
uint32_t tmp = GPIO_STATUS;
GPIO_STATUS_W1TC = tmp;
if (tmp & BIT(GPIO_IN)) {
TIMER_LOAD = pulse1_in_0us2;
TIMER_CTRL = 4 | BIT(7); // TM_DIVDED_BY_16, NO TM_AUTO_RELOAD_CNT, TM_ENABLE_TIMER
}
}
void ICACHE_RAM_ATTR TIMER_intr_cb(void *arg) {
(void)arg;
if (GPIO_OUTP & BIT(GPIO_OUT)) {
GPIO_OUT_W1TC = BIT(GPIO_OUT);
TIMER_CTRL = 0; // stop timer
gpio_pin_intr_state_set(GPIO_IN, GPIO_PIN_INTR_POSEDGE);
} else {
GPIO_OUT_W1TS = BIT(GPIO_OUT);
TIMER_LOAD = pulse2_in_0us2;
}
}
void dimmer_stop() {
ets_isr_mask(BIT(ETS_FRC_TIMER1_INUM) | BIT(ETS_GPIO_INUM)); // запретить прерывания GPIOs & Timer0
GPIO_OUT_W1TC = BIT(GPIO_OUT);
TIMER_CTRL = 0; // stop timer
}
void dimmer_start() {
dimmer_stop();
TIMER_COUNT = 0;
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
gpio_output_set(0, 0, BIT(GPIO_OUT), BIT(GPIO_IN));
GPIO_PIN2_CFG &= ~BIT(GPIO_OUT); // normal out (push-pull)
gpio_pin_intr_state_set(GPIO_IN, GPIO_PIN_INTR_POSEDGE);
ets_isr_attach(ETS_GPIO_INUM, GPIOs_intr_handler, NULL);
ets_isr_attach(ETS_FRC_TIMER1_INUM, TIMER_intr_cb, NULL);
INTC_EDGE_EN |= BIT(1); // + timer0
ets_isr_unmask(BIT(ETS_FRC_TIMER1_INUM) | BIT(ETS_GPIO_INUM)); // разрешить прерывания GPIOs & Timer0
}
void setup() {
gpio_init();
dimmer_start();
}
void loop() {
uint32_t tmp = pulse1_in_0us2;
if (++tmp > 9000 * 5)
tmp = 10 * 5;
pulse1_in_0us2 = tmp;
}