Scrolling fonts on MAX7219

Discuss the Integrated Development Environment (IDE)

Moderators: David Barker, Jerry Messina

Post Reply
toyman
Posts: 39
Joined: Tue Feb 18, 2014 8:25 pm

Scrolling fonts on MAX7219

Post by toyman » Tue Aug 05, 2014 4:54 pm

Purchased several of the MAX7219 / 8 x 8 matrix boards and with help from Jon finally got one working.
Well looking at several code examples for Ardunio using two dismensional arrays and a scrolling module.
SF dosen't have two dimensional arrays but maybe someone has come up with an easy method to scroll.
I used this for a single 8 x 8 matrix directly driven off of port pins and it works rather well but the MAX7219 registers etc. do not seem to want to conform to this. Thinking of using the Display_reg as anodes and Data_out as cathodes as in my orginal code but??
here is my existing code for the MAX7219

Code: Select all

{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 8/4/2014                                                       *
*  Version : 1.0                                                            *
*  Notes   :  new revision by starting over and addressing the registers.                                                              *
*          :                                                                *
*****************************************************************************
}

DEVICE = 18F2420
CLOCK = 20
 
INCLUDE "shift.bas"
INCLUDE "utils.bas"
INCLUDE "convert.bas"
   ' INCLUDE "DS18B20.bas"
INCLUDE "Utils.bas"
INCLUDE "convert.bas"
//PIN DESCRIPTION
DIM Load_pin  AS PORTC.5   // LATCH
DIM Data_pin AS PORTC.4    // DATA
DIM Clock_pin AS PORTC.3   // CLOCK

DIM y AS BYTE 
DIM X AS BYTE   
//DIM index AS WORD 
DIM Display_Reg AS BYTE     //register settings
DIM Display_Data AS BYTE    // Data to be displayed
DIM Data_out AS WORD        // Data for additional matrix (4)

CONST A_ray(8) AS BYTE =( %11100011,       //k    
                          %00000000,
                          %10000000,
                          %10000000,
                          %10010000,
                          %10010000,
                          %10010000,
                          %11111111)
                      
SUB Write_Matrix ()
        Load_pin = 0
        Data_out =256*Display_Reg+ Display_Data
        shift.out (MSB_first,Data_out,16)
        Load_pin =1
END SUB

PUBLIC SUB InitLed()
       Display_Reg = 9    // decode
       Display_Data = 0  //all
    Write_Matrix        // write to matrix
    
       Display_Reg = 10    //intensity
       Display_Data = 8   //max
    Write_Matrix
    
       Display_Reg = 11    //scan limit
       Display_Data = 7    // to scan entire matrix
    Write_Matrix
    
       Display_Reg = 12    //shut down
       Display_Data = 1
    Write_Matrix
 END SUB 
 
PUBLIC SUB clear_display()
           DIM I AS INTEGER
           FOR I = 1 TO 8        // for 8 colums
           Display_Reg = I
           Display_Data = 0
           Write_Matrix
       NEXT  
END SUB 

PUBLIC SUB TestMode(Test AS BOOLEAN)
       IF test = true THEN
          Display_Data = 1
          Display_Reg = %1111
          Write_Matrix
        ELSE
          Display_Data = 0
          Display_Reg = %1111
          Write_Matrix 
        END IF
   END SUB   
 
// PROGRAM CODE SET UP 
setalldigital
shift.setoutput(Data_pin)
shift.setclock(Clock_pin)
OUTPUT(Load_pin)
Load_pin = 0
X = 1
y = 1
InitLed 
Display_Data = 1
          Display_Reg = %1111
          Write_Matrix
        DELAYMS(500)
          Display_Data = 0
          Display_Reg = %1111
          Write_Matrix    
//InitLED 'sets up the registers

WHILE 1 = 1
FOR X = 7TO 1 STEP - 1    // Y is the register

Display_Reg  = x
Display_Data = A_ray(7)
Write_Matrix
    delayms(300)
  
Display_Reg  =  x
Display_Data = A_ray(6)
Write_Matrix
 
    delayms(300)  
