IoTCore I2C

I2C APIを調べました。

#前提
* Raspberry Pi 2
* Windows 10 IoT Core 10.0.10586.218
* Visual Studio 2015 14.0.25123.00 Update 2
* [LSM9DS1](http://ssci.to/2734)

#結線
![20160619D.jpg](https://qiita-image-store.s3.amazonaws.com/0/109634/bef226ae-f694-6a0f-32ac-a6432ca06b1b.jpeg)


#やり方
##1. 使用するI2CコントローラのデバイスIDを取得します。

```csharp
string aqs = I2cDevice.GetDeviceSelector(friendlyName);
var dis = await DeviceInformation.FindAllAsync(aqs);
// dis[0].Id がデバイスID
```

> 具体的な値はこれ。"\\?\ACPI#MSFT8000#1#{a11ee3c6-8421-4202-a3e7-b91ff90188e4}\I2C1"

##2. I2Cに接続したデバイスのインスタンスを生成します。

1つのスレーブアドレスに対して1インスタンスを生成します。
スレーブアドレスの指定は必須です。
[バス速度](https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.devices.i2c.i2cbusspeed.aspx)と[共有モード](https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.devices.i2c.i2csharingmode.aspx)を指定することができます。

```csharp
var device = await I2cDevice.FromIdAsync(dis[0].Id, new I2cConnectionSettings(0x6b) { BusSpeed = I2cBusSpeed.FastMode, SharingMode = I2cSharingMode.Exclusive, });
```
#3. デバイスのメソッドを実行します。

必要に応じて、[Write](https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.devices.i2c.i2cdevice.write.aspx) / [Read](https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.devices.i2c.i2cdevice.read.aspx) / [WriteRead](https://msdn.microsoft.com/ja-jp/library/windows/apps/windows.devices.i2c.i2cdevice.writeread.aspx) メソッドを実行します。
WriteRead メソッドは、Writeした後にRestartConditionでReadするアレです。

```csharp
device.Write(new byte[] { 0x20, 0xc0, });
var data = new byte[6];
device.WriteRead(new byte[] { 0x28 }, data);
```

Write メソッドの波形。
![20160619A.PNG](https://qiita-image-store.s3.amazonaws.com/0/109634/080143ec-a354-0914-4514-df33cae598bf.png)

WriteRead メソッドの波形。
![20160619B.PNG](https://qiita-image-store.s3.amazonaws.com/0/109634/0d71c073-1595-1e89-8542-6bd3d377b017.png)

#気になって調べたこと
##共有モードのExclusiveって、どういう単位で排他するの？
スレーブアドレスの単位で排他します。
例えば、Exclusiveでも、スレーブアドレスが0x6bと0x6cを同時にインスタンス生成することができます。スレーブアドレスが0x6bと0x6bはダメ。後者の戻り値がnullになります。

##共有モードのExclusiveは、Sharedより速い？
余分な処理が無い分、速いんじゃないか？と思い、通信時間を計測しましたが、、、はっきりした差はありませんでした。

##デバイス単位にバス速度が指定できるってことは、同一I2Cバスに混在可能？
可能です。
試しに、Sharedでバス速度違いのデバイスインスタンスを作って実行してみたところ、それぞれで指定したバス速度で通信しました。
ちょっと便利。

100K/400K混在の波形。
![20160619C.PNG](https://qiita-image-store.s3.amazonaws.com/0/109634/4f03298f-4f1c-9fd9-86fc-c705707af40e.png)

#サンプルコード

```csharp
private void Page_Loaded(object sender, RoutedEventArgs e)
{
    Task.Run(I2cTask);
}

private async Task I2cTask()
{
    var device = await GetI2cDevice("I2C1", 0x6b, I2cBusSpeed.FastMode);
    device.Write(new byte[] { 0x20, 0xc0, });   // CTRL_REG6_XL = 0b11000000

    var data = new byte[6];
    for (;;)
    {
        device.WriteRead(new byte[] { 0x28 }, data);    // OUT_X_XL, OUT_Y_XL, OUT_Z_XL
        Debug.WriteLine("{0} {1} {2}", BitConverter.ToInt16(data, 0), BitConverter.ToInt16(data, 2), BitConverter.ToInt16(data, 4));
    }
}

private async Task<I2cDevice> GetI2cDevice(string friendlyName, int slaveAddress, I2cBusSpeed busSpeed = I2cBusSpeed.StandardMode, I2cSharingMode sharingMode = I2cSharingMode.Exclusive)
{
    string aqs = I2cDevice.GetDeviceSelector(friendlyName);
    var dis = await DeviceInformation.FindAllAsync(aqs);

    return await I2cDevice.FromIdAsync(dis[0].Id, new I2cConnectionSettings(slaveAddress) { BusSpeed = busSpeed, SharingMode = sharingMode, });
}
```