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

NETMF constants


  • Please log in to reply
8 replies to this topic

#1 Blake Ramsdell

Blake Ramsdell

    Member

  • Members
  • PipPip
  • 20 posts

Posted 09 January 2011 - 09:26 AM

I'm working with multiple NETMF platforms (Netduino and FEZ) and I note some slight variations when it comes to hardware resources. It looks like both platforms define slightly different mappings for the Cpu.Pin as well as the SPI devices.

I'm mulling what to do about the digital input mappings, but for the SPI devices, can I just use SPI.SPI_module.SPI1 instead of the Netduino version? They're the same value (0).

#2 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 09 January 2011 - 12:14 PM

Yes, absolutely. We made sure to follow the .NET MF best practices...so you can swap in (Cpu.Pin) and (SPI.SPI_module) instead of the Netduino constants. This will also make your code portable across Netduino Mini, AUG, Device Solutions, custom boards, etc. Chris

#3 CW2

CW2

    Advanced Member

  • Members
  • PipPipPip
  • 1592 posts
  • LocationCzech Republic

Posted 09 January 2011 - 01:02 PM

I'm mulling what to do about the digital input mappings,

IMHO there are two possibilities:

1) #if preprocessor directive and set appropriate symbol in Project Properties "Conditional Compilator symbols", you'd probably need to create new build configuration for each platform (i.e. "Debug - Board_XXX", "Debug - Board_YYY")

#if Board_XXX
Cpu.Pin pin = (Cpu.Pin)xx;
#elif Board_YYY
Cpu.Pin pin = (Cpu.Pin)yy;
#else
#error Unsupported board.
#endif

2) Check SystemInfo.SystemID properties in runtime - if they are not filled correctly, you'd probably need to examine SystemInfo.OEMString

if(SystemInfo.SystemID.OEM == ... && SystemInfo.SystemID.Model == ...)
{
  return (Cpu.Pin)xx;
}
if(SystemInfo.OEMString.IndexOf("Board_YYY") == 0) // For demonstration purposes only
{
  return (Cpu.Pin)yy;
}


#4 Blake Ramsdell

Blake Ramsdell

    Member

  • Members
  • PipPip
  • 20 posts

Posted 09 January 2011 - 08:44 PM

Yes, absolutely. We made sure to follow the .NET MF best practices...so you can swap in (Cpu.Pin) and (SPI.SPI_module) instead of the Netduino constants. This will also make your code portable across Netduino Mini, AUG, Device Solutions, custom boards, etc.


This is where I'm confused -- why are there Netduino-specific constants for NETMF-provided constructs? That is, I see:

namespace SecretLabs.NETMF.Hardware.Netduino
{
    public static class SPI_Devices
    {
        public const SPI.SPI_module SPI1 = 0;
    }
}

and I see:

namespace Microsoft.SPOT.Hardware
{
    public sealed class SPI : IDisposable
    {
...
        public enum SPI_module
        {
            SPI1 = 0,
            SPI2 = 1,
            SPI3 = 2,
            SPI4 = 3,
        }
...
    }
}

So I've made it a point to use the Microsoft.SPOT.Hardware version, but I want to make sure that's safe.

#5 Blake Ramsdell

Blake Ramsdell

    Member

  • Members
  • PipPip
  • 20 posts

Posted 09 January 2011 - 09:15 PM

IMHO there are two possibilities:

1) #if preprocessor directive and set appropriate symbol in Project Properties "Conditional Compilator symbols", you'd probably need to create new build configuration for each platform (i.e. "Debug - Board_XXX", "Debug - Board_YYY")

#if Board_XXX
Cpu.Pin pin = (Cpu.Pin)xx;
#elif Board_YYY
Cpu.Pin pin = (Cpu.Pin)yy;
#else
#error Unsupported board.
#endif


This path is a little futzy and problematic. For example:

#if BOARD_NETDUINO
Cpu.Pin pin = SecretLabs.NETMF.Hardware.Netduino.Pins.GPIO_PIN_D3;
#elif BOARD_FEZ
Cpu.Pin pin = (Cpu.Pin) GHIElectronics.NETMF.FEZ.FEZ_Pin.Digital.Di3;
#else
#error Unsupported board, smooth move. Why don't you figure all the possible #defines and stop wasting my time?
#endif

