diff --git a/esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.cpp b/esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.cpp index a9633e6..cd6b6be 100644 --- a/esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.cpp +++ b/esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.cpp @@ -34,7 +34,7 @@ static StaticSemaphore_t miso_semaphore_buffer; static int ready = 0; static bool active_mode = false; - +static gpio_num_t gpio_cs_out; static SemaphoreHandle_t snapshot_semaphore_handle; static StaticSemaphore_t snapshot_semaphore_buffer; @@ -57,12 +57,12 @@ static bool IRAM_ATTR timer_group_isr_callback(void *args) esp_err_t err; BaseType_t xHigherPriorityTaskWoken; // Trigger Chip Select - gpio_set_level(GPIO_CS_OUT, 1); + gpio_set_level(gpio_cs_out, 1); if(ready) { spi_slave_transaction_t *t = (spi_slave_transaction_t *) args; err = spi_slave_queue_trans(RCV_HOST, t, 0); } - gpio_set_level(GPIO_CS_OUT, 0); + gpio_set_level(gpio_cs_out, 0); return false; } @@ -572,17 +572,18 @@ static void mhi_poll_task(void *arg) } } -void mhi_ac_ctrl_core_init() { +void mhi_ac_ctrl_core_init(const Config& config) { esp_err_t err; miso_semaphore_handle = xSemaphoreCreateMutexStatic( &miso_semaphore_buffer ); snapshot_semaphore_handle = xSemaphoreCreateBinaryStatic( &snapshot_semaphore_buffer ); + gpio_cs_out = config.cs_out; // configuration for the SPI bus spi_bus_config_t buscfg = { - .mosi_io_num = GPIO_MOSI, - .miso_io_num = GPIO_MISO, - .sclk_io_num = GPIO_SCLK, + .mosi_io_num = config.mosi, + .miso_io_num = config.miso, + .sclk_io_num = config.sclk, .quadwp_io_num = -1, .quadhd_io_num = -1, .flags = SPICOMMON_BUSFLAG_GPIO_PINS | SPICOMMON_BUSFLAG_SLAVE, @@ -590,7 +591,7 @@ void mhi_ac_ctrl_core_init() { // configuration for the SPI slave interface spi_slave_interface_config_t slvcfg = { - .spics_io_num = GPIO_CS_IN, + .spics_io_num = config.cs_in, .flags = SPI_SLAVE_BIT_LSBFIRST, .queue_size = 1, .mode = 3, //CPOL=1, CPHA=1 @@ -601,14 +602,14 @@ void mhi_ac_ctrl_core_init() { ESP_ERROR_CHECK(err); // Select and initialize basic parameters of the timer - timer_config_t config = { + timer_config_t timer_config = { .alarm_en = TIMER_ALARM_DIS, .counter_en = TIMER_PAUSE, .counter_dir = TIMER_COUNT_UP, .auto_reload = TIMER_AUTORELOAD_DIS, .divider = TIMER_DIVIDER, }; // default clock source is APB - timer_init(TIMER_GROUP_0, TIMER_0, &config); + timer_init(TIMER_GROUP_0, TIMER_0, &timer_config); // Configure the alarm value (in milliseconds) and the interrupt on alarm. there is a delay between each frame of 40ms. // so we set the alarm to 20ms. once the alarm triggers, spi_slave_queue_trans is called which will get the data from the next spi packet. This is also the point to toggle the CS line to mark the end/start of a SPI transaction. @@ -617,7 +618,7 @@ void mhi_ac_ctrl_core_init() { gpio_config_t io_conf = {}; io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL< #include #include "esp_timer.h" +#include "driver/gpio.h" // # Config -// ## pin defintions -#define GPIO_MOSI 7 -#define GPIO_MISO 2 -#define GPIO_SCLK GPIO_NUM_6 -#define GPIO_CS_OUT GPIO_NUM_9 -#define GPIO_CS_IN 10 - #define RCV_HOST SPI2_HOST #define MHI_FRAME_LEN 20 @@ -41,6 +35,14 @@ namespace mhi_ac { +struct Config { + gpio_num_t mosi; + gpio_num_t miso; + gpio_num_t sclk; + gpio_num_t cs_in; + gpio_num_t cs_out; +}; + enum class ACPower { power_off = 0, power_on = 1 @@ -72,7 +74,7 @@ enum class ACVanes { // Vanes enum //public: virtual void cbiStatusFunction(ACStatus status, int value) = 0; //}; -void mhi_ac_ctrl_core_init(); +void mhi_ac_ctrl_core_init(const Config& config); bool mhi_ac_ctrl_core_snapshot(uint32_t wait_time_ms); void mhi_ac_ctrl_core_active_mode_set(bool state); diff --git a/esphome/components/MhiAcCtrl/__init__.py b/esphome/components/MhiAcCtrl/__init__.py index 2f1ab95..80f29d0 100644 --- a/esphome/components/MhiAcCtrl/__init__.py +++ b/esphome/components/MhiAcCtrl/__init__.py @@ -2,21 +2,58 @@ import esphome.config_validation as cv from esphome.const import CONF_ID from esphome.components import climate +from esphome import pins AUTO_LOAD = ["sensor", "climate"] CODEOWNERS = ["hberntsen"] CONF_MHI_AC_CTRL_ID = "mhi_ac_ctrl_id" +mhi_core_ns = cg.global_ns.namespace("mhi_ac") +ConfigStruct = mhi_core_ns.struct("Config") MhiAcCtrl = cg.global_ns.class_("MhiAcCtrl", cg.Component, climate.Climate) +CONF_MOSI_PIN = "mosi_pin" +CONF_MISO_PIN = "miso_pin" +CONF_SCLK_PIN = "sclk_pin" +CONF_CS_IN_PIN = "cs_in_pin" +CONF_CS_OUT_PIN = "cs_out_pin" + +TYPES = [ + CONF_MOSI_PIN, + CONF_MISO_PIN, + CONF_SCLK_PIN, + CONF_CS_IN_PIN, + CONF_CS_OUT_PIN, +] + CONFIG_SCHEMA = cv.Schema( { cv.GenerateID(): cv.declare_id(MhiAcCtrl), + cv.Optional(CONF_MOSI_PIN, default="GPIO7"): pins.gpio_input_pin_schema, + cv.Optional(CONF_MISO_PIN, default="GPIO2"): pins.gpio_output_pin_schema, + cv.Optional(CONF_SCLK_PIN, default="GPIO6"): pins.gpio_input_pin_schema, + cv.Optional(CONF_CS_IN_PIN, default="GPIO10"): pins.gpio_input_pin_schema, + cv.Optional(CONF_CS_OUT_PIN, default="GPIO9"): pins.gpio_output_pin_schema, } ).extend(cv.COMPONENT_SCHEMA) - -def to_code(config): +async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) - yield cg.register_component(var, config) + + mosi_pin = await cg.gpio_pin_expression(config[CONF_MOSI_PIN]) + cg.add(var.set_mosi_pin(mosi_pin)) + + miso_pin = await cg.gpio_pin_expression(config[CONF_MISO_PIN]) + cg.add(var.set_miso_pin(miso_pin)) + + sclk_pin = await cg.gpio_pin_expression(config[CONF_SCLK_PIN]) + cg.add(var.set_sclk_pin(sclk_pin)) + + cs_in_pin = await cg.gpio_pin_expression(config[CONF_CS_IN_PIN]) + cg.add(var.set_cs_in_pin(cs_in_pin)) + + cs_out_pin = await cg.gpio_pin_expression(config[CONF_CS_OUT_PIN]) + cg.add(var.set_cs_out_pin(cs_out_pin)) + + return await cg.register_component(var, config) diff --git a/esphome/components/MhiAcCtrl/mhi_ac_ctrl.h b/esphome/components/MhiAcCtrl/mhi_ac_ctrl.h index 78f0d59..4e457ec 100644 --- a/esphome/components/MhiAcCtrl/mhi_ac_ctrl.h +++ b/esphome/components/MhiAcCtrl/mhi_ac_ctrl.h @@ -1,4 +1,5 @@ #include "MHI-AC-Ctrl-core.h" +#include "esphome/core/gpio.h" #include "esphome/components/climate/climate.h" #include "esphome/components/sensor/sensor.h" @@ -159,6 +160,22 @@ class MhiVanesUD : public select::Select { class MhiAcCtrl : public climate::Climate, public Component { public: + void set_mosi_pin(InternalGPIOPin *pin) { + this->ac_config_.mosi = static_cast(pin->get_pin()); + } + void set_miso_pin(InternalGPIOPin *pin) { + this->ac_config_.miso = static_cast(pin->get_pin()); + } + void set_sclk_pin(InternalGPIOPin *pin) { + this->ac_config_.sclk = static_cast(pin->get_pin()); + } + void set_cs_in_pin(InternalGPIOPin *pin) { + this->ac_config_.cs_in = static_cast(pin->get_pin()); + } + void set_cs_out_pin(InternalGPIOPin *pin) { + this->ac_config_.cs_out = static_cast(pin->get_pin()); + } + void setup() override { auto restore = this->restore_state_(); @@ -178,7 +195,7 @@ class MhiAcCtrl : public climate::Climate, //current_power.set_unit_of_measurement("A"); //current_power.set_accuracy_decimals(2); - mhi_ac_ctrl_core_init(); + mhi_ac_ctrl_core_init(this->ac_config_); } void loop() override @@ -415,6 +432,7 @@ class MhiAcCtrl : public climate::Climate, MhiFrameErrors *frame_errors_sensor_; MhiTotalEnergy *total_energy_sensor_; MhiPower *power_sensor_; + Config ac_config_; public: #ifdef USE_SELECT diff --git a/esphome/example.yaml b/esphome/example.yaml index cab62f3..49e67af 100755 --- a/esphome/example.yaml +++ b/esphome/example.yaml @@ -24,6 +24,13 @@ logger: MhiAcCtrl: id: ${mhi_device_id} + # Optional PIN config + # The default values are: + mosi_pin: GPIO7 + miso_pin: GPIO2 + sclk_pin: GPIO6 + cs_in_pin: GPIO10 + cs_out_pin: GPIO9 climate: - platform: MhiAcCtrl