PDA

View Full Version : Out of memory ?



Mark Bramwell
09-09-2007, 04:50 AM
I am programming away successfully and suddenly a simple case statement causes odd things to happen. I comment out the case statement and it all works again. I add 1 line of code and it breaks again. What I do notice is a bit of corruption occurring in the upper left corner of the screen.

I am running with both the TV and GRAPHICS objects. I noticed that one of them has the bitmap_base=$2000, display_base = $5000
Any chance that memory range is being overwritten because the program+vars are now hitting the bottom of that range?

This is what the Object Info screen says:

RAM Usage:
Program: 1,753 longs
Var: 246 longs
Stack/free: 6,189 longs

If I add back the case statement, the program jumps to 1,782 longs.

Am I screwed at this point? Am I out of usable memory? I want to display graphics, should I be using something else that is less memory intensive?

deSilva
09-09-2007, 05:13 AM
First lets do the analysis:

The off-screen buffer starts at 8K taking 12k, then follows the on-screen buffer of the same length to End -Of- RAM.

8K for your code and variables mean 2048 longs, You use 1782 + 246 = 2028.
20 bytes = 5 words is by no means enough for the stack, so your own analysis is quite correct.

First idea: Do you really need the double buffering? It is necessary for smooth animation, but a single buffer can be acceptable for other applications. It is easy to change...

Second idea: What is your tile-setting? Do you really need 12 kB?

Third idea: Can you possibly live with 2 color mode?

Fourth idea: When you still use all the stuff to setup the video driver for multiple-object support, you can save a hindred bytes or so by using the DAT variables directly rather then copying them into your object space... This is not much, but you can carry on at least...

Post Edited (deSilva) : 9/8/2007 10:56:04 PM GMT

deSilva
09-09-2007, 06:03 AM
o.k. a "quick-n-dirty" solution is this:


y_tiles = 12-1
bitmap_base = $2000+2*1024
display_base = $5000+1024




Note that you have now reduced the screen height to 176 rather than 192. But everthing should sort itself out automatically...

Mark Bramwell
09-09-2007, 06:58 AM
I tried your quick and dirty solution. It looks completely messed up at that point.

I doubt that I need double buffering. If I can get the same resolution (or better) with single buffering, I can carefully code around it if I suddenly get lots of ram to use. I read that double buffering gets rid of flickering. How bad is the single? Is there a demo program that uses single buffering so I can view it? Very little of the screen changes from second to second. I know the hydra has multiple video drivers but it was not clear to me if they were TV drivers and if they were single/double.

My app is mostly text. I would use "text mode" if I could get large and small fonts. I added a Vu meter graphic because I could. I would lose it if the text mode had more flexibility in the fonts.

I am using the 2 objects that are on the site (TV + Graphics). Do you have a better suggestion? I am only about half through the applet and was surprised to hit a ceiling already.

The applet is meant to control an Icom PCR shortwave receiver using a Sony remote control and viewed on a TV screen. It will actually be connected to a slingbox and will allow me to use it anywhere. The Icom PCR has no buttons or controls. It is meant to be connected to a PC via the serial port and controlled that way. It is my hope that I can write something to send the control bytes using the propeller and remotely view/control it via the slingbox.

What I have working is a decent screen GUI with the IR_KIT decoding the Sony remote. I have not added any of the RS232 stuff yet. That is why I feel I am only half way there.

Regarding the tiles.... I do not completely understand them. The sample code generates 64 colors[] yet the screen only uses about 15 or less of them. If I set a colors[x] = xxxxxxx, it affects the entire line and I only have about 15 lines for text (15 might not be the exact number, it could be less). I have attached the spin file in case you are interested in what I was trying to do. It is my 1st spin program, I am sure there are better ways to do some things, I am still learning.

deSilva
09-09-2007, 07:43 AM
Mark Bramwell said...
I tried your quick and dirty solution. It looks completely messed up at that point.

It should work, in that if you SHOULD refer to line 12 it would wrap around... Maybe this is what happenen. I can analyse it with your code now....


O.k. - there it is


gr.start
gr.setup(16, 12, 128, 96, bitmap_base)



That was naughty of you!! Why do you use 16 and 12 rather than "x_tiles" and "y_tiles"???
If you change that, it should look much better!!

It makes things a little bit more complicated that you are just learning these things....
The double buffering is a feature of GRAPHICS and has nothing to do with the videodriver TV. GRAPHICS just uses the memory that is displayed by TV. GRAPHICS uses four "symbolic" colors, but has no understanding of what they mean. You can modify these to real colors with respect to the screen position where the occur by the tiole logic.... O.k. it is NOT simpel...

Coming to double buffering...
This however is the most simple part of all!

At the end of your main loop there is something like


gr.copy(display_base)


Delete this!
Now tell GRAPHICS to write directly into the display buffer


''''''' old gr.setup(......., bitmap_base) ' old
gr.setup(....., display_base)




Now bitmap base at $2000 is no longer used and you should have additional 12KB

