NETMF constants
#1
Posted 09 January 2011 - 09:26 AM
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
Posted 09 January 2011 - 12:14 PM
#3
Posted 09 January 2011 - 01:02 PM
IMHO there are two possibilities:I'm mulling what to do about the digital input mappings,
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
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
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
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
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
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
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
http://jarrodsinclair.wordpress.com//
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users