Android Things - 汎用入出力（GPIO）の翻訳

# What's this?
https://developer.android.com/things/sdk/pio/gpio.html
の翻訳

# 汎用入出力（GPIO）
[汎用入出力](https://ja.wikipedia.org/wiki/GPIO)ピン（GPIOピン）はプッシュボタンスイッチのようなOn/Offを取得する入力や、LEDのようなOn/Offでコントロールするデバイス向けの出力に使用します。

各GPIOピンは入力用、出力用それぞれに設定することが出来、HIGHとLOWの状態を切り替えることが出来ます。入力モードのときは入力デバイスがOnかOffかを検知することが出来ます。出力モードのときはピンの状態をOnかOffのどちらかに設定することが出来ます。

## 注意
GPIOピンを壊さないために、リード線を接続する前にハードウェアの入出力制限を確認してください。こちら「[Hardware 101](https://developer.android.com/things/hardware/hardware-101.html#analog_and_digital_io)」から確認することが出来ます

# 接続管理
GPIOポートとの接続を確立するためには、ポート名を指定する必要があります。開発するにあたり、**PeripheralManagerService.getGpioList()**を呼び出すことで利用可能なポート名の一覧を取得することが出来ます

```
PeripheralManagerService manager = new PeripheralManagerService();
List<String> portList = manager.getGpioList();
if (portList.isEmpty()) {
    Log.i(TAG, "No GPIO port available on this device.");
} else {
    Log.i(TAG, "List of available ports: " + portList);
}
```

接続すべきポート名が分かれば、**PeripheralManagerService**クラスを使用して接続することが出来ます。ポートの利用が完了したら接続を閉じてリソースを開放してください。また、接続済みのコネクションを閉じるまで同じポートで新たな接続を開始することは出来ません。接続を閉じるには**close()**メソッドを使用します。

```
public class HomeActivity extends Activity {
    // GPIO Pin Name
    private static final String GPIO_NAME = ...;

    private Gpio mGpio;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Attempt to access the GPIO
        try {
            PeripheralManagerService manager = new PeripheralManagerService();
            mGpio = manager.openGpio(GPIO_NAME);
        } catch (IOException e) {
             Log.w(TAG, "Unable to access GPIO", e);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mGpio != null) {
            try {
                mGpio.close();
                mGpio = null;
            } catch (IOException e) {
                Log.w(TAG, "Unable to close GPIO", e);
            }
        }
    }
}
```

# 入力データの読み込み
## GPIOポートからデータを読み込む手順
1. **setDirection()**メソッドに**DIRECTION_IN**をセットして入力モードにする
2. **setActiveType()メソッド**に**ACTIVE_HIGH** か **ACTIVE_LOW**をセットして HIGH（IOREFに近似）とLOW（0に近似）のどちらがtrueを返すようにするかを設定する
3. **getValue()**メソッドで現在の状態を取得することが出来ます

以下がHIGHの時にtrueを返す入力モードの設定例です

```
public void configureInput(Gpio gpio) throws IOException {
    // Initialize the pin as an input
    gpio.setDirection(Gpio.DIRECTION_IN);
    // High voltage is considered active
    gpio.setActiveType(Gpio.ACTIVE_HIGH);

    ...

    // Read the active high pin state
    if (gpio.getValue()) {
        // Pin is HIGH
    } else {
        // Pin is LOW
    }
}
```

## 状態の変化を待ち受ける
入力モードにセットしたGPIOはHIGHかLOWに状態が変化したのをトリガーに検知することが出来ます
1 . **GpioCallback**をポートに登録
2 . **setEdgeTriggerType()**メソッドで何をトリガーにするかセットします

| 値 | 意味 |
|:-:|:-:|
| Gpio.EDGE_NONE  | デフォルト値（値の変化を検知しない）  |
| Gpio.EDGE_BOTH  | HIGHもしくはLOWに値が変化した時  |
| Gpio.EDGE_RISING  | LOWからHIGHに値が変化した時  |
| Gpio.EDGE_FALLING  | HIGHからLOWに値が変化した時  |

3 . **onGpioEdge()**メソッドでtrueを返すことで次の状態変化を待機します


以下がすべての状態を待機する例です

```
public void configureInput(Gpio gpio) throws IOException {
    // Initialize the pin as an input
    gpio.setDirection(Gpio.DIRECTION_IN);
    // Low voltage is considered active
    gpio.setActiveType(Gpio.ACTIVE_LOW);

    // Register for all state changes
    gpio.setEdgeTriggerType(Gpio.EDGE_BOTH);
    gpio.registerGpioCallback(mGpioCallback);
}

private GpioCallback mGpioCallback = new GpioCallback() {
    @Override
    public boolean onGpioEdge(Gpio gpio) {
        // Read the active low pin state
        if (mDevice.getValue()) {
            // Pin is LOW
        } else {
            // Pin is HIGH
        }

        // Continue listening for more interrupts
        return true;
    }

    @Override
    public void onGpioError(Gpio gpio, int error) {
        Log.w(TAG, gpio + ": Error event " + error);
    }
};
```

4 . 入力イベントの検知が不要になった場合、コールバックを解除してください

```
public class HomeActivity extends Activity {
    private Gpio mGpio;
    ...

    @Override
    protected void onStart() {
        super.onStart();

        // Begin listening for interrupt events
        mGpio.registerGpioCallback(mGpioCallback);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // Interrupt events no longer necessary
        mGpio.unregisterGpioCallback(mGpioCallback);
    }
}
```

# 出力データの書き込み
## GPIOの状態を変更する手順

1. **setDirection()**メソッドに**DIRECTION_OUT_INITIALLY_HIGH**か**DIRECTION_OUT_INITIALLY_LOW**のどちらかをセットします。該当ポートに接続されているデバイスの正しい状態を初期化時にセットしてください
2. **setActiveType()メソッド**に**ACTIVE_HIGH** か **ACTIVE_LOW**をセットして HIGH（IOREFに近似）とLOW（0に近似）のどちらがtrueを返すようにするかを設定する
3. **setValue()**メソッドを使用して状態を変更します

以下で初期値をHIGHとして**setValue()**で状態をLOWに変化させます

```
public void configureOutput(Gpio gpio) throws IOException {
    // Initialize the pin as a high output
    gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_HIGH);
    // Low voltage is considered active
    gpio.setActiveType(Gpio.ACTIVE_LOW);

    ...

    // Toggle the value to be LOW
    gpio.setValue(true);
}
```