どうせなので、Win 10 IoT を F# でやろうと思って、手始めに F# PCL と組み合わせてみます。C# の Windows Universal と、 F# の Portable Class Liberary との組み合わせです。
F# PCL を追加する
ポータブルクラスライブラリから、IoT のライブラリの参照はできないので、C# -> F# の呼び出ししかできませんが、適当なコールバック(乃至はイベント)を追加してやれば、C#/F# 間の行き来が可能です。MVVM の ViewModel を F# 側で作っておいて、C#/XAML に表示させるという方法でもよいでしょう。
F# のラインタイムは F# 4.0 ( FSharp.Core, 3.47.4.0)で動作確認しています。おそらく、その前のバージョンでも動くハズ。このあたりは、Xamarin.iOS/Android と同じになるので、PCL の範囲内で作っておけば動きます。
C# のコード
Lチカをさせているところで、F# を使ってカウントアップ。あまり意味はないけど、一応 F# のライブラリを呼び出しているということで。タクトスイッチの ValueChanged イベントはおまけです。Win IoT では、スイッチを押したときの ON/OFF をイベントで取得することができます。注意しないといけないのは、イベント自体は UI スレッドとは違うので、表示するときにはディスパッチを使います。このあたりはスレッドや非同期処理をしている方や、割り込み制御をしたことがある方にはおなじみなところです。
public sealed partial class MainPage : Page { public MainPage() { this.InitializeComponent(); this.Loaded += (s, e) => main(); } const int LED1_PIN = 13; const int LED2_PIN = 26; const int SW_PIN = 16; /// <summary> /// メインループ /// </summary> void main() { var gpio = GpioController.GetDefault(); var LED1 = gpio.OpenPin(LED1_PIN); var LED2 = gpio.OpenPin(LED2_PIN); var SW = gpio.OpenPin(SW_PIN); LED1.SetDriveMode(GpioPinDriveMode.Output); LED2.SetDriveMode(GpioPinDriveMode.Output); SW.SetDriveMode(GpioPinDriveMode.Input); LED1.Write(GpioPinValue.Low); LED2.Write(GpioPinValue.Low); /// F# の PCL クラスを作成 var fs = new PclFSharp.Sample(); textName.Text = fs.Hello("masuda"); int count = 0; new Task(async () => { while (true) { /// F# 内でカウントアップ count = fs.Add(count, 1); await textCount.Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, () => { textCount.Text = string.Format("count: {0}", count); }); LED1.Write(GpioPinValue.High); await Task.Delay(500); LED1.Write(GpioPinValue.Low); await Task.Delay(500); LED2.Write(GpioPinValue.High); await Task.Delay(500); LED2.Write(GpioPinValue.Low); await Task.Delay(500); } }).Start(); // タクトスイッチの変更イベント SW.ValueChanged += async (s, e) => { var text = SW.Read() == GpioPinValue.Low ? "OFF" : "ON"; await Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.Normal, () => { textSw.Text = text; }); }; } }
F# のコード
F# のコードがあまりチープなので実用性はないのですが、ひとまず動作確認まで。本当は、ここで LED の制御とかをやりたいのですが、IoT が参照できないので、制御自体は C# 側でやります。F# 側では、純粋にロジックを組めばよいかと。
type Sample() = member this.X = "This is F# PCL" member this.Add(x,y) = x + y member this.Hello(name) = "Hello, " + name
動作させる
面倒なので、HDMI 出力させています。本来ならば、RasPi 付属の液晶ディスプレイとか使いたいところですよね。そのあたりはいずれ I2C 制御を試してから。
こんな風に LED 2個とタクトスイッチを扱います。USB 接続しているのは ELECOM の有線マウスなのだけど、うまく動かなかった。有線 USB のマウスだと動く場合もあるそうなので、まあ相性ということでしょう。折角買ったんですが、暫くお蔵入りです。
というわけで、F# との組み合わせができることが確認できました。ということは、PCL 全般は大丈夫そうですね。また、ロジックのコードさえあれば、Windows デスクトップでテストをしてから、Win IoT のほうに持っていくということも可能です。
お次は RasPi 用のモーター制御用のハットを作って、実際に RasPi 戦車を作ってみようかなと。手元にあるハットはピンが異なってダメなので、自前で作ります。RasPi のモーター制御用のハットって意外と高いので。