【第一弾】Zen言語でLチカをしてみた

#はじめに
はじめまして、
組み込み系の会社に働く、もうすぐ社会人2年目になる二人組が、
Zen言語に魅了され、取り組んだ成果を投稿しています。
(Zen言語の詳細は[ここ](https://www.zen-lang.org/ja-JP/)を見てください)


まったり見てってください(笑)


第一弾の今回は!!
RaspberyPi 3を使って組み込みの入門プログラミング『Lチカ』にチャレンジしました！

Lチカを実現する方法はいくつかあると思います。
ですが今回は、初心者であるという点からZen言語を使った「ハードウェア直叩き」ではなく、
Wiring Piライブラリ(GPIOアクセスライブラリ)を
**Zen言語からアクセスする**という方法で実現することにしました。

#前提
- Zen言語バージョン : 0.8.20191124+552247019(Mac)
- モデル : Raspberry Pi 3 Model B

#Let's Try!!
## 全体の流れ
Zen言語を用いたLチカは5ステップ！！
1. [Wiring PiをGithubから取得する。](#1ステップwiring-piをgithubから取得する)
2. [最低限Lチカに必要な関数をZen言語から呼び出せるようにする。](#2ステップlチカに必要な関数をzen言語から呼び出せるようにする)
3. [Zen言語でLチカを行うプログラムを作成する。](#3ステップzen言語でlチカを行うプログラムを作成する)
4. [Zen言語ソースとC言語ソースをコンパイルする。](#4ステップzen言語ソースとc言語ソースをコンパイルする)

### 【1ステップ】Wiring PiをGithubから取得する
```sh
#作業用ディレクトリの作成
mkdir wiringPi-zen

#Wiring Pi のソースコードを取得します。
git clone git://git.drogon.net/wiringPi
```

### 【2ステップ】Lチカに必要な関数をZen言語から呼び出せるようにする
##### サンプルを参考に最低限必要なソースコードは以下です。
1. wiringPi/wiringPi.c
2. wiringPi/piHiPri.c
3. wiringPi/softTone.c
4. wiringPi/softPwm.c

##### Lチカに必要な最低限の関数は以下です。
``` c
#include <wiringPi.h>
/* GPIO setup: Initialises the system into GPIO Pin mode and uses the
 *	memory mapped hardware directly. 
 * (GPIO初期化)
 */
int wiringPiSetup (void);

/* Sets the mode of a pin to be input, output or PWM output 
 * (ピンのモードを入力、出力、PWM 出力のいずれかに設定する)
 */
void pinMode (int pin, int mode);

/* Set an output bit 
 * (出力設定)
 */
void digitalWrite (int pin, int value);

/* Wait for some number of milliseconds 
 * (遅延)
 */
void delay (unsigned int howLong);
```

##### ラッパー関数の作成
では、実際にZen言語から必要な関数を呼び出せるようにしたいと思います。
公式ドキュメントによると方法は3つあるそうです。

1. CソースファイルをZenソースファイルに変換する
2. 手動でCインタフェースを作成する
3. Cヘッダファイルからインポートする


今回は、3番目の方法で実現したいと思います。

[公式ドキュメント](https://www.zen-lang.org/ja-JP/docs/ch14-interfacing-c/#zen%E3%81%8B%E3%82%89c%E3%82%92%E5%91%BC%E3%81%B6)

``` zen
// Cヘッダファイルを、直接Zenソースへインポート
const c = @cImport ({
    @cInclude("wiringPi.h");
});

// ラッパー関数の定義
pub fn wiringPiSetup() void {
    _ = c.wiringPiSetup();
}

pub fn pinMode(pin: c_int, mode: c_int) void {
    _ = c.pinMode(pin, mode);
}

pub fn digitalWrite(pin: c_int, value: c_int) void {
    _ = c.pinMode(pin, value);
}

pub fn delay(howLong: c_uint) void {
    _ = c.delay(howLong);
}

```

### 【3ステップ】Zen言語でLチカを行うプログラムを作成する
wiring Piのサンプルプログラム(examples/blink.c)を参考に、
Lチカプログラムを作っていきたいと思います。

``` setup.zen
const std = @import("std");
const LED = 0;

pub fn main() anyerror!void {

    const stdout = try std.fs.getStdOut();

    try stdout.write("Raspberry Pi Blink\n");

    // 初期化
    wiringPiSetup();
    pinMode(LED, c.OUTPUT);

    // 無期限にLチカ
    while (true) {
        digitalWrite(LED, c.HIGH);
        try stdout.write("Raspberry Pi Blink[ON]\n");
        delay(500);

        digitalWrite(LED, c.LOW);
        try stdout.write("Raspberry Pi Blink[OFF]\n");
        delay(500);
    }

}
```
### 【4ステップ】Zen言語ソースとC言語ソースをコンパイルする
zen言語のコンパイラーは、ZenソースファイルとCソースファイルを同時にコンパイルする事が可能です。Cソースファイルをコンパイルするにの用いたオプションは以下になります。

1. Cソースファイルをコンパイル対象にする
```zen build-exe --c-source <Cソースファイル>```

2. C言語の標準ライブラリを利用する
```zen build-exe --library c <XXX>```

3. C言語のヘッダファイルを探索するパスを追加する
```zen build-exe -isystem <C言語ヘッダファイルパス> <XXX>```



``` sh
cd wiringPi-zen

zen build-exe --c-source  WiringPi/wiringPi/wiringPi.c \
--c-source WiringPi/wiringPi/piHiPri.c \
--c-source  WiringPi/wiringPi/softTone.c \
--c-source WiringPi/wiringPi/softPwm.c \
setup.zen --library c  --name [実行バイナリ名] \
-target armv8_5a-linux-gnueabihf \
-I WiringPi/wiringPi -isystem WiringPi/wiringPi
```
#完成
LEDが500ms毎にON,OFFしています！
![led.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158044/4246504e-6055-893c-1aed-ba1c413ce727.gif)


今回の「Zen言語でLチカをしてみた」は以上になります。

次回はこのプログラムを、Zen言語で記述するビルドスクリプト(build.zen)を用いてコンパイルしてみたいと思います。
C言語の代表的なビルドスクリプト(make)に変わるZen言語に標準に備わった、外部ビルドシステムに依存しないスクリプトらしいです笑


以上、最後まで読んで頂きありがとうございました。