Raspberry Pi > GPIO > C > i2c_send_command_180227.c > v0.1, v0.2 > GPIO24をHレベルで出力する

```
Raspberry Pi 2 Model B (以下RPi)
Raspbian Jessie
Python 2.7.9
```

### 処理予定と状況

- I2Cセンサーから測定値を読取る
- 組込みCでの実装予定
- Pythonでの動作チェックは完了
    - GitHubにあったコードで確認
    - ハードウェアは問題ない

GPIOのポート出力(OUT, IN)とレベル(High, Low)操作でのI2Cセンサー測定値の読取を実装する。

`/dev/i2c-1`を使わずに`/sys/class/gpio/`使用での実装とする。
(組込みでsoftware I2Cとして実装するため)。

こういう実装を作っておくことで、将来、別のセンサーの実装が必要な時に短時間で最終形(組込みC)の実装に到達するだろう。

### 参考

- 1. [【Raspberry Pi】GPIOで出力するメモ（コマンド）](https://qiita.com/kure/items/cf77c8ecacaf85bbbcdc) by @kureさん
    - echoを使った`/sys/class/gpio/`の書換え
- 2. [Linuxの流儀でGPIOを監視する](https://vintagechips.wordpress.com/2013/09/09/linux%E3%81%AE%E6%B5%81%E5%84%80%E3%81%A7gpio%E3%82%92%E7%9B%A3%E8%A6%96%E3%81%99%E3%82%8B/) @ 電脳伝説さん
    - `/sys/class/gpio/`のCでの制御
- 3. [MSP430 > I2C > ソフトウェアI2Cでの実装 > SDAの方向制御のタイミング](https://qiita.com/7of9/items/a1a42359cff9ed06778f)
    - マクロのみのI2C通信実装 (low level実装なし)


### code v0.1 > GPIO24をHレベル出力

```i2c_send_command_180227.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <stdbool.h>
#include <string.h>

/*
v0.1 Feb. 27, 2018
  - test > set High for [GPIO_SCL]
  - add gpio_setDirection()
  - add gpio_setHigh()
  - add gpio_setExport()
*/


#define GPIO_SDA (25) // Pin# 22
#define GPIO_SCL (24) // Pin# 18

void gpio_setExport(int index, bool bfOn)
{
    int wfd;
    static char zbuf[10];
    if (bfOn) {
        wfd = open("/sys/class/gpio/export", O_WRONLY);
    } else {
        wfd = open("/sys/class/gpio/unexport", O_WRONLY);
    }
    sprintf(zbuf, "%d", index);
    write(wfd, zbuf, (int)strlen(zbuf));
    close(wfd);
}

void gpio_setHigh(int index, bool bfTrue)
{
    int wfd;
    static char zbuf[30];
    // 1234567890123456789012345678
    // /sys/class/gpio/gpioxx/value

    sprintf(zbuf, "/sys/class/gpio/gpio%d/value", index);
    wfd = open(zbuf, O_WRONLY);
    if (bfTrue) {
        write(wfd, "1", 1);
    } else {
        write(wfd, "0", 1);
    }
    close(wfd);
}

void gpio_setDirection(int index, bool bfOut)
{
    int wfd;
    static char zbuf[33];
    // 12345678901234567890123456789012
    // /sys/class/gpio/gpioxx/direction

    sprintf(zbuf, "/sys/class/gpio/gpio%d/direction", index);
    wfd = open(zbuf, O_WRONLY);
    if (bfOut) {
        write(wfd, "out", 3);
    } else {
        write(wfd, "in", 2);
    }
    close(wfd);
}

int main(){
    gpio_setExport(GPIO_SCL, /* bfOn=*/true);
    gpio_setDirection(GPIO_SCL, /* bfOut=*/true);
    gpio_setHigh(GPIO_SCL, /* bfTrue=*/true);
    //gpio_setHigh(GPIO_SCL, /* bfTrue=*/false);
    //gpio_setExport(GPIO_SDA, /* bfOn=*/false);
}
```

```bash
$ gcc i2c_send_command_180227.c -o i2c_send_command 
$ sudo ./i2c_send_command 
```

GPIO24のHレベルがassert状態になる。

v0.1では手じまいは手動で行うこと。

```bash
$ echo "24" > /sys/class/gpio/unexport
```

v0.1のコードはリソース消費の観点からは良くない。ポーティング前の実装まで済んだ段階で再考する予定。

### link

- [Raspberry Pi > GPIO > GPIO26の出力設定(Hレベル)でssh接続が切れる > link: Why are some GPIO pins not available? | Revisionにより使えるポートはさらに変わる](https://qiita.com/7of9/items/1ac840e4544b9e18d3b7)


### code v0.2
(追記 2018/03/01)

```i2c_send_command_180227.c
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <stdbool.h>
#include <string.h>

/*
v0.2 Mar. 01, 2018
  - add s_zbuf[]
  - add [GPIO_HIGH], [GPIO_LOW]
  - refactor > change gpio_setHigh() to gpio_setLevel()
v0.1 Feb. 27, 2018
  - test > set High for [GPIO_SCL]
  - add gpio_setDirection()
  - add gpio_setHigh()
  - add gpio_setExport()
*/


#define GPIO_SDA (19) // Pin# 35
#define GPIO_SCL (26) // Pin# 37
#define GPIO_HIGH (true)
#define GPIO_LOW (false)

// 12345678901234567890123456789012
// /sys/class/gpio/gpioxx/direction
static char s_zbuf[40]; // buffer for sprintf()

void gpio_setExport(int index, bool bfOn)
{
    int wfd;
    
    if (bfOn) {
        wfd = open("/sys/class/gpio/export", O_WRONLY);
    } else {
        wfd = open("/sys/class/gpio/unexport", O_WRONLY);
    }
    sprintf(s_zbuf, "%d", index);
    write(wfd, s_zbuf, (int)strlen(s_zbuf));
    close(wfd);
}

void gpio_setLevel(int index, bool bfHigh)
{
    int wfd;

    sprintf(s_zbuf, "/sys/class/gpio/gpio%d/value", index);
    wfd = open(s_zbuf, O_WRONLY);
    if (bfHigh) {
        write(wfd, "1", 1);
    } else {
        write(wfd, "0", 1);
    }
    close(wfd);
}

void gpio_setDirection(int index, bool bfOut)
{
    int wfd;

    sprintf(s_zbuf, "/sys/class/gpio/gpio%d/direction", index);
    wfd = open(s_zbuf, O_WRONLY);
    if (bfOut) {
        write(wfd, "out", 3);
    } else {
        write(wfd, "in", 2);
    }
    close(wfd);
}

int main(){
    gpio_setExport(GPIO_SCL, /* bfOn=*/true);
    gpio_setDirection(GPIO_SCL, /* bfOut=*/true);
    gpio_setLevel(GPIO_SCL, GPIO_HIGH);

	// delay() or some other delay function 
    
    gpio_setLevel(GPIO_SCL, GPIO_LOW);
    
    // to unexport GPIO
    //gpio_setExport(GPIO_SDA, /* bfOn=*/false);

	return 0;
}
```