Source code for jitxexamples.generative_rectangles.main

# main.py
from jitx import Board, Circle, LayerSet, Net, Port, Pour, Side, current, rectangle
from jitx.circuit import Circuit
from jitx.common import Power
from jitx.feature import KeepOut, Soldermask
from jitx.net import provide
from jitx.sample import SampleDesign
from jitxlib.parts import Capacitor, CapacitorQuery, Resistor, ResistorQuery
from jitxlib.symbols.net_symbols import GroundSymbol, PowerSymbol

from . import rectangles
from .cap_touch import CapTouch

from .components.Q_J.ComponentCR2032_BS_6_1 import ComponentCR2032_BS_6_1 as Bat
from .components.TOGIALED.ComponentTJ_S3210SW5TGLC2R_A5 import (
    ComponentTJ_S3210SW5TGLC2R_A5 as led,
)
from .components.Texas_Instruments.ComponentSN74HC14PWR import (
    CircuitSN74HC14PWR as schmitt,
)
from .components.Texas_Instruments.ComponentTLV9001IDBVR import (
    ComponentTLV9001IDBVR as opamp,
)


[docs] class SchmittInverter(Port): """Custom port type for a Schmitt trigger inverter with input and output ports.""" input = Port() output = Port()
[docs] class SchmittInverterWithPassives(Circuit): """Parametric circuit for a Schmitt inverter with configurable passive components.""" # Create ports gnd = Port() out = Port() inp = Port() # External input port (connects through input resistor) schmittinverter = SchmittInverter() def __init__( self, feedback_resistance=10e6, # Feedback resistor (input to output) input_capacitance=None, # Input capacitor (input to ground) series_output_resistance=None, # Optional series resistor on output input_resistance=None, # Input resistor (external input to schmitt input) ): # Store parameters self.feedback_resistance = feedback_resistance self.input_capacitance = input_capacitance self.series_output_resistance = series_output_resistance self.input_resistance = input_resistance # Create passive components self.parts = [] self.nets = [] # Always add feedback resistor (input to output) self.parts.append( Resistor(resistance=self.feedback_resistance).insert( self.schmittinverter.input, self.schmittinverter.output ) ) # Add input capacitor if specified (input to ground) if self.input_capacitance is not None: self.parts.append( Capacitor(capacitance=self.input_capacitance).insert( self.schmittinverter.input, self.gnd ) ) # Handle input connection with optional input resistor if self.input_resistance is not None: # Add input resistor between external input and schmitt input self.parts.append( Resistor(resistance=self.input_resistance).insert( self.inp, self.schmittinverter.input ) ) else: # Direct connection from external input to schmitt input self.nets.append(self.inp + self.schmittinverter.input) # Handle output connection with optional series resistor if self.series_output_resistance is not None: # Add series resistor between schmitt output and final output self.parts.append( Resistor(resistance=self.series_output_resistance).insert( self.schmittinverter.output, self.out ) ) else: # Direct connection from schmitt output to final output self.nets.append(self.schmittinverter.output + self.out)
BOARD_W = 50.0 BOARD_H = 100.0 COPPER_ISO = 0.1 # LED footprint parameters for checks (match your physical choices) LED_DIAM = 6.0 # mm LED_TAIL = 2.0 # extra reach along the orientation LED_CLEAR = 0.25 # safety margin in tests
[docs] class Gourd(Board): shape = rectangle(BOARD_W, BOARD_H, radius=2)
[docs] class Driver(Circuit): power = Power() ctrl = Port() cap = [Port(), Port(), Port()] def __init__(self): self.sc = [schmitt(), schmitt()] # Connect schmitt inverter grounds to driver ground and create VCC ports nets_list = [] for s in self.sc: nets_list.append(s.power + self.power) self.nets = nets_list self.parts = [] # Create parametric Schmitt inverters with passives in a list self.inverters = [ # f1 and f2: Basic feedback configuration for capacitive touch inputs with series output resistance SchmittInverterWithPassives( feedback_resistance=10e6, series_output_resistance=10e6 ), SchmittInverterWithPassives( feedback_resistance=10e6, series_output_resistance=10e6 ), # s1 and s2: Oscillator configuration with timing capacitors SchmittInverterWithPassives( feedback_resistance=3.3e6, input_capacitance=100e-9, series_output_resistance=15e6, ), SchmittInverterWithPassives( feedback_resistance=4.7e6, input_capacitance=100e-9, series_output_resistance=15e6, ), ] # Connect specific inputs and outputs # f1 and f2 inputs to capacitive touch ports self.nets.append(self.inverters[0].schmittinverter.input + self.cap[0]) # f1 self.nets.append(self.inverters[1].schmittinverter.input + self.cap[1]) # f2 # Create required SchmittInverter ports and connect them inverter_ports = [self.require(SchmittInverter) for _ in self.inverters] # Connect each parametric circuit to its required SchmittInverter port for inv_circuit, inv_port in zip(self.inverters, inverter_ports): self.nets.append(inv_circuit.schmittinverter + inv_port) # Connect grounds for all inverters for inv_circuit in self.inverters: self.nets.append(inv_circuit.gnd + self.power.Vn) # All outputs to cap[2] (f1, f2, s1, s2) for inv_circuit in self.inverters: self.nets.append(inv_circuit.out + self.cap[2]) self.buffer = opamp() self.parts.append( Capacitor(capacitance=4.7e-6).insert( self.buffer.Vp, self.buffer.Vn, short_trace=True ) ) self.nets.append(self.buffer.OUT + self.ctrl) self.nets.append(self.cap[2] + self.buffer.INp) self.nets.append( self.buffer.OUT + self.buffer.INn ) # Feedback for non-inverting buffer self.nets.append(self.buffer.Vp + self.power.Vp) # Positive supply self.nets.append(self.buffer.Vn + self.power.Vn) # Ground @provide(SchmittInverter) def provide_inverter(self, bundle: SchmittInverter): for s in self.sc: yield from [ { bundle.input: s.inv.P_1A, bundle.output: s.inv.P_1Y, }, { bundle.input: s.inv.P_2A, bundle.output: s.inv.P_2Y, }, { bundle.input: s.inv.P_3A, bundle.output: s.inv.P_3Y, }, { bundle.input: s.inv.P_4A, bundle.output: s.inv.P_4Y, }, { bundle.input: s.inv.P_5A, bundle.output: s.inv.P_5Y, }, { bundle.input: s.inv.P_6A, bundle.output: s.inv.P_6Y, }, ]
[docs] class Lit(Circuit): power = Power() def __init__(self): # LED facing "down" by default; caller will rotate instance by Rect.angle self.l = led().at(0, -3.25) # Add 680 ohm resistor self.resistor = Resistor(resistance=680).insert(self.l.p[1], self.power.Vn) self.nets = [self.power.Vp + self.l.p[2]] self.sm = Soldermask(shape=Circle(radius=3.0)) self.v = KeepOut(pour=True, shape=Circle(radius=3.2), layers=LayerSet(0))
[docs] class Mondrian(Circuit): def __init__(self): # Generate rectangles (roles + angles included) rects = rectangles.mondrian_bsp( width=BOARD_W - 2.0, # slight inset from the board outline height=BOARD_H - 2.0, line_thickness=0.75, min_size=6.0, seed=6, role_weights={"mask": 0.45, "void": 0.1, "led": 0.08}, colors={"mask": "#e5e5e5", "void": "#928647", "led": "#900d1a"}, led_diam=LED_DIAM, led_extra=LED_TAIL, led_clearance=LED_CLEAR, led_count=8, ) # Soldermask for all rectangles self.sms = [Soldermask(rectangle(r.w, r.h).at(r.cx, r.cy)) for r in rects] # KeepOut (void) for 'void' and 'led' roles self.voids = [ KeepOut( pour=True, shape=rectangle(r.w, r.h).at(r.cx, r.cy), layers=LayerSet(0) ) for r in rects if r.role in ("void", "led") ] # Driver circuit with schmitt inverters self.gnd = Net(name="GND") self.vcc = Net(name="VCC") self.driver = Driver() self.battery = Bat() self.nets = [] self.gnd += self.battery.p[1] self.vcc += self.battery.p[2] self.gnd += self.driver.power.Vn self.vcc += self.driver.power.Vp self.ls = [] self.rs = [] cval = [6.8e-9, 8.2e-9, 10e-9, 12e-9, 15e-9, 18e-9, 22e-9, 27e-9] # Create parametric Schmitt inverter circuits for LEDs self.led_drivers = [] for r in rects: if r.role == "led": rot = (r.angle - 270.0) % 360 inst = Lit().at(r.cx, r.cy, rotate=rot, on=Side.Bottom) self.ls.append(inst) # Connect each LED's VCC to the main power supply self.vcc += inst.power.Vp # Create parametric Schmitt inverter with passives for this LED led_driver = SchmittInverterWithPassives( feedback_resistance=330e3, input_capacitance=cval.pop(0), input_resistance=330e3, ) self.led_drivers.append(led_driver) dr = self.driver.require(SchmittInverter) # Connect LED driver ground and output self.nets.append(led_driver.schmittinverter + dr) self.nets.append(led_driver.gnd + self.gnd) self.nets.append(led_driver.out + inst.power.Vn) # Connect driver control to LED driver input (330k resistor now internal) self.nets.append(led_driver.inp + self.driver.ctrl) # Create capacitive touch sensors self.pokes = [ CapTouch(10.0, 40.0, 0.1), CapTouch(12.0, 40.0, 0.1), CapTouch(10.0, 40.0, 0.1), ] # Connect each touch sensor: B to ground, A to driver capacitor ports for poke, cap_port in zip(self.pokes, self.driver.cap): self.gnd += poke.B self.nets.append(poke.A + cap_port) # Connect touch sensor to driver input # Build the nets list self.gnd += Pour(layer=1, shape=current.design.board.shape, isolate=COPPER_ISO) self.vcc += Pour(layer=0, shape=current.design.board.shape, isolate=COPPER_ISO) self.gnd.symbol = GroundSymbol() self.vcc.symbol = PowerSymbol()
[docs] class Resistors(SampleDesign): resistor_defaults = ResistorQuery(case="0402", tolerance=0.01) capacitor_defaults = CapacitorQuery(case="0402") board = Gourd() circuit = Mondrian()