Last active
November 8, 2025 21:38
-
-
Save raspberrypisig/e378e50add20431747f30dce6219d67c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| OUT = "output" | |
| IN = "input" | |
| HIGH = 1 | |
| LOW = 0 | |
| PULL_UP = "pull_up" | |
| PULL_DOWN = "pull_down" | |
| PULL_NONE = "pull_none" | |
| # Define a Pin "object" using a dictionary | |
| def create_pin(pin_number, mode, pull=PULL_NONE, initial_level=LOW): | |
| return { | |
| "number": pin_number, | |
| "mode": mode, | |
| "pull": pull, | |
| "initial_level": initial_level, | |
| } | |
| # Define functions to manipulate pins | |
| def pin_high(pin): | |
| # Simulate setting the pin high | |
| pass | |
| def pin_low(pin): | |
| # Simulate setting the pin low | |
| pass | |
| def pin_value(pin, level=None): | |
| # Simulate reading or setting the pin value | |
| pass | |
| def pin_cleanup(pin): | |
| # Simulate cleaning up the pin | |
| pass | |
| # Represent a pin as a string | |
| def pin_repr(pin): | |
| return "<Pin(GPIO{}, mode='{}')>".format(pin["number"], pin["mode"]) | |
| # Cleanup function | |
| def cleanup(pin_number=None): | |
| # Simulate cleanup logic | |
| pass | |
| # Expose constants as a dictionary | |
| CONSTANTS = { | |
| "OUT": OUT, | |
| "IN": IN, | |
| "HIGH": HIGH, | |
| "LOW": LOW, | |
| "PULL_UP": PULL_UP, | |
| "PULL_DOWN": PULL_DOWN, | |
| "PULL_NONE": PULL_NONE, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # gpio.star: A Starlark Module for GPIO Control on ESP32 | |
| # | |
| # This module provides a high-level, Pythonic interface for General Purpose | |
| # Input/Output (GPIO) pins. It acts as a user-friendly wrapper around | |
| # native functions implemented in Rust and exposed via an FFI boundary. | |
| # | |
| # The Rust host is responsible for providing the following native functions | |
| # in the Starlark environment before this module is loaded: | |
| # | |
| # - _native_setup_output(pin_number, initial_level) -> opaque_pin_handle | |
| # Configures a pin as an output and returns a handle. | |
| # | |
| # - _native_setup_input(pin_number, pull) -> opaque_pin_handle | |
| # Configures a pin as an input with a specific pull resistor and returns a handle. | |
| # | |
| # - _native_set_level(opaque_pin_handle, level) | |
| # Sets the logical level of an output pin. | |
| # | |
| # - _native_get_level(opaque_pin_handle) -> int | |
| # Reads the logical level of an input pin. Returns HIGH (1) or LOW (0). | |
| # | |
| # - _native_cleanup(pin_number) | |
| # De-initializes a pin, returning it to a safe, high-impedance state. | |
| # | |
| # --- Module Constants --- | |
| # Pin modes | |
| OUT = "output" | |
| IN = "input" | |
| # Pin levels | |
| HIGH = 1 | |
| LOW = 0 | |
| # Pull resistor configurations | |
| PULL_UP = "pull_up" | |
| PULL_DOWN = "pull_down" | |
| PULL_NONE = "pull_none" | |
| class Pin: | |
| """Represents a single physical GPIO pin.""" | |
| def __init__(self, pin_number, mode, pull=PULL_NONE, initial_level=LOW): | |
| """ | |
| Initializes and configures a GPIO pin. | |
| This constructor calls the underlying native Rust functions to set up | |
| the hardware pin according to the specified parameters. | |
| Args: | |
| pin_number (int): The GPIO number (e.g., 13 for GPIO13). | |
| mode (str): The mode of the pin, either OUT or IN. | |
| pull (str, optional): The pull resistor setting for input pins. | |
| Can be PULL_UP, PULL_DOWN, or PULL_NONE. | |
| Defaults to PULL_NONE. | |
| initial_level (int, optional): The initial level for output pins. | |
| Can be HIGH or LOW. Defaults to LOW. | |
| """ | |
| if not type(pin_number) == "int": | |
| fail("pin_number must be an integer.") | |
| self._number = pin_number | |
| self._mode = mode | |
| self._native_handle = None # Stores the opaque object from Rust | |
| if mode == OUT: | |
| if initial_level != HIGH and initial_level != LOW: | |
| fail("initial_level for an output pin must be HIGH or LOW.") | |
| # Call the native Rust function to configure the pin as an output. | |
| # The returned handle is stored for future operations on this pin. | |
| self._native_handle = _native_setup_output(pin_number, initial_level) | |
| elif mode == IN: | |
| # Call the native Rust function to configure the pin as an input. | |
| self._native_handle = _native_setup_input(pin_number, pull) | |
| else: | |
| fail("Unsupported pin mode: '{}'. Use OUT or IN.".format(mode)) | |
| def high(self): | |
| """Sets the output pin level to HIGH. Fails if the pin is not an output.""" | |
| if self._mode != OUT: | |
| fail("Cannot set level on an input pin.") | |
| _native_set_level(self._native_handle, HIGH) | |
| def low(self): | |
| """Sets the output pin level to LOW. Fails if the pin is not an output.""" | |
| if self._mode != OUT: | |
| fail("Cannot set level on an input pin.") | |
| _native_set_level(self._native_handle, LOW) | |
| def value(self, level=None): | |
| """ | |
| Gets or sets the value of the pin. | |
| - If `level` is provided, sets the pin's level (for output pins). | |
| - If `level` is not provided, returns the pin's level (for input pins). | |
| Args: | |
| level (int, optional): The level to set (HIGH or LOW). | |
| Returns: | |
| int or None: The current level (HIGH or LOW) if getting, or None if setting. | |
| """ | |
| if level == None: | |
| # Getting the value (for input pins) | |
| if self._mode != IN: | |
| fail("Can only read value from an input pin. Call high() or low() to set an output pin.") | |
| return _native_get_level(self._native_handle) | |
| else: | |
| # Setting the value (for output pins) | |
| if self._mode != OUT: | |
| fail("Cannot set value on an input pin.") | |
| if level != HIGH and level != LOW: | |
| fail("Value must be HIGH or LOW.") | |
| _native_set_level(self._native_handle, level) | |
| def cleanup(self): | |
| """De-initializes the pin, returning it to a safe state.""" | |
| _native_cleanup(self._number) | |
| self._native_handle = None # Invalidate the handle | |
| def __repr__(self): | |
| """Provides a string representation of the Pin object.""" | |
| return "<Pin(GPIO{}, mode='{}')>".format(self._number, self._mode) | |
| def cleanup(pin_number=None): | |
| """ | |
| De-initializes one or all pins. | |
| If a pin number is provided, only that pin is cleaned up. | |
| If no pin number is provided, the native cleanup function is expected | |
| to handle all pins (if the underlying implementation supports this). | |
| """ | |
| if pin_number != None: | |
| _native_cleanup(pin_number) | |
| else: | |
| # A pin_number of -1 could be a convention to tell the native | |
| # layer to clean up all pins it has track of. | |
| _native_cleanup(-1) | |
| # --- Public API Export --- | |
| # This dictionary defines what symbols are available when a user script | |
| # executes `load("gpio.star", "gpio")`. | |
| PIN = Pin | |
| # Expose constants for easy access, e.g., `gpio.OUT`. | |
| CONSTANTS = { | |
| "OUT": OUT, | |
| "IN": IN, | |
| "HIGH": HIGH, | |
| "LOW": LOW, | |
| "PULL_UP": PULL_UP, | |
| "PULL_DOWN": PULL_DOWN, | |
| "PULL_NONE": PULL_NONE, | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # gpio.star | |
| OUT = "output" | |
| IN = "input" | |
| HIGH = 1 | |
| LOW = 0 | |
| PULL_UP = "pull_up" | |
| PULL_DOWN = "pull_down" | |
| PULL_NONE = "pull_none" | |
| class Pin: | |
| def __init__(self, pin_number, mode, pull=PULL_NONE, initial_level=LOW): | |
| self._number = pin_number | |
| self._mode = mode | |
| pass | |
| def high(self): | |
| pass | |
| def low(self): | |
| pass | |
| def value(self, level=None): | |
| pass | |
| def cleanup(self): | |
| pass | |
| def __repr__(self): | |
| return "<Pin(GPIO{}, mode='{}')>".format(self._number, self._mode) | |
| def cleanup(pin_number=None): | |
| pass | |
| PIN = Pin | |
| CONSTANTS = { | |
| "OUT": OUT, | |
| "IN": IN, | |
| "HIGH": HIGH, | |
| "LOW": LOW, | |
| "PULL_UP": PULL_UP, | |
| "PULL_DOWN": PULL_DOWN, | |
| "PULL_NONE": PULL_NONE, | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment