' ' ************************************************** ' * * ' * AVRポート用 音楽再生プログラム * ' * (フォト トランジスタ・起動バージョン) * ' * * ' * AVR is using ATtiny45-20PU * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2008. 8.23 * ' ************************************************** ' ' Ver 1.01 初回公開バージョン ' Ver 1.02 音楽再生を途中で中断できるように、プログラムをサブルーチン化した。 ' ' $regfile = "ATtiny45.DAT" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' ' Su_port Alias Pinb.0 'サウンド出力用ポートを設定。 ' ' Config Su_port = Output 'サウンド出力用ポートを、出力に設定。(修正不要) Portb = &B00001110 '未使用ポートをプルアップ。 ' Config Adc = Single , Prescaler = Auto 'A/Dコンバータの初期設定。 Start Adc 'A/Dコンバータの電源をオン。 ' ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Tempwd1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Mu_temp1 As Byte '音楽の再生ルーチン用 テンポラリ変数 Byte型 No.1 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Temp2 = 0 Main1: Tempwd1 = Getadc(2) 'A/Dチャンネル2 からデータを取り込み。 Shift Tempwd1 , Right , 2 'A/Dデータを10ビットから8ビットに変換。 If Tempwd1 < 128 Then Goto Main 'If 明るさの設定値を超えたか? Else ' Temp1 = 1 If Tempwd1 > 200 Then Temp1 = 2 'If 明るさの設定値を超えたか? Then ' If Temp1 <> Temp2 Then 'If センサーの状態が変化したか? Then Select Case Temp1 '曲目を選択。(曲の初期化) Case 1 : Restore Mu_data1 '音楽のデータテーブルを指定。 Case 2 : Restore Mu_data2 '音楽のデータテーブルを指定。 ' End Select Gosub Mu_playini '音楽データ再生を初期化。 Temp2 = Temp1 End If ' Gosub Mu_playsub '音楽データを1コード処理する。 If Mu_temp1 = 0 Then Goto Main1 'If 再生終了? Else Goto Main ' End ' ' *********************** ' * 音楽 データテーブル * (1行は、40文字以内にして下さい) ' *********************** ' ' Ox=オクターブ変更 [1〜7] (O4Aで440Hz) , [+][-] 現在のオクターブ値よりの増減 ' C=ド , D=レ , E=ミ , F=ファ , G=ソ , A=ラ , B=シ , #=半音上げ , $=半音下げ ' 音符 1=全音符 , 2=2分音符 , 4=4分音符 , 8=8分音符 , 16=16分音符 , 32=32分音符 , 64=64分音符 ' Rx=休符(長さは音符と同じ) , Z=終了コード ' ' Mu_data1: 'モーツァルト アイネ・クライネ・ナハトムジーク 第1楽章 Data 120 'TEMPO テンポ値(1分間の拍数[4分音符分])[4〜255] Data "o4d4r8o-a8o+d4r8o-a8o+d8o-a8o+d8f#8a4r4" Data "g4r8e8g4r8e8g8e8c#8e8o-a4o+r4" Data "d4d4d8f#8e8d8d8c#8c#4c#8e8g8c#8" Data "e8d8d4d8f#8e8d8d8c#8c#4c#8e8g8c#8" Data "d8d8d16c#16o-b16o+c#16d8d8f#16e16d16e16" Data "f#8f#8a16g16f#16g16a4r4z" ' Mu_data2: 'アラーム音 Data 120 Data "o4a4z" ' ' *************************** ' * 音楽の再生 サブルーチン * [Mu_play] , [Mu_playini] , [Mu_playsub] ' *************************** ' Dim Mu_tempo As Word 'テンポ値。 Dim Mu_octave As Byte 'オクターブ値。 Dim Mu_octdiv As Word 'オクターブ分割値。 Dim Mu_pldata As String * 40 '音楽データの1行バッファー。 Dim Mu_dtlen As Byte '音楽データ行のレングス。 Dim Mu_dtposi As Byte '音楽データ行のデータ取得位置。 Dim Mu_str As String * 1 '音楽データ行からの取得データ文字。 Dim Mu_freq As Word '音階の周波数。 ' Dim Mu_temp2 As Byte '音楽の再生ルーチン用 テンポラリ変数 Byte型 No.2 Dim Mu_temp3 As Byte '音楽の再生ルーチン用 テンポラリ変数 Byte型 No.3 Dim Mu_temp4 As Byte '音楽の再生ルーチン用 テンポラリ変数 Byte型 No.4 Dim Mu_tempw1 As Word '音楽の再生ルーチン用 テンポラリ変数 Word型 No.1 Dim Mu_tempw2 As Word '音楽の再生ルーチン用 テンポラリ変数 Word型 No.2 Dim Mu_templ1 As Long '音楽の再生ルーチン用 テンポラリ変数 Long型 No.1 ' ' Mu_play: Gosub Mu_playini '音楽データ再生を初期化。 ' Mu_play1: Gosub Mu_playsub '音楽データを1コード処理する。 If Mu_temp1 = 0 Then Goto Mu_play1 'If 再生終了? Else Return ' ' * 音楽データ再生を初期化するサブルーチン * ' Mu_playini: Mu_octave = 4 'オクターブの初期値を4に設定。 Mu_octdiv = 80 Read Mu_temp1 'テンポ値を読み込み。 Mu_tempo = 60000 / Mu_temp1 'テンポ値を時間(mS)に変換。 Mu_tempo = Mu_tempo * 4 '全音符のテンポ値を計算(mS)。 Mu_dtlen = 0 Return ' ' * 音楽データを1コード処理するサブルーチン * ' Mu_playsub: If Mu_dtlen = 0 Then 'If 音楽データ行が終わり? Then Read Mu_pldata '音楽データを読み込み。 Mu_dtlen = Len(mu_pldata) '音楽データの1行の長さを確認。 Mu_dtposi = 1 End If ' Gosub Mu_datcnv 'データ行から制御コードを取得。 Mu_temp1 = Mu_temp1 And &HDF '大文字に修正。 If Mu_temp1 = &H4F Then Goto Mu_plays2 'If "O" オクターブ変更? Then If Mu_temp1 = &H52 Then Goto Mu_plays3 'If "R" 休符? Then If Mu_temp1 > &H47 Then Return 'If 終了コード ? Then ' Mu_temp1 = Mu_temp1 - &H40 'A〜Gを1〜7に変換。 Mu_temp2 = Mu_temp1 + Mu_temp1 'テーブル用に2倍する。 Gosub Mu_datcnv 'データ行からパラメーターを取得。 ' If Mu_temp1 < &H31 Then 'If "#"or"$"? Then If Mu_temp1 = &H23 Then Mu_temp2 = Mu_temp2 + 1 'If "#" 半音上げる? Then Else Mu_temp2 = Mu_temp2 - 1 'If "$" 半音下げる? Then End If Gosub Mu_datcnv 'データ行からパラメーターを取得。 End If Gosub Mu_noterd1 '音楽データ行から音符を取り出す。 ' Mu_temp2 = Mu_temp2 - 1 'A〜Gコードから、基本周波数を取得。 Mu_freq = Lookup(mu_temp2 , Mu_scale) ' Mu_freq = Mu_freq / Mu_octdiv 'オクターブに対応した周波数を計算。 Mu_tempw2 = Mu_freq * 12 'SOUND命令用の発振周波数値を計算。 Mu_templ1 = _xtal / Mu_tempw2 Mu_tempw2 = Mu_templ1 ' Mu_templ1 = Mu_tempw1 * Mu_freq 'SOUND命令用の発振期間値を計算。 Mu_templ1 = Mu_templ1 / 1000 Mu_tempw1 = Mu_templ1 ' Sound Su_port , Mu_tempw1 , Mu_tempw2 'SOUND命令によりパルス音を発生。 ' Mu_plays4: Mu_temp1 = 0 Return ' ' Mu_plays2: '"O" オクターブ変更。 Gosub Mu_datcnv 'データ行から、パラメーターを取得。 If Mu_temp1 < &H31 Then 'If "+ or -" オクターブ増減? Then If Mu_temp1 = &H2B Then 'If "+" オクターブ・プラス? Then Mu_octave = Mu_octave + 1 Else Mu_octave = Mu_octave - 1 End If Else Mu_octave = Mu_temp1 - &H30 '"1-7" 数値入力。 End If Mu_temp1 = Mu_octave - 1 Mu_octdiv = Lookup(mu_temp1 , Mu_ocdiv) 'オクターブの分割数に変換。 Goto Mu_plays4 ' ' Mu_plays3: '"R" 休符 Gosub Mu_noterd '音楽データ行から休符を取り出す。 Waitms Mu_tempw1 Goto Mu_plays4 ' ' * 音楽データ行から1文字を取り出し、ASCIIコードに変換するサブルーチン * ' Mu_datcnv: Mu_str = Mid(mu_pldata , Mu_dtposi , 1) 'データ行から1文字を取得。 Mu_dtposi = Mu_dtposi + 1 Mu_dtlen = Mu_dtlen - 1 Mu_temp1 = Asc(mu_str) 'データをASCIIコードに変換。 Return ' ' * 音楽データ行から音符・休符を取り出すサブルーチン * ' Mu_noterd: Gosub Mu_datcnv 'データ行から、パラメーターを取得。 Mu_noterd1: Mu_temp4 = Mu_temp1 '音符を取得。 Select Case Mu_temp4 Case &H36 : '64分音符 Mu_temp3 = 6 Mu_dtposi = Mu_dtposi + 1 Mu_dtlen = Mu_dtlen - 1 Case &H33 : '32分音符 Mu_temp3 = 5 Mu_dtposi = Mu_dtposi + 1 Mu_dtlen = Mu_dtlen - 1 Case &H31 : '全音符or16分音符 Mu_temp3 = 0 If Mu_dtlen <> 0 Then Gosub Mu_datcnv 'データ行から、パラメーターを取得。 If Mu_temp1 = &H36 Then 'If 16分音符? Then Mu_temp3 = 4 Else Mu_dtposi = Mu_dtposi - 1 Mu_dtlen = Mu_dtlen + 1 End If End If Case &H38 : '8分音符 Mu_temp3 = 3 Case &H32 : '2分音符 Mu_temp3 = 1 Case Else : '4分音符 Mu_temp3 = 2 End Select ' Mu_tempw1 = Mu_tempo If Mu_temp3 <> 0 Then 'If 全音符? Else Shift Mu_tempw1 , Right , Mu_temp3 '音符から時間を計算。 End If Return ' ' * 音階の周波数 データテーブル * ' Mu_scale: Data 33228% , 35200% , 37296% , 39512% , 39512% , 20930% , 22176% , 23496% 'Ab,A,A#=Bb,B,dummy,C,C#=Db,D Data 24892% , 26372% , 26372% , 27936% , 29600% , 31360% , 33228% 'D#=Eb,E,dummy,F,F#=Gb,G,G# ' ' * オクターブ値の分割 データテーブル * ' Mu_ocdiv: Data 640% , 320% , 160% , 80% , 40% , 20% , 10%