Source code for jitxlib.symbols.diode.led

"""
LED and PhotoDiode symbols for JITX Standard Library

This module provides LED and PhotoDiode symbol definitions with arrow indicators.
"""

from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING, override

from ..arrow import Arrow, ArrowConfigurable
from .diode import DiodeConfig, DiodeSymbol

if TYPE_CHECKING:
    from ..context import SymbolStyleContext


# LED/PhotoDiode constants
DEF_LED_ARROW_MARGIN = 0.3
DEF_LED_ARROW_PITCH = 0.4
DEF_LED_ARROW_ANGLE = 30.0
DEF_PHOTODIODE_ARROW_ANGLE = 150.0


[docs] @dataclass class LEDConfig(DiodeConfig, ArrowConfigurable): """ Configuration for LED symbols Extends DiodeConfig with arrow parameters for light emission indicators. """ arrow_margin: float = DEF_LED_ARROW_MARGIN """Distance from diode body to arrows""" arrow_pitch: float = DEF_LED_ARROW_PITCH """Vertical spacing between arrows""" arrow_angle: float = DEF_LED_ARROW_ANGLE """Angle of outgoing light arrows in degrees"""
[docs] class LEDSymbol(DiodeSymbol[LEDConfig]): """ LED symbol with arrows indicating light emission. The LED symbol consists of a standard diode with two arrows pointing outward to indicate light emission. Pins: 'a' (anode), 'c' (cathode) """ arrows: tuple[Arrow, Arrow] @override def _symbol_style_config( self, context: SymbolStyleContext | None = None ) -> LEDConfig: """Symbol style config for LED symbol.""" if context is None: return LEDConfig() return context.led_config @override def _build_diode_glyphs(self) -> None: """Build LED glyphs including arrows.""" super()._build_diode_glyphs() self._build_arrows() def _build_arrows(self) -> None: """Build the light emission arrows.""" bw2 = self.body_width / 2.0 h = self._get_body_height() / 2.0 angle = self.arrow_angle arrow_config = self.config.get_arrow_config() if arrow_config is None: from ..arrow import ArrowConfig # Use diode's line width for arrows to ensure consistency arrow_config = ArrowConfig(line_width=self.line_width) shaft = arrow_config.shaft_length # Position arrows to the left of the body # X position based on shaft length (not margin) x_off = -(bw2 + 1.2 * shaft) # Y positions: first arrow at h/-2, second arrow offset by y_adj y_off = h / -2.0 y_adj = 1.5 * y_off self.arrows = ( Arrow((x_off, y_off), angle, arrow_config), Arrow((x_off, y_off + y_adj), angle, arrow_config), ) @property def arrow_margin(self) -> float: """See :attr:`~.LEDConfig.arrow_margin`.""" return self.config.arrow_margin @property def arrow_pitch(self) -> float: """See :attr:`~.LEDConfig.arrow_pitch`.""" return self.config.arrow_pitch @property def arrow_angle(self) -> float: """See :attr:`~.LEDConfig.arrow_angle`.""" return self.config.arrow_angle
[docs] @dataclass class PhotoDiodeConfig(DiodeConfig, ArrowConfigurable): """ Configuration for PhotoDiode symbols Extends DiodeConfig with arrow parameters for light absorption indicators. """ arrow_margin: float = DEF_LED_ARROW_MARGIN """Distance from diode body to arrows""" arrow_pitch: float = DEF_LED_ARROW_PITCH """Vertical spacing between arrows""" arrow_angle: float = DEF_PHOTODIODE_ARROW_ANGLE """Angle of incoming light arrows in degrees (pointing toward diode)"""
[docs] class PhotoDiodeSymbol(DiodeSymbol[PhotoDiodeConfig]): """ PhotoDiode symbol with arrows indicating light absorption. The PhotoDiode symbol consists of a standard diode with two arrows pointing inward to indicate light absorption. Pins: 'a' (anode), 'c' (cathode) """ arrows: tuple[Arrow, Arrow] @override def _symbol_style_config( self, context: SymbolStyleContext | None = None ) -> PhotoDiodeConfig: """Symbol style config for PhotoDiode symbol.""" if context is None: return PhotoDiodeConfig() return context.photo_diode_config @override def _build_diode_glyphs(self) -> None: """Build PhotoDiode glyphs including arrows.""" super()._build_diode_glyphs() self._build_arrows() def _build_arrows(self) -> None: """Build the light absorption arrows.""" bw2 = self.body_width / 2.0 h = self._get_body_height() / 2.0 angle = self.arrow_angle arrow_config = self.config.get_arrow_config() if arrow_config is None: from ..arrow import ArrowConfig # Use diode's line width for arrows to ensure consistency arrow_config = ArrowConfig(line_width=self.line_width) # Position arrows to the left of the body, pointing inward x_off = -(1.2 * bw2) # Y positions: arrows positioned symmetrically with adjustment y_off = h / -2.0 y_adj = 0.3 * y_off self.arrows = ( Arrow((x_off, y_adj + y_off), angle, arrow_config), Arrow((x_off, y_adj - y_off), angle, arrow_config), ) @property def arrow_margin(self) -> float: """See :attr:`~.PhotoDiodeConfig.arrow_margin`.""" return self.config.arrow_margin @property def arrow_pitch(self) -> float: """See :attr:`~.PhotoDiodeConfig.arrow_pitch`.""" return self.config.arrow_pitch @property def arrow_angle(self) -> float: """See :attr:`~.PhotoDiodeConfig.arrow_angle`.""" return self.config.arrow_angle