Copper is a PCB EDA Tool written in Rust.
Coming from an electrical engineering background, we have used quite a few PCB EDA tools. Some of them are expensive and provide a lot of tools, that can work great or still be buggy. Some of them are open source but don't really seem to make progress in terms of neither stability nor features.
We genuinely think that this is not a misery coming from incompetent developers, but from a really old code base that is just lackluster and rusty (ha ha).
Thus we decided to try and write our own tooling.
Currently a basic KiCad schema can be rendered. Text rendering is disabled for now as the development of Pathfinder 2 by pcwalton is awaited.
A basic UI with just some info, made with GTK3, is working.
Placing, moving and rotating components works. Drawing new wires works as well.
I am working on a standalone hierarchical primitive renderer at the moment, to make rendering more convenient. Also I am trying to push azul to get a proper, native UI library.
So if you'd like to contribute, please help those two projects.
The idea is to complete a schema renderer first with regards to the PCB layouter in the future when it comes to performance questions. To start the project off, the idea is to use the KiCad formats, such that KiCad as a tool can be replaced piece by piece.
-
Schema renderer
- Text rendering on schema
- Adding & removing components
- Electrical logic correctness
- Tracking and validation of connections between components
- With regards to netlist generation
- Tracking and validation of connections between components
- Export the schema back to the KiCad format
- Store to a modern format (XML, JSON, YAML, TOML, RON, et al.) to maintain better readability, maintainability and serializing
- Generate a Netlist in the KiCad format
- (optional) Export to a modern format
- Text rendering on schema
-
Layouter
- Basic rendering
- more to come
The project consists of
- a library which contains all the operations for parsing, rendering and manipulation. The API to manipulate the designs programmatically should be a first class citizen from the get go to enable tests to the very last layer before the GUI and future possibilities of scripting and a console. A few remarks:
- The library is thematically structured into
drawing
(everything involved in the process of drawing the designs)loading
(everything involved in the process of loading the designs from various formats)parsing
(everything involved in the process of parsing the project design files)state
(contains all structures concerning the storing of the designs as well as their manipulation)utils
(helpers to make the coders life easier)geometry.rs
(for the moment contains various types; not sure if really need on the top level
- For KiCad formats parsing, nom is used. For a future modern format, https://github.com/serde-rs/serde can be used.
- No UI code should go in here.
- The library is thematically structured into
- a binary, which renders the schemata. This binary should only contain GUI code + glue which interfaces the copper library to draw and manipulate the schemata.
- For GUI https://github.com/antoyo/relm is used, which is based on https://github.com/gtk-rs/gtk.
- future binaries will be added for different tasks.
SchemaEditor
loads, holds and stores the schema
-
Schema
represents the state of the schema with all its components; does not contain any viewing information. Holds a vector of components and wires. It does not contain any manipulation methods itself.ComponentInstance
represents a single component in its logical meaning.- Each element (Components, Wires, Drawables, etc.) gets a UUID on creation. All entities are accessed via their UUID.
-
ViewState
holds the current view of the schema, cursor position, etc. It should also hold information about selected components, wires or wire preview, etc. -
SchemaLoader(&schema)
loads the schema -
SchemaViewer(&schema, &view_stae)
manipulates the current view of the schema; holds the current view state; does not manipulate the schema -
SchemaDrawer(&schema, &view_state)
daws the schema; does not manipulate the schema. Contains a single Vector of Drawables.- Updates the Drawables only on changes.
- Swaps removed Elemnts for the last one and changes indices of its vertices.
- Data will only get pushed to the GPU when it changes. Not each frame as before
- Each Drawable holds a UUID which matches the UUID of an element in the Schema.
-
Actions are perfromed using the
EventMessage
enum, theEventBus
struct and theListener
trait.Listener
is an enum which holds a variant for every single possible change of the Schema or its view. For exampleEventMessage::AddComponent(ComponentInstance)
orEventMessage::Zoom(f32)
.- Each
EventMessage
can be emitted usingEventBus::emit(EventMessage)
which internally pushes theEventMessage
onto a stack. Simultaneously it callsListener::receive(EventMessage)
of each knownListener
. When reverting an action,Listener::revert(EventMessage)
will be executed in the same fashion and theEventMessage
will be popped from the stack. Listener
is a trait implementingListenr::receive(EventMessage)
andListener::revert(EventMessage)
which apply and revert an action on a given actor respectively. It is meant that theListener
matches the enum variants it needs and discards the rest.
-
No schema state is directly manipulated. Every action is started via the
MessageBus
. States that only concern a preview can be manipulated with methods directly (selected component marker display, wire preview, etc.).
Make sure libgtk3
and libepoxy
are installed on your system.
Make sure you have the current nightly rustc enabled. You can do so with
rustup override set nightly
rustup update
Inside the repository. Finally you should be able to
cargo run --release --bin schema_editor test_data/kicad.lib test_data/kicad.sch
Set the active rustup toolchain using
rustup target add x86_64-pc-windows-gnu
rustup override set nightly-x86_64-pc-windows-gnu
rustup update
Install MSYS2.
In the “MSYS2 MSYS Shell” install libgtk3.
pacman -S mingw-w64-x86_64-gtk3
Then install the mingw toolchain
pacman -S mingw-w64-x86_64-toolchain
Start the “MSYS2 MinGW Shell” (not to be confused with “MSYS2 MSYS Shell”). All future operations should be performed from this shell.
Add the rustup/cargo binaries to the PATH
.
You can do this by adding the line
export PATH=$PATH:/c/Users/<your_name>/.cargo/bin:
to the .bashrc
.
Restart the shell.
Now make sure the MYSYS2 environment is up to date (weirdly enough this is not the case after doing a fresh install). If you are prompted about conflicts between packages, just accept that pacman resolves the conflicts by uninstalling one.
pacman -Su
Restart the shell again (You might have to force close it, that's okay!)
pacman -Su
again. Now a ton of packages should get listed. Install them.
Now you should be able to
cargo run --release --bin schema_editor test_data/kicad.lib test_data/kicad.sch
If you would like to contribute code, ideas or criticism, please do not hesitate to do so. We do not think that we already know how to perfectly write this application, so we are very open for big adjustments as well.
For now there is no "official process" of contruibuting code, so please just open issues and pull requests at will ;)
Yatekii can be found on the mozilla and freenode IRC networks with the same nick, where he wanders in various rust and general programming related channels. Sometimes tiwalun can be found there too if you get lucky.