///ATmega6 - počítadlo pro laserový terč

.include "m8def.inc"

.def adr = R24
.def trefeno = R21
.def strely2 = R22
.def strely = R23
.org 0x00
 	rjmp zac // skon na začátek programu
.org 0x18
	rjmp timer // skok na obsluhu přerušení
.org 0x100


//timer trvá asi 56us

timer: 	sts 0x0206, R16   //ulozeni cisla v R16
		ldi ZH, high(tab_adr<<1); // načtení adresy tabulky
		ldi ZL, low(tab_adr<<1); // do registru Z
		add ZL, adr
		lpm R25, Z

		andi R25,0b00001111	
		out PORTC, R25 // adresace modulu 7segmentovky
		ldi ZH, high(tabulka<<1); // načtení adresy tabulky
		ldi ZL, low(tabulka<<1); // do registru Z
		ldi YH, 0x01 // ukazuje do paměti na pozici jednotek
		ldi YL, 0x00
		mov r17, adr
		dec r17
		add YL, r17
		ld R16, Y
		add ZL, R16
		lpm R16, Z
		out PORTB, R16
	
		dec adr // dekrementace uživatelského počítadla
		brne dal
		ldi adr, 4
		clz					
//potud je multiplexování displeje
//dále je multiplexování diod pro zbývající střely
dal: 		cpi adr, 1  
			breq licha	//v polovině času svítí B7 a v polovině C4
			cpi adr, 3
			breq licha
			rjmp suda

licha: 		in R16, PINB
			ori R16,0b10000000
			out PORTB, R16
			in R16, PINC
			andi R16,0b11101111		//zapnuti B7 vypnuti C4
			out PORTC, R16
			ldi ZH, 02		//nacte pocet strel urcenych pro dany program (pozice x0202)
			ldi ZL, 02		 
			ld R16, Z		//v R16 je pocet zbyvajicich strel
		
			ldi ZH, high(tab_diod2<<1)	//nahrani adresy tabulky s cisly
			ldi ZL, low(tab_diod2<<1)
			add ZL, R16		
			lpm R17, Z		//v R17 je primo vystup na portD diod
			out PORTD, R17 
			rjmp int_konec
		

suda:		in R16, PINC
			ori R16,0b00010000
			out PORTC, R16
			in R16, PINB
			andi R16,0b01111111
			out PORTB, R16
			ldi ZH, 02		//nacte pocet strel urcenych pro dany program (pozice x0203)
			ldi ZL, 03		 
			ld R16, Z		//v R16 je pocet zbyvajicich strel
	
			ldi ZH, high(tab_diod<<1)	//nahrani adresy tabulky s cisly
			ldi ZL, low(tab_diod<<1)
			add ZL, R16		
			lpm R17, Z		//v R17 je primo vystup na portD diod
			out PORTD, R17 	
			rjmp int_konec
		

int_konec: 	ldi ZH, 02		//nahrání do R16 to co tam bylo předtím
			ldi ZL, 06
			ld R16, Z
			clz
			reti

////////////////////////////////////////////////////////////
//hlavni program
//////////////////////////////////////

zac:  	ldi R16, HIGH(RAMEND) // inicializace STACK POINTERu
		out SPH, R16
		ldi R16, LOW(RAMEND)
		out SPL, R16

		ldi R16, 0xFF	//B vystupni - jednotlivé segmenty displejů B0 - B6, B7 adresuje diody
		out DDRB, R16
		ldi R16, 0x1F	//C0-C4 vystupni - jednotlivé displeje C0 - C3 (C0 je 1. displej)  C4 adresuje diody      
		out DDRC, R16		// C5 vstupni komunikace s atmegou5
		ldi R16, 0xFF	//D0-D7 výstupni - napojení 10 ti diod
		out DDRD, R16
	
		//nastaveni casovace//
		ldi R17, 0x00
		out TCCR1A, R17
		ldi R16, 0x0B
		out TCCR1B, R16
		ldi R16, 0x00
		out OCR1AH, R16
		ldi R16, 0x30
		out OCR1AL, R16
		ldi R16, 0x10
		out TIMSK, R16 // povolení zdroje přerušení
		ldi adr, 0x04

		ldi R16, 0 // uložení čísla 0 na všechny
		sts 0x0100, r16 // pozice
		sts 0x0101, r16
		sts 0x0102, r16
		sts 0x0103, r16
		sts 0x0200, r16
		sts 0x0201, r16
		sts 0x0202, r16
		sts 0x0203, r16
		sts 0x0206, r16


		ldi R19, 0
		ldi strely2,0	//nulovani registru
		ldi strely, 0
		ldi trefeno, 0
		ldi R17, 0
		ldi R18, 0
		ldi R20, 0
		//zkotrolováno, můžu přeskočit
		rcall cekej200
