;※ 本ソースは4桁タブ、固定幅フォント、120桁で見やすくなるようコーディングしています。
;************************************
; シフトスイッチコントローラ Ver2.0A
;************************************
;
;【機能概要】
;
; ステアリングSW（オーディオ、クルーズ）のボタンに予め設定（プリセット※）した機能
;（シフトアップ・ダウン、マニュアル・ドライブ変更など）を割当、ステアリングシフト
; を実現するプログラム。
; ※プリセットは７個、各プリセットの内容は変更可
;
;【変更履歴】
;
; 2008. 9.15 Ver1.0		-00 新規作成
; 2008.10.10 Ver2.0		-00 プリセット機能追加
; 2008.10.30 Ver2.0A	-01 プリセット番号初期値修正(06 -> 01)
;						-02 ソースをテキストエディタ向けに修正
;						-03 プリセット番号１の割当変更。
;							・Vol-,Vol+にマニュアル＋シフト操作、
;							・MUTEにドライブ・マニュアル切替を割当
;						-04 プリセット番号２の割当修正。
;							・Cancelにドライブ・マニュアル切替を割当
;
;【詳細情報】
;
; １．PIC12F683の各ピンの割当
;
; ピン		機能
;------------------------------------------------------------
; 1 	Vdd P 	+5V電源
; 2 	GP5 O 	シフトアップSW用リレーへ接続(HでSW-ON)
; 3 	GP4 O 	シフトダウンSW用リレーへ接続(HでSW-ON)
; 4 	GP3 I 	マニュアル検出線へ接続（マニュアルモード検出でH）
; 5 	GP2 O 	マニュアルSW用リレーへ接続(HでSW-ON)
; 6 	GP1 I 	オートクルーズコントロールSWへ接続 (A/D変換使用)
; 7 	GP0 I 	オーディオSWへ接続 (A/D変換使用)
; 8 	Vss P 	GND
;
; ２．状態一覧
;
;	起動						：起動直後から下記モード直前までの状態
;	設定モード					：プリセット番号を選択できる状態
;	プリセット内容変更モード	：プリセット内容変更できる状態
;	運転モード					：ボタンによりマニュアル操作ができる状態
;
; ３．本ソースで使用する記号(またはID)と名称
;
; (1) ギヤボックス周辺
;
; 記号    名称            説明
; ------------------------------------------------------------------------------------------
; UpSW    シフトアップSW   シフトギヤボックス内のシフトアップ操作時にONとなるスイッチ
; DwnSW   シフトダウンSW   シフトギヤボックス内のシフトダウン操作時にONとなるスイッチ
; ManuSW  マニュアルSW     シフトギヤボックス内のマニュアルシフトモード時にONとなるスイッチ
; ManuL   マニュアル検出線 マニュアルシフトモードに入ったことを検出する線
; LgtL    シフト用ライト   シフト表面のレンジを照らすライトの＋12V側の線
; GNDL    ＧＮＤ           サイドブレーキ根元の車体アース
; LED     マニュアル用LED  シフトアップ・ダウンの"+"・"-"表示を照らすLED
;
; (2) ステアリングスイッチ関連
;
;    +----------- 運転モード用ボタン番号
;    |   +------- 設定用ボタン番号。1:Aボタン 2:Bボタン 0:押していない
;    |   |   +--- SW別ボタン番号。オーディオSW、クルーズSW毎にユニーク
;    |   |   |
; 	ID1	ID2	ID3	略名		説明（左側：オーディオSW、右側：クルーズSW）
; ------------------------------------------------------------------------------------------
; 	 0	 0	 6	-		左側または右側を(何も押していない)
; 	 1	 1	 0	Vol-		左側"－"が印字されているボリュームダウンボタン
; 	 2	 2	 1	Vol+		左側"＋"が印字されているボリュームアップボタン
; 	 5	 0	 2	▲		左側"▲"が印字されているチャンネルアップボタン
; 	 6	 0	 3	▼		左側"▼"が印字されているチャンネルダウンボタン
; 	 7	 0	 4	MODE		左側"MODE"が印字されているモードボタン
; 	 8	 0	 5	MUTE		左側 スピーカーに×が印字されている消音ボタン
; 	 3	 2	 1	SET		右側"SET/COAST"が印字されている減速ボタン
; 	 4	 1	 0	RES		右側"RES/ACCEL"が印字されている加速ボタン
; 	 9	 0	 3	OnF		右側"CANCEL"が印字されているキャンセルボタン
; 	10	 0	 2	CAN		右側"ON OFF"が印字されているクルーズON/OFFボタン
;
;  左側(オーディオ)	右側(クルーズ)
;  +----+ +----+		+----+ +----+
;  | ＋ | | ▲ |		|On  | |RES |
;  |    | | ▼ |		|Off | |ACCEL
;  |Vol | +----+		+----+ |    |
;  |    | |Mode|		|Can | |SET |
;  | － | |Mule|	 	| cel| |COAST
;  +----+ +----+		+----+ +----+
;
; (3)その他信号線
;
; 記号	名称				位置
; ------------------------------------------------------------------------------------------
; ACCL	アクセサリ電源	オーディオコネクタ
; CSWL	クルーズSW線	右側ステアリング根元の赤/白の線
; ASWL	オーディオSW線	オーディオコネクタのKEY2の線

; ４．ラベルの規約
;
; xxxx		ルーチン名
; xxxx_Ln	ループラベル。n...外側のループから昇順の整数（ルーチン内の通番）
; xxxx_Jn	ジャンプラベル。n...整数（ルーチン内の通番）
; xxxx_PC	プログラムカウンタジャンプ先頭ラベル
; xxxx_TBL	テーブル
; fxxxx		ファイルレジスタ
; bxxxx		ビット名
;
; ５．仕様
;
; [起動時]
;
; ・起動時にボリュームアップボタンを１秒以上押し続けると、設定モードへ遷移する。
; ・起動直後はLEDを少しずつ明るくし、運転モードへ遷移する。
; 　ただし、マニュアルモードになった場合は、即、運転モードへ遷移する。
;
; [設定モード]
;
; ・設定モードとなった直後は、LED消灯し、ボタンが押されなくなるのを待つ。
; ・プリセット番号を３ビットでLEDを点滅(1が長い点滅、0が短い点滅)で出力する。
; 　この出力の間、ボタンを同時に監視し、以下の処理を行う。
; 　ただし、マニュアルモードを検出した場合、即、運転モードへ遷移する。
; ・Aボタン(Vol-またはRES)クリックでプリセット番号を１つ進める
; ・Aボタン長押しで選択しているプリセット番号のプリセット内容変更モードへ遷移する。
; ・Bボタン(Vol+またはSET)クリックでプリセット番号は変更せず、運転モードへ遷移する。
; ・Bボタン長押しで選択しているプリセット番号をROMへ書き込み、運転モードへ遷移する。
;
; [プリセット内容変更モード]
;
; ・プリセット内容変更モードとなった直後は、LED消灯し、ボタンが押されなくなるのを待つ。
; ・ボタン番号を４ビットでLEDを点滅(1が長い点滅、0が短い点滅)で出力し、少し置いて、
; 　機能番号を４ビットでLEDを点滅して出力する。
; 　この出力の間、ボタンを同時に監視し、以下の処理を行う。
; 　ただし、マニュアルモードを検出した場合、即、運転モードへ遷移する。
; ・Aボタン(Vol-またはRES)クリックでボタン番号を１つ進める
; ・Aボタン長押しで設定モードへ戻る。
; ・Bボタン(Vol+またはSET)クリックで機能番号を１つ進め、ROMへ書き込む。
; ・Bボタン長押しで選択しているプリセット番号の全ボタン設定をデフォルトに戻し、ROMへ書き込む。
;
; [運転モード]
;
; ・押されたボタン番号に対応する処理番号をROMより読み出し、各処理へ遷移する。
; 　（詳細は本ソース最下部の「ステアリングボタン～機能ID割当テーブル」参照）
;

;==========
; 各種宣言
;==========

;--------------
; 基本仕様定義
;--------------

	LIST		P=PIC12F683 	; 使用するPICをPIC12F683とする
	INCLUDE	"P12F683.inc"		; PIC12F683のヘッダ定義ファイル
	__CONFIG _IESO_OFF &  _BOD_ON & _CPD_OFF & _CP_OFF & _MCLRE_OFF &  _PWRTE_ON & _WDT_OFF  & _INTOSCIO 
					; _IESO_OFF		: 内部・外部切り替えモード無効
					; _BOD_ON		: 電源電圧低下リセットを有効にする
					; _CPD_OFF		: データメモリープロテクトしない
					; _CP_OFF		: コードプロテクトしない
					; _MCLRE_OFF	: 4番ピンをGP3とする
					; _PWRTE_ON		: 電源ONでリセットを有効
					; _WDT_OFF		: ウォッチドックタイマを無効
					; _INTOSCIO		: 内部クロックを使用、2番ピンをGP5,3番ピンをGP4とする

;--------------
; ビット名定義
;--------------

; GPIO

bManuSW		EQU	2	; GP2 マユアルON
bManuL		EQU	3	; GP3 シフト位置がＭ（マニュアル）
bDwnSW		EQU	4	; GP4 シフトダウン
bUpSW		EQU	5	; GP5 シフトアップ

; fFlags

