Upgrading to Teensy 4.1 and SmartMatrix4

coinop

Member
Hi,

I am trying to upgrade from Teensy 3.5 to a Teensy 4.1. I have a custom shield that uses SmartMatrix4 https://github.com/pixelmatix/SmartMatrix. Running the FeatureDemo.ino, works fine on the 3.5, but I get a blank screen on the Teensy 4.1. The hardware configuration files are quite a bit different, with the 4.1 using FlexIO. I have attached both 3.5 and 4.1 configuration files, along with the features demo.

Any help would be appreciated -- Thanks

Here is the matrix hardware configuration for the working 3.5 (modified version of MatrixHardware_Teensy3_ShieldV1toV3.h):

Code:
// Note: only one MatrixHardware_*.h file should be included per project

#ifndef MATRIX_HARDWARE_H
#define MATRIX_HARDWARE_H

#pragma message "MatrixHardware: SmartMatrix Shield for Teensy 3.5 CoinOp"

#define COLOR_CHANNELS_PER_PIXEL        3
#define PIXELS_UPDATED_PER_CLOCK        2
#define DMA_UPDATES_PER_CLOCK           2

/* an advanced user may need to tweak these values */

// size of latch pulse - all address updates must fit inside high portion of latch pulse
// increase this value if DMA use is causing address updates to take longer


#define LATCH_TIMER_PULSE_WIDTH_NS  438

// max delay from rising edge of latch pulse to falling edge of clock
// increase this value if DMA use is delaying clock
// using largest delay seen at slowest supported clock speed (48MHz) 1400ns, saw 916ns at 96MHz
#define LATCH_TO_CLK_DELAY_NS       1400

// measured <3400ns to transfer 32 pixels at 96MHz, <6600ns to transfer 32 pixels at 48MHz
// for now, until DMA sharing complications (brought to light by Teensy 3.6 SDIO) can be worked out, enable DMA Bandwidth Control, which approximately doubles this estimated time
#define PANEL_32_PIXELDATA_TRANSFER_MAXIMUM_NS  (uint32_t)((2 * 3400 * 96000000.0) / F_CPU)

/* this section describes how the microcontroller is attached to the display */

// these defines map the HUB75 signal to PORTD signals - if your panel has non-standard RGB order, swap signals here
#define BIT_0_SIGNAL    hub75_r0
#define BIT_1_SIGNAL    hub75_clk
#define BIT_2_SIGNAL    hub75_g1
#define BIT_3_SIGNAL    pad
#define BIT_4_SIGNAL    hub75_b0
#define BIT_5_SIGNAL    hub75_b1
#define BIT_6_SIGNAL    hub75_r1
#define BIT_7_SIGNAL    hub75_g0

//#define DEBUG_PINS_ENABLED
#define DEBUG_PIN_1 17
#define DEBUG_PIN_2 18
#define DEBUG_PIN_3 19

/************ The below definitions are unlikely to be useful if changed **************/

// these pin definitions are used to set GPIO to output, and are manually used to reset FM6126A panels - swapping RGB pins here has no effect on refreshing the panel
#define GPIO_PIN_CLK_TEENSY_PIN     14
#define GPIO_PIN_B0_TEENSY_PIN      6
#define GPIO_PIN_R0_TEENSY_PIN      2
#define GPIO_PIN_R1_TEENSY_PIN      21
#define GPIO_PIN_G0_TEENSY_PIN      5
#define GPIO_PIN_G1_TEENSY_PIN      7
#define GPIO_PIN_B1_TEENSY_PIN      20

#define GPIO_PIN_LATCH_TEENSY_PIN   3
#define GPIO_PIN_OE_TEENSY_PIN      4

#define ADDX_PIN_0  3
#define ADDX_PIN_1  0
#define ADDX_PIN_2  1
#define ADDX_PIN_3  2
#define ADDX_PIN_MASK   ((1 << ADDX_PIN_0) | (1 << ADDX_PIN_1) | (1 << ADDX_PIN_2) | (1 << ADDX_PIN_3))

