;==========================================================================================================
; 
; CMtec RCRXDecoder 	 						copyright 2005				  	          v1.0 (2005-01-23)
; 
; Name: Christoffer Martinsson
; E-mail: cm@wsm.se 
;
; 7ch PPM decoder for RC-Receivers.
; Based on Atmel AT90S2313 or ATTiny2313 with 10 or 20Mhz crystal.
;	
; PORTB,PB0-PB7 assign to output ch 1 to ch 7 (ch 8 reserved)
; PORTD,PD2 assign to input PPM-signal from RX
; PORTD,PD3 assign to StoreButton
; PORTD,PD4 assign to LED 
;
; The inputsignal is decoded into two separate buffert locations in the SRAM. The output-routine work 
; with the buffert that the input-routine NOT work with. After a "good" frame is decoded the buffertPointer 
; is switch. This to ensure that a "good" pulseframe allways is available if a error should occur.
;
; Flowchart: RCRXDecoder.vsd
;
; * Up to 8 channels
; * 100step/ms resolution at 10Mhz, 200step/ms resolution at 20Mhz 
; * Allways a "good" output-signal 
; * Output is "Freezed" if error occurs
; * Failsafe sets predefined values if error not recovered in (recomended) 2sec (max 8sec/10Mhz, 4sec/20Mhz)
; * Failsafe-value easily changed by pressing a button
; * PulseValue filtered to a smooth average-value
; * Error/Glitch indicator
; 			
;==========================================================================================================
; Processor-type
.EQU 		AT90S2313 	= 1				
;EQU		ATTiny2313 	= 1 		

.NOLIST                					; Disable listfile generation
.ifdef AT90S2313
.INCLUDE 	"2313def.inc"
.else
.INCLUDE	"tn2313def.inc"
.endif
.LIST                  					; Reenable listfile generation

; General definitions 
; Adjust this numbers to make it work propely with your application

.EQU		XTAL			=10			; Used crystal (Mhz) (min 10Mhz)
.EQU		RecoveryNr		=1			; Number of "good" pulseFrames to recover from error-state
.EQU		NrOfChannels	=7			; Numbers of channels (max 8)
.EQU		FailSafeTime	=2			; Time before enter failsafe (sec) (max 8sec/10Mhz, 4sec/20Mhz)

; 8bit register	
.DEF		temp			=r16		; Temporary register
.DEF		nextSRAMAddress =r12		; Register for storing secondary SRAMAddress (buffert2)
.DEF		debounceFilter	=r15		; Button-debounce register
.DEF		timeout			=r17		; Timeout counter
.DEF		chAddressEE		=r18		; EEPROM channelAddress 
.DEF		chAddressIn		=r19		; Input channelAddress 
.DEF		chAddressOut	=r20		; Output channelAddress 
.DEF		chAddressFS		=r21		; Failsafe channelAddress 
.DEF		pulseError		=r22		; PulseErrorCounter
.DEF		pulseFlag		=r23		; Flag register

; "16bit" register
.DEF		frameCalcL		=r13		; Register for calculate FrameTime
.DEF		frameCalcH		=r14		
.DEF		tempL			=r24		; Temporary register 
.DEF		tempH			=r25		
.DEF		pulseInL		=r26		; InputPulseCounter
.DEF		pulseInH		=r27		
.DEF		pulseOutL		=r28		; OutputPulseCounter
.DEF		pulseOutH		=r29		

; pulseFlag bit-definitions
.EQU		SYNC			=0			; Sync found-Flag
.EQU		LEDredActive	=1			; LEDred Active-Flag
.EQU		LEDyellowActive	=2			; LEDyellow Active-Flag
.EQU		BuffertToUse	=3			; Buffert-Flag (0=buffert1, 1=buffert2)

; Output bit-definitions
.EQU		PPMSignal		=2			; PD2 Input for PPM-signal
.EQU		StoreButton		=3			; PD3 Input for StoreButton
.EQU		LEDred			=4			; PD4 Output for LEDred
.EQU		LEDyellow		=5			; PD4 Output for LEDyellow

; Memory definitions
.EQU		SRAMaddress1	=0x0060		; Startlocation for buffert1 in SRAM 
.EQU		SRAMAddress2 	=0x0074		; Startlocation for buffert2 in SRAM
.EQU		EEPROMaddress	=0x0000		; Startlocation for failsafe-storage in EEPROM

