Skip to content

quick_start

board707 edited this page May 11, 2024 · 5 revisions

Welcome to DMD_STM32 library!

Introduction

The following is a brief reference on how to install and use DMD_STM32 library.

Installation

There are two ways to install the library:

  • Download ZIP-archive directly from Releases section, open your Arduino IDE, click on Sketch > Include Library > Add . ZIP Library. Choose the zip file you just downloaded.
  • Using Library Manager (since Arduino IDE 1.6.2): navigate to Sketch > Include Library > Manage Libraries inside your Arduino IDE and search for the library, then click Install.

Pre-installation requirements

Arduino support packages for STM32 and Raspberry Pi Pico

Supported panels

  • Monochrome panels: The library primarily intended to work on P10 32x16 Monochrome panels with HUB12 interface. Other types of Monochrome panels are quite rare and not tested with the library.
  • RGB panels: The code works with most RGB HUB75 panels with line scanning drivers. Panels of almost any size, scanning and multiplexing type can be used. All these are configured by "matrix pattern" - a strings of digits, represents a key characteristics of given panel. More information about matrix patterns you can found in wiki.The library does provide to users a rich set of predefined matrix patterns. Full list of implemented patterns see in DMD_Panel_Templates.h file. If you haven't found a suitable pattern for your matrix, please feel free to open an issue using template.
    Using panels with a drivers with internal memory (S-PWM, EPWM types) is a difficult case; although the classes for some such drivers are implemented (FM6126a, FM6353, FM6363) in the library, as a general rule S-PWM drivers are not supported. You can found a table of known supported and unsupported drivers in the wiki/Led drivers section.

How to start

When using the library for the first time, I recommend connect the pins and use the settings, specified in the examples.

Using Monochrome panels

Include files

To include Monochrome panel support part of DMD_STM32 library add the following line at the top of your sketch:

#include <DMD_MonoChrome_SPI.h>

or

#include <DMD_Monochrome_Parallel.h>

To learn the difference between SPI and Parallel Monochrome modes see the "Connections" wiki.

Connections

Many library modes require specific MCU pins, depending on used controller. Let's assume you have a simple setup as follows: the STM32F103 "Bluepill" board with 4 P10 32x16 Monochrome panels, chained in 2x2 screen. Create constants for the pins that controls the panel:

#define DMD_PIN_A PA1
#define DMD_PIN_B PA3
#define DMD_PIN_nOE PB1

Loading data into the panel is similar to working with a shift register; the clock, data and latch pins are also used here. The way they are set depends on the selected mode:

  • Monochrome Parallel mode

    In this mode we connect each row of panels to separate DATA pin, using common clock and latch pins for all rows. Clock and data pins defined as a list:

    #define DMD_PIN_SCLK PA15   // latch
    uint8_t pins[] = { PA5, PA7, PA6 };  // CLK , row1, row2

    Note that on many panels latch pin could be labeled as SCLK

  • Monochrome SPI mode

    The mode uses hardware SPI bus as a transport interface. We use SPI_CLK and SPI_MOSI as CLK and DATA pins; it has the predefined values depends on used SPI channel. The only LAT(SCLK) pin must be defined:

    #define DMD_PIN_SCLK PA15   // latch
    SPIClass dmd_spi(1);

Recommended pin combinations for other cases are shown in the examples. If you want to change the default pins, see the Connections section in the Wiki.

Create DMD object

Setup the screen:

//Number of panels in x and y axis
#define DISPLAYS_ACROSS 2
#define DISPLAYS_DOWN 2

switch on DUAL BUFFER if needed:

#define ENABLE_DUAL_BUFFER true

