diff --git a/edg/abstract_parts/DigitalAmplifiers.py b/edg/abstract_parts/DigitalAmplifiers.py index 4220b9837..bf5617002 100644 --- a/edg/abstract_parts/DigitalAmplifiers.py +++ b/edg/abstract_parts/DigitalAmplifiers.py @@ -49,8 +49,6 @@ def generate(self): drain_current=(0, pull_current_max), gate_voltage=(self.control.link().output_thresholds.upper(), self.control.link().voltage.upper()), rds_on=(0, low_amp_rds_max), # TODO size on turnon time - gate_charge=(0, float('inf')), # TODO size on turnon time - power=(0, 0) * Watt, frequency=self.frequency, drive_current=self.control.link().current_limits # TODO this is kind of a max drive current )) @@ -71,8 +69,6 @@ def generate(self): drain_current=self.output.link().current_drawn, gate_voltage=pass_gate_voltage, rds_on=(0, self.max_rds), - gate_charge=(0, float('inf')), # TODO size on turnon time - power=(0, 0) * Watt, frequency=self.frequency, drive_current=(-1 * pwr_voltage.lower() / pull_resistance.upper(), pwr_voltage.lower() / low_amp_rds_max) # TODO simultaneously solve both FETs diff --git a/edg/abstract_parts/PartsTable.py b/edg/abstract_parts/PartsTable.py index 8fecfac3d..211097c86 100644 --- a/edg/abstract_parts/PartsTable.py +++ b/edg/abstract_parts/PartsTable.py @@ -103,7 +103,10 @@ def filter(self, fn: Callable[[PartsTableRow], bool]) -> PartsTable: def map_new_columns(self, fn: Callable[[PartsTableRow], Optional[Dict[PartsTableColumn[Any], Any]]], overwrite: bool = False) -> PartsTable: - """Creates a new table (deep copy) with additional rows.""" + """Creates a new table (deep copy) with additional rows. + All entries must have the same keys. + Specify overwrite=True to overwrite an existing row. To preserve the existing value (no-op), return it. + Return None to drop the row.""" new_rows: List[PartsTableRow] = [] first_keys: Optional[KeysView] = None for row in self.rows: diff --git a/edg/abstract_parts/PartsTablePart.py b/edg/abstract_parts/PartsTablePart.py index d5c40f651..03a81ddbd 100644 --- a/edg/abstract_parts/PartsTablePart.py +++ b/edg/abstract_parts/PartsTablePart.py @@ -81,11 +81,9 @@ def generate(self): postprocessed_table = self._table_postprocess(matching_table) postprocessed_table = postprocessed_table.sort_by(self._row_sort_by) self.assign(self.matching_parts, postprocessed_table.map(lambda row: row[self.PART_NUMBER_COL])) - if len(postprocessed_table) > 0: - selected_row = postprocessed_table.first() - self._row_generate(selected_row) - else: # if no matching part, generate a parameter error instead of crashing - self.require(False, "no matching part") + assert len(postprocessed_table) > 0, "no matching part" # crash to make generator failures more obvious + selected_row = postprocessed_table.first() + self._row_generate(selected_row) @abstract_block diff --git a/edg/abstract_parts/test_resistor_generic.py b/edg/abstract_parts/test_resistor_generic.py index 5a75c0c74..6e372ed16 100644 --- a/edg/abstract_parts/test_resistor_generic.py +++ b/edg/abstract_parts/test_resistor_generic.py @@ -8,7 +8,6 @@ def __init__(self): super().__init__() self.dut = self.Block(GenericChipResistor( resistance=1 * kOhm(tol=0.1), - power=(0, 0)*Watt )) (self.dummya, ), _ = self.chain(self.dut.a, self.Block(DummyPassive())) (self.dummyb, ), _ = self.chain(self.dut.b, self.Block(DummyPassive())) @@ -30,7 +29,6 @@ def __init__(self): super().__init__() self.dut = self.Block(GenericChipResistor( resistance=8.06 * kOhm(tol=0.01), - power=(0, 0)*Watt )) (self.dummya, ), _ = self.chain(self.dut.a, self.Block(DummyPassive())) (self.dummyb, ), _ = self.chain(self.dut.b, self.Block(DummyPassive())) diff --git a/edg/electronics_model/DigitalPorts.py b/edg/electronics_model/DigitalPorts.py index fa95a9b2f..4b9aca5de 100644 --- a/edg/electronics_model/DigitalPorts.py +++ b/edg/electronics_model/DigitalPorts.py @@ -252,8 +252,8 @@ def __init__(self): current_draw=RangeExpr() )) self.dst = self.Port(VoltageSource( - voltage_out=(self.src.link().output_thresholds.upper(), self.src.link().voltage.upper()), - current_limits=(-float('inf'), float('inf')))) + voltage_out=(self.src.link().output_thresholds.upper(), self.src.link().voltage.upper()) + )) self.assign(self.src.current_draw, self.dst.link().current_drawn) diff --git a/edg/electronics_model/GroundPort.py b/edg/electronics_model/GroundPort.py index 1d35640d0..114750333 100644 --- a/edg/electronics_model/GroundPort.py +++ b/edg/electronics_model/GroundPort.py @@ -91,7 +91,6 @@ def __init__(self): self.dst = self.Port(AnalogSource( voltage_out=self.src.link().voltage, signal_out=self.src.link().voltage, - impedance=(0, 0)*Ohm, )) diff --git a/edg/electronics_model/VoltagePorts.py b/edg/electronics_model/VoltagePorts.py index 48b921886..175c197dc 100644 --- a/edg/electronics_model/VoltagePorts.py +++ b/edg/electronics_model/VoltagePorts.py @@ -176,7 +176,6 @@ def __init__(self): super().__init__() self.src = self.Port(VoltageSink( - voltage_limits=(-float('inf'), float('inf'))*Volt, current_draw=RangeExpr() )) self.dst = self.Port(AnalogSource( diff --git a/edg/jlcparts/JlcPartsFet.py b/edg/jlcparts/JlcPartsFet.py index 5b666b4cf..e3284c90d 100644 --- a/edg/jlcparts/JlcPartsFet.py +++ b/edg/jlcparts/JlcPartsFet.py @@ -8,7 +8,10 @@ class JlcPartsBaseFet(JlcPartsBase, BaseTableFet): _JLC_PARTS_FILE_NAMES = ["TransistorsMOSFETs"] _CHANNEL_MAP = { 'N Channel': 'N', + '1 N-channel': 'N', + '1 N-Channel': 'N', 'P Channel': 'P', + '1 Piece P-Channel': 'P', } @classmethod @@ -39,14 +42,18 @@ def _entry_to_table_row(cls, row_dict: Dict[PartsTableColumn, Any], filename: st input_capacitance: Optional[float] = attributes.get("Input capacitance (ciss@vds)", float, sub='capacity') except (KeyError, TypeError): input_capacitance = None + try: # not specified for most parts apparently - gate_charge = attributes.get("Total gate charge (qg@vgs)", float, sub='charge') + gate_charge: Optional[float] = attributes.get("Total gate charge (qg@vgs)", float, sub='charge') except (KeyError, TypeError): if input_capacitance is not None: # not strictly correct but kind of a guesstimate gate_charge = input_capacitance * vgs_for_ids else: - gate_charge = 3000e-9 # very pessimistic upper bound - row_dict[cls.GATE_CHARGE] = Range.exact(gate_charge) + gate_charge = None + if gate_charge is not None: + row_dict[cls.GATE_CHARGE] = Range.exact(gate_charge) + else: + row_dict[cls.GATE_CHARGE] = Range.all() return row_dict except (KeyError, TypeError, PartParserUtil.ParseError): @@ -58,23 +65,7 @@ class JlcPartsFet(PartsTableSelectorFootprint, JlcPartsBaseFet, TableFet): class JlcPartsSwitchFet(PartsTableSelectorFootprint, JlcPartsBaseFet, TableSwitchFet): - @init_in_parent - def __init__(self, *args, manual_gate_charge: RangeLike = RangeExpr.ZERO, **kwargs): - super().__init__(*args, **kwargs) - # allow the user to specify a gate charge - self.manual_gate_charge = self.ArgParameter(manual_gate_charge) - self.generator_param(self.manual_gate_charge) - - def _table_postprocess(self, table: PartsTable) -> PartsTable: - manual_gate_charge = self.get(self.manual_gate_charge) - def process_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: - return {self.GATE_CHARGE: manual_gate_charge} - - # must run before TableFet power calculations - if not manual_gate_charge == Range.exact(0): - table = table.map_new_columns(process_row, overwrite=True) - - return super()._table_postprocess(table) + pass lambda: JlcPartsFet(), JlcPartsSwitchFet() # ensure class is instantiable (non-abstract) diff --git a/edg/parts/AdcSpi_Mcp3201.py b/edg/parts/AdcSpi_Mcp3201.py index 9ac05ccf4..3c35373b1 100644 --- a/edg/parts/AdcSpi_Mcp3201.py +++ b/edg/parts/AdcSpi_Mcp3201.py @@ -23,7 +23,6 @@ def __init__(self) -> None: dio_model = DigitalBidir.from_supply( self.vss, self.vdd, voltage_limit_tolerance=(-0.6, 0.6)*Volt, - current_draw=(0, 0), # leakage current not modeled input_threshold_factor=(0.3, 0.7) ) # Datasheet section 6.2, minimum clock speed diff --git a/edg/parts/BatteryProtector_S8261A.py b/edg/parts/BatteryProtector_S8261A.py index ba6b2368d..974f74c0b 100644 --- a/edg/parts/BatteryProtector_S8261A.py +++ b/edg/parts/BatteryProtector_S8261A.py @@ -52,17 +52,13 @@ def __init__(self) -> None: self.do_fet = self.Block(Fet.NFet( drain_current=self.pwr_in.link().current_drawn, - power=RangeExpr.ZERO, gate_voltage=self.pwr_in.link().voltage, - gate_charge=RangeExpr.ALL, rds_on=(0, 0.1)*Ohm, drain_voltage=self.pwr_in.link().voltage )) self.co_fet = self.Block(Fet.NFet( drain_current=self.pwr_in.link().current_drawn, - power=RangeExpr.ZERO, gate_voltage=self.pwr_in.link().voltage, - gate_charge=RangeExpr.ALL, rds_on=(0, 0.1)*Ohm, drain_voltage=self.pwr_in.link().voltage )) diff --git a/edg/parts/CanTransceiver_Iso1050.py b/edg/parts/CanTransceiver_Iso1050.py index ccabc78fb..5f1d0626b 100644 --- a/edg/parts/CanTransceiver_Iso1050.py +++ b/edg/parts/CanTransceiver_Iso1050.py @@ -17,7 +17,6 @@ def __init__(self): self.controller = self.Port(CanTransceiverPort(DigitalBidir( voltage_limits=(-0.5 * Volt, self.vcc1.link().voltage.lower() + 0.5 * Volt), voltage_out=(0 * Volt, self.vcc1.link().voltage.lower()), - current_draw=(0, 0), # TODO actually an unspecified default current_limits=(-5, 5) * uAmp, input_thresholds=(0.8, 2) * Volt, output_thresholds=(0 * Volt, self.vcc1.link().voltage.lower()) diff --git a/edg/parts/CanTransceiver_Sn65hvd230.py b/edg/parts/CanTransceiver_Sn65hvd230.py index 286ea0ea5..697598aec 100644 --- a/edg/parts/CanTransceiver_Sn65hvd230.py +++ b/edg/parts/CanTransceiver_Sn65hvd230.py @@ -13,7 +13,6 @@ def __init__(self): self.controller = self.Port(CanTransceiverPort(DigitalBidir( voltage_limits=(-0.5 * Volt, self.vcc.link().voltage.lower() + 0.5 * Volt), voltage_out=(0 * Volt, self.vcc.link().voltage.lower()), - current_draw=(0, 0), current_limits=(-8, 8) * mAmp, # driver pin actually -40-48mA input_thresholds=(0.8, 2) * Volt, output_thresholds=(0 * Volt, self.vcc.link().voltage.lower()) diff --git a/edg/parts/DacSpi_Mcp4901.py b/edg/parts/DacSpi_Mcp4901.py index 18a578a68..2ba2c9af0 100644 --- a/edg/parts/DacSpi_Mcp4901.py +++ b/edg/parts/DacSpi_Mcp4901.py @@ -11,7 +11,6 @@ def __init__(self) -> None: self.vref = self.Port(VoltageSink( voltage_limits=(0.04*Volt, self.vdd.link().voltage.lower() - 0.04), - current_draw=(0, 0) # input current not specified )) self.vout = self.Port(AnalogSource.from_supply( self.vss, self.vref, @@ -23,7 +22,6 @@ def __init__(self) -> None: dio_model = DigitalBidir.from_supply( self.vss, self.vdd, voltage_limit_tolerance=(-0.3, 0.3)*Volt, - current_draw=(0, 0), # leakage current not modeled current_limits=(-25, 25)*mAmp, input_threshold_factor=(0.2, 0.7) ) diff --git a/edg/parts/EInk_E2154fs091.py b/edg/parts/EInk_E2154fs091.py index a2a38f1bc..98c8e559d 100644 --- a/edg/parts/EInk_E2154fs091.py +++ b/edg/parts/EInk_E2154fs091.py @@ -102,7 +102,7 @@ def contents(self) -> None: drain_voltage=(0, 30)*Volt, drain_current=(0, 0.8)*Amp, # assumed, from inductor rating gate_voltage=(3, 16)*Volt, # assumed, from capacitor ratings # TODO use pwr voltage instead of hardcoding - rds_on=(0, 85)*mOhm, gate_charge=(0, float('inf')), + rds_on=(0, 85)*mOhm, power=(0, 0.2)*Watt # about 4x resistive loss @ 0.8A, 85mOhm; we don't know the switch frequency or drive current )) self.boost_ind = self.Block(Inductor( diff --git a/edg/parts/Fpga_Ice40up.py b/edg/parts/Fpga_Ice40up.py index 61a655bf0..f036d87d4 100644 --- a/edg/parts/Fpga_Ice40up.py +++ b/edg/parts/Fpga_Ice40up.py @@ -46,7 +46,6 @@ def make_dio_model(gnd: Ground, vccio: VoltageSink): gnd, vccio, voltage_limit_tolerance=(-0.3, 0.2) * Volt, # table 4.13 current_limits=(-8, 8)*mAmp, # for LVCMOS 3.3 (least restrictive) - current_draw=(0, 0)*Amp, input_threshold_abs=(0.8, 2.0), # most restrictive, for LVCMOS 3.3 pullup_capable=True, pulldown_capable=False, ) diff --git a/edg/parts/Fusb302b.py b/edg/parts/Fusb302b.py index a771df769..d337d4ce0 100644 --- a/edg/parts/Fusb302b.py +++ b/edg/parts/Fusb302b.py @@ -15,7 +15,6 @@ def __init__(self) -> None: self.cc = self.Port(UsbCcPort()) # TODO pass in port models? i2c_model = DigitalBidir( # interestingly, IO maximum voltages are not specified - current_draw=(0, 0), # leakage current (Table 13) not modeled voltage_out=(0, 0.35)*Volt, # low-level output voltage current_limits=(-20, 0)*mAmp, # low-level output current limits input_thresholds=(0.51, 1.32)*Volt, diff --git a/edg/parts/Jacdac.py b/edg/parts/Jacdac.py index e01c475de..b3e2dc230 100644 --- a/edg/parts/Jacdac.py +++ b/edg/parts/Jacdac.py @@ -191,8 +191,7 @@ def contents(self): signal_level = self.signal.link().voltage self.rc = self.Block(LowPassRc(impedance=220*Ohm(tol=0.05), cutoff_freq=22*MHertz(tol=0.12), voltage=signal_level)) - clamp_diode_model = Diode(reverse_voltage=(0, signal_level.upper()), - current=(0, 0)) + clamp_diode_model = Diode(reverse_voltage=(0, signal_level.upper()), current=(0, 0)*Amp) self.clamp_hi = self.Block(clamp_diode_model) self.clamp_lo = self.Block(clamp_diode_model) diff --git a/edg/parts/JlcFet.py b/edg/parts/JlcFet.py index d8fceb7cd..bf94c9273 100644 --- a/edg/parts/JlcFet.py +++ b/edg/parts/JlcFet.py @@ -5,24 +5,55 @@ from .JlcPart import DescriptionParser, JlcTableSelector +@non_library +class FetFallbackGateCharge(PartsTableSelector, BaseTableFet): + """A TableFet that allows a fallback gate charge if not specified in the table. + Unspecified entries must be Range.all(), which will be substituted with the fallback + value in per-Block post-processing.""" + @init_in_parent + def __init__(self, *args, fallback_gate_charge: RangeLike = Range.from_tolerance(3000e-9, 0), **kwargs): + super().__init__(*args, **kwargs) + # allow the user to specify a gate charge + self.fallback_gate_charge = self.ArgParameter(fallback_gate_charge) + self.generator_param(self.fallback_gate_charge) + + def _table_postprocess(self, table: PartsTable) -> PartsTable: + fallback_gate_charge = self.get(self.fallback_gate_charge) + def process_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: + if row[TableFet.GATE_CHARGE] == Range.all(): + return {TableFet.GATE_CHARGE: fallback_gate_charge} + else: + return {TableFet.GATE_CHARGE: row[TableFet.GATE_CHARGE]} + + # must run before TableFet power calculations + return super()._table_postprocess(table.map_new_columns(process_row, overwrite=True)) + + class JlcBaseFet(JlcTableSelector): PACKAGE_FOOTPRINT_MAP = { + 'SOT-23': 'Package_TO_SOT_SMD:SOT-23', 'SOT23-3': 'Package_TO_SOT_SMD:SOT-23', 'SOT-23-3': 'Package_TO_SOT_SMD:SOT-23', 'SOT-23-3L': 'Package_TO_SOT_SMD:SOT-23', 'SOT-323': 'Package_TO_SOT_SMD:SOT-323_SC-70', + 'SOT-323(SC-80)': 'Package_TO_SOT_SMD:SOT-323_SC-70', 'SOT-323-3': 'Package_TO_SOT_SMD:SOT-323_SC-70', 'SC-70-3': 'Package_TO_SOT_SMD:SOT-323_SC-70', 'TO-252': 'Package_TO_SOT_SMD:TO-252-2', # aka DPak 'TO-252-2': 'Package_TO_SOT_SMD:TO-252-2', + 'TO-252(DPAK)': 'Package_TO_SOT_SMD:TO-252-2', + 'DPAK': 'Package_TO_SOT_SMD:TO-252-2', + 'TO-252-2(DPAK)': 'Package_TO_SOT_SMD:TO-252-2', 'TO-263-2': 'Package_TO_SOT_SMD:TO-263-2', # aka D2Pak + 'D2PAK': 'Package_TO_SOT_SMD:TO-263-2', 'SOT-223': 'Package_TO_SOT_SMD:SOT-223-3_TabPin2', 'SOT-223-3': 'Package_TO_SOT_SMD:SOT-223-3_TabPin2', 'SO-8': 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', + 'SOIC-8': 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', 'SOIC-8_3.9x4.9x1.27P': 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', 'SOP-8': 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', 'SOP-8_3.9x4.9x1.27P': 'Package_SO:SOIC-8_3.9x4.9mm_P1.27mm', @@ -47,10 +78,17 @@ class JlcBaseFet(JlcTableSelector): 'PQFN-8(5x6)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', 'PRPAK5x6': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', 'PRPAK5x6-8L': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + 'PG-TDSON-8_EP_5.2x6.2x1.27P': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + + 'TDSON-8-EP(5x6)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + 'PDFN-8(5x6)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + 'DFN-8-EP(6.1x5.2)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + 'DFN-8(4.9x5.8)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', + 'PDFN-8(5.8x4.9)': 'Package_DFN_QFN:PQFN-8-EP_6x5mm_P1.27mm_Generic', } DESCRIPTION_PARSERS: List[DescriptionParser] = [ - (re.compile("(\S+V) (\S+A) (\S+W) (\S+Ω)@(\S+V),\S+A (\S+V)@\S+A ([PN]) Channel .* MOSFETs.*"), + (re.compile("(\S+V) (\S+A) (\S+W) (\S+Ω)@(\S+V),\S+A (\S+V)@\S+A.* ([PN]) Channel.* MOSFETs.*"), lambda match: { TableFet.CHANNEL: match.group(7), TableFet.VDS_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(1), 'V')), @@ -62,10 +100,25 @@ class JlcBaseFet(JlcTableSelector): PartParserUtil.parse_value(match.group(5), 'V')), TableFet.RDS_ON: Range.exact(PartParserUtil.parse_value(match.group(4), 'Ω')), TableFet.POWER_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(3), 'W')), - TableFet.GATE_CHARGE: Range.zero_to_upper(3000e-9), # not specified, pessimistic upper bound + TableFet.GATE_CHARGE: Range.all(), # unspecified + }), + # some are more detailed + (re.compile("(\S+V) (\S+A) (\S+Ω)@(\S+V),\S+A (\S+W) (\S+V)@\S+A.* ([PN]) Channel.* (\S+C)@\S+V.* MOSFETs.*"), + lambda match: { + TableFet.CHANNEL: match.group(7), + TableFet.VDS_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(1), 'V')), + TableFet.IDS_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(2), 'A')), + # Vgs isn't specified, so the Ron@Vgs is used as a lower bound; assumed symmetric + TableFet.VGS_RATING: Range.from_abs_tolerance(0, + PartParserUtil.parse_value(match.group(4), 'V')), + TableFet.VGS_DRIVE: Range(PartParserUtil.parse_value(match.group(6), 'V'), + PartParserUtil.parse_value(match.group(4), 'V')), + TableFet.RDS_ON: Range.exact(PartParserUtil.parse_value(match.group(3), 'Ω')), + TableFet.POWER_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(5), 'W')), + TableFet.GATE_CHARGE: Range.exact(PartParserUtil.parse_value(match.group(8), 'C')) }), - # Some of them have the power entry later, for whatever reason - (re.compile("(\S+V) (\S+A) (\S+Ω)@(\S+V),\S+A (\S+W) (\S+V)@\S+A ([PN]) Channel .* MOSFETs.*"), + # many still don't have the gate charge + (re.compile("(\S+V) (\S+A) (\S+Ω)@(\S+V),\S+A (\S+W) (\S+V)@\S+A.* ([PN]) Channel.* MOSFETs.*"), lambda match: { TableFet.CHANNEL: match.group(7), TableFet.VDS_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(1), 'V')), @@ -77,10 +130,42 @@ class JlcBaseFet(JlcTableSelector): PartParserUtil.parse_value(match.group(4), 'V')), TableFet.RDS_ON: Range.exact(PartParserUtil.parse_value(match.group(3), 'Ω')), TableFet.POWER_RATING: Range.zero_to_upper(PartParserUtil.parse_value(match.group(5), 'W')), - TableFet.GATE_CHARGE: Range.zero_to_upper(3000e-9), # not specified, pessimistic upper bound + TableFet.GATE_CHARGE: Range.all(), # unspecified }), ] + SUPPLEMENTAL_QC = { # mfr part number to typ Qc @ max Vgs (if multiple specified) + # QFN-8 devices + 'IRFH7440TRPBF': 92e-9, # @ Vgs=10 + 'BSC028N06NSATMA1': 37e-9, # @ Vgs=0...10V + 'BSC057N08NS3G': 42e-9, # @ Vgs=0...10V + 'BSC093N04LSG': 18e-9, # @ Vgs=0...10V + 'BSC160N10NS3G': 19e-9, # @ Vgs=0...10V + 'SIR876ADP-T1-GE3': 32.8e-9, # @ Vgs=10 + 'SI7336ADP-T1-E3': 36e-9, # @ Vgs=4.5 + 'SIR470DP-T1-GE3': 102e-9, # @ Vgs=10 + + # SOIC-8 devices, top 5 stock in the static parts table + 'AO4406A': 14e-9, # @ Vgs=10 + 'IRF8313TRPBF': 6.0e-9, # @ Vgs=4.5 + 'AO4435': 18e-9, # @ Vgs=-10 + 'AO4419': 19e-9, # @ Vgs=4.5 + 'AO4264E': 14.5e-9, # @ Vgs=10 + 'AO4485': 42e-9, # @ Vgs=10 + 'AO4459': 9.2e-9, # @ Vgs=10 + 'AO4468': 15e-9, # @ Vgs=10 + 'IRF7458TRPBF': 39e-9, # @ Vgs=10 + 'AO4407A': 30e-9, # @ Vgs=10 + + # DPAK devices + 'IRLR024NTRPBF': 15e-9, # @ Vgs=5 + 'AOD413A': 16.2e-9, # @ Vgs=-10 + 'IRLR8726TRPBF': 15e-9, # @ Vgs=4.5 + 'IRLR8726TRLPBF': 15e-9, # @ Vgs=4.5 + 'IRFR5410TRPBF': 58e-9, # @ Vgs=-10 + 'KIA50N03BD': 25e-9, # @ Vgs=10 + } + @classmethod def _make_table(cls) -> PartsTable: def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: @@ -94,6 +179,9 @@ def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: if new_cols is None: return None + if new_cols[TableFet.GATE_CHARGE] == Range.all() and row[cls.PART_NUMBER_COL] in cls.SUPPLEMENTAL_QC: + new_cols[TableFet.GATE_CHARGE] = Range.exact(cls.SUPPLEMENTAL_QC[row[cls.PART_NUMBER_COL]]) + new_cols[cls.KICAD_FOOTPRINT] = footprint new_cols.update(cls._parse_jlcpcb_common(row)) return new_cols @@ -101,28 +189,12 @@ def parse_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: return cls._jlc_table().map_new_columns(parse_row) -class JlcFet(PartsTableSelectorFootprint, JlcBaseFet, TableFet): +class JlcFet(PartsTableSelectorFootprint, JlcBaseFet, FetFallbackGateCharge, TableFet): pass -class JlcSwitchFet(PartsTableSelectorFootprint, JlcBaseFet, TableSwitchFet): - @init_in_parent - def __init__(self, *args, manual_gate_charge: RangeLike = RangeExpr.ZERO, **kwargs): - super().__init__(*args, **kwargs) - # allow the user to specify a gate charge - self.manual_gate_charge = self.ArgParameter(manual_gate_charge) - self.generator_param(self.manual_gate_charge) - - def _table_postprocess(self, table: PartsTable) -> PartsTable: - manual_gate_charge = self.get(self.manual_gate_charge) - def process_row(row: PartsTableRow) -> Optional[Dict[PartsTableColumn, Any]]: - return {self.GATE_CHARGE: manual_gate_charge} - - # must run before TableFet power calculations - if not manual_gate_charge == Range.exact(0): - table = table.map_new_columns(process_row, overwrite=True) - - return super()._table_postprocess(table) +class JlcSwitchFet(PartsTableSelectorFootprint, JlcBaseFet, FetFallbackGateCharge, TableSwitchFet): + pass lambda: JlcFet, JlcSwitchFet() # ensure class is instantiable (non-abstract) diff --git a/edg/parts/Microcontroller_Esp32.py b/edg/parts/Microcontroller_Esp32.py index ef665d6e7..3cb1b88a7 100644 --- a/edg/parts/Microcontroller_Esp32.py +++ b/edg/parts/Microcontroller_Esp32.py @@ -33,7 +33,6 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: self.gnd, pwr, voltage_limit_tolerance=(-0.3, 0.3) * Volt, current_limits=(-28, 40)*mAmp, - current_draw=(0, 0)*Amp, input_threshold_factor=(0.25, 0.75), pullup_capable=True, pulldown_capable=True, ) @@ -45,7 +44,6 @@ def _io_pinmap(self) -> PinMapUtil: self.gnd, pwr, voltage_limit_tolerance=(-0.3, 0.3) * Volt, current_limits=(-28, 20)*mAmp, # reduced sourcing capability - current_draw=(0, 0)*Amp, input_threshold_factor=(0.25, 0.75), pullup_capable=True, pulldown_capable=True, ) diff --git a/edg/parts/Microcontroller_Esp32c3.py b/edg/parts/Microcontroller_Esp32c3.py index df17f9542..11a6319a1 100644 --- a/edg/parts/Microcontroller_Esp32c3.py +++ b/edg/parts/Microcontroller_Esp32c3.py @@ -33,7 +33,6 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: self.gnd, pwr, voltage_limit_tolerance=(-0.3, 0.3)*Volt, current_limits=(-28, 40)*mAmp, - current_draw=(0, 0)*Amp, input_threshold_factor=(0.25, 0.75), pullup_capable=True, pulldown_capable=True, ) diff --git a/edg/parts/Microcontroller_Lpc1549.py b/edg/parts/Microcontroller_Lpc1549.py index 12212bf67..fad6c4473 100644 --- a/edg/parts/Microcontroller_Lpc1549.py +++ b/edg/parts/Microcontroller_Lpc1549.py @@ -61,7 +61,6 @@ def _io_pinmap(self) -> PinMapUtil: dio_5v_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_abs=(0, 5) * Volt, - current_draw=(0, 0) * Amp, current_limits=(-50, 45) * mAmp, input_threshold_factor=(0.3, 0.7), pullup_capable=True, pulldown_capable=True @@ -69,7 +68,6 @@ def _io_pinmap(self) -> PinMapUtil: dio_non5v_model = DigitalBidir.from_supply( # only used when overlapped w/ DAC PIO0_12 self.gnd, self.pwr, # up to VddA voltage_limit_tolerance=(0, 0) * Volt, - current_draw=(0, 0) * Amp, current_limits=(-50, 45) * mAmp, input_threshold_factor=(0.3, 0.7), pullup_capable=True, pulldown_capable=True @@ -77,7 +75,6 @@ def _io_pinmap(self) -> PinMapUtil: dio_highcurrrent_model = DigitalBidir.from_supply( # only used for PIO0_24 self.gnd, self.pwr, voltage_limit_abs=(0, 5) * Volt, - current_draw=(0, 0) * Amp, current_limits=(-50, 20) * mAmp, # TODO: 12mA when Vdd < 2.7V input_threshold_factor=(0.3, 0.7), pullup_capable=True, pulldown_capable=True diff --git a/edg/parts/Microcontroller_Stm32f103.py b/edg/parts/Microcontroller_Stm32f103.py index 74deddc53..24874906a 100644 --- a/edg/parts/Microcontroller_Stm32f103.py +++ b/edg/parts/Microcontroller_Stm32f103.py @@ -28,7 +28,6 @@ def __init__(self, **kwargs) -> None: self.nrst = self.Port(DigitalSink.from_supply( self.gnd, self.pwr, voltage_limit_tolerance=(-0.3, 0.3)*Volt, # Table 5.3.1, general operating conditions TODO: FT IO, BOOT0 IO - current_draw=(0, 0)*Amp, input_threshold_abs=(0.8, 2)*Volt, pullup_capable=True ), optional=True) # note, internal pull-up resistor, 30-50 kOhm by Table 35 @@ -62,21 +61,21 @@ def _io_pinmap(self) -> PinMapUtil: dio_ft_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_abs=(-0.3, 5.2) * Volt, # Table 5.3.1, general operating conditions, TODO relaxed for Vdd>2v - current_draw=(0, 0)*Amp, current_limits=(-20, 20)*mAmp, # Section 5.3.13 Output driving current, TODO loose with relaxed VOL/VOH + current_limits=(-20, 20)*mAmp, # Section 5.3.13 Output driving current, TODO loose with relaxed VOL/VOH input_threshold_factor=(0.35, 0.65), # TODO relaxed (but more complex) bounds available pullup_capable=True, pulldown_capable=True ) dio_std_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_tolerance=(-0.3, 0.3)*Volt, # Table 5.3.1, general operating conditions - current_draw=(0, 0)*Amp, current_limits=(-20, 20)*mAmp, # Section 5.3.13 Output driving current, TODO loose with relaxed VOL/VOH + current_limits=(-20, 20)*mAmp, # Section 5.3.13 Output driving current, TODO loose with relaxed VOL/VOH input_threshold_factor=(0.35, 0.65), # TODO relaxed (but more complex) bounds available pullup_capable=True, pulldown_capable=True, ) dio_pc_13_14_15_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_tolerance=(-0.3, 0.3)*Volt, # Table 5.3.1, general operating conditions - current_draw=(0, 0)*Amp, current_limits=(-3, 3)*mAmp, # Section 5.3.13 Output driving current + current_limits=(-3, 3)*mAmp, # Section 5.3.13 Output driving current input_threshold_factor=(0.35, 0.65), # TODO relaxed (but more complex) bounds available pullup_capable=True, pulldown_capable=True, ) diff --git a/edg/parts/Microcontroller_Stm32f303.py b/edg/parts/Microcontroller_Stm32f303.py index a5846ff14..0e78f7974 100644 --- a/edg/parts/Microcontroller_Stm32f303.py +++ b/edg/parts/Microcontroller_Stm32f303.py @@ -33,35 +33,35 @@ def _io_pinmap(self) -> PinMapUtil: dio_tc_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3, 0.3) * Volt, # Table 19 - current_draw=(0, 0)*Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) dio_tc_switch_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3, 0.3) * Volt, # Table 19 - current_draw=(0, 0)*Amp, current_limits=(-3, 0), # Table 13, note 1, can sink 3 mA and should not source current + current_limits=(-3, 0), # Table 13, note 1, can sink 3 mA and should not source current input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) dio_tt_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3, 3.6) * Volt, # Table 19 - current_draw=(0, 0)*Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) dio_tta_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3 * Volt, vdda.link().voltage.lower() + 0.3 * Volt), # Table 19 - current_draw=(0, 0)*Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) dio_ft_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3, 5.5) * Volt, # Table 19 - current_draw=(0, 0)*Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) @@ -69,7 +69,7 @@ def _io_pinmap(self) -> PinMapUtil: dio_boot0_model = DigitalBidir.from_supply( self.gnd, vdd, voltage_limit_abs=(-0.3, 5.5) * Volt, # Table 19 - current_draw=(0, 0)*Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) diff --git a/edg/parts/Microcontroller_Stm32g431.py b/edg/parts/Microcontroller_Stm32g431.py index dc430e415..f429cad50 100644 --- a/edg/parts/Microcontroller_Stm32g431.py +++ b/edg/parts/Microcontroller_Stm32g431.py @@ -58,7 +58,7 @@ def _io_pinmap(self) -> PinMapUtil: dio_tt_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_tolerance=(-0.3, 0.3) * Volt, # Table 19 - current_draw=(0, 0) * Amp, current_limits=current_limits, + current_limits=current_limits, input_threshold_factor=input_threshold_factor, pullup_capable=True, pulldown_capable=True ) diff --git a/edg/parts/Microcontroller_nRF52840.py b/edg/parts/Microcontroller_nRF52840.py index 1a74b481f..44bd589f1 100644 --- a/edg/parts/Microcontroller_nRF52840.py +++ b/edg/parts/Microcontroller_nRF52840.py @@ -32,7 +32,6 @@ def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: self.gnd, pwr, voltage_limit_tolerance=(-0.3, 0.3) * Volt, current_limits=(-6, 6)*mAmp, # minimum current, high drive, Vdd>2.7 - current_draw=(0, 0)*Amp, input_threshold_factor=(0.3, 0.7), pullup_capable=True, pulldown_capable=True, ) diff --git a/edg/parts/MotorDriver_Drv8870.py b/edg/parts/MotorDriver_Drv8870.py index 5b39ab5a1..b6602fb6a 100644 --- a/edg/parts/MotorDriver_Drv8870.py +++ b/edg/parts/MotorDriver_Drv8870.py @@ -13,7 +13,6 @@ def __init__(self) -> None: self.vref = self.Port(VoltageSink.from_gnd( self.gnd, voltage_limits=(0.3, 5)*Volt, # operational from 0-0.3v, but degraded accuracy - current_draw=(0, 0)*Amp )) din_model = DigitalSink.from_supply( diff --git a/edg/parts/Opamp_Lmv321.py b/edg/parts/Opamp_Lmv321.py index 11b7489c1..7ca13a946 100644 --- a/edg/parts/Opamp_Lmv321.py +++ b/edg/parts/Opamp_Lmv321.py @@ -14,7 +14,6 @@ def __init__(self): self.vss, self.vcc, voltage_limit_abs=(-0.2, 5.7), signal_limit_bound=(0, -1.0*Volt), # assumed, from Vcc = 2.7v and 5v tables - current_draw=(0, 0)*pAmp # TODO: should bias current be modeled here? ) self.vinp = self.Port(analog_in_model) self.vinn = self.Port(analog_in_model) diff --git a/edg/parts/Opamp_Mcp6001.py b/edg/parts/Opamp_Mcp6001.py index 6d92a64f9..2294418ad 100644 --- a/edg/parts/Opamp_Mcp6001.py +++ b/edg/parts/Opamp_Mcp6001.py @@ -15,7 +15,6 @@ def __init__(self): voltage_limit_tolerance=(-1.0, 1.0)*Volt, # absolute maximum ratings signal_limit_bound=(0.3*Volt, -0.3*Volt), # common-mode input range impedance=1e13*Ohm(tol=0), # no tolerance bounds given on datasheet - current_draw=(0, 0)*pAmp # TODO: should bias current be modeled here? ) self.vinp = self.Port(analog_in_model) self.vinn = self.Port(analog_in_model) diff --git a/edg/parts/PowerConditioning.py b/edg/parts/PowerConditioning.py index 3a0622e4b..0b9244ae3 100644 --- a/edg/parts/PowerConditioning.py +++ b/edg/parts/PowerConditioning.py @@ -67,14 +67,12 @@ def __init__(self, charging_current: RangeLike, sense_resistance: RangeLike, drain_voltage=(0, max_in_voltage), drain_current=(0, max_charge_current), gate_voltage=(self.pwr.link().voltage.lower(), max_in_voltage), rds_on=(0, 0.5)*Ohm, # TODO kind of arbitrary - gate_charge=(0, float('inf')), power=(0, max_in_voltage * max_charge_current) )) self.connect(self.fet.source, self.sense.b) self.diode = self.Block(Diode( reverse_voltage=(0, max_in_voltage), current=self.charging_current, voltage_drop=self.voltage_drop, - reverse_recovery_time=(0, float('inf')) )) self.connect(self.diode.anode.adapt_to(VoltageSink()), self.fet.drain.adapt_to(VoltageSource( @@ -140,8 +138,7 @@ def __init__(self, voltage_drop: RangeLike, reverse_recovery_time: RangeLike = R self.pwr_in, self.diode.cathode.adapt_to(VoltageSource( voltage_out=(self.pwr_in_diode.link().voltage.lower() - self.diode.voltage_drop.upper(), - self.pwr_in_diode.link().voltage.upper() - self.diode.voltage_drop.lower()), - current_limits=(-float('inf'), float('inf')) + self.pwr_in_diode.link().voltage.upper() - self.diode.voltage_drop.lower()) )) ) self.connect(self.merge.pwr_out, self.pwr_out) @@ -175,21 +172,17 @@ def __init__(self, voltage_drop: RangeLike, reverse_recovery_time: RangeLike = ( self.merge = self.Block(MergedVoltageSource()).connected_from( self.diode1.cathode.adapt_to(VoltageSource( voltage_out=(self.pwr_in1.link().voltage.lower() - self.diode1.voltage_drop.upper(), - self.pwr_in1.link().voltage.upper()), - current_limits=(-float('inf'), float('inf')) + self.pwr_in1.link().voltage.upper()) )), self.diode2.cathode.adapt_to(VoltageSource( voltage_out=(self.pwr_in2.link().voltage.lower() - self.diode2.voltage_drop.upper(), - self.pwr_in2.link().voltage.upper()), - current_limits=(-float('inf'), float('inf')) + self.pwr_in2.link().voltage.upper()) )) ) self.connect(self.diode1.anode.adapt_to(VoltageSink( - voltage_limits=(-float('inf'), float('inf')), current_draw=self.pwr_out.link().current_drawn )), self.pwr_in1) self.connect(self.diode2.anode.adapt_to(VoltageSink( - voltage_limits=(-float('inf'), float('inf')), current_draw=self.pwr_out.link().current_drawn )), self.pwr_in2) diff --git a/edg/parts/RfModules.py b/edg/parts/RfModules.py index 54e85b7cf..b54d701e3 100644 --- a/edg/parts/RfModules.py +++ b/edg/parts/RfModules.py @@ -17,7 +17,6 @@ def __init__(self): digital_model = DigitalBidir.from_supply( self.gnd, self.pwr, voltage_limit_tolerance=(-0.3, 0.3)*Volt, # TODO speculative deafult - current_draw=(0, 0), # TODO actually an unspecified default current_limits=(-2, 2) * mAmp, input_threshold_factor=(0.3, 0.7), output_threshold_factor=(0.05, 0.95) @@ -89,7 +88,6 @@ def __init__(self) -> None: self.pwr = self.Port(VoltageSink( voltage_limits=(3, 6) * Volt, # TODO added a -10% tolerance on the low side so things still work - technically out of spec - current_draw=(0, 0), # TODO actually an unspecified default ), [Power]) self.gnd = self.Port(Ground(), [Common]) @@ -97,7 +95,6 @@ def __init__(self) -> None: pos=self.pwr, neg=self.gnd, voltage_limit_tolerance=(-0.3, 0.3)*Volt, # TODO actually an unspecified default # TODO other parameters given the logic conversion circuit - current_draw=(0, 0), # TODO actually an unspecified default input_threshold_factor=(0.5, 0.5) # TODO completely wild relaxed unrealistic guess ) diff --git a/edg/parts/Rtc_Pcf2129.py b/edg/parts/Rtc_Pcf2129.py index eec13059b..cda7c22a0 100644 --- a/edg/parts/Rtc_Pcf2129.py +++ b/edg/parts/Rtc_Pcf2129.py @@ -18,7 +18,6 @@ def __init__(self) -> None: dio_model = DigitalBidir( voltage_limits=(-0.5, self.pwr.link().voltage.lower() + 0.5), - current_draw=(0, 0), voltage_out=(0, self.pwr.link().voltage.lower()), current_limits=(-1, 1) * mAmp, # TODO higher sink current on SDA/nCE input_thresholds=(0.25 * self.pwr.link().voltage.upper(), diff --git a/examples/Fcml/Fcml.net b/examples/Fcml/Fcml.net index fa2840cb1..fb80d6ef9 100644 --- a/examples/Fcml/Fcml.net +++ b/examples/Fcml/Fcml.net @@ -476,8 +476,8 @@ (property (name "edg_path") (value "conv.sw[0].high_fet")) (property (name "edg_short_path") (value "conv.sw[0].high_fet")) (property (name "edg_refdes") (value "Q1")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[0]/") (tstamps "/042f01b7/05ee01d3/")) (tstamps "0e85033f")) (comp (ref "Q2") @@ -488,8 +488,8 @@ (property (name "edg_path") (value "conv.sw[0].low_fet")) (property (name "edg_short_path") (value "conv.sw[0].low_fet")) (property (name "edg_refdes") (value "Q2")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[0]/") (tstamps "/042f01b7/05ee01d3/")) (tstamps "0bd402f1")) (comp (ref "C15") @@ -680,8 +680,8 @@ (property (name "edg_path") (value "conv.sw[1].high_fet")) (property (name "edg_short_path") (value "conv.sw[1].high_fet")) (property (name "edg_refdes") (value "Q3")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[1]/") (tstamps "/042f01b7/05f001d4/")) (tstamps "0e85033f")) (comp (ref "Q4") @@ -692,8 +692,8 @@ (property (name "edg_path") (value "conv.sw[1].low_fet")) (property (name "edg_short_path") (value "conv.sw[1].low_fet")) (property (name "edg_refdes") (value "Q4")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[1]/") (tstamps "/042f01b7/05f001d4/")) (tstamps "0bd402f1")) (comp (ref "D4") @@ -908,8 +908,8 @@ (property (name "edg_path") (value "conv.sw[2].high_fet")) (property (name "edg_short_path") (value "conv.sw[2].high_fet")) (property (name "edg_refdes") (value "Q5")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[2]/") (tstamps "/042f01b7/05f201d5/")) (tstamps "0e85033f")) (comp (ref "Q6") @@ -920,8 +920,8 @@ (property (name "edg_path") (value "conv.sw[2].low_fet")) (property (name "edg_short_path") (value "conv.sw[2].low_fet")) (property (name "edg_refdes") (value "Q6")) - (property (name "edg_part") (value "HSM4410 (HUASHUO)")) - (property (name "edg_value") (value "30V 12A 2.5W 9.5mΩ@10V,12A 2.5V@250μA N Channel SOP-8 MOSFETs ROHS")) + (property (name "edg_part") (value "ET4410 (ETERNAL)")) + (property (name "edg_value") (value "30V 10A 9mΩ@10V,10A 2.5W 1.7V@250uA 145pF@15V N Channel 710pF@15V 8nC@4.5V -55℃~+150℃@(Tj) SOP-8 MOSFETs ROHS")) (sheetpath (names "/conv/sw[2]/") (tstamps "/042f01b7/05f201d5/")) (tstamps "0bd402f1")) (comp (ref "D6") diff --git a/examples/test_iot_display.py b/examples/test_iot_display.py index 4887b33fe..136222ccd 100644 --- a/examples/test_iot_display.py +++ b/examples/test_iot_display.py @@ -28,8 +28,6 @@ def contents(self): drain_current=self.output.link().current_drawn, gate_voltage=self.control.link().voltage - self.pwr.link().voltage, # TODO needs to be diff from pwr.voltage rds_on=(0, self.max_rds), - gate_charge=(0, float('inf')), # TODO size on turnon time - power=(0, 0) * Watt, frequency=self.frequency, drive_current=self.control.link().current_limits # TODO this is kind of a max drive current )) diff --git a/examples/test_iot_iron.py b/examples/test_iot_iron.py index 40d62ca07..2b1fff449 100644 --- a/examples/test_iot_iron.py +++ b/examples/test_iot_iron.py @@ -239,8 +239,6 @@ def refinements(self) -> Refinements: (['reg_gate', 'ic', 'actual_dropout'], Range.exact(0)), # allow tracking (['conv', 'sw', 'high_fet', 'part'], ParamValue(['conv', 'sw', 'low_fet', 'part'])), - (['conv', 'sw', 'low_fet', 'manual_gate_charge'], Range.exact(100e-9)), # reasonable worst case estimate - (['conv', 'sw', 'high_fet', 'manual_gate_charge'], ParamValue(['conv', 'sw', 'low_fet', 'manual_gate_charge'])), ], class_refinements=[ (HalfBridgeDriver, Ucc27282), diff --git a/examples/test_usb_source_measure.py b/examples/test_usb_source_measure.py index 64a8bdcf6..cbacf24f9 100644 --- a/examples/test_usb_source_measure.py +++ b/examples/test_usb_source_measure.py @@ -165,14 +165,12 @@ def contents(self) -> None: drain_current=self.current, gate_voltage=gate_voltage, rds_on=self.rds_on, - gate_charge=RangeExpr.ALL, # don't care, it's analog not switching power=self.pwr.link().voltage * self.current)) self.low_fet = self.Block(Fet.PFet( drain_voltage=self.pwr.link().voltage, drain_current=self.current, gate_voltage=gate_voltage, rds_on=self.rds_on, - gate_charge=RangeExpr.ALL, # don't care, it's analog not switching power=self.pwr.link().voltage * self.current)) self.import_kicad(self.file_path("resources", f"{self.__class__.__name__}.kicad_sch"), @@ -799,10 +797,6 @@ def refinements(self) -> Refinements: )), # TODO model is broken for unknown reasons (['boot', 'c_fly_pos', 'voltage_rating_derating'], 0.85), (['boot', 'c_fly_neg', 'voltage_rating_derating'], 0.85), - (['conv', 'buck_sw', 'low_fet', 'manual_gate_charge'], Range.exact(100e-9)), # reasonable worst case estimate - (['conv', 'buck_sw', 'high_fet', 'manual_gate_charge'], ParamValue(['conv', 'buck_sw', 'low_fet', 'manual_gate_charge'])), - (['conv', 'boost_sw', 'low_fet', 'manual_gate_charge'], ParamValue(['conv', 'buck_sw', 'low_fet', 'manual_gate_charge'])), - (['conv', 'boost_sw', 'high_fet', 'manual_gate_charge'], ParamValue(['conv', 'buck_sw', 'low_fet', 'manual_gate_charge'])), # require all FETs to be the same; note boost must elaborate first (['conv', 'buck_sw', 'low_fet', 'part'], ParamValue(['conv', 'boost_sw', 'low_fet', 'actual_part'])), (['conv', 'buck_sw', 'high_fet', 'part'], ParamValue(['conv', 'boost_sw', 'low_fet', 'actual_part'])),