#define ADDX_TEENSY_PIN_0   9
#define ADDX_TEENSY_PIN_1   15
#define ADDX_TEENSY_PIN_2   22
#define ADDX_TEENSY_PIN_3   23

#define ADDX_GPIO_SET_REGISTER      GPIOC_PSOR
#define ADDX_GPIO_CLEAR_REGISTER    GPIOC_PCOR

#define SMARTLED_APA_ENABLED_BY_DEFAULT false
#define SMARTLED_APA_ENABLE_PIN     17
#define SMARTLED_APA_CLK_PIN        13
#define SMARTLED_APA_DAT_PIN        7

#define GPIO_WORD_ORDER_8BIT BIT_0_SIGNAL:1, BIT_1_SIGNAL:1, BIT_2_SIGNAL:1, BIT_3_SIGNAL:1, BIT_4_SIGNAL:1, BIT_5_SIGNAL:1, BIT_6_SIGNAL:1, BIT_7_SIGNAL:1

// output latch signal on pin 3 (PORTA.12), latch signal must be connected to pin 8 (PORTD.3) externally
#define ENABLE_LATCH_PWM_OUTPUT() {                                     \
        CORE_PIN3_CONFIG |= PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;  \
    }

// output OE signal on pin 4 (PORTA.13)
#define ENABLE_OE_PWM_OUTPUT() {                                        \
        CORE_PIN4_CONFIG = PORT_PCR_MUX(3) | PORT_PCR_DSE | PORT_PCR_SRE;   \
    }

// pin 3 (PORTA.12) triggers based on latch signal, on rising edge
#define ENABLE_LATCH_RISING_EDGE_GPIO_INT() {       \
        CORE_PIN3_CONFIG |= PORT_PCR_IRQC(1);           \
    }

#define DMAMUX_SOURCE_LATCH_RISING_EDGE     DMAMUX_SOURCE_PORTA

// pin 8 (PORTD.3) is set to input, and triggers based on latch signal, on falling edge
#define ENABLE_LATCH_FALLING_EDGE_GPIO_INT() {              \
        CORE_PIN8_CONFIG |= PORT_PCR_MUX(1) | PORT_PCR_IRQC(2); \
    }

#define DMAMUX_SOURCE_LATCH_FALLING_EDGE     DMAMUX_SOURCE_PORTD

#else
    #pragma GCC error "Multiple MatrixHardware*.h files included"
#endif

This is the 4.1 hardware configuration. (modified version of MatrixHardware_Teensy4_ShieldV0.h):
Code:
// Note: only one MatrixHardware_*.h file should be included per project

#ifndef MATRIX_HARDWARE_H
#define MATRIX_HARDWARE_H

#pragma message "MatrixHardware: SmartLED Shield for Teensy 4 V0"

/* an advanced user may need to tweak these values */

// size of latch pulse - can be short for V4 shield which doesn't need to update ADDX lines during latch pulse
// 20 is minimum working value on DP5020B panel
// set to 100 for improved support with FM6126A panel
// don't exceed 150 to avoid interference between latch and data transfer
#define LATCH_TIMER_PULSE_WIDTH_NS 100

// max delay from rising edge of latch pulse to falling edge of first pixel clock
// increase this value if DMA use is delaying clock
// Measured 220 ns delay at 600 MHz clock speed, 160 ns at 816 MHz. Slower speeds are not supported.
// Using larger delay for safety.
#define LATCH_TO_CLK_DELAY_NS 400

// Pixel clock frequency is generated using the 480 MHz PLL3 clock and a divide-by-n counter. Frequency is independent of CPU clock speed.
// Must increment divider value by 2 (division ratio is always even)
// Minimum tested working value is 20 (corresponding to 24 MHz clock frequency) on DP5020B panel
// Using value of 26 (corresponding to 18.462 MHz clock frequency) to improve stability and reduce glitching
// Larger values may be more stable, but will decrease maximum refresh rate
#define FLEXIO_CLOCK_DIVIDER 26

