pulse_counter: Replace storage enum with dependency injection

This substantially reduces the need for #ifdefs to handle conditional dependency on the ULP system
This commit is contained in:
brisk 2024-04-07 23:27:52 +09:30
parent fe533952cc
commit bb0ed5b855
3 changed files with 27 additions and 36 deletions

View file

@ -14,26 +14,6 @@ static const char *const TAG = "pulse_counter";
const char *const EDGE_MODE_TO_STRING[] = {"DISABLE", "INCREMENT", "DECREMENT"}; const char *const EDGE_MODE_TO_STRING[] = {"DISABLE", "INCREMENT", "DECREMENT"};
#ifdef HAS_PCNT
PulseCounterStorageBase *get_storage(Storage storage) {
switch (storage) {
case Storage::basic:
return new BasicPulseCounterStorage;
case Storage::pcnt:
return new HwPulseCounterStorage;
#ifdef CONF_USE_ULP
case Storage::ulp:
return new UlpPulseCounterStorage;
#endif
default:
return new BasicPulseCounterStorage;
}
return new BasicPulseCounterStorage;
}
#else
PulseCounterStorageBase *get_storage(Storage) { return new BasicPulseCounterStorage; }
#endif
void IRAM_ATTR BasicPulseCounterStorage::gpio_intr(BasicPulseCounterStorage *arg) { void IRAM_ATTR BasicPulseCounterStorage::gpio_intr(BasicPulseCounterStorage *arg) {
const uint32_t now = micros(); const uint32_t now = micros();
const bool discard = now - arg->last_pulse < arg->filter_us; const bool discard = now - arg->last_pulse < arg->filter_us;
@ -203,9 +183,11 @@ bool UlpPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) {
} }
/* GPIO used for pulse counting. */ /* GPIO used for pulse counting. */
gpio_num_t gpio_num = GPIO_NUM_0; gpio_num_t gpio_num = static_cast<gpio_num_t>(pin->get_pin());
int rtcio_num = rtc_io_number_get(gpio_num); int rtcio_num = rtc_io_number_get(gpio_num);
assert(rtc_gpio_is_valid_gpio(gpio_num) && "GPIO used for pulse counting must be an RTC IO"); if (!rtc_gpio_is_valid_gpio(gpio_num)) {
ESP_LOGE(TAG, "GPIO used for pulse counting must be an RTC IO");
}
/* Initialize some variables used by ULP program. /* Initialize some variables used by ULP program.
* Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program. * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
@ -222,11 +204,9 @@ bool UlpPulseCounterStorage::pulse_counter_setup(InternalGPIOPin *pin) {
ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */ ulp_io_number = rtcio_num; /* map from GPIO# to RTC_IO# */
ulp_edge_count_to_wake_up = 10; ulp_edge_count_to_wake_up = 10;
/* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */ /* Initialize selected GPIO as RTC IO, enable input */
rtc_gpio_init(gpio_num); rtc_gpio_init(gpio_num);
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_dis(gpio_num);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_hold_en(gpio_num); rtc_gpio_hold_en(gpio_num);
/* Set ULP wake up period to T = 20ms. /* Set ULP wake up period to T = 20ms.

View file

@ -20,8 +20,6 @@ enum PulseCounterCountMode {
PULSE_COUNTER_DECREMENT, PULSE_COUNTER_DECREMENT,
}; };
enum class Storage { basic, pcnt, ulp };
#ifdef HAS_PCNT #ifdef HAS_PCNT
using pulse_counter_t = int16_t; using pulse_counter_t = int16_t;
#else #else
@ -65,12 +63,9 @@ struct UlpPulseCounterStorage : public PulseCounterStorageBase {
}; };
#endif #endif
PulseCounterStorageBase *get_storage(Storage storage = Storage::basic);
class PulseCounterSensor : public sensor::Sensor, public PollingComponent { class PulseCounterSensor : public sensor::Sensor, public PollingComponent {
public: public:
explicit PulseCounterSensor(Storage storage = Storage::basic) : storage_(*get_storage(storage)) {} explicit PulseCounterSensor(PulseCounterStorageBase *storage) : storage_(*storage) {}
PulseCounterSensor(int storage = 0) : PulseCounterSensor(Storage(storage)) {}
void set_pin(InternalGPIOPin *pin) { pin_ = pin; } void set_pin(InternalGPIOPin *pin) { pin_ = pin; }
void set_rising_edge_mode(PulseCounterCountMode mode) { storage_.rising_edge_mode = mode; } void set_rising_edge_mode(PulseCounterCountMode mode) { storage_.rising_edge_mode = mode; }

View file

@ -24,6 +24,7 @@ from esphome.core import CORE
CONF_USE_PCNT = "use_pcnt" CONF_USE_PCNT = "use_pcnt"
CONF_USE_ULP = "use_ulp" CONF_USE_ULP = "use_ulp"
CONF_STORAGE_ID = "storage"
pulse_counter_ns = cg.esphome_ns.namespace("pulse_counter") pulse_counter_ns = cg.esphome_ns.namespace("pulse_counter")
PulseCounterCountMode = pulse_counter_ns.enum("PulseCounterCountMode") PulseCounterCountMode = pulse_counter_ns.enum("PulseCounterCountMode")
@ -121,6 +122,9 @@ CONFIG_SCHEMA = cv.All(
accuracy_decimals=0, accuracy_decimals=0,
state_class=STATE_CLASS_TOTAL_INCREASING, state_class=STATE_CLASS_TOTAL_INCREASING,
), ),
cv.GenerateID(CONF_STORAGE_ID): cv.declare_id(
"pulse_counter::PulseCounterStorageBase"
),
}, },
) )
.extend(cv.polling_component_schema("60s")), .extend(cv.polling_component_schema("60s")),
@ -130,15 +134,16 @@ CONFIG_SCHEMA = cv.All(
async def to_code(config): async def to_code(config):
if config.get(CONF_USE_ULP): if config.get(CONF_USE_ULP):
var = await sensor.new_sensor(config, 2) cg.add_define("CONF_USE_ULP", True)
else: storage = cg.Pvariable(
var = await sensor.new_sensor(config, config.get(CONF_USE_PCNT)) config[CONF_STORAGE_ID],
if config.get(CONF_USE_ULP): cg.RawExpression("new pulse_counter::UlpPulseCounterStorage()"),
var.add_define("CONF_USE_ULP", True) )
esp32.add_extra_build_file( esp32.add_extra_build_file(
"src/CMakeLists.txt", "src/CMakeLists.txt",
os.path.join(os.path.dirname(__file__), "CMakeLists.txt"), os.path.join(os.path.dirname(__file__), "CMakeLists.txt"),
) )
# FIXME These files don't get cleared when the config changes, necessitating deleting .esphome
esp32.add_extra_build_file( esp32.add_extra_build_file(
"ulp/pulse_cnt.S", "ulp/pulse_cnt.S",
os.path.join(os.path.dirname(__file__), "ulp/pulse_cnt.S"), os.path.join(os.path.dirname(__file__), "ulp/pulse_cnt.S"),
@ -149,6 +154,17 @@ async def to_code(config):
esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_ENABLED", True) esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_ENABLED", True)
esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_TYPE_FSM", True) esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_TYPE_FSM", True)
esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_RESERVE_MEM", 1024) esp32.add_idf_sdkconfig_option("CONFIG_ULP_COPROC_RESERVE_MEM", 1024)
elif config.get(CONF_USE_PCNT):
storage = cg.Pvariable(
config[CONF_STORAGE_ID],
cg.RawExpression("new pulse_counter::HwPulseCounterStorage()"),
)
else:
storage = cg.Pvariable(
config[CONF_STORAGE_ID],
cg.RawExpression("new pulse_counter::BasicPulseCounterStorage()"),
)
var = await sensor.new_sensor(config, storage)
await cg.register_component(var, config) await cg.register_component(var, config)
pin = await cg.gpio_pin_expression(config[CONF_PIN]) pin = await cg.gpio_pin_expression(config[CONF_PIN])