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

Commit

Permalink
Implent RP2040 pinmux; Reference fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
iopapamanoglou committed Sep 12, 2024
1 parent 7ec66e3 commit cbe8a3c
Show file tree
Hide file tree
Showing 9 changed files with 689 additions and 393 deletions.
5 changes: 5 additions & 0 deletions src/faebryk/library/Battery.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


import faebryk.library._F as F
import faebryk.libs.library.L as L
from faebryk.core.module import Module
from faebryk.libs.units import Quantity

Expand All @@ -15,3 +16,7 @@ class Battery(Module):

def __preinit__(self) -> None:
self.power.voltage.merge(self.voltage)

@L.rt_field
def single_electric_reference(self):
return F.has_single_electric_reference_defined(self.power)
6 changes: 6 additions & 0 deletions src/faebryk/library/ElectricLogic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# This file is part of the faebryk project
# SPDX-License-Identifier: MIT

import sys
from abc import abstractmethod
from enum import Enum, auto
from typing import Iterable, Self
Expand Down Expand Up @@ -170,7 +171,12 @@ def connect_all_node_references(
F.Electrical.connect(*{r.lv for r in refs})
return next(iter(refs))

# TODO remove this workaround when we have lazy mifs
recursion_depth = sys.getrecursionlimit()
sys.setrecursionlimit(10000)
F.ElectricPower.connect(*refs)
sys.setrecursionlimit(recursion_depth)

return next(iter(refs))

@classmethod
Expand Down
111 changes: 111 additions & 0 deletions src/faebryk/library/Pinmux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# 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.core.moduleinterface import ModuleInterface
from faebryk.libs.library import L # noqa: F401
from faebryk.libs.util import ( # noqa: F401
KeyErrorAmbiguous,
KeyErrorNotFound,
NotNone,
find,
)

logger = logging.getLogger(__name__)


class Pinmux(Module):
"""
Generic Pinmux Base Class
"""

# ----------------------------------------
# modules, interfaces, parameters
# ----------------------------------------

# ----------------------------------------
# traits
# ----------------------------------------

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

# ------------------------------------
# parametrization
# ------------------------------------

self._function_matrix = self._get_matrix()
self._ios = self._get_ios()
self.configured: dict[F.Electrical, F.Electrical] = {}

def _get_ios(self) -> list[F.Electrical]:
raise NotImplementedError()

def _get_matrix(self) -> dict[F.Electrical, list[F.Electrical | None]]:
raise NotImplementedError()

def set_function(self, pin: int | F.Electrical, function: int | F.Electrical):
if isinstance(pin, int):
pin = self._ios[pin]
if isinstance(function, int):
function = NotNone(self._function_matrix[pin][function])

if pin in self.configured:
if self.configured[pin].is_connected_to(function):
return
raise ValueError(f"Pin {pin} already configured")
self.configured[pin] = function
pin.connect(function)

def enable(
self, bus: ModuleInterface, pins: list[int | F.Electrical] | None = None
):
signals = [
logic.signal
for logic in bus.get_children(
direct_only=False, types=F.ElectricLogic, include_root=True
)
]

candidates = {
signal: [
pin
for pin, functions in self._function_matrix.items()
if signal in functions
]
for signal in signals
}

if pins is not None:
pins = [self._ios[pin] if isinstance(pin, int) else pin for pin in pins]

for signal, pin_candidates in candidates.items():
if not pin_candidates:
# TODO maybe allow it
raise ValueError("This bus is not part of the pinmux")

pin_candidates = [
pin for pin in pin_candidates if pin not in self.configured
]

if not pin_candidates:
raise KeyErrorNotFound("No pin available for signal")

if len(pin_candidates) == 1:
self.set_function(pin_candidates[0], signal)
continue

if pins is None:
pin = pin_candidates[0]
else:
try:
pin = find(pin_candidates, lambda pin: pin in pins)
except KeyErrorAmbiguous as e:
pin = e.duplicates[0]

self.set_function(pin, signal)
4 changes: 4 additions & 0 deletions src/faebryk/library/PoweredLED.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ def __preinit__(self):
@L.rt_field
def can_bridge(self):
return F.can_bridge_defined(self.power.hv, self.power.lv)

@L.rt_field
def single_electric_reference(self):
return F.has_single_electric_reference_defined(self.power)
Loading

0 comments on commit cbe8a3c

Please sign in to comment.