電子回路工作

Python のソースコード貼り付け

 試し書きしてみた

 ココログでソースコードを表示するやり方について調べてみたらやっぱりあった

import numpy as np
sample_rate = 8000
signal_freq = 1000
x = np.arange(0, 1, 1/sample_rate ) # x座標を-10 から 10 まで 0.1 きざみで取得
y = np.sin(2 * np.pi * signal_freq * x) # 正弦関数の式を記述
print( 'sample_rate: ', sample_rate )
for target_freq in [ 641, 701, 1000, 1191 ]:
N = 200
k = int( 0.5 + N * target_freq / sample_rate )
w = ( 2 * np.pi / N ) * k
cosine = np.cos( w )
sine = np.sin( w )
coeff = 2 * cosine
  print('----')
print( 'target_freq: ', target_freq )
print( 'N: ', N )
print( 'k: ', k )
print( 'coeff: ', coeff )
  q2 = 0
q1 = 0
for i in range( N ):
q0 = coeff * q1 - q2 + y[i]
q2 = q1
q1 = q0
real = ( q1 - q2 * cosine )
imag = ( q2 * sine )
mag = np.sqrt( real * real + imag * imag )
  print( 'real: ', real )
print( 'imag: ', imag )
print( 'mag: ', mag )

ソースコードを上記のように張り付けてみたがどう見えるだろうか。ちょっと実験してみた。

 この Python のスクリプトは Goertzel アルゴリズムといって、ターゲットにした周波数だけの FFT を簡略化して求める計算方法なのです。大量にメモリにデータを格納しなくて済むので、小さなマイコン向きの実装になります。Python では固定少数点化できないのですが、今度は C 言語で書いて Visual Studio でデバッグする予定です。

 C 言語で書いたら Arduino で実装して、生の DTMF トーンを ADC から入力して demodulate できるかどうか実験してみたいと思っています。これがうまくいったら FSK モデムの実装が Arduino みたいなマイコンでもできることを証明できます。そこまでブログでは記事にしていきます。

Ichigojam の WS.LED コマンド

 夏休みの自由研究的な電子工作

 以前にPCN秋葉原でLEDを虹色に光らせる研究がなされていたので、教えを乞うことにしました。

 9月といえばそろそろ十五夜お月様のじきかな、ということでウサギさんとお団子を光らせることにしてみました。え、月は光らないの?というツッコみはなしでお願いします。例によってアイロンビーズでウサギさんを作ってみると以下の写真のようになりました。



 光らせる場所はウサギさんの目とおなかのあたりとお団子の中心に1球ずつフルカラーLEDを裏から張り付ける作戦です。WS2812Bのミニ基板モジュールと PL9823 という砲弾型の5mmのLEDを連結させてみました。これらを連結して光るかどうかはまだ誰も確かめたことがなさそうだったのでやってみました。

 配線を隠しながら LED をアイロンビーズの裏側に接着するために、グルーガンを使いました。IYN はこの透明な樹脂を熱で溶かして LED を張り付けるというのがそんなに有効なのか知らなかったので、ちょっと感激してしまいました。ええっ、こんな簡単に、LED が思うように固定できてしまうなんて!



 適当に配列に数値を入れて WS.LED 3 とコマンドを実行するとうまいこと光ってくれました。ただし、配列の[0]~[5]はWS2812Bの2球に対応しているのでカラーデータの並びはGRBGRB、配列の[6]~[8]はPL9823(ウサギさんの眼球)なのでカラーデータの並びはRGBとなります。127くらいで光量としてはサチっているみたいなのでこのくらいの出力値にしておくのが良いでしょう。なぜなら、消費電力のわりに見た目の輝度が変わりませんし、Ichigojamからドライブさせる電力としても抑え気味にした方が賢いからです。





 さて、WS.LEDコマンドが思ったように動かせることが分かったら虹色出力です。虹色というと起点となる7色をRGBで表現したり、それを連続的に変化させるようなプログラムを書こうと思うとちょっとめんどくさいな、と感じました。それで PCN秋葉原 のお店の人に相談したところ以下のような数式1行で表現できると教えていただいたのです。

