電子ブロック工房 / MachiKania https://www.rad51.net/blog/mycom/ IC・トランジスタで出来たコンピューターを設計・製作するためのブログ / マチカニア BASIC システム ja Jeans CMS © Weblog http://backend.userland.com/rss https://www.rad51.net/jeans/skins/jeans/images/jeans2.gif 電子ブロック工房 https://www.rad51.net/blog/mycom/ MachiKania type P ver 1.4 を公開 https://www.rad51.net/blog/mycom/?itemid=982
公式ページはこちら
GitHub リリースページはこちら

ReadMeに記載した更新履歴は、次の通りです。
Phyllosoma 1.40/KM-1505 (2024.2.17)
 ・サンプルプログラムに、FILEMAN.BAS(ファイルマネージャー)を追加。
 ・クラスライブラリーに、BUTTON(ボタン操作), GEN3O(源ノ角ゴシック表示), 
  QRCODE(QRCODE表示), TSC2046(タッチパネル操作)を追加。
 ・液晶を使わない場合に、SPI命令でspi1を使う事を可能にした。
 ・PUTBMP命令で、横幅が長い画像を表示する際の不具合を修正。
 ・ファイル一覧表示の際、ファイル更新日時の表示を可能にした。
 ・ファイル一覧表示の際の、ファイル名・ファイル更新日時による表示順に対応。
 ・ILI9488液晶で縦置の際の表示不具合を修正。
 ・FRENAME, MKDIR命令及びFRENAME(), MKDIR()関数の追加。
 ・補助コード(auxcode)を追加できる機能を実装

ファイルマネージャーの同梱と、ファイル一覧の機能向上

今回の目玉機能は、ファイルマネージャーを同梱した事です。これにより、スタンドアローン機としての最低限の機能は、ほぼそろった事になります。PC と連携しなくても MachiKania のみで、一通りの事は出来るようになったと思います。ファイルマネージャーはサンプルプログラムとして、「FILEMAN.BAS」の名で保存されていますので、選択して実行してください。なお、ファイルマネージャーは USB キーボード版で利用できます。

また、ファイル一覧表示の際に、ファイル名順やファイル作成時刻順で表示できるようになりました。今までは、MMC/SDカードに保存のファイル数が多くなると、目的のファイルを見つけ出すのに苦労しましたが、そういった苦労なしで見つけることができるようになりました。加えて、ファイル作成時刻を閲覧する事も出来るようになりました。

auxcode機能

MachiKania で、C で書いたコードを実行する方法として、今まで2つの方法を提供してきました(方法1方法2)。これらの方法では、クラスファイルを作成することができるので、いったんクラス化してしまえば、BASIC プログラムから取り込んで呼び出すことが可能です。ただ、クラス化するにあたって色々とコツが必要で、場合によってはうまくクラス化できないようなケースもあります。

そこで、MachiKania をソースコードからビルドする際に、補助機能を追加してビルドする事で、さまざまな種類の C コードを取り込めるようにしました。「auxcode」と名付けた機能が、それです。

ver 1.4 以降の MachiKania のソースコードには、「auxcode」という名のディレクトリーがあります(GitHub 該当ページはこちら)。デフォルトでは「auxcode.c」と「auxcode.cmake」の2つのファイルがありますが、これを書き換えた後に、MachiKania 全体をビルドすれば、補助機能が追加された MachiKania ができます。次のレポジトリーが、一例です。

https://github.com/kmorimatsu/hm01b0_machikania

これは、HM01B0 カメラを MachiKania で使うためのものです。このレポジトリーにある「auxcode」ディレクりーを MachiKania ソースコードに上書き保存してビルドすると、HM01B0 カメラに対応した MachiKania が作成されます。実行すると「HM01B0_INIT」「HM01B0_CAPTURE」「HM01B0_DRAW」「HM01B0_REG_WRITE」の4つの命令が追加で使えるようになり、それらを用いて HM01B0 カメラを制御したり画面に映像を表示したりできるようになります。

今後、MachiKania の新しいバージョンが公開された際にも、「auxcode」を新しいバージョンのソースコードにコピーしてビルドしなおすことで、将来のバージョンにも対応できます。「auxcode」の書き方は、HM01B0 の例を参考にしてください。リクエストがあれば、書き方についてもブログ記事を書くかもしれません。

追加のクラスライブラリー

BUTTON, GEN3O, QRCODE, TSC2046 の4つのクラスを、クラスライブラリーに追加しました。それぞれ、

・BUTTON は、6つあるボタンの読み取りを容易にする
・GEN3O は、CKNJ16 より大きなサイズのフォントを表示する
・QRCODE は、文字通り QRCODE を画面に表示する
・TSC2046 は、タッチパネルを利用する

際に、便利に使えるものです。今後も、クラスライブラリーを充実させていく予定です。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=982 Fri, 16 Feb 2024 19:19:19 PST ITEM982_20240216
MachiKania type P ver 1.3 に、天気予報を喋らせる https://www.rad51.net/blog/mycom/?itemid=981
作例として、天気予報の情報サイトからデーターを取ってきて、今日と明日の天気予報を得るような物を作ってみました。NTPから今日の日付も取ってこられるので、その情報も使います。今日の日付と天気予報は、画面に表示させるのではなくスピーカーで話させるようにしてみました。完成写真は、以下の通りです。小さな箱に、電源スイッチとスピーカーが取り付けられたものです。

2023-09-26-weatherBox.jpg

どんなものか

まずは、どんな動作をするのかの参考に、twitter.com に実行中の動画を載せましたので、ご覧ください(下の画像をクリックすると、twitter.comの該当ポストに移動します;音が出ます)。

2023-09-30-twitter.com.jpg

スイッチを入れておよそ10秒待つと、まず今日の日付と曜日、次に今日の天気予報と最高気温、続けて明日の天気予報と最低気温、最高気温を音声で知らせてくれます。紹介したものは英語のバージョンですが、日本語のバージョンも用意してあります。

箱の中身と、回路

箱の中は、こんな感じです。写真上は、電池・スピーカー・電源スイッチ。下は、Raspberry Pi Pico W。その左にあるDIP-8の石はアンプ IC (NJM2113D)です。

2023-09-30-inside1.jpg

別の角度からです。手前に見えるのは、micro-SDです。アダプターを、基板に半田付けしてあります。

2023-09-30-inside2.jpg

回路図は、下の通りです(クリックで、拡大)。Raspberry Pi Pico Wには、他にMachiKania の基本構成の通り、SDカードを接続しています。液晶ディスプレイは使用しないので、接続していません。

2023-09-30-schematic.png

プログラム

プログラムは、MachiKania BASIC で書かれており、「MACHIKAP.BAS」のファイル名で保存してあります。

useclass JSON,WGET
usevar Min0,Max0,Fnum0,Fstr0
usevar Min1,Max1,Fnum1,Fstr1

out 6,1

if val(strftime$("%Y"))<2023 then ntp

j$=WGET::FORSTRING$("https://dataservice.accuweather.com/forecasts/v1/daily/5day/332097?apikey=[AccuWeather API key]")
o=new(JSON,j$)

