;**** Sine wave DDS
;*
;* Title:		DDS using external DAC
;* Version:		1.00 (demo, no calib., presets, mute)
;* Target:		AT90S2313

.include "2313def.inc"

.org	0x200
.include "sin4.asm"		;Sine wave table

;***** Constantes

.equ	TVal	= 40		;Time base 4.000 uS
.equ	Cal_0	= 180143985	;Initial calibration value
.equ	Freq_0	= 100000	;Initial frequency x 0.01 Hz
.equ	Fmax	= 5000000	;F max x0.01 Hz
.equ	Fmin	= 100		;F min x0.01 Hz
.equ	Pos_0	= 3		;Initial edit position
.equ	T0Val	= -98		;x1024x0.0001=10mS program timer
.equ	KiniD	= 80		;x10mS Initial autorepeat delay 
.equ	KrepD	= 20		;x10mS Autorepeat rate
.equ	DebVal	= 3		;x10mS Debounce delay
.equ	BliVal	= 20		;Blink delay (x blink period)

;Keys codes:

.equ	COD_NO	=0		;keys are released
.equ	COD_UP	=1		;key "UP" pressed
.equ	COD_DN	=2		;key "DOWN" pressed
.equ	COD_LF	=4		;key "LEFT" pressed
.equ	COD_RT	=8		;key "RIGHT" pressed

;LCD special symbols

.equ	Blank	=0x00		;Blank
.equ	Ch_P	=0x0e		;Char "P"
.equ	Ch_F	=0x0b		;Char "F"
.equ	Ch_min	=0x0f		;Char "-"

;***** Variables

.DSEG	;data segment (internal RAM)

Dig:	.byte 10		;Display data (Digits 1..10, chars)
.equ	Dig0	=Dig+0		;8---------
.equ	Dig1	=Dig+1		;-8--------
.equ	Dig2	=Dig+2		;--8-------
.equ	Dig3	=Dig+3		;---8------
.equ	Dig4	=Dig+4		;----8-----
.equ	Dig5	=Dig+5		;-----8----
.equ	Dig6	=Dig+6		;------8---
.equ	Dig7	=Dig+7		;-------8--
.equ	Dig8	=Dig+8		;--------8-
.equ	Dig9	=Dig+9		;---------8

MulB:	.byte 7			;Multiply buffer
COD:	.byte 1			;Keyboard last code

;Frequency calibration value (RAM copy)
;Freq = Fval x Calib / 16777216
;Nominal Calib = 180143985
;for Ttimer = 4.000 uS

Cal:	.byte 4
.equ	CalibK	=Cal+0
.equ	CalibL	=Cal+1
.equ	CalibM	=Cal+2
.equ	CalibN	=Cal+3

;***** Global Register Variables

.def	temp0	=r0		;Used in SUM (with lpm)
.def	tsreg	=r1		;Used in SUM		

.def	PhaseK	=r2		;Phase code,used in SUM
.def	PhaseL	=r3		
.def	PhaseM	=r4
.def	PhaseN	=r5

.def	FreqK	=r6		;Frequency code (delta Phase),used in SUM
.def	FreqL	=r7
.def	FreqM	=r8
.def	FreqN	=r9

.def	DebTM	=r10		;Debounce timer
.def	KeyTM	=r11		;Keyboard timer
.def	BliTM	=r12		;Blink timer

.def	tempA	=r13		;Temporary register tempA
.def	tempB	=r14		;Temporary register tempB
.def	tempC	=r15		;Temporary register tempC

.def	FvalK	=r16		;Frequency value (x 0.01 Hz)
.def	FvalL	=r17
.def	FvalM	=r18

.def	FLAGS	=r19
.equ	D_UPD	=0		;Display update flag
.equ	NewPr	=1		;Keyboard new press flag
.equ	Edit	=2		;Edit mode flag
.equ	Blnk	=3		;Digit blank flag

.def	temp	=r20		;Temporary register temp
.def	tempX	=r21		;Temporary register tempX
.def	Cnt	=r22		;Temporary register Cnt
.def	Cnt1	=r23		;Temporary register Cnt1
.def	Del	=r24		;Temporary register Del

.def	Pos	=r25		;Cursor position

.def	Tm_10	=r26		;10ms timer
.equ	Blb	=5		;Blink bit

;r28,r29 used as Y-register
;r30,r31 used as Z-register in SUM

;***** Port Definitions

.equ	PB	= PORTB		;Port B
.equ	DIRB	= 0b11111111	;Port B direction
.equ	PUPB	= 0b00000000	;Port B pull-ups

.equ	PD	= PORTD		;Port D
.equ	DIRD	= 0b01000011	;Port D direction
.equ	PUPD	= 0b00111100	;Port D pull-ups

.equ	SD	= PD0		;Serial data
.equ	SC	= PD1		;Serial clock
.equ	K_RT	= PD2		;Key RIGHT 
.equ	K_DN	= PD3		;Key DOWN  
.equ	K_LF	= PD4		;Key LEFT
.equ	K_UP	= PD5		;Key UP
.equ	MSB	= PD6		;DAC MSB

;***** Macros

.macro	clbr	;clear bit in register
	cbr @0,exp2(@1)
.endm

.macro	stbr	;set bit in register
	sbr @0,exp2(@1)
.endm

.macro	bbrc	;branch if bit in register clear
	sbrs @0,@1
	rjmp @2
.endm

.macro	bbrs	;branch if bit in register set
	sbrc @0,@1
	rjmp @2
.endm

.macro	bbic	;branch if bit in I/O clear
	sbis @0,@1
	rjmp @2
.endm

.macro	bbis	;branch if bit in I/O set
	sbic @0,@1
	rjmp @2
.endm

;***** Interrupt Vectors

.CSEG	;Code segment

.org	0

	rjmp	INIT		;Reset Handle

;***** Timer1 output compare interrupt handle
;To minimize execution time handle is located
;just at vector address. It eliminates rjmp command.

.org	OC1addr

SUM:	in	tsreg,SREG	;Save status register
	add	PhaseK,FreqK	;Phase(0..31)=Phase(0..31)+Freq(0..31)
	adc	PhaseL,FreqL
	adc	PhaseM,FreqM
	adc	PhaseN,FreqN
	mov	ZL,PhaseM	;ZL <- Phase(16..23)
	mov	ZH,PhaseN	;ZH <- Phase(24..31)
	sbrc	PhaseN,2
	com	ZL		;ZL=!ZL if Phase.26==1
	sbrc	PhaseN,2
	com	ZH		;ZH=!ZH if Phase.26==1
	andi	ZH,0x03		;Table address is 10 bit width
	ori	ZH,0x04		;Table base is 0x0400 (0x200*2)
	lpm			;r0 <- table[Z]
	sbrc	PhaseN,3	
	rjmp	ph_ab		;jump if Phase.27==1
	
ph_cd:	com	r0		;r0=!r0
	cbi	PORTD,MSB	;To minimize glitch, clear DAC.9,
	out	PORTB,r0	;and then setup DAC.1 - DAC.8
	out	SREG,tsreg	;Restore status register
	reti

ph_ab:	out	PORTB,r0	;To minimize glitch, setup DAC.1 - DAC.8,
	sbi	PORTD,MSB	;and then set DAC.9
	out	SREG,tsreg	;Restore status register
	reti

;***** Program Execution Starts Here

INIT:	ldi	temp,RAMEND	;Locate stack
	out	SPL,temp
	
	ldi	temp,PUPB
	out	PORTB,temp	;Init PORTB and on/off pullup
	ldi	temp,DIRB	
	out	DDRB,temp	;Set PORTB direction
	
	ldi	temp,PUPD
	out	PORTD,temp	;Init PORTD and on/off pullup
	ldi	temp,DIRD
	out	DDRD,temp	;Set PORTD direction

;Variables init

	clr	FLAGS		;Clear all flags
	ldi	Pos,Pos_0	;Initial cursor position
	ldi	temp,COD_NO
	sts	COD,temp
	clr	BliTM		;Clear blink timer

;Periphery setup:

	ldi	temp,0x00
	out	TCCR1A,temp	;OC disable, PWM disable
	out	GIMSK,temp
	ldi	temp,0x40	
	out	TIFR,temp	;Clear pending timer interrupt
	out	TIMSK,temp	;Enable output compare interrupt
	ldi	temp,0x09	
	out	TCCR1B,temp	;Clear on compare match, CK/1

	ldi	temp,high(TVal-1) ;Load compare register
	out	OCR1AH,temp	
	ldi	temp,low(TVal-1)
	out	OCR1AL,temp
	
	ldi	temp,0x05
	out	TCCR0,temp	;CK/1024
	