///čekání na impuls programu 
impuls:			sei
				in 		R16, 	PINC
				andi 	R16, 	0b00100000	//ceka na horni hranu impulsu od atmegy5
				cpi 	R16, 	0b00100000
				brne impuls
				rcall cekejkontrola
				in 		R16, 	PINC
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00100000	//overi, jestli impuls trva aspoň 
				brne impuls					//60 mikrosekund

plus:			inc R19			//za každý impuls se přičte 1
				ldi R18, 0			//pocitani, jestli uz dlouho nebyl impuls		
plusceka:		in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00000000	//overi, že impuls ustal
				brne plusceka
				rcall cekejkontrola
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00000000	//pro jistotku 2x
				brne plusceka
plus_uz:		inc R18			//timto pocitadlem se zjisti jestli uz neuplynulo
				cpi R18, 150		//vice nez 100us od posledniho impulsu a tedy 
				breq program	//by bylo na case ukoncit prenost a spustit dany program
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000	//
				cpi 	R16, 	0b00100000
				rcall cekejkontrola
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00100000	//pro jistotu dvakrát kvůli šumu
				brne plus_uz
				rjmp plus
//program zjištěn, čekáme na start impuls
	
				
program:		sts 0x0200, R19	//uložení informace o probihajicim programu
program_p:		ldi ZH, 02
				ldi ZL, 0
				ld R19, Z

				cpi R19, 1		//podle toho kolik impulsu přišlo
				breq p1			//z řidici atmegy5	
				cpi R19, 2		//se vybere příslušný program 
				breq p2
				cpi R19, 3		
				breq p3
				cpi R19, 4
				breq p4
				cpi R19, 5
				breq p5
				cpi R19, 6
				breq p6
				cpi R19, 7
				breq p7
				cpi R19, 8
				breq p8

				rjmp impuls

p1: rjmp program1
p2: rjmp program2
p3: rjmp program3
p4: rjmp program4
p5: rjmp program5
p6: rjmp program6
p7: rjmp program7
p8: rjmp program8

				
program1: 	ldi R16, 10		//program 10 střel
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
			
program2: 	ldi R16, 20		//program 20 střel
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
		

program3: 	ldi R16, 5		//petiboj - nutne osetrit aby atmega5 poslala strelu jenom 
			sts 0x0201, R16	//pri uspesnem zasahu
			rcall bin2num2
            rjmp strela
			
program4: 	ldi R16, 5  	//biatlon
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
			
program5: 	ldi R16, 10		//biatlon stojka	
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
			

program6: 	ldi R16, 0
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
				
program7:	ldi R16, 0
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
			
program8: 	ldi R16, 0
			sts 0x0201, R16
			rcall bin2num2
            rjmp strela
		

/// v podprogramu strela se kontroluje, jestli přišel impuls sřely popř. impuls stop

strela:		in 		R16, 	PINC
			andi 	R16, 	0b00100000	//zaznamenani impulsu 
			cpi 	R16, 	0b00100000
			brne strela
			rcall cekejkontrola
			in 		R16, 	PINC
			andi 	R16, 	0b00100000	//overeni impulsu (100us) - porad i pro strelu log. 1
			cpi 	R16, 	0b00100000
			brne strela
			rcall cekej005
			rcall cekej005
			rcall cekej005
			rcall cekej005
			rcall cekej005
			in 		R16, 	PINC
			andi 	R16, 	0b00100000	//overeni impulsu
			cpi 	R16, 	0b00000000
			brne 	stop
			//ldi R19, 0
			rjmp strela_pocet
							//delsi impuls nez 650us - stop impuls
stop:		rjmp stop2		
			
