Script Example Analysis
Per fornire un ulteriore approfondimento sugli aspetti generali del sistema di scripting e sull’uso dei modelli a oggetti Delphi e X2 negli script, vengono qui esaminati due progetti di esempio dal punto di vista funzionale: un copier del contorno della scheda e uno script per la generazione della netlist.
Gli script Board Outline Copier e Netlister sono sviluppati utilizzando i modelli a oggetti X2 per illustrare le capacità del sistema di scripting in Altium Designer. Si tratta di script esistenti disponibili nella raccolta di script di esempio, come segue:
-
Lo script Board Outline Copier utilizza il modello a oggetti PCB per copiare il contorno esistente della scheda PCB come tracce e archi su un layer specificato.
Vedere\Scripts\VB Scripts\CopyBoardOutlinePRJ.PRJSCR. -
Lo script Netlist generator utilizza il modello a oggetti WorkSpace Manager per generare una netlist nel tradizionale formato Protel (v1 e v2).
Vedere\Scripts\Delphiscript Scripts\WSM\Protel Netlister\ScripterProtelNetlist.PRJSCR.
Progetto Board Outline Copier
L’obiettivo di Board Outline Copier è copiare un contorno di scheda esistente dal documento PCB a un layer diverso nello stesso documento.
Il progetto utilizza una Script Form in modo che l’utente possa interagire con una finestra di dialogo per specificare la larghezza del contorno della scheda e selezionare il layer di destinazione da un menu a discesa. Utilizzando il modello a oggetti PCB e le relative interfacce PCB dalla PCB API, gli oggetti del contorno della scheda vengono estratti e copiati sul layer specificato.
► Esempio di funzionamento dello script
Le parti principali dello script sono:
-
Una variabile globale
PCB_Board(di tipoIPCB_Board). -
Una subroutine
CopyBoardOutlineche accetta i parametriAWidtheALayer. -
Il gestore eventi
bOkClick, che ottiene i valori di larghezza e layer dalla script form e quindi esegue la subroutineCopyBoardOutline. -
Il gestore eventi
bCancelClick, che chiude la script form (finestra di dialogo) di Board Outline.
Funzionalità dello script
Lo script utilizza una script Form che richiede gestori eventi per acquisire i clic del mouse sui singoli controlli, come i pulsanti OK e Cancel.
Il gestore eventi del pulsante OK è essenzialmente il seguente:
Sub bOKClick(Sender) Dim Width Dim Layer Call StringToCoordUnit(eWidth.Text,Width,PCB_Board.DisplayUnit) Layer = String2Layer(cbLayers.Items(cbLayers.ItemIndex)) End Sub
Qui, il gestore eventi del mouse OnClick del form (bOKClick) utilizza la funzione StringToCoordUnit per ottenere la larghezza del contorno inserita (la stringa eWidth dalla casella TEdit) in valori di coordinate interne. Questa funzione applica le unità correnti della scheda (proprietà PCB_Board.DisplayUnit) alla variabile Width.
Analogamente, la stringa del layer selezionato (l’elemento cbLayers dalla TComboBox del form) viene passata alla funzione String2Layer per ottenere un valore enumerato per la variabile Layer. Si noti che in questo progetto la TComboBox del form è precompilata con un elenco indicizzato di stringhe di layer (cbLayers.Items) – vedere il file CopyBoardOutlineForm.dfm del Form per l’elenco dei layer.
Il passaggio finale nel gestore eventi (bOKClick) richiama la subroutine CopyBoardOutline con le variabili Width e Layer come parametri passati. Il gestore del pulsante Cancel del form (bCancelClick) si limita a chiudere il form.
Interfaccia IPCB_Board
All’interno del gestore del pulsante OK (bOKClick), la scheda corrente viene ottenuta dall’interfaccia IPCB_Board tramite il valore IPCB_ServerInterface restituito dalla speciale funzione PCBServer. Qui, la funzione GetCurrentPCB imposta il riferimento alla scheda corrente nella variabile PCB_Board.
Il contorno della scheda corrente (IPC_BoardOutline) viene quindi ottenuto in tutto lo script dalla proprietà BoardOutline dell’interfaccia IPCB_Board, utilizzando il riferimento alla scheda PCB_Board sopra indicato.
Il contorno della scheda deve essere inizializzato prima di procedere con la copia e la creazione di un nuovo contorno. Un contorno, rappresentato dall’interfaccia IPCB_BoardOutline, può essere inizializzato utilizzando i metodi di ricostruzione/validazione dell’interfaccia.
PCB_Board.BoardOutline.Invalidate PCB_Board.BoardOutline.Rebuild PCB_Board.BoardOutline.Validate
Segmenti di arco e traccia del contorno
L’interfaccia IPCB_BoardOutline, che rappresenta il contorno della scheda, eredita dall’interfaccia IPCB_Group. Un’interfaccia IPCB_Group rappresenta un oggetto gruppo che può memorizzare oggetti figli. Un esempio di interfaccia IPCB_Group è un poligono o un contorno di scheda, poiché questi possono memorizzare archi e tracce come oggetti figli.
Un oggetto contorno di scheda memorizza due diversi tipi di segmenti – ePolySegmentLine e ePolySegmentArc, che rappresentano rispettivamente un oggetto traccia o arco. Il numero di segmenti è determinato dalla proprietà PointCount dell’interfaccia IPCB_BoardOutline, che estrae ciascun vertice del contorno nella variabile I per il ciclo For-To-Next.
Ciascun segmento del contorno della scheda ottenuto viene controllato per verificare la presenza di tracce e archi con l’istruzione If PCB_Board.BoardOutline.Segments(I).Kind = ePolySegmentLine Then. Se non è un segmento di traccia (ePolySegmentLine), la parte Else dell’istruzione presume che il segmento sia un arco.
Per ogni segmento trovato e in base al tipo di segmento, viene creato un nuovo oggetto traccia o arco utilizzando la funzione PCBObjectFactory.
Funzione PCBObjectFactory
La creazione dei nuovi oggetti PCB impiega direttamente la funzione PCBObjectFactory dall’interfaccia IPCB_ServerInterface.
'Create new Track object PCBServer.PCBObjectFactory(eTrackObject, eNoDimension, eCreate_Default) 'Create new Arc object PCBServer.PCBObjectFactory(eArcObject, eNoDimension, eCreate_Default)
I parametri della funzione PCBObjectFactory impostano il tipo di oggetto (Track, Arc, Via ecc.), il tipo di dimensione (Linear, Radial ecc.) e la modalità di creazione dell’oggetto (su un valore predefinito locale o sulle preferenze globali).
Dopo che ogni oggetto traccia o arco è stato creato dalla procedura PCBObjectFactory, le sue proprietà vengono istanziate dalle istruzioni track/arc che seguono.
Le proprietà di Track e Arc sono rappresentate dalle rispettive interfacce, IPCB_Track e IPCB_Arc, in cui le proprietà pertinenti sono implementate dallo script. Ad esempio, le coordinate della nuova traccia vengono ottenute dai vertici del segmento del contorno sorgente, dove Track.X1 e Track.Y1 rappresentano le coordinate iniziali della traccia e le proprietà X2 e Y2 sono le sue coordinate finali.
Track.X1 = PCB_Board.BoardOutline.Segments(I).vx Track.Y1 = PCB_Board.BoardOutline.Segments(I).vy Track.X2 = PCB_Board.BoardOutline.Segments(J).vx Track.Y2 = PCB_Board.BoardOutline.Segments(J).vy Track.Layer = ALayer Track.Width = AWidth
Come si può vedere anche nel frammento di codice sopra, le proprietà Layer e Width della traccia sono semplicemente definite dai valori passati estratti dalla finestra di dialogo dell’interfaccia utente, ovvero le variabili cbLayers e eWidth del Form.
Una volta completamente definiti, i nuovi oggetti vengono aggiunti a un layer specificato del documento PCB con l’istruzione PCB_Board.AddPCBObject(NewObject), dove NewObject qui è Track o Arc.
PreProcess e PostProcess
Quando si crea un oggetto PCB, è necessario richiamare prima il metodo PreProcess dall’interfaccia oggetto IPCB_ServerInterface per predisporre il server PCB. Dopo la creazione dell’oggetto, viene applicato il metodo PostPocess (anch’esso dall’interfaccia IPCB_ServerInterface) per informare il server che le aggiunte di oggetti sono state completate.
I metodi PreProcess e PostProcess mantengono aggiornati e sincronizzati il sistema Undo e gli altri sottosistemi dell’editor PCB. Di seguito è riportato un frammento di codice rappresentativo con le istruzioni PreProcess e PostProcess.
PCBServer.PreProcess 'Create PCB objects PCBServer.PostProcess
Quando gli oggetti vengono aggiunti a un layer selezionato che non è stato visualizzato nel documento PCB, è necessario forzare la visibilità del layer. Questo viene gestito dall’istruzione PCB_Board.LayerIsDisplayed(ALayer) = True, dove ALayer è il layer selezionato dall’utente.
Aggiornamento del documento
Infine, il documento PCB con il suo nuovo contorno della scheda viene aggiornato tramite il comando PCB:Zoom e i relativi parametri Action = Redraw. I parametri del comando di zoom vengono applicati utilizzando la procedura AddStringParameter dopo che il buffer dei parametri è stato prima cancellato con il metodo ResetParameters.
Progetto Netlister
Lo scopo di questo progetto di script Netlister è generare una netlist Protel standard, in formato Version 1 oppure Version 2, per un progetto Altium Designer contenente schemi. Una netlist flat di un progetto schematico è suddivisa in due sezioni:
- I designatori dei componenti e le informazioni associate a ciascun componente,
- I nomi delle net e le informazioni associate a ciascun nome di net, insieme alle connessioni dei pin (pin di un componente).
► Esempio di funzionamento dello script
Il modello a oggetti WorkSpace Manager dell'API fornisce interfacce che rappresentano il progetto e i suoi elementi costitutivi: i documenti, i componenti e i relativi pin, e le net. Il WorkSpace Manager è un server di sistema strettamente integrato con il modulo Client che gestisce i progetti e i documenti associati. Fornisce compilazione, supporto per progetti multi-sheet, strumenti di navigazione della connettività, supporto multi-canale, documenti di implementazione multipli e così via. Per recuperare l'interfaccia del WorkSpace Manager, richiamare la funzione GetWorkspace, che restituisce l'interfaccia IWorkspace.
Per lo script Netlister, le interfacce di interesse sono IWorkSpace, IProject, IDocument, IComponent e INet.
Si noti che alcune delle interfacce, in particolare quelle degli oggetti di progettazione, corrispondono a interfacce equivalenti degli oggetti schematici. Questo perché i documenti logici in un progetto sono documenti schematici con informazioni di connettività. In effetti, il modello a oggetti schematici può essere usato al posto del WorkSpace Manager, ma quest'ultimo fornisce la funzionalità per compilare un progetto ed estrarre documenti da un progetto, oltre a recuperare dati dagli oggetti schematici.
Le parti principali dello script Netlister sono:
-
Una variabile stringa globale
TargetFileName, che è il nome file della netlist. -
Un oggetto collection globale Netlist
TStringList, che viene popolato con i dati della netlist. -
Le procedure
WriteComponent_Version1eWriteComponent_Version2. -
Le procedure
WriteNet_Version1eWriteNet_Version2. -
Una funzione
ConvertElectricToStringche converte la proprietà elettrica di un pin in una stringa -
La procedura
GenerateNetlist, che gestisce la generazione dei dati e le attività di gestione di nome file, percorso e directory.
Funzionalità dello script
Le due procedure senza parametri, GenerateProtelV1FormatNetlist e GenerateProtelV2FormatNetlist, appariranno nella finestra di dialogo Select Item to Run dialog, offrendo la scelta di generare una netlist in formato Protel V1 oppure in formato Protel V2. Queste procedure chiamano la procedura GenerateNetlist passando come parametro la scelta del formato della netlist (0 oppure 1).
Procedure GenerateProtelV1FormatNetlist; Var Version : Integer; Begin // Formato netlist Protel 1, passa 0 GenerateNetlist(0); End; Procedure GenerateProtelV2FormatNetlist; Var Version : Integer; Begin // Formato netlist Protel 2, passa 1 GenerateNetlist(1); End;
GenerateNetList
La procedura GenerateNetList recupera l'interfaccia workspace in modo da poter poi estrarre l'interfaccia di progetto per il progetto corrente (IWorkspace.DM_FocusedProject).
Il progetto deve essere compilato prima che le net possano essere estratte, poiché il processo di compilazione costruisce le informazioni di connettività del progetto. Viene applicato il metodo DM_Compile dell'interfaccia di progetto (IProject.DM_Compile), come mostrato nel frammento di codice seguente. Si noti che le versioni recenti di Altium Designer compilano automaticamente i progetti, quindi questo passaggio è facoltativo.
WS := GetWorkspace; If WS = Nil Then Exit; Prj := WS.DM_FocusedProject; If Prj = Nil Then Exit; // Compila il progetto per recuperare le informazioni di connettività del progetto. Prj.DM_Compile;
Le informazioni su componenti e net vengono memorizzate nell'oggetto Netlist di tipo TStringList, che viene usato successivamente per generare un file di testo della netlist formattato. L'oggetto TStringList è una classe Delphi disponibile per l'uso negli script.
La procedura Generate viene quindi chiamata con parametri passati che definiscono il percorso e il nome file del progetto corrente, oltre alla versione del formato della netlist.
Generate
La procedura Generate ottiene il percorso del progetto come percorso di output di destinazione per il file netlist generato (dal parametro passato DocumentPath), determina il nome file della netlist (TargetFileName) e verifica lo stato flattened del progetto (IProject.DM_DocumentFlattened).
Per tutti i documenti schematici di un progetto, ciascun documento viene quindi controllato per net e componenti con le procedure WriteNets e WriteComponents, e infine estratto nell'oggetto Netlist.
Scrittura di net e componenti
Una netlist è composta da sezioni componenti e net, quindi sono necessarie due procedure per scrivere separatamente i dati dei componenti e quelli delle net.
Solo le net con più di due nodi verranno scritte in una netlist, mentre quelle con meno verranno scartate. Per ogni net, il nome della net si basa sul metodo DM_CalculatedNetName della Net, che estrae i nomi delle net dalle informazioni di connettività del progetto compilato.
Di seguito sono mostrati due frammenti di codice per le sezioni Components e Nets di una netlist nel formato netlist Version 1. Si noti che i dati di componenti e net sono memorizzati nell'oggetto NetList, che è di tipo TStringList. La netlist generata è composta da due sezioni: la sezione delle informazioni sui componenti e la sezione delle informazioni sulle net.
Sezione Components
Nella procedura WriteComponent, per ogni componente trovato nel progetto viene verificato se si tratta di un componente effettivo, quindi vengono estratti i valori di designatore fisico, footprint e tipo di parte. Questi vengono aggiunti al contenitore oggetto Netlist (NetList.Add) per costruire la netlist stessa.
If Component <> Nil Then
Begin
NetList.Add('[');
NetList.Add(Component.DM_PhysicalDesignator);
NetList.Add(Component.DM_FootPrint);
NetList.Add(Component.DM_PartType);
NetList.Add('');
NetList.Add('');
NetList.Add('');
NetList.Add(']');
End;
Sezione Nets
Per la procedura Nets, il NetName e i Designator vengono estratti se una net ha due o più pin (INet.DM_PinCount). Le informazioni su net e pin, insieme ai caratteri di formattazione, vengono aggiunte al contenitore Netlist per costruire la netlist. Il frammento seguente è la procedura di scrittura delle net per la netlist versione 1.
If Net.DM_PinCount >= 2 Then
Begin
NetList.Add('(');
NetList.Add(Net.DM_CalculatedNetName);
For i := 0 To Net.DM_PinCount – 1 Do
Begin
Pin := Net.DM_Pins(i);
PinDsgn := Pin.DM_PhysicalPartDesignator;
PinNo := Pin.DM_PinNumber;
NetList.Add(PinDsgn + '-' + PinNo);
End;
NetList.Add(')');
End;
Si noti che il formato netlist più verboso, Protel v2, include le proprietà elettriche per i pin delle net (In, Out, Passive, HiZ ecc.).
La procedura di scrittura delle net per il formato versione 2 (WriteNet_Version2) interroga quindi la proprietà elettrica di ciascun pin della net (INet.DM_Electical), che viene poi convertita dalla procedura chiamata ConvertElectricToString – essenzialmente una tabella di ricerca per la conversione in stringa. Questi valori vengono quindi aggiunti a una variabile stringa locale (ElectricalString), che a sua volta viene aggiunta all'oggetto contenitore Netlist.
Creazione del file netlist
Infine, con l'oggetto contenitore Netlist completamente popolato con le informazioni su componenti e net del progetto, nel formato scelto, la procedura Generate scrive i dati Netlist in un file (TStringList.SaveToFile). Il percorso e il nome del file sono definiti dalla variabile stringa TargetFileName, come determinato nella procedura Generate.