Multiple Instances .. sharing image

BlitzPlus Forums/BlitzPlus Programming/Multiple Instances .. sharing image

klasix(Posted 2004) [#1]
Hello all.

Newbie to the Blitz side of the house. Need some guidance:

I am trying to incorporate a 'main' program that uses mutex's to comm between multiple unique-function Blitz instances. That part I think (quote me) I have a handle on. What I don't have a clue about is have the 'main' load the background image (1024x768) and have the unique instances use viewports 'onto' that image. I've pretty well mangled my machine (the vid anyway) many times trying.

Any help in defining a method to do so would be appreciated.

FWIW I'm reading 6 USB devices, each instance doing their own thing (measuring and calcs) and have the main determine when they can draw. Experimenting on 'best method' for my app.

Thanx in advance,
Jim


soja(Posted 2004) [#2]
What I don't have a clue about is have the 'main' load the background image (1024x768) and have the unique instances use viewports 'onto' that image.


Does this mean you want each blitz "process" to be able to draw on parts of the main image (on the "main" or "server" process), or you want parts of the image to be copied, becoming the main canvas on each "sub" process?

Would this be a full-screen application?

One of the things that comes to mind is why you must have each subprocess draw -- why can't you send a message to the main process and have it draw on its own canvas.


klasix(Posted 2004) [#3]
Hello soja,

Correct on the first part of #1.
Correct on #2.

As for the 3rd .. that is the option I was considering .. easiest.

The intent is to offload the main from doing any graphics processing at all. It will act as the 'scheduler' in a fast >> real-time << embedded system. A lot of considerations and am investigating every method. If this can be made to work it opens up a number of possibilities .. all good :)

Thanks,
Jim


soja(Posted 2004) [#4]
I assume this is occurring on a distributed, or, at the very least, multiprocessor system. Otherwise, it wouldn't make much sense because the same CPU/GPU would be doing the work, no matter the process. Or is this just a prototype? How does the embedded system work, anyway (unless it's too detailed...)?

Anyway, you could "capture" a portion of the main process' display, but you would have to use GDI and associated WinAPI calls. By doing so, you would probably lose the benefits of being able to use Blitz' graphics commands and event system. Is this acceptable?


klasix(Posted 2004) [#5]
Hello again soja :)

Understand the distribution of work/CPU time .. was avoiding the 'other' details :) Intent was to control the other processes by having them 'suspend' themselves (or do less .. or if need be, actually 'suspend' them) once signaled to do so to give the main more breathing room. How to do that was another issue after I sorted out the vid. Yes this is a proto for a public domain effort. Reading/writing 6 USB ports .. each USB port connected to a microcontroller (uC). Each uC will be doing the apps critical timing (PWM) [acting on data FROM the PC] and ADC [data TO the PC]. The # of events per 'time period' can change considerably in a very short period of time but I do have some room per USB channel as to when I send/rcv data.

Not a game BTW .. it isn't 6 joysticks :) I'll spring what it is once I figure out if it can be done.

The 'main' will get the ADC data from the 6 instances (all ADC measurements reading different things and each ADC/USB instance with its own math/etc) and then decide what the instances should 'tell' the uC's. Hope that made sense. Not a whole lot of 'data' being passed BTW.

What I was hoping for was each instance would be responsible for a video region (viewport(s) if you will) .. various gauges mainly. Was hoping I could 'poke' into the main pages VRAM easily. Once the the overhead involved was sorted out I could then determine the viability of the method. Question is .. can it be done and if so how?

Could have each instance write images(s) to a RAMDisk and have the main read/write them .. looking at various methods. Not close minded .. investigating. Usually tinker with RTC on micro's where I control what is going on .. Windows is a bit of change (not fresh air either ;)

GDI is an option and have mildly touched on it ..seeing what Blitz can do .. and waiting to eval iBasic Pro. I do not understand Blitz's event system enough (I think because it appears to be user-event driven [mouse/etc] whereas user events are a minor fraction of a minor fraction of what I am trying to do) to take full advantage of it. Been fighting what appears to be memory leak .. rewrote the code so it doesn't happen but no clue why it happened in the 1st place.

Comments appreciated and no intent of being arguementative. If it can't be done in Blitz .. it can't.

Thank you again,


Andy_A(Posted 2004) [#6]
You may want to make an estimate of the CPU load using Blitz, and see if Blitz can perform the polling and update the graphics from just one instance. Blitz has very quick graphic routines and number crunching capabilities. You may be able do everything from one Blitz window. I don't think that you will get better response from multiple instances for each port since you are still in the Windows environment, the OS will still need to manage the time slices necessary for your program(s) to read from the ports and update the graphics. You can set up a scheme programatically that would do the same, only you will have a lot more control of how the time is sliced.

For the CPU load estimate, you need to know how often the USB ports are polled each second and how often the graphics need to be updated. You could make a window divided into six regions/areas then use a "frames per second" loop to see how fast the graphics that you are using take to display.

As far as the USB ports, each port has a maximum thoughput of ~1 Mbit per sec for USB_1 or ~12 Mbit per sec for USB2, so even with USB2 using maximum throughput, times 6 ports is 72 Mbit per sec. On a 733Mhz system, you could use up to 10 machine cycles per bit polled. On a 3.2Ghz system you could use up to 43 machine cycles per bit polled. That's the worst case scenario for 6 USB ports. If as you mentioned that there will be less data, then you will have proportionately more time.

Using the above benchmarks should give you a crude estimate as to how your app will respond in a real time environment when using Blitz or any other programming language that you are evaluating.


soja(Posted 2004) [#7]
What I was hoping for was each instance would be responsible for a video region (viewport(s) if you will) .. various gauges mainly. Was hoping I could 'poke' into the main pages VRAM easily.

As far as this goes, the easiest thing to do would be to use the main thread to change your resolution (you mentioned it's a full screen app), and then do something like this (with varying coords) for each blitz instance:
w=CreateWindow("", 0, 0, ClientWidth(Desktop())/3, ClientHeight(Desktop())/3, 0, 0)
c=CreateCanvas(0, 0, ClientWidth(w), ClientHeight(w), w)


Then you could draw what was needed on each viewport.

As far as poking into VRAM, I'm not sure how you'd do that. You'd almost certainly need another library (like GDI or something) unless you wanted a Memory Access Violation.


klasix(Posted 2004) [#8]
Thank you again,

I understand what you are saying .. fairly clearly and appreciated very, very much. I am not fixated :)

I'm going to get my tail-end kicked around for saying this .. think about it as modular programming :) I understand it might even take a little longer (Windows overhead). Fully aware I am outgunned/outsmarted and generally 'outed' in many aspects ;)

And going waaaaaaaaaaaaaaaaaaaay off topic.

Created 14 instances of the same video intensive program to load the CPU (Via 1.2 .. actually rates at ~800MHz). Win98SE running from 256MB Flash/512MB SRAM. Developing on a 1GB MicroDrive then to FLASH (faster also). Bogged CPU down a tad but OK (max 30%, zip mem). The 30% were 'peaks' occuring at regular intervals (~6 seconds), down to near 0 and then back up .. Windows/Blitz (points to Blitz) is up to something .. dunno (garbage collection, reallocating resources?). And the larger I made the windows, the higher the CPU utilzation. Geez :) Have not been tinkering with "Windows" programming for long and Blitz for less so hazarding guess's based on observation.

Might as well open the can of worms and explain the project somewhat:

One 16MHz uC on the far end of each USB.
One http://www.ftdichip.com/Documents/ds245b14.pdf per uC. max 8Mbit per second, 384 Byte FIFO Tx buffer/128 Byte FIFO Rx buffer .. won't even come close to filling them. ~16 bytes max either buffer .. on a bad day. Each 'processor' on either side of the USB chip will work at max speed. The uC will do the precalcs on any values from the uC's ADC's. The uC will rcv precalc'd PWM information from the PC.

Won't be 'polling' in the usual sense .. using the "Send Immediate" Pin will let the PC know there is something to Rcv, as soon as that is done it will Xmit and then 'instance(s)' will go about its business. I, well .. "it", is reacting to inbound data stream (near nil user input). The sequential nature of the USB R/W's and the minimal (time relative) calcs on the rcv'd data helps out. What doesn't is the devices(s) on the other side of the uC's will vary in frequency .. considerably.

The point I don't "get" with the 'all in one' (main) solution is any delays/etc effect the whole program. I do not know how B+ handles concurrent events ... particularly delays of any sort. The little experiment mentioned above (and a few others) has me pounding on the keyboard with one hand and scratching my head with the other as I can't sort out what kind of 'concurrancy' (if any?) Blitz is doing.

Anyone have a working model of a non-jittery, fast acting tachometer? I've tried, come close (red needles are embedded on my brain and have had some real interesting unintended "special effects" :), but off the mark. A swinging needle seems to be a curse of mine .. see them in games.

I'll give the suggestions a shot. May not be able to do until this weekend. In the meantime I am switching to LIME GREEN needles :)

Take care and thanks again,
Jim


soja(Posted 2004) [#9]
Well, at this point, Blitz does not support multithreading, nor is a compiled project multithreaded, so there's no concurrency there. Of course, you can have multiple Blitz programs running, but they each have their own address spaces, register sets, (and message queues), etc.

As far as the events go, they're pretty much serialized as far as I can tell, and go into a single queue. Blitz has an internal message pump which "filters" or "translates" certain messages and sends them as a return value to WaitEvent. You're right that most of the events are user-based, though with some "hackery", one can probably figure out a way to receive/act on other WIndows events.

I'm not sure what you mean by "delays".


klasix(Posted 2004) [#10]
Hello soja,

'Delays' are anything causing the program flow to stop and 'wait'. Like "Delay x". Have video flicker bad enough I have to delay between frames. I'd agree 'events' are serialized. Not sure about the timers .. yet .. but so far they seem to be also. If it is serial then any delays would be cumulative; so I'd have to write everything to the back buffer and figure out the delay for the entire screen.

If anyone is listening a multi-threaded BASIC would be nice. Too old to say "that would be AWESOME!" .. so I'll type it ;)

I can use "mailboxes" and the like on a RAM based disk file (or a mutex .. or ..) to pass data between processes. This is going to get interesting .. well .. more interesting :)

Did an experiment with the tach. If I incorporated the tach needle as part of the tach image and drew the entire tach face .. much better (mostly black on black bacground). Guessing the masking operations are causing me some grief.

Take care,
Strange you mentioned the 'hackery'. I was thinking I could fake a user event(s) ..

I read somewhere in the forum where someone said something like "Geez .. Blitz is for games". Are they in for a surprise :) [If I can get it to work].


Andy_A(Posted 2004) [#11]
Pure Basic supports independent program threads, but is beyond my level of programming to be of any use to you. Suggest you look at their forum for better information.

http://purebasic.myforums.net/


You mentioned that you receive ~16 bytes of data per event. What kind of calculations do you do on the incoming data? Whatever you do with the incoming stream, just put that portion of the program in a 1,000,000 iteration loop and calculate the average time that Blitz spends to process the incoming data stream. Then you'll at least know how many processes Blitz can handle per second. After attaining the processing time, you will need to ascertain the time Blitz takes to process each graphic area in a similar fashion. This is the only way that I know of getting real time results, afterall if you are using Windows, then you cannot acheive true real time processing, only *near* real time processing (unless you can program your own vxd's).

Looking at it from another perspective however, you should have in excess of 100 million machine cycles per second for each process, or 100,000 machine cycles per millisecond per process. With 100,000 machine cycles per millisecond, you may with to consider polling the ports instead of generating an interrupt. This should allow you quite a bit of flexibility in what you can accomplish towards real time programming. Even with an engine that screams at 12,000 RPM the engine only turns 7.2 degrees in one millisecond.


klasix(Posted 2004) [#12]
Hello Andy,

:) Thought mentioning the tach was a decent hint. The tach designed only goes to 11,000 .. thought 12 was a tad excessive ;) It is an 'open' system .. want 20,000 RPM? .. roll your own ;) I won't go past 7K .. ever (and why 7K is 'almost' straight up on the tach :)

Most of the data could be via lookups or calc'd. Simple math. Did some complex math as a test and .. no problem .. even on the $34 S635MP Via board I'm using. Not that many 'calcs' and next to no iterations. Fact is the mechanical aspects can't touch the accuracy of the calculations.

http://members.shaw.ca/megasquirt/manual/ve_tuner.pdf

Each uC has 8 10-bit ADC's. They could be attached to most anything (TPS/BARO/Boost/Vac/etc). The also need to control IAC's and the like. I may implement higher res 'sweep' ADC's and use a less feature-rich version of the uC (Atmel ATMega's). That aspect of the design will be dealt with when I get the PC side finished and will be cake as I've done most all that needs to be done.

