.NOLIST
.INCLUDE "m32def.inc"
.LIST
; ATmega32
; Verze pro komunikaci s ostatnima periferiema: 0.1

; *-----------------------------------------*
; |         KONSTANTY/NASTAVENI             |
; *-----------------------------------------*
  ; Kody museji byt shodne pro buffer i pro main_uC

  ; Kody pro synchronizaci
.EQU sync_code_1 = $FA
.EQU sync_code_2 = $02
.EQU sync_code_3 = $DA

  ; Kody po resetu
.EQU reset_code_1 = $AA
.EQU reset_code_2 = $0D
.EQU reset_code_3 = $FC

  ; Kod, ktery se objevi na sbernici behem resetu
.EQU reset_in_progress = $2A


.EQU noise_level = 20	; Definuje, kdy je signal uz sum. Pokud bude mit signal
  ; mensi rozkmit, jak toto kriterium, bude vyhodnocen jako sum a nebude se
  ; merit perioda a dalsi navazujici veliciny


; Nasledujici prirovnani udavaji, na kterem radku se bude dana informace
  ; zobrazovat. Cisluje se od 0 do 7. Radek 0 byva vymezen pro symboly (pro
  ; tento radek je cely proces optimalizovan)
.EQU OSC_info_symbols_line = 0
.EQU OSC_info_time_base_line = 1
.EQU OSC_info_voltage_range_line = 2

.EQU OSC_info_Vpp_line = 3	; peak-to-pak
.EQU OSC_info_VMAX_line = 4	; maximalni napeti
.EQU OSC_info_VRMS_line = 5	; RMS
.EQU OSC_info_VAVG_line = 6	; AVG - prumer

.EQU OSC_info_period_line = 6	; perioda
.EQU OSC_info_freq_line = 7	; frekvence

.EQU OSC_info_freq_not_found_line = 6	; Informace o tom, ze nebylo mozne
  ; urcit frekvenci

  ; KOREKCE
.EQU Vol_mode_AD_correction = 11	; Korekce pro vnitrni A/D prevodnik
  ; Cislo musi byt ve dvojkovem doplnku. Pro pripad, ze se nepodari presne
  ; nastavit potenciometr, ktery vlastne koriguje "nulu"
.EQU Corr_VRMS_sub = 2	; Korekce RMS
.EQU Corr_OSC_mode = 2	; Korekce z ext. A/D prevodniku


.EQU Vol_mode_num_of_sampl = 35	; Velikost "okna" ve Voltage modu
  ; doporucene hodnoty jsou 2~127. Vyssi cislo jak 127 je sice mozne. ale
  ; musi se pocitat s tim, ze se zabere cela pamet na vzorky a navic se pouzije
  ; dalsi pamet (2bajty na jednen vzorek)!
.EQU Vol_mode_Info_X_pos = 0	; Xova souradnice pro informaci napisy
.EQU Vol_mode_Info_Act_line = 1	; radek pro informaci zobrazujici aktualni
  ; hodnotu
.EQU Vol_mode_Info_Max_line = 2	; Maximalni hodnota
.EQU Vol_mode_Info_Min_line = 3	; Minimalni hodnota
.EQU Vol_mode_Info_Avg_line = 4	; Prumerna hodnota

.EQU Vol_mode_Info_Range_line = 5	; Rozsah (+-15V napr.)
.EQU Vol_mode_Info_Coupling_line = 6	; Vazba: AC/DC
.EQU Vol_mode_Info_Process_Stopped_line = 7	; Informace o tom, ze byla
  ; stistena klavesa "run_stop"
.EQU Vol_mode_Info_Status_bar_X = 20	; Xova souradnice grafickeho ukazatele
  ; Udavat v mezich 0~63. Ukazatel napsan pro pravou polovinu LCD

; nejake dalsi definice....
; Pro vetsi pruznost kodu (lze pak napr. prehazovat poradi jednotlivych
; funkci). Navic pokud se rozhodneme pridat nejakou uzitecnou funkci a budeme
; ji chtit dat na zacatek menu, tak nemusime slozite predelavat cely kod.
; Staci pouze zmenit cislp poradi

	; Celkove poradi v menu
.EQU Trig_mode = 3
.EQU Num_of_sampl = 1
.EQU Draw_method = 2
.EQU Show_stats = 4
.EQU Waiting_int = 8
.EQU Animations = 5
.EQU About = 6

.EQU Help = 7
.EQU VAR_mode = 0	; Umoznuje merit napeti (pripadne i odpor, nebo proud,
  ; ale musi byt k tomu vybaven HW)

.EQU Last_option = 9	; definujeme, kdy se ma posouvani zastavit, resp. kam
  ; nema uz dojit

; *-----------------------------------------*
; |         DEFAULTNI NASTAVENI             |
; *-----------------------------------------*
  ; Tyto hodnoty de-facto urcuji v jakem stavu se bude pristroj ihned po
  ; zapnuti nachazet. 
.EQU default_number_of_samples = 200
.EQU default_TimeBase = 216
.EQU default_trigger_mode = 0
.EQU default_number_of_samples_mode = 0

.EQU default_waiting_interval_buffer = 150
.EQU default_waiting_interval_keyboard = 170
; *-----------------------------------------*
; |        POJMENOVANI REGISTRU             |
; *-----------------------------------------*
  ; Toto pojmenovani neni definitivni. U nekterych podprogramu potrebujeme
  ; pracovat s vice registry, takze si napriklad "vypujcime" time1 na ukladani
  ; nejakych mezivypoctu

.DEF tmp = R16	; prevazne pro docasna data
.DEF data = R17	; vetsinou jako argument pro podprogramy
.DEF CNT = R18	; pro citani
.DEF CNT2 = R19	; opet pro citani
.DEF CNT3 = R23	; a zase citac (neceho)

  ; Registry pro cas (podprogramy v wait_XMhz.asm)
.DEF time1 = R20
.DEF time2 = R21
.DEF time3 = R22

.DEF number = R24	; sem se vetsinou uklada cislo, ktere je ulozene
  ; v pameti bufferu
.DEF number2 = R25


