Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
Library: Additions and fixes (#117)
Browse files Browse the repository at this point in the history
Add:
* Analog_Devices_ADM2587EBRWZ
* PANASONIC_AQY212EHAX
* RaspberryPiPico
* SK6812

* Fix logic reference connection
* Add RP Pico design
* Fix pin connection
* Fix switch and traits
* Fix some layouts
  • Loading branch information
ruben-iteng authored Nov 3, 2024
1 parent 8393980 commit 057e625
Show file tree
Hide file tree
Showing 21 changed files with 706 additions and 79 deletions.
127 changes: 127 additions & 0 deletions src/faebryk/library/Analog_Devices_ADM2587EBRWZ.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

import logging

import faebryk.library._F as F # noqa: F401
from faebryk.core.module import Module
from faebryk.libs.library import L # noqa: F401
from faebryk.libs.picker.picker import DescriptiveProperties
from faebryk.libs.units import P
from faebryk.libs.util import assert_once # noqa: F401

logger = logging.getLogger(__name__)


class Analog_Devices_ADM2587EBRWZ(Module):
"""
Signal and power isolated RS-485 full/half-duplex transceiver with
±15 kV ESD protection
"""

# ----------------------------------------
# modules, interfaces, parameters
# ----------------------------------------
power_unisolated: F.ElectricPower
power_isolated_out: F.ElectricPower
power_isolated_in: F.ElectricPower
uart: F.UART_Base
read_enable: F.ElectricLogic
write_enable: F.ElectricLogic
rs485: F.RS485HalfDuplex

# ----------------------------------------
# traits
# ----------------------------------------
lcsc_id = L.f_field(F.has_descriptive_properties_defined)({"LCSC": "C12081"})
designator_prefix = L.f_field(F.has_designator_prefix_defined)(
F.has_designator_prefix.Prefix.U
)
descriptive_properties = L.f_field(F.has_descriptive_properties_defined)(
{
DescriptiveProperties.manufacturer: "Analog Devices",
DescriptiveProperties.partno: "ADM2587EBRWZ-REEL7",
}
)
datasheet = L.f_field(F.has_datasheet_defined)(
"https://www.lcsc.com/datasheet/lcsc_datasheet_1809121646_Analog-Devices-ADM2587EBRWZ-REEL7_C12081.pdf" # noqa: E501
)

@L.rt_field
def can_attach_to_footprint(self):
return F.can_attach_to_footprint_via_pinmap(
pinmap={
"1": self.power_unisolated.lv,
"2": self.power_unisolated.hv,
"3": self.power_unisolated.lv,
"4": self.uart.rx.signal,
"5": self.read_enable.signal,
"6": self.write_enable.signal,
"7": self.uart.tx.signal,
"8": self.power_unisolated.hv,
"9": self.power_unisolated.lv,
"10": self.power_unisolated.lv,
"11": self.power_isolated_out.lv,
"12": self.power_isolated_out.hv,
"13": self.rs485.diff_pair.p.signal,
"14": self.power_isolated_out.lv,
"15": self.rs485.diff_pair.n.signal,
"16": self.power_isolated_out.lv,
"17": self.rs485.diff_pair.n.signal,
"18": self.rs485.diff_pair.p.signal,
"19": self.power_isolated_in.hv,
"20": self.power_isolated_out.lv,
}
)

@L.rt_field
def pin_association_heuristic(self):
return F.has_pin_association_heuristic_lookup_table(
mapping={
self.rs485.diff_pair.p.signal: ["A"],
self.rs485.diff_pair.n.signal: ["B"],
self.write_enable.signal: ["DE"],
self.power_unisolated.lv: ["GND1"],
self.power_isolated_out.lv: ["GND2"],
self.read_enable.signal: ["RE#"],
self.uart.rx.signal: ["RXD"],
self.uart.tx.signal: ["TXD"],
self.power_unisolated.hv: ["VCC"],
self.power_isolated_in.hv: ["VISOIN"],
self.power_isolated_out.hv: ["VISOOUT"],
self.rs485.diff_pair.p.signal: ["Y"],
self.rs485.diff_pair.n.signal: ["Z"],
},
accept_prefix=False,
case_sensitive=False,
)

def __init__(self, full_duplex: bool = False):
self._full_duplex = full_duplex
if full_duplex:
raise NotImplementedError("Full duplex RS485 not implemented")

def __preinit__(self):
# ------------------------------------
# connections
# ------------------------------------

# ------------------------------------
# parametrization
# ------------------------------------
self.power_isolated_out.voltage.merge(F.Range.from_center_rel(3.3 * P.V, 0.1))
self.power_unisolated.voltage.merge(F.Range(3.3 * P.V, 5 * P.V))

F.ElectricLogic.connect_all_module_references(
self,
exclude=[
self.power_unisolated,
self.uart,
self.read_enable,
self.write_enable,
],
)

# TODO: ugly
self.rs485.diff_pair.n.reference.connect(self.power_isolated_out)
self.rs485.diff_pair.p.reference.connect(self.power_isolated_out)
87 changes: 87 additions & 0 deletions src/faebryk/library/Analog_Devices_ADM2587EBRWZ_ReferenceDesign.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

import itertools
import logging

import faebryk.library._F as F # noqa: F401
from faebryk.core.module import Module
from faebryk.libs.library import L # noqa: F401
from faebryk.libs.units import P # noqa: F401

logger = logging.getLogger(__name__)


class Analog_Devices_ADM2587EBRWZ_ReferenceDesign(Module):
"""
Reference implementation of ADM2587EBRWZ isolated RS485 transceiver
"""

# ----------------------------------------
# modules, interfaces, parameters
# ----------------------------------------
transceiver = L.f_field(F.Analog_Devices_ADM2587EBRWZ)(full_duplex=False)

# ----------------------------------------
# traits
# ----------------------------------------
@L.rt_field
def pcb_layout(self):
from faebryk.exporters.pcb.layout.absolute import LayoutAbsolute
from faebryk.exporters.pcb.layout.typehierarchy import LayoutTypeHierarchy

Point = F.has_pcb_position.Point
L = F.has_pcb_position.layer_type
LVL = LayoutTypeHierarchy.Level

return F.has_pcb_layout_defined(
layout=LayoutTypeHierarchy(
layouts=[
LVL(
mod_type=F.Analog_Devices_ADM2587EBRWZ,
layout=LayoutAbsolute(Point((0, 0, 0, L.NONE))),
),
]
)
)

def __preinit__(self):
# ------------------------------------
# connections
# ------------------------------------
self.transceiver.power_isolated_in.connect(self.transceiver.power_isolated_out)

# ------------------------------------
# parametrization
# ------------------------------------
# decoupling unisolated power
power_unisolated_capacitors = (
self.transceiver.power_unisolated.decoupled.decouple()
.specialize(F.MultiCapacitor(4))
.capacitors
)
capacitance_values = [100, 10] # in nF

for cap, value in zip(
power_unisolated_capacitors, itertools.cycle(capacitance_values)
):
cap.capacitance.merge(F.Range.from_center_rel(value * P.nF, 0.05))

# decoupling isolated power in
for i, cap in enumerate(
self.transceiver.power_isolated_in.decoupled.decouple()
.specialize(F.MultiCapacitor(2))
.capacitors
):
cap.capacitance.merge(
F.Range.from_center_rel(capacitance_values[i] * P.nF, 0.05)
)
# decoupling isolated power out
for i, cap in enumerate(
self.transceiver.power_isolated_out.decoupled.decouple()
.specialize(F.MultiCapacitor(2))
.capacitors
):
cap.capacitance.merge(
F.Range.from_center_rel(capacitance_values[i] * P.nF, 0.05)
)
4 changes: 2 additions & 2 deletions src/faebryk/library/CH344Q.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ def can_attach_to_footprint(self):
"39": self.uart[0].dtr.signal,
"40": self.uart[0].rts.signal,
"41": self.uart[0].cts.signal,
"42": self.usb.n,
"43": self.usb.p,
"42": self.usb.n.signal,
"43": self.usb.p.signal,
"44": self.test.signal,
"45": self.uart[3].rts.signal,
"46": self.uart[3].cts.signal,
Expand Down
32 changes: 21 additions & 11 deletions src/faebryk/library/CH344Q_ReferenceDesign.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ class CH344Q_ReferenceDesign(Module):
power_led: F.PoweredLED
reset_lowpass: F.FilterElectricalRC

@L.rt_field
def vbus_fused(self):
return self.usb.usb_if.buspower.fused()

# ----------------------------------------
# traits
# ----------------------------------------
Expand All @@ -55,21 +51,23 @@ def pcb_layout(self):
),
LVL(
mod_type=F.Crystal_Oscillator,
layout=LayoutAbsolute(Point((0, -8, 0, L.NONE))),
layout=LayoutAbsolute(Point((-1, 10.75, 180, L.NONE))),
),
LVL(
mod_type=F.LDO,
layout=LayoutAbsolute(Point((9.5, 0, 0, L.NONE))),
layout=LayoutAbsolute(Point((7.5, -9.25, 270, L.NONE))),
),
LVL(
mod_type=F.LEDIndicator,
layout=LayoutExtrude(
base=Point((-5.75, 7.5, 0, L.NONE)), vector=(-1.75, 0, 90)
base=Point((8, 9.5, 0, L.NONE)),
vector=(-1.75, 0, 90),
reverse_order=True,
),
),
LVL(
mod_type=F.PoweredLED,
layout=LayoutAbsolute(Point((5, -8, 90, L.NONE))),
layout=LayoutAbsolute(Point((-6.5, 9.5, 270, L.NONE))),
),
LVL(
mod_type=F.FilterElectricalRC,
Expand All @@ -90,7 +88,7 @@ def __preinit__(self):
self.usb_uart_converter.power.decoupled.decouple().specialize(
F.MultiCapacitor(4)
).set_equal_capacitance_each(F.Range.from_center_rel(100 * P.nF, 0.05))
self.vbus_fused.connect_via(self.ldo, pwr_3v3)
self.usb.usb_if.buspower.connect_via(self.ldo, pwr_3v3)

self.usb.usb_if.d.connect(self.usb_uart_converter.usb)

Expand All @@ -101,10 +99,17 @@ def __preinit__(self):

self.usb_uart_converter.osc[1].connect(self.oscillator.xtal_if.xin)
self.usb_uart_converter.osc[0].connect(self.oscillator.xtal_if.xout)
self.oscillator.gnd.connect(pwr_3v3.lv)
self.oscillator.xtal_if.gnd.connect(pwr_3v3.lv)

self.reset_lowpass.out.connect(self.usb_uart_converter.reset)
self.usb_uart_converter.reset.pulled.pull(up=True)
self.reset_lowpass.in_.signal.connect(
self.usb_uart_converter.reset.reference.hv
)
self.reset_lowpass.in_.reference.connect(
self.usb_uart_converter.reset.reference
)
# TODO: already done by lowpass filter
# self.usb_uart_converter.reset.pulled.pull(up=True)

# ------------------------------------
# parametrization
Expand Down Expand Up @@ -143,3 +148,8 @@ def __preinit__(self):
self.reset_lowpass.cutoff_frequency.merge(
F.Range.from_center_rel(100 * P.Hz, 0.1)
)

# Specialize
special = self.reset_lowpass.specialize(F.FilterElectricalRC())
# Construct
special.get_trait(F.has_construction_dependency).construct()
7 changes: 3 additions & 4 deletions src/faebryk/library/Crystal_Oscillator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ class Crystal_Oscillator(Module):
current_limiting_resistor: F.Resistor

xtal_if: F.XtalIF
gnd: F.Electrical

# ----------------------------------------
# parameters
Expand Down Expand Up @@ -49,9 +48,9 @@ def __preinit__(self):
# ----------------------------------------
# connections
# ----------------------------------------
self.crystal.gnd.connect(self.gnd)
self.crystal.unnamed[0].connect_via(self.capacitors[0], self.gnd)
self.crystal.unnamed[1].connect_via(self.capacitors[1], self.gnd)
self.crystal.gnd.connect(self.xtal_if.gnd)
self.crystal.unnamed[0].connect_via(self.capacitors[0], self.xtal_if.gnd)
self.crystal.unnamed[1].connect_via(self.capacitors[1], self.xtal_if.gnd)

self.crystal.unnamed[0].connect_via(
self.current_limiting_resistor, self.xtal_if.xout
Expand Down
21 changes: 15 additions & 6 deletions src/faebryk/library/Diodes_Incorporated_AP2552W6_7.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import faebryk.library._F as F # noqa: F401
from faebryk.core.module import Module, ModuleException
from faebryk.core.parameter import Parameter
from faebryk.exporters.pcb.layout.absolute import LayoutAbsolute
from faebryk.exporters.pcb.layout.extrude import LayoutExtrude
from faebryk.exporters.pcb.layout.heuristic_decoupling import Params
from faebryk.exporters.pcb.layout.next_to import LayoutNextTo
from faebryk.exporters.pcb.layout.typehierarchy import LayoutTypeHierarchy
from faebryk.library.has_pcb_position import has_pcb_position
from faebryk.libs.library import L # noqa: F401
Expand All @@ -25,10 +26,10 @@ class Diodes_Incorporated_AP2552W6_7(Module):
"""

@assert_once
def set_current_limit(self, current: Parameter[Quantity]) -> None:
def set_current_limit(self, current: Parameter[Quantity]) -> F.Resistor:
self.current_limit.merge(current)

current_limit_setting_resistor = self.add(F.Resistor())
current_limit_setting_resistor = self.ilim.add(F.Resistor())

self.ilim.signal.connect_via(
current_limit_setting_resistor, self.ilim.reference.lv
Expand All @@ -41,7 +42,9 @@ def set_current_limit(self, current: Parameter[Quantity]) -> None:
# Rlim_max = (20.08 / (self.current_limit * P.mA)) ^ (1 / 0.904) * P.kohm

# Rlim = Range(Rlim_min, Rlim_max)
Rlim = F.Constant(51 * P.kohm) # TODO: remove: ~0.52A typical current limit
Rlim = F.Range.from_center_rel(
51 * P.kohm, 0.01
) # TODO: remove: ~0.52A typical current limit
if not Rlim.is_subset_of(F.Range(10 * P.kohm, 210 * P.kohm)):
raise ModuleException(
self,
Expand All @@ -50,6 +53,8 @@ def set_current_limit(self, current: Parameter[Quantity]) -> None:

current_limit_setting_resistor.resistance.merge(Rlim)

return current_limit_setting_resistor

# ----------------------------------------
# modules, interfaces, parameters
# ----------------------------------------
Expand Down Expand Up @@ -105,8 +110,12 @@ def has_defined_layout(self):
layouts = [
LVL(
mod_type=F.Resistor,
layout=LayoutAbsolute(
Point((0, -3, 90, L.NONE)),
layout=LayoutNextTo(
self.ilim.signal,
params=Params(
distance_between_pad_edges=1,
extra_rotation_of_footprint=90,
),
),
),
LVL(
Expand Down
2 changes: 1 addition & 1 deletion src/faebryk/library/ElecSuper_PSM712_ES.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ElecSuper_PSM712_ES(Module):
# ----------------------------------------
# modules, interfaces, parameters
# ----------------------------------------
rs485: F.RS485
rs485: F.RS485HalfDuplex

# ----------------------------------------
# traits
Expand Down
Loading

0 comments on commit 057e625

Please sign in to comment.