mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	| @@ -172,6 +172,19 @@ def add_idf_component( | ||||
|             KEY_COMPONENTS: components, | ||||
|             KEY_SUBMODULES: submodules, | ||||
|         } | ||||
|     else: | ||||
|         component_config = CORE.data[KEY_ESP32][KEY_COMPONENTS][name] | ||||
|         if components is not None: | ||||
|             component_config[KEY_COMPONENTS] = list( | ||||
|                 set(component_config[KEY_COMPONENTS] + components) | ||||
|             ) | ||||
|         if submodules is not None: | ||||
|             if component_config[KEY_SUBMODULES] is None: | ||||
|                 component_config[KEY_SUBMODULES] = submodules | ||||
|             else: | ||||
|                 component_config[KEY_SUBMODULES] = list( | ||||
|                     set(component_config[KEY_SUBMODULES] + submodules) | ||||
|                 ) | ||||
|  | ||||
|  | ||||
| def add_extra_script(stage: str, filename: str, path: str): | ||||
|   | ||||
| @@ -7,8 +7,10 @@ | ||||
|  | ||||
| #include <hardware/clocks.h> | ||||
| #include <hardware/dma.h> | ||||
| #include <hardware/irq.h> | ||||
| #include <hardware/pio.h> | ||||
| #include <pico/stdlib.h> | ||||
| #include <pico/sem.h> | ||||
|  | ||||
| namespace esphome { | ||||
| namespace rp2040_pio_led_strip { | ||||
| @@ -23,6 +25,19 @@ static std::map<Chipset, bool> conf_count_ = { | ||||
|     {CHIPSET_WS2812, false},  {CHIPSET_WS2812B, false}, {CHIPSET_SK6812, false}, | ||||
|     {CHIPSET_SM16703, false}, {CHIPSET_CUSTOM, false}, | ||||
| }; | ||||
| static bool dma_chan_active_[12]; | ||||
| static struct semaphore dma_write_complete_sem_[12]; | ||||
|  | ||||
| // DMA interrupt service routine | ||||
| void RP2040PIOLEDStripLightOutput::dma_write_complete_handler_() { | ||||
|   uint32_t channel = dma_hw->ints0; | ||||
|   for (uint dma_chan = 0; dma_chan < 12; ++dma_chan) { | ||||
|     if (RP2040PIOLEDStripLightOutput::dma_chan_active_[dma_chan] && (channel & (1u << dma_chan))) { | ||||
|       dma_hw->ints0 = (1u << dma_chan);                                               // Clear the interrupt | ||||
|       sem_release(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[dma_chan]);  // Handle the interrupt | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void RP2040PIOLEDStripLightOutput::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up RP2040 LED Strip..."); | ||||
| @@ -57,22 +72,22 @@ void RP2040PIOLEDStripLightOutput::setup() { | ||||
|   // but there are only 4 state machines on each PIO so we can only have 4 strips per PIO | ||||
|   uint offset = 0; | ||||
|  | ||||
|   if (num_instance_[this->pio_ == pio0 ? 0 : 1] > 4) { | ||||
|   if (RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1] > 4) { | ||||
|     ESP_LOGE(TAG, "Too many instances of PIO program"); | ||||
|     this->mark_failed(); | ||||
|     return; | ||||
|   } | ||||
|   // keep track of how many instances of the PIO program are running on each PIO | ||||
|   num_instance_[this->pio_ == pio0 ? 0 : 1]++; | ||||
|   RP2040PIOLEDStripLightOutput::num_instance_[this->pio_ == pio0 ? 0 : 1]++; | ||||
|  | ||||
|   // if there are multiple strips of the same chipset, we can reuse the same PIO program and save space | ||||
|   if (this->conf_count_[this->chipset_]) { | ||||
|     offset = chipset_offsets_[this->chipset_]; | ||||
|     offset = RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_]; | ||||
|   } else { | ||||
|     // Load the assembled program into the PIO and get its location in the PIO's instruction memory and save it | ||||
|     offset = pio_add_program(this->pio_, this->program_); | ||||
|     chipset_offsets_[this->chipset_] = offset; | ||||
|     conf_count_[this->chipset_] = true; | ||||
|     RP2040PIOLEDStripLightOutput::chipset_offsets_[this->chipset_] = offset; | ||||
|     RP2040PIOLEDStripLightOutput::conf_count_[this->chipset_] = true; | ||||
|   } | ||||
|  | ||||
|   // Configure the state machine's PIO, and start it | ||||
| @@ -93,6 +108,9 @@ void RP2040PIOLEDStripLightOutput::setup() { | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   // Mark the DMA channel as active | ||||
|   RP2040PIOLEDStripLightOutput::dma_chan_active_[this->dma_chan_] = true; | ||||
|  | ||||
|   this->dma_config_ = dma_channel_get_default_config(this->dma_chan_); | ||||
|   channel_config_set_transfer_data_size( | ||||
|       &this->dma_config_, | ||||
| @@ -109,6 +127,13 @@ void RP2040PIOLEDStripLightOutput::setup() { | ||||
|                         false                                            // don't start yet | ||||
|   ); | ||||
|  | ||||
|   // Initialize the semaphore for this DMA channel | ||||
|   sem_init(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_], 1, 1); | ||||
|  | ||||
|   irq_set_exclusive_handler(DMA_IRQ_0, dma_write_complete_handler_);  // after DMA all data, raise an interrupt | ||||
|   dma_channel_set_irq0_enabled(this->dma_chan_, true);                // map DMA channel to interrupt | ||||
|   irq_set_enabled(DMA_IRQ_0, true);                                   // enable interrupt | ||||
|  | ||||
|   this->init_(this->pio_, this->sm_, offset, this->pin_, this->max_refresh_rate_); | ||||
| } | ||||
|  | ||||
| @@ -126,6 +151,7 @@ void RP2040PIOLEDStripLightOutput::write_state(light::LightState *state) { | ||||
|   } | ||||
|  | ||||
|   // the bits are already in the correct order for the pio program so we can just copy the buffer using DMA | ||||
|   sem_acquire_blocking(&RP2040PIOLEDStripLightOutput::dma_write_complete_sem_[this->dma_chan_]); | ||||
|   dma_channel_transfer_from_buffer_now(this->dma_chan_, this->buf_, this->get_buffer_size_()); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include <hardware/pio.h> | ||||
| #include <hardware/structs/pio.h> | ||||
| #include <pico/stdio.h> | ||||
| #include <pico/sem.h> | ||||
| #include <map> | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -95,6 +96,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { | ||||
|  | ||||
|   size_t get_buffer_size_() const { return this->num_leds_ * (3 + this->is_rgbw_); } | ||||
|  | ||||
|   static void dma_write_complete_handler_(); | ||||
|  | ||||
|   uint8_t *buf_{nullptr}; | ||||
|   uint8_t *effect_data_{nullptr}; | ||||
|  | ||||
| @@ -120,6 +123,8 @@ class RP2040PIOLEDStripLightOutput : public light::AddressableLight { | ||||
|   inline static int num_instance_[2]; | ||||
|   inline static std::map<Chipset, bool> conf_count_; | ||||
|   inline static std::map<Chipset, int> chipset_offsets_; | ||||
|   inline static bool dma_chan_active_[12]; | ||||
|   inline static struct semaphore dma_write_complete_sem_[12]; | ||||
| }; | ||||
|  | ||||
| }  // namespace rp2040_pio_led_strip | ||||
|   | ||||
| @@ -32,7 +32,7 @@ void Rtttl::play(std::string rtttl) { | ||||
|   if (this->state_ != State::STATE_STOPPED && this->state_ != State::STATE_STOPPING) { | ||||
|     int pos = this->rtttl_.find(':'); | ||||
|     auto name = this->rtttl_.substr(0, pos); | ||||
|     ESP_LOGW(TAG, "RTTL Component is already playing: %s", name.c_str()); | ||||
|     ESP_LOGW(TAG, "RTTTL Component is already playing: %s", name.c_str()); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
| @@ -122,6 +122,7 @@ void Rtttl::stop() { | ||||
| #ifdef USE_OUTPUT | ||||
|   if (this->output_ != nullptr) { | ||||
|     this->output_->set_level(0.0); | ||||
|     this->set_state_(STATE_STOPPED); | ||||
|   } | ||||
| #endif | ||||
| #ifdef USE_SPEAKER | ||||
| @@ -129,10 +130,10 @@ void Rtttl::stop() { | ||||
|     if (this->speaker_->is_running()) { | ||||
|       this->speaker_->stop(); | ||||
|     } | ||||
|     this->set_state_(STATE_STOPPING); | ||||
|   } | ||||
| #endif | ||||
|   this->note_duration_ = 0; | ||||
|   this->set_state_(STATE_STOPPING); | ||||
| } | ||||
|  | ||||
| void Rtttl::loop() { | ||||
| @@ -342,6 +343,7 @@ void Rtttl::finish_() { | ||||
| #ifdef USE_OUTPUT | ||||
|   if (this->output_ != nullptr) { | ||||
|     this->output_->set_level(0.0); | ||||
|     this->set_state_(State::STATE_STOPPED); | ||||
|   } | ||||
| #endif | ||||
| #ifdef USE_SPEAKER | ||||
| @@ -354,9 +356,9 @@ void Rtttl::finish_() { | ||||
|     this->speaker_->play((uint8_t *) (&sample), 8); | ||||
|  | ||||
|     this->speaker_->finish(); | ||||
|     this->set_state_(State::STATE_STOPPING); | ||||
|   } | ||||
| #endif | ||||
|   this->set_state_(State::STATE_STOPPING); | ||||
|   this->note_duration_ = 0; | ||||
|   this->on_finished_playback_callback_.call(); | ||||
|   ESP_LOGD(TAG, "Playback finished"); | ||||
|   | ||||
| @@ -480,7 +480,7 @@ void HOT WaveshareEPaperTypeA::display() { | ||||
|   this->start_data_(); | ||||
|   switch (this->model_) { | ||||
|     case TTGO_EPAPER_2_13_IN_B1: {  // block needed because of variable initializations | ||||
|       int16_t wb = ((this->get_width_internal()) >> 3); | ||||
|       int16_t wb = ((this->get_width_controller()) >> 3); | ||||
|       for (int i = 0; i < this->get_height_internal(); i++) { | ||||
|         for (int j = 0; j < wb; j++) { | ||||
|           int idx = j + (this->get_height_internal() - 1 - i) * wb; | ||||
| @@ -766,7 +766,7 @@ void WaveshareEPaper2P7InV2::initialize() { | ||||
|   // XRAM_START_AND_END_POSITION | ||||
|   this->command(0x44); | ||||
|   this->data(0x00); | ||||
|   this->data(((get_width_internal() - 1) >> 3) & 0xFF); | ||||
|   this->data(((this->get_width_controller() - 1) >> 3) & 0xFF); | ||||
|   // YRAM_START_AND_END_POSITION | ||||
|   this->command(0x45); | ||||
|   this->data(0x00); | ||||
| @@ -928,8 +928,8 @@ void HOT WaveshareEPaper2P7InB::display() { | ||||
|  | ||||
|   // TCON_RESOLUTION | ||||
|   this->command(0x61); | ||||
|   this->data(this->get_width_internal() >> 8); | ||||
|   this->data(this->get_width_internal() & 0xff);  // 176 | ||||
|   this->data(this->get_width_controller() >> 8); | ||||
|   this->data(this->get_width_controller() & 0xff);  // 176 | ||||
|   this->data(this->get_height_internal() >> 8); | ||||
|   this->data(this->get_height_internal() & 0xff);  // 264 | ||||
|  | ||||
| @@ -994,7 +994,7 @@ void WaveshareEPaper2P7InBV2::initialize() { | ||||
|   // self.SetWindows(0, 0, self.width-1, self.height-1) | ||||
|   // SetWindows(self, Xstart, Ystart, Xend, Yend): | ||||
|  | ||||
|   uint32_t xend = this->get_width_internal() - 1; | ||||
|   uint32_t xend = this->get_width_controller() - 1; | ||||
|   uint32_t yend = this->get_height_internal() - 1; | ||||
|   this->command(0x44); | ||||
|   this->data(0x00); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| """Constants used by esphome.""" | ||||
|  | ||||
| __version__ = "2024.8.0b3" | ||||
| __version__ = "2024.8.0b4" | ||||
|  | ||||
| ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" | ||||
| VALID_SUBSTITUTIONS_CHARACTERS = ( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user