MachiKania

MachiKaniaの「auxcode」機能について

2025年3月2日

MachiKania の ver 1.4 からは、「auxcode 機能」が使える。これは、C で書かれたコードを、MachiKania 本体に追加で取り込んで使うための機能である。

MachiKania では、BASIC で様々なことを行う機能を提供してきた:

1.液晶ディスプレイや NTSC ビデオに、(日本語を含む)文字やグラフィックスを容易に表示
2.キーボードを接続して、BASIC コードを編集しながら実行する、スタンドアローンPCとしての機能
3.SPI・I2C・UART などの I/O 機能を、BASIC コードから容易に使用する方法を提供
4.複雑な動作を行うコードを、容易に利用するためのクラスライブラリーを提供

ここで書いた3の部分は、MachiKania 本体で提供、4の部分はクラスで提供している。ほとんどのクラスが BASIC で書かれているが、いくつかは C で書かれたコードを BASIC から呼び出す形をとっている(方法1方法2)。

C で書かれたコードの中には、容易に MachiKania から呼び出すように修正できるものもあれば、そういったことが非常に難しいものがある。例えば、RP2040 の PIO 機能を使ったものは、BASIC で利用できるように実装するのは非常に難しい。

「auxcode 機能」は、そういった C のコードを MachiKania で実行できるようにするものだ。「auxcode 機能」を使うには MachiKania 本体のビルドが必要になるが、どうしても必要な機能を MachiKania に取り込むのには汎用性が高いと言える。

auxcode 機能を使うには

auxcode 機能は、MachiKania 本体に次のような機能追加を行うものだ

1.BASIC ステートメントの追加
2.整数型関数の追加
3.文字列型関数の追加
4.浮動小数点型関数の追加
5.上記ステートメント・関数を実行する機能の追加

auxcode 機能はすべて、ソースコード中の「auxcode」ディレクトリーに収める形で提供する。MachiKania のソースコードにはデフォルトで auxcode ディレクトリーがあり、そこには次の2つのファイルが収められている。

  auxcode.c
  auxcode.cmake

これらのファイルは、デフォルトでは次の通り。

auxcode.c
#include "pico/stdlib.h"
#include "../compiler.h"

int aux_statements(void){
	return ERROR_STATEMENT_NOT_DETECTED;
}
int aux_int_functions(void){
	return ERROR_STATEMENT_NOT_DETECTED;
}
int aux_str_functions(void){
	return ERROR_STATEMENT_NOT_DETECTED;
}
int aux_float_functions(void){
	return ERROR_STATEMENT_NOT_DETECTED;
}
int lib_aux(int r0, int r1, int r2){
	return r0;
}

auxcode.cmake
add_library(aux_files
	auxcode/auxcode.c
)
target_link_libraries(aux_files 
	pico_stdlib
)

auxcode.c に書かれている5つの関数は、少し上のパラグラフで述べた5つの機能に相当する。auxcode.cmake は、デフォルトの auxcode.c をコンパイルするための、必要最小限の構成である。追加する機能は、これらのファイルを編集し、必要であればファイルを追加する。

auxcode 機能の使用例

ここでは、どのようにして auxcode 機能を使うのか、使用例を挙げて説明する。次のレポジトリーでは、HB01B0 というカメラを MachiKania で使うためのコードを、収めた。
https://github.com/kmorimatsu/hm01b0_machikania
追加したい機能は、以下の通り

1.HM01B0_INIT ステートメント
2.HM01B0_CAPTURE ステートメント
3.HM01B0_DRAW ステートメント
4.HM01B0_REG_WRITE ステートメント
5.HM01B0_ZOOM ステートメント
6.HM01B0_CAPTURE ステートメント
7.HM01B0_ANALYZE([x]) 関数(整数型)

上記の目的のため、次のコードを用意する。

1.上記1-6のステートメントを BASIC コンパイラーが認識できるように、「aux_statements()」関数を編集
2.上記7の関数を BASIC コンパイラーが認識できるように、「aux_int_functions()」関数を編集
3.上記1-7の構文を実行する際に呼び出されるコードを記述
4.カメラを制御するための C コードを、修正して追加
5.MachiKania のビルドの際に、追加の C ファイルがコンパイルされるように、auxcode.cmake を編集

順に見ていこう。

1.ステートメントを認識させる

hm01b0_machikania の auxcode.c の、aux_statements() 関数は次の通り。
int aux_statements(void){
	if (instruction_is("HM01B0_INIT")) return hm01b0_init_statement();
	if (instruction_is("HM01B0_CAPTURE")) return hm01b0_capture_statement();
	if (instruction_is("HM01B0_DRAW")) return hm01b0_draw_statement();
	if (instruction_is("HM01B0_REG_WRITE")) return hm01b0_reg_write_statement();
	if (instruction_is("HM01B0_ZOOM")) return hm01b0_zoom_statement();
	return ERROR_STATEMENT_NOT_DETECTED;
}

ステートメントを認識させるには、ここで
  「if (instruction_is("HM01B0_INIT"))」
のように記述する。続けて、
  「return hm01b0_init_statement();」
の例のように続ける。

「hm01b0_init_statement()」は、次のように書かれている。
int hm01b0_init_statement(void){
	// The first argument is the pointer to video buffer (324*324 bytes)
	return argn_function(LIB_AUXCODE,
		ARG_INTEGER<<ARG1 |
		LIB_AUX_HM01B0_INIT<<LIBOPTION);
}

コメントにあるように、「HM01B0_INIT」ステートメントは、整数型の引数を一つ取る(ポインターを整数として処理)。
  「ARG_INTEGER<<ARG1」
の部分の記述は、そのためのものだ。引数が文字列なら「ARG_INTEGER」ではなく「ARG_STRING」と、浮動小数点型なら「ARG_FLOAT」とする。

「LIB_AUXCODE」は、BASIC コードを実行中に制御を「lib_aux()」に移すために必要なので、そのままにして使う。また、
  「LIB_AUX_HM01B0_INIT<<LIBOPTION」
は「lib_aux()」内で「HM01B0_INIT」ステートメントの実行であることを認識させるために必要なコードで、
  「LIB_AUX_HM01B0_INIT」
等にはそれぞれ、固有の値を割り当てておく。

2.関数を認識させる

「aux_int_functions()」関数は、次の通り。
int aux_int_functions(void){
	if (instruction_is("HM01B0_ANALYZE(")) return hm01b0_analyze_function();
	return ERROR_STATEMENT_NOT_DETECTED;
}

上の「aux_statements()」の例と同様だが、「"HM01B0_ANALYZE("」のように、「(」が付加されている。文字列型関数の場合は「"XXXX$("」のようにして「aux_str_functions()」に記述、浮動小数点型関数の場合は「"XXXX#("」のようにして「aux_float_functions()」に記述する。

「hm01b0_analyze_function()」関数は、次のように記述されている。
int hm01b0_analyze_function(void){
	// The first argument is number of raws to analyze (default 240).
	g_default_args[1]=240;
	return argn_function(LIB_AUXCODE,
		ARG_INTEGER_OPTIONAL<<ARG1 |
		LIB_AUX_HM01B0_ANALYZE<<LIBOPTION);
}

ここで実装する「HM01B0()」関数の引数は実数値で、省略された場合のデフォルト値は240である。そういった場合は、
  「g_default_args[1]=240;」
のようにデフォルト値を指定したのちに、
  「ARG_INTEGER_OPTIONAL<<ARG1」
のように記述して対処する。

3.構文を実行する際に呼び出されるコードを記述する

ステートメントや関数を実行する際に呼び出されるコードは、「lib_aux()」関数内に記述する。
int lib_aux(int r0, int r1, int r2){
	switch(r2){
		case LIB_AUX_HM01B0_INIT:
			hm01b0_init((uint8_t*)r0);
			break;
(略)
		case LIB_AUX_HM01B0_ANALYZE:
			return (int)hm01b0_analyze(r0);
			break;
		default:
			break;
	}
	return r0;
}

この C 関数は、r0, r1, r2 という3つの引数を持つが、これらは、CPU (ARM Cortex-M0+) のレジスター値である。r2 に上で述べた「LIBOPTION」の値が入っているから、それで分岐して使う。

ここで紹介している「HM01B0_INIT」と「HM01B0_ANALYZE」というステートメント・関数は、引数が1つだ。そういう場合は、引数は「r0」に格納されている。なお、引数が2つの場合は第一引数が「r1」、第二引数が「r0」に格納される。引数が3個以上の場合は最後の引数が「r0」に、それ以外の引数は「r1」ポインターで指定される配列に格納される。

ここではそれぞれ、「hm01b0_init()」と「hm01b0_analyze()」という関数を呼び出すようになっている。これらは、別のCファイル(hm01b0.c)で記述されている。

4.C ファイルを追加する
多くの場合、auxcode.c という単一のファイルにすべてのコードを収めることはできないだろう。機能の実装のために、複数の C ファイルを auxcode ディレクトリーに展開することになる。

hb01b0_machikania の場合、auxcode ディレクトリーに含まれるCファイルは次の3つである。
  auxcode/auxcode.c
  auxcode/hm01b0.c
  auxcode/arducam/arducam.c
必要な機能の実装のために、これらのCファイルは別のところからコピーして修正するか、自分で一から書いて使うことになる。

5.C ファイルをビルドの際に認識させる

デフォルトでは MachiKania のビルドの際に「auxcode.c」しかコンパイルされないので、「hm0xb0.c」と「arducam.c」もコンパイルされるように指定する。これには、「auxcode.cmake」ファイルの編集が必要だ。

例では、「auxcode.cmake」ファイルは次の通り。
add_library(aux_files
	auxcode/auxcode.c
	auxcode/hm01b0.c
	auxcode/arducam/arducam.c
)
target_link_libraries(aux_files 
	pico_stdlib
	hardware_dma
	hardware_i2c
	hardware_pio
	hardware_pwm
)
pico_generate_pio_header(aux_files ${CMAKE_CURRENT_LIST_DIR}/image.pio)

「add_library()」に、コンパイルが必要な C ファイルを追加する。それぞれで使用する必要な Pico の機能(hardware_i2cやhardware_pwm等)については「target_link_libraries()」に追加する。例では PIO も使っているので、それに必要な行(pico_generate_pio_header)も追加されている。

C のプログラムを MachiKania にどんどん取り込もう

Raspberry Pi Pico 用の周辺機器には、C でサンプルプログラム等が供給されているものが多い。簡単なものなら BASIC に移植して MachiKania で使えるが、多くの場合は簡単には移植できない。そういった C のコードでも「auxcode」機能を使えば MachiKania でも使えるようになるものは、多いだろう。この機能を利用して、より多くの周辺機器が MachiKania で使えるようになることを期待する。

コメント

コメントはありません

コメント送信