📄 menu.asm
字号:
;==============================================================================
; Obsluga menu
; Projekt: Miernik energii i mocy na ADE7759
;==============================================================================
; 1) wiersz menu 8-bajtowy
; 2) flaga T sygnalizuje wykonanie dodatkowej akcji w calym danym podmenu
; na podstawie adresu A1:A0 w opisie wiersza z bitem podmenu, jesli (A1:A0) <> 0
; 3) AD1:AD0 = 0xFFFF i BIT_PODMENU=1 to oznacza powrot do (pod)menu nadrzednego
; (AD1:AD0 jest ustawiane w MENU_LEWO) - nalezy odczytac menu nadrzedne w stosunku do biezacego
; aby pobrac adres funkcji dodatkowej
.equ BIT_PODMENU =7 ; BIT_PODMENU na najstarszym bicie N (menu_numer)
.def k0 =r0
.def k1 =r1 ; r1:r0 -adres komunikatu
.def a0 =r2
.def a1 =r3 ; r3:r2 -adres akcji
.def par0 =r4
.def par1 =r5 ; r5:r4 -parametry
.def ad0 =r6
.def ad1 =r7 ; r7:r6 -adres dodatkowej akcji
.def menu_poziom =r18
.def menu_numer =r19
;rejestr Y zawiera biezacy adres w obszarze menu
;rejestr Z sluzy do wyswietlania tekstow na lcd
; \/ -chyba jednak niekoniecznie, bo wyjscie z menu zaczyna proces (petle) od poczatku
; REJESTRY SA (musza byc) CHRONIONE (oprocz temp)
; temp i SREG jest juz chroniony w obsludze przerwania T0 (inne.asm)
.cseg
;==============================================================================
MENU: ; wejscie w menu - inicjalizacja
push k0
push k1
push a0
push a1
push par0
push par1
push ad0
push ad1
push yl
push yh
push zl
push zh
clt
clr ad0
clr ad1
rcall LCD_CLEAR
ldi menu_poziom, 1 ; menu_poziom = 1
ldi yl, low(2*menu_kalibr)
ldi yh, high(2*menu_kalibr)
sbrc flagi, fKAL
rjmp M_KAL
ldi yl, low(2*menu_start)
ldi yh, high(2*menu_start)
M_KAL: sbiw yl, 8 ; (adres menu)-8 bo w MENU_DOL jest zwiekszany
rjmp MENU_DOL ; wyswietl
KLMN: ; detekcja, czy jest to pierwsze wejscie do procedury obslugi klawisza
; zakladam, ze klawisze sa wciskane pojedynczo, z jakas przerwa miedzy jednym a drugim nacisnieciem
wdr
sbrc flagi, fKLAW_WCIS ; przeskocz, jesli flaga wyzerowana
rjmp KLMN ; na poczatek petli
lds temp, Klawisze ; laduj zmienna o stanie klawiszy
tst temp
breq KLMN ; brak nacisniecia
; rozpoznanie wcisnietego klawisza
KLAWISZ_WCISNIETY ; ustaw bit wcisniecia klawisza
sbrc temp, KLAW_TAK ; przeskocz, jesli to nie klawisz TAK
rjmp MENU_TAK ; klawisz TAK wcisniety - zatwierdzenie
sbrc temp, KLAW_NIE
rjmp MENU_NIE ; wyjscie z (pod)menu
sbrc temp, KLAW_G
rjmp MENU_GORA
sbrc temp, KLAW_D
rjmp MENU_DOL
sbrc temp, KLAW_L
rjmp MENU_LEWO
rjmp MENU_PRAWO
KLMN_RET: rcall LCD_CLEAR
clt
pop zh
pop zl
pop yh
pop yl
pop ad1
pop ad0
pop par1
pop par0
pop a1
pop a0
pop k1
pop k0
ret
;------------------------------------------------------------------------------
MENU_DOL: ; strzalka w dol
movw zl, yl ; kopia biezacego adresu wiersza do Z
; operacje musza byc na kopii (lpm Rd, Z)
MD_W: adiw zl, 8 ; 8 bajtow dalej - nastepny wiersz
lpm temp, z ; pobierz Poziom
cp temp, menu_poziom ; porownanie z obecnym poziomem
breq MS_WYSW ; rowny
brlo KLMN ; mniejszy -> koniec (pod)menu
rjmp MD_W ; wiekszy -> powtorz raz jeszcze
;------------------------------------------------------------------------------
MENU_GORA: ; strzalka w gore
movw zl, yl ; kopia biezacego adresu wiersza do Z
movw k0, menu_poziom ; kopia menu_*
ldi temp, 1<<BIT_PODMENU
com temp
and k1, temp ; czyszczenie bitu podmenu w kopii
dec k1 ; jesli menu_numer-1 = 0 to oznacza
breq MG_SPR_P ; ...poczatek (pod)menu -> spr menu_poziom
rjmp MG_W
MG_SPR_P: dec k0 ; dodatkowo jesli menu_poziom-1 = 0 to oznacza
breq KLMN ; ...poczatek menu
MG_W: sbiw zl, 8 ; 8 bajtow wczesniej - poprzedni wiersz
lpm temp, z ; pobierz P
cp temp, menu_poziom ; porownanie z obecnym poziomem
breq MS_WYSW ; rowny
brlo KLMN ; mniejszy -> koniec (pod)menu
rjmp MG_W ; wiekszy -> powtorz raz jeszcze
;----- wspolne dla DOL i GORA --------
MS_WYSW: ; przejscie i wyswietlenie komunikatu
movw yl, zl ; nowy adres wiersza w menu
adiw zl, 1
lpm menu_numer, z+ ; zmiana numeru
lpm k0, z+ ; .
lpm k1, z+ ; adres komunikatu
lpm a0, z+ ; .
lpm a1, z+ ; adres procedury (akcji)
lpm par0, z+ ; .
lpm par1, z+ ; parametry
movw zl, k0 ; laduj adres komunikatu do Z
rcall LCD_CLEAR
rcall LCD_STR_FLASH ; wyswietl
sbrc menu_numer, BIT_PODMENU ; sprawdzenie bitu podmenu
rjmp MSW_P ; (bit podmenu)=1 --> jest podmenu
; brak podmenu - sprawdzenie flagi dodatkowej akcji
brtc MSW_K ; flaga wyzerowana -> nie ma akcji
movw zl, ad0
icall ; akcja wykonana
MSW_K: rjmp KLMN ; na poczatek petli
; jest podmenu
MSW_P: ldi temp, LCD_LINE_2 | 13 ; ustaw kursor na 14-tym znaku drugiej linii
rcall LCD_COMMAND
ldi temp, '>' ; symbol podmenu ">>>"
rcall LCD_CHAR
rcall LCD_CHAR
rcall LCD_CHAR
ser temp
cp ad0, temp
cpc ad1, temp ; czy AD1:AD0 = 0xFF ?
breq ML_AD ; ...tak -> powrot do MENU_LEWO
rjmp KLMN ; na poczatek petli
;------------------------------------------------------------------------------
MENU_LEWO: ; strzalka w lewo
movw k0, menu_poziom ; kopia menu_*
dec k0 ; jesli menu_poziom-1 = 0 to oznacza
breq ML_M ; ...najwyzszy poziom
dec menu_poziom ; wchodzimy poziom wy縠j
ldi menu_numer, 2 ; menu_numer wiekszy od 1 (nieistotne jaki numer)
ser temp
mov ad0, temp
mov ad1, temp ; AD1:AD0 = 0xFF --> oznacza powrot poziom wyzej
rjmp MENU_GORA ; i szukamy wiersza na wyzszym poziomie
ML_AD: ; pobieranie adresu akcji dodatkowej
movw k0, menu_poziom
dec k0
breq ML_AD_B ; najwyzszy poziom -> brak akcji dodatkowej
; szukanie (pod)menu nadrzednego
movw zl, yl ; kopia biezacego adresu wiersza do Z
MLG_W: sbiw zl, 8 ; 8 bajtow wczesniej - poprzedni wiersz
lpm temp, z ; pobierz P
cp temp, k0 ; porownanie
brne MLG_W ; nierowny (wiekszy)
adiw zl, 4 ; ustaw na A0
lpm k0, z+ ; adres procedury (akcji)
lpm k1, z ; ...wczytaj do K1:K0 (bo A1:A0 nie moze sie zmienic)
clr temp
cp k0, temp
cpc k1, temp ; czy k1:k0 <> 0 ?
breq ML_AD_B ; ...nie, =0
set ; ...tak -> ustaw flage wykonania dodatkowej akcji po wyswietleniu wiersza menu
movw ad0, k0 ; kopiuj adres akcji dodatkowej
rjmp KLMN ; na poczatek petli
ML_AD_B: clt
clr ad0
clr ad1
ML_M: rjmp KLMN ; na poczatek petli
;------------------------------------------------------------------------------
MENU_PRAWO: ; strzalka w prawo
sbrs menu_numer, BIT_PODMENU
rjmp KLMN ; (bit podmenu)=0 --> brak podmenu
; jest podmenu
rjmp MT_P
;------------------------------------------------------------------------------
MENU_TAK: ; klawisz TAK
sbrs menu_numer, BIT_PODMENU
rjmp MT_A ; (bit podmenu)=0 --> brak podmenu
; jest podmenu
MT_P: inc menu_poziom ; poziom ni縠j...
clr temp
cp a0, temp
cpc a1, temp ; czy A1:A0 <> 0 ?
breq MT_Z ; ...nie
set ; ...tak -> ustaw flage wykonania dodatkowej akcji po wyswietleniu wiersza menu
movw ad0, a0 ; kopiuj adres akcji dodatkowej
rjmp MENU_DOL ; i szukamy wiersza na nizszym poziomie
MT_Z: clt ; kasuj flage wykonania dodatkowej akcji
rjmp MENU_DOL ; i szukamy wiersza na nizszym poziomie
; wykonanie akcji
MT_A: clr temp
cp a0, temp
cpc a1, temp ; czy A1:A0 <> 0 ?
breq MT_K ; ...nie, =0
movw zl, a0 ; zaladowanie adresu
icall ; WYWOLANIE PROCEDURY OBSLUGI
MT_K: rjmp KLMN ; na poczatek petli
;------------------------------------------------------------------------------
MENU_NIE: ; klawisz NIE
; calkowite wyjscie z MENU
rjmp KLMN_RET ; koniec
;==============================================================================
; PROCEDURY OBSLUGI POSZCZEGOLNYCH WIERSZY MENU i PODMENU
; r1:r0 i zh:zl moga byc zmieniane, bo przechowuja adres komunikatu, ktory jest wyswietlany
; tylko raz po zmianie wiersza menu; inne trzeba chronic
;==============================================================================
M_ARM_W: ; ADE rejestr MODE -wyswietlanie biezacego stanu bitu
; ZE ZMIENNYCH (nie z ADE7759)
ldi zl, low(2*txt_ze)
ldi zh, high(2*txt_ze)
lds r0, Ade_mode
lds r1, Ade_mode+1
and r0, par0 ; maska na odpowiedni bit
and r1, par1 ; ...
clr temp
cp r0, temp
cpc r1, temp
breq MX_WYSW ; bit wyzerowany
; bit ustawiony
ldi zl, low(2*txt_us)
ldi zh, high(2*txt_us)
;------- wyswietlanie komunikatu - wspolne ------
MX_WYSW: rcall LCD_STR_FLASH ; wyswietl linie
ret
;--------------------------------------
M_ARM: ; ADE rejestr MODE -zmiana bitow i wysylanie do ADE7759
; par1:par0 -maska bitowa do zmiany [0-65535]
push r2
push r3
push xl
push xh
lds r0, Ade_mode
lds r1, Ade_mode+1
movw r2, r0 ; kopia
and r2, par0 ; maska na odpowiedni bit
and r3, par1 ; ...
clr temp
cp r2, temp
cpc r3, temp
breq MARM_US ; bit wyzerowany -> ustaw
; bit ustawiony -> zeruj
movw r2, par0 ; kopia maski
com r2
com r3 ; odwroc maski
and r0, r2
and r1, r3
ldi zl, low(2*txt_ze)
ldi zh, high(2*txt_ze)
rjmp MARM_D
MARM_US: or r0, par0
or r1, par1
ldi zl, low(2*txt_us)
ldi zh, high(2*txt_us)
MARM_D:
push r0
push r1 ; zachowaj Ade_mode
; rejestr MODE zmieniany w trybie kalibracji
movw xl, r0
sbr xl, 1<<M_DISSAG ; wylacz linie SAG
sbr xh, 1<<M_DTRT1
cbr xh, 1<<M_DTRT0 ; ustaw zbieranie probek na 7kHz (140 na okres 50Hz)
movw r0, xl
sts Ade_mode, r0
sts Ade_mode+1, r1 ; zapisz Ade_mode dla trybu kalibracji
cli
ldi temp, ADE_MODE_ADR
rcall SPI_ADE_WRITE_2B ; temp -komenda; r1:r0 -2 bajty danych
sei
rcall OIP ; przeliczenie ilosci: Probek_ile
pop r1
pop r0 ; przywroc oryginal
sts Ade_mode, r0
sts Ade_mode+1, r1 ; zapisz oryginal Ade_mode
pop xh
pop xl
pop r3
pop r2
rjmp MX_WYSW
;------------------------------------------------------------------------------
M_AOR_W: ; odczyt rejestrow ADE w drugiej linii LCD (nie trzeba zatwierdzac TAK)
; par0 -adres rejestru, par1 -ilu bajtowy
ldi temp, LCD_LINE_2
rcall LCD_COMMAND
mov temp, par1
cpi temp, 2
breq MAORW_2B ; rejestr dwubajtowy
mov temp, par0
cli
rcall SPI_ADE_READ_1B ; temp -komenda; r0 -1 bajt danych
sei
ldi temp, 'h'
rcall HEX_1B
ret
MAORW_2B: mov temp, par0
cli
rcall SPI_ADE_READ_2B ; temp -komenda; r1:r0 -2 bajty danych
sei
ldi temp, 'h'
rcall HEX_2B
ret
;==============================================================================
M_AZR_W: ; podglad zmiennych (powiazane z M_AZR)
; par1:par0 -adres danych
rcall ZE_HIST_ZERA
in r0, SREG
push r0
movw zl, par0
lpm r0, z+ ; .
lpm r1, z+ ; adres zmiennej do edycji
adiw zl, 5
lpm temp, z+ ; liczba wysylanych bajtow
movw zl, r0 ; adres zmiennej do z
; sprawdzenie czy liczba w kodzie U2
clt ; czysc flage liczby ze znakiem
sbrc temp, 7 ; jesli r7(7)=1 to zmienna U2
set ; ustaw flage liczby ze znakiem
sbrc temp, 1 ; jesli r7(1)=1 to zmienna 2-bajtowa
rjmp MAZRW_2B
; 1bajt
ld r0, z ; wczytaj wartosc zmiennej
clr r1
brtc MAZRW_PL ; jesli liczba w kodzie U2 to powiel bity znaku
sbrs r0, 7 ; bit 7 informuje o liczbie ze znakiem
rjmp MAZRW_PL
ser temp
mov r1, temp ; bity znaku
; 2bajty
MAZRW_2B: ld r0, z ; wczytaj wartosc zmiennej
ldd r1, z+1
MAZRW_PL: rcall WYSW_HEX_DEC_2B
rcall US_HIST_ZERA
pop r0
out SREG, r0
ret
ZE_HIST_ZERA:
lds temp, Hist_zera_ile
andi temp, 0b01111111 ; aby zmienna byla wyswietlana od 1
sts Hist_zera_ile, temp
ret
US_HIST_ZERA:
lds temp, Hist_zera_ile
ori temp, 0x80
sts Hist_zera_ile, temp
ret
;--------------------------------------
M_AZR: ; zmiana rejestrow ADE (oraz zmiennych) - odczyt ze zmiennej i wyslanie do ADE7759
; par1:par0 -adres danych
push r2
push r3
push r4
push r5
push r6
push r7
in r0, SREG
push r0
rcall ZE_HIST_ZERA
movw zl, par0
lpm r0, z+ ; .
lpm r1, z+ ; adres zmiennej do edycji
lpm r2, z+ ; .
lpm r3, z+ ; min
lpm r4, z+ ; .
lpm r5, z+ ; max
lpm r6, z+ ; adres rejestru w ADE
lpm r7, z+ ; liczba wysylanych bajtow
movw zl, r0 ; adres zmiennej do z
; sprawdzenie czy liczba w kodzie U2
clt ; czysc flage liczby ze znakiem
sbrc r7, 7 ; jesli r7(7)=1 to zmienna U2
set ; ustaw flage liczby ze znakiem
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -