Have you thought about using Corey's Fluent interop? It should give you _plenty_ of speed...Chris
Or you could use the Nut/OS. Right now, I'm sampling from the ADC with 25k hz and calculating 2048 line FFTs in realtime. That's speed
  | ||||||||||||||
Help converting some code.
Started by SirPoonga, Jan 23 2011 10:03 PM
44 replies to this topic
#21Posted 01 February 2011 - 03:14 PM
Or you could use the Nut/OS. Right now, I'm sampling from the ADC with 25k hz and calculating 2048 line FFTs in realtime. That's speed #22Posted 01 February 2011 - 04:56 PM
I've been trying to understand what fluent interop is. I guess I don't quite get it.
#23Posted 01 February 2011 - 06:49 PM
We'll be posting source for v4.1.0.6 in a few days once everyone gives us the green light on the release candidate. Chris #24Posted 01 February 2011 - 06:50 PM
It's basically a way to creating and/or running fast native code _using C#_. Chris #25Posted 01 February 2011 - 08:53 PM
Ok. Corey, I am not seeing how to use fluent interop. The samples don't really say much on how to use it like how to do the code generator thing.
So let's make this easy. You see what I am trying to do. Basically I need to take an arbitrary length array and for each element push out the first 12 bits most significant bit first. Then wait 500us. What would be the first steps for to use fluent interop for that?
One thing you say you need to put the fluentop firmware on the netduino first, correct? This would basically be like putting the normal netduino firmware one I assume? Any special steps?
#26Posted 01 February 2011 - 09:13 PM You mean 24 bits, not 12, right? It might be easiest if I post a complete, working program for you to look at it. I should be able to find time for that after I get home from work tonight. Unfortunately I don't have your hardware so I won't be able to test it. I'll try not to put any bugs in it. The only special step I can think of is that I compiled my firmware with gcc, not RVDS, so you'll have to flash the tinybooter (with SAM-BA) as well as the firmware (with MFDeploy). Are you comfortable doing that? If not we'll have to come up with a plan B (perhaps get someone to compile my code with RVDS, or I should figure out how to obtain and use RVDS. Last time I got a trial copy of RVDS it annoyed me, so I switched to gcc ) #27Posted 01 February 2011 - 09:29 PM
Yes, 24 bits. 12 bits is the tlc5947 code I am converting from Oh, I didn't post the project background here. I am making some leds for my motorcycle. I started with a system based on the arduino and the tlc5947 led controller. But these shift register LED pixels are much easier to work with. A lot less wiring also. I'd have a ton of wires all over my bike with the tlc.
Is there step by step instructions somewhere? The only thing I have done with the netduino is update to the latest beta firmware with mfdeploy.
thanks.
#28Posted 01 February 2011 - 09:42 PM Personally, I use the fifth post on the first page of this discussion. (Please God, let us get a Wiki someday) #29Posted 02 February 2011 - 05:39 AM
OK, Poonga my friend, I have modified your program to use my framework. This version is using Chris Walker's trick for accessing the I/O ports directly. It can easily operate in the megahertz range.
The attached zip file contains a number of things:
Disclaimer: I don't have your hardware so I haven't been able to test it. Strategy: I tried to change as little as possible. The key routine I changed is called post_frame. For reference, your original code looks like this: private void post_frame() { //Each LED requires 24 bits of data //MSB: R7, R6, R5..., G7, G6..., B7, B6... B0 //Once the 24 bits have been delivered, the IC immediately relays these bits to its neighbor //Pulling the clock low for 500us or more causes the IC to post the data. for (int LED_number = 0; LED_number < _LEDS.Length; LED_number++) { int this_led_color = _LEDS[LED_number]; //24 bits of color data for (byte color_bit = 23; color_bit != 255; color_bit--) { //Feed color bit 23 first (red data MSB) //digitalWrite(CKI, LOW); //Only change data when clock is low _clock.Write(false); int mask = 1 << color_bit; //The 1'L' forces the 1 to start as a 32 bit number, otherwise it defaults to 16-bit. if ((this_led_color & mask) != 0) //digitalWrite(SDI, HIGH); _data.Write(true); else //digitalWrite(SDI, LOW); _data.Write(false); //digitalWrite(CKI, HIGH); //Data is latched when clock goes high _clock.Write(true); } } //Pull clock low to put strip into reset/post mode //digitalWrite(CKI, LOW); //delayMicroseconds(500); //Wait for 500us to go into reset _clock.Write(false); DelayMicroSec(500); } After rewriting, it looks like this: private void post_frame() { compiledPostFrameMethod.Invoke((int)_clock.Id, (int)_data.Id, _LEDS.Length, ia0 : _LEDS); }Basically post_frame is now a stub method that invokes the native code, which has been compiled into compiledPostFrameMethod. But where do you get compiledPostFrameMethod? You have two choices. You can either take my word for it and use the compiled binaries, or you can compile the routine from yourself from fluent source. Using compiled binaries makes for the fastest runtimes and most compact deployment because the Netduino doesn't have to do any compilation. On the other hand, it takes more work to change it. This version is in LEDapp-NativeBinaries, and the code looks like this: private static CompiledCode CompilePostFrameMethod() { return new CompiledCode(unchecked(new[] { (short)0xB5F0, (short)0xB088, (short)0x9006, (short)0x9105, (short)0x9207, (short)0x9E11, (short)0x9604, (short)0x9E19, (short)0x9603, (short)0x9E03, (short)0x6CF1, (short)0xB402, (short)0x9E07, (short)0x1176, (short)0x1C30, (short)0x9E00, (short)0xF000, (short)0xF859, (short)0x4686, (short)0xBC02, (short)0x4671, (short)0x9102, (short)0x9E06, (short)0x271F, (short)0x403E, (short)0x9601, (short)0x2601, (short)0x9F01, (short)0x40BE, (short)0x9601, (short)0x9E02, (short)0x9F01, (short)0x6037, (short)0x9E02, (short)0x9F01, (short)0x6377, (short)0x9E02, (short)0x9F01, (short)0x6137, (short)0x9E03, (short)0x6CF1, (short)0xB403, (short)0x9E07, (short)0x1176, (short)0x1C30, (short)0x9E01, (short)0xF000, (short)0xF83B, (short)0x4686, (short)0xBC03, (short)0x4671, (short)0x1C08, (short)0x9E05, (short)0x271F, (short)0x403E, (short)0x9600, (short)0x2601, (short)0x9F00, (short)0x40BE, (short)0x9600, (short)0x9F00, (short)0x6007, (short)0x9F00, (short)0x6347, (short)0x9F00, (short)0x6107, (short)0x2100, (short)0xE01C, (short)0x008E, (short)0x1C33, (short)0x9E04, (short)0x58F2, (short)0x2317, (short)0xE013, (short)0x9E02, (short)0x9F01, (short)0x6377, (short)0x2601, (short)0x409E, (short)0x1C34, (short)0x1C16, (short)0x4026, (short)0x1C35, (short)0x2D00, (short)0xD002, (short)0x9F00, (short)0x6307, (short)0xE001, (short)0x9F00, (short)0x6347, (short)0x9E02, (short)0x9F01, (short)0x6337, (short)0x1E5B, (short)0x2B00, (short)0xDAE9, (short)0x1C49, (short)0x9F07, (short)0x42B9, (short)0xDBDF, (short)0x9E02, (short)0x9F01, (short)0x6377, (short)0xB008, (short)0xBCF0, (short)0xBC02, (short)0x4708, (short)0x4730 })); } The compile-from-source version is in LEDapp-WithFluent. Here, the CompilePostFrameMethod() has been written in the funky fluent metalanguage: private static CompiledCode CompilePostFrameMethod() { //Each LED requires 24 bits of data //MSB: R7, R6, R5..., G7, G6..., B7, B6... B0 //Once the 24 bits have been delivered, the IC immediately relays these bits to its neighbor //Pulling the clock low for 500us or more causes the IC to post the data. return CodeGenerator.Compile( (g, clockPin, dataPin, _LEDS_Length, ច, ឆ, ជ, ឋ, ឌ, _LEDS, ផ, ត, ថ, ទ, ធ, ន, ប, firmware) => { //set up ports for very high speed access var clock=g.Declare.FastOutputPort("clock", firmware, clockPin, false); //start low var data=g.Declare.FastOutputPort("data", firmware, dataPin, false); //start low g.For(LED_number => LED_number.Value=0, LED_number => LED_number<_LEDS_Length, LED_number => LED_number.Value=LED_number+1) .Do(LED_number => { var this_led_color=g.Declare.Int("this_led_color", _LEDS[LED_number]); //24 bits of color data g.For(color_bit => color_bit.Value=23, color_bit => color_bit>=0, color_bit => color_bit.Value=color_bit-1) .Do(color_bit => { //Feed color bit 23 first (red data MSB) //digitalWrite(CKI, LOW); //Only change data when clock is low //_clock.Write(false); clock.Clear(); var mask=g.Declare.Int("mask", ((IntExpression)1).ShiftLeft(color_bit)); //The 1'L' forces the 1 to start as a 32 bit number, otherwise it defaults to 16-bit. g.If((this_led_color&mask)!=0) .Then(() => data.Set()) .Else(() => data.Clear()) .Endif(); //digitalWrite(CKI, HIGH); //Data is latched when clock goes high clock.Set(); }); }); //Pull clock low to put strip into reset/post mode //digitalWrite(CKI, LOW); //delayMicroseconds(500); //Wait for 500us to go into reset //** note: the delay will have to be done by the C# side!!!!!! clock.Clear(); }); } You may want to study it closely, and compare the fluent code to your original source code and see the similarities. Special note to Chris Walker: check out how I've wrapped your I/O port accesses in my fancy "FastOutputPort" class. Other micro-notes:
Attached Files#30Posted 02 February 2011 - 05:45 AM
Nice, Corey!
BTW, the two namespaces are interchangeable on the current boards. We've created those two assemblies (HardwareProviders) to get people in the habit of using the one appropriate for their board--as future boards may need this.
Chris
#31Posted 02 February 2011 - 03:38 PM
Thanks Corey, will give it a try tonight.
So we have Arduino code converted to .NET MF code converted to native code. Nice.
#32Posted 02 February 2011 - 03:45 PM
If I go through the leddriver class and make it all static does that change the compiled code?
post_frame actually need to be this private void post_frame() { compiledPostFrameMethod.Invoke((int)_clock.Id, (int)_data.Id, _LEDS.Length, ia0: _LEDS); DelayMicroSec(500); } #33Posted 02 February 2011 - 05:28 PM No, the compiled code won't care (however, I believe making it all static is a step in the wrong direction, stylewise) #34Posted 02 February 2011 - 06:09 PM
If you see how I am going to use it making the LEDDriver static makes sense.
#35Posted 02 February 2011 - 06:33 PM
Poonga,
I'd like to replicate your setup here, in the event the compiled code goes horribly wrong. Can you tell me what parts you have so I can order them (in particular I am interested in the level converter)
Thanks
#36Posted 02 February 2011 - 09:01 PM
http://www.sparkfun.com/products/8745
http://www.sparkfun.com/products/10312
I am also using a 5v 3a regulator (used for R/C helicopters) because the led strip with all leds maxed is about 1.8a. For testing purposes initialize the driver for just a couple of LEDs if you don't have a good enough regulator.
#37Posted 04 February 2011 - 04:34 AM the instrustions say AT91SAM7X512-ex. The list in smba says ek, not ex, is that alright? #38Posted 04 February 2011 - 05:10 AM
I assumed that was it, seemed to work.
When I run the code I get this:
An unhandled exception of type 'System.NotSupportedException' occurred in SimpleInteropInvoker.dll
in Invoker.cs on the line that starts with return MativeInterface.Execute.
I tried running the regular code on it and it doesn't work. The LED become random colors and flicker. Something weird is happening.
#39Posted 04 February 2011 - 01:08 PM Well, that is super-weird. I don't see why my version of the firmware should have that effect; the salient differences are that it is a little bit old (based on version 1.0.3 I think) and it was compiled with gcc rather than RVDS. Maybe--maybe--gcc produces slightly poorer code and you're still timing-dependent? Seems kinda unlikely... Regarding your System.NotSupportedException, that can happen if you:
It was helpful to us for me to produce this step-by-step walkthrough for a standard sandbox program, AND with the files I am attaching to this post. Following exactly these directions worked smoothly for both of us:
I've also been thinking of posting DLL's rather than (or as well as) source. It might be easier for people to add a few DLL's to their project rather than adding a bunch of source code. Anyway, let me know if the above instructions help. Attached Files#40Posted 06 February 2011 - 01:03 AM
I can go through the same steps but with the official netduino firmware to go back, correct? It is weird the program is not working at all now. But the simple button example does. I need to rule out the custom firmware.
0 user(s) are reading this topic0 members, 0 guests, 0 anonymous users | ||||||||||||||
|
||||||||||||||
This webpage is licensed under a Creative Commons Attribution-ShareAlike License. | ||||||||||||||