Top Page cwbufkey2 の製作
自作工程のメモとして
2006.Aug.06


 ひとつ前の掲載で次の構想と書きましたが、CW信号を取り込む方法は直接の接続をする方法以外に、今流行のUSBインターフェースを介すればもっと簡単に接続できることが容易に想像できます。
また、色々なCWインターフェースがありますが、RS−232C接続のログソフトがあれば、固有のログソフトに制限されることなく自由なCW運用ができるということになります。そのようなことから、続編の cwbufkey2 を紹介いたします。

(インターフェース インタフェイス インターフェイス インタフェース)

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に変更。

エクセルファイルへのリンク(LZH)

 

電池ケースは、ふた(底になる)の片側に寄せて、下から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)