Cleanup and a failed attempt to code a fix for #338
Didn't quite work however.
This commit is contained in:
parent
69686a3747
commit
84c250c668
6 changed files with 230 additions and 151 deletions
|
@ -8,15 +8,42 @@ static const char* TAG = "MatrixPanel";
|
||||||
*/
|
*/
|
||||||
#define getRowDataPtr(row, _dpth, buff_id) &(dma_buff.rowBits[row]->data[_dpth * dma_buff.rowBits[row]->width + buff_id*(dma_buff.rowBits[row]->width * dma_buff.rowBits[row]->colour_depth)])
|
#define getRowDataPtr(row, _dpth, buff_id) &(dma_buff.rowBits[row]->data[_dpth * dma_buff.rowBits[row]->width + buff_id*(dma_buff.rowBits[row]->width * dma_buff.rowBits[row]->colour_depth)])
|
||||||
|
|
||||||
// We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel
|
/* We need to update the correct uint16_t in the rowBitStruct array, that gets sent out in parallel
|
||||||
// 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
* 16 bit parallel mode - Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
||||||
// Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual
|
* Irrelevant for ESP32-S2 the way the FIFO ordering works is different - refer to page 679 of S2 technical reference manual
|
||||||
|
*/
|
||||||
#if defined (ESP32_THE_ORIG)
|
#if defined (ESP32_THE_ORIG)
|
||||||
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) (x_coord & 1U ? (x_coord-1):(x_coord+1))
|
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) ((x_coord & 1U) ? (x_coord-1):(x_coord+1))
|
||||||
#else
|
#else
|
||||||
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) x_coord
|
#define ESP32_TX_FIFO_POSITION_ADJUST(x_coord) x_coord
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* This library is designed to take an 8 bit / 1 byte value (0-255) for each R G B colour sub-pixel.
|
||||||
|
* The PIXEL_COLOUR_DEPTH_BITS should always be '8' as a result.
|
||||||
|
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
||||||
|
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
||||||
|
*/
|
||||||
|
#if PIXEL_COLOUR_DEPTH_BITS > 8
|
||||||
|
#error "Color depth bits cannot be greater than 8."
|
||||||
|
#elif PIXEL_COLOUR_DEPTH_BITS < 2
|
||||||
|
#error "Colour depth bits cannot be less than 2."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PIXEL_COLOUR_DEPTH_BITS != 8
|
||||||
|
#define MASK_OFFSET (8 - PIXEL_COLOUR_DEPTH_BITS)
|
||||||
|
#define PIXEL_COLOUR_MASK_BIT(colour_depth_index) (1 << (colour_depth_index + MASK_OFFSET))
|
||||||
|
//static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOUR_DEPTH_BITS;
|
||||||
|
#else
|
||||||
|
#define PIXEL_COLOUR_MASK_BIT(colour_depth_index) (1 << (colour_depth_index))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
|
#else
|
||||||
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
|
@ -38,9 +65,11 @@ bool MatrixPanel_I2S_DMA::allocateDMAmemory()
|
||||||
|
|
||||||
if (ptr->data == nullptr)
|
if (ptr->data == nullptr)
|
||||||
{
|
{
|
||||||
ESP_LOGE(TAG, "CRITICAL ERROR: Can't allocate rowBitStruct %d! Not enough memory for requested PIXEL_COLOUR_DEPTH_BITS. Please reduce PIXEL_COLOUR_DEPTH_BITS value.\r\n", malloc_num);
|
ESP_LOGE(TAG, "CRITICAL ERROR: Not enough memory for requested colour depth! Please reduce PIXEL_COLOUR_DEPTH_BITS value.\r\n");
|
||||||
return false;
|
ESP_LOGE(TAG, "Could not allocate rowBitStruct %d!.\r\n", malloc_num);
|
||||||
// TODO: should we release all previous rowBitStructs here???
|
|
||||||
|
return false;
|
||||||
|
// TODO: should we release all previous rowBitStructs here???
|
||||||
}
|
}
|
||||||
|
|
||||||
allocated_fb_memory += ptr->size();
|
allocated_fb_memory += ptr->size();
|
||||||
|
@ -199,8 +228,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
// Setup DMA and Output to GPIO
|
// Setup DMA and Output to GPIO
|
||||||
//
|
//
|
||||||
auto bus_cfg = dma_bus.config(); // バス設定用の構造体を取得します。
|
auto bus_cfg = dma_bus.config(); // バス設定用の構造体を取得します。
|
||||||
|
|
||||||
//bus_cfg.i2s_port = I2S_NUM_0; // 使用するI2Sポートを選択 (I2S_NUM_0 or I2S_NUM_1) (ESP32のI2S LCDモードを使用します)
|
|
||||||
bus_cfg.bus_freq = _cfg.i2sspeed;
|
bus_cfg.bus_freq = _cfg.i2sspeed;
|
||||||
bus_cfg.pin_wr = m_cfg.gpio.clk; // WR を接続しているピン番号
|
bus_cfg.pin_wr = m_cfg.gpio.clk; // WR を接続しているピン番号
|
||||||
|
|
||||||
|
@ -227,6 +255,7 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
|
||||||
|
|
||||||
dma_bus.dma_transfer_start();
|
dma_bus.dma_transfer_start();
|
||||||
|
|
||||||
|
flipDMABuffer(); // display back buffer 0, draw to 1, ignored if double buffering isn't enabled.
|
||||||
|
|
||||||
//i2s_parallel_send_dma(ESP32_I2S_DEVICE, &dmadesc_a[0]);
|
//i2s_parallel_send_dma(ESP32_I2S_DEVICE, &dmadesc_a[0]);
|
||||||
ESP_LOGI(TAG, "DMA setup completed");
|
ESP_LOGI(TAG, "DMA setup completed");
|
||||||
|
@ -309,12 +338,15 @@ void IRAM_ATTR MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint16_t x_coord, uint
|
||||||
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
do {
|
do {
|
||||||
--colour_depth_idx;
|
--colour_depth_idx;
|
||||||
|
/*
|
||||||
// uint8_t mask = (1 << (colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST)); // expect 24 bit colour (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#else
|
#else
|
||||||
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
uint8_t mask = PIXEL_COLOUR_MASK_BIT(colour_depth_idx);
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
|
@ -357,11 +389,13 @@ void MatrixPanel_I2S_DMA::updateMatrixDMABuffer(uint8_t red, uint8_t green, uint
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST); // 24 bit colour
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST); // 24 bit colour
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
// #if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
// #else
|
||||||
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit colour (8 bits per RGB subpixel)
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
|
uint8_t mask = PIXEL_COLOUR_MASK_BIT(colour_depth_idx);
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
* BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */
|
* BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */
|
||||||
|
@ -693,11 +727,12 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
// #if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
// #else
|
||||||
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
// #endif
|
||||||
|
uint8_t mask = PIXEL_COLOUR_MASK_BIT(colour_depth_idx);
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
* BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */
|
* BIT_B2, BIT_G2, BIT_R2, BIT_B1, BIT_G1, BIT_R1 */
|
||||||
|
@ -717,14 +752,17 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
int16_t _l = l;
|
int16_t _l = l;
|
||||||
do { // iterate pixels in a row
|
do { // iterate pixels in a row
|
||||||
int16_t _x = x_coord + --_l;
|
int16_t _x = x_coord + --_l;
|
||||||
|
|
||||||
#if defined(ESP32_THE_ORIG)
|
/*
|
||||||
// Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
#if defined(ESP32_THE_ORIG)
|
||||||
uint16_t &v = p[_x & 1U ? --_x : ++_x];
|
// Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
||||||
#else
|
uint16_t &v = p[_x & 1U ? --_x : ++_x];
|
||||||
// ESP 32 doesn't need byte flipping for TX FIFO.
|
#else
|
||||||
uint16_t &v = p[_x];
|
// ESP 32 doesn't need byte flipping for TX FIFO.
|
||||||
#endif
|
uint16_t &v = p[_x];
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
uint16_t &v = p[ESP32_TX_FIFO_POSITION_ADJUST(_x)];
|
||||||
|
|
||||||
v &= _colourbitclear; // reset color bits
|
v &= _colourbitclear; // reset color bits
|
||||||
v |= RGB_output_bits; // set new color bits
|
v |= RGB_output_bits; // set new color bits
|
||||||
|
@ -759,10 +797,13 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
blue = lumConvTab[blue];
|
blue = lumConvTab[blue];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
#if defined(ESP32_THE_ORIG)
|
#if defined(ESP32_THE_ORIG)
|
||||||
// Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
// Save the calculated value to the bitplane memory in reverse order to account for I2S Tx FIFO mode1 ordering
|
||||||
x_coord & 1U ? --x_coord : ++x_coord;
|
x_coord & 1U ? --x_coord : ++x_coord;
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
x_coord = ESP32_TX_FIFO_POSITION_ADJUST(x_coord);
|
||||||
|
|
||||||
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
uint8_t colour_depth_idx = PIXEL_COLOUR_DEPTH_BITS;
|
||||||
do { // Iterating through color depth bits (8 iterations)
|
do { // Iterating through color depth bits (8 iterations)
|
||||||
|
@ -770,11 +811,13 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
|
||||||
|
|
||||||
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
// let's precalculate RGB1 and RGB2 bits than flood it over the entire DMA buffer
|
||||||
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
// uint8_t mask = (1 << colour_depth_idx COLOR_DEPTH_LESS_THAN_8BIT_ADJUST);
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS < 8
|
// #if PIXEL_COLOUR_DEPTH_BITS < 8
|
||||||
uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx+MASK_OFFSET)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#else
|
// #else
|
||||||
uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
// uint8_t mask = (1 << (colour_depth_idx)); // expect 24 bit color (8 bits per RGB subpixel)
|
||||||
#endif
|
// #endif
|
||||||
|
|
||||||
|
uint8_t mask = PIXEL_COLOUR_MASK_BIT(colour_depth_idx);
|
||||||
uint16_t RGB_output_bits = 0;
|
uint16_t RGB_output_bits = 0;
|
||||||
|
|
||||||
/* Per the .h file, the order of the output RGB bits is:
|
/* Per the .h file, the order of the output RGB bits is:
|
||||||
|
|
|
@ -8,16 +8,8 @@
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
|
|
||||||
//#include <Arduino.h>
|
//#include <Arduino.h>
|
||||||
|
|
||||||
//#include "freertos/FreeRTOS.h"
|
|
||||||
//#include "freertos/task.h"
|
|
||||||
//#include "freertos/semphr.h"
|
|
||||||
//#include "freertos/queue.h"
|
|
||||||
|
|
||||||
//#include "esp_heap_caps.h"
|
|
||||||
#include "platforms/platform_detect.hpp"
|
#include "platforms/platform_detect.hpp"
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_GFX_ROOT
|
#ifdef USE_GFX_ROOT
|
||||||
#include <FastLED.h>
|
#include <FastLED.h>
|
||||||
#include "GFX.h" // Adafruit GFX core class -> https://github.com/mrfaptastic/GFX_Root
|
#include "GFX.h" // Adafruit GFX core class -> https://github.com/mrfaptastic/GFX_Root
|
||||||
|
@ -119,23 +111,6 @@
|
||||||
// Max clock cycles to blank OE before/after LAT signal change
|
// Max clock cycles to blank OE before/after LAT signal change
|
||||||
#define MAX_LAT_BLANKING 4
|
#define MAX_LAT_BLANKING 4
|
||||||
|
|
||||||
/***************************************************************************************/
|
|
||||||
// Check compile-time only options
|
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS > 8
|
|
||||||
#error "Pixel color depth bits cannot be greater than 8."
|
|
||||||
#elif PIXEL_COLOUR_DEPTH_BITS < 2
|
|
||||||
#error "Pixel color depth bits cannot be less than 2."
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This library is designed to take an 8 bit / 1 byte value (0-255) for each R G B colour sub-pixel.
|
|
||||||
* The PIXEL_COLOUR_DEPTH_BITS should always be '8' as a result.
|
|
||||||
* However, if the library is to be used with lower colour depth (i.e. 6 bit colour), then we need to ensure the 8-bit value passed to the colour masking
|
|
||||||
* is adjusted accordingly to ensure the LSB's are shifted left to MSB, by the difference. Otherwise the colours will be all screwed up.
|
|
||||||
*/
|
|
||||||
#if PIXEL_COLOUR_DEPTH_BITS != 8
|
|
||||||
static constexpr uint8_t const MASK_OFFSET = 8-PIXEL_COLOUR_DEPTH_BITS;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
|
|
||||||
/** @brief - Structure holds raw DMA data to drive TWO full rows of pixels spanning through all chained modules
|
/** @brief - Structure holds raw DMA data to drive TWO full rows of pixels spanning through all chained modules
|
||||||
|
@ -406,7 +381,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
/**
|
/**
|
||||||
* A wrapper to fill whatever selected DMA buffer / screen with black
|
* A wrapper to fill whatever selected DMA buffer / screen with black
|
||||||
*/
|
*/
|
||||||
inline void clearScreen(){ clearFrameBuffer(back_buffer_id); /*updateMatrixDMABuffer(0,0,0);*/ };
|
inline void clearScreen(){ startWrite(); clearFrameBuffer(back_buffer_id); endWrite(); /*updateMatrixDMABuffer(0,0,0);*/ };
|
||||||
|
|
||||||
#ifndef NO_FAST_FUNCTIONS
|
#ifndef NO_FAST_FUNCTIONS
|
||||||
/**
|
/**
|
||||||
|
@ -416,7 +391,9 @@ class MatrixPanel_I2S_DMA {
|
||||||
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
|
virtual void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color){
|
||||||
uint8_t r, g, b;
|
uint8_t r, g, b;
|
||||||
color565to888(color, r, g, b);
|
color565to888(color, r, g, b);
|
||||||
|
startWrite();
|
||||||
vlineDMA(x, y, h, r, g, b);
|
vlineDMA(x, y, h, r, g, b);
|
||||||
|
endWrite();
|
||||||
}
|
}
|
||||||
// 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){ vlineDMA(x, y, h, r, g, b); };
|
virtual inline void drawFastVLine(int16_t x, int16_t y, int16_t h, uint8_t r, uint8_t g, uint8_t b){ vlineDMA(x, y, h, r, g, b); };
|
||||||
|
@ -428,7 +405,9 @@ class MatrixPanel_I2S_DMA {
|
||||||
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
|
virtual void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color){
|
||||||
uint8_t r, g, b;
|
uint8_t r, g, b;
|
||||||
color565to888(color, r, g, b);
|
color565to888(color, r, g, b);
|
||||||
|
startWrite();
|
||||||
hlineDMA(x, y, w, r, g, b);
|
hlineDMA(x, y, w, r, g, b);
|
||||||
|
endWrite();
|
||||||
}
|
}
|
||||||
// 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){ hlineDMA(x, y, w, r, g, b); };
|
virtual inline void drawFastHLine(int16_t x, int16_t y, int16_t w, uint8_t r, uint8_t g, uint8_t b){ hlineDMA(x, y, w, r, g, b); };
|
||||||
|
@ -440,10 +419,16 @@ class MatrixPanel_I2S_DMA {
|
||||||
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
virtual void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color){
|
||||||
uint8_t r, g, b;
|
uint8_t r, g, b;
|
||||||
color565to888(color, r, g, b);
|
color565to888(color, r, g, b);
|
||||||
|
startWrite();
|
||||||
fillRectDMA(x, y, w, h, r, g, b);
|
fillRectDMA(x, y, w, h, r, g, b);
|
||||||
|
endWrite();
|
||||||
}
|
}
|
||||||
// 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){fillRectDMA(x, y, w, h, r, g, 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){
|
||||||
|
startWrite();
|
||||||
|
fillRectDMA(x, y, w, h, r, g, b);
|
||||||
|
endWrite();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b);
|
void fillScreenRGB888(uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
@ -474,22 +459,14 @@ class MatrixPanel_I2S_DMA {
|
||||||
static void color565to888(const uint16_t color, uint8_t &r, uint8_t &g, uint8_t &b);
|
static void color565to888(const uint16_t color, uint8_t &r, uint8_t &g, uint8_t &b);
|
||||||
|
|
||||||
|
|
||||||
inline void IRAM_ATTR flipDMABuffer()
|
inline void flipDMABuffer()
|
||||||
{
|
{
|
||||||
if ( !m_cfg.double_buff) return;
|
if ( !m_cfg.double_buff) { return; }
|
||||||
|
|
||||||
//ESP_LOGI("flipDMABuffer()", "Set back buffer to: %d", back_buffer_id);
|
// while (active_gfx_writes) { } // wait a bit ?
|
||||||
|
// initialized = false;
|
||||||
if (back_buffer_id)
|
dma_bus.flip_dma_output_buffer( back_buffer_id );
|
||||||
{
|
// initialized = true;
|
||||||
dma_bus.set_dma_output_buffer( true );
|
|
||||||
back_buffer_id = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dma_bus.set_dma_output_buffer( false );
|
|
||||||
back_buffer_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
i2s_parallel_set_previous_buffer_not_free();
|
i2s_parallel_set_previous_buffer_not_free();
|
||||||
|
@ -506,8 +483,6 @@ class MatrixPanel_I2S_DMA {
|
||||||
while(i2s_parallel_is_previous_buffer_free() == false) { }
|
while(i2s_parallel_is_previous_buffer_free() == false) { }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setPanelBrightness(int b)
|
inline void setPanelBrightness(int b)
|
||||||
|
@ -562,8 +537,16 @@ class MatrixPanel_I2S_DMA {
|
||||||
//i2s_parallel_stop_dma(ESP32_I2S_DEVICE);
|
//i2s_parallel_stop_dma(ESP32_I2S_DEVICE);
|
||||||
dma_bus.dma_transfer_stop();
|
dma_bus.dma_transfer_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startWrite() {
|
||||||
|
//ESP_LOGI("TAG", "startWrite() called");
|
||||||
|
active_gfx_writes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void endWrite() {
|
||||||
|
active_gfx_writes--;
|
||||||
|
}
|
||||||
|
|
||||||
// ------- PROTECTED -------
|
// ------- PROTECTED -------
|
||||||
// those might be useful for child classes, like VirtualMatrixPanel
|
// those might be useful for child classes, like VirtualMatrixPanel
|
||||||
|
@ -645,6 +628,7 @@ class MatrixPanel_I2S_DMA {
|
||||||
|
|
||||||
// Other private variables
|
// Other private variables
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
int active_gfx_writes = 0; // How many async routines are 'drawing' (writing) to the DMA bit buffer. Function called from Adafruit_GFX draw routines like drawCircle etc.
|
||||||
int back_buffer_id = 0; // If using double buffer, which one is NOT active (ie. being displayed) to write too?
|
int back_buffer_id = 0; // If using double buffer, which one is NOT active (ie. being displayed) to write too?
|
||||||
int brightness = 32; // If you get ghosting... reduce brightness level. 60 seems to be the limit before ghosting on a 64 pixel wide physical panel for some panels.
|
int brightness = 32; // If you get ghosting... reduce brightness level. 60 seems to be the limit before ghosting on a 64 pixel wide physical panel for some panels.
|
||||||
int lsbMsbTransitionBit = 0; // For colour depth calculations
|
int lsbMsbTransitionBit = 0; // For colour depth calculations
|
||||||
|
@ -692,6 +676,8 @@ class MatrixPanel_I2S_DMA {
|
||||||
void brtCtrlOE(int brt, const bool _buff_id=0);
|
void brtCtrlOE(int brt, const bool _buff_id=0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}; // end Class header
|
}; // end Class header
|
||||||
|
|
||||||
/***************************************************************************************/
|
/***************************************************************************************/
|
||||||
|
|
|
@ -56,14 +56,36 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
} // end irq_hndlr
|
} // end irq_hndlr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
volatile int active_dma_buffer_output_count = 0;
|
||||||
|
|
||||||
|
static void IRAM_ATTR irq_hndlr(void* arg) {
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
active_dma_buffer_output_count++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( active_dma_buffer_output_count++ )
|
||||||
|
{
|
||||||
|
// Disable DMA chain EOF interrupt until next requested flipbuffer.
|
||||||
|
// Otherwise we're needlessly generating interrupts we don't care about.
|
||||||
|
//SET_PERI_REG_BITS(I2S_INT_ENA_REG(ESP32_I2S_DEVICE), I2S_OUT_EOF_INT_ENA_V, 0, I2S_OUT_EOF_INT_ENA_S);
|
||||||
|
active_dma_buffer_output_count = 0;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
} // end irq_hndlr
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
static i2s_dev_t* getDev(int port)
|
static i2s_dev_t* getDev()
|
||||||
{
|
{
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
||||||
return &I2S0;
|
return &I2S0;
|
||||||
#else
|
#else
|
||||||
return (port == 0) ? &I2S0 : &I2S1;
|
return (ESP32_I2S_DEVICE == 0) ? &I2S0 : &I2S1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
|
@ -78,23 +100,18 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Bus_Parallel16::config(const config_t& cfg)
|
void Bus_Parallel16::config(const config_t& cfg)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Performing config for ESP32 or ESP32-S2");
|
ESP_LOGI(TAG, "Performing config for ESP32 or ESP32-S2");
|
||||||
_cfg = cfg;
|
_cfg = cfg;
|
||||||
auto port = cfg.port;
|
auto port = ESP32_I2S_DEVICE; //cfg.port;
|
||||||
_dev = getDev(port);
|
_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(TAG, "Performing DMA bus init() for ESP32 or ESP32-S2");
|
ESP_LOGI(TAG, "Performing DMA bus init() for ESP32 or ESP32-S2");
|
||||||
|
|
||||||
if(_cfg.port < I2S_NUM_0 || _cfg.port >= I2S_NUM_MAX) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_cfg.parallel_width < 8 || _cfg.parallel_width >= 24) {
|
if(_cfg.parallel_width < 8 || _cfg.parallel_width >= 24) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +122,7 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
int irq_source;
|
int irq_source;
|
||||||
|
|
||||||
// Initialize I2S0 peripheral
|
// Initialize I2S0 peripheral
|
||||||
if (_cfg.port == 0)
|
if (ESP32_I2S_DEVICE == I2S_NUM_0)
|
||||||
{
|
{
|
||||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||||
|
@ -232,7 +249,7 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
// Must be ESP32 original
|
// Must be ESP32 original
|
||||||
#if !defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if !defined (CONFIG_IDF_TARGET_ESP32S2)
|
||||||
dev->clkm_conf.clka_en=0; // Use the 80mhz system clock (PLL_D2_CLK) when '0'
|
dev->clkm_conf.clka_en=0; // Use the 80mhz system clock (PLL_D2_CLK) when '0'
|
||||||
dev->clkm_conf.clkm_div_num = 3; // Hard code to whatever frequency this is. 26Mhz?
|
dev->clkm_conf.clkm_div_num = 3; // Hard code to 3 whatever frequency this is. 26Mhz?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -357,50 +374,27 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
|
|
||||||
dev->conf1.val = 0;
|
dev->conf1.val = 0;
|
||||||
dev->conf1.tx_stop_en = 0;
|
dev->conf1.tx_stop_en = 0;
|
||||||
/*
|
|
||||||
// Allocate I2S status structure for buffer swapping stuff
|
|
||||||
i2s_state = (i2s_parallel_state_t*) malloc(sizeof(i2s_parallel_state_t));
|
|
||||||
assert(i2s_state != NULL);
|
|
||||||
i2s_parallel_state_t *state = i2s_state;
|
|
||||||
|
|
||||||
state->desccount_a = conf->desccount_a;
|
|
||||||
state->desccount_b = conf->desccount_b;
|
|
||||||
state->dmadesc_a = conf->lldesc_a;
|
|
||||||
state->dmadesc_b = conf->lldesc_b;
|
|
||||||
state->i2s_interrupt_port_arg = port; // need to keep this somewhere in static memory for the ISR
|
|
||||||
*/
|
|
||||||
|
|
||||||
dev->timing.val = 0;
|
dev->timing.val = 0;
|
||||||
|
|
||||||
//dev->int_ena.out_eof = 1
|
|
||||||
|
/* If we have double buffering, then allocate an interrupt service routine function
|
||||||
|
* that can be used for I2S0/I2S1 created interrupts.
|
||||||
|
*/
|
||||||
|
if (_double_dma_buffer) {
|
||||||
|
|
||||||
/*
|
|
||||||
12.6.2 DMA Interrupts
|
|
||||||
• I2S_OUT_TOTAL_EOF_INT: Triggered when all transmitting linked lists are used up.
|
|
||||||
• I2S_OUT_EOF_INT: Triggered when rxlink has finished sending a packet
|
|
||||||
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
// We using the double buffering switch logic?
|
|
||||||
if (conf->int_ena_out_eof)
|
|
||||||
{
|
|
||||||
// Get ISR setup
|
// Get ISR setup
|
||||||
esp_err_t err = esp_intr_alloc(irq_source,
|
esp_err_t err = esp_intr_alloc(irq_source,
|
||||||
(int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1),
|
(int)(ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1),
|
||||||
irq_hndlr,
|
irq_hndlr, NULL, NULL);
|
||||||
&state->i2s_interrupt_port_arg, NULL);
|
|
||||||
|
|
||||||
if(err) {
|
if(err) {
|
||||||
return err;
|
ESP_LOGE(TAG, "init() Failed to setup interrupt request handeler.");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't do this here. Don't enable just yet.
|
||||||
// Setup interrupt handler which is focussed only on the (page 322 of Tech. Ref. Manual)
|
// dev->int_ena.out_eof = 1;
|
||||||
// "I2S_OUT_EOF_INT: Triggered when rxlink has finished sending a packet"
|
|
||||||
// ... whatever the hell that is supposed to mean... One massive linked list? So all pixels in the chain?
|
|
||||||
dev->int_ena.out_eof = 1;
|
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
#if defined (CONFIG_IDF_TARGET_ESP32S2)
|
||||||
|
@ -442,6 +436,7 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
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;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Allocating memory for %d DMA descriptors.", len);
|
ESP_LOGI(TAG, "Allocating memory for %d DMA descriptors.", len);
|
||||||
|
|
||||||
|
@ -474,7 +469,17 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
_dmadesc_b_idx = 0;
|
_dmadesc_b_idx = 0;
|
||||||
|
|
||||||
ESP_LOGD(TAG, "Allocating %d bytes of memory for DMA descriptors.", sizeof(HUB75_DMA_DESCRIPTOR_T) * len);
|
ESP_LOGD(TAG, "Allocating %d bytes of memory for DMA descriptors.", sizeof(HUB75_DMA_DESCRIPTOR_T) * len);
|
||||||
|
|
||||||
|
// 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->size = 1024*2;
|
||||||
|
_dmadesc_blank->length = 1024*2;
|
||||||
|
_dmadesc_blank->buf = (uint8_t*) _blank_data;
|
||||||
|
_dmadesc_blank->eof = 1;
|
||||||
|
_dmadesc_blank->sosf = 0;
|
||||||
|
_dmadesc_blank->owner = 1;
|
||||||
|
_dmadesc_blank->qe.stqe_next = (lldesc_t*) _dmadesc_blank;
|
||||||
|
_dmadesc_blank->offset = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -516,19 +521,19 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
{
|
{
|
||||||
dmadesc = &_dmadesc_b[_dmadesc_b_idx];
|
dmadesc = &_dmadesc_b[_dmadesc_b_idx];
|
||||||
|
|
||||||
next = (_dmadesc_b_idx < (_dmadesc_count-1) ) ? &_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_count-1));
|
eof = (_dmadesc_b_idx == (_dmadesc_last));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
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_count-1) ) ? _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_count-1));
|
eof = (_dmadesc_a_idx == (_dmadesc_last));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( _dmadesc_a_idx == (_dmadesc_count-1) ) {
|
if ( _dmadesc_a_idx == (_dmadesc_last) ) {
|
||||||
ESP_LOGW(TAG, "Creating final DMA descriptor and linking back to 0.");
|
ESP_LOGW(TAG, "Creating final DMA descriptor and linking back to 0.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -556,7 +561,7 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
// 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
|
// 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
|
||||||
|
@ -581,23 +586,57 @@ static void IRAM_ATTR irq_hndlr(void* arg) { // if we use I2S1 (default)
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
|
||||||
void Bus_Parallel16::set_dma_output_buffer(bool dmadesc_b)
|
void Bus_Parallel16::flip_dma_output_buffer(int ¤t_back_buffer_id) // pass by reference so we can change in main matrixpanel class
|
||||||
{
|
{
|
||||||
if ( _double_dma_buffer == false) return;
|
// 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)
|
||||||
|
//_dev->int_ena.out_eof = 1;
|
||||||
|
|
||||||
|
// MISALIGNMENT ON TOP/2 THE PANEL BETWEEN FAST MOVING GRAPHICS IS CAUSED
|
||||||
|
// DUE TO THE CHANGE OF BACK BUFFER ID AND THE FRIGGIN DMA BUFFER!!!
|
||||||
|
|
||||||
if ( dmadesc_b == true) // change across to everything 'b''
|
/*
|
||||||
{
|
if ( current_back_buffer_id == 1) {
|
||||||
_dmadesc_a[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
_dmadesc_a[_dmadesc_last].qe.stqe_next = _dmadesc_blank;
|
||||||
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_b[0];
|
}
|
||||||
}
|
else {
|
||||||
else
|
_dmadesc_b[_dmadesc_last].qe.stqe_next = _dmadesc_blank;
|
||||||
{
|
}
|
||||||
_dmadesc_a[_dmadesc_count-1].qe.stqe_next = &_dmadesc_a[0];
|
*/
|
||||||
_dmadesc_b[_dmadesc_count-1].qe.stqe_next = &_dmadesc_a[0];
|
|
||||||
}
|
// THIS WORKS SMOOTHLY EXCEPT FOR THE OFFSET ON MOVING GRAPHICS
|
||||||
|
_dev->int_ena.out_eof = 1;
|
||||||
|
|
||||||
|
// Wait until we're now stuck in a _dmadesc_a loop;
|
||||||
|
active_dma_buffer_output_count = 0;
|
||||||
|
while (!active_dma_buffer_output_count) {}
|
||||||
|
|
||||||
|
if ( current_back_buffer_id == 1) {
|
||||||
|
|
||||||
|
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0];
|
||||||
|
|
||||||
|
// Wait until we're now stuck in a _dmadesc_a loop;
|
||||||
|
active_dma_buffer_output_count = 0;
|
||||||
|
while (!active_dma_buffer_output_count) {}
|
||||||
|
|
||||||
|
_dmadesc_a[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0]; // get this preped for the next flip buffer
|
||||||
|
|
||||||
|
} else {
|
||||||
|
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_a[0];
|
||||||
|
|
||||||
|
// Wait until we're now stuck in a _dmadesc_a loop;
|
||||||
|
active_dma_buffer_output_count = 0;
|
||||||
|
while (!active_dma_buffer_output_count) {}
|
||||||
|
|
||||||
|
_dmadesc_b[_dmadesc_last].qe.stqe_next = &_dmadesc_b[0];
|
||||||
|
}
|
||||||
|
current_back_buffer_id ^= 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Disable intterupt
|
||||||
|
_dev->int_ena.out_eof = 0;
|
||||||
|
|
||||||
//_dmadesc_a_active ^= _dmadesc_a_active;
|
|
||||||
|
|
||||||
} // end flip
|
} // end flip
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,16 @@ Contributors:
|
||||||
|
|
||||||
#define DMA_MAX (4096-4)
|
#define DMA_MAX (4096-4)
|
||||||
|
|
||||||
|
#define ESP32_I2S_DEVICE I2S_NUM_0
|
||||||
|
|
||||||
// The type used for this SoC
|
// The type used for this SoC
|
||||||
#define HUB75_DMA_DESCRIPTOR_T lldesc_t
|
#define HUB75_DMA_DESCRIPTOR_T lldesc_t
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static void IRAM_ATTR irq_hndlr(void* arg);
|
||||||
|
static i2s_dev_t* getDev();
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
class Bus_Parallel16
|
class Bus_Parallel16
|
||||||
|
@ -64,8 +71,6 @@ Contributors:
|
||||||
|
|
||||||
struct config_t
|
struct config_t
|
||||||
{
|
{
|
||||||
int port = 0;
|
|
||||||
|
|
||||||
// max 20MHz (when in 16 bit / 2 byte mode)
|
// max 20MHz (when in 16 bit / 2 byte mode)
|
||||||
uint32_t bus_freq = 10000000;
|
uint32_t bus_freq = 10000000;
|
||||||
int8_t pin_wr = -1; //
|
int8_t pin_wr = -1; //
|
||||||
|
@ -112,7 +117,7 @@ Contributors:
|
||||||
void dma_transfer_start();
|
void dma_transfer_start();
|
||||||
void dma_transfer_stop();
|
void dma_transfer_stop();
|
||||||
|
|
||||||
void set_dma_output_buffer(bool dmadesc_b = false);
|
void flip_dma_output_buffer(int ¤t_back_buffer_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -124,6 +129,7 @@ Contributors:
|
||||||
//bool _dmadesc_a_active = true;
|
//bool _dmadesc_a_active = true;
|
||||||
|
|
||||||
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
uint32_t _dmadesc_count = 0; // number of dma decriptors
|
||||||
|
uint32_t _dmadesc_last = 0;
|
||||||
|
|
||||||
uint32_t _dmadesc_a_idx = 0;
|
uint32_t _dmadesc_a_idx = 0;
|
||||||
uint32_t _dmadesc_b_idx = 0;
|
uint32_t _dmadesc_b_idx = 0;
|
||||||
|
@ -131,6 +137,9 @@ Contributors:
|
||||||
HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
|
HUB75_DMA_DESCRIPTOR_T* _dmadesc_a = nullptr;
|
||||||
HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
|
HUB75_DMA_DESCRIPTOR_T* _dmadesc_b = nullptr;
|
||||||
|
|
||||||
|
HUB75_DMA_DESCRIPTOR_T* _dmadesc_blank = nullptr;
|
||||||
|
uint16_t _blank_data[1024] = {0};
|
||||||
|
|
||||||
volatile i2s_dev_t* _dev;
|
volatile i2s_dev_t* _dev;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lcd_cam_dev_t* getDev(int port)
|
static lcd_cam_dev_t* getDev()
|
||||||
{
|
{
|
||||||
return &LCD_CAM;
|
return &LCD_CAM;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@
|
||||||
void Bus_Parallel16::config(const config_t& cfg)
|
void Bus_Parallel16::config(const config_t& cfg)
|
||||||
{
|
{
|
||||||
_cfg = cfg;
|
_cfg = cfg;
|
||||||
auto port = cfg.port;
|
//auto port = cfg.port;
|
||||||
_dev = getDev(port);
|
_dev = getDev();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -402,12 +402,12 @@
|
||||||
} // end
|
} // end
|
||||||
|
|
||||||
|
|
||||||
void Bus_Parallel16::set_dma_output_buffer(bool dmadesc_b)
|
void Bus_Parallel16::flip_dma_output_buffer(int ¤t_back_buffer_id)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( _double_dma_buffer == false) return;
|
// if ( _double_dma_buffer == false) return;
|
||||||
|
|
||||||
if ( dmadesc_b == true) // change across to everything 'b''
|
if ( current_back_buffer_id == 1) // change across to everything 'b''
|
||||||
{
|
{
|
||||||
_dmadesc_a[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
_dmadesc_a[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
||||||
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_b[0];
|
||||||
|
@ -418,6 +418,8 @@
|
||||||
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_a[0];
|
_dmadesc_b[_dmadesc_count-1].next = (dma_descriptor_t *) &_dmadesc_a[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_back_buffer_id ^= 1;
|
||||||
|
|
||||||
|
|
||||||
} // end flip
|
} // end flip
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
struct config_t
|
struct config_t
|
||||||
{
|
{
|
||||||
// LCD_CAM peripheral number. No need to change (only 0 for ESP32-S3.)
|
// LCD_CAM peripheral number. No need to change (only 0 for ESP32-S3.)
|
||||||
int port = 0;
|
//int port = 0;
|
||||||
|
|
||||||
// max 40MHz (when in 16 bit / 2 byte mode)
|
// max 40MHz (when in 16 bit / 2 byte mode)
|
||||||
uint32_t bus_freq = 20000000;
|
uint32_t bus_freq = 20000000;
|
||||||
|
@ -146,7 +146,7 @@
|
||||||
void dma_transfer_start();
|
void dma_transfer_start();
|
||||||
void dma_transfer_stop();
|
void dma_transfer_stop();
|
||||||
|
|
||||||
void set_dma_output_buffer(bool dmadesc_b = false);
|
void flip_dma_output_buffer(int ¤t_back_buffer_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue