Quite a lot has happened since the 1.0 release, so I decided to do a writeup similar to how other projects do it.
List unplaced gates in schematic editor
Many users have been asking how they place the remaining symbols of an entity if they didn’t place all of them initially. This is most likely caused by there being no visual indication of the unplaced symbols.
To alleviate this, the schematic editor now lists all unplaced symbols similar to how the symbol editor lists unplaced pins.
As a bonus, the board editor now also shows all unplaced packages.
Save layer settings separately
At FOSDEM, people from KiCad and LibrePCB were mentioning that they’re planning to save layer visibility and other settings that aren’t really part of the design itself to a separate file rather than including them in the board file itself. This helps to make diffs easier to read and keeps design and non-design data separate.
Since that made sense to me as well, I implemented it by storing what
was previously at the
_imp key in the
board.json file in
Refactor Core class
Core class used to be horizon’s way to access different document types
(schematic, board, symbol, etc.) in a unified fashion. Unfortunately,
that class accumulated quite a lot of baggage in the last years as it
also hosts the tools and provides the property interface. Thus every
part of the application that needed unified access also pulled in quite
a lot of dependencies.
To fix this, the decision was made to introduce a family of interface
IDocumentSchematic, etc. that only provide the
unified access and nothing else. The
Core classes then in turn
implement these interfaces so most code can stay as-is. Since the tools
lost access to the
Core to do
ToolResponse class has been extended so that tools can use their
return value to signal commit or revert. This also helps to emphasize
that commit or revert is the end of a tool’s lifecycle.
If all went well, this should have no user-facing effects.
Unify project title and title blocks
More by accident than intent, the project’s name could be set in the project itself and in the schematic’s title blocks with no link between these two. ataoav came up with some ideas to improve the situation. After some discussion, we settled on moving all metadata to the netlist and having the project manager pick it up as well. This also enabled using these variables in texts on the board as well, so you’ll only need to set the board’s revision in the schematic editor and it can be used on the board as well.
As a bonus, we finally have the project’s title in all window titles.
Pick & place export
Pick & place export has been on my to-do list for quite some time. Finally some users were asking for it, so I implemented it. As to be expected this was rather straight forward as it’s conceptually similar to the already existing BOM export.
The biggest hurdle was to figure out the proper reference angle for components placed on the bottom side. After asking on mikrocontroller.net and on the EEVBlog Forum I settled on my initial implementation that mirrored components at the X-axis to arrive at the 0° orientation for parts on the bottom side. This is contrary to how mirroring works in Horizon EDA itself but is the same as in KiCad and Altium.
People in these threads also mentioned that since there’s no standard for pick & place files, assembly houses usually take care to match the pick & place data to the assembly drawing.
In the early phases of board layout there are usually quite a lot of airwires that might make it difficult to see what’s going on. To provide, a more focused view, the airwire filter makes it possible to hide airwires of select nets.
With the addition of the airwire filter, there are now three ways that alter the behaviour of the editor without any indication that’s directly visible:
- Selection filter
- Airwire filter
- Bottom view
To address this, the interactive manipulator now shows a message in status bar if any of these three are active:
When using a touch-enabled laptop, I’ve found myself reaching for the touch screen quite often for zooming and panning actions as it’s quicker than using the touchpad. So I wanted to have this convenience in Horizon EDA as well!
Fortunately, Gtk has kept on with the times and supports all the usual pan, zoom and rotate gestures out of the box. The only thing left to do is to make the events generated by these gestures do the right thing to the canvas. That’s why this only required about 100 lines of code each for the 2D (board, schematic, etc.) and 3D canvas.
Since showing these gestures without the hand in frame doesn’t make much sense, I recorded a short video of me aimlessly zooming and panning around. Sorry for the potato quality, but that’s what I got out of my 2011 point&shoot camera after compressing the video to a sensible file size. At least I got rid of glare and reflections.
Even if this feature might not see much use in the wild, it’s still something cool to show off. To my best knowledge, this makes Horizon EDA the first (and only?) full-featured PCB design software that supports touchscreen gestures.
Detecting URLs in text
As I found out, users like to place links to datasheets, appnotes an other related literature in schematics. Up until this point, opening the link involved awkwardly selecting the URL and pasting it into a browser.
To make this easier, the schematic editor recognizes URLs and shows a clickable link in the head-up display (the black box is the link’s tooltip). A bit of CSS was necessary to make the link easier to read against the dark background.
Support for unplaced components
There are many good reasons for having components in the design that have their footprint on the board, but won’t be populated, such as encoding revisions or future-proofing. To reliably track these across BOM, pick&place file and other formats, it’s preferable that this is supported by the design tool rather than manually editing files after the fact or repurposing component values.
eqvinox saw the need for this feature and opened a pull request that adds support for marking components as “do not place” in the schematic/netlist. Other parts of the application can then pick this up and act accordingly such as not adding the part to the BOM. After around 10 days, that PR was ready to be merged. Here’s a screenshot of how unplaced components are displayed in the schematic:
All in all, the PR amounted to about 300 lines changed (251 additions, 66 deletions). This made me wonder why other EDA software around for many decades doesn’t support unplaced components as it’s a rather low hanging fruit…
In its initial implementation, the search only supported searching for
objects identifiable by a single UUID and only looked for reference
designators in symbols. That didn’t allow for searching for pin names
or MPN. Apart from these user-facing shortcomings, the search logic was
implemented in the
Core since it was convenient at that time but
isn’t strictly necessary since the search logic only needs access to
To improve on these two aspects, the search logic got factored into its
Searcher with the appropriate subclasses such as
SearcherBoard that actually perform the search. Searching
for MPN in symbols got possible by the
Searcher class now defining its own set of types that the user
can pick from. Searching for pins and pads got possible by making
SearchResult refer to the found thing by
UUIDPath<2> that can store
both the symbol and pin UUID.
For the user, all of this mostly manifests in a longer list of object types to pick from:
As it’s evident from the commit history implementing this didn’t go without any bumps in the road. For the second (?) time in this project, I fell victim to the static initialization order fiasco that occurs when a constructor for a static object depends on another static object being initialized since that constructors for static objects get called in is undefined. This first went unnoticed, since the stars aligned just right and the constructor order ended up such that all static objects could be constructed.
Only when a Windows user
complained that the interactive manipulator didn’t start anymore, this
got my attention. After confirming that this was indeed the case on
Windows, I tried to debug this using gdb still oblivious to the root
cause. The exception occuring before
main() as verified by setting a
breakpoint then gave the hint to have a closer at look at
newly-introduced static objects. Staring at
revealed that the constructor for
Searcher::TypeInfo had a dependency
object_descriptions. Once the cause of the crash was now clear
merely involved constructing the
type_info map on first use as
suggested by the ISO C++
Can’t tell. Development will go on as usual based on what’s on my mind and issues that crop up.