As well as custom build code so that you include the right assemblies for the right variant of NETMF in the csproj file:

For Netduino:

<Reference Include="SecretLabs.NETMF.Hardware" />
<Reference Include="SecretLabs.NETMF.Hardware.Netduino" />

For FEZ:

<Reference Include="FEZDomino_GHIElectronics.NETMF.FEZ" />

And I presume there's a way to stick those in a PropertyGroup with an appropriate Condition on it.

2) Check SystemInfo.SystemID properties in runtime - if they are not filled correctly, you'd probably need to examine SystemInfo.OEMString

if(SystemInfo.SystemID.OEM == ... && SystemInfo.SystemID.Model == ...)
{
  return (Cpu.Pin)xx;
}
if(SystemInfo.OEMString.IndexOf("Board_YYY") == 0) // For demonstration purposes only
{
  return (Cpu.Pin)yy;
}


This is what I actually did in the code. So I have one function that does the magic based on SystemInfo.OEMString:

// SetupCurrentShieldConfiguration is a little fragile -- it uses
// Microsoft.SPOT.Hardware.SystemInfo.OEMString to try and figure out
// which configuration to use. If that string isn't handled, you will
// not survive.

private static void SetupCurrentShieldConfiguration()
{
    var oemString = SystemInfo.OEMString;

    switch (oemString)
    {
        case "GHI Electronics, LLC":
            CurrentShieldConfiguration = FezShieldConfiguration;
            break;

        case "Netduino by Secret Labs LLC":
            CurrentShieldConfiguration = NetduinoShieldConfiguration;
            break;

        default:
            break;
    }
}

And then I cribbed the constants from the various places:

private class ShieldConfiguration
{
    public Cpu.Pin RedLedPin { get; set;  }
    public Cpu.Pin GreenLedPin { get; set;  }
    public Cpu.Pin SpiChipSelectPin { get; set;  }
    public Cpu.Pin OnboardLedPin { get; set; }
}

private static class NetduinoConstants
{
    public const Cpu.Pin GPIO_PIN_D0 = (Cpu.Pin) 27;
    public const Cpu.Pin GPIO_PIN_D1 = (Cpu.Pin) 28;
    public const Cpu.Pin GPIO_PIN_D2 = (Cpu.Pin) 0;
    public const Cpu.Pin GPIO_PIN_D3 = (Cpu.Pin) 1;
    public const Cpu.Pin GPIO_PIN_D4 = (Cpu.Pin) 12;
    public const Cpu.Pin ONBOARD_LED = (Cpu.Pin) 55;
}

private static ShieldConfiguration NetduinoShieldConfiguration = new ShieldConfiguration
{
    RedLedPin = NetduinoConstants.GPIO_PIN_D3,
    GreenLedPin = NetduinoConstants.GPIO_PIN_D4,
    SpiChipSelectPin = NetduinoConstants.GPIO_PIN_D2,
    OnboardLedPin = NetduinoConstants.ONBOARD_LED
};

private static class FezConstants
{
    public const Cpu.Pin LED = (Cpu.Pin) 4;
    public const Cpu.Pin Di4 = (Cpu.Pin) 19;
    public const Cpu.Pin Di3 = (Cpu.Pin) 31;
    public const Cpu.Pin Di2 = (Cpu.Pin) 33;
}

private static ShieldConfiguration FezShieldConfiguration = new ShieldConfiguration
{
    RedLedPin = FezConstants.Di3,
    GreenLedPin = FezConstants.Di4,
    SpiChipSelectPin = FezConstants.Di2,
    OnboardLedPin = FezConstants.LED
};

I kinda feel icky about cribbing the numbers for everyone's pins, but this was the most elegant way I could come up with a solution.

Thanks for all of the help -- further suggestions welcome.

#6 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 09 January 2011 - 10:45 PM

This is where I'm confused -- why are there Netduino-specific constants for NETMF-provided constructs?


In part this makes sure the user is aware of how many SPI modules are available. Also vendors can assign SPI1 to another constant other than zero. Microsoft recommends building a HardwareProvider for each board this way in the porting kit...

Chris

#7 Blake Ramsdell

Blake Ramsdell

    Member

  • Members
  • PipPip
  • 20 posts

Posted 09 January 2011 - 10:49 PM

In part this makes sure the user is aware of how many SPI modules are available. Also vendors can assign SPI1 to another constant other than zero. Microsoft recommends building a HardwareProvider for each board this way in the porting kit...