bASWL		EQU	0	; GP0 ステアリングスイッチ オーディオコントロール接続
bCSWL		EQU	1	; GP1 ステアリングスイッチ オートクルーズコントロール接続
bSELAC		EQU	2	; スイッチ選択（0...オーディオ、1...オートクルーズ）
bCallS		EQU	3	; 設定モード呼び出しフラグ(0...呼び出さない、1...呼び出す)
bLngPsh		EQU	4	; 長押しフラグ(0...クリック, 1...長押し)

; fTimer

b100ms		EQU	0	; 100msecタイマーフラグ
b1sec		EQU	1	; 1secタイマーフラグ
bTMR2		EQU	2	; TMR2タイマーフラグ

;-------------
; 変数名定義
;-------------

	CBLOCK 020h

	fFlags		; 各種フラグ
	fCnt1		; 汎用カウンタ１
	fCnt2		; 汎用カウンタ２
	fWork		; 汎用Wレジスタ保存
	fCnt100m	; 100msecカウンタ
	fCnt1sec	; 500msecカウンタ
	fTimer		; タイマーフラグ
	fPreNo		; プリセット番号
	fPreNoW		; プリセット番号ワーク
	fADCSWN		; A/D変換後のスイッチ番号
	fOnCnt		; 長押しカウンタ（単位100msec）
	fSvW		; 割り込み退避領域（Ｗレジスタ）
	fSvSTAT		; 割り込み退避領域（STATUSレジスタ）
	fSaveSWN	; ボタン番号退避領域
	fSWN		; ボタン番号
	fFuncID		; ボタン番号に対応する処理番号
	fLEDidx		; CCPR1L(PWMデューティ)設定値
	fROMAdr		; EEPROM読込（または書込）アドレス
	fPreAdr		; プリセットデータ先頭アドレス
	fPreIDX		; プリセットデータ位置
	fPreDat		; プリセットデータ
	fFlshDat	; LED点滅出力データ
	fFlshBN		; LED点滅出力データビット数
	fFlshTim	; LED点滅時間(単位100msec)
	fLEDWCnt	; 待ちカウンタ
	fCntBtn0	; ボタン０検出カウンタ
	fCntBtn1	; ボタン１検出カウンタ
	fCntBtn2	; ボタン２検出カウンタ
	fCntBtn3	; ボタン３検出カウンタ
	fCntBtn4	; ボタン４検出カウンタ
	fCntBtn5	; ボタン５検出カウンタ
	fCntBtn6	; ボタン６検出カウンタ
	fTSvW		; デバッグ用Wレジスタ退避領域
	fTSvSTAT	; デバッグ用STATUSレジスタ退避領域
	fTSvGPIO	; デバッグ用GPIO退避領域
	fTDBGhD		; デバッグ用出力データ
	fTDBGhBN	; デバッグ用出力データビット数
	fTDBGWct	; デバッグ用1ビット出力時間(単位100msec)
	fTWcnt1		; デバッグ用時間待ちカウンタ１
	fTWcnt2		; デバッグ用時間待ちカウンタ２
	
	ENDC

;================
; プログラム開始
;================

;-------------------
; リセット時処理
;-------------------

	ORG	0

 	GOTO	INIT			; goto INIT							// 初期化処理へ行く

;-------------------
; 割り込み処理
;-------------------

	ORG	4

INTR
	MOVWF	fSvW			; w -> fSvW							// Wレジスタ保存
	SWAPF	STATUS,W		; STATUS -> fSvSTAT					// STATUSレジスタ保存
	MOVWF	fSvSTAT			;									// (STATUSが変化しないようSWAPする)

	BTFSS	INTCON,T0IF		; if ( INTCON[ T0IF ] == 1 ) {		// TMR0で割り込み
	GOTO	INTR_J2

	BCF		INTCON,T0IF		;	0 -> INTCON[ T0IF ] 			// 割込みフラグクリア

	DECFSZ	fCnt100m,f		;	if ( --fCnt100m == 0 ) {		// 100msカウンタのカウントダウン
	GOTO	INTR_J2

	BSF		fTimer,b100ms	;		0 -> fTimer[ b100ms ]		// 100msフラグセット
	MOVLW	d'3'			;		3 -> fCnt100ms				// 100msカウンタ初期化
	MOVWF	fCnt100m	
	DECFSZ	fCnt1sec,f		;		if ( --fCnt1sec == 0 ) {	// 500msカウンタのカウントダウン
	GOTO	INTR_J2

	BSF		fTimer,b1sec	;			0 -> fTimer[ b1sec ]	// 1secフラグセット
	MOVLW	d'10'			;			5 -> fCnt1sec			// 1secカウンタ初期化
	MOVWF	fCnt1sec

INTR_J2						;		}
							;	}
							; }
	BTFSS	PIR1,TMR2IF		; if ( PIR1[ TMR2IF ] == 1 ) {		// TMR2割り込みチェック
	GOTO	INTR_J3

	BCF		PIR1,TMR2IF		;	0 -> PRI1[ TMR2IF ]				// TMR2割り込みフラグクリア
	BSF		fTimer,bTMR2	;	1 -> fTimer[ bTMR2 ]			// TMR2フラグセット

INTR_J3						; }
	SWAPF	fSvSTAT,W		; fSvSTAT -> STATUS					// STATUSレジスタ復帰
	MOVWF	STATUS
	SWAPF	fSvW,F			; fSvW -> w							// Wレジスタ復帰
	SWAPF	fSvW,W			;									// (STATUSが変化しないようSWAPを使う)

	RETFIE					; 割込み許可リターン

;-------------------
; 初期化処理
;-------------------

INIT

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	MOVLW	B'00000111'		; B'00000111' -> CMCON0				// GP2-0はデジタルＩＯ
	MOVWF	CMCON0

	BSF		STATUS,RP0		; 1 -> STATUS[ PR0 ]				// ▼バンク１に切替え

	MOVLW	B'00001011'		; B'00001011' -> TRISIO				// GP0,1,3は入力、GP2,4,5は出力
	MOVWF	TRISIO
	MOVLW	B'00000011'		; B'00000011' -> ANSEL				// A/D変換クロック＝Fosc/2、
	MOVWF	ANSEL			;									//  AN0,AN1をアナログ入力とする
	MOVLW	B'01000000'		; B'01000000' -> OSCCON				// クロックを1MHzにする
	MOVWF	OSCCON			;									// （A/D変換ができる最低のクロック）

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// LED点灯、マニュアル線接続
	BCF		GPIO,bUpSW		; 0 -> GPIO[ bUpSW ]				// シフトアップSW OFF
	BCF		GPIO,bDwnSW		; 0 -> GPIO[ bDwnSW ]				// シフトダウンSW OFF

	BSF		STATUS,RP0		; 1 -> STATUS[ PR0 ]				// ▼バンク１に切替え

	MOVLW	B'00000100'		; B'00000100' -> OPTION_REG			// TMR0レート 1:32
	MOVWF	OPTION_REG
	MOVLW	D'127'			; 127 -> PR2						// PWM周期 127
	MOVWF	PR2
	CLRF	PIE1			; 0 -> PIE1							// 各種割り込み禁止
	MOVLW	B'00001000'		; B'00001000' -> IOC				// GP3のみGPIO割り込みを許可する
	MOVWF	IOC

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	CLRF	CCP1CON			; 0 -> CCP1CON						// CCPモジュールを使用しない
	CLRF	TMR0			; 0 -> TMR0							// TMR0初期化
	CLRF	CCPR1L			; 0 -> CCPR1L						// PWMデューティーを初期化
	CLRF	TMR2			; 0 -> TMR2							// TMR2初期化
	CLRF	PIR1			; 0 -> PIR1							// 拡張機能割り込み禁止
	MOVLW	B'01111011'		; B'01111011' -> T2CON				// ポストスケーラ 1:16、TMR2 OFF、 
	MOVWF	T2CON			;									//  プリスケーラ 1:16
	MOVLW	B'10100000'		; B'10100000' -> INTCON				// TMR0割り込みのみ許可
	MOVWF	INTCON

	CLRF	fFlags			; 0 -> fFlags						// 各種フラグ初期化

	MOVLW	00h				; ROMREAD( 00h ) -> fPreNo			// プリセット番号取得
	CALL	ROMREAD
	MOVWF	fPreNo

;---------
; LED調光
;---------
;　LEDを少しずつ明るくする。
;　ただし、マニュアルモードになった場合、即時運転モードへ遷移

LEDCON

	MOVLW	B'00001100'		; B'00001100' -> CCP1CON			// PWMモード
	MOVWF	CCP1CON
	CLRF	fLEDidx			; 0 -> fLEDidx						// LED調光データインデックス初期化
	BSF		T2CON,TMR2ON	; 1 -> T2CON[ TMR2ON ]				// TMR2の開始

LEDCON_L1					; do {
							;	do {
	BTFSC	GPIO,bManuL		; 		if ( GPIO[ bManuL ] == 1 ) break
	GOTO	LEDCON_J3		;									// マニュアルモードの場合調光中止

	BTFSS	fTimer,bTMR2	;	} while ( fTimer[ bTMR2 ] == 0 )// TMR2のカウント終了までループ
	GOTO	LEDCON_L1

	BCF		fTimer,bTMR2	;	0 -> fTimer[ bTMR2 ]			// TMR2カウント完了フラグクリア

	MOVLW	high LED_TBL	;	LED_TBL( fLEDidx ) -> w			// LED調光データを取得
	MOVWF	PCLATH
	MOVF	fLEDidx,w
	CALL	LED_TBL
	INCF	fLEDidx,f		;	fLEDidx++						// 次のLED調光データへ

	ADDLW	00h				; 	if ( w == 0 ) break				// LED調光データが0の場合ループ終了
	BTFSC	STATUS,Z
	GOTO	LEDCON_J3
	
	MOVWF	CCPR1L			;	w -> CCPR1L						// PWMディーティーに設定
	GOTO	LEDCON_L1		; }

LEDCON_J3
	BCF		T2CON,TMR2ON	; 1 -> T2CON[ TMR2ON ]				// TMR2の停止
	CLRF	CCP1CON			; 0 -> CCP1CON						// CCPモジュールを使用しない

;----------------------------
; スイッチ接続確認／設定変更
;----------------------------
;　オーディオSWとクルーズSWの接続確認。
;　また、Vol+ または、RES ボタンを長押しされた場合、設定モードへ入る

SWCHK
	BCF		fFlags,bCallS	; 0 -> fFlags[ bCallS ]				// 設定モード呼び出さない

	CALL	GETASW			; GETASW() -> w						// オーディオSW番号取得
	ADDLW	0ffh			; if ( w == 1 ) {	 				// "Vol+"(=1)が押されているか？ 
	BTFSS	STATUS,Z
	GOTO	SWCHK_J1
	
	CALL	W1SEC			; 	W1SEC()							// 1秒待つ
	CALL	GETASW			;	GETASW() -> w					// オーディオSW番号取得
	ADDLW	0ffh			;	if ( w == 1 ) {
	BTFSC	STATUS,Z
	BSF		fFlags,bCallS	;		1 -> fFlags[ bCallS ]		// 設定モード呼び出しを設定
	GOTO	SWCHK_J2		;		1 -> fFlags[ bASWL ]		// オーディオSW接続OK
							;	}

SWCHK_J1					; } else if ( w == 6 ) {			// 何も押されていない(=6)か？
	ADDLW	0fbh
	BTFSC	STATUS,Z
SWCHK_J2
	BSF		fFlags,bASWL	;		1 -> fFlags[ bASWL ]		// オーディオSW接続OK
							; }
	CALL	GETCSW			; GETCSW() -> w						// クルーズSW番号取得
	ADDLW	0ffh			; if ( w == 1 ) {					// "RES"(=1)が押されているか？
	BTFSS	STATUS,Z
	GOTO	SWCHK_J3

	CALL	W1SEC			; 	W1SEC()							// 1秒待つ
	CALL	GETCSW			;	GETCSW() -> w					// クルーズSW番号取得
	ADDLW	0ffh
	BTFSC	STATUS,Z
	BSF		fFlags,bCallS	;		1 -> fFlags[ bCallS ]		// 設定モード呼び出しを設定
	GOTO	SWCHK_J4		;		1 -> fFlags[ bCSWL ]		// クルーズSW接続OK
							;	}

SWCHK_J3					; } else if ( w == 6 ) {			// 何も押されていない(=6)か？
	ADDLW	0fbh
	BTFSC	STATUS,Z
SWCHK_J4
	BSF		fFlags,bCSWL	;	1 -> fFlags[ bCSWL ]			// クルーズSW接続OK
							; }

	BTFSC	fFlags,bCallS	; if ( fFlags[ bCallS ] == 1 ) {		// 設定モード呼び出し？
	CALL	SETTING			; 	SETTING()						// 設定モード呼び出し
							; }


;---------------------
; 主処理
;---------------------

MAIN
	MOVF	fPreNo,f		; if ( fPreNo == 0 ) {				// プリセット番号が0の場合
	BTFSC	STATUS,Z
MAIN_L1						; 	while(1){}						// 無限ループ（何も処理しない）
	GOTO	MAIN_L1			; }

	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// LED点灯、マニュアル線接続
	INCF	fPreNo,w		; (fPreNo + 1) * 10h -> fPreAdr		// プリセットデータ先頭アドレス算出
	MOVWF	fPreAdr
	SWAPF	fPreAdr,f

MAIN_L2						; do {
							;	do {
	CALL	GETSWNO			;		GETSWNO() -> w				// ボタン番号取得

	ADDLW	00h				; 	} while ( w == 0 ) 				// ボタンが押されるまでループ
	BTFSC	STATUS,Z
	GOTO	MAIN_L2

	BCF		fFlags,bLngPsh	;	0 -> fFlags[ bLngPsh ]			// クリック
	MOVWF	fSaveSWN		; 	w -> fSaveSWN					// ボンタ番号保存

	ADDLW	0ffh			;	ROMREAD(fPreAdr + w -1 ) -> w
	ADDWF	fPreAdr,w		; 									// ボタン番号に対応する処理IDを取得
	CALL	ROMREAD
	ANDLW	0fh				; 	w and 0fh -> w					// 下位４ビットにする
	MOVWF	fFuncID			;	w -> fFuncID

	MOVLW	high MAIN_PC	; 	switch ( fFuncID ) {			// high(MAIN_PC) -> PCLATH
	MOVWF	PCLATH

	MOVF	fFuncID,w		;									// fFuncID + 3 -> w
	ADDLW	03h

	ADDWF	PCL,w			; 									// PCL + w -> w
MAIN_PC
	BTFSC	STATUS,C		; 									// if ( C == 1 ) PCLATH++
	INCF	PCLATH,f
	MOVWF	PCL				; 									// w -> PCL

	GOTO	MAIN_J1			; 	case 0000B :					// 何もしない
	GOTO	SHFTDWN			;	case 0001B : SHFTDWN()			// シフトダウン
	GOTO	SHFTUP			;	case 0010B : SHFTUP()			// シフトアップ
	GOTO	MAIN_J1			; 	case 0011B :					// 何もしない
	GOTO	MANUAL			;	case 0100B : MANUAL()			// マニュアルモード
	GOTO	SHFTDWN			;	case 0101B : SHFTDWN()			// シフトダウン
	GOTO	SHFTUP			;	case 0110B : SHFTUP()			// シフトアップ
	GOTO	MSHFTDWN		; 	case 0111B : MSHFTDWN()			// 何もしない
	GOTO	DRIVE			;	case 1000B : DRIVE()			// ドライブモード
	GOTO	SHFTDWN			;	case 1001B : SHFTDWN()			// シフトダウン
	GOTO	SHFTUP			;	case 1010B : SHFTUP()			// シフトアップ
	GOTO	MSHFTUP			; 	case 1011B : MSHFTUP()			// 何もしない
	GOTO	SWICHMD			;	case 1100B : SWICHMD()			// マニュアル・ドライブ切替
	GOTO	SHFTDWN			;	case 1101B : SHFTDWN()			// シフトダウン
	GOTO	SHFTUP			;	case 1110B : SHFTUP()			// シフトアップ
							;	case 1111B :					// 何もしない

MAIN_J1						;	}

	MOVLW	0ah				; 	10 -> fOnCnt					// 長押しカウンタ初期化（ダウンカウンタ）
	MOVWF	fOnCnt
	CALL	RSTTIMER		; 	RSTTIMER()						// タイマーリセット

MAIN_L3						;	do {
	BTFSC	GPIO,bManuL		; 		if( GPIO[ bManuL ] == 0 ) {
	GOTO	MAIN_J3			;									// ドライブモードの場合
	
	BCF		GPIO,bUpSW		;			0 -> GPIO[ bUpSW ]		// シフトアップOFF
	BCF		GPIO,bDwnSW		;			0 -> GPIO[ bDwnSW ]		// シフトダウンOFF

MAIN_J3						; 		}
	CALL	GETSWNO			;		GETSWNO() -> w				// ボタン番号取得
	SUBWF	fSaveSWN,w		;		if ( w != fSaveSWN ) { 		// 同じボタンが押されなくなったら終了
	BTFSS	STATUS,Z
	GOTO	MAIN_J5			;			goto MAIN_J5
							;		}
	BTFSS	fTimer,b100ms	;		if ( fTimer[ b100ms ] == 1 ) {
	GOTO	MAIN_L3			;									// 100msec経過チェック
	BCF		fTimer,b100ms	;			0 -> fTimer[ b100ms ]
							;		}
	DECFSZ	fOnCnt,f		;	} while ( --fOnCnt > 0 )		// 長押しカウンタデクリメント
	GOTO	MAIN_L3			;

	BSF		fFlags,bLngPsh	;	1 -> fFlags[ bLngPsh ]			// 長押し
	MOVF	fFuncID,w		;	switch ( fFuncID ) {			// 保存していた処理IDを取り出す

	MOVLW	high MAIN_PC2	; 									// high(MAIN_PC2) -> PCLATH
	MOVWF	PCLATH

	MOVF	fFuncID,w		; 									// fFuncID + 3 -> w
	ADDLW	03h

	ADDWF	PCL,w			; 									// PCL + w -> w
MAIN_PC2
	BTFSC	STATUS,C		; 									// if ( C == 1 ) PCLATH++
	INCF	PCLATH,f
	MOVWF	PCL				; 									// w -> PCL

	GOTO	MAIN_J2			; 	case 0000B :					// 何もしない
	GOTO	MAIN_J2			; 	case 0001B :					// 何もしない
	GOTO	MAIN_J2			; 	case 0010B :					// 何もしない
	GOTO	JMPSTNG			; 	case 0011B :					// 設定変更
	GOTO	MAIN_J2			; 	case 0100B :					// 何もしない
	GOTO	MANUAL			;	case 0101B : MANUAL()			// マニュアルモード
	GOTO	MANUAL			;	case 0110B : MANUAL()			// マニュアルモード
	GOTO	DRIVE			;	case 0111B : DRIVE()			// ドライブモード
	GOTO	MAIN_J2			; 	case 1000B :					// 何もしない
	GOTO	DRIVE			; 	case 1001B : DRIVE()			// ドライブモードにする
	GOTO	DRIVE			; 	case 1010B : DRIVE()			// ドライブモードにする
	GOTO	DRIVE			; 	case 1011B : DRIVE()			// ドライブモードにする
	GOTO	MAIN_J2			; 	case 1100B :					// 何もしない
	GOTO	SWICHMD			; 	case 1101B : SWICHMD()			// ドライブ・マニュアル切替
	GOTO	SWICHMD			; 	case 1110B : SWICHMD()			// ドライブ・マニュアル切替
	GOTO	SWICHMD			; 	case 1111B : SWICHMD()			// ドライブ・マニュアル切替
		
MAIN_J2						; 	}
							; 	do {
	BTFSC	GPIO,bManuL		; 		if( GPIO[ bManuL ] == 0 ) {
	GOTO	MAIN_J4			;									// ドライブモードの場合

	BCF		GPIO,bUpSW		;			0 -> GPIO[ bUpSW ]		// シフトアップOFF
	BCF		GPIO,bDwnSW		;			0 -> GPIO[ bDwnSW ]		// シフトダウンOFF

MAIN_J4						; 		}
	CALL	GETSWNO			; 		GETSWNO() -> w				// ボタン番号取得
	SUBWF	fSaveSWN,w		;	 } while ( w == fSaveSWN )		// 同じボタンが押されている場合繰り返す
	BTFSC	STATUS,Z
	GOTO	MAIN_J2

MAIN_J5
	BCF		GPIO,bUpSW		; 	0 -> GPIO[ bUpSW ]				// シフトアップOFF
	BCF		GPIO,bDwnSW		; 	0 -> GPIO[ bDwnSW ]				// シフトダウンOFF
	

	GOTO		MAIN_L2		; }