; !!! Pokud budete mit nastavenou frekvenci vyssi jak 8Mhz, pak nezapomente
; upravit delku trvani "signal_enable" (pridate nop instrukce, nebo male
; zpozdeni, aby vse fungovalo spolehlive) !!!
; signal_enable je soucasti "graphic.asm". Samozrejme zmente a upravte si
; podle potreby i wait_xMhz (asi nebude aktualni, protoze jsem pracoval
; s wait_8Mhz. Presto by nemel byt problem si wait_8Mhz doupravit do
; wait_xMhz
; *-----------------------------------------*
; |   POJMENOVANI PORTU, PINU, RAM ADRESY   |
; *-----------------------------------------*

; *-----------------------------------------*
; |       SAMOTNY LCD DISPLEJ               |
; *-----------------------------------------*

.EQU RS = 0	; Pokud nekam napiseme RS, bude to same, jako kdyz bychom
; tam napsali 0 -> urcujeme na kterem pinu bude RS
.EQU RW = 1	; urcujeme na kterem pinu bude R/W
.EQU E = 2	; atd...
.EQU CS1 = 5
.EQU CS2 = 4
.EQU RST = 3

.EQU LED = 6	; samotna LED se nepouziva. Pouzival jsem ji pro debugovani

.EQU data_port = PortD	; Urcime si ktery port bude "datovy" pro LCD
.EQU data_port_in = PinD	; vstupni port (je take, takze se musi
  ; definovat). Pokud budeme chtit pracovat s timto portem jako vstupnim
  ; musime misto data_port uvest data_port_in a nadefinovat jej jako
  ; vstupni port
.EQU IO_data_LCD = DDRD		; v registru DDRD se definuje ktery pin
  ; bude vstupni a ktery vystupni. Pro zprehledneni kodu jsme si DDRD
  ; pojmenovali jako "IO_data_LCD"


.EQU control_port_LCD = PortB	; a ktery bude "ovladaci" pro LCD
.EQU IO_control_LCD = DDRB	; nutno nastavit podle vyse definovanych
  ; portu!!! Nelze vybirat nahodne. Zavisle na vyse definovanych portech!

.EQU Sleep_mode = 7	; Vypina A/D prevodnik a zastavi oscilator u bufferu
; *-----------------------------------------*
; |      DATOVE PINY PRO A/D PREVODNIK      |
; *-----------------------------------------*
.EQU IO_num = DDRC		; zase jako vyse
.EQU num_port = PortC		; na tento port se budou posilat cisla z
  ; AD prevodniku a nebo budeme z tohoto portu odesilat informace o casove
  ; zakladne
.EQU num_port_in = PinC		; zkratka pro vstup num_portu


; *-----------------------------------------*
; |       OVLADACI PINY, INTERNI A/D        |
; *-----------------------------------------*

.EQU control_port_ADC = PortA	; Tento port bude vyuzivany jako AD prevodnik
  ; pro funkci voltmetr a navic bude mit funkce pro prijimani dat z klavesnice
  ; a nastavovani priznaku "ready" atd...
.EQU control_port_ADC_in = PinA	; bude taky z casti vstupni, nize se definuje
.EQU IO_control_ADC = DDRA	; to same jako vyse, akorat pro jiny registr

; Pojmenovani pinu na control_port_ADC
.EQU main_ready = 0	; priznak pripravenosti ke cteni dat z bufferu
.EQU buffer_ready = 1	; priznak pripravenosti bufferu odeslat data


.EQU keyboard_serial_data = 4	; sem se budou posilat seriova data z klavesnice
; Dosahneme tim "pruznosti" kodu - muzeme zmenit poradi pinu (RS,RW,E,...)
; a portu (PortC, PortB, ...), pokud je potreba - a pokud to jde
.EQU main_ready_to_read_from_keyboard = 5	; priznak pripravenosti ke
  ; cteni dat z klavesnice

.EQU AD_signal = 6	; NF signál ze vstupu, upravený pro ATmega32 (pomoci
  ; NF zesilovace)
.EQU AD_trigger_level = 7	; 0~5V z potenciometru -> nutno prepocitavat
  ; pro kazdy rozsah

; *-----------------------------------------*
; |            ADRESY V SRAM                |
; *-----------------------------------------*
.EQU SRAM_user_start = $0060	; pocatek SRAM pro uzivatele. Adrese $0060
  ; jsme priradili jmeno SRAM_user_start


; Nastaveni pojmenovani urcitych adres v SRAM
.EQU TimeBaseSRAM = SRAM_user_start
  ; sem se bude ukladat informace o zvolene casove zakladne

.EQU keyboard_L_SRAM = TimeBaseSRAM+1	; sem se budou ukladat informace
  ; o stisklych tlacitkach 1-8
.EQU keyboard_H_SRAM = keyboard_L_SRAM+1	; sem se budou ukladat
  ; informace o stisklych tlacitkach 9-16
.EQU start_bit_errors_SRAM = keyboard_H_SRAM+1	; sem se ukladaji informace
  ; o spatne prenesenych datech mezi "keyboard_uC" a "main_uC"

.EQU Num_of_sampl_error_1_SRAM = start_bit_errors_SRAM+1	; pocet pripadu,
  ; kdy nesedi pocet vzorku nastaveny uzivatelem a nahrany bufferem
  ; (napr. v pripade, ze zadame bufferu velkou casovou zakladnu a v dobe, kdy
  ; zpracovava data a uzivatel zmeni pocet vzorku, tak dojde k tomuto jevu)
  ; Zde jsou ulozeny jendotky a desitky v podobe "Packed BCD"
.EQU Num_of_sampl_error_2_SRAM = Num_of_sampl_error_1_SRAM+1
  ; Zde jsou ulozeny stovky a tisice. To by melo stacit :D
.EQU Rx_data_buffer_not_valid_SRAM = Num_of_sampl_error_2_SRAM+1
  ; Pokud by prijata data nebyla "spravna", pak samozrejme nechceme, aby se
  ; zobrazila


.EQU range_SRAM = Rx_data_buffer_not_valid_SRAM+1	; sem se bude ukládat
  ; informace o tom, jaky je aktualne zvoleny rozsah
.EQU range_backup_SRAM = range_SRAM+1	; zaloha pro funkci "Stop/Run"

.EQU buffer_too_busy_SRAM = range_backup_SRAM+1	; sem se bude ukladat
  ; informace o tom, jestli je buffer vytizen na "dlouhou" dobu
.EQU Samples_offset_SRAM = buffer_too_busy_SRAM+1	; sem se bude ukladat
  ; informace o tom, o kolik samplu chceme zobrazeny signal posunout (0~255)

.EQU number_of_samples_SRAM = Samples_offset_SRAM+1	; dynamicky muzeme
  ; menit pocet vzorku a tim i rychlost nacitani dat do bufferu. Na druhou
  ; stranu si tim omezime moznost posuvu
.EQU number_of_samples_mode_SRAM = number_of_samples_SRAM+1

.EQU previous_mode_SRAM = number_of_samples_mode_SRAM+1
  ; sem se uklada informace jaky mod byl
  ; naposledy spusteny

.EQU trigger_INT_EXT_SRAM = previous_mode_SRAM+1	; sem se do LSB ulozi
  ; informace o tom, zda je zvolen interni, nebo externi synchronizace
  ; 0 - interni
  ; 1 - externi
.EQU trigger_INT_EXT_backup_SRAM = trigger_INT_EXT_SRAM+1

.EQU AC_DC_coupling_SRAM = trigger_INT_EXT_backup_SRAM+1	; Informace
  ; o vazbe na vstupu
  ; 0 - AC
  ; 1 - DC
.EQU AC_DC_coupling_backup_SRAM = AC_DC_coupling_SRAM+1

.EQU Trigger_single_mode_status_SRAM = AC_DC_coupling_backup_SRAM+1
  ; Pokud je zde nenulova hodnota, pak se "zatriggeruje" jednou

.EQU draw_mode_SRAM = Trigger_single_mode_status_SRAM+1
  ; typ vykreslovani prubehu na LCD
  ; 0 - points (body)
  ; 1 - vector (vektorove)
.EQU animations_mode_SRAM = draw_mode_SRAM+1	; Typ animace
  ; 0 - srazejici se atomy, nebo proste dve kulicky :D
  ; 1 - Matrix sporic
  ; 2 - nejaky jiny, ktery jeste nemam naprogramovany
.EQU help_option_SRAM = animations_mode_SRAM+1
  ; Napoveda pro uzivatele - jednotlive menu

.EQU main_menu_selected_option_I_SRAM = help_option_SRAM+1
  ; informace o vybrane moznosi
  ; v hlavnim menu (hlavni - prvni - moznost)
.EQU main_menu_selected_option_I_last_SRAM = main_menu_selected_option_I_SRAM+1
  ; Ulozi posledni zmenu. Je to vhodne v situacich, kdy nemusime provest
  ; refresh na LCD, kdyz jsme vlastne nic neudelali
.EQU main_menu_selected_option_II_SRAM = main_menu_selected_option_I_last_SRAM+1
  ; informace o vybrane pod-moznosti
.EQU main_menu_selected_option_II_last_SRAM = main_menu_selected_option_II_SRAM+1
  ; zaloha vyse uvedene promenne. Opet se chceme vyhnout zbytecnemu refreshi

.EQU main_menu_selected_option_III_SRAM = main_menu_selected_option_II_last_SRAM+1
  ; pripadne dalsi rozsireni
.EQU main_menu_selected_option_III_last_SRAM = main_menu_selected_option_III_SRAM+1
  ; zaloha tohoto rozsireni

.EQU main_menu_selected_option_IV_SRAM = main_menu_selected_option_III_last_SRAM+1
  ; dalsi rozsireni...


.EQU max_value_submenu_SRAM = main_menu_selected_option_IV_SRAM+1
  ; sem se bude prevazne ukladat info
  ; o maximalni mozne hodnote (napr. v menu Trigger mode to bude max. pocet
  ; moznosti triggeru)
.EQU min_value_submenu_SRAM = max_value_submenu_SRAM+1
  ; zase jako vyse, ale pro minimalni
  ; hodnotu. Dulezite treba pro nastaveni poctu vzorku, kdy nejmensi hodnota
  ; je 100 vzorku

.EQU trigger_mode_SRAM = min_value_submenu_SRAM+1
  ; informace o zvolenem modu triggerovani
  ; 0 - HW vzestupna, 1 - HW sestupna, 2 - na nic necekej a tahej data


.EQU waiting_interval_mode_SRAM = trigger_mode_SRAM+1	; urcuje, ktery
  ; z intervalu je prave vybran (buffer, keyboard)
.EQU waiting_interval_buffer_SRAM = waiting_interval_mode_SRAM+1
  ; jak dlouho se ma cekat na buffer
.EQU min_interval_buffer = 3
.EQU waiting_interval_keyboard_SRAM = waiting_interval_buffer_SRAM+1	; jak
  ; dlouho se ma cekat na klavesnici
.EQU min_interval_keyboard = 6	; minimalni interval pro 8Mhz. Pokud bychom
  ; cekali mensi dobu, tak by klavesnice byla prakticky nepouzitelna

  ; Zase pro citani (pokud nejsme narocni na cas)
.EQU CNT4_SRAM = waiting_interval_keyboard_SRAM+1
.EQU CNT5_SRAM = CNT4_SRAM+1
.EQU CNT6_SRAM = CNT5_SRAM+1

.EQU write_text_from_DB_line_SRAM = CNT6_SRAM+1	; Nepovinny parametr pro	
  ; podprogram "write_text_from_DB". Pokud delka textu presahne jeden radek,
  ; pak se musime presunout na dalsi. A prave diky teto informaci hned vime,
  ; jake cislo radku je nasledujici pro LCD (pricte se 1). Muze nabyvat 0~7
.EQU wr_txt_from_DB_actual_line_SRAM = write_text_from_DB_line_SRAM+1
  ; takovy cicac radku. Muze nabyvat 0~255. Je tu
  ; predevsim pro to, ze pokud mame dlouhy text jako celek, tak se na jednu
  ; obrazovku LCD nemuze vejit. Proto se text bude zobrazovat postupne, radek
  ; po radku, jako napr. www stranky s posuvnikem, coz znacne zvysi
  ; jednoduchost pri psani textu. Tuto promennou si koriguje sam podprogram
.EQU wr_txt_from_DB_start_line_SRAM = wr_txt_from_DB_actual_line_SRAM+1
  ; Rika, od ktereho radku se ma zacit vypisovat text. To znamena, ze napr.
  ; prvni dva radky vynechame a budeme si zobrazovat text od 3. radku. Je to
  ; vlastne kvuli dlouhym textum. Tuto promennou definuje "uzivatel"
.EQU wr_txt_from_DB_show_X_lines_SRAM = wr_txt_from_DB_start_line_SRAM+1
  ; Promenna pro "write_text_from_DB". Definuje, kolik radku se muze nejvice
  ; vypsat pod sebe. 0 - Nic se vykreslovat nebude - nema smysl pouzivat - az
  ; 7 - zaplni se cely displej. Pokud zadame cislo vetsi jak 8, pak se bude
  ; cyklycky prepisovat. Po ukonceni podprogramu se nastavi defaultne na 8.
  ; Resp. Cislo 0 nebude mit zadny efekt a bude se vykreslovat cyklycky do 255

.EQU Auto_break_line_SRAM = wr_txt_from_DB_show_X_lines_SRAM+1
  ; 0 - nezalamovat radky, cokoliv jineho - zalamovat

.EQU Font_micro_SRAM = Auto_break_line_SRAM+1	; Velikost pisma - podporuji
  ; jen nektere programy - taky je zapotrebi minimalne

.EQU D_start_20_SRAM = Font_micro_SRAM+1
  ; Sem se "rozhazuji" dekadicke hodnoty preveden z floatu
  ; Zabira 20 bajtu -> nasledujici promenna/promenne musi byt posunuty o 20B


.EQU float_extra_variables_SRAM = D_start_20_SRAM+20	; Sem se budou ukladat
  ; mezivysledky, promenne pri praci s floatem (ne vzdy staci 2 hodnoty)
.EQU float_extra_variables_count_SRAM = 5	; Pocet promennych
.EQU float_extra_variables_end_SRAM = float_extra_variables_SRAM + float_extra_variables_count_SRAM*4
  ; Definuje, kde konci tato pamet



  ; VYSLEDKY s operacemi vzorku
.EQU Samples_MAX_value_SRAM = float_extra_variables_end_SRAM	; Maximalni
  ; hodnota vzorku
.EQU Samples_MAX_value_low_SRAM = Samples_MAX_value_SRAM+1	; Spodnich
  ; 8 bitu pro maximum (v pripade, ze pocitame s 16bitovym cislem)
.EQU Samples_MAX_position_SRAM = Samples_MAX_value_low_SRAM+1	; Jeho pozice

.EQU Samples_MIN_value_SRAM = Samples_MAX_position_SRAM+1	; Minimalni
  ; hodnota vzorku
.EQU Samples_MIN_value_low_SRAM = Samples_MIN_value_SRAM+1	; Spodnich
  ; 8 bitu pro minimum (v pripade, ze pocitame s 16bitovym cislem)
.EQU Samples_MIN_position_SRAM = Samples_MIN_value_low_SRAM+1	; Pozice
  ; minimalniho vzorku

.EQU Samples_Actual_value_SRAM = Samples_MIN_position_SRAM+1	; Aktualni
  ; vzorek z A/D preodniku
.EQU Samples_Actual_value_low_SRAM = Samples_Actual_value_SRAM+1

.EQU Samples_PERIOD_value_SRAM = Samples_Actual_value_low_SRAM+1
  ; Delka periody
.EQU Samples_PERIOD_position_SRAM = Samples_PERIOD_value_SRAM+1	; Pozice
  ; pocatku periody

  ; VYSLEDKY s operacemi vzorku - FLOAT - Format X_SE, X_3, X_2, X_1 - 4bajty
.EQU Samples_PEAK_value_float_SRAM = Samples_PERIOD_position_SRAM+1
.EQU Samples_PERIOD_value_float_SRAM = Samples_PEAK_value_float_SRAM+4
.EQU Samples_FREQUENCY_value_float_SRAM = Samples_PERIOD_value_float_SRAM+4
.EQU Samples_VRMS_value_float_SRAM = Samples_FREQUENCY_value_float_SRAM+4
.EQU Samples_VAVG_value_float_SRAM = Samples_VRMS_value_float_SRAM+4
.EQU Samples_VMAX_value_float_SRAM = Samples_VAVG_value_float_SRAM+4

.EQU Samples_begin_SRAM = Samples_VMAX_value_float_SRAM+4
  ; sem se budou ukladat vzorky z bufferu a
  ; pozdeji s nimi budeme pracovat (vypocet prumerne hodnoty atd...)

;.EQU neco_dalsiho = $0170 ; nebo taky <predchozi adresa>+255, coz je
  ; univerzalnejsi nez predchozi zapis, protoze pokud se rozhodneme pridat
  ; nejakou promennou pred tuto adresu, pak musime prepisovat dalsich nekolik
  ; adres manualne

.EQU calculated_SRAM = Samples_begin_SRAM+255
.EQU last_adress_SRAM = calculated_SRAM	; rekneme, ze last_adress_SRAM
  ; bude odpovidat tato adresa (posledni pouzita adresa v SRAM)
  ; Diky teto promenne si muzeme zjistit obsazenost SRAM, kterou pak muzeme
  ; vypisovat prez menu do "Show_stats"

; *-----------------------------------------*
; |              INICIALIZACE               |
; *-----------------------------------------*
	CBI control_port_ADC,main_ready	; Nastavime status pro tento uC jako
  ; "nepripraven", aby ihned po startu bufferu nedochazelo k odesilani dat

  ; Inicializace StackPointeru na konec SRAM
	LDI tmp,LOW(RAMEND)
	OUT SPL,tmp
	LDI tmp,HIGH(RAMEND)
	OUT SPH,tmp

; Nastaveni I/O
	LDI tmp,$FF
	OUT IO_control_LCD,tmp	; nastavime cely "control_port_LCD" na vystupni

	LDI tmp,$00
	OUT IO_control_ADC,tmp	; Defaultne bude cely A/D port (kvuli tomu, aby
  ; zde nevznikaly problemy s tim, ze pin je nastaven jako vystupni)

	SBI IO_control_ADC,main_ready	; main_ready bude vystupni
	CBI IO_control_ADC,buffer_ready	; nastavime buffer_ready na vstupni

	SBI IO_control_ADC,main_ready_to_read_from_keyboard ; vystupni
	CBI IO_control_ADC,keyboard_serial_data	; vstupni

	SBI IO_control_LCD,Sleep_mode	; Vystupni

	LDI tmp,0
	OUT IO_num,tmp	; Datovy port s bufferem se nastavi jako vstupni
  ; (musi se nejprve pockat, az bude buffer pripraven)

	CBI control_port_LCD,LED	; Vypne debug LED
; *-----------------------------------------*
; |       Nastaveni defaultnich hodnot      |
; *-----------------------------------------*
	LDI tmp,default_number_of_samples
	STS number_of_samples_SRAM,tmp	; a nastavime defaultni pocet vzorku

  ; Offset vzorku se vypocitava z poctu vzorku -> zbytecne definovat
;	RCALL Calculate_samples_offset

	LDI tmp,default_TimeBase
	STS TimeBaseSRAM,tmp	; do SRAM na misto TimeBaseSRAM zapiseme
  ; hodnotu 216 - hodnota, ktera udava casovou zakladnu na 100us

	LDI tmp,default_waiting_interval_buffer
	STS waiting_interval_buffer_SRAM,tmp	; a definujeme defaultni
  ; maximalni interval, po ktery budeme cekat na buffer
	LDI tmp,default_waiting_interval_keyboard
	STS waiting_interval_keyboard_SRAM,tmp	; to same, ale pro klavesnici

	CLR tmp
	STS waiting_interval_mode_SRAM,tmp

;	CLR tmp
	STS Trigger_single_mode_status_SRAM,tmp	; Nastavime status do 0

	STS start_bit_errors_SRAM,tmp	; pocet chyb nastavit na 0
	STS Num_of_sampl_error_1_SRAM,tmp	; pocet chyb "pocet vzorku"
	STS Num_of_sampl_error_2_SRAM,tmp	; to same, ale jsou zde stovky a tisice

	CLR tmp
	STS Samples_MAX_value_SRAM,tmp	; Zatim nemame nic namereno -> vymazat
	STS Samples_MAX_position_SRAM,tmp
	STS Samples_MIN_value_SRAM,tmp
	STS Samples_MIN_position_SRAM,tmp
	STS Samples_PERIOD_value_SRAM,tmp

	LDI tmp,$FF	; Tim rekneme, ze vstupni signal je maly
	STS Samples_PERIOD_position_SRAM,tmp

	CLR tmp
	CALL Convert_8bit_unsigned_to_float_A
	LDI XH,HIGH(Samples_PEAK_value_float_SRAM)
	LDI XL,LOW(Samples_PEAK_value_float_SRAM)
	CALL Save_A_to_X	; A tam se ulozi vysledek

	LDI XH,HIGH(Samples_VMAX_value_float_SRAM)
	LDI XL,LOW(Samples_VMAX_value_float_SRAM)
	CALL Save_A_to_X


	CLR tmp
	STS buffer_too_busy_SRAM,tmp	; nastavime, ze buffer neni prave
  ; zaneprazdnen sberem dat

	LDI tmp,default_trigger_mode
	STS trigger_mode_SRAM,tmp	; nastavime trigger mode na vzestupnou
  ; hranu
  ; 0 - HW vzestupna, 1 - HW sestupna, 2 - na nic necekej a tahej data


	LDI tmp,default_number_of_samples_mode
	STS number_of_samples_mode_SRAM,tmp	; nastaveni modu u poctu vzorku
  ; 0 - Automaticky ; 1 - manualne

	LDI tmp,0
	STS animations_mode_SRAM,tmp	; defaultni animace. Seznam animaci
  ; a jejich prirazeni je vyse

;	LDI tmp,0
	STS help_option_SRAM,tmp

;	LDI tmp,0
	STS write_text_from_DB_line_SRAM,tmp	; default radek - 0.
  ; (uplne nahore)

;	LDI tmp,0
	STS wr_txt_from_DB_start_line_SRAM,tmp	; pocatecni radek pro
; vykreslovani textu (zacni vykreslovat hned). NE RADEK PRO LCD!!!

	LDI tmp,8
	STS wr_txt_from_DB_show_X_lines_SRAM,tmp	; kolik se ma
  ; vykreslit radku (8 znamena ze u 8. radku se ma zastavit)

	LDI tmp,1
	STS draw_mode_SRAM,tmp	; nastavime vykreslovani na vektorove

;	LDI tmp,1
	STS Auto_break_line_SRAM,tmp	; nastavime zalamovani radku na ANO

	LDI tmp,0
	STS Font_micro_SRAM,tmp	; Nastavime velikost pisma - 0 normalni
  ; 1 - male 

	JMP Start	; Skok na Start

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "keyboard_control.asm"	; viz. nize
  ; Na tomto miste je to jenom kvuli tomu, ze skok nemuze byt delsi nez 2048
  ; adres. Vzhledem k tomu jak velke jsou sobory "graphic.asm"
  ; a "draw_points.asm" uz by program nemusel byt schopen skocit na podprogram
  ; ktery je "na konci" pameti (kdybychom tyto asm soubory jeste o neco
  ; rozsirili a pouzili RJMP). Proto je kod vlozen sem

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

.INCLUDE "letters.asm"		; databaze pismen

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

.INCLUDE "osc_info.asm"		; ma na starosti zobrazeni informaci v prave
  ; casti v "Osc_mode"

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

.INCLUDE "initLCD.asm"	; na toto misto vlozi kod ze souboru initLCD.asm
  ; ulehcuje nam to praci a zprehledni to kod. Pokud nas bude zajimat, jak
  ; se zapina samotne LCD, pak se staci podivat do daneho souboru.
Start:
	RCALL InitLCD	; nastavi LCD (vyresetuje,zapne ho a nastavi)
  ; Je to naschval jako podprogram. Muze se stat, ze budete potrebovat
  ; restartovat LCD displej behem chodu programu
  ; - Je ulozen v initLCD.asm
; ------------------------------------------------------------------------
;RJMP end_of_debug
;	RCALL Clear_display

; Priklad nahravani dat na LCD
;	LDI data,$A5	; do promenne data se ukladaji informace, ktere
  ; jsou pak predavany jako argumenty podprogramum
;	RCALL write_left
;	LDI data,3
;	RCALL select_line_both
;	LDI data,0b11010111
;	LDI write_right

;	RCALL Clear_display	; Smaze data na displeji
; Spustime jednoduchou animaci
;	RCALL Anime ; pro zatim vyple


  ; Vypocita offset tak, abychom byli v prostredku rozsahu
	CALL Calculate_samples_offset	; Taky se to taky musi vypocitat pro
  ; pripady, ze se vratime z menu a pozmenime hodnotu vzorku - viz dale.
  ; Nesmi byt uz na Osc_mode_pre, protoze pri kazdem prechodu z menu zpet,
  ; bychom ztratili uzivatelem nastaveny offset

  ; Odesle se casova zakladna, pocet vzorku a trigger mode. Zase musi se
  ; spustit pred tim, nez budeme ocekavat data z bufferu, ale nemuze to byt
  ; na Osc_mode_pre, protoze at uz vyskocime do menu kdykoli, tmer vzdy uz ma
  ; buffer potrebna data nactena.
  ; Budto jsme mu je poslali a cekame na vyhodnoceni, nebo jsme uz vyhodnotili
  ; data a poslali jsme mu nova, ale pote uzivatel stiskl tlacitko "M", takze
  ; se dostaneme do hlavniho menu a kdyz skocime zpet na Osc_mode_pre, tak
  ; uz musime jen pockat na to, az bude buffer pripraven poslat nam pripravena
  ; data a ne mu posilat znovu zadani (dojde k tomu, ze kontrola poctu vzorku
  ; selze -> pocet chyb by se zvysil o jedno -> nezadouci)
	CBI control_port_LCD,Sleep_mode	; Vypne usporny rezim
  ; (Zapne se AD + buffer)
	RCALL init_buffer_and_send_cfg	; Inicializuje buffer (pocka se, az
  ; bude pripraveny a pote se potvrdi zacatek dat reset kody). Zaroven se
  ; odesle aktualni nastaveni do bufferu

; *-----------------------------------------*
Osc_mode_pre:		; Provede potrebne prikazy, ktere je potreba provest
  ; jen jednou pred samotnym modem
	CBI control_port_LCD,Sleep_mode	; Vypne usporny rezim

	CLR tmp
	STS Auto_break_line_SRAM,tmp	; vypneme automaticke zalamovani
  ; radku - nyni je to nevhodne. Zalamovani je vhodne pouze pri vypisovani
  ; textu na cely displej, jinak jeho vyznam postrada smysl. Navic se tim
  ; i o neco zvysi rychlost zobrazovani na LCD


; "Vycistime" displej
	RCALL Clear_display

; Vykreslit ramecek
	RCALL Draw_right_menu

; Nyni musime zkontrolovat, zda jsme "nevyskocili" do menu v dobe, kdy
; byl buffer zaneprazdnen
	LDS tmp,buffer_too_busy_SRAM	; stahneme informaci do tmp
	CPI tmp,0
	BRNE Wait_for_buffer_data	; pokud tam byla "0", pokracuje se
  ; normalne dal - nemusime cekat az buffer posle data - ale pokud tam bylo
  ; cokoliv jineho, pak musime nechat buffer svoji praco dokoncit

; Vykresli alespon rysky a pomocne body, aby pri zapnuti, kdyz neni buffer
  ; jeste pripraven (treba ceka na trigger) bylo zobrazeno alespon neco
	RCALL Draw_main_screen	; Podprogram v "graphic.asm"
  ; To neplati, pokud se vratime z menu, to by mohlo byt matouci, takze
  ; sviti pouze "B" a tim je naznaceno, ze stale se ceka na buffer

Osc_mode:
; ----
; Odstraneni "blikani" displeje. Pokud smazeme data zobrazena na LCD a pak
  ; bude nasledovat dlouha prodleva a budeme-li zobrazovana data casto
  ; aktualizovat, bude pri vetsich casovych prodlevach znatelne videt blikani,
  ; ktere neni prijemne. Proto pockame, az bude buffer pripraven a pak teprve
  ; zacit vykreslovat
Wait_for_buffer_data:
	RCALL wait_for_buffer_for_while	; pockame, dokud nebude buffer
; pripraven A opet kontrola, zda se bude cekat dlouho, nebo ne
	LDS tmp,buffer_too_busy_SRAM
	CPI tmp,0	; 0 - pripraven
	BREQ Buffer_is_aviable_to_send_data	; pokud je pripraven -> skok
  ; na Buffer_is_aviable_to_send_data
  ; Pokud neni pripraven -> musime na nej pockat, ale mezitim muzeme
  ; "odskocit" treba do menu, nebo zmenit casovku

  ; vyznam jednotlivych podprogramu je vysvetlen nize
	RCALL Draw_right_menu
	CALL recive_data_keyboard
	CALL proceed_keyboard_Osc_mode
	BRBC 6,Menu_mode_no	; pokud je T bit v "0" -> skok na Menu_mode_no
	RJMP Menu_mode_pre	; pokud je v "1", skok na Menu_mode_pre
Menu_mode_no:
	RCALL Show_time_base
	RCALL Show_voltage_range
	RCALL show_buffer_is_busy
	RCALL show_X_sync
	RCALL show_coupling
	LDS tmp,Trigger_single_mode_status_SRAM	; Stahneme si info o single modu
	CPI tmp,0	; porovnani s nulovou hodnotou
	BREQ Menu_mode_no_Trigger_not_single	; Pokud je nula
	RCALL show_trigger_single_mode
Menu_mode_no_Trigger_not_single:
  ; Namerene hodnoty
  ; Z nasbiranych vzorku vypocita Vpp, periodu atd...
;	CALL Samples_calc	; Provede vypocty potrebne pro zobrazeni Vpp,
  ; frekvence a dalsich (Neni potreba, data se nezmenila -> vysledky musi byt
  ; stejne -> nema smysl prepocitavat)
	CALL Show_samples_results	; A zobrazi provedene vypocty



	RCALL wait_50ms
	RJMP Wait_for_buffer_data	; Musime pockat, az buffer odesle
  ; sva data z SRAM - do te doby se "budeme pohybovat pouze zde"



Buffer_is_aviable_to_send_data:	; OK, buffer je pripraven, muzeme vykreslit
  ; prubehy na displej
	RCALL load_data_from_buffer	; Stahneme si data z bufferu do SRAM.
  ; To nam umozni napr. posouvat s jednou jiz navzorkovanym prubehem, zatimco
  ; se vzorkuje dalsi

  ; Odesle se casova zakladna, pocet vzorku a trigger mode
	RCALL send_config_data_to_buffer
  ; Tyto data se odeslou velice rychle, takze nas o tolik nezpomali. Navic
  ; pri vykreslovani signalu se stale budou data ukladat do bufferu, takze
  ; si tim zvysime maximalni zobrazovaci frekvenci
	LDI tmp,$FF
	STS buffer_too_busy_SRAM,tmp	; A nastavime zaneprazdnenost bufferu
  ; na "1"

  ; Nyni vykreslime primo data z SRAM, tedy pokud prijata data byla validni
	LDS tmp,Rx_data_buffer_not_valid_SRAM
	CPI tmp,0
	BRNE Osc_mode_do_not_show_invalid_data	; Pokud bude promenna ruzna od
  ; nuly, tak se vykreslovani a vypocty preskoci

  ; Z nasbiranych vzorku vypocita Vpp, periodu atd...
	CALL Samples_calc	; Provede potrebne vypocty

	RCALL Draw_points	; ulozen v draw_points.asm
Osc_mode_do_not_show_invalid_data:

	LDS tmp,Trigger_single_mode_status_SRAM	; Stahneme si informaci
  ; o single triggeru
	CPI tmp,0
	BREQ Osc_mode_not_single_trigger	; Pokud neni single trigger
  ; nastaven, pak se provede skok

Osc_mode_single_trigger:
  ; V opacnem pripade se prubeh "zastavi"
	CLR tmp
	STS Trigger_single_mode_status_SRAM,tmp	; Smaze se informace o single
  ; trigger

	SET
	BLD tmp,run_stop	; do tmp se ulozi informace o "stisklem"
  ; tlacitku Run/Stop
	CLT
  
	STS keyboard_L_SRAM,tmp	; A nahraje se informace do pameti

	CALL proceed_keyboard_Osc_mode	; A necha se vse volnemu prubehu :)

	RJMP Osc_mode_test_for_menu_mode

Osc_mode_not_single_trigger:
  ; Prijme data, co jsou ulozena na klavesnici
	CALL recive_data_keyboard	; ulozeno v "keyboard_control.asm"
  ; Zpracuje data z klavesnice
	CALL proceed_keyboard_Osc_mode	; ulozeno
  ; v "keyboard_control.asm"
Osc_mode_test_for_menu_mode:
  ; Pripadna zmena modu...
	BRBC 6,Menu_mode_no_II	; pokud je bitu T ulozena "1" ->
  ; -> skok na Menu_mode_pre
	RJMP Menu_mode_pre
Menu_mode_no_II:
  ; nyni se vykresli informacni data v prave casti
	RCALL Show_time_base	; Podprogram v "osc_info.asm"
  ; podprogram musi byt az za proceed_keyboard_Osc_mode, aby stihl "podchytit"
  ; pripadne nesmyslne nastaveni casove zakladny
	RCALL Show_voltage_range	; take v "osc_info.asm" Ukazuje
  ; aktualni rozsah
	RCALL show_X_sync	; ukaze, jestli je synchronizace int/ext
	RCALL show_coupling	; 

	CALL Show_samples_results	; A zobrazi provedene vypocty


  ; Spusti pripadne cekani, aby byl displej citelny
	RCALL wait_50ms

	RJMP Osc_mode

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "wait_8Mhz.asm"	; pro snadnejsi praci - staci akorat zmenit
  ; jmeno souboru. Zde jsou definovany casove zpozdeni podle taktu uC
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

  ; Drtiva vetsina algoritmu je v souboru "menu_mode.asm"
