No description
Find a file
2019-03-21 19:45:23 +00:00
src fixes and docs 2019-03-21 19:37:50 +00:00
LICENSE Agregar LICENSE 2019-03-21 19:39:41 +00:00
nim.cfg initial release 2019-03-19 19:03:08 +00:00
nimcdl.nimble initial release 2019-03-19 19:03:08 +00:00
README.es.md MD fixes 2019-03-21 19:45:23 +00:00
README.md MD fixes 2019-03-21 19:45:23 +00:00

NimCDL: Nim Circuit Design Language

This package is a small DSL (Domain Specific Language) for Nim that allows to design electronic circuits, make a small evaluation (composer.nim) and generate a netlist for Fritzing or Kicad.

It is still in the experimental phase and has many things to finish (See TODO).

Installation

Having installed nim and nimble, it is installed with just a simple command: nimble install nimcdl

Use

This library defines a DSL to firstly define the circuit components, then the circuit itself and finally compose and export it.

Clearly the first thing we will have to do in our Nim script is to import this library:

import nimcdl

Defining a component

In the future, components may be imported and/or this library will have standard components. For the moment we will have to define each one of the components that we are going to use.

The first thing will be to assign the component to a variable and start a definition:

let led = component("led"):

add pins

Each electronic component has a series of pins that can be inputs or outputs (they can also be both, but this is not yet supported), to define these pins, we simply add the following to the previous code:

let led = component("led"):
pins:
P1 -> PinIn((1.0,5.0), (0.1,0.3))
P2..P3 -> PinOut()

Here we see pin 1(P1), which is assigned as an input pin (PinIn), then we assign a minimum and maximum voltage supported by the component ((1.0,5.0)) and do the same with the amperage it requires ((0.1,0.3)).

Then, we see how you can assign a range of pin (PX..PY), in this case from pin 2 to pin 3 is assigned as an output pin (PinOut), in this case these default pins do not provide any electrical current (Voltage 0 and Amperage 0).

Logic of pins conections

The pins of our component may not work identical when certain pins are connected, so we can define the internal connections and their logics as follows:

let led = component("led"):
pins:
P1 -> PinIn((1.0,5.0), (0.1,0.3))
P2..P3 -> PinOut()
pinsLogic:
logic L1:
p2.p.maxVoltage = p1.p.maxVoltage

P1 <-> P2
P1<L1>P3

Let's go in parts, first connect pin 1 to pin 2, that is, if current enters through this, it leaves without being altered by pin 2 (P1 <-> P2). Then, between pin 1 and 3 we want to assign a logic, either resistance or any other alteration to the output pin or to the input current(net). For this we define the following:

logic L1:
p2.p.maxVoltage = p1.p.maxVoltage

Que gracias a macros se convertira en:

proc (netIn: var Net, p1, p2: var tuple[n: uint, p: Pin]) =
p2.p.maxVoltage = p1.p.maxVoltage

In the meantime, we specified to which pins this logic was assigned(P1P3)

De esta forma ya tendríamos nuestro componente listo.

Define a circuit

With our components already in variables, we are ready to initialize our circuit:

let ledCircuit = cirucit("ledTest"):

Creating a net

When defining nets, the first one we define will be our input network while the last one, the output network. At the moment, we can only name it but not assign the input current. Although after composing the circuit, we will be able to know the minimum and maximum voltage and amperage necessary for these.

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()

Adding components

Another fundamental part of any circuit, without a doubt, are its components. These are assigned in such a way:

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()
components:
CL0 -> f
CL1 -> f

As we can see, we can choose a reference for the component with this format CXY, where X is just a letter to identify the component and Y a number that can have as many digits as you want.

Conections

Now the final touch, the connections between networks and components or between components, for this we have several ways to express it thanks to DSL. The first is the connection of pin to pin or network to pin, ideal for making circuits in serial, which can be put in these ways:

N0 <-> P1.CL0.P2 <-> N1

N0 <-> CL0.P1
N1 <-> CL0.P2

N0 <-> P1.CL0.P2 <-> P1.CL1.P2 <-> N1

The second is a multi-pin network, perfect for parallel connections:

N0 || N1
|| P1.CL0.P2
|| P1.CL1.P2

| N0
| CL0.P1
| CL1.P1

So, our circuit could be something like this:

let ledCircuit = cirucit("ledTest"):
nets:
N0 -> Net(name: "VDD")
N1 -> Net()
components:
CL0 -> f
CL1 -> f

connections:
N0 || N1
|| P1.CL0.P2
|| P1.CL1.P2

Composer

Finally, we compose the circuit, where the composer transforms the network to be easily exported and make a slight evaluation of it (In the future it will be more exhaustive).

let final = ledCircuit.compose(2)

The 2 is the total number of networks that we have defined in the nets section. This function returns a tuple with the final circuit (final.circuit) and a collection of errors found in the circuit (final.errors).

Export

With this circuit in Nim we will not be able to do much more (for the moment), therefore we have to export it to a netlist:

  • Kicad: with the function toKicadNetlist('D') (final.toKicadNetlist('D'))
  • Fritzing: with the function toFritzingNetlist("circuit name")` (final.toFritzingNetlist("ledTest"))

Cotribute

Pulls requests accepted and well valued!!. I'm going to start another project and I don't have time to keep progressing in this one. Besides the TODOs in the code, here is a list of things to do:

  • Composer: Make a more correct ERC check and optimize.
  • types: add more important information.
  • DSL: add the buses (and document them) and allow to add logics when you get the necessary current for a network.
  • Create an importer to be able to import components from outside.
  • make a general code improvement
  • Other