;---------------------------------------------------------------
;
LC VFO周波数をPICカウンタ制御で安定化する。
;---------------------------------------------------------------
;
ORG 7N4KYG 高石
; Elecraft K-1 Version JA1XFA 田島
; Ver.
1.00 2013/12/01 Clock 10MHz版作成
;
1.01 2013/12/09
; 1.02 2013/12/14
; 1.03 2013/12/15 送信中のVFO制御を止める
; 1.04 2013/12/16 不要ルーチンを削除
; 1.05 2013/12/17 周波数が動かなかったら制御をパス
; 1.05.1 2013/12/18 同上 バグ修正
; 1.06 2013/12/25 周波数ステップの変更を追加
; 1.06.1 2013/12/27 原作のバグ修正ほか
; 1.07 2014/01/18 バグ、コメント修正ほか
; 1.08 2014/01/18 バグ、コメント修正ほか
; 1.09 2014/01/19 バグ、コメント修正ほか
; 1.10 2014/01/19 RIT使用直前の周波数を更新しない点を修正
; 1.101 2014/01/19 エンコーダ入力周り改修版
; 1.101R 2014/01/20 エンコーダ入力周り改修版(本来の接続)
;---------------------------------------------------------------
;ハードウェア(リグ)の信号条件
;
RIT/PTTは単発ではなくレベルを維持する信号であること。
;
つまり押しボタン的な信号条件は不可。トグルスイッチ的な信号が必要。
;
;システムクロック変更時にはカウンタのループ回数も変更すること。
;*****
at Clock=20MHz *****
;wait_10us equ 164 ;100 usec の定数
;***** at Clock=16MHz ***** 80%
;wait_10us equ 131 ;100
usec の定数(若干短い)
;***** at Clock=10MHz ***** 50%
wait_10us equ 82 ;100 usec
の定数
;***** at Clock= 4MHz ***** 20%
;WAIT_10US equ 32 ;100 usec
の定数
;******************
;システム構成の定義
;******************
.include 16f84.h ;CPUに16F84を指定する
.osc hs ;外部発振器、高速
.wdt off ;ウォッチドッグを使用しない
.pwrt off ;パワーアップタイマを使用しない
.protect off ;プロテクトはしない
;************************************************
;送受信に関するパラメータ群
;発信周波数
osc
;周波数ステップ
;************************************************
;Normal
step3
equ 00000000b ;周波数ステップ = 40Hz 2013/12/09
step2
equ 00000000b ; 3
2 1 0
step1
equ 00000000b ; 00 00 00 04
= 4
step0 equ 00000100b ;プログラム上で10倍比較ゆえに40。
;Wide
wstep3 equ 00000000b ;周波数ステップ = 100Hz
2013/12/28
wstep2 equ 00000000b ;
3 2 1 0
wstep1
equ 00000000b ; 00 00 00 0a
= 10(Dec)
wstep0 equ 00001010b ;プログラム上で10倍比較ゆえに100。
;VFO発振周波数(電源On時に自動設定する周波数)/10 の値
;単位 発振周波数/10(KHz)
CPUクロックには関係しない
;
; システム起動時の発振周波数の設定
;
2.990,4MHz
;設定値は、発振周波数の1/10となる
;
setf3 equ 00h ;
2013-12-14
setf2 equ 04h ; 04 b3
52
setf1 equ 0b3h ;
setf0 equ 052h ;
;******************************************
;ロータリーエンコーダに用いる H/W
定義
;******************************************
rea
equ rb.0 ;A相
reb equ rb.1 ;B相
;******************************************
;周波数ステップ切り替えポート
;
H=40Hz,L=100Hz
;******************************************
step_sw equ rb.2 ;周波数ステップSW
;******************************************
;ロータリーエンコーダで使用するメモリー定義
;******************************************
rodat ds 1
ropas ds 1
;******************************************
;システムに用いるメモリー定義
;******************************************
org 0ch
cn ds 1 ;
0ch カウンタ
wrk ds 1 ; 0dh
ワーク
freq ds 4 ; 0eh-11h
現在の周波数
stfreq ds 4 ; 12h-15h
設定周波数
trxfreq ds 4 ; 16h-19h
送受信周波数
ritfreq ds 4 ; 1ah-1dh
RIT受信周波数
x ds 4 ; 1eh-21h long
計算ワーク
y ds 4 ; 22h-25h long
計算ワーク
;**********************
;システムで使用する変数
;**********************
wrks ds 1 ;
26h ステータスの退避メモリ
wrkw ds 1 ; 27h
アキュムレータ退避メモリ
timecnt0 ds 1 ; 28h
割込みサービス変数
waitnss0 ds 1 ;
29h
waitnss1 ds 1 ; 2ah
waitnss2 ds 1 ;
2bh
par ds 1 ; 2ch
関数間の受渡しデータ
parr ds 1 ; 2dh
関数間の受渡しデータ
d8 ds 1 ; 2eh
関数間の補助受渡しデータ
os_wrk1 ds 1 ; 2fh μsec wait
カウンタ
os_wrk2 ds 1 ; 30h 1msec wait
カウンタ
rbddr ds 1 ; 31h rb
の設定データ
pa ds 1 ; 32h
ポートの読込みデータ
os_flg ds 1 ; 33h
フラグ用メモリ
lpcnt1 ds 1 ;
34h
lpcnt2 ds 1 ; 35h
;
; ;
Max
4fh
;*********************************************************
;各種フラグ&ポートの定義
;*********************************************************
timeup equ os_flg.0 ;タイムアップフラグ
rs
equ os_flg.1 ;論理ポート
rrs
equ rb.2 ;物理ポート
ee
equ rb.3 ;
vdown equ ra.0 ;vco-チャージ
vup
equ ra.1 ;vco+チャージ
;2013/12/27 rit_sw/tx_sw
配線図に合わせた。原作bugのfix.
rit_sw equ ra.2 ;rit-on→sw
tx_sw equ ra.3 ;送信時on→sw
count_in equ ra.4 ;tmr0のポートの開閉
;*********************************************************
;*****
プログラムセクション
*****
;*********************************************************
;*********************************************************
;システムの初期化と起動
;*********************************************************
org 0 ;
goto start ;
;*********************************************************
;ロータリーエンコーダかの割り込み
;
;2014-Jan-21
;K−1は逆ダイヤルのためUp/Downの周波数計算を反対にした
;*********************************************************
org 4 ;エンコーダの割り込み
call wait1ms ;1msウエイト
;
;機械式エンコーダで取りこぼしの場合は
;チャッタ除去のためウェイトを増す。
; call wait1ms ;1msウエイト
; call wait1ms ;1msウエイト
movb rodat.1,reb ;B
入力
btfss reb ;rb1が1か確認する
goto setp ;
setm
call inc_freq ;周波数を加算する(逆ダイヤル対応)
; call dec_freq ;周波数を減算する
goto
setf ;
setp
call dec_freq ;周波数を減算する(逆ダイヤル対応)
; call inc_freq ;周波数を加算する
setf
btfss tx_sw ;送信中?
goto tx_new ;yes..
btfsc rit_sw ;受信中、かつ RIT
Off?
goto tx_new ;yes..
;受信中で RIT
On
mov ritfreq[0],stfreq[0] ;基準値を更新
mov ritfreq[1],stfreq[1] ;
mov ritfreq[2],stfreq[2] ;
mov ritfreq[3],stfreq[3] ;
goto int_pro
;送信中、または受信中で RIT
Off
tx_new
mov trxfreq[0],stfreq[0] ;基準値を更新
mov trxfreq[1],stfreq[1] ;
mov trxfreq[2],stfreq[2] ;
mov trxfreq[3],stfreq[3] ;
int_pro
; call fcont_enc ;割り込み中でも周波数補正させる。
goto main ;メインに復帰、割り込み処理終了
;*********************************************************
;スタートアップ
;*********************************************************
start
bsf status,5 ;set
page 1
mov option,#01100000b
;ra4(tmr0)の設定
;プリスケーラを含む
;prescaler
1/2
set
;RBプルアップ
;立ち下がりカウント
bcf status,5 ;set
page 0
clr tmr0 ;Clear
TMR0
mov !ra,#00011100b ;ra2,3,4を入力,ra0,1をOUT に
;2013/12/27 RB2 ステップ切替に使う (=0 then 40Hz/=1 then
100Hz)
; mov !rb,#00000011b ;rb0,1 以外を全部 OUT
に
mov !rb,#00000111b ;rb0,1,2 in 他全てOUT (RB2
Step切替)
mov ra,#00000000b ;ポート初期化
mov rb,#00000000b ;ポート初期化
mov stfreq[3],#setf3 ;基準周波数を設定
mov stfreq[2],#setf2 ;
mov stfreq[1],#setf1
mov stfreq[0],#setf0
mov trxfreq[0],stfreq[0] ;送信周波数に基準値を設定
mov trxfreq[1],stfreq[1] ;
mov trxfreq[2],stfreq[2] ;
mov trxfreq[3],stfreq[3] ;
mov intcon,#10010000b ;rb0割り込みを許可する
; 初期化後メイン処理ループへ
;*********************************************************
;メインルーチン
;*********************************************************
main
call f_count ;カウンター
call vfo_cont ;vfo制御
goto main ;メインに戻る
;************************************************************************
;周波数補正ルーチン
エンコーダ割込より呼ばれる。
;************************************************************************
fcont_enc
call f_count ;周波数カウント
その後vfo制御へ
;************************************************************************
;VFO制御
;stfreq-freq(セット周波数-現在の周波数)で引き算して差があるとき
;周波数が記憶している周波数(stfreq)になるように、+/-の制御信号を出す。
;************************************************************************
vfo_cont
mov intcon,#00000000b ;rb0割り込みを許可しない。
;1.09
btfss tx_sw ;tx
on?(送信中?)
goto send_or_ritoff
;受信中
btfss rit_sw ;rit
onなら
goto rit_on ;rit_onへジャンプする。
;RIT Off
受信中もしくは送信中
send_or_ritoff
mov stfreq[0],trxfreq[0] ;送信周波数を基準にセット。
mov stfreq[1],trxfreq[1] ;
mov stfreq[2],trxfreq[2] ;
mov stfreq[3],trxfreq[3] ;
;1.10
bug
fix
mov ritfreq[0],trxfreq[0] ;RIT周波数をクリア。
mov ritfreq[1],trxfreq[1] ;
mov ritfreq[2],trxfreq[2] ;
mov ritfreq[3],trxfreq[3] ;
goto freq_check ;周波数ずれチェックへ
rit_on
;受信中かつ RIT
On
mov stfreq[0],ritfreq[0] ;受信周波数を基準にセット。
mov stfreq[1],ritfreq[1] ;
mov stfreq[2],ritfreq[2] ;
mov stfreq[3],ritfreq[3] ;
;周波数があまり動かなかった場合の処理。2013-12-17
JA1XFA
;一計測周期前の周波数と今計測した周波数がずれたか調べる
;LC発振では精密な周波数維持は難しいので、計測値の最下
;桁の2ビット分の変動は無視する。
freq_check
mov x[0],stfreq[0] ;一つ前の受信周波数を作業変数に代入
movlw 11111100b
andwf x[0],1 ;下2ビットマスク
mov y[0],freq[0] ;最新計測周波数を作業変数に代入
movlw 11111100b
andwf y[0],1 ;下2ビットマスク
;---------------------------------------------------------------------------
;
計算対象値の上位3桁は全ビットを比較する
;---------------------------------------------------------------------------
sub x[0],y[0] ;最下桁が等しいかチェック
jnz freq_calc ;等しくなければ+-計算へ
mov x[1],stfreq[1] ;桁が上がっているので全ビットチェック
mov y[1],freq[1] ;
sub x[1],y[1] ;2桁目は?
jnz freq_calc ;等しくなければ+-計算へ
mov x[2],stfreq[2] ;同上
mov y[2],freq[2] ;
sub x[2],y[2] ;3桁目は?
jnz freq_calc ;等しくなければ+-計算へ
mov x[3],stfreq[3] ;同上
mov y[3],freq[3] ;
sub x[3],y[3] ;最上桁は?
jz dainyuu ;等しかった。全桁一致。制御不要。
;周波数ズレ計算のため変数へデータを再セットする。
freq_calc
mov x[0],freq[0] ;現在の周波数
mov x[1],freq[1] ;
mov x[2],freq[2] ;
mov x[3],freq[3] ;
mov y[0],stfreq[0] ;設定周波数
mov y[1],stfreq[1] ;
mov y[2],stfreq[2] ;
mov y[3],stfreq[3] ;
;*************************************
;
周波数ズレを計算、周波数を設定。
;*************************************
call sub_xy ;現在の周波数-設定周波数
btfss x[3].7 ;+-の振り分け
;正なら代入、負なら逆数を整数に変換
goto purasu ;整数は、そのまま代入
;******周波数マイナスの時の処理*******
mov y[0],x[0] ;引き算の準備
mov y[1],x[1] ;-は逆ビット数なので整数にする。
mov y[2],x[2] ;
mov y[3],x[3] ;
clr x[0] ;マイナスを整数に変換
;notを使わず0より引く
clr x[1] ;
clr x[2] ;
clr x[3] ;
call sub_xy ;マイナスを整数へ変換のための引き算
;**************************************************************
;**
バリキャップへの電圧印加時間、マイナスの時の動作時間作り
**
;**************************************************************
;
応答時間(VFOのセットアップ時間)が不足ならハードのコンデンサを
;
減らすなどの対応が必要
;
;*****周波数マイナスの時は、電圧up********
syuuseim
bcf vdown ;ra1-off コンデンサ電圧放電やめインターロック
cje x[1],#0,jpm0 ;cje==
if fr==<#lite then goto
bsf vup ;ra0-on コンデンサへ電圧印加
mov par,#10 ;10ms
wait
call waitnms ;
goto jpm02
jpm0
cjb x[0],#32,jpm01 ;cjb== if fr<<#lite then
goto
bsf vup ;ra0-on コンデンサへ電圧印加
call wait1ms ;
1ms wait
goto jpm02
jpm01
cjb x[0],#1,jpm02 ;20hz以内は、不感帯
bsf vup ;ra0-on コンデンサへ電圧印加
mov parr,x[0] ;cへのチャージ時間に代入
call wait_nss ;
jpm02
bcf vup ;ra0-off コンデンサへ電圧印加やめ
goto dainyuu ;変数に代入
;***** バリキャップへの電圧印加時間 **********
;***** 周波数プラスの時の動作時間作り ********
;*****
制御時間不足ならハード変更検討
********
;
purasu ;周波数プラスの処理 電圧下げる。
bcf vup ;ra0-offコンデンサへ電圧印加やめインターロック
cje x[1],#0,jpp0 ;cjb==
if fr<<#lite then goto
bsf vdown ;ra1-on コンデンサ電圧放電へ
mov par,#10 ;wait
10ms
call waitnms ;
goto jpp02
;
jpp0
cjb x[0],#32,jpp01 ;cjb==
if fr<<#lite then
goto
bsf vdown ;ra0-on コンデンサへ電圧印加
call wait1ms ;wait
1ms
goto jpp02
;
jpp01
cjb x[0],#1,jpp02 ;20hz以内は、不感帯
bsf vdown ;ra1-on コンデンサ電圧放電へ
mov parr,x[0] ;cへのチャージ時間に代入
call wait_nss ;
jpp02
bcf vdown ;ra1-off コンデンサ電圧放電やめ
dainyuu
btfss rit_sw ;RIT
On?
goto riton_ret
;送信中もしくは受信中で RIT
Off
mov trxfreq[0],stfreq[0] ;送信周波数を基準にセット。
mov trxfreq[1],stfreq[1] ;
mov trxfreq[2],stfreq[2] ;
mov trxfreq[3],stfreq[3] ;
goto dai_ret
;受信中かつ RIT
On
riton_ret
mov ritfreq[0],stfreq[0] ;受信周波数を基準にセット。
mov ritfreq[1],stfreq[1] ;
mov ritfreq[2],stfreq[2] ;
mov ritfreq[3],stfreq[3] ;
dai_ret
mov intcon,#10010000b ;rb0割り込みを許可する
return
;****************
;周波数を ++
する
;****************
inc_freq
call freq_sub ;周波数偏移を計算する。
call add_xy ;x
= 現在周波数+ステップ
goto setfq
;****************
;周波数を --
する
;****************
dec_freq
call freq_sub ;周波数偏移を計算する。
call sub_xy ;x
= 現在周波数-ステップ
setfq
mov stfreq[0],x[0] ;結果の受け取り
mov stfreq[1],x[1] ;
mov stfreq[2],x[2] ;
mov stfreq[3],x[3] ;
return
;***************************
;
周波数偏移計算サブ
;***************************
freq_sub
mov x[3],stfreq[3] ;もとの周波数
mov x[2],stfreq[2] ;
mov x[1],stfreq[1] ;
mov x[0],stfreq[0] ;
btfss step_sw ;step_sw=off then
nomal
goto nor_step
; wide
step
mov y[3],#wstep3 ;Wideステップ
mov y[2],#wstep2
mov y[1],#wstep1
mov y[0],#wstep0
return
nor_step
mov y[3],#step3 ;通常ステップ
mov y[2],#step2
mov y[1],#step1
mov y[0],#step0
return
;***************************
;long
型式の引き算プログラム
;***************************
sub_xy
sub x[0],y[0]
movlw 1
btfss c
subwf x[1],1
btfss c
subwf x[2],1
btfss c
subwf x[3],1
sub x[1],y[1]
movlw 1
btfss c
subwf x[2],1
btfss c
subwf x[3],1
sub x[2],y[2]
movlw 1
btfss c
subwf x[3],1
sub x[3],y[3]
return
;***************************
;long
型式の足し算プログラム
;***************************
add_xy
add x[0],y[0]
movlw 1
btfsc c
addwf x[1],1
btfsc c
addwf x[2],1
btfsc c
addwf x[3],1
add x[1],y[1]
movlw 1
btfsc c
addwf x[2],1
btfsc c
addwf x[3],1
add x[2],y[2]
movlw 1
btfsc c
addwf x[3],1
add x[3],y[3]
return
;**************
;1msec
ウェイト
;**************
wait1ms
mov os_wrk2,#10
wm_lxh2
call waitus0
djnz os_wrk2,wm_lxh2
return
;****************
;100usec
ウェイト
;****************
waitus0
mov os_wrk1,#wait_10us
wu_lxh
djnz os_wrk1,wu_lxh
return
;***********************
;n
msec ウェイト
;n は par
にセットしコール
;***********************
waitnms
call wait1ms
djnz par,waitnms
return
;****************
;2乗タイマ
ウェイト
;****************
wait_nss
cjb parr,#0,gotowait1 ;誤動作防止マイナス計算される。
mov waitnss2,parr
wait_nss2
mov waitnss1,parr
wait_nss1
djnz waitnss1,wait_nss1
djnz waitnss2,wait_nss2
gotowait1
return
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;*********************************************************
;周波数カウンタ部
freq[0]〜freq[3]
の32ビットに計測値得る
;*********************************************************
f_count
clr freq[0] ;周波数カウントの前処理
clr freq[1] ;
clr freq[2] ;
clr freq[3] ;
bsf count_in ;ゲートを開ける。
clr tmr0 ;counter
reset
bcf intcon,2 ;reset T0IF
;各Clock における LPCNT2/LPCNT1
の数値(ゲートタイム時間)
;20MHzを基準とすると10MHzなら10/20=0.5でループ回数は半分になる。
;同様に4MHzなら4/20=0.2で五分の一で同一ゲートタイムになる。
;
↓
↓
; Clock 20MHz (15*LPCNT2 133 + 5)*LPCNT1 125 = 250,000ステップ(7N4KYG)
;
Clock 16MHz (15*LPCNT2 133 + 5)*LPCNT1 100 = 200,000 (JA1XFA)
; Clock 10MHz
(15*LPCNT2 83 + 5)*LPCNT1 100 = 125,000 (JA1XFA)
; Clock 4MHz
(15*LPCNT2 83 + 5)*LPCNT1 40 = 50,000 ( -"- )
;50msループ 開始!
; mov lpcnt1,#125 ;loop counter1 回数 Clock
20MHz
mov lpcnt1,#100 ;loop counter1 回数 Clock
10MHz
; mov lpcnt1,#40 ;loop counter1 回数 Clock
4MHz
meslp1
; mov lpcnt2,#133 ;loop counter2 回数 Clock
20MHz
mov lpcnt2,#83 ;loop counter2 回数 Clock
10MHz/4MHz
meslp2
btfss intcon,2 ;13 steps
loop
goto dumy1 ;
bcf intcon,2 ;reset
T0IF
movlw 1 ;カウントアップ
goto
next ;
dumy1
nop ;ステップ数調整
nop ;ステップ数調整
movlw 0 ;カウントアップ無し
next
nop ;ステップ数調整
nop ;ステップ数調整
addwf freq[1],1 ;freq[1]+T0IF
rlf freq[1],0 ;carry
to
d0
andlw 1 ;mask
addwf freq[2],1 ;BYTE2+Carry
decfsz lpcnt2,1 ;check
loop
end
;内側ループ
goto meslp2 ;loop
decfsz lpcnt1,1 ;
;外側ループ
goto meslp1 ;
;---------
Count Loop End
-----------------------------------------
bcf count_in ;ゲートを閉める。50msの計測時間終了
nop ;50msループから脱出
カウント終了
movf tmr0,0 ;TMR0をfreq[0]に取り出し
movwf freq[0] ;061112()と[]間違え有った
btfss intcon,2 ;オーバーフロー確認
goto tobu1 ;オーバーフローで無いなら
bcf intcon,2 ;reset
T0IF
btfsc freq[0],7 ;繰上りミス防止
goto tobu1
movlw 1
addwf freq[1],1 ;freq[1]+T0IF
rlf freq[1],0 ;carry
to
d0
andlw 1 ;mask
addwf freq[2],1 ;freq[2]+Carry
;**************************************************************
;測定間隔は100ms。現計測は50ms、そしてプリスケーラで1/2したので
;データを4倍する。
;**************************************************************
tobu1
call tobu2 ;まず2倍。プリスケーラの分
tobu2
bcf status,0
rlf freq[0],1 ;2倍にする。
rlf freq[1],1
rlf freq[2],1
rlf freq[3],1
bcf status,0
return
;----------------------------------------------------------
end