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
auxcode.cmake
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() 関数は次の通り。
ステートメントを認識させるには、ここで
「if (instruction_is("HM01B0_INIT"))」
のように記述する。続けて、
「return hm01b0_init_statement();」
の例のように続ける。
「hm01b0_init_statement()」は、次のように書かれている。
コメントにあるように、「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()」関数は、次の通り。
上の「aux_statements()」の例と同様だが、「"HM01B0_ANALYZE("」のように、「(」が付加されている。文字列型関数の場合は「"XXXX$("」のようにして「aux_str_functions()」に記述、浮動小数点型関数の場合は「"XXXX#("」のようにして「aux_float_functions()」に記述する。
「hm01b0_analyze_function()」関数は、次のように記述されている。
ここで実装する「HM01B0()」関数の引数は実数値で、省略された場合のデフォルト値は240である。そういった場合は、
「g_default_args[1]=240;」
のようにデフォルト値を指定したのちに、
「ARG_INTEGER_OPTIONAL<<ARG1」
のように記述して対処する。
3.構文を実行する際に呼び出されるコードを記述する
ステートメントや関数を実行する際に呼び出されるコードは、「lib_aux()」関数内に記述する。
この 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()」に、コンパイルが必要な 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 で使えるようになることを期待する。
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 で使えるようになることを期待する。