;*** Zacatek souboru *********************************************************
;
; Soubor: X23U05.ASM
;  Nazev: XVRT 23cm, up box - CPU v horni skrince s transvertorem
;  Verse: 0.5
;    CPU: ATMEL ATTINY15L
;  Autor: OK2PPK, Brno, 2004/03
;
; Popis:
;
;   Meri napeti ve trech bodech (hlavni napajeni 12V, vstup 12V predpeti
;   do koncoveho stupne za pojistkou, napeti 12V sepnute optoclenem
;   ovladanym klicovacim signalem) a napeti ze snimace teploty chladice.
;   Zmerene udaje odesila v seriovem tvaru po jednovodicove komunikacni
;   lince dolu smerem k ovladaci skrince. Podle namerenych udaju ovlada
;   signalizaci chyby cervenou LED na hornim boxu transvertoru.
;
;   Po zapnuti napajeni a resetu CPU 2x kratce blikne cervenou LED pro
;   signalizaci, ze CPU je funkcni. Nasledne vzdy zmeri hodnoty na
;   vsech 4 vstupech AD prevodniku, vyhodnoti udaje, prevede zmerene
;   napeti teplotniho cidla na teplotu a udaje odesle v seriovem tvaru
;   rychlosti 600Bd.
;
;   Tvar odesilanych dat (bajtove)
;
;     SYNC ! FLAG ! DATA ! CNTRL
;
;     SYNC ... 1 synchronizacni bajt ($FF)
;     FLAG ... 2 bajty magicke konstanty ($C0, $C1)
;     DATA ... 4 bajty dat (Teplota ! Ukeytx ! Upredp ! Upwr)
;     CNTRL .. 1 bajt kontrolniho souctu z FLAG az DATA
;
;   Tvar odesilanych dat (bitove)
;
;     ... (1) ! 0=start bit!b0!b1!b2!b3!b4!b5!b6!b7! 1=stop bit ...
;
;   Vyznam signalizace cervene LED:
;
;     - po zapnuti kratce 2x blikne
;     - blikne kratce jednou za 5s - signalizace funkcnosti CPU
;       (sviti 276ms, je zhasla 4830ms
;     - sviti trvale ... nizke hlavni napajeci napeti (pod 10V)
;     - blika trvale v intervalu 0,5s ... je zvysena teplota (nad 50st.C)
;       (sviti 276ms, je zhasla 276ms atd.)
;     - sviti trvale po dobu vysilani ... je nizke nebo chybejici
;       predpeti 12V pro koncovy stupen (pod 10V)
;
;     trvale sviceni ma prioritu pred blikanim od signalizace teploty
;     a od signalizace behu CPU, signalizace zvysene teploty ma vyssi
;     prioritu nez signalizace behu CPU
;
;   Vyznam prenasenych hodnot
;
;     Teplota - 0 az 150 ... teplota ve stupnich 0 az 150st.C
;               206 az 255 ... teplota -50 az -1st.C
;     Ukeytx  - 0-150 ... napeti 0.0 az 15.0V na klicovacim bode
;               za optoclenem
;     Upredp  - 0-150 ... napeti 0.0 az 15.0V v miste vstupu
;               predpeti do koncoveho stupne
;     Upwr    - 0-150 ... napeti 0.0 az 15.0V na hlavni napajeci
;               sbernici za spinacimi FETy napajeni (smysl maji jen
;               hodnoty asi nad 5.5V, potom nebude stabilizator 5V
;               schopen dodat napeti vice jak 4V a CPU bude resetovan)
;
; Popis zmen:
;
;   v0.5 (14.3.2004)
;
;     spatne zobrazuje zaporne teploty - -5 jako 022, -4 jako 023, atd. az
;     -6 jako 026 a pak uz normalne 000, 001 atd. Chyba v rutine deleni
;     Div24d16 pro deleni 24b operandu 16b operandem - nebylo pocitano se
;     zapornym znamenkem operandu OP1. Rutina doplnena o zmenu znamenka
;     OP1 na vstupu a pripadnou adekvatni zmenu znamenka i u vysledku
;     a pro uplnost i u zbytku, ackoliv zbytek neni programu vyuzit.
;
;     druha chyba zjistena v tom, ze vypoctena teplota se zpet vlozila do
;     pameti pamutep a prumerovala se tak pri dalsim odectu s uplne jinou
;     hodnotou odectenou z AD prevodniku - skutecny vliv takrka nulovy - po
;     kontrole vypoctem byl u zapornych teplot vliv nulovy a u kladnych
;     to zpusobovalo zvyseni vypoctene teploty o 1 stupen. Opraveno ulozenim
;     vypoctene teploty do jineho registru
;
;     vypusteny nevyuzite promenne poml a pomh
;
;   v0.4 (29.11.2003)
;
;     u mereni teploty dle v0.3 dochazi ke snizeni rozlisovaci schopnosti
;     vypoctene hodnoty o 1 az 2 bity. Hodnoty se meni ve skocich i 2 nebo 3
;     stupne. Duvodem je, ze namerene hodnoty na vstupu AD se pri snimanem
;     rozliseni 8bitu pohybuji v mene nez polovicnim rozsahu, nez je rozmezi
;     minimalni a maximalni vypoctene teploty. Snimani a vypocet teploty byl
;     tedy upraven tak, ze se vyhodnocuje 9bitu AD prevodu. Ke skokum po
;     2 stupnich tak dochazi jen v male mire a pouze pri vyssich teplotach.
;     V ramci uprav jiz neni potrebna rutina Div16d8 - zrusena.
;
;   v0.3 (23.11.2003)
;     oprava chybneho vypoctu zpozdovacich rutin Cas1b, Cas1bu a Cas100ms.
;     V Cas1b(u) snizeno prednastaveni POC2 ze 112 na 111 (chyba byla 3 cykly)
;     a v Cas100ms snizeno prednastaveni POC2 z 201 na 200 (chyba opet 3 cykly).
;
;   v0.2 (19.11.2003)
;     vychozi verze pro komunikaci mezi hornim a spodnim CPU
;
;     16.11.2003 - zahajeno psani kodu pro versi U (horni CPU)
;
;     19.11.2003 - odstraneni chyb zjistenych pri ladeni
;
;       Prepis v inicializacni casti - u nastaveni ovladaciho pinu
;       pro LED na vystup chybne uveden parametr SDO misto LEDR.
;
;       Chyba v rutine Div16d8 - rutina pracuje ve skutecnosti s OP2 delky
;       16b a nebyl nulovan horni bajt OP2.
;
;       Chyba v rutine Mul8x8 - OP1L se pricital chybne do VYH misto do VYM.
;
;   v0.1 (2.10.2003)
;     pouze verse D pro spodni CPU, zobrazujici jen uvodni text na LCD
;     displeji a blikajici zelenou LED. Horni CPU neosazen.
;
; Souvisejici soubory:
;
;   tn15def.inc ... definice jednotlivych registru a bitu v CPU
;
; Poznamky:
;
;   XTAL = vnitrni casovac cca 1.6MHz, tj. 1C = 0.625us
;
; Specialni nastaveni pri zapisu programu a dat do CPU:
;
;   Kalibracni bajt: precist ho a pak zapsat do posledniho bajtu
;                    flash-memory (adresa $03FF)
;
;   Fuse bity: BODLEVEL = 0 (default)
;              BODEN = 0 (naprogramovat)
;              SPIEN = 0 (default)
;              RSTDISBL = 0 (naprogramovat)
;              CKSEL1 = 0 (default)
;              CKSEL0 = 0 (default)
;
; Vyuziti moznosti integrovanych I/O zarizeni:
;
;   SPI    = moznost programovani v systemu nepouzita
;   BOD    = brownout detekce zapnuta, nastaveno 4V
;   POD    = prepnuto na interni RESET, bit PB5 uvolnen pro vyuziti jako I/O
;   WATCHD = watchdog nepouzit
;   TIM0   = nepouzito
;   TIM1   = nepouzito
;   PWM    = nepouzito
;   ACOMP  = nepouzito
;   ADC    = pouzity 4 vstupy jako single-end, reference je Vcc (5V)
;   EEPROM = nepouzito
;   PORT   = pouzit 1 bit pro vystup dat a 1 bit pro rizeni LED
;
; Preruseni:
;
;   EXTINT0   = nepouzito
;   PINCHANGE = nepouzito
;   TIM0OVF   = nepouzito
;   TIM1OVF   = nepouzito
;   TIM1CMP   = nepouzito
;   EERDY     = nepouzito
;   ANACMP    = nepouzito
;   ADC       = nepouzito
;
; Prirazeni vyvodu:
;
;   PB0 = SDO vystup dat na seriovou linku
;   PB1 = LEDR ovladani LED (0=on 1=off)
;   PB2 = ADC1 mereni napeti Ukeytx
;   PB3 = ADC2 mereni napeti Upredp
;   PB4 = ADC3 mereni napeti Upwr
;   PB5 = ADC0 mereni napeti Uteplota
;
; Spolupracujici obvody:
;
;   zadne

;*** Vlozeni souboru s popisem CPU *******************************************

.include "tn15def.inc"

;--- Doplneni chybejicich udaju v TN15DEF.INC --------------------------------

.equ	E2END	=$3F                      ;konec pameti EEPROM
.equ	FLASHEND=$3FF                     ;konec pameti programu

.equ    MUXADC0 =0                        ;nastaveni MUX pro vstup ADC 0
.equ    MUXADC1 =1                        ;nastaveni MUX pro vstup ADC 1
.equ    MUXADC2 =2                        ;nastaveni MUX pro vstup ADC 2
.equ    MUXADC3 =3                        ;nastaveni MUX pro vstup ADC 3

;*** Definice ****************************************************************

;--- Konstanty ---------------------------------------------------------------

.equ   CalByte  = FLASHEND                ;umisteni kalibracni hodnoty

.equ   CLEDRun  = 35                      ;interval blikani LED po 5s
.equ   CLEDTep  = 2                       ;interval blikani pri vysoke teplote
.equ   CLEDon   = 2                       ;doba sviceni LED pri blikani
.equ   CLEDErr  = 1                       ;roznout trvale

.equ   CTepHigh = 50                      ;zvysena teplota (50°C)
.equ   CTepNeg  = 206                     ;nejnizsi zaporna teplota (-50°C)
.equ   CTepShf  = 173                     ;posun pro vypocet teploty
.equ   CUkeytx  = 25                      ;rozpoznani klicovani (2.5V)
.equ   CUpredp  = 100                     ;snizene predpeti (10V)
.equ   CUpwr    = 100                     ;snizene napajeni (10V)

;--- Ostatni -----------------------------------------------------------------

.equ    LEDR    = PB1                     ;ovladani LED R (1=off, 0=on)
.equ    SDO     = PB0                     ;seriovy vystup dat

.equ    UTEP    = MUXADC0                 ;vstup ADC na mereni Uteplota
.equ    UKTX    = MUXADC1                 ;vstup ADC na mereni Ukeytx
.equ    UPRE    = MUXADC2                 ;vstup ADC na mereni Upredp
.equ    UPWR    = MUXADC3                 ;vstup ADC na mereni Upwr

.def    pamutep = R15                     ;pamet namereneho Uteplota
.def    pamuktx = R14                     ;pamet namereneho Uktx
.def    pamupre = R13                     ;pamet namereneho Upredp
.def    pamupwr = R12                     ;pamet namereneho Upwr

.def    pamhtep = R10                     ;pamet vypoctene teploty

.def    poc1    = R16                     ;pocitadlo 1 (rutiny zpozdeni)
.def    poc2    = R17                     ;pocitadlo 2 (rutiny zpozdeni)

.def    op2l    = R16                     ;operand 1 pro aritneticke operace
.def    op2h    = R17                     ;  8/16 bitu
.def    op1l    = R18                     ;operand 2 pro aritmeticke operace
.def    op1m    = R19                     ;  8/16/24 bitu
.def    op1h    = R20
.def    vyl     = R21                     ;operand 3 pro aritmeticke operace
.def    vym     = R22                     ;  8/16/24 bitu
.def    vyh     = R23
.def    pocp    = R24                     ;pocitadlo pruchodu pri aritmetice
.def    zbl     = R26                     ;zbytek po deleni pro aritm. operace
.def    zbm     = R27                     ; 8/16/24 bitu
.def    zbh     = R28

.def    pom     = R28                     ;pomocny registr pro AD prevod teploty

.def    par1    = R25                     ;predani parametru s rutinami
.def    regsa   = R24                     ;pracovni registr rutin A
.def    pocb    = R23                     ;pocitadlo odeslanych bitu
.def    suma    = R22                     ;kontrolni soucet

.def    pocled  = R9                      ;pocitadlo pro blikani LED
.def    ledflg  = R29                     ;nastavovac sviceni LED

;*** MAIN - hlavni cast programu *********************************************

;--- segment pameti programu -------------------------------------------------

                .cseg

;--- startovaci vektory po resetu a preruseni --------------------------------

; (u ATTINY15L adresy $000 az $008)

.org 0
		rjmp	Start             ;reset
.org INT0addr
		reti                      ;vnejsi preruseni
.org PCINTaddr
		reti                      ;zmena na pinu
.org T1COMPaddr
		reti                      ;casovac 1 - porovnani
.org OVF1addr
		reti                      ;casovac 1 - preteceni
.org OVF0addr
		reti                      ;casovac 0 - preteceni
.org EERDYaddr
		reti                      ;eeprom  - hotovo
.org ACIaddr
		reti                      ;analogovy komparator
.org ADCCaddr
		reti                      ;AD prevodnik

;--- zacatek programu po resetu ----------------------------------------------
   
Start:
                ; kalibrace oscilatoru (kalibracni bajt ulozen pri programovani
                ; CPU do posledniho bajtu programove pameti)
                ldi     ZL,low(CalByte)
                ldi     ZH,high(CalByte)
                lpm
                out     OSCCAL,r0

                ; inicializace vystupnich pinu
                sbi     DDRB, SDO         ;seriovy kanal nastavit jako vystup
                sbi     PORTB, SDO        ;seriovy kanal nastavit na 1
                sbi     DDRB, LEDR        ;pin s LED R nastavit jako vystup

                ; nastavit rezim prevodniku
                ldi     regsa, 0b10000100 ;ADEN=1,ADSC=0,ADFR=0(single),
                out     ADCSR, regsa      ;ADIF=0,ADIE=0,ADSP=100(:16...100kHz)

                ; 2x bliknuti LED R po zapnuti
                cbi     PORTB, LEDR       ;rozsvitit LED R
                rcall   Cas100ms
                sbi     PORTB, LEDR       ;zhasnout LED R
                rcall   Cas100ms
                cbi     PORTB, LEDR       ;rozsvitit LED R
                rcall   Cas100ms
                sbi     PORTB, LEDR       ;zhasnout LED R
                rcall   Cas100ms
                
                ;iniciovat blikani LED
                ldi     ledflg, CLEDRun
                mov     pocled, ledflg
                
                ;inicializovat namerene hodnoty
                ; nacteni hodnot napeti na vsech 4 vstupech
                ; celkem AD prevod trva 4x(259us+2C)=1044us
                ldi     par1, UTEP
                rcall   GetADCt
                mov     pamutep,par1
                ldi     par1, UKTX
                rcall   GetADC
                mov     pamuktx,par1
                ldi     par1, UPRE
                rcall   GetADC
                mov     pamupre,par1
                ldi     par1, UPWR
                rcall   GetADC
                mov     pamupwr,par1
Smycka:
                ; 1.nacteni hodnot napeti na vsech 4 vstupech
                ; prumerovani s predchozi sejmutou hodnotou
                ; novou hodnotu zapocitat s dvojnasobnou vahou
                ldi     par1, UTEP
                rcall   GetADCt
                add     pamutep, par1
                ror     pamutep
                add     pamutep, par1
                ror     pamutep
                ldi     par1, UKTX
                rcall   GetADC
                add     pamuktx, par1
                ror     pamuktx
                add     pamuktx, par1
                ror     pamuktx
                ldi     par1, UPRE
                rcall   GetADC
                add     pamupre, par1
                ror     pamupre
                add     pamupre, par1
                ror     pamupre
                ldi     par1, UPWR
                rcall   GetADC
                add     pamupwr, par1
                ror     pamupwr
                add     pamupwr, par1
                ror     pamupwr
                ; 2. nacteni hodnot napeti na vsech 4 vstupech
                ; prumerovani s predchozi sejmutou hodnotou
                ; novou hodnotu zapocitat s dvojnasobnou vahou
                ldi     par1, UTEP
                rcall   GetADCt
                add     pamutep, par1
                ror     pamutep
                add     pamutep, par1
                ror     pamutep
                ldi     par1, UKTX
                rcall   GetADC
                add     pamuktx, par1
                ror     pamuktx
                add     pamuktx, par1
                ror     pamuktx
                ldi     par1, UPRE
                rcall   GetADC
                add     pamupre, par1
                ror     pamupre
                add     pamupre, par1
                ror     pamupre
                ldi     par1, UPWR
                rcall   GetADC
                add     pamupwr, par1
                ror     pamupwr
                add     pamupwr, par1
                ror     pamupwr
                ; 3. nacteni hodnot napeti na vsech 4 vstupech
                ; prumerovani s predchozi sejmutou hodnotou
                ; novou hodnotu zapocitat s dvojnasobnou vahou
                ldi     par1, UTEP
                rcall   GetADCt
                add     pamutep, par1
                ror     pamutep
                add     pamutep, par1
                ror     pamutep
                ldi     par1, UKTX
                rcall   GetADC
                add     pamuktx, par1
                ror     pamuktx
                add     pamuktx, par1
                ror     pamuktx
                ldi     par1, UPRE
                rcall   GetADC
                add     pamupre, par1
                ror     pamupre
                add     pamupre, par1
                ror     pamupre
                ldi     par1, UPWR
                rcall   GetADC
                add     pamupwr, par1
                ror     pamupwr
                add     pamupwr, par1
                ror     pamupwr
                ; 4. nacteni hodnot napeti na vsech 4 vstupech
                ; prumerovani s predchozi sejmutou hodnotou
                ; novou hodnotu zapocitat s dvojnasobnou vahou
                ldi     par1, UTEP
                rcall   GetADCt
                add     pamutep, par1
                ror     pamutep
                add     pamutep, par1
                ror     pamutep
                ldi     par1, UKTX
                rcall   GetADC
                add     pamuktx, par1
                ror     pamuktx
                add     pamuktx, par1
                ror     pamuktx
                ldi     par1, UPRE
                rcall   GetADC
                add     pamupre, par1
                ror     pamupre
                add     pamupre, par1
                ror     pamupre
                ldi     par1, UPWR
                rcall   GetADC
                add     pamupwr, par1
                ror     pamupwr
                add     pamupwr, par1
                ror     pamupwr
                
                ; prevod Uteplota na teplotu
                ; celkem trva 417-472us
                ;
                ; delic napeti s cidlem KTY81-120
                ;
                ; Ru = 1000 ohmu (horni odpor)
                ; Uref = 5V ... UREFH = 511 = hodnota AD prevodu pro 5V
                ; U = namerene napeti ... UHN = odpovidajici hodnota prevodu
                ;                              (cca 173-351)
                ; UH = UHN-173 ... UH upravena tak, aby se vesla do 8 bitu
                ;
                ; interpolace zavislosti T=f(UH) cidla pro typicke hodnoty R
                ;
                ; T = 0,002179172*UH^2+0,6878442*R-47,12363
                ;
                ; realizace v celociselne aritmetice cislech
                ;
                ; T=(11*UH*UH+3439*UH-235618)/5000

                ; A=UH*UH*11

                mov     op1l, pamutep
                mov     op2l, op1l
                rcall   Mul8x8
                mov     op1l, vyl
                mov     op1m, vym
                ldi     op2l, 11
                rcall   Mul16x8
                mov     zbl, vyl
                mov     zbm, vym
                mov     zbh, vyh

                ; B=UH*3439
                ldi     op1l, $6F
                ldi     op1m, $0D
                mov     op2l, pamutep
                rcall   Mul16x8
                
                ;C=A+B-235618
                mov     op1l, vyl
                mov     op1m, vym
                mov     op1h, vyh
                add     op1l, zbl
                adc     op1m, zbm
                adc     op1h, zbh
                subi    op1l, $62
                sbci    op1m, $98
                sbci    op1h, $03
                
                ;vysledek=C/5000
                ldi     op2l, $88
                ldi     op2h, $13
                rcall   Div24d16

                mov      pamhtep, vyl
                
                ; odeslani dat na seriovy port
                ; odeslani dat trva 133,3ms

                ; vypocet kontrolniho souctu
                ; trva 5C (4us)
                ldi      suma, $C0 + $C1
                add      suma, pamhtep
                add      suma, pamuktx
                add      suma, pamupre
                add      suma, pamupwr

                ; synchronizace a magicka konstanta - celkem 50001us
                ldi      par1, $FF
                rcall    SendByte         ;16667us
                ldi      par1, $C0
                rcall    SendByte
                ldi      par1, $C1
                rcall    SendByte
                
                ; odeslani 4 hodnot namerenych dat - celkem 66668us
                mov      par1, pamhtep
                rcall    SendByte
                mov      par1, pamuktx
                rcall    SendByte
                mov      par1, pamupre
                rcall    SendByte
                mov      par1, pamupwr
                rcall    SendByte
                
                ; odeslani kontrolniho souctu
                mov      par1, suma
                rcall    SendByte
                
                ;vyhodnoceni zmerenych udaju pro signalizaci LED R
                
                ldi      regsa, CLEDRun   ;normalni rychlost blikani
                mov      par1, pamhtep    ;test na teplotu
                cpi      par1, CTepHigh
                brcs     SetLED_1
                cpi      par1, CTepNeg-1
                brcc     SetLED_1
                ldi      regsa, CLEDTep   ;rychle blikani pri vysoke teplote
SetLED_1:
                mov      par1, pamuktx    ;rozpoznani klicovani
                cpi      par1, CUkeytx
                brcs     SetLED_2         ;skoc kdyz neni zaklicovano
                mov      par1, pamupre
                cpi      par1, CUpredp
                brcc     SetLED_2         ;skoc kdyz je predpeti vporadku
                ldi      regsa, CLEDErr   ;nizke predpeti, svitit po dobu TX
SetLED_2:
                mov      par1, pamupwr
                cpi      par1, CUpwr
                brcc     SetLED_3         ;skoc kdyz je napajeni vporadku
                ldi      regsa, CLEDErr   ;nizke napajeni, svitit trvale
SetLED_3:
                mov      ledflg, regsa
                cp       ledflg, pocled
                brcc     SetLED_4
                mov      pocled, ledflg   ;zkratit cyklus kdyz by byl delsi nez
                                          ;novy interval
SetLED_4:
                ; ovladani blikani LED
                
                dec     pocled
                brne    BlikLED_2
                mov     pocled, ledflg
                sbic    PORTB, LEDR       ;preskoc nasl. instr. kdyz bit = 0
                rjmp    BlikLED_1         ;skoc, kdyz je zhasnuta
                ;LED sviti
                cpi     ledflg, CLEDErr
                breq    BlikLED_2         ;skoc kdyz se signalizuje chyba
                sbi     PORTB, LEDR       ;zhasni LED
                rjmp    BlikLED_2
BlikLED_1:
                ;LED zhasnuta
                cbi     PORTB, LEDR       ;rozni LED
                cpi     ledflg, CLEDErr
                breq    BlikLED_2         ;skoc kdyz se signalizuje chyba
                ldi     regsa, CLEDon
                mov     pocled, regsa
BlikLED_2:
                rjmp    Smycka

;*** Podprogramy *************************************************************

;--- Nacteni 1 hodnoty ADC prevodu ze zadaneho vstupniho pinu ----------------

; v PAR1 se preda cislo analogoveho vstupu 0=ADC0, 1=ADC1, 2=ADC2 a 3=ADC3
; v PAR1 vrati hornich 8 bitu nactene hodnoty

; 1 prevod pri 100kHz bude trvat 250us + rezije 3+1+1+2+(1/2)+(2/0)+1+4=15/14
; tj. 259us

GetADC:
                ori     par1, 0b00100000  ;REFS=00(Vcc),ADLAR=1,MUX=par1
                out     ADMUX, par1
                sbi     ADCSR, ADSC       ;zahajit prevod
GetADC_wait:
                sbic    ADCSR, ADSC       ;skoc kdyz je prevod hotovy (ADSR=0)
                rjmp    GetADC_wait       ;cekej dal
                in      par1, ADCH        ;precti hornich 8 bitu vysledku
                ret

;--- Nacteni 1 hodnoty teploty z ADC prevodu ze zadaneho vstupniho pinu ------

; v PAR1 se preda cislo analogoveho vstupu 0=ADC0, 1=ADC1, 2=ADC2 a 3=ADC3
; v PAR1 vrati bity 1 az 8 nactene hodnoty, bit 0 se necte
; v PAR2 vrati 9. bit nactene hodnoty

; 1 prevod pri 100kHz bude trvat 250us + rezije 3+1+1+2+(1/2)+(2/0)+5+4=19/18
; tj. 262us

GetADCt:
                ori     par1, 0b00000000  ;REFS=00(Vcc),ADLAR=0,MUX=par1
                out     ADMUX, par1
                sbi     ADCSR, ADSC       ;zahajit prevod
GetADCt_wait:
                sbic    ADCSR, ADSC       ;skoc kdyz je prevod hotovy (ADSR=0)
                rjmp    GetADCt_wait      ;cekej dal
                in      par1, ADCL        ;precti spodnich 8 bitu vysledku
                in      pom, ADCH         ;precti horni 2 bity vysledku
                lsr     pom
                ror     par1
                subi    par1, CTepShf     ;odectenim se vysledek vejde do 8b
                ;horni bajt vysledku je mozne ignorovat, vysledek bude
                ;v rozmezi 0-178, hodnota po prevodu je 173-351
                ret

;--- Aritmetika - nasobeni 8x8->16 -------------------------------------------

; nasobeni cisel bez znamenka
; 8bitu x 8bitu -> 16bitu
; op1 x op2 -> vy
; cas 3+4+4+8x7-1=66C (41.25us)

Mul8x8:                                   ;rcall = 3C
                mov     vyl, op2l         ;1C
                clr     vym               ;1C
                ldi     pocp, 8           ;1C
                lsr     vyl               ;1C
Mul8x8_1:
                brcc    Mul8x8_2          ;1/2C
                add     vym, op1l         ;1C
Mul8x8_2:
                ror     vym               ;1C
                ror     vyl               ;1C
                dec     pocp              ;1C
                brne    Mul8x8_1          ;1/2C
                ret                       ;4C

;--- Aritmetika - nasobeni 16x8->24 ------------------------------------------

; nasobeni cisel bez znamenka
; 16bitu x 8bitu -> 24bitu
; op1 x op2 -> vy
; max. cas 3+4+5+8*9-1=83 (51.875us)
; min. cas 3+4+5+8*8-1=75 (46.875us)

Mul16x8:                                  ;rcall = 3C
                mov     vyl, op2l         ;1C
                clr     vym               ;1C
                clr     vyh               ;1C
                ldi     pocp, 8           ;1C
                lsr     vyl               ;1C
Mul16x8_1:
                brcc    Mul16x8_2         ;1/2C
                add     vym, op1l         ;1C
                adc     vyh, op1m         ;1C
Mul16x8_2:
                ror     vyh               ;1C
                ror     vym               ;1C
                ror     vyl               ;1C
                dec     pocp              ;1C
                brne    Mul16x8_1         ;1/2C
                ret                       ;4C

;--- Aritmetika - deleni 24:16->24 -------------------------------------------

; deleni cisel se znamenkem u prvniho operandu
; 24bitu : 16bitu -> 24bitu vysledek a 24bitu zbytek
; op1 : op2 -> vy , zb
; max. cas 3+4+7+24*20+5=499 (312us) verze bez znamenka
; min. cas 3+4+7+24*17+5=427 (267us) verze bez znamenka
; pro kladny OP1 pripocist 7C (5us)
; pro zaporny OP1 pripocist 27C (17us)
;* pred poctem cyklu oznacuje cykly pridane kvuli upravam znamenka

Div24d16:                                 ;rcall = 3C
                tst	op1h              ;*1C, zjistit znamenko OP1
                brmi    Div24d16_1        ;*1/2C, je-li zaporne cislo, tak skoc
                mov     vyl, op1l         ;1C
                mov     vym, op1m         ;1C
                mov     vyh, op1h         ;1C
                rjmp    Div24d16_2        ;*2C
Div24d16_1:
                clr     vyl               ;*1C,zmenit znamenko u zaporneho cisla
                clr	vym               ;*1C,VY = 0 - VY
                clr	vyh               ;*1C
                clc                       ;*1C
                sbc	vyl, op1l         ;*1C
                sbc	vym, op1m         ;*1C
                sbc	vyh, op1h         ;*1C
Div24d16_2:
                clr     zbl               ;1C
                clr     zbm               ;1C
                sub     zbh,zbh           ;zbytek i carry = 0, 1C
                ldi     pocp, 25          ;1C
Div24d16_3:
                rol     vyl               ;1C
                rol     vym               ;1C
                rol     vyh               ;1C
                dec     pocp              ;1C
                brne    Div24d16_4        ;1/2C

                tst     op1h              ;*1C,test na puvodni znamenko OP1
                brpl    Div24d16_7        ;*1/2C,skoc, kdyz byl kladny OP1
                com     vyl               ;*1C,zmen znamenko u VY
                com     vym               ;*1C,VY = (-1-VY)+1
                com     vyh               ;*1C
                clr     pocp              ;*1C,nelze pricitat konstantu - pricitat
                sec                       ;*1C,nulu v registru a jednicku do L
                adc     vyl, pocp         ;*1C,operandu pricist nastavenim CY=1
                adc     vym, pocp         ;*1C
                adc     vyh, pocp         ;*1C
                com     zbl               ;*1C,zmen znamenko u zbytku
                com     zbm               ;*1C,ZB = (-1-ZB)+1
                com     zbh               ;*1C
                sec                       ;*1C
                adc     zbl, pocp         ;*1C
                adc     zbm, pocp         ;*1C
                adc     zbh, pocp         ;*1C
Div24d16_7:
                ret                       ;4C
Div24d16_4:
                rol     zbl               ;1C
                rol     zbm               ;1C
                rol     zbh               ;1C
                sub     zbl, op2l         ;1C
                sbc     zbm, op2h         ;1C
                sbci    zbh, 0            ;1C
                brcc    Div24d16_6        ;1/2C
                add     zbl, op2l         ;1C
                adc     zbm, op2h         ;1C
                brcc    Div24d16_5        ;1/2C
                inc     zbh               ;1C
Div24d16_5:
                clc                       ;1C
                rjmp    Div24d16_3        ;2C
Div24d16_6:
                sec                       ;1C
                rjmp    Div24d16_3        ;2C

;--- Odeslani 1 bajtu na port ------------------------------------------------

; odesilana hodnota se preda v par1
; celkem 10x2667C ... 16669us

SendByte:                                 ;rcall = 3C
                mov     regsa, par1       ;1C
                ldi     pocb, 8           ;1C
                ; start bit
                cbi     PORTB, SDO        ;2C
                rcall   Cas1bu            ;2661C
                nop                       ;1C, dorovnani
SendByte_1:
                lsr     regsa             ;1C
                brcc    SendByte_2        ;1/2C
                nop                       ;1C, dorovnani
                sbi     PORTB, SDO        ;2C
                rjmp    SendByte_3        ;2C
SendByte_2:
                cbi     PORTB, SDO        ;2C
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
SendByte_3:
                rcall   Cas1b             ;2655C
                dec     pocb              ;1C
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                brne    SendByte_1        ;1/2C
                ; stop bit
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                nop                       ;1C, dorovnani
                sbi     PORTB, SDO        ;2C
                rcall   Cas1b             ;2655C
                ret                       ;4C
                
;--- Zpozdeni 1 bitu pri seriove komunikaci ----------------------------------

; 600Bd => 1b=1666.7us 1C=0.625us => 1b=2667C
; Tc=3*poc2+770*poc1-760 (vcetne rcall a ret)
;
; rutina poslani 1bajtu + 1 instrukce mov ma reziji 12C mezi stop a start bitem
; Cas1b snizit o 12C, tj. na delku 2655C
; pro potreby rutiny odesilani bajtu vytvorit i cas Cas1bu o 6C delsi
;
; Tc=3*111+770*4-760=2653C
; korekce +2C na pozadovanych 2655C pomoci pridaneho 2xNOP

Cas1bu:
                nop                     ;6x1C (cela delka 2661C)
                nop
                nop
                nop
                nop
                nop
Cas1b:                                  ;rcall = 3C
                ldi     poc1, 4         ;1C
                ldi     poc2, 111       ;1C
Cas1b_1:
                dec     poc2            ;1C
                brne    Cas1b_1         ;1C pokracovani, 2C skok
                dec     poc1            ;1C
                brne    Cas1b_1         ;1C pokracovani, 2C skok
                nop                     ;1C
                nop                     ;1C
                ret                     ;4C

;--- Zpozdeni 100ms ----------------------------------------------------------

; 100ms => 160000C pri 1C=0.625us
; Tc=3*poc2+770*poc1-760 (vcetne rcall a ret)
; Tc=3*200+770*208-760=160000C

Cas100ms:                               ;rcall = 3C
                ldi     poc1, 208       ;1C
                ldi     poc2, 200       ;1C
Cas100ms_1:
                dec     poc2            ;1C
                brne    Cas100ms_1      ;1C pokracovani, 2C skok
                dec     poc1            ;1C
                brne    Cas100ms_1      ;1C pokracovani, 2C skok
                ret                     ;4C

;*** Datova cast *************************************************************

; retezce zarovnat na sudy pocet bajtu kvuli reprezentaci v pameti

;--- Identifikace programu ---------------------------------------------------

; v programu nevyuzito, pouze pro optickou identifikaci obsahu binarniho
; souboru

Identifikace:   .DB     0,"XVRT23U v0.5 14.3.2004",0

;*** Konec souboru ***********************************************************
.EXIT
