APPENDICE
Riportiamo di seguito una breve descrizione sul funzionamento dei tre strumenti
maggiormente adoperati in laboratorio e per quanto riguarda il pattern generator mostriamo
per completezza i file sorgente in linguaggio C con i quali vengono generati le maschere in
formato .wrt per definire le geometrie delle litografie a fascio elettronico.
A.1 – Microscopio ottico
Il microscopio ottico (OM) costituisce un tool molto importante per lo studio di
strutture micrometriche e resta tuttora di estrema utilità nonostante l’avvento di altre
tecniche di imaging più avanzate come SEM, TEM o AFM.
In dipartimento disponiamo di un microscopio DM 2500 M della Leica Microsystems situato
in camera gialla (chiamata così perché è un ambiente in cui si evitano componenti di luce
intorno al blu, in quanto foto/electron resist risultano sensibili a tali lunghezze d’onda).
Figura A.1: microscopio ottico Leica DM 2500 M nella camera gialla del laboratorio di tecnologie microelettroniche.
In un microscopio ottico l’oggetto sotto visione viene illuminato dalla luce (con lunghezze
d’onda appartenenti a tutto lo spettro visibile) focalizzata tramite una lente condensatrice
posizionata perpendicolarmente rispetto all’asse della lente obiettivo. Parte della luce viene
trasmessa attraverso il campione mentre la restante parte viene riflessa sulla lente obiettivo
che crea un’immagine ingrandita. Questa luce proveniente dall’obiettivo viene deviata, in
genere tramite un sistema di prismi, sia verso il piano focale dell’oculare (tipicamente
l’immagine risulta invertita) che verso una lente di proiezione dove viene formata
un’immagine su un array di fotodiodi CCD. Solitamente l’ingrandimento di un microscopio
ottico nel range del visibile può arrivare fino a X1500 con un limite teorico di risoluzione
all’incirca pari a 200 nm.
In laboratorio, considerato l’utilizzo principalmente per altri scopi, purtroppo si raggiungono
al massimo ingrandimenti X100 con un’apertura numerica di 0.90.
Per apertura numerica (NA) di un sistema ottico si intende il valore che caratterizza il
massimo angolo utile alla lente per ricevere ed emettere luce. La formula è la seguente:
NA = n∙sen(
ϑ
)
dove n rappresenta l’indice di rifrazione del mezzo in cui lavora la lente (1 per l’aria) e
ϑ
è la
metà dell’angolo del cono di luce che può attraversare la lente.
In tutto disponiamo di sei lenti d’ingrandimento: X2.5/5/10/20/50/100. La sorgente di luce è
una comune lampada alogena da 12 V/100 W.
A.2 – Microscopio a forza atomica (AFM)
L’AFM rappresenta la microscopia di terza generazione in quanto consente di ottenere
immagini tridimensionali di strutture superficiali su scala nanometrica. Il principio di
funzionamento è quello di misurare la forza presente tra una punta (probe) posizionata su un
cantilever e la superficie del campione situata molto in prossimità, solitamente tra gli 0.2 nm e
i 10 nm.
Il supporto, o cantilever, viene realizzato in silicio o nitruro di silicio (Si
3N
4) tramite tecniche
di micro-machining ed ha dimensioni del centinaio di micron in lunghezza, dieci μm in
larghezza e uno spessore di circa 1 μm. Al termine del cantilever si trova una punta molto fine,
sempre dello stesso materiale, di forma piramidale o conica che può raggiungere un raggio di
curvatura inferiore a 10 nm.
Figura A.2: a sinistra immagine SEM di un cantilever di silicio; a destra grafico dell’andamento della forza in funzione della distanza tra gli atomi della punta e quelli del campione [65].
La figura qui sopra a sinistra ne riporta un immagine al SEM mentre sulla destra è
rappresentata la configurazione di base per la gran parte degli AFM: come la distanza tra gli
atomi del materiale della punta e quelli della superficie in esame diventa piccola questi
possono iniziare ad interagire tra di loro e la forza d’interazione può risultare attrattiva (forze
di van der Waals) per distanze relativamente lunghe o repulsiva (dovuta alla repulsione
elettrostatica o da forze capillari) quando la distanza punta
L’ammontare di questa forza interatomica
costante elastica del cantilever e
quest’ultimo durante la scansione della punta
utilizzato è quello di misurare la variazione dell’angolo di riflessione
sulla superficie posteriore del cantilever
(PSPD, position sensitive photo
del movimento del campione lungo gli altri due assi X e Y (generato da attuatori piezoelettrici)
si genera un’immagine tridimensionale della superficie in questione. Inoltre il segnale
presente al PSPD viene utilizzato per stabilire una retroazione che controlla il movimento
verticale dello scanner durante la scansione linea per linea della punta sul campione.
Una semplice rappresentazione di quanto appena scritto è presente in figura A.3
notare anche la presenza dello scanner piezoelettrico triassiale convenzionale.
Figura A.3: schema generale di funzionamento di un microscopio AFM durante una scansione
In questa configurazione il movimento in una determinata direzione non risulta indipendente
da quello lungo un’altra direzione e ciò
L’AFM modello XE-100E della PSIA Corporation
nostro laboratorio elimina questo tipo di
scanner in X-Y da quello lungo l’asse Z
modo si rende anche migliore la velocità di risp
Rimangono da descrivere le tre possibili
•
Contact mode: lo studio della topografia del campione è condotto utilizzando la forza
repulsiva tra punta e superficie che risulta dell’ordine di
mantenuta costante tramite
costante la deflessione del cantilever
soprattutto per superfici rugose e permette velocità di scansione maggiori; di contro
a sinistra ne riporta un immagine al SEM mentre sulla destra è
rappresentata la configurazione di base per la gran parte degli AFM: come la distanza tra gli
atomi del materiale della punta e quelli della superficie in esame diventa piccola questi
iniziare ad interagire tra di loro e la forza d’interazione può risultare attrattiva (forze
di van der Waals) per distanze relativamente lunghe o repulsiva (dovuta alla repulsione
elettrostatica o da forze capillari) quando la distanza punta-campione è mol
uesta forza interatomica dipende, oltre che dalla distanza, anche dalla
costante elastica del cantilever e può essere rilevata monitorando la deflessione di
durante la scansione della punta sul campione. Il metodo p
misurare la variazione dell’angolo di riflessione di un fascio laser
del cantilever e riflesso verso un fotodiodo a quattro quadranti
(PSPD, position sensitive photo detector). Registrando la deflessione lungo l’asse Z in funzione
del movimento del campione lungo gli altri due assi X e Y (generato da attuatori piezoelettrici)
si genera un’immagine tridimensionale della superficie in questione. Inoltre il segnale
utilizzato per stabilire una retroazione che controlla il movimento
verticale dello scanner durante la scansione linea per linea della punta sul campione.
rappresentazione di quanto appena scritto è presente in figura A.3
scanner piezoelettrico triassiale convenzionale.
schema generale di funzionamento di un microscopio AFM durante una scansione
In questa configurazione il movimento in una determinata direzione non risulta indipendente
da quello lungo un’altra direzione e ciò crea problemi intrinseci di non linearità e cross
della PSIA Corporation, ora Park Systems (figura A.
a questo tipo di interferenza rendendo fisicamente separati lo
Y da quello lungo l’asse Z verticale comprendente anche il cantilever.
modo si rende anche migliore la velocità di risposta del sistema [65].
da descrivere le tre possibili tipologie di scansione di imaging AFM:
lo studio della topografia del campione è condotto utilizzando la forza
repulsiva tra punta e superficie che risulta dell’ordine di qualche nN.
ramite l’applicazione dell’anello di reazione
costante la deflessione del cantilever ossia la distanza tra probe
soprattutto per superfici rugose e permette velocità di scansione maggiori; di contro
a sinistra ne riporta un immagine al SEM mentre sulla destra è
rappresentata la configurazione di base per la gran parte degli AFM: come la distanza tra gli
atomi del materiale della punta e quelli della superficie in esame diventa piccola questi
iniziare ad interagire tra di loro e la forza d’interazione può risultare attrattiva (forze
di van der Waals) per distanze relativamente lunghe o repulsiva (dovuta alla repulsione
campione è molto piccola.
dipende, oltre che dalla distanza, anche dalla
do la deflessione di
. Il metodo più semplice ed
di un fascio laser puntato
e riflesso verso un fotodiodo a quattro quadranti
trando la deflessione lungo l’asse Z in funzione
del movimento del campione lungo gli altri due assi X e Y (generato da attuatori piezoelettrici)
si genera un’immagine tridimensionale della superficie in questione. Inoltre il segnale
utilizzato per stabilire una retroazione che controlla il movimento
verticale dello scanner durante la scansione linea per linea della punta sul campione.
rappresentazione di quanto appena scritto è presente in figura A.3, in cui si può
scanner piezoelettrico triassiale convenzionale.
schema generale di funzionamento di un microscopio AFM durante una scansione [65].
In questa configurazione il movimento in una determinata direzione non risulta indipendente
non linearità e cross-talk.
(figura A.5) presente nel
fisicamente separati lo
comprendente anche il cantilever. In questo
imaging AFM:
lo studio della topografia del campione è condotto utilizzando la forza
qualche nN. Questa viene
reazione in Z con cui si tiene
probe e campione. E’ utile
soprattutto per superfici rugose e permette velocità di scansione maggiori; di contro
può danneggiare la superficie d’interesse e la punta è maggiormente soggetta a usura o
possibile rottura.
•
Non contact mode: in questo caso, come suggerisce il nome, la punta non viene mai a
contatto con la superficie di scansione. Dato che si lavora a una distanza
punta-campione compresa tra 1 e 10 nm le forze in gioco dominanti sono quelle attrattive di
van der Waals che risultano però molto deboli e quindi difficili da misurare
direttamente attraverso la deflessione del cantilever. Per questo motivo il cantilever
viene fatto oscillare a una frequenza prossima a quella di risonanza intrinseca
(compresa tra 100-400 kHz) con un’ampiezza di vibrazione di qualche nanometro.
Quello che si va a rilevare è la variazione di fase o di ampiezza di questa oscillazione
indotta dalle forze di attrazione tra la punta e la superficie. Questa modalità non soffre
degli effetti di degradazione della punta riscontrati in contact mode.
Figura A.4: disegno concettuale delle due modalità contact – non contact [60].
•
Tapping mode: è un ibrido delle due modalità precedenti, il processing dell’immagine
è simile a quello con tecnica contact ma il cantilever viene fatto oscillare alla sua
frequenza di risonanza. Per realizzare l’immagine l’ampiezza dell’oscillazione viene
mantenuta costante e di conseguenza anche il tipo di interazione punta-superficie.
La distanza tra la punta e il campione varia tra 0.5 e 2 nm. Questo utilizzo è molto utile
per scansioni ad alta risoluzione su superfici facilmente danneggiabili.
A.3 – Sistema pattern generator (PG) / microscopio a
scansione elettronica (SEM) [58]
Affiancando ad un microscopio elettronico a scansione l’hardware di un pattern
generator capace di pilotare il sistema di deflessione X-Y del fascio proprio del microscopio si
ottiene uno strumento di litografia e-beam ad alta risoluzione. Le tensioni di controllo della
deflessione devono essere il più possibile precise, senza intromissione di disturbi e rumore.
Figura A.6: SEM JEOL JSF 6500F e pattern generator dell’Università di Pisa.
Dal punto di vista elettronico quindi il PG non è altro che un generatore di tensioni analogiche
ad alta precisione, che nel nostro caso utilizza convertitori digitali-analogici (DAC) a 18 bit a
basso rumore. Queste tensioni di pilotaggio devono essere proporzionali alle coordinate X ed
Y delle geometrie del layer da realizzare. Per layer si definisce un insieme di geometrie da
scrivere con un singolo passo di litografia, ossia con un solo file.
Per definire quest’ultimo può essere usato un qualsiasi strumento CAD di microelettronica
con file di uscita in formato GDSII da convertire poi in formato .wrt proprio del pattern
generator oppure, bypassando l’utilizzo del CAD, tramite semplice editor di testo inserendo le
direttive opportune che descriveremo tra poco.
Il software del PG deve trasformare le dimensioni delle geometrie in numeri adatti
all’hardware del sistema; il movimento del fascio, e quindi l’area di scansione, viene
scomposto in una griglia di punti discreti. Indichiamo con ∆X e ∆Y la distanza rispettivamente
sui due assi tra due punti adiacenti della griglia.
Queste distanze corrispondono all’incremento di una unità (LSB, least significant bit) del
numero in ingresso al convertitore digitale/analogico quindi in definitiva il numero di passi
disponibili in X ed in Y equivale al numero totale di LSB ossia 2
ndove n è il numero di bit dei
convertitori. Occorre prestare attenzione al fatto che i valori di ∆X e ∆Y dipendono oltre che
dal numero di bit anche dal tempo di esposizione del resist e dalla dimensione dell’area di
scrittura (area di scansione del fascio) che viene impostata attraverso l’ingrandimento del
microscopio:
∆
2
∆
!2
con S
Xe S
Yampiezze di scansione lungo l’asse X e Y.
Figura A.7: esempio di area di scrittura con geometria da realizzare decomposta nella griglia di punti in cui il fascio andrà a posizionarsi durante l’esposizione.
Le dimensioni dei passi sono state determinate sperimentalmente in passato facendo prove
con scritture di quadrati o linee ad un determinato ingrandimento con diversi tempi di
esposizione e misurando le dimensioni delle geometrie realizzate dopo lo sviluppo del resist.
Ad esempio, per le nostre scritture con ingrandimento a X100 avevamo che ∆X=5.2 nm e
∆Y=4.2 nm risultante quindi in un’area di scrittura di 1.36 mm (S
X) per 1.1 mm (S
Y).
Il software del PG dell’Università di Pisa (ebeam) con la relativa interfaccia grafica è stato
interamente sviluppato in linguaggio C ed è costituito da una serie di programmi che
consentono di svolgere le seguenti funzionalità:
•
convertire un file da formato binario GDS a .wrt;
•
caricare direttamente un file .wrt già convertito;
•
lanciare un processo di scrittura a 18 bit;
•
effettuare una calibrazione del sistema in X e Y;
•
lanciare un processo di scrittura veloce con architettura 16/18 bit;
•
acquisire immagini per l’allineamento di scritture successive.
Come accennato poco sopra si può evitare di caricare il file utile al PG per la litografia
passando attraverso la conversione dal file con estensione GDS producendo direttamente il
S
X
S
Y∆
X
formato .wrt con un qualsiasi editor di testo (WordPad, Emacs ecc.). Specifichiamo adesso nel
dettaglio come deve essere scritto un file del genere descrivendo inoltre il significato delle
direttive più importanti: la prima riga deve contenere obbligatoriamente la stringa
#WRITE18
mentre subito sotto vanno definiti in successione i parametri necessari per la scrittura
DELTA <∆X> <∆Y>
per inserire i valori di ∆X e ∆Y di cui parlavamo prima (in metri) conosciuti a priori;
DOSE <numero>
per indicare la dose di esposizione dell’electron resist, espressa in C/m
2;
STEP <stepX> <step
Y
>
dove <stepX> e <stepY> devono essere due numeri interi compresi tra 1 e 255. Con questa
direttiva scegliamo ogni quanti punti della griglia posizionare il fascio di elettroni cioè anziché
muoverlo con passo di un singolo LSB (posizionandolo su ogni punto della griglia) possiamo
spostarlo di <stepX> LSB lungo X e di <stepY> passi in Y. Questo significa posizionarsi su una
griglia più grande diminuendo quindi la risoluzione. Ad esempio se si scrive STEP 6 4
indichiamo che la scrittura avverrà muovendo il fascio di 6 passi per volta in X e di 4 in Y;
TIME <T
dwell>
con <T
dwell> definito in secondi indica espressamente il tempo di esposizione. Questa direttiva
è facoltativa poiché una volta inseriti i valori sopra e misurata la corrente del fascio
(procedura da svolgere in maniera accurata immediatamente prima di ogni esposizione con
l’ausilio di una gabbia di Faraday sul portacampioni e di un picoamperometro) il programma
si calcola direttamente il T
dwellattraverso la nota formula:
T
dwell=Dose7∆XstepX · ∆YstepY9/I
;<=>Se però viene indicata, questa direttiva prevale sugli altri parametri che risultano quindi
inessenziali per il calcolo del tempo di esposizione. In definitiva se ad esempio inseriamo
TIME 1.2e-05 il T
dwellequivale a 12 µs qualunque sia la corrente del fascio e la
dose/stepX/stepY impostati.
Terminato il set di parametri utili per la configurazione della scrittura possiamo procedere
inserendo le direttive di descrizione delle geometrie che si dividono in:
LINEX <Xstart> <Xstop> <Y>
ascissa iniziale, ascissa finale, ordinata; linea orizzontale
con passaggio singolo del fascio;
LINEY <Ystart> <Ystop> <X>
ordinata iniziale, ordinata finale, ascissa; linea verticale con
passaggio singolo del fascio;
LINE <Xstart> <Ystart> <Xstop> <Ystop>
coordinate di partenza, coordinate di arrive;
linea qualsiasi con passaggio singolo del fascio;
BOX <Xdown-sx> <Ydown-sx> <Xup-dx> <Yup-dx>
coordinate dei vertici in basso a
sinistra e in alto a destra; geometria rettangolo;
BOUNDARY <n> <X1> <Y1> <X2> <Y2>… <Xn> <Yn>
numero
n
di
vertici
del
poligono e coordinate di ciascun vertice; geometria poligono generico;
PATH <n> <X1> <Y1> <X2> <Y2>… <Xn> <Yn> <t
h>
numero n di punti della
spezzata, coordinate di ciascun punto e spessore t
hdella linea; linea spezzata qualsiasi con un
certo spessore;
geometrie si fa riferimento a un sistema di assi cartesiani (X,Y) rappresentante l’intera area di
scrittura con origine in basso a sinistra (vertice (0,0)) e limite massimo in alto a destra
(vertice (2
18-1, 2
18-1)).
Figura A.8: file trackfinali.wrt; notare la presenza della direttiva TIME per specificare espressamente il tempo di esposizione e della direttiva END per indicare la fine del file.
Nel caso specifico dei nostri file è stato sempre inserito un T
dwelldi 12 µs e sono state
utilizzate le seguenti geometrie:
•
croce.wrt: LINEX, LINEY sia per le braccia della croce che per i marker quadrati;
•
grafene01.wrt: LINEX, LINEY per le croci e i numeri; BOX per i marker di allineamento;
•
contatti-grafene.wrt: BOUNDARY sia per i pad che per le track;
•
trackfinali.wrt: LINEX, LINEY, LINE per tutte le track finali;
•
mascheraisolante.wrt: BOUNDARY, è un quadrato 90x90 µm.
Una volta disponibile il file per la litografia da mandare in scrittura è necessario predisporre il
SEM in modo da ottenere immagini che siano le migliori possibili. Avere delle buone
immagini, con un contrasto ben definito e senza problemi di astigmatismo significa definire
un fascio di elettroni ben focalizzato e quindi un’ottima risoluzione. Solitamente prima di
avviare la scrittura questa procedura di settaggio viene fatta posizionandosi sopra un
campione a perdere situato sul porta campioni appositamente per questa funzione.
Procedendo con la scrittura il software apre una finestra di visualizzazione grafica
(coincidente con l’area di scrittura) in cui vengono mostrate le geometrie definite dal file .wrt
caricato ed un’altra finestra in cui è possibile modificare per l’ultima volta i parametri di
esposizione (ricordiamo ancora che se nel file .wrt è presente espressamente la direttiva
TIME, impostare gli altri parametri non comporta alcun effetto sulla scrittura).
Se invece il pattern deve essere scritto sopra una struttura già esistente, prima di lanciare
l’esposizione è necessario eseguire l’operazione di allineamento andando a ritrovare tramite
imaging SEM i marker sacrificali che il sistema utilizza per riconoscere la posizione esatta del
campione (correzione di tutte le coordinate delle geometrie presenti nel file del processo di
scrittura attuale). Per una guida dettagliata sulla successione dei passi da svolgere e i relativi
tasti da selezionare durante
questa procedura si faccia riferimento al manuale apposito del pattern
generator ([58] capitolo 3, paragrafo 5).
In ogni caso, seguendo le indicazioni di conferma che compaiono sulle schermate del software
si arriva ad avviare la scrittura e iniziare il processo di esposizione: la geometria attualmente
in scrittura viene colorata di rosso mentre quelle già scritte risultano di colore verde; questo
consente di controllare lo stato di avanzamento della litografia.
A.4 – Codici C
A.4.1 – grafene01.c
# include <stdio.h> # include <stdlib.h> # define TEMPO 12e-6
5
# define NUMERO_CROCI_X 20 # define NUMERO_CROCI_Y 20
# define PASSOX 5800 //30 micron
# define PASSOY 7100 //30 micron
# define BRACCIOX 385 //2 micron
10
# define BRACCIOY 476 //2 micron
# define MEZZOQUADRATO 3000 //poco piu' di 15 micron int disegna_croce(long int centrox, long int centroy, FILE *fp)
{
15
fprintf(fp,"\nLINEX %ld %ld %ld",centrox-BRACCIOX, centrox+BRACCIOX, centroy); fprintf(fp,"\nLINEY %ld %ld %ld",centroy-BRACCIOY, centroy+BRACCIOY, centrox); }
int disegna_rettangolo_marker(long int centrox1, long int centroy1,long int centrox2,long int centroy2,FILE *fp)
20
{
fprintf(fp,"\nBOX %ld %ld %ld %ld",centrox1-(MEZZOQUADRATO/2), centroy1-(MEZZOQUADRATO/2), centrox1+(MEZZOQUADRATO/2), centroy1+(MEZZOQUADRATO/2));
fprintf(fp,"\nBOX %ld %ld %ld %ld",centrox2-(MEZZOQUADRATO/2), centroy2-(MEZZOQUADRATO/2), centrox2+(MEZZOQUADRATO/2), centroy2+(MEZZOQUADRATO/2));
25
}
# define SEGMENTOY 357 //1.5 micron
# define SEGMENTOX 288 //1.5 micron
30
int disegna_numero(long int startx, long int starty, int numero, FILE *fp) {
switch(numero){ case 1:
fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);
35
fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY, starty+SEGMENTOY*2, startx+SEGMENTOX); break; case 2: fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY);
40
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx);fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY ,starty+SEGMENTOY*2, startx+SEGMENTOX); break;
case 3:
45
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);
fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY, starty+SEGMENTOY*2, startx+SEGMENTOX);
50
break; case 4:
fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);
fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY, starty+SEGMENTOY*2, startx+SEGMENTOX); fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx);
55
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY); break; case 5: fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY);60
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX); fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx); break; case 6:65
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);70
fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx); break; case 7: fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY ,starty+SEGMENTOY*2, startx+SEGMENTOX);
75
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); break; case 8: fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY);80
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX); fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx);fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY, starty+SEGMENTOY*2,startx+SEGMENTOX);
85
break; case 9:
fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX);
fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY, starty+SEGMENTOY*2, startx+SEGMENTOX); fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx);
90
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); break; case 0:95
fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty); fprintf(fp,"\nLINEX %ld %ld %ld",startx,startx+SEGMENTOX,starty+SEGMENTOY*2); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx); fprintf(fp,"\nLINEY %ld %ld %ld",starty,starty+SEGMENTOY,startx+SEGMENTOX); fprintf(fp,"\nLINEY %ld %ld %ld",starty+SEGMENTOY,starty+SEGMENTOY*2,startx);100
fprintf(fp,"\nLINEY %ld %ld %ld", starty+SEGMENTOY, starty+SEGMENTOY*2, startx+SEGMENTOX); break;
}
}
105
void main(void) { FILE *fp; int i,j;110
long int xstart,ystart; //coordinate di partenza per la scrittura delle croci
fp=fopen("grafene-croce.wrt","w"); if (fp == NULL) {
printf("\a\nErrore nell'apertura del file\n\n");
115
exit(1); } fprintf(fp,"#WRITE18");
fprintf(fp,"\nDELTA 5.2e-9 4.2e-9"); fprintf(fp,"\nDOSE 1.9");
120
fprintf(fp,"\n\n"); fprintf(fp,"\nSTEP 5 5"); fprintf(fp,"\nTIME %g",TEMPO);125
fprintf(fp,"\n\n"); xstart=77000; ystart=62500; for(i=0;i<NUMERO_CROCI_X;i++) for(j=0;j<NUMERO_CROCI_Y;j++)130
{ disegna_croce(xstart+i*PASSOX,ystart+j*PASSOY,fp); if(i<10) disegna_numero(xstart+i*PASSOX-SEGMENTOX-200, ystart+j*PASSOY+200,i,fp); if(i>=10)135
disegna_numero(xstart+i*PASSOX+200, ystart+j*PASSOY+200,i-10,fp); if(j<10) disegna_numero(xstart+i*PASSOX-SEGMENTOX-200, ystart+j*PASSOY-SEGMENTOY*2-200,j,fp); if(j>=10)140
disegna_numero(xstart+i*PASSOX+200, ystart+j*PASSOY-SEGMENTOY*2-200,j-10,fp); } fprintf(fp,"\nSTEP 12 12");145
disegna_rettangolo_marker(38500,30000,41500,27000,fp); //coordinate X e Y: marker sx-basso disegna_rettangolo_marker(38500,232144,41500,229144,fp); //marker sx-alto
disegna_rettangolo_marker(223644,232144,226644,229144,fp); //marker dx-alto disegna_rettangolo_marker(223644,30000,226644,27000,fp); //marker dx-basso
150
fprintf(fp,"\n\nEND"); fclose(fp); }155
A.4.2 – contatti-grafene.c
# include <stdio.h> # include <stdlib.h>
# define TEMPO 12e-6 //Tdwell
5
/*I QUADRANTI SONO NUMERATI IN SENSO ANTIORARIO PARTENDO DA QUELLO IN BASSO A SINISTRA I PAD SONO NUMERATI IN SENSO ANTIORARIO PARTENDO DA QUELLO CENTRALE IN BASSO (DA 1 A 6) LE TRACK SONO NUMERATE IN SENSO ANTIORARIO PARTENDO DA QUELLA IN BASSO (DA 1 A 4)*/
# define X1_4 132072 //coordinata x di partenza pad 1 e 4
10
# define Y1 50300 //coordinata y di partenza pad 1
# define Y4 209844 //coordinata y di partenza pad 4
# define X2_3 209344 //coordinata x di partenza pad 2 e 3
# define Y2_6 94450 //coordinata y di partenza pad 2 e 6
# define Y3_5 165450 //coordinata y di partenza pad 3 e 5
15
# define X5_6 54800 //coordinata x di partenza pad 5 e 6
# define PASSOX 5800 //30 micron, distanza tra le croci lungo x # define PASSOY 7100 //30 micron, distanza tra le croci lungo y # define MEZZOQUADRATO 3000 //poco piu' di 15 micron
20
# define MEZZOQUADRATOY 17300 //90 micron # define MEZZOQUADRATOX 23000 //120 micron
# define SPESSORE 800 //poco piu' di 4 micron, spessore track
int disegna_track_pad_updown(long int centrox, long int centroy, FILE *fp)
25
{
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld", centrox-MEZZOQUADRATO, centroy-MEZZOQUADRATO, centrox-centroy-MEZZOQUADRATO, centroy+2*centroy-MEZZOQUADRATO, centrox+centroy-MEZZOQUADRATO, centroy+2*MEZZOQUADRATO, centrox+MEZZOQUADRATO, centroy-MEZZOQUADRATO);
}
30
int disegna_track_pad_laterali(long int centrox, long int centroy, FILE *fp) {
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld", centrox-MEZZOQUADRATO, centroy-MEZZOQUADRATO, centrox-centroy-MEZZOQUADRATO, centroy+centroy-MEZZOQUADRATO, centrox+2*centroy-MEZZOQUADRATO,
35
centroy+MEZZOQUADRATO,centrox+2*MEZZOQUADRATO, centroy-MEZZOQUADRATO); }
int disegna_pad_contatti_laterali(long int centrox, long int centroy, FILE *fp) {
40
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld", centrox-MEZZOQUADRATOY, centroy-MEZZOQUADRATOX, centrox-MEZZOQUADRATOY, centroy+centroy-MEZZOQUADRATOX, centrox+MEZZOQUADRATOY, centroy+MEZZOQUADRATOX,centrox+MEZZOQUADRATOY, centroy-MEZZOQUADRATOX); { if(centrox==28500) //pad n°5 e n°6
45
disegna_track_pad_laterali(centrox+MEZZOQUADRATOY+MEZZOQUADRATO,centroy,fp); if(centrox==235644) //pad n°2 e n°3 disegna_track_pad_laterali(centrox-MEZZOQUADRATOY-2*MEZZOQUADRATO,centroy,fp); }50
}int disegna_pad_contatti_updown(long int centrox, long int centroy, FILE *fp) {
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld",
centrox-MEZZOQUADRATOX-55
MEZZOQUADRATO, centroy-MEZZOQUADRATOY, centrox-MEZZOQUADRATOX-MEZZOQUADRATO,
centroy+MEZZOQUADRATOY, centrox+MEZZOQUADRATOX+MEZZOQUADRATO, centroy+MEZZOQUADRATOY, centrox+MEZZOQUADRATOX+MEZZOQUADRATO, centroy-MEZZOQUADRATOY); { if(centroy==233144) //pad n°4
60
disegna_track_pad_updown(centrox,centroy-MEZZOQUADRATOY-MEZZOQUADRATO,fp); if(centroy==27000) //pad n°1 disegna_track_pad_updown(centrox,centroy+MEZZOQUADRATOY,fp); }65
}
int disegna_track_orizzontale(long int x1, long int x2, long int y1, FILE *fp) {
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld", x1-SPESSORE/2, y1-SPESSORE/2,
70
x1-SPESSORE/2, y1+SPESSORE/2, x2+SPESSORE/2, y1+SPESSORE/2, x2+SPESSORE/2,y1-SPESSORE/2); }
int disegna_track_verticale(long int x1, long int y1, long int y2, FILE *fp) {
75
fprintf(fp,"\nBOUNDARY 4 %ld %ld %ld %ld %ld %ld %ld %ld", x1-SPESSORE/2, y1+SPESSORE/2, x1+SPESSORE/2, y1+SPESSORE/2, x1+SPESSORE/2, y2-SPESSORE/2, x1-SPESSORE/2, y2-SPESSORE/2); }
int main(void)
80
{
unsigned int x,y; //y=riga, x=colonna
long int xstart=77000; //coordinata x di inizio scrittura croci long int ystart=62500; //coordinata y di inizio scrittura croci
85
long int xp=0,yp=0;
FILE *fp;
fp=fopen("contatti-grafene.wrt","w");
90
if (fp == NULL) {
printf("\a\nErrore nell'apertura del file\n\n"); exit(1);
}
fprintf(fp,"#WRITE18");
95
fprintf(fp,"\nDELTA 5.2e-9 4.2e-9"); fprintf(fp,"\nDOSE 1.9"); fprintf(fp,"\n\n"); fprintf(fp,"\nSTEP 15 15");
100
fprintf(fp,"\nTIME %g",TEMPO); fprintf(fp,"\n\n");printf("\n\n**SELEZIONARE LA CROCE DI RIFERIMENTO PER I CONTATTI**\n\n");
105
printf("Inserire il numero della riga: "); scanf("%u", &y);
getchar();
while(y<0 || y>19) {
printf("\a\nERRORE: numero non esistente!\n");
110
printf("\nInserire un numero tra 0 e 19: "); scanf("%u", &y);
}
printf("Inserire il numero della colonna: "); scanf("%u", &x);
115
getchar();
while(x<0 || x>19) {
printf("\a\nERRORE: numero non esistente!\n"); printf("\nInserire un numero tra 0 e 19: "); scanf("%u", &x);
120
}
xp=xstart+x*PASSOX; //coordinata x della croce selezionata
yp=ystart+y*PASSOY; //coordinata y della croce selezionata
125
fprintf(fp,"\n\n#PAD NUMERO 1");
disegna_pad_contatti_updown(132072,27000,fp); //pad in basso (n°1) fprintf(fp,"\n\n#PAD NUMERO 2");
disegna_pad_contatti_laterali(235644,94450,fp); //primo pad a destra (n°2) fprintf(fp,"\n\n#PAD NUMERO 3");
130
disegna_pad_contatti_laterali(235644,165450,fp); //secondo pad a destra (n°3) fprintf(fp,"\n\n#PAD NUMERO 4");
disegna_pad_contatti_updown(132072,233144,fp); //pad in alto (n°4) fprintf(fp,"\n\n#PAD NUMERO 5");
disegna_pad_contatti_laterali(28500,165450,fp); //secondo pad a sinistra (n°5)
135
fprintf(fp,"\n\n#PAD NUMERO 6");
disegna_pad_contatti_laterali(28500,94450,fp); //primo pad a sinistra (n°6)
if(y<=10 && x<=10) //primo quadrante
{
fprintf(fp,"\n\n#TRACK NUMERO 1");
140
if(y>=3) {
disegna_track_verticale(X1_4, yp-7*PASSOY/2, Y1,fp); //pad n°1, track orizzontale piu' distante disegna_track_orizzontale(X1_4, xp+PASSOX/2, yp-7*PASSOY/2,fp);
disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, yp-7*PASSOY/2,fp);
145
} else {
disegna_track_verticale(X1_4, yp-3*PASSOY/2, Y1,fp); //pad n°1, track orizzontale piu' vicina alla croce
150
disegna_track_orizzontale(X1_4, xp+PASSOX/2, yp-3*PASSOY/2,fp); disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, yp-3*PASSOY/2,fp);
}
fprintf(fp,"\n\n#TRACK NUMERO 2");
155
disegna_track_orizzontale(xp+21*PASSOX/2, X2_3, Y2_6,fp); //pad n°2
disegna_track_verticale(xp+21*PASSOX/2, Y2_6, yp+PASSOY/2,fp);
disegna_track_orizzontale(xp+PASSOX, xp+21*PASSOX/2, yp+PASSOY/2,fp); fprintf(fp,"\n\n#TRACK NUMERO 3");
160
disegna_track_orizzontale(X5_6, xp-PASSOX/2, Y3_5,fp); //pad n°5
disegna_track_verticale(xp-PASSOX/2, Y3_5, yp+PASSOY,fp); fprintf(fp,"\n\n#TRACK NUMERO 4");
disegna_track_orizzontale(X5_6, xp-7*PASSOX/2, Y2_6,fp); //pad n°6
165
disegna_track_verticale(xp-7*PASSOX/2, Y2_6, yp-PASSOY/2,fp);
disegna_track_orizzontale(xp-7*PASSOX/2, xp-PASSOX, yp-PASSOY/2,fp); }
else if(y<=10 && x>10) //secondo quadrante
{
170
fprintf(fp,"\n\n#TRACK NUMERO 1"); if(y>=3)
{
disegna_track_verticale(X1_4, yp-7*PASSOY/2, Y1,fp); //pad n°1, track orizzontale piu' distante disegna_track_orizzontale(X1_4, xp+PASSOX/2, yp-7*PASSOY/2,fp);
175
disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, yp-7*PASSOY/2,fp);
} else {
disegna_track_verticale(X1_4, yp-3*PASSOY/2, Y1,fp); //pad n°1, track orizzontale piu' vicina
180
alla croce
disegna_track_orizzontale(X1_4, xp+PASSOX/2, yp-3*PASSOY/2,fp); disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, yp-3*PASSOY/2,fp);
}
185
fprintf(fp,"\n\n#TRACK NUMERO 2");
disegna_track_orizzontale(xp+7*PASSOX/2, X2_3, Y2_6,fp); //pad n°2
disegna_track_verticale(xp+7*PASSOX/2, Y2_6, yp+PASSOY/2,fp);
disegna_track_orizzontale(xp+PASSOX, xp+7*PASSOX/2, yp+PASSOY/2,fp);
190
fprintf(fp,"\n\n#TRACK NUMERO 3");
disegna_track_orizzontale(xp-PASSOX/2, X2_3, Y3_5,fp); //pad n°3
disegna_track_verticale(xp-PASSOX/2, Y3_5, yp+PASSOY,fp);
fprintf(fp,"\n\n#TRACK NUMERO 4");
195
disegna_track_orizzontale(X5_6, xp-21*PASSOX/2, Y2_6,fp); //pad n°6
disegna_track_verticale(xp-21*PASSOX/2, Y2_6, yp-PASSOY/2,fp); disegna_track_orizzontale(xp-21*PASSOX/2, xp-PASSOX, yp-PASSOY/2,fp); }
else if(y>10 && x>10) //terzo quadrante
200
{
fprintf(fp,"\n\n#TRACK NUMERO 1");
disegna_track_orizzontale(xp+PASSOX/2, X2_3, Y2_6,fp); //pad n°2
disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, Y2_6,fp);
205
fprintf(fp,"\n\n#TRACK NUMERO 2");
disegna_track_orizzontale(xp+7*PASSOX/2, X2_3, Y3_5,fp); //pad n°3
disegna_track_verticale(xp+7*PASSOX/2, Y3_5, yp+PASSOY/2,fp);
disegna_track_orizzontale(xp+PASSOX, xp+7*PASSOX/2, yp+PASSOY/2,fp);
210
fprintf(fp,"\n\n#TRACK NUMERO 3"); if(y<=16)
{
disegna_track_verticale(X1_4, Y4, yp+7*PASSOY/2,fp); //pad n°4, track orizzontale piu' distante disegna_track_orizzontale(X1_4, xp-PASSOX/2, yp+7*PASSOY/2,fp);
215
disegna_track_verticale(xp-PASSOX/2, yp+7*PASSOY/2, yp+PASSOY,fp); }
else {
disegna_track_verticale(X1_4, Y4, yp+3*PASSOY/2,fp); //pad n°4, track orizzontale piu' vicina
220
alla croce
disegna_track_orizzontale(X1_4, xp-PASSOX/2, yp+3*PASSOY/2,fp); disegna_track_verticale(xp-PASSOX/2, yp+3*PASSOY/2, yp+PASSOY,fp); }
225
fprintf(fp,"\n\n#TRACK NUMERO 4");
disegna_track_orizzontale(X5_6, xp-21*PASSOX/2, Y3_5,fp); //pad n°5
disegna_track_verticale(xp-21*PASSOX/2, Y3_5, yp-PASSOY/2,fp);
disegna_track_orizzontale(xp-21*PASSOX/2, xp-PASSOX, yp-PASSOY/2,fp); }
230
else if(y>10 && x<=10) //quarto quadrante
{
fprintf(fp,"\n\n#TRACK NUMERO 1");
disegna_track_orizzontale(X5_6, xp+PASSOX/2, Y2_6,fp); //pad n°6
disegna_track_verticale(xp+PASSOX/2, yp-PASSOY, Y2_6,fp);
235
fprintf(fp,"\n\n#TRACK NUMERO 2");
disegna_track_orizzontale(xp+21*PASSOX/2, X2_3, Y3_5,fp); //pad n°3
disegna_track_verticale(xp+21*PASSOX/2, Y3_5, yp+PASSOY/2,fp);
disegna_track_orizzontale(xp+PASSOX, xp+21*PASSOX/2, yp+PASSOY/2,fp);
240
fprintf(fp,"\n\n#TRACK NUMERO 3"); if(y<=16)
{
disegna_track_verticale(X1_4, Y4, yp+7*PASSOY/2,fp); //pad n°4, track orizzontale piu' distante
245
disegna_track_orizzontale(X1_4, xp-PASSOX/2, yp+7*PASSOY/2,fp); disegna_track_verticale(xp-PASSOX/2, yp+7*PASSOY/2, yp+PASSOY,fp); }
else {
250
disegna_track_verticale(X1_4, Y4, yp+3*PASSOY/2,fp); //pad n°4, track orizzontale piu' vicina alla croce
disegna_track_orizzontale(X1_4, xp-PASSOX/2, yp+3*PASSOY/2,fp); disegna_track_verticale(xp-PASSOX/2, yp+3*PASSOY/2, yp+PASSOY,fp); }
255
fprintf(fp,"\n\n#TRACK NUMERO 4");
disegna_track_orizzontale(X5_6, xp-7*PASSOX/2, Y3_5,fp); //pad n°5
disegna_track_verticale(xp-7*PASSOX/2, Y3_5, yp-PASSOY/2,fp);
disegna_track_orizzontale(xp-7*PASSOX/2, xp-PASSOX, yp-PASSOY/2,fp);
260
}
printf("\n**IL FILE contatti-grafene.wrt E' STATO CREATO**\n\n"); fprintf(fp,"\n\nEND");
fclose(fp);
265
A.4.3 – trackfinali.c
# include <stdio.h> # include <stdlib.h> # include <string.h> # include <math.h>5
# define TEMPO 12e-6 //Tdwell
# define N 30000 //dimensione buffer
# define PASSOX 5800 //30 micron, distanza tra le croci lungo x
10
# define PASSOY 7100 //30 micron, distanza tra le croci lungo y # define LSBX 0.005589
# define LSBY 0.004592
# define INTERO_MAX 262143 //massimo numero intero dell'area di scrittura: (2^18)-1 (angolo in alto a destra)
15
int disegna_track(long int startx, long int starty, long int endx, long int endy, FILE *fpw) {
fprintf(fpw,"\nLINE %ld %ld %ld %ld", startx, starty, endx, endy); }
20
int disegna_track_orizzontale(long int startx, long int endx, long int y, FILE *fpw) {
fprintf(fpw,"\nLINEX %ld %ld %ld", startx, endx, y); }
25
int disegna_track_verticale(long int starty, long int endy, long int x, FILE *fpw) {
fprintf(fpw,"\nLINEY %ld %ld %ld", starty, endy, x); }
30
int main(void) { char buf[N]; char *str;35
char nomefile[60];const char *layer= "layer-track-finali"; //mettere il nome del layer sul quale sono state disegnate le track finali (vedere qcad)
const char *iniziox= "10"; //identifica il punto iniziale lungo X della linea disegnata const char *inizioy= "20"; //identifica il punto iniziale lungo Y della linea disegnata
40
const char *finex= "11"; //identifica il punto finale lungo X della linea disegnata const char *finey= "21"; //identifica il punto finale lungo Y della linea disegnata
const char *numero_vertici= "93"; //identifica il numero di vertici del poligono disegnato con il cad float strx,stry,termx,termy;
long int int_strx, int_stry;
45
long int int_termx, int_termy; char nomelayer[40]="";
unsigned int x,y,n_vertici; //y=riga, x=colonna
long int xstart=77000; //coordinata x di inizio scrittura croci long int ystart=62500; //coordinata y di inizio scrittura croci
50
long int xp=0,yp=0,n=1;
printf("\n\n**INSERIRE IL NOME DEL FILE DI QCAD (RICORDARSI .dxf): "); scanf("%s", nomefile);
55
printf("\n\n**SELEZIONARE LA CROCE DI RIFERIMENTO PER I CONTATTI**\n\n"); printf("Inserire il numero della riga: ");
scanf("%u", &y);
while(y<0 || y>19) {
60
printf("\a\nERRORE: numero non esistente!\n"); printf("\nInserire un numero tra 0 e 19: "); scanf("%u", &y);
}
printf("Inserire il numero della colonna: ");
65
while(x<0 || x>19) {
printf("\a\nERRORE: numero non esistente!\n"); printf("\nInserire un numero tra 0 e 19: "); scanf("%u", &x);
70
}
xp=xstart+x*PASSOX; //coordinata x della croce selezionata
yp=ystart+y*PASSOY; //coordinata y della croce selezionata
75
FILE *fpw,*fpr; fpw = fopen("track-finali.wrt", "w"); if (fpw == NULL) {printf("\a\nErrore nell'apertura del file\n\n");
80
exit(1); } fprintf(fpw,"#WRITE18");
fprintf(fpw,"\nDELTA 5.2e-9 4.2e-9"); fprintf(fpw,"\nDOSE 1.9");
85
fprintf(fpw,"\n\n"); fprintf(fpw,"\nSTEP 15 15"); fprintf(fpw,"\nTIME %g",TEMPO);90
fprintf(fpw,"\n\n"); fpr = fopen(nomefile, "r"); if (fpr == NULL) {printf("\a\nErrore nell'apertura del file\n\n");
95
exit(1); } str=fgets(buf, N, fpr);100
while(str!="EOF") { do { str=fgets(buf, N, fpr);105
sscanf(str,"%s",buf); }while((strcmp(buf,"HATCH")!=0) && (strcmp(buf,"LINE")!=0) && (strcmp(str,"EOF")!=0)); //prima selezione nel file .dxf tramite l'identificatore "LINE" e "HATCH"(riguarda la SECTION)
if(strcmp(str,"EOF")==0)
110
break; else if (strcmp(buf,"HATCH")==0) { do {115
str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }while((strcmp(buf,"8")!=0) && (str!="EOF")); //seconda selezione nel file .dxf tramite l'identificatore "8" (nome del layer)
120
if(str=="EOF") break; if(strcmp(buf,"8")==0) fscanf(fpr,"%s",nomelayer);125
if(strcmp(nomelayer,layer)==0) //siamo arrivati alla riga di interesse nel file .dxf { strcpy(nomelayer," "); do
130
{ str=fgets(buf, N, fpr); sscanf(str,"%s",buf);}
while((strcmp(buf,numero_vertici)!=0) && (str!="EOF"));
135
if(str=="EOF") break;
if(strcmp(buf,"93")==0) //si prende il numero dei vertici del poligono fscanf(fpr,"%u",&n_vertici);
140
printf("\n\nNUMERO VERTICI POLIGONO %u ",n_vertici); fprintf(fpw,"\nBOUNDARY %u",n_vertici); for(n=1;n<=n_vertici;n++) { do
145
{ str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }while((strcmp(buf,iniziox)!=0) && (str!="EOF")); //inizio lungo X della linea del poligono
150
if(str=="EOF") break; fscanf(fpr,"%g",&strx); printf("\nSTARTX %g ",strx);155
int_strx=(int)floor(strx/LSBX); if(int_strx>=INTERO_MAX) {printf("\n PATTERN TROPPO GROSSO, O lsbx TROPPO PICCOLO\n\n"); exit(0);
160
} do { str=fgets(buf, N, fpr);165
sscanf(str,"%s",buf); }while((strcmp(buf,inizioy)!=0) && (str!="EOF")); //inizio lungo Y della linea del poligono if(str=="EOF")
170
break; fscanf(fpr,"%g",&stry); printf("STARTY %g \n",stry); int_stry=(int)floor(stry/LSBY); if(int_stry>=INTERO_MAX)175
{printf("\n PATTERN TROPPO GROSSO, O lsby TROPPO PICCOLO\n\n"); exit(0); }
180
fprintf(fpw," %ld %ld",int_strx+xp,int_stry+yp);} // END FOR VERTICI
fprintf(fpw,"\n\n");
185
} // END IF LAYER } // END IF "HATCH" else if(strcmp(buf,"LINE")==0) {190
do { str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }195
while((strcmp(buf,"8")!=0) && (str!="EOF")); //seconda selezione nel file .dxf tramite l'identificatore "8" (nome del layer)
if(str=="EOF") break;
if(strcmp(buf,"8")==0)
fscanf(fpr,"%s",nomelayer);
if(strcmp(nomelayer,layer)==0) //siamo arrivati alla riga di interesse nel file .dxf { strcpy(nomelayer," "); do
205
{ str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }while((strcmp(buf,iniziox)!=0) && (str!="EOF")); //inizio lungo X della linea
210
if(str=="EOF") break; fscanf(fpr,"%g",&strx); printf("\nSTARTX %g ",strx);215
int_strx=(int)floor(strx/LSBX); if(int_strx>=INTERO_MAX) {printf("\n PATTERN TROPPO GROSSO, O lsbx TROPPO PICCOLO\n\n"); exit(0);
220
} do { str=fgets(buf, N, fpr);225
sscanf(str,"%s",buf); }while((strcmp(buf,inizioy)!=0) && (str!="EOF")); //inizio lungo Y della linea if(str=="EOF")
230
break; fscanf(fpr,"%g",&stry); printf("STARTY %g ",stry); int_stry=(int)floor(stry/LSBY); if(int_stry>=INTERO_MAX)235
{printf("\n PATTERN TROPPO GROSSO, O lsby TROPPO PICCOLO\n\n"); exit(0); }
240
do { str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }245
while(strcmp(buf,finex) !=0 && str!="EOF"); //termine lungo X della linea if(str=="EOF") break; fscanf(fpr,"%g",&termx);
250
printf("\nFINEX %g ",termx); int_termx=(int)floor(termx/LSBX); if(int_termx>=INTERO_MAX) {printf("\n PATTERN TROPPO GROSSO, O lsbx TROPPO PICCOLO\n\n");
255
exit(0); } do {260
str=fgets(buf, N, fpr); sscanf(str,"%s",buf); }while(strcmp(buf,finey) !=0 && str!="EOF"); //termine lungo Y della linea if(str=="EOF")
265
break; fscanf(fpr,"%g",&termy);
printf(" FINEY %g \n",termy); int_termy=(int)floor(termy/LSBY); if(int_termy>=INTERO_MAX)
270
{
printf("\n PATTERN TROPPO GROSSO, O lsby TROPPO PICCOLO\n\n"); exit(0);
}
275
if((strx==termx)&&(stry==termy))
printf("\n**ERRORE DI DISEGNO: PUNTO SINGOLO ANZICHE' LINEA**\n\n");
else if(strx==termx)
disegna_track_verticale(yp+int_stry, yp+int_termy, xp+int_strx, fpw);
280
else if(stry==termy)
disegna_track_orizzontale(xp+int_strx, xp+int_termx, yp+int_stry, fpw);
else if((strx!=termx)&&(stry!=termy))
285
disegna_track(xp+int_strx, yp+int_stry, xp+int_termx, yp+int_termy, fpw);
} // END IF LAYER
} // END IF "LINE"
290
} // END WHILE EOF
printf("\n**IL FILE track-finali.wrt E' STATO CREATO**\n\n");