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.

schematic editor

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 board.json.imp_meta.

Refactor Core class

The 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 classes IDocument, 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 commit() and revert() the 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.

pnp 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.

Airwire filter

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.

airwire filter

View hints

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:

view hints

Touchscreen gestures

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.

link hud

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:

no populate

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…

Improved search

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 the document.

To improve on these two aspects, the search logic got factored into its own class 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:

search

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 the code revealed that the constructor for Searcher::TypeInfo had a dependency on object_descriptions. Once the cause of the crash was now clear fixing it merely involved constructing the type_info map on first use as suggested by the ISO C++ FAQ.

What’s next?

Can’t tell. Development will go on as usual based on what’s on my mind and issues that crop up.