;Initial delay 2S

	ldi	Cnt,133
DE3:	ldi	tempX,250
DE2:	ldi	temp,200
DE1:	dec	temp		;1
	brne	DE1		;2
	dec	tempX
	brne	DE2
	dec	Cnt
	brne	DE3

;Load calibratin value
		
	ldi	temp,Low(Cal_0)
	sts	CalibK,temp
	ldi	temp,High(Cal_0)		
	sts	CalibL,temp
	ldi	temp,Byte3(Cal_0)		
	sts	CalibM,temp
	ldi	temp,Byte4(Cal_0)		
	sts	CalibN,temp
	
;Load initial frequency value
	
	ldi	temp,Low(Freq_0)
	mov	FvalK,temp
	ldi	temp,High(Freq_0)
	mov	FvalL,temp
	ldi	temp,Byte3(Freq_0)
	mov	FvalM,temp
	
;Init internal variables

	rcall	MakeF		;Calculate Freq
	rcall	F2BCD		;Convert Fval to BCD
	stbr	FLAGS,D_UPD	;Set display update flag
	sei			;Enble global interrupt
	
;Main loop	
	
MAIN:	rcall	SCAN		;Scan keyboard
	lds	tempX,COD
	cp	tempX,temp	;Compare codes
	breq	Same		
	
	sts	COD,temp	;New code, save it
	ldi	temp,DebVal
	mov	DebTM,temp	;Load debounce timer
	stbr	FLAGS,NewPr	;Set new press flag
	rjmp	MA10
	
Same:	mov	tempX,temp
	tst	DebTM		;Check debounce timer
	brne	MA10		;Jump if no overflow
	
	bbrc	FLAGS,NewPr,Re	;NewPr=0, jump to repeat action
	ldi	temp,KiniD	;Load initial autorepeat delay
	mov	KeyTM,temp	;Load key timer
	rjmp	COD0		;Function processing
	
Re:	tst	KeyTM		;Check key timer
	brne	MA10		;Skip processing
	ldi	temp,KrepD
	mov	KeyTM,temp	;Reload key timer with autorepeat delay
	
;Control Functions Analysis and Processing
	
COD0:	cpi	tempX,COD_UP	;key UP
	brne	COD1
	rcall	KEY_UP
COD1:	cpi	tempX,COD_DN	;key DN
	brne	COD2
	rcall	KEY_DN
COD2:	cpi	tempX,COD_LF	;key LEFT
	brne	COD3
	rcall	KEY_LF
COD3:	cpi	tempX,COD_RT	;key RIGHT
	brne	COD4
	rcall	KEY_RT
	
COD4:	clbr	FLAGS,NewPr	;Clear new press flag
	
;Timer check

MA10:	in	temp,TIFR
	bbrc	temp,TOV0,MA50
	andi	temp,exp2(TOV0)
	out	TIFR,temp	;Timer 0 overflow flag clear
	ldi	temp,T0Val
	out	TCNT0,temp	;Timer 0 reload
	
	inc	Tm_10		;Advance 10 ms timer
	
	tst	DebTM		;Advance debounce timer 
	breq	MA41
	dec	DebTM

MA41:	tst	KeyTM		;Advance key timer
	breq	MA50
	dec	KeyTM
	
;Check blink timer

MA50:	bbrc	FLAGS,Edit,MA60	;Skip if not edit mode
	tst	BliTM
	brne	MA60		;Skip if no overflow
	clbr	FLAGS,Edit	;Clear edit flag
	stbr	FLAGS,D_UPD	;Set display update flag

;Update LCD
	
MA60:	rcall	LCD		;Update LCD
	rjmp 	MAIN		;Main loop

;***** Subroutines Area

;===== Key UP processing

KEY_UP:	bbrs	FLAGS,Edit,UP_F	;Frequency step up
	rjmp	E_Ent
	
;Frequency step up
	
UP_F:	rcall	Z_Pos		;Zero lower digits
	rcall	BCD_I		;Inc BCD value
	rcall	BCD2F		;BCD -> Fval
	rcall	Valid		;Validate Fval
	brtc	UP_OK
	rcall	F2BCD		;Correct BCD value
UP_OK:	rcall	MakeF		;Calculate Freq
	rjmp	E_Ent
	
;===== Key DOWN processing

KEY_DN:	bbrs	FLAGS,Edit,DN_F	;Frequency step up
	rjmp	E_Ent
	
;Frequency step down
	
DN_F:	rcall	Z_Pos		;Zero lower digits
	brts	No_d
	rcall	BCD_D		;Dec BCD value
No_d:	rcall	BCD2F		;BCD -> Fval
	rcall	Valid		;Validate Fval
	brtc	DN_OK
	rcall	F2BCD		;Correct BCD value
DN_OK:	rcall	MakeF		;Calculate Freq
	rjmp	E_Ent
	
;===== Key LEFT processing

KEY_LF:	bbrs	FLAGS,Edit,LF_F	;Position left
	rjmp	E_Ent
	
;Position left	
	
LF_F:	cpi	Pos,7
	breq	E_Ent
	inc	Pos		;Pos + 1
	rjmp	E_Ent

;===== Key RIGHT processing

KEY_RT:	bbrs	FLAGS,Edit,RT_F	;Position right
	rjmp	E_Ent
	
;Position right	
	
RT_F:	cpi	Pos,1
	breq	E_Ent
	dec	Pos		;Pos - 1
	rjmp	E_Ent

;Enter to edit mode

E_Ent:	stbr	FLAGS,Edit	;Set edit flag
	stbr	FLAGS,D_UPD	;Set display update flag
	ldi	temp,BliVal
	mov	BliTM,temp	;Blink timer reload
	clr	Tm_10		;Clear 10 ms timer (on blinking digit)
	ret

;Zero positions at right of cursor
;Input: Pos
;Out: [Dig...] = 0
;Out: T=0 if no action performed

Z_Pos:	mov	Cnt,Pos
	clt			;Clear T flag
Z_loop:	dec	Cnt
	breq	Z_done
	ldi	YH,high(Dig+10)	;Calculate pointer
	ldi	YL,low(Dig+10)
	sub	YL,Cnt
	sbci	YH,0
	ld	temp,Y
	tst	temp
	breq	Z_loop
	clr	temp
	st	Y,temp
	set			;Set T flag
	rjmp	Z_loop
Z_done:	ret	

;BCD buffer inc
;Input: Pos
;Out: [Dig+3]..[Dig+9]

BCD_I:	ldi	Cnt,8
	sub	Cnt,Pos		;Pos = 7..1 -> Cnt = 1..7 -> [Dig+3]..[Dig+9]
I_loop:	rcall	LD_Dig
	inc	temp
	cpi	temp,10
	brne	I_done
	clr	temp
	st	Y,temp
	dec	Cnt
	brne	I_loop
I_done:	st	Y,temp
	ret	
	
;BCD buffer dec
;Input: Pos
;Out: [Dig+3]..[Dig+9]

BCD_D:	ldi	Cnt,8
	sub	Cnt,Pos		;Pos = 7..1 -> Cnt = 1..7 -> [Dig+3]..[Dig+9]
D_loop:	rcall	LD_Dig
	dec	temp
	cpi	temp,-1
	brne	D_done
	ldi	temp,9
	st	Y,temp
	dec	Cnt
	brne	D_loop
D_done:	st	Y,temp
	ret	

;Load [Dig..] to temp

LD_Dig:	clr	temp
	ldi	YH,high(Dig+2)	;Calculate pointer
	ldi	YL,low(Dig+2)
	add	YL,Cnt
	adc	YH,temp
	ld	temp,Y		;Load digit from buffer
	ret
	
;Converts BCD to frequency value
;Input: [Dig+3]..[Dig+9] - BCD
;Out: FvalK,FvalL,FvalM

BCD2F:	ldi	YH,high(Dig+3)	;Load pointer
	ldi	YL,low(Dig+3)
	ld	FvalK,Y+
	clr	FvalL
	clr	FvalM
	ldi	Cnt,6
DoConv:	ld	temp,Y+
	rcall	mul10
	dec	Cnt
	brne	DoConv
	ret

;multiplies FvalK,FvalL,FvalM with 10 and adds temp 

