成安造形大学コラボレーション・プロジェクト
アーティストのための汎用センサ自作応援講座
2001年1月 長嶋洋一
第4話
さて、
第3話
の続きです。
まだパネルのA/D入力コネクタとボリュームの配線が残っていましたが、
まずはそれ以外の部分、つまりLEDを点滅させるとか、そもそもAKI-H8の
ソフトを開発してダウンロードする、という事ができる確認をしていなかった
ので、とりあえず準備を始めました。
これ
は、いつも並んでいるPowerBookとDynaBookに加えて、もう1台の
PowerBook2400cを出してきたところです。DynaBookは単なる「台」です。
手前右にあるのが、初期のAKI-H8キットには付属していないために、
マニュアルの回路図を参考に自作したAKI-H8ライタです。これについて
は、
このあたり
に記載されていますので、参考にして下さい。ちかぢか、AKI-H8キットに
付属しているライタを製作して紹介したいと思っていますので、
これをわざわざこれから自作する必要はないでしょう。ライタ上の
AKI-H8ソケットのCN4の全ピンをそのまま延長しています。
これ
が、自作AKI-H8ライタのコネクタ面で、同一構成のハード(MIDIを
行うぐらい)であれば、ここにAKI-H8を挿してプログラムしてしまい、
完成したAKI-H8を「部品」として製作に使います。この基板上には、
MIDIの回路も標準で載っているというのがウリです。(^_^)
これ
は、AKI-H8ライタから延長したケーブルの接続部分です。
そして、基本的なLED点滅とMIDI送りの動作を確認したあとで、
このように
パネルのコネクタとボリュームからの配線を行いました。
空中配線みたいなものですが、まぁこんなものです。これを配線すると、
もうマスター基板の裏の配線を修正したりするのは苦しくなりますので、
手順を踏んで進めていく必要があります。
実際のところを言えば、AKI-H8ライタから電源を供給している
時には起きなかったのに、ケースに内蔵したGORILLAに切り換えると、
A/Dデータが細かく変動する、というトラブルが発生しました。
オシロで追跡して電源による発振のようなノイズが混入している事を
確認し、この基板の裏側にA/Dラインごとにローパスフィルタとして
105を取り付けました。残り4セットは配線前だったのですが、
最初のテスト機だけは、この配線をした後での空中配線として
苦労しました。そういう事も、まぁ、あります。(^_^;)
ここではあまり詳しい事は説明しませんが、このマシンは、かなり
「AKI-H8による汎用のアナログ--MIDIインターフェース」として機能
すると思いますので、ここで忘れないうちに記録として残すことに
しましょう。興味のある方はどうぞ製作してみて下さい。
まず、回路図ですが、
これ
が全てです。製作のメモとして、コネクタ等のピン配置もあとから
書き込みました。この1枚だけで製作しました。あとの辻褄は、ソフト
で合わせる、という事になります。(^_^;)
この回路図を上から簡単に解説すると、コネクタCN2の7本のA/D入力
を割り当てています。ボリューム以外の全ての入力には、アナログライン
とGNDとの間に100Kと105を入れてフィルタとします。ボリューム(100K)の
ところは105だけで十分です。
その下の3つは、それぞれP1、P2、P3というポートの下位4ビットだけと
いうリッチな使い方(^_^;)で、4ビットDIPスイッチの状態を入力して
います。各データは10Kとか4.7Kの集合抵抗で+5Vにプルアップ
しておきます。つまりOFFでHI、ONでLOWですので、入力してから
ソフトで全ビットを反転します。
いちばん下の部分は、MIDI出力とパネルLEDの点滅のためのポートです。
さて、気になるソフトですが、解説は省略しますが、ソースもオブジェクトも
ここにドカンと公開します。(^_^) まずはソースプログラム。あまり美しくない
のですが、まぁ開発期間が2時間ほどの手抜きですので御容赦下さい。(^_^;)
;-----------------------------------------------------------
;
; 7 channel universal A/D to MIDI : Jan. 2000
;
;-----------------------------------------------------------
;##### Port Defines #####
smr .equ h'0fffb0
brr .equ h'0fffb1
scr .equ h'0fffb2
tdr .equ h'0fffb3
ssr .equ h'0fffb4
rdr .equ h'0fffb5
p1ddr .equ h'0fffc0
p1dr .equ h'0fffc2
p2ddr .equ h'0fffc1
p2dr .equ h'0fffc3
p3ddr .equ h'0fffc4
p3dr .equ h'0fffc6
p4ddr .equ h'0fffc5
p4dr .equ h'0fffc7
p5ddr .equ h'0fffc8
p5dr .equ h'0fffca
addrah .equ h'0fffe0
addrbh .equ h'0fffe2
addrch .equ h'0fffe4
addrdh .equ h'0fffe6
adcsr .equ h'0fffe8
adcr .equ h'0fffe9
iprb .equ h'0ffff8
tstr .equ h'0fff60
tsnc .equ h'0fff61
tmdr .equ h'0fff62
tfcr .equ h'0fff63
toer .equ h'0fff90
tocr .equ h'0fff91
tcr0 .equ h'0fff64
tior0 .equ h'0fff65
tier0 .equ h'0fff66
tsr0 .equ h'0fff67
tcnt0 .equ h'0fff68
gra0 .equ h'0fff6a
grb0 .equ h'0fff6c
;##### Vector Defines #####
.section vector,data,locate=h'000000
.data.l start
.org h'000060
.data.l int_timer0
;##### Work RAM Data Defines #####
.section ram,data,locate=h'0fef10
timer1 .res.w 1
timer2 .res.w 1
timer3 .res.w 1
tx_top .res.w 1
tx_end .res.w 1
data .res.b 1
counter .res.b 1
led .res.b 1
ad_status .res.b 1
ad_no .res.b 1
ad_data .res.b 8
channel .res.b 1
flag .res.b 1
offset .res.b 1
.org h'0ff800
tx_fifo .res.b 1024
;***** Constant Table Defines *****
.section rom,data,locate=h'001000
.data.w 500,250,200,150,125,100,80,75,67,50,40,30,25,20,15,10
;***** Reset --> Initialize --> Main Loop *****
.section program,code,locate=h'002000
start:
mov.l #h'0fff0f,er7 ; stack pointer set
mov.l #h'0fef10,er2
mov.w #h'0fe0,r1
mov.b #0,r0l
_ram_clear:
mov.b r0l,@er2
inc.l #1,er2
dec.w #1,r1
bne _ram_clear
jsr @sci0_init ; SCI initialize
mov.b #b'00100011,r0l
mov.b r0l,@tcr0 ; Timer0 init : 2MHz clock
bclr #0,@tsr0 ; Clear IMFA
bset #0,@tier0 ; timer INT set
mov.w #1999,r0 ; 1msec INT
mov.w r0,@gra0
mov.b #0,r0l
mov.b r0l,@p1ddr ; set : Port[1] all input
mov.b #0,r0l
mov.b r0l,@p2ddr ; set : Port[2] all input
mov.b #0,r0l
mov.b r0l,@p3ddr ; set : Port[3] all input
mov.b #0,r0l
mov.b r0l,@p4ddr ; set : Port[4] all input
mov.b #b'11111111,r0l
mov.b r0l,@p5ddr ; set : Port[5] all output
jsr @wait_500msec
jsr @dip_scan
bset #0,@tstr ; timer start !
mov.b #0,r0l
mov.b r0l,@ad_no
bset.b #3,r0l
mov.b r0l,@adcsr ; A/D stop
bclr.b #7,@adcr ; TRGE = 0
mov.b #b'00100000,r0l ; tx/rx start !
mov.b r0l,@scr
andc.b #b'01111111,ccr ; interrupt enable
loop:
jsr @ad_check
jsr @timer_check
jsr @tx_midi_check
jmp @loop
;***** DIP SW check *****
dip_scan:
mov.b @p1dr,r1l ; input DIP SW to Port[1]
xor.b #b'11111111,r1l
and.b #b'00001111,r1l
shll.b r1l
mov.b #b'00010000,r1h
mov.w #0,e1
mov.w @er1,r0 ; sampling rate table
mov.w r0,@timer3 ; set to [timer3] (A/D sampling rate)
mov.b @p2dr,r0l ; input DIP SW to Port[2]
xor.b #b'11111111,r0l
and.b #b'00001111,r0l
mov.b r0l,@channel ; set to [channel]
mov.b @p3dr,r0l ; input DIP SW to Port[3]
xor.b #b'11111111,r0l
and.b #b'00001111,r0l
shll.b r0l
shll.b r0l
shll.b r0l
mov.b r0l,@offset ; set to [offset]
rts
;***** A/D Check Routine *****
ad_check:
btst.b #7,@adcsr ; A/D conv end ?
bne _ad_go
rts
_ad_go:
mov.b @ad_no,r0l
mov.b r0l,r4l ; [r4l] = Data channel
cmp.b #0,r0l
beq _ad_1
cmp.b #4,r0l
beq _ad_1
cmp.b #1,r0l
beq _ad_2
cmp.b #5,r0l
beq _ad_2
cmp.b #2,r0l
beq _ad_3
cmp.b #6,r0l
beq _ad_3
cmp.b #3,r0l
beq _ad_4
cmp.b #7,r0l
beq _ad_4
_ad_1:
mov.b @addrah,r3h ; Get A/D data
bra _ad_next
_ad_2:
mov.b @addrbh,r3h ; Get A/D data
bra _ad_next
_ad_3:
mov.b @addrch,r3h ; Get A/D data
bra _ad_next
_ad_4:
mov.b @addrdh,r3h ; Get A/D data
bra _ad_next
_ad_next:
inc.b r0l
and.b #b'00000111,r0l
mov.b r0l,@ad_no
cmp.b #7,r0l
beq _ad_more
bset.b #3,r0l
mov.b r0l,@adcsr ; A/D channel = 0
bset.b #5,@adcsr ; next A/D start !
_ad_more:
extu.w r4
extu.l er4
shlr.b r3h ; R3H = now
mov.b r3h,r3l ; --> r3l
mov.b @(ad_data,er4),r2h ; R2H = old
cmp.b r2h,r3l ; r3l-r2h
bmi _minus ; if minus
sub.b r2h,r3l ; r3l-r2h -> r3l
cmp.b #2,r3l ; r3l>2 ?
bpl _ad_ok
rts
_minus:
sub.b r3l,r2h ; r2h-r3l -> r2h
cmp.b #2,r2h ; r2h>2 ?
bpl _ad_ok
rts
_ad_ok:
mov.b r3h,@(ad_data,er4) ; now -> old
mov.b @channel,r0h
or.b #b'10110000,r0h
jsr @tx_fifo_set
mov.b @offset,r0h
add.b r4l,r0h
jsr @tx_fifo_set
mov.b r3h,r0h
jsr @tx_fifo_set
rts
;***** SCI init / MIDI Transmit Routines *****
sci0_init:
mov.b #b'00000000,r0l
mov.b r0l,@scr
mov.b #b'00000000,r0l
mov.b r0l,@smr
mov.b #15,r0l
mov.b r0l,@brr
mov.w #500,r0
_sci0_wait:
dec.w #1,r0
bne _sci0_wait
mov.b @ssr,r0l ; (dummy read)
mov.b #0,r0l
mov.b r0l,@ssr
mov.b #b'00001000,r0l
mov.b r0l,@iprb ; SCI0-int priority UP !
rts
tx_midi_check:
mov.w @tx_top,r1
mov.w @tx_end,r6
cmp.w r1,r6
bne _tx_exist
rts
_tx_exist:
btst #7,@ssr ; test TRDE
bne _tx_seq
rts
_tx_seq:
mov.w #0,e6
mov.b @(tx_fifo,er6),r0l
mov.b r0l,@tdr
bclr #7,@ssr ; Transmit !
inc.w #1,r6
bclr #2,r6h
mov.w r6,@tx_end
rts
tx_fifo_set:
mov.w @tx_top,r6
mov.w #0,e6
mov.b r0h,@(tx_fifo,er6) ; transmit data = [r0h]
inc.w #1,r6
bclr #2,r6h
mov.w r6,@tx_top
rts
;***** Timer / Counter Routines *****
wait_500msec:
mov.l #500,er1
_wait_1:
jsr @wait_1msec
sub.l #1,er1
bne _wait_1
rts
wait_1msec:
mov.l #2048,er2
_wait_2:
sub.l #1,er2
bne _wait_2
rts
int_timer0:
push.w r0
mov.b #1,r0l
mov.b r0l,@flag
btst #0,@tsr0
bclr #0,@tsr0 ; Clear IMFA
pop.w r0
rte
timer_check2:
mov.w @timer2,r1
inc.w #1,r1
mov.w r1,@timer2
cmp.w #500,r1
beq _timer_2
rts
_timer_2:
mov.w #0,r1
mov.w r1,@timer2
mov.b @led,r0l
bnot #0,r0l
mov.b r0l,@led
mov.b r0l,@p5dr ; write to Port[5]
jsr @dip_scan
rts
timer_check:
mov.b @flag,r0l
cmp.b #0,r0l
bne _timer_event
rts
_timer_event:
jsr @timer_check2
mov.b #0,r0l
mov.b r0l,@flag
mov.w @timer3,r2
mov.w @timer1,r1
inc.w #1,r1
mov.w r1,@timer1
cmp.w r2,r1
beq _timer_1
rts
_timer_1:
mov.w #0,r1
mov.w r1,@timer1
mov.b #0,r0l
mov.b r0l,@ad_no
bset.b #3,r0l
mov.b r0l,@adcsr ; A/D channel = 0
bset.b #5,@adcsr ; A/D start !
rts
.end
そして、このテキストファイルをAKI-H8ライタソフトで転送すれば
とりあえず動いてしまう、というMotorolaのSフォーマット形式の
オブジェクトファイルは以下のようになります。
S00E0000466C617368524F4D4D4F5426
S107000000002000D9
S1070060000021F682
S113100001F400FA00C80096007D00640050004B14
S1131010004300320028001E00190014000F000ACC
S11320007A07000FFF0F7A02000FEF1079010FE03C
S1132010F80068A80B721B5146F85E002162F82392
S113202038647F6772007F667000790007CF6B802A
S1132030FF6AF80038C0F80038C1F80038C4F80067
S113204038C5F8FF38C85E0021D25E0020767F6075
S11320507000F8006A88EF1E703838E87FE9727004
S1132060F82038B2067F5E0020A65E0022385E00AC
S113207021825A00206629C2D9FFE90F1009F11005
S11320807909000069106B80EF1428C3D8FFE80FAB
S11320906A88EF2728C6D8FFE80F10081008100831
S11320A06A88EF2954707EE8737058600002547098
S11320B06A08EF1E0C8CA8005870002AA8045870F8
S11320C00024A80158700024A8055870001EA80217
S11320D05870001EA80658700018A80358700018FE
S11320E0A8075870001223E05800001223E258009A
S10720F0000C23E4D6
S11320F45800000623E6580000000A08E8076A8827
S1132104EF1EA80758700008703838E87FE870504D
S11321141754177411030C3B78406A22000FEF1F06
S11321241C2B58B0000A182BAB0258A0000C547097
S113213418B2A20258A00002547078406AA3000F98
S1132144EF1F6A00EF27C0B05E0021B86A00EF29D1
S113215408C05E0021B80C305E0021B85470F8004A
S113216438B2F80038B0F80F38B1790001F41B50D5
S113217446FC28B4F80038B4F80838F854706B01F6
S1132184EF166B06EF181D165860000254707EB4E8
S11321947370586000025470790E000078606A28E6
S11321A4000FF80038B37FB472700B5672266B8637
S11321B4EF1854706B06EF16790E000078606AA06E
S11321C4000FF8000B5672266B86EF1654707A01D3
S11321D4000001F45E0021E67A310000000146F4B8
S10521E4547032
S11321E67A02000008007A320000000146F85470B3
S11321F66DF0F8016A88EF287E6773007F677200C7
S11322066D7056706B01EF120B516B81EF127921D2
S113221601F4587000025470790100006B81EF12CB
S11322266A08EF1C71086A88EF1C38CA5E002076BC
S113223654706A08EF28A8005860000254705E00C4
S1132246220AF8006A88EF286B02EF146B01EF107D
S11322560B516B81EF101D215870000254707901E8
S113226600006B81EF10F8006A88EF1E703838E8BB
S10922767FE87050547074
S9032000DD
ということで、なんのこっちゃ(^_^;)、と逃げないで下さいね。
これでソフトが完成したので、ケースを組み立てて
この
ように
完成です。(^_^)
ちなみに、実際にはソフト開発の段階でパネルの1個のボリュームでは
アナログ入力が不足するので、ちょっと寄り道して、
こ
ん
な
ものを先に作ってみました。ジョイスティックで2入力、中央に右手親指用の
ボタンスイッチで1入力、あとテンキーの3列を3入力として、合計で6系列の
アナログ電圧源となっています。
これについては、またあとで書きたいと思います。なかなか楽しい世界です。(^_^)
|