deSilva
09-09-2007, 07:47 AM
BTW: The 4th parameter of gr.setup is "y_origin". when using the 11-lines solution you may want to change it from 96 (=12*16/2) to 88 (=11*16/2). But maybe not...

Ariba
09-09-2007, 08:22 AM
Just set bitmap_base to $5000 in your PCR_main, and remove gr.copy(display_base) in the start methode, then you have no double buffering anymore.

You get 12 kByte more RAM for Spin (3000 Longs), but you get also strong flickering with your momentary code.
Modify your code so, that you only redraw the display, if something changes. Perhaps you can also only redraw the portion of the screen, that has changed.

Andy

Edit: OK deSilva was faster!

Post Edited (Ariba) : 9/9/2007 1:27:39 AM GMT

Mark Bramwell
09-09-2007, 09:10 AM
I made all of the changes you suggested.

Holy Flicker! The screen is flicking all over the place. My program was clearing and redrawing everything between frames. The double-buffer made it look solid.

To stop the flickering, I added a few flags to redraw only those portions that have changed. Even then, I write the old values with the background-color (causes it to disappear without redrawing the entire box of info) and then I write the new value in the proper color.

Everything is now back to the same visual flicker-free video but I now have lots of ram again.

Thanks for the help!


One other question... Is the rom font constant pitch? I mean, does a space " " take the same number of pixels wide as a "z"?
I think it is a variable pitch font because if I write "---" and then write in another color " - ", I get overlapping color where it should be clean.

Ariba
09-09-2007, 09:52 AM
The ROM Font has a constant pitch, but the Graphics Driver don't use the ROM Font. Graphics.spin defines a scaleable font that uses lines and arcs to draw the characters in the DAT section. It's possible that this font has variable pitch.

Mark Bramwell
09-09-2007, 12:29 PM
I think I got the font problem resolved.

Now I am being hit with the signed 32-bit integer problem. I need to display upto 4-billion (with formatting) which is easy with an unsigned 32-bit int but not if it is signed.

oh well, I'll make my own lib that can handle large numbers with formatting. It slows me down a few days but I can get past it. I'll probably do it as an array of byte and perform the carrys on the addition/subtraction. That will allow me to have numbers of any size with simple add/sub capability.

deSilva
09-09-2007, 02:20 PM
@MarkB
Just an idea. Mightor is quite advanced with math in assembly language now http://forums.parallax.com/images/smilies/smile.gif Maybe you can order a package for "multi precision arithmetic" from him...

Ken Peterson
09-11-2007, 08:21 PM
I ran into RAM problems and the first thing I did was remove the double buffering. Of course my project involves a GUI with touch screen and stuff doesn't change that fast. Perhaps setting up a flag in the video driver to indicate vertical blank. Then you can wait until vertical blank to update your graphics. Just a thought..

Ken

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


The more I know, the more I know I don't know. Is this what they call Wisdom?

Ken Peterson
09-11-2007, 08:26 PM
BTW...on my application I ran into further RAM problems and ended up ditching the graphics entirely. Now I'm working with text only and simple buttons (provided in the ROM character set). Can't get nearly as much text on the screen, but at least I have more RAM to work with.

I would like to display some graphics, with small pre-defined bitmaps to mix with the text as icons. Maybe this is a little OT, but does anyone know of a good way to 64-word align an area of memory besides padding and pointer rounding? Seems redundant to define a bitmap and then have to copy it to another area before I use it.

Ken

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


The more I know, the more I know I don't know. Is this what they call Wisdom?

deSilva
09-12-2007, 03:17 AM
Ken Peterson said...
...but does anyone know of a good way to 64-word align an area of memory besides padding and


The reason for using 10 bit-addresses (=64 byte align, not 64 word align) is that this has the least redundancy. There is absolutely no reason why you should not use long-numbers (= 4 Byte align) That leaves you 2 bits for color mapping when you want to stay with the word tiles.

Everything is possible when you start to change the drivers!!

Ken Peterson
09-12-2007, 03:58 AM
Yes, what I meant to say is 64-byte or 16-long blocks. I didn't notice it until I posted, but I figured you'd catch it! http://forums.parallax.com/images/smilies/wink.gif

I agree, re-writing the driver would allow trading some of my color palette for finer resolution in memory, but I'm not about to re-write the driver only to save 15 longs of memory unless I really need 15 more longs! http://forums.parallax.com/images/smilies/wink.gif My time is short and I have bigger fish to fry.

I guess I was wondering if there was a simpler, more elegant way to align blocks of memory with greater granularity than a long. This might be useful for other things as well.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


The more I know, the more I know I don't know. Is this what they call Wisdom?

deSilva
09-12-2007, 04:26 AM
There had been many of such discussions, and even the Parallax Gurus admitted they use "copy to an aligned position".
There is simply no "ALIGN" directive, forcing a DAT section to start at - say - a multiple of 64. A DAT section always starts long aligned....