BTW: The uC's have .01ms resolution for the injector and coil drivers (3 injectors and 2 coils max per cyl, up to 12 cyls, any firing order/configuration, rotary included .. lawnmower if so inclined ;) and they track and act based on info from the PC. Pretty much feed and leave. As the PC does not have to track that I am relieved of managing that duty in Windows. The killer app would be ION sensing ... assuming someone ever comes up with circuitry.

Have LB .. looked at Pure and Power Basic; waiting for the official release of iBasic Pro to see what they come up with. I'll push Blitz as far as I can and roll over if I have to. Neat trick if I can pull it off ... using a 'game' language :) I may not need threading as much as I thought .. time will tell. Whatever I find I will post.

The intent of the project is to prototype a design that the 'public' can use as a foundation .. to show it can be done simply, cheaply (relative to a pro system and no need to purchase all the gauges/etc) and NO dependancies on the author(s). Just providing the map. Did I mention it will do blinkers also ? :) It is intended to be the core of a vehicle management system .. a 1st step.

The uC's I tinker with are usually programmed with a Basic dialect .. had to delve into ASM to get the .01ms though [It was a self invoked challenge] :) No kazillion $ dev environments, etc. An inexpensive PC/dev environ and uC of choice .. knock thyself out :) Linux and C? Go for it .. have fun with the graphics.

