;==================================================================== ;; Elektronicky kodovy zamek ;; Assembler pro Intel 8051 ;; Copyright (c) by Petr Honzik 2000 ;==================================================================== ;==================================================================== ;; Deklarace registru, bitu a konstant ;==================================================================== ;; Deklarace bitu sloupcu klavesnice Col0 bit P1.5 ; Sloupec 0 Col1 bit P1.4 ; Sloupec 1 Col2 bit P1.3 ; Sloupec 2 ;; Deklarace bitu radku klavesnice Row0 bit P3.7 ; Radek 0 - obsahuje 1, 2, 3 Row1 bit P1.0 ; Radek 1 - obsahuje 4, 5, 6 Row2 bit P1.1 ; Radek 2 - obsahuje 7, 8, 9 Row3 bit P1.2 ; Radek 3 - obsahuje *, 0, # LED bit P1.6 ; Deklarace opticke signalizace Piezo bit P3.3 ; Deklarace zvukove signalizace Vystup bit P3.1 ; Deklarace spinani vystupu Fctpin bit P3.0 ; Deklarace resetu pameti SDA bit P3.5 ; Deklarace seriovych dat IIC SCL bit P3.4 ; Deklarace seriovych hodin IIC Stisk bit 00h ; Priznak stisku nove klavesy SetCode bit 01h ; Priznak programovaciho rezimu Blink bit 02h ; Priznak povoleneho blikani LED FBlink bit 03h ; Priznak rychleho blikani TmpLed bit 04h ; Docasne zapamatovani stavu LED CntFl1 bit 09h ; 1.bit z CntFl CntFl2 bit 0Ah ; 2.bit z CntFl Klav data R2 ; Posledni stisknuta klavesa HKlav data R3 ; Hodnota posledni stisknute klavesy FTop data R0 ; Ukazatel na vrchol fronty cisel ACode data R3 ; Adresa akt.byte v datab.kodu CntFl data 21h ; Citac prodlevy pri spatnem kodu CCode data 30h ; Pocitadlo zpracovavaneho kodu Count1 data 31h ; Citac pro zpozdeni Count2 data 35h ; Sekundarni citac pro zpozdeni Depth data 32h ; Citac hloubky tonu Length data 33h ; Citac delky tonu CntBlk data 34h ; Citac pro zajisteni blikani ClrF data 36h ; Citac pro periodicke mazani fifo FAddr data 37h ; Adresovy citac pro tovarni nastaveni BEGFIFO equ 70h ; Adresa prvniho znaku ve fronte ENDFIFO equ 77h ; Adresa posledniho znaku ve fronte ESC equ 0Ah ; Cislo mazaci klavesy ENTER equ 0Bh ; Cislo potvrzovaci klavesy BEGCODE equ 00h ; Adresa prvniho byte databaze kodu ENDCODE equ 40h ; Adresa posledniho byte datab.kodu CDELAY equ 40h ; Delka zpozdeni na vystupu CDEPTH equ 25h ; Hloubka tonu CLENGTH equ 15h ; Delka tonu CBLINK equ 01h ; Delici konstanta pro rychle blikani CBLKP equ 06h ; Delici konstanta pro pomale blikani GLBADDR equ 0A0h ; Factory memory address LOCADDR equ 00h ; Device address CCLRF equ 99h ; Konstanta pro periodicke mazani fifo FILLFF equ 00h ; Vyplnovy znak prazdne fronty ENDFCT equ 41h ; Konec mapy kody OUTCNS equ 02h ; Konstanta jedne sekundy na vystupu LTIMER equ 71h ; Dolni byte citace 0 HTIMER equ 0B2h ; Horni byte citace 0 FLDELAY equ 080h ; Prodleva pri spatne zadanem kodu ;==================================================================== ;; Zacatek programoveho bloku ;==================================================================== org 0000h ; Zacatek programu 0000h jmp start org 000Bh ; Preruseni casovace 0 jmp timer0 ;------------------------------------------------------------------- ;; Main Routine ;; Hlavni program kodoveho zamku pro zakladni obsluhu ;; Obsahuje nekon.smycku pro hlavni obsluhu ;-------------------------------------------------------------------- org 0030h ; Adresa prvni instrukce Main routine start: acall init ; Volani inicializacni rutiny jb Fctpin,main acall factor main: jnb Stisk,epress ; Testuje zda nebyla stisknuta klavesa clr Stisk ; Smaze priznak stisknute klav. mov A,Klav mov DPTR,#kbcnst movc A,@A+DPTR ; Nacita hodnotu stisknute klavesy mov HKlav,A ; Testuje zda to neni ESC klavesa cjne HKlav,#ESC,compkey acall clrfifo ; Maze frontu jmp epress ; Testuje zda to neni ENTER kl. compkey:cjne HKlav,#ENTER,putkey acall comp ; Prohledava databazi kodu jmp epress putkey: nop mov @FTop,03h ; Uklada znak stisk.kl.do fronty inc FTop ; Posune na dalsi pozici ve fronte ; Testuje preteceni fronty cjne FTop,#ENDFIFO+1,epress mov FTop,#BEGFIFO epress: jmp main ;-------------------------------------------------------------------- ;; Vymazani fronty cisel ;; Rutina vymaze frontu stisknutych cisel tim ze ;; naplni pozice hodnotou #FILLFFh ;-------------------------------------------------------------------- clrfifo:mov FTop,#BEGFIFO ; Nastaveni ukaz. na zacatek fronty clrbyte:mov @FTop,#FILLFF ; Vymaze pozici inc FTop ; Posun na dalsi pozici cjne FTop,#ENDFIFO+1,clrbyte mov FTop,#BEGFIFO ; Nastaveni ukaz. na zacatek fronty ret ;-------------------------------------------------------------------- ;; Zapis kodu do pameti ;; Rutina vypocita adresu kodu v pameti a zapise ho ;; na tu adresu a ukonci programovaci mod. ;-------------------------------------------------------------------- scode: mov A,CCode ; Prenos cisla kodu pro nastaveni dec A ; Zde se cisluji kody od nuly mov B,#08h ; Nasobky adresy zacatku kodu mul AB ; Vypocet adresy kodu v pameti mov CCode,A nextset:mov B,@FTop ; Nacteni cisla z fifo pro zapsani mov A,CCode ; Nastaveni adresy v EEPROM acall write0 ; Zapis elementu do pameti acall wait inc FTop inc CCode ; Posun na dalsi slovo v EEPROM ; Testuje konec fifo pro konec zapisu cjne FTop,#ENDFIFO+1,nextset acall clrfifo ; Vymaze databazi clr SetCode ; Rusi programovaci kod clr Blink ; Prestava blikat a nastavuje jb Vystup,enext ; Led podle nastaveneho vystupu setb LED ret enext: clr LED ret ;-------------------------------------------------------------------- ;; Komparace fronty s databazi kodu ;; Rutina porovnava frontu s jednotlivymi kody v ;; pameti EEPROM ;-------------------------------------------------------------------- comp: mov FTop,#BEGFIFO ; Nastav ukazatel na zac.fronty jb SetCode,scode ; Test zda je nastaven prg.rezim mov CCode,#01h ; Cislo prvniho kodu mov ACode,#BEGCODE ; Nastav na zacatek datab.kodu cpbyte: mov A,ACode acall read0 ; Nacti byte z databaze kodu mov B,@FTop cjne A,B,nextcod ; Porovnava fifo a databazi inc ACode ; Posun na dalsi byte databaze inc FTop ; Posun na dalsi byte fronty ; Testuje konec fronty & kodu cjne FTop,#ENDFIFO+1,cpbyte acall clrfifo ; Vymaze databazi pokud byl kod uspesny mov A,CCode cjne A,#01h,puls ; Testuje zda to byl master kod setb FBlink setb Blink acall progr ; Pokud ano vola se progr. rezim ret ; Obsluha uzivatelskych kodu 2-8 puls: mov A,#CDELAY acall read0 ; Nacita delku sepnuti na vystup cjne A,#00h,puls0 ; Pokud ma nactena delka hodnotu 0 cpl Vystup ; zneguje vystup i LED jinak nastavy cpl LED ; vystup do jednicky na pozadovanou ret ; dobu puls0: clr TR0 ; Zast.cas. protoze LED zde neblika setb Vystup ; Aktivuje vystup (impulsove) clr LED acall delay ; Po zadanou delku acall clrfifo ; Maze posledni kod z fronty setb LED clr Vystup ; Vraci vystup na nulu setb TR0 ; Opet zapne casovac ret ; Dojede na konec aktualniho kodu nextcod:inc ACode inc FTop cjne FTop,#ENDFIFO+1,nextcod mov FTop,#BEGFIFO ; Nastav zacatek fronty inc CCode ; Bude se pracovat s dalsim kodem ; Testuje konec databaze kodu cjne ACode,#ENDCODE,cpbyte acall clrfifo ; Vymaze frontu mov C,LED mov TmpLed,C mov CntFl,#FLDELAY flcode: clr LED jnb CntFl1,flcd jnb CntFl2,flcd setb LED flcd: acall wait acall beep acall wait acall beep acall wait acall beep acall wait acall wait djnz CntFl,flcode mov C,TmpLed mov LED,C ret ;-------------------------------------------------------------------- ;; Inicializacni rutina ;; Nastavuje obsahy registru a jednotlive piny nastavuje na ;; vstupni ci vystupni. Konfiguruje vnitrni periferie ;; procesoru ;-------------------------------------------------------------------- init: setb Fctpin setb Row0 ; Nastaveni radku jako vstupy setb Row1 setb Row2 setb Row3 clr Col0 ; Nastaveni sloupcu jako vystupy clr Col1 clr Col2 setb LED ; Vypnuti opticke signalizace clr Stisk ; Nic neni stisknuto mov Klav,#00h clr Vystup ; Stazeni vystupu do nuly clr Blink ; Zakazani blikani clr FBlink ; Zakaz rychleho blikani clr SetCode mov CntBlk,#CBLINK ; Delici konstanta blikani acall clrfifo ; Maze fifo mov TMOD,#01h ; Nastavuje casovac na 16 bitovy clr IT0 ; INT0 reagije na log. nulu clr EX0 ; Zakazani vnejsiho preruseni INT0 setb TR0 ; Zapnuti casovace setb ET0 ; Povoleni preruseni casovace mov Depth,#CDEPTH mov Length,#0FFh acall rbeep setb EA ; Povoleni prerusovaciho systemu ret ;-------------------------------------------------------------------- ;; Casovac 0 ;; Prerusovaci rutina obsluhuje casovac 0. ;-------------------------------------------------------------------- timer0: mov TL0,#LTIMER mov TH0,#HTIMER push Acc ; Uloz pouzivane registry push B acall keyb ; Volani obsluhy klavesnice djnz CntBlk,tr001 ; Delicka frekvence blikani jb FBlink,slwb ; Testuje priznak rychleho blikani mov CntBlk,#CBLKP ; Naplneni konst. pro pomale blikani jmp blkled slwb: mov CntBlk,#CBLINK ; Naplneni konst. pro rychle blikani blkled: jnb Blink,tr001 ; Test povoleni blikani LED cpl LED ; Blikani LED pomoci negace tr001: jb Blink,tr002 ; Pokud se neprogramuje je periodicky djnz ClrF,tr002 ; vymazavana fifo aby v ni nezustavaly acall clrfifo ; stare stisknute klavesy mov ClrF,#CCLRF tr002: pop B ; Obnov pouzivane registry na puvodni pop Acc ; hodnotu reti ;-------------------------------------------------------------------- ;; Programovaci rezim ;; Rutina rozpoznava co se bude programovat a nastvy ;; potrebne registry ;-------------------------------------------------------------------- progr: jnb Stisk,progr ; Ceka na stisk klavesy clr Stisk ; Smaze priznak stisknute klav. mov A,Klav mov DPTR,#kbcnst movc A,@A+DPTR ; Nacita hodnotu stisknute klavesy mov HKlav,A cjne HKlav,#ENTER,press0 jmp setend ; Byl stisknut ENTER - nic se nedeje press0: cjne HKlav,#00h,presc jmp setend ; Stisknuta nula - nic se nedeje presc: cjne HKlav,#ESC,setout jmp setend ; Sisknut ESC - nic se nedeje setout: cjne HKlav,#09h,setprg set001: clr FBlink ; Byla stisk.9 programuje delku impulsu jnb Stisk,set001 ; Ceka na stisk cisla clr Stisk mov A,Klav mov DPTR,#kbcnst movc A,@A+DPTR ; Nacita hodnotu stiskle klavesy mov HKlav,A cjne A,#ESC,setent ; Testuje stisk ESC jmp setend ; Pokud ESC ukonci nastavovani setent: cjne A,#ENTER,setnr ; Testuje stisk ENETER jmp setend ; Pokud ENTER ukonci nastavovani setnr: mov B,#OUTCNS ; Konstanta jedne sekundy mul AB ; Vypocet delky (pocet sekund) xch A,B mov A,#CDELAY acall write0 ; Zapis delky impulsu do EEPROM acall wait setend: clr Blink jb Vystup,setl ; Nastavuje LED podle vystupu setb LED ret setl: clr LED ret setprg: setb SetCode ; Nastavuje programovaci rezim clr FBlink mov CCode,HKlav ; Urcuje ktery kod se bude editovat ret ;-------------------------------------------------------------------- ;; Obsluha klavesnice 4x3 ;; Rutina obsluhuje klavesnici. Je spoustena periodicky ;; pomoci interniho casovace. Vraci cislo stisknute ;; klavesy (Klav) a priznak stisknuti (Stisk) ;-------------------------------------------------------------------- keyb: setb Col1 ; Obsluha sloupce 0 setb Col2 clr Col0 acall tstrow mov B,#00h ; Konstanta sloupce (A + 0) jnz pushkey setb Col0 ; Obsluha sloupce 1 clr Col1 acall tstrow mov B,#04h ; Konstanta sloupce (A + 4) jnz pushkey setb Col1 ; Obsluha sloupce 2 clr Col2 acall tstrow mov B,#08h ; Konstanta sloupce (A + 8) setb Col2 jnz pushkey clr A ; Pokud nebylo nic stisknuto jmp compk pushkey:add A,B ; Vypocet cisla klavesy do A compk: cjne A,02h,newps ; Porovnava posledni a nynejsi kl. ret newps: xch A,Klav ; Uklada nove cislo klavesy jnz endkey ; Pri stisku nastavi priznak setb Stisk ; Nastavuje priznak stisku kl. mov ClrF,#CCLRF clr TR0 acall beep ; Kratke pipnuti setb TR0 endkey: ret ;-------------------------------------------------------------------- ;; Test radku ;; Rutina testuje jednotlive radky klavesnice ;; zda se na nich neobjevila 0. cislo radku vraci ;; v acumulatoru, jinak vraci 0 ;-------------------------------------------------------------------- tstrow: mov A,#01h ; Konstanta prvniho radku jnb Row0,aktrow ; Pokud je radek v 0 skoci inc A jnb Row1,aktrow inc A jnb Row2,aktrow inc A jnb Row3,aktrow clr A ; Zadny radek nebyl v 0 aktrow: ret ;-------------------------------------------------------------------- ;; Zpozdovaci smycka ;; Rutina dvouokruhove cita a tim vytvory zpozdeni ;; Delka zpozdeni se nacte z pameti ;-------------------------------------------------------------------- delay: mov Count1,#0FFh ; Naplnuje citaci registry mov Count2,#0FFh mov A,#CDELAY acall read0 ; Nacita delku zpozdeni rdelay: djnz Count1,rdelay ; Primarni okruh citani mov Count1,#0FFh djnz Count2,rdelay ; Sekundarni okruh citani mov Count1,#0FFh mov Count2,#0FFh djnz Acc,rdelay ; Menitelny okruh citani ret ;-------------------------------------------------------------------- ;; Kratka prodleva ;; Tato prodleva zabezpecuje bezpecny zapis dat do ;; pameti EEPROM ;-------------------------------------------------------------------- wait: mov Count1,#0FFh mov Count2,#15h ; Cca 10ms rwait: djnz Count1,rwait mov Count1,#0FFh djnz Count2,rwait ret ;-------------------------------------------------------------------- ;; Kratky ton ;; Rutina generuje kratky ton o parametrech CDEPTH ;; a CLENGTH ;-------------------------------------------------------------------- beep: mov Depth,#CDEPTH ; Naplneni parametru tonu mov Length,#CLENGTH rbeep: cpl Piezo ; generovani frekvence na vystup cbeep: djnz Depth,cbeep ; Primarni okruh mov Depth,#CDEPTH djnz Length,rbeep ; Sekundarni okruh setb Piezo ret ;-------------------------------------------------------------------- ;; Tovarni nastaveni ;; Rutina nastavy pamet EEPROM do pocatecnich hodnot. ;-------------------------------------------------------------------- factor: mov FAddr,#00h mov A,FAddr mov DPTR,#fctdata fctckl: acall wait movc A,@A+DPTR ; Nacita data z pameti mov B,A mov A,FAddr acall write0 ; Uklada data do EEPROM inc FAddr mov A,FAddr cjne A,#ENDFCT,fctckl; Testuje konec mapy kodu ret ;-------------------------------------------------------------------- ;; Cteni bytu z pameti ;; Rutina cte byt z pameti na adrese. Adresa je ulozena ;; v accumulatoru. V bitu C je vracena uspesnost operace ;; Volani : 1 ;; Modifikovano : SDA,SCL,C,A,B ;; Swap : 1 ;-------------------------------------------------------------------- read0: push B mov B,A ; Save programmable address acall start0 jc busyrd ; Test for free bus mov A,#GLBADDR ; Set global address orl A,#LOCADDR ; Set local address clr Acc.0 ; Specify write operation acall send0 ; Send device address jc failrd mov A,B ; Rewrite Acc programmable address acall send0 jc failrd acall start0 ; Send second part of read operation jc busyrd mov A,#GLBADDR ; Set global address orl A,#LOCADDR ; Set local address setb Acc.0 ; Specify write operation acall send0 ; Send device address jc failrd acall rcpt0 ; Receipt data from memory clr C ; Drop error bit C sjmp busyrd failrd: acall stop0 busyrd: pop B ; Return data to register B ret ;-------------------------------------------------------------------- ;; Zapis bytu do pameti ;; Rutina zapise byt do pameti na adresu ktera je ;; ulozena v akumulatoru a data jsou ulozena v ;; registru B. V bitu C je ulozena uspesnost operace. ;; Volani : 1 ;; Modifikace : SDA,SCL,C,A,B ;; Swap : 1 ;-------------------------------------------------------------------- write0: acall start0 jc busywr ; Abort if bus isn't free push Acc mov A,#GLBADDR ; Set global address orl A,#LOCADDR ; Set local address clr Acc.0 ; Specify write operation acall send0 ; Send device address jc failwr pop Acc push Acc acall send0 ; Send address of data jc failwr mov A,B acall send0 ; Send data jc failwr clr C ; Clear error flag failwr: acall stop0 pop Acc busywr: ret ;-------------------------------------------------------------------- ;; Vysila byt ;; Rutina vysila byte do pameti. Data jsou ulozena v ;; akumulatoru. Prvni se vysila nejvyznamejsi bit. ;; V bitu C je vracena uspesnost operace. ;; Modifikace : SDA,SCL,C,A ;; Swap : 1 ;-------------------------------------------------------------------- send0: push B ; Save bit C for count down mov B,#08h ; Set register on eight cycles sendnx: rlc A ; Move significant bit into bit C mov SDA,C ; Send bit C nop setb SCL nop clr SCL djnz B,sendnx ; Test for end of sending setb SDA nop nop setb SCL nop nop nop nop mov C,SDA ; Get ACK bit to C clr SCL pop B ret ;-------------------------------------------------------------------- ;; Prijme jeden byt ;; Rutina prijme jeden byt z pameti. Byt je ulozen ;; v akumulatoru. ;; Modifikace : SDA,SCL,C,Acc ;; Swap : 1 ;-------------------------------------------------------------------- rcpt0: setb SDA ; Set SDA an input push B ; Save register for count mov B,#08h ; register for countdown rcptb: setb SCL nop mov C,SDA ; Read bit from data bus rlc A ; Move bit C to accumulator clr SCL ; djnz B,rcptb ; Test for end of receipt pop B ret ;-------------------------------------------------------------------- ;; Prikaz START ;; Rutina vysila prikaz start pro zacatek komunikace. ;; V bitu C je vracen stav sbernice. ;; Modifikace : SDA,SCL,C ;-------------------------------------------------------------------- start0: setb SDA setb SCL jnb SDA,failst ; Testuje volnost sbernice jnb SCL,failst ; Testuje volnost sbernice clr SDA ; Toto je prikaz START nop clr SCL clr C ; Komunikace je zapocata sjmp endst failst: setb C ; Chyba komunikace endst: ret ;-------------------------------------------------------------------- ;; Prikaz STOP ;; Rutina vysila prikaz stop pro ukonceni komunikace ;; a uvedeni pameti do power down modu. ;; Modifikace : SDA,SCL ;-------------------------------------------------------------------- stop0: clr SDA nop setb SCL nop setb SDA ; Toto je prikaz STOP ret ;-------------------------------------------------------------------- ;; Pole konstant jednotlivych klaves ;-------------------------------------------------------------------- kbcnst: db 0FFh db 1, 4, 7, 10 ; Sloupec 0 db 2, 5, 8, 0 ; Sloupec 1 db 3, 6, 9, 11 ; Sloupec 2 ;-------------------------------------------------------------------- ;; Mapa kodu pro tovarni nastaveni ;-------------------------------------------------------------------- fctdata:db 1,2,3,4,0,0,0,0 db 2,2,2,2,0,0,0,0 db 3,3,3,3,0,0,0,0 db 4,4,4,4,0,0,0,0 db 5,5,5,5,0,0,0,0 db 6,6,6,6,0,0,0,0 db 7,7,7,7,0,0,0,0 db 8,8,8,8,0,0,0,0 db 2