Shifting message on an 8X8

wall_axe

Member
I'm pulling my hair out over this one. I've got an 8X8 LED hooked up to a MAX7219. I'm trying to display a message stored in EEPROM and scroll it right to left across the screen. So far I am able to look up the letter, convert it to the right "bit pattern" and store it in the scratchpad. What stumps me is how I keep track of what's being displayed. Ideally, locations 0 to 7 of scratchpad would mimic what the MAX7219 should display. I can scroll the alphabet since all the letters are in order...just not a message.

Can someone help me code a "scrolling window"?

Thanks!
 

Attachments

westaust55

Moderator
Firstly, a couple of comments on the code you posted:
1. Well done on good use of indentation
2. You could do to insert some comments so folks know more easily what the lines of code are specifically doing,


Now some guidance, your message is stored staring at location $90 and terminated with the value $FF

Each character is stored as an ASCII value, so
Space = $20 = 32
A = $41 = 65
B = $42 = 66
etc

Best to treat a space as a special case with an IF THEN test and set the pointer to EEPROM location 0

For all other character (A to Z) calculate the pointer to the EEPROM location by
EEPROM_Pointer = retrieved character value – 64 * 5

Now you can save these pointers to the character data in consecutive locations in say scratchpad starting at location 1 and onwards.
Use a location say scratchpad location 0 to indicate how many characters found in the string/message.
Use a location say scratchpad location 1 to indicate the current first character being displayed for scrolling purposes.


Now treat the display as a window showing 7 characters so you need a pointer to the first of the 7 visible characters.

Finally to fetch and display the data from EEPROM here in pseudo code:

Code:
Total_char = scratch_location0

First_char = 1 ; set up for start of sequence

DO
  Last_char = Firstchar + 6
  FOR Char_Ptr = First_char  TO Last_char
  Scratchpad_Ptr = Char_Ptr //  Total_char   ;  this gives us roll-over when get to end of message
  EEPROM location = value at location Scratchpad_Ptr
    FOR  Char_Data  = 1 TO 5
       Read the char_byte from EEPROM
       Send to display
  NEXT Char_Data
 NEXT Char_Ptr
INC First_char
LOOP
 
Last edited:

wall_axe

Member
westaust, thanks for the help. I posted an earlier version of the code. This is where I'm at right now. My main stumbling block is trying to keep the pointers straight. I see you have a character pointer and a scratchpad pointer. I guess that's my hang up. Here's where I left off last night:

Code:
'===-[ Variables ]-==========================================================
symbol maxreg = b0
symbol maxdata = b1
symbol index = b2
symbol currchar = b3
symbol temp = b4
symbol pointer = b5
symbol dispchar = b6
symbol tail = b7
symbol counter = b8


'===-[ PICAXE 20X2 Pin Definitions ]-========================================
symbol SData = B.2
symbol CS = B.3
symbol CLK = B.4


'===-[ MAX7221 Constants ]-==================================================
symbol noop = $00
symbol dig0 = $01
symbol dig1 = $02
symbol dig2 = $03
symbol dig3 = $04
symbol dig4 = $05
symbol dig5 = $06
symbol dig6 = $07
symbol dig7 = $08
symbol decode = $09
symbol intensity = $0A
symbol scan_limit = $0B
symbol shutdown = $0C
symbol display_test = $0F
symbol display_on = $01
symbol display_off = $00
symbol display_test_on = $01
symbol display_test_off = $00
symbol display_normal = $00
symbol blank = $0F


'===-[ Setup MAX7221 ]-======================================================
Setup_MAX7221:
	for index = 0 to 3
		lookup index,(decode,intensity,scan_limit,shutdown),maxreg
		lookup index,($00,$08,$07,display_on),maxdata
		gosub SendTo_Max7221
	next

pause 30
	
Clear_MAX7221:
	for index = 0 to 7
		lookup index,(dig0,dig1,dig2,dig3,dig4,dig5,dig6,dig7),maxreg
		maxdata = $00
		gosub SendTo_Max7221
	next
	
	
ptr = 0	
	
	
'===-[ Main Program ]-=======================================================

EEProm $90,("THE PICAXE ROCKS",254)

currchar = $90
pointer = 0