// Amount of time required to transfer 32 pixels
// Adding 200 ns overhead time to improve stability
#define PANEL_32_PIXELDATA_TRANSFER_MAXIMUM_NS  ((32*FLEXIO_CLOCK_DIVIDER*1000/480) + 200)

/* this section describes how the microcontroller is attached to the display */

// these defines control the color channel assignments - if your panel has non-standard RGB order, swap signals here
#define R_0_SIGNAL    FLEXIO_PIN_R0_TEENSY_PIN
#define G_0_SIGNAL    FLEXIO_PIN_G0_TEENSY_PIN
#define B_0_SIGNAL    FLEXIO_PIN_B0_TEENSY_PIN
#define R_1_SIGNAL    FLEXIO_PIN_R1_TEENSY_PIN
#define G_1_SIGNAL    FLEXIO_PIN_G1_TEENSY_PIN
#define B_1_SIGNAL    FLEXIO_PIN_B1_TEENSY_PIN

//#define DEBUG_PINS_ENABLED
#define DEBUG_PIN_1 17
#define DEBUG_PIN_2 18
#define DEBUG_PIN_3 19

/************ The below definitions are unlikely to be useful if changed **************/

// active pin number definitions
// data bit order is calculated in setup using the pin number definitions and color channel assignments
// these pin definitions are also manually used to reset FM6126A panels
#define FLEXPWM_PIN_OE_TEENSY_PIN       4
#define FLEXPWM_PIN_LATCH_TEENSY_PIN    3
#define FLEXIO_PIN_CLK_TEENSY_PIN       14
#define FLEXIO_PIN_CLK_TEENSY_PIN_ALT   14
#define FLEXIO_PIN_B0_TEENSY_PIN        6
#define FLEXIO_PIN_R0_TEENSY_PIN        2
#define FLEXIO_PIN_R1_TEENSY_PIN        21
#define FLEXIO_PIN_G0_TEENSY_PIN        5
#define FLEXIO_PIN_G1_TEENSY_PIN        7
#define FLEXIO_PIN_B1_TEENSY_PIN        20

#define SMARTLED_APA_ENABLED_BY_DEFAULT false
#define SMARTLED_APA_ENABLE_PIN         17
#define FLEXIO_PIN_APA102_CLK           13
#define FLEXIO_PIN_APA102_DAT           7

#define ADDX_0_SIGNAL   FLEXIO_PIN_R0_TEENSY_PIN
#define ADDX_1_SIGNAL   FLEXIO_PIN_G0_TEENSY_PIN
#define ADDX_2_SIGNAL   FLEXIO_PIN_B0_TEENSY_PIN
#define ADDX_3_SIGNAL   FLEXIO_PIN_R1_TEENSY_PIN
#define ADDX_4_SIGNAL   FLEXIO_PIN_G1_TEENSY_PIN

#else
    #pragma GCC error "Multiple MatrixHardware*.h files included"
#endif

Finally here is the FeatureDemo.ino configuration section
Code:
//#define USE_ADAFRUIT_GFX_LAYERS

// uncomment one line to select your MatrixHardware configuration - configuration header needs to be included before <SmartMatrix.h>

#include <MatrixHardware_COINOP_TEENSY_4_1.h>
#include <SmartMatrix4.h>

