Skip to content

Commit 99ec16f

Browse files
committed
Remove physical CS loopback requirement
Hope this does not break the ESP32 because of the SPI_LL_SLAVE_NEEDS_CS_WORKAROUND in the IDF code.
1 parent 161083d commit 99ec16f

File tree

7 files changed

+10
-62
lines changed

7 files changed

+10
-62
lines changed

Hardware.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@ It was not tested to directly plug the MHI-AC-Ctrl-ESP32-C3 into the AC unit. In
4646
The JST connector provides +12V. The DC-DC converter [TSR 1-2450](https://www.tracopower.com/products/browse-by-category/find/tsr-1/3/) converts the +12V to +5V.
4747

4848
## Signal Connection
49-
The ESP32-C3 SPI signals SCL (SPI clock), MOSI (Master Out Slave In) and MISO (Master In Slave Out) are connected via a voltage level shifter 5V <-> 3.3V with the AC. Direct connection of the signals without a level shifter could damage your ESP32-C3! Note that the CNS connector does not provide a Chip Select signal, this is generated internally on the ESP32-C3 and routed back through IO9 and IO10.
49+
The ESP32-C3 SPI signals SCL (SPI clock), MOSI (Master Out Slave In) and MISO (Master In Slave Out) are connected via a voltage level shifter 5V <-> 3.3V with the AC. Direct connection of the signals without a level shifter could damage your ESP32-C3! Note that the CNS connector does not provide a Chip Select signal, this is generated internally on the ESP32-C3. We used to physically route an internally generated signal from IO9 and IO10. The physical pins are currently not needed any more.

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ This code is inspired by [@absalom-muc's MHI-AC-Ctrl](https://github.com/absalom
1515
### Community supported:
1616
* [ESP32-C6](https://github.com/hberntsen/mhi-ac-ctrl-esp32-c3/pull/25)
1717
* Other ESP32-C3 boards (e.g. [ESP32-C3 super mini](https://github.com/xangin/mhi-ac-ctrl-esp32-c3/blob/master/Hardware.md)).
18-
Note that the hardware SPI used in this project needs a GPIO loopback for the chip select. Connect two free GPIOs for that, like IO9 and IO10 in the [schematic](images/MHI-AC-Ctrl_Schematic.png).
1918
* The ESP32 [has been reported to work](https://github.com/hberntsen/mhi-ac-ctrl-esp32-c3/issues/12#issuecomment-2594627493). Make sure you use the right pins, as discussed in [#11](https://github.com/hberntsen/mhi-ac-ctrl-esp32-c3/issues/11).
2019
* The AC units listed at https://github.com/absalom-muc/MHI-AC-Ctrl?tab=readme-ov-file#prerequisites should work. Some older units have to use the `use_long_frame: false` setting.
2120

esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.cpp

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "driver/gptimer.h"
1313
#include "driver/spi_slave.h"
1414
#include "driver/gpio.h"
15+
#include "soc/spi_periph.h"
1516

1617
//#undef LOG_LOCAL_LEVEL
1718
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
@@ -35,7 +36,6 @@ static StackType_t xStack[ STACK_SIZE ];
3536
static TaskHandle_t mhi_poll_task_handle = NULL;
3637

3738
static bool active_mode = false;
38-
static gpio_num_t gpio_cs_out;
3939

4040
namespace mhi_ac {
4141

@@ -78,8 +78,8 @@ static bool IRAM_ATTR gptimer_isr_callback(gptimer_handle_t timer, const gptimer
7878
gptimer_set_raw_count(cs_timer, 0);
7979

8080
// Trigger Chip Select low->high->low
81-
gpio_set_level(gpio_cs_out, 1);
82-
gpio_set_level(gpio_cs_out, 0);
81+
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[RCV_HOST].spics_in, false);
82+
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, spi_periph_signal[RCV_HOST].spics_in, false);
8383

8484
vTaskNotifyGiveFromISR(mhi_poll_task_handle, &xHigherPriorityTaskWoken);
8585

@@ -567,25 +567,9 @@ static void mhi_poll_task(void *arg)
567567
}
568568
}
569569

570-
/**
571-
* Checks whether the GPIO CS loopback works by toggling it a few times.
572-
*/
573-
static bool check_gpio_cs_loopback(gpio_num_t cs_in_pin) {
574-
int on = 0;
575-
for(int i = 0; i < 42; i++) {
576-
gpio_set_level(gpio_cs_out, on);
577-
if(gpio_get_level(cs_in_pin) != on) {
578-
return false;
579-
}
580-
on ^= 1;
581-
}
582-
return true;
583-
}
584-
585-
InitError init(const Config& config) {
570+
void init(const Config& config) {
586571
esp_err_t err;
587572

588-
gpio_cs_out = static_cast<gpio_num_t>(config.cs_out_pin);
589573
spi_state.use_long_frame(config.use_long_frame);
590574

591575
// configuration for the SPI bus
@@ -606,7 +590,7 @@ InitError init(const Config& config) {
606590

607591
// configuration for the SPI slave interface
608592
spi_slave_interface_config_t slvcfg = {
609-
.spics_io_num = config.cs_in_pin,
593+
.spics_io_num = -1,
610594
.flags = SPI_SLAVE_BIT_LSBFIRST,
611595
.queue_size = 1,
612596
.mode = 3, //CPOL=1, CPHA=1
@@ -618,6 +602,8 @@ InitError init(const Config& config) {
618602
err = spi_slave_initialize(RCV_HOST, &buscfg, &slvcfg, SPI_DMA_CH_AUTO); // can't disable DMA. no comms if you do...
619603
ESP_ERROR_CHECK(err);
620604

605+
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[RCV_HOST].spics_in, false);
606+
621607
// Set up timer
622608
gptimer_config_t timer_config = {
623609
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
@@ -660,20 +646,6 @@ io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
660646
gpio_isr_handler_add(static_cast<gpio_num_t>(config.sclk_pin), gpio_isr_handler, NULL);
661647
gpio_intr_enable(static_cast<gpio_num_t>(config.sclk_pin));
662648

663-
io_conf.mode = GPIO_MODE_OUTPUT;
664-
io_conf.pin_bit_mask = (1ULL<<gpio_cs_out);
665-
io_conf.intr_type =GPIO_INTR_DISABLE;
666-
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
667-
gpio_config(&io_conf);
668-
669-
if(!check_gpio_cs_loopback(static_cast<gpio_num_t>(config.cs_in_pin))) {
670-
return InitError::CSLoopbackFail;
671-
}
672-
673-
gpio_set_level(gpio_cs_out, 1);
674-
675649
mhi_poll_task_handle = xTaskCreateStatic(mhi_poll_task, "mhi_task", STACK_SIZE, NULL, 10, xStack, &xTaskBuffer);
676-
677-
return InitError::Ok;
678650
}
679651
} //namespace mhi_ac

esphome/components/MhiAcCtrl/MHI-AC-Ctrl-core.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ struct Config {
3737
uint8_t mosi_pin;
3838
uint8_t miso_pin;
3939
uint8_t sclk_pin;
40-
uint8_t cs_in_pin;
41-
uint8_t cs_out_pin;
4240
};
4341

4442
enum class ACPower {
@@ -72,13 +70,7 @@ enum class ACVanesLR {
7270
Left = 0, LeftCenter = 1, Center = 2, CenterRight = 3, Right = 4, Wide = 5, Spot = 6, Swing = 8
7371
};
7472

75-
enum class InitError {
76-
Ok = 0,
77-
CSLoopbackFail
78-
};
79-
80-
81-
InitError init(const Config& config);
73+
void init(const Config& config);
8274

8375
void active_mode_set(bool state);
8476
bool active_mode_get();

esphome/components/MhiAcCtrl/__init__.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@
1818
CONF_MOSI_PIN = "mosi_pin"
1919
CONF_MISO_PIN = "miso_pin"
2020
CONF_SCLK_PIN = "sclk_pin"
21-
CONF_CS_IN_PIN = "cs_in_pin"
22-
CONF_CS_OUT_PIN = "cs_out_pin"
2321

2422
TYPES = [
2523
CONF_EXTERNAL_TEMPERATURE_SENSOR,
2624
CONF_USE_LONG_FRAME,
2725
CONF_MOSI_PIN,
2826
CONF_MISO_PIN,
2927
CONF_SCLK_PIN,
30-
CONF_CS_IN_PIN,
31-
CONF_CS_OUT_PIN,
3228
]
3329

3430
CONFIG_SCHEMA = cv.Schema(
@@ -39,8 +35,6 @@
3935
cv.Optional(CONF_MOSI_PIN, default="GPIO7"): pins.gpio_input_pin_schema,
4036
cv.Optional(CONF_MISO_PIN, default="GPIO2"): pins.gpio_output_pin_schema,
4137
cv.Optional(CONF_SCLK_PIN, default="GPIO6"): pins.gpio_input_pin_schema,
42-
cv.Optional(CONF_CS_IN_PIN, default="GPIO10"): pins.gpio_input_pin_schema,
43-
cv.Optional(CONF_CS_OUT_PIN, default="GPIO9"): pins.gpio_output_pin_schema,
4438
}
4539
).extend(cv.COMPONENT_SCHEMA)
4640

@@ -51,8 +45,6 @@ async def to_code(config):
5145
("mosi_pin", (await cg.gpio_pin_expression(config[CONF_MOSI_PIN])).get_pin()),
5246
("miso_pin", (await cg.gpio_pin_expression(config[CONF_MISO_PIN])).get_pin()),
5347
("sclk_pin", (await cg.gpio_pin_expression(config[CONF_SCLK_PIN])).get_pin()),
54-
("cs_in_pin", (await cg.gpio_pin_expression(config[CONF_CS_IN_PIN])).get_pin()),
55-
("cs_out_pin", (await cg.gpio_pin_expression(config[CONF_CS_OUT_PIN])).get_pin()),
5648
)
5749

5850
var = cg.new_Pvariable(config[CONF_ID], config_struct)

esphome/components/MhiAcCtrl/mhi_ac_ctrl.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,7 @@ class MhiAcCtrl : public climate::Climate,
246246
if(this->operation_data_visible_timeouts_sensor_) {
247247
this->operation_data_visible_timeouts_sensor_->publish_state(0);
248248
}
249-
mhi_ac::InitError err = mhi_ac::init(this->ac_config_);
250-
switch(err) {
251-
case mhi_ac::InitError::CSLoopbackFail:
252-
this->status_set_error(LOG_STR("CS loopback check failed. Are cs_in_pin and cs_out_pin connected with each other?"));
253-
return;
254-
}
249+
mhi_ac::init(this->ac_config_);
255250

256251
constexpr auto opdatas = &mhi_ac::operation_data_state;
257252
opdatas->set_temperature_.enabled = this->set_temperature_sensor_;

esphome/example.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ MhiAcCtrl:
3636
mosi_pin: GPIO7
3737
miso_pin: GPIO2
3838
sclk_pin: GPIO6
39-
cs_in_pin: GPIO10
40-
cs_out_pin: GPIO9
4139

4240
climate:
4341
- platform: MhiAcCtrl

0 commit comments

Comments
 (0)