Main:
	for counter = 0 to 2
		read currchar, temp
		
		if temp = 32 then
			dispchar = $00
		else
			dispchar = temp - 65
			dispchar = dispchar * 5 + 5
		endif
		
		tail = pointer + 4
		temp = 0
		
		for index = pointer to tail
			read dispchar, temp
			put index, temp
			inc dispchar
		next
		inc index
		put index, $00
		
		inc currchar
		
		pointer = pointer + 6
	next
goto main
end



'===-[ Subroutines ]-========================================================
SendTo_Max7221:
	low CS
	shiftout CLK,SDATA,1,(maxreg,maxdata)
	high CS
	return
	

'===-[ FONT DATA ]-==========================================================
EEPROM $00,(%00000000,%00000000,%00000000,%00000000,%00000000)	' SPACE
EEPROM $05,(%00111111,%01000100,%01000100,%01000100,%00111111)	'A
EEPROM $0A,(%01111111,%01001001,%01001001,%01001001,%00110110)	'B
EEPROM $0F,(%00111110,%01000001,%01000001,%01000001,%00100010)	'C
EEPROM $14,(%01111111,%01000001,%01000001,%01000001,%00111110)	'D
EEPROM $19,(%01111111,%01001001,%01001001,%01001001,%01000001)	'E
EEPROM $1E,(%01111111,%01001000,%01001000,%01001000,%01000000)	'F
EEPROM $23,(%00111110,%01000001,%01001001,%01001001,%00101111)	'G
EEPROM $28,(%01111111,%00001000,%00001000,%00001000,%01111111)	'H
EEPROM $2D,(%00000000,%01000001,%01111111,%01000001,%00000000)	'I
EEPROM $32,(%00000010,%00000001,%01000001,%01111110,%01000000)	'J
EEPROM $37,(%01111111,%00001000,%00010100,%00100010,%01000001)	'K
EEPROM $3C,(%01111111,%00000001,%00000001,%00000001,%00000001)	'L
EEPROM $41,(%01111111,%00100000,%00011000,%00100000,%01111111)	'M
EEPROM $46,(%01111111,%00010000,%00001000,%00000100,%01111111)	'N
EEPROM $4B,(%00111110,%01000001,%01000001,%01000001,%00111110)	'O
EEPROM $50,(%01111111,%01001000,%01001000,%01001000,%00110000)	'P
EEPROM $55,(%00111110,%01000001,%01000101,%01000010,%00111101)	'Q
EEPROM $5A,(%01111111,%01001000,%01001100,%01001010,%00110001)	'R
EEPROM $5F,(%00110001,%01001001,%01001001,%01001001,%01000110)	'S
EEPROM $64,(%01000000,%01000000,%01111111,%01000000,%01000000)	'T
EEPROM $69,(%01111110,%00000001,%00000001,%00000001,%01111110)	'U
EEPROM $6E,(%01111100,%00000010,%00000001,%00000010,%01111100)	'V
EEPROM $73,(%01111110,%00000001,%00001110,%00000001,%01111110)	'W
EEPROM $78,(%01100011,%00010100,%00001000,%00010100,%01100011)	'X
EEPROM $7D,(%01110000,%00001000,%00000111,%00001000,%01110000)	'Y
EEPROM $82,(%01000011,%01000101,%01001001,%01010001,%01100001)	'Z
 

wall_axe

Member
After rereading the pseudo code, I think this would work with an 8x1 LCD but it doesn't seem like it would work with an 8x8 matrix. Each character is actually 5 columns of data. That's what is tripping me up. This seems simple...what am I missing????
 

westaust55