;--------------------------
; マニュアル＋シフトアップ
;--------------------------

MSHFTUP
	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// LED点灯、マニュアル線接続

	MOVLW	d'32'			; SHRTWAIT(32)						// 392usec待つ
	CALL	SHRTWAIT		; 									//  GPIO[GP2]のHレベル出力時間＋
							;									//  リレーのON時間＋GPIO[GP3]のHレベル検出時間待つ
							;									// ↓引き続き、シフトアップへ

;--------------
; シフトアップ
;--------------

SHFTUP
	BTFSC	GPIO,bManuL		; if ( GPIO[ bManuL ] == 1 ) 1 -> GPIO[ bUpSW ]
	BSF		GPIO,bUpSW

	GOTO	JMPMAIN			; goto JMPMAIN

;--------------------------
; マニュアル＋シフトダウン
;--------------------------

MSHFTDWN
	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// LED点灯、マニュアル線接続

	MOVLW	d'32'			; SHRTWAIT(32)						// 392usec待つ
	CALL	SHRTWAIT		; 									//  GPIO[GP2]のHレベル出力時間＋
							;									//  リレーのON時間＋GPIO[GP3]のHレベル検出時間待つ
							;									// ↓引き続き、シフトダウンへ
;--------------
; シフトダウン
;--------------

SHFTDWN
	BTFSC	GPIO,bManuL		; if ( GPIO[ bManuL ] == 1 ) {		// マニュアルモード確認
	BSF		GPIO,bDwnSW		;	1 -> GPIO[ bDwnSW ]				// シフトダウンSW ON
							; }
	GOTO	JMPMAIN			; goto JMPMAIN

;------------------------
;ドライブモードON/OFF切替
;------------------------

SWICHMD
	BTFSS	GPIO,bManuSW	; if ( GPIO[ bManuSW ] ==0 ) goto MANUAL
	GOTO	MANUAL			;									// ドライブモードの場合、マニュアルモードへ
							;									// ↓マニュアルモードの場合、ドライブモードへ

;------------------------
;ドライブモード
;------------------------

DRIVE
	BCF		GPIO,bManuSW	; 0 -> GPIO[ bManuSW ]				// ドライブモードに設定
	GOTO	JMPMAIN			

;------------------------
;マニュアルモード
;------------------------

MANUAL
	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// マニュアルモードに設定
	GOTO	JMPMAIN

;-----------
;設定変更
;-----------

JMPSTNG				
	BTFSC	GPIO,bManuL		; if ( GPIO[ bManuL ] == 1 ) return	// マニュアルの場合、JMPMAINへ
	GOTO	JMPMAIN

	BCF		GPIO,bManuSW	; 0 -> GPIO[ bManuSW ]				// ドライブモードに設定

JMPSTNG_J1					; do {
	CALL	GETSWNO			;	GETSWNO() -> w					// ボタン番号取得
	ADDLW	0h				; } while ( w != 0 ) 				// 同じボタンが押されているかチェック
	BTFSS	STATUS,Z
	GOTO	JMPSTNG_J1

	CALL	SETTING_J0		; Setting_J0()						// 設定変更
	GOTO	MAIN			; goto MAIN							// MAINへ戻る

;--------------
; メインへ戻る
;--------------

JMPMAIN
	BTFSS	fFlags,bLngPsh	; if ( fFlags[ bLngPsh ] == 0 ) {
	GOTO	MAIN_J1			; 	goto MAIN_J1					// クリックの場合、MAIN_J1へ戻る
							; }
	GOTO	MAIN_J2			; goto MAIN_J2						// 長押しの場合、MAIN_J2へ戻る


;==============
;サブルーチン
;==============

;----------------------------
; オーディオSWボタン番号取得
;----------------------------
; オーディオSWの押されたボタン番号をWレジスタにセットして戻る
;（先に10回カウントされた状態を返却する。）

;返却値
; wレジスタ
;	0 : Vol-   
;	1 : Vol+
;	2 : ▲
;	3 : ▼
;	4 : Mode
;	5 : Mute
;	6 : (何も押していない)
;

GETASW
	BCF		fFlags,bSELAC	; 0 - > fFlags[ bSELAC ]			// オーディオSWを選択
	GOTO	GETSW			; goto GETSW

;----------------------------
; クルーズSWボタン番号取得
;----------------------------
; クルーズSWの押されたボタン番号をWレジスタにセットして戻る
;（先に10回カウントされた状態を返却する。）

;返却値
; wレジスタ
;	0 : RES/ACCEL
;	1 : SET/COAST
;	2 : On/Off
;	3 : CANCEL
;	6 : (何も押していない)

GETCSW
	BSF		fFlags,bSELAC	; 1 - > fFlags[ bSELAC ]			// クルーズSWを選択

GETSW
	MOVLW	D'10'			; 10 -> w							// カウンタ初期化
	MOVWF	fCntBtn0		; w -> fCntBtn0
	MOVWF	fCntBtn1		; w -> fCntBtn1
	MOVWF	fCntBtn2		; w -> fCntBtn2
	MOVWF	fCntBtn3		; w -> fCntBtn3
	MOVWF	fCntBtn4		; w -> fCntBtn4
	MOVWF	fCntBtn5		; w -> fCntBtn5
	MOVWF	fCntBtn6		; w -> fCntBtn6

