Extracting a Circuit From the Graph

The GraphEdit node has a list of connections. It specifies the from and to points of each wire e.g. { from_port: 0, from: "R1", to_port: 1, to: "C2" }

We may loop through these connections and create a dictionary with from keys with values of to lists.

The keys and value items may be formed using an array like so: [PartName, port, side]. We can use enums to designate the left or right side of a part or 0, 1.

These arrays may be used as dictionary keys and compared for equality. This is a powerful capability!

Mirrored parts

Parts such as a vertically oriented resistor have electrically equivalent ports of the same number, so we will only set the side value to zero in these cases.

A part such as an NPN transistor may be configured with 3 pins on the left side and 2 pins on the right side, but we want port 1 on the right side to correspond with port 2 on the left side (for the emitter pin).

NPN

The port numbers are assigned according to the number of activated slots in the GraphNode. So, we will need a property of the part to tell us to increment the from port number if it is greater than 1.

Scanning the connection list

We add any newly discovered from point as a dictionary key.

Then append all points that this node goes to to its array value.

Also, we need to look for other equivalent from points due to chaining due to being mirrored parts.

Mirrored parts

The code.

func get_from_tos(pgs_, graph_):
	# { from => tos, ...}
	# {[name, port, side] => [[name, port, side], ...], ...}
	var nodes = {}
	var cons = graph_.get_connection_list()
	for con in cons:
		# Cons may have a common from value
		var from_side = 0 if pgs_.parts[con.from].is_mirrored else 1
		var from_port = con.from_port
		if from_port > 0 and pgs_.parts[con.from].inc_from_pin:
			from_port += 1
		var from = [con.from, from_port, from_side]
		var to = [con.to, con.to_port, 0] # to, to_port, left side
		var found = false
		for _from in nodes.keys():
			if _from == from: # Found an existing `from` node so append the `to` value and break
				nodes[from].append(to)
				found = true
				break
			# The `_from` node is not `from` but may be connected to `from` parent node at the same port number as `from`. In mirrored pgs_.parts, the io pins for a port number are shorted together.
			if from_side == 0: # Search in 'tos' for existing connection
				for _to in nodes[_from]:
					if _to == from: # Matching [name, port]
						found = true
						break
				if found:
					# Make `_from` node connect to the same `to` as `from`.
					# Also don't add this `from` to the node list since its redundent
					nodes[_from].append(to)
					break
		if not found: # Add new node
			nodes[from] = [to]
	return nodes

Now we have a dictionary of from_points mapped to to_points.

Now we may create an array of circuit nodes containing arrays of all parts connected to the network nodes.

func get_net_nodes(from_tos_):
	var net_nodes_ = []
	for from in from_tos_.keys():
		var node = from_tos_[from]
		if goes_to_existing_node(from, node, net_nodes_):
			continue
		node.append(from)
		net_nodes_.append(node)
	return net_nodes_


func goes_to_existing_node(from, node, net_nodes_):
	for net_node_ in net_nodes_:
			for to in node:
				if to in net_node_:
					net_node_.append(from)
					return true
	return false

Network nodes

By doing all this, we have simplified our circuit connectivity description to its simplest form.

Now we are able to generate a net list for our circuit listing all the components and what nodes they connect to. This could be used to generate SPICE files for example.

Next I will try to figure out how to analyze the circuit.

More Devlog entries

Most recent first