Merge pull request #168 from mrfaptastic/SM5266P

Implement

    Sm5266 panels
    Increase default latch blanking
    Get rid of the legacy begin() usage of the library.
    Fix a minor bug with the DMA v and h line draw with out-of-bounds x/y/length params.
This commit is contained in:
mrfaptastic 2021-08-17 10:45:20 +01:00 committed by GitHub
commit 00917150ff
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 20 deletions

View file

@ -415,14 +415,14 @@ void MatrixPanel_I2S_DMA::configureDMA(const HUB75_I2S_CFG& _cfg)
}; };
// Setup I2S // Setup I2S
i2s_parallel_driver_install(I2S_NUM_1, &cfg); i2s_parallel_driver_install(I2S_NUM_0, &cfg);
//i2s_parallel_setup_without_malloc(&I2S1, &cfg); //i2s_parallel_setup_without_malloc(&I2S1, &cfg);
// Start DMA Output // Start DMA Output
i2s_parallel_send_dma(I2S_NUM_1, &dmadesc_a[0]); i2s_parallel_send_dma(I2S_NUM_0, &dmadesc_a[0]);
#if SERIAL_DEBUG #if SERIAL_DEBUG
Serial.println(F("configureDMA(): DMA setup completed on I2S1.")); Serial.println(F("configureDMA(): DMA setup completed on I2S_NUM_0."));
#endif #endif
} // end initMatrixDMABuff } // end initMatrixDMABuff
@ -616,7 +616,15 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
// fill all x_pixels except color_index[0] (LSB) ones, this also clears all color data to 0's black // fill all x_pixels except color_index[0] (LSB) ones, this also clears all color data to 0's black
do { do {
--x_pixel; --x_pixel;
if ( m_cfg.driver == HUB75_I2S_CFG::SM5266P) {
// modifications here for row shift register type SM5266P
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164
row[x_pixel] = abcde & (0x18 << BITS_ADDR_OFFSET); // mask out the bottom 3 bits which are the clk di bk inputs
} else {
row[x_pixel] = abcde; row[x_pixel] = abcde;
}
} while(x_pixel!=dma_buff.rowBits[row_idx]->width); } while(x_pixel!=dma_buff.rowBits[row_idx]->width);
// color_index[0] (LSB) x_pixels must be "marked" with a previous's row address, 'cause it is used to display // color_index[0] (LSB) x_pixels must be "marked" with a previous's row address, 'cause it is used to display
@ -624,9 +632,34 @@ void MatrixPanel_I2S_DMA::clearFrameBuffer(bool _buff_id){
abcde = ((ESP32_I2S_DMA_STORAGE_TYPE)row_idx-1) << BITS_ADDR_OFFSET; abcde = ((ESP32_I2S_DMA_STORAGE_TYPE)row_idx-1) << BITS_ADDR_OFFSET;
do { do {
--x_pixel; --x_pixel;
if ( m_cfg.driver == HUB75_I2S_CFG::SM5266P) {
// modifications here for row shift register type SM5266P
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164
row[x_pixel] = abcde & (0x18 << BITS_ADDR_OFFSET); // mask out the bottom 3 bits which are the clk di bk inputs
} else {
row[x_pixel] = abcde; row[x_pixel] = abcde;
}
//row[x_pixel] = abcde;
} while(x_pixel); } while(x_pixel);
// modifications here for row shift register type SM5266P
// https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-I2S-DMA/issues/164
if ( m_cfg.driver == HUB75_I2S_CFG::SM5266P) {
uint16_t serialCount;
uint16_t latch;
x_pixel = dma_buff.rowBits[row_idx]->width - 16; // come back 8*2 pixels to allow for 8 writes
serialCount = 8;
do{
serialCount--;
latch = row[x_pixel] | (((((ESP32_I2S_DMA_STORAGE_TYPE)row_idx) % 8) == serialCount) << 1) << BITS_ADDR_OFFSET; // data on 'B'
row[x_pixel++] = latch| (0x05<< BITS_ADDR_OFFSET); // clock high on 'A'and BK high for update
row[x_pixel++] = latch| (0x04<< BITS_ADDR_OFFSET); // clock low on 'A'and BK high for update
} while (serialCount);
} // end SM5266P
// let's set LAT/OE control bits for specific pixels in each color_index subrows // let's set LAT/OE control bits for specific pixels in each color_index subrows
uint8_t coloridx = dma_buff.rowBits[row_idx]->color_depth; uint8_t coloridx = dma_buff.rowBits[row_idx]->color_depth;
do { do {
@ -721,7 +754,8 @@ void MatrixPanel_I2S_DMA::brtCtrlOE(int brt, const bool _buff_id){
/* /*
* overload for compatibility * overload for compatibility
*/ */
bool MatrixPanel_I2S_DMA::begin(int r1, int g1, int b1, int r2, int g2, int b2, int a, int b, int c, int d, int e, int lat, int oe, int clk){ /*
bool MatrixPanel_I2S_DMA::begin(int r1, int g1, int b1, int r2, int g2, int b2, int a, int b, int c, int d, int e, int lat, int oe, int clk) {
// RGB // RGB
m_cfg.gpio.r1 = r1; m_cfg.gpio.g1 = g1; m_cfg.gpio.b1 = b1; m_cfg.gpio.r1 = r1; m_cfg.gpio.g1 = g1; m_cfg.gpio.b1 = b1;
@ -736,6 +770,7 @@ bool MatrixPanel_I2S_DMA::begin(int r1, int g1, int b1, int r2, int g2, int b2,
return begin(); return begin();
} }
*/
/** /**
* @brief - Sets how many clock cycles to blank OE before/after LAT signal change * @brief - Sets how many clock cycles to blank OE before/after LAT signal change
@ -772,8 +807,11 @@ void MatrixPanel_I2S_DMA::hlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
if ( x_coord < 0 || y_coord < 0 || l < 1 || x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height) if ( x_coord < 0 || y_coord < 0 || l < 1 || x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height)
return; return;
if (x_coord+l > PIXELS_PER_ROW)
l = PIXELS_PER_ROW - x_coord + 1; // reset width to end of row l = ( (x_coord + l) >= PIXELS_PER_ROW ) ? (PIXELS_PER_ROW - x_coord):l;
//if (x_coord+l > PIXELS_PER_ROW)
// l = PIXELS_PER_ROW - x_coord + 1; // reset width to end of row
/* LED Brightness Compensation */ /* LED Brightness Compensation */
#ifndef NO_CIE1931 #ifndef NO_CIE1931
@ -846,8 +884,10 @@ void MatrixPanel_I2S_DMA::vlineDMA(int16_t x_coord, int16_t y_coord, int16_t l,
if ( x_coord < 0 || y_coord < 0 || l < 1 || x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height) if ( x_coord < 0 || y_coord < 0 || l < 1 || x_coord >= PIXELS_PER_ROW || y_coord >= m_cfg.mx_height)
return; return;
if (y_coord + l > m_cfg.mx_height) // check for a length that goes beyond the height of the screen! Array out of bounds dma memory changes = screwed output #163
l = m_cfg.mx_height - y_coord + 1; // reset width to end of col l = ( (y_coord + l) >= m_cfg.mx_height ) ? (m_cfg.mx_height - y_coord):l;
//if (y_coord + l > m_cfg.mx_height)
/// l = m_cfg.mx_height - y_coord + 1; // reset width to end of col
/* LED Brightness Compensation */ /* LED Brightness Compensation */
#ifndef NO_CIE1931 #ifndef NO_CIE1931

View file

@ -229,7 +229,7 @@ struct HUB75_I2S_CFG {
* Enumeration of hardware-specific chips * Enumeration of hardware-specific chips
* used to drive matrix modules * used to drive matrix modules
*/ */
enum shift_driver {SHIFTREG=0, FM6124, FM6126A, ICN2038S, MBI5124}; enum shift_driver {SHIFTREG=0, FM6124, FM6126A, ICN2038S, MBI5124, SM5266P};
/** /**
* I2S clock speed selector * I2S clock speed selector
@ -292,7 +292,7 @@ struct HUB75_I2S_CFG {
shift_driver _drv = SHIFTREG, shift_driver _drv = SHIFTREG,
bool _dbuff = false, bool _dbuff = false,
clk_speed _i2sspeed = HZ_10M, clk_speed _i2sspeed = HZ_10M,
uint8_t _latblk = 1, uint8_t _latblk = 4,
bool _clockphase = true, bool _clockphase = true,
uint8_t _min_refresh_rate = 85 uint8_t _min_refresh_rate = 85
) : mx_width(_w), ) : mx_width(_w),
@ -351,6 +351,8 @@ class MatrixPanel_I2S_DMA {
/* Propagate the DMA pin configuration, allocate DMA buffs and start data ouput, initialy blank */ /* Propagate the DMA pin configuration, allocate DMA buffs and start data ouput, initialy blank */
bool begin(){ bool begin(){
if (initialized) return true; // we don't do this twice or more!
// Change 'if' to '1' to enable, 0 to not include this Serial output in compiled program // Change 'if' to '1' to enable, 0 to not include this Serial output in compiled program
#if SERIAL_DEBUG #if SERIAL_DEBUG
Serial.printf_P(PSTR("Using pin %d for the R1_PIN\n"), m_cfg.gpio.r1); Serial.printf_P(PSTR("Using pin %d for the R1_PIN\n"), m_cfg.gpio.r1);
@ -411,7 +413,9 @@ class MatrixPanel_I2S_DMA {
/* /*
* overload for compatibility * overload for compatibility
*/ */
/*
bool begin(int r1, int g1 = G1_PIN_DEFAULT, int b1 = B1_PIN_DEFAULT, int r2 = R2_PIN_DEFAULT, int g2 = G2_PIN_DEFAULT, int b2 = B2_PIN_DEFAULT, int a = A_PIN_DEFAULT, int b = B_PIN_DEFAULT, int c = C_PIN_DEFAULT, int d = D_PIN_DEFAULT, int e = E_PIN_DEFAULT, int lat = LAT_PIN_DEFAULT, int oe = OE_PIN_DEFAULT, int clk = CLK_PIN_DEFAULT); bool begin(int r1, int g1 = G1_PIN_DEFAULT, int b1 = B1_PIN_DEFAULT, int r2 = R2_PIN_DEFAULT, int g2 = G2_PIN_DEFAULT, int b2 = B2_PIN_DEFAULT, int a = A_PIN_DEFAULT, int b = B_PIN_DEFAULT, int c = C_PIN_DEFAULT, int d = D_PIN_DEFAULT, int e = E_PIN_DEFAULT, int lat = LAT_PIN_DEFAULT, int oe = OE_PIN_DEFAULT, int clk = CLK_PIN_DEFAULT);
*/
// TODO: Disable/Enable auto buffer flipping (useful for lots of drawPixel usage)... // TODO: Disable/Enable auto buffer flipping (useful for lots of drawPixel usage)...
@ -515,7 +519,7 @@ class MatrixPanel_I2S_DMA {
Serial.printf_P(PSTR("Showtime for buffer: %d\n"), back_buffer_id); Serial.printf_P(PSTR("Showtime for buffer: %d\n"), back_buffer_id);
#endif #endif
i2s_parallel_flip_to_buffer(I2S_NUM_1, back_buffer_id); i2s_parallel_flip_to_buffer(I2S_NUM_0, back_buffer_id);
// Wait before we allow any writing to the buffer. Stop flicker. // Wait before we allow any writing to the buffer. Stop flicker.
while(!i2s_parallel_is_previous_buffer_free()) { delay(1); } while(!i2s_parallel_is_previous_buffer_free()) { delay(1); }
@ -570,7 +574,7 @@ class MatrixPanel_I2S_DMA {
*/ */
void stopDMAoutput() { void stopDMAoutput() {
resetbuffers(); resetbuffers();
i2s_parallel_stop_dma(I2S_NUM_1); i2s_parallel_stop_dma(I2S_NUM_0);
} }

View file

@ -84,6 +84,11 @@ static void dma_reset(i2s_dev_t* dev) {
dev->lc_conf.in_rst = 0; dev->lc_conf.in_rst = 0;
dev->lc_conf.out_rst = 1; dev->lc_conf.out_rst = 1;
dev->lc_conf.out_rst = 0; dev->lc_conf.out_rst = 0;
dev->lc_conf.ahbm_rst = 1;
dev->lc_conf.ahbm_rst = 0;
} }
static void fifo_reset(i2s_dev_t* dev) { static void fifo_reset(i2s_dev_t* dev) {

View file

@ -93,8 +93,7 @@ void drawText(int colorWheelOffset)
void setup() { void setup() {
// // Module configuration
HUB75_I2S_CFG mxconfig( HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width PANEL_RES_X, // module width
PANEL_RES_Y, // module height PANEL_RES_Y, // module height
@ -112,9 +111,6 @@ void setup() {
dma_display->clearScreen(); dma_display->clearScreen();
dma_display->fillScreen(myWHITE); dma_display->fillScreen(myWHITE);
//
dma_display->begin(); // use default pins
// fix the screen with green // fix the screen with green
dma_display->fillRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(0, 15, 0)); dma_display->fillRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(0, 15, 0));
delay(500); delay(500);