/*---------------------------------------------*/ /* Jan Dvořák (dvoraj19) ÚT 11:00 (6.12.2008) */ /*---------------------------------------------*/ .include "m169def.inc" .cseg .org 0x0000 jmp start .org 0x000A jmp int_T2 .org 0x0100 .dseg sekundy: .byte 1 ;proměnná pro čítač /pole velikosti 1 joys: .byte 1 ;výsledek joysticku .cseg start: .include "znaky.inc" ; soubor se znaky ACII ;vynulování čítače ldi r16, 0 sts sekundy, r16 sts joys, r16 ;inicializace zasobniku ldi r16, 0x00 out SPL, r16 ldi r16, 0x04 out SPH, r16 ;inicializace displaye call init_disp call smaz_disp ;inicializace čítače cli ; globální zakázání přerušení ldi r16, 0b00001000 sts ASSR, r16 ; vyber hodiny od oscilátoru 32768 Hz ldi r16, 0b00000001 sts TIMSK2, r16 ; povolení přerušení od časovače 2 ldi r16, 0b000011 sts TCCR2A, r16 ; spuštění čítače s dělícím poměrem 128 (1 s) sei ; povolení přerušení (globální) ;init joy in r17, DDRE andi r17, 0b11110011 in r16, PORTE ori r16, 0b00001100 out DDRE, r17 out PORTE, r16 ldi r16, 0b00000000 sts DIDR1, r16 in r17, DDRB andi r17, 0b00101111 in r16, PORTB ori r16, 0b11010000 out DDRB, r17 out PORTB, r16 ; /* DEMONSTRACE JOYSTICKU */ ldi r21, 1 smycka: lds r16, sekundy ; porovnáme jestli na dispplay je stejná hodnota jako v v sekundy cp r21, r16 breq smycka mov r21, r16; akuální hodnota nactiznovu: in r18, PINB in r19, PINE add r18,r19 ;výpočet hodnoty, zobrazení ori r18, 0b00101111; nastavíme všude jedničky ori r19, 0b11110011; kde není definován com r18; negujeme, tj 1 jen u stisknutého com r19 or r18, r19 mov r20,r18 nop nop nop nop nop in r18, PINB in r19, PINE add r18,r19 ;výpočet hodnoty, zobrazení ori r18, 0b00101111; nastavíme všude jedničky ori r19, 0b11110011; kde není definován com r18; negujeme, tj 1 jen u stisknutého com r19 or r18, r19 cp r18, r20 brne nactiznovu mov r16, r18 call zobraz_cislo rjmp smycka ;konec programu rjmp end /*----------------------------------*/ /* Obsluha přerušení */ /*----------------------------------*/ int_T2: push r16 in r16, SREG push r16 lds r16, sekundy inc r16 ;vynulování pro větší než 9 cpi r16,10 brlo pres ldi r16, 0 pres: ; sts sekundy, r16 pop r16 out SREG, r16 pop r16 ;načtení joysticku push r18 push r19 push r20 ;sts joys, r18 pop r20 pop r19 pop r18 ; reti /*----------------------------------*/ /* Inicializuj display */ /*----------------------------------*/ init_disp: ldi r16, 0xB7 sts LCDCRB, r16 ldi r16, 0x10 sts LCDFRR, r16 ldi r16, 0x0F sts LCDCCR, r16 ldi r16, 0x80 sts LCDCRA, r16 ret /*----------------------------------*/ /* Smazat display */ /*----------------------------------*/ smaz_disp: ldi r16,0 ;pozice 1 2 sts LCDDR0, r16 sts LCDDR0 + 5, r16 sts LCDDR0 + 10, r16 sts LCDDR0 + 15, r16 ;pozice 3 4 sts LCDDR1, r16 sts LCDDR1 + 5, r16 sts LCDDR1 + 10, r16 sts LCDDR1 + 15, r16 ;pozice 5 6 sts LCDDR2, r16 sts LCDDR2 + 5, r16 sts LCDDR2 + 10, r16 sts LCDDR2 + 15, r16 ;ostatni segmenty sts LCDDR3, r16 sts LCDDR3 + 5, r16 sts LCDDR3 + 10, r16 sts LCDDR3 + 15, r16 ret /*----------------------------------*/ /* Zobrazit znak ASCII */ /*----------------------------------*/ zobraz_znak: ;používám R16-R21, R0,1 R26 R27(X) R30 R31(Z) ;zobrazení znaku: r16 znak; r17 pozice ;pomocné proměné - zachování pvodních v zásobíku push r0 ;operátor mul push r1 push r16 push r17 push r18 push r19 push r20 push r21 push r26 ;X push r27 push r30 ;Z push r31 ;výpočet znaku (4*ASC()-42) subi r16, 42 lsl r16 lsl r16 ;výpočet pozice ;odečteme 1, vydělíme 2 - display po 2 znacích, zjistíme levou - pravou pozici ldi r19,0 ;R19 : levost pravost uložení informace dec r17 lsr r17 ;určení vlevo - v pravo-carry bit při dělení dvěma - liché číslo; brcc preskoc ldi r19, 1 ; informace o pozici segmentu preskoc: ;adresa na display ldi r26,LCDDR0; X registr clr r27 ; jen tak pro jistotu add r26,r17 ;pozice ;načtení znaků - registr Z ldi r30, low(znaky<<1) ldi r31, high(znaky<<1) add r30, r16; přesun na pozici znaku ;provedeme cyklus ve kterém načteme data z druhého segmentu ;a přidáme data nová, posuneme se na další řádek ldi r21, 4; cyklus: ;LCDR ld r18, X; načteme aktuální stav a vynulujeme příslušné byty - horní nebo dolní lpm r20, Z+ ; načteme z registru Z, zvětšíme o 1 - posun na další čtveřici v souboru subi r19, 0; kontrola R19 - jestli byl carry bit v dělení - pravost levost breq neposun posun: ;posun o 4 bity - levý segment lsl r20 lsl r20 lsl r20 lsl r20 ;vynulujem horní byty andi r18, 0b00001111 jmp pokracuj neposun: andi r18, 0b11110000 ;nulujeme spodní byty pokracuj: add r18, r20 mov r0, r18 st X, r0 adiw r26,5 ; posun v registru dec r21 ;správa cyklu brne cyklus; pokračuejem v cyklu dokud r21 není nula ;navrácení hodnot do záobníku registrům pop r31 pop r30 pop r27 pop r26 pop r21 pop r20 pop r19 pop r18 pop r17 pop r16 pop r1 pop r0 ret /*----------------------------------*/ /* Zobraz číslo */ /*----------------------------------*/ zobraz_cislo: ;číslo z regitru R16; další používané R17, R18 ;rozdělíme výpočet na výpočet stovek, desítek a jednotek, pak pomocí ;zobraz znak zobazíme na display (zobrazujeme zprava) push r17; uchování registrů push r18 ;stovky ldi r17, 100 call vydel_cisla ; výsledek v R16, zbytek R17 mov r18, r17 ; uchování zbytku ;mod nezobrazuj nuly, pokud zapoznámkujeme řádky s hvězdičkama, zobrazíme nuly brne mod2a ;*********************** ldi r16, '@' ;*********************** jmp mod2b ;*********************** mod2a: ;*********************** subi r16, 16 ; výpočet hodnoty pro zobrazznak (ASCII) mod2b: ;*********************** ldi r17, 4 call zobraz_znak ;desítky ldi r17, 10 mov r16, r18 call vydel_cisla mov r18, r17 ;mod nezobrazuj nuly brne mod2aa ;*********************** ldi r16, '@' ;*********************** jmp mod2ab ;*********************** mod2aa: ;*********************** subi r16, 16 ; výpočet hodnoty pro zobrazznak (ASCII) mod2ab: ;*********************** ldi r17, 5 call zobraz_znak ;jednotky mov r16, r18; přesun zbytku po delení 10 ldi r17, 6 subi r16, 16 ; výpočet hodnoty pro zobrazznak (ASCII) call zobraz_znak ;navrácení registrům pvodní hodnoty pop r18 pop r17 ; ret /*----------------------------------*/ /* Vyděl čísla */ /*----------------------------------*/ vydel_cisla: ;číslo z registru 16 čílem z registru 17 ;výsledek: r16 ;používané registry: R18, R19 push r18 ; uchování v zásobníku push r19; zbytek po deleni ldi r18, 8; 8 bitová čísla - režije cyklu ldi r19, 0 lsl r16 ; posun o byt - vynásobení 2 cyklus_del: rol r19 cp r19, r17 brlo del_preskoc sub r19, r17 del_preskoc: rol r16 dec r18 brne cyklus_del com r16 mov r17, r19 ;promenné ze zásobníku pop r19 pop r18 ; ret /*----------------------------------*/ /* Prázdná smyčka - čekání */ /*----------------------------------*/ cekej: ;používán r16, prázdná smyčka push r16 ldi r16,200 zct: dec r16 brne zct pop r16 ret end: rjmp end