; (C) Rudolf Marek a Jan Otradovec ; Semafor - rizeni na zuzene silnici s prioritou. ; ; Jendna se o model castecne uzavirky silnice, kdy je provoz veden stridave ; jednim pruhem. Pomoci majority spinacu lze behem provozu menit interval. ; Tlacitky se "privolava" zelena. ; ; Program je rizen casovacem (cte v BIOS data citac casovace). ; Pokud se meni casovy interval, je to udelano v definovanem bode. ; To same plati pro privolani 'zelene' ; Program je dobre komentovany, je univerzalni - delka trvani jednotlivych ; casovych useku i zmen je plne nastavitelna pri kompilaci. Do kodu ; neni treba zasahovat. .MODEL small ;64Kb code 64Data .STACK 100h ;zasobnik .CODE tabulka dw OFFSET casovani_1 ;pointer v ramci segmentu na tabulku obsahujici info tabulka_end dw OFFSET casovani_1_end ;kdy co sviti (zmeni se pri zmene casovani) casovani_1: stav11 dw 12d dup(0010100000000000b);1-12 sekund stav12 dw 2d dup(0100100000000000b) stav13 dw 2d dup(1000100000000000b) stav14 dw 2d dup(1000110000000000b) stav15 dw 12d dup(1000001000000000b) stav16 dw 2d dup(1100010000000000b) casovani_1_end: wait_change1_zv dw OFFSET stav16-(4*2) ;offset v tabulce pro ;preskoceni urciteho poctu cervenych pro dany smer tzv time warp wait_change1_vz dw OFFSET stav12-(4*2) casovani_2: ;casovani 2 se nelisi od 1 nijak jinak nez jeho delkou stav21 dw 25d dup(0010100000000000b);1-12 sekund stav22 dw 4d dup(0100100000000000b) stav23 dw 4d dup(1000100000000000b) stav24 dw 4d dup(1000110000000000b) stav25 dw 25d dup(1000001000000000b) stav26 dw 4d dup(1100010000000000b) casovani_2_end: wait_change2_zv dw OFFSET stav26-(4*2) ;offset v tabulce pro preskoceni urciteho poctu cervenych pro dany smer wait_change2_vz dw OFFSET stav22-(4*2) zv_change_na_zelenou_pre_run dw 0 ;toto je v podstate wait_change pro smery vz_change_na_zelenou_pre_run dw 0 ;nezavisle na pouzite tabulce(casovani) start: ;zacatek programu ;chodci off mov dx,378h ; Adresa vystupni brany LPT1: mov cx,8 ;zhasiname vsechny LED chodcu semhle: mov al,0100b ; Data=1, hodiny=0 out dx,al mov al,1100b ; Data=1, hodiny=1 (nabezna hrana) out dx,al loop semhle push cs ;CS=DS=ES nemusime se starat o segmenty push cs pop es pop ds xor ax,ax ;maze ax call vsend ;zhasneme i semafory mov ax,[wait_change1_zv] ;dame tabulku1 (casovani) mov [zv_change_na_zelenou_pre_run],ax ;zde se jedna o offset kolik mov ax,[wait_change1_vz] ;preskocit cervenejch aby sme mohli mov [vz_change_na_zelenou_pre_run],ax ;jet call diody_all_off ;vypne diody 1234 table_restart: ;tudy se uzavira hlavni smycka mov si,[tabulka] ; Zacatek hlavniho program dalsi: mov ax,[si] ; Nacteni slova z tabulky mov bl,ah and bl,00100000b ;test kdepaq je zelena jz neni call zelena_zv ;dle toho rozsvitime neni: mov bl,ah and bl,00000010b jz neni1 call zelena_vz neni1: call vsend ; Odeslani na semafor pro vozidla call delay ; Cekani add si,2 ; Uprava indexregistru cmp si,[tabulka_end] ; jsme na konci tabulky ? jnz dalsi ; ne, nacteme dalsi jmp table_restart ; ano, zpet na zacatek delay: xor ax,ax ;cekaci smycka poziva casovac (citac) na adrese 0:46Ch push es ;IRQ0 nacita 55 milisekundach push ax pop es cli ;radeji ... abychom tam nesahali oba... mov word ptr es:[046ch],0 mov word ptr es:[046ch+2h],0 sti pop es smycka: call osetri_tlacitka ;mrknem jestli nekdo nechce jet .. push es xor ax,ax push ax pop es cmp word ptr es:[046ch],18d ;uz uplynula 1 sekunda? 18Hz pop es jb smycka ret vsend: ; Vyslani 16-ti bitove hodnoty z AX mov dx,378h ; Adresa vystupni brany LPT1: mov cx,10h ; Citac pruchodu not ax ; Negace AX (0=nesviti, 1=sviti) vcykl: ror ax,1 ; Vlastni cykl pro vyslani obsahu AX jc vjedna ; Bit k odeslani = 1? call vsend0 ; ... ne, vysli 0 jmp vskip vjedna: call vsend1 ; ... ano, vysli 1 vskip: loop vcykl ; a pokracuj s dalsi rotaci AX ret vsend0: push ax ; Zapis hodnoty 0 do pos. registru mov al,0 ; Data=0, hodiny=0 out dx,al mov al,2 ; Data=0, hodiny=1 (nabezna hrana) out dx,al pop ax ret vsend1: push ax ; Zapis hodnoty 1 do pos. registru mov al,1 ; Data=1, hodiny=0 out dx,al mov al,3 ; Data=1, hodiny=1 (nabezna hrana) out dx,al pop ax ret zelena_VZ: ; nastavuje diody 1234 na pozadovane call dioda_on ;barvy call dioda_on call dioda_off call dioda_off ret zelena_ZV: call dioda_off call dioda_off call dioda_on call dioda_on ret diody_all_off: ;zhasneme 1234 call dioda_off call dioda_off call dioda_off call dioda_off ret dioda_on: ;rozvitime diodu a posuneme registr push ax mov dx,378h ; Adresa vystupni brany LPT1: mov al,0 ; Data=0, hodiny=0 out dx,al mov al,100000b ; Data=0, hodiny=1 (nabezna hrana) out dx,al pop ax ret dioda_off: ;zhasnme diodu a posuneme registr push ax mov dx,378h ; Adresa vystupni brany LPT1: mov al,010000b ; Data=1, hodiny=0 out dx,al mov al,110000b ; Data=1, hodiny=1 (nabezna hrana) out dx,al pop ax ret osetri_tlacitka: ;test a vyhodnoceni tlacitek push ax push cx call get_tlacitka ;do AL precteme stav tlacitek mov bl,[si+1] ror al,1 ;zajmaji nas jen nektere bity ostatni ror al,1 ;"zahodime" ror al,1 ror al,1 ror al,1 ror al,1 jnc je_v_zmacklej ror al,1 jnc je_z_zmacklej konec_tlac: call check_prepinace ;jste se podivame na stav prepinacu pop cx ;jestli nechceme zmenit casovani pop ax ret je_v_zmacklej: ;chceme zmenit cercenou na zelenou na vychode and bl,00001000b ;neni cervena neni co resit jz neni_push ;je cervena cmp si,[vz_change_na_zelenou_pre_run] ;jestli je uz zachvili zelene ;uz nema cenu cokoliv delat ja neni_push mov si,[vz_change_na_zelenou_pre_run] ;udelame time warp dec si ;je to zde kvuli tomu ze se na konci pricte dec si ;2ka tak aby se to uz nekomplikovalo neni_push: jmp konec_tlac je_z_zmacklej: ;zde obdobne pro druhy smer and bl,10000000b jz neni_push1 ;je cervena cmp si,[zv_change_na_zelenou_pre_run] ;jestli je si vetsi uz nema cenu ;cokoliv delat ja neni_push1 mov si,[zv_change_na_zelenou_pre_run] dec si dec si neni_push1: jmp konec_tlac get_tlacitka: ;nacteme tlacitka mov dx,0378h ;zapis konstanty na 378 mov al,4 out dx,al inc dx in al,dx ;cteni stavuy 379 ret get_prepinace: ;nacteme stav prepinacu mov al,1h mov dx,0378h out dx,al inc dx in al,dx ret zvys: ;citame kolik jich je vlastbne preklopenejch inc bl jmp pokr check_prepinace: ;test na prepinace call get_prepinace ;nacteme stav not al xor bl,bl shr al,1 ;posuneme si bity tak aby se tykaly tlacitek shr al,1 shr al,1 mov cx,4 ;delame pro 4 tlacitka smycka_1: rcr al,1 jc zvys ;je nastaveny = preklopeny tlacitko pokr: loop smycka_1 cmp bl,2 ;jsou jen 2 ? pak casovani_new jnz casovani_old new_casovani: cmp [tabulka],OFFSET casovani_2 jz ok ;neudelali sme to uz minule ? pokud ano tak nic... xor bx,bx mov al,[si+1] ;mrknem kde je cervena a budeme synchornonizovat na nove and al,10000000b ;casovani ;cervena na zapade jnz zmen inc bx ;posouva offset v tabulce asi dost prasarna inc bx ;je to zv_change_na_zelenou_pre_run+bx, preklopi se na jinou and al,00001000b ;barvu ale uz v tabulce s jinym casovanim ;cervena na vychode zmen: mov [tabulka],OFFSET casovani_2 ;novy ptr mov [tabulka_end],OFFSET casovani_2_end mov ax,[wait_change2_zv] ;offset v tabulce o ktery pocet cervenych mov [zv_change_na_zelenou_pre_run],ax ;mame se urychlit pokud chceme mov ax,[wait_change2_vz] ;zxelenou mov [vz_change_na_zelenou_pre_run],ax mov si,[zv_change_na_zelenou_pre_run+bx] ;zmena zde preblikneme v ramci jmp ok ;noveho casovani casovani_old: ;zde je to obdobne akorat pro to stare.... cmp [tabulka],OFFSET casovani_1 jz ok ;casovani se zmenilo xor bx,bx mov al,[si+1] and al,10000000b ;cervena na zapade jnz zmen1 inc bx inc bx and al,00001000b ;cervena na vychode zmen1: mov [tabulka],OFFSET casovani_1 mov [tabulka_end],OFFSET casovani_1_end mov ax,[wait_change1_zv] mov [zv_change_na_zelenou_pre_run],ax mov ax,[wait_change1_vz] mov [vz_change_na_zelenou_pre_run],ax mov si,[zv_change_na_zelenou_pre_run+bx] ;zmena zde ok: ret END start