; (c) 2002 Sugihara Toshio. ; All rights reserved. ; ; チャイムシステムプログラム[シンセサイザ側] ; 学校でのチャイム音を出すバージョン ; B0=C, B1=F, B2=G, B3=Aとする。 ; 方形波出力がベースだが、パルス幅を減衰させて音量を調整する ;----------------------------------------------------------- ;ハード定義 include 16f84.h .osc HS .pwrt on .wdt on .protect off ;----------------------------------------------------------- ;変数定義 org 0ch outbuf ds 1;出力用バッファ sec ds 1;経過秒数 ;秒生成タイマ t1 ds 1 t2 ds 1 t3 ds 1 ;O4C(261.626Hz)用 cu1 ds 1 cu2 ds 1 cd1 ds 1 cd2 ds 1 ;O4F(349.228Hz)用 fu1 ds 1 fu2 ds 1 fd1 ds 1 fd2 ds 1 ;O4G(391.995Hz)用 gu1 ds 1 gu2 ds 1 gd1 ds 1 gd2 ds 1 ;O4A用(440.000Hz) au1 ds 1 au2 ds 1 ad1 ds 1 ad2 ds 1 ;音量設定用変数 cvol ds 1 fvol ds 1 gvol ds 1 avol ds 1 ;音量減衰ループ用変数 ctm ds 1 ftm ds 1 gtm ds 1 atm ds 1 ;----------------------------------------------------------- ;プログラム本体 ;起動部分 boot org 0h goto start warikomi org 4h goto start ;ハードウエアの初期化 start movlw 00111000b ;バンク1を選択 movwf status ;すべての割り込みを禁止 startloop bcf intcon, 7 ;GIEビットを下げる btfsc intcon, 7 goto startloop clrf intcon ;割り込み管理ビットは全部off ;BポートプルアップOFF、TMR0のソースは命令サイクルクロック ;プリスケーラはTMR0で、分周比1:256に。 ;1/76.293945秒に1回オーバーフロー movlw 10000111b movwf option ;Aポート、Bポートは全て出力とする clrf porta clrf portb ;バンク0を選択 bcf status, 5 ;出力を下げる clrf porta clrf portb ;変数初期化 clrf sec ;0秒にする clrf outbuf ;出力バッファを0にする call setsecup ;秒タイマの初期値をセット call setcup ;C上げタイマの初期値をセット call setfup ;F上げタイマの初期値をセット call setgup ;Gの上げタイマの初期値をセット call setaup ;Aの上げタイマの初期値をセット movlw 1 ;初期の音量を全て0に(値1がループ0回を意味する) movwf cvol movwf fvol movwf gvol movwf avol movlw 2 ;初期の音量減衰タイマ値を2に movwf ctm movwf ftm movwf gtm movwf atm ;メインループ mainloop clrwdt ;秒の更新を検出 decf t1,1 btfss status,2 goto ccount decf t2,1 btfss status,2 goto ccount decf t3,1 btfss status,2 goto ccount call setsecup incf sec,1 ;秒を進める movlw 31 subwf sec,0 ;W = sec - 31 btfsc status,2 decf sec,1 ;secを30に戻す ;ここに、秒ごとに行うべきことを書く call secup ; O4C音のカウント ccount ;C上げカウント decf cu1,1 btfss status,2 goto cdcount decf cu2,1 btfss status,2 goto cdcount call setcup call setcdown ;C上げカウントが成立 bsf outbuf,0 cdcount ;C下げカウント btfss outbuf,0 ;下げカウントを行う必要があるか? goto clast ;いいえ、ないので次の処理へ ;はい。下げカウントを行う decf cd1,1 btfss status,2 goto fcount decf cd2,1 btfss status,2 goto fcount ;C下げカウントが成立 bcf outbuf,0 goto fcount clast nop goto fcount fcount ; O4F音のカウント ;F上げカウント decf fu1,1 btfss status,2 goto fdcount decf fu2,1 btfss status,2 goto fdcount call setfup call setfdown ;F上げカウントが成立 bsf outbuf,1 fdcount ;F下げカウント btfss outbuf,1 ;下げカウントを行う必要があるか? goto flast ;いいえ、ないので次の処理へ ;はい。下げカウントを行う decf fd1,1 btfss status,2 goto gcount decf fd2,1 btfss status,2 goto gcount ;F下げカウントが成立 bcf outbuf,1 goto gcount flast nop goto gcount gcount ;O4G音のカウント ;G上げカウント decf gu1,1 btfss status,2 goto gdcount decf gu2,1 btfss status,2 goto gdcount call setgup call setgdown ;G上げカウントが成立 bsf outbuf,2 gdcount ;G下げカウント btfss outbuf,2 ;下げカウントを行う必要があるか? goto glast ;いいえ、ないので次の処理へ ;はい。下げカウントを行う decf gd1,1 btfss status,2 goto acount decf gd2,1 btfss status,2 goto acount ;G下げカウントが成立 bcf outbuf,2 goto acount glast nop goto acount acount ; O4A音のカウント ;A上げカウント decf au1,1 btfss status,2 goto adcount decf au2,1 btfss status,2 goto adcount call setaup call setadown ;A上げカウントが成立 bsf outbuf,3 adcount ;A下げカウント btfss outbuf,3 ;下げカウントを行う必要があるか? goto alast ;いいえ、ないので次の処理へ ;はい。下げカウントを行う decf ad1,1 btfss status,2 goto sendio decf ad2,1 btfss status,2 goto sendio ;A下げカウントが成立 bcf outbuf,3 goto sendio alast nop goto sendio sendio ;I/Oへ書き出す movf outbuf,0 movwf portb goto mainloop ;秒タイマへの初期値をセット setsecup movlw 153 movwf t1 movlw 143 movwf t2 movlw 2 movwf t3 return ;Cタイマ(UP)への初期値セット setcup movlw 135 movwf cu1 movlw 2 movwf cu2 return ;Fタイマ(UP)への初期値セット setfup movlw 37 movwf fu1 movlw 2 movwf fu2 return ;Gタイマ(UP)への初期値セット setgup movlw 5 movwf gu1 movlw 2 movwf gu2 return ;Aタイマ(UP)への初期値セット setaup movlw 233 movwf au1 movlw 1 movwf au2 return ;Cタイマ(DOWN)への初期値セット setcdown movf cvol,0 movwf cd1 movlw 1 movwf cd2 ;cvol==1の時は鳴らさないモードなのですぐ返す decf cvol,0 btfsc status,2 return ;4回に1回ずつ音量ダウン decf ctm,1 btfss status,2 return movlw 4 movwf ctm decf cvol,1 decf cvol,0 btfsc status,2 incf cvol,1 return ;Fタイマ(DOWN)への初期値セット setfdown movf fvol,0 movwf fd1 movlw 1 movwf fd2 ;fvol==1の時は鳴らさないモードなのですぐ返す decf fvol,0 btfsc status,2 return ;7回に1回ずつ音量ダウン decf ftm,1 btfss status,2 return movlw 7 movwf ftm decf fvol,1 decf fvol,0 btfsc status,2 incf fvol,1 return ;Gタイマ(DOWN)への初期値セット setgdown movf gvol,0 movwf gd1 movlw 1 movwf gd2 ;gvol==0の時は鳴らさないモードなのですぐ返す decf gvol,0 btfsc status,2 return ;9回に1回ずつ音量ダウン decf gtm,1 btfss status,2 return movlw 9 movwf gtm decf gvol,1 decf gvol,0 btfsc status,2 incf gvol,1 return ;Aタイマ(DOWN)への初期値セット setadown movf avol,0 movwf ad1 movlw 1 movwf ad2 ;avol==0の時は鳴らさないモードなので返す decf avol,0 btfsc status,2 return ;11回に1回ずつ音量ダウン decf atm,1 btfss status,2 return movlw 11 movwf atm decf avol,1 decf avol,0 btfsc status,2 incf avol,1 return ;毎秒実行するルーチン ;ありうる秒数は1以上30以下 org 200h secup ;両ポートを出力状態に(確実な動作のため) bsf status,5 clrf porta clrf portb bcf status,5 ;PCLATHに512番地のオフセットをかける movlw 00000010b movwf pclath ;ON sec goto 的な処理 movf sec,0 addwf pcl,1 return; =0 return; =1 goto startf; =2 goto starta; =3 goto startg; =4 goto startc; =5 return; =6 return; =7 goto startf; =8 goto startg; =9 goto starta; =10 goto startf; =11 return; =12 return; =13 goto starta; =14 goto startf; =15 goto startg; =16 goto startc; =17 return; =18 return; =19 goto startc; =20 goto startg; =21 goto starta; =22 goto startf; =23 return; =24 return; =25 return; =26 return; =27 return; =28 return; =29 goto sysend; =30 startc movlw 196 movwf cvol return startf movlw 147 movwf fvol return startg movlw 131 movwf gvol return starta movlw 117 movwf avol return sysend clrwdt bcf status,5 clrf porta clrf portb bsf status,5 clrf porta clrf portb goto sysend