;--------------------------------------------------------------------------------------------------------------------- ;--------------------------------------------------------------------------------------------------------------------- ; ; Program File : JA0EHG10.ASM ; ; 概要 :秋月電子のDDSキットを使用したVFO ; ; ; 仕様 :DDSの基本周波数は67.10886Mhz ; :出力周波数は0〜約30Mhz(実用範囲1Mhz〜20Mhz) ; :出力電圧は50オーム負荷にて ; :5Mhz=300mV,10Mhz=230mV,15Mhz=200mV,20Mhz=180mV,30Mhz=40mV ; :16桁2行LCDへ状態表示(14ピンコネクタ接続、ケーブル延長可能)。 ; :1回転250パルスのロータリエンコーダ制御 ; :VFO A/B及びLOCK機能スイッチ×1ヶ (SW1) ; :可変レンジ桁の移動スイッチ×1ヶ (SW2) ; :22Mhzローパスフィルター実装。低周波で使用する場合は要カップリング容量変更 ; :内部EEPROMのデータエリアへ各種情報(すべてのデータ)を記憶し再始動時に復帰します。 ; :PICマイコンはPIC16F84、動作クロックは10Mhzのセラミックオシレータを使用。 ; ; 動作電圧 :内部設定ピンにより2種類の動作電圧を選択可能 ; :設定ピン I:I 6V〜13V動作(少々3端子が熱くなります) ; :設定ピン :I: 5V動作 ; ; 消費電流(5V動作時) :DDS UNIT=80mA、LCDライト無し=5mA、LCDライト付き=45mA、CPU=55mA ; :LCDバックライト付きなら合計約180mA、無しなら140mA(ちょっと大食らいなのは作者似?) ; ; 機能 ; ;  電源ON+SW1,SW2同時押し :ALL RESET(出荷時の状態へ戻す。LCDブランク表示のループ状態となり操作禁止) ;  電源ON+SW1押し :OFFSET値の設定モード (出荷時デフォルト 0) ;  電源ON+SW2押し :OFFSET演算の加算/減算切替(オルタネート動作) ; :加算時にはレンジ桁表示* (出荷時デフォルト) ; :減算時にはレンジ桁表示# ; ;  周波数可変範囲 :下限値、上限値を出荷時に設定。限界値以上・以下には変化しません。 ; :特に指定がなければ出荷時に下限値=0、上限値=67108863(3FFFFFF) ; ;  ±OFFSET表示 :DDS出力周波数にOFFSET周波数を加/減算した値をLCDへ表示可能。 ; :設定中は"OFFS"と表示されます。 ; :OFFSET値が0の場合は出力周波数をダイレクトに表示します(デフォルト) ; :(ex)DDS=12,345.678Khz,OFFSET=200,000.000Khzならば ; :  運用時の表示は" 212.345.678"となります。 ; ;  VFO A/B切替 :周波数をA/B二種類設定可能。SW1を押して1.6秒未満で離すとA/Bが反転します。 ; :LCDは" A "または" B "と表示されます。 ; :出荷時の注文にて出力周波数のデフォルトを指定できます。 ; :出荷時の注文にて出力周波数の1倍表示、2倍表示、3倍表示を選択できます。 ; :出荷時の注文にて以下の機能を選択できます。 ; :正ダイアル(出力周波数増加時に表示周波数も増加する関係) ; :逆ダイアル(出力周波数増加時に表示周波数は減少する関係) ; :逆ダイアルの場合中心となる基準周波数を指定していただければOFFSET値の設定が簡単です。 ; :基準周波数の指定が無い場合は10Mhzとします(出力周波数のデフォルトではない) ; :OFFSET値の計算は次の通り ; :8Mhzを中心にしたい場合はOFFSET値=(8−10)×2=−4Mh(ハ)を設定すればよい。 ; :結果8Mhz表示で8Mhz出力、9Mhz表示で7Mhz出力の逆ダイアルとなります。 ; :さらに8Mhz出力時(イ)に50Mhz(ロ)を表示したいなら ; :OFFSET値は (ロ)−(イ)+(ハ)の関係から50-8-4となり+38Mhzとなります。  ; :(上記はあくまで逆ダイアル時のOFFSET計算方法です。正ダイヤルなら(ハ)が不要です) ; ; ; ;  VFO LOCK :SW1を押したまま1.6秒以上経過すると使用中のVFOをロックします。 ; :LCDは"LOCK"と表示されます。 ; :LOCK状態ではLOCK解除操作のみが有効となります。その他の操作は無効となります。 ; ;  周波数可変レンジ切替 :ロータリエンコーダの1パルスに対して変化する周波数の桁位置が移動できます。 ; :SW2を一回押すと上位桁方向へ移動し最上位にいる時の操作では最下位桁に移動します。 ; :レンジの切替範囲=10Khz(デフォルト)->1hz->10hz->100hz->1Khz->10Khz->1hz・・・・・ ; ;  動作状態の保存 :電源切断しても再度電源ON時には以前の状態で復旧します。 ; :ただし、VFO操作後3.2秒以上の無操作があれば周波数は記憶されていますが ; :それ以前の場合は記憶されていません。 ; :その他のキー操作等はその都度記憶されています。 ; ;  LCD表示 :バックライト付きLCD(\1,500)、ライト無し(\1,200)どちらでも接続OK ; ;フロントパネルでコントラスト調整可能。ライトの明るさは固定抵抗で好みに調整 ; :してください(私は12オーム)。 ; ; ; 内部動作説明 ; ;  概要 :インターバルタイマー割り込みでRE(パルス数),キー操作(押している時間など)を監視し ; :アイドル(アイドリング)処理へ通知しています。 ; :情報を受け取った(判断した)アイドル処理ではDDS値を書き直したり、LCDへ再表示したり ; :キー操作に対応した状態の変更を行っています。 ; ;  インターバルタイマー :200uSecタイマー ; :ロータリエンコーダ信号の監視。立ち下がり ; :(Hi認識後,0.2mSec経過した時にLowなら信号有りと判定しパルス数を1カウントしています) ; ; :50mSecタイマー ; :DDS出力及びLCD表示する間隔を制御しているタイマー(ダウンカウンター) ; :RE回転を認識後直ちに内部の数値は演算して保持していますが ; :このタイマーの周期でDDS出力及びLCD表示が行われます。つまり間引き処理です。 ; :多パルスのREを使用した場合1パルス毎に再出力、再表示していると ; :CPUの処理が遅く処理されないで貯まるパルスがどんどん増えてしまうので・・・ ; :50mSEC程度なら違和感がありませんが100mSec間隔ですと違和感あり。 ; :この程度の遅れは人間の感覚で判断することは難しいでしょう HiHi ; ; :長いタイマー生成用にTCNT50MSのダウンカウンターで50mSecを生成して以下のタイマーを作り出す ; :最大 50mSec×128=6.4秒のタイマー 5本 ; :NOPCNT 無操作6.4秒の監視タイマー。 b7=1でオーバーフロー ; :SW1CNT SW1キーの操作を監視するタイマー 同上 ; :SW2CNT SW2キーの操作を監視するタイマー 同上 ; :SW1キータイマーは1.6秒以内の押し離しでA/B切替、以上はLOCKと判定。 ; :SW2キータイマーは押したらすぐに反応。レンジ切替後はタイマーオーバーをセット。 ; ;  起動 :EEPROM内のMODE記憶がALL ZEROならバージン動作としてALL RESET。 ; :その他は、EEPROM内の記憶内容で処理が開始されます。 ; :CPUリセット後100mSecのインターバルを経過してから内部処理を開始しています。   ;   ;  DDS制御 :シリアルにてコントロールしています(クロック、データ、ストローブの3本) ; :28ビットの有効桁数すべてを制御できます。(内部では4Byteで演算しています) ; :すべての4Byte演算領域は若いアドレスに下位桁、アドレスが増えるに従って上位桁が格納。 ; :(例)10進で123456789は演算領域の若いアドレスから表現すると15 CD 5B 07 となります。 ; ;  LCD :4ビット・バスのモードで使用しています。(バス4本、レジスタセレクト、イネーブル・シグナルの6本) ; :出力ポートが少ないのでR/W信号はLOW=Write固定のまま使用しています。 ; ;  SW1キー(A/B/LOCK) :チャタリング防止は0.3秒の無感状態で対策。あとは押しっぱなしなので大丈夫でしょう ; ;  SW2キー(STEP RANGE) :チャタリング防止は50mSec(無感状態で)行っていたような気がします。HiHi ; ;  SRAM領域 :0C〜3Fまでの52バイトしかユーザエリアが無いので ; :最小限必要なフラグ、カウンター、演算作業域のみとしています。 ; :その他必要な大きい領域はEEPROMのデータ部64Byteを利用しています。 ; ;  EEPROM領域 :無通電でも内容は保持されますが書き換え回数が100万回となっています。 ; :本プログラムでは各種操作により状態が変化した場合に書き込んで記憶しています。 ; :ただし、頻繁にVFO値を書き込んでいるとすぐに100万回を突破してしまうので ; :3秒に1回、EEPROMの記憶内容と現在値を比較し変化があれば書き直しています。 ; :ですから、VFO変化後3秒以内に電源を切断するとその内容は記憶されていません。 ; :記憶したい場合は3秒以上電源を切らないか、VFO A/B/LOCK等の操作をすれば記憶されます。 ; :ちなみにVFO操作後、3秒無操作(ワッチ)を繰り返し行っても833時間(34日)かかります。 ; :月に5時間(割とアクティブ?というより疲れる)ずつ上記ワッチ操作を行ってもなんと ; :13年はかかりますHiHi ; ; 使用上の注意  ※1 :電源投入時に電圧が安定しませんとEEPROMの読み込み(書き込み)が正しく行われず次のような ; :症状が発生します。 1.LCD表示に文字化けが発生(特にVFO A/B/LOCK/OFFS)。 ; : 2.LOCK操作した覚えが無いのにいきなりLOCKモードで立ち上がる。 ; :このようなときは迷わずSW1,SW2を押しながら電源を再投入するALL RESETを行ってください。 ; :電源の接続不良や故意に電源電圧を低めにしてぎりぎりの所で立ち上げると発生します。 ; ;  ※2 :あまりロータリエンコーダからのパルス数が多いと処理しきれず、停止してからパラパラパラと周波数が ; :後を追うように変化します。ダイアルノブを使用してグルグル何回も早く回すと確認できます。 ; :秋月のRE=1回転25パルスなら大丈夫ですが1回転250パルスのロータリエンコーダ等ですとはっきりと判ります。 ; :1回転150パルス程度のロータリエンコーダなら全く問題なく使用できると思います。 ; :これ以上の処理スピードを追求するには別のPICマイコンとなります。 ; :不確実ですがCPUクロックを10Mhzから12Mhz程度にクロックアップすると少しは改善されるかも? ; ; ポート割り当て(RBポートは内部プルアップを併用しています) ; RA4 :DDSストローブ ; RA3 :DDSデータ ; RA2 :DDSクロック ; RA1 :LCDレジスタ・セレクト ; RA0 :LCDイネーブル・シグナル ; ; RB7 :ロータリエンコーダ・シグナル1 ; RB6 :ロータリエンコーダ・シグナル2 ; RB5 :SW1 ; RB4 :SW2 ; RB3 :LCDデータ7 ; RB2 :LCDデータ6 ; RB1 :LCDデータ5 ; RB0 :LCDデータ4 ; ; CONFIG SET セラミック発信,WDT(ウオッチ・ドッグ・タイマ)は使用していません、PWRT(パワーアップタイマ)有効,プロテクトなし ; 当初MCLRのリセットがかからない事が多発していたのでWDTを働かせ無理矢理リセットをかけていました。が ; ある日、パワーアップタイマを有効にしたら必ずリセットがかかるようになりました。めでたしめでたし ; その様なわけでWDTを外し現在は組み込んでいません。 ; ; ; ; 制作後の感想 :かれこれ10年前に大手ソフト会社をスピンアウトしてハード&ファームソフト会社に勤め ; このようなアセンブラレベルのプログラムを日夜書いておりました。 ; バブルがはじけて仕事も少なくなり、そのハード会社もやめてしまいました・・・6年が経過し ; このようなソフトは作る機会は無いだろうと思っていたところ、近所の悪友?良友?の方々に ; 無線の世界に引っ張りこまれあれよあれよと半年がたち、気がついたらセコセコと寝る間を惜しんで ; 今回のプログラム作りになった次第です。難しいテクニックやアルゴリズムは駆使していない平凡な ; プログラムですが何とか自己満足の範囲で使用できる物になっていると思います。 ; 今回の研究テーマはDDS&1チップマイコン(PIC)でしたがなかなか面白かったです。 ; 初めて八重洲のDDSを制御したときの事を彷彿と思い出しましたし、昔に比べなんと簡単に ; 制御向けのプログラムが開発でき、さらに部品も少なく(少なすぎるが十分性能は良い)時間、コストも ; かからない最近の環境は本当に驚きと喜びです。 ; 制作のきっかけは自作QRP 21/50MhzSSB機の外部VFOにしようと思ったのがはじまりです。 ; ('98/12現在、まだ接続テストはしていません) ; さらに、6mAM機を自作しこれを内蔵しTRX兼OSCにしよう?とも企てています(欲張りですね!!) ; ; なお、今回のプログラムの焼き増し、若干の改造にはビール2本で注文に応じますHiHi(CPU代\600は実費) ; 簡単に今回のDDSを実験するには ; DDSキット(\6,800)+PICプログラムボードLCD付き(\3、500)+秋月扱いロータリエンコーダ(\1,000?)+若干の部品で ; 実験可能です。 ; プログラム焼き増しご希望の貴局へ朗報!!「今なら、家紋表示機能をもれなく設定するサービス中です」 ; ; さて、次回はリモート・アンテナ・チューナをこさえてみようと企んでいます。 ; シャックでコントローラを操作してタワー上のワイヤーアンテナチューナをリモート制御するものです。 ; コントローラ−チューナ間は光ケーブルで制御信号を相互に送りチューナ内部のパルスモータ(DCモータは難しい)を制御しようと ; 考えていますがまだ漠然と想像している段階です。どなたか良いアイデアがあれば教えてください。 ; 一応A/D変換(SWR)も組み込もうかな?なんて考えていますHiHi ; インテリジェントなスイッチポン式お任せタイプのアンテナチューナーは運用時に面白くなさそうなので ; 考えていません・・・が・・・でも、いずれ作るかも? ; ; 最後にロータリエンコーダ等、色々とお世話になりましたJA1XBYさんにはこの場?(プログラム・ヘッダ) ; を借りて感謝の意を書き記します。 ; ; 制作 :JF1DHM 斉藤 勲 ; ; 作成日付 :1998年12月22日 Ver1.1 ('98年11月15日〜) ; :1998年12月28日 Ver1.2 ('98年12月27日〜 出力を逓倍して使用するための周波数表示機能追加) ; :1999年01月16日 Ver1.3 (逆ダイアルのサポート) ; ; ;--------------------------------------------------------------------------------------------------------------------- ;--------------------------------------------------------------------------------------------------------------------- ; ; ; INCLUDE 16F84DHM.H .OSC HS .WDT OFF .PWRT ON .PROTECT OFF .nlist E EQU RA.0 ;LCD E信号 RS EQU RA.1 ;LCD RS信号 DCK EQU RA.2 ;DDS CLOCK信号 DDT EQU RA.3 ;DDS DATA信号 DST EQU RA.4 ;DDS STORB信号 PORT_SW1 EQU RB.5 ;SW1 INPUT VFO A/B/LOCK PORT_SW2 EQU RB.4 ;SW2 INPUT STEP UP SET_OFFSET EQU MODE.7 ;SETUP OFFSET SET_RSV6 EQU MODE.6 ; SET_RSV5 EQU MODE.5 ; SET_RSV4 EQU MODE.4 ; PMOFFS EQU MODE.3 ;+OFFSET(0)/-OFFSET(1) VFOB EQU MODE.2 ;VFO=B MODE VFOA EQU MODE.1 ;VFO=A MODE LOCK EQU MODE.0 ;LOCK MODE REVS EQU VFOCONT.4 ;逆ダイヤル表示 MLT3 EQU VFOCONT.2 ;3逓倍表示 MLT2 EQU VFOCONT.1 ;2逓倍表示 MLT1 EQU VFOCONT.0 ;1逓倍表示 ;---------------------------------------EEPROMデータエリア E_MODE EQU 0 ;運用モード E_STEP EQU E_MODE+1 ; ; ;RSV E_DDS0 EQU E_MODE+4 ;DDS-#A E_DDS1 EQU E_DDS0+4 ;DDS-#B E_OFFSET EQU E_DDS1+4 ;表示用オフセット値 E_STEP0 EQU E_OFFSET+4 ;DDS可変ステップ値 10Khz E_STEP1 EQU E_STEP0+4 ;DDS可変ステップ値 1Khz E_STEP2 EQU E_STEP1+4 ;DDS可変ステップ値 1Khz E_STEP3 EQU E_STEP2+4 ;DDS可変ステップ値 100hz E_STEP4 EQU E_STEP3+4 ;DDS可変ステップ値 10hz E_STEP5 EQU E_STEP4+4 ;DDS可変ステップ値 1hz ;--------------------------------------- ;---------------------------------------------------------------------------------------- ;---------------------------------------;汎用SRAM領域 (&0C〜&2F) ORG 0CH ;---------------------------------------割り込み用作業域 WORK_REG DS 1 ;Wレジスタ退避域 WORK_STATE DS 1 ;ステータスフラグ WORK_FSR DS 1 ;ステータスフラグ RBDS DS 1 ;RBポートの書き込み/読み込み内容を保持する RE1 EQU RBDS.7 ;RE1 INPUT DOWN KEY RE2 EQU RBDS.6 ;RE2 INPUT UP KEY SW1 EQU RBDS.5 ;SW1 INPUT VFO A/B/LOCK SW2 EQU RBDS.4 ;SW2 INPUT STEP UP ;---------------------------------------各種タイマー DSPTM DS 1 ;表示間隔制御タイマー(Max32mSec) TCNT50MS DS 1 ;50mSecタイマー生成用カウンター SW1CNT DS 1 ;SW1(VFO A/B/LOCK)タイマー(Max127) SW1RLS DS 1 ;SW1を離した時のタイマーを記録(3〜20でA/B切り替え) SW2CNT DS 1 ;SW2(STEP)タイマー(Max127) NOPCNT DS 1 ;無操作6秒監視タイマー(Max127) SW1CNT_OVR EQU SW1CNT.7 ;SW1タイマーのカウントオーバー SW2CNT_OVR EQU SW2CNT.7 ;SW2タイマーのカウントオーバー NOPCNT_OVR EQU NOPCNT.7 ;無操作6秒タイマーのカウントオーバー ;---------------------------------------DDS用作業域 MODE DS 1 ;運用モード 1xxx xxxx:セットモード OFFSET ; x1xx xxxx:セットモード ; xx1x xxxx:セットモード ; xxx1 xxxx:セットモード ; xxxx 1xxx:ノーマルモード +-OFFSET ; xxxx x1xx:ノーマルモード VFO-B ; xxxx xx1x:ノーマルモード VFO-A ; xxxx xxx1:ノーマルモード VFOロック ; STEP DS 1 ;UP/DOWNのSTEPレンジ ; 0: 10Khz ; 1: 1Khz ; 2: 1Khz ; 3: 100hz ; 4: 10hz ; 5: 1hz ; VFOCONT DS 1 ;VFO動作モード 1xxx xxxx:RSV ; x1xx xxxx:RSV ; xx1x xxxx:RSV ; xxx1 xxxx:逆ダイヤル表示 ; xxxx 1xxx:RSV ; xxxx x1xx:3逓倍表示 ; xxxx xx1x:2逓倍表示 ; xxxx xxx1:1逓倍表示 ; DS 1 ; ;---------------------------------------ロータリエンコーダ操作向け作業領域 RE_STACK DS 1 ;ロータリエンコーダ(RE)操作の監視用領域 ;0.2mSecインターバル内で入力ポートの状態をこの ;領域へシフトしながらスタックして行く ;b7-->b0(旧-->最新)として保存しxxxxxx01bの状態で ;回転ありと認識する。状態を以下のOPE_FLGでアイドルへ ;知らせる。 OPE_FLG DS 1 ;RE.& スイッチの状態を入れるフラグ REPLS EQU OPE_FLG.7 ; RE アクションあり(1) TMINT->IDLE 連絡用 ; IDLEでDDSカウントアップでクリア REDSP EQU OPE_FLG.6 ; RE DDS出力&LCD再表示の要求の有(1)/無(0) ; RECW DS 1 ;RE右回転パルスカウンター RECCW DS 1 ;RE左回転パルスカウンター ;--------------------------------------- ;---------------------------------------演算サブルーチン & BINtoBCD変換 Z4 DS 4 ;演算結果(4BYTES) X2 DS 2 ;被乗数(2BYTES) Y2 DS 2 ;乗数(2BYTES) ORG Z4 Y4 DS 4 ;加減算(4BYTES) X4 DS 4 ;加減算(4BYTES) BIN to BCD入力 X4_M DS 1 ;一時余り格納場所(サブルーチンで使用) DEC DS 11 ;10進格納場所(11バイト) DEC_TOP ;--------------------------------------- ;---------------------------------------LCDサブルーチン D4 DS 1 ;液晶へのコマンドデータを入れるレジスタ D8 DS 1 ;--------------------------------------- ;---------------------------------------DDSサブルーチン ORG D4 ; DDS_DATA DS 1 ;DDS書き込みデータ DDS_CN DS 1 ;BIT処理回数カウンター DDS DS 4 ;DDS値 DDS_BIT24 EQU DDS[3].0 ;DDS DATA BIT24 DDS_BIT25 EQU DDS[3].1 ;DDS DATA BIT25 ;--------------------------------------- ;---------------------------------------簡易ウェイトサブルーチン WAIT_CN DS 1 ;ウエイトカウント用 WAIT_CN2 DS 1 ;ウエイトカウント用 ;--------------------------------------- ;---------------------------------------16F84共通 汎用作業域 CN DS 1 ;作業カウンタ PTR DS 1 ;作業ポインタ ;--------------------------------------- ;--------------------------------------------------------------------------------------- ORG 0 ; CLR INTCON ; CLRB GIE ;割り込み禁止 NOP ; GOTO START ;プログラム開始 ORG 4 ; GOTO TMINT ;インターバルタイマー ;--------------------------------------------------------------------------------------- ;---------------------------------------定数領域 ;------------------------------------------------ ; 液晶初期表示データ ;------------------------------------------------ LCD_TBL JMP PC+W ;LCD表示定数先頭 LCD_TOP RETW 'JA0EHG 1999 V1.0' ;初期画面 VFO_CLR RETW 'VFO ' ;VFO状態初期値 VFO_OFFSET RETW 'OFFS' ;SETUP OFFSETのモード VFO_MODE0 RETW 'LOCK' ;VFOモード (A,B,ロック) VFO_MODE1 RETW ' A ' VFO_MODE2 RETW ' B ' ;======================================================================================= ;======================================================================================= ;======================================================================================= ;======================================================================================= ;------------------------------------------------ ; インターバルタイマー割り込み処理 ;------------------------------------------------ TMINT MOVWF WORK_REG ;W レジスタの待避 SWAPF STATUS,W ; MOVWF WORK_STATE ;STATUS レジスタの待避 MOV WORK_FSR,FSR ;FSR レジスタの待避 CALL TMRESET ;次のタイマー値をセット MOV RBDS,RB ;RB Port Read RLF RBDS,0 ; RLF RE_STACK ;LEFT SHIFT STACK MOV W,RE_STACK ;スタック内容を取り出し判定する AND W,#00000011b ;判定時間を最近0.4mSec部分にする XOR W,#00000010b ; JNZ TMINT1_5 ;OFF 0.2ms ON 0.2ms で操作有りと判定 ; CLR NOPCNT ;12秒無操作タイマーをクリア SETB REPLS ; REPLS=1 PLUS有りを記録 JNB RE2,TMINT1_3 ; 信号Bを判定 CJE RECCW,#255,TMINT1_5 ;  INC RECCW ; HIなら左回り (カウンター最大値なら加算しない) GOTO TMINT1_5 ; CJE RECW,#255,TMINT1_5 ; TMINT1_3 INC RECW ; LOWなら右回り (カウンター最大値なら加算しない) TMINT1_5 MOV W,DSPTM ;表示間隔タイマー JZ TMINT1_6 ; タイムアップならカウントしない DEC DSPTM ; 未タイムアップならカウントダウン TMINT1_6 TMINT1_9 DJNZ TCNT50MS,TMINT99 ;50mSecタイマーカウンター処理 MOV W,#250 ;タイムアップしたならカウンター値セット MOV TCNT50MS,W ; ;----------------------------------------以下は50mSecに一回の監視処理 ; JB NOPCNT_OVR,TMINT2 ;6秒無操作タイマー上限以下なら INC NOPCNT ; カウントアップ TMINT2 TMINT3 TMINT4 ; TMINT5 TMINT6 ; ;---------------------------------------- JNB SW1,TMINT7 ;SW1キー離れていて MOV W,SW1RLS ;リリース時間記録域がクリアされていれば JNZ TMINT8 ; MOV SW1RLS,SW1CNT ; SW1キータイマーを保存 CLR SW1CNT ; SW1キータイマーをクリア GOTO TMINT8 ; TMINT7 CLR NOPCNT ;6秒無操作タイマーをクリア JB SW1CNT.7,TMINT8 ;SW1キー押されてタイマー上限以下なら INC SW1CNT ; SW1キータイマーをカウントアップ TMINT8 ; ;---------------------------------------- JNB SW2,TMINT9 ;SW2キー離れているなら CLR SW2CNT ; SW2キータイマーをクリア GOTO TMINT10 ; TMINT9 CLR NOPCNT ;6秒無操作タイマーをクリア JB SW2CNT.7,TMINT10 ;SW2キー押されてタイマー上限以下なら INC SW2CNT ; SW2キータイマーをカウントアップ TMINT10 ; ;---------------------------------------- TMINT99 MOV FSR,WORK_FSR ;FSR レジスタの復元 SWAPF WORK_STATE,W ;STATUS レジスタの復元 MOVWF STATUS ; SWAPF WORK_REG ; SWAPF WORK_REG,W ;W レジスタの復元 RETFIE ;割り込み終了(次の割り込み許可) ;------------------------------------------------ ; タイマープリスケーラ&カウント値セット(計算式) ;------------------------------------------------ TMRESET SETB RP0 ;RAMバンク1を指定する BCF T0IF ;タイマー割り込み通知フラグをクリア MOV OPTION,#10000100b ;TMR0 プリスケーラ(1:32) CLRB RP0 ;RAMバンク0にもどす MOV TMR0,#0F0h ;0.2mSec XTAL=10Mhz プリスケーラ 1:32 では ; ; 200uSec/0.1uSec*4=500カウント ; ; 500/32=15=00Fh ; ; 0FFh-00Fh=0F0hをTMR0へセットする RET ;=================================================================================================== ;------------------------------------------------ ; プログラム開始 ;------------------------------------------------ START CALL PORTINIT ;ポート初期化 CALL INIT_SET ;メモリ初期設定 CLRB GIE ;全割り込み禁止 CALL DDS_INI ;DDS初期化 CALL INIT_LCD ;LCD初期化 START0_7 JB PORT_SW1,START0_8 ;SW1を押しながらPowerONの場合は SETB SET_OFFSET ; OFFSET値の変更モード CALL RD_DDS ;EEPROMよりOFFSET値をDDS領域へ読み込み CLRB GIE ;全割り込み禁止 START0_8 JB PORT_SW2,START0_9 ;SW2を押しながらPowerONの場合は XOR MODE,#00001000b ; OFFSETの演算方式を反転する(オルタネート動作) CALL WR_MODE ; MODEをEEPROMへ書き込む CLRB GIE ;全割り込み禁止 START0_9 CALL TITLE ;タイトル文字列表示 CALL WAIT_SEC ;1秒WAIT CALL TITLE2 ;タイトル文字列表示 CALL DSPSTEP ;STEP RANGEを表示 CALL TMRESET ;タイマー値設定 SETB T0IE ;タイマー割り込み許可 SETB GIE ;全割り込み許可 CALL WAIT_MS125 ;インターバルタイマーを有効にした後に CLR RECW ;初動のREパルス(CW)を無視する CLR RECCW ;初動のREパルス(CCW)を無視する RE_DISPLAY SETB REDSP ;再表示要求 GOTO IDLE3 ;アイドルループの開始はLCD表示 ;=================================================================================================== ;=================================================================================================== ;------------------------------------------------ ; メイン アイドル ルーチン ;------------------------------------------------ IDLE1 GOTO REPROC ;ロータリエンコーダ,UP/DOWNキーの操作判定とDDS値計算 IDLE2 ;RETURN ENTRY ;----------------------------------------------- IDLE3 MOV W,DSPTM ;表示間隔タイマーが JNZ IDLE4 ; タイムアップしていなければ何もしない MOV DSPTM,#250 ; タイムアップしていればタイマー(50mSec)をセットして表示するかさらに判定する ;----------------------------------------------- JNB REDSP,IDLE4 ; DDS UP/DWの演算処理の履歴が無いなら何もしない CLRB REDSP ; 履歴をクリアして再表示 ;-----------------------------------------------DDS出力&LCD表示処理 CALL TX_D ;DDS OUTPUT CALL ADDOFSET ;X4=DDS+OFFSET CALL CNVVFO ;X4(4Byteバイナリ)を10進文字列(M,Khz 編集済み)に変換 CALL LCDVFO ;10進文字列をLCDへ表示 IDLE4 ;-----------------------------------------------VFOセレクト処理 GOTO VFOCHG ; IDLE5 ;戻り ;----------------------------------------------- ;-----------------------------------------------DDS可変ステップの変更処理 GOTO STEPCHG ; IDLE6 ;戻り ;----------------------------------------------- ;-----------------------------------------------EEPROMの書き込み最大回数が100万回なので頻繁には書き込まずに IDLE7 ;6秒以上の無操作時など暇なときにDDS値をEEPROMへ保存する JNB NOPCNT_OVR,IDLE8 ;6秒無操作タイマーが未タイムアップなら無処理 ; ;タイムアップしているなら CLR NOPCNT ; 同タイマーをクリア CALL LOADDDS ; 現DDSをX4へ退避 CALL RD_DDS ; EEPROM内容(保存内容)をDDSへ読み込む CJNE X4[0],DDS[0],IDLE7_1 ; X4(現),DDS領域(保存内容)を比較 CJNE X4[1],DDS[1],IDLE7_1 ; CJNE X4[2],DDS[2],IDLE7_1 ; CJE X4[3],DDS[3],IDLE8 ;すべて同じなら何もしない IDLE7_1 ;異なるならば CALL SAVEDDS ; 退避したDDS値へ戻して CALL WR_DDS ; EEPROM領域へ書き込む IDLE8 ;----------------------------------------------- IDLE9 GOTO IDLE1 ;アイドル処理を繰り返す ;=================================================================================================== ;---------------------------------------------------- ; ロータリエンコーダ操作に対応したDDS値更新 ;---------------------------------------------------- REPROC CLRB GIE ;割り込み禁止 MOV W,RECW ;RE右操作無いなら次を判定 JZ REPROC2 ;RE右操作有りなら DEC RECW ; RE操作通知を−1 SETB GIE ; 割り込み許可 REPROC1 CALL DDSUP ; 通常は指定のSTEPUP値でDDS++ SETB REDSP ; DDS出力とLCD再表示要求 REPROC2 ; CLRB GIE ;割り込み禁止 MOV W,RECCW ;RE右操作無いなら次を判定 JZ REPROC4 ;RE左操作有りなら DEC RECCW ; RE操作通知を−1 SETB GIE ; 割り込み許可 REPROC3 CALL DDSDOWN ; 通常は指定のSTEPUP値でDDS−− GOTO RE_DISPLAY ; DDS出力とLCD再表示 ; REPROC4 SETB GIE ;割り込み許可 GOTO IDLE2 ; ; ;------------------------------------------------ ; VFO A/B/LOCK キー操作の判定と処理 ;------------------------------------------------ VFOCHG ;SW1押し監視タイマーが JB SW1CNT_OVR,VFOCHG_01 ; オーバーしているなら通常の監視処理へ MOV W,SW1CNT ;オーバーしていないなら押し初めてからの時間を判定 AND W,#01100000b ; JZ VFOCHG_01 ;SW1押し監視タイマーが1.6秒以内なら離した形跡の判定処理へ ;SW1押し監視タイマーが1.7秒以上なら SETB SW1CNT_OVR ; タイマー最大値を設定して JB SET_OFFSET,VFOCHG_UPD ; OFFSETのSETUP中ならLOCK機能は無効 XOR MODE,#00000001b ; LOCK設定/解除操作と見なしてMODE反転 CALL WR_MODE ; 現状のMODEをEEPROMへ書き出す GOTO VFOCHG_UPD ; LCD再表示とDDS値出力を行う VFOCHG_01 MOV W,SW1RLS ;SW1を離した形跡がなければ無処理で復帰 JZ VFOCHG_EXIT ; ;離した形跡があり AND W,#11100000b ; 1.7秒を越えているなら既にLOCK済みなので JNZ VFOCHG_UPD ;  記録のみクリア VFOCHG_TGL ; 1.6秒以内なら以下の処理 JB LOCK,VFOCHG_UPD ;  LOCK中なら操作履歴のみクリアして戻る ;  LOCK中でなければ CALL WR_DDS ;   現状のDDS値をEEPROMへ書き出す XOR MODE,#00000110b ;   現状のMODEフラグ(A/B)を反転する CALL RD_DDS ;   反転したMODE値でDDS値を読み出す CALL WR_MODE ;   現状のMODEをEEPROMへ書き出す VFOCHG_UPD CLR SW1RLS ;記録してある時間領域をクリア GOTO RE_DISPLAY ;DDS出力とLCD再表示 VFOCHG_EXIT GOTO IDLE5 ; ;------------------------------------------------ ; STEP RANGE キー操作の判定と処理 ;------------------------------------------------ STEPCHG JB LOCK,STEPCHG_EXIT ;LOCK中なら無処理 ;SW2押し監視タイマーが JB SW2CNT_OVR,STEPCHG_EXIT ; オーバーしているなら無処理 MOV W,SW2CNT ; AND W,#01111110b ;(50mSec無感) JZ STEPCHG_EXIT ;押していないなら無処理  MOV W,STEP ;押し初めならSTEPレンジ変更 JNZ STEPCHG_01 ;RANGEのコードが0なら MOV STEP,#5 ; コード最大値をセット GOTO STEPCHG_UPD ; Max(5)->(4)->(3)->(1)->(0)Minサイクリック STEPCHG_01 ; DEC STEP ; コード値--1 CJNE STEP,#2,STEPCHG_UPD ;(2)は存在しないので(1)とする DEC STEP ; STEPCHG_UPD ; SETB SW2CNT_OVR ;SW2押し監視タイマーを最大値以上にセット CALL WR_MODE ;現在のモードをEEPROMへ書き込む CALL TITLE2 ;LCD再表示 CALL DSPSTEP ;STEP RANGEを表示 GOTO RE_DISPLAY ;DDS出力とLCD再表示 STEPCHG_EXIT GOTO IDLE6 ; ;------------------------------------------------ ; プログラム開始時の初期値 ;------------------------------------------------ INIT_SET MOV FSR,#03Fh ;SRAM USERS AREA INIT_SET1 CLR INDIRECT ; ALL ZERO CLEAR DEC FSR ; CJNE FSR,#00Bh,INIT_SET1 ; CALL INIT_SET_STEP ;可変ステップ値の初期設定 MOV RBDS,RB ;RB Port Read MOV W,RBDS ; AND W,#00110000b ;PowerON時にSW1,SW2の同時押しはEEPPROMのAll Resetとして JZ INIT_SET5 ;扱う CALL RD_MODE ;EEPROMより保存したモード読み込み MOV W,MODE ; AND W,#00001111b ;必ず各種SETモードのフラグはクリア MOV MODE,W ; JZ INIT_SET5 ;MODE値がALL ZEROならバージン動作としてシステム初期値をセット XOR W,#00001111b ; JZ INIT_SET5 ;MODE値下位4ビットがALL 1でもEEPROM誤読動作としてシステム初期値をセット CALL WR_MODE ;MODE等を再書き込みしておく CALL WAIT_MS125 ; CALL RD_DDS ;EEPROMより保存DDS値の読み込み RET ; ;------------------------------------------------ ; ALL RESET ;------------------------------------------------ INIT_SET5 MOV MODE,#00001010b ;VFO-A & -OFFSET ; MOV MODE,#00000010b ;VFO-A MOV STEP,#00 ;STEP RANGE=10Khz MOV VFOCONT,#00000001b ;1逓倍 ; MOV VFOCONT,#00010001b ;1逓倍+逆ダイヤル ; MOV VFOCONT,#00000010b ;2逓倍 ; MOV VFOCONT,#00000100b ;3逓倍 CALL WR_MODE MOV DDS[0],#032h ;05811250 DDS MOV DDS[1],#0ach MOV DDS[2],#058h MOV DDS[3],#000h CALL WR_DDS ;VFO-A MOV EEADR,#E_DDS1+0 ;VFO-B CALL WR_DDS5 ; MOV Y4[0],#032h ;05811250 OFFSET MOV Y4[1],#0ach MOV Y4[2],#058h MOV Y4[3],#000h CALL WR_OFFSET MOV W,RBDS ; AND W,#00110000b ;PowerON時にSW1,SW2の同時押しはEEPPROMのAll Reset後 INIT_SET6 JZ INIT_SET6 ; 無限ループ RET ;------------------------------------------------ ; DDS出力範囲の初期値と読み出し ;------------------------------------------------ RD_DDSL MOV Y4[0],#032h ;05811250 LIMIT LOW MOV Y4[1],#0ach MOV Y4[2],#058h MOV Y4[3],#000h RET RD_DDSH MOV Y4[0],#080h ;30000000 LIMIT HI MOV Y4[1],#0C3h MOV Y4[2],#0C9h MOV Y4[3],#001h RET ;------------------------------------------------ ; 逆ダイアル中心周波数の初期値と読み出し ;------------------------------------------------ RD_CENTER MOV X4[0],#000h ;10000000×2 CENTER MOV X4[1],#02Dh MOV X4[2],#031h MOV X4[3],#001h RET ;------------------------------------------------ ; STEP RANGEの初期値 ;------------------------------------------------ INIT_SET_STEP MOV Y4[0],#010h ;00010000 STEP MOV Y4[1],#027h CLR Y4[2] CLR Y4[3] MOV EEADR,#E_STEP0 CALL WR_STEP MOV Y4[0],#0E8h ;00001000 STEP MOV Y4[1],#003h MOV EEADR,#E_STEP1 CALL WR_STEP ;;;;; MOV EEADR,#E_STEP2 ;UNUSE ;;;;; CALL WR_STEP MOV Y4[0],#100 ;00000100 STEP CLR Y4[1] MOV EEADR,#E_STEP3 CALL WR_STEP MOV Y4[0],#10 ;00000010 STEP MOV EEADR,#E_STEP4 CALL WR_STEP MOV Y4[0],#1 ;00000001 STEP MOV EEADR,#E_STEP5 CALL WR_STEP RET ;------------------------------------------------ ; ポート初期化 ;------------------------------------------------ PORTINIT MOV !RA,#00000000b ;E,RS,DCK,DDT,DSTピンをOUTに MOV !RB,#11110000b ;DB7-DB4=IN(1),DB3-DB0=OUT(0) SETB RP0 ;RAMバンク1を指定する CLRB RBPU ;PORT B Pull UP CLRB RP0 ;RAMバンク0へ戻す CLR RA ;PortAクリア CLR RB ;PortBクリア CLR RBDS ;PortB待避領域へ同じ値を書き込む CALL WAIT_MS125 ;125mSec Wait RET ;------------------------------------------------ ; 計算補助ルーチン ;------------------------------------------------ ;------------------------------------------------ ; 逓倍・OFFSETを考慮した表示値を計算 ; X4=DDS(逓倍)±OFFSET ;------------------------------------------------ ADDOFSET CALL LOADDDS ;現DDSのロード (X4) JB SET_OFFSET,ADDOFSET99 ;OFFSETのSETUP中なら逓倍もOFFSETも計算しない ; MOV W,VFOCONT ; AND W,#00000110b ; JZ ADDOFSET5 ;逓倍の指示がないならそのまま計算 CALL MOVX4TOY4 ;Y4へX4を転送 CALL ADD4B ;X4=X4+Y4を実施して2逓倍 JNB MLT3,ADDOFSET5 ;3逓倍の要求なら 更に CALL ADD4B ;X4=X4+Y4を実施して3逓倍 ADDOFSET5 JNB REVS,ADDOFSET6 ;逆ダイヤル表示なら CALL MOVX4TOY4 ;Y4へX4を転送 CALL RD_CENTER ;逆ダイヤル中心周波数×2のロード (X4) CALL SUB4B ;X4=X4-Y4 ADDOFSET6 CALL RD_OFFSET ;表示オフセットの読み込み (Y4) JB PMOFFS,ADDOFSET9 ;+OFFSET演算ならば CALL ADD4B ; X4=X4+Y4 RET ADDOFSET9 ;-OFFSET演算ならば CALL SUB4B ; X4=X4-Y4 ADDOFSET99 RET ;------------------------------------------------ ; DDS設定値のカウントアップ ; DDS=DDS+DDSSTEP ;------------------------------------------------ DDSUP JB REVS,DDSDOWN1 ;逆ダイヤル表示ならダウン処理へ DDSUP1 CALL RD_DDSSTEP ;Y4=可変ステップ値 JB LOCK,DDSUP9 ;LOCK中なら無処理 CALL LOADDDS ;X4=DDS CALL ADD4B ;X4=X4+Y4 CALL SAVEDDS ;DDS=X4 CALL RD_DDSH ;Y4=DDS上限値 JB SET_OFFSET,DDSUP9 ;OFFSETのSETUP中なら上限チェック無し MOV W,DDS[3] ;26ビットを越えている AND W,#11111100b ;データの場合は無条件にDDS上限値セット JNZ DDSLIMIT ; CJB DDS[3],Y4[3],DDSUP9 ;DDS(最上) < HI 正常 CJA DDS[3],Y4[3],DDSLIMIT ;DDS(最上) > HI オーバー CJB DDS[2],Y4[2],DDSUP9 ;DDS(上位) < HI 正常 CJA DDS[2],Y4[2],DDSLIMIT ;DDS(上位) > HI オーバー CJB DDS[1],Y4[1],DDSUP9 ;DDS(中位) < HI 正常 CJA DDS[1],Y4[1],DDSLIMIT ;DDS(中位) > HI オーバー CJA DDS[0],Y4[0],DDSLIMIT ;DDS(下位) > HI オーバー DDSUP9 RET ;------------------------------------------------ ; DDS設定値のカウントダウン ; DDS=DDS-DDSSTEP ;------------------------------------------------ DDSDOWN JB REVS,DDSUP1 ;逆ダイヤル表示ならアップ処理へ DDSDOWN1 CALL RD_DDSSTEP ;Y4=可変ステップ値 JB LOCK,DDSDOWN9 ;LOCK中なら無処理 CALL LOADDDS ;X4=DDS CALL SUB4B ;X4=X4-Y4 CALL SAVEDDS ;DDS=X4 CALL RD_DDSL ;Y4=DDS下限値 JB SET_OFFSET,DDSDOWN9 ;OFFSETのSETUP中なら上限チェック無し MOV W,DDS[3] ;マイナス及び26ビットを越えている AND W,#11111100b ;データの場合は無条件にDDS下限値セット JNZ DDSLIMIT ; CJA DDS[3],Y4[3],DDSDOWN9 ;DDS(最上) > LOW 正常 CJB DDS[3],Y4[3],DDSLIMIT ;DDS(最上) < LOW オーバー CJA DDS[2],Y4[2],DDSDOWN9 ;DDS(上位) > LOW 正常 CJB DDS[2],Y4[2],DDSLIMIT ;DDS(上位) < LOW オーバー CJA DDS[1],Y4[1],DDSDOWN9 ;DDS(中位) > LOW 正常 CJB DDS[1],Y4[1],DDSLIMIT ;DDS(中位) < LOW オーバー CJB DDS[0],Y4[0],DDSLIMIT ;DDS(下位) < LOW オーバー DDSDOWN9 RET ;------------------------------------------------上限を越えたので強制的に上/下限値 DDSLIMIT MOV DDS[3],Y4[3] MOV DDS[2],Y4[2] MOV DDS[1],Y4[1] MOV DDS[0],Y4[0] RET ;------------------------------------------------ ; 液晶タイトル(初期表示)ルーチン ;------------------------------------------------ TITLE MOV PTR,#LCD_TOP-LCD_TOP ; GOTO TITLE3 ; TITLE2 MOV PTR,#VFO_CLR-LCD_TOP ; TITLE3 MOV CN,#16 ; CALL LCDL1WC ; RET ;------------------------------------------------ ; LCD VFO表示 ; INPUT DEC=表示内容 ; MODE=現在の運用モード ;------------------------------------------------ LCDVFO CLRB RS MOV W,#10000000b+64 CALL WRITE_LCD4 ;カーソルを2行目に移動 MOV PTR,#VFO_MODE0-LCD_TOP ;モードの文字列 MOV W,MODE ; AND W,#00000111b ;現在のモード下位3ビット MOV CN,W ;から表示する文字列を決定する LCDVFO1 RR CN ; JC LCDVFO2 ; ADD PTR,#4 ; GOTO LCDVFO1 ; LCDVFO2 JNB SET_OFFSET,LCDVFO3 ;OFFSETのSETUPモードなら MOV PTR,#VFO_OFFSET-LCD_TOP ; 表示を変える LCDVFO3 MOV CN,#4 ;モードを表示する長さ CALL LCDL2WC ;タイトル表示 MOV W,#' ' ;空白セパレート表示 CALL WRITE_LCD4 ; MOV FSR,#DEC[0] ;10進数に変換した周波数を表示する MOV CN,#11 ; CALL DSPLCD ; RET ;------------------------------------------------ ; 周波数文字列をLCDへ表示 ; INPUT FSR=データアドレス ; CN=文字数 ;------------------------------------------------ DSPLCD MOV W,INDIRECT ; CALL WRITE_LCD4 ; INC FSR ; DJNZ CN,DSPLCD ;指定文字数分くり返し RET ;------------------------------------------------ ; 周波数可変レンジ文字列をLCDへ表示 ; INPUT STEP=現在のレンジコード ;------------------------------------------------ DSPSTEP CLRB RS MOV W,#10000000b+10 ; ADD W,STEP ; CALL WRITE_LCD4 ;カーソルを1行目+nに移動 SETB RS ;以後のコマンドは文字表示 MOV W,#'*' ;+OFFSET演算ならば可変桁位置へ * を表示する JNB PMOFFS,DSPSTEP1 ;-OFFSET演算ならば可変桁位置へ # を表示する MOV W,#'#' ; DSPSTEP1 CALL WRITE_LCD4 ;ステップレンジ位置にマーク RET ;------------------------------------------------ ; DDS(4Byte)の取り出し ; X4=DDS ;------------------------------------------------ LOADDDS MOV X4[0],DDS[0] MOV X4[1],DDS[1] MOV X4[2],DDS[2] MOV X4[3],DDS[3] RET ;------------------------------------------------ ; DDS(4Byte)の退避 ; DDS=X4 ;------------------------------------------------ SAVEDDS MOV DDS[0],X4[0] MOV DDS[1],X4[1] MOV DDS[2],X4[2] MOV DDS[3],X4[3] RET ;------------------------------------------------ ; X4(4Byte)->Y4 ;------------------------------------------------ MOVX4TOY4 MOV Y4[0],X4[0] MOV Y4[1],X4[1] MOV Y4[2],X4[2] MOV Y4[3],X4[3] RET ;------------------------------------------------ ; 退避MODE値(4Byte)の読み込み ; OUTPUT:MODE EEPROM内容 ; STEP EEPROM内容 ;------------------------------------------------ RD_MODE MOV FSR,#MODE MOV W,#E_MODE+0 GOTO RD_EPCOM RET ;------------------------------------------------ ; 退避DDS値(4Byte)の読み込み ; OUTPUT:DDS EEPROM内容 ;------------------------------------------------ RD_DDS JNB SET_OFFSET,RD_DDS0 ;OFFSETのSETUP中なら MOV FSR,#DDS[0] ;EEPROMのOFFSET値を領域DDSへ MOV W,#E_OFFSET+0 ;読み込む GOTO RD_EPCOM ; RD_DDS0 MOV FSR,#DDS[0] MOV W,#E_DDS0+0 JB VFOA,RD_DDS1 MOV W,#E_DDS1+0 RD_DDS1 GOTO RD_EPCOM ;------------------------------------------------ ; 表示OFFSET(4Byte)の読み込み ; OUTPUT:Y4 EEPROM内容 ;------------------------------------------------ RD_OFFSET MOV FSR,#Y4[0] MOV W,#E_OFFSET+0 GOTO RD_EPCOM ;------------------------------------------------ ; 現在の可変ステップ読み出し ; INPUT STEP=0,1,(2),3,4,5 ; OUTPUT Y4=可変ステップ値 ;------------------------------------------------ RD_DDSSTEP MOV FSR,#Y4[0] MOV CN,STEP ;現在のステップ読み出し CLC RL CN RL CN MOV W,#E_STEP0 ADD W,CN ;; GOTO RD_EPCOM ;------------------------------------------------ ; DDS可変値(4Byte)の読み込み ; OUTPUT:Y4 EEPROM内容 ;------------------------------------------------ RD_EPCOM CALL EP_READ4B RET ;------------------------------------------------ ; 現MODE値(1Byte)の書き込み ; INPUT:MODE EEPROMへの書き込み内容 ; STEP EEPROMへの書き込み内容 ;------------------------------------------------ WR_MODE MOV EEADR,#E_MODE+0 MOV FSR,#MODE GOTO WR_EPCOM RET ;------------------------------------------------ ; 現DDS値(4Byte)の書き込み ; INPUT:DDS EEPROMへの書き込み内容 ;------------------------------------------------ WR_DDS JNB SET_OFFSET,WR_DDS0 ;OFFSETのSETUP中なら MOV EEADR,#E_OFFSET+0 ;領域DDSの値をEEPROMのOFFSET領域へ MOV FSR,#DDS[0] ;書き込む GOTO WR_EPCOM ; WR_DDS0 MOV EEADR,#E_DDS0+0 ;VFO-A JB VFOA,WR_DDS5 MOV EEADR,#E_DDS1+0 ;VFO-B WR_DDS5 MOV FSR,#DDS[0] GOTO WR_EPCOM ;------------------------------------------------ ; 表示OFFSET(4Byte)の書き込み ; INPUT:Y4 EEPROMへの書き込み内容 ;------------------------------------------------ WR_OFFSET MOV EEADR,#E_OFFSET+0 MOV FSR,#Y4[0] GOTO WR_EPCOM ;------------------------------------------------ ; DDS可変値(4Byte)の書き込み ; INPUT:Y4 EEPROMへの書き込み内容 ;------------------------------------------------ WR_STEP MOV FSR,#Y4[0] WR_EPCOM CALL EP_WRITE4B RET ;--------------------------------------------------- ; 液晶表示ルーチン ;--------------------------------------------------- ;--------------------------------------------------- ; 8ビットモード専用液晶ライトルーチン ;--------------------------------------------------- WRITE_LCD8 MOV D8,W ;入力パラメタを待避 CLRB GIE ;全割り込み禁止 AND RBDS,#11110000b ;RBの下位を0に AND D8,#00001111b ;D8の上位を0に OR RBDS,D8 ;RB=RB OR D8 MOV RB,RBDS ; SETB GIE ;全割り込み許可 NOP SETB E ; Eピンを'H' NOP CLRB E MOV WAIT_CN,#50 CALL WAIT_US RET ;--------------------------------------------------- ; 4ビットモード専用液晶ライトルーチン ;--------------------------------------------------- WRITE_LCD4 MOV D4,W SWAP D4 MOV W,D4 CALL WRITE_LCD8 SWAP D4 MOV W,D4 CALL WRITE_LCD8 RET ;------------------------------------------------ ; 液晶初期化ルーチン ;------------------------------------------------ INIT_LCD CALL WAIT_MS10 ;WAIT 10mSec CLRB RS ;RS='L' MOV W,#00000011b CALL WRITE_LCD8 CALL WAIT_MS10 ;WAIT 10MS MOV W,#00000011b CALL WRITE_LCD8 CALL WAIT_MS10 ;WAIT 10MS ;;;; MOV WAIT_CN,#100 ;WAIT 100US ;;;; CALL WAIT_US MOV W,#00000011b CALL WRITE_LCD8 ;0 0 0011 (3) MOV W,#00000010b CALL WRITE_LCD8 ;0 0 0010 (4BIT) MOV W,#00101000b ;DUTY,FONT SET9 CALL WRITE_LCD4 MOV W,#00000001b ;クリアコマンド CALL WRITE_LCD4 CALL WAIT_MS10 ;クリアが終わるまで待つ MOV W,#00000110b ;ENTRY MODE SET CALL WRITE_LCD4 MOV W,#00001110b ;DISPLAY ON,CURSOR ON CALL WRITE_LCD4 RET ;------------------------------------------------ ; LCD定数表示 ; INPUT PTR=OFFSET ADDR(FROM LCD_TOP) ; CN =WRITE LENGTH ;------------------------------------------------ LCDL1WC CLRB RS MOV W,#10000000b CALL WRITE_LCD4 ;カーソルを1行目に移動 GOTO LCDLC_COM LCDL2WC CLRB RS MOV W,#10000000b+64 CALL WRITE_LCD4 ;カーソルを2行目に移動 LCDLC_COM SETB RS ;以後のコマンドは文字表示 LCDLC0 MOV W,PTR CALL LCD_TBL CALL WRITE_LCD4 ;文字表示(RS='H') INC PTR DJNZ CN,LCDLC0 ;指定文字数分くり返し RET ;------------------------------------------------ ; 32ビット加算 X4=X4+Y4 ;------------------------------------------------ ADD4B ADD X4[0],Y4[0] MOVLW 1 BTFSC C ADDWF X4[1],1 BTFSC C ADDWF X4[2],1 BTFSC C ADDWF X4[3],1 ADD X4[1],Y4[1] MOVLW 1 BTFSC C ADDWF X4[2],1 BTFSC C ADDWF X4[3],1 ADD X4[2],Y4[2] MOVLW 1 BTFSC C ADDWF X4[3],1 ADD X4[3],Y4[3] RET ;------------------------------------------------ ; 32ビット減算 X4=X4-Y4 ;------------------------------------------------ SUB4B SUB X4[0],Y4[0] MOVLW 1 BTFSS C SUBWF X4[1],1 BTFSS C SUBWF X4[2],1 BTFSS C SUBWF X4[3],1 SUB X4[1],Y4[1] MOVLW 1 BTFSS C SUBWF X4[2],1 BTFSS C SUBWF X4[3],1 SUB X4[2],Y4[2] MOVLW 1 BTFSS C SUBWF X4[3],1 SUB X4[3],Y4[3] RET ;------------------------------------------------ ; 32ビット乗算 Z4=X2*Y2 ;------------------------------------------------ ;MUL2B MOV Z4[0],X2[0] ; MOV Z4[1],X2[1] ; CLR Z4[2] ; CLR Z4[3] ; MOV CN,#16 ;MUL2B0 ; BTFSS Z4[0].0 ; GOTO MUL2B9 ; ; BCF Z4[0].0 ; ; ADD Z4[2],Y2[0] ; MOVLW 1 ; BTFSC C ; ADDWF Z4[3],1 ; BTFSC C ; ADDWF Z4[0],1 ; ; ADD Z4[3],Y2[1] ; MOVLW 1 ; BTFSC C ; ADDWF Z4[0],1 ; ;MUL2B9 MOVB C,Z4[0].0 ; RR Z4[3] ; RR Z4[2] ; RR Z4[1] ; RR Z4[0] ; ; DJNZ CN,MUL2B0 ; RET ;------------------------------------------------ ; 32ビット バイナリ−10進 変換 ; (VFO表示形式 10進は9桁まで) ;------------------------------------------------ CNVVFO MOV FSR,#DEC_TOP ; 格納場所初期値 CALL DEVIDE ; 最下位変換 CALL DEVIDE CALL DEVIDE DEC FSR MOV INDIRECT,#'.' CALL DEVIDE CALL DEVIDE CALL DEVIDE DEC FSR MOV INDIRECT,#'.' CALL DEVIDE CALL DEVIDE CALL DEVIDE ; 最上位変換 MOV W,DEC[0] AND W,#0Fh JNZ CNVVFO9 MOV DEC[0],#' ' MOV W,DEC[1] AND W,#0Fh JNZ CNVVFO9 MOV DEC[1],#' ' CNVVFO9 RET ; ; ÷10サブルーチン ; 10で除算します ; DEVIDE MOV CN,#32 ; 32ビットくり返し CLR X4_M DEVIDE0 CLC RL X4[0] RL X4[1] RL X4[2] RL X4[3] RL X4_M MOVLW 11110110b ADDWF X4_M,0 BTFSC C MOV X4_M,W BTFSC C INC X4[0] DJNZ CN,DEVIDE0 DEC FSR MOV INDIRECT,X4_M ;余り OR INDIRECT,#030h ;ASCIIコードに変換 RET ;------------------------------------------------ ; MSオーダーのウェイト ;------------------------------------------------ WAIT_MS10 MOV WAIT_CN,#10 ;10mSec Wait WAIT_MS WAIT_MS0 CLR WAIT_CN2 WAIT_MS1 NOP NOP NOP NOP NOP NOP NOP DJNZ WAIT_CN2,WAIT_MS1 DJNZ WAIT_CN,WAIT_MS0 RET ;------------------------------------------------ ; uSオーダーのウェイト ;------------------------------------------------ WAIT_US10 MOV WAIT_CN,#10 ;10uSec Wait WAIT_US WAIT_US0 DJNZ WAIT_CN,WAIT_US0 RET ;------------------------------------------------ ; SECオーダーのウェイト ;------------------------------------------------ WAIT_SEC CALL WAIT_MS250 CALL WAIT_MS250 CALL WAIT_MS250 WAIT_MS250 MOV WAIT_CN,#125 ;125mSec Wait CALL WAIT_MS WAIT_MS125 MOV WAIT_CN,#125 ;125mSec Wait CALL WAIT_MS RET ;------------------------------------------------ ; EEPROM リード(4Byte) ; INPUT W =読み込みアドレス ; FSR =格納アドレス ; OUTPUT 格納アドレスへ順次データを格納 ;------------------------------------------------ EP_READ4B CALL EP_READ ;1Byte MOV INDIRECT,W INC FSR MOV W,++EEADR CALL EP_READ ;2Byte MOV INDIRECT,W INC FSR MOV W,++EEADR CALL EP_READ ;3Byte MOV INDIRECT,W INC FSR MOV W,++EEADR CALL EP_READ ;4Byte MOV INDIRECT,W RET ;------------------------------------------------ ; EEPROM リード ; INPUT W=アドレス ; OUTPUT W=データ ;------------------------------------------------ EP_READ MOV EEADR,W ;リードアドレスセット SETB RP0 ;RAMバンク1を指定する SETB RD ;読み込み開始 CLRB RP0 ;RAMバンク0にもどす MOV W,EEDATA ;結果格納 RET ;------------------------------------------------ ; EEPROM ライト(4Byte) ; INPUT EEADR =書き込みアドレス ; FSR =書き込みデータアドレス ; OUTPUT 書き込みアドレスへ順次データを書き込み ;------------------------------------------------ EP_WRITE4B MOV W,INDIRECT CALL EP_WRITE ;1Byte INC FSR INC EEADR MOV W,INDIRECT CALL EP_WRITE ;2Byte INC FSR INC EEADR MOV W,INDIRECT CALL EP_WRITE ;3Byte INC FSR INC EEADR MOV W,INDIRECT CALL EP_WRITE ;4Byte RET ;------------------------------------------------ ; EEPROM ライト ; INPUT EEADR =書き込みアドレス ; W =書き込みデータ ;------------------------------------------------ EP_WRITE MOV EEDATA,W ; SETB RP0 ;RAMバンク1を指定する SETB WREN ; CLRB GIE ;全割り込み禁止 MOV EECON2,#055h ; MOV EECON2,#0AAh ; SETB WR ;書き込み開始 EP_WRITE2 BTFSC WR ; GOTO EP_WRITE2 SETB GIE ;全割り込み許可 CLRB RP0 ;RAMバンク0にもどす RET ;------------------------------------------------ ; DDSユニットの初期化 ;------------------------------------------------ DDS_INI CALL WAIT_MS10 ;WAIT 10mS ; CALL DDSSTB_ON ;DDSストローブ CALL BIT1 ;CSアドレス 111b CALL BIT1 ; CALL BIT1 ; CALL BIT1 ;コマンド 0001b CALL BIT0 ; CALL BIT0 ; CALL BIT0 ; CLR W ;ダミー周波数データ ALL 0 CALL DDS_SEND ; CLR W ; CALL DDS_SEND ; CLR W ; CALL DDS_SEND ; CALL BIT0 ; CALL BIT0 ; CALL DDSSTB_OFF ;DDSストローブ OFF RET ;++++++ TRANSMIT SERIAL DATA TO DDS ++++++++++ ; RA2:DCK(CLOCK) ; RA3:DDT(DATA) ; RA4:DST(STROBE) ; TX_D CALL DDSSTB_ON ;CSアドレス 111b CALL BIT1 ;CS0=1 CALL BIT1 ;CS1=1 CALL BIT1 ;CS2=1 CALL BIT0 ;コマンド 1100b CALL BIT0 ; CALL BIT1 ; CALL BIT1 ; MOV W,DDS[0] ; CALL DDS_SEND ; MOV W,DDS[1] ; CALL DDS_SEND ; MOV W,DDS[2] ; CALL DDS_SEND ; JB DDS_BIT24,TX_D24H ; TX_D24L CALL BIT0 ; GOTO TX_D24C ; TX_D24H CALL BIT1 ; TX_D24C JB DDS_BIT25,TX_D25H ; TX_D25L CALL BIT0 ; GOTO TX_D25C ; TX_D25H CALL BIT1 ; TX_D25C CALL DDSSTB_OFF ;DDSストローブ OFF RET BIT1 CLRB DCK ;CLK=0 SETB DDT ;DATA=1 CALL WAIT_CLK_REV ; RET BIT0 CLRB DCK ;CLK=0 CLRB DDT ;DATA=0 CALL WAIT_CLK_REV ; RET DDSSTB_OFF CLRB DST ;RESET STOROBE=0 CALL WAIT_US10 ;10uS WAIT DDSSTB_ON SETB DST ;NORMAL STROBE=1 RET ;*************************************** ;* SENDING 1BYTE DATA IN W-REG TO DDS ;*************************************** DDS_SEND MOV DDS_DATA,W ;書き込みデータ待避 MOV DDS_CN,#8 ; TX_LP RR DDS_DATA ;Bit shift JC TX_1 TX_0 CLRB DCK ;CLK=0 CLRB DDT ;0 send GOTO TX_NEXT TX_1 CLRB DCK ;CLK=0 SETB DDT ;1 send TX_NEXT CALL WAIT_CLK_REV DJNZ DDS_CN,TX_LP ;8bits end test RET WAIT_CLK_REV CALL WAIT_US10 ;10uS WAIT SETB DCK ;CLK REVERSE CALL WAIT_US10 ;10uS WAIT RET