[ I % 3 ] = ABS( I % 2 * 100 - H )



   この式の説明をします。色相環では360度で一周する虹色を6つのステージに分割すると、I = 0 ~ 5 となります。I % 3 は配列の要素数で、I=0, 1, 2, ... とステージが進むたびに [0] [1] [2] [0] [1] [2] と配列の添え字が変化します。つまり、G R B G R B の順番に出力するカラー情報が変化するということです。ABS の方はもう少し複雑で、ステージが I=0, 1, 2, ... と進むとABS( ... ) の数式の評価結果は

I=0: H (=Gが0→100と変化)

I=1: 100-H (=Rが100→0)

I=2: H (=Bが0→100)

I=3: 100-H (Gが100→H)

I=4: H (Rが0→100)

I=5: 100-H (Bが100→0)


というようになり、各ステージの中でHを0~100とカウントアップさせることで色相環の六角形(輝度はまちまちだけど)の中をたどることができるという優れモノなのです。上記をきちんと理解したうえで Ichigojam BASIC でプログラムを書くと以下のようになりました。

 プログラムでやっていることは、ウサギさんのおなかのあたりを虹色に変化させていることに加えてウサギさんの目は赤固定でお団子はぼんやり点滅しています。



 お彼岸が近付くにつれ、寝苦しい夜も少なくなってきました。Ichigojam を使った電子工作もゲーム開発もこれからが身に入るころですね!

