; fll 2006/07/30 7n4kyg
; dllに改名 2006/09/16 一応それなりに、動く!!
; 2006/10/01差の周波数表示としたが、いまいち上手く行かない。結果、設定周波数にした。
; 2006/10/21周波数カウント回路のポート入れ替えを削除 フリッカーノイズ対策
; 2006/10/29周波数偏差20HZ以下でも、多少調整(20hz調整すると、音質が変化する為)
; 2006/10/30 VFO-CONTを割り込み不許可にした。
; 2006/11/12 pa-3.0にて、エラー発生アリ 土台を修正(新規のファイルに貼付、変な属性あったかも?
; 他にエラー6点発生修正済み
; OPTIONで文法エラー、FCOUNTで文法エラー,freq_to_oscでエラー有り修正済み
; カウンター部127以上繰り上がり禁止でカウンター正常になった。可也苦労3週間悩んだ!!
; 2007/01/30訂正 btfsc freq[0],7;繰上りミス防止上記内容
; 2007/03/24 RITプログラム追加 rit動作ok
; 2007/05/28 RIT初期記憶追加 RIT ONで立ち上げると送信Fが違いすぎる。
; 2007/06/06 ハムフェアーに提出 落選
; 2008/08/23 ステップ50hzに変更、RIT,送信表示、周波数誤差12khz修正
; 2010/02/07 RIT、TX信号入れ替え
; 2010/03/15 フォトカプラー信号入れ替え
; 2010/06/06 7mhz拡張の為中心周波数を7.075Mhzに変更
; 2010/07/30 7mhzやっぱり中心周波数を7.050Mhzの方がイイ
; 2010/08/14 チューニング中でも周波数補正させる。 良好
; 2010/12/05 クロック20mhz&クリスタルにする。周波数カウント時間50ms最高測定5Mhz計測、プリスケーラ2倍削除
; 2011/01/22 if 10.24mhzに変更 if12だと、北京放送入るので!!
; 2011/01/23 プリスケーラをなし、前はX2 ステップ20hzに、ダイアル回しても周波数変化遅いので!。
; 2012/02/15  ritスイッチ、tx表示逆なので修正&rit周波数表示
; 2012/09/08  周波数ずれを修正 周波数誤差12khz修正この処理削除

; 2025/6/5 aki pa よりmplabに変換 変換したが表示化ける
; 2026/2/14 asc変換ok 原因はascのメモリー番地20hにした
; 2026/2/25 16f84aより16f648aにしてra5をステップ切替にした

;***** at Clock=20.00mhz *****
;wait_10us equ 164   ;100 usec の定数
;wait_4us equ 64   ;40 usec の定数
;lcd_line1 equ 0   ;LCDの1行目の先頭アドレス
;lcd_line2 equ 64   ;LCDの2行目の先頭アドレス
;***** at Clock=12.80mhz *****
;wait_10us equ 105   ;100 usec の定数
;wait_4us equ 41   ;40 usec の定数
;LCDに関する定数の定義
;***** at Clock=10MHz *****
;WAIT_10US equ 82    ;100 usec の定数
;WAIT_4US equ 32   ;40 usec の定数
;***** at Clock=4.00MHz *****
;WAIT_10US equ 32   ;100 usec の定数
;WAIT_4US equ 12   ;40 usec の定数
;******************
;システム構成の定義
;******************
 ;LIST P=PIC16F648A
 ;INCLUDE P16F648A.INC
     ; ERRORLEVEL -302   ; message 302を表示させない
 ;__CONFIG _CP_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_ON & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _HS_OSC
     ; LIST            P=PIC16F84A        ;
     ;INCLUDE   "P16F84A.INC"   ;2021-9-4--ノ「ヒョ
     ;__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF


 LIST P=PIC16F648A
  INCLUDE P16F648A.INC

 __CONFIG _CP_OFF & _CP_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_OFF & _PWRTE_ON & _LVP_OFF & _HS_OSC

;****************************
;システムに用いるメモリー定義
;****************************

     ;org 0ch
     CBLOCK  H'020'  ;0ch ;cbloockで一括定義(変数宣言?)

asc0  ;asc data,20hに置くこと
asc1  ;追伸、ascを適当な番地はngでした
asc2
asc3
asc4
asc5
asc6
asc7
asc8
asc9
asc_end
rodat   ;ロータリーエンコーダで使用するメモリー定義
ropas
cn   ;カウンタ
cnnn   ;カウンタ

x0   ;long 計算ワーク
x1
x2
x3   ;発振周波数
os_wrk1   ;μsec wait カウンタ
os_wrk2   ;1msec wait カウンタ
rbddr   ;rb の設定データ
pa   ;ポートの読込みデータ
os_flg    ;フラグ用メモリ
wrk   ;ワーク
rewrk   ;エンコーダ用ワーク;osc1 equ h'13' 
;***** at Clock=20.00mhz *****
wait_10us   ;164 ;100 usec の定数
wait_4us   ;40 usec の定数
waitnss1
waitnss2

lpcnt1
lpcnt2 

freq0   ;現在の周波数
freq1
freq2
freq3

kstep0   ;早送り記憶 110129追加
kstep1 
kstep2
kstep3

y0   ;long 計算ワーク
y1
y2
y3

stfreq0   ;設定周波数
stfreq1
stfreq2
stfreq3

iffreq0   ;中間周波数
iffreq1
iffreq2
iffreq3 

txfreq0   ;送信周波数
txfreq1
txfreq2
txfreq3

rxfreq0  ;受信周波数
rxfreq1
rxfreq2
rxfreq3

wrks   ;ステータスの退避メモリ
wrkw   ;アキュムレータ退避メモリ
timecnt0  ;割込みサービス変数

par   ;関数間の受渡しデータ
parr   ;関数間の受渡しデータ
d8   ;関数間の補助受渡しデータ
    ENDC

;************************************************
;送受信に関するパラメータ群
;発信周波数 osc
;表示周波数 freq
;add_xy x=x+y
;sub_xy x=x-y
;long_to_asc asc=ltoa( x )
;************************************************
;**************************
;LCD コントロールピンの定義
;各種フラグの定義
;**************************
#DEFINE timeup os_flg.0   ;タイムアップフラグ
#DEFINE rs os_flg,1   ;論理ポート
;***************************************
;ロータリーエンコーダーに用いる H/W 定義
;***************************************

#DEFINE rea  PORTB,0   ;A相
#DEFINE reb  PORTB,1   ;B相
#DEFINE rrs PORTB,2   ;物理ポート
#DEFINE ee  PORTB,3

#DEFINE vdown PORTA,0   ;vco-チャージでない。
#DEFINE vup  PORTA,1   ;vco+チャージ。
#DEFINE tx_sw  PORTA,2   ;送信時。 **********名前on→sw 
#DEFINE rit_sw  PORTA,3   ;ritがon。  名前on→sw
#DEFINE count_in PORTA,4   ;TMR0のポートMR0のポートの開け閉めつけました。
#DEFINE stepup PORTA,5   ;ステップ切り替え

;*****  プログラムセクション  *****
;****************
;システムの初期化
;****************
  org 0
  goto start

  org 4   ;エンコーダーの割り込み
  goto enco_in   ;割り込み処理へ
;**************
;スタートアップ
;**************
start 
  bsf STATUS,5   ;set page 1
  ;bcf vdown
 
  movlw b'01100000'   ; #01100000b  ;ra4(TMR0)の設定 プリスケーラを含む
  movwf OPTION_REG   ;prescaler 1/2 set ;RBプルアップ; 立ち下がりカウント
      
  movlw b'00011100'   ;1ch;#00011100b   ;ra2,3,4,5を入力,ra0,1をOUT に
  movwf TRISA

  movlw b'00000011'   ;#00000011b   ;rb0,1 以外を全部 OUT に
  movwf TRISB

  bcf STATUS,5   ;set page 0

  MOVLW   07h   ;b'00000111'
  MOVWF   CMCON    ;コンパイラOFF

  CLRF TMR0   ;Clear TMR0
  CLRF PORTA   ;ポート初期化
  CLRF PORTB   ;ポート初期化
 
  ;bcf STATUS,RP0

  call lcdopen   ;LCD初期化

  movlw b'00000000'   ;エンコーダの初期周波数を入力(4.95mhz)
  movwf stfreq3   ;尚、表示は、10倍にする(左へ一桁シフトさせる)
  movlw b'00000111'
  movwf stfreq2
  movlw b'10001101'
  movwf stfreq1
  movlw b'10011000'
  movwf stfreq0

  movlw b'00000000'   ;中間周波数12MHz
  movwf iffreq3   ;リテラルをメモリーに移動書き込み
  movlw b'00010010'
  movwf iffreq2
  movlw b'01001111'
  movwf iffreq1
  movlw b'10000000'
  movwf iffreq0

  movlw b'00000000'   ;ステップ40hz リテラルをメモリーに移動書き込み
  movwf kstep3
  movlw b'00000000'  
  movwf kstep2
  movlw b'00000000'
  movwf kstep1
  movlw b'00000100'
  movwf kstep0
 
  movf  stfreq3,w   ;内容をfに書き込む時movfを使う 最初に送信周波数を記憶して置く
  movwf txfreq3   ;rit、onのままだと、とんでもない数値を記憶する為
  movf  stfreq2,w   ;リセットを掛ける。
  movwf txfreq2
  movf  stfreq1,w
  movwf txfreq1
  movf  stfreq0,w
  movwf txfreq0

  movlw b'10010000'   ;intcon,#10010000b ;rb0割り込みを許可する
  movwf INTCON   ;intcon 大文字にする;

  movlw d'1'   ;cnnn,#1   ;表示回数の設定 初期値の設定 
  movwf cnnn

;**************+      
;メインルーチン
;**************
main
  call f_count   ;カウンター
  call vfo_cont   ;vfo制御
  decfsz cnnn,f   ;djnz cnnn,main  ;ループ中は、表示は、10回ループに1回;
  goto main
  call hyouji_ue   ;現在/設定差の周波数の表示
  movlw d'10'   ;mov cnnn,#10  ;表示回数の設定一秒に一回では、ちらつき過ぎ
  movwf cnnn
  goto  main   ;メインに戻る

;**************+      
;周波数補正ルーチン 割込より呼ばれる。
;**************
fcont_enc
  call f_count   ;カウンター
  call vfo_cont   ;vfo制御
  call hyouji_ue   ;現在/設定差の周波数の表示
  RETURN   ;メインに戻る

;*********************************************************
;周波数カウンター初期設定
;オーバーフロー監視、カウントアップ、一定時間の確保(25msec) 後で5mhz迄測定不可能  ここの処理おかしい
;59*163*2.6=(25msec)1命令時間 1/20MHz*4*13Step=2.6 ここの処理おかしい       
;118*163*2.6=(50msec)1命令時間 1/20MHz*4*13Step=2.6 これ OK 6khzの誤差 ここの処理おかしい
;98*157*2.6=(40msec) =25hz最小周波数 これわ 駄目!!ここの処理おかしい
;*********************************************************fcount
f_count
  ;  bsf vup++++++++++++++++++++++++++++++++++++++おかしい?
  clrf freq0   ;周波数カウントの前処理
  clrf freq1
  clrf freq2
  clrf freq3
  bsf count_in   ;ゲートを開ける 120907追加TMR0の開く指令 
  clrf TMR0   ;TMR0   ;counter reset
  bcf INTCON,2   ;intcon,2  ;reset T0IF
  movlw d'125'   ;7dh;mov lpcnt1,#125  ;loop counter 回数変更
  movwf lpcnt1
meslp1
  movlw d'133'   ;85h ;mov lpcnt2,#133  ;loop counter 回数変更
  movwf lpcnt2
meslp2
 
  btfss INTCON,2   ;13 steps loop   
 
  goto dumy1
  bcf INTCON,2   ;reset T0IF
  movlw d'1'   ;1;カウントアップ
  goto  next
dumy1
  nop   ;dumy NOP
  nop   ;同じステップ数にするため
  movlw d'0'   ;0   ;カウントアップ無し
next
  nop   ;ステップ調整  120907追加              
  nop   ;ステップ調整  120907追加
  addwf freq1,1   ;freq[1]+T0IF
  rlf freq1,0   ;carry to d0
  andlw d'1'   ;1  ;mask
  addwf freq2,1   ;BYTE2+Carry
  decfsz lpcnt2,1   ;check loop end
  goto meslp2   ;loop
  decfsz lpcnt1,1
  goto meslp1   ;(15*LPCNT2 133 +5)*LPCNT1 125 ==2500000ステップ
 
  bcf count_in   ;ゲートを閉める          
 
  nop   ;50msループから脱出
  movf TMR0,w   ;TMR0をfreq[0]に取り出し
  movwf freq0   ;061112()と[]間違え有った
  btfss INTCON,2   ;オーバーフロー確認   
  goto tobu1   ;オーバーフローで無いなら
  bcf INTCON,2   ;reset T0IF
  btfsc freq0,7   ;繰上りミス防止 '070130訂正
  goto tobu1
  movlw d'1'    ;1
  addwf freq1,1   ;freq[1]+T0IF
  rlf freq1,0   ;carry to d0
  andlw d'1'   ;1;mask
  addwf freq2,1   ;freq[2]+Carry
tobu1
   ;プリスケーラーで1/2したので最後にデーターを4倍する。50mSなので!
  bcf STATUS,0   ;status,0
  rlf freq0,1   ;2倍にする
  rlf freq1,1
  rlf freq2,1
  rlf freq3,1
  bcf STATUS,0

  bcf STATUS,0
  rlf freq0,1  ;2倍にする
  rlf freq1,1
  rlf freq2,1
  rlf freq3,1
  bcf STATUS,0
  RETURN

;********************************************************************
;vfo制御 stfreq-freq(セット周波数-現在の周波数)で引き算して、差があるとき
;周波数が+又は-に成るように、制御信号を出す。
;********************************************************************
vfo_cont
  movlw b'00000000'   ;mov INTCON,#00000000b
  movwf INTCON

;rb0割り込みを許可しない。ここで、割込発生すると、チャージ、デチャージし続ける為。
  movf  stfreq0,w   ;ritコントロール  変数に記憶する
  movwf rxfreq0
  movf  stfreq1,w
  movwf rxfreq1
  movf  stfreq2,w
  movwf rxfreq2
  movf  stfreq3,w
  movwf rxfreq3

  btfss rit_sw   ;rit onなら
  goto ritsww   ;実際は、rit onの時は、ジャンプする。
 
 movf stfreq0,w   ;ritがoffならば、送信周波数を記憶して置く
 movwf txfreq0   ;(逆に云うと、rit、onの時は、送信周波数は、固定させる。
 movf stfreq1,w
 movwf txfreq1
 movf stfreq2,w
 movwf txfreq2
 movf stfreq3,w
 movwf txfreq3
ritsww 
 btfsc tx_sw   ;tx on?(送信中?)
 goto txsww

 movf rxfreq0,w   ;現在の周波数を受信周波数に代入
 movwf stfreq0
 movf rxfreq1,w
 movwf stfreq1
 movf rxfreq2,w
 movwf stfreq2
 movf rxfreq3,w
 movwf stfreq3
  goto rxon
txsww
 movf txfreq0,w   ;現在の周波数を受信周波数に代入
 movwf stfreq0
 movf txfreq1,w
 movwf stfreq1
 movf txfreq2,w
 movwf stfreq2
 movf txfreq3,w
 movwf stfreq3
rxon
 movf freq0,w   ;現在の周波数vfo周波数
 movwf x0
 movf freq1,w
 movwf x1
 movf freq2,w
 movwf x2
 movf freq3,w
 movwf x3

 movf stfreq0,w   ;設定周波数4.95mhz
 movwf y0
 movf stfreq1,w
 movwf y1
 movf stfreq2,w
 movwf y2
 movf stfreq3,w
 movwf y3
          ;*************
  call sub_xy   ;現在の周波数-設定周波数
  btfss x3,7   ;+-の振り分け、正なら代入、負なら逆数にを整数に変換
  goto purasu   ;整数は、そのまま代入

;******周波数マイナスの時の処理*******
  movf x0,w   ;引き算の準備
  movwf y0   ;-は逆ビット数なので整数にする。
  movf x1,w
  movwf y1
  movf x2,w
  movwf y2
  movf x3,w
  movwf y3

  clrf x0   ;マイナスを整数に変換、notを使わず0より引く
  clrf x1
  clrf x2
  clrf x3
  call sub_xy   ;マイナスを整数へ変換のための引き算

;******バリキャップの印加時間、マイナスの時の動作時間作り*******
;*****周波数プラスの時は、電圧up********
syuuseim
  ;mov kstep[0],#250   ;普通に回すとステップが遅い  いい感じぢゃないので、中止
  ;cjb x[0],#64,stepmm   ;cja== if fr<<#lite then jmp
  ;mov kstep[0],#2   ;早くダイアル回すと早送りする
;stepmm
  bcf vdown   ;ra1-off コンデンサ電圧放電やめ、インターロック
 
  movlw d'0'   ;cje x[1],#0,jpm0   ;cje== if fr==<#lite then jmp
  subwf x1,0
  btfsc 3,2
  goto jpm0

  bsf vup   ;ra0-on コンデンサへ電圧印加

  movlw d'10'   ;mov par,#10 ;mswait 1ms=1000ループ  最大3万回
  movwf par

  call waitnms    ;
  goto jpm02
jpm0
  movlw d'32'   ;cjb x[0],#32,jpm01   ;cjb== if fr<<#lite then jmp
  subwf x0,0
  btfss 3,0
  goto jpm01

  bsf vup   ;ra0-on コンデンサへ電圧印加
  movlw d'1'   ;mov par,#1;wait 1ms=1000ループ
  movwf par

  call waitnms    ;
  goto jpm02

jpm01
  movlw d'1'   ;cjb x[0],#1,jpm02   ;20hz以内は、不感帯
  subwf x0,0
  btfss 3,0
  goto jpm02


  bsf vup   ;ra0-on コンデンサへ電圧印加
  movf x0,0   ;mov parr,x[0]   ;cへのチャージ時間に代入
  movwf parr

  call wait_nss   ;
jpm02
  bcf vup   ;ra0-off コンデンサへ電圧印加やめ
  goto dainyuu   ;変数に代入して表示する

;*****バリキャップの印加時間、周波数プラスの時の動作時間作り********
;*****周波数マイナスの時は、電圧down********
purasu
  ;mov kstep[0],#250   ;普通に回すとステップが遅い。いい感じぢゃないので、中止
  ;cjb x[0],#64,steppp   ;cjb== if fr<<#lite then jmp
  ;mov kstep[0],#2   ;早くダイアル回すと早送りする
;steppp       ;プラスの処理
  bcf vup   ;ra0-off コンデンサへ電圧印加やめ、インターロック

  movlw d'0'   ;cje x[1],#0,jpp0   ;cjb== if fr<<#lite then jmp
  subwf x1,0
  btfsc 3,2
  goto jpp0

  bsf vdown   ;ra1-on コンデンサ電圧放電へ
 
  movlw d'10'   ;mov par,#10 ;mswait 1ms=1000ループ  最大3万回
  movwf par
 
  call waitnms    ;
  goto jpp02
jpp0
           
  movlw d'32'   ;cjb x[0],#32,jpp01   ;cjb== if fr<<#lite then jmp
  subwf x0,0
  btfss 3,0
  goto jpp01

  bsf vdown   ;ra0-on コンデンサへ電圧印加

  movlw d'1'   ;mov par,#1    ;wait 1ms=1000ループ
  movwf par

  call waitnms    ;
  goto jpp02    ;
jpp01

  movlw d'1'   ;cjb x[0],#1,jpp02   ;20hz以内は、不感帯
  subwf x0,0
  btfss 3,0
  goto jpp02

  bsf vdown   ;ra1-on コンデンサ電圧放電へ

  movf x0,0   ;mov parr,x[0]   ;cへのチャージ時間に代入
  movwf parr

  call wait_nss   ;

jpp02
  bcf vdown   ;ra1-off コンデンサ電圧放電やめ

dainyuu

  movf rxfreq0,w   ;mov stfreq[0], rxfreq[0] ;070325 rit追加に依り変更
  movwf stfreq0   ;最後に受信周波数をsetする。
  movf rxfreq1,w
  movwf stfreq1
  movf rxfreq2,w
  movwf stfreq2
  movf rxfreq3,w
  movwf stfreq3
 
  movlw b'10010000'   ;mov INTCON,#10010000b ;rb0割り込みを許可する
  movwf INTCON
    
  RETURN
;*******************************
;lcdに表示する。(1行目)
;*******************************
hyouji_ue
  movlw b'00000000'   ; mov INTCON,#00000000b
  movwf INTCON

      ;rb0割り込みを許可しない。変な文字が出る為;lcd表示中に割込が入ると、表示が乱れてしまう。
      ;if周波数-発振周波数=現在(表示)周波数 2007/01/30追加)
  movf iffreq0,w   ;mov x[0], iffreq[0]  ;ifの周波数12mhz
  movwf x0
  movf iffreq1,w
  movwf x1
  movf iffreq2,w
  movwf x2
  movf iffreq3,w
  movwf x3

  movf freq0,w   ;設定周波数 vfo周波数
  movwf y0
  movf freq1,w
  movwf y1
  movf freq2,w
  movwf y2
  movf freq3,w
  movwf y3

  call sub_xy   ;xが引算結果     
  call long_to_asc   ;周波数をアスキー変換

  movlw d'0'   ;lcd_line1=0番目 ;表示位置の指定(1行目)
  call locate
  movlw 'f'   ;1桁目
  call print   ;
  movlw 'r'   ;2桁目
  call print   ;
  movlw 'e'   ;3桁目
  call print   ;
  movlw 'q'   ;4桁目
  call print   ;
  movlw ' '   ;5桁目
  call print   ;

  movf asc4,0    ;mov w, asc[4]  ;  6桁目

  call print
  movlw '.'   ; 7桁目
  call print
  movf asc5,0   ;mov w, asc[5]  ; 8桁目
  call print
  movf asc6,0   ;mov w, asc[6]  ; 9桁目
  call print;
  movf asc7,0   ;mov w, asc[7]  ; 10桁目
  call print
  movlw '.'   ;11桁目
  call print
  movf asc8,0   ;mov w, asc[8]  ; 12桁目
  call print
  movf asc9,0   ;mov w, asc[9]  ; 13桁目
  call print
  movlw 'M'   ; 14桁目
  call print
  movlw 'h'   ; 15桁目
  call print
  movlw 'z'   ; 16桁目
  call print
  movlw b'10010000'   ;mov INTCON,#10010000b ;rb0割り込みを許可する
  movwf INTCON ;rb0割り込みを許可する
      ;returnurn表示上と指示すると、下も表示させる、よってreturnurnを削除してある

;************************************************************************
;lcdに表示する。(2行目) 割込中の処理-表示中は、割り込み禁止にしたほうが、いい
;************************************************************************
hyouji_sita     ;ここは、割込中なので、問題ない。
  movlw b'00000000'   ;mov INTCON,#10010000b ;rb0割り込みを許可する
  movwf INTCON
 
  movlw d'64'   ;lcd_line2=64番目  ;表示位置の指定(2行目)
  call locate

  btfsc tx_sw   ;TX ONなら
   goto  okuri   ;送信表示

uke 
  movlw 'r'   ; 1桁目
  call print
  movlw 'e'   ; 2桁目
  call print
  movlw 'c'   ; 3桁目
  call print
  movlw ' '   ; 4桁目
  call print
  goto hyoujiff
okuri
  movlw 's'   ; 1桁目
  call print
  movlw 'n'   ; 2桁目
  call print
  movlw 'd'   ; 3桁目
  call print
  movlw ' '   ; 4桁目
  call print
hyoujiff 
  movlw 'R'   ;  5桁目
  call print
  movlw 'I'   ;  6桁目
  call print
  movlw 'T'   ;  7桁目
  call print
  movlw '='   ;  8桁目
  call print
 
  btfss rit_sw   ;rit onなら
  goto ritonnn 
ritofff
  movlw 'o'   ;9 区切りの表示
  call print
  movlw 'f'   ;10 区切りの表示
  call print
  movlw 'f'   ;11 区切りの表示
  call print
  movlw ' '   ;12 区切りの表示
  call print

  goto  mokuhyou            
ritonnn
  movlw 'o'   ;9 区切りの表示
  call print
  movlw 'n'   ;10 区切りの表示
  call print
  movlw ' '   ;11 区切りの表示
  call print
  movlw ' '   ;12 区切りの表示
  call print
mokuhyou
  movlw 's'   ;13 区切りの表示
  call print
  movlw 'p'   ;14 区切りの表示
  call print
 
  btfss stepup   ;ステップsw on次の命令スキップ
  goto stphh   ;プルアップなので逆になる
  movlw 'S'   ;15 区切りの表示 call print   ;
  call print
  goto stpll
stphh
  movlw 'F'   ;15 区切りの表示
  call print
stpll
  movlw ' '   ;16 区切りの表示
  call print

  movlw b'10010000'   ;mov INTCON,#10010000b ;rb0割り込みを許可する
  movwf INTCON   ;rb0割り込みを許可する
                        ;returnurn表示上と指示すると、下も表示させる、よってreturnurnを削除して
  RETURN
;************************************
;8ビット****************************
write_lcd8
  movlw 0f0h   ;and d8,#0f0h ;下位マスク(rb用に編集)
  andwf d8,f

  movf d8,w   ;mov rb, d8  ;Bポートに出力(2025-6-5-四角い升出た)
  movwf PORTB
    
  btfss rs   ;movb rrs, rs  ;rs 情報書込み
  bcf rrs
  btfsc rs
  bsf rrs

  nop
  bsf ee   ;Eピンを'H'(ストローブ)

  nop   ;時間かせぎ
  bcf ee   ;clrb ee  ;ストローブ終了

  ;call waitus0  ;100usecウエイト
  call waitus4   ;40usec wait

  RETURN
;************************************
;4ビットモード専用液晶ライトルーチン
;
;W で書込みデータを指定する
;************************************
print
  movwf par
 
  movf par,w   ;mov d8,par  ;上位書込み
  movwf d8

  call write_lcd8
 
  movf par,w   ;mov d8,par  ;下位書込み
  movwf d8

  swapf d8,f   ;swap d8  ;

  call write_lcd8 ;
  RETURN
;******************
;液晶初期化ルーチン
;;LCD では Rb5-Rb0 を使用します。このため、Rb5-Rb0は必ず出力に
;設定して下さい。各ピンの接続方法は以下のとおりです。
;PIC-LCD
;Rb7-D7;Rb6-D6;Rb5-D5;Rb4-D4;GND-D3;GND-D2;GND-D1;GND-D0;Rb3-E;Rb2-rs;GND-R/~W
;******************
;液晶初期化ルーチン
;******************
lcdopen
  movlw d'20'   ;14h ; mov par,#20    ; wait 15ms
  movwf par

  call waitnms
  bcf rs ;clrb rs   ;rs='L'

  movlw b'00110000'   ; 30h ;mov d8,#00110000b  ;8bit 指定
  movwf d8

  call write_lcd8;
  movlw d'10'   ; 0ah ;mov par,#10   ; wait 4.1ms
  movwf par

  call waitnms
  movlw b'00110000'    ;mov d8,#00110000b  ;8bit 指定
  movwf d8

  call write_lcd8
  call waitus0   ;wait 100μsec

  movlw b'00110000'   ;mov d8,#00110000b  ;8bit 指定
  movwf d8

  call write_lcd8   ; 0 0 0011 (3)
  movlw b'00100000'   ;mov d8,#00100000b  ;4bit 指定
  movwf d8

  call write_lcd8   ; 0 0 0010 (4bit)
  movlw b'00101000'   ;mov par,#00101000b  ;4bit/duty,font set9
  movwf par

  call print   ;
  movlw b'00000001'   ;mov par,#00000001b  ; クリアコマンド
  movwf par

  call print;
  movlw d'2'   ;mov par,#2   ; クリアが終わるまで待つ
  movwf par

  call waitnms
  movlw b'00000110'   ;mov par,#00000110b  ; entry mode set
  movwf par

  call print   ;
  movlw b'00001100'   ; mov par,#00001100b  ; display on,cursor off
  movwf par

  call print   ;

  RETURN
;********************
;LCD の表示位置の指定
;W で位置を指定
;1行目 0-
;2行目 64-
;********************
locate
  movwf par
  bsf par,7   ;setb par.7   ;LCD 固有のコマンド
  bcf rs   ;clrb rs   ;コマンド指定
  movf par,w
  call print   ;書込み
  bsf rs   ; setb rs  
;
  RETURN
;**************************************
;ロータリーエンコーダーから読込の割り込み
;**************************************
enco_in
  ;bcf INTCON,7  ;割り込み禁止

  btfss stepup   ;ステップsw on次の命令スキップ
    goto stepup1   ;プルアップなので逆になる
  movlw b'00000000'   ;ステップ40hzの場合d'4とする
  movwf kstep3
  movlw b'00000000'  
  movwf kstep2
  movlw b'00000000'
  movwf kstep1
  movlw b'00000100'   ;b'00000100'
  movwf kstep0
    goto stepup2
stepup1
  movlw b'00000000'   ;ステップ800hz d80'する
  movwf kstep3
  movlw b'00000000'  
  movwf kstep2
  movlw b'00000000'
  movwf kstep1
  movlw b'01010000'
  movwf kstep0
stepup2
 
  btfss reb   ;movb rodat.1, reb  ;B 入力
  bcf rodat,1
  btfsc reb
  bsf rodat,1

  btfss rodat,1   ;rb1が1か確認する   
 
  goto setp
setm
  call dec_freq   ;周波数を減算する
  goto setf   ;jmp setf   ;
setp
  call inc_freq   ;周波数を加算する
setf
  movlw b'00000000'   ;最後ステップ40hzに戻す
  movwf kstep3
  movlw b'00000000'  
  movwf kstep2
  movlw b'00000000'
  movwf kstep1
  movlw b'00000100'
  movwf kstep0
  ;call freq_to_osc  ;発振周波数を求める
  ;call SendFreq  ;DDS に周波数を書き込む
  nop   ;ちょっと時間稼ぎ
  ;call hyouji_sita  ;lcdに表示
  call fcont_enc   ;割り込み中でも周波数補正させる。
  nop    ;ちょっと時間稼ぎ
  ;mov INTCON,#10010000b ;rb0割り込みを許可する
  goto main   ;メインに復帰
  ;returnurnfie    ;割り込み終了
;****************
;周波数を ++ する
;****************
inc_freq
  movf stfreq0,w   ;mov x[0], stfreq[0]  ;もとの周波数
  movwf x0
  movf stfreq1,w
  movwf x1
  movf stfreq2,w
  movwf x2
  movf stfreq3,w
  movwf x3

  movf kstep0,w   ;mov y[0], kstep[0]  ;周波数の変位量
  movwf y0
  movf kstep1,w
  movwf y1
  movf kstep2,w
  movwf y2
  movf kstep3,w
  movwf y3

  call add_xy   ;x = 現在周波数+ステップ

  movf x0,w   ;mov stfreq[0], x[0]  ;結果の受け取り
  movwf stfreq0
  movf x1,w
  movwf stfreq1
  movf x2,w
  movwf stfreq2
  movf x3,w
  movwf stfreq3

  RETURN
;****************
;周波数を -- する
;****************
dec_freq
  movf stfreq0,w   ;mov x[0], stfreq[0] ;もとの周波数
  movwf x0
  movf stfreq1,w
  movwf x1
  movf stfreq2,w
  movwf x2
  movf stfreq3,w
  movwf x3

  movf kstep0,w   ;mov y[0], kstep[0] ;周波数の変位量
  movwf y0
  movf kstep1,w
  movwf y1
  movf kstep2,w
  movwf y2
  movf kstep3,w
  movwf y3

  call sub_xy   ;x = 現在周波数-ステップ
 
  movf x0,w   ;mov stfreq[0], x[0]  ;結果の受け取り
  movwf stfreq0
  movf x1,w
  movwf stfreq1
  movf x2,w
  movwf stfreq2
  movf x3,w
  movwf stfreq3

  RETURN
;***************************
;long 型式の引き算プログラム
;***************************
sub_xy
 
  movf y0,0   ;sub x[0],y[0]

  subwf x0,1
  movlw d'1'   ;1
  btfss STATUS,0   ;c キャリー

  subwf x1,1
  btfss STATUS,0   ;c キャリー
  subwf x2,1
  btfss STATUS,0   ;c キャリー

  subwf x3,1
 
  movf y1,0   ;sub x[1],y[1]

  subwf x1,1
  movlw d'1'  ;1
  btfss STATUS,0   ;c キャリー

  subwf x2,1
  btfss STATUS,0   ;c キャリー
  subwf x3,1
           
  movf y2,0   ;sub x[2],y[2]
  subwf x2,1

  movlw d'1'   ;1
  btfss STATUS,0   ;c キャリー
  subwf x3,1

  movf y3,0   ;sub x[3],y[3]
  subwf x3,1

  RETURN
;***************************
;long 型式の足し算プログラム
;***************************
add_xy
  movf y0,0   ;add x[0],y[0]
  addwf x0,1

  movlw d'1'   ;1
  btfsc STATUS,0   ;c キャリー c

  addwf x1,1

  btfsc STATUS,0   ;c キャリーc
  addwf x2,1
  btfsc STATUS,0   ;c キャリーc
  addwf x3,1

  movf y1,0   ;add x[1],y[1]
  addwf x1,1

  movlw d'1'   ;1
  btfsc STATUS,0   ;c キャリーc
  addwf x2,1
  btfsc STATUS,0   ;c キャリー c
  addwf x3,1

  movf y2,0   ;add x[2],y[2]
  addwf x2,1

  movlw d'1'   ;1
  btfsc STATUS,0   ;c キャリー c
  addwf x3,1

  movf y3,0   ;add x[3],y[3]
  addwf x3,1

  RETURN
;****************************
;long 型式の x を Asci に変換
;****************************
long_to_asc
  movlw asc_end   ; _end ;;mov fsr,#asc_end ; 格納場所初期値
  movwf FSR
  ;incf FSR,1  ;20260207追加
  call dev10   ; 最下位変換
  call dev10
  call dev10
  call dev10
  call dev10
  call dev10
  call dev10
  call dev10
  call dev10
  call dev10   ; 最上位変換
  RETURN
;***************
;/10サブルーチン
;***************
dev10
  movlw d'32'   ;mov cn,#32  ; 32ビットくり返し
  movwf cn
  clrf wrk

dev1001
  BCF STATUS,C   ;clrb c  ;キャリーリセット
  rlf x0,1
  rlf x1,1
  rlf x2,1
  rlf x3,1
  rlf wrk,1
 
  movlw 0F6h;   0F6h  ;W=-10
  addwf wrk,0   ;W=wrk-10
  btfsc STATUS,C   ;btfsc c キャリー
  movwf wrk   ;mov wrk,w
  btfsc STATUS,C   ;btfsc c キャリー
  incf x0,1
 
  decfsz cn,1   ;djnz cn,dev1001
  goto dev1001

  decf FSR,1   ;dec fsr  ;格納ポインタ
         
          ;こちらもokでした(webの参考) パクリ
  ;movf wrk,W
  ;movwf INDF   ;余り
  ;movlw h'30'   ;文字コードに変換
  ;addwf INDF,F

  movlw 0Fh   ;and wrk, #0Fh ;不要部分のマスク
  andwf wrk,1
 
  movlw 30h   ;or wrk, #30h ;アスキーコード変換
  iorwf wrk,1

  movf wrk,0   ;mov indirect,wrk ; 余り
  movwf INDF

  RETURN
;**************
;1msec ウェイト
;**************
wait1ms
  movlw d'10'   ;mov os_wrk2,#10
  movwf os_wrk2

wm_lxh2
  call waitus0

  decfsz os_wrk2,F   ;djnz os_wrk2, wm_lxh2
  goto wm_lxh2

  RETURN
;****************
;100usec ウェイト
;****************
waitus0
  movlw d'164'   ;ffh ;mov os_wrk1,#wait_10us =a4h=164
  movwf os_wrk1
wu_lxh
  decfsz os_wrk1,F   ;djnz os_wrk1,wu_lxh
  goto wu_lxh

  RETURN
;****************
;40usec ウェイト
;****************
waitus4
  movlw d'64'   ;mov os_wrk1,#wait_4us  ;=040h =64
  movwf os_wrk1
wu_lxh4
 decfsz os_wrk1,F   ;djnz os_wrk1,wu_lxh4
 goto wu_lxh4

  RETURN
;***********************
;n msec ウェイト
;n は par にセットします
;***********************
waitnms
  call wait1ms
  decfsz par,F   ;djnz par, waitnms
  goto waitnms

  RETURN
;****************
;2乗タイマ ウェイト
;****************
wait_nss

  movlw d'0'   ;cjb parr,#0,jmpwait1 ;誤動作防止マイナス計算される。
  subwf parr,0
  btfss STATUS,0   ;btfss 3,0
  goto jmpwait1
 
  movf parr,0   ;mov waitnss2,parr
  movwf waitnss2
 
wait_nss2

  movf parr,0   ;mov waitnss1,parr
  movwf waitnss1

wait_nss1
  
  decfsz waitnss1,1   ;djnz waitnss1,wait_nss1
  goto wait_nss1
 
  decfsz waitnss2,1   ;djnz waitnss2,wait_nss2;
  goto wait_nss2

jmpwait1

  RETURN

   END