.device attiny2313 ;běží na 8MHz, ckdiv8=1 (vypnuto) ; 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< 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< 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