Ichigojam マシン語デバッグ術

 コードレビューが一番効果的なんだけど…。

 たった数十バイトのマシン語でも暴走した時は一瞬途方にくれますね…。特に Ichigojam のようなデバッグ環境がほとんど存在しないような場合にどうしたらいいのか、頭をひねります。自己流を持ってる人は確認の意味でも IYN のやり方と比較してみてください。

 デバッグで必要なのはとにかくレジスタの値を見ることです。暴走するのは、とにかくレジスタの初期設定がおかしい時が多いのです。ループさせるコードは IYN は経験上ほとんど間違えずにループしています。アセンブラを書いていてループさせること自体にミスを含む要素はかなり少ないと考えています。

 レジスタの値を見るためには、Ichigojam の場合は R0 に目的の値を代入して BASIC に制御を返す必要があります。つまりループが始まる前に各レジスタの初期値を R0 に入れて RET するコードを書いて、それぞれのレジスタが設計意図通りなのかすべて見回しておくことです。具体的にはマシン語のループのコードにアポストロフィ(')を入れてコメントアウトしてからアセンブラ asm15 にかけて ?HEX$(USR(#700,0)) などと一発実行するわけです。

 Ichigojam の USR 関数は R1 の値を最初にベースアドレスとして用いることが多いので、このレジスタを別用途に流用するときは十分注意が必要です。IYN は R2 に VRAM の先頭アドレス #900 を作っておいて、R2 = R2 + R1 として実VRAM先頭アドレスにしていたのに、R1 を VRAM の最後アドレスにしようとしたときに R1 = R2 + R1 などともう一度ベースアドレスを加算してしまうというミスをしていたのでした。

 自分も Ichigojam のプログラミングを習得してゲーム開発をしてみたいとお考えのあなた、ベーマガ投稿研究会のメンバーになってPCN秋葉原で私と一緒に活動しましょう!

Ichigojam 用逆アセンブラ 印刷機能付き

 逆アセンブラのツール開発が進みました

ダウンロード - disasm_for_ichigojam_1_0_2.zip

 変更点 … 印刷機能と印刷プレビュー機能を追加

 印刷プレビューはプリンタの設定はデフォルト以外変更できません。用紙サイズの変更などをした結果を印刷プレビューで見たい場合はプリンタについてるユーティリティを使ってください。

 ここからは VisualStudio の話題となります。非常に参考になったのは dobon.net というサイト。印刷プレビューについては、

  1. PrintPreviewDialog オブジェクトを生成して
  2. printDocument オブジェクトを生成して
  3. printPage イベントハンドラで印刷描画を実装する

という手順で実装できました。プレビューに使ったprintPageイベントハンドラはそのまま印刷ダイアログの中で再利用できます。印刷プレビューダイアログはとても簡単に表示できるように作られていました。

 肝心の PrintPage ハンドラの中身はというと、ウィンドウ画面を描画するのと同じことを紙の上でDrawStringとやるだけでした。marginBounds.Top/Bottom/Left/Right で囲まれた座標空間の中で DrawString して文字列を置いていく作業は、きちんと考えるとなかなか大変なことをしています。画面上の描画ははみ出ないように書くのに対して、印刷物の描画ははみ出たら次のページに続きを描画する、という管変え方が必要になります。

 ですから PringPage ハンドラは1ページごとに呼び出されて次のページで呼び出される必要があるかどうか自己判断しなきゃいけないようなのです。それで e.HasMorePages = True といった代入式を最後に書くことになります。

 IYN はこの dobon.net のサイト管理者が作ったアルゴリズムを1ページに3列繰り返すことによって、番地の列、マシン語の列、ニーモニックの列をそれぞれ印刷することに成功しました。

 アセンブラの解析でも開発でも、紙に印刷して好きにメモを書き込んで使うことは頻繁に発生するので、逆アセンブラに印刷機能がついてることは利便性がかなり高いと思います。

注意: 開発は VS2015 で行ったので、.NET Framework はバージョン4.6に依存していると思ったのですが、dumpbinで調べてみるとバージョン2.0依存になっていました。アプリを実行できないという方は、両方のバージョンの.NET Frameworkのインストールをお試しください。

Ichigojam マシン語で LED ピカピカ

 ichigojam マシン語熱が高まってきた夏休み

20190814_disasm01   ichigojam の OUT1ポートにWS2878用のデータを出力するマシン語プログラムを解読してみました。R0にはLEDの個数*3の値を代入して、R1にはデータアドレス、R2には出力ポートアドレスを代入して#EE番地に書いてあるWS.LEDコマンドのベクターにgotoするというコードです。

 R1には画面のアドレス#900番地を入れていますが、画面上に乱数生成した文字列をBASICで書いているので結局は256*3個の乱数をOUT1ポートに送信することになっています。

 もともと福野さんが書いたハンドアセンブラが R2=[@OUT1]L となっているところが実際のマシン語でどうなるのか見てみたかったため、逆アセンブラしてみたわけです。[PC+2]L ということで、4バイト単位のアドレッシングになっているのですが、NOPを挿入することでアラインを取って#714、#716番地からOUT1ポートの番地#50010004を読み取っていることが分かります。

 マシン語でないと速度で気に間に合わないケースがあると聞いてどうやって実装するんだろうと疑問に思っていましたが、これで IYN にもマシン語で I/O 出力のやりかたが分かってきました。I2CコマンドもAPI呼び出しすればよいのでしょう。

 

逆アセンブラ for Ichigojam

 久しぶりにwinアプリ作りました!

ダウンロード - disasm_for_ichigojam.zip

 zip ファイルを展開すると小さな exe ファイルが一つ出てきます。実行すると、発行元不明とか言われて止められますがわかる方はそのまま実行してみてください。このブログがハッカーに侵されない限り安全だと思います。念のためにセキュリティスキャンしてみてください。実行が確認できたのは、win10 Home edition のみです。開発ツールは VS2015 express です。

 実行すると以下のようなウィンドウが出てきます。各所の説明をします。

  • 開始番地…ここに16進数で先頭番地を入力しておくと、マシン語変換の際に「番地」にアドレスが表示されます
  • 番地…アドレスを自動生成した結果を表示します
  • マシン語…テキスト入力で、各種マシン語表記を入力します
  • ニーモニック…逆アセンブラの出力結果を表示します

「ファイル」メニュー

  • 終了 … プログラムを終了します
  • 印刷、印刷プレビュー … 開発中

「解析」メニュー

  • カンマ区切り10進数 … マシン語の枠に記入された「254,181, ... 」といった8ビットずつカンマ区切りされた10進数を16ビット16進数に変換します
  • カンマ区切り2進数 … マシン語の枠に記入された「`00000001,`00110000, ... 」といった、8ビットずつカンマ区切りされた2進数を16ビット16進数に変換します
  • 16ビット2進数 … マシン語の枠に記入された「`0000000100110000 …」といった改行で区切られた16ビット2進数を16ビット16進数に変換します
  • 逆アセンブル … マシン語の枠に記入された改行区切りの16ビット16進数を逆アセンブルし、結果をニーモニックの枠に出力します

「ヘルプ」メニュー

  • バージョン情報 … 現在使用しているツールのバージョンを示します。印刷、印刷プレビューが実装できた段階で ver 1.0.0 とするつもりです。

 という説明から使用方法がわかると思いますが、順を追って説明します。

1. マシン語コードの準備 … カンマ区切り2進数のマシン語を例にとって用意します。エディタなどで、「POKE #700」の文字列を取り除いてマシン語データ部分のみ残します(元のコードは Ichigojam 開発者の福野さんのページからお借りしました)。

20190810_02_bin_array

2. マシン語の枠へのマシン語データの貼り付け … 作ったカンマ区切りデータを「マシン語」の枠に貼り付けます。ここで、開始番地にデフォルト値#700を変更することもできます。

20190810_03_paste_bin

3. マシン語変換 … 「解析」→「カンマ区切り2進数」をクリックして4ケタの16進数に変換するコマンドをメニューから選びます。

20190810_04_convert_bin

4. マシン語変換結果 … 上記3. のコマンドを実行すると以下のような画面になります。4ケタの16進数に変換できなかったものは空行になります。

20190810_05_convert_result 

5. 逆アセンブル実行 … 「解析」→「逆アセンブル実行」をクリックします

20190810_06_disassemble_cmd

6. 逆アセンブル実行結果 … 上記5. のコマンドを実行すると以下のように、ニーモニックの枠に逆アセンブル結果が出力されます。

20190810_07_disassemble_result

 ここからは注意書きになりますが、基本的に自分のために作ったツールですのでいろいろと不備があります。くれぐれも objdump とかと比較したりしないでください。

  • 逆アセンブルできる命令は Cortex-M0 Arm マシン語表(asm15, 抜粋) に書いてあるものから有用なものだけ取り出して対応しています。
  • つまり、asm15 が吸えるニーモニックを部分的に解釈できるようにしたものです。
  • goto 文の分岐先はマシン語コードに対して2を足しています。したがって飛び先は命令個数分だけ数えれば済みます。
  • 改行文字はCRLFのみ対応しています。そのほかは動作確認しておりません。
  • 印刷機能は最終的に削除するかもしれません。自分の勉強用の課題ということにしておきます。

童心に返る #4 Ichigoboy ゲーム開発

 何作か作りました。

 PCN秋葉原に遊びに行くたびに IYN の作ったゲームで遊んでくださる方がいらっしゃるので、ついつい IYN は得意げになってしまうのであります。Ichigojam に入門する方がこちらでは多いので嬉しい限りです。ついでに Ichigoboy の方に食指を伸ばしてみませんか?

 一作目はだいぶ前に Ichigojam 向けに作ったわびさびなインベーダーゲーム「サシベーダー」の進化版です。実行画面の撮影の仕方が難しくて上手く撮れないのですが、敵がフワンフワン動き回ってなかなか狙いが定まらないシューティングになりました。これはベーマガに投稿してみたのでどうなることでしょうか。掲載されるようであれば IYN の中で大騒ぎですが、画面が地味なので意見が分かれるところでしょう。

 二作目はカーレースゲーム。ライバル車は出てこなくて、道路をはみ出たら急減速するというだけのルールで決められたコースを5周するゲーム。とは言っても、コースをはみ出てもそんなに大きくタイムロスするわけではない仕上がりになってしまいました。コースのデザイン次第ではもっとスマートにドライブする方向で熱くなるゲームにできると思います。

 三作目は落ちゲー。これは独特のルールでオブジェが消えていくのが面白くてついやってしまうゲームです。こちらもベーマガに投稿してみようとしているので内容は今のところ内緒です。

P_20181005_185546  四作目はスーマリ風のジャンプしてよけるタイプのゲームを試作しているところですがここで問題発生。液晶モニタの反応が鈍いので、ブロックの有無がスクロールすると見えづらくなってしまうのです!本当は落とし穴があいているのに、隣同士のブロックが黒いために横スクロールすると穴が埋まって見えてしまうのです。

P_20181005_182931_hdr 本当は左図のように穴が開いているのですよ!これがスクロールすることによって塗りつぶされてしまうというわけ。あーあ限界かなぁ Ichigoboy ではあまり背景の画像を置いてスクロールしてはいけないような気がしてきました。

 むむっ、というわけで制約がまた一つ見えてきました。だけどジャンプしてよける要素のゲーム作りはあきらめたくない、ということで落とし穴を付けるのはやめて障害物を転がす方向で検討し始めました

童心に返る #3 Ichigoboy組み立て

 子どもパソコンのケータイ版

P_20180909_151108 秋葉原を歩いていてそんな触れ込みで売られている Ichigoboy シールドと出会いました。Ichigojam でゲーム作って遊んだのも1作品だけでそのあとホコリをかぶっていました。画面の小ささ、メモリ容量の少なさなどいろいろな制約の下で作るゲーム開発はおもしろいものだという発想を思い出させてくれました。

 しかしこの Ichigoboy、IYNの持っていた Ichigojam U だとコネクタがオスメス逆のところがあって工夫しなければならないところがあります。また、PS/2コネクタがでかいので多少 Ichigoboy シールドが傾きます。それでも動くんだからありがたいですね。

P_20180917_173949 それに加えて IYN は裏側にピンヘッダを立てなきゃいけないのに液晶を張り付ける側にピンヘッダを立ててはんだ付けしてしまい、はがして取り換えるのにとても手間をかけてしまいました。すぐにゲーム開発に入りたいのにこれはショック。最後にPCN秋葉原アセンブラージュに駆け込んでサポートを受けてようやくシールドが復活できました。

 と、シールドを組み立てました報告だけならほかの人のブログでもやっていることですが、ゲームを作りましたよ報告をしている人を見たことがないくらい、このIchigoboyの稼働率は低いのです、きっと。Ichigoboy含めてIchigojamでゲーム作りたいけどプログラムができないなぁ…という人がたくさんいるんじゃないでしょうか。

 そんな人たちをうまくサポートできないだろうかと思うんですが、そんなマイコンBASICマガジンみたいな役回りを果たす場所ってどこかにありませんでしょうかね。IYN は時間が許す限り是非そういう場所に繰り出して貢献したいと思っています。

 もちろんお手本になるゲーム開発のアイデアから実装に至るまでの発想を提示し続けられなきゃいけません。あなたがなりたい姿を私が演じて見せてあげなければ、夢を見させることはできないでしょう。今のところはスタッフでもないのにPCN秋葉原に自作ゲームを持ち込んで出入りしているだけなんですが、ゲーム作りたい人が集える場所になるといいな。

P_20180917_173850 左図はインベーダゲームっぽい画面を動かすプログラムです。こういうのは何種類か型があるからつくりやすい。ゲーム開発っていうのはインクリメンタルに仕様を決めることが多いので、バシッと設計書を作ったりしなくていい点は業務ソフト開発とだいぶ違います。仕様検討と実装検討との間を行ったり来たりするのってセンスが大事なんです。

 ホラ、1画面プログラムなんか作っていた人は語りだすと長くなりそうでしょ?ゲーム開発のセンスと呼んでいる部分をうまいこと伝授する方法を IYN は探り出していきたいものです。

Arduino制御のDSPラジオ #7 ソースコード公開

 Arduino の .ino ファイルそのものです

「dsp_radio_Exp_20180912.zip」をダウンロード

20180912_seeking 実行するとシリアルモニタに左図のような文字列がプリントされてきます。単にR/WレジスタとROレジスタの主要な部分をマルチバイトリードしてプリントしているだけです。でもこれを見ただけでも DSP ラジオ M6951 の挙動がよくわかります。レジスタ20番が6Xになっていればseek, tuneは完了していて選局できてることになります。

 でレジスタ2,3番ではNHK2が選局されていますが、レジスタ20,21番を読むと1A7h(=1134kHz)文化放送が選局されています。これはseekupをした結果なのです。前回書いた通り、ユーザーが直接選局する際に使用したレジスタ2,3番にはシーク結果は反映されず、リードオンリーのレジスタ20,21番に出てくるのです。マイコン側で常時選局周波数を把握していたい場合はここに注意が必要です。

 さてソースコードに書いたライブラリ M6951 クラスについて説明します。ほぼ見たとおりですと言ってしまいたいところですがいくつかの関数があります。

 まずクラスなのでインスタンス宣言をsetup()の手前でやります。ソースコードではdspRadioというインスタンス名にしております。で setup() の中で、beginする前に必ず Wire.begin() を入れてください。その後delay100msec してから dspRadio.begin すると AMラジオとしてDSPラジオM6951 を初期化します。戻り値は Wire.endTransmission の戻り値をそのまま返しているので、I2Cの接続状況に応じてエラーになります。

 ReadRegs()関数はデバッグ用で、上述のようなレジスタをシリアルモニタに返します。

 loop()関数の中でやっている、tuneAM, tuneFMはそれぞれバンド指定と選局を直接行っています。周波数を書き込んだ値はレジスタ2,3番を読むことで見直すことができます。それと選局状態は isTuned 関数で確認。seekup() は現在の周波数を開始位置として高い周波数の方向にシークします。これは探す時間があるので、isSeeked関数を使いながら次のシークコマンドを書き込んでいいかどうかループの中で判断しています。

 初期化直後にFMラジオにしたい場合は m_fm_en=1;などとしておいてください。m_Chan12_8, m_Chan7_0は確実に選局できる周波数を選んでおくとデバッグが楽だと思います。遊んでみてください。

Arduino制御のDSPラジオ #6 機能の探求

 ラジオといえばシーク機能!

 AM/FM それぞれを M6951 で再生できた IYN は気をよくして、それまで謎だった tune 機能とか seek 機能を使ってみることにしました。レジスタ0番の seek とか tune に1 を書き込むとプロセスが始まるとだけマニュアルに記述があって、書き込んだ後何がどうなるかの説明は一切ありません。レジスタ20番のSTCが1が立つことでtuneやseekが終了するとあります。ということは、seekやtuneに1を書く→STC=1になるまで待つ、というコードを Arduino で書いてあげる必要がありますね。

 マニュアルとレジスタをいじってみてわかったことは以下の通りになります。

  • tune…選局ができているかどうかのフラグ(レジスタ20番のtuned)を立てる機能
  • seek…自動選局した結果をレジスタ20番の readchan に表示する機能

 レジスタ2,3番でChanを指定したときもtuneフラグは動いているようではあります。IYN のArduino ソースコードでは5秒ごとにシークアップをループするようにしているので、繰り返しシーク機能を読んでいます。ここで分かったことは、seekビットは0を書き込んで1を書くとやらないと繰り返し機能が使えないということです。それにシークした結果はレジスタ2,3 には反映されず、レジスタ20,21のreadchanにのみ反映されます。

 つまりシークした選局結果はレジスタ2,3のChanを読んでもわからないのです。I2Cマスターから書き込むレジスタは、たとえ状態が変わってもDSPラジオ側では更新しない設計なのです。その代わり、リードオンリーレジスタ側はDSPラジオが常に更新している値であり、I2Cマスター側からは書き込むことはできません。

シークされた結果をreadchanから読んでみると、FMは10局くらい、AMは電波の調子が良ければ5局くらい選局できました。シークにかかる時間もほぼ1秒くらいでとても速いです。途中の周波数がどのくらいなのかを読み取る手段がありませんが、ラジオの機能としては十分ではないでしょうか。

 そのほかの機能としては、ほかのリードオンリーレジスタを読むことくらいでしょうか。RFアンプのゲイン設定値だとか、選局した局の電波強度なんかが表示されています。それとCareer to Noise Ratio の値は見ていると楽しいかもしれませんね…。

 次回は実験に使ったソースコードを公開したいと思います。

より以前の記事一覧

2022年3月
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    
無料ブログはココログ