Display_Reg  =  x
Display_Data = A_ray(5)
Write_Matrix
      delayms(300)
Display_Reg  = x
Display_Data = A_ray(4)
Write_Matrix
  
     delayms(300)
Display_Reg  =  x
Display_Data = A_ray(3)
Write_Matrix
   
       delayms(300)
Display_Reg  =  x
Display_Data = A_ray(2)
Write_Matrix
       delayms(300)
Display_Reg  =  x
Display_Data = A_ray(1)
Write_Matrix




 {

Display_Reg  = y
Display_Data = A_ray(1)
Write_Matrix

Display_Reg  = y
Display_Data = A_ray(2)
Write_Matrix

Display_Reg  = y
Display_Data = A_ray(3)
Write_Matrix

Display_Reg = y
Display_Data = A_ray(4)
Write_Matrix

Display_Reg  = y
Display_Data = A_ray(5)
Write_Matrix

Display_Reg = y
Display_Data = A_ray(6)
Write_Matrix

Display_Reg  = y
Display_Data = A_ray(6)
Write_Matrix
 next
 }
DELAYMS(100)

clear_display

Y = Y + 1
 next
WEND

code for single 8 x 8 matrix

Code: Select all

{
*****************************************************************************
*  Name    : UNTITLED.BAS                                                   *
*  Author  : [select VIEW...EDITOR OPTIONS]                                 *
*  Notice  : Copyright (c) 2014 [select VIEW...EDITOR OPTIONS]              *
*          : All Rights Reserved                                            *
*  Date    : 3/9/2014                                                       *
*  Version : 1.0                                                            *
*  Notes   :                                                                *
*          :                                                                *
*****************************************************************************
}
DEVICE = 18F2420

CLOCK = 8
    

// import LCD library...

INCLUDE "convert.bas"
INCLUDE "InternalOscillator.bas"
INCLUDE "SetDigitalIO.bas"       // Include this file when we compile so that we can use keywords like 'setalldigital'
INCLUDE "utils.bas"

 

       
         // A
