From 4d005cfd84f27660e046f9bdf5601c4f2b84fb34 Mon Sep 17 00:00:00 2001 From: Richard Lin Date: Wed, 24 Jul 2024 22:31:04 -0700 Subject: [PATCH] improve categorization (#370) Resolves #312 - Add subcategorizations of Interface and EnvironmentalSensor - Add MultipackDevice categorization, which replaces any prior categorization - multipack devices should not be used in the context of a normal block --- edg/abstract_parts/AbstractCapacitor.py | 2 +- edg/abstract_parts/AbstractLed.py | 2 +- edg/abstract_parts/AbstractOpamp.py | 4 +- edg/abstract_parts/AbstractResistorArray.py | 2 +- edg/abstract_parts/Categories.py | 50 +++++++++++++++++++++ edg/abstract_parts/UsbBitBang.py | 2 +- edg/abstract_parts/__init__.py | 8 ++-- edg/core/Generator.py | 1 + edg/parts/EnvironmentalSensor_Bme680.py | 2 +- edg/parts/EnvironmentalSensor_Sensirion.py | 2 +- edg/parts/EnvironmentalSensor_Ti.py | 4 +- edg/parts/IoExpander_Pca9554.py | 2 +- edg/parts/IoExpander_Pcf8574.py | 2 +- edg/parts/Microphone_Sd18ob261.py | 2 +- edg/parts/SpeakerDriver_Analog.py | 6 +-- edg/parts/SpeakerDriver_Max98357a.py | 2 +- 16 files changed, 73 insertions(+), 20 deletions(-) diff --git a/edg/abstract_parts/AbstractCapacitor.py b/edg/abstract_parts/AbstractCapacitor.py index 9277776fd..a4b396f2d 100644 --- a/edg/abstract_parts/AbstractCapacitor.py +++ b/edg/abstract_parts/AbstractCapacitor.py @@ -355,7 +355,7 @@ def contents(self): self.assign(self.actual_capacitance, self.capacitance) # fake it, since a combined capacitance is handwavey -class CombinedCapacitor(PassiveComponent, MultipackBlock, GeneratorBlock): +class CombinedCapacitor(MultipackDevice, MultipackBlock, GeneratorBlock): """A packed capacitor that combines multiple individual capacitors into a single component, with the sum of or taking the max of the constituent capacitances.""" @init_in_parent diff --git a/edg/abstract_parts/AbstractLed.py b/edg/abstract_parts/AbstractLed.py index 0a56a76dc..04af0b401 100644 --- a/edg/abstract_parts/AbstractLed.py +++ b/edg/abstract_parts/AbstractLed.py @@ -278,7 +278,7 @@ def __init__(self): super().__init__(current_draw=RangeExpr()) -class IndicatorSinkPackedRgbLed(Light, MultipackBlock): +class IndicatorSinkPackedRgbLed(MultipackDevice, MultipackBlock): def __init__(self): super().__init__() diff --git a/edg/abstract_parts/AbstractOpamp.py b/edg/abstract_parts/AbstractOpamp.py index 4bccfe89b..697a4ef71 100644 --- a/edg/abstract_parts/AbstractOpamp.py +++ b/edg/abstract_parts/AbstractOpamp.py @@ -1,7 +1,7 @@ from typing import Mapping, Tuple, List, NamedTuple from ..electronics_model import * -from .Categories import Analog +from .Categories import Analog, MultipackDevice @abstract_block @@ -32,7 +32,7 @@ class OpampElement(Opamp): @abstract_block -class MultipackOpamp(Analog, MultipackBlock): +class MultipackOpamp(MultipackDevice, MultipackBlock): """Base class for packed opamps - devices that have multiple opamps in a single package, with shared power and ground connections. Typically used with the multipack feature to fit individual opamps across the design hierarchy into one of these.""" diff --git a/edg/abstract_parts/AbstractResistorArray.py b/edg/abstract_parts/AbstractResistorArray.py index 86e95df0d..8aca0b341 100644 --- a/edg/abstract_parts/AbstractResistorArray.py +++ b/edg/abstract_parts/AbstractResistorArray.py @@ -14,7 +14,7 @@ def __init__(self): @abstract_block -class ResistorArray(PassiveComponent, MultipackBlock): +class ResistorArray(MultipackDevice, MultipackBlock): """An n-element resistor array, where all resistors have the same resistance and power rating.""" @init_in_parent def __init__(self, count: IntLike = 0) -> None: # 0 means 'size automatically' diff --git a/edg/abstract_parts/Categories.py b/edg/abstract_parts/Categories.py index 9ebcfdd9e..9dda721a5 100644 --- a/edg/abstract_parts/Categories.py +++ b/edg/abstract_parts/Categories.py @@ -85,6 +85,22 @@ class DigitalToAnalog(Interface): pass +@abstract_block +class SpeakerDriver(Interface): + pass + + +@abstract_block +class IoExpander(Interface): + pass + + +@abstract_block +class BitBangAdapter(Interface): + """Adapters that break out a structured Bundle to component wires, useful when bit-banging those protocols""" + pass + + @abstract_block class Radiofrequency(Block): """Radiofrequency devices.""" @@ -194,6 +210,28 @@ class EnvironmentalSensor(Sensor): pass +@abstract_block +class TemperatureSensor(EnvironmentalSensor): + pass + + +@abstract_block +class HumiditySensor(EnvironmentalSensor): + pass + + +@abstract_block +class PressureSensor(EnvironmentalSensor): + """Sensors measuring ambient pressure""" + pass + + +@abstract_block +class GasSensor(EnvironmentalSensor): + """Sensors measuring gas concentration, including non-particle IAQ, TVOC, eCO2, and CO2 sensors.""" + pass + + @abstract_block class LightSensor(Sensor): pass @@ -204,6 +242,11 @@ class Magnetometer(Sensor): pass +@abstract_block +class Microphone(Sensor): + pass + + @abstract_block class Camera(Sensor): """Imaging sensors, including visible / RGB, IR, and thermal.""" @@ -227,6 +270,13 @@ class Testing(Block): pass +@abstract_block +class MultipackDevice(Block): + """A multipack device (e.g., dualpack opamp, quadpack resistor array) which blocks across the design + can be merged into.""" + pass + + @abstract_block class ProgrammingConnector(Connector, Testing): """Programming / debug / JTAG connectors.""" diff --git a/edg/abstract_parts/UsbBitBang.py b/edg/abstract_parts/UsbBitBang.py index 9cd4a32f3..ef62fb906 100644 --- a/edg/abstract_parts/UsbBitBang.py +++ b/edg/abstract_parts/UsbBitBang.py @@ -5,7 +5,7 @@ from .AbstractResistor import Resistor -class UsbBitBang(Interface, Block): +class UsbBitBang(BitBangAdapter, Block): """Bit-bang circuit for USB, from the UPduino3.0 circuit and for 3.3v. Presumably generalizes to any digital pin that can be driven fast enough. diff --git a/edg/abstract_parts/__init__.py b/edg/abstract_parts/__init__.py index fd432575e..ab85f69f5 100644 --- a/edg/abstract_parts/__init__.py +++ b/edg/abstract_parts/__init__.py @@ -10,13 +10,15 @@ from .Categories import Analog, OpampApplication from .Categories import Filter, AnalogFilter, DigitalFilter from .Categories import Microcontroller, Fpga, Memory, RealtimeClock, Radiofrequency -from .Categories import Interface, AnalogToDigital, DigitalToAnalog +from .Categories import Interface, AnalogToDigital, DigitalToAnalog, SpeakerDriver, IoExpander, BitBangAdapter from .Categories import PowerConditioner, PowerSwitch, MotorDriver, BrushedMotorDriver, BldcDriver from .Categories import PowerSource, Connector, ProgrammingConnector from .Categories import HumanInterface, Display, Lcd, Oled, EInk, Light -from .Categories import Sensor, CurrentSensor, Accelerometer, Gyroscope, Magnetometer, DistanceSensor, Camera, \ - EnvironmentalSensor, LightSensor +from .Categories import Sensor, CurrentSensor, Accelerometer, Gyroscope, Magnetometer, DistanceSensor, Microphone, \ + Camera, LightSensor +from .Categories import EnvironmentalSensor, TemperatureSensor, HumiditySensor, PressureSensor, GasSensor from .Categories import Label, Testing, TypedJumper, TypedTestPoint, InternalSubcircuit, DeprecatedBlock, Mechanical +from .Categories import MultipackDevice from .ESeriesUtil import ESeriesUtil from .SmdStandardPackage import SmdStandardPackage, SmdStandardPackageSelector diff --git a/edg/core/Generator.py b/edg/core/Generator.py index 61a0bedcc..198e86357 100644 --- a/edg/core/Generator.py +++ b/edg/core/Generator.py @@ -134,6 +134,7 @@ def _generated_def_to_proto(self, generate_values: Iterable[Tuple[edgir.LocalPat return self._def_to_proto() +@non_library class DefaultExportBlock(GeneratorBlock): """EXPERIMENTAL UTILITY CLASS. There needs to be a cleaner way to address this eventually, perhaps as a core compiler construct. diff --git a/edg/parts/EnvironmentalSensor_Bme680.py b/edg/parts/EnvironmentalSensor_Bme680.py index be1f47311..e183418df 100644 --- a/edg/parts/EnvironmentalSensor_Bme680.py +++ b/edg/parts/EnvironmentalSensor_Bme680.py @@ -41,7 +41,7 @@ def contents(self) -> None: self.assign(self.actual_basic_part, False) -class Bme680(EnvironmentalSensor, DefaultExportBlock): +class Bme680(TemperatureSensor, HumiditySensor, PressureSensor, GasSensor, DefaultExportBlock): """Gas (indoor air quality), pressure, temperature, and humidity sensor. Humidity accuracy /-3% RH, pressure noise 0.12 Pa, temperature accuracy +/-0.5 C @ 25C""" def __init__(self): diff --git a/edg/parts/EnvironmentalSensor_Sensirion.py b/edg/parts/EnvironmentalSensor_Sensirion.py index 7535289f9..ae8c39d94 100644 --- a/edg/parts/EnvironmentalSensor_Sensirion.py +++ b/edg/parts/EnvironmentalSensor_Sensirion.py @@ -34,7 +34,7 @@ def contents(self) -> None: self.assign(self.actual_basic_part, False) -class Shtc3(EnvironmentalSensor, Block): +class Shtc3(TemperatureSensor, HumiditySensor, Block): """Humidity and temperature sensor with +/-2% RH and +/-0.2C""" def __init__(self): super().__init__() diff --git a/edg/parts/EnvironmentalSensor_Ti.py b/edg/parts/EnvironmentalSensor_Ti.py index 168644baf..543a53ecb 100644 --- a/edg/parts/EnvironmentalSensor_Ti.py +++ b/edg/parts/EnvironmentalSensor_Ti.py @@ -36,7 +36,7 @@ def contents(self) -> None: self.assign(self.actual_basic_part, False) -class Hdc1080(EnvironmentalSensor, Block): +class Hdc1080(TemperatureSensor, HumiditySensor, Block): """Temperature and humidity sensor with +/- 0.2C and +/- 2% RH typical accuracy""" def __init__(self): super().__init__() @@ -95,7 +95,7 @@ def generate(self) -> None: self.assign(self.actual_basic_part, False) -class Tmp1075n(EnvironmentalSensor, Block): +class Tmp1075n(TemperatureSensor, Block): """Temperature sensor with 0.25C typical accuracy""" @init_in_parent def __init__(self, addr_lsb: IntLike = 0): diff --git a/edg/parts/IoExpander_Pca9554.py b/edg/parts/IoExpander_Pca9554.py index 54cf9894c..4de5d3bcd 100644 --- a/edg/parts/IoExpander_Pca9554.py +++ b/edg/parts/IoExpander_Pca9554.py @@ -78,7 +78,7 @@ def generate(self) -> None: self.assign(self.lcsc_part, 'C86803') -class Pca9554(Interface, PinMappable): +class Pca9554(IoExpander, PinMappable): """8 bit I2C IO expander""" @init_in_parent def __init__(self, addr_lsb: IntLike = 0) -> None: diff --git a/edg/parts/IoExpander_Pcf8574.py b/edg/parts/IoExpander_Pcf8574.py index bebed2eef..7d2ed6bc7 100644 --- a/edg/parts/IoExpander_Pcf8574.py +++ b/edg/parts/IoExpander_Pcf8574.py @@ -78,7 +78,7 @@ def generate(self) -> None: self.assign(self.lcsc_part, "C86832") -class Pcf8574(Interface, PinMappable): +class Pcf8574(IoExpander, PinMappable): """8 bit I2C IO expander with 'quasi-bidirectional IOs'""" @init_in_parent def __init__(self, addr_lsb: IntLike = 0) -> None: diff --git a/edg/parts/Microphone_Sd18ob261.py b/edg/parts/Microphone_Sd18ob261.py index 714764398..c646208c5 100644 --- a/edg/parts/Microphone_Sd18ob261.py +++ b/edg/parts/Microphone_Sd18ob261.py @@ -44,7 +44,7 @@ def contents(self): self.assign(self.actual_basic_part, False) -class Sd18ob261(Interface, GeneratorBlock): +class Sd18ob261(Microphone, GeneratorBlock): """SD18OB261-060 PDM microphone, probably footprint-compatible with similar Knowles devices. Application circuit is not specified in the datasheet, this uses the one from SPH0655LM4H (single 0.1uF decap).""" diff --git a/edg/parts/SpeakerDriver_Analog.py b/edg/parts/SpeakerDriver_Analog.py index db6851397..d6d7f20d8 100644 --- a/edg/parts/SpeakerDriver_Analog.py +++ b/edg/parts/SpeakerDriver_Analog.py @@ -39,7 +39,7 @@ def contents(self): ) -class Lm4871(Interface, Block): +class Lm4871(SpeakerDriver, Block): def __init__(self): super().__init__() # TODO should be a SpeakerDriver abstract part @@ -128,7 +128,7 @@ def contents(self): self.assign(self.actual_basic_part, False) -class Tpa2005d1(Interface, GeneratorBlock): +class Tpa2005d1(SpeakerDriver, GeneratorBlock): """TPA2005D1 configured in single-ended input mode. Possible semi-pin-compatible with PAM8302AASCR (C113367), but which has internal resistor.""" @init_in_parent @@ -232,7 +232,7 @@ def contents(self): self.assign(self.actual_basic_part, False) -class Pam8302a(Interface): +class Pam8302a(SpeakerDriver, Block): """PAM8302A configured in single-ended input mode.""" @init_in_parent def __init__(self): diff --git a/edg/parts/SpeakerDriver_Max98357a.py b/edg/parts/SpeakerDriver_Max98357a.py index 964556913..91cc807ae 100644 --- a/edg/parts/SpeakerDriver_Max98357a.py +++ b/edg/parts/SpeakerDriver_Max98357a.py @@ -74,7 +74,7 @@ def generate(self): self.assign(self.lcsc_part, jlc_part) self.assign(self.actual_basic_part, False) -class Max98357a(Interface, Block): +class Max98357a(SpeakerDriver, Block): """MAX98357A I2S speaker driver with default gain.""" @init_in_parent def __init__(self):