strela_pocet:	//inc R19
				//cpi R19, 255
				//breq navrat
				in 		R16, 	PINC
				andi 	R16, 	0b00100000	//ceka na horni hranu impulsu od atmegy5
				cpi 	R16, 	0b00100000
				brne strela_pocet
				rcall cekejkontrola
				in 		R16, 	PINC
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00100000	//overi, jestli impuls trva aspoň 
				brne strela_pocet
				rjmp nulastrel				//200 mikrosekund

plus2:			rcall bin2num

nulastrel:		inc strely
							//za každý impuls se přičte 1 bod
				cpi strely, 100
				breq strelysto
pomocnik:		ldi R18, 0			//pocitani, jestli uz dlouho nebyl impuls		
plusceka2:		in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00000000	//overi, že impuls ustal
				brne plusceka2
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00000000	//pro jistotku 2x
				brne plusceka2
plus_uz2:		inc R18			//timto pocitadlem se zjisti jestli uz neuplynulo
				cpi R18, 255		//vice nez 400us od posledniho impulsu a tedy 
				breq navrat	//by bylo na case ukoncit prenost a spustit dany program
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000	//
				cpi 	R16, 	0b00100000
				in 		R16, 	PINC		
				andi 	R16, 	0b00100000
				cpi 	R16, 	0b00100000	//pro jistotu dvakrát kvůli šumu
				brne plus_uz2
				rjmp plus2

navrat:			rcall bin2num
				cli			//tento kousek vzdy zhasne dalsi diodu za strelu
				ldi ZH, 02		//nacte pocet strel urcenych pro dany program (pozice x0201)
				ldi ZL, 01		 
				ld R16, Z		//v R16 je pocet zbyvajicich strel
				dec R16
				cpi R16, 0xFF //znamenalo by to že v R16 už byla nula
				breq skip	//tím pádem bych už nedekrementoval počet zbývajících střel v paměti
				sts 0x0201, R16					
skip:			rcall bin2num2
				rjmp strela

strelysto:		ldi strely, 0
				inc strely2
				ldi R18, 0
				rjmp plusceka2


stop2:		rcall cekej200
			sei

reset:		in 		R16, 	PINC
			andi 	R16, 	0b00100000	//overeni impulsu
			cpi 	R16, 	0b00100000
			brne 	reset
			rcall cekej005
			rcall cekej005
			in 		R16, 	PINC
			andi 	R16, 	0b00100000	//pokud projde, znovu se restuje program
			cpi 	R16, 	0b00100000
			breq    konec
			rjmp reset

konec:   	ldi R16, 0 // uložení čísla 0 na všechny
			sts 0x0100, r16 // pozice
			sts 0x0101, r16
			sts 0x0102, r16
			sts 0x0103, r16
			ldi ZH, 02		//načte znovu cislo programu a znovu ho spusti dalsim vystrelem
			ldi ZL, 0
			ld R19, Z
			ldi strely, 0	//a vynuluje počet střel
			rcall cekej200
			rjmp program_p	//program zacina znovu od ukazani cisla na displeji

tab_adr:
.db 0, 0b00000001, 0b00000010, 0b00000100, 0b00001000

tabulka: 	
.db 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111,0b01101111
////poradi 0 1 2 3 ....

tab_diod: //tabulka k spusteni spravneho poctu diod zbyvajicich strel 
.db 0b00000000,0b00000001, 0b00000011, 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111, 0b11111111, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255
tab_diod2: //tabulka k spusteni spravneho poctu diod zbyvajicich strel 
.db 0b00000000,0b00000001, 0b00000011, 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111, 0b11111111, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,255, 255, 255, 255, 255, 255, 255, 255


/////////////////////////////////////////////////////////////////////////////
///zpozdeni////////////////////////////////////////
////////////////////////////////////////////////////////////////

cekej1:
			ldi R17, 5			//cca 1s (R17 5)
	d1:		ldi R18, 0
	d2:		ldi R19, 0
	d3:		dec R19
		
			brne d3
			dec R18
			brne d2
			dec R17
			brne d1
	
				ret

cekej200:	
			
			ldi R18, 0
	b1:		ldi R19, 0
	b2:		dec R19
		
			brne b2
			dec R18
			brne b1
			cli
				ret

cekej24:
			 						//cca 24mss (R17 neni)
			ldi R18, 60
	c1:		ldi R19, 0
	c2:		dec R19
		
			brne c2
			dec R18
			brne c1
			
		
	
				ret

