
; 1 кнопка брелка выставляет лог1 на декодере вывод 5 у пика
; 2 кнопка сбрасывает в лог0 вывод 5 у пика
; реагировать только на эти кнопки 
; управлять только 1 выходом


;=====================================;
;  	       DECODER		      ;
;=====================================;

	LIST p=12f675
        __config b'11000001011100'
	include <p12f675.inc>

;=======================================================================
#define		TimeSync		0xBB		; 0.008 * 187 = 1.5 ms 
#define		TimeOutSet		0x32		; 0.4 ms	
#define		TimeOutClear		0x64		; 0.8 ms

;=======================================================================
#define		modeEnterSetup		0xA5
#define		modeSetup		0xA7
#define		modeProgBrelok		d'9'

#define		TRIS_DECODER		b'001011'
;=======================================================================
; #define		BUS		GPIO, 1

;=======================================================================
#define		dataBANK0	bcf	STATUS, RP0
#define		dataBANK1	bsf	STATUS, RP0

;=======================================================================
#define		EE_Master	0x04
#define		EE_Addr		0x10
#define		LEN_BR		d'90'
; структура данных в ЕЕПРОМ AddH AddL Stat
; LEN_BR должна быть кратка длине струтуры

;=======================================================================
Mode		equ 0x20

DataBus		equ 0x21
Counter		equ 0x22

OLDGPIO		equ 0x23
ReciveBit	equ 0x24
Switch		equ 0x25
Mask		equ 0x26

StatBr		equ 0x27
Tmp		equ 0x28	;

TimerRec	equ 0x29
CountKey	equ 0x2A
CountKey_h	equ 0x2B

Key		equ 0x2C	
prevKey		equ 0x2D	
sec		equ 0x2F

AddrHigh	equ 0x30
AddrLow		equ 0x31

ptr		equ 0x32	
eeDATA		equ 0x33	
statTemp	equ 0x34

countCode	equ 0x35

CBLOCK 0x37
Eeadr1
B88
ENDC


;=======================================================================

	org 0x00
;=======================================================================
Start:
	dataBANK1
	call	0x3FF
	movwf   OSCCAL          ; update register with factory cal value 

	movlw	b'00000010'	; d = 0.008 us
	movwf	OPTION_REG

	movlw	TRIS_DECODER
	movwf	TRISIO

	clrf	ANSEL
	movlw	b'00000001'
;	movlw	0xFF
	movwf	WPU

	movlw	b'00100000'	
;	movlw	b'10100111'	; input digital
	movwf	VRCON

;================
	dataBANK0

	movlw	b'00100001'
	movwf	T1CON

	movlw	b'00010100'
	movwf	CMCON

	clrf	INTCON

 	clrf	Key
	clrf	prevKey

	clrf	GPIO
	clrf	countCode

;======================================================================
	movlw	d'1'
	movwf	sec
	clrw
	call	Delay_s

	movlw	d'3'
	movwf	CountKey_h
        movlw	d'80'
	movwf	sec
	movwf	CountKey
TstEnterSetup:
	movlw	d'3'		; ЙНД ЯХМУПНХЛОСКЭЯЮ
	movwf	Switch
	call	ReadBit
	xorwf	Switch, f
	bz	modeEnterSetupL
TstSetupNext:
	decfsz	CountKey, f
	goto	TstEnterSetup

; НАШВМШИ ОСЯЙ
StartNorma:
	movlw	0x00
	clrf	GPIO
GoMain:
 	clrf	Key
	clrf	prevKey
	movwf	Mode
	clrf	CountKey

	goto	MainLoop

;======================================================================
modeEnterSetupL:

	call	ReadByte
	bz	TstSetupNext		; Error
	movfw	DataBus
	movwf	AddrHigh

	call	ReadByte
	bz	TstSetupNext		; Error
	movfw	DataBus
	movwf	AddrLow

	call	ReadByte
	bz	TstSetupNext		; Error

	movlw	EE_Master
	call	ReadEeprom
	comf	eeDATA, f
	bnz	TestMasterKeySetup
	movlw	EE_Master + 1
	call	ReadEeprom
	comf	eeDATA, f
	bnz	TestMasterKeySetup

	movfw	DataBus
        xorlw	0x16	; KeyPress
	bnz	TestMasterKeySetup

