NTS1カスタムコントロールパネルSDKの内部構造

Nucleo-F030R8を使ってKorg NTS-1のカスタムコントロールパネルをで作ってみる実験を行った際、Korgが提供しているカスタムコントロールパネルSDKの内部を一通り見たので、その内容を簡単にまとめておきたいと思います。

まず、カスタムコントロールパネル側の全体構成は以下のようになっています。

コントロールパネルとメインボードの間の通信はSPIで、コントロールパネルはスレーブとして動作します。

メインボードとの通信を制御するソフトウェアの本体はnts1_iface.cで、これをラップする形でArduino用ライブラリのnts-1.cppが提供されています。

SPI周りの制御にはSTMicroが提供するHALライブラリが使えますが、IRQハンドラの中ではMCUのレジスタを直接読み書きしています。ユーザプログラムであるArduinoスケッチは基本的にnts1_iface.cの関数を呼び出す必要はありませんが、動作の詳細を知りたければnts-1.cppではなくnts1_iface.cを調べる必要があることは覚えておくといいでしょう。

SPI通信に関与しない、コントロールパネルをArduinoボードとして扱うためのピン名の定義と、GPIOを高速に読み書きする関数nts1_digital_read(pin)nts1_digital_write(pin, value)variant.cppが提供します。(このファイルはGitHubリポジトリ上に載っていないようです。)

◆◆◆

以下、nts1_iface.cの処理内容をまとめていきます。

基本的な処理の流れは以下のようになっています。

Arduinoのループの中で、nts1_idle()が繰り返し呼ばれます。この関数は受信バッファをチェックして、データがあればメッセージハンドラ関数s_rx_msg_handler()にデータを渡します。

受信バッファへの書き込みは割り込みで行われます。コントロールパネルがデータをSPI経由で受信すると割り込みが起こり、割り込みハンドラSPI_IRQ_HANDLER()が呼ばれます。この関数はSPIのデータレジスタから受信データを読み取って受信バッファに書き込んだ後、コントロールパネルからの送信データが送信バッファにあればそのデータを、無ければダミーデータをSPIのデータレジスタに書き込みます。

メインボードへのデータ送信は専用の関数が提供されています。APIリファレンスにあるように

・ノートオン
・ノートオフ
・指定したパラメータへの値の設定(mainとsubの2つのIDでパラメータを指定)

の3つです。

このほか、メインボードにデータをリクエストするコマンドがあります。
リクエストできるデータは

・OSC、フィルタ、エンベロープ、モジュレーション、ディレイ、リバーブの
 ・「ユニットの個数」
 ・N番目のユニットの情報(詳細は後述)
・OSCについて、N番目のユニットのパラメータ情報(詳細は後述)
・アルペジエイターについて、パターン数、パターンの内容、変動域の種類の個数、変動域の内容
・メインボードのシステムのバージョン番号
・指定したパラメータの値の読み出し(mainとsubの2つのIDでパラメータを指定)

があります。

パラメータの指定に使うIDは、メインIDはこちら、サブIDはこちらが一覧となります。また、nts1_iface.hの中でも同様の値が定義されています(SDKのサンプルのシーケンサーはこちらを使っていました)。
パラメータそのものはNTS-1を使っていればおなじみのものばかりです。

◆◆◆

次に、メインボードからのデータ受信です。データ受信の契機には、上記のデータリクエストに関する応答が返ってくる場合と、メインボードが受信したイベント(コントロールパネル経由、MIDI経由)に関するデータがあります。

これらのデータはまず先述のs_rx_msg_handler()が1バイトずつ受け取りますが、1つのメッセージを構成するデータが揃ったところで、メッセージ種別に応じた「メッセージハンドラ関数」が呼び出され、その関数にデータ一式が渡されます。

このメッセージハンドラ関数はユーザが作成します。作成した関数へのポインタをこちらの関数群を使って予めシステム側に登録しておきます。

各メッセージハンドラ関数の仕様はこちらです。tick eventだけはパラメータ無し、それ以外の関数はパラメータを1つ取ります。そのパラメータは、メッセージ形式ごとに定義された構造体へのポインタです。

この「メッセージ形式ごとに定義された構造体」が、前述の「ユニットの情報」や「OSCユニットのパラメータ情報」に相当します。
これらの構造体の定義はこちらにあります。

長くなったので次回に続きます。
次回はAPIを使用する実例と、SDKのバグ(たぶん)について書きます。

コメント