Compare commits
1 commit
master
...
fix/allow-
Author | SHA1 | Date | |
---|---|---|---|
95dccdcc38 |
2 changed files with 560 additions and 561 deletions
|
@ -306,7 +306,7 @@ struct HUB75_I2S_CFG
|
||||||
bool clkphase;
|
bool clkphase;
|
||||||
|
|
||||||
// Minimum refresh / scan rate needs to be configured on start due to LSBMSB_TRANSITION_BIT calculation in allocateDMAmemory()
|
// Minimum refresh / scan rate needs to be configured on start due to LSBMSB_TRANSITION_BIT calculation in allocateDMAmemory()
|
||||||
uint8_t min_refresh_rate;
|
uint16_t min_refresh_rate;
|
||||||
|
|
||||||
// struct constructor
|
// struct constructor
|
||||||
HUB75_I2S_CFG(
|
HUB75_I2S_CFG(
|
||||||
|
@ -498,7 +498,6 @@ public:
|
||||||
vlineDMA(x, y, h, r, g, b);
|
vlineDMA(x, y, h, r, g, b);
|
||||||
else
|
else
|
||||||
hlineDMA(x, y, w, r, g, b);
|
hlineDMA(x, y, w, r, g, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
// rgb888 overload
|
// rgb888 overload
|
||||||
virtual inline void drawFastVLine(int16_t x, int16_t y, int16_t h, uint8_t r, uint8_t g, uint8_t b)
|
virtual inline void drawFastVLine(int16_t x, int16_t y, int16_t h, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
@ -526,7 +525,6 @@ public:
|
||||||
vlineDMA(x, y, h, r, g, b);
|
vlineDMA(x, y, h, r, g, b);
|
||||||
else
|
else
|
||||||
hlineDMA(x, y, w, r, g, b);
|
hlineDMA(x, y, w, r, g, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
// rgb888 overload
|
// rgb888 overload
|
||||||
virtual inline void drawFastHLine(int16_t x, int16_t y, int16_t w, uint8_t r, uint8_t g, uint8_t b)
|
virtual inline void drawFastHLine(int16_t x, int16_t y, int16_t w, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
@ -550,7 +548,6 @@ public:
|
||||||
|
|
||||||
transform(x, y, w, h);
|
transform(x, y, w, h);
|
||||||
fillRectDMA(x, y, w, h, r, g, b);
|
fillRectDMA(x, y, w, h, r, g, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
// rgb888 overload
|
// rgb888 overload
|
||||||
virtual inline void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t r, uint8_t g, uint8_t b)
|
virtual inline void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t r, uint8_t g, uint8_t b)
|
||||||
|
@ -558,7 +555,6 @@ public:
|
||||||
|
|
||||||
transform(x, y, w, h);
|
transform(x, y, w, h);
|
||||||
fillRectDMA(x, y, w, h, r, g, b);
|
fillRectDMA(x, y, w, h, r, g, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -603,12 +599,9 @@ public:
|
||||||
|
|
||||||
dma_bus.flip_dma_output_buffer(back_buffer_id);
|
dma_bus.flip_dma_output_buffer(back_buffer_id);
|
||||||
|
|
||||||
//back_buffer_id ^= 1;
|
// back_buffer_id ^= 1;
|
||||||
back_buffer_id = back_buffer_id^1;
|
back_buffer_id = back_buffer_id ^ 1;
|
||||||
fb = &frame_buffer[back_buffer_id];
|
fb = &frame_buffer[back_buffer_id];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -716,11 +709,11 @@ protected:
|
||||||
clearFrameBuffer(0);
|
clearFrameBuffer(0);
|
||||||
brtCtrlOEv2(brightness, 0);
|
brtCtrlOEv2(brightness, 0);
|
||||||
|
|
||||||
if (m_cfg.double_buff) {
|
if (m_cfg.double_buff)
|
||||||
|
{
|
||||||
|
|
||||||
clearFrameBuffer(1);
|
clearFrameBuffer(1);
|
||||||
brtCtrlOEv2(brightness, 1);
|
brtCtrlOEv2(brightness, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,7 +770,7 @@ private:
|
||||||
/**
|
/**
|
||||||
* @brief - DP3246-family chips initialization routine
|
* @brief - DP3246-family chips initialization routine
|
||||||
*/
|
*/
|
||||||
void dp3246init(const HUB75_I2S_CFG& _cfg);
|
void dp3246init(const HUB75_I2S_CFG &_cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief - reset OE bits in DMA buffer in a way to control brightness
|
* @brief - reset OE bits in DMA buffer in a way to control brightness
|
||||||
|
@ -841,7 +834,6 @@ protected:
|
||||||
Bus_Parallel16 dma_bus;
|
Bus_Parallel16 dma_bus;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Matrix i2s settings
|
// Matrix i2s settings
|
||||||
HUB75_I2S_CFG m_cfg;
|
HUB75_I2S_CFG m_cfg;
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,14 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
|
|
||||||
/----------------------------------------------------------------------------*/
|
/----------------------------------------------------------------------------*/
|
||||||
#include <sdkconfig.h>
|
#include <sdkconfig.h>
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32) || defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32) || defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
#include "esp32_i2s_parallel_dma.hpp"
|
#include "esp32_i2s_parallel_dma.hpp"
|
||||||
|
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
#pragma message "Compiling for ESP32-S2"
|
#pragma message "Compiling for ESP32-S2"
|
||||||
#else
|
#else
|
||||||
#pragma message "Compiling for original ESP32 (released 2016)"
|
#pragma message "Compiling for original ESP32 (released 2016)"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
|
@ -39,8 +39,7 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
#include <soc/gpio_sig_map.h>
|
#include <soc/gpio_sig_map.h>
|
||||||
#include <soc/i2s_periph.h> //includes struct and reg
|
#include <soc/i2s_periph.h> //includes struct and reg
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
#if defined (ARDUINO_ARCH_ESP32)
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -50,65 +49,68 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
// Get CPU freq function.
|
// Get CPU freq function.
|
||||||
#include <soc/rtc.h>
|
#include <soc/rtc.h>
|
||||||
|
|
||||||
|
volatile bool previousBufferFree = true;
|
||||||
|
|
||||||
volatile bool previousBufferFree = true;
|
static void IRAM_ATTR i2s_isr(void *arg)
|
||||||
|
{
|
||||||
static void IRAM_ATTR i2s_isr(void* arg) {
|
|
||||||
|
|
||||||
// From original Sprite_TM Code
|
// From original Sprite_TM Code
|
||||||
//REG_WRITE(I2S_INT_CLR_REG(1), (REG_READ(I2S_INT_RAW_REG(1)) & 0xffffffc0) | 0x3f);
|
// REG_WRITE(I2S_INT_CLR_REG(1), (REG_READ(I2S_INT_RAW_REG(1)) & 0xffffffc0) | 0x3f);
|
||||||
|
|
||||||
// Clear flag so we can get retriggered
|
// Clear flag so we can get retriggered
|
||||||
SET_PERI_REG_BITS(I2S_INT_CLR_REG(ESP32_I2S_DEVICE), I2S_OUT_EOF_INT_CLR_V, 1, I2S_OUT_EOF_INT_CLR_S);
|
SET_PERI_REG_BITS(I2S_INT_CLR_REG(ESP32_I2S_DEVICE), I2S_OUT_EOF_INT_CLR_V, 1, I2S_OUT_EOF_INT_CLR_S);
|
||||||
|
|
||||||
// at this point, the previously active buffer is free, go ahead and write to it
|
// at this point, the previously active buffer is free, go ahead and write to it
|
||||||
previousBufferFree = true;
|
previousBufferFree = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DRAM_ATTR i2s_parallel_is_previous_buffer_free() {
|
bool DRAM_ATTR i2s_parallel_is_previous_buffer_free()
|
||||||
|
{
|
||||||
return previousBufferFree;
|
return previousBufferFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Static
|
||||||
// Static
|
i2s_dev_t *getDev()
|
||||||
i2s_dev_t* getDev()
|
{
|
||||||
{
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
return &I2S0;
|
return &I2S0;
|
||||||
#else
|
#else
|
||||||
return (ESP32_I2S_DEVICE == 0) ? &I2S0 : &I2S1;
|
return (ESP32_I2S_DEVICE == 0) ? &I2S0 : &I2S1;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
}
|
// Static
|
||||||
|
void _gpio_pin_init(int pin)
|
||||||
// Static
|
{
|
||||||
void _gpio_pin_init(int pin)
|
|
||||||
{
|
|
||||||
if (pin >= 0)
|
if (pin >= 0)
|
||||||
{
|
{
|
||||||
gpio_pad_select_gpio(pin);
|
gpio_pad_select_gpio(pin);
|
||||||
//gpio_hi(pin);
|
// gpio_hi(pin);
|
||||||
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_OUTPUT);
|
gpio_set_direction((gpio_num_t)pin, GPIO_MODE_OUTPUT);
|
||||||
gpio_set_drive_capability((gpio_num_t)pin, (gpio_drive_cap_t)3); // esp32s3 as well?
|
gpio_set_drive_capability((gpio_num_t)pin, (gpio_drive_cap_t)3); // esp32s3 as well?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int i2s_parallel_get_memory_width(int port, int width) {
|
inline int i2s_parallel_get_memory_width(int port, int width)
|
||||||
switch(width) {
|
{
|
||||||
|
switch (width)
|
||||||
|
{
|
||||||
case 8:
|
case 8:
|
||||||
|
|
||||||
#if !defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
// Only I2S1 on the legacy ESP32 WROOM MCU supports space saving single byte 8 bit parallel access
|
// Only I2S1 on the legacy ESP32 WROOM MCU supports space saving single byte 8 bit parallel access
|
||||||
if(port == 1)
|
if (port == 1)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
return 2;
|
return 2;
|
||||||
|
@ -117,21 +119,21 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
default:
|
default:
|
||||||
return -ESP_ERR_INVALID_ARG;
|
return -ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bus_Parallel16::config(const config_t &cfg)
|
||||||
void Bus_Parallel16::config(const config_t& cfg)
|
{
|
||||||
{
|
|
||||||
ESP_LOGI("ESP32/S2", "Performing config for ESP32 or ESP32-S2");
|
ESP_LOGI("ESP32/S2", "Performing config for ESP32 or ESP32-S2");
|
||||||
_cfg = cfg;
|
_cfg = cfg;
|
||||||
_dev = getDev();
|
_dev = getDev();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bus_Parallel16::init(void) // The big one that gets everything setup.
|
bool Bus_Parallel16::init(void) // The big one that gets everything setup.
|
||||||
{
|
{
|
||||||
ESP_LOGI("ESP32/S2", "Performing DMA bus init() for ESP32 or ESP32-S2");
|
ESP_LOGI("ESP32/S2", "Performing DMA bus init() for ESP32 or ESP32-S2");
|
||||||
|
|
||||||
if(_cfg.parallel_width < 8 || _cfg.parallel_width >= 24) {
|
if (_cfg.parallel_width < 8 || _cfg.parallel_width >= 24)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +151,8 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
iomux_clock = I2S0O_WS_OUT_IDX;
|
iomux_clock = I2S0O_WS_OUT_IDX;
|
||||||
irq_source = ETS_I2S0_INTR_SOURCE;
|
irq_source = ETS_I2S0_INTR_SOURCE;
|
||||||
|
|
||||||
switch(_cfg.parallel_width) {
|
switch (_cfg.parallel_width)
|
||||||
|
{
|
||||||
case 8:
|
case 8:
|
||||||
case 16:
|
case 16:
|
||||||
iomux_signal_base = I2S0O_DATA_OUT8_IDX;
|
iomux_signal_base = I2S0O_DATA_OUT8_IDX;
|
||||||
|
@ -162,15 +165,17 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
// Can't compile if I2S1 if it doesn't exist with that hardware's IDF....
|
// Can't compile if I2S1 if it doesn't exist with that hardware's IDF....
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
periph_module_reset(PERIPH_I2S1_MODULE);
|
periph_module_reset(PERIPH_I2S1_MODULE);
|
||||||
periph_module_enable(PERIPH_I2S1_MODULE);
|
periph_module_enable(PERIPH_I2S1_MODULE);
|
||||||
iomux_clock = I2S1O_WS_OUT_IDX;
|
iomux_clock = I2S1O_WS_OUT_IDX;
|
||||||
irq_source = ETS_I2S1_INTR_SOURCE;
|
irq_source = ETS_I2S1_INTR_SOURCE;
|
||||||
|
|
||||||
switch(_cfg.parallel_width) {
|
switch (_cfg.parallel_width)
|
||||||
|
{
|
||||||
case 16:
|
case 16:
|
||||||
iomux_signal_base = I2S1O_DATA_OUT8_IDX;
|
iomux_signal_base = I2S1O_DATA_OUT8_IDX;
|
||||||
break;
|
break;
|
||||||
|
@ -182,7 +187,7 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
return ESP_ERR_INVALID_ARG;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Setup GPIOs
|
// Setup GPIOs
|
||||||
int bus_width = _cfg.parallel_width;
|
int bus_width = _cfg.parallel_width;
|
||||||
|
@ -193,17 +198,19 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
_gpio_pin_init(_cfg.pin_rs); // not used
|
_gpio_pin_init(_cfg.pin_rs); // not used
|
||||||
|
|
||||||
// Data output GPIO setup
|
// Data output GPIO setup
|
||||||
int8_t* pins = _cfg.pin_data;
|
int8_t *pins = _cfg.pin_data;
|
||||||
|
|
||||||
for(int i = 0; i < bus_width; i++)
|
for (int i = 0; i < bus_width; i++)
|
||||||
_gpio_pin_init(pins[i]);
|
_gpio_pin_init(pins[i]);
|
||||||
|
|
||||||
// Route clock signal to clock pin
|
// Route clock signal to clock pin
|
||||||
gpio_matrix_out(_cfg.pin_wr, iomux_clock, _cfg.invert_pclk, 0); // inverst clock if required
|
gpio_matrix_out(_cfg.pin_wr, iomux_clock, _cfg.invert_pclk, 0); // inverst clock if required
|
||||||
|
|
||||||
for (size_t i = 0; i < bus_width; i++) {
|
for (size_t i = 0; i < bus_width; i++)
|
||||||
|
{
|
||||||
|
|
||||||
if (pins[i] >= 0) {
|
if (pins[i] >= 0)
|
||||||
|
{
|
||||||
gpio_matrix_out(pins[i], iomux_signal_base + i, false, false);
|
gpio_matrix_out(pins[i], iomux_signal_base + i, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,28 +218,28 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
////////////////////////////// Clock configuration //////////////////////////////
|
////////////////////////////// Clock configuration //////////////////////////////
|
||||||
|
|
||||||
unsigned int freq = (_cfg.bus_freq);
|
unsigned int freq = (_cfg.bus_freq);
|
||||||
ESP_LOGD("ESP32/S2", "Requested output clock frequency: %u Mhz", (unsigned int)(freq/1000000));
|
ESP_LOGD("ESP32/S2", "Requested output clock frequency: %u Mhz", (unsigned int)(freq / 1000000));
|
||||||
|
|
||||||
// What is the current CPU frequency?
|
// What is the current CPU frequency?
|
||||||
|
|
||||||
// Calculate clock divider for ESP32-S2
|
// Calculate clock divider for ESP32-S2
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
// Right shift (>> 1) and divide 160mhz in half to 80Mhz for the calc due to the fact
|
// Right shift (>> 1) and divide 160mhz in half to 80Mhz for the calc due to the fact
|
||||||
// that later we must have tx_bck_div_num = 2 for both esp32 and esp32-s2
|
// that later we must have tx_bck_div_num = 2 for both esp32 and esp32-s2
|
||||||
|
|
||||||
//static uint32_t pll_160M_clock_d2 = 160 * 1000 * 1000 >> 1;
|
// static uint32_t pll_160M_clock_d2 = 160 * 1000 * 1000 >> 1;
|
||||||
|
|
||||||
// I2S_CLKM_DIV_NUM 2=40MHz / 3=27MHz / 4=20MHz / 5=16MHz / 8=10MHz / 10=8MHz
|
// I2S_CLKM_DIV_NUM 2=40MHz / 3=27MHz / 4=20MHz / 5=16MHz / 8=10MHz / 10=8MHz
|
||||||
//auto _div_num = std::min(255u, 1 + ((pll_160M_clock_d2) / (1 + freq)));
|
// auto _div_num = std::min(255u, 1 + ((pll_160M_clock_d2) / (1 + freq)));
|
||||||
unsigned int _div_num = (unsigned int) (160000000L / freq / i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)); // 16 bits in parallel
|
unsigned int _div_num = (unsigned int)(160000000L / freq / i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)); // 16 bits in parallel
|
||||||
|
|
||||||
if(_div_num < 2 || _div_num > 0xFF) {
|
if (_div_num < 2 || _div_num > 0xFF)
|
||||||
|
{
|
||||||
// return ESP_ERR_INVALID_ARG;
|
// return ESP_ERR_INVALID_ARG;
|
||||||
_div_num = 8;
|
_div_num = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ESP_LOGD("ESP32", "i2s pll_160M_clock_d2 clkm_div_num is: %u", _div_num);
|
ESP_LOGD("ESP32", "i2s pll_160M_clock_d2 clkm_div_num is: %u", _div_num);
|
||||||
|
|
||||||
// I2S_CLK_SEL Set this bit to select I2S module clock source.
|
// I2S_CLK_SEL Set this bit to select I2S module clock source.
|
||||||
|
@ -244,10 +251,10 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dev->clkm_conf.clk_en = 1;
|
dev->clkm_conf.clk_en = 1;
|
||||||
|
|
||||||
// Calc
|
// Calc
|
||||||
unsigned int output_freq = (unsigned int)(160000000L/_div_num);
|
unsigned int output_freq = (unsigned int)(160000000L / _div_num);
|
||||||
|
|
||||||
// Calculate clock divider for Original ESP32
|
// Calculate clock divider for Original ESP32
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Note: clkm_div_num must only be set here AFTER clkm_div_b, clkm_div_a, etc. Or weird things happen!
|
// Note: clkm_div_num must only be set here AFTER clkm_div_b, clkm_div_a, etc. Or weird things happen!
|
||||||
// On original ESP32, max I2S DMA parallel speed is 20Mhz.
|
// On original ESP32, max I2S DMA parallel speed is 20Mhz.
|
||||||
|
@ -255,34 +262,35 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
// 160Mhz is only assured when the CPU clock is 240Mhz on the ESP32...
|
// 160Mhz is only assured when the CPU clock is 240Mhz on the ESP32...
|
||||||
// [esp32-hal-cpu.c:244] setCpuFrequencyMhz(): PLL: 480 / 2 = 240 Mhz, APB: 80000000 Hz
|
// [esp32-hal-cpu.c:244] setCpuFrequencyMhz(): PLL: 480 / 2 = 240 Mhz, APB: 80000000 Hz
|
||||||
|
|
||||||
//static uint32_t pll_d2_clock = (source_freq/2) * 1000 * 1000 >> 1;
|
// static uint32_t pll_d2_clock = (source_freq/2) * 1000 * 1000 >> 1;
|
||||||
|
|
||||||
// I2S_CLKM_DIV_NUM 2=40MHz / 3=27MHz / 4=20MHz / 5=16MHz / 8=10MHz / 10=8MHz
|
// I2S_CLKM_DIV_NUM 2=40MHz / 3=27MHz / 4=20MHz / 5=16MHz / 8=10MHz / 10=8MHz
|
||||||
//auto _div_num = std::min(255u, 1 + ((pll_d2_clock) / (1 + freq)));
|
// auto _div_num = std::min(255u, 1 + ((pll_d2_clock) / (1 + freq)));
|
||||||
|
|
||||||
unsigned int _div_num = (unsigned int) (80000000L / freq / i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)); // 16 bits in parallel
|
unsigned int _div_num = (unsigned int)(80000000L / freq / i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)); // 16 bits in parallel
|
||||||
if(_div_num < 2 || _div_num > 0xFF) {
|
if (_div_num < 2 || _div_num > 0xFF)
|
||||||
|
{
|
||||||
// return ESP_ERR_INVALID_ARG;
|
// return ESP_ERR_INVALID_ARG;
|
||||||
_div_num = 4;
|
_div_num = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
///auto _div_num = 80000000L/freq;
|
_div_num = 1;
|
||||||
|
|
||||||
|
/// auto _div_num = 80000000L/freq;
|
||||||
|
|
||||||
ESP_LOGD("ESP32", "i2s pll_d2_clock clkm_div_num is: %u", _div_num);
|
ESP_LOGD("ESP32", "i2s pll_d2_clock clkm_div_num is: %u", _div_num);
|
||||||
|
|
||||||
dev->clkm_conf.clka_en=1; // Use the 80mhz system clock (PLL_D2_CLK) when '0'
|
dev->clkm_conf.clka_en = 1; // Use the 80mhz system clock (PLL_D2_CLK) when '0'
|
||||||
dev->clkm_conf.clkm_div_a = 1; // Clock denominator
|
dev->clkm_conf.clkm_div_a = 1; // Clock denominator
|
||||||
dev->clkm_conf.clkm_div_b = 0; // Clock numerator
|
dev->clkm_conf.clkm_div_b = 0; // Clock numerator
|
||||||
dev->clkm_conf.clkm_div_num = _div_num;
|
dev->clkm_conf.clkm_div_num = _div_num;
|
||||||
|
|
||||||
unsigned int output_freq = (unsigned int)(80000000L/_div_num);
|
unsigned int output_freq = (unsigned int)(80000000L / _div_num);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
output_freq = output_freq + 0; // work around arudino 'unused var' issue if debug isn't enabled.
|
output_freq = output_freq + 0; // work around arudino 'unused var' issue if debug isn't enabled.
|
||||||
ESP_LOGI("ESP32/S2", "Output frequency is %u Mhz??", (unsigned int)(output_freq/1000000/i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)));
|
ESP_LOGI("ESP32/S2", "Output frequency is %u Mhz??", (unsigned int)(output_freq / 1000000 / i2s_parallel_get_memory_width(ESP32_I2S_DEVICE, 16)));
|
||||||
|
|
||||||
|
|
||||||
// Setup i2s clock
|
// Setup i2s clock
|
||||||
dev->sample_rate_conf.val = 0;
|
dev->sample_rate_conf.val = 0;
|
||||||
|
@ -301,16 +309,16 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
// I2S conf2 reg
|
// I2S conf2 reg
|
||||||
dev->conf2.val = 0;
|
dev->conf2.val = 0;
|
||||||
dev->conf2.lcd_en = 1;
|
dev->conf2.lcd_en = 1;
|
||||||
dev->conf2.lcd_tx_wrx2_en=0;
|
dev->conf2.lcd_tx_wrx2_en = 0;
|
||||||
dev->conf2.lcd_tx_sdx2_en=0;
|
dev->conf2.lcd_tx_sdx2_en = 0;
|
||||||
|
|
||||||
// I2S conf reg
|
// I2S conf reg
|
||||||
dev->conf.val = 0;
|
dev->conf.val = 0;
|
||||||
|
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
dev->conf.tx_dma_equal=1; // esp32-s2 only
|
dev->conf.tx_dma_equal = 1; // esp32-s2 only
|
||||||
dev->conf.pre_req_en=1; // esp32-s2 only - enable I2S to prepare data earlier? wtf?
|
dev->conf.pre_req_en = 1; // esp32-s2 only - enable I2S to prepare data earlier? wtf?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Now start setting up DMA FIFO
|
// Now start setting up DMA FIFO
|
||||||
dev->fifo_conf.val = 0;
|
dev->fifo_conf.val = 0;
|
||||||
|
@ -318,19 +326,22 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dev->fifo_conf.tx_data_num = 32;
|
dev->fifo_conf.tx_data_num = 32;
|
||||||
dev->fifo_conf.dscr_en = 1;
|
dev->fifo_conf.dscr_en = 1;
|
||||||
|
|
||||||
#if !defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if !defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
|
||||||
// Enable "One datum will be written twice in LCD mode" - for some reason,
|
// Enable "One datum will be written twice in LCD mode" - for some reason,
|
||||||
// if we don't do this in 8-bit mode, data is updated on half-clocks not clocks
|
// if we don't do this in 8-bit mode, data is updated on half-clocks not clocks
|
||||||
if(_cfg.parallel_width == 8)
|
if (_cfg.parallel_width == 8)
|
||||||
dev->conf2.lcd_tx_wrx2_en=1;
|
dev->conf2.lcd_tx_wrx2_en = 1;
|
||||||
|
|
||||||
// Not really described for non-pcm modes, although datasheet states it should be set correctly even for LCD mode
|
// Not really described for non-pcm modes, although datasheet states it should be set correctly even for LCD mode
|
||||||
// First stage config. Configures how data is loaded into fifo
|
// First stage config. Configures how data is loaded into fifo
|
||||||
if(_cfg.parallel_width == 24) {
|
if (_cfg.parallel_width == 24)
|
||||||
|
{
|
||||||
// Mode 0, single 32-bit channel, linear 32 bit load to fifo
|
// Mode 0, single 32-bit channel, linear 32 bit load to fifo
|
||||||
dev->fifo_conf.tx_fifo_mod = 3;
|
dev->fifo_conf.tx_fifo_mod = 3;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Mode 1, single 16-bit channel, load 16 bit sample(*) into fifo and pad to 32 bit with zeros
|
// Mode 1, single 16-bit channel, load 16 bit sample(*) into fifo and pad to 32 bit with zeros
|
||||||
// *Actually a 32 bit read where two samples are read at once. Length of fifo must thus still be word-aligned
|
// *Actually a 32 bit read where two samples are read at once. Length of fifo must thus still be word-aligned
|
||||||
dev->fifo_conf.tx_fifo_mod = 1;
|
dev->fifo_conf.tx_fifo_mod = 1;
|
||||||
|
@ -347,24 +358,25 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dev->conf_chan.tx_chan_mod = 1;
|
dev->conf_chan.tx_chan_mod = 1;
|
||||||
dev->conf_chan.rx_chan_mod = 1;
|
dev->conf_chan.rx_chan_mod = 1;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Reset FIFO
|
// Reset FIFO
|
||||||
dev->conf.rx_fifo_reset = 1;
|
dev->conf.rx_fifo_reset = 1;
|
||||||
|
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
while(dev->conf.rx_fifo_reset_st); // esp32-s2 only
|
while (dev->conf.rx_fifo_reset_st)
|
||||||
#endif
|
; // esp32-s2 only
|
||||||
|
#endif
|
||||||
|
|
||||||
dev->conf.rx_fifo_reset = 0;
|
dev->conf.rx_fifo_reset = 0;
|
||||||
dev->conf.tx_fifo_reset = 1;
|
dev->conf.tx_fifo_reset = 1;
|
||||||
|
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
while(dev->conf.tx_fifo_reset_st); // esp32-s2 only
|
while (dev->conf.tx_fifo_reset_st)
|
||||||
#endif
|
; // esp32-s2 only
|
||||||
|
#endif
|
||||||
dev->conf.tx_fifo_reset = 0;
|
dev->conf.tx_fifo_reset = 0;
|
||||||
|
|
||||||
|
|
||||||
// Reset DMA
|
// Reset DMA
|
||||||
dev->lc_conf.in_rst = 1;
|
dev->lc_conf.in_rst = 1;
|
||||||
dev->lc_conf.in_rst = 0;
|
dev->lc_conf.in_rst = 0;
|
||||||
|
@ -377,18 +389,16 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dev->in_link.val = 0;
|
dev->in_link.val = 0;
|
||||||
dev->out_link.val = 0;
|
dev->out_link.val = 0;
|
||||||
|
|
||||||
|
|
||||||
// Device reset
|
// Device reset
|
||||||
dev->conf.rx_reset=1;
|
dev->conf.rx_reset = 1;
|
||||||
dev->conf.tx_reset=1;
|
dev->conf.tx_reset = 1;
|
||||||
dev->conf.rx_reset=0;
|
dev->conf.rx_reset = 0;
|
||||||
dev->conf.tx_reset=0;
|
dev->conf.tx_reset = 0;
|
||||||
|
|
||||||
dev->conf1.val = 0;
|
dev->conf1.val = 0;
|
||||||
dev->conf1.tx_stop_en = 0;
|
dev->conf1.tx_stop_en = 0;
|
||||||
dev->timing.val = 0;
|
dev->timing.val = 0;
|
||||||
|
|
||||||
|
|
||||||
// If we have double buffering, then allocate an interrupt service routine function
|
// If we have double buffering, then allocate an interrupt service routine function
|
||||||
// that can be used for I2S0/I2S1 created interrupts.
|
// that can be used for I2S0/I2S1 created interrupts.
|
||||||
|
|
||||||
|
@ -398,19 +408,17 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
// Allocate a level 1 intterupt: lowest priority, as ISR isn't urgent and may take a long time to complete
|
// Allocate a level 1 intterupt: lowest priority, as ISR isn't urgent and may take a long time to complete
|
||||||
esp_intr_alloc(irq_source, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), i2s_isr, NULL, NULL);
|
esp_intr_alloc(irq_source, (int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1), i2s_isr, NULL, NULL);
|
||||||
|
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32S2)
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
|
||||||
ESP_LOGD("ESP32-S2", "init() GPIO and clock configuration set for ESP32-S2");
|
ESP_LOGD("ESP32-S2", "init() GPIO and clock configuration set for ESP32-S2");
|
||||||
#else
|
#else
|
||||||
ESP_LOGD("ESP32-ORIG", "init() GPIO and clock configuration set for ESP32");
|
ESP_LOGD("ESP32-ORIG", "init() GPIO and clock configuration set for ESP32");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Bus_Parallel16::release(void)
|
||||||
void Bus_Parallel16::release(void)
|
{
|
||||||
{
|
|
||||||
if (_dmadesc_a)
|
if (_dmadesc_a)
|
||||||
{
|
{
|
||||||
heap_caps_free(_dmadesc_a);
|
heap_caps_free(_dmadesc_a);
|
||||||
|
@ -424,24 +432,25 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
_dmadesc_b = nullptr;
|
_dmadesc_b = nullptr;
|
||||||
_dmadesc_count = 0;
|
_dmadesc_count = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus_Parallel16::enable_double_dma_desc(void)
|
void Bus_Parallel16::enable_double_dma_desc(void)
|
||||||
{
|
{
|
||||||
_double_dma_buffer = true;
|
_double_dma_buffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need this to work for double buffers etc.
|
// Need this to work for double buffers etc.
|
||||||
bool Bus_Parallel16::allocate_dma_desc_memory(size_t len)
|
bool Bus_Parallel16::allocate_dma_desc_memory(size_t len)
|
||||||
{
|
{
|
||||||
if (_dmadesc_a) heap_caps_free(_dmadesc_a); // free all dma descrptios previously
|
if (_dmadesc_a)
|
||||||
|
heap_caps_free(_dmadesc_a); // free all dma descrptios previously
|
||||||
|
|
||||||
_dmadesc_count = len;
|
_dmadesc_count = len;
|
||||||
_dmadesc_last = len-1;
|
_dmadesc_last = len - 1;
|
||||||
|
|
||||||
ESP_LOGI("ESP32/S2", "Allocating memory for %d DMA descriptors.", (int)len);
|
ESP_LOGI("ESP32/S2", "Allocating memory for %d DMA descriptors.", (int)len);
|
||||||
|
|
||||||
_dmadesc_a= (HUB75_DMA_DESCRIPTOR_T*)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * len, MALLOC_CAP_DMA);
|
_dmadesc_a = (HUB75_DMA_DESCRIPTOR_T *)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * len, MALLOC_CAP_DMA);
|
||||||
|
|
||||||
if (_dmadesc_a == nullptr)
|
if (_dmadesc_a == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -449,14 +458,14 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_double_dma_buffer)
|
if (_double_dma_buffer)
|
||||||
{
|
{
|
||||||
if (_dmadesc_b) heap_caps_free(_dmadesc_b); // free all dma descrptios previously
|
if (_dmadesc_b)
|
||||||
|
heap_caps_free(_dmadesc_b); // free all dma descrptios previously
|
||||||
|
|
||||||
ESP_LOGD("ESP32/S2", "Allocating the second buffer (double buffer enabled).");
|
ESP_LOGD("ESP32/S2", "Allocating the second buffer (double buffer enabled).");
|
||||||
|
|
||||||
_dmadesc_b = (HUB75_DMA_DESCRIPTOR_T*)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * len, MALLOC_CAP_DMA);
|
_dmadesc_b = (HUB75_DMA_DESCRIPTOR_T *)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * len, MALLOC_CAP_DMA);
|
||||||
|
|
||||||
if (_dmadesc_b == nullptr)
|
if (_dmadesc_b == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -472,23 +481,22 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
ESP_LOGD("ESP32/S2", "Allocating %d bytes of memory for DMA descriptors.", (int)sizeof(HUB75_DMA_DESCRIPTOR_T) * len);
|
ESP_LOGD("ESP32/S2", "Allocating %d bytes of memory for DMA descriptors.", (int)sizeof(HUB75_DMA_DESCRIPTOR_T) * len);
|
||||||
|
|
||||||
// New - Temporary blank descriptor for transitions between DMA buffer
|
// New - Temporary blank descriptor for transitions between DMA buffer
|
||||||
_dmadesc_blank = (HUB75_DMA_DESCRIPTOR_T*)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * 1, MALLOC_CAP_DMA);
|
_dmadesc_blank = (HUB75_DMA_DESCRIPTOR_T *)heap_caps_malloc(sizeof(HUB75_DMA_DESCRIPTOR_T) * 1, MALLOC_CAP_DMA);
|
||||||
_dmadesc_blank->size = 1024*2;
|
_dmadesc_blank->size = 1024 * 2;
|
||||||
_dmadesc_blank->length = 1024*2;
|
_dmadesc_blank->length = 1024 * 2;
|
||||||
_dmadesc_blank->buf = (uint8_t*) _blank_data;
|
_dmadesc_blank->buf = (uint8_t *)_blank_data;
|
||||||
_dmadesc_blank->eof = 1;
|
_dmadesc_blank->eof = 1;
|
||||||
_dmadesc_blank->sosf = 0;
|
_dmadesc_blank->sosf = 0;
|
||||||
_dmadesc_blank->owner = 1;
|
_dmadesc_blank->owner = 1;
|
||||||
_dmadesc_blank->qe.stqe_next = (lldesc_t*) _dmadesc_blank;
|
_dmadesc_blank->qe.stqe_next = (lldesc_t *)_dmadesc_blank;
|
||||||
_dmadesc_blank->offset = 0;
|
_dmadesc_blank->offset = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
void Bus_Parallel16::create_dma_desc_link(void *data, size_t size, bool dmadesc_b)
|
||||||
|
{
|
||||||
void Bus_Parallel16::create_dma_desc_link(void *data, size_t size, bool dmadesc_b)
|
static constexpr size_t MAX_DMA_LEN = (4096 - 4);
|
||||||
{
|
|
||||||
static constexpr size_t MAX_DMA_LEN = (4096-4);
|
|
||||||
|
|
||||||
if (size > MAX_DMA_LEN)
|
if (size > MAX_DMA_LEN)
|
||||||
{
|
{
|
||||||
|
@ -496,9 +504,10 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
ESP_LOGW("ESP32/S2", "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
ESP_LOGW("ESP32/S2", "Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !dmadesc_b )
|
if (!dmadesc_b)
|
||||||
|
{
|
||||||
|
if ((_dmadesc_a_idx + 1) > _dmadesc_count)
|
||||||
{
|
{
|
||||||
if ( (_dmadesc_a_idx+1) > _dmadesc_count) {
|
|
||||||
ESP_LOGE("ESP32/S2", "Attempted to create more DMA descriptors than allocated memory for. Expecting a maximum of %u DMA descriptors", (unsigned int)_dmadesc_count);
|
ESP_LOGE("ESP32/S2", "Attempted to create more DMA descriptors than allocated memory for. Expecting a maximum of %u DMA descriptors", (unsigned int)_dmadesc_count);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -508,11 +517,11 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
volatile lldesc_t *next;
|
volatile lldesc_t *next;
|
||||||
bool eof = false;
|
bool eof = false;
|
||||||
|
|
||||||
if ( (dmadesc_b == true) ) // for primary buffer
|
if ((dmadesc_b == true)) // for primary buffer
|
||||||
{
|
{
|
||||||
dmadesc = &_dmadesc_b[_dmadesc_b_idx];
|
dmadesc = &_dmadesc_b[_dmadesc_b_idx];
|
||||||
|
|
||||||
next = (_dmadesc_b_idx < (_dmadesc_last) ) ? &_dmadesc_b[_dmadesc_b_idx+1]:_dmadesc_b;
|
next = (_dmadesc_b_idx < (_dmadesc_last)) ? &_dmadesc_b[_dmadesc_b_idx + 1] : _dmadesc_b;
|
||||||
eof = (_dmadesc_b_idx == (_dmadesc_last));
|
eof = (_dmadesc_b_idx == (_dmadesc_last));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -520,40 +529,44 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dmadesc = &_dmadesc_a[_dmadesc_a_idx];
|
dmadesc = &_dmadesc_a[_dmadesc_a_idx];
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/47170740/c-negative-array-index
|
// https://stackoverflow.com/questions/47170740/c-negative-array-index
|
||||||
next = (_dmadesc_a_idx < (_dmadesc_last) ) ? _dmadesc_a + _dmadesc_a_idx+1:_dmadesc_a;
|
next = (_dmadesc_a_idx < (_dmadesc_last)) ? _dmadesc_a + _dmadesc_a_idx + 1 : _dmadesc_a;
|
||||||
eof = (_dmadesc_a_idx == (_dmadesc_last));
|
eof = (_dmadesc_a_idx == (_dmadesc_last));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _dmadesc_a_idx == (_dmadesc_last) ) {
|
if (_dmadesc_a_idx == (_dmadesc_last))
|
||||||
|
{
|
||||||
ESP_LOGW("ESP32/S2", "Creating final DMA descriptor and linking back to 0.");
|
ESP_LOGW("ESP32/S2", "Creating final DMA descriptor and linking back to 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
dmadesc->size = size;
|
dmadesc->size = size;
|
||||||
dmadesc->length = size;
|
dmadesc->length = size;
|
||||||
dmadesc->buf = (uint8_t*) data;
|
dmadesc->buf = (uint8_t *)data;
|
||||||
dmadesc->eof = eof;
|
dmadesc->eof = eof;
|
||||||
dmadesc->sosf = 0;
|
dmadesc->sosf = 0;
|
||||||
dmadesc->owner = 1;
|
dmadesc->owner = 1;
|
||||||
dmadesc->qe.stqe_next = (lldesc_t*) next;
|
dmadesc->qe.stqe_next = (lldesc_t *)next;
|
||||||
dmadesc->offset = 0;
|
dmadesc->offset = 0;
|
||||||
|
|
||||||
if ( (dmadesc_b == true) ) { // for primary buffer
|
if ((dmadesc_b == true))
|
||||||
|
{ // for primary buffer
|
||||||
_dmadesc_b_idx++;
|
_dmadesc_b_idx++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_dmadesc_a_idx++;
|
_dmadesc_a_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end create_dma_desc_link
|
} // end create_dma_desc_link
|
||||||
|
|
||||||
void Bus_Parallel16::dma_transfer_start()
|
void Bus_Parallel16::dma_transfer_start()
|
||||||
{
|
{
|
||||||
auto dev = _dev;
|
auto dev = _dev;
|
||||||
|
|
||||||
// Configure DMA burst mode
|
// Configure DMA burst mode
|
||||||
dev->lc_conf.val = I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN;
|
dev->lc_conf.val = I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN;
|
||||||
|
|
||||||
// Set address of DMA descriptor, start with buffer 0 / 'a'
|
// Set address of DMA descriptor, start with buffer 0 / 'a'
|
||||||
dev->out_link.addr = (uint32_t) _dmadesc_a;
|
dev->out_link.addr = (uint32_t)_dmadesc_a;
|
||||||
|
|
||||||
// Start DMA operation
|
// Start DMA operation
|
||||||
dev->out_link.stop = 0;
|
dev->out_link.stop = 0;
|
||||||
|
@ -561,12 +574,10 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
|
|
||||||
dev->conf.tx_start = 1;
|
dev->conf.tx_start = 1;
|
||||||
|
|
||||||
|
} // end
|
||||||
|
|
||||||
} // end
|
void Bus_Parallel16::dma_transfer_stop()
|
||||||
|
{
|
||||||
|
|
||||||
void Bus_Parallel16::dma_transfer_stop()
|
|
||||||
{
|
|
||||||
auto dev = _dev;
|
auto dev = _dev;
|
||||||
|
|
||||||
// Stop all ongoing DMA operations
|
// Stop all ongoing DMA operations
|
||||||
|
@ -574,39 +585,35 @@ Modified heavily for the ESP32 HUB75 DMA library by:
|
||||||
dev->out_link.start = 0;
|
dev->out_link.start = 0;
|
||||||
dev->conf.tx_start = 0;
|
dev->conf.tx_start = 0;
|
||||||
|
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
void Bus_Parallel16::flip_dma_output_buffer(int buffer_id) // pass by reference so we can change in main matrixpanel class
|
||||||
void Bus_Parallel16::flip_dma_output_buffer(int buffer_id) // pass by reference so we can change in main matrixpanel class
|
{
|
||||||
{
|
|
||||||
|
|
||||||
// Setup interrupt handler which is focussed only on the (page 322 of Tech. Ref. Manual)
|
// Setup interrupt handler which is focussed only on the (page 322 of Tech. Ref. Manual)
|
||||||
// "I2S_OUT_EOF_INT: Triggered when rxlink has finished sending a packet" (when dma linked list with eof = 1 is hit)
|
// "I2S_OUT_EOF_INT: Triggered when rxlink has finished sending a packet" (when dma linked list with eof = 1 is hit)
|
||||||
|
|
||||||
if ( buffer_id == 1) {
|
if (buffer_id == 1)
|
||||||
|
{
|
||||||
|
|
||||||
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0]; // Start sending out _dmadesc_b (or buffer 1)
|
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0]; // Start sending out _dmadesc_b (or buffer 1)
|
||||||
|
|
||||||
//fix _dmadesc_ loop issue #407
|
// fix _dmadesc_ loop issue #407
|
||||||
//need to connect the up comming _dmadesc_ not the old one
|
// need to connect the up comming _dmadesc_ not the old one
|
||||||
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0];
|
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0];
|
||||||
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
|
|
||||||
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0];
|
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0];
|
||||||
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0];
|
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
previousBufferFree = false;
|
previousBufferFree = false;
|
||||||
//while (i2s_parallel_is_previous_buffer_free() == false) {}
|
// while (i2s_parallel_is_previous_buffer_free() == false) {}
|
||||||
while (!previousBufferFree);
|
while (!previousBufferFree)
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end flip
|
|
||||||
|
|
||||||
|
|
||||||
|
} // end flip
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue