cwbufkey2 の製作
自作工程のメモとして
2006.Aug.06
(インターフェース インタフェイス インターフェイス インタフェース)
1.RS-232Cインターフェース |
各社から、色々なUSBインターフェースが出ていますが、使用できるソフトに制約の大きいUSBとCWインターフェースが一緒になったものや、RS232Cの信号レベルから再度ICの電圧に変換するタイプのものをよく見かけますが、ここではより簡単に実現できるストロベリーリナックス社のFT232RXを使用することにしました。
以前にCI−Vのインターフェースを同社の別キットを使って組み立てましたが、それより簡単に実現できそうです。
その時気づか無かったのが残念ですが、色々やることも楽しみの一つとして、割り切ることも必要かもしれません。購入したFT232RX USBシリアルインターフェース
その他のパーツも、改めてそろえました。
2.ケース加工 |
前回は、アイデアの実装だけでしたから簡単に作ってしまいましたが、今回は実用品としてパネルデザインから先に決めて穴あけ加工を進めました。
例によって、パワーポイントでパネルイメージを作り、パウチで仕上げます。
今回は、次のようなイメージにしました。(対象ケースは、タカチ YM−100)<--パワーポイント2000で作ったファイルにリンクします。
上面のフロントイメージでは、左のSW位置のみは決めていますが、5mmの穴は、広げていません。
位置決め後、カッターナイフでそれなりの大きさに広げます。
また、下のリアイメージのUSBコネクタ穴(四角)は、ほぼ正確ですが、このイメージによって穴を開けるより、次のように実物あわせが必要だと思います。次はケースへの実装の様子ですが、タカチのケース「YM−100」の隅に位置決めをしています。
この四角の穴が全ての基準になります。
基板の下には、5mmのスペーサで浮かせて四角の穴の位置を決めます。
フロントパネルの ON と Speed の間にLEDを入れるつもりで、予定しています。
LEDを取り付けてみました。
後ろから見た加工状況です。ここまで何度もやり直していますので、ほどほどの位置に収まっています。
3.配線組み立て |
配線は、前作と同様に回路図は無くて実態配線図から作り始めました。
今度は手作りではなく、エクセルで升目を作り、それとなく部品のイメージをのせていき、ある程度こじんまりまとめることが出来ました。CW出力は、フォトカプラで(LED側を5mA)駆動していますが、出力側の必要能力を、IC−7000Mで実測してみると、開放時:約3.3V、ショート時:0.26mAの電流が流れます。
入力側の駆動電流が大きすぎますが、LED側の定格電流から見ると半分程度だと思います。上側の中央から右にLED駆動回路を組んでいますが、PICの3ピンからジャンパー(ミドリ線)を持ってくるか、+3Vラインから常時通電(桃色線)とするかを選択できるようにしています。
このPICの3ピンは、次項で出てきますが、スピーカー駆動の信号を取り出す用途に使うことも考えており、汎用性を持たせたつもりです。2011/01/03:パドルのプルアップ抵抗を100Kから10Kに変更。
電池ケースは、ふた(底になる)の片側に寄せて、下から3φの皿ネジで取り付けます。
電池の寿命について
製作後の最初の電池交換は、2009年10月12日となりました。(交換前の旧電池電圧:1.44V)
アルカリ電池が3年ちょっと持ったことになります。
その間の交信は60局ほどしか有りませんが、SWを入れっぱなしにして数日放置したことが何度もあります。
また、空振りの呼び出しも多々ありました。
CW入力は、プラス駆動(DTRとアース)ならびにマイナス駆動(+3.3VとDTR)が選択できるようにしており、次の画像ではFT232RX基板側の配線はマイナス駆動にしています。
当初はプラス駆動で結線していましたが、USBケーブルをつないで、PCのロギングソフトを駆動していない状態のとき、CW入力が「有り」状態が続くため、マイナス駆動にして、次のCW送出設定も変更しています。【Ctestwin の場合】
上記のマイナス駆動にすると、CtestwinのCW送出設定画面で、【CW Outoput Positive】[A] を選択す必要があります。
また、入力速度を40WPMで設計しているため、CTESTWINからのCW送出速度(CW Speed部分)は40WPMに設定する必要があります。
(20091018:画像を入換えて追記)
4.追加機能 |
あまり代わり映えはしませんが、前作にPICの3ピンを使って、サイドトーンを駆動させるプログラムと、その端子をそのままパイロットランプ(LED)に応用するときの、電源が入っている事が分かるフラッシュプログラムも組み込みました。
そのうちの、サイドトーン波形を示します。(次の2画面は、ドット・ダッシュの比率を測っています。)
周波数は、602.9Hzになりました。
Logレンジで周波数成分を見ると、高調波がそのまま出ています。
こちらはHALPSKの画面で見た画像です。600Hzの次は1800Hzが出ています。
5.ソースファイル |
追加機能として、スピーカー駆動をさせるプログラムと、その端子をそのままパイロットランプ(LED)に応用するときの、電源が入っている事が分かるフラッシュプログラムも組み込みました。
(エディタ上でTAB間隔を8文字に設定し直しましたが、これでもコメント等の位置がずれています。)--------------------------------------------------------------------
; ;PICマイコンによる、CWバッファ付キーヤープログラム ;cwbufkey ; ;製作過程の掲載は、 http://jlb.jp/jlb/jisaku/cwbufkey2/ ; ;V1.00:2006/06/25:(C)JE3JLB (最下部へコード埋め込みあり) ; 2006/07/02:ソースファイルのコメント記述を整理した。 ; :8文字TABに変更した。 ;V1.01:2006/07/29:ダッシュの先頭から約1/3間は、パドルのドットを記憶しない。 ; ;V2.00:2006/07/18:GP4 にスピーカ出力を付加した。 ; 2011/01/03:パドルのプルアップ抵抗を100Kから10Kに変更。 ; ; ; ; ;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├────┴────(パドル:ドット) ; │ │ │ │ ; SP出力 <─────┤3 6├──────┴──(パドル:ダッシュ) ; (R)100K │ │ 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 出力 スピーカ出力(タイマ1使用、600Hz) ;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 ; ; ;◆その他メモ ;数値の初期値は16進のため、10進数は必ず D'15' とする。 ; ; ;---------------------------------------------------------------- ;#define MODE_TM1SP ;■◆■ タイマ1によるスピーカモード。 ;■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆■◆ ; LIST P=12F629 INCLUDE P12F629.INC ERRORLEVEL -205 ;アセンブル時に 205( ifdef )警告を出さない。 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'0200' ;IDロケーションへ、バージョン2.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'11110000' ;割込みの設定。(バンク0・1共通) ;bit7 GIE 割込みを使用する=1 ;bit6 PIE1 レジスタの割込みを使うので=1(TM1) ;bit5 タイマ0オーバーフロー割込みを使うので=1 ;bit4 INTピン入力エッジ割込みを使うので=1 ;bit3 GPIO入力変化割込みを使わないので=0 ;bit2 T0IF タイマ0オーバーフロー時=1となる。 ;bit1 ◆◆GP2/INTピン入力信号のエッジがあったときだけ=1 ;bit0 GPIOポートで入力データが変化したときだけ=1 ;---------------------------------------------------------------- DEF_PIE1_REG equ B'00000001' ;(バンク1) ;bit7 データEPROM使わない=0 ;bit6 AD変換割込みを使わない=0 ;bit5 無し ;bit4 無し ;bit3 コンパレータ割込みを使わない=0 ;bit2 無し ;bit1 無し ;bit0 ◆タイマ1オーバフロー割込みを使う=1 ; ;---------------------------------------------------------------- DEF_PIR1_REG equ B'00000000' ;(バンク0) ;bit7 データEPROMの書き込み終了フラグ=1 ;bit6 AD変換割込み終了フラグ=1 ;bit5 無し ;bit4 無し ;bit3 コンパレータ出力変化で=1 ;bit2 無し ;bit1 無し ;bit0 TMR1IF タイマ1オーバフローしたとき=1 ; (プログラムでクリヤ) ;このレジスタの初期セット以外は、 ;◆bit0 のみ bcf PIR1,TMR1IF でクリヤする。 ;---------------------------------------------------------------- DEF_T1CON equ B'00000001' ;(バンク0) ;bit7 無し ;bit6 外部信号でタイマ1を止めない=0 ;bit5 プリスケーラ設定=使わない。 ;bit4 プリスケーラ設定=使わない。 ;bit3 タイマ1用に発信回路を使わない=0 ;bit2 外部クロック同期設定=X ;bit1 タイマ1の入力クロックに命令クロックを使う=0 ;bit0 ◆タイマ1スタートさせるので=1★ ;---------------------------------------------------------------- DEF_TM1_STH equ D'252' ;CW送出中のスピーカ音を設定する。★ DEF_TM1_STL equ D'216' ;INT処理の中で設定する。★ ; 250=624Hz 200=586 220=602Hz 216=600Hz ; ;MSB側 DEF_TM1_STH 251 250 249 ; ;LSB側 DEF_TM1_STL 45 123 140 ; ; ; ;---------------------------------------------------------------- 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送出速度に関係する。) ; ;LED_FLASH のタイミング用 sleepの手前で使用する。 FLASH_ON equ D'250' FLASH_OFF equ D'251' ; ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆電源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 INT_EDG_END ;それ以外なら、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_E ;オーバーフローではないので終了。 incf CCC256,F ;上位のカウンタ +1 movlw DEF_CCC movwf CCC ;◆タイミングカウンタ下位を初期セット INT_EDG_E: ;----------------------------◆◆ここまで割込み処理を書く bcf INTCON,INTF ;INTF 入力エッジ割込みフラグを、 ;プログラムでクリヤして復帰する。 INT_EDG_END: ; goto ISR_INT_END ;◆有っても動作に関係ないが、 ; ;INT入力エッジ割込みの確認後に、 ; ;次のタイマ割込みをチェックするために ; ;コメント扱いとする。 TM0_INT: ;タイマ0の割込み処理 btfss INTCON,T0IF ;タイマ0割込みか? goto TM0_INT_END ;それ以外なら、タイマ0の終了へ行く。 ; ;----------------------------◆◆ここから割込み処理を書く incf CW_CLK,F ;CW入力信号の読み込みカウンタを+1する ;----------------------------◆◆ここまで割込み処理を書く bcf INTCON,T0IF ;タイマ0の割込みフラグをクリヤ TM0_INT_END: goto TM1_INT ;駄目押し的なジャンプ TM1_INT: ;タイマ1の割込み処理 btfss PIR1,TMR1IF ;タイマ1 割込みか? goto TM1_INT_END ;それ以外なら、タイマ1の終了へ行く。 ; ;---------------------------- ◆◆ここに割込み処理を書く btfsc GPIO_OUT,LED_BIT ;CW信号送出中では無い? goto TM1_INT1 bcf T1CON,TMR1ON ;◆タイマ1を止める。★ bcf GPIO_OUT,ST_BIT ;スピーカ出力をLowにする。 goto TM1_INT3 ;トグル動作せずに終了。 TM1_INT1: ;トグル動作処理開始 call TM1_RESTART ;タイマ1を再起動★ ; btfss GPIO_OUT,ST_BIT ;このトグル動作で周波数を発生させる。 goto TM1_INT2 ; ; bcf GPIO_OUT,ST_BIT ; goto TM1_INT3 ; ; TM1_INT2: ; bsf GPIO_OUT,ST_BIT ; ; ; ;トグル動作処理終了 TM1_INT3: movf GPIO_OUT,W ;下の命令とペアでポートへ出力 movwf GPIO bcf PIR1,TMR1IF ;タイマ1の割込みフラグをクリヤ ; goto TM1_INT_END ;駄目押し的なジャンプ TM1_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 へ行く。 ; ;★★★★ LED_FLASH ; ;SP出力をLED点灯に使っているときは、 ; ;電源ON状態を示すフラッシュ動作をさせる。 FLASH: movlw FLASH_ON ;フラッシュONの単位時間を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタから単位時間を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,Z ;Z=1 で、時間が経過した。 goto FLASH2 bsf GPIO_OUT,ST_BIT ;スピーカ出力端子を High にする。 call IOPORT ;ポート出力。 goto FLASH3 FLASH2: movlw FLASH_OFF ;フラッシュONの単位時間を W へ呼び出す。 subwf CCC256,W ;CCC256カウンタから単位時間 を引く。 ; ;結果を W レジスタに入れる。 btfss STATUS,Z ;Z=1 で、時間が経過した。 goto FLASH3 bcf GPIO_OUT,ST_BIT ;スピーカ出力を Low にする。 call IOPORT ;ポート出力。 FLASH3: ; ;待機時の電流(速度設定により変動) 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_PIE1_REG ;タイマ1関連(バンク1) movwf PIE1 movlw DEF_OP_REG ;割込みのオプションレジスタ初期値 movwf OPTION_REG ;INTピン入力信号の ; ;立下りエッジ割込み設定、(bank1) ; clrf ANSEL ;GPIOポートをデジタルI/Oモードにする。 ; ;12F675 のみの設定。 movlw GPIO_MODE ;先頭の equ 定義 B'00001011' movwf TRISIO ;GP2 は出力指定。 bcf STATUS,RP0 ;■■バンク 0 にする。 movlw DEF_PIR1_REG ;タイマ1関連(バンク0) movwf PIR1 movlw DEF_T1CON ;タイマ1関連(バンク0) movwf T1CON ;------------------------------------------------------------------- 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 ;------------------------------------------------------------------- ;/////////////////////////////////////////////////////////////////// ; ◆◆◆ここより下は、サブルーチンを記述する。◆◆◆ ;/////////////////////////////////////////////////////////////////// ;------------------------------------------------------------------- ; ;割込みタイミング用のカウンタクリヤ 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 call TM1_RESTART ;タイマ1を起動★ goto IOPORT ;--------------------------------------- CW_OFF: ;Key出力 OFF bcf GPIO_OUT,LED_BIT goto IOPORT ;--------------------------------------- IOPORT: ;データ出力 movf GPIO_OUT,W ;GPIOに出力データを書く。 movwf GPIO return ;------------------------------------------------------------------- TM1_RESTART: ;タイマ1のスタートおよび再スタート★ ;上記 CW_ON と割り込み処理で使用する。 ; CW_ON で起動して、割込み処理の中で ;トグル動作とストップをする。 bcf T1CON,TMR1ON ;◆タイマ1を止める。 movlw DEF_TM1_STH ;MSB側用の初期値を再設定(プリセット) movwf TMR1H ;MSB 側へ書き込み。 movlw DEF_TM1_STL ;LSB側用の初期値を再設定(プリセット) movwf TMR1L ;LSB 側へ書き込み。 bsf T1CON,TMR1ON ;◆タイマ1を動かす。 ;◆タイマ1のストップは割り込み処理の中で、 ;GPIO_OUT,LED_BIT の状態を確認し実施する。★ 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','2','.','0','0' data '(','C',')','2','0','0','6',' ','J','E','3','J','L','B' ;------------------------------------------------------------------- ; org 3FFH ;念のため用意している、 ; dw 3468H ;チップ固有のキャリブレDATA。 end------------------------------------------------------------------------
ソースファイル cwbufkey2.asm (2006/08/06) (プルアップ抵抗変更のため差し替えました。2011/01/03)
Hexファイル cwbufkey2.hex (2006/08/06) (誤添付のためファイルを差し替えました。2006/08/20)