2008年03月11日
gauche.gongの発表で使ったプレゼン資料等を公開します。
※livedoor Blogの追記欄容量をオーバーするので、この記事は3エントリに分けました。
発表スライドの内容
※会場に向かうタクシーでKeynoteを開いて、楽屋で完成させたもの。
リンクなど追加。
自己紹介
- naoya_t@生駒山
- 文系プログラマ
- 普段は Gauche, AWK, Brainf*ck, ...
- R5RS > PIC > R6RS
最後のは愛情の大きさ順。 第一部座談会「R6RSを斬る」をスルーしてPICデモコードを書いていた自分を揶揄
事の発端
- 12月に、PICkit2 Starter Kitを買った
- PIC初心者
- ところで、gauche.gongに出たい
- Gauche+PICで何かやってみるか
某紫ログによると購入は12/29になっています。gauche.gong当日でPIC歴ちょうど100日!
苦難の道程
- PICの開発環境一式(MPASM, C, 書き込みアプリ等)がWindows専用。
- マカーです><
- → 読み書きはlibusbとpk2-3.00αで読み書き出来るよ
- → asm/disasmぐらい自分で作るか
詳しくは拙エントリ「libusbをインストール」「Mac OS Xから直接PICkit2を読み書きする」を参照のこと
asm/disasm
- PICkit2 Starter Kitに付いてる PIC16F690 の場合、命令長は14bit固定。命令数も少ないのでdisasmもasmも容易に書ける li>→デブサミ2008会場4FでひげぽんとLiveCoding
ひげぽんとはデブサミ会場でたまたま・・・
コードを見せあったりとかして良い勉強になりました。
どこまで行けるか
- 時間がとれればSchemeを実装するぐらいは行けそう
- 時間ない><
- SICP5章のregister-machineとか?
- 3軸加速度センサ使いたいけど
Scheme実装のプランはだいぶ出来ていたのですが、実装にとれる時間が限られていて断念。
バイナリデータの処理はR5RSでは処理系依存?
- Gaucheはバイナリ大丈夫だけど
- Intel HEX形式を読み書きすればいいのでこの問題はスルー
- 将来はpk2を使わずに直接読み書き?
これは楽屋のモニタでR6RSが斬られてるのを聞いていて小耳に挟んで
デモその1 - LEDを光らせる
- 表示デバイスはPICkit2 Starter Kitのボード上のLED(×4)を使う
- LED点灯用マクロとか書く
webcamのピントが合わなくて、ここで余計な時間をとってしまった><
(そのためのリハーサルですよ!)
(require "./demo-base")
(define code '(
loop
(LED #b0000 0.1) ; LEDをパターン0000で0.1秒間点灯する
(LED #b0001 0.1)
(LED #b0011 0.1)
(LED #b0010 0.1)
(LED #b0110 0.1)
(LED #b0100 0.1)
(LED #b1100 0.1)
(LED #b1000 0.1)
(LED #b0000 0.1)
(LED #b1000 0.1)
(LED #b1100 0.1)
(LED #b0100 0.1)
(LED #b0110 0.1)
(LED #b0010 0.1)
(LED #b0011 0.1)
(LED #b0001 0.1)
(LED #b0000 0.1)
(goto loop)
))
(macro-asm-test code #t #t #t 10)
デモその2 - GCD (最大公約数) を計算し、結果をLEDで2進数表示する
- LEDが4つしかないので、できれば0〜15で結果が出る演算がいい!
- fibonacciはどんどん数がでかくなる><
- GCD(最大公約数)の計算とかどうよ
fibonacciを避ける理由のもう1つ(というかそっちが最大)は、CALLスタックが8段しかないこと。自前で帰り先を積まないといけないのを今回は忌避。
計算結果(デモでは 3)が2進数 0011 で表示されるところで会場が妙に受けていた。
(require "./demo-base")
(define code '(
(alloc a)
(alloc b)
(alloc t)
(assign a 24) ; 24と15の最大子役数は?
(assign b 15)
; gcd
test-b
(test = b 0)
(branch gcd-done) ; goto gcd-done if b == 0
(assign t a) ; t = a
rem-loop
(test < t b)
(branch rem-done) ; goto rem-done if t < b
(assign t - t b) ; t = t - b
(goto rem-loop)
rem-done
(assign a b) ; a = b
(assign b t) ; b = t
(goto test-b)
gcd-done
(LED/display-reg a)
(LED/display-reg a)
(LED/display-reg a)
))
(macro-asm-test code #t #t #t 5)
デモその3 - RA0への電圧入力をA/Dで変換しLED表示。
- 時間切れ・・・ここまでか?
- 3軸加速度センサもやりたい
- 出力を内蔵A/Dコンバータで10bitデジタル値に変換し、上の方のbitを表示、とか
このコードでは上の方のbitを取らず、動かしたらLEDに反応が出るだけ。
Starter Kitボードの配線上、可変抵抗RP1を通した電流との合算値になるので適宜調整しながら。
(require "./demo-base")
(define code '(
loop
(a2d)
;; デフォルトは RA0 (=AN0) ; = #7
;; // これは可変抵抗RP1との合算なので、可変抵抗で適宜調整
;; A/D変換結果の上位8ビットが a2d-upper および Wレジスタに入る
(ADDLW #b11100111) ; W -= 11001b
(MOVWF display)
(MOVF display W)
(MOVWF PORTC))
;↑すみませんアセンブラ直書きです。インラインアセンブリっぽく
; (asm (ADDLW #b11100111) ; W -= 11001b
; (MOVWF display)
; (MOVF display W)
; (MOVWF PORTC))
;のようにも書けます。でも実は
; (assign display - a2d-upper #b11001)
; (assign PORTC display)
;と書けます。
;
(goto loop)
))
(macro-asm-test code #t #t #t 60)
あと少しで
- スタック(save/restore)の実装
- consセル(Pair)を表現するデータ形式を実装してリスト処理
- register-machineをフル実装
- call/ccの実装
目星はついているので、時間が取れ次第書きますよ!>ひげぽんほか
最後に
- 3月に会社抜けるので春から比較的暇です
- 東京に出たい
- お仕事のお誘いWelcome!!
www
ご清聴ありがとうございました。
★おまけ - デモその3の改良版
3軸加速度センサの出力をRA4から入力し、A/D変換し、加速度に応じたLEDを表示。
(require "./demo-base")
(define code '(
loop
(a2d RA4) ; AN2; 使えるのは RA1(=AN1) RA2(=AN2) RA4(=AN3) の3つ
;; RA5 RA4 RA3 RC5 RC4 RC3 RA0 RA1 RA2 RC0 RC1 RC2 +5V GND
;; - <3> - - - <7> <0> <1> <2> <4> <5> <6>
;; SW1 LED RP1 LED LED LED
(test < 213 a2d-upper)
(branch +2g)
(test < 161 a2d-upper)
(branch +1g)
(test < 113 a2d-upper)
(branch 0g)
(test < 61 a2d-upper)
(branch -1g)
-2g
(LED #b0011 0.1)
(goto loop)
-1g
(LED #b0010 0.1)
(goto loop)
0g
(LED #b0000 0.1)
(GOTO loop)
+1g
(LED #b0100 0.1)
(goto loop)
+2g
(LED #b1100 0.1)
(goto loop)
))
(macro-asm-test code #t #t #t 60)
demo-base.scm - macro-asm-test関数
(use srfi-1)
(use util.match)
(require "./macro-asm")
(require "./pic-asm")
(require "./pic-disasm")
(require "./pic-device")
(define (macro-asm-test src asm? disasm? write? runsec)
(print "-------")
;;コンパイル
(let1 asm-code (pic-macro-asm src)
(when asm?
(map asm-pp asm-code)
(print "-------"))
;;アセンブル
(let1 obj-code (pic-asm asm-code)
;;(map print obj-code)
;;(print "-------")
;;オブジェクトコードをdisasmして表示(デバッグ用)
(when disasm?
(map print (pic-disasm obj-code))
(print "-------"))
(when write?
;;オブジェクトコードをPICに書き込んで実行(5秒)
(pic-write obj-code)
;;指定した秒数だけ給電
(when (number? runsec)
(pic-on)
(sys-sleep runsec)
(pic-off))
;;delete hex-file here if you wish
))))
pic-device.scm - pk2への書き込みとか給電on/offとか
;
; オブジェクトコードをhex化して書き込み
;
(define (pic-write obj-code)
(let1 hex-file "_test.hex"
(save-obj-code obj-code hex-file)
(pic-write-hex-file hex-file)))
;
; hexファイルを書き込み
;
(define (pic-write-hex-file hex-file)
(sys-system (format "pk2 -write ~a" hex-file)))
;
; 給電ON
;
(define (pic-on) (sys-system (format "pk2 -on")))
;
; 給電OFF
;
(define (pic-off) (sys-system (format "pk2 -off")))
;
; オブジェクトコードを書き込んで走らせる
;
(require "./intelhex")
(define (pic-run obj-code name sec)
(let1 hex-file (string-append name ".hex")
(save-obj-code obj-code hex-file)
(pic-write-hex-file hex-file)
(pic-on)
(sys-sleep sec)
(pic-off)
;delete hex-file here
))
>>gauche.gong発表資料2(asm/disasm)へ
>>gauche.gong発表資料3(マクロアセンブラ)へ
(12:34)


