You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
493 lines
14 KiB
493 lines
14 KiB
;Imitace sacovane bomby, Ondrej Hruska (c) 2010
|
|
;-------------------------------------------------
|
|
; Zapojeni:
|
|
; +------u------+
|
|
; reset --+ /RST Vcc +-- napajeni +5V
|
|
; Anoda jednotek --+ PD0 PB7 +-- segment D
|
|
; Anoda desitek --+ PD1 PB6 +-- sedment E
|
|
; (nezapojeno) --+ XT2 PB5 +-- segment C
|
|
; (nezapojeno) --+ XT1 PB4 +-- segment H
|
|
; Spatny drat 1 --+ PD2 PB3 +-- segment G
|
|
; Spatny drat 2 --+ PD3 PB2 +-- segment A
|
|
; Spatny drat 3 --+ PD4 PB1 +-- segment F
|
|
; Spatny drat 4 --+ PD5 PB0 +-- segment B
|
|
; GND --+ GND PD6 +-- Spravny drat
|
|
; +-------------+
|
|
;
|
|
; Nazvy segmentu na displeji:
|
|
; ---A---
|
|
; | |
|
|
; F B
|
|
; | |
|
|
; ---G---
|
|
; | |
|
|
; E C
|
|
; | |
|
|
; ---D--- H
|
|
;
|
|
|
|
.device attiny2313
|
|
;běží na 8MHz, ckdiv8=1 (vypnuto)
|
|
|
|
;LFUSE: 0xE4
|
|
;HFUSE: 0xDF
|
|
|
|
; A L I A S Y
|
|
.def numL = r20
|
|
.def numH = r21
|
|
.def dispL = r22
|
|
.def dispH = r23
|
|
.def wOld = r24
|
|
.def InitLoopN = r25
|
|
|
|
.equ CUvodniIntervaly = 60 ;pocet intervalu cekani
|
|
.equ CInitLoopMax = 180 ;delka 1 intervalu cekani (s)
|
|
.equ CUnitSecs = 60 ;delka 1 jednotky (s) - zacina se s 99 jednotkami
|
|
|
|
; M A K R A
|
|
.MACRO TimIntEnable
|
|
ldi r16,(1<<OCIE1A)
|
|
out TIMSK,r16 ;povolit interrupt pri Compare Match A
|
|
.ENDMACRO
|
|
|
|
.MACRO TimIntDisable
|
|
ldi r16,0
|
|
out TIMSK,r16 ;zakazat interrupt pri Compare Match A
|
|
.ENDMACRO
|
|
|
|
; Z A C A T E K P R O G R A M U
|
|
.org 0x0000 ;RESET
|
|
rjmp RESET ;skok na start po resetu
|
|
|
|
.org 0x0004 ;TC1 Compare match A
|
|
rjmp TIMER
|
|
|
|
.org 0x0010
|
|
; NASTAVENI PO RESETU
|
|
.DB "IMITACE CASOVANE BOMBY. Ondrej Hruska 2010"
|
|
RESET:
|
|
ldi r16,low(RAMEND) ;nastavi stack pointer
|
|
out SPL,r16
|
|
|
|
cli ;zakazat vsechna preruseni
|
|
|
|
; Nastaveni portu
|
|
ldi r16,0b11111111 ;smer portu B - vystupni: segmenty (=katody)
|
|
out DDRB,r16
|
|
ldi r16,0b11111111 ;vse v PORTB na 1, segmenty zhasnuty
|
|
out PORTB,r16
|
|
|
|
ldi r16,0b00000011 ;smer portu D - PD0 a PD1 jsou vystupni - spinaji anody displeje. Zbytek: dratky. PD2 je spravny drat
|
|
out DDRD,r16
|
|
ldi r16,0b01111100 ;enable pullup, 0 na anody = zhasnout. dratky pripojeny na GND, s pullupy
|
|
out PORTD,r16
|
|
|
|
; 16bitovy citac - generator f=1Hz
|
|
ldi r16,0 ;port se neovlivnuje citacem
|
|
out TCCR1A,r16
|
|
ldi r16,(1<<WGM12)|(1<<CS12) ;TC1 prescaler na 256 (8000000/256=31250), CTC mod
|
|
out TCCR1B,r16
|
|
|
|
ldi r16,0b01111010 ;Compare Match 1 A high
|
|
ldi r17,0b00010010 ;Compare Match 1 A low (celkem 31250, overflow f=1Hz)
|
|
out OCR1AH,r16 ;set high
|
|
out OCR1AL,r17 ;set low
|
|
|
|
TimIntDisable ;vypni casovac (makro)
|
|
sei ;Global Interrupt Enable
|
|
|
|
; Navesti, ze se povedl start
|
|
; DEChGAFB
|
|
ldi dispH,0b00011000
|
|
ldi dispL,0b10010111
|
|
ldi r16,100
|
|
nav:
|
|
ldi r17,255
|
|
nav2:
|
|
rcall multiplex
|
|
dec r17
|
|
brne nav2
|
|
dec r16
|
|
brne nav
|
|
|
|
ldi r16,0b00000000 ;disable pullupy a 0 na anody. Musime setrit energii!
|
|
out PORTD,r16
|
|
clr r16
|
|
clr r17
|
|
|
|
; INIT LOOP
|
|
ldi InitLoopN, CUvodniIntervaly ;cekej n intervalu
|
|
ldi r19,CInitLoopMax ;delka prvniho intervalu jako obecny interval
|
|
;soucasny interval: r19, defaultni interval: CInitLoopMax
|
|
TimIntEnable ;zapni casovac (makro)
|
|
InitLoop:
|
|
;kontroluje se InitLoopN. snizovani zajistuje casovac.
|
|
cpi InitLoopN,0 ;zbyva 0 intervalu?
|
|
brne InitLoop ;pokud ne, testuj znova
|
|
|
|
; P R I P R A V Y N A H L A V N I P R O G R A M
|
|
cli ;vypni preruseni - skoncila uvodni smycka, zacina odpocitavani
|
|
;vycisteni registru
|
|
clr r16 ;vynuluj registry
|
|
clr r17
|
|
clr r18
|
|
clr r19
|
|
|
|
;pullupy PORTD
|
|
ldi r16,0b01111100 ;enable pullup
|
|
out PORTD,r16
|
|
|
|
;cas 99
|
|
ldi numL,9
|
|
ldi numH,9
|
|
|
|
mov r17,numL ;zpracovat numL
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
mov dispL,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
mov r17,numH ;zpracovat numH
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
mov dispH,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
;vychozi rozlozeni dratu
|
|
in wOld,PIND ;nastaveni stareho rozlozeni dratu
|
|
andi wOld,0b01111000 ;ignorovat anody a spravny drat
|
|
;nastaveni vychoziho rozlozeni dratu k prestrihnuti
|
|
mov r16, wOld ;uloz wOld -> r16
|
|
;v r16 jsou pouze rozpojene draty: 0b00010000
|
|
in r17, PORTD ;do r17 stav portu D
|
|
mov r18,r16
|
|
com r18
|
|
and r17,r18 ;v r17 vynuluj bity patrici k rozpojenym dratum (ochrana X zkratu)
|
|
out PORTD,r17 ;dej na vystup
|
|
|
|
in r17, DDRD ;do r17 DDRD
|
|
or r17, r16 ;k vystupnim pinum pridej prave rozpojeny drat
|
|
out DDRD,r17
|
|
|
|
ldi r19,CUnitSecs ;nastav citac intervalu pro hlavni odpocet
|
|
|
|
ldi r16,0b11111111 ;255 na PORTB, vse zhasnuto
|
|
out PORTB, r16
|
|
|
|
sei ;zacina hlavni program s casovacem, bude se pouzivat preruseni
|
|
|
|
loop:
|
|
rcall WireTest ;test dratku
|
|
|
|
sbic PIND,2 ;pokud je spravny drat PD2 = 0, preskoc
|
|
rjmp CHCIP ;skoc na CHCIP
|
|
;spravny drat je neprerusen
|
|
|
|
rcall multiplex
|
|
|
|
rjmp loop ;hlavni smycka se opakuje
|
|
|
|
multiplex:
|
|
push r16
|
|
push r17
|
|
;DISPLEJ JEDNOTEK
|
|
ser r16 ;katody na +: vypnout vsechny segmenty
|
|
out PORTB,r16
|
|
cbi PORTD,0
|
|
sbi PORTD,1 ;PORTD = 01 - zapnout anodu pro jednotky
|
|
out PORTB,dispL ;PORTB = dispL (displej jednotek)
|
|
ldi r17,100 ;pocet smycek
|
|
dL: ;smycka
|
|
nop
|
|
nop
|
|
nop
|
|
dec r17
|
|
brne dL
|
|
|
|
;DISPLEJ DESITEK
|
|
ser r16 ;katody na +: vypnout vsechny segmenty
|
|
out PORTB,r16
|
|
cbi PORTD,1
|
|
sbi PORTD,0 ;PORTD 10 - zapnout anodu pro desitky
|
|
out PORTB,dispH ;PORTB = dispH (displej desitek)
|
|
ldi r17,100 ;pocet smycek
|
|
dH:
|
|
nop
|
|
nop
|
|
nop
|
|
dec r17
|
|
brne dH
|
|
|
|
ser r16 ;katody na +: vypnout vsechny segmenty
|
|
out PORTB,r16
|
|
cbi PORTD,0
|
|
cbi PORTD,1
|
|
pop r17
|
|
pop r16
|
|
ret
|
|
|
|
; r17 konvertuj do 7segmentovyho kodu pro displej se spol. anodou DECGAFB ---> r16
|
|
dec7seg: ;dec7seg(r17) -> r16
|
|
clr r16 ;do r16 budeme ukladat vystup, v r17 je vstupni cislo 0-9
|
|
|
|
cpi r17,9 ;je r17 = 9?
|
|
brne dec7segN8 ;neni -> pokracuj s 8
|
|
; DEChGAFB
|
|
ldi r16, 0b01000000 ;katody DCGAFB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN8:
|
|
cpi r17,8 ;je r17 = 8?
|
|
brne dec7segN7 ;neni -> pokracuj s 7
|
|
; DEChGAFB
|
|
ldi r16, 0b00000000 ;katody DECGAFB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN7:
|
|
cpi r17,7 ;je r17 = 7?
|
|
brne dec7segN6 ;neni -> pokracuj s 6
|
|
; DEChGAFB
|
|
ldi r16, 0b11001010 ;katody CAB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN6:
|
|
cpi r17,6 ;je r17 = 6?
|
|
brne dec7segN5 ;neni -> pokracuj s 5
|
|
; DEChGAFB
|
|
ldi r16, 0b00000001 ;katody DECGAF na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN5:
|
|
cpi r17,5 ;je r17 = 5?
|
|
brne dec7segN4 ;neni -> pokracuj s 4
|
|
; DEChGAFB
|
|
ldi r16, 0b01000001 ;katody DCGAF na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN4:
|
|
cpi r17,4 ;je r17 = 4?
|
|
brne dec7segN3 ;neni -> pokracuj s 3
|
|
; DEChGAFB
|
|
ldi r16, 0b11000100 ;katody CGFB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN3:
|
|
cpi r17,3 ;je r17 = 3?
|
|
brne dec7segN2 ;neni -> pokracuj s 2
|
|
; DEChGAFB
|
|
ldi r16, 0b01000010 ;katody DCGAB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN2:
|
|
cpi r17,2 ;je r17 = 2?
|
|
brne dec7segN1 ;neni -> pokracuj s 1
|
|
; DEChGAFB
|
|
ldi r16, 0b00100010 ;katody DEGAB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN1:
|
|
cpi r17,1 ;je r17 = 1?
|
|
brne dec7segN0 ;neni -> pokracuj s 0
|
|
; DEChGAFB
|
|
ldi r16, 0b11001110 ;katody CB na 0; H = 0, ale bude prepsano pri vystupu
|
|
rjmp dec7segReturn
|
|
dec7segN0:
|
|
; DEChGAFB
|
|
ldi r16, 0b00001000 ;katody DECAFB na 0; H = 0, ale bude prepsano pri vystupu
|
|
dec7segReturn:
|
|
ret
|
|
|
|
; TEST DRATU (nutno volat rucne)
|
|
WireTest:
|
|
push r16
|
|
push r17
|
|
push r18
|
|
in r16,PIND
|
|
andi r16, 0b01111000 ;odfiltrovat anody a spravny drat
|
|
;test dratku
|
|
cp wOld,r16 ;porovnej r16 a wOld
|
|
brsh WireTestReturn ;wOld >= r16: nebyl prestrizen dratek, nebo byl nejaky spojen
|
|
;dratek byl prestrizen
|
|
;ODECTENI 3 desitek
|
|
cpi numH,3 ;jsou aspon 3 desitky?
|
|
brlo WireTestMaloCasu ;nejsou-li ani 3 desitky, vynuluj vse a vybuchni
|
|
subi numH,3 ;jinak odecti 3 desitky
|
|
|
|
;nedoslo k vynulovani?
|
|
brne WireTestReturn ;desitky > 0: odejdi bez vybuchu
|
|
cpi numL,0 ;desitky = 0. kolik je jednotek?
|
|
breq WireTestBum ;je-li 0 jednotek, vybuchni
|
|
;0 desitek, n > 0 jednotek
|
|
rjmp WireTestReturn ;0 desitek ale n > 0 jednotek, odejdi bez vybuchu
|
|
WireTestMaloCasu:
|
|
clr numL ;vymazat jednotky
|
|
clr numH ;vymazat desitky
|
|
WireTestBum:
|
|
rcall BUM ;vybuchnout
|
|
WireTestReturn:
|
|
mov wOld, r16 ;uloz soucasny stav dratu do wOld
|
|
;v r16 jsou pouze rozpojene draty: 0b00010000
|
|
in r17, PORTD ;do r17 stav portu D
|
|
mov r18,r16
|
|
com r18
|
|
and r17,r18 ;v r17 vynuluj bity patrici k rozpojenym dratum (ochrana X zkratu)
|
|
out PORTD,r17 ;dej na vystup
|
|
|
|
in r17, DDRD ;do r17 DDRD
|
|
or r17, r16 ;k vystupnim pinum prodej prave rozpojeny drat
|
|
out DDRD,r17
|
|
|
|
;obnovit displej
|
|
mov r17,numL ;zpracovat numL
|
|
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbrc dispL,4 ;neni-li H nastaven na displeji, preskoc
|
|
sbr r16,0b00010000 ;nastaveni H v novem stavu displeje
|
|
mov dispL,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
mov r17,numH ;zpracovat numL
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbrc dispH,4 ;neni-li H nastaven na displeji, preskoc
|
|
sbr r16,0b00010000 ;nastaveni H v novem stavu displeje
|
|
mov dispH,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
pop r18
|
|
pop r17
|
|
pop r16
|
|
ret ;navrat
|
|
|
|
; B U M
|
|
BUM:
|
|
;vybuch - blikajici nuly
|
|
cli ;vypni preruseni
|
|
|
|
ldi r17,0 ;0 jednotek
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbr r16,0b00010000 ;1 na katodu H - zhasnout tecku
|
|
mov dispL,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
|
|
ldi r17,0 ;0 desitek
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbr r16,0b00010000 ;1 na katodu H - zhasnout tecku
|
|
mov dispH,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
BUMsmycka: ;nekonecna smycka, blikaji nuly
|
|
ldi r16, 255
|
|
BUMsmyckaMX:
|
|
rcall multiplex
|
|
dec r16
|
|
brne BUMsmyckaMX
|
|
|
|
ldi r16, 255
|
|
BUMsmyckaPAUZA:
|
|
ldi r17, 255
|
|
BUMsmyckaPAUZAb:
|
|
dec r17
|
|
brne BUMsmyckaPAUZAb
|
|
dec r16
|
|
brne BUMsmyckaPAUZA
|
|
|
|
rjmp BUMsmycka
|
|
|
|
; C H C I P
|
|
CHCIP:
|
|
;nekdo prestrihl spravny drat
|
|
cli
|
|
;ldi dispL,0b00000000
|
|
;ldi dispH,0b00000000
|
|
ldi r16,180 ; citac delky cekani
|
|
CHCIPsmycka:
|
|
mov r17,r16
|
|
com r17
|
|
CHCIPsmyckaMX:
|
|
rcall multiplex
|
|
dec r17
|
|
brne CHCIPsmyckaMX
|
|
|
|
mov r17,r16 ; nastaveni smycky cekani
|
|
inc r16
|
|
cpi r16,255
|
|
brsh CHCIPsleep ;uz je to moc dlouhy, usnout
|
|
|
|
CHCIPsmyckaPAUZA: ;r17*200
|
|
mov r18,r16
|
|
CHCIPsmyckaPAUZAb:
|
|
dec r18
|
|
brne CHCIPsmyckaPAUZAb
|
|
dec r17
|
|
brne CHCIPsmyckaPAUZA
|
|
rjmp CHCIPsmycka
|
|
|
|
CHCIPsleep:
|
|
cli
|
|
ldi r16,(1<<SE)|(1<<SM0)
|
|
out MCUCR,r16
|
|
sleep
|
|
|
|
; PRERUSENI OD CASOVACE f=1Hz
|
|
TIMER: ; casovac ma frekvenci 1Hz
|
|
push r16
|
|
push r17
|
|
push r18
|
|
; r19 je citac intervalu
|
|
cpi InitLoopN,0 ;je InitLoopN = 0?
|
|
breq TIMERnormal ;Je-li InitLoopN = 0, pokracuj normalnim prerusenim
|
|
; probiha uvodni cekani
|
|
; test intervaloveho citace (pokud je InitLoopN > 0, pouziva k tomu se r19)
|
|
cpi r19,0 ;je r19 = 0?
|
|
breq TIMERsnizitILN ;je-li r19 = 0, snizit InitLoopN: jdi na TIMERsnizitILN
|
|
dec r19 ;jinak o 1 sniz r19 (intervalovy citac)
|
|
;out PORTB,r19 ;DEBUG test r19
|
|
rjmp TIMERreturn ;a odejdi
|
|
TIMERsnizitILN:
|
|
dec InitLoopN ;snizit InitLoopN
|
|
ldi r19,CInitLoopMax ;nastaveni delky dalsiho intervalu
|
|
rjmp TIMERreturn ;odejdi
|
|
|
|
TIMERnormal:
|
|
;invertuj tecku (Low)
|
|
ldi r16,0b00010000
|
|
eor dispL,r16
|
|
cbr dispH,0b00010000
|
|
sbrc dispL,4 ;do H zkopiruj tecku z L (tim se zajisti, ze budou vzdy stejne)
|
|
sbr dispH,0b00010000
|
|
|
|
; r19 slouzi jako citac sekund
|
|
dec r19 ;sniz citac intervalu o 1
|
|
brne TIMERreturn ;neni-li 0, odejdi
|
|
ldi r19,CUnitSecs ;nastaveni dalsiho intervalu
|
|
; ODECTENI JEDNOTKY
|
|
cpi numL,0 ;je jednotek vic nez 0?
|
|
brne TIMERnOdectiJednotku ;jednotky > 0, jdi na odecteni jednotky
|
|
;0 jednotek
|
|
cpi numH, 0 ;0 jednotek. je desitek vic nez 0?
|
|
brne TIMERnOdectiPresDesitku ;je-li desitek vic nez 0, jdi na odecteni desitky
|
|
;0 jednotek i desitek
|
|
rcall BUM
|
|
|
|
TIMERnOdectiPresDesitku:
|
|
;0 jednotek, n > 0 desitek
|
|
dec numH ;odecti desitku
|
|
ldi numL,9 ;dej jednotky=9
|
|
rjmp TIMERnOdecteniHotovo ;preskoc na TIMERnOdecteniHotovo
|
|
|
|
TIMERnOdectiJednotku:
|
|
dec numL ;odecti jednotku
|
|
|
|
TIMERnOdecteniHotovo:
|
|
cpi numH,0 ;test desitek
|
|
brne TIMERnHotovoNevybuch ; neni nula -> ok
|
|
cpi numL,0 ;test jednotek
|
|
brne TIMERnHotovoNevybuch ; neni nula -> ok
|
|
;je nula
|
|
rcall BUM ;je nula: vybuchni
|
|
|
|
TIMERnHotovoNevybuch:
|
|
;uprav displej
|
|
mov r17,numL ;zpracovat numL
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbrc dispL,4 ;neni-li H nastaven na displeji, preskoc
|
|
sbr r16,0b00010000 ;nastaveni H v novem stavu displeje
|
|
mov dispL,r16 ;presunout vysledek do vystupu displeje
|
|
|
|
mov r17,numH ;zpracovat numH
|
|
rcall dec7seg ;najdi 7seg. reprezentaci jednotek a dej ji do r16
|
|
sbrc dispH,4 ;neni-li H nastaven na displeji, preskoc
|
|
sbr r16,0b00010000 ;nastaveni H v novem stavu displeje
|
|
mov dispH,r16 ;presunout vysledek do vystupu displeje
|
|
;je obnoven stav displeje, konec preruseni
|
|
|
|
TIMERreturn:
|
|
pop r18 ;navratit puvodni hodnoty registru
|
|
pop r17
|
|
pop r16
|
|
reti |