cekej005:
			 						//cca 216us (R19 = 72)
			ldi R19, 72
	w1:		dec R19
			brne w1
			ret

cekejkontrola:
			 						//cca 54us (R19 = 18)
			ldi R17, 18
	v1:		dec R17
			brne v1
			ret

f1kHz:		 						//projede za 0,5ms 
			ldi R18, 5				//neboli vytvoří frekvenci 1kHz
	e1:		ldi R19, 32				//protože musim zapnout PORT, 0,5ms počkat
	e2:		dec R19					//vypnout port a znovu počkat takže dohromady 1ms
			brne e2	
			dec R18
			brne e1
			
			ret

f2kHz:		 						//projede za 0,24ms 
			ldi R18, 5				//neboli vytvoří frekvenci 2kHz
	a1:		ldi R19, 15
	a2:		dec R19
			brne a2	
			dec R18
			brne a1
			
			ret


//////////////////////////////////////////////
////děleni cisel na segmentovy display///
////////////////////////

bin2num: 	
			cli 				// zákaz přerušení
			mov R16, strely2		//nahraje strely2
			ldi ZH, 0x01		//pointer ukazuje na 0x0100
			ldi ZL, 0x00

			ldi r17, 0			

desitky: 	cpi r16, 10 // porovnání velikosti čísel
			brcs zap_des
			inc r17 // pokud je první číslo větší, tak
						// se k počítadlu přičte 1
			subi r16, 10 // od vstupního čísla se odečte dělitel
			rjmp desitky

zap_des: 	st Z+, R17		//na pozici 0x0100
			st Z+, R16		//na pozici 0x0101
			
			mov R16, strely //nahraje strely
			ldi R17, 0
		
desitky_strely: 	
			cpi r16, 10 // porovnání velikosti čísel
			brcs zap_des_strely
			inc r17 // pokud je první číslo větší, tak
						// se k počítadlu přičte 1
			subi r16, 10 // od vstupního čísla se odečte dělitel
			rjmp desitky_strely
zap_des_strely: 
			st Z+, R17		//pozice 0x0102
			st Z+, R16		//opzice 0x0103
			sei // povolení přerušení
			clz
			ret

///////////////////////////////////////////////
//////konec deleni////
////////////////////////////////////////
//////bin2num2 slouzi k deleni cisla zbyvajicich ran poctu ran na B7 a C4
////výsledkem jsou čísla od 0 do 8 na adresách 0x0202 a 0x0203

bin2num2: 	cli
			ldi ZH, 02		//nacte pocet strel urcenych pro dany program (pozice x0201)
			ldi ZL, 01		 
			ld R16, Z

			ldi ZH, 0x02		//pointer ukazuje na 0x0202
			ldi ZL, 0x02
			ldi r17, 0			

strelya: 	cpi r16, 8 		// porovnání velikosti čísel, vice než 8 znamena zapis do dalsiho kousku paměti
			brcs zap_strely
			inc r17 // pokud je první číslo větší, tak
						// se k počítadlu přičte 1
			subi r16, 8 // od vstupního čísla se odečte dělitel
			rjmp strelya

zap_strely:	cpi R17, 0			//1-16 (0 0)
			breq zapis0			
			cpi R17, 1
			breq zapis0
			cpi R17, 2			//17-24 (0 R16)
			breq zapis2
			cpi R17, 3			//25-32 (8 R16)
			breq zapis
			ldi R17, 8			//řeší zapsani spravněho počtu registrů rozsvícených did
			ldi R16, 8
			rjmp zapis			//33-64 (8 8)

zapis0:		ldi R17, 0
			ldi R16, 0
			st Z+, R17		//na pozici 0x0202
			st Z+, R16		//na pozici 0x0203
			rjmp zapis3
			
zapis:		ldi R17, 8
			st Z+, R17		//na pozici 0x0202
			st Z+, R16		//na pozici 0x0203
			rjmp zapis3
			
zapis2:		ldi R17, 0
			st Z+, R17		//na pozici 0x0202
			st Z+, R16		//na pozici 0x0203

zapis3:		sez // nastaví bit Z aby mi to pak breq po navrácení nebral
			sei
			ret