Moderator
Maybe you have not fully understood the pseudo code that I provided.
First we set the pointer for the first display character to the first character pointer
Then we enter the DO … LOOP structure forever
Within that loop we define the pointer to the last character to be displayed (ie 6 chars further on)
Then we step through from the current first to the current last chars to be displayed on the 7 character display
By using the modulus (//) function if we reach the end of the message the pointer will roll over back to the first character in the buffer.
For each of the five bytes of data used to create each character you must then read the data in and send it to the display
So the FOR Char_Data = 1 to 5 … NEXT structure does that. Inside you must read the 5 bytes of data by incrementing the location in the EEPROM read statement for each byte.
Then we increment the pointer for the first display character and loop back to do it all again.
 

wall_axe

Member
Maybe you have not fully understood the pseudo code that I provided.
That's usually the case until I can get it to "sink in"... :eek:

Here's my final code with comments. It gets the job done, but isn't overly pretty. I'll have to try the modulus trick to check for rolling over. Haven't done that before.

I was hoping to use this code to scroll the current time, but I don't think it will work. I'll try something else I guess.

Code:
'===-[ Variables ]-==========================================================
symbol head = b0		' start of eeprom translation
symbol tail = b1		' end of eeprom translation
symbol char = b2		' character that the loop read
symbol charpntr = b3	' which character are we looking at?
symbol scratchpntr = b4	' scratchpad pointer
symbol index = b5		' general purpose counter
symbol temp = b6		' general temp variable
symbol messageend = b7	' end of message scroll
symbol maxreg = b8	' register for MAX7219
symbol maxdata = b9	' data to send to MAX7219


'===-[ PICAXE 20X2 Pin Definitions ]-========================================
symbol SData = B.2	' MAX7219 serial data
symbol CS = B.3		' MAX7219 chip select
symbol CLK = B.4		' MAX7219 serial clock


'===-[ MAX7221 Constants ]-==================================================
symbol noop = $00			' no operation
symbol dig0 = $01			' column 0
symbol dig1 = $02			' column 1
symbol dig2 = $03			' column 2
symbol dig3 = $04			' column 3
symbol dig4 = $05			' column 4
symbol dig5 = $06			' column 5
symbol dig6 = $07			' column 6
symbol dig7 = $08			' column 7
symbol decode = $09		' turn on/off BCD decoding (off)
symbol intensity = $0A		' brightness
symbol scan_limit = $0B		' how many digits to display
symbol shutdown = $0C		' turn off MAX7219
symbol display_test = $0F	' test
symbol display_on = $01		' display on
symbol display_off = $00	' display off
symbol display_test_on = $01	' test on
symbol display_test_off = $00	' test off
symbol display_normal = $00	' normal operation
symbol blank = $0F		' blank display



EEPROM $90,(" THE PICAXE ROCKS",255)	' The message to display

charpntr = $90		' start of the message data in EEPROM
scratchpntr = 3		' scratchpad pointer starts at 3 for the data


'===-[ Setup MAX7221 ]-======================================================
' Quick setup routine for the MAX7221
Setup_MAX7221:
	for index = 0 to 3
		lookup index,(decode,intensity,scan_limit,shutdown),maxreg
		lookup index,($00,$08,$07,display_on),maxdata
		gosub SendTo_Max7221
	next

pause 30

' Clear anything on the display	
Clear_MAX7221:
	for index = 0 to 7
		lookup index,(dig0,dig1,dig2,dig3,dig4,dig5,dig6,dig7),maxreg
		maxdata = $00
		gosub SendTo_Max7221
	next

	

Main:
	do
	read charpntr, char			' grab a character
	
	if char = 255 then			' if char = 255 we've reached end of string
		goto ScratchPadLoaded		' go display the contents
	else
	
		Convert_Character:			' this subroutine converts to EEPROM location
			if char = 32 then
				char = $00			' special case for the space
			else
				char = char-64 * 5
			endif
		
		head = scratchpntr
		tail = head + 4				' set start and end points
		
		Load_Scratchpad:				
			for index = head to tail
				read char, temp		' this subroutine reads the EEPROM dada
				put index, temp		' and puts the contents into scratchpad
				inc char			' next column of the character
			next index
		
		inc index				' increase the counter and...
		put index, $00			' ...pad a space
		
		scratchpntr = tail + 2		' account for space padding
		inc charpntr			' go get the next character
	
	endif
	
	loop

ScratchPadLoaded:
	dec scratchpntr				' remove the last padded space
	put 0, scratchpntr			' put the value of scratchpntr into scratchpad location 0
	get 0, messageend			' load messageend with value
	
	scratchpntr = 3
	index = 0

Display_It:
	do
		head = scratchpntr		' set the start of column data
		tail = head + 7			' set the end of the column data
	
		temp = 1				' used to select column
		for index = head to tail	' get 8 columns of data
			get index, maxdata	' load column data into maxdata variable
			maxreg = temp		' select which column
			gosub SendTo_Max7221	' we have column and data -> go display it
			inc temp			' advance column pointer
		next index				' next column
		
		inc scratchpntr			' move "window" forward by 1
		pause 20				' slow down scrolling
		
	loop while scratchpntr < messageend		' do for length of message
	
	scratchpntr = 3		' reset the pointer to the beginning
	
	goto Display_It		' display the message forever

end



'===-[ Subroutines ]-========================================================
' maxreg is the digit (column) to be displayed
' maxdata is the LED pattern (1=on 0=off)
SendTo_Max7221:
	low CS
	shiftout CLK,SDATA,1,(maxreg,maxdata)
	high CS
	return


'===-[ FONT DATA ]-==========================================================
' 5x7 fonts
EEPROM $00,(%00000000,%00000000,%00000000,%00000000,%00000000)	' SPACE
'EEPROM $05,(%00111111,%01000100,%01000100,%01000100,%00111111)	'A
EEPROM $05,(%00011111,%00100100,%01000100,%00100100,%00011111)	'A - Alternate
EEPROM $0A,(%01111111,%01001001,%01001001,%01001001,%00110110)	'B
EEPROM $0F,(%00111110,%01000001,%01000001,%01000001,%00100010)	'C
EEPROM $14,(%01111111,%01000001,%01000001,%01000001,%00111110)	'D
EEPROM $19,(%01111111,%01001001,%01001001,%01001001,%01000001)	'E
EEPROM $1E,(%01111111,%01001000,%01001000,%01001000,%01000000)	'F
EEPROM $23,(%00111110,%01000001,%01001001,%01001001,%00101111)	'G
EEPROM $28,(%01111111,%00001000,%00001000,%00001000,%01111111)	'H
EEPROM $2D,(%00000000,%01000001,%01111111,%01000001,%00000000)	'I
EEPROM $32,(%00000010,%00000001,%01000001,%01111110,%01000000)	'J
EEPROM $37,(%01111111,%00001000,%00010100,%00100010,%01000001)	'K
EEPROM $3C,(%01111111,%00000001,%00000001,%00000001,%00000001)	'L
EEPROM $41,(%01111111,%00100000,%00011000,%00100000,%01111111)	'M
EEPROM $46,(%01111111,%00010000,%00001000,%00000100,%01111111)	'N
EEPROM $4B,(%00111110,%01000001,%01000001,%01000001,%00111110)	'O
EEPROM $50,(%01111111,%01001000,%01001000,%01001000,%00110000)	'P
EEPROM $55,(%00111110,%01000001,%01000101,%01000010,%00111101)	'Q
EEPROM $5A,(%01111111,%01001000,%01001100,%01001010,%00110001)	'R
;EEPROM $5F,(%00110001,%01001001,%01001001,%01001001,%01000110)	'S
EEPROM $5F,(%00110010,%01001001,%01001001,%01001001,%00100110)	'S - Alternate
EEPROM $64,(%01000000,%01000000,%01111111,%01000000,%01000000)	'T
EEPROM $69,(%01111110,%00000001,%00000001,%00000001,%01111110)	'U
EEPROM $6E,(%01111100,%00000010,%00000001,%00000010,%01111100)	'V
EEPROM $73,(%01111110,%00000001,%00001110,%00000001,%01111110)	'W
EEPROM $78,(%01100011,%00010100,%00001000,%00010100,%01100011)	'X
EEPROM $7D,(%01110000,%00001000,%00000111,%00001000,%01110000)	'Y
EEPROM $82,(%01000011,%01000101,%01001001,%01010001,%01100001)	'Z
 

westaust55

Moderator
Two comments before trying to guide you further.

1. Adding the alternative character data immediately after the EEPROM data for “A” and “S” will break the calculation char = char-64 * 5
If you want some alternatives suggest you put then at the end and treat by exception.

2. Are you trying to scroll left one pixel at a time (so 5 steps to move a character to the adjoining 5x8 cell, or
are you trying to scroll left one character at a time (in 5 pixel jumps)
That may have a big impact on how you can handle the data.
 

wall_axe

Member
1. Adding the alternative character data immediately after the EEPROM data for “A” and “S” will break the calculation char = char-64 * 5
If you want some alternatives suggest you put then at the end and treat by exception.
I didn't like the way the original "A" and "S" looked. I created new ones but don't want to get rid of the existing ones. I commented out the original "A" and "S" so the calculation isn't broken.

2. Are you trying to scroll left one pixel at a time (so 5 steps to move a character to the adjoining 5x8 cell, or
are you trying to scroll left one character at a time (in 5 pixel jumps)
That may have a big impact on how you can handle the data.
I want to smoothly scroll the message from the right of the display to the left of the display. This code works nicely but it's fairly limited in that the message size can't be very large because the scratchpad fills up. For the record, this code/circuit is breadboarded and is working. To confirm, I've attached an image of what I'm using.
 

Attachments

Simmicht

Senior Member
Version of code for 28X2

Great stuff, I love coming to the forum and finding just about exactly what I need.:).

I have modified the code to use the 28X2. Other feature enhancements are
  1. using code space for the font 5x7 not the EEPROM.
  2. extended the characters to be from SPACE ASCII 32 to ASCII 96
  3. mapped the lower case alphas to upper case.
  4. using the 28X2 gives 1024 bytes of decompressed message space and at 5 bytes per character that is about 200 characters of message.
To Do next will be to do cascading ....to 4 8x8 displays.

The new code is attached.
 

Attachments

william47316

New Member
probably not relevant however i have made a similar thing scrolling up to 150 characters on my 8digit display it just stores the characters on the spare eeprom of the picaxe 08M and sends out the bytes, 8 characters at a time and shifting over a character (on your display it would be a line if controlled direct), enough for my 8 digit display's serial input which im guessing yours would be basically the same thing 8 byte serial input to control the 8x8,

my display is using an 08m and shift register controlling 7 segments so it uses 1 byte per value lookup table for the 7 seg numbers and letters and some simple decoding to get the ASCII to the 7 segment,

depending on how your updating the display (multiplexed or shift registered) you may want a separate picaxe, one for controlling the screen and another for decoding ascii to the 8 byte code for the 8x8 display and scrolling a row at a time, the code below can be modified for such and it is carriage return terminated, eg you load in the characters in and send a carriage return and it goes and sends it out

either way, each letter for the 8x8 is going to take up 8 bytes, a bit less if you can compress the white space (0) codes down, for a full ascii character set your looking at 2 kilobytes right there a little less than 9-hundred-and-something bytes if you only do the first 126 and some coding mojo that will address and return, probably 1.5k for the processing + my code which will take ~104 bytes maybe with some mods and store characters on the remaining eeprom unless its seperate

that is if you want it controlled row by row, character by character will need the decoding on the driver, although the scrolling will be really clunky, similar code as below just get it to send out one at a time

Code:
'8 digit display scrolling addon
setfreq m8
if input1 = 0 then disp 'with a jumper pulling down it will loop the message to the display
'remove and reinsert to "program in"

main:
serin 3,n2400,b1 'serial in 4800 baud characters
if b1 = 13 then ' if its carriage return
write b2,b1 'write it
b2 = 0 'reset the byte
goto disp ' goto the display routine
end if
if b1 = 32 then ' if its a space
b1 = 0 'change it to a null
end if
write b2,b1 ' write
inc b2 ' increment the location
if b2 >= 151 then 'if its exceeded the space available
write b2,13 ' write a carriage return
goto disp 'and goto display scrolling routine
end if
goto main

disp:
b3 = b2 + 8 'take current b2 value and add 8
for b5 = b2 to b3 'count from b2 to b2+8
read b5,b4 'read it
if b4 = 13 then 'if its read a carriage return
pause 640 'pause a bit
b2 = 0 'reset
read b2,b4 'read the character at that location
end if
serout 0,n2400,(b4) 'serial out
next ' do the next one
pause 640
inc b2 'shift over one
if b2 >= 151 then
b2 = 0
end if
if input1 = 1 then 'if the link is off
b2 = 0 'reset
goto main ' go and set it to receive serial
end if
goto disp 'keep looping if above input is still low
 
Last edited:
Top