GETSW_L1					; do {
	BTFSC	fFlags,bSELAC	;	if ( fFlags[ bSELAC ] == 0 ) {
	GOTO	GETSW_J2

	CALL	AADCN			;		AADCN() -> fADCSWN			// スイッチ状態取得
	GOTO	GETSW_J3		;	} else {

GETSW_J2
	CALL	CADCN			;		CADCN() -> fADCSWN			// スイッチ状態取得

GETSW_J3					;	}
	MOVWF	fADCSWN

	MOVLW	high GETSW_PC	; 	switch ( fADCSWN ) {			// GETSW_PC + fADCSWN * 2 + 3
	MOVWF	PCLATH			;									//   のアドレスにジャンプする

	BCF		STATUS,C
	RLF		fADCSWN,w
	ADDLW	03h

	ADDWF	PCL,w
GETSW_PC
	BTFSC	STATUS,C
	INCF		PCLATH,f
	MOVWF	PCL

	DECF	fCntBtn0,f		; 	case 0: fCntBtn0--				// ボタン０のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn1,f		; 	case 1: fCntBtn1--				// ボタン１のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn2,f		; 	case 2: fCntBtn2--				// ボタン２のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn3,f		; 	case 3: fCntBtn3--				// ボタン３のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn4,f		; 	case 4: fCntBtn4--				// ボタン４のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn5,f		; 	case 5: fCntBtn5--				// ボタン５のカウントアップ
	GOTO	GETSW_J1
	DECF	fCntBtn6,f		; 	case 6: fCntBtn6--				// ボタン６のカウントアップ

GETSW_J1					; 	}
	BTFSS	STATUS,Z		; } while ( ( fCntBtn0 != 0 || fCntBtn1 != 0 || ... fCntBtn6 != 0 )
	GOTO	GETSW_L1		;									// カウントのどれかが0になったら終了

	MOVF	fADCSWN,w		; return fADCSWN
	return
	

;----------------------------
; オーディオSWボタン番号取得
;----------------------------
;返却値
; wレジスタ
;	0 : Vol-   
;	1 : Vol+
;	2 : ▲
;	3 : ▼
;	4 : Mode
;	5 : Mute
;	6 : (何も押していない)
;

AADCN

	MOVLW	B'00000001'		; 001B -> ADCON0					// Bit7 0=左詰めでセットし、右(下位ビット)の6ビットは0
							;									// Bit6 0=ＶDD（電源電圧）を基準電圧とする
							;									// bit3,2 00=AN0
							;									// bit1 1=Ａ／Ｄ変換開始指示
							;									// bit0 1=Ａ／Ｄ変換機能は有効
	MOVWF	ADCON0
	MOVLW	01h				; SHRTWAIT()						// 20usec待ち(コンデンサ充電時間)
	CALL	SHRTWAIT

	BSF		ADCON0,GO		; 1 -> ADCON0[GO] 					// A/D変換開始

AADCN_L1
	BTFSC	ADCON0,GO		; while ( ADCON0[GO] == 1 ) {}		// A/D変換完了までループ
	GOTO	AADCN_L1

	MOVLW	024h			; if ( ADRESH < 24h ) return 00h	// Vol-ボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C
	RETLW	00h

	MOVLW	048h			; if ( ADRESH < 48h ) return 01h	// Vol+ボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	01h

	MOVLW	06Ch			; if ( ADRESH < 6Ch ) return 02h	// ▲ボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	02h

	MOVLW	090h			; if ( ADRESH < 90h ) return 03h	// ▼ボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	03h

	MOVLW	0B4h			; if ( ADRESH < B4h ) return 04h	// Modeボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	04h

	MOVLW	0D8h			; if ( ADRESH < D8h ) return 05h	// Muteボタン
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	05h

	RETLW	06h				; return 06h						// どのボタンも押していない


;--------------------------
; クルーズSWボタン番号取得
;--------------------------
;返却値
; wレジスタ
;	0 : RES/ACCEL
;	1 : SET/COAST
;	2 : On/Off
;	3 : CANCEL
;	6 : (何も押していない)


CADCN

	MOVLW	B'00000101'		; 101B -> ADCON0					// Bit7 0=左詰めでセットし、右(下位ビット)の6ビットは0
							;									// Bit6 0=ＶDD（電源電圧）を基準電圧とする
							;									// bit3,2 01=AN1
							;									// bit1 1=Ａ／Ｄ変換開始指示
							;									// bit0 1=Ａ／Ｄ変換機能は有効
	MOVWF	ADCON0
	MOVLW	01h				; SHRTWAIT()						// 20usec待ち(コンデンサ充電時間)
	CALL	SHRTWAIT

	BSF		ADCON0,GO		; 1 -> ADCON0[GO] 					// A/D変換開始

CADCN_L1
	BTFSC	ADCON0,GO		; while ( ADCON0[GO] == 1 ) {}		// A/D変換完了までループ
	GOTO	CADCN_L1

	MOVLW	01Ch			; if ( ADRESH < 1Ch ) return 02h	// On/Offボタン(0.017V)
	SUBWF	ADRESH,w
	BTFSS	STATUS,C
	RETLW	02h

	MOVLW	06Ah			; if ( ADRESH < 6Ah ) return 03h	// CANCELボタン(1.107V)
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	03h

	MOVLW	0B9h			; if ( ADRESH < B9h ) return 00h	// SET/COASTボタン(3.080V)
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	00h

	MOVLW	0EBh			; if ( ADRESH < EBh ) return 01h	// RES/ACCELボタン(4.206V)
	SUBWF	ADRESH,w
	BTFSS	STATUS,C	
	RETLW	01h

	RETLW	06h				; return 06h						// どのボタンも押していない(5.031V)


;----------
; 時間待ち
;----------
; クロックが1MHzの場合、Wレジスタ × 12usec + 8usec 待つ
; ただし、wレジスタが 0 のときは256で計算

SHRTWAIT
	ADDLW	0ffh			; while ( --W > 0 ) {				// wレジスタの回数繰り返す
	BTFSS	STATUS,Z
	GOTO	SHRTWAIT		; }

	RETURN					; return

;---------
; 1秒待ち
;---------
; １秒待つ

W1SEC
	CALL	RSTTIMER		; RSTTIMER()						// タイマー初期化
W1SEC_L1
	BTFSS	fTimer,b1sec	; while( timer[ b1sec ] == 0) {		// １秒フラグが立つまで待つ
	GOTO	W1SEC_L1		; }

	RETURN					; return

;--------------
; 設定変更処理
;--------------
; 設定モード。プリセット番号変更や内容変更をする。
;
; Aボタン --- 終了（選択しているプリセット番号をEEPROMへ保存）
; Bボタン --- プリセット番号＋１
; Aボタン長押し --- 選択しているプリセット番号の設定をデフォルトに戻す
; Bボタン長押し --- 選択しているプリセット番号の設定変更モードへ遷移する

SETTING

	BCF		GPIO,bManuSW	; 0 -> GP2(bManuSW) 				// LED消灯
				
SETTING_L1					; do {								// 設定開始ボタンが離されるまで待つ
	CALL	GETSTBTN		;	getStnBtn() -> w
	ADDLW	00h				; } while( w != 0 )
	BTFSS	STATUS,Z
	GOTO	SETTING_L1

SETTING_J0					;									// 押されたボタンにより処理を分ける
	MOVF	fPreNo,w		; fPreNo -> fPreNoW					// プリセット番号をワークへ設定
	MOVWF	fPreNoW
	CLRF	fSaveSWN		; 0 -> fSaveSWN
	CLRF	fOnCnt			; 0 -> fOnCnt						// 長押しカウンタ初期化（アップカウンタ）

	CALL	RSTTIMER		; RSTTIMER()						// タイマー初期化
	
SETTING_L2					; do {
	MOVLW	03h				; 	LEDFLSH( fPreNoW, 03h ) -> w	// fPreNoWを3ビットで出力
	MOVWF	fFlshBN
	MOVF	fPreNoW,w
	CALL	LEDFLSH

	ADDLW	0ffh			; 	if ( w == 1 ) {					// Ａボタンの場合
	BTFSS	STATUS,Z		; 	
	GOTO	SETTING_J1

	MOVLW	0h				;		ROMWRITE(0,fPreNoW)			// EEPROM アドレス0 にプリセット番号を書き込む
	MOVWF	fROMAdr
	MOVF	fPreNoW,w		;		fPreNoW -> fPreNo
	MOVWF	fPreNo
	CALL 	ROMWRITE

	RETURN					;		return						// 設定完了で終了

SETTING_J1
	ADDLW	0ffh			; 	} else if ( w == 2 ) {			// Ｂボタンの場合
	BTFSS	STATUS,Z
	GOTO	SETTING_J3
			
	INCF	fPreNoW,f		; 		if ( ++fPreNoW >= 08 ) 0 -> fPreNoW
	MOVLW	07h				; 									// プリセット番号を１進め、8以上で0に戻す
	ANDWF	fPreNoW,f
	GOTO	SETTING_L2

SETTING_J3
	ADDLW	0feh			;	} else if ( w == 4 ) {			// マニュアルONの場合
	BTFSC	STATUS,Z
	RETURN					;		return						// 終了

	ADDLW	0ffh			;	} else if ( w == 5 ) {			// Ａボタン長押しの場合
	BTFSS	STATUS,Z
	GOTO	SETTING_J2

	MOVF	fPreNoW,w		;		PRSTRST( fPreNoW )			// 選択しているプリセット番号の設定を初期化
	CALL	PRSTRST
	GOTO	SETTING_L2

SETTING_J2					;	} else if ( w == 6 ) {			// Ｂボタン長押しの場合
	ADDLW	0ffh
	BTFSS	STATUS,Z
	GOTO	SETTING_L2

	MOVLW	0h				;		if ( fPreNoW != 0 ) { 		// プリセット番号が０意外の場合
	ADDWF	fPreNoW,w
	BTFSC	STATUS,Z
	GOTO	SETTING_L2

	CALL	PRSTEDT			;			PRSTEDT()				// プリセット変更
	GOTO	SETTING_L2		;		}
							; 	}
							; } while(1)


;----------------------
; プリセット内容初期化
;----------------------
; 指定したプリセット番号(wレジスタ)の設定を初期化する

PRSTRST
	ADDLW	01h				; (w + 1) * 10h -> fROMAdr			// プリセット番号(Wレジスタ)の
	MOVWF	fROMAdr			;									//   EEPEOM先頭アドレス(fROMAdr)算出
	SWAPF	fROMAdr,f

	MOVLW	10h				; for( fCnt1=010h ; fCnt1-- ; fCnt1>0 ) {
	MOVWF	fCnt1			;									// データ数分繰り返す

PRSTRST_L1
	MOVF	fROMAdr,w		;	ROMREAD(fROMAdr) -> w			// データ読み出し
	CALL	ROMREAD
	ANDLW	0f0h			;	(w and 0f0h) or swapf(w and 0f0h) -> w
	MOVWF	fPreDat			;									// 上位４ビットを下位４ビットにコピーする
	SWAPF	fPreDat,w
	IORWF	fPreDat,w

	CALL 	ROMWRITE		;	ROMWRITE(fROMAdr,w)				// データを書き込む

	INCF	fROMAdr,f		;	fROMAdr++
	DECFSZ	fCnt1,f
	GOTO	PRSTRST_L1		; }

	RETURN					; return


;------------------
;プリセット内容変更
;------------------
; プリセット番号（fPreNoW）のプリセット内容（データ）を変更する
;
; Aボタン --- データ＋１
; Bボタン --- データ位置＋１
; Aボタン長押し --- 選択データをデフォルトに戻す
; Bボタン長押し --- プリセット番号選択にもどる
;
; Ａボタン ... Vol+ or RES ボタン
; Ｂボタン ... Vol- or SET ボタン


PRSTEDT
	CALL	RSTTIMER		; RSTTIMER()						// タイマーリセット

	INCF	fPreNoW,w		; (fPreNoW + 1) * 10h -> fPreAdr	// プリセット番号 fPreNoW の
	MOVWF	fPreAdr			;									//   EEPEOM先頭アドレス(fPreAdr)算出
	SWAPF	fPreAdr,f

PRSTEDT_L0
	CLRF	fPreIDX			; 0 -> fPreIDX						// プリセットデータ位置初期化

PRSTEDT_L1					; do {
							; 	do {

	MOVLW	04h				; 		LEDFLSH( fPreIDX, 4 ) -> w	
	MOVWF	fFlshBN			;									// fPreIDXを4ビットで出力
	MOVF	fPreIDX,w
	CALL	LEDFLSH	
	ADDLW	00h				;		if ( w != 0 ) break			// イベントがあったらループを出る
	BTFSS	STATUS,Z
	GOTO	PRSTEDT_J0

	MOVLW	04h				;
	MOVWF	fFlshBN

	MOVF	fPreAdr,w		;		ROMREAD(fPreAdr + fPreIDX) -> fPreDat
	ADDWF	fPreIDX,w		;									// プリセットデータ取得
	CALL	ROMREAD
	MOVWF	fPreDat

	CALL	LEDFLSH			;		LEDFLSH( fPreDat, 04h ) -> w
							;									// データ下位４ビットを出力
	ADDLW	00h				;		if ( w != 0 ) break
	BTFSS	STATUS,Z
	GOTO	PRSTEDT_J0

	MOVLW	08h				;		LEDOFF( 08h ) - > w			// 08h x 0.1sec LED消灯で待つ
	CALL	LEDOFF
	ADDLW	00h				;		if ( w != 0 ) break			// イベントがあったらループを出る
	BTFSC	STATUS,Z
	GOTO	PRSTEDT_L1		; 	}

PRSTEDT_J0

	ADDLW	0ffh			; 	if ( w == 1 ) {					// Ａボタンの場合
	BTFSS	STATUS,Z		; 	
	GOTO	PRSTEDT_J1

	MOVLW	0fh				;		(fPreDat and 0fh) + 1) and 0fh or (fPreDat and 0f0h) -> fPreDat
	ANDWF	fPreDat,w		;									// fPreDatの下位４桁を＋１
	XORWF	fPreDat,f
	ADDLW	01h
	ANDLW	0fh
	IORWF	fPreDat,f

	MOVF	fPreAdr,w		;		ROMWRITE(fPreAdr + fPreIDX,fPreDat)
	ADDWF	fPreIDX,w		;									// EEPROMアドレス fPreAdr + fPreIDX にfPreDatを書き込む
	MOVWF	fROMAdr
	MOVF	fPreDat,w
	CALL 	ROMWRITE
	GOTO	PRSTEDT_L1

PRSTEDT_J1
	ADDLW	0ffh			; 	} else if ( w == 2 ) {			// Ｂボタンの場合
	BTFSS	STATUS,Z
	GOTO	PRSTEDT_J2		;		
	
	MOVF	fPreIDX,w		;		if ( 08h < fPreIDX ) {
	SUBLW	08h
	BTFSS	STATUS,C
	GOTO	PRSTEDT_L0		;			0 -> fPreIDX
							;		} else {
	INCF	fPreIDX,f		;			fPreIDX++
	GOTO	PRSTEDT_L1		;		}

PRSTEDT_J2
	ADDLW	0feh			;	} else if ( w == 4 ) {			// マニュアルONの場合
	BTFSC	STATUS,Z
	RETURN					;		return						// 設定終了

	ADDLW	0ffh			;	} else if ( w == 5 ) {			// Ａボタン長押しの場合
	BTFSC	STATUS,Z
	RETURN					;		return						// 設定終了

	ADDLW	0ffh			;	} else if ( w == 6 ) {			// Ｂボタン長押しの場合
	BTFSS	STATUS,Z
	GOTO	PRSTEDT_L1

	MOVF	fPreDat,w		;		(fPreDat and 0f0h) or swapf(fPreDat) -> fPreDat
	ANDLW	0f0h			;									// 上位４ビットを下位４ビットにコピーする
	MOVWF	fPreDat
	SWAPF	fPreDat,w
	IORWF	fPreDat,f

	MOVF	fPreAdr,w		;		ROMWRITE(fPreAdr + fPreIDX,fPreDat)
	ADDWF	fPreIDX,w		;									// EEPROMアドレス fPreAdr + fPreIDX にfPreDatを書き込む
	MOVWF	fROMAdr
	MOVF	fPreDat,w
	CALL 	ROMWRITE

	GOTO	PRSTEDT_L1		; 	}
							; } while(1)