; Time definitions (timer0)
.EQU		FSTimeoutTime	=(2*XTAL*FailSafeTime)	; 1sec*FailSafeTime

; Time definitions (timer1)
.EQU		MinPulseTime	=(95*(XTAL/10))		; ~0,95ms
.EQU		MaxPulseTime	=(220*(XTAL/10))	; ~2,2ms
.EQU		MinSyncTime		=(400*(XTAL/10))	; ~4ms
.EQU		MaxSyncTime		=(1400*(XTAL/10))	; ~14ms
.EQU		FrameTime		=(1950*(XTAL/10))	; ~20ms

.CSEG											; CODE segment
.ORG 		0	
;==========================================================================================================
; Reset- and Interrupt-vectors
;==========================================================================================================
			RJMP 	Main				; Reset Handler
			RJMP 	Ex_Int0				; External Interrupt0 Handler
			RETI						; External Interrupt1 Handler
			RETI 						; Timer1 Capture Handler
			RJMP 	Timer_Int1			; Timer1 CompareA Handler
			RETI 			 			; Timer1 Overflow Handler
			RJMP 	Timer_Int0 			; Timer0 Overflow Handler
			RETI 				 		; USART0 RX Complete Handler
			RETI 						; USART0,UDR Empty Handler
			RETI 				 		; USART0 TX Complete Handler
			RETI 			 			; Analog Comparator Handler

.ifdef ATTiny2313

			RETI 						; Pin Change Interrupt
			RETI 				 		; Timer1 Compare B Handler
			RETI 						; Timer0 Compare A Handler
			RETI 						; Timer0 Compare B Handler
			RETI 						; USI Start Handler
			RETI 				 		; USI Overflow Handler
			RETI 						; EEPROM Ready Handler
			RETI 				 		; Watchdog Overflow Handler
.endif
;==========================================================================================================
; Macro
;==========================================================================================================
;----------------------------------------------------------------------------------------------------------
; Load16Temp 
; 
; Description: Load 16bit tempReg with 16bit @0-value
;
; Input: @0,@1
; ChangedReg: tempH,tempL
; UsedReg: tempH,tempL
;----------------------------------------------------------------------------------------------------------
.MACRO		Load16Temp				
			LDI				tempH,HIGH(@0)
			LDI				tempL,LOW(@0)
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Compare16Temp 
; 
; Description: Compare 16bit tempReg with 16bit @0,@1-reg
;
; Input: @0,@1
; ChangedReg: Carry
; UsedReg: tempH,tempL
;----------------------------------------------------------------------------------------------------------
.MACRO		Compare16Temp			 
			CP				tempL,@1
			CPC 			tempH,@0		
.ENDMACRO	
;----------------------------------------------------------------------------------------------------------
; Clear16Reg 
; 
; Description: Clear 16bit @0,@1-register
;
; Input: @0,@1
; ChangedReg: @0,@1
; UsedReg: -
;----------------------------------------------------------------------------------------------------------
.MACRO		Clear16Reg				
			CLR				@0
			CLR				@1
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Add16Reg 
; 
; Description: Add 16bit @2,@3 to 16bit @0,@1
;
; Input: @0,@1
; ChangedReg: @0,@1,Carry
; UsedReg: -
;----------------------------------------------------------------------------------------------------------
.MACRO		Add16Reg
			ADD				@1,@3
			ADC				@0,@2
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Sub16Reg 
; 
; Description: Subtract 16bit @2,@3 from 16bit @0,@1
;
; Input: @0,@1
; ChangedReg: @0,@1,Carry
; UsedReg: -
;----------------------------------------------------------------------------------------------------------
.MACRO		Sub16Reg
			SUB				@1,@3
			SBC				@0,@2
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; DivByTwo16Reg 
; 
; Description: Divide 16bit @0,@1 by two
;
; Input: @0,@1
; ChangedReg: @0,@1
; UsedReg: -
;----------------------------------------------------------------------------------------------------------
.MACRO		DivByTwo16Reg
			CLC
			ROR				@0
			ROR				@1
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Write16SRAM 
; 
; Description: Write data in 16bit @1,@2-reg to SRAM at position @0 
;
;	           (BuffertToUse-Flag: 0=buffert1, 1=buffert2)
;
; Input: @0,@1,@2
; ChangedReg: -
; UsedReg: ZL,pulseFlag
;----------------------------------------------------------------------------------------------------------
.MACRO		Write16SRAM
			LDI				ZL,LOW(SRAMaddress1)
			SBRC			pulseFlag,BuffertToUse
			ADD				ZL,nextSRAMAddress
			ADD				ZL,@0
			ST				Z+,@1
			ST				Z,@2
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Read16SRAM 
; 
; Description: Read data in SRAM at position @0 to 16bir @1,@2-reg 
;
;              (BuffertToUse-Flag: 0=buffert1, 1=buffert2)
;
; Input: @0,@1,@2
; ChangedReg: @1,@2
; UsedReg: ZL,pulseFlag
;----------------------------------------------------------------------------------------------------------
.MACRO		Read16SRAM
			LDI				ZL,LOW(SRAMaddress1)
			SBRC			pulseFlag,BuffertToUse
			ADD				ZL,nextSRAMAddress
			ADD				ZL,@0
			LD				@1,Z+
			LD				@2,Z				
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Write16EEPROM 
; 
; Description: Write data in 16bit @1,@2-reg to EEPROM at position @0
;
; Input: @0,@1,@2
; ChangedReg: -
; UsedReg: temp,EECR,EEARL,EEDR
;----------------------------------------------------------------------------------------------------------
.MACRO		Write16EEPROM
MWEEWait1:	SBIC			EECR,1
			RJMP			MWEEWait1
			LDI				temp,LOW(EEPROMaddress)
			ADD				temp,@0
			OUT				EEARL,temp
			OUT				EEDR,@1
			SBI				EECR,EEMWE
			SBI				EECR,EEWE

