From c708e28c00cc87f2651e2b25419c56299ee58f9a Mon Sep 17 00:00:00 2001 From: ruben-iteng <94007802+ruben-iteng@users.noreply.github.com> Date: Thu, 5 Sep 2024 22:58:32 +0200 Subject: [PATCH] Add: CH342F --- src/faebryk/library/CH342.py | 64 ++++++++ src/faebryk/library/CH342F.py | 148 ++++++++++++++++++ src/faebryk/library/CH342F_ReferenceDesign.py | 71 +++++++++ src/faebryk/library/_F.py | 3 + 4 files changed, 286 insertions(+) create mode 100644 src/faebryk/library/CH342.py create mode 100644 src/faebryk/library/CH342F.py create mode 100644 src/faebryk/library/CH342F_ReferenceDesign.py diff --git a/src/faebryk/library/CH342.py b/src/faebryk/library/CH342.py new file mode 100644 index 00000000..82ec4ae3 --- /dev/null +++ b/src/faebryk/library/CH342.py @@ -0,0 +1,64 @@ +# This file is part of the faebryk project +# SPDX-License-Identifier: MIT + +import logging +from enum import Enum, auto + +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 CH342(Module): + """ + Base class for CH342x USB to double UART converter + """ + + class DuplexMode(Enum): + FULL = auto() + HALF = auto() + + # ---------------------------------------- + # modules, interfaces, parameters + # ---------------------------------------- + usb: F.USB2_0 + uart = L.list_field(2, F.UART) + tnow = L.list_field(2, F.ElectricLogic) + ri = L.list_field(2, F.ElectricLogic) + dcd = L.list_field(2, F.ElectricLogic) + + reset = F.ElectricLogic() + active = F.ElectricLogic() + + vdd_5v = F.ElectricPower() + v_io = F.ElectricPower() + v_3v = F.ElectricPower() + + # ---------------------------------------- + # traits + # ---------------------------------------- + datasheet = L.f_field(F.has_datasheet_defined)( + "https://wch-ic.com/downloads/CH342DS1_PDF.html" + ) + + def __preinit__(self): + # ---------------------------------------- + # aliasess + # ---------------------------------------- + gnd = self.usb.usb_if.buspower.lv + + # ---------------------------------------- + # parametrization + # ---------------------------------------- + self.vdd_5v.voltage.merge(F.Range(4 * P.V, 5.5 * P.V)) + self.v_3v.voltage.merge(F.Constant(3.3 * P.V)) + self.v_io.voltage.merge(F.Range(1.7 * P.V, 3.6 * P.V)) + + # ---------------------------------------- + # connections + # ---------------------------------------- + for powerrail in [self.vdd_5v, self.v_io, self.v_3v]: + powerrail.lv.connect(gnd) diff --git a/src/faebryk/library/CH342F.py b/src/faebryk/library/CH342F.py new file mode 100644 index 00000000..3054beaf --- /dev/null +++ b/src/faebryk/library/CH342F.py @@ -0,0 +1,148 @@ +# 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 # noqa: F401 +from faebryk.libs.util import NotNone + +logger = logging.getLogger(__name__) + + +class CH342F(Module): + """ + Dual UART-USB converter + """ + + # ---------------------------------------- + # modules, interfaces, parameters + # ---------------------------------------- + usb: F.USB2_0 + uart = L.list_field(2, F.UART) + + tnow = L.list_field(2, F.ElectricLogic) + ri = L.list_field(2, F.ElectricLogic) + dcd = L.list_field(2, F.ElectricLogic) + + reset: F.ElectricLogic + active: F.ElectricLogic + + vdd_5v: F.ElectricPower + v_io: F.ElectricPower + v_3v: F.ElectricPower + + designator_prefix = L.f_field(F.has_designator_prefix_defined)("U") + + # ---------------------------------------- + # traits + # ---------------------------------------- + datasheet = L.f_field(F.has_datasheet_defined)( + "https://wch-ic.com/downloads/CH342DS1_PDF.html" + ) + + @L.rt_field + def can_attach_to_footprint(self): + return F.can_attach_to_footprint_via_pinmap( + { + "1": self.ri[0].signal, + "2": self.usb.usb_if.buspower.lv, + "3": self.usb.usb_if.d.p, + "4": self.usb.usb_if.d.n, + "5": self.v_io.hv, + "6": self.v_3v.hv, + "7": self.vdd_5v.hv, + "8": self.usb.usb_if.buspower.hv, + "9": self.reset.signal, + "10": self.uart[1].cts.signal, + "11": self.uart[1].rts.signal, + "12": self.uart[1].base_uart.rx.signal, + "13": self.uart[1].base_uart.tx.signal, + "14": self.uart[1].dsr.signal, + "15": self.uart[1].dtr.signal, + "16": self.dcd[1].signal, + "17": self.ri[1].signal, + "18": self.uart[0].cts.signal, + "19": self.uart[0].rts.signal, + "20": self.uart[0].base_uart.rx.signal, + "21": self.uart[0].base_uart.tx.signal, + "22": self.uart[0].dsr.signal, + "23": self.uart[0].dtr.signal, + "24": self.dcd[0].signal, + "25": self.usb.usb_if.buspower.lv, + } + ) + + def __init__( + self, + duplex_mode_uart_0: F.CH342.DuplexMode = F.CH342.DuplexMode.FULL, + duplex_mode_uart_1: F.CH342.DuplexMode = F.CH342.DuplexMode.FULL, + ): + super().__init__() + self._duplex_mode_uart_0 = duplex_mode_uart_0 + self._duplex_mode_uart_1 = duplex_mode_uart_1 + + def __preinit__(self) -> None: + # ---------------------------------------- + # aliasess + # ---------------------------------------- + # ---------------------------------------- + # parametrization + # ---------------------------------------- + self.vdd_5v.voltage.merge(F.Range(4 * P.V, 5.5 * P.V)) + self.v_3v.voltage.merge(F.Constant(3.3 * P.V)) + self.v_io.voltage.merge(F.Range(1.7 * P.V, 3.6 * P.V)) + + # set the duplex mode + if self._duplex_mode_uart_0 == F.CH342.DuplexMode.HALF: + self.uart[0].dtr.get_trait(F.ElectricLogic.can_be_pulled).pull(up=False) + NotNone( + self.uart[0].dtr.get_trait(F.ElectricLogic.has_pulls).get_pulls()[1] + ).resistance.merge(F.Constant(4.7 * P.kohm)) + self.tnow[0].connect(self.uart[0].dtr) + if self._duplex_mode_uart_1 == F.CH342.DuplexMode.HALF: + self.uart[1].dtr.get_trait(F.ElectricLogic.can_be_pulled).pull(up=False) + NotNone( + self.uart[1].dtr.get_trait(F.ElectricLogic.has_pulls).get_pulls()[1] + ).resistance.merge(F.Constant(4.7 * P.kohm)) + self.tnow[1].connect(self.uart[1].dtr) + + # ---------------------------------------- + # connections + # ---------------------------------------- + # configure for 3.3V GPIO operation with internal LDO + self.vdd_5v.connect(self.usb.usb_if.buspower) + self.v_3v.connect(self.v_io) + + self.vdd_5v.get_trait(F.can_be_decoupled).decouple().capacitance.merge( + F.Constant(1 * P.uF) + ) + self.v_3v.get_trait(F.can_be_decoupled).decouple().capacitance.merge( + F.Constant(0.1 * P.uF) + ) + self.v_io.get_trait(F.can_be_decoupled).decouple().capacitance.merge( + F.Constant(1 * P.uF) + ) + + F.can_attach_to_footprint().attach( + F.QFN( + pin_cnt=24, + exposed_thermal_pad_cnt=1, + size_xy=(4 * P.mm, 4 * P.mm), + pitch=0.5 * P.mm, + exposed_thermal_pad_dimensions=(2.65 * P.mm, 2.65 * P.mm), + has_thermal_vias=False, + ) + ) + + self.add( + F.has_descriptive_properties_defined( + { + DescriptiveProperties.manufacturer: "WCH", + DescriptiveProperties.partno: "CH342F", + }, + ) + ) diff --git a/src/faebryk/library/CH342F_ReferenceDesign.py b/src/faebryk/library/CH342F_ReferenceDesign.py new file mode 100644 index 00000000..79eeb68c --- /dev/null +++ b/src/faebryk/library/CH342F_ReferenceDesign.py @@ -0,0 +1,71 @@ +# 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.units import P # noqa: F401 +from faebryk.libs.util import NotNone + +logger = logging.getLogger(__name__) + + +class CH342F_ReferenceDesign(Module): + """ + Minimal reference implementation of the CH342F + """ + + # ---------------------------------------- + # modules, interfaces, parameters + # ---------------------------------------- + ch324: F.CH342F + + def __init__( + self, + duplex_mode_uart_0: F.CH342.DuplexMode = F.CH342.DuplexMode.FULL, + duplex_mode_uart_1: F.CH342.DuplexMode = F.CH342.DuplexMode.FULL, + ) -> None: + super().__init__() + self._duplex_mode_uart_0 = duplex_mode_uart_0 + self._duplex_mode_uart_1 = duplex_mode_uart_1 + + def __preinit__(self): + # ---------------------------------------- + # aliasess + # ---------------------------------------- + # ---------------------------------------- + # parametrization + # ---------------------------------------- + # set the duplex mode + if self._duplex_mode_uart_0 == F.CH342.DuplexMode.HALF: + self.ch324.uart[0].dtr.get_trait(F.ElectricLogic.can_be_pulled).pull( + up=False + ) + NotNone( + self.ch324.uart[0] + .dtr.get_trait(F.ElectricLogic.has_pulls) + .get_pulls()[1] + ).resistance.merge(F.Constant(4.7 * P.kohm)) + self.ch324.tnow[0].connect(self.ch324.uart[0].dtr) + if self._duplex_mode_uart_1 == F.CH342.DuplexMode.HALF: + self.ch324.uart[1].dtr.get_trait(F.ElectricLogic.can_be_pulled).pull( + up=False + ) + NotNone( + self.ch324.uart[1] + .dtr.get_trait(F.ElectricLogic.has_pulls) + .get_pulls()[1] + ).resistance.merge(F.Constant(4.7 * P.kohm)) + self.ch324.tnow[1].connect(self.ch324.uart[1].dtr) + + # ---------------------------------------- + # connections + # ---------------------------------------- + # configure for 3.3V GPIO operation with internal LDO + self.ch324.vdd_5v.connect(self.ch324.usb.usb_if.buspower) + self.ch324.v_3v.connect(self.ch324.v_io) + + self.ch324.vdd_5v.get_trait(F.can_be_decoupled).decouple() + self.ch324.v_3v.get_trait(F.can_be_decoupled).decouple() diff --git a/src/faebryk/library/_F.py b/src/faebryk/library/_F.py index b5ed3534..632fd94c 100644 --- a/src/faebryk/library/_F.py +++ b/src/faebryk/library/_F.py @@ -199,6 +199,7 @@ from faebryk.library.RS232_3D5R_Tranceiver import RS232_3D5R_Tranceiver from faebryk.library.CBM9002A_56ILG import CBM9002A_56ILG from faebryk.library.CH340x import CH340x +from faebryk.library.CH342 import CH342 from faebryk.library.CH344 import CH344 from faebryk.library.ESP32_C3 import ESP32_C3 from faebryk.library.MCP2221A import MCP2221A @@ -211,6 +212,7 @@ from faebryk.library.TI_CD4011BE import TI_CD4011BE from faebryk.library.CBM9002A_56ILG_Reference_Design import CBM9002A_56ILG_Reference_Design from faebryk.library.USB_RS485 import USB_RS485 +from faebryk.library.CH342F import CH342F from faebryk.library.CH344Q import CH344Q from faebryk.library.ESP32_C3_MINI_1 import ESP32_C3_MINI_1 from faebryk.library.RP2040_Reference_Design import RP2040_Reference_Design @@ -219,6 +221,7 @@ from faebryk.library.USB_C import USB_C from faebryk.library.PowerSwitchMOSFET import PowerSwitchMOSFET from faebryk.library.PowerSwitchStatic import PowerSwitchStatic +from faebryk.library.CH342F_ReferenceDesign import CH342F_ReferenceDesign from faebryk.library.CH344Q_ReferenceDesign import CH344Q_ReferenceDesign from faebryk.library.ESP32_C3_MINI_1_Reference_Design import ESP32_C3_MINI_1_Reference_Design from faebryk.library.USB_C_5V_PSU import USB_C_5V_PSU