Menu_mode_pre:	; provedou se operace, ktere behem celeho modu je potreba
  ; provest jen jednou

	CLR tmp
	STS Auto_break_line_SRAM,tmp	; Vypne se zalamovani radku

	LDI tmp,0
	STS main_menu_selected_option_I_SRAM,tmp	; zvolime defaultni
  ; moznost_v_menu

;	LDI tmp,0	; jen kdyby se tato hodnota lisila od te predchozi
	STS main_menu_selected_option_II_SRAM,tmp	; zvolime si defaultni
  ; pod-moznost

;	RJMP Menu_mode	; Zbytecne, PC si tam "dojde" sam
; *-----------------------------------------*
Menu_mode:

	RCALL Clear_display	; smazeme data na LCD, aby se nasledujici
 ; zapsala korektne, resp. aby zde nebyly zbytky predchozich pismen, znaku
 ; atd.

	LDS tmp,main_menu_selected_option_I_SRAM
	STS main_menu_selected_option_I_last_SRAM,tmp	; do SRAM si zapiseme
  ; informaci o tom, jaka polozka byla posledne zvolena -> nize kvuli
  ; obnovovani dat na LCD (pokud budeme casto mazat cely displej a data na nej
  ; znovu nahravat, kvuli technologii tohoto displeje, bude LCD neprijemne
  ; "blikat". Proto se pouzije trochu sofistikovanejsi metoda

 ; Nejprve se vykresli pismena
	CALL Draw_main_menu_options

Menu_mode_recive_data_from_keyboard:
  ; Nacteme data z klavesnice
	CALL recive_data_keyboard	; ulozeno v "keyboard_control.asm"
  ; Zpracuji se data z klavesnice
	LDS time1,keyboard_L_SRAM	; data ulozime do time1

	SBRC time1,OK			; test na tlacitko "OK"
	CALL Enter_to_submenu

	SBRC time1,arrow_right		; test na tlacitko "->"
	CALL Enter_to_submenu


	SBRC time1,plus_time_base	; test na tlacitko "nahoru"
	CALL In_main_menu_pressed_up

	SBRC time1,minus_time_base	; test na tlacitko "dolu"
	CALL In_main_menu_pressed_down

	SBRC time1,X	; pokud bylo stisknuto tlacitko "X", pak nasleduje
  ; navrat do modu "Osc_mode"
	RJMP Osc_mode_pre


  ; Stare reseni "blikani" LCD. Neni prilis sofistikovane, ale funguje taky
  ; Zpozdeni je tu kvuli LCD (aby "neblikalo" prilis)
;	RCALL wait_100ms
;	RJMP Menu_mode

  ; Nove reseni:

	LDS tmp,main_menu_selected_option_I_last_SRAM
	LDS data,main_menu_selected_option_I_SRAM
  ; informace o nastavenych modech a jejich zmenach jsou vlastne ulozeny
  ; v techto pametovych bunkach. Takze si je ulozime do registru, abychom
  ; s nimo mohli pracovat
	CP tmp,data	; porovnani
	BREQ Menu_mode_recive_data_from_keyboard	; pokud se budou
  ; rovnat, pak neni potreba mazat LCD a znovu vykreslovat data na LCD. Takze
  ; se skoci na nadepsane navesti

	RJMP Menu_mode	; no a pokud se nerovnali, tak se skoci sem :)
  ; Toto reseni ma jediny zadrhel. Pokud "vlezeme" do nejake nabidky a pak
  ; se vratime zpet, tak se vlastne moznost v menu nezmenila -> musi se
  ; manualne zmenit "main_menu_selected_option_I_last_SRAM" hned po spusteni
  ; "Enter_to_submenu"
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
END:
	SBI control_port_LCD,LED ; pro debug
	CALL wait_1000ms
	CBI control_port_LCD,LED
	CALL wait_1000ms
	RJMP end

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