;---------------------
;LEDビットパターン点滅
;---------------------
;
;W ... ビットパターン
;fFlshBN...ビット数
;<返却値>
; wレジスタ
;	0...正常終了
;	1...ボタンＡ（Vol- or SET ボタン）シングル
;	2...ボタンＢ（Vol+ or RES ボタン）シングル
;	4...マニュアルＯＮ
;	5...ボタンＡ（Vol- or SET ボタン）長押し
;	6...ボタンＢ（Vol+ or RES ボタン）長押し
;
;ビットパターンによりLEDを点滅させる *点灯、-消灯
; 0 ---> *-
; 1 ---> **--
; 全ビット出力後 ---> --
; 例) 1011B,4bit --> **--*-**--**----
;

LEDFLSH
	MOVWF	fFlshDat

LEDFLSH_L1					; do {

	MOVLW	02h				; 	02h -> fFlshTim					// 点滅長を200msecとする
	RRF		fFlshDat,f		; 	if ( fFlshDat[0] == 1 ) {		// ビット0が1の場合は
	BTFSC	STATUS,C
	MOVLW	04h				; 		04h -> fFlshTim				//   点滅長を400msecとする
	MOVWF	fFlshTim		; 	}
							; 	fFlshDat >> 1 -> fFlshDat		// fFlshDatを１ビットシフト
	MOVF	fFlshTim,w		; 	LEDON( fFlshTim ) -> w			// LEDを点灯し、点滅長 待つ
	CALL	LEDON
	ADDLW	00h				; 	if ( w != 0 ) return w			// 何かイベントが発生したら、復帰
	BTFSS	STATUS,Z
	RETURN

	MOVF	fFlshTim,w		; 	LEDOFF( fFlshTim) -> w			// LEDを消灯し、点滅長 待つ
	CALL	LEDOFF
	ADDLW	00h				; 	if ( w != 0 ) return w			// 何かイベントが発生したら、復帰
	BTFSS	STATUS,Z
	RETURN

	DECFSZ	fFlshBN,f		; 	fFlshBN--						// 指定ビット数繰り返す
	GOTO	LEDFLSH_L1		; } while ( fFlshBN != 0 )

	MOVLW	08h				; LEDOFF( 08h ) - > w				// 08h x 0.1sec LED消灯で待つ
	CALL	LEDOFF

	RETURN					; return w


;---------------------
; LED点灯イベント待ち
;---------------------

LEDON

	BSF		GPIO,bManuSW	; 1 -> GPIO[ bManuSW ]				// LED点灯
	GOTO	WAITEVNT		; GOTO WAITEVNT 					// イベント待ちへ

;---------------------
; LED消灯イベント待ち
;---------------------
LEDOFF

	BCF		GPIO,bManuSW	; 0 -> GPIO[ bManuSW ]				// LED消灯
							;									// イベント待ちへ
;--------------
; イベント待ち
;--------------
; wレジスタ×100msec 待つ間、イベント（ボタン入力、マニュアルモード等）を待つ。
;
;<返却値>
; wレジスタ
;	0...正常終了
;	1...ボタンＡ（Vol- or SET ボタン）シングル
;	2...ボタンＢ（Vol+ or RES ボタン）シングル
;	4...マニュアルＯＮ
;	5...ボタンＡ（Vol- or SET ボタン）長押し
;	6...ボタンＢ（Vol+ or RES ボタン）長押し
;
;下記変数は初回の呼び出し時には初期化しておくこと
;	0 -> fSaveSWN		;ボタン番号退避
;	0 -> fOnCnt		;長押しカウンタ
;	CALL RSTTIMER		;タイマリセット

WAITEVNT
	MOVWF	fLEDWCnt		; w -> fLEDWCnt						// 繰り返し回数設定

