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時定数により放電されて電圧がスレショルドを越えるまで待つ、 ということで計測しているのだった。
repeat outa[pin] := state ' set pin to state dira[pin] := 1 ' make pin an ouput time.pause1ms(1) ' allow cap to (dis)charge dira[pin] := 0 ' make pin an input rctemp := cnt ' get current counter waitpeq(1-state,|< pin, 0) ' wait for state change on pin rctemp := || (cnt - rctemp) ' calculate duration rctemp := rctemp - 1600 ' adjust for instructions (for zero) rctemp := rctemp >> 4 ' scale value (divide by 16) long [rcvalueaddress] := rctemp ' move result to targetPropellerはピンが基本的に単独(シリアル)であること、 そして各Cogに仕事を割り振ってしまえば、 それぞれがいかに冗長に待っていても全体のパフォーマンスに関係ないこと、 を考えればうまい手であるが、まだまだこの発想は思い付かなかった。
「A/D変換のためには外部にV-Fコンバータを」という構想についても、 これは間違いではないが、Propellerのシステムでは、同じピンを双方向に使う、 というこのサンプルのような発想をすれば、外付けのV/Fコンバータ回路なども省略できそうである。 汎用センサ(電圧出力)に対応したA/D変換というよりも、 センサごとに特化して、センサデバイスによくある抵抗値変化をこの方法で検出するなど、 センシング手法を考えた方がよさそうである。
2008年4月16日(水)
ビデオでなくVGA出力である「microphone_to_vga.spin」だが、 マイクの感度を上げてみると以下のように綺麗にサウンドが表示される。これは「音センサ」としても捨て難いので、無謀と分かっていながら、 ここからビデオ出力への改造に挑戦してみた。 Propeller Toolでメモリ使用状況を見ると、以下のように、 VGA出力のためのグラフィックメモリとして共有RAMの大部分を使用している。
これでは既存のビデオ出力オブジェクト群と統合しただけで、 「メモリが足りません」と叱られてコンパイルが失敗するのは確実である。 それを承知で、Propeller Demo Boardに対応した過去のオブジェクトを発掘して、 とりあえずエラーが出ないところまで、グラフィックメモリの割り当てを無理矢理に削減して、 「何か動く」ものを作ってみた。 以下のように、ビデオモニタとVGAモニタの両方に、サウンド入力に対応して動く何かが出ているが、 音圧がオーバーフローすると、ビデオ出力は真っ黒に昇天する。(^_^;)
このTopオブジェクトは microphone_001.spin であり、冒頭のCON領域の定義で、
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 tiles = vga#xtiles * vga#ytiles tiles32 = tiles * 8と、本来は32倍しなければならない領域を8倍と、 1/4のサイズに無理矢理に抑えることで、コンパイルに通るメモリサイズとしている。 そのため、プログラムは勝手にこの上のアドレス領域もどんどん更新していくので、 ビデオ出力画面にも何かノイズのようなものが出て、それがマイクの音量とともに幅を変化させている。 きちんと領域確保・初期化できていないので、VGA出力もヘンになっていて、 音量が大きくなると色々な矩形が現れて、まぁ暴走による現象ではあるが、 インスタ的にも面白いことになった。 かなり無謀であるが、とりあえずここをスタートラインとした。 暴走しても「F10」で一瞬にして簡単にリトライできるからこそ、の実験である。
・・・あれこれ実験してみて、とりあえずマイクからの音に反応して、 ビデオモニタにサウンドのピーク値(閾値を越えたものだけ)を数字で表示する、 というものが出来た。それが microphone_002.spin である。 ここでは以下のように、Topオブジェクト中でサウンド追従のアセンブラルーチンと、 それをメインとして無限ループで呼び出すものの両方が入っているので、 他のモジュールと組み合わせるには適していないが、「サウンドセンサ」として使える、 という事を検証できた。
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 bits = 14 'try different values from table here attenuation = 0 'try 0-4 averaging = 13 '2-power-n samples to compute average with OBJ Num : "E_Numbers02" TV : "E_TV_Terminal02" VAR long mic PUB start | i,dummy, para, p1 Num.Init { Num.Init MUST be called before first object use. } para := TV.Start1(12) dummy := TV.Start2 TV.out(0) { display home } TV.Str(string("TV_port_Cog =")) TV.Str(Num.ToStr(para, Num#DEC)) TV.Str(string(", Graphic_driver_Cog =")) TV.Str(Num.ToStr(dummy, Num#DEC)) cognew(@asm_entry, @mic) repeat dummy := mic if(dummy <> p1) para := dummy - 260 if(para > 0) TV.Str(Num.ToStr(para, Num#DEC)) p1 := dummy DAT org asm_entry mov dira,asm_dira 'make pin 8 (ADC) output movs ctra,#8 'POS W/FEEDBACK mode for CTRA movd ctra,#9 movi ctra,#%01001_000 mov frqa,#1 mov asm_cnt,cnt 'prepare for WAITCNT loop add asm_cnt,asm_cycles :loop waitcnt asm_cnt,asm_cycles 'wait for next CNT value (timing is determinant after WAITCNT) mov asm_sample,phsa 'capture PHSA and get difference sub asm_sample,asm_old add asm_old,asm_sample add average,asm_sample 'compute average periodically so that djnz average_cnt,#:avgsame 'we can 0-justify samples mov average_cnt,average_load shr average,#averaging mov asm_justify,average mov average,#0 'reset average for next averaging :avgsame max peak_min,asm_sample 'track min and max peaks for triggering min peak_max,asm_sample djnz peak_cnt,#:pksame mov peak_cnt,peak_load mov x,peak_max 'compute min+12.5% and max-12.5% sub x,peak_min shr x,#3 mov trig_min,peak_min add trig_min,x mov trig_max,peak_max sub trig_max,x mov peak_min,bignum 'reset peak detectors mov peak_max,#0 :pksame cmp mode,#0 wz 'wait for negative trigger threshold if_z cmp asm_sample,trig_min wc if_z_and_c mov mode,#1 if_z jmp #:loop cmp mode,#1 wz 'wait for positive trigger threshold if_z cmp asm_sample,trig_max wc if_z_and_nc mov mode,#2 if_z jmp #:loop sub asm_sample,asm_justify 'justify sample to bitmap center y sar asm_sample,#attenuation 'this # controls attenuation (0=none) add asm_sample,#384 / 2 mins asm_sample,#0 maxs asm_sample,#384 - 1 wrlong asm_sample,par jmp #:loop asm_cycles long |< bits - 1 'sample time asm_dira long $00000200 'output mask average_cnt long 1 peak_cnt long 1 peak_load long 512 mode long 0 bignum long $FFFFFFFF average_load long |< averaging asm_justify res 1 trig_min res 1 trig_max res 1 average res 1 asm_cnt res 1 asm_old res 1 asm_sample res 1 asm_mask res 1 asm_data res 1 x res 1 y res 1 peak_min res 1 peak_max res 1ここで部品が届いたので、Propeller Demo Boardでなく、 オリジナルの実験試作ボードの方に、マイク入力回路と、 サンプルにあったCR時定数回路の可変RのところにCdSを使って、 いずれも搭載してみることにした。 既にピンとして確定しているのは、
である。 マイク入力には2本、CR時定数の計測には1本が必要なので、ここでは
- P8/9/10 - ビデオ出力(A)
- P12/13/14 - ビデオ出力(B) - Propeller Demo Boardと同じ
- P24/25 - Audio出力(ステレオ)
- P26 - MIDI Output
- P27 - MIDI Input
- P28/29 - シリアルEEPROM用
- P30/31 - ホスト接続用
としてみた。 回路図はいずれもParallax社のサンプルをそのまま参考にして、 ピン(ポート)番号だけオリジナルとして、以下のようになった。
- P15 - CR時定数(Cds照度センサ)
- P16/17 - マイク入力
回路そのものは簡単なので、まずは microphone_002.spin をコピーしてリネームした「microphone_003.spin」を作って、 以下の赤字の部分だけを変更してみると、見事にマイク入力でビデオ画面に数値を表示した。
・・・ DAT org asm_entry mov dira,asm_dira 'make pin 8 (ADC) output movs ctra,#16 'POS W/FEEDBACK mode for CTRA movd ctra,#17 movi ctra,#%01001_000 mov frqa,#1 mov asm_cnt,cnt 'prepare for WAITCNT loop add asm_cnt,asm_cycles ・・・ asm_cycles long |< bits - 1 'sample time asm_dira long $00020000 'output mask average_cnt long 1 ・・・また、CdSをセンサ(可変抵抗)としたRC時定数センサについても、 RCTIME_DEMO.spin をコピーしてリネームした「RCTIME_001.spin」を作って、 以下の赤字の部分だけを変更してみると、見事にCdSの照度に対応してビデオ画面に数値を表示した。
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 = 5 thickness = 2 VAR long tv_status '0/1/2 = off/visible/invisible read-only long tv_enable '0/? = off/on write-only long tv_pins '%ppmmm = pins write-only long tv_mode '%ccinp = chroma,interlace,ntsc/pal,swap write-only long tv_screen 'pointer to screen (words) write-only long tv_colors 'pointer to colors (longs) write-only long tv_hc 'horizontal cells write-only long tv_vc 'vertical cells write-only long tv_hx 'horizontal cell expansion write-only long tv_vx 'vertical cell expansion write-only long tv_ho 'horizontal offset write-only long tv_vo 'vertical offset write-only long tv_broadcast 'broadcast frequency (Hz) write-only long tv_auralcog 'aural fm cog write-only long colors[64] word screen[x_tiles * y_tiles] byte x[lines] byte y[lines] byte xs[lines] byte ys[lines] long RCValue OBJ tv : "tv" gr : "graphics" RC : "RCTIME" Num : "Numbers" PUB start | i,dx,dy 'start tv longmove(@tv_status, @tvparams, paramcount) tv_screen := @screen tv_colors := @colors tv.start(@tv_status) 'init colors repeat i from 0 to 64 colors[i] := $00001010 * (i+4) & $F + $2B060C02 'init tile screen repeat dx from 0 to tv_hc - 1 repeat dy from 0 to tv_vc - 1 screen[dy * tv_hc + dx] := display_base >> 6 + dy + dx * tv_vc + ((dy & $3F) << 10) 'start and setup graphics gr.start gr.setup(16, 12, 128, 96, bitmap_base) 'Initialize RCValue RCValue := 0 RC.start(15,1,@RCValue ) repeat 'clear bitmap gr.clear 'draw text gr.textmode(1,1,7,5) gr.colorwidth(1,0) gr.text(0,90,string("Parallax RCTIME background demo")) 'display text of RCtime value gr.text(0,50,Num.ToStr(RCValue, 10)) 'copy bitmap to display gr.copy(display_base) DAT tvparams long 0 'status long 1 'enable 'long %011_0000 'pins Old Board long %001_0101 'pins New Board long %0000 'mode long 0 'screen long 0 'colors long x_tiles 'hc long y_tiles 'vc long 10 'hx long 1 'vx long 0 'ho long 0 'vo long 60_000_000'_xinfreq<<4 'broadcast long 0 'auralcogこれで、とりあえず以下のように、Propeller Demo Boardでなく、 自前のハードウェアで、コンデンサマイクによるサウンドのセンサと、 CdSによる明るさセンサ(CR時定数計測)が実際に動いた。
ただし、それぞれ単独・完結したサンプルプログラムそのもので走っているので、 これまでオリジナル開発してきたオブジェクトと同様に、 このセンサ部分のソフトウェアを解析・改造して、 ライブラリとして「ソフトウェア部品」化する必要がある。 これは明日以降の課題としよう。
2008年4月17日(木)
1限から大学院の講義、午後には連続して会議、とロクにまとまった時間が取れないので、 ハードウェア実験でなく、昨日の宿題のソフトウェア改造の作業を合間に進めることにした。 この時点で、作業ディレクトリは以下のようになっている。ドライブ C のボリューム ラベルは ACER です ボリューム シリアル番号は 8861-32F2 です C:\Propeller のディレクトリ 04/17/2008 11:09 AM DIR . 04/17/2008 11:09 AM DIR .. 04/07/2008 04:20 PM DIR Archive 03/28/2008 11:36 AM 6,370 AudioOut06.spin 02/28/2008 11:31 AM DIR CDROM 02/18/2008 11:18 AM DIR Education 04/15/2008 06:16 PM 1,078 exp101.spin 03/30/2008 02:51 PM 117,356 E_Graphics01.spin 03/30/2008 03:51 PM 117,340 E_Graphics02.spin 04/07/2008 03:40 PM 64,424 E_Graphics03.spin 03/30/2008 01:29 PM 9,340 E_Numbers01.spin 03/30/2008 01:29 PM 9,340 E_Numbers02.spin 03/30/2008 02:51 PM 28,563 E_TV01.spin 03/30/2008 03:51 PM 28,555 E_TV02.spin 03/30/2008 02:51 PM 4,642 E_TV_Terminal01.spin 03/30/2008 04:17 PM 4,701 E_TV_Terminal02.spin 02/16/2006 09:00 AM 60,594 Graphics.spin 04/02/2008 02:25 PM DIR kari 02/18/2008 04:22 PM DIR Library 03/10/2008 12:51 PM DIR Manuals 04/16/2008 12:58 PM 4,201 microphone_001.spin 04/15/2008 06:35 PM 6,322 microphone_001_tmp.spin 04/16/2008 01:00 PM 4,201 microphone_002.spin 04/16/2008 04:22 PM 4,202 microphone_003.spin 06/09/2006 01:34 AM 6,446 microphone_to_vga.spin 03/19/2008 08:13 AM 3,645 MidiIn03.spin 03/19/2008 04:55 PM 2,727 MidiOut01.spin 02/15/2006 07:54 PM 42,946 Numbers.spin 04/07/2008 04:23 PM 4,568 proto003.spin 03/07/2006 02:19 PM 4,756 RCTime.spin 02/19/2006 11:53 PM 9,856 RCTIME_DEMO.spin 03/07/2006 02:02 PM 1,510 Timing.spin 11/16/2005 05:17 PM 28,312 tv.spin 06/06/2006 10:51 PM 8,873 vga_512x384_bitmap.spin 27 個のファイル 594,726 バイト 8 個のディレクトリ 68,108,861,440 バイトの空き領域この中で、ソフトウェア部品として確定しているオブジェクト類は、以下である。
- AudioOut06.spin
- E_Graphics02.spin
- E_Graphics03.spin
- E_Numbers02.spin
- E_TV02.spin
- E_TV_Terminal02.spin
- MidiIn03.spin
- MidiOut01.spin
また、スタンドアロンとして動作する(Topとなる)オブジェクト類は、以下である。
- microphone_003.spin
- exp101.spin
- proto003.spin
- RCTIME_DEMO.spin
全てを同時に1つのシステムに混在させるのは、Cogsの制限を越えるので無理であるが、 仕様に応じて自在に取捨選択できるようにしたい、という戦略である。 いま対象としているのは、「microphone_003.spin」「RCTIME_001.spin」の2つであるが、 いずれもTopオブジェクト内でアセンブラの無限ループによりセンシングしているがので、 これをTopから呼ばれる子プロセスに改造する、という事になる。
まずは、センサ情報をテキスト表示させるために、 exp101.spinをコピーしてリネームしたexp102.spinを使うことにした。 ここからは、ビデオ出力にフルグラフィック表示するために削減改造したE_Graphics03.spinでなく、 E_TV_Terminal02.spinを参照するE_Graphics02.spinを呼び出している。 追加機能として、表示テキストの色のパラメータを持たせたので、 マイクの音響センサを緑色で、CdSのCR時定数センサを赤色で表示することにした。
いくつかの実験の結果として、Topとして「exp102.spin」に対して、
というソフトウェアを完成した。 動作状況は以下のようなもので、マイクの音響とCdsの照度の両方をセンシング表示している。 ここにバックグラウンド処理としてMIDIの入出力を加えたとしても、センシングの処理能力が低下しない、 というのがPropellerの強味である。「exp102.spin」のメイン処理の部分は以下のようになっていて、 それぞれのセンサに対してデータをポーリングしているが、 データの取得方法は異なっている。
OBJ mic : "microphone_004" RC : "RCtime001" VAR long RCValue PUB Main | dummy, para, p1, p2 Num.Init { Num.Init MUST be called before first object use. } para := TV.Start1(12) dummy := TV.Start2 TV.out(0) { display home } TV.Str(string("TV_port_Cog =")) TV.Str(Num.ToStr(para, Num#DEC)) TV.Str(string(", Graphic_driver_Cog =")) TV.Str(Num.ToStr(dummy, Num#DEC)) dummy := mic.start TV.Str(string(", microphone_Cog =")) TV.Str(Num.ToStr(dummy, Num#DEC)) RCValue := 0 dummy := RC.start(15,1,@RCValue ) TV.Str(string(", RCtime_Cog =")) TV.Str(Num.ToStr(dummy, Num#DEC)) repeat dummy := mic.input(350) if(dummy <> p1) if(dummy > 0) TV.gr_test(1) TV.Str(Num.ToStr(dummy, Num#DEC)) p1 := dummy dummy := RCValue if(dummy <> p2) if(dummy > 2000) TV.gr_test(2) TV.Str(Num.ToStr(dummy, Num#DEC)) p2 := dummy「microphone_004.spin」の方では、以下のような処理に対応して、 Topからメソッドを呼び出した返り値として取得している。 つまり、「microphone_004.spin」の中に定義したlong変数micに、 アセンブラルーチン中でPARレジスタにより指定したwrlong命令で書き込んで、 これをメソッドinputの返り値としている。 Propellerアセンブラで子メソッドを記述する場合の典型例である。
VAR long mic PUB start return cognew(@asm_entry, @mic) PUB input(level) : result result := (mic - level) #> 0 DAT org asm_entry ・・・ wrlong asm_sample,par jmp #:loopそれに対して「RCTIME_001.spin」では、以下のような処理に対応して、 メソッドrctimeに与えるパラメータとして、 返り値を格納する変数のアドレス(ポインタ)を指定している。 Topオブジェクト内に定義したlong変数RCValueをこれで与えて、 結果としてRCValueに入った値を読み出している。 spin言語で子メソッドを記述する場合の典型例である。
PUB start(pin, state, rcvalueaddress) return cognew(rctime(pin, state, rcvalueaddress), @rcstack) PUB rctime(pin, state, rcvalueaddress) repeat outa[pin] := state ' set pin to state dira[pin] := 1 ' make pin an ouput pause1ms(1) ' allow cap to (dis)charge dira[pin] := 0 ' make pin an input rctemp := cnt ' get current counter waitpeq(1-state,|< pin, 0) ' wait for state change on pin rctemp := || (cnt - rctemp) ' calculate duration rctemp := rctemp - 1600 ' adjust for instructions (for zero) rctemp := rctemp >> 4 ' scale value (divide by 16) long [rcvalueaddress] := rctemp ' move result to target比較的短時間で、2種類の異なったバックグラウンド処理をソフトウェア部品として切り出すことができた。 ようやく、Propellerのソフトウェアもちょっと身近になってきたようである。 まだこの「exp102.spin」はテキスト表示の暫定システムなので、 次にはいよいよ、2画面ビデオ出力グラフィクスとこのセンサ群を組み合わせていくことになる。
2008年4月18日(金)
この日は新学期の最初のゼミなどがあったが、午後にまとまった時間があったので、 音楽情報科学研究会の予稿 を一気に作ってしまった。 長いことAKI-H8で止まっていたマイコンの話題が、 ここでPropellerの紹介とともにいよいよ新展開することになる。 末尾にはこの日記のURLも書いたので、発表とともにWeb公開となる。 トラ技の末尾の参考文献には、逆にこの音情研の資料をreferするつもりである。2008年4月24日(木)
今週は、月曜日と火曜日は講義があり、 火曜日の午後から東京に行ってサントリーホールのコンサートで1泊。 ・・・などとあまり時間が取れない。 実験は進んでいないが、トラ技の記事を書き始めてみると、 Propellerの説明だけで分量に達してしまいそうで、悩ましい。 製作記事の余地を残してPropellerをいかに説明するか、 これはけっこう、大変かもしれない。2008年5月10日(土)
前回の日記から2週間ほど経過した。この間に、「とりあえず」版(途中まで)をトラ技に送ったり、 急逝した父の葬儀で9日ほど筑波に滞在したりして、 Propellerについてはまったくストップしていた。 編集部からのメイルで「既に超過している」とのことで(^_^;)、 これまでに書いた原稿から削減しつつ、単発のまとめた記事にする、 という作業である。
また、Sketching in Hardware08 の招待も来たので、 Propellerネタをアメリカで発表することになりそうである。 トラ技と、学会発表と、Sketchingと、さらに大学院での研究と、 すべて同時進行で効率良くやっていこう。
2008年5月11日(日)
これまでに制作した実験システムを融合させて、ビデオインスタレーションとなる雛形を作った。 迷ったのは、Cogsの制約でどの機能を残してどの機能を捨てるか、であった。 最終的には、子プロセスとしてを使用して、グラフィックは独立2画面描画とし、 センサにはサウンド(マイク)と照度(CdS)、 そして外部インターフェースはMIDI出力を採用した。
- E_Graphics03.spin
- E_TV02.spin
- MidiOut01.spin
- microphone_004.spin
- RCtime001.spin
とりあえず、グラフィックのプログラミング以前の、 動作確認のための「proto005.spin」は以下である。
{{ proto005.spin }} CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 _stack = ($3000 + $3000 + 190) >> 2 'accomodate display memory and stack x_tiles = 16 y_tiles = 12 x_origin = 128 y_origin = 96 bitmap_base1 = $2000 bitmap_base2 = $5000 VAR long tv_status1, tv_enable1, tv_pins1, tv_mode1, tv_screen1, tv_colors1 long tv_hc1, tv_vc1, tv_hx1, tv_vx1, tv_ho1, tv_vo1, tv_broadcast1, tv_auralcog1 long tv_status2, tv_enable2, tv_pins2, tv_mode2, tv_screen2, tv_colors2 long tv_hc2, tv_vc2, tv_hx2, tv_vx2, tv_ho2, tv_vo2, tv_broadcast2, tv_auralcog2 long colors[64] word screen1[x_tiles * y_tiles], screen2[x_tiles * y_tiles] long RCValue OBJ midiOut : "MidiOut01" tv[2] : "E_TV02" gr[2] : "E_Graphics03" mic : "microphone_004" RC : "RCtime001" PUB start | i, k, dx, dy, dummy, para, dark, p1, p2 midiOut.start(26) longmove(@tv_status1, @tvparams, 14) tv_screen1 := @screen1 tv_colors1 := @colors tv[0].start(@tv_status1) longmove(@tv_status2, @tvparams, 14) tv_status2[2] += %0101 tv_screen2 := @screen2 tv_colors2 := @colors tv[1].start(@tv_status2) gr[0].setup(x_tiles, y_tiles, x_origin, y_origin, bitmap_base1) gr[1].setup(x_tiles, y_tiles, x_origin, y_origin, bitmap_base2) a mic.start RCValue := 0 RC.start(15,1,@RCValue ) para := 1 repeat dx from 0 to tv_hc1 - 1 repeat dy from 0 to tv_vc1 - 1 screen1[dy * tv_hc1 + dx] := bitmap_base1 >> 6 + dy + dx * tv_vc1 + ((dy & $3F) << 10) screen2[dy * tv_hc1 + dx] := bitmap_base2 >> 6 + dy + dx * tv_vc1 + ((dy & $3F) << 10) repeat i from 0 to 63 colors[i] := $00001010 * ( (i+4) & $F ) + $2B060C02 repeat k++ if ++dark > 123 dark := 0 gr[0].clear gr[1].clear 'draw spinning triangles gr[0].colorwidth(3,0) gr[1].colorwidth(para,0) repeat i from 1 to 8 gr[0].vec(0, 0, (k & $7F) << 3 + i << 5, k << 6 + i << 8, @vecdef) gr[1].vec(0, 0, (k & $7F) << 3 + i << 5, k << 6 + i << 8, @vecdef) 'draw expanding pixel halo gr[1].colorwidth(1,k) gr[1].arc(0,0,80,30,-k<<5,$2000/9,9,0) 'draw spinning stars gr.colorwidth(dark/30+1,0) repeat i from 0 to 7 gr[0].vecarc(0,0,30,30,-(i<<10+k<<6),$A0,-(k<<7),@vecdef2) dummy := mic.input(350) if(dummy <> p1) if(dummy > 0) midiOut.fifoset($B00000 + (dummy & $7F)) gr[0].clear gr[1].clear p1 := dummy dummy := RCValue if(dummy <> p2) if(dummy > 2000) para := (dummy/20) & $7F midiOut.fifoset($B00100 + para) colors[i] := para * ( (i+4) & $F ) + $2B060C02 p2 := dummy DAT tvparams long 0 'status long 1 'enable long %001_0000 'pins --- 8..10=[001_0000] , 12..14=[001_0101] long %0000 'mode long 0 'screen long 0 'colors long x_tiles 'hc long y_tiles 'vc long 10 'hx long 1 'vx long 0 'ho long 0 'vo long 0 'broadcast long 0 'auralcog vecdef word $4000+$2000/3*0, 50, $8000+$2000/3*1+1, 50 word $8000+$2000/3*2-1, 50, $8000+$2000/3*0, 50 word 0 vecdef2 word $4000+$2000/12*0, 50, $8000+$2000/12*1, 20 word $8000+$2000/12*2, 50, $8000+$2000/12*3, 20 word $8000+$2000/12*4, 50, $8000+$2000/12*5, 20 word $8000+$2000/12*6, 50, $8000+$2000/12*7, 20 word $8000+$2000/12*8, 50, $8000+$2000/12*9, 20 word $8000+$2000/12*10, 50, $8000+$2000/12*11, 20 word $8000+$2000/12*0, 50 word 0これで、サウンド入力イベントで画面をとりあえずリフレッシュすること、 照度の変化で「何かが起きる」こと、 それらの情報をMIDI出力すること、を確認した。 MIDI入力で色々なパラメータを与えた方が自由度は大きくなるが、 インスタレーションとしては、センサのイベントでグラフィクスが変化するとともに、 何かのサウンドが発生することが重要と考えて、 これをMIDI出力して、Max/MSPで自在にサウンド生成する、という方針とした。
2008年5月18日(日)
これまでデスクトップ機だったホストを、Sketch03で海外に持ち出してプログラミングするために、 小型のWindowsノートに移行した。このページ のどこかに写真がさりげに載っている。(^_^;)
2008年5月21日(水)
本日でこの「Propeller日記」はおしまいである。 トラ技の記事の原稿はまだ続いているが、それ以外の状況の進展としては 以下のようなカンジになってきた。 なので、今後は別のWebページで、もっとPropellerを紹介していくことになる。
- 日本音楽知覚認知学会での発表で紹介(5/24)
- 音楽情報科学研究会での発表で紹介(5/28)
- Sketch03で紹介(6/25-27、米国RISD)
- 音情研・夏シンポで詳細紹介(8/6-8)
- FIT2008で紹介(9/2-4)
- RFIDのリーダ製作予定(ゼミの学生作品)
- オープンキャンパス/MAF2008でのインスタレーション作品に応用(12画面ディスプレイ)
- A/D変換回路のアイデアあり
- D/A変換回路のアイデアあり
- etc (乞う御期待)
たまたま知ったプロセッサであるが、もうしばらくは付き合ってみたいと思う。