; Pockame na buffer nejakou dobu, pokud tato doba presahne urcity interval
  ; napriklad v dusledku toho, ze musi nasbirat mnoho vzorku ve velkem
  ; casovem intervali, pak se preskoci nektere sekvence a na displeji
  ; zobrazime posledni prubeh, plus informaci o tom, ze se data nahravaji
  ; do bufferu
wait_for_buffer_for_while:
	LDS CNT,waiting_interval_buffer_SRAM	; pocitadlo na cekani
  ; na buffer
	CLR tmp
	STS buffer_too_busy_SRAM,tmp	; nastavime zaneprazdnenost na 0 :)
wait_for_buffer_for_while_post:
	SBIC control_port_ADC_in,buffer_ready	 ;pokud bude "1" ->
  ; ->  pripraven -> pokracuje na dalsi radek ; "0" skok obradek
	RET	; buffer_too_busy_SRAM - $00
  ; pokud se dostaneme sem, neni buffer stale pripraven
	DEC CNT	; odecteme 1 pokus o cekani
	BRNE wait_for_buffer_for_while_post	; pokud jsme neodpocitali do 0, tak
  ; se skoci na wait_for_buffer_for_while_post a ceka se dalsi cyklus

; Pokud se dostaneme sem, znaci to o tom, ze je buffer zaneprazdnen

	LDI tmp,$FF
	STS buffer_too_busy_SRAM,tmp	; a nastavime priznak zaneprazdnenosti
	RET	; buffer_too_busy_SRAM - $FF - pak vyhodnotime
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
wait_for_buffer:
	SBIS control_port_ADC_in,buffer_ready	 ;pokud bude "1" ->
  ; ->  pripraven -> skok. Jinak se pokracuje na dalsi radek, tedy na
  ; RJMP wait_for_buffer
	RJMP wait_for_buffer
	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
