' $prog &HFF , &H7A , &HFF , &H00 'CKDIV8 = [1] ' ' *********************************************** ' * * ' * 鉄道模型用 踏切 制御装置 プログラム * ' * * ' * AVR is using ATtiny13A-PU * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2010. 6. 8 * ' *********************************************** ' ' Ver 2.01 ATtiny13Aへ移植バージョン。 ' Ver 2.02 踏切音にタイムアウトを追加。(鳴り続けの防止) 2010. 6. 8 ' ' $regfile = "ATtiny13.DAT" '使用するAVRを設定。 $crystal = 9600000 'AVRクロックを設定。 ' $hwstack = 32 'ハードウェア・スタックの容量を指定。 $swstack = 8 'ソフトウェア・スタックの容量を指定。 $framesize = 8 'フレーム領域の容量を設定。 ' ' Const Timeout = 50 '踏切音のタイムアウト回数。 ' ' *************************************** ' * 波形ROMポインターの加算値を計算する * ' *************************************** ' ' 波形の分割数 = AVR動作クロック ÷ 256(キャリヤ周波数) ÷ 256(PWMの分解能) ' [146 = 9,600,000Hz / 256 /256] ' ' ポインターの加算値 = 発生周波数 × 256(16bitの上位8bitを使用) ÷ 波形の分割数 ' ' 波形[A] 1,206 (&H04B6) = 688Hz * 256 / 146 Const Poiadd_al = &HB6 '波形[A]のポインターの加算値(下位)。 Const Poiadd_ah = &H04 '波形[A]のポインターの加算値(上位)。 ' 波形[B] 1,289 (&H0509) = 735Hz * 256 / 146 Const Poiadd_bl = &H09 '波形[B]のポインターの加算値(下位)。 Const Poiadd_bh = &H05 '波形[B]のポインターの加算値(上位)。 ' Const Wavmin = 64 '波形減衰時の最小値。(0〜255) Const Attack = 5 '波形の立ち上がり時間。(1〜255) Const Release = 255 '波形の余韻時間。 (1〜65535) ' ' * 変数の宣言 * ' Dim Fmstart As Byte '踏切動作開始フラグ。 Dim Ledff As Byte 'LED点滅用フリップ・フロップ。 Dim Wavpoi_a As Word 'Timer0割り込み用の波形[A]ROMポインター。 Dim Wavpoi_b As Word 'Timer0割り込み用の波形[B]ROMポインター。 Dim Wavenv As Byte '波形のエンベロープ値。 Dim Fmtout As Byte '踏切音のタイムアウト回数カウンター。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Tempw1 As Word '汎用テンポラリ変数 Woed型 No.1 ' ' * ポートの初期設定 * ' Config Portb = &B0000_0111 '[PB0],[PB1],[PB2] を出力に設定する。 Portb = &B0001_1000 '入力ポートをプルアップする。 ' ' * タイマーの設定 * ' Config Timer0 = Pwm , Prescale = 1 , Clear Timer = 1 , Compare B Pwm = Clear Down 'Timer0 8bit高速PWM動作。 Ocr0b = 128 'パルス幅。(初期値) On Ovf0 Tm0int Nosave 'Timer0 オーバーフロー 割り込みルーチンを設定。 Enable Ovf0 'Timer0 オーバーフロー 割り込みを許可。 ' Stop Timer0 'Timer0を停止。(踏切音を停止) Wait 1 'ポートが安定するまでの待ち時間。 Set Tifr.tov0 'Timer0 オーバーフロー 割り込みをリセット。 Enable Interrupts 'すべての割り込みを許可。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: If Pinb.4 = 1 Then Goto Main 'If 踏切始動? Else Fmtout = Timeout '踏切音のタイムアウト回数を設定する。 Ledff = 0 Fmstart = 1 Wavpoi_a = 0 '波形[A]のポインターを初期化。 Wavpoi_b = 0 '波形[B]のポインターを初期化。 Wavenv = 0 Start Timer0 'Timer0を始動。(踏切音を発生開始) ' Main1: If Ledff = 0 Then 'LEDを交互に点滅させる。 Ledff = 1 Set Portb.2 Reset Portb.0 Else Ledff = 0 Set Portb.0 Reset Portb.2 End If ' For Temp1 = Wavmin To 255 '波形の立ち上がりを作成。 Wavenv = Temp1 For Temp2 = 0 To Attack '停止信号を確認しながらウエイト処理。 If Pinb.3 = 0 Then Fmstart = 0 Next Temp2 Next Temp1 ' For Temp1 = 255 To Wavmin Step -1 '波形の余韻を作成。 Wavenv = Temp1 For Tempw1 = 0 To Release '停止信号を確認しながらウエイト処理。 If Pinb.3 = 0 Then Fmstart = 0 Next Tempw1 Next Temp1 ' Fmtout = Fmtout - 1 If Fmtout = 0 Then Goto Main2 'If 踏切音のタイムアウト回数になったか? Then If Fmstart <> 0 Then Goto Main1 'If 踏切作動中? Then ' Main2: Stop Timer0 'Timer0を停止。(踏切音を停止) Reset Portb.0 'LEDを両方消灯。 Reset Portb.2 Goto Main ' ' ********************************************** ' * Timer0 オーバーフロー 割り込み処理ルーチン * ' ********************************************** ' Tm0int: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R16 PUSH R17 PUSH R22 PUSH R23 'R23は、拡張I/Oレジスタへのアクセスに使用する。 ; ; '--- 波形[A]の処理 --- LDS R17,{wavpoi_a+1} 'ポインターの位置を確認(上位8bitのみ使用)。 MOV R16,R17 SBRC R17,6 'If [$00-$3F または $80-$BF]か? Then COM R16 '[$40-$7F または $C0-$FF] Sin波の下り方向の場合。 ; ANDI R16,$3F Out Eearl , R16 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R22,EEDR 'EEPROMデータを取得。 ; SBRC R17,7 'If 波形の前半か? Then COM R22 '波形を後半用に処理。 ; LDS R16,{wavpoi_a} 'ポインターに加算値を加える。(16bit + 16bit) LDI R23,poiadd_al ADD R16,R23 LDI R23,poiadd_ah ADC R17,R23 STS {wavpoi_a},R16 '新しいポインター位置を格納。 STS {wavpoi_a+1},R17 ; ; '--- 波形[B]の処理 --- LDS R17,{wavpoi_b+1} 'ポインターの位置を確認(上位8bitのみ使用)。 MOV R16,R17 SBRC R17,6 'If [$00-$3F または $80-$BF]か? Then COM R16 '[$40-$7F または $C0-$FF] Sin波の下り方向の場合。 ; ANDI R16,$3F Out Eearl , R16 'EEPROMアドレスの下位バイトを設定。 SBI EECR,EERE 'EEPROM読み出し開始。 IN R16,EEDR 'EEPROMデータを取得。 ; SBRC R17,7 'If 波形の前半か? Then COM R16 '波形を後半用に処理。 ; ; ADD R22,R16 '--- [A],[B]波形を合成 --- ROR R22 LDS R16,{Wavenv} 'エンベロープ制御。(波形データ × エンベロープ値 ÷ 256) RCALL Mpy8u '8bitの掛け算。 Out Ocr0b , R23 '波形データをTimer0の比較器Bにセット。 ; LDS R16,{wavpoi_b} 'ポインターに加算値を加える。(16bit + 16bit) LDI R23,poiadd_bl ADD R16,R23 LDI R23,poiadd_bh ADC R17,R23 STS {wavpoi_b},R16 '新しいポインター位置を格納。 STS {wavpoi_b+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 ' ' **************************************** ' * EEPROM用 Sin波形データ (前1/4波形分) * ' **************************************** ' $eeprom '$eepromhex 'EEPROMファイルを、インテルHEX形式で作成する場合にコメントを外す。 ' Data &H80 , &H83 , &H86 , &H89 , &H8C , &H8F , &H92 , &H95 Data &H98 , &H9C , &H9F , &HA2 , &HA5 , &HA8 , &HAB , &HAE Data &HB0 , &HB3 , &HB6 , &HB9 , &HBC , &HBF , &HC1 , &HC4 Data &HC7 , &HC9 , &HCC , &HCE , &HD1 , &HD3 , &HD5 , &HD8 Data &HDA , &HDC , &HDE , &HE0 , &HE2 , &HE4 , &HE6 , &HE8 Data &HEA , &HEC , &HED , &HEF , &HF0 , &HF2 , &HF3 , &HF5 Data &HF6 , &HF7 , &HF8 , &HF9 , &HFA , &HFB , &HFC , &HFC Data &HFD , &HFE , &HFE , &HFF , &HFF , &HFF , &HFF , &HFF