;Program do "modyfikatora sygnału"
;Parametry techniczne dla taktowania 4MHz:
;- skrócenie czasu o wartość max ponad 2,5ms z krokiem co 10us
;- lub wydłużenie czasu o max stałą wartość ponad 20ms z krokiem co 80us
;- mnożenie czasu przez współczynnik około 1,00 do 2,55
;- wejścia sygnałowe portB 0-3
;- wyjścia sygnałowe portB 4-7
;- portD2 - klawisz "zapisz"
;- portD2 i portD1 - klawisz "default"
;- PortD3 - klawisz "plus"
;- portD3 i portD4 - klawisz "minus"
;- portD3 i PortD5 - klawisz "razy"
;- portD3 i portD6 - klawisz "dziel"
.include "2313def.inc"
;*********************** definiowanie nazw dla poszczególnych rejestrów mikroprocesora**
.def lo = R0 ;niższy baht licznika
.def hi = R1 ;wyższy bajt licznika
.def hi1 = R2 ;najwyższy bajt licznika
.def zero = R4 ;zero
.def one = R5 ;jeden
.def tsk = R6 ;tymczasowy wskaźnik skrócenia
.def twy = R7 ;tymczaspwy wskaźnik wydłużenia
.def adres = R8 ;wskaźnik adresu komórki EEPROM
.def dod = R16 ;mnożnik
.def ode = R17 ;dzielnik
.def skr = R18 ;skrócenie
.def wyd = r19 ;wydłużenie
.def tmp = r20 ;rejestr tymczasowy
.def pod = r21 ;pętla do odejmowania
.def psk = R22 ;pętla do skrócenia
.def pwy = R23 ;pętla do wydłużenia
.def klawzm = R26 ;tymczasowy rejestr klawiatury zmiany
.def klawzp = R27 ;tymczasowy rejestr klawiatury zapisu
.org 0x0000
rjmp RESET ;
;*********************** Tabela wektorów przerwań (Interrupt Vectors) ******************
.org INT0addr ;External Interrupt0 Vector
rjmp intzapis ;skacz do zapis
.org INT1addr ;External Interrupt1 Vector
rjmp zmiana ;skacz do zmiana
.org ICP1addr ;Input Capture1 Interrupt
reti ;Vector Address
.org OC1addr ;Output Compare1A
reti ;Interrupt Vector Address
.org OVF1addr ;Overflow1 Interrupt Vector
reti ;Address
.org OVF0addr ;Overflow0 Interrupt Vector
reti ;Address
.org URXCaddr ;UART Receive Complete
reti ;Interrupt Vector Address
.org UDREaddr ;UART Data Register Empty
reti ;Interrupt Vector Address
.org UTXCaddr ;UART Transmit Complete
reti ;Interrupt Vector Address
.org ACIaddr ;Analog Comparator
reti ;Interrupt Vector Address
;*********************** inicjalizacja procesora ************************************
RESET:
cli ;zablokowanie przerwań
ldi tmp,ramend ;ostati wolny adres RAM do tmp
out spl,tmp ;inicjacja stosu pod ostatnim wolnym adresem RAM zawatym w tmp
clr zero
clr one
inc one
clr hi
clr lo
ldi tmp,0x01
mov adres,tmp ;załaduj adres pierwszej zmiennej w EEPORM do tmp
out eear,adres ;ustaw rejestr adresowy EEPROM
sbi eecr,eere ;ustaw bit odczytu z EEPROM
in dod,eedr ;załaduj zmienną DODAJ z rejestru danych EEPROM
inc adres ;zwiększ wskaźnik adresu EEPROMu
out eear,adres ;ustaw rejestr adresowy EEPROM
sbi eecr,eere ;ustaw bit odczytu z EEPROM
in wyd,eedr ;załaduj zmienną WYDŁUŻ z rejestru danych EEPROM
inc adres ;zwiększ wskaźnik adresu EEPROMu
out eear,adres ;ustaw rejestr adresowy EEPROM
sbi eecr,eere ;ustaw bit odczytu z EEPROM
in skr,eedr ;załaduj zmienną SKRÓĆ z rejestru danych EEPROM
ldi ode,100 ;załaduj do ode stałą odejmowaną równą 100
ldi tmp,0xf0 ;
out ddrb,tmp ;ustaw portb 0-3 jako wejścia
ldi tmp,0xff ;
out portb,tmp ;podciągnij wszystkie w portb do "1"
ldi tmp,0x00 ;
out ddrd,tmp ;ustaw portd jako wejscia
ldi tmp,0xff
out portd,tmp ;podciągnij wszystkie w portd do "1"
ldi tmp,0x0a
out mcucr,tmp ;ustawienie przerwań zewnętrznych - wyzwalanie zboczem opadającym
ldi tmp,0xc0
out gimsk,tmp ;ustawienie maski przerwań - aktywacja przerwań zewnętrznych
sei ;odblokowanie przerwań
;*********************** program główny ***************************************
main: ;główna pętla programu
sbis pinb,0 ;czy sygnał na wejściu 0
rjmp delay
sbis pinb,1 ;czy sygnał na wejściu 1
rjmp delay
sbis pinb,2 ;czy sygnał na wejściu 2
rjmp delay
sbis pinb,3 ;czy sygnał na wejściu 3
rjmp delay
rjmp main ;powrót do począdku programu głównego
;*********************** skracanie czasu o stałą wartość **********************
delay: ;procedura skracania max ponad 2,5 ms.
cli ;zablokowanie przerwań
cpi skr,0 ;sprawdzanie czy skrócenie =0
breq start ;skacz do start jeśli skrócenie =0
mov tsk,skr ;załąduj współczynnik opóźnienia do licznika pętli opóźnienia
ldi psk,10 ;załaduj pętlę opóźnienia
clc
delay1: ;pętla odliczania opóźnienia dla 4HMz = 10mikrosekund
nop ;1;
dec psk ;1;zmniejsz o 1 wskaźnik pętli
brne delay1 ;1/2;skacz jeśli psk większe od 0
sub tsk,one ;zmniejsz licznik pętli opóźnienia
cp tsk,zero ;porównanie licnzika pętli z zerem
breq start ;jeśli tsk=0 skacz do start
ldi psk,10 ;załąduj pętlę opuźnienia
rjmp delay1
;*********************** mnożenie poprzez wielokrotne dodawanie **************
start: ;procedura rozpoznawania wejścia
sbis pinb,0 ;czy sygnał na wejściu 0
rjmp start0
sbis pinb,1 ;czy sygnał na wejściu 1
rjmp start1
sbis pinb,2 ;czy sygnał na wejściu 2
rjmp start2
sbis pinb,3 ;czy sygnał na wejściu 3
rjmp start3
sei ;odblokowanie przerwań
rjmp main ;powrót do począdku programu głównego
start0: ;procedura mnożenia przez dodawanie dla wejścia 0
cbi portb,4 ;ustaw 0 na pinb5
cp dod,zero ;sprawdź czy współczynnik mnożenia = 0
breq zwieksz ;jeśli współczynnik mnożenia=0 skacz do zwieksz
start01: ;pętla sprawdzająca stan wejścia 0 (17 MIPS z podprogramem)
sbic pinb,0 ;1;czy 0 na pinb0
rjmp odejmij ;2;jeśli pinb0=1 skacz do odejmij
rcall dodaj ;3;wywołaj podprogram dodaj
rjmp start01 ;2;wróc do począdku pętli sprawdzania portb0
start1: ;procedura mnożenia przez dodawanie dla wejścia 1
cbi portb,5 ;ustaw 0 na pinb5
cp dod,zero ;sprawdź czy współczynnik mnożenia = 0
breq zwieksz ;jeślo współczynnik mnożenia=0 skacz do zwieksz
start11: ;pętla sprawdzająca stan wejścia 1 (17 MIPS z podprogramem)
sbic pinb,1 ;1/2;czy 0 na pinb0
rjmp odejmij ;2;jeśli pinb0=1 skacz do odejmij
rcall dodaj ;3;wywołaj podprogram dodaj
rjmp start11 ;2;wróc do począdku pętli sprawdzania portb0
start2: ;procedura mnożenia przez dodawanie dla wejścia 2
cbi portb,6 ;ustaw 0 na pinb5
cp dod,zero ;sprawdź czy współczynnik mnożenia = 0
breq zwieksz ;jeślo współczynnik mnożenia=0 skacz do zwieksz
start21: ;pętla sprawdzająca stan wejścia 2 (17 MIPS z podprogramem)
sbic pinb,2 ;1/2;czy 0 na pinb0
rjmp odejmij ;2;jeśli pinb0=1 skacz do odejmij
rcall dodaj ;3;wywołaj podprogram dodaj
rjmp start21 ;2;wróc do począdku pętli sprawdzania portb0
start3: ;procedura mnożenia przez dodawanie dla wejścia 3
cbi portb,7 ;ustaw 0 na pinb5
cp dod,zero ;sprawdź czy współczynnik mnożenia = 0
breq zwieksz ;jeślo współczynnik mnożenia=0 skacz do zwieksz
start31: ;pętla sprawdzająca stan wejścia 3 (17 MIPS z podprogramem)
sbic pinb,0 ;1/2;czy 0 na pinb0
rjmp odejmij ;2;jeśli pinb0=1 skacz do odejmij
rcall dodaj ;3;wywołaj podprogram dodaj
rjmp start31 ;2;wróc do począdku pętli sprawdzania portb0
;*********************** podprogram dodawania **************************************
dodaj: ;podprobram dodawania (łącznie 11 MIPS)
add lo,dod ;1;dodaj współczynnik dodawania do lo
brcc dodaj1 ;1/2;skocz jeślni nie było C=0
add hi,one ;1;zwiększ hi o 1
brcc dodaj2 ;1/2;skacz jeśli hi różne od 0
inc hi1 ;1;zwiększ hi1 o 1
rjmp dodajexit ;2
dodaj1:
nop ;1
nop ;1
dodaj2:
nop ;1
nop ;1
dodajexit:
ret ;4;powrót z podprogramu (11 MIPS)
;*********************** dzielenie przez wielokrotne odejmowanie *******************
odejmij: ;pętla odejmowania (17MIPS)
nop ;1;dla zrównania czasu jednej pełnej
nop ;1;pętli dodawania
nop ;1;i odejmowania
nop ;1;
nop ;1;
sub lo,ode ;1;odejmij stałą od najmłoszego bajtu
brcc odejmij1 ;1/2;jeśli nie wystąiła pożyczka skacz do odejmij1
sub hi,one ;1;zmniejsz średni bajt o 1
brcc odejmij2 ;1/2;jeśli nie wystąpiła pożyczka skacz do odekmij2
sub hi1,one ;1;zmniejsz nawyższy bajt o 1
brcs odejmijexit ;1/2;jeśli wystąpiła pożyczkaskacz do odejmijexit
rjmp odejmij ;2;skacz do odejmij
odejmij1: ;
nop ;1;opóźnienie czasowe do wyrównania długości pętli
odejmij2: ;
nop ;1;opóźnienie czasowe do wyrównania długości pętli
rjmp odejmij ;2;skacz do odemij
odejmijexit: ;kończenie procedury
nop
;*********************** wydłóżenie czasu o stałą wartość **********************
zwieksz: ;procedura wydłużania czasu max nieco ponad 20ms
cp wyd,zero ;sprawdź czy wdłużenie=0
breq end ;jeśli wydłużenie=0 skacz do pońcowej procedury
mov twy,wyd ;
ldi pwy,80 ;ustaw dłuość pętli wydłużenia
zwieksz1: ;przy 4MHz czas trwania pętli wydłużenia = 80mikrosekund
nop ;1;
dec pwy ;1;zmniejsz współcznnik pętli wydłużenia o 1
brne zwieksz1 ;1/2;skacz do zwieksz1 dopuki pwy różne od 0
dec twy ;zmniejsz tymczaswe wydłużenie
breq end ;jeśli tymczasowe wydłużenie=0 skacz do końcowej procedury
ldi pwy,80 ;ustaw długość pętli wydłużenia
rjmp zwieksz1 ;skacz do zwieksz1
end: ;końcowa procedura modyfikacji sygnału wejściowego
ldi tmp,0xff
out portb,tmp ;ustaw na wszystkich pinach 1
sei ;odblokuj przerwania
rjmp main ;skacz do programu głównego
;*********************** obsłua przerwania INT0 ************************************
intzapis: ;przerwanie od klawiatury zapisu
cli ;zablokowanie przerwań
in klawzp,PIND ;zczytanie stanu portów z PIND
andi klawzp,0x6 ;zerój nieistotne bity
cpi klawzp,0x2 ;czy nacśnięty klawisz "PLUS"
breq zapis ;jeśli tak skacz do plus
cpi klawzp,0x0 ;czy naciśnięty klawisz "MINUS"
breq def ;jeśli tak to skacz do minus
rjmp int0exit
zapis: ;obsługa przerwania klawisza "ZAPIS"
cli ;zablokowanie przerwań
ldi tmp,1 ;
mov adres,tmp ;załaduj wskaźnik adresu warością 1
zapis1: ;pętla gotowości zapisu pierwszej zmiennej
sbic eecr,eewe ;czy EEPROM gotowy do zapisu
rjmp zapis1 ;jeśli EEPROM nie gotowy wróć do pętli
out eear,adres ;ustaw rejestr adresowy
out eedr,dod ;umieść zmienną DODAJ w rejestrze danych
sbi eecr,eemwe ;ustaw bit gotowości do zapisu
sbi eecr,eewe ;ustaw strob zapisu do EEPROM
zapis2: ;pętla gotowości zapisu drugiej zmiennej
sbic eecr,eewe ;czy EEPROM gotowy do zapisu
rjmp zapis2 ;jeśli EEPROM nie gotowy wróć do pętli
inc adres ;zwiększ wskaźnik adresu
out eear,adres ;ustaw rejestr adresowy
out eedr,wyd ;umieść zmienną WYDŁUŻ w rejestrze danych
sbi eecr,eemwe ;ustaw bit gotowości do zapisu
sbi eecr,eewe ;ustaw strob zapisu do EEPROM
zapis3: ;pętla gotowości zapisu trzeciej zmiennej
sbic eecr,eewe ;czy EEPROM gotowy do zapisu
rjmp zapis3 ;jeśli EEPROM nie gotowy wróć do pętli
inc adres ;zwiększ wskaźnik adresu
out eear,adres ;ustaw rejestr adresowy
out eedr,skr ;umieść zmienną SKRÓĆ w rejestrze danych
sbi eecr,eemwe ;ustaw bit gotowości do zapisu
sbi eecr,eewe ;ustaw strob zapisu do EEPROM
zapis4: ;pętla sprawdzająca zakończenie zapisu trzeciej zmiennej
sbic eecr,eewe ;czy zapis w EEPROM zakończony
rjmp zapis4 ;jeśli zapis w EEPROM nie zakończony wróć do pętli
rjmp int0exit ;skok do wyjścia z procedury obsługi przerwania
def: ;wpisanie defaultowych wartości zmiennych
ldi tmp,10
mov dod,tmp ;ustaw dod na 10
ldi tmp,25
mov dod,tmp ;ustaw wyd na 25
clr skr ;wyzeruj skr
int0exit:
sei ;odblokuj przerwania
reti ;skok powrotny z obsługi przerwania
;*********************** Obsługa przerwania zewnętrznego INT1 **********************
zmiana: ;przerwanie od klawiatury zmiennych
cli ;zablokowanie przerwań
in klawzm,PIND ;zczytanie stanu portów z PIND
andi klawzm,0x78 ;zerój nieistotne bity
cpi klawzm,0x70 ;czy nacśnięty klawisz "PLUS"
breq plus ;jeśli tak skacz do plus
cpi klawzm,0x60 ;czy naciśnięty klawisz "MINUS"
breq minus ;jeśli tak to skacz do minus
cpi klawzm,0x50 ;czy naciśnięty klawisz "RAZY"
breq razy ;jeśli tak to skacz do razy
cpi klawzm,0x30 ;czy naciśnięty klawisz "DZIEL"
breq dziel ;jeśli tak to skacz do dziel
rjmp intexit
plus: ;obsługa klawisza "PLUS"
cp skr,zero ;czy współczynnik skróceia równy 0
brne plus1 ;jeśli nie to skacz do plus1
cpi wyd,0xff ;czy współczynnik wydłużenia równy 255
breq intexit ;jeśli tak to skacz do końca przerwania
inc wyd ;zwiększ współczynnik wydłużenia
rjmp intexit ;skacz do końca przerwania
plus1: ;jeśli skr większe od 0
dec skr ;zmniejsz współczynnik skrócenia
rjmp intexit ;skacz końca przerwania
minus: ;obsługa klawisza "MINUS"
cp wyd,zero ;czy współczynnik wydłużenia równy 0
brne minus1 ;jeśli nie skacz do minus1
cpi skr,0xFF ;czy współczynnik skrócenia równy 255
breq intexit ;jeśli tak skacz do końca przerwania
inc skr ;zwiększ współczynnik skrócenia
rjmp intexit ;skacz do końca przerwania
minus1: ;jeśli wyd większe od 0
dec wyd ;zmniejsz współczynnik wydłużenia
rjmp intexit ;skacz do końca przerwania
razy: ;obsługa klawisza "RAZY"
cpi dod,0xff ;czy współczynnik mnożenia równy 255
breq intexit ;jeśli tak skacz do końća przerwania
inc dod ;zwiększ współczynnik mnożenia
rjmp intexit ;skacz do końca przerwania
dziel: ;obsługa klawisza "DZIEL"
cp dod,zero ;czy współczynik mnożenia równy 0
breq intexit ;jeśli tak skacz do końca przerwania
dec dod ;zmniejsz współczynnk mnożenia
intexit: ;koniec przerwania
sei ;odblkowanie przerwań
reti ;powrót z obsługi przerwania