Now I'm really confused. So they provide a constant. That might not work at all on some particular platform. How is that useful?

It sounds like you should never, ever used the Microsoft-provided one, and always use the vendor-provided one, since it's possible that the vendor might choose a different SPI identifier than Microsoft...

#8 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 7767 posts
  • LocationNew York, NY

Posted 09 January 2011 - 10:52 PM

Now I'm really confused. So they provide a constant. That might not work at all on some particular platform. How is that useful?

It sounds like you should never, ever used the Microsoft-provided one, and always use the vendor-provided one, since it's possible that the vendor might choose a different SPI identifier than Microsoft...


The built-in constants for cpu pin and spi module are partially for legacy purposes. I wish we could hide them. I would recommend that you always use the board-specific ones.

Chris

#9 Jarrod Sinclair

Jarrod Sinclair

    Advanced Member

  • Members
  • PipPipPip
  • 50 posts
  • LocationSF Bay Area, CA

Posted 17 January 2011 - 02:07 PM

The built-in constants for cpu pin and spi module are partially for legacy purposes. I wish we could hide them. I would recommend that you always use the board-specific ones.

Chris



As an example, the Netduino has it's pins set as follows:

namespace SecretLabs.NETMF.Hardware.Netduino
{
    public static class Pins
    {
        public const Cpu.Pin GPIO_NONE = -1;
        public const Cpu.Pin GPIO_PIN_A0 = 59;
        public const Cpu.Pin GPIO_PIN_A1 = 60;
        public const Cpu.Pin GPIO_PIN_A2 = 61;
        public const Cpu.Pin GPIO_PIN_A3 = 62;
        public const Cpu.Pin GPIO_PIN_A4 = 10;
        public const Cpu.Pin GPIO_PIN_A5 = 11;
        public const Cpu.Pin GPIO_PIN_D0 = 27;
        public const Cpu.Pin GPIO_PIN_D1 = 28;
        public const Cpu.Pin GPIO_PIN_D10 = 54;
        public const Cpu.Pin GPIO_PIN_D11 = 17;
        public const Cpu.Pin GPIO_PIN_D12 = 16;
        public const Cpu.Pin GPIO_PIN_D13 = 18;
        public const Cpu.Pin GPIO_PIN_D2 = 0;
        public const Cpu.Pin GPIO_PIN_D3 = 1;
        public const Cpu.Pin GPIO_PIN_D4 = 12;
        public const Cpu.Pin GPIO_PIN_D5 = 51;
        public const Cpu.Pin GPIO_PIN_D6 = 52;
        public const Cpu.Pin GPIO_PIN_D7 = 3;
        public const Cpu.Pin GPIO_PIN_D8 = 4;
        public const Cpu.Pin GPIO_PIN_D9 = 53;
        public const Cpu.Pin ONBOARD_LED = 55;
        public const Cpu.Pin ONBOARD_SW1 = 29;
    }
}

The "default" MS Spot assignments are this:

namespace Microsoft.SPOT.Hardware
{
    public static class Cpu
    {
        public enum Pin
        {
            GPIO_NONE = -1,
            GPIO_Pin0 = 0,
            GPIO_Pin1 = 1,
            GPIO_Pin2 = 2,
            GPIO_Pin3 = 3,
            GPIO_Pin4 = 4,
            GPIO_Pin5 = 5,
            GPIO_Pin6 = 6,
            GPIO_Pin7 = 7,
            GPIO_Pin8 = 8,
            GPIO_Pin9 = 9,
            GPIO_Pin10 = 10,
            GPIO_Pin11 = 11,
            GPIO_Pin12 = 12,
            GPIO_Pin13 = 13,
            GPIO_Pin14 = 14,
            GPIO_Pin15 = 15,
        }

So if you used the MS SPOT for GPIO_Pin0 then on the Netduino it would actually be D2. I am not even sure what would happen if you tried to using GPIO_Pin15 as the Netduino does not have that cpu.pin exposed. If you really want to write your code to be hardware agnostic then the route your taking is best. remember that each reference you use increases the memory and CPU load on the system so you could also take it one step further and not use any of their libraries and map all the pins yourself. however that is time consuming and error prone (as you know) but will reduce the size of your code.

- Jarrod




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.