; 16F88_LEDflasher.asm					2005/10/24 22:55:47

; RA7 LED-A3	output H				RB7 LED-A7	output H
; RA6 LED-A2	output H				RB6 LED-A6	output H
; RA5 MCLR	input					RB5 TX		output
; RA4 LED-A1	output H				RB4 LED-A5	output H
; RA3 LED-A0	output H				RB3 LED-A4	output H
; RA2 LED-K_C(Pat-No_C)	output(input) Pos.Log(Neg.Log)	RB2 RX		input
; RA1 LED-K_B(Pat-No_B)	output(input) Pos.Log(Neg.Log)	RB1 EEPROM SCL	output L/H
; RA0 LED-K_A(Pat-No_A)	output(input) Pos.Log(Neg.Log)	RB0 EEPROM SDA	output L/H
; TRISA		b'00100000'('00100111')			TRISB		b'00000100'

; 受信	

; 送信 	

	list		p=PIC16F88
	#include	<P16F88.INC>

	__CONFIG	_CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _INTRC_IO
	__CONFIG	_CONFIG2, _IESO_OFF & _FCMEN_OFF

	CBLOCK	20H
	work1			; メインルーチンの汎用
	work2			; メインルーチンの汎用
	i_work			; 割込み時の汎用
	RX_Dat			; 受信データ
	CNT1			; タイマカウンタ

	B_PortA			; PORTAバッファ
	B_PortB			; PORTBバッファ

	A_Stg			; LEDステージカウンタ
	Stg_Dat			; ステージデータ
	LED_No			; LED番号(0～7)
	LED_Bit			; K_CNTに対応する8個のLEDの点滅データ
	LED_Dat0		; K_CNTに対応する8個のLEDのステージデータ
	LED_Dat1		;   全8バイト
	LED_Dat2
	LED_Dat3
	LED_Dat4
	LED_Dat5
	LED_Dat6
	LED_Dat7

	K_CNT			; LED-Kカウンタ (74145の入力 0～7/1サイクル)
	KCyc_Max		; K_CNTサイクル(0～7)の繰返し数 (1～31)
	Stp_Max			; LEDステップ回数
	A_Stp			; LEDステップカウンタ
	Pat_No			; パターン番号(0～7)
	Next_Pat		; 連続パターン番号(0～7) Pat_No<>Next_Patの時、Next_Patを連続して実行する
				;   ex.パターン4のみ：Pat_No=4 Next_Pat=4 パターン1→3：Pat_No=1 Next_Pat=3

	AddrL			; EEPROM address L
	AddrH			; EEPROM address H
	N_Byte			; 書込み、読出しバイト数
	RW_Addr			; 書込み、読出しRAMアドレス
	RW_Byte			; 書込み、読出しバイト数(減算用)
	EP_Cnt			; 書込み、読出しbitカウンタ(8)
	EP_Dat			; 書込み、読出しデータ
	Err_Cnt			; エラーカウンタ 3で異常終了させる

	W_temp			; 割込み時の退避
	STATUS_temp
	FSR_temp
	pclath_temp
	ENDC

	org	0
init	bsf     STATUS,RP0	; sel bank 1
	movlw	b'01110000'
	movwf	OSCCON		; 8MHz
	goto	start

	org	4
	movwf   W_temp		; save W
	swapf	STATUS,W
	movwf	STATUS_temp	; save STATUS
	movf	FSR,W
	movwf	FSR_temp	; save FSR
	movf	PCLATH,W
	movwf	pclath_temp	; save PCLATH
	btfsc	INTCON,TMR0IF	; time out interruption ?
	call	intr
	movf	pclath_temp,W
	movwf	PCLATH		; restore PCLATH
	movf	FSR_temp,W
	movwf	FSR		; restore FSR
	swapf	STATUS_temp,W
	movwf	STATUS		; restore STATUS
	swapf	W_temp,F
	swapf	W_temp,W	; restore W
	retfie

start	clrw
	movwf	ANSEL		; set degital pin
	movlw	b'00100111'
	movwf	TRISA
	movlw	b'00000100'
	movwf	TRISB
	movlw	b'11010111'	; pullup off TMR0CLK=osc/4
	movwf	OPTION_REG	; prescaler=1/256  128us
	movlw	b'00100100'	; 許可 非同期 高速
	movwf	TXSTA
	movlw	d'25'		; 8MHz 25 at 19200bps
	movwf	SPBRG
	bcf     STATUS,RP0	; sel bank 0
	movlw	b'10010000'	; シリアル 連続
	movwf	RCSTA
	movlw	b'00000111'
	movwf	PORTA		; LED off
	movlw	b'00000000'	; LED off  EEPROM(SCL,SDA) Low
	movwf	PORTB
	movlw	work1
	movwf	FSR
start1	clrf	INDF		; clear memory
	incf	FSR,F
	movlw	pclath_temp+1
	subwf	FSR,W
	btfss	STATUS,Z
	goto	start1

	movf	PORTA,W
	xorlw	d'7'		; 負論理のSWのため、反転
	andlw	d'7'
	movwf	Pat_No
	bsf     STATUS,RP0	; sel bank 1
	movlw	b'00100000'
	movwf	TRISA
	bcf     STATUS,RP0	; sel bank 0
	call	Rd_Pat
	movlw	d'231'		; set timer value 256-3.2ms/0.128ms = 231
	movwf	TMR0		; TMR0 = 3.2ms
	movlw	b'10100000'	; GIE=0,TMR0IE=1
	movwf	INTCON		; interrupt enable

main	bcf	INTCON,7	; interrupt disable
	incf	A_Stg,F
	movlw	d'7'
	andwf	A_Stg,F
	movlw	b'00100100'
	movwf	B_PortB		; PORTBバッファ クリア
	movf	K_CNT,W
	andlw	d'7'
	movwf	B_PortA		; PORTAバッファ クリア	
	btfsc	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RX_IRQ

	clrf	LED_Bit
	clrf	LED_No
main1	movf	LED_No,W
	addlw	LED_Dat0
	movwf	FSR
	movf	INDF,W
	movwf	Stg_Dat

	movf	A_Stg,W
	btfss	STATUS,Z	; A_Stg=0?
	goto	main2
	movf	Stg_Dat,W
	btfsc	STATUS,Z	; Stg_Dat<>0?
	goto	main6
	goto	main5

main2	sublw	d'3'
	btfsc	STATUS,Z	; A_Stg<>3
	goto	main3
	movf	A_Stg,W
	sublw	d'6'
	btfss	STATUS,Z	; A_Stg=6
	goto	main4
main3	btfss	Stg_Dat,1	; Stg_Dat=2 or =3?
	goto	main6
	goto	main5

main4	movf	Stg_Dat,W	; A_Stg=1,2,4,5 or 7
	sublw	d'3'
	btfss	STATUS,Z	; Stg_Dat=3?
	goto	main6
main5	call	onLED		; LED on
	iorwf	LED_Bit,F
main6	incf	LED_No,F
	movf	LED_No,W
	sublw	d'8'
	btfss	STATUS,Z	; LED8個終わり?
	goto	main1

	btfsc	LED_Bit,7
	bsf	B_PortB,7	; LED-A7 on
	btfsc	LED_Bit,6
	bsf	B_PortB,6	; LED-A6 on
	btfsc	LED_Bit,5
	bsf	B_PortB,4	; LED-A5 on
	btfsc	LED_Bit,4
	bsf	B_PortB,3	; LED-A4 on
	btfsc	LED_Bit,3
	bsf	B_PortA,7	; LED-A3 on
	btfsc	LED_Bit,2
	bsf	B_PortA,6	; LED-A2 on
	btfsc	LED_Bit,1
	bsf	B_PortA,4	; LED-A1 on
	btfsc	LED_Bit,0
	bsf	B_PortA,3	; LED-A0 on

	movlw	b'00100100'
	movwf	PORTB		; LED off
	movf	K_CNT,W
	andlw	d'7'
	movwf	PORTA		; LED off
	call	Wait5		; 5μsec Wait

	movf	B_PortA,W
	movwf	PORTA
	movf	B_PortB,W	; LED出力
	movwf	PORTB

	movf	A_Stg,W
	sublw	d'7'
	btfsc	STATUS,Z	; A_Stg<>7?
	bsf	INTCON,7	; interrupt enable
	goto	main

