diff options
author | Sam Guyer <sam.guyer@gmail.com> | 2020-12-30 21:38:39 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-30 21:38:39 +0300 |
commit | 41652f2045ec9df7d5faf5b35efac280e13837f5 (patch) | |
tree | bf30a4b44c3ba0608b6690a1c78659a2f4bf8c9e | |
parent | 82e2c4a5f2914632ab7d20f0f88c611a83974eb7 (diff) | |
parent | 51d2891cff0264dcb17c05939b09a27a47f87447 (diff) |
Merge pull request #1163 from samguyer/master
Fix for a bug that was limiting parallelism
-rw-r--r-- | src/platforms/esp/32/clockless_rmt_esp32.cpp | 35 | ||||
-rw-r--r-- | src/platforms/esp/32/clockless_rmt_esp32.h | 61 |
2 files changed, 40 insertions, 56 deletions
diff --git a/src/platforms/esp/32/clockless_rmt_esp32.cpp b/src/platforms/esp/32/clockless_rmt_esp32.cpp index 658f6daa..ca8aec47 100644 --- a/src/platforms/esp/32/clockless_rmt_esp32.cpp +++ b/src/platforms/esp/32/clockless_rmt_esp32.cpp @@ -34,7 +34,12 @@ CMinWait<50> gWait; static bool gInitialized = false; -ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3) +// -- Stored values for FASTLED_RMT_MAX_CHANNELS and FASTLED_RMT_MEM_BLOCKS +int ESP32RMTController::gMaxChannel; +int ESP32RMTController::gMemBlocks; + + +ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3, int maxChannel, int memBlocks) : mPixelData(0), mSize(0), mCur(0), @@ -43,6 +48,10 @@ ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3) mBufferSize(0), mCurPulse(0) { + // -- Store the max channel and mem blocks parameters + gMaxChannel = maxChannel; + gMemBlocks = memBlocks; + // -- Precompute rmt items corresponding to a zero bit and a one bit // according to the timing values given in the template instantiation // T1H @@ -75,11 +84,11 @@ ESP32RMTController::ESP32RMTController(int DATA_PIN, int T1, int T2, int T3) // -- Get or create the buffer for the pixel data // We can't allocate it ahead of time because we don't have // the PixelController object until show is called. -uint32_t * ESP32RMTController::getPixelBuffer(int size_in_bytes) +uint8_t * ESP32RMTController::getPixelBuffer(int size_in_bytes) { if (mPixelData == 0) { - mSize = ((size_in_bytes-1) / sizeof(uint32_t)) + 1; - mPixelData = (uint32_t *) calloc( mSize, sizeof(uint32_t)); + mSize = size_in_bytes; + mPixelData = (uint8_t *) malloc(mSize); } return mPixelData; } @@ -90,15 +99,15 @@ void ESP32RMTController::init(gpio_num_t pin) { if (gInitialized) return; - for (int i = 0; i < FASTLED_RMT_MAX_CHANNELS; i++) { + for (int i = 0; i < gMaxChannel; i += gMemBlocks) { gOnChannel[i] = NULL; // -- RMT configuration for transmission rmt_config_t rmt_tx; rmt_tx.channel = rmt_channel_t(i); rmt_tx.rmt_mode = RMT_MODE_TX; - rmt_tx.gpio_num = pin; // The particular pin will be assigned later - rmt_tx.mem_block_num = FASTLED_RMT_MEM_BLOCKS; + rmt_tx.gpio_num = pin; + rmt_tx.mem_block_num = gMemBlocks; rmt_tx.clk_div = DIVIDER; rmt_tx.tx_config.loop_en = false; rmt_tx.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW; @@ -167,11 +176,11 @@ void IRAM_ATTR ESP32RMTController::showPixels() // -- First, fill all the available channels int channel = 0; - while (channel < FASTLED_RMT_MAX_CHANNELS && gNext < gNumControllers) { + while (channel < gMaxChannel && gNext < gNumControllers) { ESP32RMTController::startNext(channel); // -- Important: when we use more than one memory block, we need to // skip the channels that would otherwise overlap in memory. - channel += FASTLED_RMT_MEM_BLOCKS; + channel += gMemBlocks; } // -- Wait here while the data is sent. The interrupt handler @@ -318,7 +327,7 @@ void IRAM_ATTR ESP32RMTController::interruptHandler(void *arg) uint8_t channel; bool stuff_to_do = false; - for (channel = 0; channel < FASTLED_RMT_MAX_CHANNELS; channel++) { + for (channel = 0; channel < gMaxChannel; channel++) { int tx_done_bit = channel * 3; int tx_next_bit = channel + 24; @@ -376,16 +385,16 @@ void IRAM_ATTR ESP32RMTController::fillNext(bool check_time) // -- Use locals for speed volatile register uint32_t * pItem = mRMT_mem_ptr; - for (register int i = 0; i < PULSES_PER_FILL/32; i++) { + for (register int i = 0; i < PULSES_PER_FILL/8; i++) { if (mCur < mSize) { // -- Get the next four bytes of pixel data - register uint32_t pixeldata = mPixelData[mCur]; + register uint32_t pixeldata = mPixelData[mCur] << 24; mCur++; // Shift bits out, MSB first, setting RMTMEM.chan[n].data32[x] to the // rmt_item32_t value corresponding to the buffered bit value - for (register uint32_t j = 0; j < 32; j++) { + for (register uint32_t j = 0; j < 8; j++) { *pItem++ = (pixeldata & 0x80000000L) ? one_val : zero_val; // Replaces: RMTMEM.chan[mRMT_channel].data32[mCurPulse].val = val; diff --git a/src/platforms/esp/32/clockless_rmt_esp32.h b/src/platforms/esp/32/clockless_rmt_esp32.h index 2e723179..3a10f9ca 100644 --- a/src/platforms/esp/32/clockless_rmt_esp32.h +++ b/src/platforms/esp/32/clockless_rmt_esp32.h @@ -183,10 +183,9 @@ __attribute__ ((always_inline)) inline static uint32_t __clock_cycles() { #define FASTLED_RMT_MAX_CONTROLLERS 32 #endif -// -- Number of RMT channels to use (up to 8, but 4 by default) -// Redefine this value to 1 to force serial output +// -- Max RMT channel (default to 8) #ifndef FASTLED_RMT_MAX_CHANNELS -#define FASTLED_RMT_MAX_CHANNELS (8/FASTLED_RMT_MEM_BLOCKS) +#define FASTLED_RMT_MAX_CHANNELS 8 #endif class ESP32RMTController @@ -210,7 +209,7 @@ private: uint32_t mLastFill; // -- Pixel data - uint32_t * mPixelData; + uint8_t * mPixelData; int mSize; int mCur; @@ -225,18 +224,23 @@ private: uint16_t mBufferSize; // bytes int mCurPulse; + // -- These values need to be real variables, so we can access them + // in the cpp file + static int gMaxChannel; + static int gMemBlocks; + public: // -- Constructor // Mainly just stores the template parameters from the LEDController as // member variables. - ESP32RMTController(int DATA_PIN, int T1, int T2, int T3); + ESP32RMTController(int DATA_PIN, int T1, int T2, int T3, int maxChannel, int memBlocks); // -- Get max cycles per fill uint32_t IRAM_ATTR getMaxCyclesPerFill() const { return mMaxCyclesPerFill; } // -- Get or create the pixel data buffer - uint32_t * getPixelBuffer(int size_in_bytes); + uint8_t * getPixelBuffer(int size_in_bytes); // -- Initialize RMT subsystem // This only needs to be done once. The particular pin is not important, @@ -308,12 +312,11 @@ private: public: ClocklessController() - : mRMTController(DATA_PIN, T1, T2, T3) + : mRMTController(DATA_PIN, T1, T2, T3, FASTLED_RMT_MAX_CHANNELS, FASTLED_RMT_MEM_BLOCKS) {} void init() { - // mRMTController = new ESP32RMTController(DATA_PIN, T1, T2, T3); } virtual uint16_t getMaxRefreshRate() const { return 400; } @@ -329,43 +332,15 @@ protected: { // -- Make sure the buffer is allocated int size_in_bytes = pixels.size() * 3; - uint32_t * pData = mRMTController.getPixelBuffer(size_in_bytes); + uint8_t * pData = mRMTController.getPixelBuffer(size_in_bytes); - // -- Read out the pixel data using the pixel controller methods that - // perform the scaling and adjustments - int count = 0; - int which = 0; + // -- This might be faster while (pixels.has(1)) { - // -- Get the next four bytes of data - uint8_t four[4] = {0,0,0,0}; - for (int i = 0; i < 4; i++) { - switch (which) { - case 0: - four[i] = pixels.loadAndScale0(); - break; - case 1: - four[i] = pixels.loadAndScale1(); - break; - case 2: - four[i] = pixels.loadAndScale2(); - pixels.advanceData(); - pixels.stepDithering(); - break; - } - // -- Move to the next color - which++; - if (which > 2) which = 0; - - // -- Stop if there's no more data - if ( ! pixels.has(1)) break; - } - - // -- Pack the four bytes into a 32-bit value with the right bit order - uint8_t a = four[0]; - uint8_t b = four[1]; - uint8_t c = four[2]; - uint8_t d = four[3]; - pData[count++] = a << 24 | b << 16 | c << 8 | d; + *pData++ = pixels.loadAndScale0(); + *pData++ = pixels.loadAndScale1(); + *pData++ = pixels.loadAndScale2(); + pixels.advanceData(); + pixels.stepDithering(); } } |