def main(): if len(sys.argv) < 2: # read from stdin layout_json = sys.stdin.read() netlist_file = "keyboard.net" layout_output = "keyboard.layout" else: # read from file f_name = sys.argv[1] # TODO evaluate if this is appropriate behaviour... f_name_root = f_name if f_name.endswith(".json"): f_name_root = f_name.replace(".json", "") netlist_file = f_name_root + ".net" layout_output = f_name_root + ".layout" with open(f_name) as f: layout_json = f.read() original_layout = json_to_layout(layout_json) layout = min_pin_assignment(original_layout) with open(layout_output, 'w') as l_out_file: print(layout.to_json(), file=l_out_file) skidl_setup() row_nets = [Net('row{}'.format(i)) for i in range(layout.rows)] col_nets = [Net('col{}'.format(j)) for j in range(layout.cols)] for key in layout.keys: get_key_module(key.row, key.col, row_nets, col_nets) connect_microcontroller(row_nets, col_nets) generate_netlist(file_=netlist_file)
def __init__(self, store, pcb, is_mx=True, is_hotswap=True): self._partstore = store self.__key_matrix_rows = [] self.__key_matrix_cols = [] self.__key_matrix_keys = None self.__pcb = pcb self.__vcc = Net('VCC') self.__gnd = Net('GND') self.__led_din_pin = None self.__led_dout_pin = None self.__key_matrix_x = 0 self.__key_matrix_y = 0 self.__legend_rows = [] self.__legend_cols = [] self._is_mx = is_mx self._is_hotswap = is_hotswap self._prior_y = -1 self.__led_din_pin_name = None
def spi(self, instance): """ If additional devices are connected to the ISP lines, the programmer must be protected from any device that may try to drive the lines, other than the AVR. This is important with the SPI bus, as it is similar to the ISP interface. Applying series resistors on the SPI lines, as depicted in Connecting the SPI Lines to the ISP Interface, is the easiest way to achieve this. Typically, the resistor value R can be of 330тДж """ mosi = Net('MOSI') miso = Net('MISO') sck = Net('SCK') isp_mosi = self['MOSI'] & Resistor()( 330 @ u_Ohm) & mosi & instance['MOSI'] isp_miso = self['MISO'] & Resistor()( 330 @ u_Ohm) & miso & instance['MISO'] isp_sck = self['SCK'] & Resistor()(330 @ u_Ohm) & sck & instance['SCK'] for pin in ['MOSI', 'MISO', 'SCK']: instance[pin].disconnect() instance_pin = instance[pin] instance_pin += self[pin] self.MOSI = mosi self.MISO = miso self.SCK = sck
def part_spice(self): from skidl.pyspice import K Transformer = { '1': Net('TransformerInputP'), '2': Net('TransformerInputN'), '3': Net('TransformerOutputP'), '4': Net('TransformerOutputN') } Spacer = Resistor()(value=1 @ u_Ohm) # Lin = L(value=100 @ u_H) Lin = RLC(series=['L', 'R'])( R_series = 1 @ u_Ohm, L_series = 10 @ u_H ) Lout = RLC(series=['L', 'R'])( R_series = 1 @ u_Ohm, L_series = .5 @ u_H ) primary = Transformer['1'] & Lin & Transformer['2'] secondary = Transformer['3'] & Lout & Transformer['4'] transformer = K(inductor1='L_s', inductor2='L_s_1', coupling_factor=self.coupling_factor) return Transformer
def generate_wemos_d1_mini(): """Generate Wemos D1 footprint""" subcircuit_label('wemos_d1_mini') global U1 U1 = Part('MCU_Module', 'WeMOs_D1_mini', footprint='Module:WEMOS_D1_mini_light') U1['5V'] += Net.fetch('+VBatt') U1['GND'] += Net.fetch('GND')
def connect_parts(a, b): """Connect pins with same name of two parts""" flatten = itertools.chain.from_iterable a_pins = list(flatten([pin.name.split("/") for pin in a.get_pins()])) b_pins = list(flatten([pin.name.split("/") for pin in b.get_pins()])) common_pins = [value for value in a_pins if value in b_pins] for pin_name in common_pins: a[pin_name] += Net.fetch(pin_name) b[pin_name] += Net.fetch(pin_name)
def circuit(self, *args, **kwargs): transformer = self.part() self.v_ref = Net() self.gnd = Net() self.input = transformer['1'] self.input_n = transformer['2'] self.output = transformer['3'] self.output_n = transformer['4']
def generate_esp(): """Generate ESP-module code to circuit""" subcircuit_label('esp') global U1 U1 = Part('RF_Module', 'ESP-12E', footprint='RF_Module:ESP-12E') U1['VCC'] += Net.fetch('+3V3') U1['GND'] += Net.fetch('GND') U1['EN'] & R('10k') & Net.fetch('+3V3') U1['GPIO15'] & R('4k7') & Net.fetch('GND') @subcircuit def generate_power_led(): """Generate led connected to ESP GPI0 that is on after boot""" subcircuit_label('power_led') led = Part('Device', 'LED', footprint='LED_SMD:LED_1206_3216Metric') U1['GPIO0'] & (R('1k') & led & Net.fetch('+3V3')) generate_power_led() # Generate button for pulling ESP RST pin to low (e.g. reset) sw_reset = Part('Switch', 'SW_Push', footprint="Button_Switch_SMD:SW_SPST_B3U-1000P") sw_reset[1] += Net.fetch('RST') sw_reset[2] += Net.fetch('GND') # Generate ESP serial networks U1['TX'] += Net.fetch('tx') U1['RX'] += Net.fetch('rx')
def circuit(self): transistor = self.element = self.part() common = self.props.get('common', 'emitter') follow = self.props.get('follow', 'collector') common_end = self.gnd if not common: common_end = Net('NC') elif type(common) == NetType: common_end = common if common and self[common]: common_line = transistor[common] & self[common] & common_end elif common and common: common_end += transistor[common] input_side = 'emitter' if common == 'base' else 'base' if self[input_side]: input_line = self.input & self[input_side] & transistor[input_side] else: self.input += transistor[input_side] v_ref_side = 'emitter' if common == 'collector' else 'collector' if self[v_ref_side]: v_ref_line = self.v_ref & self[v_ref_side] & transistor[v_ref_side] else: self.v_ref += transistor[v_ref_side] self.collector, self.base, self.emitter = transistor['collector', 'base', 'emitter'] self.output += self[follow]
def part_aliases(block): if not hasattr(block, 'selected_part'): return if not hasattr(block.selected_part, 'pins'): return units = defaultdict(lambda: defaultdict(list)) for pin in block.selected_part.pins: units[pin.unit][pin.block_pin].append(pin.pin) units = dict(units) if not units.get(block.unit, None): return for block_pin in units[block.unit].keys(): for part_pin in units[block.unit][block_pin]: pin_number = int(part_pin.split('/')[1]) device_name = block.name.replace('.', '') net_name = device_name + ''.join( [word.capitalize() for word in block_pin.split('_')]) + str(pin_number) pin_net = Net(net_name) pin_net += block._part[pin_number] setattr(block, block_pin, pin_net)
def generate_esp(): """Generate ESP-module code to circuit""" global U1 U1 = Part('RF_Module', 'ESP-12E', footprint='RF_Module:ESP-12E') U1['VCC'] += Net.fetch('+VBatt') U1['GND'] += Net.fetch('GND') U1['EN'] & R('10k') & Net.fetch('+VBatt') U1['GPIO15'] & R('4k7') & Net.fetch('GND') @subcircuit def generate_power_led(): """Generate led connected to ESP GPI0 that is on after boot""" led = Part('Device', 'LED', footprint='LED_SMD:LED_1206_3216Metric') U1['GPIO0'] & (R('1k') & led & Net.fetch('+VBatt')) generate_power_led()
def generate_esp_uart_reset(): """Generate reset circuitry for ESP""" subcircuit_label('esp_uart_reset') Q1 = Part('Device', 'Q_NPN_BEC', value='mmbt2222', footprint='Package_TO_SOT_SMD:SOT-23') Q2 = Part('Device', 'Q_NPN_BEC', value='mmbt2222', footprint='Package_TO_SOT_SMD:SOT-23') Net.fetch('DTR') & R('10k') & Q1['B'] Net.fetch('RTS') & R('10k') & Q2['B'] Net.fetch('DTR') & Q2['E'] Net.fetch('RTS') & Q1['E'] Q1['C'] & Net.fetch('RST') Q2['C'] & Net.fetch('GPIO0')
def circuit(self, *args, **kwargs): super().circuit(*args, **kwargs) signal = self.output self.output = Net('SignalClampedOutput') restoration = signal & Capacitor()( value=1 @ u_uF) & self.output & Diode( type='generic')()['K', 'A'] & self.gnd
def connect_keyswitch_and_diode(self, key, keysw_part, diode_part): net = Net("%s_%s" % (keysw_part.ref, diode_part.ref)) net += keysw_part[2], diode_part[2] # COL2ROW means the connection goes COL_ to switch to diode anode # to diode cathode to ROW_. See # https://github.com/qmk/qmk_firmware/blob/master/docs/config_options.md self.assign_matrix_location_to_key(key) self.connect_to_matrix(keysw_part[1], diode_part[1])
def circuit(self): super().circuit() output = Net('SignalRecrifiedOutput') rectifier = self & \ Differentiator(via='rc')() & \ Rectifier(wave='half')() & \ output self.output = output
def create_matrix_nets(self, key_count, key_row_count, key_col_count, gpio_count): if key_row_count + key_col_count <= gpio_count: row_count = key_row_count col_count = key_col_count self._conserve_cols = False else: import math square_matrix_size = math.ceil(math.sqrt(key_count)) if square_matrix_size * 2 >= gpio_count: raise OverflowError("not enough GPIOs for this keyboard") row_count = square_matrix_size col_count = square_matrix_size self._conserve_cols = True for y in range(0, row_count): self.__key_matrix_rows.append(Net("ROW_%d" % (y + 1))) for x in range(0, col_count): self.__key_matrix_cols.append(Net("COL_%d" % (x + 1))) self.__key_matrix_keys = [[None] * col_count for i in range(row_count)]
def circuit(self): super().circuit() R = Resistor() D = Diode(type='generic') signal = self.output self.output = Net('SignalLimitedOutput') limiter = signal & R(1000 @ u_Ohm) & self.output & (D() | D()) & self.v_ref
def circuit(self, *args, **kwargs): self.element = element = self.part(*args, **kwargs) # Ground problem fix if self.wire_gnd == True: gnd = Net.get('0') if not gnd: gnd = Net('0') gnd.fixed_name = True element['-'] & gnd # TODO: Probably bad idea, because you could mixing voltage sources self.output.fixed_name = True gnd & self.gnd self.v_ref & element['+'] & self.output self.gnd & element['-'] & self.input
def circuit(self): super().circuit() signal = self.output self.output = Net('FilterTrapOutput') rin = Resistor()(value=self.R_trap, ref='R_in') lc = RLC(series=['L', 'C'])(L_series=self.L_notch, C_series=self.C_notch) lc.output += self.gnd circuit = signal & rin & (self.output | lc.input)
def circuit(self): super().circuit() self.output_inverse = self.output_n self.output_n = Net('BridgeOutputGround') C = Capacitor(**self.mods, **self.props) self.C_ripple = self.I_load / (self.Frequency * self.V_ripple) @ u_F C_ripple_out = C(self.C_ripple) C_ripple_inv = C(self.C_ripple) circuit = self.output & C_ripple_out & self.output_n & C_ripple_inv & self.output_inverse
def set_spice_enviroment(): Block.scope = [] Block.refs = [] set_backup_lib('.') set_default_tool(SPICE) builtins.SIMULATION = True scheme = Circuit() scheme.units = defaultdict(list) builtins.default_circuit.reset(init=True) del builtins.default_circuit builtins.default_circuit = scheme scheme.NC = Net('NC') builtins.NC = scheme.NC
def generate_mcp73831(): """Generate MCP73831 battery management IC""" subcircuit_label('mcp73831') BATTERYMANAGER = Part('Battery_Management', 'MCP73831-2-OT', footprint='Package_TO_SOT_SMD:SOT-23-5') BM_LED = Part('Device', 'LED', footprint='LED_SMD:LED_1206_3216Metric') BATTERYMANAGER['STAT'] & R('1k') & BM_LED & Net.fetch('+VBus') BATTERYMANAGER['VSS'] += Net.fetch('GND') Net.fetch('GND') & R('2k') & BATTERYMANAGER['PROG'] Net.fetch('+VLipo') & C('10uF') & Net.fetch('GND')
def circuit(self): new_outputs = [] for signal in self.inputs: inverted = Net('LogicInverted') inverter = Bipolar(type='npn', common='emitter', follow='collector')( collector = Resistor()(1000), base = Resistor()(10000) ) inverter.v_ref += self.v_ref inverter.gnd += self.gnd circuit = signal & inverter & inverted new_outputs.append(inverted) self.outputs = new_outputs
def circuit(self): transistor = self.element = self.part(model=self.model) common = self.props.get('common', 'source') follow = self.props.get('follow', 'drain') if not self.gnd: self.gnd = Net('FieldGnd') common_end = self.gnd if not common: common_end = Net('NC') elif type(common) == NetType: common_end = common if common and self[common]: common_line = transistor[common] & self[common] & common_end elif common and common: common_end += transistor[common] input_side = 'source' if common == 'gate' else 'gate' if self[input_side]: input_line = self.input & self[input_side] & transistor[input_side] else: self.input += transistor[input_side] v_ref_side = 'source' if common == 'drain' else 'drain' if self[v_ref_side]: v_ref_line = self.v_ref & self[v_ref_side] & transistor[v_ref_side] else: self.v_ref += transistor[v_ref_side] self.drain, self.gate, self.source = transistor['drain', 'gate', 'source'] self.output += self[follow]
def circuit(self): super().circuit() signal = self.output self.output = Net('SignalClampedOutput') Rref = None clamp = Diode(type='generic')() if self.V_out and self.V and self.V > self.V_out: Rref = Divider(type='resistive')(V=self.V, V_out=self.V_out - clamp.V_j, Load=self.I_load * 10) Rref.gnd += self.gnd else: Rref = Resistor()(667) self.v_ref & Rref & clamp['K', 'A'] & self.output signal_input = signal & Resistor()(self.R_load / 3) & self.output
def generate_esp(): """Generate ESP-module code to circuit""" global U1 U1 = Part('RF_Module', 'ESP-12E', footprint='RF_Module:ESP-12E') U1['VCC'] += Net.fetch('+VBatt') U1['GND'] += Net.fetch('GND') U1['EN'] & R('10k') & Net.fetch('+VBatt') U1['GPIO15'] & R('4k7') & Net.fetch('GND') U1['RST'] += Net.fetch('RST') U1['GPIO16'] += Net.fetch('RST') @subcircuit def generate_power_led(): """Generate led connected to ESP GPI0 that is on after boot""" led = Part('Device', 'LED', footprint='LED_SMD:LED_1206_3216Metric') U1['GPIO0'] & (R('1k') & led & Net.fetch('+VBatt')) generate_power_led() # Generate button for pulling ESP RST pin to low (e.g. reset) sw_reset = Part('Switch', 'SW_Push', footprint="Button_Switch_SMD:SW_SPST_B3U-1000P") sw_reset[1] += Net.fetch('RST') sw_reset[2] += Net.fetch('GND') # Generate button for pulling pulling ESP GPIO0 low (e.g. flash mode when booting) sw_flash = Part('Switch', 'SW_Push', footprint="Button_Switch_SMD:SW_SPST_B3U-1000P") sw_flash[1] += U1['GPIO0'] sw_flash[2] += Net.fetch('GND')
def buck_impl(pwm: Net, v_in: Net, v_out: Net, gnd: Net): buck_inner_net = Net('buck_inner') nmos_inst = nmos.copy() nmos_inst['gate'] = pwm nmos_inst['drain'] = v_in nmos_inst['source'] = buck_inner_net inductor_inst = inductor.copy() inductor_inst['+'] = buck_inner_net inductor_inst['-'] = v_out diode_inst = diode.copy() diode_inst['-'] = buck_inner_net diode_inst['+'] = gnd cap_input_inst = cap_input.copy() cap_input_inst['+'] = v_in cap_input_inst['-'] = gnd cap_output_inst = cap_output.copy() cap_output_inst['+'] = v_in cap_output_inst['-'] = gnd
def generate_power_led(): """Generate led connected to ESP GPI0 that is on after boot""" led = Part('Device', 'LED', footprint='LED_SMD:LED_1206_3216Metric') U1['GPIO0'] & (R('1k') & led & Net.fetch('+VBatt'))
def add_controller(): nets["+5v"] = Net("+5v") nets["GND"] = Net("GND") parts["U1"] = Part('/Users/swilson/dev/kicad-library/library/atmel.lib', 'ATMEGA32U4-AU', ref="U1", footprint='Housings_QFP:TQFP-44_10x10mm_Pitch0.8mm') for c in ("C4", ): parts[c] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'C', ref=c, value="1µF", footprint='Capacitors_SMD:C_0805') for c in ("C3", "C7", "C6", "C8", "C9"): parts[c] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'C', ref=c, value="0.1µF", footprint='Capacitors_SMD:C_0805') for c in ("C1", "C2"): parts[c] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'C', ref=c, value="18pF", footprint='Capacitors_SMD:C_0805') parts["C5"] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'C', ref="C5", value="4.7µF", footprint='Capacitors_SMD:C_1206') for r in ("R1", ): parts[r] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'R', ref=r, value="10k", footprint='Resistors_SMD:R_0805') for r in ("R4", "R5"): parts[r] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'R', ref=r, value="22", footprint='Resistors_SMD:R_0805') for r in ("R2", "R3"): parts[r] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'R', ref=r, value="4.7k", footprint='Resistors_SMD:R_0805') # for r in ("R7", "R8"): # parts[r] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'R', ref=r, value="120", footprint='Resistors_SMD:R_0805') # parts["R6"] = Part('/Users/swilson/dev/kicad-library/library/device.lib', 'R', ref="R6", value="150", footprint='Resistors_SMD:R_0805') parts["F1"] = Part('/Users/swilson/dev/mechkeys/kicad-libs/device.lib', 'FP_Small', ref="F1", footprint='Capacitors_SMD:C_1206') parts["P1"] = Part('/Users/swilson/dev/kicad-library/library/conn.lib', 'USB_OTG', ref="P1", footprint='Capacitors_SMD:C_1206') parts["Y1"] = Part('/Users/swilson/dev/mechkeys/kicad-libs/device.lib', 'CRYSTAL_SMD', ref="Y1", footprint='Crystals:Crystal_SMD_5032_4Pads') parts["RESET"] = Part('/Users/swilson/dev/mechkeys/kicad-libs/device.lib', 'SW_PUSH', ref="S1", footprint='Buttons_Switches_SMD:SW_SPST_EVQP0') # parts["RGB33"] = Part('/Users/swilson/dev/mechkeys/kicad-libs/device.lib', 'Led_RGB_CA', ref="RGB33", footprint='Keyboard:SMP4-RGB-PIPE') # Power nets["+5v"] += parts["U1"]["VCC,VBUS"] nets["+5v"] += parts["F1"][2] # nets["+5v"] += parts["RGB33"][1] nets["+5v"] += parts["R1"][1] nets["GND"] += parts["U1"]["GND"] nets["GND"] += parts["U1"]["PE2"] for ref in ("C5", "C6", "C7", "C8", "C9"): nets["+5v"] += parts[ref][1] nets["GND"] += parts[ref][2] # XTAL parts["U1"]["XTAL1"] += parts["Y1"][1] parts["U1"]["XTAL1"] += parts["C1"][2] parts["U1"]["XTAL2"] += parts["Y1"][2] parts["U1"]["XTAL2"] += parts["C2"][2] nets["GND"] += parts["Y1"]["case"] nets["GND"] += parts["C1"][1] nets["GND"] += parts["C2"][1] # USB nets["VBUS"] += parts["P1"]["VBUS"] nets["VBUS"] += parts["F1"][1] nets["USB-"] += parts["P1"]["D-"] nets["USB-"] += parts["R4"][2] nets["USB+"] += parts["P1"]["D\+"] nets["USB+"] += parts["R5"][2] nets["D-"] += parts["R4"][1] nets["D-"] += parts["U1"]["D-"] nets["D+"] += parts["R5"][1] nets["D+"] += parts["U1"]["D\+"] nets["GND"] += parts["P1"]["GND"] nets["GND"] += parts["P1"]["shield"] # MCU parts["U1"]["UCAP"] += parts["C3"][1] nets["GND"] += parts["C3"][2] parts["U1"]["AREF"] += parts["C4"][1] nets["GND"] += parts["C4"][2] nets["RESET"] += parts["U1"]["RESET"] nets["RESET"] += parts["RESET"][1] nets["RESET"] += parts["R1"][2] nets["GND"] += parts["RESET"][2] for k, v in matrix_to_mcu.items(): print(k, v) nets[k] += parts["U1"][v] # I2C nets["+5v"] += parts["R2"][1] nets["LED_SCL"] += parts["R2"][2] nets["LED_SCL"] += parts["U1"]["SCL/"] nets["+5v"] += parts["R3"][1] nets["LED_SDA"] += parts["R3"][2] nets["LED_SDA"] += parts["U1"]["SDA/"] # USB Connector parts["P2"] = Part( '/Users/swilson/dev/kicad-library/library/conn.lib', 'CONN_01X05', ref="P2", footprint='Connectors_JST:JST_SH_SM05B-SRSS-TB_05x1.00mm_Angled') nets["VBUS"] += parts["P2"][5] nets["USB-"] += parts["P2"][4] nets["USB+"] += parts["P2"][3] nets["GND"] += parts["P2"][1] # ISP Connector parts["P3"] = Part( '/Users/swilson/dev/kicad-library/library/conn.lib', 'CONN_02X03', ref="P3", footprint='Connectors_JST:JST_SH_SM06B-SRSS-TB_06x1.00mm_Angled') nets["+5v"] += parts["P3"][2] nets["GND"] += parts["P3"][6] nets["RESET"] += parts["P3"][5] parts["P3"][1] += parts["U1"]["MISO"] parts["P3"][3] += parts["U1"]["SCLK"] parts["P3"][4] += parts["U1"]["MOSI"] # USB Connector parts["P4"] = Part( '/Users/swilson/dev/kicad-library/library/conn.lib', 'CONN_01X03', ref="P4", footprint='Connectors_JST:JST_SH_SM03B-SRSS-TB_03x1.00mm_Angled') nets["+5v"] += parts["P4"][2] nets["GND"] += parts["P4"][1] parts["P4"][3] += parts["U1"]["PC6"]
from skidl import Part, Net, ERC, TEMPLATE, generate_netlist from solderstation.signal import voltage_divider FOOTPRINT_R_0603 = 'Resistor_SMD:R_0603_1608Metric' if __name__ == '__main__': v_in = Net('v_in') out = Net('out') gnd = Net('gnd') voltage_divider(Part('Device', 'R', footprint=FOOTPRINT_R_0603, dest=TEMPLATE), ratio=(24, 2))(v_in=v_in, gnd=gnd, out=out) ERC() generate_netlist()