; LED onデータ作成

onLED	movf	LED_No,W
	addwf	PCL,F
	DT	1H		; 0
	DT	2H		; 1
	DT	4H		; 2
	DT	8H		; 3
	DT	10H		; 4
	DT	20H		; 5
	DT	40H		; 6
	DT	80H		; 7

RX_IRQ	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W		; rcregレジスタから受信データを読み込む	
	movwf	RX_Dat
	sublw	52H
	btfss	STATUS,Z	; Rコマンド?
	goto	RX_IRQ1
RComm	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RComm
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	RX_Dat	
	sublw	d'7'
	btfss	STATUS,C	; パターン番号 0～7?
	goto	NAK_Tx

RComm1	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RComm1
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	work1
	sublw	d'7'
	btfss	STATUS,C	; Next_Pat 0～7?
	goto	NAK_Tx
	movlw	0A0H
	movwf	FSR
	movf	work1,W
	movwf	INDF

RComm2	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RComm2
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	work1
	movwf	work2
	btfsc	STATUS,Z	; ステップ回数>0?
	goto	NAK_Tx
	sublw	d'60'
	btfss	STATUS,C	; ステップ回数<=60?
	goto	NAK_Tx	
	incf	FSR,F
	movf	work1,W
	movwf	INDF
	rrf	work1,F
	rrf	work1,F
	movlw	0FH
	andwf	work1,F		; LEDデータ/64
	movf	work2,W
	andlw	d'3'
	btfss	STATUS,Z	; (LEDデータ mod 64)=0?
	incf	work1,F		; mod<>0 なら LEDデータ/64+1 切り上げ
	rlf	work1,F
	movlw	1EH		; LEDデータ/32
	andwf	work1,F

RComm3	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RComm3
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	work2
	btfsc	STATUS,Z	; KCyc_Max>0?
	goto	NAK_Tx
	sublw	d'31'
	btfss	STATUS,C	; KCyc_Max<=31?
	goto	NAK_Tx
	incf	FSR,F
	movf	work2,W
	movwf	INDF

	movf	RX_Dat,W
	movwf	AddrH
	rlf	AddrH,F
	rlf	AddrH,F
	movlw	1CH		; EEPROMアドレス計算
	andwf	AddrH,F
	clrf	AddrL
	movlw	0A0H
	movwf	RW_Addr
	movlw	d'3'
	movwf	N_Byte		; Next_Pat、ステップ回数とKCyc_MaxをEEPROMに書き込み
	call	EP_WRT		; EEPROMのAddrH、AddrLにRW_AddrからN_Byte数を書く 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常書き込み?
	goto	NAK_Tx
RComm4	call	EP_WR_End
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 書き込み完了?
	goto	RComm4
	movlw	d'6'		; ACK
	call	txd

	movlw	d'32'		; Page Write のロールオーバを回避するため
	movwf	AddrL		; 次のPageにする
RComm5	movlw	0A0H
	movwf	FSR
	movlw	d'32'
	movwf	N_Byte
RComm6	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	RComm6
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	INDF
	incf	FSR,F
	decfsz	N_Byte,F	; 32byte受信終わり?
	goto	RComm6

	movlw	0A0H
	movwf	RW_Addr
	movlw	d'32'
	movwf	N_Byte		; 点滅データ(32byte)EEPROMに書き込み
	call	EP_WRT		; EEPROMのAddrH、AddrLにRW_AddrからN_Byte数を書く 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常書き込み?
	goto	NAK_Tx
RComm7	call	EP_WR_End
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 書き込み完了?
	goto	RComm7
	movlw	d'32'
	addwf	AddrL,F
	btfsc	STATUS,C	; 下位アドレスオーバー?
	incf	AddrH,F		; 上位アドレス+1
	movlw	d'6'		; ACK
	call	txd
	decfsz	work1,F		; 全LEDデータ書き込み完了?
	goto	RComm5
	movf	RX_Dat,W
	movwf	Pat_No
	call	Rd_Pat		; パターン初期化
	goto	RX_End

RX_IRQ1	movlw	54H
	subwf	RX_Dat,W
	btfss	STATUS,Z	; Tコマンド?
	goto	RX_IRQ2
TComm	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	TComm
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	RX_Dat	
	sublw	d'7'
	btfss	STATUS,C	; パターン番号 0～7?
	goto	NAK_Tx
	movlw	54H		; T送信
	call	txd
	movf	RX_Dat,W
	movwf	AddrH
	call	txd		; パターン番号送信
	rlf	AddrH,F
	rlf	AddrH,F
	movlw	1CH		; EEPROMアドレス計算
	andwf	AddrH,F
	clrf	AddrL
	movlw	0A0H
	movwf	RW_Addr
	movlw	d'3'
	movwf	N_Byte
	call	EP_RED		; EEPROMのAddrH、AddrLからN_Byte数をRW_Addrへ読込む 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常読込む?
	goto	NAK_Tx
	movlw	0A0H
	movwf	FSR
	movf	INDF,W
	call	txd		; Next_Pat 送信

	incf	FSR,F
	movf	INDF,W
	movwf	work1
	call	txd		; ステップ回数 送信

	rrf	work1,F
	rrf	work1,F
	movlw	0FH
	andwf	work1,F		; LEDデータ/64
	movf	INDF,W
	andlw	d'3'
	btfss	STATUS,Z	; (LEDデータ mod 64)=0?
	incf	work1,F		; mod<>0 なら LEDデータ/64+1 切り上げ
	rlf	work1,F
	movlw	1EH		; LEDデータ/32
	andwf	work1,F

	incf	FSR,F
	movf	INDF,W
	call	txd		; KCyc_Max 送信

	movlw	d'32'		; Page Write のロールオーバを回避するため
	movwf	AddrL		; 次のPageにする
TComm1	movlw	0A0H
	movwf	RW_Addr
	movlw	d'32'
	movwf	N_Byte
	call	EP_RED		; EEPROMのAddrH、AddrLからN_Byte数をRW_Addrへ読込む 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常読込む?
	goto	NAK_Tx

	movlw	0A0H
	movwf	FSR
TComm2	movf	INDF,W
	call	txd
	incf	FSR,F
	decfsz	N_Byte,F	; 32byte送信終わり?
	goto	TComm2
	movlw	d'32'
	addwf	AddrL,F
	btfsc	STATUS,C	; 下位アドレスオーバー?
	incf	AddrH,F		; 上位アドレス+1
	decfsz	work1,F		; 全LEDデータ送信終わり?
	goto	TComm1
	movlw	d'6'		; ACK
	call	txd
	goto	RX_End

RX_IRQ2	movlw	4BH
	subwf	RX_Dat,W
	btfss	STATUS,Z	; Kコマンド?
	goto	RX_IRQ3
KComm	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	KComm
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	btfsc	STATUS,Z	; K_CNTサイクル(0～7)の繰返し数>0?
	goto	NAK_Tx
	movwf	RX_Dat
	sublw	d'31'
	btfss	STATUS,C	; K_CNTサイクル(0～7)の繰返し数<=31?
	goto	NAK_Tx
	movf	RX_Dat,W
	movwf	KCyc_Max	; 1ステージ(msec)=25.6msec(3.2msec×8)×KCyc_Max
	movlw	d'6'		; ACK
	call	txd
	goto	RX_End

RX_IRQ3	movlw	50H
	subwf	RX_Dat,W
	btfss	STATUS,Z	; Pコマンド?
	goto	NAK_Tx
PComm	btfss	PIR1,RCIF	; USART 受信割り込みフラグビットチェック
	goto	PComm
	btfsc	RCSTA,FERR	; フレーミングエラーのチェック（1:エラー,0:正常）
	goto	frame
	btfsc	RCSTA,OERR	; オーバーランエラーのチェック（1:エラー,0:正常）
	goto	over
	movf	RCREG,W
	movwf	RX_Dat	
	sublw	d'7'
	btfss	STATUS,C	; パターン番号 0～7?
	goto	NAK_Tx
	movf	RX_Dat,W
	movwf	Pat_No
	movlw	d'6'		; ACK
	call	txd
	call	Rd_Pat		; パターン初期化
	goto	RX_End

frame
over	movf	RCREG,W
	bcf	RCSTA,CREN
	bsf	RCSTA,CREN

NAK_Tx	movlw	15H		; NAK
	call	txd
RX_End	clrf	A_Stp		; A_Stp初期化
	clrf	K_CNT		; K_CNT初期化
	goto	main

; ------------------------------ sub routine -------------------------------------

Rd_Pat	movf	Pat_No,W
	movwf	AddrH
	rlf	AddrH,F
	rlf	AddrH,F
	movlw	1CH		; EEPROMアドレス計算
	andwf	AddrH,F
	clrf	AddrL
	movlw	0A0H
	movwf	RW_Addr
	movlw	d'3'
	movwf	N_Byte
	call	EP_RED		; EEPROMのAddrH、AddrLからN_Byte数をRW_Addrへ読込む 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常読込む?
	goto	Rd_Pat
	movlw	0A0H
	movwf	FSR
	movf	INDF,W
	movwf	Next_Pat
	incf	FSR,F
	movf	INDF,W
	movwf	Stp_Max
	incf	FSR,F
	movf	INDF,W
	movwf	KCyc_Max	; 1ステージ=25.6msec(3.2msec×8)×KCyc_Max
	clrf	A_Stp		; A_Stp初期化
	clrf	K_CNT		; K_CNT初期化
	return

intr	movlw	d'231'		; set timer value 256-3.2ms/0.128ms = 231
	movwf	TMR0		; TMR0 = 3.2ms
	bcf	INTCON,TMR0IF	; clear timer int flag

	incf	K_CNT,F
	movf	K_CNT,W
	movwf	i_work
	rrf	i_work,F
	rrf	i_work,F
	rrf	i_work,F
	movf	i_work,W
	andlw	1FH
	subwf	KCyc_Max,W	; K_CNT/8がKCyc_Maxになったか？
	btfss	STATUS,Z
	goto	intr1
	clrf	K_CNT		; K_CNT初期化

	incf	A_Stp,F
	movf	A_Stp,W
	subwf	Stp_Max,W
	btfss	STATUS,Z	; ステップ回数=Stp_Max?
	goto	intr1
	clrf	A_Stp		; A_Stp初期化

	movf	Next_Pat,W
	subwf	Pat_No,W
	btfsc	STATUS,Z	; Next_Pat<>Pat_No?
	goto	intr1
	movf	Next_Pat,W
	movwf	Pat_No		; next Pat_No
	call	Rd_Pat

intr1	movf	Pat_No,W
	movwf	AddrH
	rlf	AddrH,F
	rlf	AddrH,F
	movlw	1CH
	andwf	AddrH,F
	swapf	A_Stp,W
	andlw	d'3'
	addwf	AddrH,F		; AddrH=Pat_No×4+(A_Stp/4×64)\256

	movf	K_CNT,W		; EEPROMアドレス計算
	movwf	i_work
	rlf	i_work,F
	rlf	i_work,F
	rlf	i_work,F
	movf	i_work,W
	andlw	38H
	addlw	d'32'		; Fix
	movwf	AddrL
	swapf	A_Stp,W
	andlw	0C0H
	addwf	AddrL,F		; AddrL=K_Cnt×8+32+(A_Stp/4×64) mod 256
	btfsc	STATUS,C	; AddrL<=256?
	incf	AddrH,F		; AddrH+1

intr2	movlw	0A0H
	movwf	RW_Addr
	movlw	d'8'
	movwf	N_Byte
	call	EP_RED		; EEPROMのAddrH、AddrLからN_Byte数をRW_Addrへ読込む 成功でW=0  失敗でW=0FFH
	andlw	0FFH
	btfss	STATUS,Z	; EEPROM 正常読込む?
	goto	intr2

	clrf	LED_No
intr3	movlw	0A0H
	addwf	LED_No,W
	movwf	FSR
	movf	INDF,W
	movwf	Stg_Dat

	movf	A_Stp,W
	xorlw	d'3'		; ステップ反転
	andlw	d'3'
	movwf	i_work
intr4	btfsc	STATUS,Z
	goto	intr5
	rrf	Stg_Dat,F	; LEDステージデータを下位2bitに移動する
	rrf	Stg_Dat,F
	decf	i_work,F
	goto	intr4