send_data_to_buffer:	; 
  ; odesleme data v registru "data" bufferu
	LDI tmp,$FF
	OUT IO_num,tmp	; nastavime port na vystupni
	OUT num_port,data	; nahrajeme na vystupy
	SBI control_port_ADC,main_ready	; "pripraven"
	NOP
	CBI control_port_ADC,main_ready	; "nepripraven" - hotovo
	RCALL wait_1us	; aby si stihl data stahnout

	LDI tmp,$00
	OUT IO_num,tmp	; nastavime port na vstupni

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
send_config_data_to_buffer:
 ; Default: bezi mod osciloskopu a je casova zakladna je nastavena na
  ; 100us/div, offset vzorku je 100 (abychom mohli hybat do obou stran)
  ; vypocitava se z nastavenych poctu vzorku.

	RCALL wait_for_buffer	; Tady se buffer nemuze zaseknout -> nebudeme
  ; totiz prakticky na nej vubec cekat


  ; Pocet vzorku
	LDS data,number_of_samples_SRAM
	RCALL send_data_to_buffer

  ; Tirgger mode
	RCALL wait_for_buffer	; Opet nebude cekat dlouho (prakticky vubec)
	LDS data,trigger_mode_SRAM
	RCALL send_data_to_buffer


  ; Time base
	RCALL wait_for_buffer	; Opet nebude cekat dlouho (prakticky vubec)
	LDS data,TimeBaseSRAM
  ; Buffer "zvlada" jen do casove zakladny 209. Pokud zvolime nizsi casovou
  ; zakladnu, je to v podstate jen zoom na casovou zakladnu 209 (0.5us)
	CPI data,209
	BRSH Osc_mode_send_time_base	; pokud se jedna o casovou zakladnu
  ; 209 a vyssi, neni potreba nic menit
	LDI data,209	; v opacnem pripade si zvolime nejmensi moznou casovku
  ; 209 - 0.5us/dilek a pokracuje se dal. Tzn. v SRAM mame ulozenou uzivatelem
  ; zvolenou casovku, ale bufferu jsme poslali nejmensi