and create the library object:

  • Monochrome Parallel mode
  DMD_Monochrome_Parallel dmd(DMD_PIN_A, DMD_PIN_B, DMD_PIN_nOE, DMD_PIN_SCLK, pins, DISPLAYS_ACROSS, DISPLAYS_DOWN,ENABLE_DUAL_BUFFER);
  • Monochrome SPI mode
  DMD_MonoChrome_SPI dmd(DMD_PIN_A, DMD_PIN_B, DMD_PIN_nOE, DMD_PIN_SCLK, DISPLAYS_ACROSS, DISPLAYS_DOWN, dmd_spi, ENABLE_DUAL_BUFFER);

After creating an instance of the DMD class, the last thing you need to do before you start working with panels is to initialize the library. Place the line

dmd.init()

somewhere in setup().

Congratulations! Setup is complete. See the "Use cases" section and example directory to view how to work with DMD Led panels in your code.

Using RGB panels

Include files

In order to start using library with RGB panels add the following line at the top of your sketch:

#include <DMD_RGB.h>

In some cases to work with panels equipped with non-standard drivers you may need to include a different headers to work: DMD_RGB_FM6126a.h or DMD_RGB_FM6353.h. See examples for detail.

Connections

Many library modes require specific MCU pins, depending on used controller. Let's assume you have a simple setup as follows: the STM32F401 "Blackpill" board with 4 64x32 s16 RGB panels, chained in 2x2 screen. Create constants for the pins that controls the panel:

#define DMD_PIN_A PB6
#define DMD_PIN_B PB5
#define DMD_PIN_C PB4
#define DMD_PIN_D PB3
#define DMD_PIN_E PB8
// put all mux pins at list
uint8_t mux_list[] = { DMD_PIN_A , DMD_PIN_B , DMD_PIN_C , DMD_PIN_D , DMD_PIN_E };

// pin OE must be one of PB0 PB1 PA6 PA7
#define DMD_PIN_nOE PB0    // OE
#define DMD_PIN_SCLK PB7   // LAT

The RGB panels has a six data pins - a two for each color Red, Green, Blue. All these pins as well a CLK pin must be connected to the same controller port:

// All this pins must be selected on the same mcu port!
uint8_t custom_rgbpins[] = {PA6, PA0,PA1,PA2,PA3,PA4,PA5 }; // CLK, R0, G0, B0, R1, G1, B1

Recommended pin combinations for other cases are shown in the examples. If you want to change the default pins, see the Connections section in the Wiki.

Create DMD object

Setup the screen:

//Number of panels in x and y axis
#define DISPLAYS_ACROSS 2
#define DISPLAYS_DOWN 2

switch on DUAL BUFFER if needed:

#define ENABLE_DUAL_BUFFER true

and create the library object:

DMD_RGB <RGB64x32plainS16, COLOR_4BITS> dmd(mux_list, DMD_PIN_nOE, DMD_PIN_SCLK, custom_rgbpins, DISPLAYS_ACROSS, DISPLAYS_DOWN, ENABLE_DUAL_BUFFER);

Working with panel that used a shift_register type (aka 595 type) multiplexer chip, just replace the DMD_RGBclass to DMD_RGB_SHIFTREG_ABC class. Similar to it, when use a panel with a specific drivers FM6126, FM6353 or FM6363 - replace the DMD_RGB to DMD_RGB_FM6126, DMD_RGB_FM6353 or DMD_RGB_FM6363 respectively.

After creating an instance of the DMD class, the last thing you need to do before you start working with panels is to initialize the library. Place the line

dmd.init()

somewhere in setup().

Congratulations! Setup is complete. See the "Use cases" section and example directory to view how to work with DMD Led panels in your code.

Examples

All examples in this section are not a stand-alone sketches, but only a code snippets. Let's assume you already defined the pins and setup the matrix, as described in section How to start.

How to output a static text

In order to output the text on the panel you need to attach a font to the sketch. Select one from the library's font folder and add to your code somewhere before setup():

#include "gfx_fonts/GlametrixLight12pt7b.h"

DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b,  13);

Than set the text, choose the color and draw the string on display:

void setup() {
  // initialize DMD objects
  dmd.init(); 
  
  // set the brightness
  dmd.setBrightness(100); 

  // create the colors
  uint16_t bg = 0;                      // background - black
  uint16_t fg = dmd.Color888(255, 0, 0); // foreground - red   
  
  //define the text
  char str[] = "Hello DMD_STM32!";

  // select the font and draw the string at pos (x,y) 0,0 with color fg
  dmd.selectFont(&GlametrixL);
  dmd.drawString(0, 0, str, strlen(str),fg);
}

How to output a multi-color text

The only difference from the previous example is a method of the setting the colors. Instead of selecting a single color we setup a color list.

// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b,  13);

void setup() {
  // initialize DMD objects
  dmd.init(); 
  
  // set the brightness
  dmd.setBrightness(100); 

  // create color array
  uint16_t col[] = {
        0,                       // background = black
        dmd.Color888(255,0, 0),  // red
        dmd.Color888(0, 255, 0), // green
        dmd.Color888(0, 0, 255)  // blue

  };
  // create colorlist
  DMD_Colorlist multicolor(4, col );  // list length, pointer to color array
  
  //define the text
  char str[] = "Hello DMD_STM32!";

  // select the font and draw the string at pos (x,y) with colors from the list
  dmd.selectFont(&GlametrixL);
  dmd.drawStringX(0, 15, str, &multicolor);
}

How to scroll

To run the scrolling string you need to perform the same steps as for displaying text. Working with scrolling is performed by two functions - the drawMarquee() function prepares and displays the string on the matrix, and the stepMarquee() function controls its movement. Scrolling text is a dynamic process, so we need a cycle that calls the stepMarquee() with a given interval. The condition for completing or restarting scrolling may be that the text leaves the screen completely.
Take note, that as a default you can use only one marquee on the time. To see the workaround, read the next examples.

// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b,  13);

void setup() {
  // initialize DMD objects
  dmd.init(); 
  
  // set the brightness
  dmd.setBrightness(100); 

  // create the colors
  uint16_t bg = 0;                      // background - black
  uint16_t fg = dmd.Color888(255, 0, 0); // foreground - red   
  
  // we need set text colors when using it with Marquee functions
  dmd.setTextColor(fg, bg);

  // select the font 
  dmd.selectFont(&GlametrixL);
}

//define the text
const char str[] = "Hello DMD_STM32!";
bool first_start = true;

void loop() {
  
   // initial marquee setup. We need to do it once so we use the marquee_start flag
   if (first_start) {
    dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);  // start the scroll from the left border of the screen
    first_start = false;
  }
  
  // scrolling step interval
  const uint32_t interval = 30;  // milliseconds
  static uint32_t prev_step = millis();

  if ((millis() - prev_step) > interval) {
    prev_step = millis();
    if (dmd.stepMarquee(1, 0) & MARQUEE_OUT_OF_SCREEN ) { // if text is reached screen bounds

      // clear the screen and restart marquee
      dmd.clearScreen(true);  
      dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);
    }
  }
}

See also dmd_rgb.ino in library examples.

How to output fixed text and scroll

As a default the stepMarquee() shifts the entire screen, so you can't have a static elements on display when you use a scrolling. To solve the issue we have to use a DUAL_BUFFER_MODE and redraw the static text every time as we moved the marquee. Add this BEFORE creating the dmd object:

// Enable of output buffering
// if true, changes only outputs to matrix after
// swapBuffers(true) command
// If dual buffer not enabled, all output draw at matrix directly
// and swapBuffers(true) command do nothing
#define ENABLE_DUAL_BUFFER true

Now we can fullfil our usual procedures:

// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b,  13);

// create the colors
uint16_t bg = 0;                      // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // marquee foreground - red   
uint16_t fg2 = dmd.Color888(0, 255, 0); // static text foreground - green