Min0=int(o.FQUERY#(".DailyForecasts[0].Temperature.Minimum.Value")+0.5)
Max0=int(o.FQUERY#(".DailyForecasts[0].Temperature.Maximum.Value")+0.5)
Fnum0=o.IQUERY(".DailyForecasts[0].Day.Icon")
Fstr0$=o.SQUERY$(".DailyForecasts[0].Day.IconPhrase")
Min1=int(o.FQUERY#(".DailyForecasts[1].Temperature.Minimum.Value")+0.5)
Max1=int(o.FQUERY#(".DailyForecasts[1].Temperature.Maximum.Value")+0.5)
Fnum1=o.IQUERY(".DailyForecasts[1].Day.Icon")
Fstr1$=o.SQUERY$(".DailyForecasts[1].Day.IconPhrase")

do
  c=coretimer()
  
  setdir "/wav"
  out 6,0
  gosub pwaveb,"todayis1.wav"
  gosub pwaveb,"todayis2.wav"
  gosub pwaveb,"week"+strftime$("%a")+".wav"
  gosub pwaveb,"month"+dec$(val(strftime$("%m")))+".wav"
  gosub pwaveb,"day"+dec$(val(strftime$("%d")))+".wav"
  gosub pwaveb,"forecas1.wav"
  gosub pwaveb,"weath"+dec$(Fnum0)+".wav"
  gosub pwaveb,"temp1.wav"
  gosub pwaveb,dec$(Max0)+"deg.wav"
  gosub pwaveb,"forecas2.wav"
  gosub pwaveb,"weath"+dec$(Fnum1)+".wav"
  gosub pwaveb,"temp3.wav"
  gosub pwaveb,dec$(Min1)+"deg.wav"
  gosub pwaveb,"temp4.wav"
  gosub pwaveb,dec$(Max1)+"deg.wav"
  out 6,1
  
  do until 60000000<coretimer()-c : idle :loop
loop

label pwaveb
  print args$(1);
  PLAYWAVE args$(1)
  print " ... ";
  do while playwave(0)
    idle
  loop
  print "done"
return

天気予報は、AccuWeather から得ています。上のコードの URL の所で「[AccuWeather API key]」は、私の個人用のAPIキーです。AccuWeatherは、登録すれば無料で使えますので、必要ならば登録して API key を取得してください。また「332097」は、私が住んでいる町(カリフォルニア・デービス)の番号です。これを他の番号に変えれば、別の町の情報を得ることができます。

上のコードとほぼ同じものを、GitHubレポジトリーに上げましたので、参考にしてください(ENGLISH.BASがそれ)。

https://github.com/kmorimatsu/machikania-basic/tree/main/weather

URLは、"http://www.rad51.net/projects/weather/tokyo.php"としています。これを使用する分には、AccuWeatherのアカウントは必要ありません。ただし、東京限定です(osaka.phpも使えます)。

GitHubには、「TOKYO.BAS」「OSAKA.BAS」の2つのプログラムも載せてあります。こちらは、日本語で今日の日付・曜日・天気予報を喋るものです。それぞれ、東京・大阪の天気予報バージョンです。

JSONクラスについて

このプロジェクトでは、WGET クラス以外に JSON クラスを用いています。JSON クラスも、WGET と同様に、ver 1.3 でライブラリーに追加しました。JSON 文字列の中から、目的のものを抽出するのに便利です。詳しい使い方は、help.txtを参照してください。

ここでは、JSON クラスをどのように使っているかを説明します。まず、「o=new(JSON,j$)」で JSON オブジェクトを作成しています。「j$」は、web サイトから得られた JSON 文字列です。

続けて、「o.FQUERY#(".DailyForecasts[0].Temperature.Minimum.Value")」のように使っています。「FQUERY#()」は、浮動小数点実数値を読み込むためのメソッドです。「".DailyForecasts[0].Temperature.Minimum.Value"」の部分で、どの情報を読み出すかを指定しています。この例では、「DailyForecasts」をまず見つけ、これが配列なので「[0]」で配列の一番初めの内容を調べます。続けて「Temperature」「Minimum」「Value」順で追っています。「IQUERY()」「SQUERY$()」も同様で、それぞれ、整数値・文字列の内容を調べて読み込むためのメソッドです。

音声データーについて

発声する音声データーは、実行時にその都度作成するのではなく、予めすべての可能性について発声させたものを WAVE ファイルにして保存してあり、その中から選んで再生しています。英語のデーターは https://ttsreader.com/ から取得して、「wav」ディレクトリーに配置しました。日本語のデーターは https://note.cman.jp/other/voice/ から取得して「wavjp」ディレクトリーに配置してあります。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=981 Sun, 01 Oct 2023 00:28:30 PDT ITEM981_20231001
MachiKania type P ver 1.3 で、http サーバー https://www.rad51.net/blog/mycom/?itemid=980 WiFi 接続及びインターネット接続が出来るようになりました。この記事では、MachiKania を http サーバーとして利用する方法について述べます。

ver 1.3 では WiFi 機能の追加に伴って13種類の新たな命令・関数が追加されていますが、それらを使ってサーバーを構築するのは、骨の折れる作業です。そこで、需要の高い http サーバーを構築するためのクラス、HTTPD を作成しました。

この、HTTPD クラスを用いれば、簡単に http サーバー(www サーバー)を構築することができます。この記事では、HTTPD クラスの使い方について述べます。

サンプルプログラム

ver 1.3 の配布アーカイブには、HTTPDクラス用のサンプルプログラムが付いています。「HDEAMON.BAS」がそれで、以下の内容です。

useclass HTTPD
h=new(HTTPD,80,"/httproot")
print "server started as http://";ifconfig$(0);"/"
do
  h.START()
  system 201,val(h.GETPARAM$("led"))
  print h.LASTURI$()
loop


REM 次の内容を、"index.htm"のファイル名で保存し、
REM "httproot"ディレクトリーに配置する。
REM ただし、各行冒頭の「REM 」は、削除すること。

REM <html><head><title>Test</title>
REM <meta name="viewport" content="width=1, initial-scale=5"></head>
REM <body>
REM <h5 style="text-align:center"><a href="?led=1">ON</a></h5>
REM <h5 style="text-align:center"><a href="?led=0">OFF</a></h5>
REM </body></html>

11行目以下は、コメントです。このコメントの内容に従って、「index.htm」という名のファイルを用意し、「httproot」ディレクトリーを作成してそこにコピーしてください。「HDEAMON.BAS」を実行すると、下のような表示になるはずです。

2023-09-27-hdeamon.jpg

「192.168.137.109」の所は、環境によって異なります。多くの場合、「192.168」から始まる4つの数字になる筈で、http サーバーが走っているローカルLANのIPアドレスです。この場合、「http://192.168.137.109/」に、ブラウザーからアクセスしてみます。PCでもスマートフォンでも構いません。下は、スマートフォンから接続した時の表示です。

2023-09-27-smartphone.jpg

MachiKaniaの画面は、下のようになります。

2023-09-27-hdeamon2.jpg

ここで、スマートフォンの画面で「ON」「OFF」「ON」の順でゆっくり押すと、Raspberry Pi Pico W の LED が、ついたり消えたりするはずです。MachiKania の画面は、以下のようになります。

2023-09-27-hdeamon3.jpg

どうでしょうか。MachiKania 上に http サーバーが構築できて、PCやスマートフォンからアクセスする事で、MahiKaniaに信号を送ることができるのが、分かると思います。

ほぼ同じ操作を動画にしてtwitter.comに上げましたので、興味があればご覧ください。

2023-09-27-movie.png

より複雑な web ページも、構築可能

上で紹介したサーバーで表示されるのは、たった6行からなるシンプルな HTML ですが、より複雑なページや、画像を含むページを表示可能です。

試しに、役者の阿部寛さんのホームページをローカルな環境の MachiKania type P で構築した http サーバー上にコピーさせていただき(外部公開していません)、ブラウザーからアクセスしてみました。動画を、twitter.comに上げてあります。

2023-09-27-abe.png

ファイル一覧とPCへのファイルダウンロード

HTTPD クラスは、ディレクトリー中のファイル一覧表示機能を持っています。例えば、以下の BASIC プログラムを実行すると、MMC/SDカードの一覧が、Apache のファイル一覧に似た形式で表示されます。

useclass HTTPD
h=new(HTTPD,80,"/")
do
  h.START()
loop

ディレクトリー間の移動も可能です。下は、「/LIB/WGET/」ディレクトリーに移動した時の表示です。表示は左から順に、ファイル名・更新日時・バイトサイズ・属性フラグです。

2023-09-27-wgetdir.png

ファイル名をクリックすると、当該ファイルをダウンロードする事も可能です。この機能を使うと、MachiKania 上のファイルを簡単にPCに取り込むことができます。

HTTPD クラスでサーバーを構築する場合、逆に、ディレクトリー一覧を表示させたくないときもあると思います。そういった場合は、該当のディレクトリーに「index.htm」を作成してください。ファイル内容は、空でも「<html></html>」でも、何でも良いです。

他のタイプのサーバーも構築可能

http サーバー以外のサーバーも、理論的には構築可能です。下は、TELNETサーバーを構築した例です。アルファベットの大文字は小文字に、小文字は大文字に変換して表示される仕様です。

TCPSERVER 23,0
print "Server started at port 23"
do
  do
    delayms 10
    c=TCPACCEPT()
  loop until c
  print "Connected"
  TCPSEND("Hello TELNET server!\r\n",-1,c)
  do while TCPSTATUS(0,c)
    for i=1 to 1000
      delayms 1
      if 0=TCPRECEIVE(&b,1,c) then continue
      i=0
      break
    next
    if 0x40<b and b<0x5b then
      b=b+0x20
    elseif 0x60<b and b<0x7b then
      b=b-0x20
    endif
    if i then b=0
    TCPSEND &b,1,c
    if 0x0d=b then
      b=0x0a
      TCPSEND &b,1,c
    endif
  loop
  print "Closed"
loop

実行中の様子の動画は、twitter.comに上げました。

2023-09-27-telnet.png ]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=980 Fri, 29 Sep 2023 19:25:34 PDT ITEM980_20230929
MachiKania type P ver 1.3 で、http クライアント https://www.rad51.net/blog/mycom/?itemid=979 WiFi 接続及びインターネット接続が出来るようになりました。この記事では、MachiKania を http クライアントとして利用する方法について述べます。

ver 1.3 では WiFi 機能の追加に伴って13種類の新たな命令・関数が追加されています。それらを使えば様々なインターネット接続(クライアント・サーバー)を行うことができますが、非常に複雑な手続きが必要です。そこで、インターネットの接続で最もよく使う、http プロトコルに関して、クラスライブラリーを用意しました。

ここでは、新規に追加されたクラスのうち、WGET クラスについて説明します。http クライアントを簡易に構築するためのクラスです。

最も簡単な使用方法

WGETクラスは、オブジェクトを作成せずに、スタティックメソッド呼び出しで使います(help.txtを参照)。多くの方が一番よく使うのは、おそらく「WGET::FORSTRING$()」です。以下の例は、もっとも簡単なサンプルプログラムです。

useclass WGET
t$=WGET::FORSTRING$("http://www.rad51.net/projects/typep/")
print t$

Webページにアクセスして、その内容を表示するものです。上のコードを実行すると、結果は以下の例のようになるはずです。
2023-09-24-wget.jpg
「<html>」から「</html>」が、指定のURLから取得した内容です。

多くの場合、「WGET::FORSTRING$()」を使うのが、確実で簡単な方法でしょう。得る情報がテキストなら(HTML, JSON, RSSなど)、この方法で簡単に得ることができます。

バイナリーファイルのダウンロード

「WGET::FORSTRING$()」では、ヌル文字(\0)を含むデーター、例えば画像ファイルの取り込みが出来ません。そういったデーターをインターネットからダウンロードしてくるには、「WGET::FORFILE()」もしくは「WGET::FORBUFFER()」を使います。下は、「WGET::FORFILE()」を使って、TIFFファイルをダウンロードしてファイルとして保存し、表示する例です(TIFFファイルは、16色もしくは256色の、圧縮無しのものに対応)。

useclass WGET,CSWTIF
WGET::FORFILE("temp.tif","http://www.rad51.net/projects/typep/image.tif")
i=new(CSWTIF,"temp.tif")
point 0,200
i.SHOW()

実行結果は、以下の例のようになるはずです。
2023-09-26-wget_forfile.jpg

「WGET::FORBUFFER()」を使う場合は、少し複雑ですが、以下のように書きます。実行結果は、上と同じです。下のコードの「b,4800」で、「b」はバッファーアドレス、「4800」はバッファーの有効バイト数です(ここで使用したTIFFファイルは、4770バイトです)。

useclass WGET,CSWTIF
dim b(1199)
s=WGET::FORBUFFER(b,4800,"http://www.rad51.net/projects/typep/image.tif")
fopen "temp.tif","w"
fput b,s
fclose
i=new(CSWTIF,"temp.tif")
point 0,200
i.SHOW()

セキュアーコネクション(https)も可能

httpプロトコルをセキュアーコネクションで行いたい場合(http ではなく、https)も、WGETを使えます。使い方は同じで、URLに"https://"と書くだけです。

ただし、ドキュメントの wifi.txt にも書きましたが、MachiKania で https サイトにアクセスした場合、通常のブラウザーによる https サイトへのアクセスに比べて、セキュリティーレベルが低いです。MachiKania から https サイトへのアクセスでは、パスワードや個人情報などを送付しないようにしてください。こちらから送付する情報なしでデーターを取得するだけなら、何も問題にする必要はありません。

WGETクラスの利用例

WGETクラスを利用して、天気予報をインターネットから得て知らせてくれる箱を作りました。詳しくは、別記事で説明します
2023-09-26-weatherBox.jpg]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=979 Fri, 29 Sep 2023 19:25:20 PDT ITEM979_20230929
MachiKania type P ver 1.3 で、ネット接続 https://www.rad51.net/blog/mycom/?itemid=978
公式ページはこちら
GitHubリリースページはこちら

ReadMeに記載した更新履歴は、次の通りです。
・Raspberry Pi Pico W を用いた WiFi 接続に対応。次の命令・関数を追加: 
 DNS$(), IFCONFIG$(), NTP, TCPACCEPT(), TCPCLIENT, TCPCLOSE, TCPRECEIVE, 
 TCPSEND, TCPSERVER, TCPSTATUS, TLSCLIENT, WIFIERR(), WIFIERR$()
・GCOLOR()関数の不具合を修正
・一部USBキーボードでのキー入力不具合に対応
・EOFの時、FGETC()関数が-1を返すようにした
・embed用にXIAO RP2040, RP2040-Zero, and Tiny-2040に対応
・SPIの対応ポートをINIファイルで指定出来るようにした
・SERIALステートメントの第3引数を省略した時の不具合を修正
・例外をトラップして画面表示するようにした
・CORETIMERが電源投入後およそ2000秒後から不具合を起こす事を修正
・ILI9488に対応
・RTC(Real Time Clock)をサポート。次の命令・関数を追加: 
 GETTIME$(), SETTIME. STRFTIME$()
・ファイル保存時の日時設定をサポート
・NTPサーバーによるRTCのセットをサポート
・SYSTEM 201 呼び出しにより、ボード付属のLEDのオン・オフを出来るようにした
・メモリーアロケーションの不具合を修正
・FREMOVE/SETDIR等のファイル関連命令を使用時の、ガベージコレクション不具合を修正
・WAVEプレーヤーの安定性を改善
・クラスのスタティックメソッド呼び出し不具合を修正
・FFINGD$(), FINFO(), FINFO$()の3つの関数を追加。ファイル一覧の作成が可能に
・REM 文に「"」を含む際のコンパイル時の不具合を修正


WiFi 接続機能

ver 1.3 で追加された目玉機能は、WiFi 接続です。WiFi 対応の Raspberry Pi Pico W で MachiKania を利用する事により、インターネットに接続して情報を得たり、イントラネットでサーバーを構築して他の機器と接続したりすることができるようになりました。まずは、ドキュメントのwifi.txtをお読みください。

WiFi接続用のBASIC命令群が多数追加されています。ただし、これらを直接利用してネット接続するコードを書くのは骨が折れるので、ネット接続を容易に行えるクラスを用意しました。

・WGET クラス。インターネットのhttp、httpsサイトから情報を得ることができる。
・HTTPDクラス。http サーバーを構築することができる。

これらに関しては、別途記事を書きましたので、そちらを参照してください(WGETの記事はこちらHTTPDの記事はこちら)。

WiFi機能を使用する場合は、次の点に注意して下さい。

1.Raspberry Pi Pico Wを使用する(Raspberry Pi Picoでは不可)。
2.Raspberry Pi Pico W用のuf2ファイル(pico_w_ili9341/phyllosoma.uf2等)をロードする。
3.MACHIKAP.INIで、WiFi を使うように設定する(「USEWIFI」を有効にする)。
4.MACHIKAP.INIでWiFi接続用のSSIDとパスワードを指定する(「WIFISSID=」及び「WIFIPASSWD=」)。
5.MACHIKAP.INIで、国情報を設定する(日本の場合は、「WIFICOUNTRY=JP」)
6.リアルタイムクロックを利用する場合(下記参照)は、MACHIKAP.INIで「INITIALNTP」を有効にする。

なお、5.のWIFICOUNTRYは、cyw43のソースコード(cyg43-driver/src/syw43_country.h)の60行目辺りからを参考にしてください。

設定がうまく行けば、起動時に次のような表示になります。ただし、「192.168.1.156」と「macserver」の部分は、環境によって異なります。
2023-09-23-MachiKaniaWiFi.jpg
このような表示が確認できれば、MachiKaniaでWiFiを使う準備が整いました。

リアルタイムクロック

リアルタイムクロック(Real Time Clock; RTC)が使えるようになりました。現在時刻は、プログラム中で指定する事も、ネット上のNTPサーバーから取得して設定する事も出来ます。また、ファイル保存時に、作成時刻・日時を設定する事が出来るようになりました。

NTPサーバーを利用して現在時刻を取得する方法で、リアルタイムクロックを使用する場合は、次の点に注意してください。

1.Raspberry Pi Pico Wを使う。
2.Pi Pico W 用のuf2ファイルをロードする。
3.MACHIKAP.INIで、WiFi を使うように設定する(「USEWIFI」を有効にする)
4.MACHIKAP.INIで、タイムゾーンを設定する(日本なら、TIMEZONE=9)
5.MACHIKAP.INIで、起動時にNTPサーバーに接続する様に設定する(「INITIALNTP」を有効にする)

RTCを扱う命令・関数として、GETTIME$(), SETTIME, STRFTIME$() の3つを用意しました。これらの使い方の詳細は、help.txtを参照してください。なお、一連の命令・関数では、日付・時刻を扱うために、ISO-8601 形式の文字列を使います。 ISO-8601 文字列は、次の例のような書式です(日付と時刻の間に「T」が挟まれています)。

2023-09-01T13:00:00(2023年9月1日午後1時0分0秒の場合)

XIAO RP2040, RP2040-Zero, Tiny-2040などの、小型RP2040ボードに対応

Ver 1.2までは、Raspberry Pi Picoや、ピンに互換性のあるYD-RP2040などが対象でしたが、Ver 1.3からは、XIAO RP2040, RP2040-Zero, Tiny-2040といった、ピン数の少ない小型互換ボードでも使えるようになりました。ただし、ピン数がRaspberry Pi Picoより少ないため、組込み機能(embed)での対応です。

RP2040-Zero, Tiny-2040で使う場合、デフォルトではSPI用のポートが取れないので、MACHIKAP.INIでSPI用のポートを設定できるようにしました。多くの場合、以下のように設定すれば使えるようになります。
SPIMISO=4
SPIMOSI=7
SPICLK=6
このように設定すれば、MISOがGP4で、MOSIがGP7で、CLKがGP6で使えるようになります。その他の使い方は、Ver1.2と同じです。上記のように設定したMACHIKAP.INI以外にBASICプログラムを含むMACHIKAP.BASを用意して、convert.phpもしくはconvert_kb.phpを実行してください。

Seeed XIAO RP2040の場合、GP5が使えないため、専用のuf2ファイルを用意しました。machikap-p2-130-RC3.zipに含まれている「xiao_embed」ディレクトリーのものを使用してください。なお、I/Oの割り当ては、下の通りです。

・GP0 I/O bit0 / UART TX / PWM3
・GP1 I/O bit1 / UART RX / SPI CS / PWM2
・GP2 I/O bit2 / SPI SCK / PWM1
・GP3 I/O bit3 / SPI MOSI
・GP4 I/O bit4 / SPI MISO
・GP6 I/O bit6 / I2C SDA
・GP7 I/O bit7 / I2C SCL

ILI9488液晶に対応

ILI9341の2倍の大きさの、ILI9488に対応しました。キャラクター表示の場合60x40文字、グラフィック表示の場合480x320ピクセルの表示が可能です。machikap-p2-130-RC3.zipに含まれている「pico_ili9488」ディレクトリーもしくは「pico_w_ili9488」のものを使用してください。それぞれ、Raspberry Pi Pico用と、Raspberry Pi Pico W用(WiFi用)です。

その他

その他、バグ修正と、色々追加機能があります。

CPUが例外を起こした場合、例外原因などを画面に表示するようにしました。何が不具合が起きた時の原因を調べやすくなりました。

Raspberry Pi PicoとRaspberry Pi Pico Wのボード搭載LEDの制御が、SYSTEMステートメントで行えるようになりました。「SYSTEM 201,1」でオン、「SYSTEM 201,0」でオフです。

MMC/SDカードに存在するファイルの一覧を、BASICプログラム中で得ることができるようになりました。FFINGD$(), FINFO(), FINFO$()の3つの関数を追加しています。使用方法は、help.txtを参照してください。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=978 Fri, 29 Sep 2023 19:24:59 PDT ITEM978_20230929
MachiKania type Pで、BASICコードからCで書かれたコードを呼び出す、その2 https://www.rad51.net/blog/mycom/?itemid=977 ひとつ前の記事では、CプロジェクトをHEXファイルに変換し、そこから必要なC関数を呼び出す方法について述べた。この記事では、もう一つの方法について述べる。

HEXファイルに変換する方法においては、複雑なCでのコーディングが必要な多くの事例に対応できる。一つの例として、正規表現エンジンを実装するMachiKaniaクラス(REGEXP クラス)の実装について述べた。

この記事で述べる方法では、Cのプロジェクトから必要なコードを抜き取って BASIC コードに変換してプログラムに埋め込む方法を取る。HEXを介する方法と比べた長所は、以下の通り。

1.一つの BASIC ファイルの中に C コードを埋め込むことができる
2.HEX を介した方法では HEX コードのメモリ上での配置位置を考慮する必要があったが、この方法ではその必要が無い
3.C プログラムの中から必要なものだけを抜き取って BASIC プログラムに埋め込むので、メモリー占有領域を最小限にできる


他方、短所は以下の通り

1.複雑な C プログラムでは対応できない場合がある

従って、それほど大きくない C のプログラムの場合はこの記事で述べる方法が有利である。後に述べる「c_convert.php」スクリプトの実行でエラーが出る、あるいは、作成されたBASIC プログラムが意図したように動作しない場合は、HEXを介する方法に移行すればよい。

BASIC に C コードを埋め込む例(hcw1アプリケーション)

先の記事と同様、次のような C 関数を BASIC から呼び出す例について述べる。
int add_values(int a, int b){
	return a+b;
}

この例を説明するために、GitHubレポジトリーを作成したので、参照していただきたい。Git Cloneした後に「hcw1」ブランチにスイッチし、Commit Log を見ていただければ、説明が分かりやすいと思う。
2023-03-18-log.png
また、この記事では、1から5までの手順ごとに該当レポジトリーへのリンクを付けたので、そちらも見ていただきたい。

1.まずは、Hello, World! から
まず、Cのプロジェクトを一つ作成する必要がある。何でも良いのだが、ここではpico-examplesからhello_usb.cを選んで、若干変更した物から始める事とする。これは、ビルドした後にPi Picoにインストールすれば、USB シリアル接続を通して、コンソール上に「Hello, World!」と表示し続けるプログラムだ(前の記事と同じ)。
#include <stdio.h>
#include "pico/stdlib.h"

int main() {
	stdio_init_all();
	while (true) {
		printf("Hello, world!\n");
		sleep_ms(1000);
	}
	return 0;
}
このプロジェクトをcmake/makeでビルドすると、hello_cw.uf2に加えてhello_cw.hexが作成されることが分かる。このようにして作成されたhexファイルを用いることになる。

2.目的のコードを、プロジェクト内に記述する
Cアプリケーションを記述してテストする環境が整ったので、ここで目的のコードを書いてみる。なお、ひとつ前の記事の方法とは異なり、この記事の方法では、プログラムはRAM上ではなくフラッシュ上に構築する方法を取る。上で述べたadd_values()関数を追加して、テスト結果を表示するようなものにした。
#include <stdio.h>
#include "pico/stdlib.h"

int add_values(int a, int b){
	return a+b;
}

int main() {
	int a=0,b=0;
	stdio_init_all();
	while (true) {
		printf("%d + %d = %d\n", a, b, add_values(a,b));
		a+=1;
		b+=2;
		sleep_ms(1000);
	}
	return 0;
}

3.C コンパイラーの最適化を無効にする
ARM gcc コンパイラーの最適化を無効にするため、CMakeFiles.txtに次の記述を追加している。
add_definitions(-O0)

ひとつ前の記事でも述べたが、この記事で述べる方法でも、C のコードを埋め込もうとする場合、以下の点に注意が必要だ。

a.呼び出そうとするC関数が、必ずビルドオブジェクトに含まれるようにする
b.呼び出そうとするC関数の引数は、4つまで
c.呼び出そうとするC関数の引数の取り扱いに関して、ビルドの際の最適化で標準のARMレジスター使用(R0, R1, R2, R3を使用する)から変更されないようにする


a.の対策のためには、必要な関数がすべて、「main()」関数、もしくはそこから呼び出される関数の中で、最低一度は呼び出される必要がある。でないと、リンクの際に不必要な関数コードとして、削除されてしまう。

また、Cコンパイラー(gcc)が行う最適化のために、関数がインライン展開されてしまう事もあり、そうなると外部から呼び出すことができなくなってしまう。これを防ぐ方法にはさまざまあり、1:目的の関数を「main.c」とは別のファイル内に記述する、2:「__declspec(noinline)」アトリビュートを使う、3:最適化を行わない、などがある。

b.は ARM gcc コンパイラーの規約に関係するもので、これを遵守しないと(引数を5つ以上にしてしまうと)、正常に動作しない。

c.の対策は色々と複雑で、同一のCファイル内で目的の関数を呼び出している場合に変なレジスター使用が起こるようだ。最適化の一つなので、当然ながら最適化を行わないようにすることで回避することができる。

以上の事から、トラブルを防ぐにはgccの最適化を停止することが有効である。CMakeLists.txtに「add_definitions(-O0)」の一行を加えたのは、そのためである。特殊な作例で、実行速度が最大でないといけないようなケースにはこの方法は使えないが、そうでなければ、最適化を停止して使用するのが無難だろう。

4.PHPスクリプトを配置する
作成されたHEXファイルを呼び出すBASICプログラムを自動作成するためのスクリプト「c_convert.php」を用意した。このスクリプトは、PHPで記述されているので、PHPがない場合はインストールが必要である。このPHPスクリプトは汎用であるが、冒頭の記述(13-34行目辺り)を若干編集して使用する。今回の例では、次のようになっている。
class configclass{
	// File names
	public $dis_file='./build/hello_cw.dis';
	public $map_file='./build/hello_cw.elf.map';
	public $hex_file='./build/hello_cw.hex';
	//public $debug_file='./machikap/machikap.bas';
	
	// Functions to be exported
	public $functions=array(
//		'machikania_init',
		'add_values',
	);
	
	// Additional .rodata to be used (function names are excluded)
	public $rodata=array(
	);
	
	// Excluded addresses as .rodata and RAM
	public $excluded=array(
		0x20040000,
	);
};
$dis_file, $map_file, $hex_fileでは、ビルドの際に作成された「*.dis」「*.map」「*.hex」の3つのファイルの位置を指定する。$debug_fileはオプションで、PC-Connect機能を利用してデバッグを行っている際の、BASICファイルの位置を指定する。必要が無い場合は、「//」でコメントアウトしておく。また、$functionsには、BASICから呼び出したいCの関数名を列挙しておく。$rodataには、自動認識されないが必要な部品名を文字列で指定したリストを指定する。逆に、$excludedには必要のない部品の物理アドレスのリストを指定する。通常は、$rodataと$excludedの設定は変更の必要は無いはずだ。

5.Cプログラムのビルドと、PHPスクリプトの実行
ここまで準備できれば、Cプログラムをビルドした後に、PHPスクリプトを実行する。「result.txt」と「log.txt」の二つのファイルが出来ているはずだ。ここでの例のように進めると、「result.txt」の内容は次のようになる。
USEVAR C_RAM
GOSUB INIT_C
END

LABEL INIT_C
  DIM C_RAM(0)
  REM ram vectors
  REM rodata vectors
  REM ram function vectors
  REM callback function vectors
RETURN

ALIGN4
LABEL C_ADD_VALUES
  EXEC $68f0,$6931,$6972,$69b3,$f000,$f802,$bd00,$46c0

REM 28 bytes
LABEL C_FUNCTIONS
EXEC $b580,$b082,$af00,$6078,$6039,$687a,$683b,$18d3,$0018,$46bd,$b002,$bd80,$b580,$b082

REM 0 bytes
LABEL C_RODATA
このBASICプログラムは、C コードを埋め込んで呼び出しできるようにした、必要最小限の構成になっている。目的のコードを、3行目の「gosub INIT_C」と4行目の「end」の間に書けばよい。例えば、次のように変更して、BASICプログラムを完成させてみよう。
USEVAR C_RAM
GOSUB INIT_C

for i=1 to 10
  print a,b,a+b,gosub(C_ADD_VALUES,a,b)
  a=a+1
  b=b+2
next

END

LABEL INIT_C
  DIM C_RAM(0)
  REM ram vectors
  REM rodata vectors
  REM ram function vectors
  REM callback function vectors
RETURN

ALIGN4
LABEL C_ADD_VALUES
  EXEC $68f0,$6931,$6972,$69b3,$f000,$f802,$bd00,$46c0

REM 28 bytes
LABEL C_FUNCTIONS
EXEC $b580,$b082,$af00,$6078,$6039,$687a,$683b,$18d3,$0018,$46bd,$b002,$bd80,$b580,$b082

REM 0 bytes
LABEL C_RODATA
あとは、このBASICプログラムをMMC/SDカードにコピーすれば、実行することができる。実行時のスナップショットは、以下の通り。
2023-03-18-20230318_205201.png

以上が、簡単なCコードをBASICプログラムに埋め込んで呼び出すための手順である。

エラーが出た場合

「c_convert.php」は、ひとつ前の記事で述べた「c_convert2.php」と比べて少し複雑なアルゴリズムを用いていて、C のコードから必要部分を抜き出して BASIC に埋め込む動作をしている。残念ながら、複雑な構造の C コードに関しては、解析がうまく行かず、PHPスクリプトの実行中にエラーになったり、完成した BASIC プログラムが正常に動作しない事が起きうる。そういう場合は、ひとつ前の記事で述べた HEX ファイルを作成する方法の方が対応できる範囲が広いので、そちらを試していただきたい。

どんどん C コードを取り込もう

ひとつ前の記事では、複雑な C プログラムの MachiKania BASIC への取り込みについて述べたが、手続きが複雑であった。簡単な C プログラムならこの記事で書いた方法でより簡便に取り込める。それにより、MachiKania の応用範囲がさらに広くなることを、期待している。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=977 Sun, 26 Mar 2023 10:45:14 PDT ITEM977_20230326
MachiKania type Pで、BASICコードからCで書かれたコードを呼び出す https://www.rad51.net/blog/mycom/?itemid=976
方法は大きく分けて二通りあって、一つは RAM 上に HEX アプリケーションを読み込んでそこに含まれる機能を呼び出す方法である。RAM 上にアプリケーションを配置して HEX ファイルを作成する方法は、別の記事で紹介した。この記事では、作成したHEXファイル中にある C で関数をどのようにして呼び出すかについて述べる。この手法を用いて HELLO_CW アプリケーションREGEXP クラスを作成したので、それを例に挙げながら説明する。

もう一つは、C でビルドしたオブジェクトから、必要な機能だけをピックアップして、BASIC の EXEC ステートメントに変換して埋め込む方法である。簡単な C のコードを実行させる場合には、この方法が簡便でサイズもコンパクトにできるが、これについては、別の記事で取り上げることにする。

この記事では HEX アプリケーションを読み込んでそこに含まれる機能を呼び出す方法について述べたい。複雑な C のコードを呼び出すのに向いた方法である。

BASIC からHEX アプリケーションを呼び出す例(hello_cwアプリケーション)

もっとも簡単な例として、2つの整数値の和を返す関数をCで次のように記述して、この関数を呼び出す方法について説明する。
int add_values(int a, int b){
	return a+b;
}

この例を説明するために、GitHubレポジトリーを作成したので、参照していただきたい。Git CloneしてCommit Logを見ていただければ、説明が分かりやすいと思う。
2023-03-17-log.png
また、この記事では、1から8までの手順ごとに該当レポジトリーへのリンクを付けたので、そちらも見ていただきたい。

1.まずは、Hello, World! から
まず、Cのプロジェクトを一つ作成する必要がある。何でも良いのだが、ここではpico-examplesからhello_usb.cを選んで、若干変更した物から始める事とする。これは、ビルドした後にPi Picoにインストールすれば、USB シリアル接続を通して、コンソール上に「Hello, World!」と表示し続けるプログラムだ。
#include <stdio.h>
#include "pico/stdlib.h"

int main() {
	stdio_init_all();
	while (true) {
		printf("Hello, world!\n");
		sleep_ms(1000);
	}
	return 0;
}
このプロジェクトをcmake/makeでビルドすると、hello_cw.uf2に加えてhello_cw.hexが作成されることが分かる。このようにして作成されたhexファイルを用いることになる。

2.RAM上のアプリケーションに変更する
このHello, World!アプリケーションは、hello_cw.uf2をRPI-RP2ドライブにコピーすると、フラッシュ上にプログラムが構築され、電源を切ったりリセットボタンを押したりしても、同じプログラムが実行される。しかし、今回必要なCプログラムは、フラッシュ上に構築されるものではなく、RAM上に実行コードが構築されるタイプの物である。このための変更を行う。この方法については、別に記事を書いてあるので、詳細はそちらを参照していただきたい。この変更を施すと、hello_cw.uf2をRPI-RP2ドライブにコピーした直後は目的のプログラムが実行されるが、リセットボタンを押すと、元の(フラッシュにインストールされていた)プログラムに戻ることが分かる。

3.目的のコードを、プロジェクト内に記述する
Cアプリケーションを記述してテストする環境が整ったので、ここで目的のコードを書いてみる。上で述べたadd_values()関数を追加して、テスト結果を表示するようなものにした。
#include <stdio.h>
#include "pico/stdlib.h"

int add_values(int a, int b){
	return a+b;
}

int main() {
	int a=0,b=0;
	stdio_init_all();
	while (true) {
		printf("%d + %d = %d\n", a, b, add_values(a,b));
		a+=1;
		b+=2;
		sleep_ms(1000);
	}
	return 0;
}

4.RAM格納アドレスを変更する
今のままでは、作成されたCアプリケーションが、0x20000000から配置され、これはMachiKania BASICの実行コード配置位置と重なってしまう。そこで、これらが重ならないように、配置されるRAMアドレスを修正しなければならない。0x20000000から0x2002FFFFまでがMachiKania BASICのコード格納領域なので、始めの方のアドレスをBASICコード用に少し取っておいて、その少し後ぐらいに格納すればよい。ここでは、0x20010000からの64K bytesを使う事とする。「memmap_no_flash.ld」の26行目を、次のように書き換える。
RAM(rwx) : ORIGIN =  0x20010000, LENGTH = 64k

5.MachiKaniaライブラリーを取り込む
ここで、アプリケーションに、MachiKania BASICと連携するためのライブラリーを取り込む。
2023-03-17-include.png
「machikania.c」と「machikania.h」を追加した。これらのファイルはhello_cwプロジェクトに特化したものではなく、共通の物なので、他のケースでもここからコピーして使えるはずである。また、「hello_usb.c」を編集して、以下のような内容にした。
#include <stdio.h>
#include "pico/stdlib.h"
#include "machikania.h"

int add_values(int a, int b){
	return a+b;
}

int main() {
	int a=0,b=0;
	stdio_init_all();
	machikania_init();
	while (true) {
		printf("%d + %d = %d\n", a, b, add_values(a,b));
		a+=1;
		b+=2;
		sleep_ms(1000);
	}
	return 0;
}
「#include "machikania.h"」と、「machikania_init();」の2行を加えてある。また、「CMakeFiles.txt」は、「machikania.c」をビルドの対象に加えるようにするだけでなく、12行目に以下の行を追加している。
add_definitions(-O0)
この設定項目の追加の意味については、次の段落で述べる。

この記事で述べる方法で、MachiKaniaからHEXファイル内のコードを呼び出そうとする場合、以下の点に注意が必要だ。

a.呼び出そうとするC関数が、必ずHEXオブジェクトに含まれるようにする
b.呼び出そうとするC関数の引数は、4つまで
c.呼び出そうとするC関数の引数の取り扱いに関して、ビルドの際の最適化で標準のARMレジスター使用(R0, R1, R2, R3を使用する)から変更されないようにする


a.の対策のためには、必要な関数がすべて、「main()」関数、もしくはそこから呼び出される関数の中で、最低一度は呼び出される必要がある。でないと、リンクの際に不必要な関数コードとして、削除されてしまう。

また、Cコンパイラー(gcc)が行う最適化のために、関数がインライン展開されてしまう事もあり、そうなると外部から呼び出すことができなくなってしまう。これを防ぐ方法にはさまざまあり、1:目的の関数を「main.c」とは別のファイル内に記述する、2:「__declspec(noinline)」アトリビュートを使う、3:最適化を行わない、などがある。

b.は ARM gcc コンパイラーの規約に関係するもので、これを遵守しないと(引数を5つ以上にしてしまうと)、正常に動作しない。

c.の対策は色々と複雑で、同一のCファイル内で目的の関数を呼び出している場合に変なレジスター使用が起こるようだ。最適化の一つなので、当然ながら最適化を行わないようにすることで回避することができる。

以上の事から、トラブルを防ぐにはgccの最適化を停止することが有効である。CMakeLists.txtに「add_definitions(-O0)」の一行を加えたのは、そのためである。特殊な作例で、実行速度が最大でないといけないようなケースにはこの方法は使えないが、そうでなければ、最適化を停止して使用するのが無難だろう。

6.PHPスクリプトを配置する
作成されたHEXファイルを呼び出すBASICプログラムを自動作成するためのスクリプト「c_convert2.php」を用意した。このスクリプトは、PHPで記述されているので、PHPがない場合はインストールが必要である。このPHPスクリプトは汎用であるが、冒頭の記述(13-26行目辺り)を若干編集して使用する。今回の例では、次のようになっている。
class configclass{
	// File names
	public $dis_file='./build/hello_cw.dis';
	public $map_file='./build/hello_cw.elf.map';
	public $hex_file='./build/hello_cw.hex';
	//public $debug_file='./machikap/machikap.bas';
	//public $debug_hex='./machikap/hello_cw.hex';
	
	// Functions to be exported
	public $functions=array(
		'machikania_init',
		'add_values',
	);
};
$dis_file, $map_file, $hex_fileでは、ビルドの際に作成された「*.dis」「*.map」「*.hex」の3つのファイルの位置を指定する。$debug_file, $debug_hexはオプションで、PC-Connect機能を利用してデバッグを行っている際の、BASICファイルとHEXファイルの位置を指定する。必要が無い場合は、「//」でコメントアウトしておく。また、$functionsには、BASICから呼び出したいCの関数名を列挙しておく。

7.不必要なUSB機能を削除する
Pi PicoのUSBシリアル機能は、アプリケーション作成時やデバッグ時には便利であるが、完成したHEXファイルには必要が無い機能である。USBシリアル機能のためには大きなプログラム領域が必要なので、これを削除することで、HEXファイル及び占有RAM領域を小さくすることができる。USBシリアル機能を削除するためには、CMakeLists.txtの26行目を、次のようにすればよい。
pico_enable_stdio_usb(hello_cw 0)

8.Cプログラムのビルドと、PHPスクリプトの実行
ここまで準備できれば、Cプログラムをビルドした後に、PHPスクリプトを実行する。「result.txt」と「log.txt」の二つのファイルが出来ているはずだ。ここでの例のように進めると、「result.txt」の内容は次のようになる。
useclass CLDHEX
usevar C_CODE
gosub INIT_C
end

label INIT_C
  var A,V
  REM Load the main code
  A=$20010000
  C_CODE=new(CLDHEX,"HELLO_CW.HEX",A,65536)
  REM data_cpy_table
  REM Link functions
  V=(A+1168-DATAADDRESS(C_MACHIKANIA_INIT)-12)>>1
  poke16 DATAADDRESS(C_MACHIKANIA_INIT)+8,$f000+(V>>11)
  poke16 DATAADDRESS(C_MACHIKANIA_INIT)+10,$f800+(V and $7ff)
  V=(A+1068-DATAADDRESS(C_ADD_VALUES)-12)>>1
  poke16 DATAADDRESS(C_ADD_VALUES)+8,$f000+(V>>11)
  poke16 DATAADDRESS(C_ADD_VALUES)+10,$f800+(V and $7ff)
  REM Initialize C global variables
  gosub C_MACHIKANIA_INIT
return

label C_MACHIKANIA_INIT
  exec $68f0,$6931,$6972,$69b3,$f000,$f800,$bd00
label C_ADD_VALUES
  exec $68f0,$6931,$6972,$69b3,$f000,$f800,$bd00
このBASICプログラムは、カレントディレクトリーにあるHEXファイル(HELLO_CW.HEX)を取り込み、Cプログラム中の「machikania_init();」を呼び出すだけの、必要最小限の構成になっている。目的のコードを、3行目の「gosub INIT_C」と4行目の「end」の間に書けばよい。例えば、次のように変更して、BASICプログラムを完成させてみよう。
useclass CLDHEX
usevar C_CODE
gosub INIT_C

for i=1 to 10
  print a,b,a+b,gosub(C_ADD_VALUES,a,b)
  a=a+1
  b=b+2
next

end

label INIT_C
  var A,V
  REM Load the main code
  A=$20010000
  C_CODE=new(CLDHEX,"HELLO_CW.HEX",A,65536)
  REM data_cpy_table
  REM Link functions
  V=(A+1168-DATAADDRESS(C_MACHIKANIA_INIT)-12)>>1
  poke16 DATAADDRESS(C_MACHIKANIA_INIT)+8,$f000+(V>>11)
  poke16 DATAADDRESS(C_MACHIKANIA_INIT)+10,$f800+(V and $7ff)
  V=(A+1068-DATAADDRESS(C_ADD_VALUES)-12)>>1
  poke16 DATAADDRESS(C_ADD_VALUES)+8,$f000+(V>>11)
  poke16 DATAADDRESS(C_ADD_VALUES)+10,$f800+(V and $7ff)
  REM Initialize C global variables
  gosub C_MACHIKANIA_INIT
return

label C_MACHIKANIA_INIT
  exec $68f0,$6931,$6972,$69b3,$f000,$f800,$bd00
label C_ADD_VALUES
  exec $68f0,$6931,$6972,$69b3,$f000,$f800,$bd00
あとは、このBASICプログラムとHELLO_CW.HEXをMMC/SDカードにコピーすれば、実行することができる。実行時のスナップショットは、以下の通り。
2023-03-18-20230318_012739.png

以上が、簡単なCコードをHEXに変換して、MachiKania BASICプログラムから呼び出すための手順である。

応用編:REGEXPクラスでの使用例

HEX アプリケーションを利用する方法について、応用例について取り上げる。また、ここでは動作のメカニズムに関しても少し説明する。REGEXP クラスを見ていただきたい。上で述べたHELLO_CWプログラムはCのコードを実行するための最小限の構成であるが、REGEXPクラスでは、次のように発展させてある。

・RAM配置アドレスの異なる複数のHEXファイルを作成し、メモリーの空きを見つけて適切なHEXプログラムをロードする
・複数の*.cファイルにまたがる、少し規模の大きいプログラムである
・mallocを使用している
・RAM占有領域を、必要最小限の大きさ(32 kb)に制限している


このクラスの構造がどうなっているか、まず説明しよう。REGEXP ディレクトリーには、以下のファイル・ディレクトリーが存在する。

2023-01-30-dir.png

help.txtは説明書きなので、ここでは取り上げない。「regexp.bas」以外に「hex」ディレクトリーと「c」ディレクトリーがある。「hex」ディレクトリーに含まれるファイルは、以下の通り。

2023-01-30-hexdir.png

ここには、7つの HEX ファイルがあり、それぞれでRAM上の配置アドレスが異なる。「c」ディレクトリーに含まれるファイルは、以下の通り。

2023-01-30-cdir.png

ここには、「c_convert2.php」という PHP スクリプトと、C のソースコードを含む「src」ディレクトリーがある。

まずは、regexp.bas の中身から見てみよう。ソースコードは、こちらで閲覧していただきたい。なお、ここではc_convert2.phpで自動作成されるコードについてのみ説明し、REGEXPクラスが扱う正規表現エンジンに関するコードの説明は割愛する。

まず冒頭の6行目:
useclass CLDHEX
CDLHEXクラスを読み込んでいる。このクラスは、HEX ファイルを読み込んで、RAM に構築する役割がある。なお、ここで作成した HEX ファイルは、前の記事で説明したように作成されたもので、アプリケーションはフラッシュ上でなく、RAM上に構築される。上記「HEX」ディレクトリーにあるものがそれで、REGEXPクラスでは7つある中から適応するもの(なるだけ、格納アドレスが若い物)を選んで読み込むようにしてある。

次に見ていただきたいのが、111行目の
label INIT_C
以降のコードである。ここは、REGEXP クラスの実行時の初めに呼ばれる部分で、C で書かれたコードを BASIC から呼び出すための前準備をしている。まず、
A=gosub(INIT_C_LDHEX)
でHEXファイルをロードして、その後に複数の「POKE16」ステートメントを実行している。これらは、「C_PRECOMP」「C_REGCOMP」等のサブルーチン呼び出しで、HEXファイル中のどのアドレスを呼び出すかを、設定するための物である。

136行目の「label C_MACHIKANIA_INIT」以下のコードを見ていただきたい。EXEC ステートメントが並んでいる。これらの機械語は、次のアセンブリーコードである。
68f0          ldr    r0, [r6, #12]
6931          ldr    r1, [r6, #16]
6972          ldr    r2, [r6, #20]
69b3          ldr    r3, [r6, #24]
f000 f800     bl    <xxxx>
bd00          pop    {pc}
「[r6, #12]」等は、MachiKania BASIC の「ARGS(1)」等に相当するコードで、サブルーチン呼び出し時の引数を、R0 などの ARM レジスターに代入している。ここから分かるように、関数の引数は4つまでに限定される。「bl」 インストラクションは、上で述べた「POKE16」ステートメントにより、HEXファイル中の該当する関数へジャンプするアセンブリーに置き換えられる。これらの仕様により、BASICコードからHEXファイル中の該当する関数を呼び出す事が可能になる。最後の「pop {pc}」は、MachiKania BASIC の「RETURN」ステートメントに相当する。

HEXファイルの作成方法と、HEX 中の C 関数を呼び出すBASICコードの作成方法

HEXファイルは、「c/src」ディレクトリー内のソースコードをビルドすると、作成できる。一回のビルドで、7つのHEXファイルが同時に作成できる構成である。対応するリンカースクリプトは、「c/src/lds」ディレクトリーにある7つで、0x20002000, 0x20004000, 0x20008000, 0x2000c000, 0x20010000, 0x20018000, 0x20020000 の RAM アドレスに、32k バイトの長さでビルドオブジェクトを配置するタイプの物だ(memmap_no_flash.ld を元に作成; 領域の長さはビルドオブジェクトが収まるぎりぎりの長さ+α)。ビルドすると、*.hex だけでなく、*.elf, *.uf2, *.dis, *.map などのファイルも同じディレクトリーに作成される。私は、すべて「build」という名のディレクトリーに作成されるようにした。

次に、BASIC コードを作成する。これは、上で説明した C コードのビルドが終わった後に、「c_convert2.php」スクリプトをPHPで実行することにより行う。このスクリプトを使用する前に、以下の箇所を編集する。
class configclass{
	// File names
	public $dis_file='./build/regexp02.dis';
	public $map_file='./build/regexp02.elf.map';
	public $hex_file='./build/regexp02.hex';
	public $debug_file='./machikap/regexp.bas';
	public $debug_hex='./machikap/regexp02.hex';
	
	// Functions to be exported
	public $functions=array(
		'machikania_init',
		'precomp',
		'regcomp',
		'regexec',
		'regsub',
	);
};
「$dis_file」「$map_file」「$hex_file」には、3つのビルドオブジェクトファイルの格納位置を指定する。「$debug_file」と「$debug_hex」はオプションで、指定しなくても良いが、このスクリプトを実行後にテストを行いたい場合、書き換える BASIC ファイルと HEX ファイルを指定する(PC-connect 機能を用いてデバッグを行う事を想定;指定しない場合は、これらの2つの行を「//」でコメントアウトする)。「$functions」には、エクスポートしたい C コードの関数を指定する。REGEXPの例では、5つの関数が指定されている。

「c_convert2.php」を実行すると、「result.txt」が作成される。この BASIC ファイルには、HEX 中の C 関数を呼び出すための必要最小限のコードが含まれるため、目的のアプリケーションを作成するために編集して用いる。

C ソースコードの書き方

ここでの C のソースコードを書く際は、いくらか工夫が必要である。

1.上でも述べたが、フラッシュ領域ではなく RAM 領域にコードを配置する(リンカースクリプトは memmap_no_flash.ld を元に作成)。
2.必要のないライブラリーなどは、なるだけ取り込まれないようにする。
3.gcc による最適化は、行わない。

「c/src/CMakeLists.txt」の次の記述を見ていただきたい。
set(PICO_NO_FLASH 1)
set(ENABLE_USB_UART 0)
add_definitions(-O0)
上で述べた3つの事項に該当する部分の記述である。「PICO_NO_FLASH 1」は、フラッシュを用いずに RAM 領域にコードを構築するのに必要な設定。「ENABLE_USB_UART 0」は、USBを用いたシリアル通信機能を含めないための指定である(CMakeListsSub.txtの中で「pico_enable_stdio_usb(${ENV_TARGET} ${ENABLE_USB_UART})」として使用されている)。この通信機能は、C のコードをデバッグするときには必要であるが、最終的な HEX ファイルに含める必要はない。最後の「-O0」は、gcc によるコンパイルの際に最適化を行わないようにする指定だ。最適化を行うと、時として関数の引数の扱いを変えたりすることによる誤動作の可能性があるので、最適化をオフにしておくことをお勧めする。

BASIC から呼び出しを行いたい関数は、なるだけmain() 関数とは別の C ファイルに記述するようにする(CMakeLists.txtで「add_definitions(-O0)」を指定した場合は、同じCファイルに記述可能)。また、main() 関数内では、これらの関数を呼び出すコードを記述しておく。これにより、最終的なビルドオブジェクトに、必要とする関数のコードが必ず含まれるようにする。

C から MachiKania の機能を呼び出すためのコードは、「machikania.c」に用意した。使用の際は、「machikania.h」をインクルードして用いる。なお、ここには「malloc()」「calloc()」「free()」「exit()」の4つの関数も含まれているので、これらを用いたい場合も、「machikania.c」と「machikania.h」が必要だ。

HEX ファイルは、一つでも良い

REGEXP では、他のクラスファイルなどとのコードの配置を考えて、複数の HEX ファイルを準備してフィットする物を用いるという、複雑な構成になっている。多くのケースでは、そのような複雑な構成を取る必要はないだろう。HEX ファイルは、一つだけでも良い。リンカースクリプトとしては、「c/src/lds」ディレクトリーの中から一つだけ選んで用いればよい。多くのケースで、「memmap_no_flash_02.ld」であろう。メインの BASIC ファイルや、読み込むクラスファイルのサイズが大きければ、より下位のアドレスを用いる ld ファイルを用いればよい。

どんどん C コードを取り込もう

この記事と、HELLO_CW アプリケーション・REGEXP クラスの例を参考にすれば、C でのソースコードが公表されている様々な機能を、MachiKania に取り込むことができる。それにより、MachiKania の応用範囲がさらに広くなることを、期待している。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=976 Sun, 26 Mar 2023 09:44:54 PDT ITEM976_20230326
Raspberry Pi Picoで、RAM領域にアプリケーションを配置する https://www.rad51.net/blog/mycom/?itemid=975
この記事では、フラッシュ領域ではなく RAM 領域(アドレス 0x20000000 からの 256 kbytes)にプログラムを配置する方法について述べる。ソースコードに若干の変更を加えるだけでよい。(ビルドすると、uf2 ファイルだけではなく hex ファイルも作成されるが、この hex ファイルは、MachiKania type P でファイル選択すると、実行可能。)

1.フラッシュ領域を使わないリンカースクリプトをコピー

Pi Pico のアプリケーションをビルドすると、デフォルトでは「pico-sdk/src/rp2_common/pico_standard_link」ディレクトリーに存在する「memmap_default.ld」がリンカースクリプトとして使用される。同ディレクトリーにある「memmap_no_flash.ld」が目的のリンカースクリプトなので、これを「CMakeLists.txt」があるディレクトリーにコピーする。

MachiKania type P 用の HEX ファイルを作成する場合は、コピーした「memmap_no_flash.ld」の26行目、「RAM(rwx) : ORIGIN = 0x20000000, 」の次の「LENGTH = 256k」を、「LENGTH = 192k」と書き換える。他の用途に用いる場合は、この変更は必須ではない。

2.CMakeLists.txt を修正する

次の2つの行を、CMakeLists.txt のどこかに書き加える。
set(PICO_NO_FLASH 1)

pico_set_linker_script(target_name ${CMAKE_CURRENT_SOURCE_DIR}/memmap_no_flash.ld)
ただし、「target_name」は、ビルドの際の任意のターゲット名に書き換える事。

3.あとは、いつも通りビルド

以上の変更を加えたのちに、いつも通りビルドすれば、RAM 領域にアプリケーションが配置された uf2 ファイルと hex ファイルが作成される。 ]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=975 Mon, 30 Jan 2023 15:35:30 PST ITEM975_20230130
MachiKania type P ver 1.2の新機能 https://www.rad51.net/blog/mycom/?itemid=974
公式ページは、こちら。
Github リリースページは、こちら。

Readmeに記載した更新履歴は、次の通りです。
Phyllosoma 1.20/KM-1502(2022.1.28)
 ・USBキーボード及びエディターをサポート
 ・INKEY()・READKEY()・INPUT$()の3つの関数と、INKEY割り込み機能を整備
 ・クラスファイルコンパイル時に一部の環境で生じる不具合を修正
 ・ALIGN4ステートメント・DATAADDRESS()関数・FUNCADDRESS()関数を追加
 ・タイマー割り込みのタイミングが少しずれていたのを修正
 ・SYSTEM()に、メモリーアロケーション関連の機能を追加
 ・文字列で「\r」「\t」のエスケープシークエンスが使用可能に
 ・OPTION CLASSCODEに対応
 ・BASICプログラム実行中でのカードの抜き差しが可能に
 ・ファイル選択画面でC言語で作成したHEXファイルのロードが可能に
 ・CRDINI・CLDHEX・REGEXP・STRINGの4つのクラスを、ライブラリーに追加

USB キーボードが使用可能

何といっても、新機能の目玉は、USB キーボードの接続に対応した事と、type M/Z と同じエディターを搭載した事です。これにより、スタンドアローンのパソコンとして使えるようになったほか、プログラムの開発も MachiKania 単独で行えるようになりました。従来の PC-connect 機能も使えますので、用途に応じて使い分けてください。

公式ページや Github の README に書かれてある通り、USB キーボードは USB-OTG コネクターを介して接続し、5 V 給電は Raspberry Pi Pico の VBUS 端子(40番ピン)から行うのが基本ですが、私は以下のような回路を自作して接続しています。
2023-01-30-usbkb.png
USB-OTG コネクターに、通常通りの USB type A 端子からの 5 V の電源供給を追加した様な構成です。このような構成なら YD-RP2040でも、MachiKania type P と USB キーボードを接続して使えるはずなので、参考にしてみて下さい。

(追記:同じ機能の市販品もあるようです。この商品が動くことを、確認しました。)

C で作成したアプリケーションの読み込みと実行

もう一つの目玉は、type P で使う用のアプリケーションやコードの一部について、C で記述したものを取り込む機能の追加です。

一つは、C で作成した type P 用のアプリケーションを、HEX ファイルで MMC/SD カードに保存しておけば、ファイル選択画面で選んで実行できるようにした事です。公式ページのパックマンの紹介を見てください。ダウンロードできる ZIP アーカイブに「pacman.hex」というファイルが含まれていますから、これをカードにコピーし、ファイル選択メニューからそれを選んでください。パックマンが起動します。リセットボタンを押せば、元の MachiKania に戻ることが分かると思います。uf2 ファイルからインストールした場合は、元の MachiKania に戻すには、MachiKania を再度 uf2 ファイルを用いてインストールする必要がありましたが、この HEX ファイル読み込み機能により、その必要がなくなりました。ただし、この HEX ファイルを作成するのにちょっとした工夫が必要なので、その方法については別記事で説明します

Cで作成したコードを、BASIC から読み込んで実行する機能

もう一つは、プログラムの一部について、C で記述されたコードを BASIC プログラムから読み込んで実行する機能です。この機能のために、MachiKania ベーシックでは、3つのステートメント・関数を追加しました(ALIGN4ステートメント・DATAADDRESS()関数・FUNCADDRESS()関数)。

複雑な処理を行うコードについて、C で書かれたものが一般に公開されているケースが多々あります。シンプルなコードなら BASIC のコードに移植して使えますが、複雑なコードだとそう簡単にはいきません。そこで、そういった、公開された C コードを MachiKania で活用するために、この機能を追加しました。この機能を用いたものとして、ver 1.2 では正規表現を扱うためのクラスである REGEXP がライブラリーに追加されています。これは、ここで公開されている正規表現実装コードを、MachiKania BASIC から呼び出せるようにしたものです。C コードの BASIC からの呼び出しをどのように行うかについては、別記事で説明します。

embed(コード埋め込み)機能は、USB キーボード接続時でも使える

Ver 1.0 からある embed 機能ですが、USB キーボード版(phyllosoma_kb.uf2)でも使えるようにしました。方法は、以前書いた記事を参考にしてください。キーボード使用版に埋め込むか、非使用版に埋め込みかの選択は、convert_kb.php を実行するか convert.php を実行するかで行えます。これにより、USB キーボードを使用する組み込み開発が、BASIC で簡便に行えるようになりました。もちろん、実行速度は MicroPythonを用いた場合の数倍で、C で開発した場合に准ずるものなので、様々な用途に使えるはずです。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=974 Mon, 30 Jan 2023 14:39:20 PST ITEM974_20230130
MachiKaniaを使ったチャートレコーダー https://www.rad51.net/blog/mycom/?itemid=973
2022-12-27-ChartRecorder.png

チャートレコーダーは、各種データーを記録する装置のうち、結果を紙に印刷するタイプの物です。古いものだと、例えば
2022-12-27-ClassicChartRecorder.png
こんな形の物です。他には、円形の紙に印字するようなタイプもあります。

これと同等の事を、紙に印刷するのではなく液晶画面に表示し、MMC/SDカードにデーターを保存するようなタイプの物を作成しました。OSに、MachiKania type Pを用いています。

仕様と特徴

次のような仕様です。

・最大3つの値を記録可能
・データーの入力電圧は、フルスケールが 0-1 V もしくは 0-100 mV
・1秒ごとにデーターを記録
・データーは、CSVファイルとしてMMC/SDカードに保存
・測定中もMMC/SDカードを抜いて、PCに取り込むことが可能
・マイクロコントローラーに、Raspberry Pi Picoを使用
・液晶表示に、ILI9341を使用(320 x 240 pixels)
・OSに、MachiKania type Pを使用

この装置が持っている機能の簡単な説明は、以下の通りです。
2022-12-27-HowToUse.png
なお、ここでは3つの入力を下のように接続しています。
2022-12-27-connections.png
・フラクションコレクター(fraction collector;溶出液回収用;緑線)
・紫外線吸収度計(UV absorption;蛋白質の分量測定用;黒線)
・電気伝導度計(conductivity;バッファー特性測定用;赤線)

に繋げて使っています。

使用中は、液晶表示が以下のようになります。
2022-12-27-Display.png
なお、X軸・Y軸共に、ズーム表示が出来ます。

使用中は、10秒ごとにカードに記録されます。液晶表示の「save」の色が変わる時に、ファイル保存されます。
2022-12-27-movie.gif


カードに含まれるファイルは、以下の通りです。
2022-12-27-files.png
「machikania.bas」は MachiKania type P の実行ファイル、「MACHIKAP.INI」はMachiKaniaの設定ファイルです。機器を作動させると、「CHARTxxx.CSV」のファイル名で、測定結果が保存されます。ファイル名は、機器の再起動ごとに別の名が割り当てられます。

回路とプログラム

回路図とソースコードについては、Githubにレポジトリーを作成しました。

マチカニア部分の回路図は、以下の通りです。
2022-12-27-machikania.png
上記回路図の ADC0, ADC1, ADC2 の部分は、オペアンプに繋げます。回路図は以下の通りです。
2022-12-27-opamp.png

オペアンプは、マチカニア側と入力側で、異なる接地レベルが使える仕様です。この仕様のために、Analog Devicesの絶縁オペアンプ、ADuM3190を用いました。また、電源供給用に、同じく絶縁タイプのDC-DCコンバーターを用いています。

オペアンプ回路中に、2つのジャンパーピンがあります。上のピンは、オープンコレクターもしくはオープンドレイン入力の際のプルアップに、下のピンは0-1 V入力の際(デフォルトは、0-100 mV 入力)に用います。

筐体のふたを開けると、以下のようになっています。
2022-12-27-opened.png

液晶とボタン基板を外した状態が、以下の写真です。
2022-12-27-lower.png


メイン基板の説明:
2022-12-27-mainboard.png

なお、この装置は電源を選ぶようで、安物のUSB電源では、正常に動作しませんでした。下は、さまざまなUSB電源を用いて、リファレンス電圧を Raspberry Pi Picoの AD コンバーターで読み取った値のグラフです。
2022-12-27-refvoltage.png
安価な電源を用いた場合、不定期にリファレンス電圧が落ちてしまう現象が起きました。安定に動く電源もあるので、マッチしたものを使う必要がありそうです。電源容量の問題かもしれません。

MachiKania BASICで書かれたソースコードは、Githubのレポジトリーを参照してください。コメントも含めて400行ほどのプログラムです。タイマー割り込みで定期的に3つのアナログ入力を読み込んで、一秒おきにグラフ表示させています。]]>
MachiKania https://www.rad51.net/blog/mycom/?itemid=973 Tue, 27 Dec 2022 16:26:03 PST ITEM973_20221227