I've recently been blinking LEDs for a video tracking project and thought I'd share my IO
library for the Edison Arduino board. At this point in time only pins D03, D05, D06, D09
and D10 have been implemented and tested. If you need other pins initialization is handled in the
IOSet()
constructor. Every new IO must be added to the pins
dictionary
with a Pin
enumeration (you'll have to add an enumeration constant here too) and
new ArdGPIO(...)
. The ArdGPIO constructor takes low level intel edison pins controlling
pull-up/down, direction, and value states respectively and has an optional Action
parameter
for special initialization procedures such as are required for PWM pins (see D10 initialization). Pin
connection diagrams can be found in
this document which was taken
from a post on the Edison Forum (can't find the link right now...).
using Edison.IO;
...
ArdGPIO pin3 = ArdIO.GPIO[ArdGPIO.Pin.D03];
...
//Output - Output value written to pin.Value
pin3.IODirection = ArdGPIO.Direction.Out;
pin3.IOValue = ArdIO.Value.High; //Physical pin D03 should be outputting a High state signal
pin3.IOValue = ArdIO.Value.Low; //Physical pin D03 should be outputting a Low state signal
//Input - Set pin to High-Z state. values can be read from pin.Value
pin3.IODirection = ArdGPIO.Direction.In;
ArdIO.Value value = pin3.IOValue; //value will contain the digital state read from Pyisical pin D03
//High - Set pin to input state with pull-up resistor enabled. values can be read from pin.Value
pin3.IODirection = ArdGPIO.Direction.High;
ArdIO.Value value = pin3.IOValue; //value will contain the digital state read from Pyisical pin D03, High if no connection
//Low - Set pin to input state with pull-down resistor enabled. values can be read from pin.Value
pin3.IODirection = ArdGPIO.Direction.Low;
ArdIO.Value value = pin3.IOValue; //value will contain the digital state read from Pyisical pin D03, Low if no connection
using System;
using System.Collections.Generic;
namespace Edison.IO
{
class ArdGPIO
{
private static void ExportIO(int io)
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter("/sys/class/gpio/export"))
{
sw.Write(io.ToString());
}
}
private static bool IsIOExported(int io)
{
return System.IO.Directory.Exists("/sys/class/gpio/gpio" + io.ToString());
}
private static void SetMux(int pin, int mode)
{
using (System.IO.StreamWriter sw =
new System.IO.StreamWriter("/sys/kernel/debug/gpio_debug/gpio" +
pin.ToString() + "/current_pinmux"))
{
sw.Write("mode" + mode.ToString());
}
}
private static void SetDirection(int pin, Direction dir)
{
using (System.IO.StreamWriter sw =
new System.IO.StreamWriter("/sys/class/gpio/gpio" + pin.ToString() + "/direction"))
{
switch (dir)
{
case Direction.High:
sw.Write("high");
break;
case Direction.Low:
sw.Write("low");
break;
case Direction.In:
sw.Write("in");
break;
case Direction.Out:
sw.Write("out");
break;
}
}
}
private static Direction GetDirection(int pin)
{
using (System.IO.StreamReader sr =
new System.IO.StreamReader("/sys/class/gpio/gpio" + pin.ToString() + "/direction"))
{
string val = sr.ReadToEnd().Trim().ToLower();
if (val == "high")
return Direction.High;
else if (val == "low")
return Direction.Low;
else if (val == "in")
return Direction.In;
else if (val == "out")
return Direction.Out;
}
throw new FormatException("Unrecognized Response");
}
private static void SetValue(int pin, Value value)
{
using (System.IO.StreamWriter sw =
new System.IO.StreamWriter("/sys/class/gpio/gpio" + pin.ToString() + "/value"))
{
switch (value)
{
case Value.High:
sw.Write("1");
break;
case Value.Low:
sw.Write("0");
break;
}
}
}
private static Value GetValue(int pin)
{
using (System.IO.StreamReader sr =
new System.IO.StreamReader("/sys/class/gpio/gpio" + pin.ToString() + "/value"))
{
string val = sr.ReadToEnd().Trim();
if (val == "0")
return Value.Low;
else if (val == "1")
return Value.High;
}
throw new FormatException("Unrecognized Response");
}
public enum Pin
{
D03, D05, D06, D09, D10
}
public enum Direction
{
In, Out, High, Low
}
public enum Value
{
High, Low
}
public class IOSet
{
internal static bool isInitialized
{
get
{
return ArdGPIO.IsIOExported(214);
}
}
internal static void Initialize()
{
ArdGPIO.ExportIO(214);
ArdGPIO.SetDirection(214, Direction.High);
}
private Dictionary<Pin, ArdGPIO> pins = new Dictionary<Pin,ArdGPIO>();
public ArdGPIO this[Pin pin]
{
get { return this.pins[pin]; }
}
public IOSet()
{
this.pins.Add(Pin.D03, new ArdGPIO(219, 251, 12));
this.pins.Add(Pin.D05, new ArdGPIO(221, 253, 13));
this.pins.Add(Pin.D06, new ArdGPIO(222, 254, 182));
this.pins.Add(Pin.D09, new ArdGPIO(225, 257, 183));
this.pins.Add(Pin.D10, new ArdGPIO(226, 258, 41, () =>
{
if (!IsIOExported(240))
ExportIO(240);
SetDirection(240, Direction.Out);
SetValue(240, Value.Low);
if (!IsIOExported(263))
ExportIO(263);
SetDirection(263, Direction.Out);
SetValue(263, Value.High);
}));
}
}
private static IOSet gpios = new IOSet();
public static IOSet GPIO
{
get { return gpios; }
}
private int PullUD_Pin;
private int Direction_Pin;
private int IO_Pin;
private bool init = false;
public Direction IODirection
{
set
{
this.InitilizeIfRequired();
switch (value)
{
case Direction.High:
ArdGPIO.SetDirection(this.IO_Pin, Direction.High);
ArdGPIO.SetValue(this.PullUD_Pin, Value.High);
ArdGPIO.SetDirection(this.PullUD_Pin, Direction.Out);
ArdGPIO.SetValue(this.Direction_Pin, Value.Low);
ArdGPIO.SetDirection(this.IO_Pin, Direction.In);
break;
case Direction.Low:
ArdGPIO.SetDirection(this.IO_Pin, Direction.Low);
ArdGPIO.SetValue(this.PullUD_Pin, Value.Low);
ArdGPIO.SetDirection(this.PullUD_Pin, Direction.Out);
ArdGPIO.SetValue(this.Direction_Pin, Value.Low);
ArdGPIO.SetDirection(this.IO_Pin, Direction.In);
break;
case Direction.In:
ArdGPIO.SetDirection(this.IO_Pin, Direction.Low);
ArdGPIO.SetDirection(this.PullUD_Pin, Direction.In);
ArdGPIO.SetValue(this.Direction_Pin, Value.Low);
ArdGPIO.SetDirection(this.IO_Pin, Direction.In);
break;
case Direction.Out:
var val = ArdGPIO.GetValue(this.IO_Pin);
ArdGPIO.SetDirection(this.IO_Pin, val == Value.High ? Direction.High : Direction.Low);
ArdGPIO.SetDirection(this.PullUD_Pin, Direction.In);
ArdGPIO.SetValue(this.Direction_Pin, Value.High);
ArdGPIO.SetDirection(this.IO_Pin, Direction.Out);
break;
}
}
get
{
this.InitilizeIfRequired();
var dirVal = ArdGPIO.GetValue(this.Direction_Pin);
if (dirVal == Value.High)
return Direction.Out;
else
{
var puDir = ArdGPIO.GetDirection(this.PullUD_Pin);
if (puDir == Direction.In)
return Direction.In;
else
{
if (ArdGPIO.GetValue(this.PullUD_Pin) == Value.High)
return Direction.High;
else
return Direction.Low;
}
}
}
}
public Value IOValue
{
get
{
this.InitilizeIfRequired();
return ArdGPIO.GetValue(this.IO_Pin);
}
set
{
this.InitilizeIfRequired();
ArdGPIO.SetValue(this.IO_Pin, value);
}
}
public ArdGPIO(int PullUD_Pin, int Direction_Pin, int IO_Pin, Action preInit = null)
{
if (preInit != null)
preInit();
this.PullUD_Pin = PullUD_Pin;
this.Direction_Pin = Direction_Pin;
this.IO_Pin = IO_Pin;
}
private void InitilizeIfRequired()
{
if (this.init)
return;
this.init = true;
if (!IOSet.isInitialized)
IOSet.Initialize();
if (!ArdGPIO.IsIOExported(this.IO_Pin))
ArdGPIO.ExportIO(this.IO_Pin);
if (!ArdGPIO.IsIOExported(this.Direction_Pin))
ArdGPIO.ExportIO(this.Direction_Pin);
if (!ArdGPIO.IsIOExported(this.PullUD_Pin))
ArdGPIO.ExportIO(this.PullUD_Pin);
ArdGPIO.SetMux(this.IO_Pin, 0);
ArdGPIO.SetDirection(this.IO_Pin, Direction.High);
ArdGPIO.SetDirection(this.Direction_Pin, Direction.Low);
ArdGPIO.SetDirection(this.PullUD_Pin, Direction.Low);
ArdGPIO.SetValue(this.Direction_Pin, Value.Low);
ArdGPIO.SetDirection(this.Direction_Pin, Direction.Out);
ArdGPIO.SetValue(this.PullUD_Pin, Value.Low);
ArdGPIO.SetDirection(this.IO_Pin, Direction.In);
}
}
}