Script Example Analysis
Чтобы дать более глубокое представление об общих аспектах системы скриптинга, а также об использовании Delphi и объектных моделей X2 в скриптах, здесь с точки зрения функциональности рассматриваются два примера проектов — копировщик контура платы и скрипт генерации нетлиста.
Скрипты Board Outline Copier и Netlister разработаны с использованием объектных моделей X2, чтобы продемонстрировать возможности системы скриптинга в Altium Designer. Это существующие скрипты, доступные в коллекции примеров скриптов, а именно:
-
Скрипт Board Outline Copier использует объектную модель PCB для копирования существующего контура платы PCB в виде треков и дуг на указанный слой.
См.\Scripts\VB Scripts\CopyBoardOutlinePRJ.PRJSCR. -
Скрипт генератора нетлиста использует объектную модель WorkSpace Manager для формирования нетлиста в традиционном формате Protel (v1 и v2).
См.\Scripts\Delphiscript Scripts\WSM\Protel Netlister\ScripterProtelNetlist.PRJSCR.
Проект Board Outline Copier
Цель Board Outline Copier — скопировать существующий контур платы из PCB-документа на другой слой в том же документе.
Проект использует форму скрипта (Script Form), чтобы пользователь мог взаимодействовать с диалогом: задать ширину контура платы и выбрать целевой слой из выпадающего списка. С помощью объектной модели PCB и её PCB-интерфейсов из PCB API объекты контура платы извлекаются и копируются на указанный слой.
Основные части скрипта:
-
Глобальная переменная
PCB_Board(типаIPCB_Board). -
Подпрограмма
CopyBoardOutline, принимающая параметрыAWidthиALayer. -
Обработчик события
bOkClick, который получает значения ширины и слоя из формы скрипта и затем выполняет подпрограммуCopyBoardOutline. -
Обработчик события
bCancelClick, который закрывает форму (диалог) Board Outline.
Функциональность скрипта
Скрипт использует форму, для которой нужны обработчики событий, чтобы фиксировать щелчки мышью по отдельным элементам управления, таким как кнопки OK и Cancel.
Обработчик события кнопки OK по сути выглядит так:
Sub bOKClick(Sender) Dim Width Dim Layer Call StringToCoordUnit(eWidth.Text,Width,PCB_Board.DisplayUnit) Layer = String2Layer(cbLayers.Items(cbLayers.ItemIndex)) End Sub
Здесь обработчик события мыши формы OnClick (bOKClick) использует функцию StringToCoordUnit, чтобы получить введённую ширину контура (строку eWidth из поля TEdit) во внутренних координатных значениях. Эта функция применяет текущие единицы платы (свойство PCB_Board.DisplayUnit) к переменной Width.
Аналогично, выбранная строка слоя (элемент cbLayers из TComboBox формы) передаётся в функцию String2Layer, чтобы получить перечислимое значение для переменной Layer. Обратите внимание: в этом проекте TComboBox формы заранее заполнен индексированным списком строк слоёв (cbLayers.Items) — см. файл формы CopyBoardOutlineForm.dfm со списком слоёв.
Заключительный шаг в обработчике события (bOKClick) вызывает подпрограмму CopyBoardOutline, передавая в качестве параметров переменные Width и Layer. Обработчик кнопки формы Cancel (bCancelClick) просто закрывает форму.
Интерфейс IPCB_Board
Внутри обработчика кнопки OK (bOKClick) текущая плата получается из интерфейса IPCB_Board через IPCB_ServerInterface, возвращаемый специальной функцией PCBServer. Здесь функция GetCurrentPCB устанавливает ссылку на текущую плату в переменную PCB_Board.
Текущий контур платы (IPC_BoardOutline) затем получается в скрипте через свойство BoardOutline интерфейса IPCB_Board, используя указанную выше ссылку на плату PCB_Board.
Перед тем как продолжить копирование и создание нового контура, контур платы нужно инициализировать. Контур — представленный интерфейсом IPCB_BoardOutline — можно инициализировать с помощью методов перестроения/валидации этого интерфейса.
PCB_Board.BoardOutline.Invalidate PCB_Board.BoardOutline.Rebuild PCB_Board.BoardOutline.Validate
Сегменты контура: дуги и треки
Интерфейс IPCB_BoardOutline, представляющий контур платы, наследуется от интерфейса IPCB_Group. Интерфейс IPCB_Group представляет групповой объект, который может хранить дочерние объекты. Пример интерфейса IPCB_Group — полигон или контур платы, поскольку они могут хранить дуги и треки как дочерние объекты.
Объект контура платы хранит два разных типа сегментов — ePolySegmentLine и ePolySegmentArc, которые представляют объект трека или дуги соответственно. Количество сегментов определяется свойством PointCount интерфейса IPCB_BoardOutline, которое извлекает каждую вершину контура в переменную I для цикла For-To-Next.
Каждый сегмент полученного контура платы проверяется на треки и дуги оператором If PCB_Board.BoardOutline.Segments(I).Kind = ePolySegmentLine Then. Если это не сегмент трека (ePolySegmentLine), то часть Else оператора предполагает, что сегмент является дугой.
Для каждого найденного сегмента, в зависимости от его типа, создаётся новый объект трека или дуги с помощью функции PCBObjectFactory.
Функция PCBObjectFactory
Создание новых объектов PCB выполняется с использованием функции PCBObjectFactory напрямую из интерфейса IPCB_ServerInterface.
'Create new Track object PCBServer.PCBObjectFactory(eTrackObject, eNoDimension, eCreate_Default) 'Create new Arc object PCBServer.PCBObjectFactory(eArcObject, eNoDimension, eCreate_Default)
Параметры функции PCBObjectFactory задают тип объекта (Track, Arc, Via и т. д.), вид размерности (Linear, Radial и т. д.) и режим создания объекта (по локальным значениям по умолчанию или по глобальным предпочтениям).
После того как каждый объект трека или дуги создан процедурой PCBObjectFactory, его свойства инициализируются следующими далее операторами трека/дуги.
Свойства Track и Arc представлены соответствующими интерфейсами IPCB_Track и IPCB_Arc, где скрипт реализует нужные свойства. Например, координаты нового трека берутся из вершин сегмента исходного контура, где Track.X1 и Track.Y1 — начальные координаты трека, а свойства X2 и Y2 — его конечные координаты.
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
Как видно из приведённого фрагмента кода, свойства Layer и Width трека просто задаются переданными значениями, извлечёнными из диалога пользовательского интерфейса — переменными формы cbLayers и eWidth.
После полного задания параметров новые объекты добавляются на указанный слой PCB-документа оператором PCB_Board.AddPCBObject(NewObject), где NewObject — это Track или Arc.
PreProcess и PostProcess
При создании объекта PCB сначала нужно вызвать метод PreProcess из интерфейса объекта IPCB_ServerInterface, чтобы подготовить PCB-сервер. После создания объекта применяется метод PostPocess (также из интерфейса IPCB_ServerInterface), чтобы сообщить серверу, что добавление объектов завершено.
Методы PreProcess и PostProcess поддерживают систему Undo и другие подсистемы PCB-редактора в актуальном состоянии и синхронизации. Ниже приведён типовой фрагмент кода с операторами PreProcess и PostProcess.
PCBServer.PreProcess 'Create PCB objects PCBServer.PostProcess
Когда объекты добавляются на выбранный слой, который не отображался в PCB-документе, слой нужно принудительно сделать видимым. Это выполняется оператором PCB_Board.LayerIsDisplayed(ALayer) = True, где ALayer — слой, выбранный пользователем.
Обновление документа
Наконец, PCB-документ с новым контуром платы обновляется командой PCB:Zoom и связанными с ней параметрами Action = Redraw. Параметры команды масштабирования применяются процедурой AddStringParameter после того, как буфер параметров сначала очищается методом ResetParameters.
Проект Netlister
Цель этого проекта скрипта Netlister — сгенерировать стандартный netlist Protel (в формате Version 1 или Version 2) для проекта Altium Designer, содержащего схемы. Плоский netlist проекта схемы разделяется на две секции:
- Позиционные обозначения компонентов и информация, связанная с каждым компонентом,
- Имена цепей и информация, связанная с каждым именем цепи, вместе с подключениями выводов (выводы компонента).
Объектная модель WorkSpace Manager в API предоставляет интерфейсы, представляющие проект и его составные части — документы, компоненты и их выводы, а также цепи. WorkSpace Manager — это системный сервер, тесно связанный с модулем Client, который работает с проектами и связанными с ними документами. Он обеспечивает компиляцию, поддержку многолистовых проектов, инструменты навигации по связности, поддержку многоканальности, несколько документов реализации и т. д. Чтобы получить интерфейс WorkSpace Manager, вызовите функцию GetWorkspace, которая возвращает интерфейс IWorkspace.
Для скрипта Netlister интерес представляют интерфейсы IWorkSpace, IProject, IDocument, IComponent и INet.
Обратите внимание, что некоторые интерфейсы, особенно интерфейсы объектов проектирования, соответствуют эквивалентным интерфейсам Schematic Object. Это связано с тем, что логические документы в проекте — это документы схем с информацией о связности. Фактически вместо WorkSpace Manager можно использовать объектную модель Schematic Object, однако WorkSpace Manager предоставляет функциональность компиляции проекта и извлечения документов из проекта, а также получения данных из объектов схемы.
Основные части скрипта Netlister:
-
Глобальная строковая переменная
TargetFileName, которая является именем файла netlist. -
Глобальный объект-коллекция Netlist
TStringList, который заполняется данными netlist. -
Процедуры
WriteComponent_Version1иWriteComponent_Version2. -
Процедуры
WriteNet_Version1иWriteNet_Version2. -
Функция
ConvertElectricToString, которая преобразует электрическое свойство вывода в строку -
Процедура
GenerateNetlist, которая управляет генерацией данных и задачами обслуживания имени файла, пути и каталога.
Функциональность скрипта
Две процедуры без параметров, GenerateProtelV1FormatNetlist и GenerateProtelV2FormatNetlist, появятся в диалоге Select Item to Run dialog, предлагая выбор: сгенерировать netlist в формате Protel V1 или в формате Protel V2. Эти процедуры вызывают процедуру GenerateNetlist, передавая в качестве параметра выбор формата netlist (0 или 1).
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
Процедура GenerateNetList получает интерфейс рабочей области, чтобы затем извлечь интерфейс проекта для текущего проекта (IWorkspace.DM_FocusedProject).
Перед тем как можно будет извлечь цепи, проект необходимо скомпилировать, поскольку процесс компиляции строит информацию о связности проекта. Применяется метод DM_Compile интерфейса проекта (IProject.DM_Compile), как показано в фрагменте кода ниже. Обратите внимание: последние версии Altium Designer компилируют проекты автоматически, поэтому этот шаг необязателен.
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;
Информация о компонентах и цепях хранится в объекте Netlist типа TStringList, который позже используется для генерации форматированного текстового файла netlist. Объект TStringList — это класс Delphi, доступный для использования в скриптах.
Затем вызывается процедура Generate с переданными параметрами, которые задают путь и имя файла текущего проекта, а также версию формата netlist.
Generate
Процедура Generate получает путь проекта как целевой путь вывода для сгенерированного файла netlist (из переданного параметра DocumentPath), определяет имя файла netlist (TargetFileName) и проверяет статус «flattened» проекта (IProject.DM_DocumentFlattened).
Для всех документов схем в проекте каждый документ затем проверяется на наличие цепей и компонентов с помощью процедур WriteNets и WriteComponents и в итоге извлекается в объект Netlist.
Запись цепей и компонентов
Netlist состоит из секций компонентов и цепей, поэтому требуются две процедуры, чтобы записывать данные компонентов и данные цепей отдельно.
В netlist будут записаны только цепи с числом узлов больше двух; цепи с меньшим числом отбрасываются. Для каждой цепи имя цепи берётся на основе метода DM_CalculatedNetName объекта Net, который извлекает имена цепей из информации о связности скомпилированного проекта.
Ниже показаны два фрагмента кода для секций Components и Nets netlist в формате Version 1. Обратите внимание, что данные компонентов и цепей хранятся в объекте NetList, который имеет тип TStringList. Сгенерированный netlist состоит из двух секций: секции информации о компонентах и секции информации о цепях.
Секция Components
В процедуре WriteComponent каждый компонент, найденный в Project, проверяется на то, является ли он реальным компонентом, после чего извлекаются значения физического позиционного обозначения, посадочного места и типа компонента. Они добавляются в контейнер объекта Netlist (NetList.Add) для построения самого 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;
Секция Nets
Для процедуры Nets извлекаются NetName и Designators, если цепь имеет два или более выводов (INet.DM_PinCount). Информация о цепи и выводах, а также символы форматирования добавляются в контейнер Netlist для построения netlist. Ниже приведён фрагмент процедуры записи цепей для netlist версии 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;
Обратите внимание, что более подробный формат netlist, Protel v2, включает электрические свойства для выводов цепей (In, Out, Passive, HiZ и т. д.).
Поэтому процедура записи цепей для формата версии 2 (WriteNet_Version2) опрашивает электрическое свойство каждого вывода цепи (INet.DM_Electical), которое затем преобразуется вызываемой процедурой ConvertElectricToString — по сути, это таблица соответствий для преобразования в строку. Затем эти значения добавляются в локальную строковую переменную (ElectricalString), которая, в свою очередь, добавляется в объект-контейнер Netlist.
Создание файла netlist
Наконец, когда объект-контейнер Netlist полностью заполнен информацией о компонентах и цепях проекта в выбранном формате, процедура Generate записывает данные Netlist в файл (TStringList.SaveToFile). Путь и имя файла задаются строковой переменной TargetFileName, как определено в процедуре Generate.