Windows and realtime :) If in doubt, crank up the CPU speed. Using the SNAP protocol http://www.hth.com/snap/

Polling/etc will be derived with testing. I can send fake data up the USB pipe and watch what happens.

Keep in mind, I'm new to Windows programming (and Blitz) and I'm going to ask at least a few (maybe more) stupid questions :)

Have an in-the-works dash layout if someone wants to take a look and comment/recommend suggestions. It will be high-end game level when done. Think I have the tach beat .. everything else will be easy street.

Thanks and take care,


Andy_A(Posted 2004) [#13]
Hello Jim,

As far as I can tell from what you've mentioned, the uC's are sending interrupts asynchronously to the CPU (S635MP Via MoBo), and the graphics are not able to keep up with the incoming data.

It seems to me that if you were to buffer the incoming data in memory and average the incoming data for each uC every 16 milliseconds via a polling routine, you would have a flicker free 60Hz display. As it stands now you could have each of the uC's generating an interrupt every .01 milliseconds (or perhaps even every uSec). There isn't an off the shelf monitor/video card combo in the world that can keep up with that type of blistering pace (though if you used oscilliscopes for each channel you might - verrry expensive). So back to averaging out the incoming data at 16 millisecs intervals, you could use Blitz banks, which are chunks of managed memory that you can use any way you like, and is very fast, as the buffer for the incoming data stream.

Better still, if you can use a rolling average for the each of the incoming data streams, you should get a display that is exactly what you have described with a silky smooth flicker free 60Hz and still be very accurate. Even at only 60Hz display updates, the gauges will *appear* to be functioning in real time to the average person.



;===========  Pseudo-code =============

;Main processing loop
While Not( KeyHit(1) )

	;is it time to update display?
	If cycleTime < MilliSecs() Then
		
		;set up for next 16 millisec poll
		cycleTime = MilliSecs() + 16
		
		;update all graphics displays here
		;using averaged data
		;
		;
		;
		Flip ;make graphics update visible
	End If
	
	;Read incoming stream from process1
		;generate rolling average for data stream 1 here
	
	;Read incoming stream from process2
		;generate rolling average for data stream 2 here

	;Read incoming stream from process3
		;generate rolling average for data stream 3 here

	;Read incoming stream from process4
		;generate rolling average for data stream 4 here

	;Read incoming stream from process5
		;generate rolling average for data stream 5 here

	;Read incoming stream from process6
		;generate rolling average for data stream 6 here

Wend

End	

;========== End Pseudo-code ===========



klasix(Posted 2004) [#14]
Hello Andy,

"As far as I can tell from what you've mentioned, the uC's are sending interrupts asynchronously to the CPU (S635MP Via MoBo), and the graphics are not able to keep up with the incoming data."

Ah .. not exactly. I am having trouble keeping the graphics from flickering on the tach. Running less that 1% CPU. Case of getting the graphics to function the way I want :)

"It seems to me that if you were to buffer the incoming data in memory and average the incoming data for each uC every 16 milliseconds via a polling routine, you would have a flicker free 60Hz display. As it stands now you could have each of the uC's generating an interrupt every .01 milliseconds (or perhaps even every uSec). There isn't an off the shelf monitor/video card combo in the world that can keep up with that type of blistering pace (though if you used oscilliscopes for each channel you might - verrry expensive). So back to averaging out the incoming data at 16 millisecs intervals, you could use Blitz banks, which are chunks of managed memory that you can use any way you like, and is very fast, as the buffer for the incoming data stream."

To poll or not to poll, that is the question :)

Reference the timing: The uC's 'resolution' for the PW time period is .01ms .. the PC hasn't a clue about this. PC would 'send' a value to a uC stating how many .01ms iterations were required .. 255 * .01 = 2.55ms total PWM time period etc. All a UC thing.

12K RPM = 100 Rcv/Xmit 'events' per second per cylinder = .01 seconds. The .01ms is uC specific. A 12 Cyl at 12K would have 6 events per 360 degree revolution = 600 total 'events' per second per rev = 1.33 Million instructions 'between' events at 800MHz. Considering I had been dealing solely with 16MHz uC's .. that is a lifetime :)

Assuming a fixed display freq of 60Hz and the system providing 600Hz freq of "information" I see it as reading the 'latest' information in some cases and averaging in others. At 1K RPM I'm only getting 50Hz of info.

Take care,


And why I lean toward multiple instances. Need a function? Add an instance (or mod an existing one). Then mess with main as to when to display the display the data.








Better still, if you can use a rolling average for the each of the incoming data streams, you should get a display that is exactly what you have described with a silky smooth flicker free 60Hz and still be very accurate. Even at only 60Hz display updates, the gauges will *appear* to be functioning in real time to the average person.