View Full Version : max7219 4x 8x8 panels spi
richard
- 26th December 2020, 04:22
for pic16 with spi port . 5 digits 6x5 numeric font right justified with leading zero suppression
Ioannis
- 12th January 2022, 07:58
A bit late but just noticed this valuable post! Thanks once again.
Is this driver for such a display?
richard
- 12th January 2022, 08:36
https://youtu.be/DanYYBoVOBU
looks the same
Ioannis
- 12th January 2022, 16:49
Thanks!
Really cheap toys to play with!
Ioannis
Ioannis
- 15th January 2022, 20:23
Since I have on hand only 16F1827, I modified the code for the PortC pins but as expected does not work. Modifications in red.
I really do not know what lata.5 does in your code. Maybe a led to sign start?
'************************************************* ***************
'* Name : max7219 16f1825 *
'* Author : richard *
'* Notice : Copyright (c) 2019 *
'* : *
'* Date : 25/2/2020 *
'* Version : 1.1 *
'* Notes : max7219 5 6x5 chrs on 4 8x8 panels *
'* : right justified leading zero suppression *
'* : *
'* : *
'* : modified for pic16f1827 *
'************************************************* ******************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG
define OSC 32
goto overasm
asm
GetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
movlw High Label ; get high byte
movwf Wout + 1
endm
endasm
overasm:
SSPCON1 = $20;
SSPSTAT = $40;
ANSELA = 0
ANSELB = 0
OSCCON = $70
tmp var byte
dsp var byte
dspbuff var byte[32]
BUFF var byte[16]
cnt var byte
row var byte
drow var byte
srow var byte
col var byte
dcol var byte
aFont var word
fOffset var word
cga var byte
cgah var byte
ch var byte
chr var byte
inx var byte
mask var word
counter var word
bcnt var byte
ncnt var byte
number var word
clear
'mxld var portc.1
'mxck var portc.0
'mxdi var portc.2
mxld var portb.1
mxck var portb.4
mxdi var porta.6
'trisc = %11111000
'trisa = %11011110
trisb = 0
trisa = 0
init:
lata.5 = 1
mxld = 1
dsp = 11
tmp = 5
gosub xfer4
dsp = 9
tmp = 0
gosub xfer4
dsp = 12
tmp = 1
gosub xfer4
dsp = 10
tmp = 8
gosub xfer4
dsp = $b
tmp = 7
gosub xfer4
dsp = $f
tmp = 0
gosub xfer4
@ GetAddress _font,_aFont
loopy:
row = 1:col = 1
gosub showrjbuf
gosub strchr
gosub show
counter = counter + 1
pause 100
GOTO loopy
end
strchr: ;null terminated
bcnt = 0
while buff[bcnt]
chr = buff[bcnt]
gosub gcga
bcnt = bcnt + 1
col = col + 6
wend
return
show:
for srow = 0 to 7
GOSUB SHOWROW
next
return
showROW:
mxld = 0
for dcol = 0 to 3
SSPBUF = srow + 1
while !pir1.3:wend
pir1.3 = 0
SSPBUF = dspbuff[(srow<<2) + dcol] rev 8
while !pir1.3:wend
pir1.3 = 0
next
mxld = 1
return
xfer4:
for dcol = 0 to 3
mxld = 0
pir1.3 = 0
SSPBUF = dsp
while !pir1.3:wend
pir1.3=0
SSPBUF =tmp
while !pir1.3:wend
pir1.3 = 0
next
mxld = 1
return
gcga: ;ROW= 0-1 COL=0-28 CHR = SPACE,"0" TO ";"
if chr = " " then chr = ";" ;TRANSLATE SPACE TO ";"
fOffset = (chr - "0")*3 + aFont ; point to cga data
drow = row ;0 or 1
mask = ~(63<<(col//8))
inx = col/8
for tmp = 0 to 2
gosub unpack
inx = (drow<<2) + col/8
dspbuff[inx] = dspbuff[inx] & mask.lowbyte
dspbuff[inx] = dspbuff[inx] | (cga<<(col//8))
if mask.highbyte then
INX = INX + 1
dspbuff[inx] = dspbuff[inx] & mask.highbyte
dspbuff[inx] = dspbuff[inx] | (cga>>(8-col//8) )
inx = inx + 3
else
inx = inx + 4
endif
' SROW=DROW
' GOSUB SHOWROW
' PAUSE 50
drow = drow + 1
dspbuff[inx] = dspbuff[inx] & mask.lowbyte
dspbuff[inx] = dspbuff[inx] | (cgah<<(col//8))
if mask.highbyte then
INX = INX+1
dspbuff[inx] = dspbuff[inx] & mask.highbyte
dspbuff[inx] = dspbuff[inx] | (cgah>>(8 - col//8) )
endif
' SROW=DROW
' GOSUB SHOWROW
' PAUSE 50
drow = drow + 1
fOffset = fOffset + 1
next
return
showrjbuf: ;load buff righ justified
number = counter
for ncnt = 0 to 4
BUFF[ncnt] = $30
next
while number >10000
buff[0] = buff[0] + 1
number = number - 10000
wend
while number >1000
buff[1] = buff[1] + 1
number = number - 1000
wend
while number>100
buff[2] = buff[2] + 1
number = number - 100
wend
while number >10
buff[3] = buff[3] + 1
number = number -10
wend
buff[4] = buff[4] + number
lzr: ;repress leading zeros
for ncnt = 0 to 3
if BUFF[ncnt] == $30 then
BUFF[ncnt] = $20
else
return
endif
next
return
unpack:
asm
CHK?RP _fOffset
MOVF _fOffset+1,W
CHK?RP EEADRH
MOVWF EEADRH ;MS Byte of Program Address to read
CHK?RP _fOffset
MOVF _fOffset,W
CHK?RP EEADR
MOVWF EEADR ;LS Byte of Program Address to read
CHK?RP EECON1
BSF EECON1, EEPGD ;Point to PROGRAM memory
BSF EECON1, RD ;EE Read
NOP
NOP
CHK?RP EEDAT ;UNPACK DATA
RLF EEDAT, W
RLF EEDATH, W
CHK?RP _cgah
MOVWF _cgah
CHK?RP EEDAT
BCF EEDAT,7
MOVF EEDAT,W
CHK?RP _cga
MOVWF _cga
RST?RP
return
endasm
'//Font Generated by MikroElektronika GLCD Font Creator 1.2.0.0
'//MikroElektrnika 2011
'//http://www.mikroe.com
'//GLCD FontName : Untitled5x6
'//GLCD FontSize : 5 x 6
'const unsigned short Untitled5x6[] = {
font : ;in packed format for pic16 dw lines
;@ db 0x0E,0x11,0x11,0x11,0x11,0x0E; // Code for char num 48 0
@ dw 0x88e,0x891,0x711 ;
;@ db 0x04,0x06,0x04,0x04,0x04,0x0E; // Code for char num 49 1
@ dw 0x304,0x204,0x704
;@ db 0x0E,0x11,0x08,0x04,0x02,0x1F; // Code for char num 50
@ dw 0x88e,0x208,0xf82
;@ db 0x0E,0x10,0x1C,0x10,0x10,0x0E; // Code for char num 51
@ dw 0x80e,0xe10,0x710
;@ db 0x01,0x01,0x05,0x1F,0x04,0x04; // Code for char num 52
@ dw 0x81,0xf85,0x204
;@ db 0x0F,0x01,0x01,0x0E,0x10,0x0F; // Code for char num 53
@ dw 0x8f,0x701,0x790
;@ db 0x0E,0x11,0x01,0x0F,0x11,0x0E; // Code for char num 54 6
@ dw 0x88e,0x781,0x711
;@ db 0x1F,0x10,0x08,0x04,0x02,0x02; // Code for char num 55
@ dw 0x81f,0x208,0x102
;@ db 0x0E,0x11,0x11,0x0E,0x11,0x0E; // Code for char num 56 8
@ dw 0x88e,0x88e ,0x711
;@ db 0x0E,0x11,0x11,0x1E,0x10,0x0E; // Code for char num 57
@ dw 0x88e,0xf11,0x711
;@ db 0x00,0x04,0x00,0x00,0x04,0x00; // Code for char num 58 ;
@ dw 0x200,0,0x200
;@ db 0x00,0x00,0x00,0x00,0x00,0x00; // space
@ dw 0,0, 0
Ioannis
richard
- 15th January 2022, 20:45
Since I have on hand only 16F1827, I modified the code for the PortC pins but as expected does not work. Modifications in red.
default sdo for that chip is rb2, for mxdi var porta.6 you need to set apfcon0.6
I really do not know what lata.5 does in your code. Maybe a led to sign start?
nether do i , most probably a trigger for log analyzer
Ioannis
- 15th January 2022, 21:06
Well, I was just about to post that logic analyzer keeps data at zero. I was watching that and could not think what was wrong...!
Doh!
Thanks Richard. Works now.
Ioannis
Ioannis
- 15th January 2022, 22:32
What is the logic in the packing of the characters into words?
Ioannis
richard
- 16th January 2022, 00:02
What is the logic in the packing of the characters into words?
uses half the amount of flash memory when using 7bit numbers [pic16 flash is 14 bits wide] so you need to pack it.
it takes very little time for the pic to unpack so there is no real penalty for a huge saving
Ioannis
- 16th January 2022, 00:14
Yes, OK. But from 6 bytes you went to 3 words. Cannot understand the calculation you did.
;@ db 0x0E,0x10,0x1C,0x10,0x10,0x0E; // Code for char num 51 "3"
@ dw 0x80e,0xe10,0x710
0E=00001110, 10=00010000 and all these makes 80E?
Ioannis
richard
- 16th January 2022, 01:36
0xE=0b00001110, 0x10=0b00010000
and all these makes 80E
7 high bits | 7 low bits
0x10<<7 | 0x0e &0x7f = 0x80e
0b000100000000000 | 0b0001110 = 0b00010000001110 <==> 0x80e [14 bits]
Ioannis
- 16th January 2022, 10:22
After making the paper and pencil homework, I was amazed by your thinking! So simple, so clever, so efficient!
Ioannis
Ioannis
- 16th January 2022, 11:21
Mikroe outputs the characters in columns but your data is in rows. Did you rotate them by hand or can GLCD do that?
Ioannis
richard
- 16th January 2022, 11:33
http://www.picbasic.co.uk/forum/showthread.php?t=24452&p=147955#post147955
9162
Ioannis
- 16th January 2022, 14:41
Well, results don't match.
I do this:
1. on GLCD Font Creator 5x6 is selected since that is what says in the program: '//GLCD FontSize : 5 x 6
9169
2. Then the character 48 is designed
9170
3.Then Export for GLCD
9171
The data do not match as can be seen. I am sure that I did something wrong, but what?
Ioannis
richard
- 16th January 2022, 21:19
thats glcd mode you need tft mode
Ioannis
- 17th January 2022, 21:18
Yes, that did it.
Thanks,
Ioannis
Ioannis
- 22nd January 2022, 10:24
The 5x6 grid is not very roomy for good fonts. After a bit of experimenting I ended up with the rectangular fonts that follow. I thing they are readable from longer distance.
@ dw 0x89F, 0x891, 0xF91 ; 0
@ dw 0x206, 0x204, 0xF84 ; 1
@ dw 0x81F, 0x9F, 0xF81 ; 2
@ dw 0x81F, 0x81E, 0xF90 ; 3
@ dw 0x489, 0xF89, 0x408 ; 4
@ dw 0x9F, 0x81F, 0xF90 ; 5
@ dw 0x9F, 0x89F, 0xF91 ; 6
@ dw 0x81F, 0x410, 0x408 ; 7
@ dw 0x89F, 0x89F, 0xF91 ; 8
@ dw 0x89F, 0x81F, 0xF90 ; 9
@ dw 0x200, 0x0, 0x200 ; :
@ dw 0,0,0 ; space
A small demo video is uloaded here:
https://youtu.be/6Lhbh82X1es
Ioannis
HenrikOlsson
- 20th August 2022, 23:43
I'm slowly working on an 18F version.
Currently running on the 18F57Q43 using the SPI peripheral (planning to get to DMA eventually) but can work with MSSP or even SHIFTOUT.
Supports an arbitrary width display (within limits of available RAM) but only one row (starting to second guess myself on that one). Pixel by pixel scrolling left/right/up/down is almost working. We'll see where this ends up in the comming weeks...
9264
richard
- 22nd August 2022, 07:05
you could always just add a driver to suit this and not have to reinvent the wheel font&graphics wise etc
http://www.picbasic.co.uk/forum/showthread.php?t=24218
i'm sure a max7219 driver would be easy enough to contrive and it would make multi row /column display simpler
Ioannis
- 22nd August 2022, 08:19
I'm slowly working on an 18F version....
Very interesting work! Looking forward!
Ioannis
richard
- 2nd September 2022, 04:16
now with scrolling
https://www.youtube.com/watch?v=huAudugRXts
'************************************************* ***************'* Name : max7219 16f1825 *
'* Author : richard *
'* Notice : Copyright (c) 2019 *
'* : *
'* Date : 25/2/2020 *
'* Version : 1.1 *
'* Notes : max7219 5 6x5 chrs on 4 8x8 panels *
'* : right justified leading zero suppression *
'* : *
'* : *
'* : pic16f1825 *
'************************************************* ******************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_OFF & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG
define OSC 32
goto overasm
asm
GetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
movlw High Label ; get high byte
movwf Wout + 1
endm
endasm
overasm:
SSPCON1 = $20;
SSPSTAT = $40;
ANSELA = 0
ANSELC = 0
OSCCON = $70
tmp var byte
dsp var byte
dspbuff var byte[32]
BUFF var byte[16]
cnt var byte
row var byte
drow var byte
srow var byte
col var byte
dcol var byte
aFont var word
fOffset var word
cga var byte
cgah var byte
ch var byte
chr var byte
inx var byte
mask var word
counter var word
bcnt var byte
ncnt var byte
number var word
clear
mxld var portc.1
mxck var portc.0
mxdi var portc.2
trisc = %11111000
trisa = %11011110
lata.0=1
init:
lata.5 = 1
mxld = 1
dsp = 11
tmp = 5
gosub xfer4
dsp = 9
tmp = 0
gosub xfer4
dsp = 12
tmp = 1
gosub xfer4
dsp = 10
tmp = 8
gosub xfer4
dsp = $b
tmp = 7
gosub xfer4
dsp = $f
tmp = 0
gosub xfer4
@ GetAddress _font,_aFont
'dspbuff[0]=$73
'dspbuff[4]=$37
counter=1235
col = 1
gosub showrjbuf
gosub strchr
gosub show
pause 100
loopy:
gosub rotate
' col = 1
' gosub showrjbuf
' gosub strchr
' chr=":" + counter.0
' col = 27
' gosub gcga
gosub show
' counter = counter + 1
pause 100
GOTO loopy
end
strchr: ;null terminated
bcnt = 0
while buff[bcnt]
chr = buff[bcnt]
gosub gcga
bcnt = bcnt + 1
col = col + 5
wend
return
show:
for srow = 0 to 7
GOSUB SHOWROW
next
return
showROW:
mxld = 0
for dcol = 0 to 3
SSPBUF = srow + 1
while !pir1.3:wend
pir1.3 = 0
SSPBUF = dspbuff[(srow<<2) + dcol] rev 8
while !pir1.3:wend
pir1.3 = 0
next
mxld = 1
return
xfer4:
for dcol = 0 to 3
mxld = 0
pir1.3 = 0
SSPBUF = dsp
while !pir1.3:wend
pir1.3=0
SSPBUF =tmp
while !pir1.3:wend
pir1.3 = 0
next
mxld = 1
return
gcga: ;ROW= 0-1 COL=0-28 CHR = SPACE,"0" TO ";"
if chr = " " then chr = ";" ;TRANSLATE SPACE TO ";"
fOffset = (chr - "0")*4 + aFont ; point to cga data
drow = 0
mask = ~(31<<(col//8))
inx = col/8
for tmp = 0 to 3
gosub unpack
inx = (drow<<2) + col/8
dspbuff[inx] = dspbuff[inx] & mask.lowbyte
dspbuff[inx] = dspbuff[inx] | (cga<<(col//8))
if mask.highbyte then
INX = INX + 1
dspbuff[inx] = dspbuff[inx] & mask.highbyte
dspbuff[inx] = dspbuff[inx] | (cga>>(8-col//8) )
inx = inx + 3
else
inx = inx + 4
endif
drow = drow + 1
dspbuff[inx] = dspbuff[inx] & mask.lowbyte
dspbuff[inx] = dspbuff[inx] | (cgah<<(col//8))
if mask.highbyte then
INX = INX+1
dspbuff[inx] = dspbuff[inx] & mask.highbyte
dspbuff[inx] = dspbuff[inx] | (cgah>>(8 - col//8) )
endif
drow = drow + 1
fOffset = fOffset + 1
next
return
showrjbuf: ;load buff righ justified
number = counter
for ncnt = 0 to 4
BUFF[ncnt] = $30
next
while number >10000
buff[0] = buff[0] + 1
number = number - 10000
wend
while number >1000
buff[1] = buff[1] + 1
number = number - 1000
wend
while number>100
buff[2] = buff[2] + 1
number = number - 100
wend
while number >10
buff[3] = buff[3] + 1
number = number - 10
wend
buff[4] = buff[4] + number
lzr: ;repress leading zeros
for ncnt = 0 to 3
if BUFF[ncnt] == $30 then
BUFF[ncnt] = $20
else
return
endif
next
return
unpack:
readcode foffset ,cgah
cga=(cgah >> 4)
cgah=(cgah&15 )
return
rotate:
asm
bcf STATUS,C
rrf _dspbuff+3,f
rrf _dspbuff+2,f
rrf _dspbuff+1,f
rrf _dspbuff ,f
btfsc STATUS, C
bsf _dspbuff+3,7
bcf STATUS,C
rrf _dspbuff+7,f
rrf _dspbuff+6,f
rrf _dspbuff+5,f
rrf _dspbuff+4 ,f
btfsc STATUS, C
bsf _dspbuff+7,7
bcf STATUS,C
rrf _dspbuff+11,f
rrf _dspbuff+10,f
rrf _dspbuff+9,f
rrf _dspbuff+8 ,f
btfsc STATUS, C
bsf _dspbuff+11,7
bcf STATUS,C
rrf _dspbuff+15,f
rrf _dspbuff+14,f
rrf _dspbuff+13,f
rrf _dspbuff+12 ,f
btfsc STATUS, C
bsf _dspbuff+15,7
bcf STATUS,C
rrf _dspbuff+19,f
rrf _dspbuff+18,f
rrf _dspbuff+17,f
rrf _dspbuff+16 ,f
btfsc STATUS, C
bsf _dspbuff+19,7
bcf STATUS,C
rrf _dspbuff+23,f
rrf _dspbuff+22,f
rrf _dspbuff+21,f
rrf _dspbuff+20 ,f
btfsc STATUS, C
bsf _dspbuff+23,7
bcf STATUS,C
rrf _dspbuff+27,f
rrf _dspbuff+26,f
rrf _dspbuff+25,f
rrf _dspbuff+24 ,f
btfsc STATUS, C
bsf _dspbuff+27,7
bcf STATUS,C
rrf _dspbuff+31,f
rrf _dspbuff+30,f
rrf _dspbuff+29,f
rrf _dspbuff+28 ,f
btfsc STATUS, C
bsf _dspbuff+31,7
endasm
return
font:
@ dw 0x69,0x99,0x99,0x96
@ dw 0x46,0x54,0x44,0x4F
@ dw 0x69,0x98,0x61,0x1F
@ dw 0x69,0x86,0x89,0x96
@ dw 0x99,0x9E,0x88,0x88
@ dw 0xF1,0x17,0x89,0x96
@ dw 0x69,0x17,0x99,0x96
@ dw 0xF8,0x84,0x42,0x22
@ dw 0x69,0x96,0x99,0x96
@ dw 0x69,0x9E,0x89,0x96
@ dw 0x00,0x10,0x01,0x00
@ dw 0x00,0x00,0x00,0x00
Ioannis
- 2nd September 2022, 09:07
Thanks for the new example.
In real life does it look like the video? I mean it seems that the scrolling is not very smooth but stepping a bit. OK, since the resolution is not that great this is expected I guess.
Ioannis
richard
- 2nd September 2022, 11:07
ITS as smooth as silk , can't say the same for the camera
made a better parametric version too
rotate:
asm
banksel _bcnt ;ROW
movlw 8
movwf _bcnt
banksel _inx
movlw 31 ;BUFFER SIZE
movwf _inx
NROW
banksel _inx
movlw high (_dspbuff)
movwf FSR0H
movlw low (_dspbuff)
movwf FSR0L
movf _inx,W
ADDWF FSR0L,F
bcf STATUS, C
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
btfss STATUS, C
GOTO NBNC
addfsr 0,3
bsf INDF0,7
NBNC
movlw 4 ;ROW LENGTH
SUBWF _inx,F
banksel _bcnt
DECFSZ _bcnt ,F
GOTO NROW
endasm
return
richard
- 2nd September 2022, 12:22
even nicer
rotate:
asm
banksel _bcnt ;ROW
movlw 8
movwf _bcnt
movlw high (_dspbuff)
movwf FSR0H
movlw low (_dspbuff)
movwf FSR0L
movlw 31 ;BUFFER SIZE
ADDWF FSR0L,F
banksel _bcnt
NROW
bcf STATUS, C
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
addfsr 0,-1
rrf INDF0 ,f ;PER COLUMN
btfss STATUS, C
GOTO NBNC
addfsr 0,3
bsf INDF0,7
addfsr 0,-3
NBNC
addfsr 0,-1
DECFSZ _bcnt ,F
GOTO NROW
endasm
return
Demon
- 14th February 2024, 19:04
https://youtu.be/DanYYBoVOBU
looks the same
Is anyone else getting "video not available" for Richard's stuff?
I can see Ioannis' video's properly.
richard
- 14th February 2024, 19:52
"video not available" for Richard's stuff?
i pressed the wrong button on my youtube dashboard and deleted a bit of stuff , its not recoverable and the originals are lost too
Powered by vBulletin® Version 4.1.7 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.