Basic stamp, MAX7219, 7 segment display and custom characters, how?
Hello.
I want to be able to display on 4 segment LED connected to BS2 via MAX7219 not only digits, but also some letters, which can be displayed, say A,C, H, L, P, E and some others. How should I?
I know that MAX7219 has so called "no decode" mode, which I already enabled, I'm using the code below for this:
The code, as posted, displays "1234". However, despite my attempts, I was not able to make it display any other chars. Only when I enable no decode mode and assign various digits to SWHi and SWLo, several random segments come on, but MAX7219 stucks after that, and I have to cycle power to make it responsive again.
I want to be able to display on 4 segment LED connected to BS2 via MAX7219 not only digits, but also some letters, which can be displayed, say A,C, H, L, P, E and some others. How should I?
I know that MAX7219 has so called "no decode" mode, which I already enabled, I'm using the code below for this:
' {$STAMP BS2}
' {$PBASIC 2.5}
Clk PIN 10
DIN PIN 12
CS PIN 11
SWord VAR Word 'word which is shifted out to 7219
SWHi VAR SWord.HIGHBYTE
SWLo VAR SWord.LOWBYTE
Digit VAR Word
cukuna VAR Word
begin:
HIGH CS 'normally not selected
LOW CLK 'make these outputs
LOW DIN
SWord = $0C01 'shutdown register, normal operation
GOSUB DMX7219
SWord = $09ff 'decode register, decode
GOSUB DMX7219
SWord = $0B07 'scan limit, all rows
GOSUB DMX7219
SWord = $0A05 'intensity register, medium
GOSUB DMX7219
Drive: 'display seven thru zero
FOR Digit = 0 TO 3 'go from right to left
SWHi = (digit+1)
SWLo = digit
GOSUB DMX7219
NEXT
END
DMX7219: 'drive MX 7219
LOW CS 'enable
SHIFTOUT DIN, CLK, MSBFIRST, [SWord \16] 'shift out 16 bits
HIGH CS 'it loads and executes
RETURN
The code, as posted, displays "1234". However, despite my attempts, I was not able to make it display any other chars. Only when I enable no decode mode and assign various digits to SWHi and SWLo, several random segments come on, but MAX7219 stucks after that, and I have to cycle power to make it responsive again.
Comments
You really need to study the MX7219 data sheet to understand how to program the chip. Here is a pointer to a page that will take you to it.
http://www.maximintegrated.com/en/products/power/display-power-control/MAX7219.html
Go to that page now, find the data sheet, download it and print it out. Do that now, before you continue with this message.
OK, got the data sheet in from of you? Look at Table 2 on page seven. This corresponds to SWHI in your code fragment. It specifies what register in the chip you are writing to. Addresses xxxx_0001 thru xxxx_1000 specify one of the eight digits.
Now look at table 6 on page 8. This corresponds to SWLO. In no-decode mode, each bit directly controls one segment (or DP).
So to write a "P" to digit three, I would program
[code]
SWHI = $03
SWLO = %01100111 'segments A, B, F, G, E
GOSUB DMX7219
[COLOR=#333333][FONT=Parallax]SWord = $0900 'decode register, no decode[/FONT][/COLOR]
1. It displays two additional segments in 4th digit
2. To update display, I have to turn off power, wait some time for capacitor discharge and then run code again. If not, then display won't get updated and it'll stuck.
As to extra segments, they may well be left over from before you turned decode off or however the MX7219 powered up. Here is a re-do of the code fragment that clears the display for sure and then programs four digits to letters. I'm sure you will know when it works.
' {$STAMP BS2} ' {$PBASIC 2.5} ' {$PORT COM14} Clk PIN 10 DIN PIN 12 CS PIN 11 SWord VAR Word 'word which is shifted out to 7219 Digit VAR SWord.HIGHBYTE Segments VAR SWord.LOWBYTE Work VAR Byte begin: HIGH CS 'normally not selected LOW CLK 'make these outputs LOW DIN SWord = $0C01 'shutdown register, normal operation GOSUB DMX7219 SWord = $0900 'decode register, no decode GOSUB DMX7219 SWord = $0B07 'scan limit, all rows GOSUB DMX7219 SWord = $0A08 'intensity register, medium GOSUB DMX7219 FOR digit = 1 TO 8 'make sure all segments of all digits are off Segments = 0 GOSUB DMX7219 NEXT Digit = 3 Segments = %01100111 'letter P on digit 3 GOSUB DMX7219 digit = 4 Segments = %01001111 'letter E on digit 4 GOSUB DMX7219 digit = 2 Segments = %00110000 GOSUB DMX7219 digit = 1 Segments = %01001110 GOSUB DMX7219 END DMX7219: 'drive MX 7219 LOW CS 'enable SHIFTOUT DIN, CLK, MSBFIRST, [SWord \16] 'shift out 16 bits HIGH CS 'it loads and executes RETURN
I see we have parallel threads on two forums. I am continuing on just this thread; the other will naturally go away.
Also, I changed the labels on the two halves of SWORD to make them a little more mnemonic.
1. FONT
Google "seven-segment font images" to get a look at the various attempts to build recognizable characters. Some look just fine, like numerics and "ACEFHLP"; some letters are lower case, like "bdgjnr"; some are just horrible, like "mn"; and some are ambiguous "IOKZ". I think my take-away is "A lot of people won't like it". The characters in my font are in ASCII order except I replaced the punctuation between "9" and "@" with the hex characters "A..F" which appear twice.
2. MX7219 Control
I think the MX7219 can very easily come up in a very bad state. I have a pullup on CS AND a pull-down on DataIn and it still likes to come up in lamp test. I have very carefully coded it to get out of lamp test and that appears to work reliably. Here is a pointer to a demo. As always, the video is over-exposed.
https://www.youtube.com/watch?v=X8szESJvHAw&feature=youtu.be
Here is the code, including the font:
' {$STAMP BS2} ' {$PBASIC 2.5} ' {$PORT COM4} Font30 DATA %01111110, %00110000, %01101101, %01111001, %00110011, %01011011, %01011111, %01110000 '0..7 Font38 DATA %01111111, %01111011, %01110111, %00011111, %01001110, %00111101, %01001111, %01000111 '8..F Font40 DATA 0, %01110111, %00011111, %01001110, %00111101, %01001111, %01000111, %01111011 '(@) A..g Font48 DATA %00110111, %00110000, %00111100, %00110111, %00001110, %01010100, %00010101, %01111110 'H..O Font50 DATA %01100111, %01110011, %00000101, %01011011, %00001111, %00111110, %00011100, %00101010 'P..w Font58 DATA %00110111, %00111011, %01101101 'XYZ M0 DATA "Hello world ", 0 M1 DATA "0123456789ABCDEF ", 0 M2 DATA "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 0 M3 DATA "The quick brown fox jumped over the lazy dogs back ", 0 M4 DATA "Now is the time for all good men to come to the aid of their country ", 0 M5 DATA "Four score and seven years ago ", 0 Clk PIN 10 DIN PIN 12 CS PIN 11 SWord VAR Word 'word which is shifted out to 7219 Digit VAR SWord.HIGHBYTE 'typically a register address Segments VAR SWord.LOWBYTE 'data for the register Ascii VAR Byte 'Ascii character Mess VAR Nib 'message number we are currently processing TextPoint VAR Word 'pointer into current message Buffer VAR Byte(8) 'letters being displayed (in the form of segments) GoesInAt VAR Nib 'buffer input pointer ComesOutAt VAR Nib 'buffer output pointer begin: HIGH CS 'normally not selected LOW CLK 'make these outputs LOW DIN Initialize: 'try to get control of MX7219 no matter how it comes up SWord = 0 'a nop, get it in sync with my commands GOSUB DMX7219 SWord = $0C00 'shutdown register, shutdown GOSUB DMX7219 SWord = $0F00 'not lamp test GOSUB DMX7219 SWord = $0C01 'shutdown register, normal operation GOSUB DMX7219 SWord = $0900 'decode register, no decode GOSUB DMX7219 SWord = $0B07 'scan limit, all rows GOSUB DMX7219 SWord = $0A02 'intensity register, medium GOSUB DMX7219 FOR digit = 1 TO 8 'make sure all segments of all digits are off Segments = 0 GOSUB DMX7219 NEXT top: FOR Mess = 0 TO 5 'do each of the messages in order LOOKUP Mess, [M0, M1, M2, M3, M4, M5], TextPoint GOSUB DoMessage PAUSE 2000 NEXT GOTO top DoMessage: READ TextPoint, Ascii 'get one Ascii character IF Ascii > 91 THEN Ascii = Ascii - 32 'convert lower case to upper case IF Ascii = 0 THEN RETURN 'end of message PAUSE 150 'not so fast IF Ascii = " " THEN segments = 0 'treat blank as a special case ELSE READ Font30+(Ascii-"0"), segments 'look up font ENDIF GOSUB DoChar 'insert one char into buffer and display entire buffer TextPoint = TextPoint + 1 'on to next character GOTO DoMessage DoChar: buffer(GoesInAt) = Segments 'insert new one ComesOutAt = (GoesInAt + 1) & %111 'modulo seven FOR digit = 8 TO 1 'now write from left to right segments = buffer(ComesOutAt) 'get the font GOSUB DMX7219 'send to display ComesOutAt = (ComesOutAt) + 1 &%111 'to next entry in buffer modulo 7 NEXT 'for each digit GoesInAt = (GoesInAt + 1) &%111 'next char will go at next slot (modulo 7) RETURN DMX7219: 'drive MX 7219 LOW CS 'enable SHIFTOUT DIN, CLK, MSBFIRST, [SWord \16] 'shift out 16 bits HIGH CS 'it loads and executes RETURN
Oddly enough, I struggled with the circular buffer. For a while I had convinced myself that, with such a short buffer, it was more efficient to actually shift the contents than to keep recomputing the output pointer.