CONST A_data(210)AS BYTE =      (%00000000,                      
                                  %00000000,
                                  %00000000,             	
                                  %00111110,                    
                                  %01001000,                    
                                  %01001000,                    
                                  %00111110,                    
                                  %00000000,                    
                                  %00000000,                    
                                  %00000000,         
                                    //B                                       
                                  %00000000,
                                  %00000000,
                                  %00111100, 	
                                  %01000010,                               
                                  %01000010,
                                  %01000010,
                                  %00000000,
                                  %00000000,
                                 	//C
                                  %00000000,
                                  %00000000,
                                  %00111100, 	
                                  %01000010,                               
                                  %01000010,
                                  %01000010,
                                  %00000000,
                                  %00000000,
                                  //D
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01000010,                               
                                  %01000010,
                                  %00111100,
                                  %00000000,
                                  %00000000,
                                     //E
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01001010,                               
                                  %01000010,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                    //F
                                  
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01010000,                               
                                  %01000000,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                           // G
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01001010,                               
                                  %00001110,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                            //H
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %00001000,                               
                                  %00001000,
                                  %01111110,
                                  %00000000,
                                  %00000000,
                                  
                                  //I
                                  %00000000,
                                  %00000000,
                                  %01000010, 	
                                  %01111110,                               
                                  %01000010,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  //J
                                  %00000000,
                                  %00000000,
                                  %00000110, 	
                                  %00000010,                               
                                  %01111110,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  //K
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %00011000,                               
                                  %00100100,
                                  %00000010,
                                  %00000000,
                                  %00000000,
                                  //L
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %00000010,                               
                                  %00000010,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  //M
                                  %00000000,
                                  %01111110,
                                  %00100000, 	
                                  %00010000,                               
                                  %00100000,
                                  %01111110,
                                  %00000000,
                                  %00000000,
                                  //N
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %00110000,                               
                                  %00001100,
                                  %01111110,
                                  %00000000,
                                  %00000000,
                                     //O
                                  %00000000,
                                  %00000000,
                                  %00111100, 	
                                  %01000010,                               
                                  %01000010,
                                  %00111100,
                                  %00000000,
                                  %00000000,
                                  
                                  //P
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01001000,                               
                                  %00111000,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  
                                  //Q
                                  %00000000,
                                  %00000000,
                                  %00111100, 	
                                  %01000010,                               
                                  %01000010,
                                  %00111100,
                                  %00000010,
                                  %00000000,
                                  
                                  //R
                                  %00000000,
                                  %00000000,
                                  %01111110, 	
                                  %01001000,                               
                                  %00111000,
                                  %00000110,
                                  %00000000,
                                  %00000000,
                                  
                                  //S
                                  %00000000,
                                  %00000000,
                                  %00110010, 	
                                  %01010010,                               
                                  %01001100,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  
                                  //T
                                  %00000000,
                                  %00000000,
                                  %01000000, 	
                                  %01111110,                               
                                  %01000000,
                                  %00000000,
                                  %00000000,
                                  %00000000,
                                  
                                  //U
                                  %00000000,
                                  %00000000,
                                  %01111100, 	
                                  %00000010,                               
                                  %00000010,
                                  %01111100,
                                  %00000000,
                                  %00000000,
                                  
                                  //v
                                  %00000000,
                                  %00000000,
                                  %01111000, 	
                                  %00000100,                               
                                  %00000010,
                                  %00000100,
                                  %01111000,
                                  %00000000,
                                  
                                  //W
                                  %00000000,
                                  %01111100,
                                  %00000010, 	
                                  %00000100,                               
                                  %00000010,
                                  %01111100,
                                  %00000000,
                                  %00000000,
                                  
                                  //X
                                  %00000000,
                                  %01000010,
                                  %00100100, 	
                                  %00011100,                               
                                  %00100100,
                                  %01000010,
                                  %00000000,
                                  %00000000,
                                  
                                  //Y
                                  %00000000,
                                  %01000000,
                                  %00100000, 	
                                  %00011110,                               
                                  %00100000,
                                  %01000000,
                                  %00000000,
                                  %00000000,
                                  
                                  //Z
                                  %00000000,
                                  %00000000,
                                  %01001110, 	
                                  %01010010,                               
                                  %01100010,
                                  %00000010,
                                  %00000000,
                                  %00000000)
                               
                                
CONST Cathodes_Data(8) AS BYTE = (%11111110, %11111101, %11111011, %11110111, %11101111, %11011111, %10111111, %01111111)    

DIM Scroll_Speed AS INTEGER
DIM x AS BYTE
DIM y AS BYTE
SetAllDigital                       // Make all Pins digital I/O's
TRISC = %00000000                   // Make PORTD all outputs
TRISB = %00000000

Scroll_Speed = 50
 y = 0
WHILE true
   
   FOR x = 0 TO 7
      portc = %00000000
      portc = A_data(x + y)         //CONST array data Portc C is Anodes
      portb = Cathodes_Data(x)      // Cathodes on PortB
      DELAYMS(1)
     portc = %00000000
     DELAYUS(100)
   NEXT
   
     IF y +x <210  THEN    // number of byte data in CONST arrays
    DELAYMS(Scroll_Speed)
     y = y + 1             // next A_Data byte data
     
     ELSE
     y = 0
     
     END IF
   
     
      WEND
this code works rather well but migrating to work with MAX7219??

Jon Chandler
Registered User
Registered User
Posts: 167
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Re: Scrolling fonts on MAX7219

Post by Jon Chandler » Wed Aug 06, 2014 7:46 am

This is exactly the same thing as your scrolling arrow or your scrolling single matrix. If you take the effort to understand what's going on, moving from a PIC doing the work to a '595 shift register to a MAX7219 will be a piece of cake. In fact, the MAX7219 will be easier to use, because it's taking care of all the busy work of multiplexing the display.