intr5	movlw	d'3'
	andwf	Stg_Dat,F
	movf	LED_No,W
	addlw	LED_Dat0
	movwf	FSR
	movf	Stg_Dat,W
	movwf	INDF
	incf	LED_No,F
	movf	LED_No,W
	sublw	d'8'
	btfss	STATUS,Z	; LED8個終了?
	goto	intr3
	return

; 5μsec Wait

Wait5	movlw	d'1'		;(4n+6)*1サイクル時間(4/Fosc)
	movwf	CNT1		;	8MHz 4/8=0.5μsec
Wloop	nop			;	5μsec(1)
	decfsz	CNT1,F
	goto	Wloop
	nop
	nop
	return

; 1Byte送信

txd	bsf     STATUS,RP0	; sel bank 1
	btfss	TXSTA,TRMT
	goto	txd
	bcf     STATUS,RP0	; sel bank 0
	movwf	TXREG
	return

; EEPROMのAddrH、AddrLにRW_AddrからN_Byte数を書く 成功でW=0  失敗でW=0FFHを返す

EP_WRT	clrf	Err_Cnt
EP_WR1	call	EP_init		; EEPROMの初期化 & スタートコード
	movlw	b'10100000'	; 書込み要求
	call	WR_Byte
	andlw	0FFH
	btfsc	STATUS,Z	; エラー？
	goto	EP_WR3
EP_WR2	incf	Err_Cnt,F
	movf	Err_Cnt,W
	sublw	d'3'
	btfss	STATUS,Z	; エラー3回？
	goto	EP_WR1
	bcf	PORTB,1		; SCL Low
	nop
	bcf	PORTB,0		; SDA Low
	retlw	0FFH		; W=0FFHで戻り

EP_WR3	movf	AddrH,W		; 上位アドレスを送る
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_WR2
	movf	AddrL,W		; 下位アドレスを送る
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_WR2

	movf	N_Byte,W
	movwf	RW_Byte		; データをN_Byte数送る
	movf	RW_Addr,W	; 0A0H
	movwf	FSR
EP_WR4	movf	INDF,W
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_WR2
	incf	FSR,F
	decfsz	RW_Byte,F	; N_Byte終了?
	goto	EP_WR4
				; ストップ信号を送る
	bcf	PORTB,0		; SDA Low
	nop
	bsf	PORTB,1		; SCL High
	nop
	bsf	PORTB,0		; SDA High
	nop
	bcf	PORTB,1		; SCL Low
	nop
	bcf	PORTB,0		; SDA Low
	retlw	d'0'		; W=0で戻り

; 書き終わりの判定  終了でW=0  未完でW=0FFHを返す

EP_WR_End
	call	EP_init		; EEPROMの初期化 & スタートコード
	movlw	b'10100000'	; 書き込み要求

; Wレジスタの値1ByteをEEPROMに送る。EEPROMからACKを受け取る。成功でW=0。ACKなしでW=0FFHを返す。

WR_Byte	movwf	EP_Dat		; データを保管
	movlw	d'8'
	movwf	EP_Cnt		; 8回くりかえす
WR_Byt1	bcf	PORTB,0		; SDA Low
	btfsc	EP_Dat,7
	bsf	PORTB,0		; SDA High
	nop
	rlf	EP_Dat,F
	bsf	PORTB,1		; SCL High
	nop
	bcf	PORTB,1		; SCL Low
	decfsz	EP_Cnt,F	; 終了判定
	goto	WR_Byt1		; この時点でEP_Cntは0
				; ACKの読み取り
	BANKSEL	TRISB		; Select Bank 1
	bsf	TRISB,0		; SDA(RB0)を入力にする
	BANKSEL	PORTB		; Select Bank 0
	bsf	PORTB,1		; SCL High
	nop
	btfsc	PORTB,0		; ACKが来た？
	decf	EP_Cnt,F	; いいえ EP_Cnt=0FFH  はい EP_Cnt=00
	bcf	PORTB,1		; SCL Low
	BANKSEL	TRISB		; Select Bank 1
	bcf	TRISB,0		; SDA(RB0)をを出力にする
	BANKSEL	PORTB		; Select Bank 0
	bcf	PORTB,0		; SDA Low
	movf	EP_Cnt,W	; 戻り値をWレジスタに入れる
	return

