diff --git a/edg/abstract_parts/BaseIoControllerWrapped.py b/edg/abstract_parts/BaseIoControllerWrapped.py new file mode 100644 index 000000000..ee48bfa87 --- /dev/null +++ b/edg/abstract_parts/BaseIoControllerWrapped.py @@ -0,0 +1,86 @@ +from typing import * + +from ..electronics_interfaces import * +from .IoController import BaseIoController + + +class BaseIoControllerWrapped(BaseIoController): + """Base class for IoController wrapped blocks, particularly footprints that are used + with an outer WrapperSubboardBlock to implement e.g. a dev board or module around a modeling subcircuit. + + Provides some utility functions to remap pin assignments from the model to the footprint. + + In this class, pin_assigns is treated as the model's pin assigns and internally remapped. + """ + + @staticmethod + def _remap_pin_assigns_list( + remapping: Dict[str, str], + pin_assigns: List[str], + *, + invert_remapping: bool = False, + ) -> Dict[str, str]: + """Given a remapping dict and a list of pin assigns, returns the mapping as a dict with the remapping applied. + If invert_remapping is True, the remapping dict is inverted before applying. + Assigns not present in the remapping dict are passed unchanged, eg for non-pin-assigns like bundle containers. + """ + if invert_remapping: + remapping = {v: k for k, v in remapping.items()} + + remapped_assigns = {} + for assign in pin_assigns: + name, pindef = assign.split("=") + pin = pindef.split(",")[0].strip() # take the first (gpio name) if multiple + remapped_pin = remapping.get(pin) + if remapped_pin is not None: + remapped_assigns[name.strip()] = remapped_pin + else: + remapped_assigns[name.strip()] = pindef # pass unmodified if not remappable, eg bundle containers + return remapped_assigns + + def _remap_to_footprint_pinning( + self, pin_assigns: Dict[str, str], valid_pins: Iterable[str] + ) -> Dict[str, HasPassivePort]: + """Given the pin assigns in a dict form as port name -> footprint pin, eg from _remap_pin_assigns_list, + returns the footprint-compatible form as footprint pin -> port object. + + This simplified pin assignment tool requires all pins to be assigned. + It does not automatically assign unassigned pins, that is assumed to have happened at a higher level.""" + pinning: Dict[str, HasPassivePort] = {} + seen_names: Set[str] = set() + + def remap_port_recursive(port: Port, prefix: str = "") -> None: + """Remaps a port, recursively for bundles""" + if isinstance(port, HasPassivePort): + pin = pin_assigns.get(prefix) + assert pin is not None, f"pin {prefix} not assigned" + assert pin in valid_pins, f"pin {pin} not in valid pins {valid_pins}" + pinning[pin] = port + + for subport_name, subport in port._ports.items(): + remap_port_recursive(subport, f"{prefix}.{subport_name}") + + for io_port in self._io_ports: + if isinstance(io_port, Vector): + io_port.defined() + for subport_name in self.get(io_port.requested()): + assert subport_name not in seen_names, f"duplicate pin name {subport_name}" + seen_names.add(subport_name) + subport = io_port.append_elt(io_port._tpe.empty(), subport_name) + remap_port_recursive(subport, subport_name) + elif isinstance(io_port, Port): + if self.get(io_port.is_connected()): + port_name = io_port._name_from(self) + assert port_name not in seen_names, f"duplicate pin name {port_name}" + seen_names.add(port_name) + remap_port_recursive(io_port, port_name) + else: + raise NotImplementedError(f"unknown port type {io_port}") + + return pinning + + @staticmethod + def _remap_assigns_to_value(assigns: Dict[str, str]) -> List[str]: + """Given a dict of pin assigns from _remap_pinning_assigns, returns a list of assign strings + for use in self.actual_pin_assigns""" + return [f"{name}={assign}" for name, assign in assigns.items()] diff --git a/edg/abstract_parts/IoController.py b/edg/abstract_parts/IoController.py index b1946f1b7..7dc2002eb 100644 --- a/edg/abstract_parts/IoController.py +++ b/edg/abstract_parts/IoController.py @@ -206,6 +206,52 @@ def _export_tap_ios_inner(self, inner: "BaseIoController") -> None: inner_io = inner_ios_by_type[self_io_type] self.export_tap(self_io, inner_io) + def _generator_param_all_ios(self) -> None: + """Declares all BaseIoController IOs as generator params. + This must be a GeneratorBlock.""" + assert isinstance(self, GeneratorBlock) + for io_port in self._io_ports: + if isinstance(io_port, Vector): + self.generator_param(io_port.requested()) + elif isinstance(io_port, Port): + self.generator_param(io_port.is_connected()) + else: + raise NotImplementedError(f"unknown port type {io_port}") + + def _generator_pin_dict(self) -> Dict[str, Port]: + """Returns a dict of pin name to port for all IO ports, recursing into bundles Ports. + This includes both the bundle container Port and their (recursive) contents. + Users of this may want to filter by the port type. + + For Vector-typed IO ports, this generates the subports and must be authoritative. + This cannot be used with anything else that generates vector sub-ports. + This must be a GeneratorBlock.""" + assert isinstance(self, GeneratorBlock) + + pin_dict: Dict[str, Port] = {} + + def recurse_port(port: Port, prefix: str = "") -> None: + assert prefix not in pin_dict, f"duplicate pin name {prefix}" + pin_dict[prefix] = port + + for subport_name, subport in port._ports.items(): + recurse_port(subport, f"{prefix}.{subport_name}") + + for io_port in self._io_ports: + if isinstance(io_port, Vector): + io_port.defined() + for subport_name in self.get(io_port.requested()): + subport = io_port.append_elt(io_port._tpe.empty(), subport_name) + recurse_port(subport, subport_name) + elif isinstance(io_port, Port): + if self.get(io_port.is_connected()): + port_name = io_port._name_from(self) + recurse_port(io_port, port_name) + else: + raise NotImplementedError(f"unknown port type {io_port}") + + return pin_dict + @staticmethod def _instantiate_from( ios: List[BasePort], allocations: List[AllocatedResource] diff --git a/edg/abstract_parts/IoControllerWrapped.py b/edg/abstract_parts/IoControllerWrapped.py deleted file mode 100644 index 7202b3347..000000000 --- a/edg/abstract_parts/IoControllerWrapped.py +++ /dev/null @@ -1,64 +0,0 @@ -from typing import * - -from ..electronics_interfaces import * -from .IoController import BaseIoController - - -class IoControllerWrapped(BaseIoController): - """Base class for IoController wrapped blocks, particularly footprints that are used - with an outer WrapperSubboardBlock to implement e.g. a dev board or module around a modeling subcircuit. - - Provides some utility functions to remap pin assignments from the model to the footprint. - """ - - def _remap_pinning_assigns( - self, model_pin_assigns: List[str], remapping: Dict[str, str] - ) -> Tuple[Dict[str, HasPassivePort], Dict[str, str]]: - """Given the actual pin assignments and a remapping dict, returns the pinning dict for the footprint - and the updated actual pin assignments. - Generates concrete ports elements for IO Vectors""" - pinning: Dict[str, HasPassivePort] = {} - actual_pin_assigns: Dict[str, str] = {} - seen_names: Set[str] = set() - - model_pin_assigns_dict: Dict[str, str] = {} - for assign in model_pin_assigns: - name, pindef = assign.split("=") - pins = pindef.split(",") - model_pin_assigns_dict[name.strip()] = pins[0].strip() # use the GPIO name - - def remap_port_recursive(port: Port, prefix: str = "") -> None: - """Remaps a port, recursively for bundles""" - if isinstance(port, HasPassivePort): - if prefix not in model_pin_assigns_dict: - raise ValueError(f"pin {prefix} not assigned") - pin = model_pin_assigns_dict[prefix] - if pin not in remapping: - raise ValueError(f"pin {pin} not in remapping") - remapped_pin = remapping[pin] - pinning[remapped_pin] = port - actual_pin_assigns[prefix] = f"{pin}, {remapped_pin}" - - for subport_name, subport in port._ports.items(): - remap_port_recursive(subport, f"{prefix}.{subport_name}") - - for io_port in self._io_ports: - if isinstance(io_port, Vector): - io_port.defined() - for subport_name in self.get(io_port.requested()): - assert subport_name not in seen_names, f"duplicate pin name {subport_name}" - subport = io_port.append_elt(io_port._tpe.empty(), subport_name) - remap_port_recursive(subport, subport_name) - seen_names.add(subport_name) - elif isinstance(io_port, Port): - if self.get(io_port.is_connected()): - raise NotImplementedError("TODO implement me") - else: - raise NotImplementedError(f"unknown port type {io_port}") - - return pinning, actual_pin_assigns - - def _remap_assigns_to_value(self, assigns: Dict[str, str]) -> List[str]: - """Given a dict of pin assigns from _remap_pinning_assigns, returns a list of assign strings - for use in self.actual_pin_assigns""" - return [f"{name}={assign}" for name, assign in assigns.items()] diff --git a/edg/abstract_parts/PinMappable.py b/edg/abstract_parts/PinMappable.py index fc40eb065..70bb0cdff 100644 --- a/edg/abstract_parts/PinMappable.py +++ b/edg/abstract_parts/PinMappable.py @@ -53,15 +53,24 @@ class BaseDelegatingPinMapResource(BasePinMapResource): class PinResource(BaseLeafPinMapResource): - """A resource for a single chip pin, which can be one of several port types (eg, an ADC and DIO sharing a pin).""" + """A resource for a single chip pin, which can be one of several port types (eg, an ADC and DIO sharing a pin). - def __init__(self, pin: str, name_models: Mapping[str, Union[Passive, HasPassivePort]]): + Generally, this is initially created with pin = pin name (like GPIO0), then remapped so the pin = pin number, + with the pinname inheriting the prior pin name.""" + + def __init__( + self, pin: str, name_models: Mapping[str, Union[Passive, HasPassivePort]], pinname: Optional[str] = None + ): self.pin = pin self.name_models = name_models + if pinname is not None: + self.pinname = pinname + else: + self.pinname = pin @override def __repr__(self) -> str: - return f"PinResource({self.pin}, {self.name_models})" + return f"PinResource({self.pinname}, {self.pin}, {self.name_models})" @override def __eq__(self, other: Any) -> bool: @@ -79,14 +88,24 @@ class PeripheralFixedPin(BaseLeafPinMapResource): """A resource for a peripheral as a bundle port, where the internal ports are fixed. No allocation happens. The internal port model must be fully defined here.""" - def __init__(self, name: str, port_model: Port, inner_allowed_pins: Dict[str, str]): + def __init__( + self, + name: str, + port_model: Port, + inner_allowed_pins: Dict[str, str], + inner_pinnames: Optional[Dict[str, str]] = None, + ): self.name = name self.port_model = port_model self.inner_allowed_pins = inner_allowed_pins + if inner_pinnames is not None: + self.inner_pinnames = inner_pinnames + else: + self.inner_pinnames = inner_allowed_pins @override def __repr__(self) -> str: - return f"PeripheralFixedPin({self.name}, {self.port_model.__class__.__name__} {self.inner_allowed_pins})" + return f"PeripheralFixedPin({self.name}, {self.port_model.__class__.__name__} {self.inner_allowed_pins} {self.inner_pinnames})" @override def __eq__(self, other: Any) -> bool: @@ -96,6 +115,7 @@ def __eq__(self, other: Any) -> bool: and self.name == other.name and self.port_model is other.port_model and self.inner_allowed_pins == other.inner_allowed_pins + and self.inner_pinnames == other.inner_pinnames ) @@ -274,7 +294,7 @@ def remap_pins(self, pinmap: Dict[str, str]) -> "PinMapUtil": def remap_resource(resource: BasePinMapResource) -> Optional[BasePinMapResource]: if isinstance(resource, PinResource): if resource.pin in pinmap: - return PinResource(pinmap[resource.pin], resource.name_models) + return PinResource(pinmap[resource.pin], resource.name_models, resource.pinname) else: return None elif isinstance(resource, PeripheralFixedPin): @@ -283,7 +303,7 @@ def remap_resource(resource: BasePinMapResource) -> Optional[BasePinMapResource] for elt_name, elt_pin in resource.inner_allowed_pins.items() if elt_pin in pinmap } - return PeripheralFixedPin(resource.name, resource.port_model, remapped_pins) + return PeripheralFixedPin(resource.name, resource.port_model, remapped_pins, resource.inner_pinnames) elif isinstance(resource, BaseDelegatingPinMapResource): return resource else: @@ -308,6 +328,44 @@ def resource_pin(resource: BasePinMapResource) -> List[str]: return PinMapUtil(remapped_resources, self.transforms) + def filter_pins(self, allowed_pins: List[str]) -> "PinMapUtil": + """Returns a new PinMapUtil with only the specified pins kept. + If the allowed_pins list is empty, returns the input (all pins kept). + allowed_pins may be specified as a pin name or pin number.""" + + if not allowed_pins: + return self + + def filter_resource(resource: BasePinMapResource) -> Optional[BasePinMapResource]: + if isinstance(resource, PinResource): + if resource.pin in allowed_pins or resource.pinname in allowed_pins: + return resource + else: + return None + elif isinstance(resource, PeripheralFixedPin): + filtered_keys = [] + for key, pin in resource.inner_allowed_pins.items(): + if pin in allowed_pins or resource.inner_pinnames[key] in allowed_pins: + filtered_keys.append(key) + if filtered_keys: + return PeripheralFixedPin( + resource.name, + resource.port_model, + {k: v for k, v in resource.inner_allowed_pins.items() if k in filtered_keys}, + {k: v for k, v in resource.inner_pinnames.items() if k in filtered_keys}, + ) + else: + return None + elif isinstance(resource, BaseDelegatingPinMapResource): + return resource + else: + raise NotImplementedError(f"unknown resource {resource}") + + filtered_resources_raw = [filter_resource(resource) for resource in self.resources] + filtered_resources = [resource for resource in filtered_resources_raw if resource is not None] + + return PinMapUtil(filtered_resources, self.transforms) + @staticmethod def _resource_port_types(resource: BasePinMapResource) -> List[Type[Port]]: if isinstance(resource, PinResource): @@ -363,7 +421,7 @@ def try_allocate_resource( if isinstance(resource, PinResource): # single pin: just assign it sub_assignments.check_empty() resource_name, resource_model = resource.get_name_model_for_type(port_type) - allocated_resource = AllocatedResource(resource_model, port_name, resource_name, resource.pin) + allocated_resource = AllocatedResource(resource_model, port_name, resource.pinname, resource.pin) return allocated_resource elif isinstance(resource, PeripheralFixedPin): # fixed pin: check user-assignment, or assign first inner_pin_map: Dict[str, Tuple[str, Optional[str]]] = {} @@ -372,7 +430,7 @@ def try_allocate_resource( if inner_assignment is not None and inner_assignment != inner_pin: raise BadUserAssignError(f"invalid assignment to {port_name}.{inner_name}: {inner_assignment}") - inner_pin_map[inner_name] = (inner_pin, None) + inner_pin_map[inner_name] = (inner_pin, resource.inner_pinnames[inner_name]) inner_sub_assignments.check_empty() sub_assignments.check_empty() diff --git a/edg/abstract_parts/__init__.py b/edg/abstract_parts/__init__.py index d2b35fdc7..27f2c284e 100644 --- a/edg/abstract_parts/__init__.py +++ b/edg/abstract_parts/__init__.py @@ -129,7 +129,7 @@ from .IoController import BaseIoController, IoController, IoControllerPowerRequired, BaseIoControllerPinmapGenerator from .IoControllerExportable import BaseIoControllerExportable -from .IoControllerWrapped import IoControllerWrapped +from .BaseIoControllerWrapped import BaseIoControllerWrapped from .IoControllerInterfaceMixins import ( IoControllerSpiPeripheral, IoControllerI2cTarget, diff --git a/edg/abstract_parts/test_pinmappable.py b/edg/abstract_parts/test_pinmappable.py index 210753e5d..563f1191a 100644 --- a/edg/abstract_parts/test_pinmappable.py +++ b/edg/abstract_parts/test_pinmappable.py @@ -61,10 +61,92 @@ def test_assign_assigned(self) -> None: # fully user-specified ).allocate( [(DigitalBidir, ["DIO3", "DIO2"]), (AnalogSink, ["AIO4", "AIO5"])], ["DIO3=3", "DIO2=2", "AIO4=4", "AIO5=5"] ) - self.assertIn(AllocatedResource(dio_model, "DIO3", "PIO3", "3"), allocated) - self.assertIn(AllocatedResource(dio_model, "DIO2", "PIO2", "2"), allocated) - self.assertIn(AllocatedResource(ain_model, "AIO4", "AIn4", "4"), allocated) - self.assertIn(AllocatedResource(ain_model, "AIO5", "AIn5", "5"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO3", "3", "3"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO2", "2", "2"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO4", "4", "4"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO5", "5", "5"), allocated) + + def test_assign_remapped(self) -> None: # fully user-specified + dio_model = DigitalBidir() + ain_model = AnalogSink() + allocated = ( + PinMapUtil( + [ + PinResource("P1", {"PIO1": dio_model}), + PinResource("P2", {"PIO2": dio_model}), + PinResource("P3", {"PIO3": dio_model, "AIn3": ain_model}), + PinResource("P4", {"PIO4": dio_model, "AIn4": ain_model}), + PinResource("P5", {"AIn5": ain_model}), + ] + ) + .remap_pins( + { + "P1": "1", + "P2": "2", + "P3": "3", + "P4": "4", + "P5": "5", + } + ) + .allocate( + [(DigitalBidir, ["DIO3", "DIO2"]), (AnalogSink, ["AIO4", "AIO5"])], + ["DIO3=3", "DIO2=2", "AIO4=4", "AIO5=5"], + ) + ) + self.assertIn(AllocatedResource(dio_model, "DIO3", "P3", "3"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO2", "P2", "2"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO4", "P4", "4"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO5", "P5", "5"), allocated) + + def test_assign_filtered(self) -> None: # fully user-specified + dio_model = DigitalBidir() + allocated = ( + PinMapUtil( + [ + PinResource("P1", {"PIO1": dio_model}), + PinResource("P2", {"PIO2": dio_model}), + PinResource("P3", {"PIO3": dio_model}), + ] + ) + .remap_pins( + { + "P1": "1", + "P2": "2", + "P3": "3", + } + ) + .filter_pins(["P1", "P3"]) # test both pin name and pin number + .allocate([(DigitalBidir, ["DIO1", "DIO3"])]) + ) + self.assertIn(AllocatedResource(dio_model, "DIO1", "P1", "1"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO3", "P3", "3"), allocated) + + def test_assign_filtered_empty(self) -> None: + dio_model = DigitalBidir() + allocated = ( + PinMapUtil( + [ + PinResource("P1", {"PIO1": dio_model}), + PinResource("P2", {"PIO2": dio_model}), + ] + ) + .filter_pins([]) + .allocate([(DigitalBidir, ["DIO1", "DIO2"])]) + ) + self.assertIn(AllocatedResource(dio_model, "DIO1", "P1", "P1"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO2", "P2", "P2"), allocated) + + def test_assign_filtered_overflow(self) -> None: + dio_model = DigitalBidir() + with self.assertRaises(AutomaticAllocationError): + PinMapUtil( + [ + PinResource("1", {"PIO1": dio_model}), + PinResource("3", {"PIO3": dio_model}), + ] + ).filter_pins( + ["1"] + ).allocate([(DigitalBidir, ["DIO1", "DIO2"])]) def test_assign_mixed(self) -> None: # mix of user-specified and automatic assignments, assuming greedy algo dio_model = DigitalBidir() @@ -78,10 +160,10 @@ def test_assign_mixed(self) -> None: # mix of user-specified and automatic assi PinResource("5", {"AIn5": ain_model}), ] ).allocate([(DigitalBidir, ["DIO3", "DIO1"]), (AnalogSink, ["AIO5", "AIO4"])], ["DIO3=3", "AIO4=4"]) - self.assertIn(AllocatedResource(dio_model, "DIO3", "PIO3", "3"), allocated) - self.assertIn(AllocatedResource(dio_model, "DIO1", "PIO1", "1"), allocated) - self.assertIn(AllocatedResource(ain_model, "AIO4", "AIn4", "4"), allocated) - self.assertIn(AllocatedResource(ain_model, "AIO5", "AIn5", "5"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO3", "3", "3"), allocated) + self.assertIn(AllocatedResource(dio_model, "DIO1", "1", "1"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO4", "4", "4"), allocated) + self.assertIn(AllocatedResource(ain_model, "AIO5", "5", "5"), allocated) def test_assign_bad(self) -> None: # bad user-specified assignments dio_model = DigitalBidir() @@ -123,7 +205,7 @@ def test_assign_bundle_fixed(self) -> None: PeripheralFixedPin("USB0", usb_model, {"dm": "2", "dp": "3"}), ] ).allocate([(UsbDevicePort, ["usb"])], ["usb.dm=2", "usb.dp=3"]) - self.assertIn(AllocatedResource(usb_model, "usb", "USB0", {"dm": ("2", None), "dp": ("3", None)}), allocated) + self.assertIn(AllocatedResource(usb_model, "usb", "USB0", {"dm": ("2", "2"), "dp": ("3", "3")}), allocated) def test_assign_bundle_fixed_auto(self) -> None: usb_model = UsbDevicePort() @@ -132,7 +214,7 @@ def test_assign_bundle_fixed_auto(self) -> None: PeripheralFixedPin("USB0", usb_model, {"dm": "2", "dp": "3"}), ] ).allocate([(UsbDevicePort, ["usb"])]) - self.assertIn(AllocatedResource(usb_model, "usb", "USB0", {"dm": ("2", None), "dp": ("3", None)}), allocated) + self.assertIn(AllocatedResource(usb_model, "usb", "USB0", {"dm": ("2", "2"), "dp": ("3", "3")}), allocated) def test_assign_bundle_fixed_badspec(self) -> None: usb_model = UsbDevicePort() @@ -163,7 +245,7 @@ def test_assign_bundle_delegating(self) -> None: ).allocate([(UartPort, ["uart"])], ["uart.tx=1", "uart.rx=3"]) self.assertEqual(allocated[0].name, "uart") self.assertEqual(allocated[0].resource_name, "UART0") - self.assertEqual(allocated[0].pin, {"tx": ("1", "PIO1"), "rx": ("3", "PIO3")}) + self.assertEqual(allocated[0].pin, {"tx": ("1", "1"), "rx": ("3", "3")}) def test_assign_bundle_delegating_auto(self) -> None: dio_model = DigitalBidir() @@ -179,7 +261,7 @@ def test_assign_bundle_delegating_auto(self) -> None: ).allocate([(UartPort, ["uart"])]) self.assertEqual(allocated[0].name, "uart") self.assertEqual(allocated[0].resource_name, "UART0") - self.assertEqual(allocated[0].pin, {"tx": ("1", "PIO1"), "rx": ("2", "PIO2")}) + self.assertEqual(allocated[0].pin, {"tx": ("1", "1"), "rx": ("2", "2")}) def test_assign_bundle_delegating_badspec(self) -> None: dio_model = DigitalBidir() @@ -223,7 +305,7 @@ def test_assign_bundle_delegating_fixed(self) -> None: ).allocate([(UartPort, ["uart"])]) self.assertEqual(allocated[0].name, "uart") self.assertEqual(allocated[0].resource_name, "UART0") - self.assertEqual(allocated[0].pin, {"tx": ("3", "PIO3"), "rx": ("1", "PIO1")}) + self.assertEqual(allocated[0].pin, {"tx": ("3", "3"), "rx": ("1", "1")}) assert isinstance(allocated[0].port_model, UartPort) self.assertTrue(allocated[0].port_model.tx.voltage_out.initializer is not None) @@ -241,4 +323,4 @@ def test_assign_bundle_delegating_notconnected(self) -> None: ).allocate([(UartPort, ["uart"])], ["uart.tx=NC"]) self.assertEqual(allocated[0].name, "uart") self.assertEqual(allocated[0].resource_name, "UART0") - self.assertEqual(allocated[0].pin, {"rx": ("1", "PIO1")}) + self.assertEqual(allocated[0].pin, {"rx": ("1", "1")}) diff --git a/edg/parts/microcontroller/Lpc1549.py b/edg/parts/microcontroller/Lpc1549.py index ec908d498..e819eac71 100644 --- a/edg/parts/microcontroller/Lpc1549.py +++ b/edg/parts/microcontroller/Lpc1549.py @@ -370,7 +370,6 @@ class Lpc1549Base( IoControllerWithSwdTargetConnector, WithCrystalGenerator, IoControllerPowerRequired, - BaseIoControllerExportable, GeneratorBlock, ): DEVICE: Type[Lpc1549Base_Device] = Lpc1549Base_Device @@ -378,8 +377,13 @@ class Lpc1549Base( def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) - self.ic: Lpc1549Base_Device - self.generator_param(self.reset.is_connected()) + self.generator_param( + self.reset.is_connected(), + self.pin_assigns, + self.gpio.requested(), + self.usb.requested(), + self.can.requested(), + ) @override def contents(self) -> None: @@ -412,6 +416,9 @@ def contents(self) -> None: def generate(self) -> None: super().generate() + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {DigitalBidir: lambda port, assign: port}) + if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.reset) diff --git a/edg/parts/microcontroller/Rp2040.py b/edg/parts/microcontroller/Rp2040.py index c4ce7bce4..88c0e2fb8 100644 --- a/edg/parts/microcontroller/Rp2040.py +++ b/edg/parts/microcontroller/Rp2040.py @@ -51,16 +51,19 @@ class Rp2040_Device( "SWCLK": "24", } - def __init__(self, **kwargs: Any) -> None: + def __init__(self, *, allowed_pins: ArrayStringLike = [], _model: BoolLike = False, **kwargs: Any) -> None: super().__init__(**kwargs) + self.allowed_pins = self.ArgParameter(allowed_pins) # TODO move to infrastructure + self.generator_param(self.allowed_pins) + self._model = self.ArgParameter(_model) + self.gnd = self.Port(Ground(), [Common]) self.iovdd = self.Port( VoltageSink( voltage_limits=(1.62, 3.63) * Volt, # Table 628 current_draw=(1.2, 4.3) * mAmp + self.io_current_draw.upper(), # Table 629 ), - [Power], ) self.dvdd = self.Port( @@ -75,6 +78,7 @@ def __init__(self, **kwargs: Any) -> None: current_limits=(0, 100) * mAmp, # Table 1, max current ) ) + self.vreg_vin = self.Port( VoltageSink( voltage_limits=(1.62, 3.63) * Volt, # Table 628 @@ -107,10 +111,19 @@ def __init__(self, **kwargs: Any) -> None: pulldown_capable=True, ) - self.qspi = self.Port(SpiController(self._dio_std_model)) # TODO actually QSPI - self.qspi_cs = self.Port(self._dio_std_model) - self.qspi_sd2 = self.Port(self._dio_std_model) - self.qspi_sd3 = self.Port(self._dio_std_model) + self.qspi = self.Port(SpiController(self._dio_std_model), optional=True) # TODO actually QSPI + self.qspi_cs = self.Port(self._dio_std_model, optional=True) + self.qspi_sd2 = self.Port(self._dio_std_model, optional=True) + self.qspi_sd3 = self.Port(self._dio_std_model, optional=True) + self.require( + (~self._model).implies( + self.qspi.is_connected() + & self.qspi_cs.is_connected() + & self.qspi_sd2.is_connected() + & self.qspi_sd3.is_connected() + ), + "SPI memory required", + ) self.xosc = self.Port( CrystalDriver( @@ -119,7 +132,7 @@ def __init__(self, **kwargs: Any) -> None: optional=True, ) - self.swd = self.Port(SwdTargetPort.empty()) + self.swd = self.Port(SwdTargetPort.empty(), optional=True) self.run = self.Port(DigitalSink.from_bidir(self._dio_ft_model), optional=True) # internally pulled up self._io_ports.insert(0, self.swd) @@ -189,112 +202,116 @@ def _io_pinmap(self) -> PinMapUtil: i2c_model = I2cController(DigitalBidir.empty()) i2c_target_model = I2cTarget(DigitalBidir.empty()) - return PinMapUtil( - [ - PinResource("GPIO0", {"GPIO0": self._dio_ft_model}), - PinResource("GPIO1", {"GPIO1": self._dio_ft_model}), - PinResource("GPIO2", {"GPIO2": self._dio_ft_model}), - PinResource("GPIO3", {"GPIO3": self._dio_ft_model}), - PinResource("GPIO4", {"GPIO4": self._dio_ft_model}), - PinResource("GPIO5", {"GPIO5": self._dio_ft_model}), - PinResource("GPIO6", {"GPIO6": self._dio_ft_model}), - PinResource("GPIO7", {"GPIO7": self._dio_ft_model}), - PinResource("GPIO8", {"GPIO8": self._dio_ft_model}), - PinResource("GPIO9", {"GPIO9": self._dio_ft_model}), - PinResource("GPIO10", {"GPIO10": self._dio_ft_model}), - PinResource("GPIO11", {"GPIO11": self._dio_ft_model}), - PinResource("GPIO12", {"GPIO12": self._dio_ft_model}), - PinResource("GPIO13", {"GPIO13": self._dio_ft_model}), - PinResource("GPIO14", {"GPIO14": self._dio_ft_model}), - PinResource("GPIO15", {"GPIO15": self._dio_ft_model}), - PinResource("GPIO16", {"GPIO16": self._dio_ft_model}), - PinResource("GPIO17", {"GPIO17": self._dio_ft_model}), - PinResource("GPIO18", {"GPIO18": self._dio_ft_model}), - PinResource("GPIO19", {"GPIO19": self._dio_ft_model}), - PinResource("GPIO20", {"GPIO20": self._dio_ft_model}), - PinResource("GPIO21", {"GPIO21": self._dio_ft_model}), - PinResource("GPIO22", {"GPIO22": self._dio_ft_model}), - PinResource("GPIO23", {"GPIO23": self._dio_ft_model}), - PinResource("GPIO24", {"GPIO24": self._dio_ft_model}), - PinResource("GPIO25", {"GPIO25": self._dio_ft_model}), - PinResource("GPIO26", {"GPIO26": self._dio_std_model, "ADC0": adc_model}), - PinResource("GPIO27", {"GPIO27": self._dio_std_model, "ADC1": adc_model}), - PinResource("GPIO28", {"GPIO28": self._dio_std_model, "ADC2": adc_model}), - PinResource("GPIO29", {"GPIO29": self._dio_std_model, "ADC3": adc_model}), - # fixed-pin peripherals - PeripheralFixedPin("USB", UsbDevicePort(self._dio_usb_model), {"dm": "USB_DM", "dp": "USB_DP"}), - # reassignable peripherals - PeripheralFixedResource( - "UART0", - uart_model, - {"tx": ["GPIO0", "GPIO12", "GPIO16", "GPIO28"], "rx": ["GPIO1", "GPIO13", "GPIO17", "GPIO29"]}, - ), - PeripheralFixedResource( - "UART1", - uart_model, - {"tx": ["GPIO4", "GPIO8", "GPIO20", "GPIO24"], "rx": ["GPIO5", "GPIO9", "GPIO21", "GPIO25"]}, - ), - PeripheralFixedResource( - "SPI0", - spi_model, - { - "miso": ["GPIO0", "GPIO4", "GPIO16", "GPIO20"], # RX - "sck": ["GPIO2", "GPIO6", "GPIO18", "GPIO22"], - "mosi": ["GPIO3", "GPIO7", "GPIO19", "GPIO23"], # TX - }, - ), - PeripheralFixedResource( - "SPI1", - spi_model, - { - "miso": ["GPIO8", "GPIO12", "GPIO24", "GPIO28"], # RX - "sck": ["GPIO10", "GPIO14", "GPIO26"], - "mosi": ["GPIO11", "GPIO15", "GPIO27"], # TX - }, - ), - # SPI peripheral omitted, since TX tri-state is not tied to CS and must be controlled in software - PeripheralFixedResource( - "I2C0", - i2c_model, - { - "sda": ["GPIO0", "GPIO4", "GPIO8", "GPIO12", "GPIO16", "GPIO20", "GPIO24", "GPIO28"], - "scl": ["GPIO1", "GPIO5", "GPIO9", "GPIO13", "GPIO17", "GPIO21", "GPIO25", "GPIO20"], - }, - ), - PeripheralFixedResource( - "I2C1", - i2c_model, - { - "sda": ["GPIO2", "GPIO6", "GPIO10", "GPIO14", "GPIO18", "GPIO22", "GPIO24", "GPIO26"], - "scl": ["GPIO3", "GPIO7", "GPIO11", "GPIO15", "GPIO19", "GPIO23", "GPIO25", "GPIO27"], - }, - ), - PeripheralFixedResource( - "I2C0_T", - i2c_target_model, - { # TODO shared resource w/ I2C controller - "sda": ["GPIO0", "GPIO4", "GPIO8", "GPIO12", "GPIO16", "GPIO20", "GPIO24", "GPIO28"], - "scl": ["GPIO1", "GPIO5", "GPIO9", "GPIO13", "GPIO17", "GPIO21", "GPIO25", "GPIO20"], - }, - ), - PeripheralFixedResource( - "I2C1_T", - i2c_target_model, - { # TODO shared resource w/ I2C controller - "sda": ["GPIO2", "GPIO6", "GPIO10", "GPIO14", "GPIO18", "GPIO22", "GPIO24", "GPIO26"], - "scl": ["GPIO3", "GPIO7", "GPIO11", "GPIO15", "GPIO19", "GPIO23", "GPIO25", "GPIO27"], - }, - ), - PeripheralFixedPin( - "SWD", - SwdTargetPort(self._dio_std_model), - { - "swdio": "SWDIO", - "swclk": "SWCLK", - }, - ), - ] - ).remap_pins(self._PIN_MAPPING) + return ( + PinMapUtil( + [ + PinResource("GPIO0", {"GPIO0": self._dio_ft_model}), + PinResource("GPIO1", {"GPIO1": self._dio_ft_model}), + PinResource("GPIO2", {"GPIO2": self._dio_ft_model}), + PinResource("GPIO3", {"GPIO3": self._dio_ft_model}), + PinResource("GPIO4", {"GPIO4": self._dio_ft_model}), + PinResource("GPIO5", {"GPIO5": self._dio_ft_model}), + PinResource("GPIO6", {"GPIO6": self._dio_ft_model}), + PinResource("GPIO7", {"GPIO7": self._dio_ft_model}), + PinResource("GPIO8", {"GPIO8": self._dio_ft_model}), + PinResource("GPIO9", {"GPIO9": self._dio_ft_model}), + PinResource("GPIO10", {"GPIO10": self._dio_ft_model}), + PinResource("GPIO11", {"GPIO11": self._dio_ft_model}), + PinResource("GPIO12", {"GPIO12": self._dio_ft_model}), + PinResource("GPIO13", {"GPIO13": self._dio_ft_model}), + PinResource("GPIO14", {"GPIO14": self._dio_ft_model}), + PinResource("GPIO15", {"GPIO15": self._dio_ft_model}), + PinResource("GPIO16", {"GPIO16": self._dio_ft_model}), + PinResource("GPIO17", {"GPIO17": self._dio_ft_model}), + PinResource("GPIO18", {"GPIO18": self._dio_ft_model}), + PinResource("GPIO19", {"GPIO19": self._dio_ft_model}), + PinResource("GPIO20", {"GPIO20": self._dio_ft_model}), + PinResource("GPIO21", {"GPIO21": self._dio_ft_model}), + PinResource("GPIO22", {"GPIO22": self._dio_ft_model}), + PinResource("GPIO23", {"GPIO23": self._dio_ft_model}), + PinResource("GPIO24", {"GPIO24": self._dio_ft_model}), + PinResource("GPIO25", {"GPIO25": self._dio_ft_model}), + PinResource("GPIO26", {"GPIO26": self._dio_std_model, "ADC0": adc_model}), + PinResource("GPIO27", {"GPIO27": self._dio_std_model, "ADC1": adc_model}), + PinResource("GPIO28", {"GPIO28": self._dio_std_model, "ADC2": adc_model}), + PinResource("GPIO29", {"GPIO29": self._dio_std_model, "ADC3": adc_model}), + # fixed-pin peripherals + PeripheralFixedPin("USB", UsbDevicePort(self._dio_usb_model), {"dm": "USB_DM", "dp": "USB_DP"}), + # reassignable peripherals + PeripheralFixedResource( + "UART0", + uart_model, + {"tx": ["GPIO0", "GPIO12", "GPIO16", "GPIO28"], "rx": ["GPIO1", "GPIO13", "GPIO17", "GPIO29"]}, + ), + PeripheralFixedResource( + "UART1", + uart_model, + {"tx": ["GPIO4", "GPIO8", "GPIO20", "GPIO24"], "rx": ["GPIO5", "GPIO9", "GPIO21", "GPIO25"]}, + ), + PeripheralFixedResource( + "SPI0", + spi_model, + { + "miso": ["GPIO0", "GPIO4", "GPIO16", "GPIO20"], # RX + "sck": ["GPIO2", "GPIO6", "GPIO18", "GPIO22"], + "mosi": ["GPIO3", "GPIO7", "GPIO19", "GPIO23"], # TX + }, + ), + PeripheralFixedResource( + "SPI1", + spi_model, + { + "miso": ["GPIO8", "GPIO12", "GPIO24", "GPIO28"], # RX + "sck": ["GPIO10", "GPIO14", "GPIO26"], + "mosi": ["GPIO11", "GPIO15", "GPIO27"], # TX + }, + ), + # SPI peripheral omitted, since TX tri-state is not tied to CS and must be controlled in software + PeripheralFixedResource( + "I2C0", + i2c_model, + { + "sda": ["GPIO0", "GPIO4", "GPIO8", "GPIO12", "GPIO16", "GPIO20", "GPIO24", "GPIO28"], + "scl": ["GPIO1", "GPIO5", "GPIO9", "GPIO13", "GPIO17", "GPIO21", "GPIO25", "GPIO20"], + }, + ), + PeripheralFixedResource( + "I2C1", + i2c_model, + { + "sda": ["GPIO2", "GPIO6", "GPIO10", "GPIO14", "GPIO18", "GPIO22", "GPIO24", "GPIO26"], + "scl": ["GPIO3", "GPIO7", "GPIO11", "GPIO15", "GPIO19", "GPIO23", "GPIO25", "GPIO27"], + }, + ), + PeripheralFixedResource( + "I2C0_T", + i2c_target_model, + { # TODO shared resource w/ I2C controller + "sda": ["GPIO0", "GPIO4", "GPIO8", "GPIO12", "GPIO16", "GPIO20", "GPIO24", "GPIO28"], + "scl": ["GPIO1", "GPIO5", "GPIO9", "GPIO13", "GPIO17", "GPIO21", "GPIO25", "GPIO20"], + }, + ), + PeripheralFixedResource( + "I2C1_T", + i2c_target_model, + { # TODO shared resource w/ I2C controller + "sda": ["GPIO2", "GPIO6", "GPIO10", "GPIO14", "GPIO18", "GPIO22", "GPIO24", "GPIO26"], + "scl": ["GPIO3", "GPIO7", "GPIO11", "GPIO15", "GPIO19", "GPIO23", "GPIO25", "GPIO27"], + }, + ), + PeripheralFixedPin( + "SWD", + SwdTargetPort(self._dio_std_model), + { + "swdio": "SWDIO", + "swclk": "SWCLK", + }, + ), + ] + ) + .remap_pins(self._PIN_MAPPING) + .filter_pins(self.get(self.allowed_pins)) + ) class Rp2040( @@ -338,7 +355,7 @@ def contents(self) -> None: self.connect(self.ic.qspi_sd2, mem_qspi.io2) self.connect(self.ic.qspi_sd3, mem_qspi.io3) - self.connect(self.pwr, self.ic.vreg_vin, self.ic.adc_avdd, self.ic.usb_vdd) + self.connect(self.pwr, self.ic.iovdd, self.ic.vreg_vin, self.ic.adc_avdd, self.ic.usb_vdd) self.connect(self.ic.vreg_vout, self.ic.dvdd) self.dvdd_cap = ElementDict[DecouplingCapacitor]() @@ -367,7 +384,9 @@ def _crystal_required(self) -> bool: # crystal needed for USB b/c tighter freq return len(self.get(self.usb.requested())) > 0 or super()._crystal_required() -class Xiao_Rp2040_Device(Rp2040_Interfaces, IoControllerWrapped, InternalSubcircuit, GeneratorBlock, FootprintBlock): +class Xiao_Rp2040_Device( + Rp2040_Interfaces, BaseIoControllerWrapped, InternalSubcircuit, GeneratorBlock, FootprintBlock +): """Footprint-only device model for the Xiao RP2040 microcontroller dev board""" _PIN_REMAPPING = { @@ -384,39 +403,26 @@ class Xiao_Rp2040_Device(Rp2040_Interfaces, IoControllerWrapped, InternalSubcirc "GPIO3": "11", } - def __init__(self, model_pin_assigns: ArrayStringLike): - super().__init__() - self.model_pin_assigns = self.ArgParameter(model_pin_assigns) + def __init__(self, **kwargs: Any) -> None: + super().__init__(**kwargs) self.gnd = self.Port(Ground.empty(), optional=True) - self.v3v3 = self.Port(VoltageSink.empty(), optional=True) - self.v3v3_out = self.Port(VoltageSource.empty(), optional=True) - self.vcc = self.Port(VoltageSink.empty(), optional=True) # VUsb - self.vcc_out = self.Port(VoltageSource.empty(), optional=True) - self.generator_param(self.v3v3.is_connected(), self.vcc.is_connected(), self.model_pin_assigns) - - # TODO MOVE TO INFRASTRUCTURE - for io_port in self._io_ports: - if isinstance(io_port, Vector): - self.generator_param(io_port.requested()) - elif isinstance(io_port, Port): - self.generator_param(io_port.is_connected()) - else: - raise NotImplementedError(f"unknown port type {io_port}") + self.v3v3 = self.Port(Passive.empty(), optional=True) + self.vcc = self.Port(Passive.empty(), optional=True) # VUsb + self.generator_param(self.pin_assigns) + self._generator_param_all_ios() @override def generate(self) -> None: super().generate() - pinning: Dict[str, HasPassivePort] = { - "12": self.v3v3 if self.get(self.v3v3.is_connected()) else self.v3v3_out, + pinning: Dict[str, Union[Passive, HasPassivePort]] = { + "12": self.v3v3, "13": self.gnd, - "14": self.vcc if self.get(self.vcc.is_connected()) else self.vcc_out, # VUsb + "14": self.vcc, # VUsb } - remap_pinnings, remap_pin_assigns = self._remap_pinning_assigns( - self.get(self.model_pin_assigns), self._PIN_REMAPPING - ) - pinning.update(remap_pinnings) - self.assign(self.actual_pin_assigns, self._remap_assigns_to_value(remap_pin_assigns)) + remapped_pin_assigns = self._remap_pin_assigns_list(self._PIN_REMAPPING, self.get(self.pin_assigns)) + pinning.update(self._remap_to_footprint_pinning(remapped_pin_assigns, self._PIN_REMAPPING.values())) + self.assign(self.actual_pin_assigns, self._remap_assigns_to_value(remapped_pin_assigns)) self.footprint( "U", @@ -451,6 +457,7 @@ class Xiao_Rp2040( def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self.generator_param( + self.pin_assigns, self.gnd.is_connected(), self.pwr.is_connected(), self.pwr_out.is_connected(), @@ -459,8 +466,8 @@ def __init__(self, **kwargs: Any) -> None: ) @override - def contents(self) -> None: - super().contents() + def generate(self) -> None: + super().generate() self.pwr_vin.init_from( VoltageSink( # based on RS3236-3.3 @@ -492,21 +499,28 @@ def contents(self) -> None: "ground required if power used", ) - self.model = self.Block(Rp2040(pin_assigns=ArrayStringExpr())) - model_pin_assigns = self._export_ios_inner(self.model) - self.assign(self.model.pin_assigns, model_pin_assigns) + self.model = self.Block( + Rp2040_Device( + pin_assigns=BaseIoControllerWrapped._remap_assigns_to_value( + BaseIoControllerWrapped._remap_pin_assigns_list( + Xiao_Rp2040_Device._PIN_REMAPPING, self.get(self.pin_assigns), invert_remapping=True + ) + ), + allowed_pins=list(Xiao_Rp2040_Device._PIN_REMAPPING.keys()), + _model=True, + ) + ) + self._export_ios_inner(self.model) - self.device = self.Block(Xiao_Rp2040_Device(model_pin_assigns=self.model.actual_pin_assigns), external=True) + self.device = self.Block(Xiao_Rp2040_Device(pin_assigns=self.model.actual_pin_assigns), external=True) self._export_tap_ios_inner(self.device) self.assign(self.actual_pin_assigns, self.device.actual_pin_assigns) - @override - def generate(self) -> None: - super().generate() - + self.connect(self.model.vreg_vout, self.model.dvdd) + model_pwr = self.connect(self.model.iovdd, self.model.vreg_vin, self.model.adc_avdd, self.model.usb_vdd) if self.get(self.pwr.is_connected()): # power supplied externally - self.connect(self.pwr, self.model.pwr) - self.export_tap(self.pwr, self.device.v3v3) + self.connect(self.pwr, model_pwr) + self.export_tap(self.pwr.net, self.device.v3v3) else: # board sources power from USB self.pwr_out_model = self.Block( DummyVoltageSource( @@ -514,15 +528,15 @@ def generate(self) -> None: current_limits=UsbConnector.USB2_CURRENT_LIMITS, ) ) - self.connect(self.pwr_out_model.pwr, self.model.pwr) + self.connect(self.pwr_out_model.pwr, model_pwr) if self.get(self.pwr_out.is_connected()): self.connect(self.pwr_out, self.pwr_out_model.pwr) - self.export_tap(self.pwr_out, self.device.v3v3_out) + self.export_tap(self.pwr_out.net, self.device.v3v3) if self.get(self.pwr_vin.is_connected()): - self.export_tap(self.pwr_vin, self.device.vcc) + self.export_tap(self.pwr_vin.net, self.device.vcc) if self.get(self.vusb_out.is_connected()): - self.export_tap(self.vusb_out, self.device.vcc_out) + self.export_tap(self.vusb_out.net, self.device.vcc) self.export_tap(self.gnd, self.device.gnd) if self.get(self.gnd.is_connected()): diff --git a/edg/parts/microcontroller/Stm32f103.py b/edg/parts/microcontroller/Stm32f103.py index c9eb5b7e3..dca5196df 100644 --- a/edg/parts/microcontroller/Stm32f103.py +++ b/edg/parts/microcontroller/Stm32f103.py @@ -294,7 +294,6 @@ class Stm32f103Base( IoControllerWithSwdTargetConnector, WithCrystalGenerator, IoControllerPowerRequired, - BaseIoControllerExportable, GeneratorBlock, ): DEVICE: Type[Stm32f103Base_Device] = Stm32f103Base_Device @@ -302,8 +301,13 @@ class Stm32f103Base( def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) - self.ic: Stm32f103Base_Device - self.generator_param(self.reset.is_connected()) + self.generator_param( + self.reset.is_connected(), + self.pin_assigns, + self.gpio.requested(), + self.can.requested(), + self.usb.requested(), + ) @override def contents(self) -> None: @@ -329,24 +333,19 @@ def contents(self) -> None: def generate(self) -> None: super().generate() - if self.get(self.reset.is_connected()): - self.connect(self.reset, self.ic.nrst) - - ExportType = TypeVar("ExportType", bound=Port) - - @override - def _make_export_vector( - self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str] - ) -> Optional[str]: - if isinstance(self_io, UsbDevicePort): # assumed at most one USB port generates - inner_io = inner_vector.request(name) + def usb_export_transform(self_io: BasePort, assign: Optional[str]) -> Optional[BasePort]: self.usb_pull = self.Block( UsbDpPullUp(resistance=1.5 * kOhm(tol=0.01)) ) # required by datasheet Table 44 # TODO proper tolerancing? self.connect(self.usb_pull.pwr, self.pwr) - self.connect(inner_io, self_io, self.usb_pull.usb) - return assign - return super()._make_export_vector(self_io, inner_vector, name, assign) + self.connect(self_io, self.usb_pull.usb) + return self_io + + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {UsbDevicePort: usb_export_transform, DigitalBidir: lambda port, assign: port}) + + if self.get(self.reset.is_connected()): + self.connect(self.reset, self.ic.nrst) @override def _crystal_required(self) -> bool: # crystal needed for CAN or USB b/c tighter freq tolerance diff --git a/edg/parts/microcontroller/Stm32g031.py b/edg/parts/microcontroller/Stm32g031.py index 441f25f69..d3d4c948e 100644 --- a/edg/parts/microcontroller/Stm32g031.py +++ b/edg/parts/microcontroller/Stm32g031.py @@ -240,7 +240,6 @@ class Stm32g031Base( Microcontroller, IoControllerWithSwdTargetConnector, IoControllerPowerRequired, - BaseIoControllerExportable, GeneratorBlock, ): DEVICE: Type[Stm32g031Base_Device] = Stm32g031Base_Device @@ -248,7 +247,7 @@ class Stm32g031Base( def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) self.ic: Stm32g031Base_Device - self.generator_param(self.reset.is_connected()) + self.generator_param(self.reset.is_connected(), self.pin_assigns, self.gpio.requested()) @override def contents(self) -> None: @@ -267,6 +266,9 @@ def contents(self) -> None: def generate(self) -> None: super().generate() + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {DigitalBidir: lambda port, assign: port}) + if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.nrst) # otherwise NRST has internal pull-up diff --git a/edg/parts/microcontroller/Stm32g431.py b/edg/parts/microcontroller/Stm32g431.py index 00b99edb3..3f9c48da5 100644 --- a/edg/parts/microcontroller/Stm32g431.py +++ b/edg/parts/microcontroller/Stm32g431.py @@ -267,15 +267,13 @@ class Stm32g431Base( Microcontroller, IoControllerWithSwdTargetConnector, IoControllerPowerRequired, - BaseIoControllerExportable, GeneratorBlock, ): DEVICE: Type[Stm32g431Base_Device] = Stm32g431Base_Device def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) - self.ic: Stm32g431Base_Device - self.generator_param(self.reset.is_connected()) + self.generator_param(self.reset.is_connected(), self.pin_assigns, self.gpio.requested()) @override def contents(self) -> None: @@ -296,6 +294,10 @@ def contents(self) -> None: @override def generate(self) -> None: super().generate() + + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {DigitalBidir: lambda port, assign: port}) + if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.nrst) # otherwise NRST has internal pull-up diff --git a/edg/parts/microcontroller/Stm32l432.py b/edg/parts/microcontroller/Stm32l432.py index 569b06e5e..90a7686d5 100644 --- a/edg/parts/microcontroller/Stm32l432.py +++ b/edg/parts/microcontroller/Stm32l432.py @@ -244,15 +244,13 @@ class Stm32l432Base( IoControllerWithSwdTargetConnector, WithCrystalGenerator, IoControllerPowerRequired, - BaseIoControllerExportable, GeneratorBlock, ): DEVICE: Type[Stm32l432Base_Device] = Stm32l432Base_Device def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) - self.ic: Stm32l432Base_Device - self.generator_param(self.reset.is_connected()) + self.generator_param(self.reset.is_connected(), self.pin_assigns, self.gpio.requested(), self.can.requested()) @override def contents(self) -> None: @@ -275,6 +273,9 @@ def contents(self) -> None: def generate(self) -> None: super().generate() + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {DigitalBidir: lambda port, assign: port}) + if self.get(self.reset.is_connected()): self.connect(self.reset, self.ic.nrst) # otherwise NRST has internal pull-up diff --git a/edg/parts/microcontroller/nRF52840.py b/edg/parts/microcontroller/nRF52840.py index 9adc4609e..4189f6a73 100644 --- a/edg/parts/microcontroller/nRF52840.py +++ b/edg/parts/microcontroller/nRF52840.py @@ -14,45 +14,142 @@ class Nrf52840_Interfaces( """Defines base interfaces for nRF52840 microcontrollers""" -@non_library -class Nrf52840_Ios(Nrf52840_Interfaces, BaseIoControllerPinmapGenerator, GeneratorBlock, FootprintBlock): - """nRF52840 IO mappings - https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf""" +class Mdbt50q_1mv2_Device( + Nrf52840_Interfaces, BaseIoControllerPinmapGenerator, InternalSubcircuit, JlcPart, GeneratorBlock, FootprintBlock +): + # in the absence of a chip-level subcircuit, this is used as the authoritative base device model + # that other modules should wrap + + _PIN_MAPPING = { # boundary pins only, inner pins ignored + "P1.10": "3", + "P1.11": "4", + "P1.12": "5", + "P1.13": "6", + "P1.14": "7", + "P1.15": "8", + "P0.03": "9", + "P0.29": "10", + "P0.02": "11", + "P0.31": "12", + "P0.28": "13", + "P0.30": "14", + "P0.27": "16", + "P0.00": "17", + "P0.01": "18", + "P0.26": "19", + "P0.04": "20", + "P0.05": "21", + "P0.06": "22", + "P0.07": "23", + "P0.08": "24", + "P1.08": "25", + "P1.09": "26", + "P0.11": "27", + "P0.12": "29", + "D-": "34", + "D+": "35", + "P0.14": "36", + "P0.13": "37", + "P0.16": "38", + "P0.15": "39", + "P0.17": "41", + "P0.19": "42", + "P0.21": "43", + "P0.20": "44", + "P0.23": "45", + "P0.22": "46", + "P1.00": "47", + "P0.24": "48", + "P0.25": "49", + "P1.02": "50", + "SWDIO": "51", + "P0.09": "52", + "SWCLK": "53", + "P0.10": "54", + "P1.04": "56", + "P1.06": "57", + "P1.07": "58", + "P1.05": "59", + "P1.03": "60", + "P1.01": "61", + } - RESOURCE_PIN_REMAP: Dict[str, str] # resource name in base -> pin name + def __init__(self, allowed_pins: ArrayStringLike = [], **kwargs: Any) -> None: + super().__init__(**kwargs) + + self.allowed_pins = self.ArgParameter(allowed_pins) # TODO move to infrastructure + self.generator_param(self.allowed_pins) - @abstractmethod - def _vddio(self) -> Port[VoltageLink]: ... + self.gnd = self.Port(Ground(), [Common]) + self.pwr = self.Port( + VoltageSink( + voltage_limits=(1.75, 3.6) * Volt, # 1.75 minimum for power-on reset + current_draw=(0, 212 / 64 + 4.8) * mAmp + + self.io_current_draw.upper(), # CPU @ max 212 Coremarks + 4.8mA in RF transmit + ), + [Power], + ) - def _vdd_model(self) -> VoltageSink: - return VoltageSink( - voltage_limits=(1.75, 3.6) * Volt, # 1.75 minimum for power-on reset - current_draw=(0, 212 / 64 + 4.8) * mAmp - + self.io_current_draw.upper(), # CPU @ max 212 Coremarks + 4.8mA in RF transmit + self.pwr_usb = self.Port( + VoltageSink( + voltage_limits=(4.35, 5.5) * Volt, + current_draw=(0.262, 7.73) * mAmp, # CPU/USB sleeping to everything active + ), + optional=True, ) + self.require((self.usb.length() > 0).implies(self.pwr_usb.is_connected()), "USB require Vbus connected") - def _dio_model(self, pwr: Port[VoltageLink]) -> DigitalBidir: - return DigitalBidir.from_supply( + self._dio_model = DigitalBidir.from_supply( self.gnd, - pwr, + self.pwr, voltage_limit_tolerance=(-0.3, 0.3) * Volt, current_limits=(-6, 6) * mAmp, # minimum current, high drive, Vdd>2.7 input_threshold_factor=(0.3, 0.7), pullup_capable=True, pulldown_capable=True, ) + self._dio_lf_model = self._dio_model # "standard drive, low frequency IO only" (differences not modeled) + self.swd = self.Port(SwdTargetPort.empty(), optional=True) + self.nreset = self.Port(DigitalSink.from_bidir(self._dio_model), optional=True) + self._io_ports.insert(0, self.swd) + + @override + def generate(self) -> None: + super().generate() + + self.assign(self.lcsc_part, "C5118826") + self.assign(self.actual_basic_part, False) + self.footprint( + "U", + "RF_Module:Raytac_MDBT50Q", + self._make_pinning(), + mfr="Raytac", + part="MDBT50Q-1MV2", + datasheet="https://www.raytac.com/download/index.php?index_id=43", + ) + + @override + def _system_pinmap(self) -> Dict[str, Union[Passive, HasPassivePort]]: + return { + "28": self.pwr, # Vdd + "30": self.pwr, # VddH + # "31": DccH is disconnected - from section 8.3 for input voltage <3.6v + "1": self.gnd, + "2": self.gnd, + "15": self.gnd, + "33": self.gnd, + "55": self.gnd, + "32": self.pwr_usb, + "40": self.nreset, + } @override def _io_pinmap(self) -> PinMapUtil: """Returns the mappable for given the input power and ground references. This separates the system pins definition from the IO pins definition.""" - pwr = self._vddio() - dio_model = self._dio_model(pwr) - dio_lf_model = dio_model # "standard drive, low frequency IO only" (differences not modeled) - adc_model = AnalogSink.from_supply( self.gnd, - pwr, + self.pwr, voltage_limit_tolerance=(0, 0), # datasheet 6.23.2, analog inputs cannot exceed Vdd or be lower than Vss signal_limit_tolerance=(0, 0), impedance=Range.from_lower(1) * MOhm, @@ -94,249 +191,245 @@ def _io_pinmap(self) -> PinMapUtil: "P1.00", ] - return PinMapUtil( - [ # Section 7.1.2 with QIAA aQFN73 & QFAA QFN48 pins only - PinResource("P0.31", {"P0.31": dio_lf_model, "AIN7": adc_model}), - PinResource("P0.29", {"P0.29": dio_lf_model, "AIN5": adc_model}), - PinResource("P0.02", {"P0.02": dio_lf_model, "AIN0": adc_model}), - PinResource("P1.15", {"P1.15": dio_lf_model}), - PinResource("P1.13", {"P1.13": dio_lf_model}), - PinResource("P1.10", {"P1.10": dio_lf_model}), - PinResource("P0.30", {"P0.30": dio_lf_model, "AIN6": adc_model}), - PinResource("P0.28", {"P0.28": dio_lf_model, "AIN4": adc_model}), - PinResource("P0.03", {"P0.03": dio_lf_model, "AIN1": adc_model}), - PinResource("P1.14", {"P1.14": dio_lf_model}), - PinResource("P1.12", {"P1.12": dio_lf_model}), - PinResource("P1.11", {"P1.11": dio_lf_model}), - PinResource("P0.00", {"P0.00": dio_model}), # TODO also 32.768 kHz crystal in - PinResource("P0.01", {"P0.01": dio_model}), # TODO also 32.768 kHz crystal in - PinResource("P0.26", {"P0.26": dio_model}), - PinResource("P0.27", {"P0.27": dio_model}), - PinResource("P0.04", {"P0.04": dio_model, "AIN2": adc_model}), - PinResource("P0.10", {"P0.10": dio_lf_model}), # TODO also NFC2 - PinResource("P0.05", {"P0.05": dio_model, "AIN3": adc_model}), - PinResource("P0.06", {"P0.06": dio_model}), - PinResource("P0.09", {"P0.09": dio_lf_model}), # TODO also NFC1 - PinResource("P0.07", {"P0.07": dio_model}), - PinResource("P0.08", {"P0.08": dio_model}), - PinResource("P1.08", {"P1.08": dio_model}), - PinResource("P1.07", {"P1.07": dio_lf_model}), - PinResource("P1.09", {"P1.09": dio_model}), - PinResource("P1.06", {"P1.06": dio_lf_model}), - PinResource("P0.11", {"P0.11": dio_model}), - PinResource("P1.05", {"P1.05": dio_lf_model}), - PinResource("P0.12", {"P0.12": dio_model}), - PinResource("P1.04", {"P1.04": dio_lf_model}), - PinResource("P1.03", {"P1.03": dio_lf_model}), - PinResource("P1.02", {"P1.02": dio_lf_model}), - PinResource("P1.01", {"P1.01": dio_lf_model}), - PinResource("P0.14", {"P0.14": dio_model}), - PinResource("P0.16", {"P0.16": dio_model}), - # PinResource('P0.18', {'P0.18': dio_model}), # configurable as RESET, mappable - PinResource("P0.19", {"P0.19": dio_model}), - PinResource("P0.21", {"P0.21": dio_model}), - PinResource("P0.23", {"P0.23": dio_model}), - PinResource("P0.25", {"P0.25": dio_model}), - PinResource("P0.13", {"P0.13": dio_model}), - PinResource("P0.15", {"P0.15": dio_model}), - PinResource("P0.17", {"P0.17": dio_model}), - PinResource("P0.20", {"P0.20": dio_model}), - PinResource("P0.22", {"P0.22": dio_model}), - PinResource("P0.24", {"P0.24": dio_model}), - PinResource( - "P1.00", {"P1.00": dio_model} - ), # TRACEDATA[0] and SWO, if used as IO must clear TRACECONFIG reg - PeripheralFixedPin( - "SWD", - SwdTargetPort(dio_model), - { - "swclk": "SWCLK", - "swdio": "SWDIO", - }, - ), - PeripheralFixedPin("USBD", UsbDevicePort(), {"dp": "D+", "dm": "D-"}), - PeripheralFixedResource( - "SPIM0", - spi_model, - { - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIM1", - spi_model, - { - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIM2", - spi_model, - { - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIM3", - spi_model, - { - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIS0", - spi_peripheral_model, - { # TODO shared resource w/ SPI controller - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIS1", - spi_peripheral_model, - { # TODO shared resource w/ SPI controller - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "SPIS2", - spi_peripheral_model, - { # TODO shared resource w/ SPI controller - "sck": hf_io_pins, - "miso": hf_io_pins, - "mosi": hf_io_pins, - }, - ), - PeripheralFixedResource( - "TWIM0", - i2c_model, - { - "scl": hf_io_pins, - "sda": hf_io_pins, - }, - ), - PeripheralFixedResource( - "TWIM1", - i2c_model, - { - "scl": hf_io_pins, - "sda": hf_io_pins, - }, - ), - PeripheralFixedResource( - "TWIS0", - i2c_target_model, - { # TODO shared resource w/ I2C controller - "scl": hf_io_pins, - "sda": hf_io_pins, - }, - ), - PeripheralFixedResource( - "TWIS1", - i2c_target_model, - { # TODO shared resource w/ I2C controller - "scl": hf_io_pins, - "sda": hf_io_pins, - }, - ), - PeripheralFixedResource( - "UARTE0", - uart_model, - { - "tx": hf_io_pins, - "rx": hf_io_pins, - }, - ), - PeripheralFixedResource( - "UARTE1", - uart_model, - { - "tx": hf_io_pins, - "rx": hf_io_pins, - }, - ), - PeripheralFixedResource( - "I2S", - i2s_model, - { - "sck": hf_io_pins, - "ws": hf_io_pins, - "sd": hf_io_pins, - }, - ), - ] - ).remap_pins(self.RESOURCE_PIN_REMAP) + return ( + PinMapUtil( + [ # Section 7.1.2 with QIAA aQFN73 & QFAA QFN48 pins only + PinResource("P0.31", {"P0.31": self._dio_lf_model, "AIN7": adc_model}), + PinResource("P0.29", {"P0.29": self._dio_lf_model, "AIN5": adc_model}), + PinResource("P0.02", {"P0.02": self._dio_lf_model, "AIN0": adc_model}), + PinResource("P1.15", {"P1.15": self._dio_lf_model}), + PinResource("P1.13", {"P1.13": self._dio_lf_model}), + PinResource("P1.10", {"P1.10": self._dio_lf_model}), + PinResource("P0.30", {"P0.30": self._dio_lf_model, "AIN6": adc_model}), + PinResource("P0.28", {"P0.28": self._dio_lf_model, "AIN4": adc_model}), + PinResource("P0.03", {"P0.03": self._dio_lf_model, "AIN1": adc_model}), + PinResource("P1.14", {"P1.14": self._dio_lf_model}), + PinResource("P1.12", {"P1.12": self._dio_lf_model}), + PinResource("P1.11", {"P1.11": self._dio_lf_model}), + PinResource("P0.00", {"P0.00": self._dio_model}), # TODO also 32.768 kHz crystal in + PinResource("P0.01", {"P0.01": self._dio_model}), # TODO also 32.768 kHz crystal in + PinResource("P0.26", {"P0.26": self._dio_model}), + PinResource("P0.27", {"P0.27": self._dio_model}), + PinResource("P0.04", {"P0.04": self._dio_model, "AIN2": adc_model}), + PinResource("P0.10", {"P0.10": self._dio_lf_model}), # TODO also NFC2 + PinResource("P0.05", {"P0.05": self._dio_model, "AIN3": adc_model}), + PinResource("P0.06", {"P0.06": self._dio_model}), + PinResource("P0.09", {"P0.09": self._dio_lf_model}), # TODO also NFC1 + PinResource("P0.07", {"P0.07": self._dio_model}), + PinResource("P0.08", {"P0.08": self._dio_model}), + PinResource("P1.08", {"P1.08": self._dio_model}), + PinResource("P1.07", {"P1.07": self._dio_lf_model}), + PinResource("P1.09", {"P1.09": self._dio_model}), + PinResource("P1.06", {"P1.06": self._dio_lf_model}), + PinResource("P0.11", {"P0.11": self._dio_model}), + PinResource("P1.05", {"P1.05": self._dio_lf_model}), + PinResource("P0.12", {"P0.12": self._dio_model}), + PinResource("P1.04", {"P1.04": self._dio_lf_model}), + PinResource("P1.03", {"P1.03": self._dio_lf_model}), + PinResource("P1.02", {"P1.02": self._dio_lf_model}), + PinResource("P1.01", {"P1.01": self._dio_lf_model}), + PinResource("P0.14", {"P0.14": self._dio_model}), + PinResource("P0.16", {"P0.16": self._dio_model}), + # PinResource('P0.18', {'P0.18': dio_model}), # configurable as RESET, mappable + PinResource("P0.19", {"P0.19": self._dio_model}), + PinResource("P0.21", {"P0.21": self._dio_model}), + PinResource("P0.23", {"P0.23": self._dio_model}), + PinResource("P0.25", {"P0.25": self._dio_model}), + PinResource("P0.13", {"P0.13": self._dio_model}), + PinResource("P0.15", {"P0.15": self._dio_model}), + PinResource("P0.17", {"P0.17": self._dio_model}), + PinResource("P0.20", {"P0.20": self._dio_model}), + PinResource("P0.22", {"P0.22": self._dio_model}), + PinResource("P0.24", {"P0.24": self._dio_model}), + PinResource( + "P1.00", {"P1.00": self._dio_model} + ), # TRACEDATA[0] and SWO, if used as IO must clear TRACECONFIG reg + PeripheralFixedPin( + "SWD", + SwdTargetPort(self._dio_model), + { + "swclk": "SWCLK", + "swdio": "SWDIO", + }, + ), + PeripheralFixedPin("USBD", UsbDevicePort(), {"dp": "D+", "dm": "D-"}), + PeripheralFixedResource( + "SPIM0", + spi_model, + { + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIM1", + spi_model, + { + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIM2", + spi_model, + { + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIM3", + spi_model, + { + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIS0", + spi_peripheral_model, + { # TODO shared resource w/ SPI controller + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIS1", + spi_peripheral_model, + { # TODO shared resource w/ SPI controller + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "SPIS2", + spi_peripheral_model, + { # TODO shared resource w/ SPI controller + "sck": hf_io_pins, + "miso": hf_io_pins, + "mosi": hf_io_pins, + }, + ), + PeripheralFixedResource( + "TWIM0", + i2c_model, + { + "scl": hf_io_pins, + "sda": hf_io_pins, + }, + ), + PeripheralFixedResource( + "TWIM1", + i2c_model, + { + "scl": hf_io_pins, + "sda": hf_io_pins, + }, + ), + PeripheralFixedResource( + "TWIS0", + i2c_target_model, + { # TODO shared resource w/ I2C controller + "scl": hf_io_pins, + "sda": hf_io_pins, + }, + ), + PeripheralFixedResource( + "TWIS1", + i2c_target_model, + { # TODO shared resource w/ I2C controller + "scl": hf_io_pins, + "sda": hf_io_pins, + }, + ), + PeripheralFixedResource( + "UARTE0", + uart_model, + { + "tx": hf_io_pins, + "rx": hf_io_pins, + }, + ), + PeripheralFixedResource( + "UARTE1", + uart_model, + { + "tx": hf_io_pins, + "rx": hf_io_pins, + }, + ), + PeripheralFixedResource( + "I2S", + i2s_model, + { + "sck": hf_io_pins, + "ws": hf_io_pins, + "sd": hf_io_pins, + }, + ), + ] + ) + .remap_pins(self._PIN_MAPPING) + .filter_pins(self.get(self.allowed_pins)) + ) -@abstract_block -class Nrf52840_Base(Nrf52840_Ios, GeneratorBlock): - SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] # pin name in base -> pin name(s) +class Mdbt50q_1mv2( + Microcontroller, + Radiofrequency, + Resettable, + Nrf52840_Interfaces, + IoControllerWithSwdTargetConnector, + IoControllerPowerRequired, + GeneratorBlock, +): + """Wrapper around the Mdbt50q_1mv2 that includes the reference schematic.""" - @override - def _vddio(self) -> Port[VoltageLink]: - return self.pwr + def __init__(self, **kwargs: Any) -> None: + super().__init__(**kwargs) + self.ic = self.Block(Mdbt50q_1mv2_Device(pin_assigns=ArrayStringExpr())) + self.pwr_usb = self.Export(self.ic.pwr_usb, optional=True) + self.generator_param(self.reset.is_connected(), self.pin_assigns, self.gpio.requested(), self.usb.requested()) @override - def _system_pinmap(self) -> Dict[str, Union[Passive, HasPassivePort]]: - return VariantPinRemapper( - { - "Vdd": self.pwr, - "Vss": self.gnd, - "Vbus": self.pwr_usb, - "nRESET": self.nreset, - } - ).remap(self.SYSTEM_PIN_REMAP) + def contents(self) -> None: + super().contents() + self.connect(self.pwr, self.ic.pwr) + self.connect(self.gnd, self.ic.gnd) - def __init__(self, **kwargs: Any) -> None: - super().__init__(**kwargs) + self.connect(self.swd_node, self.ic.swd) + self.connect(self.reset_node, self.ic.nreset) - self.gnd = self.Port(Ground(), [Common]) - self.pwr = self.Port(self._vdd_model(), [Power]) + with self.implicit_connect(ImplicitConnect(self.pwr, [Power]), ImplicitConnect(self.gnd, [Common])) as imp: + self.vcc_cap = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) - self.pwr_usb = self.Port( - VoltageSink( - voltage_limits=(4.35, 5.5) * Volt, - current_draw=(0.262, 7.73) * mAmp, # CPU/USB sleeping to everything active - ), - optional=True, - ) - self.require((self.usb.length() > 0).implies(self.pwr_usb.is_connected()), "USB require Vbus connected") + @override + def generate(self) -> None: + super().generate() - # Additional ports (on top of IoController) - # Crystals from table 15, 32, 33 - # TODO Table 32, model crystal load capacitance and series resistance ratings - self.xtal = self.Port( - CrystalDriver(frequency_limits=(1, 25) * MHertz, voltage_out=self.pwr.link().voltage), optional=True - ) - # Assumed from "32kHz crystal" in 14.5 - self.xtal_rtc = self.Port( - CrystalDriver(frequency_limits=(32, 33) * kHertz, voltage_out=self.pwr.link().voltage), optional=True - ) + def usb_export_transform(self_io: BasePort, assign: Optional[str]) -> Optional[BasePort]: + self.vbus_cap = self.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))).connected(self.gnd, self.pwr_usb) + self.usb_res = self.Block(UsbSeriesResistor(27 * Ohm(tol=0.05))) + self.connect(self_io, self.usb_res.exterior) + return self.usb_res.interior - self.swd = self.Port(SwdTargetPort.empty()) - self.nreset = self.Port(DigitalSink.from_bidir(self._dio_model(self.pwr)), optional=True) - self._io_ports.insert(0, self.swd) + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {UsbDevicePort: usb_export_transform, DigitalBidir: lambda port, assign: port}) + if self.get(self.reset.is_connected()): + self.connect(self.reset, self.ic.nreset) -class Holyiot_18010_Device(Nrf52840_Base, InternalSubcircuit): - SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] = { - "Vdd": "14", - "Vss": ["1", "25", "37"], - "Vbus": "22", - "nRESET": "21", - } - RESOURCE_PIN_REMAP = { # boundary pins only, inner pins ignored + +class Holyiot_18010_Footprint( + Nrf52840_Interfaces, BaseIoControllerWrapped, InternalSubcircuit, GeneratorBlock, FootprintBlock +): + _PIN_REMAPPING = { # boundary pins only, inner pins ignored "P1.11": "2", "P1.10": "3", "P1.13": "4", @@ -370,161 +463,121 @@ class Holyiot_18010_Device(Nrf52840_Base, InternalSubcircuit): "P0.10": "36", } + def __init__(self, **kwargs: Any) -> None: + super().__init__(**kwargs) + self.gnd = self.Port(Ground.empty()) + self.vdd_nrf = self.Port(VoltageSink.empty(), optional=True) + self.vbus = self.Port(VoltageSink.empty(), optional=True) + self.p0_18 = self.Port(DigitalSink.empty(), optional=True) # nRESET + self.swd = self.Port(SwdTargetPort.empty()) + self._io_ports.insert(0, self.swd) + self.generator_param(self.pin_assigns) + self._generator_param_all_ios() + @override def generate(self) -> None: super().generate() + pinning: Dict[str, HasPassivePort] = { + "14": self.vdd_nrf, + "1": self.gnd, + "25": self.gnd, + "37": self.gnd, + "22": self.vbus, + "21": self.p0_18, + } + remapped_pin_assigns = self._remap_pin_assigns_list(self._PIN_REMAPPING, self.get(self.pin_assigns)) + pinning.update(self._remap_to_footprint_pinning(remapped_pin_assigns, self._PIN_REMAPPING.values())) + self.assign(self.actual_pin_assigns, self._remap_assigns_to_value(remapped_pin_assigns)) + self.footprint( "U", "edg:Holyiot-18010-NRF52840", - self._make_pinning(), + pinning, mfr="Holyiot", part="18010", datasheet="http://www.holyiot.com/tp/2019042516322180424.pdf", ) -class Holyiot_18010( - Microcontroller, - Radiofrequency, - Resettable, +class Holyiot_18010_Device( Nrf52840_Interfaces, - IoControllerWithSwdTargetConnector, - IoControllerPowerRequired, - BaseIoControllerExportable, + BaseIoController, + InternalSubcircuit, GeneratorBlock, + WrapperSubboardBlock, ): - """Wrapper around the Holyiot 18010 that includes supporting components (programming port)""" def __init__(self, **kwargs: Any) -> None: super().__init__(**kwargs) - self.ic: Holyiot_18010_Device - self.ic = self.Block(Holyiot_18010_Device(pin_assigns=ArrayStringExpr())) - self.pwr_usb = self.Export(self.ic.pwr_usb, optional=True) - self.generator_param(self.reset.is_connected()) - - @override - def contents(self) -> None: - super().contents() - self.connect(self.pwr, self.ic.pwr) - self.connect(self.gnd, self.ic.gnd) - - self.connect(self.swd_node, self.ic.swd) - self.connect(self.reset_node, self.ic.nreset) - - @override - def generate(self) -> None: - super().generate() - if self.get(self.reset.is_connected()): - self.connect(self.reset, self.ic.nreset) - -class Mdbt50q_1mv2_Device(Nrf52840_Base, InternalSubcircuit, JlcPart): - SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] = { - "Vdd": ["28", "30"], # 28=Vdd, 30=VddH; 31=DccH is disconnected - from section 8.3 for input voltage <3.6v - "Vss": ["1", "2", "15", "33", "55"], - "Vbus": "32", - "nRESET": "40", - } - RESOURCE_PIN_REMAP = { # boundary pins only, inner pins ignored - "P1.10": "3", - "P1.11": "4", - "P1.12": "5", - "P1.13": "6", - "P1.14": "7", - "P1.15": "8", - "P0.03": "9", - "P0.29": "10", - "P0.02": "11", - "P0.31": "12", - "P0.28": "13", - "P0.30": "14", - "P0.27": "16", - "P0.00": "17", - "P0.01": "18", - "P0.26": "19", - "P0.04": "20", - "P0.05": "21", - "P0.06": "22", - "P0.07": "23", - "P0.08": "24", - "P1.08": "25", - "P1.09": "26", - "P0.11": "27", - "P0.12": "29", - "D-": "34", - "D+": "35", - "P0.14": "36", - "P0.13": "37", - "P0.16": "38", - "P0.15": "39", - "P0.17": "41", - "P0.19": "42", - "P0.21": "43", - "P0.20": "44", - "P0.23": "45", - "P0.22": "46", - "P1.00": "47", - "P0.24": "48", - "P0.25": "49", - "P1.02": "50", - "SWDIO": "51", - "P0.09": "52", - "SWCLK": "53", - "P0.10": "54", - "P1.04": "56", - "P1.06": "57", - "P1.07": "58", - "P1.05": "59", - "P1.03": "60", - "P1.01": "61", - } + self.model = self.Block( + Mdbt50q_1mv2_Device( + pin_assigns=ArrayStringExpr(), allowed_pins=list(Holyiot_18010_Footprint._PIN_REMAPPING.keys()) + ) + ) + self.gnd = self.Export(self.model.gnd) + self.pwr = self.Export(self.model.pwr) + self.pwr_usb = self.Export(self.model.pwr_usb, optional=True) + self.reset = self.Export(self.model.nreset, optional=True) + self.swd = self.Export(self.model.swd, optional=True) + self.generator_param(self.pin_assigns) @override def generate(self) -> None: super().generate() - self.assign(self.lcsc_part, "C5118826") - self.assign(self.actual_basic_part, False) - self.footprint( - "U", - "RF_Module:Raytac_MDBT50Q", - self._make_pinning(), - mfr="Raytac", - part="MDBT50Q-1MV2", - datasheet="https://www.raytac.com/download/index.php?index_id=43", + self._export_ios_inner(self.model) + self.assign( + self.model.pin_assigns, + BaseIoControllerWrapped._remap_assigns_to_value( + BaseIoControllerWrapped._remap_pin_assigns_list( + Holyiot_18010_Footprint._PIN_REMAPPING, self.get(self.pin_assigns), invert_remapping=True + ) + ), ) + self.device = self.Block(Holyiot_18010_Footprint(pin_assigns=self.model.actual_pin_assigns)) + self.assign(self.actual_pin_assigns, self.device.actual_pin_assigns) + self._export_tap_ios_inner(self.device) + self.export_tap(self.gnd, self.device.gnd) + self.export_tap(self.pwr, self.device.vdd_nrf) + self.export_tap(self.pwr_usb, self.device.vbus) + self.export_tap(self.reset, self.device.p0_18) + self.export_tap(self.swd, self.device.swd) -class Mdbt50q_1mv2( + +class Holyiot_18010( Microcontroller, Radiofrequency, Resettable, Nrf52840_Interfaces, - IoControllerWithSwdTargetConnector, IoControllerPowerRequired, - BaseIoControllerExportable, + IoControllerWithSwdTargetConnector, GeneratorBlock, ): - """Wrapper around the Mdbt50q_1mv2 that includes the reference schematic""" + """Wrapper around the Holyiot 18010 that includes supporting components (programming port)""" - def __init__(self, **kwargs: Any) -> None: + def __init__( + self, + **kwargs: Any, + ) -> None: super().__init__(**kwargs) - self.ic: Mdbt50q_1mv2_Device - self.ic = self.Block( - Mdbt50q_1mv2_Device(pin_assigns=ArrayStringExpr()) - ) # defined in generator to mix in SWO/TDI + + self.ic = self.Block(Holyiot_18010_Device(pin_assigns=ArrayStringExpr())) self.pwr_usb = self.Export(self.ic.pwr_usb, optional=True) - self.generator_param(self.reset.is_connected()) + + self.generator_param(self.reset.is_connected(), self.pin_assigns, self.gpio.requested(), self.usb.requested()) @override def contents(self) -> None: super().contents() - self.connect(self.pwr, self.ic.pwr) + self.connect(self.gnd, self.ic.gnd) + self.connect(self.pwr, self.ic.pwr) self.connect(self.swd_node, self.ic.swd) - self.connect(self.reset_node, self.ic.nreset) + self.connect(self.reset_node, self.ic.reset) with self.implicit_connect(ImplicitConnect(self.pwr, [Power]), ImplicitConnect(self.gnd, [Common])) as imp: self.vcc_cap = imp.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))) @@ -533,39 +586,22 @@ def contents(self) -> None: def generate(self) -> None: super().generate() - if self.get(self.reset.is_connected()): - self.connect(self.reset, self.ic.nreset) + def usb_export_transform(self_io: BasePort, assign: Optional[str]) -> Optional[BasePort]: + self.vbus_cap = self.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))).connected(self.gnd, self.pwr_usb) + self.usb_res = self.Block(UsbSeriesResistor(27 * Ohm(tol=0.05))) + self.connect(self_io, self.usb_res.exterior) + return self.usb_res.interior - ExportType = TypeVar("ExportType", bound=Port) + # add a passthrough for gpio (DigitalBidir) to allow the SWD pins to be attached, if using + self._wrap_inner(self.ic, {UsbDevicePort: usb_export_transform, DigitalBidir: lambda port, assign: port}) - @override - def _make_export_vector( - self, self_io: ExportType, inner_vector: Vector[ExportType], name: str, assign: Optional[str] - ) -> Optional[str]: - if isinstance(self_io, UsbDevicePort): # assumed at most one USB port generates - inner_io = inner_vector.request(name) - (self.usb_res,), self.usb_chain = self.chain( - inner_io, self.Block(UsbSeriesResistor(27 * Ohm(tol=0.05))), self_io - ) - self.vbus_cap = self.Block(DecouplingCapacitor(10 * uFarad(tol=0.2))).connected(self.gnd, self.pwr_usb) - return assign - return super()._make_export_vector(self_io, inner_vector, name, assign) + if self.get(self.reset.is_connected()): + self.connect(self.reset, self.ic.reset) -class Feather_Nrf52840( - IoControllerUsbOut, IoControllerPowerOut, Nrf52840_Ios, IoController, GeneratorBlock, FootprintBlock -): - """Feather nRF52840 socketed dev board as either power source or sink""" +class Feather_Nrf52840_Device(Nrf52840_Interfaces, BaseIoControllerWrapped, GeneratorBlock, FootprintBlock): - SYSTEM_PIN_REMAP: Dict[str, Union[str, List[str]]] = { - "Vdd": "2", # 3v3 - "Vss": "4", - # 'reset': '1', - "Vbus": "26", - # 'EN': '27', # controls the onboard 3.3 LDO, internally pulled up - # 'Vbat': '28', - } - RESOURCE_PIN_REMAP = { # boundary pins only, inner pins ignored + _PIN_REMAPPING = { # boundary pins only, inner pins ignored "P0.31": "3", # AREF "P0.04": "5", # A0 "P0.05": "6", # A1 @@ -594,63 +630,119 @@ class Feather_Nrf52840( # note onboard VBAT sense divider at P0.29 } - @override - def _vddio(self) -> Port[VoltageLink]: - if self.get(self.pwr.is_connected()): # board sinks power - return self.pwr - else: - return self.pwr_out - - @override - def _system_pinmap(self) -> Dict[str, Union[Passive, HasPassivePort]]: - if self.get(self.pwr.is_connected()): # board sinks power - self.require(~self.vusb_out.is_connected(), "can't source USB power if power input connected") - self.require(~self.pwr_out.is_connected(), "can't source 3v3 power if power input connected") - return VariantPinRemapper( - { - "Vdd": self.pwr, - "Vss": self.gnd, - } - ).remap(self.SYSTEM_PIN_REMAP) - else: # board sources power (default) - return VariantPinRemapper( - { - "Vdd": self.pwr_out, - "Vss": self.gnd, - "Vbus": self.vusb_out, - } - ).remap(self.SYSTEM_PIN_REMAP) - - @override - def contents(self) -> None: - super().contents() - - self.gnd.init_from(Ground()) - self.pwr.init_from(self._vdd_model()) - - mbr120_drop = (0, 0.340) * Volt - ap2112_3v3_out = 3.3 * Volt(tol=0.015) # note dropout voltage up to 400mV, current up to 600mA - self.vusb_out.init_from( - VoltageSource( - voltage_out=UsbConnector.USB2_VOLTAGE_RANGE - mbr120_drop, - current_limits=UsbConnector.USB2_CURRENT_LIMITS, - ) - ) - self.pwr_out.init_from( - VoltageSource(voltage_out=ap2112_3v3_out, current_limits=UsbConnector.USB2_CURRENT_LIMITS) - ) + def __init__(self, **kwargs: Any) -> None: + super().__init__(**kwargs) + self.gnd = self.Port(Ground.empty(), optional=True) + # power ports are passive so directionality and concrete types can be resolved at the higher modeling level + self.pwr = self.Port(Passive.empty(), optional=True) + self.vusb = self.Port(Passive.empty(), optional=True) - self.generator_param(self.pwr.is_connected()) + self.generator_param(self.pin_assigns) + self._generator_param_all_ios() @override def generate(self) -> None: super().generate() + pinning: Dict[str, Union[HasPassivePort, Passive]] = { + "2": self.pwr, + "4": self.gnd, + # "1": reset, + "26": self.vusb, + # 'EN': '27', # controls the onboard 3.3 LDO, internally pulled up + # 'Vbat': '28', + } + remapped_pin_assigns = self._remap_pin_assigns_list(self._PIN_REMAPPING, self.get(self.pin_assigns)) + pinning.update(self._remap_to_footprint_pinning(remapped_pin_assigns, self._PIN_REMAPPING.values())) + self.assign(self.actual_pin_assigns, self._remap_assigns_to_value(remapped_pin_assigns)) + self.footprint( "U", "bldc:FEATHERWING_NODIM", - self._make_pinning(), + pinning, mfr="Adafruit", part="Feather nRF52840 Express", datasheet="https://learn.adafruit.com/assets/68545", ) + + +class Feather_Nrf52840( + IoControllerUsbOut, + IoControllerPowerOut, + Nrf52840_Interfaces, + IoController, + WrapperSubboardBlock, + GeneratorBlock, + FootprintBlock, +): + """Feather nRF52840 socketed dev board as either power source or sink""" + + _MBR120_DROP = (0, 0.340) * Volt + _AP2112_3V3_OUT = 3.3 * Volt(tol=0.015) # note dropout voltage up to 400mV, current up to 600mA + + def __init__(self, **kwargs: Any) -> None: + super().__init__(**kwargs) + self.generator_param( + self.pin_assigns, + self.gnd.is_connected(), + self.pwr.is_connected(), + self.pwr_out.is_connected(), + self.vusb_out.is_connected(), + ) + + @override + def generate(self) -> None: + super().generate() + + self.require( + self.pwr.is_connected().implies(~self.vusb_out.is_connected()), + "can't source USB power if power input connected", + ) + self.require( + self.pwr.is_connected().implies(~self.pwr_out.is_connected()), + "can't source 3v3 power if power input connected", + ) + + self.model = self.Block( + Mdbt50q_1mv2_Device( + pin_assigns=BaseIoControllerWrapped._remap_assigns_to_value( + BaseIoControllerWrapped._remap_pin_assigns_list( + Feather_Nrf52840_Device._PIN_REMAPPING, self.get(self.pin_assigns), invert_remapping=True + ) + ), + allowed_pins=list(Feather_Nrf52840_Device._PIN_REMAPPING.keys()), + ) + ) + self._export_ios_inner(self.model) + + self.device = self.Block(Feather_Nrf52840_Device(pin_assigns=self.model.actual_pin_assigns), external=True) + self._export_tap_ios_inner(self.device) + self.assign(self.actual_pin_assigns, self.device.actual_pin_assigns) + + if self.get(self.pwr.is_connected()): # power supplied externally + self.connect(self.pwr, self.model.pwr) + self.export_tap(self.pwr.net, self.device.pwr) + else: # board sources power from USB + self.pwr_out_model = self.Block( + DummyVoltageSource(voltage_out=self._AP2112_3V3_OUT, current_limits=UsbConnector.USB2_CURRENT_LIMITS) + ) + self.connect(self.pwr_out_model.pwr, self.model.pwr) + if self.get(self.pwr_out.is_connected()): + self.connect(self.pwr_out, self.pwr_out_model.pwr) + self.export_tap(self.pwr_out.net, self.device.pwr) + + if self.get(self.vusb_out.is_connected()): + self.vusb_out.init_from( + VoltageSource( + voltage_out=UsbConnector.USB2_VOLTAGE_RANGE - self._MBR120_DROP, + current_limits=UsbConnector.USB2_CURRENT_LIMITS, + ) + ) + self.export_tap(self.vusb_out.net, self.device.vusb) + + if self.get(self.gnd.is_connected()): + self.connect(self.gnd, self.model.gnd) + else: + self.gnd_model = self.Block(DummyGround()) + self.connect(self.gnd_model.gnd, self.model.gnd) + self.export_tap(self.gnd, self.device.gnd) diff --git a/edg/parts/microcontroller/test_mcu_wrapper.py b/edg/parts/microcontroller/test_mcu_wrapper.py new file mode 100644 index 000000000..4011666f7 --- /dev/null +++ b/edg/parts/microcontroller/test_mcu_wrapper.py @@ -0,0 +1,65 @@ +import unittest +from typing_extensions import override + +from .Rp2040 import Xiao_Rp2040 +from ...circuits import * + + +class OverallocateTest(DesignTop): + def __init__(self) -> None: + super().__init__() + self.pwr = self.Block(DummyVoltageSource(voltage_out=3.3 * Volt(tol=0))) + self.gnd = self.Block(DummyGround()) + with self.implicit_connect( + ImplicitConnect(self.pwr.pwr, [Power]), + ImplicitConnect(self.gnd.gnd, [Common]), + ) as imp: + self.dut = imp.Block(Xiao_Rp2040()) + + self.ios = ElementDict[DummyDigitalSource]() + for i in range(12): # device only has 11 IOs + self.ios[i] = self.Block(DummyDigitalSource()) + self.connect(self.ios[i].io, self.dut.gpio.request(str(i))) + + +class BaseMcuTest(DesignTop): + def __init__(self) -> None: + super().__init__() + self.pwr = self.Block(DummyVoltageSource(voltage_out=3.3 * Volt(tol=0))) + self.gnd = self.Block(DummyGround()) + with self.implicit_connect( + ImplicitConnect(self.pwr.pwr, [Power]), + ImplicitConnect(self.gnd.gnd, [Common]), + ) as imp: + self.dut = imp.Block(Xiao_Rp2040()) + + self.ios = ElementDict[DummyDigitalSource]() + for i in range(2): + self.ios[i] = self.Block(DummyDigitalSource()) + self.connect(self.ios[i].io, self.dut.gpio.request(str(i))) + + +class AutoPinsTest(BaseMcuTest): + pass + + +class AssignedPinsTest(BaseMcuTest): + @override + def refinements(self) -> Refinements: + return Refinements(instance_values=[(["dut", "pin_assigns"], ["0=1", "1=3"])]) + + +class McuWrapperTestCase(unittest.TestCase): + def test_overallocate(self) -> None: + with self.assertRaises(CompilerCheckError): + ScalaCompiler.compile(OverallocateTest) + + def test_auto_pins(self) -> None: + compiled = ScalaCompiler.compile(AutoPinsTest) + self.assertEqual(compiled.get_value(["dut", "actual_pin_assigns"]), ["0=7", "1=8"]) + self.assertEqual(compiled.get_value(["dut", "model", "actual_pin_assigns"]), ["0=GPIO0, 2", "1=GPIO1, 3"]) + + def test_assigned_pins(self) -> None: + compiled = ScalaCompiler.compile(AssignedPinsTest) + self.assertEqual(compiled.get_value(["dut", "actual_pin_assigns"]), ["0=1", "1=3"]) + self.assertEqual(compiled.get_value(["dut", "model", "actual_pin_assigns"]), ["0=GPIO26, 38", "1=GPIO28, 40"]) diff --git a/examples/BasicKeyboard/BasicKeyboard.net.ref b/examples/BasicKeyboard/BasicKeyboard.net.ref index d9309348f..3b2479df2 100644 --- a/examples/BasicKeyboard/BasicKeyboard.net.ref +++ b/examples/BasicKeyboard/BasicKeyboard.net.ref @@ -183,7 +183,7 @@ (node (ref U1) (pin 13))) (net (code 7) (name "mcu.pwr_out") (node (ref U1) (pin 12))) -(net (code 8) (name "mcu.device.vcc_out") +(net (code 8) (name "mcu.device.vcc") (node (ref U1) (pin 14))) (net (code 9) (name "sw.sw[0,0].sw") (node (ref SW1) (pin 1)) diff --git a/examples/BasicKeyboard/BasicKeyboard.svgpcb.js b/examples/BasicKeyboard/BasicKeyboard.svgpcb.js index 12949d788..2fe774a62 100644 --- a/examples/BasicKeyboard/BasicKeyboard.svgpcb.js +++ b/examples/BasicKeyboard/BasicKeyboard.svgpcb.js @@ -15,7 +15,7 @@ board.setNetlist([ {name: "mcu.gpio.1_2", pads: [["U1", "10"], ["D3", "2"], ["D6", "2"]]}, {name: "mcu.gnd", pads: [["U1", "13"]]}, {name: "mcu.pwr_out", pads: [["U1", "12"]]}, - {name: "mcu.device.vcc_out", pads: [["U1", "14"]]}, + {name: "mcu.device.vcc", pads: [["U1", "14"]]}, {name: "sw.sw[0,0].sw", pads: [["SW1", "1"], ["D1", "1"]]}, {name: "sw.sw[0,1].sw", pads: [["SW2", "1"], ["D2", "1"]]}, {name: "sw.sw[0,2].sw", pads: [["SW3", "1"], ["D3", "1"]]}, diff --git a/examples/BldcController/BldcController.net.ref b/examples/BldcController/BldcController.net.ref index f1e554dcd..cb7cf5a6e 100644 --- a/examples/BldcController/BldcController.net.ref +++ b/examples/BldcController/BldcController.net.ref @@ -41,7 +41,7 @@ (footprint "bldc:FEATHERWING_NODIM") (property (name "Sheetname") (value "")) (property (name "Sheetfile") (value "")) - (property (name "edg_path") (value "mcu")) + (property (name "edg_path") (value "mcu.device")) (property (name "edg_short_path") (value "mcu")) (property (name "edg_refdes") (value "U1")) (property (name "edg_part") (value "Feather nRF52840 Express (Adafruit)")) diff --git a/examples/BldcController/BldcController.svgpcb.js b/examples/BldcController/BldcController.svgpcb.js index 1385b8e9a..cbd17e214 100644 --- a/examples/BldcController/BldcController.svgpcb.js +++ b/examples/BldcController/BldcController.svgpcb.js @@ -15,7 +15,7 @@ const H3 = board.add(JlcToolingHole_1_152mm, { translate: pt(0.485, 1.803), rotate: 0, id: 'H3' }) -// mcu +// mcu.device const U1 = board.add(FEATHERWING_NODIM, { translate: pt(0.643, 1.763), rotate: 0, id: 'U1' diff --git a/examples/Keyboard/Keyboard.net.ref b/examples/Keyboard/Keyboard.net.ref index f4dfc08a2..e3f510ffb 100644 --- a/examples/Keyboard/Keyboard.net.ref +++ b/examples/Keyboard/Keyboard.net.ref @@ -156,18 +156,6 @@ (property (name "edg_value") (value "50V 1uF X5R ±10% 0603 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "15dd03c3")) -(comp (ref "R3") - (value "mcu.usb_pull") - (footprint "Resistor_SMD:R_0603_1608Metric") - (property (name "Sheetname") (value "mcu")) - (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) - (property (name "edg_path") (value "mcu.usb_pull.dp")) - (property (name "edg_short_path") (value "mcu.usb_pull")) - (property (name "edg_refdes") (value "R3")) - (property (name "edg_part") (value "0603WAF1501T5E (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0603 Chip Resistor - Surface Mount ROHS")) - (sheetpath (names "/mcu/") (tstamps "/02850146/")) - (tstamps "0f5f0367")) (comp (ref "X1") (value "mcu.crystal.package") (footprint "Crystal:Crystal_SMD_3225-4Pin_3.2x2.5mm") @@ -216,6 +204,18 @@ (property (name "edg_value") (value "PinHeader1.27 Shrouded 2x5")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "02ae014f")) +(comp (ref "R3") + (value "mcu.usb_pull") + (footprint "Resistor_SMD:R_0603_1608Metric") + (property (name "Sheetname") (value "mcu")) + (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) + (property (name "edg_path") (value "mcu.usb_pull.dp")) + (property (name "edg_short_path") (value "mcu.usb_pull")) + (property (name "edg_refdes") (value "R3")) + (property (name "edg_part") (value "0603WAF1501T5E (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0603 Chip Resistor - Surface Mount ROHS")) + (sheetpath (names "/mcu/") (tstamps "/02850146/")) + (tstamps "0f5f0367")) (comp (ref "SW1") (value "sw.sw[0,0]") (footprint "Switch_Keyboard_Hotswap_Kailh:SW_Hotswap_Kailh_MX") @@ -426,8 +426,8 @@ (node (ref C6) (pin 1)) (node (ref C7) (pin 1)) (node (ref C8) (pin 1)) - (node (ref R3) (pin 1)) - (node (ref J2) (pin 1))) + (node (ref J2) (pin 1)) + (node (ref R3) (pin 1))) (net (code 8) (name "mcu.gpio.0_0") (node (ref U2) (pin 10)) (node (ref SW1) (pin 2)) diff --git a/examples/Keyboard/Keyboard.svgpcb.js b/examples/Keyboard/Keyboard.svgpcb.js index 45172caa7..cb3b12aca 100644 --- a/examples/Keyboard/Keyboard.svgpcb.js +++ b/examples/Keyboard/Keyboard.svgpcb.js @@ -66,11 +66,6 @@ const C8 = board.add(C_0603_1608Metric, { translate: pt(1.332, 0.647), rotate: 0, id: 'C8' }) -// mcu.usb_pull.dp -const R3 = board.add(R_0603_1608Metric, { - translate: pt(1.488, 0.647), rotate: 0, - id: 'R3' -}) // mcu.crystal.package const X1 = board.add(Crystal_SMD_3225_4Pin_3_2x2_5mm, { translate: pt(1.201, 0.512), rotate: 0, @@ -78,12 +73,12 @@ const X1 = board.add(Crystal_SMD_3225_4Pin_3_2x2_5mm, { }) // mcu.crystal.cap_a const C9 = board.add(C_0603_1608Metric, { - translate: pt(1.644, 0.647), rotate: 0, + translate: pt(1.488, 0.647), rotate: 0, id: 'C9' }) // mcu.crystal.cap_b const C10 = board.add(C_0603_1608Metric, { - translate: pt(1.800, 0.647), rotate: 0, + translate: pt(1.644, 0.647), rotate: 0, id: 'C10' }) // mcu.swd.conn @@ -91,6 +86,11 @@ const J2 = board.add(PinHeader_2x05_P1_27mm_Vertical_SMD, { translate: pt(1.732, 0.146), rotate: 0, id: 'J2' }) +// mcu.usb_pull.dp +const R3 = board.add(R_0603_1608Metric, { + translate: pt(1.800, 0.647), rotate: 0, + id: 'R3' +}) board.setNetlist([ {name: "usb.pwr", pads: [["J1", "A4"], ["J1", "A9"], ["J1", "B4"], ["J1", "B9"], ["U1", "3"], ["C1", "1"]]}, @@ -99,7 +99,7 @@ board.setNetlist([ {name: "usb.usb.dm", pads: [["J1", "A7"], ["J1", "B7"], ["U2", "32"]]}, {name: "usb.conn.cc.cc1", pads: [["J1", "A5"], ["R1", "2"]]}, {name: "usb.conn.cc.cc2", pads: [["J1", "B5"], ["R2", "2"]]}, - {name: "reg.pwr_out", pads: [["U1", "2"], ["C2", "1"], ["U2", "1"], ["U2", "24"], ["U2", "36"], ["U2", "48"], ["U2", "9"], ["C3", "1"], ["C4", "1"], ["C5", "1"], ["C6", "1"], ["C7", "1"], ["C8", "1"], ["R3", "1"], ["J2", "1"]]}, + {name: "reg.pwr_out", pads: [["U1", "2"], ["C2", "1"], ["U2", "1"], ["U2", "24"], ["U2", "36"], ["U2", "48"], ["U2", "9"], ["C3", "1"], ["C4", "1"], ["C5", "1"], ["C6", "1"], ["C7", "1"], ["C8", "1"], ["J2", "1"], ["R3", "1"]]}, {name: "mcu.gpio.0_0", pads: [["U2", "10"], ["SW1", "2"], ["SW2", "2"], ["SW3", "2"]]}, {name: "mcu.gpio.0_1", pads: [["U2", "11"], ["SW4", "2"], ["SW5", "2"], ["SW6", "2"]]}, {name: "mcu.gpio.1_0", pads: [["U2", "12"], ["D1", "2"], ["D4", "2"]]}, diff --git a/examples/Multimeter/Multimeter.net.ref b/examples/Multimeter/Multimeter.net.ref index 33b26525c..3c2ed3555 100644 --- a/examples/Multimeter/Multimeter.net.ref +++ b/examples/Multimeter/Multimeter.net.ref @@ -396,6 +396,30 @@ (property (name "edg_value") (value "X5R 25V ±10% 10uF 0805 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "0b5902d0")) +(comp (ref "J2") + (value "mcu.swd") + (footprint "Connector:Tag-Connect_TC2050-IDC-NL_2x05_P1.27mm_Vertical") + (property (name "Sheetname") (value "mcu")) + (property (name "Sheetfile") (value "edg.parts.microcontroller.nRF52840.Mdbt50q_1mv2")) + (property (name "edg_path") (value "mcu.swd.conn")) + (property (name "edg_short_path") (value "mcu.swd")) + (property (name "edg_refdes") (value "J2")) + (property (name "edg_part") (value "")) + (property (name "edg_value") (value "")) + (sheetpath (names "/mcu/") (tstamps "/02850146/")) + (tstamps "02ae014f")) +(comp (ref "C8") + (value "mcu.vbus_cap") + (footprint "Capacitor_SMD:C_0805_2012Metric") + (property (name "Sheetname") (value "mcu")) + (property (name "Sheetfile") (value "edg.parts.microcontroller.nRF52840.Mdbt50q_1mv2")) + (property (name "edg_path") (value "mcu.vbus_cap.cap")) + (property (name "edg_short_path") (value "mcu.vbus_cap")) + (property (name "edg_refdes") (value "C8")) + (property (name "edg_part") (value "CL21A106KAYNNNE (Samsung Electro-Mechanics)")) + (property (name "edg_value") (value "X5R 25V ±10% 10uF 0805 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) + (sheetpath (names "/mcu/") (tstamps "/02850146/")) + (tstamps "0f3a0354")) (comp (ref "R6") (value "mcu.usb_res.dp") (footprint "Resistor_SMD:R_0603_1608Metric") @@ -420,30 +444,6 @@ (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±200ppm/℃ -55℃~+155℃ 27Ω 0603 Chip Resistor - Surface Mount ROHS")) (sheetpath (names "/mcu/usb_res/") (tstamps "/02850146/0be502f4/")) (tstamps "013700d2")) -(comp (ref "C8") - (value "mcu.vbus_cap") - (footprint "Capacitor_SMD:C_0805_2012Metric") - (property (name "Sheetname") (value "mcu")) - (property (name "Sheetfile") (value "edg.parts.microcontroller.nRF52840.Mdbt50q_1mv2")) - (property (name "edg_path") (value "mcu.vbus_cap.cap")) - (property (name "edg_short_path") (value "mcu.vbus_cap")) - (property (name "edg_refdes") (value "C8")) - (property (name "edg_part") (value "CL21A106KAYNNNE (Samsung Electro-Mechanics)")) - (property (name "edg_value") (value "X5R 25V ±10% 10uF 0805 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) - (sheetpath (names "/mcu/") (tstamps "/02850146/")) - (tstamps "0f3a0354")) -(comp (ref "J2") - (value "mcu.swd") - (footprint "Connector:Tag-Connect_TC2050-IDC-NL_2x05_P1.27mm_Vertical") - (property (name "Sheetname") (value "mcu")) - (property (name "Sheetfile") (value "edg.parts.microcontroller.nRF52840.Mdbt50q_1mv2")) - (property (name "edg_path") (value "mcu.swd.conn")) - (property (name "edg_short_path") (value "mcu.swd")) - (property (name "edg_refdes") (value "J2")) - (property (name "edg_part") (value "")) - (property (name "edg_value") (value "")) - (sheetpath (names "/mcu/") (tstamps "/02850146/")) - (tstamps "02ae014f")) (comp (ref "R8") (value "vbatsense.top_res") (footprint "Resistor_SMD:R_0603_1608Metric") @@ -1315,10 +1315,10 @@ (node (ref U5) (pin 33)) (node (ref U5) (pin 55)) (node (ref C7) (pin 2)) - (node (ref C8) (pin 2)) (node (ref J2) (pin 2)) (node (ref J2) (pin 3)) (node (ref J2) (pin 5)) + (node (ref C8) (pin 2)) (node (ref R9) (pin 2)) (node (ref U6) (pin 3)) (node (ref SW2) (pin 2)) @@ -1549,17 +1549,17 @@ (net (code 35) (name "mcu.reset_node") (node (ref U5) (pin 40)) (node (ref J2) (pin 6))) -(net (code 36) (name "mcu.usb_chain_0.d_P") +(net (code 36) (name "mcu.swd.tdi") + (node (ref J2) (pin 7))) +(net (code 37) (name "mcu.swd.swo") + (node (ref U5) (pin 47)) + (node (ref J2) (pin 8))) +(net (code 38) (name "mcu.usb_res.interior.dp") (node (ref U5) (pin 35)) (node (ref R6) (pin 2))) -(net (code 37) (name "mcu.usb_chain_0.d_N") +(net (code 39) (name "mcu.usb_res.interior.dm") (node (ref U5) (pin 34)) (node (ref R7) (pin 2))) -(net (code 38) (name "mcu.swd.tdi") - (node (ref J2) (pin 7))) -(net (code 39) (name "mcu.swd.swo") - (node (ref U5) (pin 47)) - (node (ref J2) (pin 8))) (net (code 40) (name "vbatsense.output") (node (ref U5) (pin 9)) (node (ref R8) (pin 2)) diff --git a/examples/Multimeter/Multimeter.svgpcb.js b/examples/Multimeter/Multimeter.svgpcb.js index 3cafe9ed5..b0b7ea2fc 100644 --- a/examples/Multimeter/Multimeter.svgpcb.js +++ b/examples/Multimeter/Multimeter.svgpcb.js @@ -165,6 +165,16 @@ const C7 = board.add(C_0805_2012Metric, { translate: pt(0.596, 0.728), rotate: 0, id: 'C7' }) +// mcu.swd.conn +const J2 = board.add(Tag_Connect_TC2050_IDC_NL_2x05_P1_27mm_Vertical, { + translate: pt(0.245, 0.822), rotate: 0, + id: 'J2' +}) +// mcu.vbus_cap.cap +const C8 = board.add(C_0805_2012Metric, { + translate: pt(0.770, 0.728), rotate: 0, + id: 'C8' +}) // mcu.usb_res.dp.res const R6 = board.add(R_0603_1608Metric, { translate: pt(0.588, 0.834), rotate: 0, @@ -175,16 +185,6 @@ const R7 = board.add(R_0603_1608Metric, { translate: pt(0.744, 0.834), rotate: 0, id: 'R7' }) -// mcu.vbus_cap.cap -const C8 = board.add(C_0805_2012Metric, { - translate: pt(0.770, 0.728), rotate: 0, - id: 'C8' -}) -// mcu.swd.conn -const J2 = board.add(Tag_Connect_TC2050_IDC_NL_2x05_P1_27mm_Vertical, { - translate: pt(0.245, 0.822), rotate: 0, - id: 'J2' -}) // vbatsense.div.top_res const R8 = board.add(R_0603_1608Metric, { translate: pt(3.628, 2.237), rotate: 0, @@ -537,7 +537,7 @@ const C31 = board.add(C_1206_3216Metric, { }) board.setNetlist([ - {name: "gnd", pads: [["U1", "2"], ["J1", "A1"], ["J1", "A12"], ["J1", "B1"], ["J1", "B12"], ["J1", "S1"], ["R1", "1"], ["R2", "1"], ["R4", "1"], ["Q2", "2"], ["SW1", "2"], ["U2", "2"], ["C1", "2"], ["C2", "2"], ["D3", "2"], ["U3", "2"], ["C3", "2"], ["C4", "2"], ["D4", "2"], ["U4", "2"], ["C5", "2"], ["C6", "2"], ["D5", "2"], ["U5", "1"], ["U5", "15"], ["U5", "2"], ["U5", "33"], ["U5", "55"], ["C7", "2"], ["C8", "2"], ["J2", "2"], ["J2", "3"], ["J2", "5"], ["R9", "2"], ["U6", "3"], ["SW2", "2"], ["SW3", "2"], ["J3", "2"], ["C9", "2"], ["C10", "2"], ["U7", "7"], ["U7", "9"], ["C11", "2"], ["C12", "2"], ["C14", "2"], ["R18", "2"], ["U8", "2"], ["C15", "2"], ["U9", "2"], ["U9", "3"], ["C16", "2"], ["U10", "2"], ["C17", "2"], ["U11", "2"], ["C18", "2"], ["U12", "2"], ["C19", "2"], ["U13", "2"], ["C20", "2"], ["U14", "19"], ["U14", "2"], ["U14", "3"], ["C21", "2"], ["C22", "2"], ["C23", "2"], ["C24", "2"], ["C25", "2"], ["U15", "2"], ["C26", "2"], ["U16", "2"], ["C27", "2"], ["U17", "2"], ["C28", "2"], ["U18", "2"], ["C29", "2"], ["U19", "2"], ["C30", "2"], ["C31", "2"]]}, + {name: "gnd", pads: [["U1", "2"], ["J1", "A1"], ["J1", "A12"], ["J1", "B1"], ["J1", "B12"], ["J1", "S1"], ["R1", "1"], ["R2", "1"], ["R4", "1"], ["Q2", "2"], ["SW1", "2"], ["U2", "2"], ["C1", "2"], ["C2", "2"], ["D3", "2"], ["U3", "2"], ["C3", "2"], ["C4", "2"], ["D4", "2"], ["U4", "2"], ["C5", "2"], ["C6", "2"], ["D5", "2"], ["U5", "1"], ["U5", "15"], ["U5", "2"], ["U5", "33"], ["U5", "55"], ["C7", "2"], ["J2", "2"], ["J2", "3"], ["J2", "5"], ["C8", "2"], ["R9", "2"], ["U6", "3"], ["SW2", "2"], ["SW3", "2"], ["J3", "2"], ["C9", "2"], ["C10", "2"], ["U7", "7"], ["U7", "9"], ["C11", "2"], ["C12", "2"], ["C14", "2"], ["R18", "2"], ["U8", "2"], ["C15", "2"], ["U9", "2"], ["U9", "3"], ["C16", "2"], ["U10", "2"], ["C17", "2"], ["U11", "2"], ["C18", "2"], ["U12", "2"], ["C19", "2"], ["U13", "2"], ["C20", "2"], ["U14", "19"], ["U14", "2"], ["U14", "3"], ["C21", "2"], ["C22", "2"], ["C23", "2"], ["C24", "2"], ["C25", "2"], ["U15", "2"], ["C26", "2"], ["U16", "2"], ["C27", "2"], ["U17", "2"], ["C28", "2"], ["U18", "2"], ["C29", "2"], ["U19", "2"], ["C30", "2"], ["C31", "2"]]}, {name: "vbat", pads: [["U1", "1"], ["R3", "1"], ["Q1", "2"]]}, {name: "v5v", pads: [["U2", "4"], ["C2", "1"], ["TP1", "1"], ["D3", "1"], ["U3", "1"], ["U3", "3"], ["C3", "1"], ["U4", "1"], ["U4", "3"], ["C5", "1"], ["U7", "1"], ["U7", "6"], ["C11", "1"], ["C12", "1"]]}, {name: "v3v3", pads: [["U3", "5"], ["C4", "1"], ["TP2", "1"], ["D4", "1"], ["U5", "28"], ["U5", "30"], ["C7", "1"], ["J2", "1"], ["D6", "2"], ["J3", "7"], ["R13", "1"], ["C9", "1"], ["R24", "1"]]}, @@ -572,10 +572,10 @@ board.setNetlist([ {name: "mcu.swd_node.swdio", pads: [["U5", "51"], ["J2", "10"]]}, {name: "mcu.swd_node.swclk", pads: [["U5", "53"], ["J2", "9"]]}, {name: "mcu.reset_node", pads: [["U5", "40"], ["J2", "6"]]}, - {name: "mcu.usb_chain_0.d_P", pads: [["U5", "35"], ["R6", "2"]]}, - {name: "mcu.usb_chain_0.d_N", pads: [["U5", "34"], ["R7", "2"]]}, {name: "mcu.swd.tdi", pads: [["J2", "7"]]}, {name: "mcu.swd.swo", pads: [["U5", "47"], ["J2", "8"]]}, + {name: "mcu.usb_res.interior.dp", pads: [["U5", "35"], ["R6", "2"]]}, + {name: "mcu.usb_res.interior.dm", pads: [["U5", "34"], ["R7", "2"]]}, {name: "vbatsense.output", pads: [["U5", "9"], ["R8", "2"], ["R9", "1"]]}, {name: "rgb.package.k_red", pads: [["D6", "3"], ["R10", "1"]]}, {name: "rgb.package.k_green", pads: [["D6", "4"], ["R11", "1"]]}, diff --git a/examples/SwdDebugger/SwdDebugger.net.ref b/examples/SwdDebugger/SwdDebugger.net.ref index 8b0eb1db1..76987738a 100644 --- a/examples/SwdDebugger/SwdDebugger.net.ref +++ b/examples/SwdDebugger/SwdDebugger.net.ref @@ -240,18 +240,6 @@ (property (name "edg_value") (value "25V 1uF X5R ±10% 0402 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "15dd03c3")) -(comp (ref "SR3") - (value "mcu.usb_pull") - (footprint "Resistor_SMD:R_0402_1005Metric") - (property (name "Sheetname") (value "mcu")) - (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) - (property (name "edg_path") (value "mcu.usb_pull.dp")) - (property (name "edg_short_path") (value "mcu.usb_pull")) - (property (name "edg_refdes") (value "SR3")) - (property (name "edg_part") (value "0402WGF1501TCE (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/16W Thick Film Resistors 50V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0402 Chip Resistor - Surface Mount ROHS")) - (sheetpath (names "/mcu/") (tstamps "/02850146/")) - (tstamps "0f5f0367")) (comp (ref "SU4") (value "mcu.crystal") (footprint "Crystal:Resonator_SMD_Murata_CSTxExxV-3Pin_3.0x1.1mm") @@ -276,6 +264,18 @@ (property (name "edg_value") (value "PinHeader1.27 Shrouded 2x5")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "02ae014f")) +(comp (ref "SR3") + (value "mcu.usb_pull") + (footprint "Resistor_SMD:R_0402_1005Metric") + (property (name "Sheetname") (value "mcu")) + (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) + (property (name "edg_path") (value "mcu.usb_pull.dp")) + (property (name "edg_short_path") (value "mcu.usb_pull")) + (property (name "edg_refdes") (value "SR3")) + (property (name "edg_part") (value "0402WGF1501TCE (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/16W Thick Film Resistors 50V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0402 Chip Resistor - Surface Mount ROHS")) + (sheetpath (names "/mcu/") (tstamps "/02850146/")) + (tstamps "0f5f0367")) (comp (ref "SU5") (value "usb_esd") (footprint "Package_TO_SOT_SMD:SOT-23") @@ -557,8 +557,8 @@ (node (ref SC8) (pin 1)) (node (ref SC9) (pin 1)) (node (ref SC10) (pin 1)) - (node (ref SR3) (pin 1)) (node (ref SJ2) (pin 1)) + (node (ref SR3) (pin 1)) (node (ref SR6) (pin 1)) (node (ref SR12) (pin 1))) (net (code 4) (name "Svtarget") diff --git a/examples/SwdDebugger/SwdDebugger.svgpcb.js b/examples/SwdDebugger/SwdDebugger.svgpcb.js index bf0f0bdb2..4c7a0155a 100644 --- a/examples/SwdDebugger/SwdDebugger.svgpcb.js +++ b/examples/SwdDebugger/SwdDebugger.svgpcb.js @@ -100,11 +100,6 @@ const SC10 = board.add(C_0402_1005Metric, { translate: pt(0.147, 0.613), rotate: 0, id: 'SC10' }) -// mcu.usb_pull.dp -const SR3 = board.add(R_0402_1005Metric, { - translate: pt(0.399, 0.463), rotate: 0, - id: 'SR3' -}) // mcu.crystal const SU4 = board.add(Resonator_SMD_Murata_CSTxExxV_3Pin_3_0x1_1mm, { translate: pt(0.079, 0.508), rotate: 0, @@ -115,6 +110,11 @@ const SJ2 = board.add(PinHeader_2x05_P1_27mm_Vertical_SMD, { translate: pt(0.614, 0.146), rotate: 0, id: 'SJ2' }) +// mcu.usb_pull.dp +const SR3 = board.add(R_0402_1005Metric, { + translate: pt(0.399, 0.463), rotate: 0, + id: 'SR3' +}) // usb_esd const SU5 = board.add(SOT_23, { translate: pt(1.520, 1.225), rotate: 0, @@ -209,7 +209,7 @@ const SR15 = board.add(R_0402_1005Metric, { board.setNetlist([ {name: "Svusb", pads: [["SJ1", "A4"], ["SJ1", "A9"], ["SJ1", "B4"], ["SJ1", "B9"], ["SD1", "1"], ["SU1", "1"], ["SU1", "3"], ["SC1", "1"], ["SU2", "1"], ["SC3", "1"]]}, {name: "Sgnd", pads: [["SJ1", "A1"], ["SJ1", "A12"], ["SJ1", "B1"], ["SJ1", "B12"], ["SJ1", "S1"], ["SR1", "1"], ["SR2", "1"], ["SD1", "2"], ["SU1", "2"], ["SC1", "2"], ["SC2", "2"], ["SU2", "2"], ["SC3", "2"], ["SC4", "2"], ["SU3", "23"], ["SU3", "35"], ["SU3", "44"], ["SU3", "47"], ["SU3", "8"], ["SC5", "2"], ["SC6", "2"], ["SC7", "2"], ["SC8", "2"], ["SC9", "2"], ["SC10", "2"], ["SU4", "2"], ["SJ2", "3"], ["SJ2", "5"], ["SJ2", "9"], ["SU5", "3"], ["SR4", "2"], ["SR5", "2"], ["SSW1", "2"], ["SJ3", "3"], ["SJ3", "5"], ["SJ3", "9"], ["SR13", "2"], ["SR15", "2"]]}, - {name: "Sv3v3", pads: [["SU1", "5"], ["SC2", "1"], ["SU3", "1"], ["SU3", "24"], ["SU3", "36"], ["SU3", "48"], ["SU3", "9"], ["SC5", "1"], ["SC6", "1"], ["SC7", "1"], ["SC8", "1"], ["SC9", "1"], ["SC10", "1"], ["SR3", "1"], ["SJ2", "1"], ["SR6", "1"], ["SR12", "1"]]}, + {name: "Sv3v3", pads: [["SU1", "5"], ["SC2", "1"], ["SU3", "1"], ["SU3", "24"], ["SU3", "36"], ["SU3", "48"], ["SU3", "9"], ["SC5", "1"], ["SC6", "1"], ["SC7", "1"], ["SC8", "1"], ["SC9", "1"], ["SC10", "1"], ["SJ2", "1"], ["SR3", "1"], ["SR6", "1"], ["SR12", "1"]]}, {name: "Svtarget", pads: [["SU2", "5"], ["SC4", "1"], ["SJ3", "1"], ["SD4", "2"], ["SR14", "1"]]}, {name: "Susb_chain_0.d_P", pads: [["SJ1", "A6"], ["SJ1", "B6"], ["SU3", "33"], ["SR3", "2"], ["SU5", "2"]]}, {name: "Susb_chain_0.d_N", pads: [["SJ1", "A7"], ["SJ1", "B7"], ["SU3", "32"], ["SU5", "1"]]}, diff --git a/examples/TestBlinkyBasic/TestBlinkyBasic.net.ref b/examples/TestBlinkyBasic/TestBlinkyBasic.net.ref index 4f6524606..27af5ce41 100644 --- a/examples/TestBlinkyBasic/TestBlinkyBasic.net.ref +++ b/examples/TestBlinkyBasic/TestBlinkyBasic.net.ref @@ -42,7 +42,7 @@ (node (ref R1) (pin 2))) (net (code 2) (name "mcu.pwr_out") (node (ref U1) (pin 12))) -(net (code 3) (name "mcu.device.vcc_out") +(net (code 3) (name "mcu.device.vcc") (node (ref U1) (pin 14))) (net (code 4) (name "led.signal") (node (ref U1) (pin 7)) diff --git a/examples/TestBlinkyBasic/TestBlinkyBasic.svgpcb.js b/examples/TestBlinkyBasic/TestBlinkyBasic.svgpcb.js index 64dacd4ad..ca7adcd27 100644 --- a/examples/TestBlinkyBasic/TestBlinkyBasic.svgpcb.js +++ b/examples/TestBlinkyBasic/TestBlinkyBasic.svgpcb.js @@ -19,7 +19,7 @@ const R1 = board.add(R_0603_1608Metric, { board.setNetlist([ {name: "mcu.gnd", pads: [["U1", "13"], ["R1", "2"]]}, {name: "mcu.pwr_out", pads: [["U1", "12"]]}, - {name: "mcu.device.vcc_out", pads: [["U1", "14"]]}, + {name: "mcu.device.vcc", pads: [["U1", "14"]]}, {name: "led.signal", pads: [["U1", "7"], ["D1", "2"]]}, {name: "led.package.k", pads: [["D1", "1"], ["R1", "1"]]} ]) diff --git a/examples/TofArray/TofArray.net.ref b/examples/TofArray/TofArray.net.ref index 33105948f..cb7adfffa 100644 --- a/examples/TofArray/TofArray.net.ref +++ b/examples/TofArray/TofArray.net.ref @@ -252,18 +252,6 @@ (property (name "edg_value") (value "50V 1uF X5R ±10% 0603 Multilayer Ceramic Capacitors MLCC - SMD/SMT ROHS")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "15dd03c3")) -(comp (ref "R3") - (value "mcu.usb_pull") - (footprint "Resistor_SMD:R_0603_1608Metric") - (property (name "Sheetname") (value "mcu")) - (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) - (property (name "edg_path") (value "mcu.usb_pull.dp")) - (property (name "edg_short_path") (value "mcu.usb_pull")) - (property (name "edg_refdes") (value "R3")) - (property (name "edg_part") (value "0603WAF1501T5E (UNI-ROYAL(Uniroyal Elec))")) - (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0603 Chip Resistor - Surface Mount ROHS")) - (sheetpath (names "/mcu/") (tstamps "/02850146/")) - (tstamps "0f5f0367")) (comp (ref "X1") (value "mcu.crystal.package") (footprint "Crystal:Crystal_SMD_3225-4Pin_3.2x2.5mm") @@ -312,6 +300,18 @@ (property (name "edg_value") (value "")) (sheetpath (names "/mcu/") (tstamps "/02850146/")) (tstamps "02ae014f")) +(comp (ref "R3") + (value "mcu.usb_pull") + (footprint "Resistor_SMD:R_0603_1608Metric") + (property (name "Sheetname") (value "mcu")) + (property (name "Sheetfile") (value "edg.parts.microcontroller.Stm32f103.Stm32f103_48")) + (property (name "edg_path") (value "mcu.usb_pull.dp")) + (property (name "edg_short_path") (value "mcu.usb_pull")) + (property (name "edg_refdes") (value "R3")) + (property (name "edg_part") (value "0603WAF1501T5E (UNI-ROYAL(Uniroyal Elec))")) + (property (name "edg_value") (value "±1% 1/10W Thick Film Resistors 75V ±100ppm/℃ -55℃~+155℃ 1.5kΩ 0603 Chip Resistor - Surface Mount ROHS")) + (sheetpath (names "/mcu/") (tstamps "/02850146/")) + (tstamps "0f5f0367")) (comp (ref "SW1") (value "sw1") (footprint "Button_Switch_SMD:SW_SPST_SKQG_WithoutStem") @@ -972,8 +972,8 @@ (node (ref C6) (pin 1)) (node (ref C7) (pin 1)) (node (ref C8) (pin 1)) - (node (ref R3) (pin 1)) (node (ref J3) (pin 1)) + (node (ref R3) (pin 1)) (node (ref D2) (pin 2)) (node (ref D3) (pin 2)) (node (ref D4) (pin 2)) diff --git a/examples/TofArray/TofArray.svgpcb.js b/examples/TofArray/TofArray.svgpcb.js index 6f96cbcfb..7c8565b4c 100644 --- a/examples/TofArray/TofArray.svgpcb.js +++ b/examples/TofArray/TofArray.svgpcb.js @@ -105,11 +105,6 @@ const C8 = board.add(C_0603_1608Metric, { translate: pt(0.214, 0.647), rotate: 0, id: 'C8' }) -// mcu.usb_pull.dp -const R3 = board.add(R_0603_1608Metric, { - translate: pt(0.370, 0.647), rotate: 0, - id: 'R3' -}) // mcu.crystal.package const X1 = board.add(Crystal_SMD_3225_4Pin_3_2x2_5mm, { translate: pt(0.083, 0.512), rotate: 0, @@ -117,12 +112,12 @@ const X1 = board.add(Crystal_SMD_3225_4Pin_3_2x2_5mm, { }) // mcu.crystal.cap_a const C9 = board.add(C_0603_1608Metric, { - translate: pt(0.526, 0.647), rotate: 0, + translate: pt(0.370, 0.647), rotate: 0, id: 'C9' }) // mcu.crystal.cap_b const C10 = board.add(C_0603_1608Metric, { - translate: pt(0.682, 0.647), rotate: 0, + translate: pt(0.526, 0.647), rotate: 0, id: 'C10' }) // mcu.swd.conn @@ -130,6 +125,11 @@ const J3 = board.add(Tag_Connect_TC2050_IDC_FP_2x05_P1_27mm_Vertical, { translate: pt(0.661, 0.167), rotate: 0, id: 'J3' }) +// mcu.usb_pull.dp +const R3 = board.add(R_0603_1608Metric, { + translate: pt(0.682, 0.647), rotate: 0, + id: 'R3' +}) // sw1.package const SW1 = board.add(SW_SPST_SKQG_WithoutStem, { translate: pt(0.742, 1.424), rotate: 0, @@ -364,7 +364,7 @@ const D7 = board.add(LED_LiteOn_LTST_C19HE1WT, { board.setNetlist([ {name: "vusb", pads: [["J1", "A4"], ["J1", "A9"], ["J1", "B4"], ["J1", "B9"], ["TP1", "1"], ["U1", "3"], ["C1", "1"], ["U11", "1"], ["U11", "6"], ["C23", "1"], ["C24", "1"]]}, {name: "gnd", pads: [["J1", "A1"], ["J1", "A12"], ["J1", "B1"], ["J1", "B12"], ["J1", "S1"], ["R1", "1"], ["R2", "1"], ["J2", "3"], ["TP2", "1"], ["U1", "1"], ["C1", "2"], ["C2", "2"], ["D1", "2"], ["U2", "23"], ["U2", "35"], ["U2", "44"], ["U2", "47"], ["U2", "8"], ["C3", "2"], ["C4", "2"], ["C5", "2"], ["C6", "2"], ["C7", "2"], ["C8", "2"], ["X1", "2"], ["X1", "4"], ["C9", "2"], ["C10", "2"], ["J3", "2"], ["J3", "3"], ["J3", "5"], ["SW1", "2"], ["U3", "12"], ["U3", "2"], ["U3", "3"], ["U3", "4"], ["U3", "6"], ["C11", "2"], ["C12", "2"], ["U4", "12"], ["U4", "2"], ["U4", "3"], ["U4", "4"], ["U4", "6"], ["C13", "2"], ["C14", "2"], ["U5", "12"], ["U5", "2"], ["U5", "3"], ["U5", "4"], ["U5", "6"], ["C15", "2"], ["C16", "2"], ["U6", "12"], ["U6", "2"], ["U6", "3"], ["U6", "4"], ["U6", "6"], ["C17", "2"], ["C18", "2"], ["U7", "12"], ["U7", "2"], ["U7", "3"], ["U7", "4"], ["U7", "6"], ["C19", "2"], ["C20", "2"], ["U8", "3"], ["U9", "2"], ["U9", "8"], ["C21", "2"], ["U10", "3"], ["C22", "2"], ["U11", "7"], ["U11", "9"], ["C23", "2"], ["C24", "2"], ["C26", "2"]]}, - {name: "v3v3", pads: [["U1", "2"], ["C2", "1"], ["TP3", "1"], ["D1", "1"], ["U2", "1"], ["U2", "24"], ["U2", "36"], ["U2", "48"], ["U2", "9"], ["C3", "1"], ["C4", "1"], ["C5", "1"], ["C6", "1"], ["C7", "1"], ["C8", "1"], ["R3", "1"], ["J3", "1"], ["D2", "2"], ["D3", "2"], ["D4", "2"], ["D5", "2"], ["D6", "2"], ["U3", "1"], ["U3", "11"], ["C11", "1"], ["C12", "1"], ["U4", "1"], ["U4", "11"], ["C13", "1"], ["C14", "1"], ["U5", "1"], ["U5", "11"], ["C15", "1"], ["C16", "1"], ["U6", "1"], ["U6", "11"], ["C17", "1"], ["C18", "1"], ["U7", "1"], ["U7", "11"], ["C19", "1"], ["C20", "1"], ["R4", "1"], ["R5", "1"], ["U9", "3"], ["C21", "1"], ["D7", "2"]]}, + {name: "v3v3", pads: [["U1", "2"], ["C2", "1"], ["TP3", "1"], ["D1", "1"], ["U2", "1"], ["U2", "24"], ["U2", "36"], ["U2", "48"], ["U2", "9"], ["C3", "1"], ["C4", "1"], ["C5", "1"], ["C6", "1"], ["C7", "1"], ["C8", "1"], ["J3", "1"], ["R3", "1"], ["D2", "2"], ["D3", "2"], ["D4", "2"], ["D5", "2"], ["D6", "2"], ["U3", "1"], ["U3", "11"], ["C11", "1"], ["C12", "1"], ["U4", "1"], ["U4", "11"], ["C13", "1"], ["C14", "1"], ["U5", "1"], ["U5", "11"], ["C15", "1"], ["C16", "1"], ["U6", "1"], ["U6", "11"], ["C17", "1"], ["C18", "1"], ["U7", "1"], ["U7", "11"], ["C19", "1"], ["C20", "1"], ["R4", "1"], ["R5", "1"], ["U9", "3"], ["C21", "1"], ["D7", "2"]]}, {name: "sw1_chain_0", pads: [["U2", "19"], ["SW1", "1"]]}, {name: "leds_chain_0.0", pads: [["U2", "20"], ["RN1", "8"]]}, {name: "leds_chain_0.1", pads: [["U2", "25"], ["RN1", "7"]]},