' ' *********************************************** ' * * ' * PWM サイン波 発生プログラム + 音量調整 * ' * * ' * AVR is using ATtiny45-20PU * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2008.12.27 * ' *********************************************** ' ' Ver 3.01 初回公開バージョン ' Ver 3.51 音量制御を追加したバージョン。 ' ' Const Prgver = "03.51" 'プログラム・バージョン。 ' $regfile = "ATtiny45.DAT" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' ' Const Wav_frq = 1000 'Sin波形の発生周波数を設定。(1〜約5000Hz) ' ' ' Dim Wavpoi As Word 'Timer0割り込み用の波形ROMポインター。 Dim Poiadd As Word '波形ROMポインターの加算値。 Dim Wavdiv As Word '波形の分割数。(AVR動作クロック÷256÷256) Dim Volume As Byte '音量。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Tempw1 As Word '汎用テンポラリ変数 Woed型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Temps1 As Single '汎用テンポラリ変数 Single型 No.1 Dim Temps2 As Single '汎用テンポラリ変数 Single型 No.2 Dim Temps3 As Single '汎用テンポラリ変数 Single型 No.3 ' Dim Eepsum As Eram Word At $02 'EEPROM Sinデータのチェックサム。 Dim Wavrom(128) As Eram Byte At $80 'Sin波形 保存用。 ' ' ' ' * ポートの初期設定 * ' Config Portb = Output ' ' * タイマーの設定 * ' Config Timer0 = Pwm , Prescale = 1 , Clear Timer = 1 , Compare A Pwm = Clear Down 'Timer0 8bit高速PWM動作。 Ocr0a = 128 'パルス幅。(初期値) On Ovf0 Tm0int Nosave 'Timer0 オーバーフロー 割り込みルーチンを設定。 Enable Ovf0 'Timer0 オーバーフロー 割り込みを許可。 ' ' **************************** ' * サイン波形のデータを準備 * ' **************************** ' Tempw1 = 0 'EEPROM波形のチェックサムを計算。 For Temp1 = 1 To 128 Temp2 = Wavrom(temp1) Tempw1 = Tempw1 + Temp2 Next Temp1 ' If Eepsum <> Tempw1 Then 'If EEPROMへSinデータを書き込み済み? Else ' Tempw1 = 0 Temps1 = Deg2rad(180) '角度180°のラジアン(弧度)値を取得。 Temps1 = Temps1 / 128 '波形の分解能を計算。 Temps2 = 0 For Temp1 = 1 To 128 '波形のコサイン値を計算(波形の前半分のみ)。 Temps3 = Cos(temps2) Temps3 = Temps3 * 128 '0〜127の値に変換。 Temp2 = Int(temps3) '整数化。 Temp2 = Temp2 + 128 'オフセットを加算 Wavrom(temp1) = Temp2 'EEPROMへ格納。 Tempw1 = Tempw1 + Temp2 'EEPROM波形のチェックサムを計算。 Temps2 = Temps2 + Temps1 Next Temp1 Eepsum = Tempw1 'EEPROMへチェックサムを書き込み。 ' End If ' ' *********************************** ' * 波形ROMポインターの加算値を計算 * ' *********************************** ' Templ1 = _xtal '波形の分割数を算出。 Wavdiv = Highw(templ1) 'AVR動作クロック÷256÷256 ' Templ1 = Wav_frq * 256 'ポインターは16bitの内、上位8bitを使用する。 Templ1 = Templ1 / Wavdiv 'ポインターの加算値を算出。 Poiadd = Templ1 'ポインターの加算値(16bit)を格納。 Wavpoi = 0 'ポインターを初期化。 Volume = 255 '音量を最大値に設定。 ' Enable Interrupts 'すべての割り込みを許可。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: For Volume = 0 To 255 '音量を変化させるテストプログラム。 Waitms 5 Next Volume ' Goto Main ' End ' ' ********************************************** ' * Timer0 オーバーフロー 割り込み処理ルーチン * ' ********************************************** ' Tm0int: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R16 PUSH R17 PUSH R22 PUSH R23 'R23は、拡張I/Oレジスタへのアクセスに使用する。 ; CLR R16 'EEPROMアドレスの上位バイトを設定。 Out Eearh , R16 LDS R17,{wavpoi+1} 'ポインターの位置を確認(上位8bitのみ使用)。 CPI R17,&H80 BRCC Tm0int1 'If 波形の後半? Then ; LDI R16,&H80 'EEPROMアドレスにオフセットを加算。 OR R16,R17 Out Eearl , R16 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R22,EEDR 'EEPROMデータを取得。 RJMP Tm0int2 ; Tm0int1: '波形の後半処理。 Out Eearl , R17 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R22,EEDR 'EEPROMデータを取得。 COM R22 '波形を後半用に処理。 ; Tm0int2: LDS R16,{Volume} '音量制御。(波形データ(R22) × 音量値(R16) ÷ 256) RCALL Mpy8u '8bitの掛け算。 Out Ocr0a , R23 'SinデータをTimer0の比較器Aにセット。 ' LDS R16,{wavpoi} 'ポインターに加算値を加える。(16bit + 16bit) LDS R22,{poiadd} LDS R23,{poiadd+1} ADD R16,R22 ADC R17,R23 STS {wavpoi},R16 '新しいポインター位置を格納。 STS {wavpoi+1},R17 ; POP R23 POP R22 POP R17 POP R16 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return ' ' ************************************************** ' * 8 X 8 = 16bit 符号無し(速度重視)サブルーチン * ' ************************************************** ' Mc8u Alias R22 '被乗数 Mp8u Alias R16 '乗数 M8ul Alias R16 '結果 下位バイト M8uh Alias R23 '結果 上位バイト ' Mpy8u: $asm Clr M8uh lsr mp8u brcc noad80 add m8uH,mc8u Noad80: Ror M8uh ror m8uL brcc noad81 add m8uH,mc8u Noad81: Ror M8uh ror m8uL brcc noad82 add m8uH,mc8u Noad82: Ror M8uh ror m8uL brcc noad83 add m8uH,mc8u Noad83: Ror M8uh ror m8uL brcc noad84 add m8uH,mc8u Noad84: Ror M8uh ror m8uL brcc noad85 add m8uH,mc8u Noad85: Ror M8uh ror m8uL brcc noad86 add m8uH,mc8u Noad86: Ror M8uh ror m8uL brcc noad87 add m8uH,mc8u Noad87: Ror M8uh ror m8uL ret $end Asm ' End