Propeller日記 (5)
Propeller日記(1)
2008年4月5日(土)
Parallax社のPropeller Demo Boardでなく、オリジナルに製作した試作実験ボードに切り替えて、 インスタレーションのために2系統ビデオ出力にトライすることにした。 前日のproto001.spinでは、ビデオ出力のポート指定が分かったところまでだったので、 proto001.spinをコピーしてリネームしたproto002.spinでいろいろと実験した。まず最初に出て来たのは、単純にproto001.spinの中のビデオ出力関係をダブルに持つことが出来ない、 という壁だった。 VAR領域の変数、初期化、OBJ領域のTVとgrの定義を
OBJ midiIn : "MidiIn03" midiOut : "MidiOut01" audio : "AudioOut06" tv[2] : "E_TV02" gr[2] : "E_Graphics02"とダブルで持って、プログラム中のtvメソッドとgrメソッドの部分をそっくりコピーして、 tv[0]とtv[1]と指定する・・・というような定番の改訂をまず、行ってみた。 すると、Propeller ToolのF10(コンパイル+ダウンロード+実行)に対して、 「Run Time Error : Memory Full」みたいな表示が出て、 ○○longsだけオーバーしているのでPropellerのRAMに入らない、と叱られた。
ここまではいくつもの仕事をどんどん快調に加えてきても何も起きなかったが、 どうやら、グラフィック表示は色々とメモリを使うようである。 仕方ないので、
などあれこれして、ようやくメモリ不足エラーが出なくなり、Propellerに転送できた。 ところが、2つのビデオモニタが沈黙したり、何か描画しているらしいがチラついたり、 グラフィック表示してもヘンな表示になったり・・・と、試行錯誤するたびに異常となった。
- MIDIは入力だけで出力をコメントアウト
- デモのグラフィクス表示の大部分をコメントアウト
- 定数エリアのデータ定義もコメントアウト
ここでは試行錯誤のいちいち全ては書かないが、次第に分かってきたのは、 このデモで紹介されている(1系統の)ビデオ出力のグラフィック処理は、 けっこうPropellerのCogsの処理としては頑張っている、キチキチなデモなのだった。 倍増ではオーバーして、少しカットするとOKになるぐらい、限界ギリギリだった。
そして発見した最大の問題は、「2系統のグラフィックメモリは持てない」という事実だった。 CON領域の定数として定義している
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = ($3000 + $3000 + 100) >> 2 'accomodate display memory and stack x_tiles = 16 y_tiles = 12 paramcount = 14 bitmap_base = $2000 display_base = $5000 lines = 10の部分が問題で、少しずつ変えてコンパイルしてはビデオ画面に入るノイズの位置で実験した結果、
を全て使用していることが分かった。 従って、プログラムとメモリ領域は $0000 - $1FFF に入らなければならないが、 これが既に $1F00 付近まで行っていて、増やすと越えてしまうのであった。
- 「bitmap_base」の領域は $2000 - $4FFFF
- 「display_base」の領域は $5000 - $7FFFF
ビデオの1系統でこれだけ使うので、とても2チャンネルの別個のビデオを同時に表示は出来ない。 ただしこれは、
repeat 'clear bitmap gr.clear ・・・・・・・・ 'copy bitmap to display gr.copy(display_base)というループで、グラフィックの1フレームの冒頭にグラフィックメモリをクリアし、 そこに描画処理をして、最後にこれを表示メモリに転送する、 というダブルバッファであることが分かった。 フリッカ(ちらつき)対策であり、この最後の「gr.copy(display_base)」をコメントアウトすると、 見事にフリッカ画面となった。
そこで、今回のシステムでは仕様として2系統ビデオ出力を優先することにして、 ダブルバッファを捨てることにした。 つまり、メインのCogのループごとの冒頭に「gr.clear」を行わない代わりに、 ループの最後の「gr.copy(display_base)」も行わない。 これで、2系統のグラフィックのための定義も
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = ($3000 + $3000 + 100) >> 2 'accomodate display memory and stack x_tiles = 16 y_tiles = 12 paramcount = 14 bitmap_base1 = $2000 bitmap_base2 = $5000 display_base1 = $2000 display_base2 = $5000 lines = 10と、それぞれシングルだけ持つグラフィックメモリに対して描画処理を行えばよい。 つまり、昔のコンピュータの「ストレージ管」ディスプレイみたいなものであり、 どんどん上から塗りつぶしていくグラフィックとなる。 これは、コンテンツの方で工夫すればいいわけである。
いろいろ半日ほど悩んだ結果として、とりあえず2系統のビデオ出力を生成しながら、 MIDI入力に対応してサウンドを出したり、画面クリアをしたり、描画パラメータを変化させる、 という proto002.spin を作ってみた。 動作している風景は以下である。 パソコン無しに、グラフィックチップもシリアル用UARTもサウンドチップも無く全てソフトウェアだけで、 これだけの処理を淡々とこなす、というのは、ちょっと考えるとなかなかのものである。
2008年4月6日(日)
この日は半日かけて、Webサーバに上げたここまでのPropeller日記を読み返して、 全体の再整理をしたりバグを訂正したりしただけで終わった。 すっかり忘れていたが、Diary02で「_stack」についてちゃんと書いてあった。 この予約語の意味は、ちょうど直面している問題に関係したものだった。 その横ではずっと、実験用試作ボードのPropellerがずっと、2台のビデオモニタにグラフィクスを生成し続けた。2008年4月7日(月)
Propellerによるスタンドアロンのインスタレーション、という目標に向けて、 まずはグラフィック関係を詳しく調べてみることにした。 ここまでの手応えとしては、かなりメモリ占有度が高い状況なので、 いくらでもソフトウェア部品を増設していける、という事でもないので、 常に残りメモリを気にしながらの作業となりそうだ。proto002.spinをコピーしてリネームしたMainオブジェクトproto003.spinで、 テンポラリ変数を配列で持つのはOK、と確認したので、 とりあえずリアルタイムのグラフィック演算の定数をテンポラリ変数にして、 MIDIから色々と変化させてみることにした。 また、E_Graphics02.spinを見ると、テキストを表示するために多量のフォントデータを持っていたので、 これをコピーしてリネームしたE_Graphics03.spinに対して、大幅な削減(でもグラフィックは同等に表示)を目指した。
・・・時間はそこそこかかったが、結果はかなり地味である。 Mainはとりあえず proto003.spin となり、グラフィックのオブジェクトも E_Graphics03.spin となった。 ここまでで、以下のように、けっこうな残りスペースを作ることができた。
続きは明日だが、いよいよ入学式とか学科会議とか大学院ガイダンスがあるので、 ここからの進みは遅々としたものになるかもしれない。
2008年4月14日(月)
先週は、火曜日に雨模様の中で 入学式 があり、さらに水曜日からは連日、学科会議、大学院ガイダンス、学科ガイダンス、履修相談、と予定が続いて、 予想していたものの、プログラミングはほとんど進展しなかった。 この間に進めたのは、インスタレーションとしての手法、センサ、グラフィクス、 サウンドなどのシステム構成要素について、合間の時間に検討したぐらいである。トラ技の編集者とのメイルで、記事の完成を5月中旬、と繰り上げて宣言したので、 ここからちょうど1ヶ月が、記事の執筆期間となる。 システムの構想・設計・実験・試作と並行しての執筆となるので、この日記では、 さらにその裏側をメモしていくことにした。 記事の末尾の「参考文献」のところでは、このページのURLを公開する予定なので、 この日記も、あと1ヶ月でとりあえず終了となる。
インスタレーションの中ではセンサを使うことになるが、 まだそのインターフェースを実験していなかったので、この部分について検討した。 Propellerでは、基本的にビット単位のデジタル(シリアル)入力となるので、 A/D入力についても、カウンタのパルスを計数する、というのが基本となる。 このためには、外部に「V/Fコンバータ」があればよい。 そこで、かつて活用していた「74124」(汎用dualのVCO)をネットで調べてみたが、 どうもこれは廃品種となった模様である。 駄目モトで、とりあえず「世界中のディーラーに打診」というサイトに、 50個、発注依頼しておいた。
次にネットで検索して発見したのが、「74HC4046」である。 これはVCOとPLLとが一体になったものであるが、 データシート を見ると、以下のように、PLLを無視してVCOだけでも、なんとか使えそうである。 そこでさっそくネットで発注してみた。 パッケージがまたまたDIPでないので苦労しそうだが仕方ない。
そして、Propeller Demo Boardには「コンデンサマイク入力」というのがあった、 と思い出して、サンプルプログラムを調べてみることにした。 既に制作が進んでいる実験試作ボードでなく、マイクまで搭載されているPropeller Demo Boardをパソコンに接続して、 以下のサンプルを呼び出してみた。
このプログラムでは「microphone_to_vga.spin」がTopオデジェクトであり、 起動すると最初に呼び出す「vga_512x384_bitmap.spin」が、 刻々とサンプリングされたオーディオサンプルのポイント値をVGAビットマップに書き出している。 VGAモニタ画面は、マイクの入力サウンドをリアルタイム表示するオシロスコープとなった。 「vga_512x384_bitmap.spin」は並列処理として、このビットマップのデータをVGA画像出力している。これまでPropellerのプログラムを色々と調べたおかげで、新しいプログラムを見ても、 だいたいの予想がつくようになってきた。 A/D変換の部分については、ピンとして2本を用いて、 比較対象の信号を出力しつつ、入力とミックスして逐次比較している模様であった。
ここで新しい発見としては、2つのオブジェクトの間で定数の共有をしたい場合の書式として、 microphone_to_vga.spinの以下の部分
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 tiles = vga#xtiles * vga#ytiles tiles32 = tiles * 32 OBJ vga : "vga_512x384_bitmap"と、vga_512x384_bitmap.spinの以下の部分
CON ' 512x384 settings - signals as 1024 x 768 @ 67Hz hp = 512 'horizontal pixels vp = 384 'vertical pixels hf = 8 'horizontal front porch pixels hs = 48 'horizontal sync pixels hb = 88 'horizontal back porch pixels vf = 1 'vertical front porch lines vs = 3 'vertical sync lines vb = 28 'vertical back porch lines hn = 1 'horizontal normal sync state (0|1) vn = 1 'vertical normal sync state (0|1) pr = 35 'pixel rate in MHz at 80MHz system clock (5MHz granularity) ' Tiles xtiles = hp / 32 ytiles = vp / 32 ' H/V inactive states hv_inactive = (hn << 1 + vn) * $0101との、「#」を使った対応関係があった。 今回のシステムではVGAでなくNTSCビデオにしたいので、このライブラリを使う場合には、 VGAの部分はカットして、さらにオーディオサンプリングの部分を子オブジェクトに移動して、 Topからピーク値を参照するような構造に変更することを目指すことになるが、 ちょっとこれは簡単ではなさそうである。
2008年4月15日(火)
他にもA/D変換のようなサンプルが無いか、と調べているうちに、 というデモを発見した。 他に呼び出されているオブジェクトは、既に出て来たものなので省略した。 この「RCTIME_DEMO.spin」では、ピンに接続されたCR時定数を刻々とビデオモニタに出力する。 そこで、抵抗Rにボリュームを使うと、以下のようにアナログ値の表示のようになる。ここで驚いたのは、「RCTime.spin」の以下の部分である。 つまり、サンプリングのたびに、いったんピンを出力に設定して信号を出してコンデンサに充電し、 次にそのピンを入力に設定変更して、CR時定数により放電されて電圧がスレショルドを越えるまで待つ、 ということで計測しているのだった。
r e p e a t o u t a [ p i n ] : = s t a t e ' s e t p i n t o s t a t e d i r a [ p i n ] : = 1 ' m a k e p i n a n o u p u t t i m e . p a u s e 1 m s ( 1 ) ' a l l o w c a p t o ( d i s ) c h a r g e d i r a [ p i n ] : = 0 ' m a k e p i n a n i n p u t r c t e m p : = c n t ' g e t c u r r e n t c o u n t e r w a i t p e q ( 1 - s t a t e , | <