diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..ae7308cf1 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,56 @@ +# Contribution Guidelines + +We take pull requests! + +All pull requests are thoroughly reviewed for code quality. + + +## Parts Contributions + +This repository maintains a curated parts library since: +- parts represent a continuing maintenance commitment +- we want libraries to produce working boards with reasonably high confidence +- we want to avoid choice overload for users + +There will be many useful parts that are not a good fit for inclusion on this repository, but we encourage an ecosystem of community libraries. +Consider creating a separate repository and publishing it on pip with a dependency on this project. +We may maintain a list of high quality third-party parts libraries. + +Good candidates for inclusion in this repository are: +- parts with good support among the maker and open-source community, such as support in ESPHome or high quality Arduino or Rust libraries +- parts with breakout boards available, such as by Sparkfun or Adafruit +- parts available from many distributors, including JLC assembly (particularly basic parts), Mouser, and Digi-Key +- parts with wide applicability +- parts using footprints in the standard KiCad libraries, or in PCM libraries +- parts that have been tested functional in a real PCB, consider opening PRs after you've brought up your device + +Parts that are poor candidates for inclusion are: +- parts that cannot be sourced by individuals +- parts with no public documentation (community-provided documentation and libraries count) +- parts that cannot be hand-soldered (including with hot air), primarily BGA +- extremely integrated parts which do not have a clean block boundary or interface +- niche parts + +Borderline case? Feel free to open an issue or PR for discussion. + + +## Compiler / Infrastructure Contributions + +If you're thinking of implementing a significant feature or refactor, please discuss the plan with us first such as through an issue. +We'd prefer to figure out and nail down an architecture and plan before any detailed coding. + + +## Third Party Tools + +If you build a tool that integrates with / makes use of this HDL, feel free to open an issue to request we add it to a list of such tools. +We may review such tools for quality and readiness before listing. + +We are also open to collaborating and discussing on how we can better support third party tooling, particularly community-driven open-source projects. + + +## Example Boards + +Third party designs should go in their own repositories, unless you feel it makes sense as an integration test here. + +We may link high quality example / built-with designs. +Feel free to open an issue or PR. diff --git a/README.md b/README.md index 62649af43..9c20c502c 100644 --- a/README.md +++ b/README.md @@ -3,187 +3,198 @@    - + +_subcircuit generator library based hardware description language for circuit board design_ -Polymorphic Blocks is an open-source, Python-based [hardware description language (HDL)](https://en.wikipedia.org/wiki/Hardware_description_language) for [printed circuit boards (PCBs)](https://en.wikipedia.org/wiki/Printed_circuit_board). -By making use of programming concepts and capabilities, this project aims to **make circuit design faster and easier through high-level subcircuit library blocks** much like what makes software development so productive and approachable. -Underlying language features enable these libraries to be general across many applications and provide a high degree of design automation. +Polymorphic Blocks is an open-source, Python-based [hardware description language (HDL)](https://en.wikipedia.org/wiki/Hardware_description_language) for schematic-equivalent design of printed circuit boards (PCBs). +Its library of components provide a high-level abstraction for circuit design while subcircuit generators automate the calculation of fine details. +Abstract component interfaces enable these libraries to be general across applications and component vendors. -We've been using this system to create a variety of boards of varying complexity, [examples](#examples) range from a charlieplexed LED matrix to a USB source-measure unit. +Generates stable KiCad netlists to be routed in the KiCad PCB Editor. -### A Keyboard Example -An example of all this in action is this design for a USB keyboard with a 3x2 switch matrix: +### Built Boards -
| User input | -What this tool does | -
| -The board is defined using high-level library subcircuits blocks, including parameterized ones like the switch matrix. -Choices for internal components can also be specified as refinements, for example generic switches (used in the switch matrix) are refined to Kailh mechanical keyswitch sockets. +## Example: from HDL to Keyboard + +**Overall flow**: write HDL -> generate netlist -> import into KiCad PCB editor -> place and route (optionally iterating with HDL) -> export BoM and Gerbers -> optionally generate JLC PCBA data + +A simplified version of the [getting started tutorial](getting-started.md) is this snippet for a 3x4 mechanical keyboard: ```python +from edg import * + class Keyboard(SimpleBoardTop): - def contents(self) -> None: - super().contents() + def contents(self) -> None: + super().contents() - self.usb = self.Block(UsbCReceptacle()) - self.reg = self.Block(Ldl1117(3.3*Volt(tol=0.05))) - self.connect(self.usb.gnd, self.reg.gnd) - self.connect(self.usb.pwr, self.reg.pwr_in) + self.usb = self.Block(UsbCReceptacle()) + self.reg = self.Block(LinearRegulator(3.3 * Volt(tol=0.05))) + self.connect(self.usb.gnd, self.reg.gnd) + self.connect(self.usb.pwr, self.reg.pwr_in) - with self.implicit_connect( + with self.implicit_connect( ImplicitConnect(self.reg.pwr_out, [Power]), ImplicitConnect(self.reg.gnd, [Common]), - ) as imp: - self.mcu = imp.Block(Stm32f103()) - self.connect(self.usb.usb, self.mcu.usb.request()) - - self.sw = self.Block(SwitchMatrix(nrows=3, ncols=2)) - self.connect(self.sw.cols, self.mcu.gpio.request_vector()) - self.connect(self.sw.rows, self.mcu.gpio.request_vector()) - - def refinements(self) -> Refinements: - return super().refinements() + Refinements( - class_refinements=[ - (Switch, KailhSocket), - ], - ) + ) as imp: + self.mcu = imp.Block(IoController()) + self.connect(self.usb.usb, self.mcu.usb.request()) + + self.sw = self.Block(SwitchMatrix(ncols=3, nrows=4)) + self.connect(self.sw.cols, self.mcu.gpio.request_vector("sw_col")) + self.connect(self.sw.rows, self.mcu.gpio.request_vector("sw_row")) + + self.enc = imp.Block(DigitalRotaryEncoder()) + self.connect(self.enc.a, self.mcu.gpio.request("enc_a")) + self.connect(self.enc.b, self.mcu.gpio.request("enc_b")) + self.connect(self.enc.with_mixin(DigitalRotaryEncoderSwitch()).sw, self.mcu.gpio.request("enc_sw")) + + def refinements(self) -> Refinements: + return super().refinements() + Refinements( + class_refinements=[ + (IoController, Ch32v203), + (Switch, KailhSocket), + ]) + +compile_board_inplace(Keyboard) ``` -These library blocks contain logic to adjust the subcircuit based on how it is used or its parameters. -For example, the USB-C port generates the required CC pulldown resistors if a power delivery controller is not attached, and the STM32 generates the required crystal oscillator if USB is used. -This helps eliminate gotchas for the system designer and makes the overall board more correct-by-construction. +The system: +- provides a library of subcircuit generators, like switch matrices and USB-C ports, that automatically include supporting components like decoupling capacitors and pullup resistors +- automatically selects generic parts like resistors and diodes against builtin parts tables +- performs basic electrical checks on the design, including voltage and current limits, automating some common datasheet parameter checking +- runs fully locally - | -+This generates: +- a netlist that can be imported into the KiCad PCB editor + - ... including hierarchical data, allowing subcircuit replication / channelization + - ... and have stable tstamps, allowing incremental updates to in-progress board layouts +- a JLCPCB-compatible BoM + - including a [postprocessing script](edg/tools/jlc_pcba/__main__.py) to shift part rotations from KiCad-generated component placements for JLC PCBA +- a [JSON representation of the full design](edg/core/CompiledDesignExport.py), including connectivity and solved circuit values, to integrate with custom / third-party tooling -Compiling the design produces a netlist that can be imported into KiCad for board layout and ultimately Gerber generation for manufacturing: - -_Placement and routing are out of scope of this project, components were manually placed._ + -Additionally, the compiler... -- generates stable netlists, allowing incremental updates to in-progress board layouts -- checks electrical properties like voltage and current limits -- automatically selects generic parts like resistors and diodes against a parts table -- generates a BoM for factory assembly +Advanced capabilities include: +- multi-board support including connector-pair management +- cross-hierarchy packing of multi-pack devices like dual op-amps and quad resistors +- standard abstract component interfaces, allowing for custom implementations of parts like resistors (including from a parts table), and microcontrollers +- full support for user component definition; very little is hard-coded into the infrastructure - | -
-
+Be prepared for things to be rough around the edges.
+The error messages in particular are not great and need work.
-**[LED Matrix](examples/test_ledmatrix.py)**: a 6x5 LED matrix using a [charlieplexed](https://en.wikipedia.org/wiki/Charlieplexing) circuit generator that drives 30 LEDs off of just 7 IO pins.
+Building boards with the included libraries should be relatively straightforward, but building custom library parts is a more complex process.
- |
-
-
+### Scope
+The current libraries best support intermediate-level (and simpler) PCB designs.
+This includes circuits with discrete microcontrollers, microcontroller modules (like ESP32s), and socketed dev boards.
+Libraries include common subcircuits like switch matrices, digitally attached peripherals like I2C sensors, voltage converters, and some analog signal conditioning circuits.
+Check out the [subcircuits library folder](edg/circuits/) and [parts library folder](edg/parts/).
-[Simon](examples/test_simon.py): a [Simon memory game](https://en.wikipedia.org/wiki/Simon_(game)) implementation with a speaker and [12v illuminated dome buttons](https://www.sparkfun.com/products/9181).
+There is no prescribed architecture and microcontrollers are not required.
- |
-
-
+Designs that do not decompose neatly(ish) into subcircuits blocks are a poor fit.
-**[IoT Fan Driver](examples/test_iot_fan.py)**: an [ESPHome](https://esphome.io/index.html)-based internet-of-things fan controller, controlling and monitoring up to two computer fans from a web page or [home automation dashboard](https://www.home-assistant.io/).
+There is no support for high-speed digital design (like DDR memories).
+There are some experimental RF subcircuits.
- |
-
-
+The electrical checks are not a design assurance tool and only automate some of the most common datasheet checks.
+More advanced parameters, especially performance characteristics not related to maximum ratings, are currently out of scope of the electronics model.
-**[CAN Adapter](examples/test_can_adapter.py)**: an isolated [CANbus](https://en.wikipedia.org/wiki/CAN_bus) to USB-C adapter.
+### Parameter Engine
- |
-
-
+Assertions are supported on parameters to enforce electrical correctness checks.
-**[BLE Multimeter](examples/test_multimeter.py)**: a BLE (Bluetooth Low Energy) compact (stick form factor) multimeter, supporting volts / ohms / diode / continuity test mode, for low voltage applications.
+Solving may happen within a single block with arbitrary Python code (for example, find the best set of E12 resistor values to implement a divider), but not across multiple blocks.
+Search involving multiple blocks must be handled by the block exposing tuning knobs and the user turning those knobs with recompilation.
- |
-
-
-**[USB Source-Measure Unit](examples/test_usb_source_measure.py)**: a USB PD (type-C power delivery) source-measure unit -- which can both act as a DC power supply with configurable voltage and current, and as a DC load. More precisely, it's a digitally-controlled 2-quadrant (positive voltage, positive or negative current) power source.
+### Parts Data
- |
-