MWEEWait2:	SBIC			EECR,1
			RJMP			MWEEWait2
			LDI				temp,LOW(EEPROMaddress)
			ADD				temp,@0
			INC				temp
			OUT				EEARL,temp
			OUT				EEDR,@2
			SBI				EECR,EEMWE
			SBI				EECR,EEWE
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; Read16EEPROM 
; 
; Description: Read data in EEPROM at position @0 to 16bir @1,@2-reg
;
; Input: @0,@1,@2
; ChangedReg: @1,@2
; UsedReg: temp,EECR,EEARL,EEDR
;----------------------------------------------------------------------------------------------------------
.MACRO		Read16EEPROM
MREEWait1:	SBIC			EECR,1
			RJMP			MREEWait1
			LDI				temp,LOW(EEPROMaddress)
			ADD				temp,@0
			OUT				EEARL,temp
			SBI				EECR,EERE
			IN				@1,EEDR

MREEWait2:	SBIC			EECR,1
			RJMP			MREEWait2
			LDI				temp,LOW(EEPROMaddress)
			ADD				temp,@0
			INC				temp
			OUT				EEARL,temp
			SBI				EECR,EERE
			IN				@2,EEDR
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; StartTimer0 
; 
; Description: Start timer0. Prescale set to CK/1024
;
; Input: -
; ChangedReg: -
; UsedReg: temp,TCCR0
;----------------------------------------------------------------------------------------------------------
.MACRO		StartTimer0
			LDI				temp,0x05		
			OUT				TCCR0,temp			; Prescale set to CK/1024
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; StopTimer0 
; 
; Description: Stop timer0
;
; Input: -
; ChangedReg: -
; UsedReg: temp,TCCR0
;----------------------------------------------------------------------------------------------------------
.MACRO		StopTimer0
			CLR				temp
			OUT				TCCR0,temp
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; StartTimer1 
; 
; Description: Star timer1. Prescale set to CK
;
; Input: -
; ChangedReg: -
; UsedReg: temp,OCR1AH,OCR1AL,TCCR1B
;----------------------------------------------------------------------------------------------------------
.MACRO		StartTimer1
			LDI				temp,HIGH(100)
			OUT				OCR1AH,temp			
			LDI				temp,LOW(100)
			OUT				OCR1AL,temp
			LDI				temp,0x09
			OUT				TCCR1B,temp			; Prescale set to CK
.ENDMACRO	
;----------------------------------------------------------------------------------------------------------
; StopTimer1 
; 
; Description: Stop timer1
;
; Input: -
; ChangedReg: -
; UsedReg: temp,TCCR1B
;----------------------------------------------------------------------------------------------------------
.MACRO		StopTimer1
			CLR				temp
			OUT				TCCR1B,temp