mul10:	mov	tempA,FvalK	;make copy
	mov	tempB,FvalL
	mov	tempC,FvalM
	
	lsl	FvalK		;multiply original by 2
	rol	FvalL
	rol	FvalM
	
	rcall	Rl_ABC		;multiply copy by 2
	rcall	Rl_ABC		;multiply copy by 2 (4)
	rcall	Rl_ABC		;multiply copy by 2 (8)
			
	add	FvalK,tempA	;add copy to original
	adc	FvalL,tempB
	adc	FvalM,tempC
		
	add	FvalK,temp	;add temp
	ldi	temp,0
	adc	FvalL,temp
	adc	FvalM,temp
	ret	

Rl_ABC:	lsl	tempA		;multiply copy by 2
	rol	tempB		
	rol	tempC
	ret

;Fval validate
;If Fval>Fmax then Fval=Fmax
;If Fval<Fmin then Fval=Fmin
;Out: T = 0 if no action performed

Valid:	clt			;Clear T flag

	ldi	temp,Low(Fmax)	;Check for Fmax limit
	cp	FvalK,temp
	ldi	temp,High(Fmax)
	cpc	FvalL,temp
	ldi	temp,Byte3(Fmax)
	cpc	FvalM,temp
	brlo	Max_OK
	
	ldi	FvalK,Low(Fmax)	;Load max limit value
	ldi	FvalL,High(Fmax)
	ldi	FvalM,Byte3(Fmax)
	set			;Set T flag
	rjmp	V_done
	
Max_OK:	ldi	temp,Low(Fmin)	;Check for Fmin limit
	cp	FvalK,temp	
	ldi	temp,High(Fmin)
	cpc	FvalL,temp
	ldi	temp,Byte3(Fmin)
	cpc	FvalM,temp
	brsh	V_done
	
	ldi	FvalK,Low(Fmin)	;Load min limit value
	ldi	FvalL,High(Fmin)
	ldi	FvalM,Byte3(Fmin)
	set			;Set T flag

V_done:	ret	

;Converts frequency to BCD format
;Input: FvalK,FvalL,FvalM
;Out: [Dig+0]..[Dig+2] - blank, [Dig+3]..[Dig+9] - BCD

F2BCD:	push	tempX

	mov	tempA,FvalK
	mov	tempB,FvalL
	mov	tempC,FvalM
	
	ldi	Cnt,10
	ldi	YH,high(Dig)
	ldi	YL,low(Dig)
	clr	temp
ClrD:	st	Y+,temp		;output array clear
	dec	Cnt
	brne	ClrD

	ldi	Cnt,24		;input bits count
H_Loop:	lsl	tempA
	rol	tempB
	rol	tempC

	ldi	Del,7
	ldi	YH,high(Dig+10)
	ldi	YL,low(Dig+10)
S_Loop:	ld	temp,-Y
	in	tempX,SREG
	push	tempX		;Save C
	subi	temp,-0x03	;temp+3
	sbrs	temp,3
	ld	temp,Y
	pop	tempX
	out	SREG,tempX	;Restore C
	rol	temp
	clc			;C <- 0
	sbrc	temp,4
	sec			;C <- 1
	andi	temp,0x0f
	st	Y,temp
	dec	Del
	brne	S_Loop
	
	dec	Cnt
	brne	H_Loop

	pop	tempX
	ret
	
;Calculate Freq
;Freq = Fval x Calib / 16777216
;Nominal Calib = 180143985
;for Ttimer = 4.000 uS
;
;m = mc x mp
;mc - CalibK,L,M,N
;mp - FvalK,L,M -> [MulB+0]..[MulB+2]
;m  - [MulB+0]..[MulB+6]

MakeF:	push	tempX
	ldi	YH,High(MulB)
	ldi	YL,Low(MulB)
	ldi	Cnt,7
	clr	temp
ClrM:	st	Y+,temp		;Clear m		
	dec	Cnt
	brne	ClrM
	
	ldi	Cnt,24		;Load cycle counter
	mov	temp,FvalM
	lsr	temp
	sts	MulB+2,temp	;Init mp
	mov	temp,FvalL
	ror	temp
	sts	MulB+1,temp
	mov	temp,FvalK
	ror	temp
	sts	MulB+0,temp

