' ' ****************************************************** ' * * ' * 周波数カウンター・プログラム (Wave Display PLUS) * ' * * ' * AVR is using ATmega164P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2008.12.16 * ' ****************************************************** ' ' Ver 2.01 初回公開バージョン ' ' Const Prgver = "02.01" 'プログラム・バージョン。 ' $regfile = "m164Pdef.dat" '使用するAVRを設定。 $crystal = 20000000 'AVRクロックを設定。 ' Sw_o1 Alias Porta.2 'スイッチ1のポートピン指定。 Sw_1 Alias Pina.2 Sw_o2 Alias Porta.1 'スイッチ2のポートピン指定。 Sw_2 Alias Pina.1 Sw_o3 Alias Porta.0 'スイッチ3のポートピン指定。 Sw_3 Alias Pina.0 Sw_pt Alias Pina 'スイッチ接続ポート。 Const Sw_and = &H07 'スイッチのビットマスク用データ。 ' Msel_a Alias Portb.2 '計測モード選択Aのポートピン指定。 Msel_b Alias Portd.2 '計測モード選択Bのポートピン指定。 ' ' Dim Sampbuf(768) As Byte At $100 'サンプリング データ・バッファー。 Dim Buffadr As Word 'サンプリング・バッファーのアドレス・ポインター。 Dim Chiplcd As Byte 'G-LCDのチップ番号。 Dim Lastdat As Byte '波形描画時の前回データ値。 Dim Wavadr As Word 'サンプリング波形の先頭アドレス。 Dim Wavbit As Byte 'サンプリング波形の先頭ビット番号。 Dim Wavsmpt As Long '波形のサンプリング時間。 Dim Wavnum As Byte 'サンプリング波形の採取間隔数。 ' Dim Capmode As Byte 'キャプチャー割り込みの動作モード。 Dim Capendf As Byte 'キャプチャー計測完了フラグ。 Dim Capdat1 As Word 'キャプチャー・レジスター値 バッファー1。 Dim Capovf1 As Word 'オーバーフロー・カウント値 バッファー1。 Dim Capdat2 As Word 'キャプチャー・レジスター値 バッファー2。 Dim Capovf2 As Word 'オーバーフロー・カウント値 バッファー2。 Dim Capovfc As Word 'オーバーフロー・カウンター。 Dim Cap5hc As Byte 'ゲート・モード用の5Hzカウンター。 ' Dim Frqdat As Long 'キャプチャー・データを差分計算したカウント値。 Dim Measure As Byte '計測モード。(0 = ゲート・モード , 1 = レシプロカル・モード) Dim Prescale As Byte 'プリスケラ値。(0=1/1 , 1=1/10 , 2=1/100) Dim Average As Long 'レシプロカル・モード用の平均値。 Dim Avernum As Long 'レシプロカル・モード用の平均数。 Dim Aver05c As Byte 'レシプロカル・モード用の0.5秒カウンター。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 Dim Temp4 As Byte '汎用テンポラリ変数 Byte型 No.4 Dim Temp5 As Byte '汎用テンポラリ変数 Byte型 No.5 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Templ2 As Long '汎用テンポラリ変数 Long型 No.2 Dim Temps1 As Single '汎用テンポラリ変数 Single型 No.1 Dim Tempstr As String * 15 '汎用テンポラリ変数 String型 Dim Tempstr2 As String * 15 '汎用テンポラリ変数 String型 No.2 ' ' ' ' * ポートの初期設定 * ' Config Msel_a = Output 'モード選択Aポートを出力に設定。 Config Msel_b = Output 'モード選択Bポートを出力に設定。 Config Portd.5 = Output 'G-LCD [RES]ポートを出力に設定。 Config Portd.7 = Output '[OC2A]ポートを出力に設定。##### BASCOM-AVR のバグ ##### Config Portb.3 = Output '[OC0A]ポートを出力に設定。##### BASCOM-AVR のバグ ##### ' Set Sw_o1 'スイッチ1 ポートをプルアップ。 Set Sw_o2 'スイッチ2 ポートをプルアップ。 Set Sw_o3 'スイッチ3 ポートをプルアップ。 Set Portd.0 '未使用ポートをプルアップ。 Set Portd.1 '未使用ポートをプルアップ。 Set Portd.3 '未使用ポートをプルアップ。 Set Portd.4 '未使用ポートをプルアップ。 ' ' * G-LCDの初期設定 * ' Reset Portd.5 'G-LCDをリセットする。 Waitms 100 Set Portd.5 ' $lib "glcdKS108c.LBX" 'S1D1520チップ用ライブラリ(KS108修正版)の使用を指示。 Config Graphlcd = 128 * 64sed , Dataport = Portc , Controlport = Porta , Ce = 4 , Ce2 = 5 , Cd = 3 , Rd = 7 , Reset = 3 , Enable = 6 Cls 'LCD表示をすべて消去。 Setfont Offont6x8 'フォント・データを定義。 ' ' * タイマーの設定 * ' 'Config Timer2 = Timer , Prescale = 64 , Clear Timer = 1 , Compare A = Toggle '20,000,000Hz / 64 = 312,500Hz Tccr2a = &H42 '##### BASCOM-AVR のバグ ##### Tccr2b = &H04 Ocr2a = 125 - 1 '312,500Hz / 125カウント = (2,500 / 2) = 1,250Hz ' Config Timer0 = Counter , Edge = Rising , Clear Timer = 1 'Compare A = Toggle '[OC0A]端子から5Hzパルスを出力。 Set Tccr0a.com0a0 '##### BASCOM-AVR のバグ ##### Ocr0a = 125 - 1 '1,250Hz / 125カウント = (10 / 2) = 5Hz ' Config Timer1 = Counter , Edge = Falling , Capture Edge = Falling '[T1]の立ち下がりエッジでカウント。 On Capture1 Tintcap Nosave 'キャプチャー割り込みルーチンのラベルを設定。 Enable Capture1 'キャプチャー割り込みを許可。 On Timer1 Tintovf Nosave 'オーバーフロー割り込みルーチンのラベルを設定。 Enable Timer1 'オーバーフロー割り込みを許可。 ' ' * ハードウェアSPIの設定 * ' Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = No , Polarity = Low , Phase = 0 Spiinit ' ' * プログラム・バージョンの表示 * ' If Sw_1 = 0 Then 'If スイッチ1が押されているか? Then Lcdat 1 , 7 , "Frequency Counter" 'プログラム・バージョンを表示。 Lcdat 3 , 31 , "Ver. " Lcdat 3 , 61 , Prgver Bitwait Sw_1 , Set 'スイッチ1が離されるまで待つ。 Waitms 30 'チャタリング・タイマー。 Cls End If ' ' * 変数と表示の初期設定 * ' Measure = 0 '0 = ゲート・モード。 Prescale = 0 'プリスケラ値 0 = 1/1 。 Average = 0 'レシプロカル・モード用の平均値。 Avernum = 0 'レシプロカル・モード用の平均数。 Gosub Prescdss 'プリスケラ値の表示と設定。 Enable Interrupts 'すべての割り込みを許可。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Switchin 'スイッチの入力処理。 Gosub Frqcal 'カウント値の計算処理。 Goto Main ' ' ********************************** ' * スイッチの入力処理サブルーチン * ' ********************************** ' Switchin: If Sw_1 = 0 Then Goto Switchin1 'If スイッチ1が押されたか? Then If Sw_2 = 0 Then Goto Switchin2 'If スイッチ2が押されたか? Then Return ' Switchin1: 'スイッチ1 (モードの選択) Cls 'LCD画面をクリアする。 If Measure = 0 Then 'If 計測モードがゲート・モード? Then Measure = 1 'レシプロカル・モードに設定。 Lcdat 1 , 1 , "Recp" Lcdat 2 , 1 , " " Set Msel_a 'モードセレクターを設定。 Set Msel_b Prescale = 0 Config Timer1 = Timer , Prescale = 1 , Capture Edge = Falling 'AVR動作クロックによりカウント。 Else Measure = 0 'ゲート・モードに設定。 Gosub Prescdss Config Timer1 = Counter , Edge = Falling , Capture Edge = Falling '[T1]の立ち下がりエッジでカウント。 End If Bitwait Sw_1 , Set 'スイッチ1が離されるまで待つ。 Waitms 30 'チャタリング・タイマー。 Return ' ' Switchin2: 'スイッチ2 (プリスケラの選択) If Measure <> 0 Then Return 'If ゲート・モード? Else Prescale = Prescale + 1 Gosub Prescdss 'プリスケラ値の表示と設定。 Bitwait Sw_2 , Set 'スイッチ2が離されるまで待つ。 Waitms 30 'チャタリング・タイマー。 Return ' ' * プリスケラ値の表示と設定サブルーチン * ' Prescdss: Lcdat 1 , 1 , "Gate" Select Case Prescale Case 1 : 'プリスケラ 1/10。 Lcdat 2 , 1 , "P10 " Set Msel_a 'モードセレクターを設定。 Reset Msel_b Case 2 : 'プリスケラ 1/100。 Lcdat 2 , 1 , "P100" Reset Msel_a 'モードセレクターを設定。 Set Msel_b Case Else : 'プリスケラ 1/1。 Lcdat 2 , 1 , "P1 " Reset Msel_a 'モードセレクターを設定。 Reset Msel_b Prescale = 0 End Select Return ' ' ************************************ ' * カウント値の計算処理サブルーチン * ' ************************************ ' Frqcal: If Capendf = 0 Then Return 'If キャプチャー計測が完了したか? Else ' Gosub Capsubt 'キャプチャー・バッファーの値を差分計算する。=> (Frqdat) If Measure = 1 Then Goto Frqcal2 'If レシプロカル・モード? Then ' ' ****************** ' * ゲート・モード * ' ****************** ' Tempstr = Str(frqdat) '計測値を文字列に変換。 Templ1 = 1000000000 '周期測定用の被除数。(1/1 用) Select Case Prescale 'プリスケラにより、無効桁のマーク(x)を追加。 Case 1 : Tempstr = Tempstr + "x" '1/10 モード。 Templ1 = 100000000 '周期測定用の被除数。(1/10 用) Case 2 : Tempstr = Tempstr + "xx" '1/100 モード。 Templ1 = 10000000 '周期測定用の被除数。(1/100 用) End Select ' ' * LCDへ周波数を表示 * ' Temp1 = Len(tempstr) '計測値の桁数を調べる。 Select Case Temp1 '周波数により表示桁を整える。 Case Is > 8: Tempstr2 = "--- Over ---" '100MHz以上。 Case 8 : Tempstr2 = Format(tempstr , " . ") + "MHz" '10MHz以上。 Case 7 : Tempstr2 = Format(tempstr , " . ") + " MHz" '1〜9MHz。 Case Is > 3: Tempstr2 = " " + Format(tempstr , " . ") + " KHz" '1〜999KHz。 Case Else : Tempstr2 = " " + Format(tempstr , " ") + " Hz " '1〜999Hz。 End Select Lcdat 1 , 43 , Tempstr2 ' ' * LCDへ周期を表示 * ' Templ1 = Templ1 / Frqdat '計測値を周期に変換。 Gosub Timdss '1ns〜2Secまでの周期を表示する。 Lcdat 2 , 37 , Tempstr2 ' Gosub Spisamp 'SPI スレーブ・モードで、測定入力をサンプリングし表示する。 Capendf = 0 'キャプチャー計測完了フラグをクリア。 Return ' ' ************************ ' * レシプロカル・モード * ' ************************ ' Frqcal2: If Frqdat < 56 Then Goto Frqcal21 'If 350KHzを超えたか? Then If Frqdat < 20000000 Then Goto Frqcal22 'If 1Hz以上か? Then ' ' * LCDへ周波数を表示 * ' Frqcal24: Temps1 = 20000000 / Frqdat '計測値を周波数に変換。 Frqcal25: Select Case Temps1 '周波数により表示桁を整える。 Case Is >= 100000 : Tempstr2 = Fusing(temps1 , "#.##") '100000〜999999Hz。 Case Is >= 10000 : Tempstr2 = Fusing(temps1 , "#.###") '10000〜99999Hz。 Case Is >= 1000 : Tempstr2 = Fusing(temps1 , "#.####") '1000〜9999Hz。 Case Is >= 100 : Tempstr2 = Fusing(temps1 , "#.#####") '100〜999Hz。 Case Is >= 10 : Tempstr2 = Fusing(temps1 , "#.######") '10〜99Hz。 Case Else : Tempstr2 = Fusing(temps1 , "#.#######") '0〜9Hz。 End Select Lcdat 1 , 37 , Tempstr2 Lcdat 1 , 91 , " Hz" ' ' * LCDへ周期を表示 * ' If Frqdat < 40000000 Then 'If 周期が2秒未満か? Then (Long変数がオーバーフローするため) Templ1 = 50 * Frqdat '計測値を周期に変換。 Gosub Timdss '1ns〜2Secまでの周期を表示する。 Else Temps1 = 0.5 * Frqdat '計測値を周期に変換。 Templ1 = Int(temps1) '整数化。 Tempstr = Str(templ1) '周期値を文字列に変換。 If Templ1 < 100000000 Then Tempstr2 = Format(tempstr , " . ") + " S " '2S〜9S。 Else Tempstr = Left(tempstr , 8) Tempstr2 = Format(tempstr , " . ") + " S " '10S〜99S。 End If End If Lcdat 2 , 37 , Tempstr2 ' Frqcal26: Capendf = 0 'キャプチャー計測完了フラグをクリア。 Return ' ' Frqcal21: '200KHzを超えたオーバー表示。 Lcdat 1 , 37 , "--- Over ---" Lcdat 2 , 37 , " " Goto Frqcal26 ' Frqcal22: '1Hz以上の場合、0.5秒間隔で平均処理し表示を更新。 If Tifr0.ocf0a = 0 Then Goto Frqcal27 'If 0.5秒経過したか? Else Set Tifr0.ocf0a 'タイマー0比較A割り込み要求フラグをリセット。 Aver05c = Aver05c + 1 If Aver05c = 5 Then Goto Frqcal23 'If 0.5秒経過したか? Then ' Frqcal27: Average = Average + Frqdat '平均値に加算。 Avernum = Avernum + 1 '平均数を加算。 Goto Frqcal26 ' Frqcal23: Aver05c = 0 If Avernum = 0 Then Goto Frqcal24 'If 平均化処理が済んでいないか? Then Temps1 = Average / Avernum '平均値を算出。 Temps1 = 20000000 / Temps1 '計測値を周波数に変換。 Average = 0 Avernum = 0 Goto Frqcal25 ' ' ********************************************* ' * 1ns〜2Secまでの周期を表示するサブルーチン * ' ********************************************* ' Timdss: Tempstr = Str(templ1) '周期値を文字列に変換。 Temp1 = Len(tempstr) '周期値の桁数を調べる。 Select Case Temp1 '周期値により表示桁を整える。 Case 10 : Tempstr = Left(tempstr , 8) Tempstr2 = Format(tempstr , " . ") + " S " '1S以上。 Case 9 : Tempstr = Left(tempstr , 8) '100〜999mS。 Tempstr2 = Format(tempstr , " . ") + " mS" Case Is >= 7 : Tempstr2 = Format(tempstr , " . ") + " mS" '1〜99mS。 Case Is >= 4: Tempstr2 = " " + Format(tempstr , " . ") + " uS" '1〜999uS。 Case Else : Tempstr2 = " " + Format(tempstr , " ") + " nS" '1〜999nS。 End Select Return ' ' ****************************************************** ' * SPI スレーブ・モードで、測定入力をサンプリングする * ' ****************************************************** ' Spisamp: If Prescale <> 0 Then Goto Cantdisp 'If プリスケラが「1/1」か? Else If Frqdat > 2500000 Then Goto Cantdisp 'If 計測周波数が2.5MHz以上か? Then If Frqdat = 0 Then Goto Cantdisp 'If 入力が無いか? Then ' Disable Interrupts 'すべての割り込みを禁止する。 ' ' *** [OC0A]出力を、サンプリング・クロックに切り換える *** ' Config Timer0 = Timer , Prescale = 1 , Clear Timer = 1 'Compare A = Toggle Set Tccr0a.com0a0 '##### BASCOM-AVR のバグ ##### Ocr0a = 2 - 1 '20MHz / 2カウント = (10Mz / 2) = 5MHz (200nS) Wavsmpt = 200 '波形のサンプリング時間。 ' ' * 測定周波数により、サンプリング採取間隔とサンプリング時間を選択する * ' Select Case Frqdat Case Is >= 85000 : '[2.5MHz〜85KHz] Wavnum = 1 'サンプリング波形の採取間隔数。 Case Is >= 43000 : '[84.999KHz〜43KHz] Wavnum = 2 'サンプリング波形の採取間隔数。 Case Is >= 22000 : '[42.999KHz〜22KHz] Wavnum = 4 'サンプリング波形の採取間隔数。 Case Is >= 11000 : '[21.999KHz〜11KHz] Wavnum = 8 'サンプリング波形の採取間隔数。 Case Is >= 6000 : '[10.999KHz〜6KHz] Wavnum = 16 'サンプリング波形の採取間隔数。 Case Is >= 2500 : '[5.999KHz〜2.5KHz] Wavnum = 32 'サンプリング波形の採取間隔数。 Case Is >= 1100 : '[2.499KHz〜1.1KHz] Ocr0a = 5 - 1 '20MHz / 5カウント = (4Mz / 2) = 2MHz (500nS) Wavsmpt = 500 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 Case Is >= 600 : '[1.099KHz〜600Hz] Ocr0a = 10 - 1 '20MHz / 10カウント = (2Mz / 2) = 1MHz (1uS) Wavsmpt = 1000 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 Case Is >= 110 : '[599Hz〜110Hz] Ocr0a = 50 - 1 '20MHz / 50カウント = (400KHz / 2) = 200KHz (5uS) Wavsmpt = 5000 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 Case Is >= 28 : '[109Hz〜28Hz] Ocr0a = 200 - 1 '20MHz / 200カウント = (100KHz / 2) = 50KHz (20uS) Wavsmpt = 20000 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 Case Is >= 5 : '[27Hz〜5Hz] Tccr2b = &H01 'Config Timer2 = Timer , Prescale = 1 , Clear Timer = 1 , Compare A = Toggle Ocr2a = 50 - 1 '20,000,000Hz / 50カウント = (400KHz / 2) = 200KHz Config Timer0 = Counter , Edge = Rising , Clear Timer = 1 'Compare A = Toggle Set Tccr0a.com0a0 '##### BASCOM-AVR のバグ ##### Ocr0a = 10 - 1 '200KHz / 10カウント = (20KHz / 2) = 10KHz (100uS) Wavsmpt = 100000 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 Case Else : '[4Hz〜1Hz] Tccr2b = &H01 'Config Timer2 = Timer , Prescale = 1 , Clear Timer = 1 , Compare A = Toggle Ocr2a = 50 - 1 '20,000,000Hz / 50カウント = (400KHz / 2) = 200KHz Config Timer0 = Counter , Edge = Rising , Clear Timer = 1 'Compare A = Toggle Set Tccr0a.com0a0 '##### BASCOM-AVR のバグ ##### Ocr0a = 50 - 1 '200KHz / 50カウント = (4KHz / 2) = 2KHz (500uS) Wavsmpt = 500000 '波形のサンプリング時間。 Wavnum = 32 'サンプリング波形の採取間隔数。 End Select Waitms 1 'Timer0 安定動作待ち。 ' ' * ハードウェアSPIで波形をサンプリングする * ' If Wavsmpt = 200 Then 'If サンプリング時間が200nSか? Then $asm Loadadr Sampbuf(1) , X 'X = サンプリング データ・バッファーの先頭アドレス。 Spisamp1: SBIS SPSR,SPIF0 'If 1byte(8個)のデータをサンプリング完了か? Else RJMP Spisamp1 ; IN R16,SPDR 'SPI 受信データを読み込み。 ST X+,R16 'サンプリング データ・バッファーへ書き込み。 CPI XH,$04 BRNE Spisamp1 'If 768byte書き込み終了か? Else $end Asm ' Else 'サンプリング時間が長い場合は、キー入力をチェックする。 $asm Loadadr Sampbuf(1) , X 'X = サンプリング データ・バッファーの先頭アドレス。 Spisamp5: SBIS SPSR,SPIF0 'If 1byte(8個)のデータをサンプリング完了か? Else RJMP Spisamp5 ; IN R16,SPDR 'SPI 受信データを読み込み。 ST X+,R16 'サンプリング データ・バッファーへ書き込み。 IN R17,Sw_pt 'キー入力をチェックする。 ANDI R17,Sw_and CPI R17,Sw_and BRNE Spisamp4 'If キー入力があったか? The CPI XH,$04 BRNE Spisamp5 'If 768byte書き込み終了か? Else Spisamp4: $end Asm End If ' ' *** [OC0A]出力を、ゲート信号に戻す *** ' 'Config Timer2 = Timer , Prescale = 64 , Clear Timer = 1 , Compare A = Toggle '20,000,000Hz / 64 = 312,500Hz Tccr2a = &H42 '##### BASCOM-AVR のバグ ##### Tccr2b = &H04 Ocr2a = 125 - 1 '312,500Hz / 125カウント = (2,500 / 2) = 1,250Hz ' Config Timer0 = Counter , Edge = Rising , Clear Timer = 1 'Compare A = Toggle '[OC0A]端子から5Hzパルスを出力。 Set Tccr0a.com0a0 '##### BASCOM-AVR のバグ ##### Ocr0a = 125 - 1 '1,250Hz / 125カウント = (10 / 2) = 5Hz ' ' ********************************************************* ' * サンプリング データ・バッファーから波形の周期を調べる * ' ********************************************************* ' Buffadr = 2 'バッファーのスタートアドレス。(最初の1バイトは不定のため使わない) Temp2 = Sampbuf(buffadr) 'バッファーを検索する初期値を設定。 Temp3 = 7 ' Temp1 = 1 '[0]レベルを検索する。(バッファー内の波形は、74AC14で反転している) Gosub Bufsearch If Tempw1 = 0 Then Goto Spisamp2 'If [0]レベルが見つからなかったか? Then ' Temp1 = 0 '[1]レベルを検索する。(立ち上がりエッジを検出する) Gosub Bufsearch If Tempw1 = 0 Then Goto Spisamp2 'If [1]レベルが見つからなかったか? Then ' Wavadr = Buffadr 'サンプリング波形の先頭アドレスを保管。 Wavbit = Temp3 'サンプリング波形の先頭ビット番号を保管。 ' Temp1 = 1 '[0]レベルを検索する。(Hレベルの期間をカウントする) Gosub Bufsearch If Tempw1 = 0 Then Goto Spisamp2 'If [0]レベルが見つからなかったか? Then Tempw1 = Tempw1 - 1 Templ1 = Tempw1 * Wavsmpt '周期 = サンプル数 * サンプリング時間 ' Temp1 = 0 '[1]レベルを検索する。(Lレベルの期間をカウントする) Gosub Bufsearch If Tempw1 = 0 Then Goto Spisamp2 'If [1]レベルが見つからなかったか? Then Tempw1 = Tempw1 - 1 Templ2 = Tempw1 * Wavsmpt '周期 = サンプル数 * サンプリング時間 ' ' Lcdat 4 , 61 , " " Frqdat = Templ1 '[H]レベルの周期値を表示する。 Gosub Tstrcnv '周期を文字列に変換する Lcdat 4 , 1 , "H=" 'G-LCDへ表示する。 Lcdat 4 , 11 , Tempstr2 ' Frqdat = Templ2 '[L]レベルの周期値を表示する。 Gosub Tstrcnv '周期を文字列に変換する Lcdat 4 , 65 , "L=" 'G-LCDへ表示する。 Lcdat 4 , 75 , Tempstr2 ' ' *************************************************** (Wavadr = サンプリング波形の先頭アドレス) ' * サンプリング データ・バッファーの波形を表示する * (Wavbit = サンプリング波形の先頭ビット番号) ' *************************************************** (Wavnum = サンプリング波形の採取間隔数) ' Glcdcmd &HBA , 1 'G-LCDチップ1に、Yアドレス(3行目)設定コマンドを送る。 Glcdcmd &H00 , 1 'G-LCDチップ1に、Xアドレス設定コマンドを送る。 Glcdcmd &HBA , 2 'G-LCDチップ2に、Yアドレス(3行目)設定コマンドを送る。 Glcdcmd &H00 , 2 'G-LCDチップ2に、Xアドレス設定コマンドを送る。 Lastdat = 0 Chiplcd = 1 Temp2 = Sampbuf(wavadr) ' For Temp1 = 1 To 122 'G-LCD 1行分の波形を表示する。 If Temp1 = 62 Then Chiplcd = 2 'If G-LCDのチップを変更か? Then ' Temp4 = 0 '周波数により、データの採取間隔のレベルを検査する。 For Temp3 = 1 To Wavnum '採取間隔分の繰り返し。 If Temp2.wavbit = 1 Then 'If 波形が[L]レベルか? Then Temp4 = Temp4 Or &H01 '[L]値を論理和。 Temp5 = 0 '最終位置のレベルを保存。 Else Temp4 = Temp4 Or &H02 '[H]値を論理和。 Temp5 = 1 '最終位置のレベルを保存。 End If ' Wavbit = Wavbit - 1 '検査するビット位置を更新する。 If Wavbit = &HFF Then 'If 8bit分のチェックが終わったか? Else Wavbit = 7 Wavadr = Wavadr + 1 Temp2 = Sampbuf(wavadr) End If Next Temp3 ' If Temp4 = &H03 Then 'If [L]と[H]レベルが混在しているか? Then Glcddata &H7E , Chiplcd Lastdat = Temp5 Else If Temp4 = &H01 Then 'If 波形が[L]レベルか? Then If Lastdat = 0 Then 'If 前のデータが[L]レベルか? Then Glcddata &H40 , Chiplcd '[L]レベルの続き。 Else Glcddata &H7E , Chiplcd '[H]レベルへ変更。 End If Lastdat = 0 Else '波形が[H]レベル。 If Lastdat = 0 Then 'If 前のデータが[L]レベルか? Then Glcddata &H7E , Chiplcd '[L]レベルへ変更。 Else Glcddata &H02 , Chiplcd '[H]レベルの続き。 End If Lastdat = 1 End If End If ' Next Temp1 ' Spisamp3: Capmode = 0 'キャプチャー・モードを初期化する。 Cap5hc = 4 'ゲート・モード用の5HzカウンターをMAXに設定。 Timer0 = 120 Set Tifr1.icf1 'キャプチャー割り込みフラグをクリア。 Enable Interrupts 'すべての割り込みを許可。 Return ' ' Spisamp2: Gosub Cantdisp '「波形表示できない」メッセージを表示する。 Goto Spisamp3 ' ' * 「波形表示できない」メッセージを表示する * ' Cantdisp: Lcdat 3 , 1 , " " Lcdat 4 , 1 , "---Cannot Display--- " Return ' ' ******************************************************** Temp1 = 検索するレベル 。(0 or 1) ' * バッファー内の、(0 or 1)レベルを検索するサブルーチン * Temp2 = バッファーのバイト単位データ。 ' ******************************************************** Temp3 = 調べるビット番号。(7〜0) ' Tempw1 <= 検索した個数。 Bufsearch: Tempw1 = 1 Bufsearch1: Temp4 = Temp2.temp3 If Temp4 = Temp1 Then Return 'If 検索するレベルを見つけたか? Then Tempw1 = Tempw1 + 1 Temp3 = Temp3 - 1 If Temp3 <> &HFF Then Goto Bufsearch1 'If 8bit分のチェックが終わったか? Else Buffadr = Buffadr + 1 If Buffadr > 768 Then Goto Bufsearch2 'If 指定レベルが見つからなかったか? Then Temp2 = Sampbuf(buffadr) Temp3 = 7 Goto Bufsearch1 ' Bufsearch2: '指定レベルが見つからなかった。 Tempw1 = 0 Return ' ' ************************************** ' * 周期を文字列に変換するサブルーチン * (Frqdat => Tempstr2) ' ************************************** ' Tstrcnv: Tempstr = Str(frqdat) '周期値を文字列に変換。 Temp1 = Len(tempstr) '周期値の桁数を調べる。 Tempstr = Left(tempstr , 5) Select Case Temp1 '周期値により表示桁を整える。 Case 10 : Tempstr2 = Format(tempstr , " . ") + " S " '1S以上。 Case 9 : Tempstr2 = Format(tempstr , " . ") + "mS" '100〜999mS。 Case 8 : Tempstr2 = Format(tempstr , " . ") + "mS" '10〜99mS。 Case 7 : Tempstr2 = Format(tempstr , " . ") + "mS" '1〜9mS。 Case 6: Tempstr2 = Format(tempstr , " . ") + "uS" '100〜999uS。 Case Is >= 4: Tempstr2 = Format(tempstr , " . ") + "uS" '1〜99uS。 Case Else : Tempstr2 = Format(tempstr , " ") + "nS" '1〜999nS。 End Select Return ' ' ********************************************************** ' * キャプチャー・バッファーの値を差分計算するサブルーチン * 差分カウント値 => Frqdat(ロング型) ' ********************************************************** ' Capsubt: $asm LDS R24,{Capendf} 'キャプチャー・バッファーの使用状況を調べる。 SBRC R24,0 'バッファー1が測定終了データか? Then RJMP Capsubt1 ; LDS R16,{capdat1} '32bit引き算(バッファー2)−(バッファー1)。 LDS R17,{capdat1+1} LDS R18,{capovf1} LDS R19,{capovf1+1} LDS R20,{capdat2} LDS R21,{capdat2+1} LDS R22,{capovf2} LDS R23,{capovf2+1} RJMP Capsubt2 ; Capsubt1: LDS R16,{capdat2} '32bit引き算(バッファー1)−(バッファー2)。 LDS R17,{capdat2+1} LDS R18,{capovf2} LDS R19,{capovf2+1} LDS R20,{capdat1} LDS R21,{capdat1+1} LDS R22,{capovf1} LDS R23,{capovf1+1} ; Capsubt2: Sub R20 , R16 '32bit引き算。 SBC R21,R17 SBC R22,R18 SBC R23,R19 STS {Frqdat},R20 '計算結果をロング型変数に格納。 STS {Frqdat+1},R21 STS {Frqdat+2},R22 STS {Frqdat+3},R23 $end Asm Return ' ' ******************************************** ' * Timer1 キャプチャー 割り込み処理ルーチン * ' ******************************************** ' Tintcap: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R22 PUSH R23 'R23は、拡張I/Oレジスタへのアクセスに使用する。 PUSH R24 PUSH R25 ; LDS R22,{Measure} '計測モードを確認する。 CPI R22,0 BRNE Tintcap9 'If 計測モードがゲート・モードか? Else ; LDS R22,{Cap5hc} 'ゲート・モード時に、5Hzから1秒をカウントする。 INC R22 STS {Cap5hc},R22 CPI R22,5 BREQ Tintcap11 'If 1秒になったか? Then JMP Tintcap10 ; Tintcap11: CLR R22 STS {Cap5hc},R22 ; ; Tintcap9: LDS R22,{Capendf} 'メインルーチンの処理状態をチェック。 CPI R22,0 BREQ Tintcap1 'If メインルーチンでキャプチャー・データの処理が終了しているか? Else JMP Tintcap8 ; Tintcap1: IN R24,ICR1L 'キャプチャー・レジスターの下位バイトを取得。 IN R23,ICR1H 'キャプチャー・レジスターの上位バイトを取得。 ; LDS R22,{Capmode} 'キャプチャー割り込みのモードを調べる。 SBRC R22,0 'If データ・バッファー2 へ書き込み? Then RJMP Tintcap2 ; ; '---<データ・バッファー1 書き込み処理>--- STS {Capdat1},R24 'データ・バッファー1へ保存。 STS {Capdat1+1},R23 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を取得。 LDS R25,{Capovfc+1} CPI R23,0 BRNE Tintcap3 'If キャプチャー・データの上位バイトが00? Else ; IN R23,TIFR1 SBRS R23,TOV1 'オーバーフローが発生しているか? Else RJMP Tintcap3 ; ADIW R24,1 'オーバーフロー・カウント値を+1 ; Tintcap3: STS {Capovf1},R24 'データ・バッファー1へ保存。 STS {Capovf1+1},R25 ORI R22,&H01 'モードをデータ・バッファー2 書き込みに変更。 RJMP Tintcap5 ; ; Tintcap2: '---<データ・バッファー2 書き込み処理>--- STS {Capdat2},R24 'データ・バッファー2へ保存。 STS {Capdat2+1},R23 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を取得。 LDS R25,{Capovfc+1} CPI R23,0 BRNE Tintcap4 'If キャプチャー・データの上位バイトが00? Else ; IN R23,TIFR1 SBRS R23,TOV1 'オーバーフローが発生しているか? Else RJMP Tintcap4 ; ADIW R24,1 'オーバーフロー・カウント値を+1 ; Tintcap4: STS {Capovf2},R24 'データ・バッファー2へ保存。 STS {Capovf2+1},R25 ANDI R22,&HF0 'モードをデータ・バッファー1 書き込みに変更。 ; ; Tintcap5: CPI R22,&H10 BRCC Tintcap6 'If 1と2の両バッファーにデータの準備が完了か? Then ORI R22,&H10 'キャプチャー・モードを2つめのデータ待ちにセット。 RJMP Tintcap7 ; Tintcap6: STS {Capendf},R22 'キャプチャー計測完了フラグをセット。 Tintcap7: STS {Capmode},R22 'キャプチャー・モードを更新。 ; Tintcap10: POP R25 POP R24 POP R23 POP R22 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return ' ' $asm Tintcap8: 'メインルーチンでキャプチャー・データの処理が終わっていない。 LDI R22,0 'キャプチャー・モードを初期化する。 RJMP Tintcap7 $end Asm ' ' ********************************************** ' * Timer1 オーバーフロー 割り込み処理ルーチン * ' ********************************************** ' Tintovf: $asm PUSH R1 IN R1,SREG 'ステータス・レジスタを待避。 PUSH R24 PUSH R25 ; LDS R24,{Capovfc} 'オーバーフロー・カウント値を+1。 LDS R25,{Capovfc+1} ADIW R24,1 STS {Capovfc},R24 STS {Capovfc+1},R25 ; POP R25 POP R24 Out Sreg , R1 'ステータス・レジスタを復帰 POP R1 $end Asm Return ' End ' ' ******************* ' * フォント データ * ' ******************* ' Offont6x8: $asm .db 1 , 6 , 6 , 0 .db $00 , $00 , $00 , $00 , $00 , $00 ; .db $00 , $00 , $00 , $5f , $00 , $00 ; ! .db $00 , $00 , $07 , $00 , $07 , $00 ; .db $00 , $14 , $7f , $14 , $7f , $14 ; # .db $00 , $24 , $2a , $7f , $2a , $12 ; $ .db $00 , $23 , $13 , $08 , $64 , $62 ; % .db $00 , $36 , $49 , $55 , $22 , $50 ; & .db $00 , $00 , $05 , $03 , $00 , $00 ; .db $00 , $00 , $1c , $22 , $41 , $00 ; .db $00 , $00 , $41 , $22 , $1c , $00 ; .db $00 , $14 , $08 , $3e , $08 , $14 ; * .db $00 , $08 , $08 , $3e , $08 , $08 ; + .db $00 , $00 , $50 , $30 , $00 , $00 ; , .db $00 , $08 , $08 , $08 , $08 , $08 ; - .db $00 , $00 , $60 , $60 , $00 , $00 ; . .db $00 , $20 , $10 , $08 , $04 , $02 ; / .db $00 , $3e , $51 , $49 , $45 , $3e ; 0 .db $00 , $00 , $42 , $7f , $40 , $00 ; 1 .db $00 , $62 , $51 , $49 , $49 , $46 ; 2 .db $00 , $22 , $41 , $49 , $49 , $36 ; 3 .db $00 , $18 , $14 , $12 , $7f , $10 ; 4 .db $00 , $27 , $45 , $45 , $45 , $39 ; 5 .db $00 , $3c , $4a , $49 , $49 , $30 ; 6 .db $00 , $01 , $71 , $09 , $05 , $03 ; 7 .db $00 , $36 , $49 , $49 , $49 , $36 ; 8 .db $00 , $06 , $49 , $49 , $29 , $1e ; 9 .db $00 , $00 , $36 , $36 , $00 , $00 ; : .db $00 , $00 , $56 , $36 , $00 , $00 ; ; .db $00 , $08 , $14 , $22 , $41 , $00 ; < .db $00 , $14 , $14 , $14 , $14 , $14 ; = .db $00 , $00 , $41 , $22 , $14 , $08 ; > .db $00 , $02 , $01 , $51 , $09 , $06 ; .db $00 , $32 , $49 , $79 , $41 , $3e ; @ .db $00 , $7e , $11 , $11 , $11 , $7e ; A .db $00 , $7f , $49 , $49 , $49 , $36 ; B .db $00 , $3e , $41 , $41 , $41 , $22 ; C .db $00 , $7f , $41 , $41 , $22 , $1c ; D .db $00 , $7f , $49 , $49 , $49 , $41 ; E .db $00 , $7f , $09 , $09 , $09 , $01 ; F .db $00 , $3e , $41 , $49 , $49 , $7a ; G .db $00 , $7f , $08 , $08 , $08 , $7f ; H .db $00 , $00 , $41 , $7f , $41 , $00 ; I .db $00 , $30 , $40 , $40 , $40 , $3f ; J .db $00 , $7f , $08 , $14 , $22 , $41 ; K .db $00 , $7f , $40 , $40 , $40 , $40 ; L .db $00 , $7f , $02 , $0c , $02 , $7f ; M .db $00 , $7f , $04 , $08 , $10 , $7f ; N .db $00 , $3e , $41 , $41 , $41 , $3e ; O .db $00 , $7f , $09 , $09 , $09 , $06 ; P .db $00 , $3e , $41 , $51 , $21 , $5e ; Q .db $00 , $7f , $09 , $19 , $29 , $46 ; R .db $00 , $26 , $49 , $49 , $49 , $32 ; S .db $00 , $01 , $01 , $7f , $01 , $01 ; T .db $00 , $3f , $40 , $40 , $40 , $3f ; U .db $00 , $0f , $30 , $40 , $30 , $0f ; V .db $00 , $1f , $60 , $1c , $60 , $1f ; W .db $00 , $63 , $14 , $08 , $14 , $63 ; X .db $00 , $07 , $08 , $70 , $08 , $07 ; Y .db $00 , $61 , $51 , $49 , $45 , $43 ; Z .db $00 , $00 , $7f , $41 , $41 , $00 ; [ .db $00 , $15 , $16 , $7c , $16 , $15 ; \ .db $00 , $00 , $41 , $41 , $7f , $00 ; ] .db $00 , $04 , $02 , $01 , $02 , $04 ; ^ .db $00 , $40 , $40 , $40 , $40 , $40 ; .db $00 , $00 , $01 , $02 , $04 , $00 ; ` .db $00 , $20 , $54 , $54 , $54 , $78 ; A .db $00 , $7f , $48 , $48 , $48 , $30 ; B .db $00 , $38 , $44 , $44 , $44 , $28 ; C .db $00 , $30 , $48 , $48 , $48 , $7f ; D .db $00 , $38 , $54 , $54 , $54 , $18 ; E .db $00 , $00 , $08 , $7e , $09 , $01 ; F .db $00 , $0c , $52 , $52 , $52 , $3e ; G .db $00 , $7f , $08 , $04 , $04 , $78 ; H .db $00 , $00 , $00 , $7d , $00 , $00 ; I .db $00 , $20 , $40 , $40 , $3d , $00 ; J .db $00 , $7f , $10 , $28 , $44 , $00 ; K .db $00 , $00 , $00 , $7f , $40 , $00 ; L .db $00 , $7c , $04 , $78 , $04 , $78 ; M .db $00 , $7c , $08 , $04 , $04 , $78 ; N .db $00 , $38 , $44 , $44 , $44 , $38 ; O .db $00 , $7c , $14 , $14 , $14 , $08 ; P .db $00 , $08 , $14 , $14 , $14 , $7c ; Q .db $00 , $7c , $08 , $04 , $04 , $08 ; R .db $00 , $48 , $54 , $54 , $54 , $20 ; S .db $00 , $00 , $04 , $3e , $44 , $20 ; T .db $00 , $3c , $40 , $40 , $20 , $7c ; U .db $00 , $0c , $30 , $40 , $30 , $0c ; V .db $00 , $3c , $40 , $38 , $40 , $3c ; W .db $00 , $44 , $28 , $10 , $28 , $44 ; X .db $00 , $0c , $50 , $50 , $30 , $1c ; Y .db $00 , $44 , $64 , $54 , $4c , $44 ; Z .db $00 , $00 , $08 , $36 , $41 , $00 ; { .db $00 , $00 , $00 , $77 , $00 , $00 ; | .db $00 , $00 , $41 , $36 , $08 , $00 ; } .db $00 , $02 , $01 , $02 , $01 , $00 ; ~ .db $00 , $7f , $7f , $7f , $7f , $7f ;  $end Asm