diff --git a/components/FastLED-idf/hal/esp32-hal-rmt.c b/components/FastLED-idf/hal/esp32-hal-rmt.c deleted file mode 100644 index 2a36a5e..0000000 --- a/components/FastLED-idf/hal/esp32-hal-rmt.c +++ /dev/null @@ -1,836 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "freertos/FreeRTOS.h" -#include "freertos/event_groups.h" -#include "freertos/semphr.h" - -#include "esp32-hal.h" -#include "esp8266-compat.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_reg.h" - -#include "esp32-hal-rmt.h" -#include "driver/periph_ctrl.h" - -#include "soc/rmt_struct.h" -#include "esp_intr_alloc.h" - -/** - * Internal macros - */ -#define MAX_CHANNELS 8 -#define MAX_DATA_PER_CHANNEL 64 -#define MAX_DATA_PER_ITTERATION 62 -#define _ABS(a) (a>0?a:-a) -#define _LIMIT(a,b) (a>b?b:a) -#define __INT_TX_END (1) -#define __INT_RX_END (2) -#define __INT_ERROR (4) -#define __INT_THR_EVNT (1<<24) - -#define _INT_TX_END(channel) (__INT_TX_END<<(channel*3)) -#define _INT_RX_END(channel) (__INT_RX_END<<(channel*3)) -#define _INT_ERROR(channel) (__INT_ERROR<<(channel*3)) -#define _INT_THR_EVNT(channel) ((__INT_THR_EVNT)<<(channel)) - -#if CONFIG_DISABLE_HAL_LOCKS -# define RMT_MUTEX_LOCK(channel) -# define RMT_MUTEX_UNLOCK(channel) -#else -# define RMT_MUTEX_LOCK(channel) do {} while (xSemaphoreTake(g_rmt_objlocks[channel], portMAX_DELAY) != pdPASS) -# define RMT_MUTEX_UNLOCK(channel) xSemaphoreGive(g_rmt_objlocks[channel]) -#endif /* CONFIG_DISABLE_HAL_LOCKS */ - -#define _RMT_INTERNAL_DEBUG -#ifdef _RMT_INTERNAL_DEBUG -# define DEBUG_INTERRUPT_START(pin) digitalWrite(pin, 1); -# define DEBUG_INTERRUPT_END(pin) digitalWrite(pin, 0); -#else -# define DEBUG_INTERRUPT_START(pin) -# define DEBUG_INTERRUPT_END(pin) -#endif /* _RMT_INTERNAL_DEBUG */ - -/** - * Typedefs for internal stuctures, enums - */ -typedef enum { - E_NO_INTR = 0, - E_TX_INTR = 1, - E_TXTHR_INTR = 2, - E_RX_INTR = 4, -} intr_mode_t; - -typedef enum { - E_INACTIVE = 0, - E_FIRST_HALF = 1, - E_LAST_DATA = 2, - E_END_TRANS = 4, - E_SET_CONTI = 8, -} transaction_state_t; - -struct rmt_obj_s -{ - bool allocated; - EventGroupHandle_t events; - int pin; - int channel; - bool tx_not_rx; - int buffers; - int data_size; - uint32_t* data_ptr; - intr_mode_t intr_mode; - transaction_state_t tx_state; - rmt_rx_data_cb_t cb; - bool data_alloc; -}; - -/** - * Internal variables for channel descriptors - */ -static xSemaphoreHandle g_rmt_objlocks[MAX_CHANNELS] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static rmt_obj_t g_rmt_objects[MAX_CHANNELS] = { - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, - { false, NULL, 0, 0, 0, 0, 0, NULL, E_NO_INTR, E_INACTIVE, NULL, false}, -}; - -/** - * Internal variables for driver data - */ -static intr_handle_t intr_handle; - -static bool periph_enabled = false; - -static xSemaphoreHandle g_rmt_block_lock = NULL; - -/** - * Internal method (private) declarations - */ -static void _initPin(int pin, int channel, bool tx_not_rx); - -static bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous); - -static void IRAM_ATTR _rmt_isr(void* arg); - -static rmt_obj_t* _rmtAllocate(int pin, int from, int size); - -static void _initPin(int pin, int channel, bool tx_not_rx); - -static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel); - -static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch); - -static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch); - - -/** - * Public method definitions - */ -bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high) -{ - if (!rmt || low > 0xFFFF || high > 0xFFFF) { - return false; - } - size_t channel = rmt->channel; - - RMT_MUTEX_LOCK(channel); - - RMT.carrier_duty_ch[channel].low = low; - RMT.carrier_duty_ch[channel].high = high; - RMT.conf_ch[channel].conf0.carrier_en = carrier_en; - RMT.conf_ch[channel].conf0.carrier_out_lv = carrier_level; - - RMT_MUTEX_UNLOCK(channel); - - return true; - -} - -bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level) -{ - if (!rmt || filter_level > 0xFF) { - return false; - } - size_t channel = rmt->channel; - - RMT_MUTEX_LOCK(channel); - - RMT.conf_ch[channel].conf1.rx_filter_thres = filter_level; - RMT.conf_ch[channel].conf1.rx_filter_en = filter_en; - - RMT_MUTEX_UNLOCK(channel); - - return true; - -} - -bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value) -{ - if (!rmt || value > 0xFFFF) { - return false; - } - size_t channel = rmt->channel; - - RMT_MUTEX_LOCK(channel); - RMT.conf_ch[channel].conf0.idle_thres = value; - RMT_MUTEX_UNLOCK(channel); - - return true; -} - - -bool rmtDeinit(rmt_obj_t *rmt) -{ - if (!rmt) { - return false; - } - - // sanity check - if (rmt != &(g_rmt_objects[rmt->channel])) { - return false; - } - - size_t from = rmt->channel; - size_t to = rmt->buffers + rmt->channel; - size_t i; - -#if !CONFIG_DISABLE_HAL_LOCKS - if(g_rmt_objlocks[from] != NULL) { - vSemaphoreDelete(g_rmt_objlocks[from]); - } -#endif - - if (g_rmt_objects[from].data_alloc) { - free(g_rmt_objects[from].data_ptr); - } - - for (i = from; i < to; i++) { - g_rmt_objects[i].allocated = false; - } - - g_rmt_objects[from].channel = 0; - g_rmt_objects[from].buffers = 0; - - return true; -} - -bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size) -{ - if (!rmt) { - return false; - } - - int channel = rmt->channel; - int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers; - - if (size > allocated_size) { - return false; - } - return _rmtSendOnce(rmt, data, size, true); -} - -bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size) -{ - if (!rmt) { - return false; - } - - int channel = rmt->channel; - int allocated_size = MAX_DATA_PER_CHANNEL * rmt->buffers; - - if (size > allocated_size) { - - int half_tx_nr = MAX_DATA_PER_ITTERATION/2; - RMT_MUTEX_LOCK(channel); - // setup interrupt handler if not yet installed for half and full tx - if (!intr_handle) { - esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle); - } - - rmt->data_size = size - MAX_DATA_PER_ITTERATION; - rmt->data_ptr = ((uint32_t*)data) + MAX_DATA_PER_ITTERATION; - rmt->intr_mode = E_TX_INTR | E_TXTHR_INTR; - rmt->tx_state = E_SET_CONTI | E_FIRST_HALF; - - // init the tx limit for interruption - RMT.tx_lim_ch[channel].limit = half_tx_nr+2; - // reset memory pointer - RMT.conf_ch[channel].conf1.apb_mem_rst = 1; - RMT.conf_ch[channel].conf1.apb_mem_rst = 0; - RMT.conf_ch[channel].conf1.mem_rd_rst = 1; - RMT.conf_ch[channel].conf1.mem_rd_rst = 0; - RMT.conf_ch[channel].conf1.mem_wr_rst = 1; - RMT.conf_ch[channel].conf1.mem_wr_rst = 0; - - // set the tx end mark - RMTMEM.chan[channel].data32[MAX_DATA_PER_ITTERATION].val = 0; - - // clear and enable both Tx completed and half tx event - RMT.int_clr.val = _INT_TX_END(channel); - RMT.int_clr.val = _INT_THR_EVNT(channel); - RMT.int_clr.val = _INT_ERROR(channel); - - RMT.int_ena.val |= _INT_TX_END(channel); - RMT.int_ena.val |= _INT_THR_EVNT(channel); - RMT.int_ena.val |= _INT_ERROR(channel); - - RMT_MUTEX_UNLOCK(channel); - - // start the transation - return _rmtSendOnce(rmt, data, MAX_DATA_PER_ITTERATION, false); - } else { - // use one-go mode if data fits one buffer - return _rmtSendOnce(rmt, data, size, false); - } -} - -bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size) -{ - if (!rmt) { - return false; - } - int channel = rmt->channel; - - if (g_rmt_objects[channel].buffers < size/MAX_DATA_PER_CHANNEL) { - return false; - } - - size_t i; - volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val); - for (i=0; ichannel; - - RMT.int_clr.val = _INT_ERROR(channel); - RMT.int_ena.val |= _INT_ERROR(channel); - - RMT.conf_ch[channel].conf1.mem_owner = 1; - RMT.conf_ch[channel].conf1.mem_wr_rst = 1; - RMT.conf_ch[channel].conf1.rx_en = 1; - - return true; -} - -bool rmtReceiveCompleted(rmt_obj_t* rmt) -{ - if (!rmt) { - return false; - } - int channel = rmt->channel; - - if (RMT.int_raw.val&_INT_RX_END(channel)) { - // RX end flag - RMT.int_clr.val = _INT_RX_END(channel); - return true; - } else { - return false; - } -} - -bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb) -{ - if (!rmt && !cb) { - return false; - } - int channel = rmt->channel; - - RMT_MUTEX_LOCK(channel); - rmt->intr_mode = E_RX_INTR; - rmt->tx_state = E_FIRST_HALF; - rmt->cb = cb; - // allocate internally two buffers which would alternate - if (!rmt->data_alloc) { - rmt->data_ptr = (uint32_t*)malloc(2*MAX_DATA_PER_CHANNEL*(rmt->buffers)*sizeof(uint32_t)); - rmt->data_size = MAX_DATA_PER_CHANNEL*rmt->buffers; - rmt->data_alloc = true; - } - - RMT.conf_ch[channel].conf1.mem_owner = 1; - - RMT.int_clr.val = _INT_RX_END(channel); - RMT.int_clr.val = _INT_ERROR(channel); - - RMT.int_ena.val |= _INT_RX_END(channel); - RMT.int_ena.val |= _INT_ERROR(channel); - - RMT.conf_ch[channel].conf1.mem_wr_rst = 1; - - RMT.conf_ch[channel].conf1.rx_en = 1; - RMT_MUTEX_UNLOCK(channel); - - return true; -} - -bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout) -{ - if (!rmt) { - return false; - } - int channel = rmt->channel; - - if (g_rmt_objects[channel].buffers < size/MAX_DATA_PER_CHANNEL) { - return false; - } - - if (eventFlag) { - xEventGroupClearBits(eventFlag, RMT_FLAGS_ALL); - rmt->events = eventFlag; - } - - if (data && size>0) { - rmt->data_ptr = (uint32_t*)data; - rmt->data_size = size; - } - - RMT_MUTEX_LOCK(channel); - rmt->intr_mode = E_RX_INTR; - - RMT.conf_ch[channel].conf1.mem_owner = 1; - - RMT.int_clr.val = _INT_RX_END(channel); - RMT.int_clr.val = _INT_ERROR(channel); - - RMT.int_ena.val |= _INT_RX_END(channel); - RMT.int_ena.val |= _INT_ERROR(channel); - - RMT.conf_ch[channel].conf1.mem_wr_rst = 1; - - RMT.conf_ch[channel].conf1.rx_en = 1; - RMT_MUTEX_UNLOCK(channel); - - // wait for data if requested so - if (waitForData && eventFlag) { - uint32_t flags = xEventGroupWaitBits(eventFlag, RMT_FLAGS_ALL, - pdTRUE /* clear on exit */, pdFALSE /* wait for all bits */, timeout); - if (flags & RMT_FLAG_ERROR) { - return false; - } - } - - return true; -} - -float rmtSetTick(rmt_obj_t* rmt, float tick) -{ - if (!rmt) { - return false; - } - /* - divider field span from 1 (smallest), 2, 3, ... , 0xFF, 0x00 (highest) - * rmt tick from 1/80M -> 12.5ns (1x) div_cnt = 0x01 - 3.2 us (256x) div_cnt = 0x00 - * rmt tick for 1 MHz -> 1us (1x) div_cnt = 0x01 - 256us (256x) div_cnt = 0x00 - */ - int apb_div = _LIMIT(tick/12.5, 256); - int ref_div = _LIMIT(tick/1000, 256); - - float apb_tick = 12.5 * apb_div; - float ref_tick = 1000.0 * ref_div; - - size_t channel = rmt->channel; - - if (_ABS(apb_tick - tick) < _ABS(ref_tick - tick)) { - RMT.conf_ch[channel].conf0.div_cnt = apb_div & 0xFF; - RMT.conf_ch[channel].conf1.ref_always_on = 1; - return apb_tick; - } else { - RMT.conf_ch[channel].conf0.div_cnt = ref_div & 0xFF; - RMT.conf_ch[channel].conf1.ref_always_on = 0; - return ref_tick; - } -} - -rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize) -{ - int buffers = memsize; - rmt_obj_t* rmt; - size_t i; - size_t j; - - // create common block mutex for protecting allocs from multiple threads - if (!g_rmt_block_lock) { - g_rmt_block_lock = xSemaphoreCreateMutex(); - } - // lock - while (xSemaphoreTake(g_rmt_block_lock, portMAX_DELAY) != pdPASS) {} - - for (i=0; i MAX_CHANNELS || j != buffers) { - xSemaphoreGive(g_rmt_block_lock); - return NULL; - } - rmt = _rmtAllocate(pin, i, buffers); - - xSemaphoreGive(g_rmt_block_lock); - - size_t channel = i; - -#if !CONFIG_DISABLE_HAL_LOCKS - if(g_rmt_objlocks[channel] == NULL) { - g_rmt_objlocks[channel] = xSemaphoreCreateMutex(); - if(g_rmt_objlocks[channel] == NULL) { - return NULL; - } - } -#endif - - RMT_MUTEX_LOCK(channel); - - rmt->pin = pin; - rmt->tx_not_rx = tx_not_rx; - rmt->buffers =buffers; - rmt->channel = channel; - _initPin(pin, channel, tx_not_rx); - - // Initialize the registers in default mode: - // - no carrier, filter - // - timebase tick of 1us - // - idle threshold set to 0x8000 (max pulse width + 1) - RMT.conf_ch[channel].conf0.div_cnt = 1; - RMT.conf_ch[channel].conf0.mem_size = buffers; - RMT.conf_ch[channel].conf0.carrier_en = 0; - RMT.conf_ch[channel].conf0.carrier_out_lv = 0; - RMT.conf_ch[channel].conf0.mem_pd = 0; - - RMT.conf_ch[channel].conf0.idle_thres = 0x80; - RMT.conf_ch[channel].conf1.rx_en = 0; - RMT.conf_ch[channel].conf1.tx_conti_mode = 0; - RMT.conf_ch[channel].conf1.ref_cnt_rst = 0; - RMT.conf_ch[channel].conf1.rx_filter_en = 0; - RMT.conf_ch[channel].conf1.rx_filter_thres = 0; - RMT.conf_ch[channel].conf1.idle_out_lv = 0; // signal level for idle - RMT.conf_ch[channel].conf1.idle_out_en = 1; // enable idle - RMT.conf_ch[channel].conf1.ref_always_on = 0; // base clock - RMT.apb_conf.fifo_mask = 1; - - if (tx_not_rx) { - // RMT.conf_ch[channel].conf1.rx_en = 0; - RMT.conf_ch[channel].conf1.mem_owner = 0; - RMT.conf_ch[channel].conf1.mem_rd_rst = 1; - } else { - // RMT.conf_ch[channel].conf1.rx_en = 1; - RMT.conf_ch[channel].conf1.mem_owner = 1; - RMT.conf_ch[channel].conf1.mem_wr_rst = 1; - } - - // install interrupt if at least one channel is active - if (!intr_handle) { - esp_intr_alloc(ETS_RMT_INTR_SOURCE, (int)ESP_INTR_FLAG_IRAM, _rmt_isr, NULL, &intr_handle); - } - RMT_MUTEX_UNLOCK(channel); - - return rmt; -} - -/** - * Private methods definitions - */ -bool _rmtSendOnce(rmt_obj_t* rmt, rmt_data_t* data, size_t size, bool continuous) -{ - if (!rmt) { - return false; - } - int channel = rmt->channel; - RMT.apb_conf.fifo_mask = 1; - if (data && size>0) { - size_t i; - volatile uint32_t* rmt_mem_ptr = &(RMTMEM.chan[channel].data32[0].val); - for (i = 0; i < size; i++) { - *rmt_mem_ptr++ = data[i].val; - } - // tx end mark - RMTMEM.chan[channel].data32[size].val = 0; - } - - RMT_MUTEX_LOCK(channel); - RMT.conf_ch[channel].conf1.tx_conti_mode = continuous; - RMT.conf_ch[channel].conf1.mem_rd_rst = 1; - RMT.conf_ch[channel].conf1.tx_start = 1; - RMT_MUTEX_UNLOCK(channel); - - return true; -} - - -static rmt_obj_t* _rmtAllocate(int pin, int from, int size) -{ - size_t i; - // setup how many buffers shall we use - g_rmt_objects[from].buffers = size; - - for (i=0; i 0) { - size_t i; - uint32_t * data = g_rmt_objects[ch].data_ptr; - // in case of callback, provide switching between memories - if (g_rmt_objects[ch].cb) { - if (g_rmt_objects[ch].tx_state & E_FIRST_HALF) { - g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF; - } else { - g_rmt_objects[ch].tx_state |= E_FIRST_HALF; - data += MAX_DATA_PER_CHANNEL*(g_rmt_objects[ch].buffers); - } - } - uint32_t *data_received = data; - for (i = 0; i < g_rmt_objects[ch].data_size; i++ ) { - *data++ = RMTMEM.chan[ch].data32[i].val; - } - if (g_rmt_objects[ch].cb) { - // actually received data ptr - (g_rmt_objects[ch].cb)(data_received, _rmt_get_mem_len(ch)); - - // restart the reception - RMT.conf_ch[ch].conf1.mem_owner = 1; - RMT.conf_ch[ch].conf1.mem_wr_rst = 1; - RMT.conf_ch[ch].conf1.rx_en = 1; - RMT.int_ena.val |= _INT_RX_END(ch); - } else { - // if not callback provide, expect only one Rx - g_rmt_objects[ch].intr_mode &= ~E_RX_INTR; - } - } - } else { - // Report error and disable Rx interrupt - log_e("Unexpected Rx interrupt!\n"); // TODO: eplace messages with log_X - RMT.int_ena.val &= ~_INT_RX_END(ch); - } - - - } - - if (intr_val & _INT_ERROR(ch)) { - // clear the flag - RMT.int_clr.val = _INT_ERROR(ch); - RMT.int_ena.val &= ~_INT_ERROR(ch); - // report error - log_e("RMT Error %d!\n", ch); - if (g_rmt_objects[ch].events) { - xEventGroupSetBits(g_rmt_objects[ch].events, RMT_FLAG_ERROR); - } - // reset memory - RMT.conf_ch[ch].conf1.mem_rd_rst = 1; - RMT.conf_ch[ch].conf1.mem_rd_rst = 0; - RMT.conf_ch[ch].conf1.mem_wr_rst = 1; - RMT.conf_ch[ch].conf1.mem_wr_rst = 0; - } - - if (intr_val & _INT_TX_END(ch)) { - - RMT.int_clr.val = _INT_TX_END(ch); - _rmt_tx_mem_second(ch); - } - - if (intr_val & _INT_THR_EVNT(ch)) { - // clear the flag - RMT.int_clr.val = _INT_THR_EVNT(ch); - - // initial setup of continuous mode - if (g_rmt_objects[ch].tx_state & E_SET_CONTI) { - RMT.conf_ch[ch].conf1.tx_conti_mode = 1; - g_rmt_objects[ch].intr_mode &= ~E_SET_CONTI; - } - _rmt_tx_mem_first(ch); - } - } -} - -static void IRAM_ATTR _rmt_tx_mem_second(uint8_t ch) -{ - DEBUG_INTERRUPT_START(4) - uint32_t* data = g_rmt_objects[ch].data_ptr; - int half_tx_nr = MAX_DATA_PER_ITTERATION/2; - int i; - - RMT.tx_lim_ch[ch].limit = half_tx_nr+2; - RMT.int_clr.val = _INT_THR_EVNT(ch); - RMT.int_ena.val |= _INT_THR_EVNT(ch); - - g_rmt_objects[ch].tx_state |= E_FIRST_HALF; - - if (data) { - int remaining_size = g_rmt_objects[ch].data_size; - // will the remaining data occupy the entire halfbuffer - if (remaining_size > half_tx_nr) { - for (i = 0; i < half_tx_nr; i++) { - RMTMEM.chan[ch].data32[half_tx_nr+i].val = data[i]; - } - g_rmt_objects[ch].data_size -= half_tx_nr; - g_rmt_objects[ch].data_ptr += half_tx_nr; - } else { - for (i = 0; i < half_tx_nr; i++) { - if (i < remaining_size) { - RMTMEM.chan[ch].data32[half_tx_nr+i].val = data[i]; - } else { - RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F; - } - } - g_rmt_objects[ch].data_ptr = NULL; - - } - } else if ((!(g_rmt_objects[ch].tx_state & E_LAST_DATA)) && - (!(g_rmt_objects[ch].tx_state & E_END_TRANS))) { - for (i = 0; i < half_tx_nr; i++) { - RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0x000F000F; - } - RMTMEM.chan[ch].data32[half_tx_nr+i].val = 0; - g_rmt_objects[ch].tx_state |= E_LAST_DATA; - RMT.conf_ch[ch].conf1.tx_conti_mode = 0; - } else { - log_d("RMT Tx finished %d!\n", ch); - RMT.conf_ch[ch].conf1.tx_conti_mode = 0; - RMT.int_ena.val &= ~_INT_TX_END(ch); - RMT.int_ena.val &= ~_INT_THR_EVNT(ch); - g_rmt_objects[ch].intr_mode = E_NO_INTR; - g_rmt_objects[ch].tx_state = E_INACTIVE; - } - DEBUG_INTERRUPT_END(4); -} - -static void IRAM_ATTR _rmt_tx_mem_first(uint8_t ch) -{ - DEBUG_INTERRUPT_START(2); - uint32_t* data = g_rmt_objects[ch].data_ptr; - int half_tx_nr = MAX_DATA_PER_ITTERATION/2; - int i; - RMT.int_ena.val &= ~_INT_THR_EVNT(ch); - RMT.tx_lim_ch[ch].limit = 0; - - if (data) { - int remaining_size = g_rmt_objects[ch].data_size; - - // will the remaining data occupy the entire halfbuffer - if (remaining_size > half_tx_nr) { - RMTMEM.chan[ch].data32[0].val = data[0] - 1; - for (i = 1; i < half_tx_nr; i++) { - RMTMEM.chan[ch].data32[i].val = data[i]; - } - g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF; - // turn off the treshold interrupt - RMT.int_ena.val &= ~_INT_THR_EVNT(ch); - RMT.tx_lim_ch[ch].limit = 0; - g_rmt_objects[ch].data_size -= half_tx_nr; - g_rmt_objects[ch].data_ptr += half_tx_nr; - } else { - RMTMEM.chan[ch].data32[0].val = data[0] - 1; - for (i = 1; i < half_tx_nr; i++) { - if (i < remaining_size) { - RMTMEM.chan[ch].data32[i].val = data[i]; - } else { - RMTMEM.chan[ch].data32[i].val = 0x000F000F; - } - } - - g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF; - g_rmt_objects[ch].data_ptr = NULL; - } - } else { - for (i = 0; i < half_tx_nr; i++) { - RMTMEM.chan[ch].data32[i].val = 0x000F000F; - } - RMTMEM.chan[ch].data32[i].val = 0; - - g_rmt_objects[ch].tx_state &= ~E_FIRST_HALF; - RMT.tx_lim_ch[ch].limit = 0; - g_rmt_objects[ch].tx_state |= E_LAST_DATA; - RMT.conf_ch[ch].conf1.tx_conti_mode = 0; - } - DEBUG_INTERRUPT_END(2); -} - -static int IRAM_ATTR _rmt_get_mem_len(uint8_t channel) -{ - int block_num = RMT.conf_ch[channel].conf0.mem_size; - int item_block_len = block_num * 64; - volatile rmt_item32_t* data = RMTMEM.chan[channel].data32; - int idx; - for(idx = 0; idx < item_block_len; idx++) { - if(data[idx].duration0 == 0) { - return idx; - } else if(data[idx].duration1 == 0) { - return idx + 1; - } - } - return idx; -} diff --git a/components/FastLED-idf/hal/esp32-hal-rmt.h b/components/FastLED-idf/hal/esp32-hal-rmt.h deleted file mode 100644 index ff6da39..0000000 --- a/components/FastLED-idf/hal/esp32-hal-rmt.h +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef MAIN_ESP32_HAL_RMT_H_ -#define MAIN_ESP32_HAL_RMT_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -// notification flags -#define RMT_FLAG_TX_DONE (1) -#define RMT_FLAG_RX_DONE (2) -#define RMT_FLAG_ERROR (4) -#define RMT_FLAGS_ALL (RMT_FLAG_TX_DONE | RMT_FLAG_RX_DONE | RMT_FLAG_ERROR) - -struct rmt_obj_s; - -typedef enum { - RMT_MEM_64 = 1, - RMT_MEM_128 = 2, - RMT_MEM_192 = 3, - RMT_MEM_256 = 4, - RMT_MEM_320 = 5, - RMT_MEM_384 = 6, - RMT_MEM_448 = 7, - RMT_MEM_512 = 8, -} rmt_reserve_memsize_t; - -typedef struct rmt_obj_s rmt_obj_t; - -typedef void (*rmt_rx_data_cb_t)(uint32_t *data, size_t len); - -typedef struct { - union { - struct { - uint32_t duration0 :15; - uint32_t level0 :1; - uint32_t duration1 :15; - uint32_t level1 :1; - }; - uint32_t val; - }; -} rmt_data_t; - -/** -* Initialize the object -* -*/ -rmt_obj_t* rmtInit(int pin, bool tx_not_rx, rmt_reserve_memsize_t memsize); - -/** -* Sets the clock/divider of timebase the nearest tick to the supplied value in nanoseconds -* return the real actual tick value in ns -*/ -float rmtSetTick(rmt_obj_t* rmt, float tick); - -/** -* Sending data in one-go mode or continual mode -* (more data being send while updating buffers in interrupts) -* -*/ -bool rmtWrite(rmt_obj_t* rmt, rmt_data_t* data, size_t size); - -/** -* Loop data up to the reserved memsize continuously -* -*/ -bool rmtLoop(rmt_obj_t* rmt, rmt_data_t* data, size_t size); - -/** -* Initiates async receive, event flag indicates data received -* -*/ -bool rmtReadAsync(rmt_obj_t* rmt, rmt_data_t* data, size_t size, void* eventFlag, bool waitForData, uint32_t timeout); - -/** -* Initiates async receive with automatic buffering -* and callback with data from ISR -* -*/ -bool rmtRead(rmt_obj_t* rmt, rmt_rx_data_cb_t cb); - - -/* Additional interface */ - -/** -* Start reception -* -*/ -bool rmtBeginReceive(rmt_obj_t* rmt); - -/** -* Checks if reception completes -* -*/ -bool rmtReceiveCompleted(rmt_obj_t* rmt); - -/** -* Reads the data for particular channel -* -*/ -bool rmtReadData(rmt_obj_t* rmt, uint32_t* data, size_t size); - -/** - * Setting threshold for Rx completed - */ -bool rmtSetRxThreshold(rmt_obj_t* rmt, uint32_t value); - -/** - * Setting carrier - */ -bool rmtSetCarrier(rmt_obj_t* rmt, bool carrier_en, bool carrier_level, uint32_t low, uint32_t high); - -/** - * Setting input filter - */ -bool rmtSetFilter(rmt_obj_t* rmt, bool filter_en, uint32_t filter_level); - -/** - * Deinitialize the driver - */ -bool rmtDeinit(rmt_obj_t *rmt); - -// TODO: -// * uninstall interrupt when all channels are deinit -// * send only-conti mode with circular-buffer -// * put sanity checks to some macro or inlines -// * doxy comments -// * error reporting - -#ifdef __cplusplus -} -#endif - -#endif /* MAIN_ESP32_HAL_RMT_H_ */ diff --git a/components/FastLED-idf/hal/esp32-hal-spi.c b/components/FastLED-idf/hal/esp32-hal-spi.c deleted file mode 100644 index a1a460c..0000000 --- a/components/FastLED-idf/hal/esp32-hal-spi.c +++ /dev/null @@ -1,1095 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "esp32-hal-spi.h" -#include "esp32-hal.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" -#include "esp32/rom/ets_sys.h" -#include "esp_attr.h" -#include "esp_intr.h" -#include "esp32/rom/gpio.h" -#include "soc/spi_reg.h" -#include "soc/spi_struct.h" -#include "soc/io_mux_reg.h" -#include "soc/gpio_sig_map.h" -#include "soc/dport_reg.h" -#include "soc/rtc.h" - -#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0)))) -#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0)))) -#define SPI_MOSI_IDX(p) ((p==0)?SPID_IN_IDX:((p==1)?SPID_IN_IDX:((p==2)?HSPID_IN_IDX:((p==3)?VSPID_IN_IDX:0)))) - -#define SPI_SPI_SS_IDX(n) ((n==0)?SPICS0_OUT_IDX:((n==1)?SPICS1_OUT_IDX:((n==2)?SPICS2_OUT_IDX:SPICS0_OUT_IDX))) -#define SPI_HSPI_SS_IDX(n) ((n==0)?HSPICS0_OUT_IDX:((n==1)?HSPICS1_OUT_IDX:((n==2)?HSPICS2_OUT_IDX:HSPICS0_OUT_IDX))) -#define SPI_VSPI_SS_IDX(n) ((n==0)?VSPICS0_OUT_IDX:((n==1)?VSPICS1_OUT_IDX:((n==2)?VSPICS2_OUT_IDX:VSPICS0_OUT_IDX))) -#define SPI_SS_IDX(p, n) ((p==0)?SPI_SPI_SS_IDX(n):((p==1)?SPI_SPI_SS_IDX(n):((p==2)?SPI_HSPI_SS_IDX(n):((p==3)?SPI_VSPI_SS_IDX(n):0)))) - -#define SPI_INUM(u) (2) -#define SPI_INTR_SOURCE(u) ((u==0)?ETS_SPI0_INTR_SOURCE:((u==1)?ETS_SPI1_INTR_SOURCE:((u==2)?ETS_SPI2_INTR_SOURCE:((p==3)?ETS_SPI3_INTR_SOURCE:0)))) - -struct spi_struct_t { - spi_dev_t * dev; -#if !CONFIG_DISABLE_HAL_LOCKS - xSemaphoreHandle lock; -#endif - uint8_t num; -}; - -#if CONFIG_DISABLE_HAL_LOCKS -#define SPI_MUTEX_LOCK() -#define SPI_MUTEX_UNLOCK() - -static spi_t _spi_bus_array[4] = { - {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), 0}, - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), 1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), 2}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), 3} -}; -#else -#define SPI_MUTEX_LOCK() do {} while (xSemaphoreTake(spi->lock, portMAX_DELAY) != pdPASS) -#define SPI_MUTEX_UNLOCK() xSemaphoreGive(spi->lock) - -static spi_t _spi_bus_array[4] = { - {(volatile spi_dev_t *)(DR_REG_SPI0_BASE), NULL, 0}, - {(volatile spi_dev_t *)(DR_REG_SPI1_BASE), NULL, 1}, - {(volatile spi_dev_t *)(DR_REG_SPI2_BASE), NULL, 2}, - {(volatile spi_dev_t *)(DR_REG_SPI3_BASE), NULL, 3} -}; -#endif - -void spiAttachSCK(spi_t * spi, int8_t sck) -{ - if(!spi) { - return; - } - if(sck < 0) { - if(spi->num == HSPI) { - sck = 14; - } else if(spi->num == VSPI) { - sck = 18; - } else { - sck = 6; - } - } - pinMode(sck, OUTPUT); - pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false); -} - -void spiAttachMISO(spi_t * spi, int8_t miso) -{ - if(!spi) { - return; - } - if(miso < 0) { - if(spi->num == HSPI) { - miso = 12; - } else if(spi->num == VSPI) { - miso = 19; - } else { - miso = 7; - } - } - SPI_MUTEX_LOCK(); - pinMode(miso, INPUT); - pinMatrixInAttach(miso, SPI_MISO_IDX(spi->num), false); - SPI_MUTEX_UNLOCK(); -} - -void spiAttachMOSI(spi_t * spi, int8_t mosi) -{ - if(!spi) { - return; - } - if(mosi < 0) { - if(spi->num == HSPI) { - mosi = 13; - } else if(spi->num == VSPI) { - mosi = 23; - } else { - mosi = 8; - } - } - pinMode(mosi, OUTPUT); - pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false); -} - -void spiDetachSCK(spi_t * spi, int8_t sck) -{ - if(!spi) { - return; - } - if(sck < 0) { - if(spi->num == HSPI) { - sck = 14; - } else if(spi->num == VSPI) { - sck = 18; - } else { - sck = 6; - } - } - pinMatrixOutDetach(sck, false, false); - pinMode(sck, INPUT); -} - -void spiDetachMISO(spi_t * spi, int8_t miso) -{ - if(!spi) { - return; - } - if(miso < 0) { - if(spi->num == HSPI) { - miso = 12; - } else if(spi->num == VSPI) { - miso = 19; - } else { - miso = 7; - } - } - pinMatrixInDetach(SPI_MISO_IDX(spi->num), false, false); - pinMode(miso, INPUT); -} - -void spiDetachMOSI(spi_t * spi, int8_t mosi) -{ - if(!spi) { - return; - } - if(mosi < 0) { - if(spi->num == HSPI) { - mosi = 13; - } else if(spi->num == VSPI) { - mosi = 23; - } else { - mosi = 8; - } - } - pinMatrixOutDetach(mosi, false, false); - pinMode(mosi, INPUT); -} - -void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss) -{ - if(!spi) { - return; - } - if(cs_num > 2) { - return; - } - if(ss < 0) { - cs_num = 0; - if(spi->num == HSPI) { - ss = 15; - } else if(spi->num == VSPI) { - ss = 5; - } else { - ss = 11; - } - } - pinMode(ss, OUTPUT); - pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false); - spiEnableSSPins(spi, (1 << cs_num)); -} - -void spiDetachSS(spi_t * spi, int8_t ss) -{ - if(!spi) { - return; - } - if(ss < 0) { - if(spi->num == HSPI) { - ss = 15; - } else if(spi->num == VSPI) { - ss = 5; - } else { - ss = 11; - } - } - pinMatrixOutDetach(ss, false, false); - pinMode(ss, INPUT); -} - -void spiEnableSSPins(spi_t * spi, uint8_t cs_mask) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->pin.val &= ~(cs_mask & SPI_CS_MASK_ALL); - SPI_MUTEX_UNLOCK(); -} - -void spiDisableSSPins(spi_t * spi, uint8_t cs_mask) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->pin.val |= (cs_mask & SPI_CS_MASK_ALL); - SPI_MUTEX_UNLOCK(); -} - -void spiSSEnable(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->user.cs_setup = 1; - spi->dev->user.cs_hold = 1; - SPI_MUTEX_UNLOCK(); -} - -void spiSSDisable(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->user.cs_setup = 0; - spi->dev->user.cs_hold = 0; - SPI_MUTEX_UNLOCK(); -} - -void spiSSSet(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->pin.cs_keep_active = 1; - SPI_MUTEX_UNLOCK(); -} - -void spiSSClear(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->pin.cs_keep_active = 0; - SPI_MUTEX_UNLOCK(); -} - -uint32_t spiGetClockDiv(spi_t * spi) -{ - if(!spi) { - return 0; - } - return spi->dev->clock.val; -} - -void spiSetClockDiv(spi_t * spi, uint32_t clockDiv) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->clock.val = clockDiv; - SPI_MUTEX_UNLOCK(); -} - -uint8_t spiGetDataMode(spi_t * spi) -{ - if(!spi) { - return 0; - } - bool idleEdge = spi->dev->pin.ck_idle_edge; - bool outEdge = spi->dev->user.ck_out_edge; - if(idleEdge) { - if(outEdge) { - return SPI_MODE2; - } - return SPI_MODE3; - } - if(outEdge) { - return SPI_MODE1; - } - return SPI_MODE0; -} - -void spiSetDataMode(spi_t * spi, uint8_t dataMode) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - switch (dataMode) { - case SPI_MODE1: - spi->dev->pin.ck_idle_edge = 0; - spi->dev->user.ck_out_edge = 1; - break; - case SPI_MODE2: - spi->dev->pin.ck_idle_edge = 1; - spi->dev->user.ck_out_edge = 1; - break; - case SPI_MODE3: - spi->dev->pin.ck_idle_edge = 1; - spi->dev->user.ck_out_edge = 0; - break; - case SPI_MODE0: - default: - spi->dev->pin.ck_idle_edge = 0; - spi->dev->user.ck_out_edge = 0; - break; - } - SPI_MUTEX_UNLOCK(); -} - -uint8_t spiGetBitOrder(spi_t * spi) -{ - if(!spi) { - return 0; - } - return (spi->dev->ctrl.wr_bit_order | spi->dev->ctrl.rd_bit_order) == 0; -} - -void spiSetBitOrder(spi_t * spi, uint8_t bitOrder) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - if (SPI_MSBFIRST == bitOrder) { - spi->dev->ctrl.wr_bit_order = 0; - spi->dev->ctrl.rd_bit_order = 0; - } else if (SPI_LSBFIRST == bitOrder) { - spi->dev->ctrl.wr_bit_order = 1; - spi->dev->ctrl.rd_bit_order = 1; - } - SPI_MUTEX_UNLOCK(); -} - -static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb) -{ - spi_t * spi = (spi_t *)arg; - if(ev_type == APB_BEFORE_CHANGE){ - SPI_MUTEX_LOCK(); - while(spi->dev->cmd.usr); - } else { - spi->dev->clock.val = spiFrequencyToClockDiv(old_apb / ((spi->dev->clock.clkdiv_pre + 1) * (spi->dev->clock.clkcnt_n + 1))); - SPI_MUTEX_UNLOCK(); - } -} - -static void spiInitBus(spi_t * spi) -{ - spi->dev->slave.trans_done = 0; - spi->dev->slave.slave_mode = 0; - spi->dev->pin.val = 0; - spi->dev->user.val = 0; - spi->dev->user1.val = 0; - spi->dev->ctrl.val = 0; - spi->dev->ctrl1.val = 0; - spi->dev->ctrl2.val = 0; - spi->dev->clock.val = 0; -} - -void spiStopBus(spi_t * spi) -{ - if(!spi) { - return; - } - - removeApbChangeCallback(spi, _on_apb_change); - - SPI_MUTEX_LOCK(); - spiInitBus(spi); - SPI_MUTEX_UNLOCK(); -} - -spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder) -{ - if(spi_num > 3){ - return NULL; - } - - spi_t * spi = &_spi_bus_array[spi_num]; - -#if !CONFIG_DISABLE_HAL_LOCKS - if(spi->lock == NULL){ - spi->lock = xSemaphoreCreateMutex(); - if(spi->lock == NULL) { - return NULL; - } - } -#endif - - if(spi_num == HSPI) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST); - } else if(spi_num == VSPI) { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_2); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_2); - } else { - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI_CLK_EN_1); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_SPI_RST_1); - } - - SPI_MUTEX_LOCK(); - spiInitBus(spi); - spi->dev->user.usr_mosi = 1; - spi->dev->user.usr_miso = 1; - spi->dev->user.doutdin = 1; - - int i; - for(i=0; i<16; i++) { - spi->dev->data_buf[i] = 0x00000000; - } - SPI_MUTEX_UNLOCK(); - - spiSetDataMode(spi, dataMode); - spiSetBitOrder(spi, bitOrder); - spiSetClockDiv(spi, clockDiv); - - addApbChangeCallback(spi, _on_apb_change); - return spi; -} - -void spiWaitReady(spi_t * spi) -{ - if(!spi) { - return; - } - while(spi->dev->cmd.usr); -} - -void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len) -{ - if(!spi) { - return; - } - int i; - if(len > 16) { - len = 16; - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - for(i=0; idev->data_buf[i] = data[i]; - } - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - SPI_MUTEX_UNLOCK(); -} - -void spiTransfer(spi_t * spi, uint32_t *data, uint8_t len) -{ - if(!spi) { - return; - } - int i; - if(len > 16) { - len = 16; - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = (len * 32) - 1; - spi->dev->miso_dlen.usr_miso_dbitlen = (len * 32) - 1; - for(i=0; idev->data_buf[i] = data[i]; - } - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - for(i=0; idev->data_buf[i]; - } - SPI_MUTEX_UNLOCK(); -} - -void spiWriteByte(spi_t * spi, uint8_t data) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - SPI_MUTEX_UNLOCK(); -} - -uint8_t spiTransferByte(spi_t * spi, uint8_t data) -{ - if(!spi) { - return 0; - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; - spi->dev->miso_dlen.usr_miso_dbitlen = 7; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0] & 0xFF; - SPI_MUTEX_UNLOCK(); - return data; -} - -static uint32_t __spiTranslate32(uint32_t data) -{ - union { - uint32_t l; - uint8_t b[4]; - } out; - out.l = data; - return out.b[3] | (out.b[2] << 8) | (out.b[1] << 16) | (out.b[0] << 24); -} - -void spiWriteWord(spi_t * spi, uint16_t data) -{ - if(!spi) { - return; - } - if(!spi->dev->ctrl.wr_bit_order){ - data = (data >> 8) | (data << 8); - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - SPI_MUTEX_UNLOCK(); -} - -uint16_t spiTransferWord(spi_t * spi, uint16_t data) -{ - if(!spi) { - return 0; - } - if(!spi->dev->ctrl.wr_bit_order){ - data = (data >> 8) | (data << 8); - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; - spi->dev->miso_dlen.usr_miso_dbitlen = 15; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0]; - SPI_MUTEX_UNLOCK(); - if(!spi->dev->ctrl.rd_bit_order){ - data = (data >> 8) | (data << 8); - } - return data; -} - -void spiWriteLong(spi_t * spi, uint32_t data) -{ - if(!spi) { - return; - } - if(!spi->dev->ctrl.wr_bit_order){ - data = __spiTranslate32(data); - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - SPI_MUTEX_UNLOCK(); -} - -uint32_t spiTransferLong(spi_t * spi, uint32_t data) -{ - if(!spi) { - return 0; - } - if(!spi->dev->ctrl.wr_bit_order){ - data = __spiTranslate32(data); - } - SPI_MUTEX_LOCK(); - spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; - spi->dev->miso_dlen.usr_miso_dbitlen = 31; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0]; - SPI_MUTEX_UNLOCK(); - if(!spi->dev->ctrl.rd_bit_order){ - data = __spiTranslate32(data); - } - return data; -} - -static void __spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t bytes) -{ - if(!spi) { - return; - } - int i; - - if(bytes > 64) { - bytes = 64; - } - - uint32_t words = (bytes + 3) / 4;//16 max - - uint32_t wordsBuf[16] = {0,}; - uint8_t * bytesBuf = (uint8_t *) wordsBuf; - - if(data) { - memcpy(bytesBuf, data, bytes);//copy data to buffer - } else { - memset(bytesBuf, 0xFF, bytes); - } - - spi->dev->mosi_dlen.usr_mosi_dbitlen = ((bytes * 8) - 1); - spi->dev->miso_dlen.usr_miso_dbitlen = ((bytes * 8) - 1); - - for(i=0; idev->data_buf[i] = wordsBuf[i]; //copy buffer to spi fifo - } - - spi->dev->cmd.usr = 1; - - while(spi->dev->cmd.usr); - - if(out) { - for(i=0; idev->data_buf[i];//copy spi fifo to buffer - } - memcpy(out, bytesBuf, bytes);//copy buffer to output - } -} - -void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - while(size) { - if(size > 64) { - __spiTransferBytes(spi, data, out, 64); - size -= 64; - if(data) { - data += 64; - } - if(out) { - out += 64; - } - } else { - __spiTransferBytes(spi, data, out, size); - size = 0; - } - } - SPI_MUTEX_UNLOCK(); -} - -void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spiTransferBitsNL(spi, data, out, bits); - SPI_MUTEX_UNLOCK(); -} - -/* - * Manual Lock Management - * */ - -#define MSB_32_SET(var, val) { uint8_t * d = (uint8_t *)&(val); (var) = d[3] | (d[2] << 8) | (d[1] << 16) | (d[0] << 24); } -#define MSB_24_SET(var, val) { uint8_t * d = (uint8_t *)&(val); (var) = d[2] | (d[1] << 8) | (d[0] << 16); } -#define MSB_16_SET(var, val) { (var) = (((val) & 0xFF00) >> 8) | (((val) & 0xFF) << 8); } -#define MSB_PIX_SET(var, val) { uint8_t * d = (uint8_t *)&(val); (var) = d[1] | (d[0] << 8) | (d[3] << 16) | (d[2] << 24); } - -void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); - spi->dev->clock.val = clockDiv; - switch (dataMode) { - case SPI_MODE1: - spi->dev->pin.ck_idle_edge = 0; - spi->dev->user.ck_out_edge = 1; - break; - case SPI_MODE2: - spi->dev->pin.ck_idle_edge = 1; - spi->dev->user.ck_out_edge = 1; - break; - case SPI_MODE3: - spi->dev->pin.ck_idle_edge = 1; - spi->dev->user.ck_out_edge = 0; - break; - case SPI_MODE0: - default: - spi->dev->pin.ck_idle_edge = 0; - spi->dev->user.ck_out_edge = 0; - break; - } - if (SPI_MSBFIRST == bitOrder) { - spi->dev->ctrl.wr_bit_order = 0; - spi->dev->ctrl.rd_bit_order = 0; - } else if (SPI_LSBFIRST == bitOrder) { - spi->dev->ctrl.wr_bit_order = 1; - spi->dev->ctrl.rd_bit_order = 1; - } -} - -void spiSimpleTransaction(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_LOCK(); -} - -void spiEndTransaction(spi_t * spi) -{ - if(!spi) { - return; - } - SPI_MUTEX_UNLOCK(); -} - -void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data) -{ - if(!spi) { - return; - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); -} - -uint8_t spiTransferByteNL(spi_t * spi, uint8_t data) -{ - if(!spi) { - return 0; - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 7; - spi->dev->miso_dlen.usr_miso_dbitlen = 7; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0] & 0xFF; - return data; -} - -void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data) -{ - if(!spi) { - return; - } - if(!spi->dev->ctrl.wr_bit_order){ - MSB_16_SET(data, data); - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); -} - -uint16_t spiTransferShortNL(spi_t * spi, uint16_t data) -{ - if(!spi) { - return 0; - } - if(!spi->dev->ctrl.wr_bit_order){ - MSB_16_SET(data, data); - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 15; - spi->dev->miso_dlen.usr_miso_dbitlen = 15; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0] & 0xFFFF; - if(!spi->dev->ctrl.rd_bit_order){ - MSB_16_SET(data, data); - } - return data; -} - -void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data) -{ - if(!spi) { - return; - } - if(!spi->dev->ctrl.wr_bit_order){ - MSB_32_SET(data, data); - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); -} - -uint32_t spiTransferLongNL(spi_t * spi, uint32_t data) -{ - if(!spi) { - return 0; - } - if(!spi->dev->ctrl.wr_bit_order){ - MSB_32_SET(data, data); - } - spi->dev->mosi_dlen.usr_mosi_dbitlen = 31; - spi->dev->miso_dlen.usr_miso_dbitlen = 31; - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0]; - if(!spi->dev->ctrl.rd_bit_order){ - MSB_32_SET(data, data); - } - return data; -} - -void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len){ - size_t longs = len >> 2; - if(len & 3){ - longs++; - } - uint32_t * data = (uint32_t*)data_in; - size_t c_len = 0, c_longs = 0; - - while(len){ - c_len = (len>64)?64:len; - c_longs = (longs > 16)?16:longs; - - spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - for (int i=0; idev->data_buf[i] = data[i]; - } - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - - data += c_longs; - longs -= c_longs; - len -= c_len; - } -} - -void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, uint32_t len){ - if(!spi) { - return; - } - size_t longs = len >> 2; - if(len & 3){ - longs++; - } - uint32_t * data = (uint32_t*)data_in; - uint32_t * result = (uint32_t*)data_out; - size_t c_len = 0, c_longs = 0; - - while(len){ - c_len = (len>64)?64:len; - c_longs = (longs > 16)?16:longs; - - spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1; - spi->dev->miso_dlen.usr_miso_dbitlen = (c_len*8)-1; - if(data){ - for (int i=0; idev->data_buf[i] = data[i]; - } - } else { - for (int i=0; idev->data_buf[i] = 0xFFFFFFFF; - } - } - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - if(result){ - for (int i=0; idev->data_buf[i]; - } - } - if(data){ - data += c_longs; - } - if(result){ - result += c_longs; - } - longs -= c_longs; - len -= c_len; - } -} - -void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits) -{ - if(!spi) { - return; - } - - if(bits > 32) { - bits = 32; - } - uint32_t bytes = (bits + 7) / 8;//64 max - uint32_t mask = (((uint64_t)1 << bits) - 1) & 0xFFFFFFFF; - data = data & mask; - if(!spi->dev->ctrl.wr_bit_order){ - if(bytes == 2) { - MSB_16_SET(data, data); - } else if(bytes == 3) { - MSB_24_SET(data, data); - } else { - MSB_32_SET(data, data); - } - } - - spi->dev->mosi_dlen.usr_mosi_dbitlen = (bits - 1); - spi->dev->miso_dlen.usr_miso_dbitlen = (bits - 1); - spi->dev->data_buf[0] = data; - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - data = spi->dev->data_buf[0]; - if(out) { - *out = data; - if(!spi->dev->ctrl.rd_bit_order){ - if(bytes == 2) { - MSB_16_SET(*out, data); - } else if(bytes == 3) { - MSB_24_SET(*out, data); - } else { - MSB_32_SET(*out, data); - } - } - } -} - -void IRAM_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len){ - size_t longs = len >> 2; - if(len & 3){ - longs++; - } - bool msb = !spi->dev->ctrl.wr_bit_order; - uint32_t * data = (uint32_t*)data_in; - size_t c_len = 0, c_longs = 0, l_bytes = 0; - - while(len){ - c_len = (len>64)?64:len; - c_longs = (longs > 16)?16:longs; - l_bytes = (c_len & 3); - - spi->dev->mosi_dlen.usr_mosi_dbitlen = (c_len*8)-1; - spi->dev->miso_dlen.usr_miso_dbitlen = 0; - for (int i=0; idev->data_buf[i], data[i]); - } else { - spi->dev->data_buf[i] = data[i] & 0xFF; - } - } else { - MSB_PIX_SET(spi->dev->data_buf[i], data[i]); - } - } else { - spi->dev->data_buf[i] = data[i]; - } - } - spi->dev->cmd.usr = 1; - while(spi->dev->cmd.usr); - - data += c_longs; - longs -= c_longs; - len -= c_len; - } -} - - - -/* - * Clock Calculators - * - * */ - -typedef union { - uint32_t value; - struct { - uint32_t clkcnt_l: 6; /*it must be equal to spi_clkcnt_N.*/ - uint32_t clkcnt_h: 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/ - uint32_t clkcnt_n: 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/ - uint32_t clkdiv_pre: 13; /*it is pre-divider of spi_clk.*/ - uint32_t clk_equ_sysclk: 1; /*1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/ - }; -} spiClk_t; - -#define ClkRegToFreq(reg) (apb_freq / (((reg)->clkdiv_pre + 1) * ((reg)->clkcnt_n + 1))) - -uint32_t spiClockDivToFrequency(uint32_t clockDiv) -{ - uint32_t apb_freq = getApbFrequency(); - spiClk_t reg = { clockDiv }; - return ClkRegToFreq(®); -} - -uint32_t spiFrequencyToClockDiv(uint32_t freq) -{ - uint32_t apb_freq = getApbFrequency(); - - if(freq >= apb_freq) { - return SPI_CLK_EQU_SYSCLK; - } - - const spiClk_t minFreqReg = { 0x7FFFF000 }; - uint32_t minFreq = ClkRegToFreq((spiClk_t*) &minFreqReg); - if(freq < minFreq) { - return minFreqReg.value; - } - - uint8_t calN = 1; - spiClk_t bestReg = { 0 }; - int32_t bestFreq = 0; - - while(calN <= 0x3F) { - spiClk_t reg = { 0 }; - int32_t calFreq; - int32_t calPre; - int8_t calPreVari = -2; - - reg.clkcnt_n = calN; - - while(calPreVari++ <= 1) { - calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari; - if(calPre > 0x1FFF) { - reg.clkdiv_pre = 0x1FFF; - } else if(calPre <= 0) { - reg.clkdiv_pre = 0; - } else { - reg.clkdiv_pre = calPre; - } - reg.clkcnt_l = ((reg.clkcnt_n + 1) / 2); - calFreq = ClkRegToFreq(®); - if(calFreq == (int32_t) freq) { - memcpy(&bestReg, ®, sizeof(bestReg)); - break; - } else if(calFreq < (int32_t) freq) { - if(abs(freq - calFreq) < abs(freq - bestFreq)) { - bestFreq = calFreq; - memcpy(&bestReg, ®, sizeof(bestReg)); - } - } - } - if(calFreq == (int32_t) freq) { - break; - } - calN++; - } - return bestReg.value; -} - diff --git a/components/FastLED-idf/hal/esp32-hal-spi.h b/components/FastLED-idf/hal/esp32-hal-spi.h deleted file mode 100644 index 1317f38..0000000 --- a/components/FastLED-idf/hal/esp32-hal-spi.h +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef MAIN_ESP32_HAL_SPI_H_ -#define MAIN_ESP32_HAL_SPI_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include - -#define SPI_HAS_TRANSACTION - -#define FSPI 1 //SPI bus attached to the flash (can use the same data lines but different SS) -#define HSPI 2 //SPI bus normally mapped to pins 12 - 15, but can be matrixed to any pins -#define VSPI 3 //SPI bus normally attached to pins 5, 18, 19 and 23, but can be matrixed to any pins - -// This defines are not representing the real Divider of the ESP32 -// the Defines match to an AVR Arduino on 16MHz for better compatibility -#define SPI_CLOCK_DIV2 0x00101001 //8 MHz -#define SPI_CLOCK_DIV4 0x00241001 //4 MHz -#define SPI_CLOCK_DIV8 0x004c1001 //2 MHz -#define SPI_CLOCK_DIV16 0x009c1001 //1 MHz -#define SPI_CLOCK_DIV32 0x013c1001 //500 KHz -#define SPI_CLOCK_DIV64 0x027c1001 //250 KHz -#define SPI_CLOCK_DIV128 0x04fc1001 //125 KHz - -#define SPI_MODE0 0 -#define SPI_MODE1 1 -#define SPI_MODE2 2 -#define SPI_MODE3 3 - -#define SPI_CS0 0 -#define SPI_CS1 1 -#define SPI_CS2 2 -#define SPI_CS_MASK_ALL 0x7 - -#define SPI_LSBFIRST 0 -#define SPI_MSBFIRST 1 - -struct spi_struct_t; -typedef struct spi_struct_t spi_t; - -spi_t * spiStartBus(uint8_t spi_num, uint32_t freq, uint8_t dataMode, uint8_t bitOrder); -void spiStopBus(spi_t * spi); - -//Attach/Detach Signal Pins -void spiAttachSCK(spi_t * spi, int8_t sck); -void spiAttachMISO(spi_t * spi, int8_t miso); -void spiAttachMOSI(spi_t * spi, int8_t mosi); -void spiDetachSCK(spi_t * spi, int8_t sck); -void spiDetachMISO(spi_t * spi, int8_t miso); -void spiDetachMOSI(spi_t * spi, int8_t mosi); - -//Attach/Detach SS pin to SPI_CSx signal -void spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss); -void spiDetachSS(spi_t * spi, int8_t ss); - -//Enable/Disable SPI_CSx pins -void spiEnableSSPins(spi_t * spi, uint8_t cs_mask); -void spiDisableSSPins(spi_t * spi, uint8_t cs_mask); - -//Enable/Disable hardware control of SPI_CSx pins -void spiSSEnable(spi_t * spi); -void spiSSDisable(spi_t * spi); - -//Activate enabled SPI_CSx pins -void spiSSSet(spi_t * spi); -//Deactivate enabled SPI_CSx pins -void spiSSClear(spi_t * spi); - -void spiWaitReady(spi_t * spi); - -uint32_t spiGetClockDiv(spi_t * spi); -uint8_t spiGetDataMode(spi_t * spi); -uint8_t spiGetBitOrder(spi_t * spi); - - -/* - * Non transaction based lock methods (each locks and unlocks when called) - * */ -void spiSetClockDiv(spi_t * spi, uint32_t clockDiv); -void spiSetDataMode(spi_t * spi, uint8_t dataMode); -void spiSetBitOrder(spi_t * spi, uint8_t bitOrder); - -void spiWrite(spi_t * spi, const uint32_t *data, uint8_t len); -void spiWriteByte(spi_t * spi, uint8_t data); -void spiWriteWord(spi_t * spi, uint16_t data); -void spiWriteLong(spi_t * spi, uint32_t data); - -void spiTransfer(spi_t * spi, uint32_t *out, uint8_t len); -uint8_t spiTransferByte(spi_t * spi, uint8_t data); -uint16_t spiTransferWord(spi_t * spi, uint16_t data); -uint32_t spiTransferLong(spi_t * spi, uint32_t data); -void spiTransferBytes(spi_t * spi, const uint8_t * data, uint8_t * out, uint32_t size); -void spiTransferBits(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits); - -/* - * New (EXPERIMENTAL) Transaction lock based API (lock once until endTransaction) - * */ -void spiTransaction(spi_t * spi, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder); -void spiSimpleTransaction(spi_t * spi); -void spiEndTransaction(spi_t * spi); - -void spiWriteNL(spi_t * spi, const void * data_in, uint32_t len); -void spiWriteByteNL(spi_t * spi, uint8_t data); -void spiWriteShortNL(spi_t * spi, uint16_t data); -void spiWriteLongNL(spi_t * spi, uint32_t data); -void spiWritePixelsNL(spi_t * spi, const void * data_in, uint32_t len); - -#define spiTransferNL(spi, data, len) spiTransferBytesNL(spi, data, data, len) -uint8_t spiTransferByteNL(spi_t * spi, uint8_t data); -uint16_t spiTransferShortNL(spi_t * spi, uint16_t data); -uint32_t spiTransferLongNL(spi_t * spi, uint32_t data); -void spiTransferBytesNL(spi_t * spi, const void * data_in, uint8_t * data_out, uint32_t len); -void spiTransferBitsNL(spi_t * spi, uint32_t data_in, uint32_t * data_out, uint8_t bits); - -/* - * Helper functions to translate frequency to clock divider and back - * */ -uint32_t spiFrequencyToClockDiv(uint32_t freq); -uint32_t spiClockDivToFrequency(uint32_t freq); - -#ifdef __cplusplus -} -#endif - -#endif /* MAIN_ESP32_HAL_SPI_H_ */ diff --git a/components/FastLED-idf/hal/esp32-hal.h b/components/FastLED-idf/hal/esp32-hal.h index c561f87..ead9a5c 100644 --- a/components/FastLED-idf/hal/esp32-hal.h +++ b/components/FastLED-idf/hal/esp32-hal.h @@ -51,9 +51,6 @@ void yield(void); #include "esp32-hal-log.h" #include "esp32-hal-gpio.h" -#include "esp32-hal-spi.h" -#include "esp32-hal-i2c.h" -#include "esp32-hal-rmt.h" #include "esp32-hal-cpu.h" #ifndef BOARD_HAS_PSRAM