Osc_mode_send_time_base:
	RCALL send_data_to_buffer

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
  ; Restartuje buffer a posle mu aktualni nastaveni
reset_buffer_and_send_cfg:

	CBI control_port_ADC,main_ready	; hlavni jednotka na "nepripraven"
  ; Tim se zabrani nechtenemu posilani dat (napriklad pri preruseni behem
  ; prenosu dat - to by se sice delat nemelo, ale i to se muze stat)
	CLR tmp
	OUT num_port,tmp	; Nastavi vsechny vystupy do 0 -> tim je
  ; zajisteno, ze se buffer "nezasekne" ani pri debug modu (vzdy bude na
  ; sbernici platne konfiguracni slovo)
	OUT IO_num,tmp	; A nastavi se port na vstupni (bude se zjistovat, jaky
  ; kod / data buffer nastavil na vystup

rst_buff_test_4_reset_rdy:
	SBIS control_port_ADC_in,buffer_ready	; Precteme si stav bufferu
	RJMP rst_buff_not_rdy	; Pokud neni priznak pripravenosti nastaven
  ; Muze se resetovat

  ; V opacnem pripade musime vyvolat prikaz/impulz "pripraven", aly se buffer
  ; "pohnul dal" a umoznil restart
	SBI control_port_ADC,main_ready	; "pripraven"
	NOP
	CBI control_port_ADC,main_ready	; "nepripraven" - hotovo

  ; A provede se reset, jakmile bude buffer_ready v nizke urovni
rst_w8_4_low:
	SBIC control_port_ADC_in,buffer_ready
	RJMP rst_w8_4_low

rst_buff_not_rdy:
  ; Pokud se dostane PC sem, pak je buffer pripraven na reset
  ; Vyvola se reset impulz
	SBI IO_control_ADC,buffer_ready	; Nastavime port jako vystupni
	SBI control_port_ADC,buffer_ready
	NOP	; Aby byl impulz dostatecne dlouhy a zaroven je to pojisteni
  ; proti parazitnim kapacitam (pro pripad, ze by nabeh byl prilis pomaly)
	CBI control_port_ADC,buffer_ready
	CBI IO_control_ADC,buffer_ready	; A opet ho prenastavime jako vstupni

	RCALL wait_2us	; Urcite to bude trvat delsi dobu...

	IN tmp,num_port_in
	CPI tmp,reset_in_progress	; overime, zda jsme opravdu v modu
  ; resetovani bufferu... Pokud ne, musel by se cely proces opakovat
	BRNE rst_buff_test_4_reset_rdy	; Pokud neni program v resetovancim
  ; procesu -> znovu

init_buffer_and_send_cfg:	; Pocka si, az bude buffer pripraven
rst_buff_w8_4_reset_code_1:
	CALL wait_for_buffer	; Cekame, az bude buffer pripraven
	; Pockame, az se na sbernici objevi dane slovo
	IN tmp,num_port_in
	CPI tmp,reset_code_1	; porovnani s reset kodem 1 (musi byt stejny
  ; pro buffer i pro main_uC
	BRNE reset_fail	; pokud nevyhovuje -> chyba

  ; Data uspesne prijata

  ; Musime pockat, az bude buffer pripraven 
	SBI control_port_ADC,main_ready	; "pripraven"
	RCALL wait_2us	; aby si stihl data stahnout
	CBI control_port_ADC,main_ready	; "nepripraven" - hotovo

rst_buff_w8_4_reset_code_2:
	CALL wait_for_buffer
	IN tmp,num_port_in
	CPI tmp,reset_code_2
	BRNE reset_fail

	SBI control_port_ADC,main_ready	; "pripraven"
	RCALL wait_2us
	CBI control_port_ADC,main_ready	; "nepripraven" - hotovo

rst_buff_w8_4_reset_code_3:
	CALL wait_for_buffer
	IN tmp,num_port_in
	CPI tmp,reset_code_3
	BRNE reset_fail

	SBI control_port_ADC,main_ready	; "pripraven"
	RCALL wait_2us
	CBI control_port_ADC,main_ready	; "nepripraven" - hotovo
  ; A potvrdime spravnost posledniho kodu

  ; Nyni uz pro uplnost zbyva odeslat konfiguracni data
	RCALL send_config_data_to_buffer	; A posle mu aktualni data

	RET

reset_fail:
	RJMP reset_buffer_and_send_cfg
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "graphic.asm"	; viz nize ;-)
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "draw_points.asm"	; na toto misto vlozi jakoby kod v
  ; draw_points.asm
  ; Vyhoda je jasna: pokud budeme potrebovat zmenit urcitou cast kodu
  ; je jeho dohledani jednodussi

; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "float_operation.asm"	; Prace s floatem. zamerne zvlast, aby mohlo
  ; byt implementovano nezavisle na programu
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "math.asm"	; ruzne matematicke funkce, jako prevod z binarniho
  ; cisla na dekadicke atd...
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "menu_mode.asm"	; zde bude vestina algoritmu pro vetsi
  ; prehled
  ; tyto algoritmy nejsou az tak kriticke na cas, takze je dam na konec
  ; pameti (pokud budeme pouzivat CALL misto RCALL, tak to sice zabere o jeden
  ; cykl vic, ale muzeme se odvolavat na cely rozsah pameti)
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "voltage_mode.asm"	; Cely "Voltage mod" - vlsatne takovy voltmetr
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*


Anime_elements:
  ; Animace "Castice"
	LDI CNT2,63
	CLR CNT3
; Musime pouzit dalsi promenne. Data a CNT totiz vyuzivaji i jine podprogramy
Anime_elements_1:
	LDI data,3
	CALL select_line_both
; line nastaveny
	MOV data,CNT3
	CALL select_X_left
; nastavime X souradnici na leve strane
	MOV data,CNT2
	CALL select_X_right
; nastavime X souradnici na prave strane
	LDI data,0b10000000
	CALL write_both	; zapiseme na obe poloviny displeje 1000 000

; to same, akorat pro radek niz
	LDI data,4
	CALL select_line_both
; o radek niz
	MOV data,CNT3
	CALL select_X_left
	MOV data,CNT2
	CALL select_X_right
	LDI data,0b00000001
	CALL write_both

	CALL wait_10ms	; zavolame zpozdeni
	CALL wait_10ms
	CALL wait_10ms	; celkove zpozdeni bude tedy 20ms
	CALL Clear_display	; a "vycistime" displej (aby nevznikala cara)
  ; displej si totiz "pamatuje"
	INC CNT3	; vlevo se poduneme o 1 bod vlevo
	DEC CNT2	; vpravo se posuneme o 1 vpravo
	BRNE Anime_elements_1	; dokud nebude hodnota v CNT2=0

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*

Anime_matrix:
	CALL Clear_display
	LDI tmp,63
	STS CNT4_SRAM,tmp
Anime_matrix_post:
  ; CNT5_SRAM - X pozice - leva cast
  ; CNT6_SRAM - X pozice - prava cast
  ; time3 - pocita jestli jsme uz "dojeli na konec"
  ; CNT4_SRAM - pocita Y rotaci (0~63)
	LDI XH,HIGH($00F1)
	LDI XL,LOW($00A3)

	LDI YH,HIGH($000)
	LDI YL,LOW($0122)

	LDI ZH,HIGH($001F)
	LDI ZL,LOW(0)
Anime_matrix_erase:
	RCALL Anime_matrix_erase_some

	CALL recive_data_keyboard	; test na stisknuti "X"
  ; do data si ulozi info o keyboard_L_SRAM
	LDS data,keyboard_L_SRAM
	SBRC data,X
	RJMP Anime_matrix_end
;	RCALL Anime_matrix_erase_some
;	RCALL Anime_matrix_erase_some
;	RCALL Anime_matrix_erase_some

	RCALL Anime_matrix_write

	CALL recive_data_keyboard	; test na stisknuti "X"
  ; do data si ulozi info o keyboard_L_SRAM
	LDS data,keyboard_L_SRAM
	SBRC data,X
	RJMP Anime_matrix_end

	RCALL Anime_matrix_write

	CALL recive_data_keyboard	; test na stisknuti "X"
  ; do data si ulozi info o keyboard_L_SRAM
	LDS data,keyboard_L_SRAM
	SBRC data,X
	RJMP Anime_matrix_end

  ; provedeme Y rotaci o 1
	LDS data,CNT4_SRAM	; nacteme data z SRAM
	CALL rotate_Y_both
	DEC data	; tim zajistime, ze se budeme pohybovat "dolu"
	CPI data,255	; kontrola, zda jsme se nedostali pod cislo nula
	BRNE Anime_matrix_write_rotate_OK
	LDI data,63	; pokud ano, tak nastavit na 63 a pokracuje se dal
Anime_matrix_write_rotate_OK:
	STS CNT4_SRAM,data	; a ulozime zase do SRAM



  ; Jeste se musi provest kontrola, jestli nejsme na konci pameti
	MOV tmp,ZH
	CPI tmp,HIGH(FLASHEND)
	BREQ Anime_matrix_reset

  ; a pokud ne, jeste pro jistotu se koukneme, zda data nejsou $FF. To pak
  ; dela cele cary a to neni taky vhodne
	LPM tmp,Z
	CPI tmp,$FF
	BREQ Anime_matrix_reset

	RJMP Anime_matrix_erase

Anime_matrix_reset:
	RJMP Anime_matrix_post

Anime_matrix_end:
  ; Musime nastavit Y rotaci na puvodni, tzn. 0!!!
	LDI data,0
	CALL rotate_Y_both

	RET
; *-----------------------------------------*
Get_random_X:
  ; Nastavime "nahodne" Xovou souradnici
	ADIW XL,4

	LD data,X+
	LSR data
	LSR data
  ; Kontrola, zda dalsi kod neni stejny -> nevypadalo by to tak verohodne
	LDS tmp,CNT5_SRAM
	CP tmp,data
	BREQ Get_random_X	; pokud bude stejny, tak se bude cist dalsi
  ; bajt
	STS CNT5_SRAM,data	; v opacnem pripade se data zapisi

Get_random_X_1:
	ADIW YL,6

	LD data,Y+
	LSR data
	LSR data

	LDS tmp,CNT6_SRAM
	CP tmp,data
	BREQ Get_random_X_1

	STS CNT6_SRAM,data

	RET
; *-----------------------------------------*
Anime_matrix_write:
	CLT	; priznak "ukoncit"
	CLR time3
  ; Nastavime "nahodne" Xovou souradnici
	RCALL Get_random_X
Anime_matrix_write_post:
	MOV data,time3
	CALL select_line_both
  ; Tim jsme nastavili spravny radek

  ; A ted nastavit Xovou souradnici
	LDS data,CNT5_SRAM
	CALL select_X_left

	LDS data,CNT6_SRAM
	CALL select_X_right

Anime_matrix_write_L:
  ; A ted vykreslit
	LPM data,Z+
;	SBIW ZL,3
;	LPM tmp,Z
	ADIW ZL,3
;	CP data,tmp
;	BREQ Anime_matrix_write_L
	CALL write_left


;	CALL wait_10ms
	CALL wait_10ms
	CALL wait_10ms
	CALL wait_10ms
	CALL wait_10ms

Anime_matrix_write_R:
	LPM data,Z+
;	SBIW ZL,3
;	LPM tmp,Z
;	ADIW ZL,3
;	CP data,tmp
;	BREQ Anime_matrix_write_R
	CALL write_right

	INC time3
	CPI time3,8
	BRNE Anime_matrix_write_post

	RET
; *-----------------------------------------*
Anime_matrix_erase_some:
	CLR time3
  ; Nastavime "nahodne" Xovou souradnici
	RCALL Get_random_X
Anime_matrix_erase_some_post:
  ; A smazeme nejake sloupce
	MOV data,time3
	CALL select_line_both
  ; nastavime radek

  ; A ted nastavit Xovou souradnici
	LDS data,CNT5_SRAM
	CALL select_X_left

	LDS data,CNT6_SRAM
	CALL select_X_right

  ; "vycistit"
	CLR data
	CALL write_both


	INC time3
	CPI time3,8
	BRNE Anime_matrix_erase_some_post

	RET
; *-----------------------------------------*
; |                                         |
; *-----------------------------------------*
.INCLUDE "lang_EN.asm"	; zde jsou ulozeny veskere texty. Je to hlavne pro
  ; vetsi prehlednost v kodu, ale muzeme si modifikaci tohoto souboru vytvorit
  ; vlastni soubor, lokalizovany do aktualni zeme. Navic zde nejsou ulozeny
  ; zadne programy, ale jen data, takze je de-facto jedno, kde jsou. A pro
  ; nas je vhodne je dat "na konec" pameti, protoze jinak by se muselo casto
  ; pouzivat CALL namisto RCALL (ktere zabira min pameti a je rychlejsi)