.ENDMACRO	
;----------------------------------------------------------------------------------------------------------
; StoreTempOnStack 
; 
; Description: Store Status and temp-register on Stack
;
; Input: -
; ChangedReg: -
; UsedReg: temp,tempH,tempL,SREG
;----------------------------------------------------------------------------------------------------------
.MACRO		StoreTempOnStack
			PUSH			tempH
			PUSH			tempL
			PUSH			temp
			IN				temp,SREG
			PUSH			temp
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; RestoreTempFromStack 
; 
; Description: Restore Status and temp-register from Stack
;
; Input: -
; ChangedReg: temp,tempH,tempL,SREG
; UsedReg: temp,tempH,tempL,SREG
;----------------------------------------------------------------------------------------------------------
.MACRO		RestoreTempFromStack
			POP				temp
			OUT				SREG,temp
			POP				temp
			POP				tempL
			POP				tempH
.ENDMACRO
;----------------------------------------------------------------------------------------------------------
; SwitchBuffert
; 
; Description: Switches buffertPointer in SRAM (BuffertToUse-Flag: 0=buffert1, 1=buffert2)
;
; Input: -
; ChangedReg: pulseFlag
; UsedReg: temp,pulseFlag
;----------------------------------------------------------------------------------------------------------
.MACRO		SwitchBuffert
			LDI				temp,(1<<BuffertToUse)
			EOR				pulseFlag,temp						; Switch Buffert in SRAM
.ENDMACRO
;==========================================================================================================
; Interrupt routines
;==========================================================================================================
;----------------------------------------------------------------------------------------------------------
; Ex_Int0 
; 
; Description: Measure incoming pulse-value, filter it and then store it in SRAM.
;----------------------------------------------------------------------------------------------------------
Ex_Int0:	StoreTempOnStack

ChkSync:	SBRC			pulseFlag,SYNC						; Check if sync found
			RJMP			ChkError
			Load16Temp		MinSyncTime
			Compare16Temp	pulseInH,pulseInL					; Chrck if pulseIn > MinSyncTime
			BRCC			Error;
			Load16Temp		MaxSyncTime
			Compare16Temp	pulseInH,pulseInL					; Check if pulseIn < MaxSyncTime
			BRCS 			Error
			SBR				pulseFlag,(1<<SYNC)					; SYNC-Flag set
			CLR				chAddressIn							; Clear chAddressIn 

ChkSyncExit:Clear16Reg		pulseInH,pulseInL					; Clear pulseIn register
			RestoreTempFromStack
			RETI

ChkError:	Load16Temp		MinPulseTime
			Compare16Temp	pulseInH,pulseInL					; Check if pulseIn > MinPulseTime
			BRCC			Error
			Load16Temp		MaxPulseTime
			Compare16Temp	pulseInH,pulseInL					; Check if pulseIn < MaxPulseTime
			BRCS			Error

			CPI 			pulseError,0						; Check if pulseError == 0
			BREQ			NoError 
			DEC				pulseError							; Decrement pulseError
	
			INC				chAddressIn							; Increment pulseOut-address twice
			INC				chAddressIn
			CPI				chAddressIn,(NrOfChannels*2)		; Check if chAddress == (NrOfChannels*2)
			BRNE			ChkErrExit
			CBR				pulseFlag,(1<<SYNC)					; Clear SYNC-Flag
			Clear16Reg		frameCalcH,frameCalcL				; Clear FrameCalculation register
										
ChkErrExit:	Clear16Reg		pulseInH,pulseInL					; Clear pulseIn register
			RestoreTempFromStack
			RETI

Error:		CBR				pulseFlag,(1<<SYNC)					; SYNC-Flagg cleared
			SBR				pulseFlag,(1<<LEDredActive)			; LEDActive-Flag set
			LDI 			pulseError,(RecoveryNr*NrOfChannels); pulseError = 	(RecoveryNr*NrOfChannels)	
			
ErrorExit:	Clear16Reg		pulseInH,pulseInL					; Clear pulseIn register
			RestoreTempFromStack
			RETI

