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"};
#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) {
const uint32_t now = micros();
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_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);
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.
* 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_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_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);
/* Set ULP wake up period to T = 20ms.

View file

@ -20,8 +20,6 @@ enum PulseCounterCountMode {
PULSE_COUNTER_DECREMENT,
};
enum class Storage { basic, pcnt, ulp };
#ifdef HAS_PCNT
using pulse_counter_t = int16_t;
#else
@ -65,12 +63,9 @@ struct UlpPulseCounterStorage : public PulseCounterStorageBase {
};
#endif
PulseCounterStorageBase *get_storage(Storage storage = Storage::basic);
class PulseCounterSensor : public sensor::Sensor, public PollingComponent {
public:
explicit PulseCounterSensor(Storage storage = Storage::basic) : storage_(*get_storage(storage)) {}
PulseCounterSensor(int storage = 0) : PulseCounterSensor(Storage(storage)) {}
explicit PulseCounterSensor(PulseCounterStorageBase *storage) : storage_(*storage) {}
void set_pin(InternalGPIOPin *pin) { pin_ = pin; }
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_ULP = "use_ulp"
CONF_STORAGE_ID = "storage"
pulse_counter_ns = cg.esphome_ns.namespace("pulse_counter")
PulseCounterCountMode = pulse_counter_ns.enum("PulseCounterCountMode")
@ -121,6 +122,9 @@ CONFIG_SCHEMA = cv.All(
accuracy_decimals=0,
state_class=STATE_CLASS_TOTAL_INCREASING,
),
cv.GenerateID(CONF_STORAGE_ID): cv.declare_id(
"pulse_counter::PulseCounterStorageBase"
),
},
)
.extend(cv.polling_component_schema("60s")),
@ -130,15 +134,16 @@ CONFIG_SCHEMA = cv.All(
async def to_code(config):
if config.get(CONF_USE_ULP):
var = await sensor.new_sensor(config, 2)
else:
var = await sensor.new_sensor(config, config.get(CONF_USE_PCNT))
if config.get(CONF_USE_ULP):
var.add_define("CONF_USE_ULP", True)
cg.add_define("CONF_USE_ULP", True)
storage = cg.Pvariable(
config[CONF_STORAGE_ID],
cg.RawExpression("new pulse_counter::UlpPulseCounterStorage()"),
)
esp32.add_extra_build_file(
"src/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(
"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_TYPE_FSM", True)
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)
pin = await cg.gpio_pin_expression(config[CONF_PIN])