.include "znaky.inc" ; inicializace LCD displeje ; neničí obsah žádných registrů init_disp: push r16 ldi r16, 0xB7 sts LCDCRB, r16 ldi r16, 0x10 sts LCDFRR, r16 ldi r16, 0x0F sts LCDCCR, r16 ldi r16, 0x80 sts LCDCRA, r16 pop r16 ret ; vymaže obsah LCD displeje ; neničí obsah žádných registrů clear_disp: push r16 ldi r16, 0x00 sts LCDDR0, r16 sts LCDDR0+5, r16 sts LCDDR0+10, r16 sts LCDDR0+15, r16 sts LCDDR1, r16 sts LCDDR1+5, r16 sts LCDDR1+10, r16 sts LCDDR1+15, r16 sts LCDDR2, r16 sts LCDDR2+5, r16 sts LCDDR2+10, r16 sts LCDDR2+15, r16 sts LCDDR3, r16 sts LCDDR3+5, r16 sts LCDDR3+10, r16 sts LCDDR3+15, r16 pop r16 ret ; zobrazí na LCD displeji dvojtečky ; neničí obsah žádných registrů zobr_dvojtecky: push r16 lds r16, LCDDR3+5 ori r16, 0b00000011 sts LCDDR3+5, r16 pop r16 ret ; zhasne na LCD displeji dvojtečky ; neničí obsah žádných registrů zhasni_dvojtecky: push r16 lds r16, LCDDR3+5 andi r16, 0b11111100 sts LCDDR3+5, r16 pop r16 ret ; zobrazí na displeji přesípací hodiny ; neničí obsah žádných registrů presip_hodiny: push r16 ldi r16, 0x09 sts LCDDR0, r16 ldi r16, 0x02 sts LCDDR0+5, r16 ldi r16, 0x0D sts LCDDR0+15, r16 pop r16 ret ; zobrazí na displeji znak ; push ASCII hodnota ; push pozice ; neničí obsah žádných registrů show_char: ; uložím do zásobníku obsah použitých registrů push r0 push r16 push r17 push r18 push r28 ; Y(L) push r29 ; Y(H) push r30 ; Z(L) push r31 ; Z(H) ; načtu ze zásobníku vstupní parametry in r28, SPL in r29, SPH ldd r16, Y+12 ; parametr 1 (ASCII hodnota) ldd r17, Y+11 ; parametr 2 (pozice) ; překopíruju návratovou adresu + 2 * r0 na stacku ldd r30, Y+10 ldd r31, Y+9 std Y+12, r30 std Y+11, r31 std Y+10, r0 std Y+10, r0 ; do registru Z (r30, r31) načtu adresu v tabulce znaků ldi r30, low(znaky<<1) ldi r31, high(znaky<<1) subi r16,42 ; r16 = řádek v tabulce (L) clr r18 ; r18 = řádek v tabulce (H) lsl r16 rol r18 lsl r16 rol r18 add r30, r16 ; adresa = "znaky" + 4 * číslo řádku adc r31, r18 ; do Y uložím adresu ovládacích bytů, do r17, r18 pozici ldi r28, low(LCDDR0) ; Y = ovládací byty ldi r29, high(LCDDR0) subi r17, 2 ; pozice mínus dva (první číslice má označení 2) clr r18 ; ovládání horním nebo dolním nibblem? lsr r17 ; pozice děleno dvěma brlo show_char_horni ; liché pozice se ovládají horním nibblem show_char_dolni: add r28, r17 adc r29, r18 ld r16, Y andi r16, 0xF0 lpm add r0, r16 st Y, r0 adiw r30, 1 ldd r16, Y+5 andi r16, 0xF0 lpm add r0, r16 std Y+5, r0 adiw r30, 1 ldd r16, Y+10 andi r16, 0xF0 lpm add r0, r16 std Y+10, r0 adiw r30, 1 ldd r16, Y+15 andi r16, 0xF0 lpm add r0, r16 std Y+15, r0 jmp show_char_konec show_char_horni: add r28, r17 adc r29, r18 ld r16, Y andi r16, 0x0F lpm swap r0 add r0, r16 st Y, r0 adiw r30, 1 ldd r16, Y+5 andi r16, 0x0F lpm swap r0 add r0, r16 std Y+5, r0 adiw r30, 1 ldd r16, Y+10 andi r16, 0x0F lpm swap r0 add r0, r16 std Y+10, r0 adiw r30, 1 ldd r16, Y+15 andi r16, 0x0F lpm swap r0 add r0, r16 std Y+15, r0 show_char_konec: ; obnovím ze zásobníku obsah použitých registrů pop r31 pop r30 pop r29 pop r28 pop r18 pop r17 pop r16 pop r0 pop r0 ; 2 * r0, protože se kvůli vstup. parametrům posunul zásobník pop r0 ret ; zobrazí dekadické číslo na displeji ; push 8-bitové číslo ; neničí obsah žádných registrů show_dec: ; uložím do zásobníku obsah použitých registrů push r16 push r17 push r28 ; Y(L) push r29 ; Y(H) ; načtu ze zásobníku vstupní parametry in r28, SPL in r29, SPH ldd r16, Y+7 ; parametr 1 (zobrazované číslo) ; překopíruju návratovou adresu + r16 na stacku ldd r17, Y+6 std Y+7, r17 ldd r17, Y+5 std Y+6, r17 ldd r17, Y+4 std Y+5, r17 ; vymažu displej call clear_disp ; přeskočím nulové číslice cpi r16, 10 brlo show_dec_10_preskoc cpi r16, 100 brlo show_dec_100_preskoc ; zobrazím číslici v řádu stovek ldi r17, '0' show_dec_100: cpi r16, 100 brlo show_dec_100_end subi r16, 100 inc r17 jmp show_dec_100 show_dec_100_end: push r17 ldi r17, 5 ; pozice push r17 call show_char; show_dec_100_preskoc: ; zobrazím číslici v řádu desítek ldi r17, '0' show_dec_10: cpi r16, 10 brlo show_dec_10_end subi r16, 10 inc r17 jmp show_dec_10 show_dec_10_end: push r17 ldi r17, 6 ; pozice push r17 call show_char; show_dec_10_preskoc: ; zobrazím číslici v řádu jednotek ldi r17, '0' add r17, r16 push r17 ldi r17, 7 ; pozice push r17 call show_char; ; obnovím ze zásobníku obsah použitých registrů pop r29 pop r28 pop r17 pop r16 pop r16 ; protože se kvůli vstup. parametrům posunul zásobník ret ; zobrazí dekadické číslo na displeji ; push 8-bitové číslo ; neničí obsah žádných registrů show_dec1: push r16 push r16 push r28 ; Y(L) push r29 ; Y(H) in r28, SPL in r29, SPH ldd r16, Y+5 ; návratová adresa (high) std Y+4, r16 ldd r16, Y+6 ; návratová adresa (low) std Y+5, r16 ldi r16, 0 ; vyšší byte zobrazovaného čísla std Y+6, r16 pop r29 pop r28 pop r16 jmp show_dec2 ; zobrazí dekadické číslo na displeji ; push nižší byte 16-bitového čísla ; push vyšší byte 16-bitového čísla ; neničí obsah žádných registrů show_dec2: ; význam jednotlivých registrů: ; r16 = nižší byte vstupního čísla ; r17 = vyšší byte vstupního čísla ; r18 = nižší byte řádu ; r19 = vyšší byte řádu ; r20 = znak '0' nebo ' ' ; r21 = zobrazovaná číslice ; r22 = nižší byte doplňku řádu ; r23 = vyšší byte doplňku řádu ; uložím do zásobníku obsah použitých registrů (10 bytů) push r16 push r17 push r18 push r19 push r20 push r21 push r22 push r23 push r28 ; Y(L) push r29 ; Y(H) ; načtu ze zásobníku vstupní parametry in r28, SPL in r29, SPH ldd r16, Y+14 ; parametr 1 (nižší byte zobrazovaného čísla) ldd r17, Y+13 ; parametr 2 (vyšší byte zobrazovaného čísla) ; překopíruju návratovou adresu + r16 na stacku ldd r20, Y+12 std Y+14, r20 ldd r20, Y+11 std Y+13, r20 ldd r20, Y+10 std Y+12, r20 ; zobrazení jednotlivých číslic ldi r20, '@' ldi r18, 0x10 ldi r19, 0x27 call show_dec2_pom push r21 ldi r21, 3 push r21 call show_char ldi r18, 0xE8 ldi r19, 0x03 call show_dec2_pom push r21 ldi r21, 4 push r21 call show_char ldi r18, 100 ldi r19, 0 call show_dec2_pom push r21 ldi r21, 5 push r21 call show_char ldi r18, 10 ldi r19, 0 call show_dec2_pom push r21 ldi r21, 6 push r21 call show_char ldi r20, '0' ldi r18, 1 ldi r19, 0 call show_dec2_pom push r21 ldi r21, 7 push r21 call show_char ; obnovím ze zásobníku obsah použitých registrů pop r29 pop r28 pop r23 pop r22 pop r21 pop r20 pop r19 pop r18 pop r17 pop r16 pop r16 pop r16 ; protože se kvůli vstup. parametrům posunul zásobník ret ; pomocná procedura pro výpočet jedné číslice show_dec2_pom: ; vypočítám dvojkový doplněk řádu číslice mov r22, r18 mov r23, r19 com r22 com r23 ldi r21, 1 add r22, r21 ldi r21, 0 adc r23, r21 ; cyklem vypočítám číslici pro zobrazení ldi r21, '0' show_dec2_pom_cykl: cp r17, r19 brlo show_dec2_pom_hotovo breq show_dec2_pom_nevim show_dec2_pom_odecti: add r16, r22 adc r17, r23 inc r21 ldi r20, '0' jmp show_dec2_pom_cykl show_dec2_pom_nevim: cp r16, r18 brlo show_dec2_pom_hotovo jmp show_dec2_pom_odecti show_dec2_pom_hotovo: ; nuly na začátku čísla nahradím mezerami cpi r21, '0' brne show_dec2_pom_konec mov r21, r20 ; konec pomocné procedury show_dec2_pom_konec: ret