NoError:	CLR				timeout								; Clear timeout register
			CLR				chAddressFS							; Clear chAddressEE
			StartTimer0											; Start timer0

			Read16SRAM		chAddressIn,tempH,tempL				; Copy SRAM to temp
			Add16Reg		pulseInH,pulseInL,tempH,tempL		; Add past value to current value
			DivByTwo16Reg	pulseInH,pulseInL					; Divide value by two

			Write16SRAM 	chAddressIn,pulseInH,pulseInL		; Copy temp to SRAM
			Add16Reg		frameCalcH,frameCalcL,pulseInH,pulseInL; Add curren value to frameCalc register
	
			INC				chAddressIn							; Increment pulseOut-address twice
			INC				chAddressIn
			CPI				chAddressIn,(NrOfChannels*2)		; Check if chAddress == (NrOfChannels*2)
			BRNE			NoErrorExit
			CBR				pulseFlag,(1<<SYNC)					; Clear SYNC-Flag

			Load16Temp		FrameTime
			Sub16Reg		tempH,tempL,frameCalcH,frameCalcL	; Calculate frame-time
			Write16SRAM 	chAddressIn,tempH,tempL				; Write frame-time to SRAM

			SwitchBuffert										; Switch Buffert in SRAM
			CBR				pulseFlag,(1<<LEDredActive)			; LEDredActive-Flag cleared
			CBR				pulseFlag,(1<<LEDyellowActive)		; LEDywllowActive-Flag cleared

			Clear16Reg		frameCalcH,frameCalcL				; Clear frameCalc register

NoErrorExit:Clear16Reg		pulseInH,pulseInL					; Clear pulseIn register
			RestoreTempFromStack
			RETI			
;----------------------------------------------------------------------------------------------------------
; Timer_Int1   
; 
; Description: Increment pulseIn and pulseOut counter-registers              
;----------------------------------------------------------------------------------------------------------
Timer_Int1:	ADIW			pulseInL,1							; Increment pulseIn register
			ADIW			pulseOutL,1							; Increment pulseOut register

;----------------------------------------------------------------------------------------------------------
; Timer_Int0 
; 
; Description: Failsafe "watchdog". Restore pulse-value from EEPROM to SRAM if timeout occurs.
;----------------------------------------------------------------------------------------------------------
Timer_Int0:	StoreTempOnStack
			CPI				timeout,FStimeoutTime				; Check if timeout == FailsafeTime
			BREQ			CopyPulseES
			INC				timeout								; Increment timeout
			RestoreTempFromStack
			RETI

CopyPulseES:SBR				pulseFlag,(1<<LEDyellowActive)		; LEDActive-Flgg set
			Read16EEPROM	chAddressFS,tempH,tempL				; Copy EEPROM to temp
			Write16SRAM		chAddressFS,tempH,tempL				; Copy temp to SRAM
			SwitchBuffert										; Switch Buffert in SRAM
			Write16SRAM		chAddressFS,tempH,tempL				; Copy temp to SRAM
			SwitchBuffert										; Switch Buffert in SRAM
			INC				chAddressFS							; Increment chAddressFS twice
			INC				chAddressFS
			CPI				chAddressFS,((NrOfChannels*2)+2)	; Check if chAddressFS ==
			BRNE			NextPulseES							; ((NrOfChannels*2)+2)
			StopTimer0											; Stop timer0
		
NextPulseES:RestoreTempFromStack
			RETI

;==========================================================================================================
; Main
;==========================================================================================================
Main:		LDI				temp,LOW(RAMEND)
			OUT				SPL,temp							; Set StackPointeradress

			CLI													; Disable GlobalInterrupt

			LDI				temp,0xFF
			OUT				DDRB,temp							; All output on PORTB 
			SBI				DDRD,LEDred							; All input except PIN"LEDred" 
			SBI				DDRD,LEDyellow						; and PIN"LEDyellow" 
			SBI				PORTD,PPMSignal						; Enable pullup on INT0 input
			SBI				PORTD,StoreButton					; Enable pullup on StoreButton input

			LDI				temp,(1<<INT0)
			OUT				GIMSK,temp							; Enable external interrupt 0
			LDI				temp,(1<<ISC01)
			OUT				MCUCR,temp							; Trigg on falling edge
			LDI				temp,(1<<OCIE1A)|(1<<TOIE0)
			OUT				TIMSK,temp							; Enable internal timer0  
																; and timer1 interrupt
			CLR				chAddressOut						; Clear register
			CLR				chAddressIn
			CLR				chAddressFS
			CLR				timeout
			CLR				pulseFlag

			CLR				ZH									; Clear Z-Pointer MSB

			Clear16Reg		pulseInH,pulseInL					; Clear pulseIn-Reg
			Clear16Reg		pulseOutH,pulseOutL					; Clear pulseOut-Reg

			LDI				temp,(LOW(SRAMAddress2)-SRAMAddress1)			
			MOV				nextSRAMAddress,temp				; Set nextSRAMAddress
			
InitMemES:	Read16EEPROM	chAddressEE,tempH,tempL				; Copy pulse-value from EEPROM to SRAM
			Write16SRAM		chAddressEE,tempH,tempL
			SwitchBuffert										; Switch Buffert in SRAM
			Write16SRAM		chAddressEE,tempH,tempL
			SwitchBuffert										; Switch Buffert in SRAM
			INC				chAddressEE
			INC				chAddressEE
			CPI				chAddressEE,((NrOfChannels*2)+2); 
			BRNE			InitMemES

			CBR				pulseFlag,(1<<SYNC)					; Generate error
			SBR				pulseFlag,(1<<LEDredActive)
			LDI 			pulseError,(RecoveryNr*NrOfChannels)
			
			SEI													; Enable GlobalInterrupt

			StartTimer1											; Start timer1
			StartTimer0											; Start timer0
;----------------------------------------------------------------------------------------------------------
; MainLoop
;----------------------------------------------------------------------------------------------------------
MainLoop:	
; Generate output-pulses from SRAM to PORTB.
				
			CPI				chAddressOut,0						; Check if chAddressOut == 0
			BRNE			ReadOPulse	
			LDI				temp,0x01
			OUT				PORTB,temp							; PORTB = 0x01
			

ReadOPulse:	;SwitchBuffert										; Switch Buffert in SRAM
			Read16SRAM		chAddressOut,tempH,tempL			; Copy SRAM to temp
			;SwitchBuffert										; Switch Buffert in SRAM
			Compare16Temp	pulseOutH,pulseOutL					; Check if pulseOut < temp 
			BRCS			NextOPulse
			
			RJMP			ExitOPulse
			
NextOPulse:	CPI				chAddressOut,(NrOfChannels*2)		; Check if chAddressOut ==
			BREQ			ResetOPulse							; (NrOfChannels*2)
			IN				temp,PORTB
			LSL				temp
			OUT				PORTB,temp							; Roll PORTB left
			INC				chAddressOut						; Increment chAddressOut twice
			INC				chAddressOut
			Clear16Reg		pulseOutH,pulseOutL					; Clear pulseOut register
						
			RJMP			ExitOPulse

ResetOPulse:CLR				chAddressOut						; Clear chAddressOut register
			Clear16Reg		pulseOutH,pulseOutL					; Clear pulseOut register
ExitOPulse:	RJMP			MainLoop

;output yellow led-status
LEDy:		SBRC			pulseFlag,LEDyellowActive			; Check if LEDyellowActive is set
			RJMP			LEDyON
LEDyOFF:	CBI				PORTD,LEDyellow						; LEDyellow OFF (No Error)
			RJMP			LEDr
LEDyON:		SBI				PORTD,LEDyellow						; LEDyellow ON (Error detected)

;output red led-status
LEDr:		SBRC			pulseFlag,LEDredActive				; Check if LEDredActive is set
			RJMP			LEDrON
LEDrOFF:	CBI				PORTD,LEDred						; LEDred OFF (No Error)
			RJMP			CheckButton
LEDrON:		SBI				PORTD,LEDred						; LEDred ON (Error detected)
			RJMP			MainLoop			

CheckButton:SBIC			PIND,StoreButton					; Check if button pressed
			CLR				debounceFilter						; Clear debounce register
			INC				debounceFilter						; Incerment debounce register
			BRNE			MainLoop

BPressed:	CLI													; Disable GlobalInterrupt
			SBI				PORTD,LEDyellow						; Led ON (Work in progress)
			CLR				temp
			OUT				PORTB,temp							; PORTB = 0x00
			CLR				chAddressEE							; Clear chAddressEE register
			SwitchBuffert										; Switch Buffert in SRAM

CopyPulseSE:Read16SRAM		chAddressEE,tempH,tempL				; Copy SRAM to temp
			Write16EEPROM	chAddressEE,tempH,tempL				; Copy temp to EEPROM
			INC				chAddressEE							; Increment chAddressEE twice
			INC				chAddressEE	
			CPI				chAddressEE,((NrOfChannels*2)+2)	; Check if chAddressFE ==					
			BRNE			CopyPulseSE							; ((NrOfChannels*2)+2)
			CBI				PORTD,LEDyellow						; Led OFF (Work complete)
			SwitchBuffert										; Switch Buffert in SRAM

ButtonLoop:	SBIS			PIND,StoreButton					; Check if button pressed
			RJMP			ButtonLoop
			SEI													; Enable GlobalInterrupt
			RJMP			MainLoop

;==========================================================================================================
; END
;==========================================================================================================