;=================================
; save master brelok
	clrf	GPIO
	movlw	d'254'
	call	Delay
	movlw	d'254'
	call	Delay
	movlw	0xFF
	movwf	GPIO

	movfw	AddrHigh
	movwf	eeDATA
	movlw	EE_Master
	call	WriteEeprom

	movfw	AddrLow
	movwf	eeDATA
	movlw	EE_Master + 1
	call	WriteEeprom

	movlw	0xA0
	movwf	eeDATA
	movlw	EE_Master + 2
	call	WriteEeprom

	goto	Start

;====================
TestMasterKeySetup:
	movlw	EE_Master
	call	ReadEeprom
	movfw	AddrHigh
	xorwf	eeDATA, f
	bnz	TstSetupNext
	movlw	EE_Master + 1
	call	ReadEeprom
	movfw	AddrLow
	xorwf	eeDATA, f
	bnz	TstSetupNext	; no master-brelok

GoModeProgBrelok:
	movlw	d'10'
	movwf	Tmp
LedSetup0: 
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	decfsz	Tmp, f
	goto	LedSetup0


	movlw	EE_Addr
	movwf	ptr

DelNextBrelok:
	movlw	0xFF
	movwf	eeDATA
	movfw	ptr
	call	WriteEeprom
	incf	ptr, f
	movlw	EE_Addr + LEN_BR + 1
	xorwf	ptr, w
	bnz	DelNextBrelok

	movlw	modeProgBrelok
	goto	GoMain

;======================================================================
ReadByte:		; Z = 1 - Error
	movlw	d'8'
	movwf	Counter

	clrf	DataBus
	movlw	d'1'
	movwf	Mask
ReciveNextBit:
	call	ReadBit
	movwf	Switch
	decf	Switch, f
	bz	RecSet
	decf	Switch, f
	bnz	RecError
	goto	ShiftMask

RecSet:	movfw	Mask
	addwf	DataBus, f
ShiftMask:
	clrc
	rlf	Mask, f
	decfsz	Counter, f
	goto	ReciveNextBit
	clrz
	retlw	0

RecError:
	setz
	retlw 	0
;======================================================================
ReadBit: clrwdt
	btfss	GPIO,0		; отслеживаем замыкание ножки
	call	EraseEPPROM  ;====

	movfw	OLDGPIO
	movwf	ReciveBit
	movfw	CMCON
	movwf	OLDGPIO
	xorwf	ReciveBit, f
	btfsc	ReciveBit, COUT
	goto	ChPort
	movfw	TimerRec
	subwf	TMR0, w
	movwf	ReciveBit
	movlw	d'235'
	subwf	ReciveBit, w
	bnc	ReadBit
	movlw	d'235'
	movwf	TimerRec
	subwf	TMR0, w
	movwf	TimerRec
	retlw	0      		; Error

