I think the methods in the child object are cleaner now. There aren't so many "rotated" versions of methods.
The main loop in the demo alternates between rotated displays and normal displays.
I added methods to make it easier to plot points and lines. The points and lines can be plotted on the combined arrays or there are methods to effect only a single array.
The object could greatly be improved with a double buffer. As it is now the plotted lines flash as they rotate. With a double buffer I could fill one section of memory while displaying another. I don't think the double buffer will be very hard to program but I'm getting kind of tired of this object for now. I'm sure I'll work on it more when my 16 array PCBs get delivered.
Once I have a larger number of displays to play with, I'll add support for multiple rows of arrays. The current driver can only make use of a single row.
I haven't made a video of the new code in action. but it can do a bit more than the previous version.
The best thing about the new code is I now have a clear understanding to the relationship between LEDs and the bits in the Propeller's RAM. The two types of displays (rotated and normal) store bitmaps in RAM differently from each other.
The method "IdentifyDisplays" will place a "1" in the first array, a "2" in the second and so on.
I considered not changing the bitmaps for the two type of displays but this would require rotating the bits prior to sending them to the MAX7219 chip. This would have severely increased the overhead of sending the bitmaps to the displays.
@Duane
In an effort to understand how your code works, I stripped out a lot things to get down to basics.
Your use of the dirb and outb registers for rotating a character map threw me and I decided to try a different approach.
I'm not sure if it is any slower but I find it easier to follow.
My program uses you ShiftOutSingle to display a character in each of my five arrays.
Here is the rotate logic:
VAR
byte work 'byte for rotate column
RotateChar(4,@freeDesign080)
RotateChar(3,@freeDesign105)
RotateChar(2,@freeDesign112)
RotateChar(1,@freeDesign112)
RotateChar(0,@freeDesign110)
PUB RotateChar(arynum, charptr) | idx,idy,idz,setb
idz := 1
repeat idy from 7 to 0
work := 000000
repeat idx from 0 to 7
setb := (byte[charptr + idx] & (|<idy)) 'get bit# idy from font
if setb > 0
work |= (|<idx) 'set bit# idx in work
ShiftOutSingle(arynum, idz, work)
idz+=1
. . .
Your use of the dirb and outb registers for rotating a character map threw me and I decided to try a different approach.
. . .
I can't say that I blame you. It's hard to see what I was doing as I look at the code today.
My first attempt to rotate the bits ended up placing the bits back in their original location. I was at least expecting the bits to be scrambled if I got it wrong, not put back in their original location.
The dirb and outb can be used like dira and outa, but the "b" registers don't affect any I/O pins. I'm sure I learned the trick used here on the forum.
In case those at home want to follow along here's the original version (the one that works).
"localFont" can be either zero or one to indicate which of the two fonts to use.
"localCharacter" is the letter to be rotated, for example "a". "destination" is the memory location where the eight bytes of the rotated character bitmap is to be stored.
PUB RotateCharacter(localFont, localCharacter, destination)
result := fontAddress[localFont] + (8 * (localCharacter - FIRST_CHARACTER))
if destination == -1
destination := result
RotateBitmap8x8(destination, result)
PUB RotateBitmap8x8(destination, source) | temp[2], scratch[2], rowOld, rowNew, colOld, colNew, testResult, testBit, bitOfInterest
'' This method rotates the bits in eight bytes
'' located at "source" and places the rotated bytes
'' in "destination".
'' "source" and "destination" may be the same
'' location.
'' The rotation is 90 degrees clockwise
'Pst.Str(string(13, " RotateCharacter"))
longfill(@temp, 0, 2)
bytemove(@scratch, source, LINES_IN_ARRAY)
repeat rowNew from 0 to 7
bitOfInterest := 7 - rowNew
repeat rowOld from 0 to 7
dirb[7..0] := byte[@scratch][rowOld]
outb[rowOld] := dirb[bitOfInterest]
byte[@temp][rowNew] := outb
'Pst.Str(string(13, " %"))
'Pst.Bin(byte[@temp][rowNew], LINES_IN_ARRAY)
bytemove(destination, @temp, LINES_IN_ARRAY)
I don't think I was trying for speed, I was just trying to get it to work. As I look at the above code I find it very hard to see what I was doing. IMO, rotating bits in a bitmap doesn't lend itself to easy to read code.
If one were really interested in getting text to scroll quickly, it would be a good idea to store the font bitmaps in a rotated state.
A rotated font would allow one column of bits to be easily read by just reading a single byte from the bitmap. As the font is currently stored, a column of bits has to be extracted from eight different bytes.
One reason for storing the bitmaps as they currently are is because it was easier to type them in this way. I think it's easier to read the vertical "1" and "2" in post #32 then the rotated numbers. Neither of these reasons is a very good one. It wouldn't be hard to write a program to output the bitmaps in their rotated state which could then be pasted into the DAT section of a program. How the font looks in the DAT section isn't a very important consideration.
I noticed the Simplytronics font isn't even displayed in binary.
Having the bitmap stored as hex only requires on line be character. Obviously the the Simplytronics font wouldn't be any harder to read in a rotated state than its current state.
I'm sure I'll be thinking more about these issues once my 16 array PCBs arrive. I think I submitted my order just after the cutoff date to have them made prior the "New Year" festivities so I probably have to wait a month before I receive them.
I also plan to work on scrolling larger bitmaps across multiple rows once I have some larger arrays to play with.
...
If one were really interested in getting text to scroll quickly, it would be a good idea to store the font bitmaps in a rotated state.
...
It wouldn't be hard to write a program to output the bitmaps in their rotated state which could then be pasted into the DAT section of a program.
I thought about writing a VBScript to rotate the bits and replace the character bit maps but decided that there might be a reason to use them as is.
A rotated font would allow one column of bits to be easily read by just reading a single byte from the bitmap.
As the font is currently stored, a column of bits has to be extracted from eight different bytes.
That's what my code does - it extracts a bit (using the "decode value" operator |<) from the same column in each row and builds a new byte setting the appropriate bits.
Effectively grabbing a column, and rotating it 90 degrees to the right...
I'm using WYSIWYG so the percent signs wont come through correctly.
I was going to post it after I clean it up. If you'd like I'll post it before cleaning it up.
I just noticed the SimplyTronics font isn't left justified. My scrolling software assumes fonts are left justified. I'll need to decide if I care enough to edit the font.
I just wrote a Spin program that rotates the fonts and outputs the bits to the terminal.
...
I'm using WYSIWYG so the percent signs wont come through correctly.
I was going to post it after I clean it up. If you'd like I'll post it before cleaning it up.
I just noticed the SimplyTronics font isn't left justified. My scrolling software assumes fonts are left justified. I'll need to decide if I care enough to edit the font.
Pretty slick!
I tweaked some of the freeDesign character maps like the lower case "i".
It looked strange left justified - created a big gap between it and the following character, so I shoved it over a couple of pixels...
I tweaked some of the freeDesign character maps like the lower case "i".
It looked strange left justified - created a big gap between it and the following character, so I shoved it over a couple of pixels...
Is this with the font scrolling?
There should be the same number of spaces between each character when scrolled (if the font is left justified).
Part of the setup process finds the width of each character and stores it in the "characterWidth" array, so then the "ScrollCharacter" method is called it wont use the empty columns of the bitmap.
PRI ScrollCharacter(characterPtr) | fontPtr, localSize '' Font does not need to be rotated.
fontPtr := fontAddress[activeFontId] + (LINES_IN_ARRAY * (byte[characterPtr] - FIRST_CHARACTER))
localSize := [B]characterWidth[/B][(activeFontId * CHARACTERS) + (byte[characterPtr] - FIRST_CHARACTER)]
ScrollBitmap(fontPtr, localSize)
ScrollBlank(LINES_BETWEEN_CHARACTERS)
The space between character can be changed by changing the value of "LINES_BETWEEN_CHARACTERS".
Spaces have a defined width of matching the width of the letter "n". In my education media class (we called it the "bulletin board" class) they called this "n spacing" where the space was supposed to have the same width as the letter n.
After the width of a font has been found the space width (which would have initially been zero) is changed to match the width of a "n".
No, it wasn't during scrolling - at least not with the freeDesign font but it does with the other font. Probably because it isn't left justified as you said earlier.
It can be seen at .25 secs in my latest video above.
I'm glad you explained now the FindWidth, etc functions work.
I was just looking through your code. I like your idea of measuring the width of a character on the fly. I was kind of concerned about the time is would take. It's one of those speed vs memory trade offs. I chose speed over memory savings but I might switch to the way you're doing it. I don't like having to have a separate memory for each characters width.
You're ordering the arrays opposite to how I am (at least in the latest drivers). I might have ordered them differently with my first attempt.
Thanks for sharing your modifications. I'll likely incorporate some of your changes into my version.
I'm seriously thinking of making a PASM version of the method "LoadBitsToArray". Once I'm up to 16 or more arrays, animations and scrolling text will take too long to shift out bits in Spin.
I also want to use a double buffer so one buffer can be updated while the other one is displayed.
I started adding a double buffer in the Spin version but I realized, it didn't do any good unless I add a second cog to shift out bits from one buffer while the other buffer is being written to. If I'm going to the trouble of adding a second cog, I'll probably have it run PASM.
IMO, these LEDs are a fun way of learning about memory manipulation and shifting bits.
I was just looking through your code. I like your idea of measuring the width of a character on the fly. I was kind of concerned about the time is would take. It's one of those speed vs memory trade offs. I chose speed over memory savings but I might switch to the way you're doing it. I don't like having to have a separate memory for each characters width.
You're ordering the arrays opposite to how I am (at least in the latest drivers). I might have ordered them differently with my first attempt.
Thanks for sharing your modifications. I'll likely incorporate some of your changes into my version.
I'm seriously thinking of making a PASM version of the method "LoadBitsToArray". Once I'm up to 16 or more arrays, animations and scrolling text will take too long to shift out bits in Spin.
I also want to use a double buffer so one buffer can be updated while the other one is displayed.
I started adding a double buffer in the Spin version but I realized, it didn't do any good unless I add a second cog to shift out bits from one buffer while the other buffer is being written to. If I'm going to the trouble of adding a second cog, I'll probably have it run PASM.
IMO, these LEDs are a fun way of learning about memory manipulation and shifting bits.
That last code I had from you was from Jan 28. Ordering the arrays from right to left was a PAIN - I may change mine around although I've gotten used to dealing with the way they are ordered now.
I also had trouble trying to use your waitcnt delay routines in my version but my approach seems to work with without problems (due the 53 sec system counter rollover).
I hope you continue to post your code as you make improvements.
- Ron
I figured out what you meant by the "ordering" of the arrays. The ShiftoutSingle procedure in the code I grabbed from your posted zip handled the arrays as 4 to 0 (left to right) while all my other code was ordering them 0 to 4 (left to right).
No wonder I was having trouble!! Now everything is ordered 0 to 4.
I created some routines that let me set any individual LED on or off using a column number (1 to 40 with five arrays) and row number (1 to 8).
I use the memory array to store the bit pattern for each of the 40 columns so I can maintain the status of each LED.
I set or clear one bit in a byte representing a particular column and update only that specific column using the ShiftoutSingle routine.
Here is a video setting individual LEDs at two different speeds and directions...
(The camera keeps trying to adjust the exposure)
EDIT: Here is the routine
VAR
byte work
PUB SetPixel(colnum, rownum, status) | arraynum, arraycol, pixel
'turn individual LED on or off
'colnum ranges from 1 to number of arrays x 8
'rownum ranges from 1 to 8
'status: 1 turns on LED, 0 turns it off
work := byte[arrayAddress-1+colnum]
arraynum := (colnum-1) / 8
arraycol := ((colnum-1) // 8) + 1
pixel := 7 - (rownum - 1)
if status
work |= (|<pixel) 'set bit 'pixel' to 1
else
work &= !(|<pixel) 'set bit 'pixel' to 0
ShiftOutSingle(arraynum, arraycol, work)
byte[arrayAddress-1+colnum] := work
@Duane Degn, I just wanted to say thanks for the help with this. I ordered several of these from EBay but low and behold the 10 uf capacitor location on the board did not show a + or -. Try explaining that to the Chinese seller!!!! Fortunately yours is marked. I have one of them going. Just a quick question, is CS the Data Out? I want to daisy chain the ones I have but need to verify this before moving forward.
EDIT: I could actually use a quick schematic of how to daisy chain.
EDIT::: After looking at post #23 I was able to figure it out. Great work all!
EDIT:::: @Ron Czapala, Is the code in post #44 an add on to other code or what? I would like to accomplish the same thing as in yor video.
No, CS stands for Chip Select. Though it's technically not really the normal chip select used with standard SPI chips. Instead it's called "Load" on the MAX7219 datasheet. Even though it's technically called "Load" all the PCBs I've seen which use the MAX7219 label it "CS".
Data Out is labeled "DOUT" in the photo photo below.
(Photo from post #1 of this thread.)
All the pins on one side of the board are electrically connected to the pins on the other side except the data pins. One side has a Data In "DIN" and the other side a Data Out "DOUT".
Here's the traces of one of the small PCBs I made.
With four of the pins, you can follow the red traces from the 5-pin header on the left side across the board to the 5-pin header on the right. All the pins on the left are electrically connected to the corresponding pins on the right except the center pins which are the data pins (the pins are in the same order as on the green PCB pictured above).
The microcontroller connects to the Data In pin on the first board and the Data Out of the first board connects with the Data In pin on the second board. The chain can be continued by connecting the Data Out pin of one board to the Data In pin of the next board in line.
Lots of this boards have the headers positioned so one board can be chained to the next using jumpers. Here's a picture showing some boards from ICStation and small purple boards I made. Both types of PCBs can be linked with jumpers.
The code attached to post #3 includes a "SetBufferPixel" method. I think it's similar to Ron's "SetPixel" method.
PUB SetBufferPixel(localX, localY, localState) | arrayIndex, localBit'' Changes bit value at location localX, localY in active array to localState.
'' Returns the index value of the byte containing the pixel.
'' Returns -1 if the coordinates are outside the buffer area.
'' The changes made to the buffer do not change the LEDs until
'' "LoadBitsToArray" is called or the register with the
'' updated pixel is written.
"localState" should be set to one to turn the pixel on or set to zero to turn it off.
I still need to incorporate Tom's code in with mine.
My latest code will use the ROM font to display text with an array 32 pixels high but by the time I make an array that's 32 pixels high and at least 32 pixels wide, the refresh rate using Spin becomes painfully slow. Incorporating Tom's driver will solve this problem. I've built a large display but I haven't spent the time needed to get the code working properly. Getting Tom's code to work with mine has been at the top of my Propeller todo list for a while now and as has been the case for the at least a month, I'm just a few days away from getting back to work on this project. I really do want to get back to this project so can make use of my larger display. I presently have 64 x 64 pixel display which I intend to expand to 96 x 64 very soon.
I must be doing something wrong. I have 2 Arrays daisy chained but the text does not scroll from one to the other. Rather, the text is the same on both arrays. Anyone know what the issue is?
I don't think a picture will be of much help as it is a spider web so I will explain what I have. I am using a Prop BOE Board.LED Master Array: VCC to 5V, GND to Ground (on BOE Board), DIN to Pin 14, CLK to Pin 13, CS to Pin 14. LED Slave Array: VCC to 5V, GND to Ground (On BOE Board), DOUT to DIN on Master, CLK to CLK on Master, CS to CS on Master. I have changed "ARRAYS_IN_USE" to 2. The code I am trying is the 3 Demos you created, Max7219Demo131226c, Max7219Demo140128d and Max140116e. I also tried Ron's ScrollDemo and I get the same results. I will post a video as soon as I figure out how to shrink the size down without having to zip it.
DAT programName byte "Max7219Demo131226c", 0
CON
{{
******* Public Notes *******
Author: Duane Degn
Date: December 26, 2013
MIT License
An attempt to control an 8x8 LED array with a MAX7219 chip.
The number of arrays may be changed by changing the
"ARRAYS_IN_USE" constant.
The constants marked with "User changeable" may be
changed based on the LED project is configured.
The code in this program is pretty much all original.
I did look at Hover1's 7-segment MAX7219 code. Which
helped get me started.
}}
{
******* Private Notes *******
131225c Displays a message one character at a time.
25c Appears to be working.
25d Change font with each message.
25e Try to rotate text.
25e Didn't work.
25g Rotation worked.
25h Try to add scrolling.
25j Working reasonably well.
25k Seems to scroll single rotated array correctly.
25l Try adding additional array.
25l Doesn't work. The two displays are almost the
same. Both have lots of glitches.
25m Better but a lot of noise on the last display.
25n Much worse.
25o Abandon 25n.
26a Start moving MAX7219 specific code to a
child object.
26a Appears to work correctly.
26b Make the split.
26b Appears to work correctly using the child
object "Max7219MultiArray131226b".
26c Start adding a few features.
}
CON ' Parent Constants
_clkmode = xtal1 + pll16x
_xinfreq = 5_000_000
CS_PIN = 15 '' User changeable
DATA_PIN = 14 '' User changeable
CLOCK_PIN = 13 '' User changeable
ARRAYS_IN_USE = 2 '' User changeable
QUOTE = 34
VAR
byte arrayBuffer[Leds#LINES_IN_ARRAY * ARRAYS_IN_USE]
OBJ
Leds : "Max7219MultiArray131226c"
PUB Demo
Leds.Init(CLOCK_PIN, DATA_PIN, CS_PIN, ARRAYS_IN_USE, @arrayBuffer)
waitcnt(clkfreq * 2 + cnt) ' time to open terminal window
MainLoop
PUB MainLoop
repeat
Leds.SetFont(Leds#FREE_DESIGN)
Leds.ScrollRotatedText(@message0)
Leds.SetFont(Leds#ASCII_0508)
Leds.ScrollRotatedText(@message0)
DAT
message0 byte "Merry Christmas ", 0
Without switching the wires, switch the order of the arrays. Put the array on the right on the left.
After doing the above, slap your forehead.
It's easier to see the arrays are working correctly by pausing the video than it would be in real life since it's hard to freeze images in our brain.
I'm pretty sure the order isn't consistent in my first attempts at a driver so be prepared to rearrange the arrays when trying different versions of the driver.
So what do you use to power the arrays? I am using a 12V 2 Amp Wall Wart on my BOE Board and it controls 2 of the Arrays. I then hooked up my bench top power supply to power the third one. Working on soldering the fourth one and I am thinking of putting together a case to hold all 4 in and was thinking of using @erco's favorite rechargeable batteries. I just need to put together a Prop on a small PCB to control the arrays as I do not want to waste an entire Prop BOE Board for them!!
I'm still trying to figure out the best way to power these type of arrays. When I'm working at the computer, I tend to use my bench supply. Sometimes I'll power one or two arrays from a QuickStart's Vin pin while the QuickStart is powered by an USB connection.
There are lots of 5V chargers with USB connections on them. These might be a good power supply for a few arrays.
For a portable display, I've used four AA NiMH cells with a holder like this one (it has a built in power switch). I also use Li-Ion cells and LiPo packs along with a DC-DC regulator.
I agree with your not wanting to use the PropBOE just to control your arrays. Currently, the least expensive Propeller board I'm aware of is the Propeller Project Board. If you can find some QuickStart boards on sale from Radio Shack they would work well to control the arrays.
The project board is quite large for controlling 4 arrays. Any reason the Prop Mini would not work? http://www.parallax.com/product/32150
I can also put my own together with chip and a crystal and a few other components. I think if the Prop Mini will work that might be the easiest way to go. I am going to mount the 4 I currently have in something, possibly Polymorph if the Shack still has it on sale. I would like to get my hands on one of your 16 array boards. I could have some fun with one or two of those!!!
If any of you use this object, I hope you let me know. It's always fun to learn when someone else is using code I wrote.
I'll add some details on how to use the program in the following posts.
I have wired up 4 of these displays and was really amazed at the brightness they give out...... even @3.3V supply to them (outside in sunlight ....wonderful)
Your examples work well and I am currently try to clear the "Chaff from the Wheat" to see what is going on....
Q:- I have a question with regards to using the 8x8 Led Array in a 2x2 array ie a square of 4 modules.
I have only seen examples of them working in a linear scrolling fashion...
.......so what i am asking is there an easy way to give for example an X,Y coordinate and get it to plot a point say 12,12 ..... ?
I used a triple stacked "Turned Pin IC sockets" to raise the two right most arrays (2&4) .... which means they can easily be butted together.
Q:- I have a question with regards to using the 8x8 Led Array in a 2x2 array ie a square of 4 modules.
I have only seen examples of them working in a linear scrolling fashion...
.......so what i am asking is there an easy way to give for example an X,Y coordinate and get it to plot a point say 12,12 ..... ?
Hi Gareth,
I do have code which allows any arbitrary size of array and there's code to place a pixel anywhere on the array.
I've used this code to display 32x32 bitmaps and to scroll the Parallax font from ROM.
I've been meaning to get back to working on this code and add Tom's PASM MAX7219 driver to allow faster display updates. I've been planning on working on this code "sometime in the next few days" for the last few months. I'll work on it today.
I don't know if you've seen the thread about the smaller arrays? Post #102 of the thread shows a partially populated PCB with can hold 16 of the small arrays. I successfully used my code on a 64x32 pixel array but when I tried it on a 64x64 display, it didn't work correctly. I'm planning on adding two more of the PCBs to my display to make it 96x64 pixels and I'll need to use Tom's code to speed up the refresh.
I'll be working on this today and I'll hopefully have code to allow easy X, Y placement of pixels on any size of array posted today or tomorrow.
I've never tried to run the MAX7219 chips at 3.3V. I'm surprised they work. Interesting.
I'll be working on the code in between my experiments to add color to Polymorph. I wonder who I should blame the coloured Polymorph distraction on?
I've used this code to display 32x32 bitmaps and to scroll the Parallax font from ROM.
Aha... I am glad you are doing the ROM extraction for the Max chip...............my POV ROM extraction was quite a feat too....
Indeed yes I have been watching your Mega Panel .... woohooo .... this is one reason for me to check these display types out..... that display is calling out for the "Life" program..
I was on my way to try to trap the x,y coords and port and cross jump the result to each display...messy however a quick work around.... I have not tried Toms driver yet....so will do so "Next" before i go further...
Re:- 3.3Volts ..... surprised me to....... strangely I just checked the Max Spec sheet and it quotes the supply voltage 5.5V down to about 4.0V ...... even stranger....
Coloured PM ... oh I still remember the pigment ,,lots of it,,, and glowing hands after the UV pigment ....
BTW if you add around 40% by volume graphite to the PM a calculated guess "says" it will conduct.... more about that in the not to distant future....... exciting times are developing.
Hai everyone , is possible two set module max7219 running with different pattern on LED dot matrix at the same signal line?
For example, one of dot matrix scrolling "L" to left another one dot matrix just display 'G' only.
Comments
I think the methods in the child object are cleaner now. There aren't so many "rotated" versions of methods.
The main loop in the demo alternates between rotated displays and normal displays.
I added methods to make it easier to plot points and lines. The points and lines can be plotted on the combined arrays or there are methods to effect only a single array.
The object could greatly be improved with a double buffer. As it is now the plotted lines flash as they rotate. With a double buffer I could fill one section of memory while displaying another. I don't think the double buffer will be very hard to program but I'm getting kind of tired of this object for now. I'm sure I'll work on it more when my 16 array PCBs get delivered.
Once I have a larger number of displays to play with, I'll add support for multiple rows of arrays. The current driver can only make use of a single row.
I haven't made a video of the new code in action. but it can do a bit more than the previous version.
The best thing about the new code is I now have a clear understanding to the relationship between LEDs and the bits in the Propeller's RAM. The two types of displays (rotated and normal) store bitmaps in RAM differently from each other.
The method "IdentifyDisplays" will place a "1" in the first array, a "2" in the second and so on.
Here's the code:
"arrayAddress" holds the memory location where the active bitmap is stored.
On a normal array, the numeric characters can be placed in the active bitmap with a simple "bytemove".
So if two arrays were used, the contents of the active bitmap would be:
If the arrays are rotated, then these characters would be stored like this:
I considered not changing the bitmaps for the two type of displays but this would require rotating the bits prior to sending them to the MAX7219 chip. This would have severely increased the overhead of sending the bitmaps to the displays.
In an effort to understand how your code works, I stripped out a lot things to get down to basics.
Your use of the dirb and outb registers for rotating a character map threw me and I decided to try a different approach.
I'm not sure if it is any slower but I find it easier to follow.
My program uses you ShiftOutSingle to display a character in each of my five arrays.
Here is the rotate logic:
I can't say that I blame you. It's hard to see what I was doing as I look at the code today.
My first attempt to rotate the bits ended up placing the bits back in their original location. I was at least expecting the bits to be scrambled if I got it wrong, not put back in their original location.
The dirb and outb can be used like dira and outa, but the "b" registers don't affect any I/O pins. I'm sure I learned the trick used here on the forum.
In case those at home want to follow along here's the original version (the one that works).
"localFont" can be either zero or one to indicate which of the two fonts to use.
"localCharacter" is the letter to be rotated, for example "a". "destination" is the memory location where the eight bytes of the rotated character bitmap is to be stored.
I don't think I was trying for speed, I was just trying to get it to work. As I look at the above code I find it very hard to see what I was doing. IMO, rotating bits in a bitmap doesn't lend itself to easy to read code.
If one were really interested in getting text to scroll quickly, it would be a good idea to store the font bitmaps in a rotated state.
A rotated font would allow one column of bits to be easily read by just reading a single byte from the bitmap. As the font is currently stored, a column of bits has to be extracted from eight different bytes.
One reason for storing the bitmaps as they currently are is because it was easier to type them in this way. I think it's easier to read the vertical "1" and "2" in post #32 then the rotated numbers. Neither of these reasons is a very good one. It wouldn't be hard to write a program to output the bitmaps in their rotated state which could then be pasted into the DAT section of a program. How the font looks in the DAT section isn't a very important consideration.
I noticed the Simplytronics font isn't even displayed in binary.
Here's Simplytronic's "1" and "2" "bitmaps".
Having the bitmap stored as hex only requires on line be character. Obviously the the Simplytronics font wouldn't be any harder to read in a rotated state than its current state.
I'm sure I'll be thinking more about these issues once my 16 array PCBs arrive. I think I submitted my order just after the cutoff date to have them made prior the "New Year" festivities so I probably have to wait a month before I receive them.
I also plan to work on scrolling larger bitmaps across multiple rows once I have some larger arrays to play with.
I thought about writing a VBScript to rotate the bits and replace the character bit maps but decided that there might be a reason to use them as is.
That's what my code does - it extracts a bit (using the "decode value" operator |<) from the same column in each row and builds a new byte setting the appropriate bits.
Effectively grabbing a column, and rotating it 90 degrees to the right...
This thread was helpful: http://forums.parallax.com/showthread.php/118828-1-Bit-variables-in-Propeller
Ron,
I just wrote a Spin program that rotates the fonts and outputs the bits to the terminal.
Here's the last of the output.
I'm using WYSIWYG so the percent signs wont come through correctly.
I was going to post it after I clean it up. If you'd like I'll post it before cleaning it up.
I just noticed the SimplyTronics font isn't left justified. My scrolling software assumes fonts are left justified. I'll need to decide if I care enough to edit the font.
Pretty slick!
I tweaked some of the freeDesign character maps like the lower case "i".
It looked strange left justified - created a big gap between it and the following character, so I shoved it over a couple of pixels...
Is this with the font scrolling?
There should be the same number of spaces between each character when scrolled (if the font is left justified).
Part of the setup process finds the width of each character and stores it in the "characterWidth" array, so then the "ScrollCharacter" method is called it wont use the empty columns of the bitmap.
The space between character can be changed by changing the value of "LINES_BETWEEN_CHARACTERS".
Spaces have a defined width of matching the width of the letter "n". In my education media class (we called it the "bulletin board" class) they called this "n spacing" where the space was supposed to have the same width as the letter n.
After the width of a font has been found the space width (which would have initially been zero) is changed to match the width of a "n".
From the "FindWidth" method.
If you were to just place a character in the buffer with bytemove, then you'd want to make sure and adjust the spacing.
Here's the main part which rotates and displays the fonts (somewhat edited).
The output from the terminal could be cut and pasted into a program to use the rotated font.
It can be seen at .25 secs in my latest video above.
I'm glad you explained now the FindWidth, etc functions work.
I took a stab at creating a stripped down version as I went along.
Instead of calculating and storing the width of each character map, I drop blank columns on the fly as I load them into the buffer.
Of course, I had to modify the ASCII_0508 patterns to left justify them for this to work.
I added a character shifting approach to display and shift characters rather than columns and a All Characters routine to scroll thru the entire font.
Think I'm finally getting a better handle on driving these MAX7219 modules thanks to your efforts!
You're ordering the arrays opposite to how I am (at least in the latest drivers). I might have ordered them differently with my first attempt.
Thanks for sharing your modifications. I'll likely incorporate some of your changes into my version.
I'm seriously thinking of making a PASM version of the method "LoadBitsToArray". Once I'm up to 16 or more arrays, animations and scrolling text will take too long to shift out bits in Spin.
I also want to use a double buffer so one buffer can be updated while the other one is displayed.
I started adding a double buffer in the Spin version but I realized, it didn't do any good unless I add a second cog to shift out bits from one buffer while the other buffer is being written to. If I'm going to the trouble of adding a second cog, I'll probably have it run PASM.
IMO, these LEDs are a fun way of learning about memory manipulation and shifting bits.
That last code I had from you was from Jan 28. Ordering the arrays from right to left was a PAIN - I may change mine around although I've gotten used to dealing with the way they are ordered now.
I also had trouble trying to use your waitcnt delay routines in my version but my approach seems to work with without problems (due the 53 sec system counter rollover).
I hope you continue to post your code as you make improvements.
- Ron
I figured out what you meant by the "ordering" of the arrays. The ShiftoutSingle procedure in the code I grabbed from your posted zip handled the arrays as 4 to 0 (left to right) while all my other code was ordering them 0 to 4 (left to right).
No wonder I was having trouble!! Now everything is ordered 0 to 4.
I created some routines that let me set any individual LED on or off using a column number (1 to 40 with five arrays) and row number (1 to 8).
I use the memory array to store the bit pattern for each of the 40 columns so I can maintain the status of each LED.
I set or clear one bit in a byte representing a particular column and update only that specific column using the ShiftoutSingle routine.
Here is a video setting individual LEDs at two different speeds and directions...
(The camera keeps trying to adjust the exposure)
EDIT: Here is the routine
EDIT: I could actually use a quick schematic of how to daisy chain.
EDIT::: After looking at post #23 I was able to figure it out. Great work all!
EDIT:::: @Ron Czapala, Is the code in post #44 an add on to other code or what? I would like to accomplish the same thing as in yor video.
No, CS stands for Chip Select. Though it's technically not really the normal chip select used with standard SPI chips. Instead it's called "Load" on the MAX7219 datasheet. Even though it's technically called "Load" all the PCBs I've seen which use the MAX7219 label it "CS".
Data Out is labeled "DOUT" in the photo photo below.
(Photo from post #1 of this thread.)
All the pins on one side of the board are electrically connected to the pins on the other side except the data pins. One side has a Data In "DIN" and the other side a Data Out "DOUT".
Here's the traces of one of the small PCBs I made.
With four of the pins, you can follow the red traces from the 5-pin header on the left side across the board to the 5-pin header on the right. All the pins on the left are electrically connected to the corresponding pins on the right except the center pins which are the data pins (the pins are in the same order as on the green PCB pictured above).
The microcontroller connects to the Data In pin on the first board and the Data Out of the first board connects with the Data In pin on the second board. The chain can be continued by connecting the Data Out pin of one board to the Data In pin of the next board in line.
Lots of this boards have the headers positioned so one board can be chained to the next using jumpers. Here's a picture showing some boards from ICStation and small purple boards I made. Both types of PCBs can be linked with jumpers.
While I like the ICStation boards, I think I also like these boards from Electrodragon.
The Electrodragon boards have mounting holes.
"localState" should be set to one to turn the pixel on or set to zero to turn it off.
One problem with my driver is it's really slow. Tom Crawford has written a PASM driver which updates the arrays much faster than my Spin version.
I still need to incorporate Tom's code in with mine.
My latest code will use the ROM font to display text with an array 32 pixels high but by the time I make an array that's 32 pixels high and at least 32 pixels wide, the refresh rate using Spin becomes painfully slow. Incorporating Tom's driver will solve this problem. I've built a large display but I haven't spent the time needed to get the code working properly. Getting Tom's code to work with mine has been at the top of my Propeller todo list for a while now and as has been the case for the at least a month, I'm just a few days away from getting back to work on this project. I really do want to get back to this project so can make use of my larger display. I presently have 64 x 64 pixel display which I intend to expand to 96 x 64 very soon.
If you post your code as an archive we can take a look at it.
A picture of your wiring may be helpful.
After doing the above, slap your forehead.
It's easier to see the arrays are working correctly by pausing the video than it would be in real life since it's hard to freeze images in our brain.
I'm pretty sure the order isn't consistent in my first attempts at a driver so be prepared to rearrange the arrays when trying different versions of the driver.
Electricity.
I'm still trying to figure out the best way to power these type of arrays. When I'm working at the computer, I tend to use my bench supply. Sometimes I'll power one or two arrays from a QuickStart's Vin pin while the QuickStart is powered by an USB connection.
There are lots of 5V chargers with USB connections on them. These might be a good power supply for a few arrays.
For a portable display, I've used four AA NiMH cells with a holder like this one (it has a built in power switch). I also use Li-Ion cells and LiPo packs along with a DC-DC regulator.
I agree with your not wanting to use the PropBOE just to control your arrays. Currently, the least expensive Propeller board I'm aware of is the Propeller Project Board. If you can find some QuickStart boards on sale from Radio Shack they would work well to control the arrays.
I can also put my own together with chip and a crystal and a few other components. I think if the Prop Mini will work that might be the easiest way to go. I am going to mount the 4 I currently have in something, possibly Polymorph if the Shack still has it on sale. I would like to get my hands on one of your 16 array boards. I could have some fun with one or two of those!!!
Not that I'm aware of.
I have wired up 4 of these displays and was really amazed at the brightness they give out...... even @3.3V supply to them (outside in sunlight ....wonderful)
Your examples work well and I am currently try to clear the "Chaff from the Wheat" to see what is going on....
Q:- I have a question with regards to using the 8x8 Led Array in a 2x2 array ie a square of 4 modules.
I have only seen examples of them working in a linear scrolling fashion...
.......so what i am asking is there an easy way to give for example an X,Y coordinate and get it to plot a point say 12,12 ..... ?
I used a triple stacked "Turned Pin IC sockets" to raise the two right most arrays (2&4) .... which means they can easily be butted together.
Regards G
Hi Gareth,
I do have code which allows any arbitrary size of array and there's code to place a pixel anywhere on the array.
I've used this code to display 32x32 bitmaps and to scroll the Parallax font from ROM.
I've been meaning to get back to working on this code and add Tom's PASM MAX7219 driver to allow faster display updates. I've been planning on working on this code "sometime in the next few days" for the last few months. I'll work on it today.
I don't know if you've seen the thread about the smaller arrays? Post #102 of the thread shows a partially populated PCB with can hold 16 of the small arrays. I successfully used my code on a 64x32 pixel array but when I tried it on a 64x64 display, it didn't work correctly. I'm planning on adding two more of the PCBs to my display to make it 96x64 pixels and I'll need to use Tom's code to speed up the refresh.
I'll be working on this today and I'll hopefully have code to allow easy X, Y placement of pixels on any size of array posted today or tomorrow.
I've never tried to run the MAX7219 chips at 3.3V. I'm surprised they work. Interesting.
I'll be working on the code in between my experiments to add color to Polymorph. I wonder who I should blame the coloured Polymorph distraction on?
Indeed yes I have been watching your Mega Panel .... woohooo .... this is one reason for me to check these display types out..... that display is calling out for the "Life" program..
I was on my way to try to trap the x,y coords and port and cross jump the result to each display...messy however a quick work around.... I have not tried Toms driver yet....so will do so "Next" before i go further...
Re:- 3.3Volts ..... surprised me to....... strangely I just checked the Max Spec sheet and it quotes the supply voltage 5.5V down to about 4.0V ...... even stranger....
Coloured PM ... oh I still remember the pigment ,,lots of it,,, and glowing hands after the UV pigment ....
BTW if you add around 40% by volume graphite to the PM a calculated guess "says" it will conduct.... more about that in the not to distant future....... exciting times are developing.
For example, one of dot matrix scrolling "L" to left another one dot matrix just display 'G' only.