; EEPROMのAddrH、AddrLからN_Byte数をRW_Addrへ読込む 成功でW=0  失敗でW=0FFHを返す

EP_RED	clrf	Err_Cnt
EP_RD1	call	EP_init		; EEPROMの初期化 & スタートコード
	movlw	b'10100000'	; 書込み要求
	call	WR_Byte
	andlw	0FFH
	btfsc	STATUS,Z	; エラー？
	goto	EP_RD3
EP_RD2	incf	Err_Cnt,F
	movf	Err_Cnt,W
	sublw	d'3'
	btfss	STATUS,Z	; エラー3回？
	goto	EP_RD1
	bcf	PORTB,1		; SCL Low
	nop
	bcf	PORTB,0		; SDA Low
	retlw	0FFH		; W=0FFHで戻り

EP_RD3	movf	AddrH,W		; 上位アドレスを送る
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_RD2

	movf	AddrL,W		; 下位アドレスを送る
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_RD2
	call	STR_Bit		; スタートコード
	movlw	b'10100001'	; 読み取り要求
	call	WR_Byte
	andlw	0FFH
	btfss	STATUS,Z	; エラー?
	goto	EP_RD2
	movf	N_Byte,W
	movwf	RW_Byte
	movf	RW_Addr,W	; 0A0H
	movWf	FSR
EP_RD4
	BANKSEL	TRISB		; Select Bank 1
	bsf	TRISB,0		; SDA(RB0)を入力にする
	BANKSEL	PORTB		; Select Bank 0
	movlw	d'8'
	movwf	EP_Cnt
EP_RD5	rlf	EP_Dat,F
	bsf	PORTB,1		; SCL High
	bcf	EP_Dat,0	; bit=0
	btfsc	PORTB,0		; EEPROM bit=0?
	bsf	EP_Dat,0	; bit=1
	bcf	PORTB,1		; SCL Low
	decfsz	EP_Cnt,F	; 8bit終了?
	goto	EP_RD5
	movf	EP_Dat,W
	movwf	INDF
	incf	FSR,F
	decfsz	RW_Byte,F	; N_Byte終了?
	goto	EP_RD6
	goto	EP_RD7
				; ACKを送る
EP_RD6	
	BANKSEL	TRISB		; Select Bank 1
	bcf	TRISB,0		; SDA(RB0)を出力にする
	BANKSEL	PORTB		; Select Bank 0
	bcf	PORTB,0		; SDA Low
	nop
	bsf	PORTB,1		; SCL High
	nop
	bcf	PORTB,1		; SCL Low
	goto	EP_RD4
				; NAKを送る
EP_RD7	
	BANKSEL	TRISB		; Select Bank 1
	bcf	TRISB,0		; SDA(RB0)を出力にする
	BANKSEL	PORTB		; Select Bank 0
	bsf	PORTB,0		; SDA High
	nop
	bsf	PORTB,1		; SCL High
	nop
	bcf	PORTB,1		; SCL Low
	nop
				; STOPコードを送る
	bcf	PORTB,0		; SDA Low
	nop
	bsf	PORTB,1		; SCL High
	nop
	bsf	PORTB,0		; SDA High
	nop
	bcf	PORTB,1		; SCL Low
	nop
	bcf	PORTB,0		; SDA Low
	retlw	d'0'		; W=0で戻り

; EEPROMの初期化

EP_init
	BANKSEL	TRISB		; Select Bank 1
	bcf	TRISB,1		; 
	bcf	TRISB,0
	BANKSEL	PORTB		; Select Bank 0
	bcf	PORTB,1		; SCL(RB1) Low
	bsf	PORTB,0		; SDA(RB0)は上げておく	
	nop
STR_Bit				; スタートコードを送る
	bsf	PORTB,0		; SDA High
	nop
	bsf	PORTB,1		; SCL High
	nop
	bcf	PORTB,0		; SDA Low
	nop
	bcf	PORTB,1		; SCL Low
	return

	end
