Avtor:
Matjaž Finc
Uvod2. PRETVORBA PREJETIH ASCII ZNAKOV V UKAZHPGL je 2D grafični format prvotno načrtovan za uporabo na ploterjih HP. Zaradi svoje enostavne strukture in uporabe so ga privzeli tudi ostali proizvajalci ploterjev in CAD programov. Format se uporablja v večini programov za načrtovanje in risanje (npr. AutoCad ipd.).
Osnove
Datoteka HPGL je sestavljena iz več ukazov. Vsi ukazi imajo enako strukturo:
funkcija+argumenti+ločilo
Funkcija (instruction) je sestavljena iz dveh velikih črk. V našem primeru smo uporabili le štiri najosnovnejše funkcije:
Argumenti (arguments) so lahko različnih tipov (stevila, črke) in so med sabo ločeni z vejico. Vsaka funkcija ima svoje argumente in določeno njihovo zaporedje. Če funkcija argumentov nima, jih enostavno izpustimo in na koncu postavimo ločilo.PU - Pen Up (dvig risala) PD - Pen Down (spust risala) PR - Plot Relative (risanje oz. premikanje po relativnih koordinatah - glede na trenuten položaj) PA - Plot Absolute (risanje oz. premikanje po absolutnih koordinatah - glede na začetno izhodišče) Ločilo (separator) pomeni konec HPGL ukaza. Privzeto ločilo je podpičje.
Primer - risanje ravne črte od (1,0) do (2,0):
PU;PA1,0;PD;PR1,0;PU;
Podrobnejši opis najdete na naslovu:
Wotsit's Format: The programmer's file formats and data formats resource.
V sprejemni buffer ploter prejme HPGL ukaz v ASCII obliki. ASCII znake je treba pretvoriti v obliko, ki bo ploterju omogočila izvajanje ukaza. V ta namen imamo tri spremenljivke:> UKAZ - ukazni register (8 bitni)
- UKAZ
- UKAZX
- UKAZY
Ukazni register zgleda takole:
DAV ONLINE BUSY NEGATIVE APPENDY PENUP RELATIVE STOP
(MSB) (LSB)Pomen posameznih bitov:
> UKAZX - koordinata X (16 bitna)
- DAV (Data Valid): ali je ukaz svež in v celoti sprejet (pretvorjen)
- ONLINE: ali je ploter v stanju online ali offline
- BUSY: ali ploter še vedno izvaja kakšen ukaz
Preden začnemo izvajati nov ukaz, moramo počakati da dokonča izvajanje trenutnega ukaza.
- NEG (negative): ali je prejeta koordinata negativna ali pozitivna
- APPENDY (Append Y): katero koordinato trenutno beremo (X ali Y)
Če v buffer ni prispel celoten ukaz, nam APPENDY pove katera koordinata je aktualna v naslednjem ciklu branja.- PENUP: stanje pisala (dvignjeno ali spuščeno)
- RELATIVE: relativne ali absolutne koordinate
- STOP: brezpogojna zaustavitev
> UKAZY - koordinata Y (16 bitna)
PRETVORBA
Rutina, ki pretvarja ASCII v ukaz ploterja se imenuje CONVERT. Pri pretvorbi sem privzel, da so v vhodni HPGL datoteki uporabljeni samo ukazi PD, PU, PR in PA ter da so vsi ukazi podani strukturno pravilno.
Uporabljenih je tudi nekaj subrutin:
Test prebranega znaka
- RECCHR - prebere znak iz sprejemnega bufferja (če buffer prazen postavi Z=1)
RECCHR pshx
ldx RECB
cpx RECE
beq NORCHAR
ldaa 0,x
inx
cpx #RECE
bne NORROL
ldx #RECB+2
NORROL stx RECB
NORCHAR pulx
rts
- XY0 - pobriše UKAZX in UKAZY
XY0 ldx #$0
stx UKAZX
ldx #$0
stx UKAZY
rts
- MINUS1 - test predznaka (če je znak ‘-‘ spremeni NEG na 1 in vrne Z=1)
MINUS1 cmpa #"-"
bne MINEND
ldaa UKAZ
oraa #%00010000
staa UKAZ
ldaa #0
rts
MINEND tab
ldaa UKAZ
anda #%11101111
staa UKAZ
tba
rts
- CONVERT
Glavna rutina CONVERT je okvirno sestavljena takole:
- test prebranega znaka
- ugotavljanje črke
- računanje X koordinate
- računanje Y koordinate
- konec rutine
Program najprej preveri če je zadnji ukaz v celoti izvršen in če je ploter preipravljen na sprejem novega ukaza (DAV=0, ONLINE=0, BUSY=0). Če so ti pogoji izpolnjeni, prebere prvi naslednji znak v sprejemnem bufferju. Če je slučajno buffer poln (ni vrnjenega znaka oz. Z=1) prekinemo izvajanje rutine. Naslednji korak je ugotavljanje prebranega znaka. Prvi prebrani znak ni nujno prva črka ukaza - če je v prejšnjem ciklu pretvorba bila nedokončana (ostane DAV=0) oz. če je bil buffer poln preden smo v njega spravili celoten ukaz (nismo prebrali znak do konca). Torej, ta znak je lahko črka (prva ali druga črka ukaza), številka (del X ali Y koordinate), vejica (vmesno ločilo med argumenti za X in Y koordinato), minus (predznak X ali Y koordinate) ali podpičje (ločilo - konec ukaza). Če je prebrani znak vejica, potem se nastavi zastavica APPENDY=1, kar nam pove katero koordinato bomo obdelovali (če bo slučajno buffer poln, in bomo v naslednjem ciklu prebrali število).
CONVERT ldaa UKAZ
anda #%11100000 ;najprej pogleda ce je DAV=1, ONLINE=1, BUSY=1
bne DAVEND1 ;ce je, skoci na konec
jsr RECCHR ;prebere prvi znak na vrsti
beq DAVEND1 ;ce v bufferju ni znaka gre na konec
cmpa #","
bmi DAVEND1
cmpa #"A" ;preveri ce je crka
bpl CRKA ;ce je skoci na test za crke
cmpa #";" ;ali je podpicje
beq JEPD2 ;ce je skoci na konec (JEPOD)
jsr MINUS1 ;ali je minus
bne VEJMIN ;ce ni, skoci na test za vejico
ldaa UKAZ
anda #%00001000 ;katero koordinato moramo obdelovati (naslednji znak)
bne JEVJ ;ce je APPENDY=1 vpisujemo Y
bra STEVIL ;ce ni, pa vpisujemo XDAVEND1 bra DAVEND2 ;pomozni skok zaradi prevelike dolzine
VEJMIN cmpa #","
beq VEJTS1
ldaa UKAZ
anda #%00001000
beq NIVEJ
bra NIPOD1Ugotavljanje črke
S tem delom programa ugotavljamo, kateri ukaz bomo izvajali. Vsaka prebrana zadnja črka ukaza nam resetira UKAZX in UKAZY (rutina XY0) in nastavi ustrezne zastavice v ukaznem registru.
CRKA cmpa #"P" ;ce je crka P
bne NIP ;ce je, prebere naslednjo, ce ne, pa ugotavlja katera crka je
jsr RECCHR ;gleda drugo crko ukaza
beq DAVEND1 ;ce v bufferju ni znaka gre na konec
NIP cmpa #"A" ;(=A)ali je ukaz PA
bne RUKAZ ;ce ni, preverja naprej
ldaa UKAZ ;ce je, nastavi zastavico RELATIVE=0
anda #%11111101
staa UKAZ
bra STEVX
RUKAZ cmpa #"R" ;(=R)ali je PR
bne UUKAZ
ldaa UKAZ
oraa #%00000010 ;zastavica RELATIVE=1
staa UKAZ
STEVX jsr XY0
jsr RECCHR
beq DAVEND1
jsr MINUS1
beq STEVIL
jmp NIVEJ
;bra VEJIC
JEPD2 bra JEPD
UUKAZ cmpa #"U" ;(=U)ali je PU
bne DUKAZ
ldaa UKAZ
oraa #%00000110 ;nastavitev zastavic PENUP=1, RELATIVE=1
staa UKAZ
jsr XY0
jsr RECCHR ;pregleda ce je podpicje naslednji
beq DAVEND1 ;ce v bufferju ni znaka gre na konec
bra PODPIC1
DUKAZ ldaa UKAZ ;ce ni nobena od zgornjih, potem je PD (oz. crka D)
anda #%11111011 ;PENUP=0
oraa #%00000010 ;nastavitev zastavice RELATIVE=1
staa UKAZ
jsr XY0
jsr RECCHR ;pregleda ce je podpicje
beq DAVEND1 ;ce v bufferju ni znaka gre na konec
bra PODPIC1
JEPD bra JEPD1 ;pomozni skoki zaradi prevelike dolzine
DAVEND2 bra DAVEND3
JEVJ bra JEVEJ
NIPOD1 bra NIPOD
VEJTS1 bra VEJTSTRačunanje X koordinate
Prebrani ASCII znak iz bufferja najprej spremenimo v število (odštejemo ASCII vrednost znaka ‘0’). Če je spremenljivka UKAZX prazna (vrednost 0), novo prebrano število enostavno shranimo v spremenljivko. Če pa je v spremenljivki UKAZX že kakšna neničelna vrednost, jo pomnožimo z (desetiškim) faktorjem 10 in prištejemo na novo prebrano število. To ponavljamo, dokler prebrani znak ni vejica. Množenje s faktorjem deset izvedemo s pomočjo ‘shiftanja’ v levo (množenje z 2) in to takole:
število*10 = število*2*2*2+število+število
;---Racunanje X koordinate---
STEVIL jsr RECCHR
beq DAVEND2 ;ce v bufferju ni znaka gre na konec
jmp VEJICA ;ali je slučajno ze vejica
NIVEJ suba #"0" ;pretvori ASCII v stevilo
psha ;shrani v sklad
ldd UKAZX ;ali je to prva stevilka po vrsti
bne RACUNX ;ce ni, moramo staro vsebino *10 in pristeti novo
pula ;prvo stevilko po vrsti le zacasno zapisemo v UKAZX
tab ;tu moramo uporabiti celotni akumulator (D=A,B)
clra
std UKAZX
bra STEVIL ;ponovimo (dokler ni vejice - potem Y koordinato)
RACUNX ldd UKAZX ;množenje z 10 za X koordinato:******
asld ;*2
asld ;*2
asld ;*2
addd UKAZX ;+zacetna vrednost
addd UKAZX ;+zacetna vrednost
std UKAZX ;nazaj v X
pula ;potegnemo zadnje stevilo iz sklada
tab ;akum. D pretvorimo v obliko '00000000,stevilo'
clra
addd UKAZX ;pristejemo novo stevilko (enice)
std UKAZX
bra STEVIL
DAVEND3 jmp DAVEND4 ;pomozni skoki zaradi prevelike dolzine
JEPD1 bra JEPOD
PODPIC1 bra PODPIC
VEJIC bra VEJICA
Pomožna veja za test vejice (VEJICA) naredi naslednje:
;---Pomozna veja za test vejice---
- če ni vejice se vrne na nadaljevanje računanja X koordinate
- če je vejica: ? če je NEG=1, naredi dvojiški komplement spremenljivke UKAZX (negativno število)
- resetira zastavico NEG
- postavi APPENDY=1 (naslednja bo koordinata Y)
- skoči na računanje Y koordinate
VEJICA cmpa #"," ;ali je vejica
bne NIVEJ ;ce ni, je stevilo oz. koordinata X
VEJTST ldaa UKAZ
anda #%00010000 ;ce je, pogledamo ce je X negativen
beq NINEG
ldd UKAZX ;in ga pretvorimo v neg. stevilo*******
coma
comb
addd #1
std UKAZX
NINEG ldaa UKAZ
oraa #%00001000 ;postavimo APPENDY=1
;anda #%11101111 ;brisemo NEG
staa UKAZ
jsr RECCHR
beq DAVEND4
jsr MINUS1
beq JEVEJ ;gremo racunat Y koordinato
bra PODPICRačunanje Y koordinate
Ta podveja programa naredi podobno kot ‘računanje X koordinate’. Vmes testiramo za podpičje (skok na podvejo PODPIC).
;---Racunanje Y koordinate---
JEVEJ jsr RECCHR
beq DAVEND4 ;ce v bufferju ni znaka gre na konec
bra PODPIC
NIPOD suba #"0" ;pretvori ASCII v stevilo
psha ;shrani v sklad
ldd UKAZY ;ali je to prva stevilka po vrsti
bne RACUNY ;ce ni, moramo staro vsebino *10 in pristeti novo
pula ;prvo stevilko po vrsti le zacasno zapisemo v UKAZY
tab ;tu moramo uporabiti celotni akumulator (D=A,B)
clra
std UKAZY
bra JEVEJ ;ponovimo (dokler ni podpicja - potem konec)
RACUNY ldd UKAZY ;množenje z 10 za Y:
asld ;*2
asld ;*2
asld ;*2
addd UKAZY ;+zacetna vrednost
addd UKAZY ;+zacetna vrednost
std UKAZY ;nazaj v Y
pula
tab
clra
addd UKAZY ;pristejemo novo stevilko (enice)
std UKAZY
bra JEVEJ;---Pomozna veja za test podpicja---
PODPIC cmpa #";" ;ce je podpicje potem JEPOD
bne NIPOD ;ce ni pa racunamo Y
bra JEPOD4.5. Konec rutine
Preveri ali je treba UKAZY dvojiško komplementirati (zastavica NEG), resetira zastavici APPENDY in NEG, postavi DAV=1.
;---Konec rutine---
JEPOD ldaa UKAZ
anda #%00010000 ;pogleda ce je zadnjo koord. treba spremenit v negativno
beq JEY
ldd UKAZY ;in ga pretvorimo v neg. stevilo
coma
comb
addd #1
std UKAZY
JEY ldaa UKAZ
anda #%11100111 ;brise APPENDY in NEG
oraa #%10000000 ;postavi DAV=1
staa UKAZ
bra DAVEND4
DAVEND4 rts
Zaključek
Po končani rutini CONVERT so ukazni register UKAZ in pozicijski spremenljivki UKAZX in UKAZY pripravljeni na nadaljno uporabo (izris oz. izvedba ukaza). Ko bo ukaz izveden (DAV=0) oz. sprejemni buffer ponovno napolnjen, bo CONVERT izvedel novo pretvorbo za naslednji ukaz.
Vsebina
Tekst je napisal Matjaž Finc
Stran je uredil Miha Krejan
25. Marec 1999