A MAX7219 can drive 8 seven-segment digits or a single 8x8 matrix of the common cathode type. Each digit (7-segment display) or each column (matrix) is controlled by one byte. To control the display, a data byte is written to the register that controls that digit or column. Eight registers must be written to control an 8 digit display or a 8x8 matrix.

Forget scrolling. If you start with the basics, maybe you'll learn enough to do this without the need for dozens of posts. To start, draw a letter on one matrix. But not a symmetrical letter like X or O or even A or W. An F will be an easy character to start with.

The data for the first column of an F will be %11111111 – the % indicates a binary number, and there are exactly eight 1s to illuminate the entire column. Let's write this value to register 3 to illuminate the third column. The next two columns will be %10010000, to illuminate the top and center crossbars of the F. Write this value to registers 4 & 5. Finally, the last bit of the F will be formed by %10000000. Write this value to register 6. Note: all of these binary values contain exactly 8 digits.

Try this program. What did you get? With a little luck, you got an F...but chances are, it may be upside down and/or backwards. Why? Because we don't know how the designer arranged the board. Is column 1 on the left or on the right? Is the LSB (least significant bit) on the top or is it the MSB (most significant bit)? That why we had to use a non-symmetric character for this test – otherwise, you couldn't tell if it was reversed or flipped.

Get the F flipped around as needed and make note of the arrangement for encoding your message.

So, now that we know how to get a character on the screen, we can move on to scrolling. This is exactly the same as you're done before, but this time, let's try to understand the concept. We want the character to scroll from right to left. So the first step is to write the first column of the F to the right-most column. I've assumed it's column 8 but you may have found it's column 1. Adjust these instructions accordingly.

So write the data for the first column of the F to register 8. Wait some period of time, say 500ms.

Now, write the (data for the) first column of the F to register 7 and the second column of the F to register 8. Wait 500ms.

First column to register 6, second column to register 7 and third column to register 8. Wait.

Keep going on the process. After the last column of the F is written to register 8, keep going, adding bank columns (i.e., data = 0) until all of the columns of the F have vanished off the left of the matrix.

Piece of cake, right?

To scroll a longer message create a byte array of each column and march them across the display just as we did with the F. Get this working on one matrix before worrying about 3 or 4. It's exactly the same process.

Make this work and understand the process before doing anything else.
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

toyman
Posts: 39
Joined: Tue Feb 18, 2014 8:25 pm

Re: Scrolling fonts on MAX7219

Post by toyman » Wed Aug 06, 2014 9:22 pm

I did all that you explained. Got one letter to appear on the matrix correctly and scrolled it across the matrix. Just seems like alot of code but that's the way it is. Was trying to do similar with the Max7219 as I did with just a matrix driven off a pic as my second code I posted does. Just a few (15) lines of code to cycle through the desired text.
Decided to connect a second matrix and now a whole new can of worms. I read and re read the data sheet but get two similar but not the same data displayed on each matrix.
I addressed the no-op register along with several other register adjustments but getting no where. Kinda running out of time so I might just pack up this project come Saturday if I don't get any further and tinker with it in September when I unpack.

Code: Select all

WHILE true
   
   FOR x = 0 TO 7
      portc = %00000000
      portc = A_data(x + y)         //CONST array data Portc C is Anodes
      portb = Cathodes_Data(x)      // Cathodes on PortB
      DELAYMS(1)
     portc = %00000000
     DELAYUS(100)
   NEXT
   
     IF y +x <210  THEN    // number of byte data in CONST arrays
    DELAYMS(Scroll_Speed)
     y = y + 1             // next A_Data byte data
     
     ELSE
     y = 0
     
     END IF
   
     
      WEND

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Scrolling fonts on MAX7219

Post by SHughes_Fusion » Thu Aug 07, 2014 10:48 am

One suggestion for scrolling, if you are using three or less displays one easy solution would be to use an array of longwords to store your output data. You can reference bytes 3, 2 and 1 as the output to each matrix, load new characters in to byte 0 and scroll using shift left (<<) on each array longword. This uses the top three bytes of the longword as your 'visible' array allowing you to load characters in to an invisible byte and move them across one bit at a time.

