6 #include <driver/gpio.h> 9 namespace remote_transmitter {
11 static const char *
const TAG =
"remote_transmitter";
14 ESP_LOGCONFIG(TAG,
"Setting up Remote Transmitter...");
20 ESP_LOGCONFIG(TAG,
"Remote Transmitter:");
21 #if ESP_IDF_VERSION_MAJOR >= 5 22 ESP_LOGCONFIG(TAG,
" Clock resolution: %" PRIu32
" hz", this->clock_resolution_);
23 ESP_LOGCONFIG(TAG,
" RMT symbols: %" PRIu32, this->rmt_symbols_);
25 ESP_LOGCONFIG(TAG,
" Channel: %d", this->
channel_);
26 ESP_LOGCONFIG(TAG,
" RMT memory blocks: %d", this->mem_block_num_);
27 ESP_LOGCONFIG(TAG,
" Clock divider: %u", this->clock_divider_);
29 LOG_PIN(
" Pin: ", this->
pin_);
35 if (this->is_failed()) {
36 ESP_LOGE(TAG,
"Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->
error_code_),
41 #if ESP_IDF_VERSION_MAJOR >= 5 43 rmt_symbol_word_t symbol = {
49 rmt_transmit_config_t config;
50 memset(&config, 0,
sizeof(config));
51 config.loop_count = 0;
52 config.flags.eot_level = value;
53 esp_err_t error = rmt_transmit(this->
channel_, this->
encoder_, &symbol,
sizeof(symbol), &config);
54 if (error != ESP_OK) {
55 ESP_LOGW(TAG,
"rmt_transmit failed: %s", esp_err_to_name(error));
56 this->status_set_warning();
58 error = rmt_tx_wait_all_done(this->
channel_, -1);
59 if (error != ESP_OK) {
60 ESP_LOGW(TAG,
"rmt_tx_wait_all_done failed: %s", esp_err_to_name(error));
61 this->status_set_warning();
67 #if ESP_IDF_VERSION_MAJOR >= 5 72 rmt_tx_channel_config_t channel;
73 memset(&channel, 0,
sizeof(channel));
74 channel.clk_src = RMT_CLK_SRC_DEFAULT;
75 channel.resolution_hz = this->clock_resolution_;
76 channel.gpio_num = gpio_num_t(this->
pin_->
get_pin());
77 channel.mem_block_symbols = this->rmt_symbols_;
78 channel.trans_queue_depth = 1;
79 channel.flags.io_loop_back = open_drain;
80 channel.flags.io_od_mode = open_drain;
81 channel.flags.invert_out = 0;
83 channel.intr_priority = 0;
84 error = rmt_new_tx_channel(&channel, &this->
channel_);
85 if (error != ESP_OK) {
87 if (error == ESP_ERR_NOT_FOUND) {
101 rmt_copy_encoder_config_t encoder;
102 memset(&encoder, 0,
sizeof(encoder));
103 error = rmt_new_copy_encoder(&encoder, &this->
encoder_);
104 if (error != ESP_OK) {
112 if (error != ESP_OK) {
123 error = rmt_apply_carrier(this->
channel_,
nullptr);
125 rmt_carrier_config_t carrier;
126 memset(&carrier, 0,
sizeof(carrier));
129 carrier.flags.polarity_active_low = this->
inverted_;
130 carrier.flags.always_on = 1;
131 error = rmt_apply_carrier(this->
channel_, &carrier);
133 if (error != ESP_OK) {
143 c.rmt_mode = RMT_MODE_TX;
145 c.tx_config.loop_en =
false;
148 c.tx_config.carrier_en =
false;
150 c.tx_config.carrier_en =
true;
155 c.tx_config.idle_output_en =
true;
157 c.tx_config.carrier_level = RMT_CARRIER_LEVEL_HIGH;
158 c.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
160 c.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
161 c.tx_config.idle_level = RMT_IDLE_LEVEL_HIGH;
164 esp_err_t error = rmt_config(&c);
165 if (error != ESP_OK) {
173 error = rmt_driver_install(this->
channel_, 0, 0);
174 if (error != ESP_OK) {
176 if (error == ESP_ERR_INVALID_STATE) {
190 if (this->is_failed())
201 #if ESP_IDF_VERSION_MAJOR >= 5 202 rmt_symbol_word_t rmt_item;
204 rmt_item32_t rmt_item;
208 bool level =
val >= 0;
211 val = this->from_microseconds_(static_cast<uint32_t>(
val));
214 int32_t item = std::min(
val, int32_t(32767));
217 if (rmt_i % 2 == 0) {
218 rmt_item.level0 =
static_cast<uint32_t
>(level ^ this->
inverted_);
219 rmt_item.duration0 =
static_cast<uint32_t
>(item);
221 rmt_item.level1 =
static_cast<uint32_t
>(level ^ this->
inverted_);
222 rmt_item.duration1 =
static_cast<uint32_t
>(item);
229 if (rmt_i % 2 == 1) {
231 rmt_item.duration1 = 0;
236 ESP_LOGE(TAG,
"Empty data");
240 #if ESP_IDF_VERSION_MAJOR >= 5 241 for (uint32_t i = 0; i < send_times; i++) {
242 rmt_transmit_config_t config;
243 memset(&config, 0,
sizeof(config));
244 config.loop_count = 0;
247 this->
rmt_temp_.size() *
sizeof(rmt_symbol_word_t), &config);
248 if (error != ESP_OK) {
249 ESP_LOGW(TAG,
"rmt_transmit failed: %s", esp_err_to_name(error));
250 this->status_set_warning();
252 this->status_clear_warning();
254 error = rmt_tx_wait_all_done(this->
channel_, -1);
255 if (error != ESP_OK) {
256 ESP_LOGW(TAG,
"rmt_tx_wait_all_done failed: %s", esp_err_to_name(error));
257 this->status_set_warning();
259 if (i + 1 < send_times)
263 for (uint32_t i = 0; i < send_times; i++) {
265 if (error != ESP_OK) {
266 ESP_LOGW(TAG,
"rmt_write_items failed: %s", esp_err_to_name(error));
267 this->status_set_warning();
269 this->status_clear_warning();
271 if (i + 1 < send_times)
rmt_channel_handle_t channel_
RemoteTransmitData temp_
Use same vector for all transmits, avoids many allocations.
Trigger * transmit_trigger_
uint32_t get_carrier_frequency() const
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
virtual gpio::Flags get_flags() const =0
Retrieve GPIO pin flags.
virtual uint8_t get_pin() const =0
void dump_config() override
std::string str_sprintf(const char *fmt,...)
void send_internal(uint32_t send_times, uint32_t send_wait) override
uint32_t current_carrier_frequency_
Trigger * complete_trigger_
std::string error_string_
rmt_encoder_handle_t encoder_
uint8_t carrier_duty_percent_
Implementation of SPI Controller mode.
void IRAM_ATTR HOT delayMicroseconds(uint32_t us)
void digital_write(bool value)
const RawTimings & get_data() const
std::vector< rmt_symbol_word_t > rmt_temp_
virtual bool is_inverted() const =0