WAITEVNT_L1					; do {

WAITEVNT_L2					; 	do {
	BTFSC	GPIO,bManuL		; 		if ( GPIO[ bManuL ] == 1 ) return 04h
	RETLW	04h				;									// もしマニュアルモードに入った場合、強制終終了

	CALL	GETSTBTN		;		GETSTBTN() -> fSWN			// ボタン番号取得
	MOVWF	fSWN
	SUBWF	fSaveSWN,w		;		if ( fSaveSWN != fSWN ) {	// ボタン番号に変化があった場合
	BTFSC	STATUS,Z
	GOTO	WAITEVNT_J1
	
	CLRF	fOnCnt			;			0 -> fOnCnt				// 長押しカンウンタ初期化（アップカウンタ）
	MOVF	fSaveSWN,w		;			fSaveSWN -> fWork
	MOVWF	fWork
	MOVF	fSWN,w			;			fSWN -> fSaveSWN		// ボタン番号保存
	MOVWF	fSaveSWN
	MOVF	fWork,w			;			if ( fWork !=0 ) return fWork	
	BTFSS	STATUS,Z		;									// 押されていたボタン番号が 0 意外か？
	RETURN					;									// 押されていたボタン番号を返却

WAITEVNT_J1					;		}
	BTFSS	fTimer,b100ms	; 	} while ( fTimer[ b100ms ] == 0 )
	GOTO	WAITEVNT_L2		;									// 100msec経過するまでループする。

	BCF		fTimer,b100ms	;	0 -> fTimer[ b100ms ]			// 100msecフラグクリア

	MOVF	fSWN,w			;	if ( fSWN != 0 )				// 何かボタンが押されている場合
	BTFSC	STATUS,Z
	GOTO	WAITEVNT_J2

	INCF	fOnCnt,f		;		fOnCnt++					// 長押しカンウンタインクリメント
	MOVLW	0ah				;		if ( fOnCnt >= 0ah ) {
	SUBWF	fOnCnt,w 		;									// 1sec(100msec x 10回) 経過？
	BTFSS	STATUS,C
	GOTO	WAITEVNT_J2

	BCF		GPIO,bManuSW	;			0 -> GPIO[ bManuSW ]	// LED消灯
WAITEVNT_L3					;			while ( GETSTBTN() != 0 ) {
	CALL	GETSTBTN		;									// ボタンが離されるのを待つ
	ADDLW	0h
	BTFSS	STATUS,Z
	GOTO	WAITEVNT_L3		;			}

	CLRF	fOnCnt			;			0 -> fOnCnt				// 長押しカウンタ初期化
	CLRF	fSaveSWN		;			0 -> fSaveSWN			// ボタン押していない状態を保存 
	MOVLW	04h				;			return (fSWN + 4)
	ADDWF	fSWN,w

	RETURN

WAITEVNT_J2					;		}
							;	}
	DECFSZ	fLEDWCnt,f		;	fLEDWCnt--						// 指定回数繰り返す
	GOTO	WAITEVNT_L1		; } while ( fLEDWCnt > 0 )

	RETLW	0h				; return 0
	
;------------------
;設定ボタン番号取得
;------------------
; 設定用ボタンの状態を確認し、設定用ボタン番号を返却する。
;
;返却値
; wレジスタ
;	0...何も押されていない
;	1...vol- or SET/COAST 
;	2...vol+ or RES/ACCEL

