Shop OBEX P1 Docs P2 Docs Learn Events
MAX7219 multi-display output for TAQOZ — Parallax Forums

MAX7219 multi-display output for TAQOZ

Peter JakackiPeter Jakacki Posts: 10,193
edited 2021-01-30 02:53 in Propeller 2

Here's a character output module for the MAX7219 display which can be cascaded to form much larger displays (default is 8 displays of 8 digits = 64 characters). This was adapted from an earlier Tachyon version and works as a normal character output device in TAQOZ. Just divert to this device and print text and numbers as normal and control characters are handled as you would expect them to. ^N enables the display and ^O blanks it btw.


Usage: MAX7219 PRINT" HELLO WORLD! " 1234 1000 * PRINT


I don't have any displays to test this with although I may scope the timing to make sure it is under the 10MHz limit of the chip.

This is the code complete with the full alpha-numeric look-up tables in around 500 bytes.

TAQOZ


pub *MAX7219*   PRINT" MAX7219/7221 Multiple 8-digit LED Driver by PBJ 160409-0000 " ;


{
Handles strings of MAX7219 LED displays as one character output device.
Simply switch to the output and print as normal
Displays can be cascaded with up to 8 displays or 64 digits or increase buffer sizes
MAX7219 PRINT" NUMERIC DISPLAY " 1234567 100 * PRINT CON


210130  Convert to TAQOZ from Tachyon V3
}



pub displays  4 ; --- Use "<n> AT displays C!" to change
pri ledsz     displays 3 << ;


9 bytes ledwr
64 bytes ledbuf



--- write to control register but duplicate for every display
pub CLED! ( val reg -- )    displays FOR SPIWB SWAP SPIWB SWAP NEXT 2DROP SPICE ;



--- Talk to the register in the specified cascaded chip by issuing dummy nops as necessary
pub DLED! ( val dreg chip -- )
  -ROT SPIWB DROP SPIWB DROP
  ?DUP IF 0 SWAP FOR SPIWL NEXT DROP THEN
  SPICE
;


--- refresh the display by copying the ledbuf to the chip - <182us
pub REFRESH       ledsz FOR ledbuf I + C@ I 7 AND 7 XOR 1+ I 3 >> DLED! NEXT ;


( ASCII to 7-segment LED decode table - all characters and symbols )
\  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
0 TABLE 7segs
  $00 | $86 | $42 | $49 | $2D | $52 | $5B | $02 |     --- $20..$27  !"#$%&'
  $39 | $0F | $C9 | $46 | $04 | $40 | $80 | $52 |     --- $28..$2F ()*+,-./
  $3F | $06 | $5B | $4F | $66 | $6D | $7D | $07 |     --- $30..$37 01234567
  $7F | $6F | $41 | $45 | $70 | $48 | $46 | $D3 |     --- $38..$3F 89:;<=>?
  $7B | $77 | $7C | $39 | $5E | $79 | $71 | $3D |     --- $40..$47 @ABCDEFG
  $76 | $30 | $0E | $72 | $38 | $23 | $54 | $5C |     --- $48..$4F HIJKLMNO
  $73 | $7B | $50 | $6D | $46 | $3E | $62 | $1D |     --- $50..$57 PQRSTUVW
  $52 | $6E | $5B | $39 | $64 | $0F | $01 | $08 |     --- $58..$5F XYZ[\]^_
  $20 | $77 | $7C | $39 | $5E | $79 | $71 | $3D |     --- $60..$67 `abcdefg
  $76 | $30 | $0E | $72 | $38 | $23 | $54 | $5C |     --- $68..$6F hijklmno
  $73 | $79 | $50 | $6D | $46 | $3E | $62 | $1D |     --- $70..$77 pqrstuvw
  $52 | $6E | $5B | $39 | $36 | $0F | $52 | $00 |     --- $78..$7F xyz{|}~


--- Fix table to suit hardware as segments are flipped (except decimal)
7segs 96 ADO I C@ REV 25 >> I C@ $80 AND OR I C! LOOP


pub (LED) ( char -- )
    SWITCH                --- use the ASCII value as a switch in the case statement
    ^M  CASE ledwr C~ BREAK --- on CR reset display pos
    ^J  CASE ledbuf ledsz ERASE BREAK --- erase line but don't update yet
    ^L  CASE ledwr ledsz 1+ ERASE REFRESH BREAK --- reset and blank
    ^N  CASE 1 12 CLED! BREAK --- enable display (unblank)
    ^O  CASE 0 12 CLED! BREAK --- disable display (blank)
    "." CASE $80 ledwr C@ 1- ledsz >> ledbuf + C+! REFRESH BREAK  --- add in DP to previous character (or first)
    CASE@ $10 < IF BREAK --- ignore any other controls <$10
    CASE@ $20 < IF CASE@ >N 10 CLED! BREAK        --- set 4-bit brightness $10..$1F
    ( char is printable )
    ledwr C@ ledsz =>
      IF ledbuf 1+ ledbuf ledsz 1- CMOVE ledwr C-- 50 ms THEN   --- scroll if at end but slowly so it can be read
    CASE@ $20 - 7segs + C@            --- decode character to 8 segments
    ledwr C@ ledsz // ledbuf + C!         --- display it as a character
    ledwr C++               --- increment position
    REFRESH
;


pri !LEDPINS
    &14.12.13.15 SPIPINS --- setup pins used by SPI instructions
    SPICE 2 COG@ LOW --- MAX7219 likes to work with clock low to high
  ;


pub MAXPINS   AT !LEDPINS 2+ ! ;


--- Switch character output to the MAX7219 LED display
pub MAX7219
  EMIT:
pub >LED ( char -- )
    ledbuf @ 0=           --- initialise the display if necessary (all zeros on startup)
    IF
      !LEDPINS
      $FD64401F $1AE COG!     --- slow down the SPI output to a max of 10MHz (TBD)     --- slow down the SPI output to a max of 10MHz (TBD)
      7 11 CLED!          --- scan limit for 8 digits
      0 9 CLED!           --- no decode, use table
      0 15 CLED!          --- don't forget to reset TEST mode
      $18 (LED)           --- SET BRIGHTNESS
      ^L (LED)            --- clear the display
      ^N (LED)            --- enable display
    THEN
   (LED)
;


END

edit: patched the delay for <10MHz

Sign In or Register to comment.