boeboy
09-12-2007, 06:27 AM
Somebody said...
I ran into RAM problems and the first thing I did was remove the double buffering. Of course my project involves a GUI with touch screen and stuff doesn't change that fast. Perhaps setting up a flag in the video driver to indicate vertical blank. Then you can wait until vertical blank to update your graphics. Just a thought..



how?


▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My computer, http://forums.parallax.com/showthread.php?p=630466

Ariba
09-12-2007, 07:46 AM
boeboy:

tv.spin has the tv_status variable that indicates in which state the driver is.
Draw only, if tv_status is 1 and wait if tv_status is 2.

Mark Bramwell
09-12-2007, 08:32 AM
I tried the following:

repeat until tv_status == 1
remove old graphic
draw new graphic


I still get the flicker on that particular object. Not a big deal. Perhaps spin is not fast enough to execute the draw commands before the sync is done.
This is how I remove the old text. I change the text to the background color, overwrite it with the same data which causes it to disappear and then write the new text.
I am not sure if this is the fastest way to remove text from a portion of the screen but it seems to work (with some flicker).

gr.textmode(2,3,6,5)
gr.colorwidth(1,1) ' background color
' remove old text
gr.text(0,55,num.ToStr(PCR_Freq[PCR_VFO],num#DSDEC14))

gr.colorwidth(2,1) ' new color
' draw current text
gr.text(0,55,num.ToStr(PCR_Freq[PCR_VFO],num#DSDEC14))
gr.finish

Ken Peterson
09-12-2007, 08:43 AM
Might be quicker if you just replace it with spaces. Or, if your area is well defined, just draw a rectangle over the area with the background color to clear it.

I don't know how much stuff you have on your screen, but you might also consider clearing and re-drawing the entire screen every update. How often are you updating the screen? Perhaps you can divide your update routine over several frames.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


The more I know, the more I know I don't know. Is this what they call Wisdom?

Ken Peterson
09-12-2007, 08:44 AM
Sorry...I see that you were re-drawing the entire screen before...nevermind that suggestion.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


The more I know, the more I know I don't know. Is this what they call Wisdom?

_Mark
09-12-2007, 09:03 AM
Mark Bramwell said...
Now I am being hit with the signed 32-bit integer problem. I need to display upto 4-billion (with formatting) which is easy with an unsigned 32-bit int but not if it is signed.

About the signed/unsigned thing, as long as you are just adding and subtracting, there is no difference between how signed and unsigned math works. For example, the propeller "sees" a long with all bits set to '1', as representing the number -1. That same long, when treated as unsigned, represents 4,294,967,295 (i.e. 2^32-1). Now if you subtract 1, the lowest bit becomes a 0. When treated as a signed value it is correctly "seen" as -2, and when treated as an unsigned value it is correctly "seen" as 4,294,967,294 (i.e. 2^32-2). This works for any value. So if you have 2 billion, and want to add 2 billion, it will work. The propeller will "see" the result as some negative value, but that same combination of bits when treated as an unsigned value, represents 4 billion.

So basically, you don't need any special library for 32-bit unsigned values, unless you need more than just add and subtract. The only change you'd need to make is in the code that converts a long to the human-readable string of digits that you show on screen, to correctly show the unsigned "interpretation" of those 32 bits. It might be a bit tricky to do this conversion on the propeller, but it should be possible.

If you need multiplication and division, or just like to know more about signed/unsigned values, you might check here: http://en.wikipedia.org/wiki/Two's_complement

Post Edited (_Mark) : 9/12/2007 2:11:04 AM GMT

Mark Bramwell
09-13-2007, 05:16 AM
I managed to get a rock solid display, even when I am holding down the remote-control button to quickly change frequencies on-screen.

I have a variable called PCR_Freq[PCR_VFO] that contains the newly calculated number to display (13 character string)
DisplayedFreq contains what is on the screen.

The following routine looks for differences and wipes that small portion of the screen and paints the new number (that single digit).

No more flicker!

I might have the unsigned part sorted out due to some help from a parallax guy (beta object)
It would be nice for some addition 'types' to be added to spin.




bytemove(@NewFreq,num.ToStr(PCR_Freq[PCR_VFO],num#DSDEC14),20)
NewFreq[10] := "." ' add a decimal point to our frequency (num.ToStr makes it a comma)
TempSTR := string(" ") ' initialize our temporary storage to a single character

gr.textmode(2,3,6,5)
gr.colorwidth(2,1) ' color, width

' only update the digits that have changed
repeat FreqCounter from 1 to 13
if DisplayedFreq[FreqCounter] <> NewFreq[FreqCounter]
bytemove(@TempSTR,@NewFreq[FreqCounter],1) ' move a single digit into our temp string
gr.colorwidth(1,1) ' color, width
gr.box(-82+(FreqCounter*12),40,10,30) ' wipe a single digit from a calculated screen position
gr.finish
gr.colorwidth(2,1) ' color, width
gr.text(-78+(FreqCounter*12),55, @TempSTR) ' write a digit to a calculated screen position
gr.finish

bytemove(@DisplayedFreq,num.ToStr(PCR_Freq[PCR_VFO],num#DSDEC14),20)