GETSTBTN

	BTFSS	fFlags,bASWL	; if ( fFlags[ bASWL ] == 1 ) {		// オーディオSW接続？
	GOTO	GETSTBTN_J1
	CALL	GETASW			;	GETASW() -> w					// オーディオSW状態取得

	ADDLW	00h				;	if ( w == 0 ) return 1			// Vol- ボタン？
	BTFSC	STATUS,Z
	RETLW	01h

	XORLW	01h				;	if ( w == 1 ) return 2			// Vol+ ボタン？
	BTFSC	STATUS,Z
	RETLW	02h

GETSTBTN_J1
	BTFSS	fFlags,bCSWL	; if ( fFlags[ bCSWL ] == 0 ) {		// クルーズSW接続?
	RETLW	00h				;	return 0						// 何も押していない
							; }
	CALL	GETCSW			; GETCSW() -> w						// クルーズSW状態取得

	ADDLW	00h				; if ( w == 0 ) return 1			// SET/COAST ボタン？
	BTFSC	STATUS,Z
	RETLW	01h

	XORLW	01h				; if ( w == 1 ) return 2			// RES/ACCEL ボタン？
	BTFSC	STATUS,Z
	RETLW	02h

	RETLW	00h				; return 0							// 何も押していない


;----------------
; ボタン番号取得
;----------------
; オーディオSW、クルーズSWの押しているボタン番号を返却する。
;
;返却値
; wレジスタ
;	 0 ... (何も押していない)
;	 1 ... V-
;	 2 ... V+
;	 3 ... SET
;	 4 ... RES
;	 5 ... ▲
;	 6 ... ▼
;	 7 ... MOD
;	 8 ... MUT
;	 9 ... CAN
;	10 ... Onf

GETSWNO
	BTFSS	fFlags,bASWL	; if ( fFlags[ bASWL ] == 1 ) {		// オーディオSW接続？
	GOTO	GETSWNO_J1

	CALL	GETASW			;	GETASW() -> fWork				// オーディオボタン取得
	MOVWF	fWork
	MOVLW	high ASW_TBL	;	ASW_TBL(fWork) -> w				// 押したオーディオボタンに対応する
	MOVWF	PCLATH			;									//  ボタン番号を取得
	MOVF	fWork,w
	CALL	ASW_TBL
	
	ADDLW	0h				;	if ( w != 0 ) return			// 何か押していたらボタン番号(w)を
	BTFSS	STATUS,Z		;									//  返却
	RETURN

GETSWNO_J1					; }
	BTFSS	fFlags,bCSWL	; if ( fFlags[ bCSWL ] == 0 ) {		// クルーズSW接続？
	RETLW	0h				;	return 0						// 何も押していないとして終了
							; }
	CALL	GETCSW			; GETCSW() -> fWork					// クルーズボタン取得
	MOVWF	fWork
	MOVLW	high CSW_TBL	; CSW_TBL(fWork) -> w				// 押したクルーズボタンに対応する
	MOVWF	PCLATH			;									//  ボタン番号を取得
	MOVF	fWork,w
	CALL	CSW_TBL

	RETURN					; return							// ボタン番号(w)を返却
	

;----------------
; EEPROM読み込み
;----------------
; wレジスタ : 読み込みアドレス
; wレジスタ : 読み込みデータ

ROMREAD

	BSF		STATUS,RP0		; 1 -> STATUS[ PR0 ]				// ▼バンク１に切替え

	MOVWF	EEADR			; w -> EEADR						// EEPROMアドレス設定
	BSF		EECON1,RD		; 1 -> EECON1[ RD ]					// 読み込み
	MOVF	EEDAT,w			; EEDAT -> w						// EEPROM読み込み値 -> w	

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	RETURN

;--------------
; EEPROM書込み
;--------------
; EEPROMの指定アドレス（fROMAdr）にwレジスタの値を書き込む

ROMWRITE
	BSF		STATUS,RP0		; 1 -> STATUS[ PR0 ]				// ▼バンク１に切替え

	MOVWF	EEDAT			; w(データ) -> EEDAT				// 書き込みデータ設定

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	MOVF	fROMAdr,w		; fROMAdr(アドレス) -> W			// 書き込みアドレス設定

	BSF		STATUS,RP0		; 1 -> STATUS[ PR0 ]				// ▼バンク１に切替え

	MOVWF	EEADR			; w(アドレス) -> EEADR
	BSF		EECON1,WREN		; 1 -> EECON1[ WREN ]				// 書き込み許可
	BCF		INTCON,GIE		; 0 -> INTCON[ GIE ]				// 全割り込み拒否
	MOVLW	055h			; 55h -> EECON2						// EEPROM書き込み開始
	MOVWF	EECON2
	MOVLW	0AAh			; 0aah -> EECON2
	MOVWF	EECON2
	BSF		EECON1,WR		; 1 -> EECON1[ WR ]
	BSF		INTCON,GIE		; 1 -> INTCON[ GIE ]				// 全割り込み許可
ROMWRITE_L1					; while( EECON1[ WR ] == 1 ) {		// 書き込み完了待ち
	BTFSC	EECON1,WR	
	GOTO	ROMWRITE_L1		; }

	BCF		STATUS,RP0		; 0 -> STATUS[ PR0 ]				// ▲バンク０に切替え

	RETURN					; return


;---------------
; タイマリセット
;---------------
; タイマーの初期化を行う。

RSTTIMER
	CLRF	TMR0			; 0 -> TMR0							// TMR0の初期化
	MOVLW	d'3'			; 3 -> fCnt100m						// 100msecカウンタの初期化
	MOVWF	fCnt100m		;									// (32.77msを３回カウント=98.3ms)
	MOVLW	d'10'			; 10 -> fCnt1sec					// 1秒カウンタの初期化
	MOVWF	fCnt1sec		;									// (98.3msを１０回カウントする=983ms)
	CLRF	fTimer			; 0 -> fTimer						// タイマフラグの初期化

	RETURN					; return


;----------------------------------
; （デバッグ用）ビットパターン確認
;----------------------------------
; WレジスタのビットパターンでシフトアップドライブSWとシフトダウンSWをON/OFFする
;    0 の場合、 シフトダウンSWをONにする
;    1 の場合、 シフトアップSWをONにする
;	★本サブルーチンはデバッグ用であり、通常使用しない

TLEDFLSH
	MOVWF	fTSvW			; w -> fTSvW						// Wレジスタ退避
	SWAPF	STATUS,W		; STATUS -> fTSvSTAT				// STATUSレジスタ退避
	MOVWF	fTSvSTAT		;									// (STATUSが変化しないようSWAPする)
	MOVF		GPIO,w		; GPIO -> fTSvGPIO					// GPIOレジスタ退避
	MOVWF	fTSvGPIO

	MOVF		fTSvW,w		; fTSvW -> fTDBGhD					// Wレジスタ -> ビットパターン
	MOVWF	fTDBGhD
	MOVLW	08h				; 8 -> fTDBGhBN						// ８ビットの出力
	MOVWF	fTDBGhBN

	MOVLW	03h				; TOUTOFF(3)						// 300msec両SWともOFFにする
	CALL		TOUTOFF

TLEDFLSH_L1					; do {

	RRF		fTDBGhD,f		; 	if ( fFlshDat[0] == 1 ) {		// ビット0が1の場合は
	BTFSC	STATUS,C		; 		fFlshDat >> 1 -> fFlshDat	// fFlshDatを１ビットシフト
	GOTO	TLEDFLSH_J1

	MOVLW	04h				;		TLOUT(4)					// 400msecシフトダウンSWをONにする
	CALL	TLOUT
	GOTO	TLEDFLSH_J2		;	} else {
							; 		fFlshDat >> 1 -> fFlshDat	// fFlshDatを１ビットシフト
TLEDFLSH_J1
	MOVLW	04h				;		THOUT(4)					// 400msecシフトアップSWをONにする
	CALL	THOUT

TLEDFLSH_J2					;	}
	MOVLW	04h				;	TOUTOFF(4)						// 100msec両SWともOFFにする
	CALL	TOUTOFF

	DECFSZ	fTDBGhBN,f		; } while ( --fFlshBN != 0 )		// 指定ビット数繰り返す
	GOTO	TLEDFLSH_L1

	MOVLW	0ah
	CALL	TOUTOFF

	MOVF	fTSvGPIO,w		; fTSvGPIO -> GPIO					// GPIOレジスタ復帰
	MOVWF	GPIO
	SWAPF	fTSvSTAT,W		; fTSvSTAT -> STATUS				// STATUSレジスタ復帰
	MOVWF	STATUS
	SWAPF	fTSvW,F			; fTSvW -> w						// Wレジスタ復帰
	SWAPF	fTSvW,W			;									// (STATUSが変化しないようSWAPを使う)

	RETURN					; return

;----------------------
;（デバッグ用）出力OFF
;----------------------
; wレジスタ×100msecの間、シフトアップSW、および、シフトダウンSWをOFFにする。
;	★本サブルーチンはデバッグ用であり、通常使用しない

TOUTOFF
	BCF		GPIO,bUpSW		; 0 -> GPIO[ bUpSW ]				// シフトアップSW OFF
	BCF		GPIO,bDwnSW		; 0 -> GPIO[ bDwnSW ]				// シフトダウンSW OFF
	GOTO	TWAITEVNT		; return TWAITEVNT() 

;--------------------
;（デバッグ用）H出力
;--------------------
; wレジスタ×100msecの間、シフトアップSWをON、シフトダウンSWをOFFにする。
;	★本サブルーチンはデバッグ用であり、通常使用しない

THOUT

	BSF		GPIO,bUpSW		; 1 -> GPIO[ bUpSW ]				// シフトアップSW ON
	BCF		GPIO,bDwnSW		; 0 -> GPIO[ bDwnSW ]				// シフトダウンSW OFF
	GOTO	TWAITEVNT		; return TWAITEVNT() 

;--------------------
;（デバッグ用）L出力
;--------------------
; wレジスタ×100msecの間、シフトアップSWをOFF、シフトダウンSWをONにする。
;	★本サブルーチンはデバッグ用であり、通常使用しない

TLOUT

	BCF		GPIO,bUpSW		; 0 -> GPIO[ bUpSW ]				// シフトアップSW OFF
	BSF		GPIO,bDwnSW		; 1 -> GPIO[ bDwnSW ]				// シフトダウンSW ON

;--------------------
;（デバッグ用）待ち
;--------------------
; wレジスタ×100msec待つ
;	★本サブルーチンはデバッグ用であり、通常使用しない

TWAITEVNT
	MOVWF	fTDBGWct		; w -> fTDBGWct						// w回繰り返す
TWAITEVNT_L2				; do {

	MOVLW 	028h			;	for( fTWcnt1=28h; fTWcnt1>0; fTWcnt1-- ) {
	MOVWF 	fTWcnt1			;									// 100msecのループ
TWAITEVNT_J2
	MOVLW 	0cfh			;		for( fTWcnt2=0cfh; fTWcnt2>0; fTWcnt2-- ) {
	MOVWF 	fTWcnt2
TWAITEVNT_L3	
	DECFSZ	fTWcnt2,f		;		}
	GOTO 	TWAITEVNT_L3
	DECFSZ 	fTWcnt1,f		;	}
	GOTO 	TWAITEVNT_J2

	DECFSZ	fTDBGWct,f		;	fTDBGWct--						// 指定回数繰り返す
	GOTO	TWAITEVNT_L2	; } while ( fTDBGWct > 0 )

	RETURN					; return

;==========
; テーブル
;==========

;-------------------------------------------
; LED調光データ
;   PWMのCCPR1Lに設定する値。
;   10^(n/10) n=0,1,2,...21 の四捨五入
;-------------------------------------------
	ORG		0300h

LED_TBL
	ADDWF	PCL,f
	
	RETLW 	D'1'
	RETLW 	D'1'
	RETLW 	D'2'
	RETLW 	D'2'
	RETLW 	D'3'
	RETLW 	D'3'
	RETLW 	D'4'
	RETLW 	D'5'
	RETLW 	D'6'
	RETLW 	D'8'
	RETLW 	D'10'
	RETLW 	D'13'
	RETLW 	D'16'
	RETLW 	D'20'
	RETLW 	D'25'
	RETLW 	D'32'
	RETLW 	D'40'
	RETLW 	D'50'
	RETLW 	D'63'
	RETLW 	D'79'
	RETLW 	D'100'
	RETLW 	D'126'
	RETLW 	D'0'		;データ終了マーク

;----------------------------------
; オーディオSW番号～ID変換テーブル
;----------------------------------

ASW_TBL
	ADDWF	PCL,f

	;		ID		オーディオSW
	;		-----------------------
	RETLW	01h		;Vol-
	RETLW	02h		;Vol+
	RETLW	05h		;▲
	RETLW	06h		;▼
	RETLW	07h		;Mode
	RETLW	08h		;Mute
	RETLW	00h		;(何も押していない)

;--------------------------------
; クルーズSW番号～ID変換テーブル
;--------------------------------

CSW_TBL
	ADDWF	PCL,f

	;		ID		クルーズSW
	;		-----------------------
	RETLW	03h		;SET/COAST
	RETLW	04h		;RES/ACCEL
	RETLW	09h		;On/Off
	RETLW	0Ah		;CANCEL
	RETLW	00h		;(未割当)
	RETLW	00h		;(未割当)
	RETLW	00h		;(何も押していない)


;========
; EEPROM
;========

;------------
; 各種設定値
;------------
; 16バイト分の設定値保存域
; （現バージョンでは１バイトしか使ってない）

	ORG	2100h

	DE	01h		;プリセット番号（01h:初期値）

;----------------------------------------	
; ステアリングボタン～機能ID割当テーブル
;----------------------------------------	

	;機能ID一覧
	;
	; 機能ID		クリック時割当機能			長押し時割当機能
	; ------------------------------------------------------------------
	; 0 (0000)		－							－
	; 1 (0001)		シフトダウン				－
	; 2 (0010)		シフトアップ				－
	; 3 (0011)		－							設定モードへ遷移
	; 4 (0100)		マニュアル					－
	; 5 (0101)		シフトダウン				マニュアル
	; 6 (0110)		シフトアップ				マニュアル
	; 7 (0111)		マニュアル+シフトダウン		ドライブ
	; 8 (1000)		ドライブ					－
	; 9 (1001)		シフトダウン				ドライブ
	; A (1010)		シフトアップ				ドライブ
	; B (1011)		マニュアル+シフトアップ		ドライブ
	; C (1100)		マニュアル/ドライブ切替		－
	; D (1101)		シフトダウン				マニュアル/ドライブ切替
	; E (1110)		シフトアップ				マニュアル/ドライブ切替
	; F (1111)		－							マニュアル/ドライブ切替
	;	 ||||
	;	 |||| [基本的な割当] （↓最初は単純だった…でも↑高機能化してしまった）
	;	 |||+-bit0 ... シフトダウン
	;	 ||+--bit1 ... シフトアップ
	;	 |+---bit2 ... マニュアル
	;	 +----bit3 ... ドライブ
	;
	; bit7-4 ... 初期値（誤った設定を戻す時に使用。bit3-0と同じ値を設定する。）
	;
	;例）プリセット１の機能割当
	;	"V-"と"SET"への割当 : 055h クリックでシフトダウン、長押しでマニュアル 
	;	"V+"と"RES"への割当 : 0AAh クリックでシフトアップ、長押しでドライブ 

	ORG	2110h

	;	V-   V+   SET  RES  ▲  ▼  MOD MUT  Onf CAN  <--（未割当）-->
	DE	000h,000h,000h,000h,00h,00h,00h,000h,00h,000h,0h,0h,0h,0h,0h,0h	;停止
	DE	077h,0BBh,000h,000h,00h,00h,00h,0CCh,00h,000h,0h,0h,0h,0h,0h,0h	;P1
	DE	011h,011h,022h,022h,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P2
	DE	022h,022h,011h,011h,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P3
	DE	011h,022h,011h,022h,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P4
	DE	022h,011h,022h,011h,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P5
	DE	077h,077h,0BBh,0BBh,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P6
	DE	0BBh,0BBh,077h,077h,00h,00h,00h,033h,00h,0CCh,0h,0h,0h,0h,0h,0h	;P7


;================
; プログラム終了
;================

	END
