目次
前
次
Step Sequencer
アナログシンセサイザーで、ループで音出しを
するときは、ステップシーケンサを使います。
このステップシーケンサの回路図は以下。
8ステップシーケンサなので、8ビットを次のように
出力すればよいはず。
8ピンをポート1に割当てして、Q0からQ7を
出力すれば実現できると判ります。
レジスタに格納した値を回転していけば
指定ピンだけに論理値の'1'を出力。
パターンを出力するには、次のコードで対応。
SND_VAL:
; get value
mov a,r7
; impress
outl P1,a
;
ret
レジスタr7の内容を取得しているので、値を回転
するとともにテンポを変えるためタイマー割込み
を使うとします。
レジスタr7の回転処理は、次のようにすればよいでしょう。
MAIN:
; get event trigger
mov a,@r0
jz MAINX
; clear flag
mov @r0,#0
; impress
call SND_VAL
; rotate
mov a,r7
rl a
mov r7,a
;
MAINX:
;
jmp MAIN
テンポを増減しないといけないので、T1、T0に
スイッチを接続して、内部カウンタの設定値を
増減して対応。
回路は、以下。
T1で増加、T0で減少という処理を加えておきます。
MAIN:
; get event trigger
mov a,@r0
jz MAINX
; clear flag
mov @r0,#0
; impress
call SND_VAL
; rotate
mov a,r7
rl a
mov r7,a
; ? increase
MAINX:
; ? push
jnt1 MAINY
; increment
inc r6
; judge
mov a,r6
jnz MAINY
; upper limit
mov a,#255
mov r6,a
; exit
jmp MAINZ
; ? decrease
MAINY:
; ? push
jnt0 MAINZ
; decrement
mov a,r6
dec a
mov r6,a
; judge
mov a,r6
jnz MAINZ
; lower limit
mov a,#1
mov r6,a
; update
MAINZ:
;
jmp MAIN
時間経過をフラグEFLAGで判断するので、タイマー割込み時に
カウンタをインクリメントし、指定値と一致したときに
イベント通知フラグとしてEFLAGを利用します。
E_TIMX:
; push
mov r2,a
; stop counter
stop tcnt
; initialize
mov a,#TZERO
mov t,a
; increment
inc r1
; judge
mov a,r1
xrl a,r6
jz E_TIMY
; exit
jmp E_TIMZ
; set flag
E_TIMY:
; set flag
mov @r0,#1
; clear
mov r1,#0
;
E_TIMZ:
; pop
mov a,r2
;
retr
初期化で、12.5kHzで割込みしていけるようにします。
INIT_TIM:
; stop counter
stop tcnt
; initialize
mov a,#TZERO
mov t,a
; start timer
strt t
;
ret
ここまでできたなら、全体を見られる回路を
図面にしておきます。
他の処理を追加して、まとめると以下。
; step sequencer
;
INCLUDE 8048.LIB
;*******************
; value and address
;*******************
TZERO equ 6
TFLAG equ 18h
EFLAG equ 19h
;****************
; define symbols
;****************
ENTRY equ 0h
E_INT equ 3h
E_TIM equ 7h
;*******************
; interrupt vectors
;*******************
org ENTRY
jmp START
; external interrupt
org E_INT
retr
; timer interrupt
org E_TIM
jmp E_TIMX
org 10h
;**************
; sub routines
;**************
E_TIMX:
; push
mov r2,a
; stop counter
stop tcnt
; initialize
mov a,#TZERO
mov t,a
; increment
inc r1
; judge
mov a,r1
xrl a,r6
jz E_TIMY
; exit
jmp E_TIMZ
; set flag
E_TIMY:
; set flag
mov @r0,#1
; clear
mov r1,#0
;
E_TIMZ:
; pop
mov a,r2
;
retr
INIT:
; disable external interrupt
dis i
; disable timer interrupt
dis tcnti
; initialize I/O
clr a
outl p1,a
outl p2,a
; enable timer
start t
; set pointer
mov r0,#EFLAG
;
ret
INIT_TIM:
; stop counter
stop tcnt
; initialize
mov a,#TZERO
mov t,a
; start timer
strt t
;
ret
INIT_P1:
; zero clear
clr a
; impress
outl P1,a
;
ret
SND_VAL:
; get value
mov a,r7
; impress
outl P1,a
;
ret
;**************
; main routine
;**************
org 100h
START:
call INIT
call INIT_TIM
call INIT_P1
; enable
en TCNTI
; initialize
mov r6,#128
mov r7,#1
; endless loop
MAIN:
; get event trigger
mov a,@r0
jz MAINX
; clear flag
mov @r0,#0
; impress
call SND_VAL
; rotate
mov a,r7
rl a
mov r7,a
; ? increase
MAINX:
; ? push
jnt1 MAINY
; increment
inc r6
; judge
mov a,r6
jnz MAINY
; upper limit
mov a,#255
mov r6,a
; exit
jmp MAINZ
; ? decrease
MAINY:
; ? push
jnt0 MAINZ
; decrement
mov a,r6
dec a
mov r6,a
; judge
mov a,r6
jnz MAINZ
; lower limit
mov a,#1
mov r6,a
; update
MAINZ:
;
jmp MAIN
end
リスティングファイルは次のようになります。
0000 ; step sequencer
0000 ;
0000 INCLUDE 8048.LIB
0000 list
0000
0000 ;*******************
0000 ; value and address
0000 ;*******************
0006 TZERO equ 6
0018 TFLAG equ 18h
0019 EFLAG equ 19h
0000
0000 ;****************
0000 ; define symbols
0000 ;****************
0000 ENTRY equ 0h
0003 E_INT equ 3h
0007 E_TIM equ 7h
0000
0000 ;*******************
0000 ; interrupt vectors
0000 ;*******************
0000 org ENTRY
0000 2400 + jmp START
0002
0002 ; external interrupt
0002 org E_INT
0003 93 + retr
0004
0004 ; timer interrupt
0004 org E_TIM
0007 0410 + jmp E_TIMX
0009
0009 org 10h
0010 ;**************
0010 ; sub routines
0010 ;**************
0010 E_TIMX:
0010 ; push
0010 AA + mov r2,a
0011 ; stop counter
0011 65 + stop tcnt
0012 ; initialize
0012 2306 + mov a,#TZERO
0014 62 + mov t,a
0015 ; increment
0015 19 + inc r1
0016 ; judge
0016 F9 + mov a,r1
0017 DE + xrl a,r6
0018 C61C + jz E_TIMY
001A ; exit
001A 0420 + jmp E_TIMZ
001C ; set flag
001C E_TIMY:
001C ; set flag
001C B001 + mov @r0,#1
001E ; clear
001E B900 + mov r1,#0
0020 ;
0020 E_TIMZ:
0020 ; pop
0020 FA + mov a,r2
0021 ;
0021 93 + retr
0022
0022 INIT:
0022 ; disable external interrupt
0022 15 + dis i
0023 ; disable timer interrupt
0023 35 + dis tcnti
0024 ; initialize I/O
0024 27 + clr a
0025 39 + outl p1,a
0026 3A + outl p2,a
0027 ; enable timer
0027 55 + start t
0028 ; set pointer
0028 B819 + mov r0,#EFLAG
002A ;
002A 83 + ret
002B
002B INIT_TIM:
002B ; stop counter
002B 65 + stop tcnt
002C ; initialize
002C 2306 + mov a,#TZERO
002E 62 + mov t,a
002F ; start timer
002F 55 + strt t
0030 ;
0030 83 + ret
0031
0031 INIT_P1:
0031 ; zero clear
0031 27 + clr a
0032 ; impress
0032 39 + outl P1,a
0033 ;
0033 83 + ret
0034
0034 SND_VAL:
0034 ; get value
0034 FF + mov a,r7
0035 ; impress
0035 39 + outl P1,a
0036 ;
0036 83 + ret
0037
0037 ;**************
0037 ; main routine
0037 ;**************
0037 org 100h
0100 START:
0100 1422 + call INIT
0102 142B + call INIT_TIM
0104 1431 + call INIT_P1
0106 ; enable
0106 25 + en TCNTI
0107 ; initialize
0107 BE80 + mov r6,#128
0109 BF01 + mov r7,#1
010B ; endless loop
010B MAIN:
010B ; get event trigger
010B F0 + mov a,@r0
010C C615 + jz MAINX
010E ; clear flag
010E B000 + mov @r0,#0
0110 ; impress
0110 1434 + call SND_VAL
0112 ; rotate
0112 FF + mov a,r7
0113 E7 + rl a
0114 AF + mov r7,a
0115
0115 ; ? increase
0115 MAINX:
0115 ; ? push
0115 4620 + jnt1 MAINY
0117 ; increment
0117 1E + inc r6
0118 ; judge
0118 FE + mov a,r6
0119 9620 + jnz MAINY
011B ; upper limit
011B 23FF + mov a,#255
011D AE + mov r6,a
011E ; exit
011E 242B + jmp MAINZ
0120
0120 ; ? decrease
0120 MAINY:
0120 ; ? push
0120 262B + jnt0 MAINZ
0122 ; decrement
0122 FE + mov a,r6
0123 07 + dec a
0124 AE + mov r6,a
0125 ; judge
0125 FE + mov a,r6
0126 962B + jnz MAINZ
0128 ; lower limit
0128 2301 + mov a,#1
012A AE + mov r6,a
012B
012B ; update
012B MAINZ:
012B ;
012B 240B + jmp MAIN
012D
012D end
目次
前
次