aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Sucan <sucanjan@fit.cvut.cz>2019-09-22 21:16:27 +0200
committerJan Sucan <sucanjan@fit.cvut.cz>2019-09-22 21:16:27 +0200
commit1715cc7f241a236372eed03aa8279b9ed864e4b0 (patch)
treed9e182d2da722c035648a21721d2e10d664a8764
Initial commit
-rw-r--r--firmware.asm722
1 files changed, 722 insertions, 0 deletions
diff --git a/firmware.asm b/firmware.asm
new file mode 100644
index 0000000..05efb2a
--- /dev/null
+++ b/firmware.asm
@@ -0,0 +1,722 @@
+; Zdrojove kody mozete pouzivat k akemukolvek ucelu.
+; Za mozne sposobene skody nenesiem zodpovednost.
+;
+; You can use the source codes for anything you want.
+; I am not responsible for any damages.
+
+; Firmware prevodniku pre programovanie mikrokontrolerov
+; Vykonava prevod medzi seriovymi signalmi pre programovanie
+; mikrokontroleru AT89S51 a paralelnymi signalmi pre programovanie
+; mikrokontroleru AT89C1051, AT89C2051 alebo AT89C4051.
+
+
+; ----------------------------------------------------------------------
+; hardware
+; ----------------------------------------------------------------------
+green equ p3.6 ; zelena led
+red equ p3.5 ; cervena led
+up equ p3.7 ; upload led
+down equ p3.4 ; download led
+ ; definice paralelneho rozhrania
+rstsw equ p2.1 ; spinac rst signalu
+vccsw equ p2.0 ; spinac napajacieho napatia
+pdata equ p0 ; paralelne data
+xtal equ p2.6 ; xtal
+prog equ p2.5 ; prog
+m0 equ p2.4 ; prvy bit modu
+m1 equ p2.3 ; druhy bit modu
+m2 equ p2.2 ; treti a stvrty bit modu
+ ; definicie fram
+frwp equ p1.0 ; write protect
+frscl equ p1.1 ; hodinovy signal
+frsda equ p1.2 ; datovy signal
+ ; signaly serioveho rozhrania
+mosi equ p1.5 ; master in slave out
+miso equ p1.6 ; master out slave in
+sck equ p1.7 ; hodinovy signal
+rst equ p3.2 ; resetovaci signal
+btn equ p3.3 ; ovladacie tlacitko
+; ----------------------------------------------------------------------
+; premenne a konstanty
+; ----------------------------------------------------------------------
+ bseg at 20h
+lock: dbit 1 ; zamok modelu
+spe: dbit 1 ; vlajka serial programming enabled
+taskerr:dbit 1 ; vlajka chyby ulohy
+
+ dseg at 30h
+ ; premenne modelu
+vlocks: ds 1 ; lock bity
+vsign: ds 3 ; bajty signatury
+vchange:ds 1 ; bity zmeny
+ ; 0. bit - chip erase
+ ; 1. bit - write program memory
+ ; 2. bit - write lock bits
+ ; premenne fram
+frct: ds 1 ; pocitadlo pre fram podprogramy
+frerr: ds 1 ; pocet opakovani pri chybe prenosu
+frtmp: ds 1 ; docasne ulozenie dat fram
+
+ ; pwm konstanty
+volt equ 30 ; trvanie aktivnej casti periody pwm
+period equ 2200 ; trvanie periody pwm
+
+vmargin equ 08h ; velkost pamate programu at89cx051 mcu
+ ; velkost pamate v bajtoch je ziskana
+ ; vynasobenim tohoto cisla cislom 256
+ ; 04h je pre at89c1051
+ ; 08h je pre at89c2051
+ ; 10h je pre at89c4051
+; ----------------------------------------------------------------------
+; kod programu
+; ----------------------------------------------------------------------
+ cseg
+
+ org 00h
+ ajmp main ; skok na zaciatok programu
+
+ org 03h
+ ajmp serial ; obsluha serioveho programatoru
+
+ org 0bh
+ ajmp rstpwm ; obsluha pwm kanalu
+
+ org 13h
+ ajmp button ; obsluha ovladacieho tlacitka
+; ----------------------------------------------------------------------
+; hlavny program
+; ----------------------------------------------------------------------
+main: clr green ; zasviet vsetky led
+ clr red
+ clr up
+ clr down ; ok
+
+ setb frwp ; signaly fram do kludoveho stavu
+ setb frscl
+ setb frsda ; ok
+
+ anl tmod,#0fh ; 16 bitovy casovac 1
+ orl tmod,#10h
+ setb tr1 ; spust
+ ; signaly paralelneho rozhrania do
+ acall poff ; kludoveho stavu
+
+ anl tmod,#0f0h ; 16 bitovy casovac 0
+ orl tmod,#01h
+ setb tr0 ; spust
+ setb pt0 ; vysoka priorita
+
+ mov a,#0 ; vychodzie hodnoty premennych modelu
+ mov vlocks,a ; deaktivovane lock bity
+ mov a,#1eh ; platna signatura at89s51
+ mov vsign,a
+ mov a,#51h
+ mov vsign+1,a
+ mov a,#06h
+ mov vsign+2,a ; ok
+ mov vchange,a ; ziadne zmeny
+
+ clr it0 ; int0 citlive na log. 0
+ setb ex0
+
+ clr it1 ; int1 citlive na zostupnu hranu
+ setb ex1
+
+ setb red ; led do pohotovostneho stavu
+ setb green
+ setb down
+ clr up ; ok
+ setb ea ; povolene vsetky prerusenia
+
+task: clr lock ; odomkni pamat
+ mov r0,#100 ; cakaj 2 s
+task_wait:
+ clr tf1
+ mov tl1,#low (65535 - 40000)
+ mov th1,#high (65535 - 40000)
+ jnb tf1,$
+ djnz r0,task_wait
+ setb lock ; zamkni pamat a detekuj zmenu
+ mov a,vchange
+ jz task ; ak nie je zmena, odomkni a cakaj
+ clr green ; je zmena, zasviet oranzovu led
+ clr red
+ clr taskerr ; zhod priznak zmeny
+task_select:
+ mov a,vchange ; zisti kde je zmena
+ jb acc.0,task_perasechip
+ jb acc.1,task_pcodewrite
+ jb acc.2,task_plockwrite
+ jb taskerr,task_error
+ setb red ; nie je chyba, zasviet zelenu led
+ clr green
+ ajmp task ; cakaj na dalsie zmeny
+task_error:
+ setb green ; je chyba, zasviet cervenu led
+ clr red
+ mov vchange,#0 ; zrus vsetky zmeny
+ ajmp task ; cakaj na dalsie zmeny
+task_perasechip:
+ acall perasechip ; zmaz at89cx8051
+ mov a,vchange ; zhod priznak zmeny
+ clr acc.0
+ mov vchange,a ; ok
+ ajmp task_select ; pokracuj dalsou ulohou
+task_pcodewrite:
+ acall pcodewrite ; zapis pamat programu at89cx051
+ mov taskerr,c ; nastav vlajku chyby
+ mov a,vchange ; nie je chyba, zhod priznak zmeny
+ clr acc.1
+ mov vchange,a ; ok
+ ajmp task_select ; pokracuj dalsou ulohou
+task_plockwrite:
+ acall plockwrite ; zapis lock bity at89cx501
+ mov a,vchange ; zhod priznak zmeny
+ clr acc.2
+ mov vchange,a ; ok
+ ajmp task_select ; pokracuj dalsou ulohou
+
+; ----------------------------------------------------------------------
+; obsluzne procedury
+; ----------------------------------------------------------------------
+ ; obsluha serioveho rozhrania
+serial: jnb lock,$+4 ; skontroluj zamok
+ reti
+ clr spe ; zhod vlajku programming enable
+sdecode:
+ acall srcv ; prijmi 1. bajt
+ cjne a,#0ach,$+5 ; a dekoduj ho
+ ajmp sdecode_l0
+ cjne a,#20h,$+5
+ ajmp sbyteread
+ cjne a,#40h,$+5
+ ajmp sbytewrite
+ cjne a,#24h,$+5
+ ajmp slockread
+ cjne a,#28h,$+5
+ ajmp ssignread
+ cjne a,#30h,$+5
+ ajmp spageread
+ cjne a,#50h,$+5
+ ajmp spagewrite
+ ajmp sterm ; nebol rozpoznany, skonci
+sdecode_l0:
+ acall srcv ; prijmi 2. bajt
+ mov r0,a ; a zalohuj ho, moze obsahovat data
+ cjne a,#53h,$+5
+ ajmp senableprog
+ anl a,#11111100b
+ cjne a,#0e0h,$+5
+ ajmp slockwrite
+ anl a,#11100000b
+ cjne a,#80h,$+5
+ ajmp serasechip
+ ajmp sterm ; nebol rozpoznany, skonci
+sterm_p2:
+ pop acc ; zahod 2 bajty navratovej adresy
+ pop acc
+sterm: pop acc
+ pop acc
+ mov a,#low task
+ push acc
+ mov a,#high task
+ push acc
+ setb green ; zhasni zelenu a cervenu led
+ setb red
+ reti
+
+senableprog: ; programming enable
+ setb spe ; nastav priznak programming enable
+ acall srcv ; prijmi 3. bajt
+ mov a,#01101001b
+ acall ssend ; posli 4. bajt
+ ajmp sdecode
+
+serasechip: ; chip erase
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ clr green ; zasviet cervenu led a zelenu led
+ clr red
+ acall srcv ; prijmi 3.
+ acall srcv ; a 4. bajt
+ mov dptr,#0 ; zmaz 4 kib fram
+ acall vwrite_open ; otvor model
+serasechip_l0:
+ mov a,#0ffh ; vymazany bajt
+ acall vwrite_byte ; zapis bajt do modelu
+ inc dptr ; inkrementuj adresu
+ mov a,dph
+ cjne a,#10h,serasechip_l0
+ acall vwrite_close ; zatvor model
+ mov a,vchange ; zaznamenaj zmenu
+ setb acc.0
+ mov vchange,a
+ ajmp sdecode
+
+sbyteread: ; read program memory (byte mode)
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ acall srcv ; prijmi 2. bajt (upper address byte)
+ anl a,#0fh ; vymaskuj nahodne bity
+ mov dph,a
+ acall srcv ; prijmi 3. bajt (lower address byte)
+ mov dpl,a
+ acall vread
+ acall ssend ; posli 4. bajt (data)
+ ajmp sdecode
+
+sbytewrite: ; write program memory (byte mode)
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ clr green ; zasviet cervenu led a zelenu led
+ clr red
+ acall srcv ; prijmi 2. bajt (upper address byte)
+ anl a,#0fh ; vymaskuj nahodne bity
+ mov dph,a
+ acall srcv ; prijmi 3. bajt (lower address byte)
+ mov dpl,a
+ acall srcv ; prijmi 4. bajt (data)
+ acall vwrite
+ mov a,vchange ; zaznamenaj zmenu
+ setb acc.1
+ mov vchange,a
+ ajmp sdecode
+
+slockwrite: ; write lock bits
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ clr green ; zasviet cervenu led a zelenu led
+ clr red
+ acall srcv ; prijmi 3.
+ acall srcv ; a 4. bajt
+ mov a,r0 ; vyber 2. bajt zo zalohy
+ anl a,#03h ; vymaskuj nahodne bity
+ mov r0,a
+ mov a,vlocks ; nastav prislusny lock bit
+ cjne r0,#1,$+5
+ setb acc.2
+ cjne r0,#2,$+5
+ setb acc.3
+ cjne r0,#3,$+5
+ setb acc.4
+ mov vlocks,a
+ mov a,vchange ; zaznamenaj zmenu
+ setb acc.2
+ mov vchange,a
+ ajmp sdecode
+
+slockread: ; read lock bits
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ acall srcv ; prijmi 2.
+ acall srcv ; a 3. bajt
+ mov a,vlocks
+ acall ssend ; posli 4. bajt (lock bits)
+ ajmp sdecode
+
+ssignread: ; read signature bytes
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ acall srcv ; prijmi 2. bajt (upper address)
+ mov r0,a
+ acall srcv ; prijmi 3. bajt (lower address)
+ jnz ssignread_l0 ; ak nie je 0, ignoruj upper address
+ mov a,r0
+ anl a,#0fh
+ mov dptr,#vsign
+ movc a,@a+dptr
+ssignread_l0:
+ acall ssend ; posli 4. bajt (signature byte)
+ ajmp sdecode
+
+spageread: ; read program memory (page mode)
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ acall srcv ; prijmi 2. bajt (upper address)
+ anl a,#0fh ; vymaskuj nahodne bity
+ mov dph,a
+ mov dpl,#0
+spageread_l0:
+ acall vread
+ acall ssend ; posli 0. az 255. datovy bajt
+ inc dpl
+ mov a,dpl
+ cjne a,#0,spageread_l0
+ ajmp sdecode
+
+spagewrite: ; write program memory (page mode)
+ jb spe,$+5 ; skontroluj programming enable
+ ajmp sterm
+ clr green ; zasviet cervenu led a zelenu led
+ clr red
+ acall srcv ; prijmi 2. bajt (upper address)
+ anl a,#0fh ; vymaskuj nahodne bity
+ mov dph,a
+ mov dpl,#0
+spagewrite_l0:
+ acall srcv ; prijmi 0. az 255. datovy bajt
+ acall vwrite
+ inc dpl
+ mov a,dpl
+ cjne a,#0,spagewrite_l0
+ mov a,vchange ; zaznamenaj zmenu
+ setb acc.1
+ mov vchange,a
+ ajmp sdecode
+
+ ; prijem bajtu od programatoru
+srcv: mov r1,#8 ; prijmi 8 bitov
+srcv_l0:
+ jnb rst,$+5 ; kontroluj rst
+ ajmp sterm_p2
+ jb sck,$-5 ; cakaj na sck = 0
+ jnb rst,$+5
+ ajmp sterm_p2
+ jnb sck,$-5 ; cakaj na sck = 1
+ mov c,mosi ; prijmi bit
+ rlc a
+ jnb rst,$+5
+ ajmp sterm_p2
+ jb sck,$-5 ; cakaj na sck = 0
+ djnz r1,srcv_l0
+ ret
+
+ ; odoslanie bajtu programatoru
+ssend: mov r1,#8 ; posli 8 bitov
+ssend_l0:
+ jnb rst,$+5
+ ajmp sterm_p2
+ jb sck,$-5 ; cakaj na sck = 0
+ jnb rst,$+5
+ ajmp sterm_p2
+ jnb sck,$-5 ; cakaj na sck = 1
+ rlc a
+ mov miso,c ; posli bit
+ jnb rst,$+5
+ ajmp sterm_p2
+ jb sck,$-5 ; cakaj na sck = 0
+ djnz r1,ssend_l0
+ ret
+
+; ----------------------------------------------------------------------
+ ; obsluha casovaca 0 pre pwm
+rstpwm: jb rstsw,rstpwm_low
+ setb rstsw ; rst = 12 v
+ mov tl0,#low (0ffffh - volt)
+ mov th0,#high (0ffffh - volt)
+ reti
+rstpwm_low:
+ clr rstsw ; rst = 0 v
+ mov tl0,#low (0ffffh - period + volt)
+ mov th0,#high (0ffffh - period + volt)
+ reti
+
+ ; rst = 0 v
+rst0v: clr et0 ; zakaz prerusenie od casovaca 0
+ clr rstsw ; rst = 0 v
+ jmp rstv_exit
+ ; rst = 5 v
+rst5v: setb et0 ; povol prerusenie od casovaca 0
+ setb tf0 ; vyvolaj obsluhu casovaca 0
+ ;ajmp $ ; nekonecne cakanie pre odladenie generovania
+ ; napatia 5 v
+ jmp rstv_exit
+ ; rst = 12 v
+rst12v: clr et0 ; zakaz prerusenie od casovaca 0
+ setb rstsw ; rst = 12 v
+rstv_exit: ; cakaj na ustalenie rst napatia
+ mov r2,#20
+rstv_exit_loop:
+ clr tf1
+ mov tl1,#0
+ mov th1,#0
+ jnb tf1,$ ; ok
+ djnz r2,rstv_exit_loop
+ ret
+
+; ----------------------------------------------------------------------
+button: jnb lock,$+4 ; skontroluj zamok
+ reti
+ setb lock ; zamkni model
+ mov r0,#3 ; zober 3 vzorky
+button_noise:
+ clr tf1 ; po 5 ms
+ mov tl1,#low (65535 - 10000)
+ mov th1,#high (65535 - 10000)
+ jnb tf1,$
+ jnb btn,$+6
+ clr lock
+ reti
+ djnz r0,button_noise
+ mov r0,#30 ; hranicny cas 700 ms
+button_wait:
+ clr tf1
+ mov tl1,#low (65535 - 50000)
+ mov th1,#high (65535 - 50000)
+ ; detekovane kratke stlacenie
+ jb btn,button_short
+ jnb tf1,$-3
+ djnz r0,button_wait
+ ajmp button_long ; detekovane dlhe stlacenie
+
+button_short: ; kratke stlacenie
+ cpl up ; prepni smer synchronizacie
+ cpl down
+ ajmp button_exit ; skonci
+
+button_long: ; dlhe stlacenie
+ ; reaguj podla smeru synchronizacie
+ jnb up,button_upload
+ jnb down,button_download
+button_upload: ; at89cx501 do prevodniku
+ clr green ; led do aktivneho stavu
+ clr red
+ acall pcoderead ; precitaj pamat programu
+ setb red ; zasviet zelenu led
+ ajmp button_exit ; skonci
+button_download: ; prevodnik do at89cx501
+ clr green ; led do aktivneho stavu
+ clr red
+ acall perasechip ; zamaz at89cx501
+ acall pcodewrite ; zapis data
+ jnc button_download_l0
+ setb green ; zapis neuspesny, zasviet cervenu led
+ ajmp button_exit ; a skonci
+button_download_l0:
+ acall plockwrite ; zapis lock bity
+ setb red ; zapis uspesny, zasviet zelenu led
+ ajmp button_exit ; a skonci
+
+button_exit: ; cakaj na pustenie tlacidla
+ mov r0,#10 ; zober 10 vzoriek
+button_exit_l0:
+ clr tf1 ; po 5 ms
+ mov tl1,#low (65535 - 10000)
+ mov th1,#high (65535 - 10000)
+ jnb tf1,$
+ jnb btn,button_exit ; ak je detekovane stlacenie, znovu
+ djnz r0,button_exit_l0
+ clr lock ; odomkni model
+ reti
+
+; ----------------------------------------------------------------------
+ ; vypinacia sekvencia
+poff: clr xtal ; xtal = 0 v
+ acall rst0v ; rst = 0 v
+ clr vccsw ; vypni napajanie
+ ret
+
+pcodewrite: ; naprogramovanie pamate at89cx051
+ setb vccsw ; zapni napajanie
+ setb prog ; prog = 5 v
+ acall rst5v ; rst = 5 v
+ clr m0 ; mod
+ setb m1
+ setb m2 ; ok
+ mov dptr,#0 ; nastav fram adresu
+ clr f0 ; nabeh rst na 12 v len pre 1. bajt
+pcodewrite_l0:
+ acall vread ; precitaj bajt z modelu
+ mov pdata,a ; posli bajt at89cx051
+ jb f0,$+7
+ acall rst12v ; rst = 12 v
+ setb f0 ; len pre prvy bajt
+ clr prog ; 1 us prog pulz
+ nop
+ setb prog ; ok
+ clr tf1 ; cakaj 2 ms na skoncenie zapisu
+ mov tl1,#low (65535 - 4000)
+ mov th1,#high (65535 - 4000)
+ jnb tf1,$
+ setb xtal ; zvys adresu at89cx501
+ clr xtal
+ inc dptr ; zvys adresu modelu
+ mov a,dph ; skontroluj adresu
+ cjne a,#vmargin,pcodewrite_l0
+pcodeverify: ; kontrola pamate at89cx051
+ acall rst5v ; rst = 5 v
+ setb prog ; prog = 5 v
+ clr m0 ; mod
+ clr m1
+ setb m2 ; ok
+ mov dptr,#0 ; zaklad adresy modelu
+pcodeverify_l0:
+ acall vread ; precitaj byte z modelu
+ xrl a,pdata ; a porovnaj z at89cx501
+ ; ak acc != 0, chyba
+ jnz pcodeverify_error
+ setb xtal ; zvys adresu at89cx501
+ clr xtal
+ inc dptr ; zvys adresu modelu
+ mov a,dph ; skontroluj adresu
+ cjne a,#vmargin,pcodeverify_l0
+ acall poff ; vypinacia sekvencia
+ clr c ; zhod vlajku chyby
+ ret
+pcodeverify_error:
+ acall poff ; vypinacia sekvencia
+ setb c ; nastav vlajku chyby
+ ret
+
+pcoderead: ; citanie pamate at89cx051
+ mov dptr,#0 ; zmaz 4 kib fram
+ acall vwrite_open ; otvor model
+pcoderead_l1:
+ mov a,#0ffh ; vymazany bajt
+ acall vwrite_byte ; zapis bajt do modelu
+ inc dptr ; inkrementuj adresu
+ mov a,dph
+ cjne a,#10h,pcoderead_l1
+ acall vwrite_close ; zatvor model
+ setb vccsw ; zapni napajanie
+ acall rst5v ; rst = 5 v
+ setb prog ; prog = 5 v
+ mov pdata,#0ffh ; pdata ako vstupy
+ clr m0 ; mod
+ clr m1
+ setb m2 ; ok
+ mov dptr,#0 ; zaklad adresy modelu
+pcoderead_l0:
+ mov a,pdata ; precitaj data
+ acall vwrite ; zapis do modelu
+ setb xtal ; zvys adresu at89cx501
+ clr xtal
+ inc dptr ; zvys adresu modelu
+ mov a,dph ; skontroluj adresu
+ cjne a,#vmargin,pcoderead_l0
+ acall poff ; vypinacia sekvencia
+ ret
+
+plockwrite: ; zapis lock bitov at89cx501
+ mov a,vlocks
+ jnb acc.2,$+7 ; test 1. lock bitu
+ setb m2 ; nastav prislusny mod
+ acall plockwrite_l0 ; a zapis
+ jnb acc.3,$+7 ; test 2. lock bitu
+ clr m2 ; nastav prislusny mod
+ acall plockwrite_l0 ; a zapis
+ ret
+plockwrite_l0:
+ setb vccsw ; zapni napajanie
+ setb prog ; prog = 5 v
+ acall rst5v ; rst = 5 v
+ setb m0 ; mod
+ setb m1
+ acall rst12v ; rst = 12 v
+ clr prog ; 1 us prog pulz
+ nop
+ setb prog ; ok
+ clr tf1 ; cakaj na skoncenie zapisu
+ mov tl1,#low (65535 - 4000)
+ mov th1,#high (65535 - 4000)
+ jnb tf1,$
+ acall poff ; vypinacia sekvencia
+ ret
+
+perasechip: ; zmazanie pamate at89cx501
+ setb vccsw ; zapni napajanie
+ acall rst5v ; rst = 5 v
+ setb prog ; prog = 5 v
+ setb m0 ; nastav mod
+ clr m1
+ clr m2 ; ok
+ acall rst12v ; rst = 12 v
+ clr prog ; prog pulz 10 ms
+ clr tf1
+ mov tl1,#low (65535 - 20000)
+ mov th1,#high (65535 - 20000)
+ jnb tf1,$
+ setb prog ; ok
+ acall poff ; vypinacia sekvencia
+ ret
+
+; ----------------------------------------------------------------------
+vwrite: mov b,a ; zapis 1 bajt do fram
+ acall vwrite_open
+ mov a,b
+ acall vwrite_byte
+ acall vwrite_close ; ok
+ ret
+
+vwrite_open: ; otvorenie fram pre zapis
+ clr frwp ; povol zapis
+ clr frsda ; start
+ clr frscl ; adresa zariadenia
+ mov a,#10100000b
+ acall frsend
+ mov a,dph ; vrchny bajt adresy
+ acall frsend
+ mov a,dpl ; spodny bajt adresy
+ acall frsend
+ ret
+vwrite_byte: ; zapis bajtu do fram
+ acall frsend
+ ret
+vwrite_close: ; zatvorenie fram
+ setb frscl ; stop
+ setb frsda
+ setb frwp ; zakaz zapis
+ ret
+
+frsend: mov frerr,#2 ; pocet opakovani pri chybe
+ mov frct,#8 ; posli 8 bitov
+ mov frtmp,a ; zalohuj data
+frsend_l0:
+ rlc a
+ mov frsda,c ; acc.7 na sda
+ setb frscl ; zapis
+ clr frscl
+ djnz frct,frsend_l0 ; dalsi bit
+ setb frsda ; ack
+ setb frscl
+ mov c,frsda ; precitaj ack
+ clr frscl
+ jc frsend_retry ; vyhodnot ack
+ ret ; zapis prebehol uspesne, skonci
+frsend_retry: ; chyba zapisu
+ djnz frerr,$+5
+ ajmp fatal ; pocet pokusov vycerpany, fatalna chyba
+ mov frct,#8 ; posli 8 bitov
+ mov a,frtmp ; obnov data zo zalohy
+ ajmp frsend_l0 ; a znovu
+
+vread: acall vwrite_open ; precitaj 1 bajt z fram
+ setb frwp ; zakaz zapis
+ setb frscl ; start
+ clr frsda
+ clr frscl
+ mov a,#10100001b ; adresa zariadenia
+ acall frsend
+ mov frct,#8 ; prijmi 8 bitov
+vread_l0:
+ mov c,frsda ; zober bit z sda
+ rlc a
+ setb frscl ; vypytaj dalsi bit
+ clr frscl
+ djnz frct,vread_l0
+ setb frsda ; no ack
+ setb frscl
+ clr frscl ; ok
+ setb frscl ; stop
+ setb frsda
+ ret
+
+; ----------------------------------------------------------------------
+ ; neopravitelna chyba
+fatal: clr ea ; zakaz vsetky prerusenia
+ setb green ; zhasni vsetky led
+ setb up
+ setb down
+ setb red
+fatal_blink:
+ mov r0,#25 ; blikaj cervenou led s periodou 0.5 s
+ cpl red
+fatal_wait:
+ clr tf1
+ mov tl1,#low (65535 - 40000)
+ mov th1,#high (65535 - 40000)
+ jnb tf1,$
+ djnz r0,fatal_wait
+ ajmp fatal_blink ; cakaj do resetu
+
+ end