mohan-bee/rc-link-breakaway-panel

A four-layer RC link panel combining an STM32/E28 2.4‑GHz transmitter with USB-RP2040 socket and an STM32/E28 receiver providing six buffered PWM servo outputs, regulated 3.3‑V power, headers, controls, and protection/decoupling.

Version
0.1.5
License
unset
Stars
0

circuits/transmitter/index.circuit.tsx

import pourOutline from "./pour-outline.json";
import { reviewedRouting } from "./routing/reviewed-routing";
import { XiaoSocket } from "./XiaoSocket";
import { TS_1187A_B_A_B as Button } from "./EnableButton";
import { STM32G431KBT6 } from "./imports/STM32G431KBT6";
import { E28_2G4M12S } from "./imports/E28_2G4M12S";
import { AP2112K_3_3TRG1 } from "./imports/AP2112K_3_3TRG1";
import { TAXM8M4RDBCCT2T } from "./imports/TAXM8M4RDBCCT2T";

const pins = [
  ["U_TX_USB",6,"RF_ENABLE"],["U_TX_USB",13,"GND"],["U_TX_USB",12,"USB_3V3"],["U_TX_USB",14,"USB_5V"],
  ["U_TX_USB",7,"HOST_TX"],["U_TX_USB",8,"HOST_RX"],["U_TX_USB",1,"ENABLE_N"],["U_TX_USB",2,"STOP_N"],["U_TX_USB",3,"STATUS"],
  ["U_TX_MCU",1,"RF_3V3"],["U_TX_MCU",17,"RF_3V3"],["U_TX_MCU",15,"VDDA"],
  ["U_TX_MCU",14,"GND"],["U_TX_MCU",16,"GND"],["U_TX_MCU",32,"GND"],
  ["U_TX_MCU",2,"HSE_IN"],["U_TX_MCU",3,"HSE_OUT"],["U_TX_MCU",4,"NRST"],
  ["U_TX_MCU",9,"RF_NSS"],["U_TX_MCU",10,"RF_SCK"],["U_TX_MCU",11,"RF_MISO"],["U_TX_MCU",12,"RF_MOSI"],
  ["U_TX_MCU",27,"RF_IRQ"],["U_TX_MCU",28,"RF_BUSY"],["U_TX_MCU",29,"RF_RESET"],
  ["U_TX_MCU",26,"CRSF"],["U_TX_MCU",21,"BIND_N"],["U_TX_MCU",23,"SWDIO"],["U_TX_MCU",24,"SWCLK"],["U_TX_MCU",31,"BOOT0"],
  ["U_TX_RF",1,"RF_3V3"],["U_TX_RF",2,"GND"],["U_TX_RF",7,"GND"],["U_TX_RF",8,"GND"],["U_TX_RF",14,"GND"],
  ["U_TX_RF",3,"RF_MISO"],["U_TX_RF",4,"RF_MOSI"],["U_TX_RF",5,"RF_SCK"],["U_TX_RF",6,"RF_NSS"],
  ["U_TX_RF",9,"RF_RESET"],["U_TX_RF",10,"RF_BUSY"],["U_TX_RF",11,"RF_IRQ"],
  ["U_TX_LDO",1,"USB_5V"],["U_TX_LDO",3,"RF_ENABLE"],["U_TX_LDO",2,"GND"],["U_TX_LDO",5,"RF_3V3"],
  ["X_TX_1",1,"HSE_IN"],["X_TX_1",3,"HSE_OUT"],["X_TX_1",2,"GND"],["X_TX_1",4,"GND"],
  ["J_TX_SWD",1,"RF_3V3"],["J_TX_SWD",2,"GND"],["J_TX_SWD",3,"SWDIO"],["J_TX_SWD",4,"SWCLK"],["J_TX_SWD",5,"NRST"],
] as const;
const resistors = [
  ["R_TX_PWR_PD","100k",-7,17,"RF_ENABLE","GND"],["R_TX_TX","220",-8,2,"HOST_TX","CRSF"],["R_TX_RX","220",-4,5,"CRSF","HOST_RX"],["R_TX_BUS","10k",0,2,"CRSF","GND"],
  ["R_TX_ENABLE","10k",-25,-5,"USB_3V3","ENABLE_N"],["R_TX_STOP","10k",-13,-5,"USB_3V3","STOP_N"],
  ["R_TX_LED","1k",-2,-14,"STATUS","LED_A"],["R_TX_RESET","10k",3,-12,"RF_3V3","NRST"],["R_TX_BOOT","10k",17,-7,"BOOT0","GND"],
  ["R_TX_NSS","10k",3,10,"RF_3V3","RF_NSS"],["R_TX_RFRESET","10k",26,10,"RF_3V3","RF_RESET"],["R_TX_VDDA","10",18,-1,"RF_3V3","VDDA"],
] as const;
const caps = [
  ["C_TX_IN","4.7uF",-4,13,"USB_5V"],["C_TX_OUT","4.7uF",0,13,"RF_3V3"],["C_TX_RF","100nF",3,16,"RF_3V3"],["C_TX_RF_BULK","4.7uF",3,19,"RF_3V3"],
  ["C_TX_MCU1","100nF",6,-12,"RF_3V3"],["C_TX_MCU2","100nF",15,1,"RF_3V3"],["C_TX_BULK","4.7uF",2,-6,"RF_3V3"],["C_TX_VDDA","100nF",17,-4,"VDDA"],
  ["C_TX_RESET","100nF",3,-15,"NRST"],["C_TX_ENABLE","100nF",-22,-5,"ENABLE_N"],["C_TX_STOP","100nF",-10,-5,"STOP_N"],
  ["C_TX_X1","12pF",6.2,-14.85,"HSE_IN"],["C_TX_X2","12pF",13,-13.15,"HSE_OUT"],
] as const;
const resistorParts = { "100k": "C25741", "220": "C25091", "10k": "C25744", "1k": "C11702", "10": "C25077" } as const;
const capacitorParts = { "4.7uF": "C23733", "100nF": "C1525", "12pF": "C1547" } as const;
const capacitorVoltages = { "4.7uF": "10V", "100nF": "16V", "12pF": "50V" } as const;
const nets=[...new Set([...pins.map(p=>p[2]),...resistors.flatMap(p=>[p[4],p[5]]),...caps.map(p=>p[4])])];
export default function PhoneTransmitter({pcbX = 0, pcbY = 0}: {pcbX?: number; pcbY?: number} = {}) {
  return <group subcircuit name="TX" pcbX={pcbX} pcbY={pcbY} width="70mm" height="60mm" schTraceAutoLabelEnabled autorouter={{preset:"auto",traceClearance:"0.3mm",allowViaInPad:false}}>
    <autoroutingphase name="txroute" phaseIndex={0} algorithmFn={reviewedRouting} autorouter={{preset:"auto",traceClearance:"0.3mm",allowViaInPad:false}}/>
    <schematicsheet sheetSize="A4" name="TX_usb" displayName="USB and controls" sheetIndex={0}/>
    <schematicsheet sheetSize="A4" name="TX_radio" displayName="mLRS controller and radio" sheetIndex={1}/>
    <schematicsheet sheetSize="A4" name="TX_power" displayName="Power and decoupling" sheetIndex={2}/>
    <schematicsection name="USB controller" schSheetName="TX_usb"/>
    <schematicsection name="Radio" schSheetName="TX_radio"/>
    <schematicsection name="Power" schSheetName="TX_power"/>
    {nets.map(name=><net key={name} name={`TX_${name}`} isGroundNet={name === "GND"} routingPhaseIndex={0} nominalTraceWidth={name==="USB_5V"||name==="RF_3V3"?0.35:0.15}/>)}
    <XiaoSocket/>
    <STM32G431KBT6 name="U_TX_MCU" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={10} pcbY={-6} schX={0} schY={0} schWidth={3.1} schHeight={3.6} schSheetName="TX_radio" schSectionName="Radio"/>
    <E28_2G4M12S name="U_TX_RF" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={15} pcbY={12.5} pcbRotation={180} schX={10} schY={0} schWidth={2.5} schHeight={1.6} schSheetName="TX_radio" schSectionName="Radio"/>
    <AP2112K_3_3TRG1 name="U_TX_LDO" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={-2} pcbY={17} schX={0} schY={6} schSheetName="TX_power" schSectionName="Power"/>
    <TAXM8M4RDBCCT2T name="X_TX_1" pcbStyle={{silkscreenTextVisibility:"hidden"}} loadCapacitance="8pF" pcbX={10} pcbY={-14} schX={6} schY={-6} schSheetName="TX_radio" schSectionName="Radio"/>
    {resistors.map(([name,value,x,y,a,b],i)=><resistor key={name} name={name} pcbStyle={{silkscreenTextVisibility:"hidden"}} resistance={value} supplierPartNumbers={{jlcpcb:[resistorParts[value]]}} cadModel={{glbUrl:"https://modelcdn.tscircuit.com/jscad_models/0402.glb"}} footprint="0402_nosilkscreen" pcbX={x} pcbY={y} pcbRotation={["R_TX_RX","R_TX_RESET"].includes(name)?180:0}
      schRotation={["R_TX_TX","R_TX_RX","R_TX_LED"].includes(name)?0:270} schX={-9+(i%4)*6} schY={1-Math.floor(i/4)*3} schSheetName="TX_power" schSectionName="Power"/>)}
    {caps.map(([name,value,x,y,net],i)=><capacitor key={name} name={name} pcbStyle={{silkscreenTextVisibility:"hidden"}} capacitance={value} supplierPartNumbers={{jlcpcb:[name==="C_TX_IN"?"C19666":capacitorParts[value]]}} cadModel={{glbUrl:`https://modelcdn.tscircuit.com/jscad_models/${name==="C_TX_IN"?"0603":"0402"}.glb`}} footprint={name==="C_TX_IN"?"0603_nosilkscreen":"0402_nosilkscreen"} maxVoltageRating={name==="C_TX_IN"?"16V":capacitorVoltages[value]} pcbX={x} pcbY={y} pcbRotation={["C_TX_OUT","C_TX_X1"].includes(name)?180:0}
      schX={net==="RF_3V3"?-7.6+(i-1)*1.8:-11.4+(i%7)*3.8} schY={-8-Math.floor(i/7)*3} schRotation={270} schSheetName="TX_power" schSectionName="Power"/>)}
    <Button name="SW_TX_ENABLE" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={-25} pcbY={-13} schX={-4} schY={-6} schSheetName="TX_usb"/>
    <Button name="SW_TX_STOP" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={-13} pcbY={-13} schX={2} schY={-6} schSheetName="TX_usb"/>
    <Button name="SW_TX_BIND" pcbStyle={{silkscreenTextVisibility:"hidden"}} pcbX={23} pcbY={-14} schX={-8} schY={-6} schSheetName="TX_radio"/>
    <led name="D_TX_STATUS" pcbStyle={{silkscreenTextVisibility:"hidden"}} color="green" supplierPartNumbers={{jlcpcb:["C2899882"]}} cadModel={{glbUrl:"https://modelcdn.tscircuit.com/jscad_models/0603.glb"}} footprint="0603_nosilkscreen" pcbX={-2} pcbY={-18} schX={8} schY={-6} schRotation={270} schSheetName="TX_usb"/>
    <pinheader name="J_TX_SWD" pcbStyle={{silkscreenTextVisibility:"hidden"}} pinCount={5} pitch="2.54mm" platedDiameter="1.8mm" holeDiameter="1mm" doNotPlace gender="male"
      pcbX={10} pcbY={-23} pinLabels={["3V3","GND","DIO","CLK","RST"]} schWidth={0.485} schX={13} schY={-6} schSheetName="TX_radio"/>
    {[-31,31].flatMap(x=>[-26,26].map(y=><hole key={x+","+y} pcbX={x} pcbY={y} diameter="3.2mm"/>))}
    <keepout name="ANT_KEEPOUT" shape="rect" pcbX={15} pcbY={26.4} width={25} height={6.8} layers={["top","inner1","inner2","bottom"]} excludeRefs={[".U_TX_RF"]}/>
    <silkscreenrect pcbX={15} pcbY={26.4} width={25} height={6.8} strokeWidth={0.15}/>
    <silkscreentext pcbX={15} pcbY={27} text="PCB ANT" fontSize={1.8}/>
    <silkscreentext pcbX={-25} pcbY={-19} text="HOLD" fontSize={1.8}/>
    <silkscreentext pcbX={-13} pcbY={-19} text="STOP" fontSize={1.8}/>
    <silkscreentext pcbX={-10} pcbY={-27} text="USB TX V2" fontSize={1.8}/>
    <silkscreentext pcbX={23} pcbY={-20} text="BIND" fontSize={1.8}/>
    <silkscreentext pcbX={-18} pcbY={23} text="USB-C" fontSize={1.8}/>
    <silkscreentext pcbX={-18} pcbY={18} text="XIAO" fontSize={1.8}/>
    {["V","G","D","C","R"].map((text,i)=><silkscreentext key={text} pcbX={4.92+i*2.54} pcbY={-26} text={text} fontSize={1.8}/>)}
    {pins.map(([ref,pin,net])=><trace key={ref+":"+pin} from={"."+ref+" > .pin"+pin} to={"net.TX_"+net}/>)}
    {resistors.flatMap(([ref,value,x,y,a,b])=>[<trace key={ref+":1"} from={"."+ref+" > .pin1"} to={"net.TX_"+a}/>,<trace key={ref+":2"} from={"."+ref+" > .pin2"} to={"net.TX_"+b}/>])}
    {caps.flatMap(([ref,value,x,y,net])=>[<trace key={ref+":1"} from={"."+ref+" > .pin1"} to={"net.TX_"+net}/>,<trace key={ref+":2"} from={"."+ref+" > .pin2"} to="net.TX_GND"/>])}
    {[["SW_TX_ENABLE","ENABLE_N"],["SW_TX_STOP","STOP_N"],["SW_TX_BIND","BIND_N"]].flatMap(([ref,net])=>[1,2,3,4].map(pin=><trace key={ref+":"+pin} from={"."+ref+" > .pin"+pin} to={"net.TX_"+(pin%2?net:"GND")}/>))}
    <trace from=".D_TX_STATUS > .pin1" to="net.TX_LED_A"/><trace from=".D_TX_STATUS > .pin2" to="net.TX_GND"/>
    <netlabel net="TX_GND" connection=".U_TX_LDO > .pin2" schX={-2} schY={6} schSheetName="TX_power"/>
    <netlabel net="TX_RF_3V3" connection=".U_TX_LDO > .pin5" schX={2} schY={6} schSheetName="TX_power"/>
    <copperpour outline={pourOutline} name="GND_PLANE" layer="inner1" connectsTo="net.TX_GND" clearance="0.3mm" boardEdgeMargin="0.6mm" useThermalReliefs={false}/>
    <copperpour outline={pourOutline} name="GND_BOTTOM" layer="bottom" connectsTo="net.TX_GND" clearance="0.3mm" boardEdgeMargin="0.6mm" useThermalReliefs={false}/>
    <fiducial name="FID1" pcbX={-30} pcbY={18} padDiameter={1} soldermaskPullback={0.5} layer="top"/>
    <fiducial name="FID2" pcbX={29} pcbY={16} padDiameter={1} soldermaskPullback={0.5} layer="top"/>
    <fiducial name="FID3" pcbX={-27} pcbY={-23} padDiameter={1} soldermaskPullback={0.5} layer="top"/>
    {[[-30,18],[29,16],[-27,-23]].map(([x,y])=><pcbsoldermaskopening key={x} pcbX={x} pcbY={y} shape="circle" radius={1} layer="top"/>)}
  </group>;
}