ChPort:	movfw	TimerRec
	subwf	TMR0, w
	movwf	ReciveBit
	movfw	TMR0
	movwf	TimerRec

	movlw	(TimeOutSet  * d'75' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	0		; Error
	movlw	(TimeOutSet  * d'125' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	1		; ОПХЬКЮ "1"

	movlw	(TimeOutClear * d'75' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	0		;  Error
	movlw	(TimeOutClear * d'125' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	2		; ОПХЬЕК "0"

	movlw	(TimeSync * d'75' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	0		;  Error
	movlw	(TimeSync * d'125' / d'100')
	subwf	ReciveBit, w
	skpc
	retlw	3		; ОПХЬЕК Sync

	retlw	0		;  Error

;======================================================================
RecFrame:
	call	ReadByte
	bz	jmpMainClearCount	;jmpMain		;  Error
	movfw	DataBus
	movwf	AddrHigh

	call	ReadByte
	bz	jmpMainClearCount	;jmpMain		;  Error
	movfw	DataBus
	movwf	AddrLow

	iorwf	AddrHigh, w
	bz	jmpMainClearCount	;jmpMain		;  Error - АПЕКНЙ Я МСКЕБШЛ ЮДПЕЯНЛ ГЮОПЕЫЕМ!!!

	call	ReadByte
	bz	jmpMainClearCount	;jmpMain		;  Error

	movlw	EE_Master
	call	ReadEeprom
	movfw	AddrHigh
	xorwf	eeDATA, f
	bnz	NoMasterBrelok
	movlw	EE_Master + 1
	call	ReadEeprom
	movfw	AddrLow
	xorwf	eeDATA, f
	bnz	NoMasterBrelok	; Master-brelok

	movlw	EE_Master + 0x02
	call	ReadEeprom
	movwf	StatBr

	goto	TestAddrOk

; Дополнительные брелки
;=============================
NoMasterBrelok:
	movlw	modeProgBrelok		; 
	xorwf	Mode, w			; 
	bz	LoadKeyPress		; 

;=========================
TestAddr:
	clrf	StatBr
	movlw	EE_Addr
	movwf	ptr
	goto	TestHighAddr

Add3:	incf	ptr, f
Add2:	incf	ptr, f
Add1:	incf	ptr, f
TestHighAddr:
	movlw	EE_Addr + LEN_BR
	xorwf	ptr, w
	bz	jmpMainClearCount	;jmpMain

	movfw	ptr
	call	ReadEeprom
	movfw	AddrHigh
	xorwf	eeDATA, f
	bnz	Add3

	incf	ptr, f
	movfw	ptr
	call	ReadEeprom
	movfw	AddrLow
	xorwf	eeDATA, f
	bnz	Add2

	; прочитать статус брелка из ЕЕПРОМ 
	incf	ptr, f
	movfw	ptr
	call	ReadEeprom
	movwf	StatBr

TestAddrOk:
	; код должен прийти 3 раза
	incf	countCode, f
	movlw	0x03
	xorwf	countCode, w
	bnz	jmpMain
	clrf	countCode


LoadKeyPress:
	movfw	DataBus		; Нажатые кнопки
	movwf	Key

jmpMain:
	goto	MainLoop


jmpMainClearCount:
	clrf	countCode
	goto	MainLoop

;=====================================================================
WriteEeprom:
; W   - EEADDR
; eeDATA - data

	dataBANK1
	movwf	EEADR
	dataBANK0
	movfw	eeDATA
	dataBANK1
	movwf	EEDATA

	bsf	EECON1, WREN
	bcf	INTCON, GIE
	movlw	0x55
	movwf	EECON2
	movlw	0xAA
	movwf	EECON2
	bsf	EECON1, WR
	bsf	INTCON, GIE

	dataBANK0
	movlw	d'20'
	call	Delay
	return

;======================================================================
ReadEeprom:
;       Inputs:   W   - Address
;       Outputs:  eeDATA - Data

	dataBANK1
	movwf	EEADR
	bsf	EECON1, RD
	movfw	EEDATA
	dataBANK0
	movwf	eeDATA
	clrwdt
	return

;======================================================================
Delay:	; Counter * 2 ms
	movwf	Counter

Dela0:	movlw	d'5'		
	movwf	TMR0
	clrwdt
Dela:	movfw	TMR0
	bnz	Dela
	decfsz	Counter, f
	goto	Dela0
	movlw	(TimeSync * d'125' / d'100') + 5
	movwf	TMR0

	retlw	0

;========================================================================
Delay_s:
	movfw	sec
	movwf	Tmp
	skpnz
	retlw	0x00

Delay_ss:
	movlw   d'4'
	movwf	Counter
Delay_m1S:
	movlw	d'250'
	movwf	DataBus
Delay_m2S:
	clrf	TMR0
	clrwdt

WaitDelaS:
	btfss	Key, 0
	goto	TstInp1S
	btfss	GPIO, 3
	retlw	0x01
TstInp1S:
	btfss	Key, 1
	goto	EndTstInpS
	btfsc	CMCON, COUT
	goto	ClearMaskS	
	incf	Mask, f
	movlw	d'50'
	xorwf	Mask, w
	skpnz
	retlw	0x2
	goto	EndTstInpS
ClearMaskS:
	clrf	Mask

EndTstInpS:
	btfss	TMR0, 7
	goto	WaitDelaS
	decfsz	DataBus, f
	goto	Delay_m2S
	decfsz	Counter, f
	goto	Delay_m1S

	decfsz	Tmp, f
	goto	Delay_ss

	retlw	0x00

;======================================================================
MainLoop:
	clrwdt

;======================================================================
Mode0:	
        movfw	Mode
	bnz	ModeSetupL

	movfw	Key
	bz	NoTstKey

	andlw	0x06
	xorlw	0x06
	bnz	NoPress2Key	
; нажаты две кнопки
	movlw	EE_Master
	call	ReadEeprom
	movfw	AddrHigh
	xorwf	eeDATA, f
	bnz	NoPress2Key
	movlw	EE_Master + 1
	call	ReadEeprom
	movfw	AddrLow
	xorwf	eeDATA, f
	bnz	NoPress2Key ; 
; нажаты две кнопки на мастер брелке

	movfw	CountKey
	sublw	d'50'
	bnc	GoModeProgBrelok
	
	movfw	Key
	movwf	prevKey		
	goto	NoTstKey
;=======================
NoPress2Key:
	clrf	CountKey
	clrf	TMR1H

	movfw	StatBr
	xorlw	0xA0
	bz	Contr2Key

	movfw	StatBr
	xorwf	Key, w
	bnz	Mode0End

	; однокнопочное управление
	movfw	prevKey
	bnz	Mode0End
	movfw	Key
	movwf	prevKey

	; переключить выход 
	btfss	GPIO, 2
	goto	SetOut
	bcf	GPIO, 2
	goto	Mode0End
SetOut: bsf	GPIO, 2
	goto	Mode0End

Contr2Key:
	; двухкнопочное управление 	
	btfsc	Key, 1	; Кнопка №1
	bsf	GPIO, 2
	btfsc	Key, 2	; Кнопка №2
	bcf	GPIO, 2

NoTstKey:
	movfw	TMR1H
	sublw	d'100'
	bc	Mode0End
	clrf	TMR1H
	movfw	prevKey
	skpz
	incf	CountKey, f
	clrf	prevKey

Mode0End:
	goto	TstBus
;========================================================================
ModeSetupL: ; SETUP
	movlw	modeSetup
        xorwf	Mode, w            	
	bnz	ModeProgBrelokL

	movfw	Key
	bz	TstBus

	goto	TstBus
;========================================================================
TstBus: clrf	Key
	movlw	d'3'		; Sync
	movwf	Switch
	call	ReadBit
	xorwf	Switch, f
	bnz	MainLoop

	goto	RecFrame

;========================================================================
ModeProgBrelokL: 
	movlw	modeProgBrelok	; d'9'
        xorwf	Mode, w            	
	bnz	ModeEnd

	clrf	CountKey

	movfw	Key
	bz	TstBus

	movlw	EE_Master
	call	ReadEeprom
	movfw	AddrHigh
	xorwf	eeDATA, f
	bnz	SaveEEPROM
	movlw	EE_Master + 1
	call	ReadEeprom
	movfw	AddrLow
	xorwf	eeDATA, f
	bnz	SaveEEPROM	; ЛЮЯРЕП-АПЕКНЙ

;========================= ЛЮЯРЕП АПЕКНЙ ===============================
	movfw	Key
	andlw	0x06
	xorlw	0x06
	bnz	NoExitSetup

ExitSetup:
	movlw	d'5'
	movwf	Tmp
LedSetup1: 
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay

	decfsz	Tmp, f
	goto	LedSetup1
	goto	StartNorma	; 

NoExitSetup:
	btfss	Key, 1
	goto	TestMaster1
	movlw	0x01
	movwf	statTemp

	; одно длинное моргание
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay
	goto	TestMasterEnd

TestMaster1:
	btfss	Key, 2
	goto	TestMasterEnd
	movlw	0xA0
	movwf	statTemp

	; два длинных моргания
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay

TestMasterEnd:

	goto	TstBus
;=========================
; Записать брелок в EEPROM
SaveEEPROM:
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	bcf	GPIO, 2

;======================
	movlw	EE_Addr - 0x02
	movwf	ptr

TestSaveNextBrelok:
	incf	ptr, f
	incf	ptr, f

	movlw	EE_Addr + LEN_BR
	xorwf	ptr, w
	bz	TstBus

	; ищем последнюю запись в EEPROM 
	movfw	ptr
	call	ReadEeprom
	incf	ptr, f
	movfw	eeDATA
	xorlw	0xFF
	bnz	NoSaveB
	movfw	ptr
	call	ReadEeprom
	movfw	eeDATA
	xorlw	0xFF
	bz	SaveBrelok ; запись пустая

NoSaveB:
	decf	ptr, f
	movfw	ptr
	call	ReadEeprom
	incf	ptr, f
	movfw	eeDATA
	xorwf	AddrHigh, w
	bnz	TestSaveNextBrelok

	movfw	ptr
	call	ReadEeprom
	movfw	eeDATA
	xorwf	AddrLow, w
	bnz	TestSaveNextBrelok
	goto	TstBus

SaveBrelok:
	decf	ptr, f
	movfw	AddrHigh
	movwf	eeDATA
	movfw	ptr
	call	WriteEeprom
	movfw	AddrLow
	movwf	eeDATA
	incf	ptr, f
	movfw	ptr
	call	WriteEeprom

	movfw	statTemp
	xorlw	0xA0
	bz	Save2Contr
	movfw	Key	
	goto	Save1Contr
Save2Contr:
	movlw	0xA0
Save1Contr:
	movwf	eeDATA
	incf	ptr, f
	movfw	ptr
	call	WriteEeprom

	movlw	d'20'
	movwf	Tmp
LedSetup2: 
	bsf	GPIO, 2
	movlw	d'70'
	call	Delay
	bcf	GPIO, 2
	movlw	d'70'
	call	Delay

	decfsz	Tmp, f
	goto	LedSetup2

	goto	TstBus
EraseEPPROM:
	; W   - EEADDR
	; eeDATA - data
	CLRW
	MOVLW  0	
WF:	
	MOVWF  Eeadr1
	MOVLW  0xFF
	MOVWF	B88	
	MOVF  Eeadr1,W
	Call ReadEeprom
	MOVF  eeDATA,W
	bcf STATUS,Z
	XORWF B88,W
	BTFSC STATUS,Z
	goto W2

W0:	
	CLRF eeDATA
	
	MOVLW  0xFF
	MOVWF	B88	
	MOVWF  eeDATA
	MOVF  Eeadr1,W
	Call WriteEeprom
W1:	
	MOVF  Eeadr1,W
	Call ReadEeprom
    clrwdt
	MOVF  eeDATA,W
	bcf STATUS,Z
	XORWF B88,W
	NOP
	NOP
	BTFSS STATUS,Z

	goto W1
		
W2: INCFSZ Eeadr1, W
	goto WF
	goto EraseOK
return

EraseOK:
	dataBANK0
	bcf	GPIO, 2
	movlw	d'250'
	call	Delay
	bsf	GPIO, 2
	movlw	d'250'
	call	Delay
	movlw	d'250'
	call	Delay

	bcf	GPIO, 2
return


;========================================================================
ModeEnd:
	clrf	Mode

	goto	TstBus
;========================================================================
	end
