Tv and graphics
Jaco
Posts: 9
Hi,
after a long time finally I had the chance to play a little with the propeller chip. I've designed a circuit that takes some measurements from various sensors and I wanted to display the measurements in a tv using the propeller and a serial connection to my device. Currently I use a 320x240 graphic display attached to an ARM7 LPC2368 that does this job very well and instead of writing a library to produce an RGB signal I prefer to use the propeller. The problem though is that I ran out of memory in propeller before I even started. I've made some search in the forum regarding objects, graphics and memory to see if I'm doing something wrong and right now I've only come to the conclusion that the chip has too few memory to use it for video. To me it seems that the graphics_demo is not just a demo but it drives the chip to its limits.
Someone proposed in a thread to disable double buffering and actually this saves a lot of memory but the flickering is way too annoying, therefore double buffering is needed. I've also tried to cut-down the graphics.spin object but I didn't manage to save a lot of memory.
I also understand that assembly may be the solution but in my case it's not an option as my brain stack is near to overflow with a dozen programming and assembly languages I already use in my work and I'm not really willing to put myself in this learning procedure for once again if it's really not necessary for my job.
I just to ask you if there is something that I'm missing and if I can save memory to finish my project. This is my code until now:
This code right now doesn't compile but if for a test you change
to
then it compiles.
My purpose is to display several counters and info but I think that this will not be possible.
Display speed isn't critical while the sensors updates are every few seconds or minutes.
Thank you.
Edit:
There seems to be a bug in the forum's code section that doesn't ignore the symbols "[noparse][[/noparse]" and "]"
Post Edited (Jaco) : 12/22/2007 5:34:30 PM GMT
after a long time finally I had the chance to play a little with the propeller chip. I've designed a circuit that takes some measurements from various sensors and I wanted to display the measurements in a tv using the propeller and a serial connection to my device. Currently I use a 320x240 graphic display attached to an ARM7 LPC2368 that does this job very well and instead of writing a library to produce an RGB signal I prefer to use the propeller. The problem though is that I ran out of memory in propeller before I even started. I've made some search in the forum regarding objects, graphics and memory to see if I'm doing something wrong and right now I've only come to the conclusion that the chip has too few memory to use it for video. To me it seems that the graphics_demo is not just a demo but it drives the chip to its limits.
Someone proposed in a thread to disable double buffering and actually this saves a lot of memory but the flickering is way too annoying, therefore double buffering is needed. I've also tried to cut-down the graphics.spin object but I didn't manage to save a lot of memory.
I also understand that assembly may be the solution but in my case it's not an option as my brain stack is near to overflow with a dozen programming and assembly languages I already use in my work and I'm not really willing to put myself in this learning procedure for once again if it's really not necessary for my job.
I just to ask you if there is something that I'm missing and if I can save memory to finish my project. This is my code until now:
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = ($3000 + $3000 + 100) >> 2 'accomodate display memory and stack x_tiles = 16 y_tiles = 12 paramcount = 14 bitmap_base = $2000 display_base = $5000 lines = 5 thickness = 2 VAR long tv_status '0/1/2 = off/visible/invisible read-only long tv_enable '0/? = off/on write-only long tv_pins '%ppmmm = pins write-only long tv_mode '%ccinp = chroma,interlace,ntsc/pal,swap write-only long tv_screen 'pointer to screen (words) write-only long tv_colors 'pointer to colors (longs) write-only long tv_hc 'horizontal cells write-only long tv_vc 'vertical cells write-only long tv_hx 'horizontal cell expansion write-only long tv_vx 'vertical cell expansion write-only long tv_ho 'horizontal offset write-only long tv_vo 'vertical offset write-only long tv_broadcast 'broadcast frequency (Hz) write-only long tv_auralcog 'aural fm cog write-only word screen[noparse][[/noparse]x_tiles * y_tiles] long colors[noparse][[/noparse]64] byte x[noparse][[/noparse]lines] byte y[noparse][[/noparse]lines] byte xs[noparse][[/noparse]lines] byte ys[noparse][[/noparse]lines] OBJ tv : "tv" gr : "graphics" serial: "FullDuplexSerial" strInt: "Numbers" PUB start | i, dx, dy, myColorScheme 'start tv longmove(@tv_status, @tvparams, paramcount) tv_screen := @screen tv_colors := @colors tv.start(@tv_status) 'init colors repeat i from 0 to 63 colors[noparse][[/noparse] i ] := $98072802 myColorScheme := 0 << 10 ' or 1 or 2 or 63 'init tile screen repeat dx from 0 to tv_hc - 1 repeat dy from 0 to tv_vc - 1 screen[noparse][[/noparse] dy * tv_hc + dx] := display_base >> 6 + dy + dx * tv_vc + myColorScheme gr.start gr.setup(16, 12, 128, 96, bitmap_base) 'start serial 'serial.start(31, 30, 2, 115200) 'start Numbers strInt.Init gr.clear i := 0 repeat gr.clear if i == 100 i := 0 else i += 1 DrawBarGraph(100, i, -40, -80) 'DrawBarGraph(100, i, -80, -55) DrawConterLeft(string("S1"), 100, i, -85, 50, 40) DrawConterRight(string("S2"), 100, i, 85, 50, 40) DrawConterUP(string("S3"), 100, i, 0, 40, 60) DrawConterDown(string("S4"), 100, i, 0, 40, 60) gr.copy(display_base) PUB DrawConterUP(name, total, value, center_x, center_y, radius) | full, angle, free gr.textmode(1,1,6,5) 'Draw numbers gr.color(3) 'Draw arc gr.color(3) gr.arc(center_x, center_y, radius - 20 , radius - 20, $1FFF * 45 / 360, 1, $1FFF * 135 / 360 - $1FFF * 45 / 360, 3) gr.color(0) gr.arc(center_x, center_y, radius - 40, radius - 40, $1FFF * 45 / 360, 1, $1FFF * 135 / 360 - $1FFF * 45 / 360, 3) 'Draw line gr.color(2) full := ($1FFF * 135 / 360) - ($1FFF * 45 / 360) free := full * value / total angle := ($1FFF * 45 / 360) + full - free gr.arc(center_x, center_y, radius - 20, radius - 20, angle, 0, 1, 3) gr.textmode(1,1,6,2) gr.text(center_x +18, center_y + 25, strInt.ToStr(100*value/total, DEC)) gr.text(center_x - 40, center_y + 25, name) PUB DrawConterDown(name, total, value, center_x, center_y, radius) | full, angle, free gr.textmode(1,1,6,5) 'Draw numbers gr.color(3) 'Draw arc gr.color(3) gr.arc(center_x, center_y, radius - 20 , radius - 20, $1FFF * 225 / 360, 1, $1FFF * 315 / 360 - $1FFF * 225 / 360, 3) gr.color(0) gr.arc(center_x, center_y, radius - 40, radius - 40, $1FFF * 225 / 360, 1, $1FFF * 315 / 360 - $1FFF * 225 / 360, 3) 'Draw line gr.color(2) full := ($1FFF * 315 / 360) - ($1FFF * 225 / 360) free := full * value / total angle := ($1FFF * 225 / 360) + free gr.arc(center_x, center_y, radius - 20, radius - 20, angle, 0, 1, 3) gr.textmode(1,1,6,2) gr.text(center_x +18, center_y - 10, strInt.ToStr(100*value/total, DEC)) gr.text(center_x - 40, center_y - 10, name) PUB DrawConterLeft(name, total, value, center_x, center_y, radius) | full, angle, free gr.textmode(1,1,6,5) 'Draw numbers gr.color(3) angle := $1FFF * 180 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("0")) angle := $1FFF * 155 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("20")) angle := $1FFF * 130 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("40")) angle := $1FFF * 105 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("60")) angle := $1FFF * 80 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("80")) angle := $1FFF * 55 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("100")) 'Draw arc gr.arc(center_x, center_y, radius - 10, radius - 10, angle, 1, $1FFF * 180 / 360 - angle, 2) 'Draw line gr.color(2) full := ($1FFF * 180 / 360) - ($1FFF * 55 / 360) free := full * value / total angle := ($1FFF * 55 / 360) + full - free gr.arc(center_x, center_y, radius - 12, radius - 12, angle, 0, 1, 3) gr.textmode(1,1,6,2) gr.text(center_x , center_y, strInt.ToStr(100*value/total, DEC)) gr.text(center_x - 25, center_y - 5, name) PUB DrawConterRight(name, total, value, center_x, center_y, radius) | full, angle, free gr.textmode(1,1,6,5) 'Draw numbers gr.color(3) angle := 0 gr.textarc(center_x, center_y, radius, radius, angle, string("0")) angle := $1FFF * 25 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("20")) angle := $1FFF * 50 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("40")) angle := $1FFF * 75 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("60")) angle := $1FFF * 100 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("80")) angle := $1FFF * 125 / 360 gr.textarc(center_x, center_y, radius, radius, angle, string("100")) 'Draw arc gr.arc(center_x, center_y, radius - 10, radius - 10, 0, 1, angle, 2) 'Draw line gr.color(2) full := $1FFF * 125 / 360 free := full * value / total angle := free gr.arc(center_x, center_y, radius - 12, radius - 12, angle, 0, 1, 3) gr.textmode(1,1,6,2) gr.text(center_x , center_y, strInt.ToStr(100*value/total, DEC)) gr.text(center_x - 25, center_y - 5, name) PUB DrawPie(name, total, free, center_x, center_y, radius) | full full := $1FFF free := full*free/total gr.textmode(1,1,6,5) gr.color(2) gr.text(center_x, center_y +28, name) gr.color(7) gr.arc(center_x, center_y, radius, radius, 0, 1, free, 3) gr.color(2) gr.arc(center_x, center_y, radius, radius, free, 1, full - free, 3) gr.text(center_x - 30, center_y - 30, strInt.ToStr(free, DEC )) PUB DrawBarGraph(total, value, position_x, position_y) | width, high, value1 width := 80 high := 20 gr.color(2) value1 := width * value / total gr.text(position_x + width, position_y + 18, strInt.ToStr(value1 * 100 / width, DEC)) gr.text(position_x + width + 20, position_y + 18, string("%")) if value < 5 value := 5 value := width * value / total gr.quad(position_x, position_y, position_x, position_y + high, position_x + width, position_y + high, position_x + width, position_y) gr.color(3) gr.quad(position_x + 1, position_y + 1, position_x + 1, position_y + high - 1, position_x + value - 1, position_y + high - 1, position_x + value - 1, position_y + 1) DAT tvparams long 0 'status long 1 'enable long %001_0101 'pins long %0000 'mode long 0 'screen long 0 'colors long x_tiles 'hc long y_tiles 'vc long 10 'hx long 1 'vx long 0 'ho long 0 'vo long 0 'broadcast long 0 'auralcog CON DEC = %000_000_000_0_0_000000_01010
This code right now doesn't compile but if for a test you change
long colors[noparse][[/noparse]64]
to
long colors[noparse][[/noparse] 4 ]
then it compiles.
My purpose is to display several counters and info but I think that this will not be possible.
Display speed isn't critical while the sensors updates are every few seconds or minutes.
Thank you.
Edit:
There seems to be a bug in the forum's code section that doesn't ignore the symbols "[noparse][[/noparse]" and "]"
Post Edited (Jaco) : 12/22/2007 5:34:30 PM GMT
Comments
I see that you understand the situation perfectly.
The propeller needs CREATIVE solutions for nearly every new graphics application.
12kB video buffer and 12kB swap buffer leaves too little head room.
There are generally 5 ways forward:
(1) Optimize code - this generally adds up to peanuts
(2) Reclaim the HUB area where GRAPHICS and TV have been allocated - this is somewhat tricky but more awarding (yields 3 kB)
(3) Use two-color mode - this will half the memory requirements (giving you back 12 KB!), but needs detailed changes in GRAPHICS
(4) Try a tile-scheme - using blocks of 16x16 self defined "characters" can give you a lot of possibilities (though this will need double buffering as well)
(5) Try a small graphics window within a character (=tile) screen
When the screen can be updated very fast there is the chance to do it all during the non-drawing timeslot (around 4ms).
This will need changes in GRAPHICS as well. Note that GRAPHICS is highly optimized and there is no space left for evan a single instruction.
In fact GRAPHICS is a truly astonishing piece of code...
I can type this list so easily as it had been my design for an advanced course for my microcontroller students,
but I realized only a part of it upto now. I shall look for my (5) approach, but don't push me, please
However there are some experimental solutions for all of this distributed through this forum... I am sure the programmers will call here shortly
Post Edited (deSilva) : 12/22/2007 2:35:24 PM GMT
comment out all of the lowercase characters in the graphics code
from
down to
never use these characters in your application
Perry
deSilva summed up you possiblilities.
Personally, I would not use Graphics at all. Instead, I would use the basic VGA or TV tile drivers and use the internal font and perhaps custom characters to display the information. Unless, you really need a pixel level graph... In that case maybe use Graphics, but not for the whole screen, but from small areas (as deSilva mentioned).
To be honest I didn't expect a solution but as they say hope dies last.
@deSilva
As you say: "In fact GRAPHICS is a truly astonishing piece of code...", therefore there aren't many things to change or optimize there except cut-off features like colors, functions not needed, character memory map. I did the last two because it was no-time for first reading the code. I don't know if I'm willing to do in-depth optimizations because it seems that propeller isn't the propriate for this current task. Although I understand that propeller is not targeting graphics where video ram must be in tons, I can't find the reason why the ram is so limited.
@perry
All characters and symbols except capitals and number was the first victim. Although I've gained some ram, if you think that before even start programming the ram was again almost full then there weren't much room to go.
@Rayman
You're right about not using the graphics.spin in the sense that it will free the ram but on the other hand I lose the power of what a descriptive language can offer because everything then would be static (graphics with predefined fonts) and I cannot create graphics with maths and code. Only with the idea I feel very limited like in cell.
Seems that I'll stick to ARM7 for that, I was just hoping to do something with this chip as I've bought the dev kit almost a year ago and never had the time to play with or to include it to any product. I don't want to put it again in the pile of dev kits so I'll have to find something else to do with it during Christmass.
Seeing some things now clearly I would like to ask a question that I hope it would not sound heretic as it isn't. Is there any massive production device in the market that uses the propeller chip? Do you have any links?
Thank you.
Post Edited (Jaco) : 12/22/2007 5:28:41 PM GMT
and you would have to dig really deep. I recognized this problem and the need for an easy to use family of video drivers
a long time ago, but this was not the only issue
I would be interested in such information as well!
I like to describe the Propeller as a "generalist", able to perform anything, but for each task you will find a "specialist" that can do it faster and for less money.
And it is great for prototyping and feasibilty studies!
Within its limitations...
http://www.rayslogic.com/propeller/Programming/RaysStuff/RaysStuff.htm
I have info and tools to create your own graphics and tiles here:
http://www.rayslogic.com/propeller/Programming/Programming.htm
Sometimes this doesn't always mean lack of knowledge it's just time efficient, for example I'm always thinking that although I hate .NET Framework and I find it the worst piece of code the MS did since 1998 I'm really lucky I don't have to program web services with the alternative ways...
Anyway, thank you for your response.
Thank you for your response.
Thanks Rayman, I'll take a look also in the Hydra section.
Consider changing the draw scheme to something that leaves most of the screen intact, for most of the time. This boils down to just spreading out the draw operations over time, and eliminating the full screen clear.
You've likely got some static elements on the screen, so draw those, then leave them there, meaning you just don't ever clear the entire screen, or maybe clear it all once in a while, just in case. Use longfill to clear specific areas of the screen, where variable elements are present. Alternate the drawing of variable elements such that only one of them, say the pie or line graph, is being drawn at a time. This will leave most of the screen static most of the time, thus sharply diminishing the perception of flicker. Align your screen elements to the tile addressing so that a few longfill instructions will clear the area of the screen required for the graph, without having to supply too many address blocks.
Your single buffered loop then looks something like this:
{clear graphics screen}
{draw all static elements]
repeat
{clear area of screen related to variable element 1}
{draw variable element 1}
{pause}
{clear area of screen related to variable element 2}
{draw variable element 2}
{pause}
{or, maybe draw them all, then pause some reasonable amount of time, say, 1/3 sec to 1/2 sec}
The idea being to never clear the entire screen, and limit the drawing to those areas where and when it needs to occur. It takes some time for the data to accumulate right? Use the pause to allow that to happen, or just limit the number of changes per second to a lower level. IMHO, this graphics could be significantly improved, without having to deal with assembly, or double buffering. The only real cost is a lower number of total screen updates per second. If each variable element were displayed every few frames, you could get 2 - 3 complete screen updates per second, with flicker that's below the level of annoyance.
An alternative would be to draw the graphics more slowly.
So, incorporate a delay into the procedures that draw the graphics. Eliminate the delays in the main loop, but keep the localized clear operation. At any time, one graph is building, leaving the others static on the screen for some length of time. Arrange the delays so that an entire screen is drawn every 1/2 to 1/3 second or so. In that scenario, you are really just drawing changes and the single buffered display will have little overall impact on the perception of flicker.
Set the display up for 4 colors, single buffered display, if you've the RAM to do that.
Edit: Just saw that display speed is not critical. This will work nicely, and you can spread your variable drawing operations over a second or so. I would draw one graph, pause, draw the next graph, and the next, with each one in a one second cycle, resulting in a screen that fully updates every 3 -5 seconds. Do your localized clear operation, for a given variable screen element, then draw that element right after that, then pause to consume some time and let the viewer see that display for a time, before drawing the next graph.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Post Edited (potatohead) : 12/22/2007 6:40:05 PM GMT
you're right about not changing the whole image and change parts of it instead. This is also a very well used image compression method but in my case it will be a "RAM compression" method. Of course the complexity is much higher and I have to write a very efficient piece of code that will act as a mechanism that detects only the changes in the current buffer (whatever that is) and apply them on the buffer without further procession. This ain't easy at all but it's sure the most effective and actually the most programatically correct method but it's really time consuming and I think it will be again a problem if various pixels change simultaneously (not in my case though). Therefore, the problem seems to be my free time and not the prop at least for now that I can't view the result of it to decide if this method will be acceptable for a viewer.
Maybe this method could be included in a future graphics object.
Thank you for your response.
No compression is needed.
It's also not a whole lot of time. Try this before bailing on this whole thing:
Simply insert a delay into your main repeat loop, maybe 2 seconds. Set your display back to single buffer, leave everything else as is. Place it right after the last graphic element is drawn. You will see your graphics build, then remain static for most of the time. Little flicker, high display utility. That one change would mean the code you have right now crosses the border from annoying to useful. If that's enough, you are done!
What I meant by localized screen clear operations was far more coarse than I think you understood. For each graphic, there is an area of the screen it occupies. To make things really easy, just draw a black filled rectangle over that area to clear it, prior to it drawing.
To employ fully, what I was trying to convey, one only needs two new code elements:
one being a few clear operations that only clear where a graph is drawn. Could be just the filled rectangle command, one line then, per graph.
the other being a delay in the main repeat loop so that things are not being drawn so rapidly. (that's the core problem, and it's just not needed, given your slow rate of change on the sensors)
Move the full screen clear out of the main repeat loop, and it's all done.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
I'll try tommorow the method you propose which is to black only small areas and redraw only on that areas, that's far easier. Of course I expect flickering but I'll try to find a "window frame" that in given processor speed is redrawn faster than 15-20fps.
Again, thank you.
however not when you have a complex graphic, containing overlapping elements.
However I think the idea to update a (rectangular) part of the screen is fine as long as it is self contained.
Combining it with clearing and drawing within the 4 ms retrace gap - "peu-a-peu" - will be worth persuing further.
We shall need a "patchwork" driver for it this is the fourth kind of drivers:
- tile drivers
- bitmap drivers
- sprite drivers
- and now: a "patchwork driver"
Post Edited (deSilva) : 12/22/2007 8:16:20 PM GMT
Your data rate is on the order of seconds, therefore you only need unique graphics screens on the order of seconds.
If you spread your graphics draws over some time, there will be moments of flicker, when an area is cleared and the new graphic is drawn, but they will be seen as program activity, not overall graphics flicker.
Flicker will be seen and annoying at 15-20fps. Screen contrast is too high for that number to yield the perception of a steady display. Leave it static for as high percentage of time as is possible. What will happen is the eye will be drawn to the new graph, right after it is made current. This is actually useful!
Best!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
This is quite independent of the size of the area.
That is not the case on this problem though. So, we've an easy solution. Keep the display static as much of the time as is possible and spread graph redraws over some time. I would personally just draw one new one every second, alternating between all of them, such that a new, complete display happens every few seconds. That's only a few new clear commands, and a light sprinkling of delays throughout the main graphics loop --and the omission of the full screen clear, but for every hundred cycles or so. At any given time, the user has a very high percentage chance of seeing a static display. Should the user see one redraw, it's actually then a feature, indicating new data is present!
The idea here being the flicker is managed and kept below the threshold where it's annoying. Think of how many older medical display systems worked. They employ various delay draw systems to manage flicker such that it's actually useful. For the code above, a clear, followed by a draw of the graph will be seen as activity, not annoying display quality.
On your point of overlapping elements, really a display list is needed. If they are drawn in a specific order, then clear / XOR operations can be managed, keeping overall display change within the VBLANK period. Another option is to draw into a sub-buffer, smaller than the overall single buffered screen. Of course, the elements will need clipping, but I think the existing graphics library does that. If that's the case, then the list of display elements can be processed into the smaller buffer, clipped, then copied to the main screen in less time than a VBLANK would take. The result is more computationally heavy than other means, but one does get most of the benefit of the double buffer without actually having to have a complete double buffer. On the propeller, we usually have compute time. What we don't always have is memory.
If those redraw, clip, copy operations were done checkerboard fashion, one per frame, the end result would be pretty decent, IMHO. Given the number of elements to be handled is not too high, screen updates, on the order of 10fps would be totally viewable and solid looking.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Post Edited (potatohead) : 12/22/2007 8:28:17 PM GMT
It will take another COG, but will improve the useability.
I think this is exactly what I was looking for, for some time now... We had great difficulties in the classes starting with TV and GRAPHICS, as both are NOT user friendly.
We see the same requests here in the forum....
----
Edit: No, it still needs reconsideration. There are too many "show stoppers"...
(a) You cannot have any decent animation
(b) you cannot build complex structures, e.g. a shooting target. The flat-fill is the slowest part of GRAPHICS..
I still prefer the "patch-work" solution, something like static sprites... GRAPHICS can easily be modified to work on many canvases...
Post Edited (deSilva) : 12/22/2007 8:55:12 PM GMT
(hope this is ok, on this thread)
The perception of animation begins somewhere at 8fps, looks smooth at 12-15 or so. Decent animation then is not outside the realm of possibilities for many of these options.
If one decouples the graphics draw, from a game engine, then lower frame rates do permit things like moving targets. Also, one can use XOR to draw small elements that lie beneath the VBLANK time to generate, thus eliminating the need for a buffer at all. The moving target, and other things could happen in this fashion. If too much draw time is needed, skip frames, cull objects, etc...
The down side for this kind of thing is that one needs to build an engine for their particular display. That's been going on for the games we are seeing so far. Lots of great examples there. Takes time, if one is not well versed and practicing that art regularly.
If it were me, I would significantly restructure the graphics demo program for teaching.
It's default mode is to generate the entire screen, then bulk copy it from one HUB memory region to another. In the double buffered configuration, this works, but is not optimal at all. One change, that would free significant compute time, would be to toggle the draw pointer and display pointer once drawing is complete. It would be ideal to time that toggle to the VBLANK as well, to eliminate tearing. There is no need for the bulk memory move. Higher overall frame rates are possible, as well as displays locked to the screen refresh are possible as well. Edit: Well, only if a quick screen clear is quicker than the copy.
In the single buffer mode, putting the screen to be displayed in a single bulk repeat is highly likely to result in significant flicker for a majority of displays.
For the single buffer then, a number of options become viable:
-sub-buffer drawing (draw to this buffer, when complete, copy into screen memory, ideally during VBLANK)
-slow drawing (basically, let the screen get built over some time, turning flicker into activity instead)
-tiles (one can build up static display elements, then point the screen addresses to those areas of memory that contain the image to be displayed this one can do nice animation, BTW. The Parallax screen memory layout is very flexible, but somewhat complex. A procedure to simplify this might help students. If the same image is to appear multiple places, this can be a big savings, particularly when combined with sub-buffer drawing.)
-XOR (draw, then re-draw, then draw again, during VBLANK times good for smaller moving things that have no overlaps if there are overlaps, then masking must happen too)
-compression / pixel difference engines. (takes a lot of compute & highly likely to not deliver more than the other methods applied well.)
IMHO, small examples of each would then convey the options to the students, where they then build their own display engine to solve whatever problem they have at hand.
@deSilva Thought of another option. If graphics.spin were keyed to the vertical blank, as in only draw while VBLANK = 1, then anything written with it would then have it's drawing keyed to the display. Changes would only occur during non-display times, and I'm assuming a clear can get done in one VBLANK time. The higher level program then just sees slower graphics draws in general and has to do nothing else.
Given that, a whole lot of graphics cases would draw largely flicker free. Some of them might appear over the course of a few frames, but that's not gonna be as detracting as the flat out flicker is, when just drawing all of it, clearing, not synced is.
With that modification, people can plan some of their graphics, without having to deal with so many of the lower level issues.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
Post Edited (potatohead) : 12/22/2007 11:04:22 PM GMT
Your idea of using VBLANK can easily be checked without any change in GRAPHICS!
Just WAIT until VBLANK starts before calling CLEAR
Filling 3k longs will take 600 µs only
Post Edited (Jaco) : 12/23/2007 7:18:34 AM GMT
But -also in principle - there are many possibilities for "clever short cuts". The Video Drivers need not rely on a fixed video bitmap, but can to things "on the fly" (which is the sprite concept). Display lists COULD work similar, but we are far away from the needed processor speed...
It already becomes awkward with sprites when you are not on byte boundary. TV timing gives you some headroom, but VGA will not..
I hope I see in the future an improved graphic object.
Thank you all for your replies and keep up the good work!