Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Help converting some code.


  • Please log in to reply
44 replies to this topic

#21 Illishar

Illishar

    Advanced Member

  • Members
  • PipPipPip
  • 146 posts

Posted 01 February 2011 - 03:14 PM

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 :P

#22 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 01 February 2011 - 04:56 PM

I've been trying to understand what fluent interop is. I guess I don't quite get it.

#23 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 01 February 2011 - 06:49 PM

(side note to Chris: I guess I should inject my entry point into the latest firmware you've posted. Hopefully it compiles with some version of gcc, and you have the source on codeplex or something)


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

#24 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 01 February 2011 - 06:50 PM

I've been trying to understand what fluent interop is. I guess I don't quite get it.


It's basically a way to creating and/or running fast native code _using C#_.

Chris

#25 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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?

#26 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 01 February 2011 - 09:13 PM

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.

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. ;)

Any special steps?

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 :) )

#27 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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.

#28 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 01 February 2011 - 09:42 PM

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.

Personally, I use the fifth post on the first page of this discussion. (Please God, let us get a Wiki someday)

#29 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 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:
  • firmware - this folder contains the TinyBooterDecompressor.bin file that you need for SAM-BA, as well as the ER_CONFIG and ER_FLASH files that you need for MFDeploy
  • LEDapp-WithFluent - your program, modified to contain the "fluent source code" of the routine I modified.
  • LEDapp-NativeBinaries - same program, but with only the compiled "fluent binaries"

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:
  • I removed the reference to System because it was taking up a lot of space and you didn't appear to need it.
  • For some reason your installation wants to reference SecretLabs.NETMF.Hardware.NetduinoPlus, whereas mine wants to reference SecretLabs.NETMF.Hardware.Netduino. I don't know why these two different namespaces exist. I'm always swapping my Netduino and Plus back and forth on the same code with no apparent harm.

Attached Files



#30 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 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

#31 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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.

#32 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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);
        }


#33 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 02 February 2011 - 05:28 PM

If I go through the leddriver class and make it all static does that change the compiled code?

No, the compiled code won't care (however, I believe making it all static is a step in the wrong direction, stylewise)

#34 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 02 February 2011 - 06:09 PM

If you see how I am going to use it making the LEDDriver static makes sense.

#35 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 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

#36 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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.

#37 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 04 February 2011 - 04:34 AM

Personally, I use the fifth post on the first page of this discussion. (Please God, let us get a Wiki someday)

the instrustions say AT91SAM7X512-ex. The list in smba says ek, not ex, is that alright?

#38 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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.

#39 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 04 February 2011 - 01:08 PM

I tried running the regular code on it and it doesn't work. The LED become random colors and flicker. Something weird is happening.

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:
  • Are running in the emulator and not on the actual device (the emulator doesn't have my new firmware :) )
  • Have not flashed my firmware on your device
  • Have modified, renamed, or moved the SimpleInterop project
These things are fragile enough that I'd like to look at them one issue at a time. I'm pretty confident I can get my interop framework working for you. I was working with Bill.French the other day when he was getting the same exception (in his case it turned out that he had re-orged my solution file and moved the interop declarations to a different project--unfortunately native interop on the .NET framework is hostile to that kind of thing)

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:

  • touch the erase pad with a wire connected to +5V
  • power-cycle netduino plus
  • run sam-ba
  • connect to (on my computer: com4), and board=at91samx512-ek
  • boot from flash and enable flash access
  • navigate to firmware\TinyBooterDecompresser.bin inside this package I just sent you
  • press "send file"
  • "no" to "Do you want to lock involved lock regions (0 to 5)"
  • close samba, power-cycle netduino plus
  • MFDeploy
  • Ping... TinyBooter
  • Browse to firmware inside the package I sent you. shift-click on both ER_CONFIG and ER_FLASH
  • Deploy
  • Wait a while
  • Notice that in the log inside MFDeploy, SimpleInterop.dll is mentioned (this is a slightly newer version) (160 RAM - 272 ROM - 93 METADATA)
  • Now load the program FluentSandbox\FluentSandbox.sln in your IDE
  • Navigate to Program.cs in the project FluentSandbox
  • Set a breakpoint on line 22 (by clicking in the very left most margin)
  • Right click on the project FluentSandbox to select its properties
  • Click on .NET Micro Framework, go to Transport, set to USB
  • Press F5 to build and run
  • See the code be compiled in the output window, then you will hit the breakpoint on line 22
  • Press F10 to step over this line. The onboard LED will turn on
  • Press F10 again. The onboard LED will turn off
  • Press F10 again. The onboard LED will turn on.

These steps worked smoothly for me with exactly the attached files I am sending you with this email. Let me know how it goes for you!


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



#40 SirPoonga

SirPoonga

    Advanced Member

  • Members
  • PipPipPip
  • 96 posts

Posted 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 topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.