How is your second MAX7219 connected? Do you daisy-chain them or use the same SPI bus with multiple Chip Select inputs?

toyman
Posts: 39
Joined: Tue Feb 18, 2014 8:25 pm

Re: Scrolling fonts on MAX7219

Post by toyman » Fri Aug 08, 2014 3:49 am

I have the MAX7219's daisy chained using one Din for eventually all 4 matrixes but going in steps. Got one working but getting the second to display the correct data.
The data sheet says to address the NO-OP register after each write command per matrix (3 matrixes 3 address to options or display reg 0 (I am calling it Display_reg.

SHughes_Fusion
Posts: 219
Joined: Wed Sep 11, 2013 1:27 pm
Location: Chesterfield

Re: Scrolling fonts on MAX7219

Post by SHughes_Fusion » Fri Aug 08, 2014 7:59 am

You don't actually have to send NOPs, if you want to update more than one device you can do that as well.

To help you understand, the DOUT output of the first MAX7219 mirrors the DIN input but 'delayed' by two bytes.

So if you send 4 bytes then do a latch the second MAX7219 will get the first two bytes and the first MAX7219 will get the second two.

You only do one latch per transmission, don't latch after every two bytes.

So if you want to update the second device only, send two data bytes (one 16 bit word) followed by two zero (NOP) bytes then latch.

To update the first device send two NOP bytes then two data bytes then latch.

To update both send four data bytes then latch.

Remember that once you transmit data it will carry on moving through the devices on each clock so it is easiest to always transmit enough data for the number of devices you have cascaded. For example, if you only send 2 bytes to change the first device then send two more, the first two will end up being loaded in to the second device.

toyman
Posts: 39
Joined: Tue Feb 18, 2014 8:25 pm

Re: Scrolling fonts on MAX7219

Post by toyman » Fri Aug 08, 2014 12:02 pm

Ah yes I think I get the picture??
At present I am latching after each two bytes ( after each 16 bits I am calling sub WRITE_MATRIX)

Code: Select all

SUB Write_Matrix1() 
        Load_pin = 0
        Data_out2=256* Display_Reg + Display_Data
        shift.out (MSB_first,Data_out2,16)
         Load_pin = 1
 END SUB       
Hopefully this will lead me down the path to success in getting this to work.Sounds easier than doing a no-op

Code: Select all

 Load_pin = 0
        //case = 1  // matrix 1
        Data_out1 =256*0+ Display_Data
        shift.out (MSB_first,Data_out1,16)
        Data_out1 =256*Display_Reg+ Display_Data
        shift.out (MSB_first,Data_out1,16)
         Load_pin = 1
I was just doing

Code: Select all

Load_pin = 0
 Display_Reg = 0
        Data_out2=256* Display_Reg + Display_Data
        shift.out (MSB_first,Data_out2,16)
         Load_pin = 1
for the no op

THANKS will try and decipher and hopefully get somewhere.

Jon Chandler
Registered User
Registered User
Posts: 167
Joined: Mon Mar 10, 2008 8:20 am
Location: Seattle, WA USA
Contact:

Re: Scrolling fonts on MAX7219

Post by Jon Chandler » Fri Aug 08, 2014 4:31 pm

Just FYI, MrDEB aka Toyman has spread this topic over at least 3 different forums. This inconsiderate practice results in a duplication of effort of people attempting to help him. MrDEB doesn't place much value on other people's time and effort.

Electrotech

Brads Projects Forum

The multilated scrap of code above came from a subroutine to support multiple MAX7219s I wrote for him on Electrotech.
Jon

Check out the TAP-28 PIC Application board at http://www.clever4hire.com/throwawaypic/

toyman
Posts: 39
Joined: Tue Feb 18, 2014 8:25 pm

Re: Scrolling fonts on MAX7219

Post by toyman » Fri Aug 08, 2014 6:32 pm

More than one opinion is better to figure out something than just one opinion. There are several methods to solve a problem so asking different forums helps. No one has all the right answers.
And yes Jon has helped a-lot as has other people.

Post Reply