#!/usr/bin/env python3 """PM_K-1 MIDI block (SKiDL) -- DNP populate-option: opto-isolated IN + buffered OUT + THRU. Run INSIDE the EDA container: cd hardware/eda && ./run.sh python3 ../eda/circuits/midi.py Outputs ERC + hardware/kicad/midi.net. USB-MIDI is the DEFAULT (firmware). This hardware DIN/TRS MIDI is a DO-NOT-POPULATE option for laptop-free sync to standalone gear (a "stage" face fits the connector + parts). IN : opto-isolated (H11L1) -- breaks the ground loop the MIDI spec requires. OUT : RP2350 UART TX -> 74LVC14 buffer (2 inverters = non-inverting) -> series R. THRU: a buffered copy of the received IN signal (re-transmit), same buffer chip. PINOUTS * 74LVC14 hex Schmitt inverter: standard 14-pin (1A/1Y..6A/6Y, GND=7, VCC=14). * H11L1 6-pin Schmitt opto: standard 1=Anode 2=Cathode 3=NC 4=GND 5=VO 6=VCC (universal across makers of this part; datasheet fetch timed out -- reconfirm at layout). CONFIRM: the series-resistor values for 3.3V MIDI per the MIDI Association spec (placeholders below). Connector (TRS-MIDI Type-A vs DIN-5) is a FACE choice; the core exposes the loop nets. """ import os from skidl import * set_default_tool(KICAD9) P = Pin.types R = Part("Device","R", dest=TEMPLATE, footprint="Resistor_SMD:R_0402_1005Metric") def C(v): return Part("Device","C", value=v, footprint="Capacitor_SMD:C_0402_1005Metric") D = Part("Device","D", dest=TEMPLATE, footprint="Diode_SMD:D_SOD-323") p3v3, gnd = Net("+3V3"), Net("GND") p3v3.drive = POWER; gnd.drive = POWER midi_tx, midi_rx = Net("MIDI_TX"), Net("MIDI_RX") # to/from RP2350 UART (assign free GPIO at integ.) in_a, in_b = Net("MIDI_IN_A"), Net("MIDI_IN_B") # isolated current loop -> face connector out_a, out_b = Net("MIDI_OUT_A"), Net("MIDI_OUT_B") thru_a, thru_b = Net("MIDI_THRU_A"), Net("MIDI_THRU_B") OPTO = Part(name="H11L1", tool=SKIDL, dest=TEMPLATE, ref_prefix="U", footprint="Package_DIP:DIP-6_W7.62mm", pins=[Pin(num=1,name="A",func=P.PASSIVE),Pin(num=2,name="C",func=P.PASSIVE),Pin(num=3,name="NC",func=P.NOCONNECT), Pin(num=4,name="GND",func=P.PWRIN),Pin(num=5,name="VO",func=P.OPENCOLL),Pin(num=6,name="VCC",func=P.PWRIN)]) BUF = Part(name="74LVC14", tool=SKIDL, dest=TEMPLATE, ref_prefix="U", footprint="Package_SO:TSSOP-14_4.4x5mm_P0.65mm", pins=[Pin(num=1,name="1A",func=P.INPUT),Pin(num=2,name="1Y",func=P.OUTPUT),Pin(num=3,name="2A",func=P.INPUT), Pin(num=4,name="2Y",func=P.OUTPUT),Pin(num=5,name="3A",func=P.INPUT),Pin(num=6,name="3Y",func=P.OUTPUT), Pin(num=7,name="GND",func=P.PWRIN),Pin(num=8,name="4Y",func=P.OUTPUT),Pin(num=9,name="4A",func=P.INPUT), Pin(num=10,name="5Y",func=P.OUTPUT),Pin(num=11,name="5A",func=P.INPUT),Pin(num=12,name="6Y",func=P.OUTPUT), Pin(num=13,name="6A",func=P.INPUT),Pin(num=14,name="VCC",func=P.PWRIN)]) opto = OPTO(ref="U8"); buf = BUF(ref="U9") # ---- MIDI IN (opto-isolated) ---- rin = R(value="220"); dprot = D(value="1N4148WS") in_a += rin[1]; rin[2] += opto["A"] # current-limit into LED opto["C"] += in_b # LED return (isolated side) dprot[2] += opto["C"]; dprot[1] += opto["A"] # reverse-protection across the LED (pin1=K,2=A) opto["VCC"] += p3v3; opto["GND"] += gnd rvo = R(value="10k"); opto["VO"] += midi_rx; midi_rx += rvo[1]; rvo[2] += p3v3 # pull-up; received data copt = C("100nF"); p3v3 += copt[1]; copt[2] += gnd # ---- MIDI OUT: TX -> two inverters -> series R ---- buf["1A"] += midi_tx; buf["1Y"] += Net("MIDI_OUT_N") # first invert buf["2A"] += buf["1Y"] # second invert -> non-inverted ro_b = R(value="33"); buf["2Y"] += ro_b[1]; ro_b[2] += out_b ro_a = R(value="33"); p3v3 += ro_a[1]; ro_a[2] += out_a # current-source leg # ---- MIDI THRU: re-buffer the received signal ---- buf["3A"] += midi_rx; buf["3Y"] += Net("MIDI_THRU_N") buf["4A"] += buf["3Y"] rt_b = R(value="33"); buf["4Y"] += rt_b[1]; rt_b[2] += thru_b rt_a = R(value="33"); p3v3 += rt_a[1]; rt_a[2] += thru_a # unused inverters parked, supply buf["5A"] += gnd; buf["6A"] += gnd buf["VCC"] += p3v3; buf["GND"] += gnd cbuf = C("100nF"); p3v3 += cbuf[1]; cbuf[2] += gnd ERC() out = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "kicad", "midi.net")) generate_netlist(file_=out) print("MIDI netlist ->", out)