' ' *********************************************** ' * * ' * 秋月電子製 DDSキット コントローラ * ' * * ' * AVR is using ATmega88 * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2009. 1.31 * ' *********************************************** ' ' Ver 1.02 初回公開バージョン ' ' Const Prgver = "01.02" 'プログラム・バージョン。 ' $regfile = "m88def.dat" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' ' Dim Frqdata As Long 'DDSに設定する周波数データ値。 Dim Fsmode As Byte '周波数の設定モード。 Dim Keyflg As Byte 'キー入力検出フラグ。 Dim Keydata As Byte 'キー入力データ。 Dim Keytmp As Byte 'キー入力用テンポラリ。 Dim Periodf As Byte '「ピリオド」入力確認フラグ。 Dim Vrdstim As Byte 'ボリュームモードのLCD表示タイマー。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Templ2 As Long '汎用テンポラリ変数 Long型 No.2 Dim Templ3 As Long '汎用テンポラリ変数 Long型 No.3 Dim Tempstr As String * 20 '汎用テンポラリ変数 String型 Dim Tempstr1 As String * 1 '汎用テンポラリ変数 String型 1文字用 Dim Tempstr2 As String * 20 '汎用テンポラリ変数 String型 No.2 Dim Tempstr3 As String * 20 '汎用テンポラリ変数 String型 No.3 ' Dim Eepuse As Eram Word At $02 'EEPROM 使用確認データ。 Dim Eepsta As Eram Long At $10 'EEPROM スイープ開始周波数。 Dim Eepend As Eram Long At $14 'EEPROM スイープ終了周波数。 Dim Eepstp As Eram Long At $18 'EEPROM スイープステップ周波数。 ' ' * ポート名の定義 * ' Dds_stb Alias Portc.3 'DDSキットの[/STB]接続ポート。 Dds_data Alias Portc.2 'DDSキットの[DATA]接続ポート。 Dds_sck Alias Portc.1 'DDSキットの[SCK]接続ポート。 Key_sw Alias Portd 'キースイッチの接続ポート。 Key_swin Alias Pind 'キースイッチの接続ポート。 Ad_vr1 Alias 4 'ボリューム1を接続するA/Dチャネル。 Ad_vr2 Alias 5 'ボリューム2を接続するA/Dチャネル。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portb.3 , Db5 = Portb.4 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portb.5 , Db7 = Portb.0 Config Lcdpin = Pin , E = Portb.2 , Rs = Portb.1 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 ' Cursor Off 'LCDのカーソルをオフ。 Cls 'LCD表示をすべて消去。 ' ' * ポートの初期設定 * ' Config Dds_stb = Output 'DDSの[/STB]接続ポートを出力に設定。 Set Portc.0 '未使用ポートをプルアップ。 Set Portb.6 '未使用ポートをプルアップ。 Set Portb.7 '未使用ポートをプルアップ。 Config Kbd = Key_sw 'キースイッチの接続構成を設定。 ' ' * Timer + ADC の設定 * ' Config Timer0 = Timer , Prescale = 1024 , Clear Timer = 1 'Timer0 8,000,000Hz / 1,024 = 7,813Hz Ocr0a = 78 - 1 '7,813Hz / 78 = 100Hz (約10mS) ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 ' ' * EEPROMの使用確認 * ' If Eepuse <> &H7355 Then 'If EEPROMが初期状態か? Then Eepsta = 0 'EEPROMに規定値を書き込む。 Eepend = 0 Eepstp = 0 Eepuse = &H7355 End If ' ' * プログラム・バージョンの表示 * ' Keydata = 16 Gosub Keychk 'キー入力を検出する。 If Keydata = 15 Then 'If [Fn]キーが押されているか? Then Locate 1 , 1 'プログラム・バージョンを表示。 Lcd "DDS Kit Cont." Locate 2 , 3 Lcd "Ver. " ; Prgver Prgvds: Gosub Keychk 'キー入力を検出する。 If Keyflg <> 0 Then Goto Prgvds 'If キーが離されたか? Else Cls 'LCD表示をすべて消去。 End If ' ' * 変数と表示の初期設定 * ' Set Dds_stb 'DDSの[/STB]接続ポートを[H]にする。 Temp1 = &H07 Gosub Ddsset 'DDSの出力を停止させる。 Keydata = 16 Locate 1 , 1 '「キー入力」モードの表示。 Lcd "Ky" Locate 1 , 15 Lcd "Hz" Locate 2 , 1 'ファンクション番号を表示。 Lcd "Fn0" ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Keyin 'キー入力処理。 Gosub Adconvt 'ボリューム値のA/D変換処理。 Goto Main ' End ' ' **************** ' * キー入力処理 * ' **************** ' Keyin: Gosub Keychk 'キー入力を検出する。 If Keydata > 15 Then Return 'If キーが押されたか? Else If Keydata = 15 Then Goto Keyin5 'If [Fn]キーが押されたか? Then If Keydata = 14 Then Goto Keyin4 'If [CLR]キーが押されたか? Then ' If Fsmode > 3 Then Return 'If ボリュームモードか? Then ' If Keydata > 10 Then Goto Keyin3 'If [MHz][KHz][Hz]キーが押されたか? Then ' ' * [数字]と[.]キーの処理 * ' Temp1 = Len(tempstr) If Temp1 < 10 Then 'If 文字数が9文字以内か? Then If Keydata = 10 Then 'If [.]キーか? Then If Periodf = 0 Then 'If 初めてのピリオド入力か? Then Tempstr1 = "." Periodf = 1 Else Tempstr1 = "" '2つめ以降のピリオドは無視する。 End If Else Tempstr1 = Str(keydata) 'キーコードを文字変数に変換。 End If Tempstr = Tempstr + Tempstr1 '文字列にキー入力文字を追加。 Locate 2 , 8 Lcd Format(tempstr , " ") '入力された文字列を右詰で表示。 End If Keyin01: Keydata = 16 'キー処理を完了。 Return ' ' * [Fn]ファンクション・キーの処理 * ' Keyin5: Locate 2 , 3 '[Fn]表示の右にカーソルを点滅させる。 Cursor On Blink ' Keyin51: Gosub Keychk 'キー入力を検出する。 If Keydata > 9 Then Goto Keyin51 'If 0-9キーが押されたか? Else Cursor Off Noblink 'カーソルを消去。 Lcd Keydata 'ファンクション番号を表示。 Fsmode = Keydata 'モードを変更。 ' If Fsmode > 3 Then Goto Keyin52 'If ボリュームモードか? Then If Fsmode = 0 Then Goto Keyin4 'If [Fn0]のキー入力モードか? Then ' Locate 1 , 1 '「キー入力」状態の表示。 Lcd "Ky" Locate 2 , 5 '[Fn1-3]のスイープモード。 Select Case Fsmode 'スイープモードの入力項目を表示。 Case 1: '「開始周波数」 Lcd "St" Frqdata = Eepsta Case 2: '「終了周波数」 Lcd "Ed" Frqdata = Eepend Case Else '「周波数間隔」 Lcd "Sp" Frqdata = Eepstp End Select Goto Keyin35 '* DDSに周波数を設定する * へジャンプ。 ' ' Keyin52: '[Fn4-9]のボリュームモード。 Locate 1 , 1 '「ボリューム設定」状態の表示。 Lcd "Vr" Temp1 = Fsmode - 4 Tempstr = Lookupstr(temp1 , Vrdspt) 'ボリュームの可変範囲を表示。 Locate 2 , 5 Lcd Spc(2) ; Tempstr Temp1 = &H0F 'DDSの出力を開始させる。 Gosub Ddsset Goto Keyin01 ' ' * [CLR]キーの処理 * ' Keyin4: Temp1 = &H07 'DDSの出力を停止させる。 Gosub Ddsset Locate 1 , 4 '周波数表示アリアを消去。 Lcd Spc(10) Keyin42: Locate 2 , 3 'キー入力モードにリセットする。 Lcd "0" ; Spc(3) Fsmode = 0 Locate 1 , 1 '「キー入力」状態の表示。 Lcd "Ky" Keyin41: Locate 2 , 7 'キー入力エリアを消去。 Lcd Spc(10) Tempstr = "" '文字列バッファをクリア。 Periodf = 0 'ピリオドフラグをクリア。 Goto Keyin01 ' ' * [MHz][KHz][Hz]キーの処理 * ' Keyin3: If Tempstr = "" Then Goto Keyin31 'If [MHz][KHz][Hz]キーのみが押されたか(DDS出力ON)? Then ' Temp1 = Instr(tempstr , ".") '[.]を検索する。(Temp1 = ピリオドの位置) ' If Keydata = 12 Then Goto Keyin33 'If [KHz]キーが押されたか? then If Keydata = 11 Then Goto Keyin34 'If [Hz]キーが押されたか? then ' ' * [MHz]キーの処理 * ' If Temp1 = 0 Then 'If [.]が無いか? Then Temp2 = Len(tempstr) '[.]が無い場合。 If Temp2 > 2 Then 'If 文字数が3桁以上か? Then Tempstr = Left(tempstr , 2) '左から2文字を有効とする。 End If Tempstr = Tempstr + "000000" 'MHzオーダーに修正する。 Else '[.]が有る場合。 If Temp1 < 4 Then 'If 整数桁が2以下か? Then Temp2 = Temp1 - 1 '整数桁を取り出す。 Tempstr2 = Left(tempstr , Temp2) Tempstr = Tempstr + "000000" '小数桁を取り出す。 Temp2 = Temp1 + 1 'Temp2 = 小数点桁の先頭位置。 Tempstr3 = Mid(tempstr , Temp2 , 6) Tempstr = Tempstr2 + Tempstr3 Else '整数桁が3桁以上の場合。 Tempstr = Left(tempstr , 2) '左から2文字を有効とする。 Tempstr = Tempstr + "000000" 'MHzオーダーに修正する。 End If End If Goto Keyin32 ' ' * [KHz]キーの処理 * ' Keyin33: If Temp1 = 0 Then 'If [.]が無いか? Then Temp2 = Len(tempstr) '[.]が無い場合。 If Temp2 > 5 Then 'If 文字数が5桁以上か? Then Tempstr = Left(tempstr , 5) '左から5文字を有効とする。 End If Tempstr = Tempstr + "000" 'KHzオーダーに修正する。 Else '[.]が有る場合。 If Temp1 < 7 Then 'If 整数桁が5以下か? Then Temp2 = Temp1 - 1 '整数桁を取り出す。 Tempstr2 = Left(tempstr , Temp2) Tempstr = Tempstr + "000" '小数桁を取り出す。 Temp2 = Temp1 + 1 'Temp2 = 小数点桁の先頭位置。 Tempstr3 = Mid(tempstr , Temp2 , 3) Tempstr = Tempstr2 + Tempstr3 Else '整数桁が6桁以上の場合。 Tempstr = Left(tempstr , 5) '左から5文字を有効とする。 Tempstr = Tempstr + "000" 'KHzオーダーに修正する。 End If End If Goto Keyin32 ' ' * [Hz]キーの処理 * ' Keyin34: If Temp1 = 0 Then 'If [.]が無いか? Then Temp2 = Len(tempstr) '[.]が無い場合。 If Temp2 > 8 Then 'If 文字数が9か? Then Tempstr = Left(tempstr , 8) '左から8文字を有効とする。 End If Else '[.]が有る場合。 Temp2 = Temp1 - 1 '[.]以下を削除する。 Tempstr2 = Left(tempstr , Temp2) Tempstr = Tempstr2 End If ' ' Keyin32: Frqdata = Val(tempstr) '文字列を数値に変換。 Keyin31: If Frqdata > 33554431 Then Frqdata = 33554431 'If 設定上限を超えているか? Then If Fsmode > 0 Then Goto Keyin36 'If スイープモードか? Then ' ' * DDSに周波数を設定する * ' Keyin35: Temp1 = &H67 'DDSに周波数を設定。 Gosub Ddsset Temp1 = &H0F 'DDSの出力を開始させる。 Gosub Ddsset ' Gosub Frqdisp 'LCDに設定周波数を表示する。 Goto Keyin41 ' ' * スイープモードの設定 * ' Keyin36: Locate 2 , 5 'スイープモードの入力項目を消去。 Lcd Spc(2) If Fsmode = 3 Then Goto Sweep 'If 「スイープモード」開始か? Then If Tempstr = "" Then Goto Keyin42 'If 数値入力が無かったか? Then If Fsmode = 1 Then 'If スイープ開始周波数の設定か? Then Eepsta = Frqdata Else 'スイープ終了周波数の設定。 Eepend = Frqdata End If Locate 2 , 3 'キー入力モードにリセットする。 Lcd "0" ; Spc(3) Fsmode = 0 Goto Keyin35 ' ' * スイープモードを開始 * ' Sweep: If Tempstr <> "" Then 'If 数値入力が有ったか? Then Eepstp = Frqdata 'スイープ周波数間隔の設定。 End If ' Locate 2 , 6 'スイープモードの表示。 Lcd "Sweep Start" Templ1 = Eepsta 'EEPROMデータをSRAMにコピー。 Templ2 = Eepend Templ3 = Eepstp Temp1 = &H0F 'DDSの出力を開始させる。 Gosub Ddsset Key_sw = &H7F '[C]キーを検出する設定。(右列のキーを有効にする) If Templ1 > Templ2 Then Goto Sweep1 'If 周波数の変位がマイナスか? Then ' Locate 2 , 5 '周波数を[+]に変位。 Lcd "<" Sweep2: Frqdata = Templ1 Temp1 = &H67 'DDSに周波数を設定。 Gosub Ddsset Templ1 = Templ1 + Templ3 If Templ1 > Templ2 Then 'If 終了周波数に達したか? Then Templ1 = Eepsta End If ' Tempw1 = Getadc(ad_vr1 , &H20) 'ボリューム1をA/D変換する(8bit)。 Temp1 = High(tempw1) Sweep3: If Key_swin = &H7E Then Goto Keyin4 'If [C]キーが押されたか? Else If Temp1 = 0 Then Goto Sweep2 'If 待ち時間に達したか? Then Temp1 = Temp1 - 1 Goto Sweep3 ' ' Sweep1: '周波数を[-]に変位。 Locate 2 , 5 Lcd ">" Sweep4: Frqdata = Templ1 Temp1 = &H67 'DDSに周波数を設定。 Gosub Ddsset Templ1 = Templ1 - Templ3 If Templ1 < Templ2 Then 'If 終了周波数に達したか? Then Templ1 = Eepsta End If ' Tempw1 = Getadc(ad_vr1 , &H20) 'ボリューム1をA/D変換する(8bit)。 Temp1 = High(tempw1) Sweep5: If Key_swin = &H7E Then Goto Keyin4 'If [C]キーが押されたか? Else If Temp1 = 0 Then Goto Sweep4 'If 待ち時間に達したか? Then Temp1 = Temp1 - 1 Goto Sweep5 ' ' ***************************** ' * ボリューム値のA/D変換処理 * ' ***************************** ' Adconvt: If Fsmode < 4 Then Return 'If ボリュームモードか? Else ' If Tifr0.ocf0a = 0 Then Return 'If Timer0が10mSカウント終了? Else Set Tifr0.ocf0a 'Timer0 比較A一致フラグをリセット。 ' Tempw1 = Getadc(ad_vr1 , &H20) 'ボリューム1をA/D変換する(8bit)。 Temp1 = High(tempw1) Select Case Fsmode 'モードに合わせて、周波数範囲を設定する。 Case 4: '[Fn4] 0-12.8 KHz Shift Temp1 , Right , 1 Frqdata = Temp1 * 100 Case 5: '[Fn5] 0-25.6 KHz Frqdata = Temp1 * 100 Case 6: '[Fn6] 0-127 KHz Shift Temp1 , Right , 1 Frqdata = Temp1 * 1000 Case 7: '[Fn7] 0-1.27 MHz Shift Temp1 , Right , 1 Frqdata = Temp1 * 10000 Case 8: '[Fn8] 0-12.7 MHz Shift Temp1 , Right , 1 Frqdata = Temp1 * 100000 Case 9: '[Fn9] 0-25.5 MHz Frqdata = Temp1 * 100000 End Select ' Tempw1 = Getadc(ad_vr2 , &H20) 'ボリューム2をA/D変換する(8bit)。 Temp1 = High(tempw1) Select Case Temp1 '微調整(オフセット)を加算する。 Case Is > 134 : '[+]加算の場合。 Temp1 = Temp1 - 135 Frqdata = Frqdata + Temp1 Case Is < 121 : '[-]減算の場合。 Temp1 = 120 - Temp1 Frqdata = Frqdata - Temp1 End Select If Frqdata < 0 Then Frqdata = 0 'If 周波数値がマイナスか? Then ' Temp1 = &H67 'DDSに周波数を設定。 Gosub Ddsset ' ' * 200mS毎に、LCDに設定周波数を表示する * ' Vrdstim = Vrdstim + 1 If Vrdstim < 20 Then Return 'If 200mS経過したか? Else Vrdstim = 0 ' Gosub Frqdisp 'LCDに設定周波数を表示する。 Return ' ' **************************** ' * キー入力検出サブルーチン * Keydata = キーコード。 ' **************************** ' Keychk: If Keyflg <> 0 Then Goto Keychk1 'If キーが離されるのを検出中か? Then Keytmp = Getkbd() 'キー入力を検出する。 If Keytmp > 15 Then Return 'If キーが押されたか? Else Keydata = Lookup(keytmp , Keytab) 'キーデータをテーブルで変換する。 Waitms 30 'チャタリング防止の待ち時間。 Keyflg = 1 Return ' ' Keychk1: 'キーが離されるのを待つ処理。 Keytmp = Getkbd() 'キー入力を検出する。 If Keytmp < 16 Then Return 'If キーが押され続けているか? Then Waitms 30 'チャタリング防止の待ち時間。 Keyflg = 0 Return ' ' *************************************** Temp1 = コマンド。(&H07 = 出力OFF , &H0F = 出力ON) ' * DDSにコマンドを送信するサブルーチン * (&H67 = 周波数設定) ' *************************************** Frqdata = 設定周波数。(26ビット ロング型) ' Ddsset: Shiftout Dds_data , Dds_sck , Temp1 , 3 , 7 'DDSにコマンドを送信。 Shiftout Dds_data , Dds_sck , Frqdata , 3 , 26 'DDSに周波数データを送信。 Reset Dds_stb 'DDSの[/STB]を[L]にする。 Set Dds_stb 'DDSの[/STB]を[H]にする。 Return ' ' ***************************************** ' * LCDに設定周波数を表示するサブルーチン * ' ***************************************** ' Frqdisp: Locate 1 , 4 Tempstr = Str(frqdata) '周波数を文字列に変換。 Temp1 = Len(tempstr) '文字列の桁数を調べる。 Select Case Temp1 Case Is < 4 : '[3桁以下の場合] Lcd Spc(7); Lcd Format(tempstr , " ") '下位3桁を表示する。 Case Is < 7 : '[6桁以下の場合] Lcd Spc(3); Temp2 = Temp1 - 3 '上位3桁を表示する。 Tempstr2 = Left(tempstr , Temp2) Lcd Format(tempstr2 , " "); Tempstr2 = Right(tempstr , 3) '下位3桁を表示する。 Lcd "," ; Tempstr2 Case Else : '[7桁以上の場合] Temp2 = Temp1 - 6 '上位2桁を表示する。 Tempstr2 = Left(tempstr , Temp2) Lcd Format(tempstr2 , " "); Temp2 = Temp1 - 5 '中間の3桁を表示する。 Tempstr2 = Mid(tempstr , Temp2 , 3) Lcd "," ; Tempstr2; Tempstr2 = Right(tempstr , 3) '下位3桁を表示する。 Lcd "," ; Tempstr2 End Select Return ' End ' ' * キーコードの変換テーブル * ' Keytab: Data 11 , 10 , 0 , 15 , 12 , 3 , 2 , 1 , 13 , 6 , 5 , 4 , 14 , 9 , 8 , 7 ' ' * ボリュームモードの範囲表示テーブル * ' Vrdspt: Data "0-12.8 KHz" '[Fn4] Data "0-25.6 KHz" '[Fn5] Data "0-127 KHz " '[Fn6] Data "0-1.27 MHz" '[Fn7] Data "0-12.7 MHz" '[Fn8] Data "0-25.5 MHz" '[Fn9]