void setup() {
  // initialize DMD objects
  dmd.init(); 
  
  // set the brightness
  dmd.setBrightness(100); 

  // we need set text colors when using it with Marquee functions
  dmd.setTextColor(fg, bg);

  // select the font 
  dmd.selectFont(&GlametrixL);

  // disable moving the marquee by shifting the screen
  dmd.disableFastTextShift(true);
}

//define the text
const char str[] = "Hello DMD_STM32!";
bool first_start = true;

void loop() {
  
   // initial marquee setup. We need to do it once so we use the marquee_start flag
   if (first_start) {
    dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);  // start the scroll from the left border of the screen
    first_start = false;
  }
  
  // scrolling step interval
  const uint32_t interval = 30;  // milliseconds
  static uint32_t prev_step = millis();

  if ((millis() - prev_step) > interval) {
    prev_step = millis();
    if (dmd.stepMarquee(1, 0) & MARQUEE_OUT_OF_SCREEN ) { // if text is reached screen bounds

      // clear the screen and restart marquee
      dmd.clearScreen(true);  
      dmd.drawMarqueeX(str, -1 * (dmd.stringWidth(str)), 0);
    }
    // renew fixed text
    dmd.drawFilledBox(0, 0, 15, dmd.height() - 1, bg);
    dmd.drawStringX(0, 0, "23", fg2);

    // output mem buffer to matrix
    dmd.swapBuffers(true);
  }
}

Another example of using this technique see at the dmd_rgb_dual_buf.ino code.

Scroll and fixed text

How to use a more than one scroll

The principle the same as for scrolling with a static text - you have to move a marquee and redraw the second string. But instead of redrawing it in a fixed position - we will increment the x coordinate by one pixel every time, moving the second string in opposite direction to the marquee.

#define ENABLE_DUAL_BUFFER true  // add this BEFORE the creating a DMD instance

// ...create a DMD...

// attach the font
#include "gfx_fonts/GlametrixLight12pt7b.h"
DMD_GFX_Font GlametrixL((uint8_t*)&GlametrixLight12pt7b,  13);

// create the colors
uint16_t bg = 0;                      // background - black
uint16_t fg = dmd.Color888(255, 0, 0); // marquee foreground - red   
uint16_t fg2 = dmd.Color888(0, 255, 0); // second text foreground - green

void setup() {
  // initialize DMD objects
  dmd.init(); 
  
  // set the brightness
  dmd.setBrightness(100); 

  // we need set text colors when using it with Marquee functions
  dmd.setTextColor(fg, bg);

  // select the font 
  dmd.selectFont(&GlametrixL);

  // disable moving the marquee by shifting the screen
  dmd.disableFastTextShift(true);
}



//define the texts
const char str[] = "Hello DMD_STM32!";
const char fixed_str[] = "FIXED TEXT";
bool first_start = true;

void loop() {
  
   // initial marquee setup. We need to do it once so we use the marquee_start flag
   if (first_start) {
    dmd.drawMarqueeX(str, dmd.width() -2 , 16);  // start the scroll from the right border of the screen
    first_start = false;
  }
  
  // scrolling step interval
  const uint32_t interval = 30;  // milliseconds
  static uint32_t prev_step = millis();
  static int16_t i = 0;
  
  if ((millis() - prev_step) > interval) {
    prev_step = millis();
    if (dmd.stepMarquee(-1, 0) & MARQUEE_OUT_OF_SCREEN ) { // move text left and checks if text is reached screen bounds

      // clear the screen and restart marquee
      dmd.clearScreen(true);  
      dmd.drawMarqueeX(str, dmd.width() -2 , 16);
    }

    // renew a second  text
    dmd.drawStringX(i, 0, fixed_str, fg2); 
    i++;  // increment the X coordinate
    if (i >= (dmd.width() +2) ) i = -1 * (dmd.stringWidth(fixed_str));  // if text is out the right screen border - restart from the left

    // output mem buffer to matrix
    dmd.swapBuffers(true);
  }
}

Two scroll Two scroll 2

Further reading

Additional info about library's classes and methods see in Library API Reference.