#define COLOR_DEPTH 24                  // Choose the color depth used for storing pixels in the layers: 24 or 48 (24 is good for most sketches - If the sketch uses type `rgb24` directly, COLOR_DEPTH must be 24)
const uint16_t kMatrixWidth = 128;       // Set to the width of your display, must be a multiple of 8
const uint16_t kMatrixHeight = 32;      // Set to the height of your display
const uint8_t kRefreshDepth = 24;       // Tradeoff of color quality vs refresh rate, max brightness, and RAM usage.  36 is typically good, drop down to 24 if you need to.  On Teensy, multiples of 3, up to 48: 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48.  On ESP32: 24, 36, 48
const uint8_t kDmaBufferRows = 4;       // known working: 2-4, use 2 to save RAM, more to keep from dropping frames and automatically lowering refresh rate.  (This isn't used on ESP32, leave as default)
const uint8_t kPanelType = SMARTMATRIX_HUB75_32ROW_MOD16SCAN;   // Choose the configuration that matches your panels.  See more details in MatrixCommonHub75.h and the docs: https://github.com/pixelmatix/SmartMatrix/wiki
const uint32_t kMatrixOptions = (SM_HUB75_OPTIONS_NONE);        // see docs for options: https://github.com/pixelmatix/SmartMatrix/wiki
const uint8_t kBackgroundLayerOptions = (SM_BACKGROUND_OPTIONS_NONE);
const uint8_t kScrollingLayerOptions = (SM_SCROLLING_OPTIONS_NONE);
const uint8_t kIndexedLayerOptions = (SM_INDEXED_OPTIONS_NONE);
 
I guess I really have 2 questions here:

1. are any of those pins used for something else on the Teensy 4.1 vs the 3.5?

2. for the SmartMatrix on the 4.1, all I did was map the FLEXIO pins to match the pins of the 3.5. it should be straight forward, or is there something special I need to do to make the FLEXIO versions to work?

I am using the following pins on my 3.5 shield:
Code:
#define GPIO_PIN_CLK_TEENSY_PIN     14
#define GPIO_PIN_B0_TEENSY_PIN      6
#define GPIO_PIN_R0_TEENSY_PIN      2
#define GPIO_PIN_R1_TEENSY_PIN      21
#define GPIO_PIN_G0_TEENSY_PIN      5
#define GPIO_PIN_G1_TEENSY_PIN      7
#define GPIO_PIN_B1_TEENSY_PIN      20
#define GPIO_PIN_LATCH_TEENSY_PIN   3
#define GPIO_PIN_OE_TEENSY_PIN      4

4.1
Code:
#define FLEXPWM_PIN_OE_TEENSY_PIN       4
#define FLEXPWM_PIN_LATCH_TEENSY_PIN    3
#define FLEXIO_PIN_CLK_TEENSY_PIN       14
#define FLEXIO_PIN_CLK_TEENSY_PIN_ALT   14
#define FLEXIO_PIN_B0_TEENSY_PIN        6
#define FLEXIO_PIN_R0_TEENSY_PIN        2
#define FLEXIO_PIN_R1_TEENSY_PIN        21
#define FLEXIO_PIN_G0_TEENSY_PIN        5
#define FLEXIO_PIN_G1_TEENSY_PIN        7
#define FLEXIO_PIN_B1_TEENSY_PIN        20

#define SMARTLED_APA_ENABLED_BY_DEFAULT false
#define SMARTLED_APA_ENABLE_PIN         17
#define FLEXIO_PIN_APA102_CLK           13
#define FLEXIO_PIN_APA102_DAT           7
 
I don't really know the details under the hood, but the Smartmatrix shield on the Teensy 3.1/3.2/3.5/3.6 uses different pins for the Smartmatrix shield on Teensy 4.0/4.1. I suspect you probably need to ask the question on the SmartLed (previously SmartMatrix) forum.

 
looking at the serial monitor, I see the following errors, maybe someone here knows what this means:
Code:
Error: incorrect FlexIO pin configuration!
Error: Latch and OE must be complementary channels from a single FlexPWM submodule!

I'm using the following pins:
Code:
#define FLEXPWM_PIN_OE_TEENSY_PIN       4
#define FLEXPWM_PIN_LATCH_TEENSY_PIN    3

I just posted in the SmartLed forum also- Thanks!
 
I think we're going to redesign our shield to use the same pins as SmartLed to avoid any issues with pins.

thanks for the help!
 
Back
Top