cwbufkey の製作
自作工程のメモとして
2006.Jul.29
よく、パソコン(以下、PC)でコンテストログソフトを動かしてCWを運用するインターフェースが紹介されていますが、送出速度の設定はPC上で実行する タイプがほとんどで、パドルが使えない、パドルとPCからの送出速度が違う、等々の制約があります。
次のアイデアは、そのソフト毎の制約をPICマイコンで吸収してやり、パドルの速度調節(ボリューム)で全ての速度をコントロールできる、CW- BUFFER-Key( cwbufkey )という物で、PCからのCW速度を一定にしておけば、記憶して順次指定速度で送り出すことが可能としています。
続編 cwbufkey2 を掲載しました。(2006/08/06)
2019年9月:処分しました。
1.なぜ cwbufkey か |
今まで作ってきたエレキーも、自作のログソフト(MS−DOS)からRS232C経由で送られてきた文字を受け、Z80やPIC等のMPUで処理してい ました。
現在は、そのような処理をするログソフトも少なく(国内では見当たりません)、操作感の好みもあることから、自作のログソフトを使わなくなってからは、旧 作のエレキーはほとんど使っていませんでした。
また、6年ほど移動運用にも行っていませんし、記念局を時々呼ぶぐらいのアクティビティでした。
旧作のエレキー 今回、PICの命令を覚えているうちに、同じようなものを実現してみようと考えてみました。
よく考えると、PC側のソフトからCW信号は共通して送出されていますので、その信号を処理して速度調節を手元で調節できるもとしています。
2.動作の概要 cwbufkey |
全体のイメージをつかんでいただくために動作は、WMVファイルにして動画再生で示しま す。(音声は出ません)
左にあるUSBIF4CWのKey−LED (一番右側)の点滅速度で送り出されたCW信号を、右側の cwbufkey で受け取り、cwbufkey の設定速度(必ず入力速度より遅くする)で再出力しています。
この再出力速度は、パドル( cwbufkey 側に接続中)を操作したときの速度と同じになります。
<===ページ内で表示するよう変更しました(2013/05/19)
Windows Media Player Firefox Plugin のインストールは、こ ちらを参照しました。TKS(2015/04/26)以下のPC側のソフトでCQを送出しました。
3.入力信号の確認 |
PC上の簡易オシロで見たCW入力波形です。
信号が遅いため、High・Lowを保持できずゼロ点へ回帰していますが、符号比率等は確認できます。
30WPMの速度ですから、ドット(ON部のみ)が約40mS、文字間が約120mSあり、当たり前ですが計算どおりとなっています。
送出したCW信号のPC上の画面
4.ケースへの実装 |
実験だけでは、アイデアだけとなりますので、実装(インプリメンテーション、implementation)してみました。
簡単な回路なので、プリンタで穴あき基板のイメージを作り、ボールペンと鉛筆で部品の配線を書いていきます。
CW信号の出力は、フォトカプラのダイオードを、直接ポートからのHigh信号で駆動し、トランシーバ側とは、絶縁処理しました。
フォトカプラのダイオード側に、直列に入れた抵抗は300オームで、5mA程度を流すことになります。実際の配線は若干違いますが、何回か書き直すうちにまとまってきます。
小PCBに組み上げて、配線をした様子が次のようになります。
昔から、PCB上での接続は、丸ピンのICソケット(1列もの)を切って使い、ソケットとプラグに使っています。
Z80を使ったエレキーの頃から使っていますが、トラブルは有りません。
また、ボリュームは当初50KΩで実験していましたが、20KΩで充分な速度範囲が確保できました。消費電流は、ソースファイル中にも記しましたが、待機時は1mA以下で、動作時はフォトカプラを駆動する関係で実測 5.05mAとなります。
ケースはタカチのSW−85を使いました。その外観、裏面からと
前面からです。
次の構想があるため簡単に作って、IC−7000Mにつないで実験してみましたが、回り込み等は起きていないようです。
この cwbufkey で使ってみたいソフトは、次のCTESTWINで、私の好みに合いそうで期待しています。
5.ソースファイル |
先月に掲載したソースファイルに、追記した形になり若干の相違があるかも 知れませんが、タイマ0を使ってCW入力をサンプリングし、リングバッファに取り込んで、指定速度で送り出しています。
また、今までのエレキー(Z80、16F84、16C73B使 用)と同様に、リングバッファのクリヤは、パドル操作で行うようにしています。特に旧作は、1文字を1バイトとしてバッファで記憶していましたが、今回は符号(ダッシュ・ドット・文字間・スペース)を2ビットに置換えて記憶してい ます。
PARISコードで記憶効率を試算してみますと、文字記憶で6バイト、符号記憶で40ビット(5バイト)となり、記憶効率は悪くは無いようです。
1語=(PARIS+スペース)なお、入力速度(PC側からの出力速度)への許容範囲は有る程度ありますので、汎用性は高いと考えます。
(エディタ上でTAB間隔を8文字に設定し直しましたが、これでもコメント等の位置がずれています。)
--------------------------------------------------------------------
; ;PICマイコンによる、CWバッファ付キーヤープログラム ;cwbufkey ; ;製作過程の掲載は、 http://jlb.jp/jlb/jisaku/cwbufkey/ ; ;V1.00:2006/06/25:(C)JE3JLB (最下部へコード埋め込みあり) ; 2006/07/02:ソースファイルのコメント記述を整理した。 ; :8文字TABに変更した。 ;V1.01:2006/07/29:ダッシュの先頭から約1/3間は、パドルのドットを記憶しない。 ; ; ; ; ;CWコードの定数を確認 ;PARISコードの1ワード(W)は、14+8+10+6+8+(4)=50ドット ;1分間に 5W( 25文字)送出するには、 250ドット/分 ; (4.2dot/Sec 240ms/dot)短点連続周波数= 2.1Hz ;1分間に10W( 50文字)送出するには、 500ドット/分 ; (8.3dot/Sec 120ms/dot)短点連続周波数= 4.2Hz ;1分間に20W(100文字)送出するには、1,000ドット/分 ; (16.7dot/Sec 60ms/dot)短点連続周波数= 8.3Hz ;1分間に30W(150文字)送出するには、1,500ドット/分 ; (25.0dot/Sec 40ms/dot)短点連続周波数=12.5Hz ;1分間に40W(200文字)送出するには、2,000ドット/分 ; (33.3dot/Sec 30ms/dot)短点連続周波数=16.7Hz ; ; ;---------------------------------------------------------------- ;◆回路構成の概略(全半角等幅文字) ; ; ; PIC 12F629 3V 3V ; 3V 3V ┌──V──┐ │ │ ; │ │ │ │ 10K│ │10K ; │ └─┤1 8├─┐ (R) (R) ; │ │ │ E │ │ ; CW出力 <─────┤2 7├────┴────(パドル:ドット) ; │ │ │ │ ; 100K│ NC:<-┤3 6├──────┴──(パドル:ダッシュ) ; (R) │ │ 10K ; CW入力 >─┴───┤4 5├───┬──(R)-┐ ; │ │ (C) (VR) 50K ; └─────┘ │103 │ ; E E ; ; Eはアース、NC:は未接続。 ; ;GP0=1 入力 パドル ドット ;GP1=1 入力 パドル ダッシュ ;GP2=1 出力 初期は出力で、1を出力指定しておく。 ; 外部のボリュームを読み込む時は、瞬間入力に設定して ; 放電時間経過後のLowエッジ割込みを待つ。 ;GP3=1 入力 CW信号入力ポート(Lowアクティブ) ;GP4=0 出力 未使用 ;GP5=0 出力 キー出力(ハイアクティブ) ;---------------------------------------------------------------- ;◆動作について ;SQUEEZE Key 二枚羽のパドルを持つキーヤー の、 ;アイアンビック mode B の動作になるとは思いますが、明確には不明です。 ; ;◆CW Bufferの動作概要 ;パソコン(以下:PC)から送り出される一定速度のCW信号を、 ;それ以下の速度に減速して送り出す。(ボリューム調整) ;(例) ;1.ezkey 等で、速度を30W(150文字)に設定する。(要調整) ;2.PCからのCW出力を、cwbufkey のCW入力へ入れる。 ;3.rig へのCW出力は、cwbufkey のCW出力を使用する。 ;4.その結果、PCからのCW出力もパドルからの送出速度と一緒になる。 ;5.送出待ちの符号群がバッファに残っている時にパドルを操作すると、 ; その時点でバッファをクリヤする。 ;6.入力速度を 30WPM で設定しているが、20 〜 40WPM 程度の許容あり。 ; ;---------------------------------------------------------------- ;◆参考書籍 ;中尾真治氏著 オーム社 (平成17年3月20日 第1版) ;おもしろいPICマイコン −PIC12F675 を使いこなす− ; ;固有定数のメモ:3474 ;固有定数のメモ:3468 ; ; ;---------------------------------------------------------------- ;■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆ ; LIST P=12F629 INCLUDE P12F629.INC ERRORLEVEL -302 ;アセンブル時に 302(バンク切替え)警告を出さない。 INDF equ H'0000' ;間接読出し・書込み時の仮想レジスター FSR equ H'0004' ;間接データメモリ・ポインタ CB = _CPD_OFF ;データEEPROMもプログラム・メモリも CB &= _CP_OFF ;コード・プロテクトしない。 CB &= _BODEN_ON ;ブラウンアウト・リセットを使う。 CB &= _MCLRE_OFF ;MCLRリセットを使わない。 CB &= _PWRTE_ON ;パワーアップ・タイマを使う。 CB &= _WDT_OFF ;ウォッチドッグ・タイマを使わない。 CB &= _INTRC_OSC_NOCLKOUT ;内部発振器を使う。 __CONFIG CB __IDLOCS H'0101' ;IDロケーションへ、バージョン1.00 CBLOCK H'20' GPIO_OUT ;GPIOポートの出力データ W_TEMP ;割込み処理用 S_TEMP ;割込み処理用 CCC ;カウンタ CCC256 ;カウンタ上位 PAD_MEMO ;パドルの状態をメモしておく(Hi アクティブ) ; ;bit1 1=ダッシュ が押された。 ; ;bit0 1=ドット が押された。 RUN_MEMO ;実行中の状態をメモ(Hi アクティブ) ;bit5 1=スペース信号 (CWバッファで使用) ;bit4 1=文字間信号 (CWバッファで使用) ;bit3 1=ダッシュ信号 0=ダッシュ後の間隔(1ドット分) ;bit2 1=ドット信号 0=ドット後の間隔(1ドット分) ;bit1 1=ダッシュ送出中 ;bit0 1=ドット送出中 ; ; DM_GPIO ;★★★ debug ★★★ ;MPLAB SIM(debugger)使用時に、入力ポートの代替とする。 ;-----------------------;◆ここから CW-buffer用 CB_BIT_INPOS ;CWバッファのビット単位格納の入力位置 CB_BYT_INPOS ;CWバッファのバイト単位格納の入力位置 CB_BIT_OTPOS ;CWバッファのビット単位格納の出力位置 CB_BYT_OTPOS ;CWバッファのバイト単位格納の出力位置 CB_CW_CNT ;CW信号入力数のカウント CB_TMP ;CWバッファの入出力TMP ; ;■bit 1.0 を使用する。■ ; ;(11=ダッシュ符号、10=ドット符号、 ; ; 01=文字間、00=スペース) CW_CLK ;CW信号を2mSのインターバルで ; ;確認した回数をカウント CW_IN_STA ;CW符号の入力状態を表す。 ; ;■bit 2〜0 を使用する。■ ; ; 101=CW信号有り、110=CW信号が途切れた状態、 ; ; 100=符号間を確認済み状態 ; ; (後は、文字間とスペースの判断のみ残る) CW_BUFF ;CW符号を格納するバッファ ; ;この位置から最終番地まで使う。(0x5f) ;-----------------------;◆ここまで CW-buffer用 ENDC ;----------------------- ;CW-buffer用 CB_POS_ST equ CW_BUFF ;バッファのスタートアドレス CB_POS_END equ H'5F' ;バッファのエンドアドレス(0x5f) ;----------------------- ; ;---------------------------------------------------------------- DEF_OP_REG equ B'10000010' ;割込みのオプションレジスタ ;bit7 ウィーク・プルアップ使わない=1 ;bit6 INTピン立下りエッジを使うので=0 ;bit5 タイマ0の入力を命令クロック使う=0 ;bit4 タイマ0の外部クロック時の設定 X ;bit3 プリスケーラをタイマ0で使う=0 ;bit2 bit 2〜0 でプリスケーラの分周比を設定する。 ; bit-> 2 1 0 ;bit1 0 1 0 =1:8 ;bit0 256uS X 8 = 2.048mS ; ;タイマ0の動作イメージ ; ←2.048mS→ 毎の割込み ; │ │ ; ┌──┐ ┌──┐ ┌──┐ ┌─ ; │ │ │ │ │ │ │ ; ┘ └──┘ └──┘ └──┘ ; ;■■実測周波数=491Hz 2.037mS ; ;---------------------------------------------------------------- GPIO_MODE equ B'00001011' ; ;GP0-1.3 をインプット ; ;GP2.4-5 をアウトプットに設定する。 ;---------------------------------------------------------------- DEF_INTCON equ B'10110000' ;割込みの設定。 ;bit7 GIE 割込みを使用する=1 ;bit6 PIE1 レジスタの割込みを使わないので=0 ;bit5 タイマ0オーバーフロー割込みを使うので=1 ;bit4 INTピン入力エッジ割込みを使うので=1 ;bit3 ◆◆GPIO入力変化割込みを使わないので=0 ;bit2 タイマ0オーバーフロー時=1となる。 ;bit1 GP2/INTピン入力信号のエッジがあったときだけ=1 ;bit0 ◆◆GPIOポートで入力データが変化したときだけ=1 ; ;---------------------------------------------------------------- PAD_DOT equ O'0' ;パドル:ドットのビット位置。 PAD_DAS equ O'1' ;パドル:ダッシュのビット位置。 CR_BIT equ O'2' ;外部でボリュームをつけている端子 CW_BIT equ O'3' ;CW信号入力(バッファで使用) ST_BIT equ O'4' ;ボリュームにHを出力して、 ; ;その後Lowにする。(使用せず) LED_BIT equ O'5' ;LEDのビット DOT_STA equ O'2' ;ドット ステータス DAS_STA equ O'3' ;ダッシュ ステータス ; ;次の二つはCWバッファで使用し、 ; ;RUN_MEMO の位置を示す。 BIT_MJK equ O'4' ;文字間 BIT_SPC equ O'5' ;スペース ; ;---------------------------------------------------------------- ; ;■■CW信号送出タイミングに使用■■ ; TIME_1 equ D'20' ;@ドットの長さと符号間(基準:変えない) TIME_2 equ D'36' ;A文字間の長さ(好みにより調整) TIME_3 equ D'60' ;Bダッシュの長さ(ドット×3倍) ; ;(例)1:3.4 にするなら、20 X 3.4 = 68を ; ; 記述する。 TIME_4 equ D'72' ;C文字間後のスペース長(好みにより調整) ; │@│@│<A>│<− C −>│ ; ┌─┐ ┌─┐ ┌─────┐ ; │ │ │ │<−− スペース −−−>│ │ ; ┘ └─┘ └─────────────┘ └─ ; ; │<符号単位−>│<A>│@│ │<−B−>│ ; ┌─────┐ ┌─┐ ┌─────┐ ; │ │<文字間>│ │ │ │ ; ┘ └─────┘ └─┘ └── ; >│ │< ; 符号間 ;---------------------------------------------------------------- ; ;■■CW信号入力タイミングに使用(CW−Buffer)■■ ;30WPMの入力をサンプリングするときの理論値は1単位 20 ;補正値: 40mS / 2.037mS = 19.6回 ; ;40WPMの入力をサンプリングするときの理論値は1単位 15 ;補正値: 30mS / 2.037mS = 14.7回 IN_CLK equ D'15' ;1単位当りのサンプリング回数 ; CLK_1 equ D'20' ;20カウント(未使用) CLK_2 equ IN_CLK * 2 ;A2単位ダッシュとドットの判定 ; ;符号間と、文字間の判定に使用する。(2ヶ所) CLK_3 equ IN_CLK * 3 ;B文字間とスペースの判定(2ヶ所) CLK_4 equ D'80' ;80カウント(未使用) ; ; ; │ │ Bここでスペースと判断 ; ┌─┐ ┌─┐ │<文字間>│ ┌─────┐ ; │ │ │ │ │ 判定 │ │ │ ; ┘ └─┘ └─────────────┘ └─ ; │<−スペース:単位7 −>│ ; │ ; ┌─────┐ ┌─┐ ┌─┐ ┌─────┐ ; │ │ │ │ │ │ │ │ │ ; ┘ │ └─────┘ └─┘ └── ; │ │ ; ドット<−A−> │ ; ダッシュ │ ; │ ; 符号間<−A−>文字間以上 ; ;---------------------------------------------------------------- DEF_CCC equ D'240' ;タイミングカウンタ下位の初期値 ; ;(CW送出速度に関係する。) ; ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆電源ON時のスタート◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- org 0 ;電源onスタート goto START_DEF ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆割込み発生時の処理◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- org 4 ;割込み発生時の処理 movwf W_TEMP ;以下の4行は割込み処理前の定型処理。 movf STATUS,W ; clrf STATUS ; movwf S_TEMP ; ; ISR_INT: btfss INTCON,INTF ;INT入力エッジ割込みか? goto TM0_INT ;それ以外なら、Timer0 割込みの確認へ行く。 ; bsf STATUS,RP0 ;■バンク 1 にする。 bcf TRISIO,CR_BIT ;GP2ビットを出力に戻す。 ; ;(High=コンデンサへ充電) bcf STATUS,RP0 ;■バンク 0 にする。 ;----------------------------充電のための時間稼ぎ(実質不要) nop nop ;----------------------------割込み発生の再スタート処理 bsf STATUS,RP0 ;■バンク 1 にする。 bsf TRISIO,CR_BIT ;GP2ビットを一時的に入力にする。 bcf STATUS,RP0 ;■バンク 0 にする。 ;----------------------------◆◆ここから割込み処理を書く incfsz CCC,F ;CCC +1 オーバーフローか?:スキップ goto INT_EDG_END ;オーバーフローではないので終了。 incf CCC256,F ;上位のカウンタ +1 movlw DEF_CCC movwf CCC ;◆タイミングカウンタ下位を初期セット INT_EDG_END: ;----------------------------◆◆ここまで割込み処理を書く bcf INTCON,INTF ;INTF 入力エッジ割込みフラグを、 ;プログラムでクリヤして復帰する。 ; goto ISR_INT_END ;◆有っても動作に関係ないが、 ; ;INT入力エッジ割込みの確認後に、 ; ;次のタイマ割込みをチェックするために ; ;コメント扱いとする。 TM0_INT: ;タイマ0の割込み処理 btfss INTCON,T0IF ;Timer 0 割込みか? goto ISR_INT_END ;それ以外なら、終了へ行く。 ; ;----------------------------◆◆ここから割込み処理を書く incf CW_CLK,F ;CW入力信号の読み込みカウンタを+1する ;----------------------------◆◆ここまで割込み処理を書く bcf INTCON,T0IF ;Timer0 の割込みフラグをクリヤ goto ISR_INT_END ;駄目押し的なジャンプ ISR_INT_END: movf S_TEMP,W ;以下の4行は割込み復帰の定型処理。 movwf STATUS ; swapf W_TEMP,F ; swapf W_TEMP,W ; retfie ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆以下は、電源ON後に1回だけ通過する。◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- ; MAIN_LOOP0: bcf INTCON,INTF ;INT入力エッジ割込みフラグをクリヤ ;------------------------------- ;INT入力エッジ割込み発生のスタート処理 bsf STATUS,RP0 ;■バンク 1 にする。 bsf TRISIO,CR_BIT ;GP2ビットを一時的に入力にする。 bcf STATUS,RP0 ;■バンク 0 にする。 ;---------------------------------------------------------------- ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆メインルーチンの先頭◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- MAIN_LOOP: ;-------------------------- パドル入力の確認 PAD_CHECK0: btfsc RUN_MEMO,PAD_DOT ;ドット送出中以外ならドットを確認 goto PAD_CHECK1 ;ダッシュチェックへ btfsc GPIO,PAD_DOT ;ドット側が押されたか? goto PAD_CHECK1 ;ダッシュチェックへ call TM0_CLR ;◆パドルが押されたときは、 ;CWバッファーを全クリヤする。 bsf PAD_MEMO,PAD_DOT ;パドルメモへドットをセット PAD_CHECK1: btfsc RUN_MEMO,PAD_DAS ;ダッシュ送出中以外ならダッシュを確認 goto PAD_CHECK_E ;パドル確認終了へ btfsc GPIO,PAD_DAS ;ダッシュ側が押されたか? goto PAD_CHECK_E call TM0_CLR ;◆パドルが押されたときは、 ; ;CWバッファーを全クリヤする。 bsf PAD_MEMO,PAD_DAS ;パドルメモへドットをセット PAD_CHECK_E: goto RUN_CHECK0 ;あえて記述した。(処理に影響なし) ;---------------------------------------------------------------- ;------------------------------- 実行中の処理を確認 RUN_CHECK0: btfss RUN_MEMO,PAD_DOT ;ドット送出中か? goto RUN_CHECK1 ;次のチェックへ goto RUN_DOT_0 ;ドット送出処理へ行く。 RUN_CHECK1: btfss RUN_MEMO,PAD_DAS ;ダッシュ送出中か? goto RUN_CHECK_E ;次のチェックへ goto RUN_DAS_0 ;ダッシュ送出処理へ RUN_CHECK_E: btfss RUN_MEMO,BIT_MJK ;◆文字間送出中か? goto RUN_CHECK_E1 ;次のチェックへ goto RUN_MJK_0 ;文字間送出処理へ行く。 RUN_CHECK_E1: ; btfss RUN_MEMO,BIT_SPC ;◆スペース送出中か? goto RUN_CHECK_EE ;次のチェックへ goto RUN_SPC_0 ;スペース送出処理へ行く。 RUN_CHECK_EE: call MEMO_DOT_CHECK ;サブルーチンでドット押下を確認 call MEMO_DAS_CHECK ;サブルーチンでダッシュ押下を確認 ;---------------------------------------------------------------- ;CW Buffer用 ; ;◆◆◆◆CW入力があるか? movf CB_CW_CNT,F ;ゼロか判定(内容に影響しない) btfss STATUS,Z ;入力文字数がゼロならスキップ call CB_CHECK ;CWバッファをチェックに行く goto PAD_LOOP_E ;◆◆パドル処理の最終位置へ ; ;---------------------------------------------------------------- RUN_DOT_0: ;ドット送出処理 btfss RUN_MEMO,DOT_STA ;信号部分か判定する。 goto RUN_DOT_1 movlw TIME_1 ;単位時間1を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_1(ドット時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_DOT_E ;◆RUN_DOT 最終処理へ call CNT_CLR ;タイミングカウンタクリヤ(初期化) call CW_OFF ;信号送出を止める。 bcf RUN_MEMO,DOT_STA ;状態を信号送出後の間隔時間にする。 goto RUN_DOT_E ;RUN_DOT 最終処理へ RUN_DOT_1: movlw TIME_1 ;単位時間1を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_1(ドット時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_DOT_E ;◆RUN_DOT 最終処理へ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bcf RUN_MEMO,PAD_DOT ;ドット送出の終了 bcf PAD_MEMO,PAD_DOT ;パドルのドットメモをクリヤ ; bcf PAD_MEMO,PAD_DAS ;◆これを有効にすると、アイアンビックの ; ; mode A になるはず。(もう一箇所有り) ; call MEMO_DAS_CHECK ;ドット処理直後は、 ; ;ダッシュの状態を優先確認する。 ; ;(アイアンピック動作) RUN_DOT_E: goto PAD_LOOP_E ;◆◆パドル処理の最終位置へ ;---------------------------------------------------------------- ;------------------------- RUN_DAS_0: ;ダッシュ送出処理 btfss RUN_MEMO,DAS_STA ;信号部分か判定する。 goto RUN_DAS_1 ; ;---------------------------------- movlw TIME_1 ;単位時間 1 を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_1(ドット時間相当)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 bcf PAD_MEMO,PAD_DOT ;パドルのドットメモをクリヤ ;◆◆◆ダッシュの先頭から約1/3間は、 ;パドルのドットを記憶しない。 ; ;---------------------------------- movlw TIME_3 ;単位時間3を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_3(ダッシュ時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_DAS_E ;◆RUN_DAS 最終処理へ call CNT_CLR ;タイミングカウンタクリヤ(初期化) call CW_OFF ;信号送出を止める。 bcf RUN_MEMO,DAS_STA ;状態を信号送出後の間隔時間にする。 goto RUN_DAS_E ;◆RUN_DAS 最終処理へ RUN_DAS_1: movlw TIME_1 ;単位時間1を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_1(ドット時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_DAS_E ;◆RUN_DAS 最終処理へ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bcf RUN_MEMO,PAD_DAS ;ダッシュ送出の終了 bcf PAD_MEMO,PAD_DAS ;パドルのダッシュメモをクリヤ ; bcf PAD_MEMO,PAD_DOT ;◆これを有効にすると、アイアンビックの ; ; mode A になるはず。(もう一箇所有り) call MEMO_DOT_CHECK ;ダッシュ処理直後は、 ; ;ドットの状態を優先確認する。 ; ;(アイアンピック動作) RUN_DAS_E: goto PAD_LOOP_E ;◆◆パドル処理の最終位置へ ;---------------------------------------------------------------- ;------------------------- RUN_MJK_0: ;文字間送出処理 movlw TIME_2 ;単位時間 2を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_2(文字間時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_MJK_E call CNT_CLR ;タイミングカウンタクリヤ(初期化) clrf RUN_MEMO RUN_MJK_E: goto PAD_LOOP_E ;◆◆パドル処理の最終位置へ ;------------------------- RUN_SPC_0: ;スペース送出処理 movlw TIME_4 ;単位時間 4を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタからTIME_4(スペース時間)を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,C ;C=1 で、時間が経過した。 goto RUN_SPC_E call CNT_CLR ;タイミングカウンタクリヤ(初期化) clrf RUN_MEMO RUN_SPC_E: goto PAD_LOOP_E ;あえて記述した。(処理に影響なし) PAD_LOOP_E: ;◆◆パドル処理の最終位置◆◆ goto CB_LOOP ;あえて記述した。(処理に影響なし) ;---------------------------------------------------------------- ; ;ここからCW入力のチェックをする。 ; ; ■CW_IN_STAの状態■ ; ; 0= 初期値、 ; ; 1=CW信号有り、2=CW信号が途切れた状態(文字間待ち)、 ; ; 3=文字間を確認中、4=スペース確認中 ;----------------------------------------------------------------- CB_LOOP: movf CW_IN_STA,F ;状態がゼロかを確認 btfss STATUS,Z ;ゼロか? goto CB_LOOP1 ;入力が有る状態を処理中 goto btfsc GPIO,CW_BIT ;ポートにCW信号有る状態か? goto CB_LOOP_E ;信号無し... CB_LOOP_0R5: ;◆途中から信号があったときの処理位置。 movlw 1 ; 1 を movwf CW_IN_STA ;状態へセット clrf CW_CLK ;2mSインターバルをクリヤ goto CB_LOOP_E ;LOOP の最後へ。 ;--------------------------------------- CB_LOOP1: movf CW_IN_STA,W ;状態を呼び出し sublw D'1' ; 1=CW信号有り btfss STATUS,Z ; goto CB_LOOP2 btfss GPIO,CW_BIT ;ポートにCW信号無い状態か? goto CB_LOOP_E ;ポートにCW信号有れば LOOP の最後へ。 ; ;信号が途切れたときに、以下の処理をする。 movlw 2 ;2 を movwf CW_IN_STA ;状態へセット movf CW_CLK,W ;インターバルカウンタ読み出し。 sublw CLK_2 ;ドットとダッシュの間を判定する。 ; ;40 - CW_CLK = マイナス時は、C = 0 btfsc STATUS,C ;ダッシュか? ( C bitは負論理) goto CB_DOT_SET ;ドットをセットする。 goto CB_DAS_SET ;ダッシュをセット ;--------------------------------------- CB_LOOP2: movf CW_IN_STA,W ;状態を呼び出し sublw D'2' ; 2=CW信号が途切れた状態(文字間待ち) btfss STATUS,Z ; goto CB_LOOP3 btfss GPIO,CW_BIT ;ポートにCW信号無ければスキップ goto CB_LOOP_0R5 ;◆次の符号処理のため先頭付近から再スタート movf CW_CLK,W ;インターバルカウンタ読み出し。 sublw CLK_2 ;符号間と文字間の間を判定する。 ; ;40 - CW_CLK = マイナス時は、C = 0 btfsc STATUS,C ;文字間か? ( C bitは負論理) goto CB_LOOP_E ;符号間の扱い(何もしない) movlw 3 ;3 を(文字間) movwf CW_IN_STA ;状態へセット goto CB_MJK_SET ;文字間をセット ;--------------------------------------- CB_LOOP3: movf CW_IN_STA,W ;状態を呼び出し sublw D'3' ; 3=文字間を確認中 btfss STATUS,Z ; goto CB_LOOP_E btfss GPIO,CW_BIT ;ポートにCW信号無ければスキップ goto CB_LOOP_0R5 ;◆次の符号処理のため先頭付近から再スタート movf CW_CLK,W ;インターバルカウンタ読み出し。 sublw CLK_3 ;文字間とスペースの間を判定する。 ; ;60 - CW_CLK = マイナス時は、C = 0 btfsc STATUS,C ;スペースか? ( C bitは負論理) goto CB_LOOP_E ;文字間の扱い(何もしない) clrf CW_IN_STA ;状態をクリヤ goto CB_SPC_SET ;スペースセット ;--------------------------------------- CB_LOOP3_A: ;タイマオーバーか? movf CW_CLK,W ;インターバルカウンタ読み出し。 sublw CLK_3 ;文字間とスペースの間を判定する。 ; ;60 - CW_CLK = マイナス時は、C = 0 btfsc STATUS,C ;スペースか? ( C bitは負論理) goto CB_LOOP_E ;文字間の扱い(何もしない) clrf CW_IN_STA ;◆状態をクリヤ goto CB_SPC_SET ;スペースセット ;---------------------------------------------------------------- CB_DAS_SET: ;CW_Buffer にダッシュをセット movlw B'00000011' ;dash goto CB_ALL_SET ;◆符号セットの共通処理へ。 ;--------------------------------------- CB_DOT_SET: ;CW_Buffer にドットをセット movlw B'00000010' ;dot goto CB_ALL_SET ;◆符号セットの共通処理へ。 ;--------------------------------------- CB_SPC_SET: ;CW_Buffer にスペースをセット movlw B'00000000' ;スペース goto CB_ALL_SET ;◆符号セットの共通処理へ。 ;--------------------------------------- CB_MJK_SET: ;CW_Buffer に文字間をセット movlw B'00000001' ;文字間 goto CB_ALL_SET ;◆符号セットの共通処理へ。 ;--------------------------------------- CB_ALL_SET: ;◆符号セットの共通処理 clrf CW_CLK ;2mSインターバルをクリヤ movwf CB_TMP ;テンポラリに置いて call PUT_BUF ;バッファへ格納 goto CB_LOOP_E ;LOOP の最後へ。 ;---------------------------------------------------------------- CB_LOOP_E: nop MAIN_LOOP_E: ; ;◆命令クロックをタイマ入力にすると、 ; ;sleep 中はカウントアップしない。 ; ;そのためCWバッファの確認をして、 ; ;sleep モードへ入る。 ; ;sleep 中は、CRによるINT割込みで再起動する。 ; ;(数mS〜約10mS間隔) btfss GPIO,CW_BIT ;ポートにCW信号無い状態か? goto MAIN_LOOP_ESS ;◆(CW信号有り)SleepSkip へ行く。 movf CW_IN_STA,F ;状態がゼロか?を確認 btfss STATUS,Z ;ゼロならスキップ goto MAIN_LOOP_ESS ;◆(バッファ動作中)SleepSkip へ行く。 movf CB_CW_CNT,F ;CW信号入力数のゼロ確認 btfss STATUS,Z ;ゼロならスキップ goto MAIN_LOOP_ESS ;◆(バッファに処理待ちの符号有り)SleepSkip へ行く。 movf RUN_MEMO,F ;CW信号の送出処理中 btfss STATUS,Z ;ゼロならスキップ goto MAIN_LOOP_ESS ;◆(送出処理中)SleepSkip へ行く。 ; ;待機時の電流(速度設定により変動) sleep ;sleep挿入で 0.20mA 〜0.64mA ; ;sleep挿入しないと 0.62mA 〜0.76mA nop ;sleep のおまじない。 MAIN_LOOP_ESS: ;◆SleepSkip の位置。 goto MAIN_LOOP ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆初期設定◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- START_DEF: ;---------------------------; bcf STATUS,RP0 ;■バンク 0 にする。 call H'3FF' ;内部発振器をキャリブレーションする。 bsf STATUS,RP0 ;■バンク 1 にする。 movwf OSCCAL bcf STATUS,RP0 ;■バンク 0 にする。 movlw B'00000111' ;コンパレーターoffにする movwf CMCON clrwdt ;WDTをクリヤする。(PSAビット関連) bsf STATUS,RP0 ;■バンク 1 にする。 clrf WPU ;ウィーク・プルアップの各ビット設定無し。 movlw DEF_OP_REG ;割込みのオプションレジスタ初期値 movwf OPTION_REG ;INTピン入力信号の ; ;立下りエッジ割込み設定、(bank1) ; ;タイマ0の設定、プリスケーラの設定。 ; clrf ANSEL ;GPIOポートをデジタルI/Oモードにする。 ; ;12F675 のみの設定。 movlw GPIO_MODE ;先頭の equ 定義 B'00001011' ;GP2 は出力指定。 movwf TRISIO bcf STATUS,RP0 ;■バンク 0 にする。 ;------------------------------------------------------------------- movlw B'00000100' ;GP2 だけはHighを出力指定。Sleep時に注意。 movwf GPIO_OUT ;GPIO_OUTの内容を初期化する (レジスター上のポート) call IOPORT ;初期値を出力ポートに書き込み(必須) ;------------------------------------------------------------------- ; call CNT_CLR ;タイミングカウンタクリヤ(初期化) call TM0_CLR ;タイマ0関連のクリヤ clrf RUN_MEMO ;送出中信号メモをクリヤ clrf PAD_MEMO ;パドルの状態をクリヤ movlw DEF_INTCON ;割込みのセット movwf INTCON goto MAIN_LOOP0 ;ここに MAIN_LOOP0 部の記述を書いても良いが、 ; ;初期化の一部をメインループの中で回せるようにする ; ;プログラム記述上の癖から、このようにした。 ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆ここより下は、サブルーチンを記述する。◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- ; ;割込みタイミング用のカウンタクリヤ CNT_CLR: movlw DEF_CCC ;設定値があるためサブルーチンで定義する。 ;(他にもう一箇所あり) movwf CCC ;タイミングカウンタを初期セット clrf CCC256 ;タイミングカウンタ上位を初期セット return ;------------------------------------------------------------------- TM0_CLR: ;CWバッファ機能で使用する。 movlw CB_POS_ST ;◆◆◆ スタートアドレスをセット movwf CB_BYT_INPOS ;バイトの入力位置 movwf CB_BYT_OTPOS ;バイトの出力位置 movwf FSR ;相対アドレス指示 clrf INDF ;CWバッファの先頭をクリヤ clrf CB_BIT_INPOS ;ビットの入力位置 clrf CB_BIT_OTPOS ;ビットの出力位置 clrf CB_CW_CNT ;バッファに入ったCW符号数 clrf CB_TMP ;符号入出力のテンポラリ clrf CW_IN_STA ;CW符号の入力状態 clrf CW_CLK ;割込みで使うカウンタ return ;------------------------------------------------------------------- ;---------------------------------------;■ 何も実行中で無い時に実行する。■ ; ;パドルメモの確認 MEMO_DOT_CHECK: btfss PAD_MEMO,PAD_DOT ;ドットが押されているか? goto MEMO_DOT_CHECK_E call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,DOT_STA ;状態ビットの信号部分処理中にセット call CW_ON ;CW信号ON bsf RUN_MEMO,PAD_DOT ;ドット処理中をセット bcf PAD_MEMO,PAD_DOT ;ドットが押されていたメモをクリヤ MEMO_DOT_CHECK_E: return ;-------------------------------- MEMO_DAS_CHECK: btfss PAD_MEMO,PAD_DAS ;ダッシュが押されているか? goto MEMO_DAS_CHECK_E call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,DAS_STA ;状態ビットの信号部分処理中にセット call CW_ON ;CW信号ON bsf RUN_MEMO,PAD_DAS ;ダッシュ処理中をセット bcf PAD_MEMO,PAD_DAS ;ダッシュが押されていたメモをクリヤ MEMO_DAS_CHECK_E: return ;------------------------------------------------------------------- ;---------------------------------------;■ 何も実行中で無い時に実行する。■ ; (11=ダッシュ符号、10=ドット符号、01=文字間、00=スペース) ; ;CWバッファーチェック CB_CHECK: ;CWバッファーチェック movf CB_CW_CNT,F ;ゼロか判定(内容に影響しない) btfsc STATUS,Z ;入力文字数がゼロ以上なら goto CB_CHECK_E ;そのままリターンする。goto call GET_BUF ;◆◆◆◆◆ movf CB_TMP,F ;00判定 btfss STATUS,Z ; goto CB_CHECK_2 ;次のチェックへ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,BIT_SPC ;スペース処理中にセット goto CB_CHECK_E ;--------------------------------------- CB_CHECK_2 movf CB_TMP,W ; sublw D'1' ;CB_TMP から 1 を引いて(スキップ) btfss STATUS,Z ;ゼロなら?(スキップ) goto CB_CHECK_3 ;次のチェックへ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,BIT_MJK ;文字間処理中にセット goto CB_CHECK_E ;--------------------------------------- CB_CHECK_3 movf CB_TMP,W ; sublw D'2' ;CB_TMP から 2 を引いて(スキップ) btfss STATUS,Z ;ゼロなら?(スキップ) goto CB_CHECK_4 ;次のチェックへ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,DOT_STA ;状態ビットの信号部分処理中にセット call CW_ON ;CW信号ON bsf RUN_MEMO,PAD_DOT ;ドット処理中をセット ;--------------------------------------- CB_CHECK_4 movf CB_TMP,W ; sublw D'3' ;CB_TMP から 3 を引いて(スキップ) btfss STATUS,Z ;ゼロなら?(スキップ) goto CB_CHECK_E ;次のチェックへ call CNT_CLR ;タイミングカウンタクリヤ(初期化) bsf RUN_MEMO,DAS_STA ;状態ビットの信号部分処理中にセット call CW_ON ;CW信号ON bsf RUN_MEMO,PAD_DAS ;ダッシュ処理中をセット CB_CHECK_E: return ;------------------------------------------------------------------- CW_ON: ;Key出力 ON bsf GPIO_OUT,LED_BIT goto IOPORT ;--------------------------------------- CW_OFF: ;Key出力 OFF bcf GPIO_OUT,LED_BIT goto IOPORT ;--------------------------------------- IOPORT: ;データ出力 movf GPIO_OUT,W ;GPIOに出力データを書く。 movwf GPIO return ;------------------------------------------------------------------- ; ; ◆入力符号は CB_TMP に格納して、このルーチンを呼び出す。 ; CB_TMP は、最下位側の2ビットに符号を格納する。 ; ■11=ダッシュ符号、10=ドット符号、01=文字間、00=スペース■ ; ; ◆最初の呼び出し時はbuffer先頭部の内容が、未確定なので、 ; 起動後のレジクリヤで消す。 ; ◆CB_BIT_INPOS の初期値は、0とする。 ; ◆CB_BIT_INPOS は、3〜0 の値を持って、3はMSB側の2ビットとし、 ; 0は、LSB側の2ビットへ格納する。 ; ; bit-> 76│54│32│10 ; POS-> 3│2│1│0 ; ; ◆処理の最後に、入力符号数を加算する。 ; ; (メインループの動きを分かりやすくするためにサブルーチン化した。) ;--------------------------------------- PUT_BUF: movf CB_BIT_INPOS,F ;ビット位置を呼び出し ; ;ゼロかを判定 btfss STATUS,Z ;同数ならスキップ goto PUT_BUF_1 ; movf CB_TMP,W ; andlw B'00000011' ;最下位2ビット movwf CB_TMP ; goto PUT_BUF_E ;復帰処理へ ;--------------------------------------- PUT_BUF_1: movf CB_BIT_INPOS,W ;ビット位置を呼び出し sublw 1 ;位置 1 か btfss STATUS,Z ;同数ならスキップ goto PUT_BUF_2 ; rlf CB_TMP,F ;2回 左へ rlf CB_TMP,F ; movf CB_TMP,W andlw B'00001100' ;下位2ビット movwf CB_TMP ; goto PUT_BUF_E ;復帰処理へ ;--------------------------------------- PUT_BUF_2: movf CB_BIT_INPOS,W ;ビット位置を呼び出し sublw 2 ;位置 2 か btfss STATUS,Z ;同数ならスキップ goto PUT_BUF_3 ; rlf CB_TMP,F ;4回 左へ rlf CB_TMP,F ; rlf CB_TMP,F ; rlf CB_TMP,F ; movf CB_TMP,W andlw B'00110000' ;上位側2ビット movwf CB_TMP ; goto PUT_BUF_E ;復帰処理へ ;--------------------------------------- PUT_BUF_3: movf CB_BIT_INPOS,W ;ビット位置を呼び出し sublw 3 ;位置 3 か btfss STATUS,Z ;同数ならスキップ goto PUT_BUF_4 ; rlf CB_TMP,F ;6回 左へ rlf CB_TMP,F ; rlf CB_TMP,F ; rlf CB_TMP,F ; rlf CB_TMP,F ; rlf CB_TMP,F ; movf CB_TMP,W andlw B'11000000' ;最上位2ビット movwf CB_TMP ; goto PUT_BUF_E ;復帰処理へ ;--------------------------------------- PUT_BUF_4: ;◆◆この位置に飛び込んでくることは、 ; ;発生しないはず。(不正処理) call TM0_CLR ;タイマ0クリヤへ行って、 goto PUT_BUF_END ;初期化後、最初から格納する。 ; ;(はき捨て) ;--------------------------------------- PUT_BUF_E: movf CB_BYT_INPOS,W movwf FSR ;間接アドレスセット movf CB_TMP,W ;位置あわせをしたデータを呼び出し。 iorwf INDF,F ;DATA 相対アドレス へOR格納する。 incf CB_BIT_INPOS,F ;位置を+1 movf CB_BIT_INPOS,W ;ビット位置を呼び出し sublw 4 ;位置がオーバーフローか btfss STATUS,Z ;4だったならスキップ goto PUT_BUF_E2 ;4以内なのでバイト位置はそのまま clrf CB_BIT_INPOS ;ビット位置をゼロに incf CB_BYT_INPOS,F ;バイト位置を+1 movlw CB_POS_END ;レジスタのエンド位置を呼び出し subwf CB_BYT_INPOS,W ;入力(格納)のアドレスが btfss STATUS,Z ;最終アドレスを超えていないか? goto PUT_BUF_E1 ;超えていない。GOTO movlw CB_POS_ST ;超えたので、 movwf CB_BYT_INPOS ;スタートアドレスをセット PUT_BUF_E1: movf CB_BYT_INPOS,W ;バイト位置を呼び出し movwf FSR ;間接アドレスセット clrf INDF ;次の格納位置をクリヤする。 PUT_BUF_E2: incf CB_CW_CNT,F ;入力符号を加算 PUT_BUF_END: return ;------------------------------------------------------------------- ; ; ◆出力符号は、このルーチンを呼び出し CB_TMP に格納して取り出す。 ; CB_TMP は、最下位側の2ビットに符号を格納する。 ; ■11=ダッシュ符号、10=ドット符号、01=文字間、00=スペース■ ; ; ◆CB_BIT_OTPOS の初期値は、0とする。 ; ◆CB_BIT_OTPOS は、3〜0 の値を持って、3はMSB側の2ビットとし、 ; 0は、LSB側の2ビットへ格納する。 ; ; bit-> 76│54│32│10 ; POS-> 3│2│1│0 ; ; ◆処理の最後に、入力符号数を減算する。 ; ; (メインループの動きを分かりやすくするためにサブルーチン化した。) ;--------------------------------------- ; GET_BUF: movf CB_BYT_OTPOS,W ;バイト位置をセット movwf FSR ;間接アドレスセット movf INDF,W ;間接呼び出し。 movwf CB_TMP ;符号(複数)を一時格納 movf CB_BIT_OTPOS,F ;ビット位置を呼び出し ; ;位置 0 か btfss STATUS,Z ;同数ならスキップ goto GET_BUF_1 ; movf CB_TMP,W ;符号(複数)を呼び出し andlw B'00000011' ;下位2ビット指定 movwf CB_TMP ;引渡し位置(LSB)にセット goto GET_BUF_E ;復帰処理へ ;--------------------------------------- GET_BUF_1: movf CB_BIT_OTPOS,W ;ビット位置を呼び出し sublw 1 ;位置 1 か btfss STATUS,Z ;同数ならスキップ goto GET_BUF_2 ; rrf CB_TMP,F ; 2回 右へ rrf CB_TMP,F ; movf CB_TMP,W andlw B'00000011' ;下位2ビット指定 movwf CB_TMP ;引渡し位置(LSB)にセット goto GET_BUF_E ;復帰処理へ ;--------------------------------------- GET_BUF_2: movf CB_BIT_OTPOS,W ;ビット位置を呼び出し sublw 2 ;位置 2 か btfss STATUS,Z ;同数ならスキップ goto GET_BUF_3 ; rrf CB_TMP,F ; 4回 右へ rrf CB_TMP,F ; rrf CB_TMP,F ; rrf CB_TMP,F ; movf CB_TMP,W andlw B'00000011' ;下位2ビット指定 movwf CB_TMP ;引渡し位置(LSB)にセット goto GET_BUF_E ;復帰処理へ ;--------------------------------------- GET_BUF_3: movf CB_BIT_OTPOS,W ;ビット位置を呼び出し sublw 3 ;位置 3 か btfss STATUS,Z ;同数ならスキップ goto GET_BUF_4 ; rrf CB_TMP,F ; 6回 右へ rrf CB_TMP,F ; rrf CB_TMP,F ; rrf CB_TMP,F ; rrf CB_TMP,F ; rrf CB_TMP,F ; movf CB_TMP,W andlw B'00000011' ;下位2ビット指定 movwf CB_TMP ;引渡し位置(LSB)にセット goto GET_BUF_E ;復帰処理へ ;--------------------------------------- GET_BUF_4: ;◆◆この位置に飛び込んでくることは、 ; ;発生しないはず。(不正処理) call TM0_CLR ;タイマ0クリヤへ行って、 goto GET_BUF_END ;初期化後、最初から処理する。 ; ;(はき捨て) ;--------------------------------------- GET_BUF_E: incf CB_BIT_OTPOS,F ;位置を+1 movf CB_BIT_OTPOS,W ;ビット位置を呼び出し sublw 4 ;位置がオーバーフローか btfss STATUS,Z ;4だったならスキップ goto GET_BUF_E1 ;4以内なのでバイト位置はそのまま clrf CB_BIT_OTPOS ;ビット位置をゼロに incf CB_BYT_OTPOS,F ;バイト位置を+1 movlw CB_POS_END ;レジスタのエンド位置を呼び出し subwf CB_BYT_OTPOS,W ;入力(格納)のアドレスが btfss STATUS,Z ;最終アドレスを超えていないか? goto GET_BUF_E1 ;超えていない。GOTO movlw CB_POS_ST ;超えたので、 movwf CB_BYT_OTPOS ;スタートアドレスをセット ;--------------------------------------- GET_BUF_E1: decf CB_CW_CNT,F ;◆入力文字数を減算 GET_BUF_END: return ;------------------------------------------------------------------- data 'c','w','b','u','f','f','k','e','y',':' data 'V','1','.','0','1' data '(','C',')','2','0','0','6',' ','J','E','3','J','L','B' ;------------------------------------------------------------------- ; org 3FFH ;念のため用意している、 ; dw 3468H ;チップ固有のキャリブレDATA。 end------------------------------------------------------------------------
ソースファイル cwbufkey.asm (2006/07/29)
Hexファイル cwbufkey.hex (2006/07/29)