Phân tích Ví dụ Script
Để cung cấp thêm cái nhìn sâu hơn về các khía cạnh tổng quát của Hệ thống Scripting, cũng như việc sử dụng các Mô hình Đối tượng Delphi và X2 trong script, tại đây sẽ xem xét hai dự án ví dụ dưới góc độ chức năng – một script sao chép đường bao bo mạch và một script tạo netlist.
Các script Board Outline Copier và Netlister được phát triển bằng các Mô hình Đối tượng X2 để minh họa khả năng của hệ thống scripting trong Altium Designer. Đây là các script có sẵn trong bộ sưu tập script ví dụ như sau:
-
Script Board Outline Copier sử dụng PCB Object Model để sao chép đường bao PCB hiện có dưới dạng các track và arc lên một layer được chỉ định.
Xem\Scripts\VB Scripts\CopyBoardOutlinePRJ.PRJSCR. -
Script Netlist generator sử dụng WorkSpace Manager Object Model để tạo netlist theo định dạng Protel truyền thống (v1 và v2).
Xem\Scripts\Delphiscript Scripts\WSM\Protel Netlister\ScripterProtelNetlist.PRJSCR.
Dự án Board Outline Copier
Mục tiêu của Board Outline Copier là sao chép một đường bao bo mạch hiện có từ tài liệu PCB sang một layer khác trong cùng tài liệu đó.
Dự án sử dụng một Script Form để người dùng có thể tương tác với hộp thoại nhằm chỉ định độ rộng của đường bao bo mạch và chọn layer đích từ menu thả xuống. Bằng cách sử dụng PCB Object model và các giao diện PCB của nó từ PCB API, các đối tượng của đường bao bo mạch được trích xuất và sao chép lên layer được chỉ định.
Các dự án VBScript hiện được xem là dạng legacy. Để bật khả năng tạo dự án VBScript mới, hãy chọn tùy chọn Legacy.Scripts.SupportOldLanguages trong hộp thoại Advanced Settings.
Tài liệu về scripting API có thể được tìm thấy tại đây: Scripting API Objects. Xin lưu ý rằng tài liệu này được cập nhật lần cuối cho một phiên bản Altium Designer cũ hơn. Mặc dù nhiều nguyên lý và cách tiếp cận vẫn giữ nguyên, bạn cần lưu ý rằng các interface, object, method, property, và những thành phần tương tự đã thay đổi kể từ đó, và sẽ không phản ánh đầy đủ những gì có trong các phiên bản phần mềm mới hơn.
Các phần chính của script là:
-
Một biến toàn cục
PCB_Board(kiểuIPCB_Board). -
Một chương trình con
CopyBoardOutlinenhận các tham sốAWidthvàALayer. -
Trình xử lý sự kiện
bOkClick, lấy các giá trị độ rộng và layer từ script form rồi thực thi chương trình conCopyBoardOutline. -
Trình xử lý sự kiện
bCancelClick, đóng form script Board Outline (hộp thoại).
Chức năng của script
Script sử dụng một Form script cần có các trình xử lý sự kiện để bắt các lần nhấp chuột lên từng điều khiển như các nút OK và Cancel.
Trình xử lý sự kiện của nút OK về cơ bản như sau:
Sub bOKClick(Sender) Dim Width Dim Layer Call StringToCoordUnit(eWidth.Text,Width,PCB_Board.DisplayUnit) Layer = String2Layer(cbLayers.Items(cbLayers.ItemIndex)) End Sub
Tại đây, trình xử lý sự kiện chuột OnClick của form (bOKClick) sử dụng hàm StringToCoordUnit để lấy độ rộng đường bao đã nhập (chuỗi eWidth từ ô TEdit) theo các giá trị tọa độ nội bộ. Hàm này áp dụng đơn vị bo mạch hiện tại (thuộc tính PCB_Board.DisplayUnit) cho biến Width.
Tương tự, chuỗi layer đã chọn (mục cbLayers từ TComboBox của form) được truyền vào hàm String2Layer để lấy giá trị liệt kê cho biến Layer. Lưu ý rằng trong dự án này, TComboBox của form được nạp sẵn danh sách chuỗi layer có đánh chỉ mục (cbLayers.Items) – xem tệp CopyBoardOutlineForm.dfm của Form để biết danh sách layer.
Bước cuối cùng trong trình xử lý sự kiện (bOKClick) gọi chương trình con CopyBoardOutline với các biến Width và Layer được truyền làm tham số. Trình xử lý cho nút Cancel của form (bCancelClick) chỉ đơn giản là đóng form.
Giao diện IPCB_Board
Trong trình xử lý nút OK (bOKClick), bo mạch hiện tại được lấy từ giao diện IPCB_Board thông qua IPCB_ServerInterface được trả về bởi hàm đặc biệt PCBServer. Tại đây, hàm GetCurrentPCB đặt tham chiếu bo mạch hiện tại cho biến PCB_Board.
Sau đó, đường bao bo mạch hiện tại (IPC_BoardOutline) được lấy xuyên suốt script từ thuộc tính IPCB_Board của giao diện BoardOutline, sử dụng tham chiếu bo mạch PCB_Board ở trên.
Đường bao bo mạch cần được khởi tạo trước khi tiếp tục sao chép và tạo đường bao mới. Một outline – được biểu diễn bởi giao diện IPCB_BoardOutline – có thể được khởi tạo bằng các phương thức rebuild/validate của giao diện đó.
PCB_Board.BoardOutline.Invalidate PCB_Board.BoardOutline.Rebuild PCB_Board.BoardOutline.Validate
Các đoạn Arc và Track của outline
Giao diện IPCB_BoardOutline, đại diện cho đường bao bo mạch, được kế thừa từ giao diện IPCB_Group. Giao diện IPCB_Group biểu diễn một group object có thể lưu các child object. Ví dụ về giao diện IPCB_Group là polygon hoặc board outline, vì chúng có thể lưu arc và track làm child object.
Một đối tượng board outline lưu hai loại segment khác nhau – ePolySegmentLine và ePolySegmentArc, lần lượt biểu diễn đối tượng track hoặc arc. Số lượng segment được xác định bởi thuộc tính PointCount từ giao diện IPCB_BoardOutline, thuộc tính này trích xuất từng đỉnh của outline vào biến I cho vòng lặp For-To-Next.
Mỗi segment của đường bao bo mạch thu được sẽ được kiểm tra xem là track hay arc bằng câu lệnh If PCB_Board.BoardOutline.Segments(I).Kind = ePolySegmentLine Then. Nếu không phải segment dạng track (ePolySegmentLine) thì phần Else của câu lệnh sẽ giả định segment đó là arc.
Đối với mỗi segment được tìm thấy, và tùy theo loại segment, một đối tượng track hoặc arc mới được tạo bằng hàm PCBObjectFactory.
Hàm PCBObjectFactory
Việc tạo các đối tượng PCB mới sử dụng trực tiếp hàm PCBObjectFactory từ giao diện IPCB_ServerInterface.
'Create new Track object PCBServer.PCBObjectFactory(eTrackObject, eNoDimension, eCreate_Default) 'Create new Arc object PCBServer.PCBObjectFactory(eArcObject, eNoDimension, eCreate_Default)
Các tham số của hàm PCBObjectFactory thiết lập loại đối tượng (Track, Arc, Via, v.v.), kiểu kích thước (Linear, Radial, v.v.) và chế độ tạo đối tượng (theo mặc định cục bộ hoặc tùy chọn toàn cục).
Sau khi mỗi đối tượng track hoặc arc được tạo bởi procedure PCBObjectFactory, các thuộc tính của nó được khởi tạo bởi các câu lệnh track/arc tiếp theo.
Các thuộc tính của Track và Arc được biểu diễn bởi các giao diện tương ứng của chúng, IPCB_Track và IPCB_Arc, trong đó script triển khai các thuộc tính liên quan. Ví dụ, tọa độ track mới được lấy từ các đỉnh segment của outline nguồn, trong đó Track.X1 và Track.Y1 biểu diễn tọa độ đầu của track, còn các thuộc tính X2 và Y2 là tọa độ cuối của nó.
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
Như cũng có thể thấy trong đoạn mã ở trên, các thuộc tính Layer và Width của track được xác định đơn giản bằng các giá trị truyền vào được trích xuất từ hộp thoại giao diện người dùng – các biến cbLayers và eWidth của Form.
Khi đã được định nghĩa đầy đủ, các đối tượng mới sẽ được thêm vào một layer được chỉ định của tài liệu PCB bằng câu lệnh PCB_Board.AddPCBObject(NewObject), trong đó NewObject ở đây là Track hoặc Arc.
PreProcess và PostProcess
Khi tạo một đối tượng PCB, trước tiên cần gọi phương thức PreProcess từ giao diện đối tượng IPCB_ServerInterface để chuẩn bị PCB server. Sau khi tạo đối tượng xong, áp dụng phương thức PostPocess (cũng từ giao diện IPCB_ServerInterface) để thông báo cho server rằng việc thêm đối tượng đã hoàn tất.
Các phương thức PreProcess và PostProcess giúp hệ thống Undo và các hệ thống con khác của PCB editor luôn được cập nhật và đồng bộ. Bên dưới là một đoạn mã tiêu biểu có các câu lệnh PreProcess và PostProcess.
PCBServer.PreProcess 'Create PCB objects PCBServer.PostProcess
Khi các đối tượng được thêm vào một layer được chỉ định nhưng layer đó chưa được hiển thị trong tài liệu PCB, cần buộc layer đó hiển thị. Việc này được xử lý bởi câu lệnh PCB_Board.LayerIsDisplayed(ALayer) = True, trong đó ALayer là layer do người dùng chọn.
Làm mới tài liệu
Cuối cùng, tài liệu PCB cùng với đường bao bo mạch mới được làm mới bằng lệnh PCB:Zoom và các tham số Action = Redraw đi kèm. Các tham số của lệnh zoom được áp dụng bằng procedure AddStringParameter sau khi bộ đệm tham số được xóa trước bằng phương thức ResetParameters.
Dự án Netlister
Mục tiêu của dự án script Netlister này là tạo ra một netlist Protel tiêu chuẩn (ở định dạng Version 1 hoặc Version 2) cho một dự án Altium Designer có chứa sơ đồ nguyên lý. Một netlist phẳng của dự án schematic được tách thành hai phần:
- Ký hiệu linh kiện và thông tin liên quan đến từng linh kiện,
- Tên net và thông tin liên quan đến từng tên net, cùng với các kết nối chân (các chân của linh kiện).
Mô hình đối tượng WorkSpace Manager của API cung cấp các giao diện đại diện cho dự án và các thành phần cấu thành của nó – tài liệu, linh kiện và các chân của chúng, cùng các net. WorkSpace Manager là một system server được tích hợp chặt chẽ với module Client để xử lý dự án và các tài liệu liên quan. Nó cung cấp khả năng biên dịch, hỗ trợ thiết kế nhiều sheet, công cụ điều hướng kết nối, hỗ trợ đa kênh, nhiều tài liệu triển khai, v.v. Để lấy giao diện WorkSpace Manager, hãy gọi hàm GetWorkspace, hàm này trả về giao diện IWorkspace.
Đối với script Netlister, các giao diện cần quan tâm là IWorkSpace, IProject, IDocument, IComponent và INet.
Lưu ý rằng một số giao diện, đặc biệt là các giao diện đối tượng thiết kế, tương ứng với các giao diện Schematic Object tương đương. Điều này là do các tài liệu logic trong một dự án là các tài liệu schematic có thông tin kết nối. Trên thực tế, có thể sử dụng mô hình Schematic Object thay cho WorkSpace Manager, nhưng WorkSpace Manager cung cấp chức năng biên dịch một dự án và trích xuất tài liệu từ dự án, cũng như lấy dữ liệu từ các đối tượng schematic.
Các phần chính của script Netlister là:
-
Một biến chuỗi toàn cục
TargetFileName, là tên tệp của netlist. -
Một đối tượng tập hợp Netlist toàn cục
TStringList, được điền dữ liệu netlist. -
Các thủ tục
WriteComponent_Version1vàWriteComponent_Version2. -
Các thủ tục
WriteNet_Version1vàWriteNet_Version2. -
Một hàm
ConvertElectricToStringdùng để chuyển thuộc tính điện của chân thành chuỗi -
Thủ tục
GenerateNetlistquản lý việc tạo dữ liệu cũng như các tác vụ quản lý tên tệp, đường dẫn và thư mục.
Chức năng của script
Hai thủ tục không tham số, GenerateProtelV1FormatNetlist và GenerateProtelV2FormatNetlist, sẽ xuất hiện trong hộp thoại Select Item to Run dialog, cho phép chọn tạo netlist định dạng Protel V1 hoặc Protel V2. Các thủ tục này gọi thủ tục GenerateNetlist với lựa chọn định dạng netlist (0 hoặc 1) được truyền dưới dạng tham số.
Procedure GenerateProtelV1FormatNetlist; Var Version : Integer; Begin // Protel 1 Netlist format, pass 0 GenerateNetlist(0); End; Procedure GenerateProtelV2FormatNetlist; Var Version : Integer; Begin // Protel 2 Netlist format, pass 1 GenerateNetlist(1); End;
GenerateNetList
Thủ tục GenerateNetList lấy giao diện workspace để từ đó có thể trích xuất giao diện dự án cho dự án hiện tại (IWorkspace.DM_FocusedProject).
Dự án cần được biên dịch trước khi có thể trích xuất các net, vì quá trình biên dịch sẽ xây dựng thông tin kết nối của dự án. Phương thức DM_Compile của giao diện dự án được áp dụng (IProject.DM_Compile) như thể hiện trong đoạn mã dưới đây. Lưu ý rằng các phiên bản Altium Designer gần đây tự động biên dịch dự án, vì vậy bước này là tùy chọn.
WS := GetWorkspace; If WS = Nil Then Exit; Prj := WS.DM_FocusedProject; If Prj = Nil Then Exit; // Compile the project to fetch the connectivity info for design. Prj.DM_Compile;
Thông tin linh kiện và net được lưu trong đối tượng Netlist thuộc kiểu TStringList, đối tượng này sẽ được dùng sau đó để tạo tệp văn bản netlist đã định dạng. Đối tượng TStringList là một lớp Delphi có thể sử dụng trong script.
Sau đó, thủ tục Generate được gọi với các tham số truyền vào xác định đường dẫn và tên tệp của dự án hiện tại, cùng với phiên bản định dạng netlist.
Generate
Thủ tục Generate lấy đường dẫn dự án làm đường dẫn đầu ra đích cho tệp netlist được tạo (từ tham số DocumentPath được truyền vào), xác định tên tệp netlist (TargetFileName) và kiểm tra trạng thái flattened của dự án (IProject.DM_DocumentFlattened).
Đối với tất cả các tài liệu schematic trong một dự án, mỗi tài liệu sau đó được kiểm tra net và linh kiện bằng các thủ tục WriteNets và WriteComponents, rồi cuối cùng được trích xuất vào đối tượng Netlist.
Ghi Nets và Components
Một netlist bao gồm các phần linh kiện và net, vì vậy cần hai thủ tục riêng để ghi dữ liệu linh kiện và dữ liệu net.
Chỉ các net có nhiều hơn hai node mới được ghi vào netlist; các net có ít hơn sẽ bị loại bỏ. Với mỗi net, tên net dựa trên phương thức DM_CalculatedNetName của Net, phương thức này trích xuất tên net từ thông tin kết nối của dự án đã biên dịch.
Hai đoạn mã cho phần Components và Nets của một netlist được trình bày bên dưới cho định dạng netlist Version 1. Lưu ý rằng dữ liệu linh kiện và net được lưu trong đối tượng NetList, là kiểu TStringList. Netlist được tạo gồm hai phần: phần thông tin linh kiện và phần thông tin net.
Phần Components
Trong thủ tục WriteComponent, mỗi linh kiện tìm thấy từ Project được kiểm tra xem có phải là linh kiện thực sự hay không, sau đó các giá trị physical designator, footprint và part type được trích xuất. Chúng được thêm vào bộ chứa đối tượng Netlist (NetList.Add) để xây dựng chính netlist.
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;
Phần Nets
Đối với thủ tục Nets, NetName và các Designator được trích xuất nếu một net có từ hai chân trở lên (INet.DM_PinCount). Thông tin net và chân cùng với các ký tự định dạng được thêm vào bộ chứa Netlist để xây dựng netlist. Đoạn mã dưới đây là thủ tục ghi net cho netlist version 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;
Lưu ý rằng định dạng netlist chi tiết hơn, Protel v2, bao gồm các thuộc tính điện cho các chân net (In, Out, Passive, HiZ v.v.).
Do đó, thủ tục ghi net cho định dạng version 2 (WriteNet_Version2) sẽ truy vấn thuộc tính điện của từng chân net (INet.DM_Electical), rồi được chuyển đổi bởi thủ tục ConvertElectricToString được gọi – về cơ bản là một bảng tra chuyển đổi chuỗi. Sau đó, chúng được thêm vào một biến chuỗi cục bộ (ElectricalString), và biến này tiếp tục được thêm vào đối tượng bộ chứa Netlist.
Tạo tệp Netlist
Cuối cùng, khi đối tượng bộ chứa Netlist đã được điền đầy đủ thông tin linh kiện và net của dự án theo định dạng đã chọn, thủ tục Generate sẽ ghi dữ liệu Netlist vào một tệp (TStringList.SaveToFile). Đường dẫn và tên tệp được xác định bởi biến chuỗi TargetFileName, như đã được xác định trong thủ tục Generate.