M24_32:	brcc	NoAdd
	ldi	YH,High(MulB+3)
	ldi	YL,Low(MulB+3)
	ld	temp,Y
	lds	tempX,CalibK
	add	temp,tempX
	st	Y+,temp
	ld	temp,Y
	lds	tempX,CalibL
	adc	temp,tempX
	st	Y+,temp
	ld	temp,Y
	lds	tempX,CalibM
	adc	temp,tempX
	st	Y+,temp
	ld	temp,Y
	lds	tempX,CalibN
	adc	temp,tempX
	st	Y+,temp
	
NoAdd:	ldi	YH,High(MulB+7)
	ldi	YL,Low(MulB+7)
	
	ldi	Cnt1,7
RRY:	ld	temp,-Y
	ror	temp
	st	Y,temp
	dec	Cnt1
	brne	RRY
	
	dec	Cnt
	brne	M24_32

;FreqK,L,M,N = [MulB+3]..[MulB+6] + 0.5

	ldi	YH,High(MulB+2)
	ldi	YL,Low(MulB+2)
	ldi	Cnt,0x80
	ld	temp,Y+
	add	temp,Cnt
	clr	Cnt
	cli			;Interrupts disable
	ld	FreqK,Y+
	adc	FreqK,Cnt
	ld	FreqL,Y+
	adc	FreqL,Cnt
	ld	FreqM,Y+
	adc	FreqM,Cnt
	ld	FreqN,Y+
	adc	FreqN,Cnt
	sei			;Interrupts enable
	pop	tempX
	ret
	
;Loads 10 chars from RAM buffer (Dig) to LCD controller

LCD:	bbrc	FLAGS,Edit,LCDa	;Jump to display if not edit mode
	cpi	tempX,COD_NO
	brne	LCDa		;Jump to display if key pressed

	bbrc	Tm_10,Blb,Dblf	;Check bit Blb of 10 ms timer
	bbrs	FLAGS,Blnk,Lre	;Blb = 1, off blinking digit
	
	stbr	FLAGS,Blnk	;Set blank flag
	tst	BliTM		;Advance blink timer
	breq	LCD0
	dec	BliTM
	rjmp	LCD0

Dblf:	bbrc	FLAGS,Blnk,Lre	;Blb = 0, on blinking digit
	clbr	FLAGS,Blnk	;Clear blank flag
	rjmp	LCD0
	
LCDa:	clbr	FLAGS,Blnk	;Blinking not used, clear blank flag
	bbrc	FLAGS,D_UPD,Lre	;Check update flag
	
LCD0:	ldi	Cnt,10		;Load digits counter
	ldi	YH,high(Dig)	;Load pointer
	ldi	YL,low(Dig)
	clt	
LCD1:	ld	temp,Y+		;Load char

	bbrc	FLAGS,Edit,LCD4	;Skip if not edit mode
	cp	Cnt,Pos		;Check position
	brne	LCD4		;Edit position not match
	set
	bbrc	FLAGS,Blnk,LCD4	;Skip if digit must be on
	clr	temp		;Load blank code
	rjmp	LCD3		;Jump to display
	
LCD4:	tst	temp		;Check char for zero
	brne	LCD2		;non-zero char
	brtc	LCD3		;skip if leading zero
	ldi	temp,10		;non-leading zero, load "0" code
LCD2:	set			;set non-zero char flag
LCD3:	rcall	LCDLD		;Load LCD controller
	dec	Cnt		;Next digit
	brne	LCD1
	clbr	FLAGS,D_UPD	;Clear display update flag
Lre:	ret

;Loads char from temp to LCD controller

LCDLD:	push	Cnt
	ldi	Cnt,4
	swap	temp
LDL:	rol	temp
	brcs	LD1
LD0:	cbi	PORTD,SD
	rjmp	STR
LD1:	sbi	PORTD,SD
STR:	sbi	PORTD,SC
	ldi	Del,5
HNG1:	dec	Del
	brne	HNG1
	cbi	PORTD,SC
	ldi	Del,10
HNG2:	dec	Del
	brne	HNG2
	dec	Cnt
	brne	LDL
	ldi	Del,25
HNG3:	dec	Del
	brne	HNG3
	cbi	PORTD,SD
	pop	Cnt
	ret
		
;Local keyboard scan
;Out:	temp - scan code
;

SCAN:	clr	temp
	sbis	PIND,K_UP
	stbr	temp,0
	sbis	PIND,K_DN
	stbr	temp,1
	sbis	PIND,K_LF
	stbr	temp,2
	sbis	PIND,K_RT
	stbr	temp,3
	ret

	