0
mirror of https://github.com/Architeuthis-Flux/Jumperless.git synced 2026-07-05 04:50:07 +00:00
Files

1709 lines
46 KiB
Python

"""
Type stub for Jumperless MicroPython Module
============================================
This file provides type hints and autocomplete support for the jumperless module.
All functions and constants are available globally without needing to import.
"""
from typing import Union, Tuple, Dict, List, Optional
# ============================================================================
# Custom Types
# ============================================================================
class GPIOState:
"""GPIO state: HIGH, LOW, or FLOATING"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
class GPIODirection:
"""GPIO direction: INPUT or OUTPUT"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
class GPIOPull:
"""GPIO pull configuration: PULLUP, PULLDOWN, or NONE"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
class ConnectionState:
"""Connection state: CONNECTED or DISCONNECTED"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
class ProbeButton:
"""Probe button state: CONNECT, REMOVE, or NONE"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
class ProbePad:
"""Probe pad: numbered pads (1-60) or special pads"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
def __eq__(self, other) -> bool: ...
def __ne__(self, other) -> bool: ...
def __add__(self, other) -> str: ...
class Node:
"""Node object for hardware connections"""
def __bool__(self) -> bool: ...
def __int__(self) -> int: ...
def __float__(self) -> float: ...
def __str__(self) -> str: ...
def __eq__(self, other) -> bool: ...
def __ne__(self, other) -> bool: ...
# Type aliases for function parameters
NodeRef = Union[int, str, Node]
DACChannel = Union[int, NodeRef]
ADCChannel = int
INASensor = int
GPIOPin = Union[int, NodeRef]
PWMPin = int
# ============================================================================
# DAC Functions
# ============================================================================
def dac_set(channel: DACChannel, voltage: float, save: bool = True) -> None:
"""Set DAC output voltage (-8.0 to 8.0V)
Args:
channel: 0-3, or DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL
voltage: Output voltage in volts (-8.0 to 8.0)
save: Save to config file (default: True)
"""
...
def dac_get(channel: DACChannel) -> float:
"""Get DAC output voltage
Args:
channel: 0-3, or DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL
Returns:
Current voltage setting in volts
"""
...
def set_dac(channel: DACChannel, voltage: float, save: bool = True) -> None:
"""Alias for dac_set()"""
...
def get_dac(channel: DACChannel) -> float:
"""Alias for dac_get()"""
...
# ============================================================================
# ADC Functions
# ============================================================================
def adc_get(channel: ADCChannel) -> float:
"""Read ADC input voltage
Args:
channel: 0-4 (0-3: 8V range, 4: 5V range)
Returns:
Measured voltage in volts
"""
...
def get_adc(channel: ADCChannel) -> float:
"""Alias for adc_get()"""
...
# ============================================================================
# INA Current/Power Monitor Functions
# ============================================================================
def ina_get_current(sensor: INASensor) -> float:
"""Read current in amperes"""
...
def ina_get_voltage(sensor: INASensor) -> float:
"""Read shunt voltage"""
...
def ina_get_bus_voltage(sensor: INASensor) -> float:
"""Read bus voltage"""
...
def ina_get_power(sensor: INASensor) -> float:
"""Read power in watts"""
...
def get_ina_current(sensor: INASensor) -> float:
"""Alias for ina_get_current()"""
...
def get_ina_voltage(sensor: INASensor) -> float:
"""Alias for ina_get_voltage()"""
...
def get_ina_bus_voltage(sensor: INASensor) -> float:
"""Alias for ina_get_bus_voltage()"""
...
def get_ina_power(sensor: INASensor) -> float:
"""Alias for ina_get_power()"""
...
def get_current(sensor: INASensor) -> float:
"""Alias for ina_get_current()"""
...
def get_voltage(sensor: INASensor) -> float:
"""Alias for ina_get_voltage()"""
...
def get_bus_voltage(sensor: INASensor) -> float:
"""Alias for ina_get_bus_voltage()"""
...
def get_power(sensor: INASensor) -> float:
"""Alias for ina_get_power()"""
...
# ============================================================================
# GPIO Functions
# ============================================================================
def gpio_set(pin: GPIOPin, value: Union[bool, int, GPIOState]) -> None:
"""Set GPIO pin state (HIGH/LOW)"""
...
def gpio_get(pin: GPIOPin) -> GPIOState:
"""Read GPIO pin state (returns HIGH/LOW/FLOATING)"""
...
def gpio_set_dir(pin: GPIOPin, direction: Union[bool, int, str, GPIODirection]) -> None:
"""Set GPIO pin direction (True/OUTPUT or False/INPUT)"""
...
def gpio_get_dir(pin: GPIOPin) -> GPIODirection:
"""Get GPIO pin direction (returns INPUT or OUTPUT)"""
...
def gpio_set_pull(pin: GPIOPin, pull: Union[int, str, GPIOPull]) -> None:
"""Set GPIO pull resistor (1/PULLUP, -1/PULLDOWN, 0/NONE)"""
...
def gpio_get_pull(pin: GPIOPin) -> GPIOPull:
"""Get GPIO pull resistor (returns PULLUP, PULLDOWN, or NONE)"""
...
# GPIO Aliases
def set_gpio(pin: GPIOPin, value: Union[bool, int, GPIOState]) -> None:
"""Alias for gpio_set()"""
...
def get_gpio(pin: GPIOPin) -> GPIOState:
"""Alias for gpio_get()"""
...
def set_gpio_dir(pin: GPIOPin, direction: Union[bool, int, str, GPIODirection]) -> None:
"""Alias for gpio_set_dir()"""
...
def get_gpio_dir(pin: GPIOPin) -> GPIODirection:
"""Alias for gpio_get_dir()"""
...
def set_gpio_pull(pin: GPIOPin, pull: Union[int, str, GPIOPull]) -> None:
"""Alias for gpio_set_pull()"""
...
def get_gpio_pull(pin: GPIOPin) -> GPIOPull:
"""Alias for gpio_get_pull()"""
...
def gpio_set_read_floating(pin: GPIOPin, enable: bool) -> None:
"""Set whether GPIO reads as floating when disconnected"""
...
def gpio_get_read_floating(pin: GPIOPin) -> bool:
"""Get whether GPIO reads as floating when disconnected"""
...
def set_gpio_read_floating(pin: GPIOPin, enable: bool) -> None:
"""Alias for gpio_set_read_floating()"""
...
def get_gpio_read_floating(pin: GPIOPin) -> bool:
"""Alias for gpio_get_read_floating()"""
...
def gpio_claim_pin(pin: GPIOPin) -> None:
"""Claim pin for timing-critical use (e.g. NeoPixels); release when done"""
...
def gpio_release_pin(pin: GPIOPin) -> None:
"""Release a previously claimed pin"""
...
def gpio_release_all_pins() -> None:
"""Release all claimed GPIO pins"""
...
# ============================================================================
# PWM Functions
# ============================================================================
def pwm(pin: PWMPin, frequency: float = 1000.0, duty_cycle: float = 0.5) -> None:
"""Setup PWM on GPIO pin (pins 1-8 only)
Args:
pin: GPIO pin 1-8
frequency: 0.001Hz to 62.5MHz (default 1000Hz)
duty_cycle: 0.0 to 1.0 (default 0.5 = 50%)
"""
...
def pwm_set_duty_cycle(pin: PWMPin, duty_cycle: float) -> None:
"""Set PWM duty cycle (0.0 to 1.0)"""
...
def pwm_set_frequency(pin: PWMPin, frequency: float) -> None:
"""Set PWM frequency (0.001Hz to 62.5MHz)"""
...
def pwm_stop(pin: PWMPin) -> None:
"""Stop PWM on pin"""
...
# PWM Aliases
def set_pwm(pin: PWMPin, frequency: float = 1000.0, duty_cycle: float = 0.5) -> None:
"""Alias for pwm()"""
...
def set_pwm_duty_cycle(pin: PWMPin, duty_cycle: float) -> None:
"""Alias for pwm_set_duty_cycle()"""
...
def set_pwm_frequency(pin: PWMPin, frequency: float) -> None:
"""Alias for pwm_set_frequency()"""
...
def stop_pwm(pin: PWMPin) -> None:
"""Alias for pwm_stop()"""
...
# ============================================================================
# Waveform Generator Functions
# ============================================================================
def wavegen_set_output(channel: DACChannel) -> None:
"""Set wavegen output: DAC0, DAC1, TOP_RAIL, or BOTTOM_RAIL"""
...
def wavegen_set_freq(hz: float) -> None:
"""Set frequency (0.0001 to 10000 Hz)"""
...
def wavegen_set_wave(shape: Union[int, str]) -> None:
"""Set waveform shape: SINE, TRIANGLE, SAWTOOTH, SQUARE"""
...
def wavegen_set_sweep(start_hz: float, end_hz: float, seconds: float) -> None:
"""Configure linear frequency sweep"""
...
def wavegen_set_amplitude(vpp: float) -> None:
"""Set amplitude (0.0 to 16.0 Vpp)"""
...
def wavegen_set_offset(v: float) -> None:
"""Set DC offset (-8.0 to +8.0 V)"""
...
def wavegen_start(run: bool = True) -> None:
"""Start waveform generation"""
...
def wavegen_stop() -> None:
"""Stop waveform generation"""
...
def wavegen_get_output() -> int:
"""Get current output channel"""
...
def wavegen_get_freq() -> float:
"""Get current frequency"""
...
def wavegen_get_wave() -> int:
"""Get current waveform"""
...
def wavegen_get_amplitude() -> float:
"""Get current amplitude"""
...
def wavegen_get_offset() -> float:
"""Get current offset"""
...
def wavegen_is_running() -> bool:
"""Check if wavegen is active"""
...
# Wavegen Aliases
def set_wavegen_output(channel: DACChannel) -> None:
"""Alias for wavegen_set_output()"""
...
def set_wavegen_freq(hz: float) -> None:
"""Alias for wavegen_set_freq()"""
...
def set_wavegen_wave(shape: Union[int, str]) -> None:
"""Alias for wavegen_set_wave()"""
...
def set_wavegen_sweep(start_hz: float, end_hz: float, seconds: float) -> None:
"""Alias for wavegen_set_sweep()"""
...
def set_wavegen_amplitude(vpp: float) -> None:
"""Alias for wavegen_set_amplitude()"""
...
def set_wavegen_offset(v: float) -> None:
"""Alias for wavegen_set_offset()"""
...
def start_wavegen(run: bool = True) -> None:
"""Alias for wavegen_start()"""
...
def stop_wavegen() -> None:
"""Alias for wavegen_stop()"""
...
def get_wavegen_output() -> int:
"""Alias for wavegen_get_output()"""
...
def get_wavegen_freq() -> float:
"""Alias for wavegen_get_freq()"""
...
def get_wavegen_wave() -> int:
"""Alias for wavegen_get_wave()"""
...
def get_wavegen_amplitude() -> float:
"""Alias for wavegen_get_amplitude()"""
...
def get_wavegen_offset() -> float:
"""Alias for wavegen_get_offset()"""
...
# ============================================================================
# Node Connection Functions
# ============================================================================
def node(name_or_id: Union[str, int, Node]) -> Node:
"""Create a node object from string name or integer ID"""
...
def connect(node1: NodeRef, node2: NodeRef, duplicates: int = -1) -> None:
"""Connect two nodes
Args:
node1, node2: Nodes to connect (int, string, or Node constant)
duplicates: Duplicate connection behavior (default: -1)
-1: Just add the connection (standard behavior, no duplicate management)
0: Force exactly 0 duplicates (remove any existing duplicates)
1+: Force exactly N duplicates (add/remove connections to reach count)
Example:
connect(1, 5) # Add connection without managing duplicates
connect(1, 5, duplicates=0) # Ensure no duplicate paths exist
connect(1, 5, duplicates=2) # Force exactly 2 duplicate paths
"""
...
def disconnect(node1: NodeRef, node2: NodeRef) -> None:
"""Disconnect two nodes (set node2 to -1 to disconnect all from node1)"""
...
def fast_connect(node1: NodeRef, node2: NodeRef, duplicates: int = -1) -> None:
"""Connect two nodes, skipping LED computation
This function adds connections without updating LED state. Useful when making
many connections at once - you can defer LED updates until all connections are done.
Note: This is not much faster overall, it just skips LED updates for bulk operations.
Args:
node1, node2: Nodes to connect (int, string, or Node constant)
duplicates: Same behavior as connect() (default: -1)
Example:
# Make multiple connections without LED updates
for i in range(10):
fast_connect(i, i+10)
# LEDs update automatically after loop completes
"""
...
def fast_disconnect(node1: NodeRef, node2: NodeRef) -> None:
"""Disconnect two nodes, skipping LED computation
Same LED-skipping behavior as fast_connect(). Useful for bulk disconnections.
Args:
node1, node2: Nodes to disconnect
"""
...
def nodes_clear() -> None:
"""Clear all connections"""
...
def is_connected(node1: NodeRef, node2: NodeRef) -> ConnectionState:
"""Check if nodes are connected (returns CONNECTED or DISCONNECTED)"""
...
def nodes_save(slot: int = -1) -> int:
"""Save connections to slot (default: current slot)
Returns:
Slot number that was saved to
"""
...
def nodes_has_changes() -> bool:
"""Check if there are unsaved changes"""
...
# ============================================================================
# Net Information Functions
# ============================================================================
def get_net_name(netNum: int) -> Optional[str]:
"""Get the name of a net"""
...
def set_net_name(netNum: int, name: Optional[str]) -> None:
"""Set a custom net name (pass None or empty string to reset)"""
...
def get_net_color(netNum: int) -> int:
"""Get net color as 0xRRGGBB hex value"""
...
def get_net_color_name(netNum: int) -> str:
"""Get net color as human-readable string"""
...
def set_net_color(netNum: int, color: Union[str, int], r: int = None, g: int = None, b: int = None) -> bool:
"""Set net color by name, hex string, or RGB values
Args:
netNum: Net number
color: Color name ("red", "blue"), hex string ("#FF0000"), or RGB int
r, g, b: Optional RGB values (0-255)
Returns:
True on success, False on failure
"""
...
def get_num_nets() -> int:
"""Get number of active nets"""
...
def get_num_bridges() -> int:
"""Get number of bridges"""
...
def get_net_nodes(netNum: int) -> str:
"""Get comma-separated list of nodes in a net"""
...
def get_bridge(bridgeIdx: int) -> Tuple[int, int, int]:
"""Get bridge info as tuple (node1, node2, duplicates)"""
...
def get_net_info(netNum: int) -> Dict[str, Union[str, int]]:
"""Get full net info as dict with keys: name, number, color, color_name, nodes"""
...
# Net Info Aliases
def net_name(netNum: int) -> Optional[str]:
"""Alias for get_net_name()"""
...
def net_color(netNum: int) -> int:
"""Alias for get_net_color()"""
...
def net_info(netNum: int) -> Dict[str, Union[str, int]]:
"""Alias for get_net_info()"""
...
def get_all_nets() -> List[Dict[str, Union[str, int]]]:
"""Get list of all nets with full info"""
...
def set_net_color_hsv(netNum: int, h: float, s: float = -1, v: float = -1) -> bool:
"""Set net color using HSV color space (auto-detects 0.0-1.0 vs 0-255 range)
Args:
netNum: The net number
h: Hue value (0.0-1.0 or 0-255, auto-detected based on value)
s: Saturation (0.0-1.0 or 0-255, default: max saturation if not provided)
v: Value/brightness (0.0-1.0 or 0-255, default: 32 for reasonable brightness)
Returns:
True on success, False on failure
Example:
set_net_color_hsv(0, 0.0) # Red at default brightness
set_net_color_hsv(1, 0.33) # Green
set_net_color_hsv(2, 0.66, 1.0, 1.0) # Blue at max brightness
"""
...
# ============================================================================
# Path Query Functions
# ============================================================================
def get_num_paths(include_duplicates: bool = True) -> int:
"""Get the number of routing paths
Args:
include_duplicates: If True, count all paths. If False, count only primary paths.
Returns:
Number of paths
Example:
total = get_num_paths() # All paths including duplicates
primary = get_num_paths(False) # Only primary paths
"""
...
def get_path_info(path_idx: int) -> Optional[Dict]:
"""Get detailed routing path information
Args:
path_idx: Path index (0 to get_num_paths()-1)
Returns:
Dict with keys: node1, node2, net, chips, x, y, duplicate
Returns None if index is invalid
Example:
path = get_path_info(0)
if path:
print(f"Path from {path['node1']} to {path['node2']}")
"""
...
def get_all_paths() -> List[Dict]:
"""Get all routing paths as a list of dicts
Returns:
List of path dicts, same format as get_path_info()
Example:
for path in get_all_paths():
print(f"{path['node1']} -> {path['node2']}")
"""
...
def get_path_between(node1: int, node2: int) -> Optional[Dict]:
"""Query the routing path between two specific nodes
Args:
node1, node2: Nodes to query path between
Returns:
Path dict if found, None otherwise
Example:
path = get_path_between(1, 5)
if path:
print(f"Route uses chips: {path['chips']}")
"""
...
# ============================================================================
# Slot Management
# ============================================================================
def switch_slot(slot: int) -> int:
"""Switch to a different slot (0-7)
Returns:
Previous slot number
"""
...
CURRENT_SLOT: int
"""Current active slot number"""
# ============================================================================
# Context Control
# ============================================================================
def context_toggle() -> None:
"""Toggle connection context between 'global' and 'python' modes"""
...
def context_get() -> str:
"""Get current context name ('global' or 'python')"""
...
# ============================================================================
# OLED Display Functions
# ============================================================================
def oled_print(text: Union[str, int, float, Node, GPIOState, ConnectionState], size: int = 2) -> None:
"""Display text on OLED (size: 1 or 2)"""
...
def oled_clear() -> None:
"""Clear OLED display"""
...
def oled_show() -> None:
"""Refresh OLED display"""
...
def oled_connect() -> None:
"""Connect I2C lines to OLED"""
...
def oled_disconnect() -> None:
"""Disconnect I2C lines from OLED"""
...
def oled_set_text_size(size: int) -> bool:
"""Set the default text size for oled_print()
Args:
size: Text size (0=small multiline scrolling, 1=normal, 2=large centered)
Returns:
True if successful, False if invalid size
"""
...
def oled_get_text_size() -> int:
"""Get the current default text size
Returns:
Current default text size (0-2)
"""
...
def oled_copy_print(enable: bool) -> None:
"""Enable/disable copying MicroPython print() output to OLED
When enabled, all print() statements will also appear on the OLED
in small scrolling text mode.
Args:
enable: True to enable copy mode, False to disable
"""
...
def oled_get_fonts() -> list[str]:
"""Get list of available font families
Returns:
List of font family names that can be used with oled_set_font()
"""
...
def oled_set_font(font_name: str) -> bool:
"""Set the current font family
Args:
font_name: Name of font family (e.g., "Eurostile", "Jokerman", "Comic Sans")
Returns:
True if font was set successfully, False if font not found
"""
...
def oled_get_current_font() -> str:
"""Get the name of the currently active font
Returns:
Current font family name
"""
...
def oled_load_bitmap(filepath: str) -> bool:
"""Load a bitmap file into the internal bitmap buffer
Supports raw bitmap files and custom format with header.
Common sizes: 128x32 (512 bytes), 128x64 (1024 bytes)
Args:
filepath: Path to bitmap file
Returns:
True if loaded successfully, False on error
"""
...
def oled_display_bitmap(x: int, y: int, width: int, height: int, data: Optional[bytes] = None) -> bool:
"""Display a bitmap on the OLED
If data is provided, displays that bitmap directly.
If data is None, displays the previously loaded bitmap from oled_load_bitmap().
Args:
x: X position on display
y: Y position on display
width: Bitmap width in pixels (ignored if using loaded bitmap)
height: Bitmap height in pixels (ignored if using loaded bitmap)
data: Optional bitmap data as bytes (1 bit per pixel, packed)
Returns:
True if displayed successfully, False on error
"""
...
def oled_show_bitmap_file(filepath: str, x: int, y: int) -> bool:
"""Load and display a bitmap file in one call
Convenience function that combines oled_load_bitmap() and oled_display_bitmap().
Args:
filepath: Path to bitmap file
x: X position on display
y: Y position on display
Returns:
True if successful, False on error
"""
...
def oled_get_framebuffer() -> bytes:
"""Get the current OLED framebuffer as bytes
Returns a copy of the framebuffer that can be modified and
written back with oled_set_framebuffer().
Returns:
Framebuffer data as bytes (1 bit per pixel, packed)
Size depends on display: 128x32 = 512 bytes, 128x64 = 1024 bytes
"""
...
def oled_set_framebuffer(data: Union[bytes, bytearray]) -> bool:
"""Set the entire OLED framebuffer from bytes
Allows direct manipulation of the display buffer.
Data must be the correct size for the display.
Args:
data: Framebuffer data (1 bit per pixel, packed)
Must be 512 bytes for 128x32 or 1024 bytes for 128x64
Returns:
True if successful, False if wrong size
"""
...
def oled_get_framebuffer_size() -> tuple[int, int, int]:
"""Get the framebuffer dimensions
Returns:
Tuple of (width, height, buffer_size_in_bytes)
"""
...
def oled_set_pixel(x: int, y: int, color: int) -> bool:
"""Set a single pixel on the OLED
Note: Call oled_show() to make the change visible.
Args:
x: X coordinate (0 to width-1)
y: Y coordinate (0 to height-1)
color: Pixel color (0=black/off, 1=white/on)
Returns:
True if successful, False if OLED not connected
"""
...
def oled_get_pixel(x: int, y: int) -> int:
"""Get the value of a single pixel
Args:
x: X coordinate (0 to width-1)
y: Y coordinate (0 to height-1)
Returns:
Pixel color (0=black/off, 1=white/on, -1=error)
"""
...
# ============================================================================
# OLED GUI (retained screens)
# ============================================================================
def oled_screen() -> int:
"""Create a new retained screen; returns a screen handle (>=1) or 0."""
...
def oled_screen_free(screen: int) -> None: ...
def oled_screen_clear(screen: int) -> None: ...
def oled_screen_show(screen: int) -> bool:
"""Make the screen the active display (starts live rendering)."""
...
def oled_screen_hide() -> None: ...
def oled_screen_reset() -> None:
"""Free every retained screen and blank the panel (call at script start to discard prior screens)."""
...
def oled_add_text(screen: int, text: str, x: int = 0, y: int = 0, font: str = "Pragmatism",
size: int = 8, halign: int = -1, valign: int = -1, z: int = 0) -> int:
"""Add a text element. text may contain {token} templates. Returns an element handle."""
...
def oled_add_shape(screen: int, kind: int = 1, x: int = 0, y: int = 0, w: int = 0, h: int = 0,
filled: int = 0, z: int = 0) -> int:
"""Add a shape (0=line, 1=rect outline, 2=filled rect). Returns an element handle."""
...
def oled_set(elem: int, prop: str, value: Union[int, str]) -> bool:
"""Set an element property: text/font (str) or x/y/w/h/z/size/visible/anchor/halign/valign/shape/filled (int)."""
...
def oled_set_var(name: str, value: Union[int, float, str]) -> None:
"""Push a live value into the variable registry, referenced as {name} in text templates."""
...
def oled_screen_save(screen: int, name: str) -> bool:
"""Save the screen to /screens/<name>.json."""
...
def oled_screen_load(name: str) -> int:
"""Load /screens/<name>.json into a new screen; returns its handle or 0."""
...
ALIGN_LEFT: int
ALIGN_CENTER: int
ALIGN_RIGHT: int
ALIGN_TOP: int
ALIGN_MIDDLE: int
ALIGN_BOTTOM: int
SHAPE_LINE: int
SHAPE_RECT: int
SHAPE_FILLED_RECT: int
# NOTE: The object-oriented OLED layout API (Screen, Text, Shape, Line, Rect,
# load_screen) is NOT part of the native `jumperless` module - it is pure-Python
# and lives in `oledgui.py`, built on top of the flat oled_screen()/oled_add_*()
# functions above. Import it explicitly: from oledgui import Screen, Text, ...
# (Declaring those classes here shadowed the real oledgui ones with a less
# precise signature, so `scr.add(Text(...))` was typed as `Text | Shape`.)
# ============================================================================
# Probe Functions
# ============================================================================
def probe_read(blocking: bool = True) -> ProbePad:
"""Read probe pad (default: blocking until touched)"""
...
def read_probe(blocking: bool = True) -> ProbePad:
"""Alias for probe_read()"""
...
def probe_read_blocking() -> ProbePad:
"""Wait for probe touch (explicit blocking)"""
...
def probe_read_nonblocking() -> ProbePad:
"""Check probe immediately (returns NO_PAD if not touched)"""
...
def probe_wait() -> ProbePad:
"""Alias for probe_read_blocking()"""
...
def wait_probe() -> ProbePad:
"""Alias for probe_read_blocking()"""
...
def probe_touch() -> ProbePad:
"""Alias for probe_read_blocking()"""
...
def wait_touch() -> ProbePad:
"""Alias for probe_read_blocking()"""
...
def probe_tap(node: NodeRef) -> None:
"""Simulate tapping probe on a node"""
...
# ============================================================================
# Probe Button Functions
# ============================================================================
def get_button(blocking: bool = True) -> ProbeButton:
"""Get probe button state (default: blocking until pressed)"""
...
def probe_button(blocking: bool = True) -> ProbeButton:
"""Alias for get_button()"""
...
def probe_button_blocking() -> ProbeButton:
"""Wait for button press (explicit blocking)"""
...
def probe_button_nonblocking() -> ProbeButton:
"""Check button immediately"""
...
def button_read(blocking: bool = True) -> ProbeButton:
"""Alias for get_button()"""
...
def read_button(blocking: bool = True) -> ProbeButton:
"""Alias for get_button()"""
...
def check_button() -> ProbeButton:
"""Alias for probe_button_nonblocking()"""
...
def button_check() -> ProbeButton:
"""Alias for probe_button_nonblocking()"""
...
# ============================================================================
# Probe Switch Functions
# ============================================================================
def get_switch_position() -> int:
"""Get current probe switch position
Returns:
0 (SWITCH_MEASURE): Probe in measure mode
1 (SWITCH_SELECT): Probe in select mode
-1 (SWITCH_UNKNOWN): Position unknown
Example:
if get_switch_position() == SWITCH_MEASURE:
voltage = measureMode()
"""
...
def set_switch_position(position: int) -> None:
"""Manually set probe switch position
Args:
position: 0 (SWITCH_MEASURE), 1 (SWITCH_SELECT), or -1 (SWITCH_UNKNOWN)
"""
...
def check_switch_position() -> int:
"""Check probe switch position via current sensing and update state
Uses hysteresis thresholds to prevent oscillation between modes.
Returns:
Updated switch position (0, 1, or -1)
Example:
position = check_switch_position()
if position == SWITCH_SELECT:
pad = probe_read(blocking=False)
"""
...
# ============================================================================
# Clickwheel Functions
# ============================================================================
def clickwheel_up(clicks: int = 1) -> None:
"""Scroll clickwheel up"""
...
def clickwheel_down(clicks: int = 1) -> None:
"""Scroll clickwheel down"""
...
def clickwheel_press() -> None:
"""Press clickwheel button"""
...
def clickwheel_get_position() -> int:
"""Get raw clickwheel position counter
Returns:
Current position value (accumulates as you turn)
Example:
pos = clickwheel_get_position()
print(f"Position: {pos}")
"""
...
def clickwheel_reset_position() -> None:
"""Reset clickwheel position counter to 0"""
...
def clickwheel_get_direction(consume: bool = True) -> int:
"""Get clickwheel direction event
Args:
consume: If True (default), clears direction after reading (one-shot).
If False, direction persists until consumed.
Returns:
0 (CLICKWHEEL_NONE), 1 (CLICKWHEEL_UP), or 2 (CLICKWHEEL_DOWN)
Note: Direction persists until consumed, so you won't miss turn events
Example:
direction = clickwheel_get_direction()
if direction == CLICKWHEEL_UP:
value += 1
"""
...
def clickwheel_get_button() -> int:
"""Get clickwheel button state
Returns:
0 (CLICKWHEEL_IDLE), 1 (CLICKWHEEL_PRESSED), 2 (CLICKWHEEL_HELD),
3 (CLICKWHEEL_RELEASED), or 4 (CLICKWHEEL_DOUBLECLICKED)
"""
...
def clickwheel_is_initialized() -> bool:
"""Check if clickwheel hardware is initialized and ready"""
...
# ============================================================================
# Service Management Functions
# ============================================================================
def force_service(name: str) -> bool:
"""Force immediate execution of a specific system service
Args:
name: Service name (e.g., "ProbeButton", "Peripherals")
Returns:
True if service found and executed, False otherwise
Example:
while True:
force_service("ProbeButton") # Ensure button updates
button = check_button()
time.sleep(0.001)
"""
...
def force_service_by_index(index: int) -> bool:
"""Force service execution by index (faster than name lookup)
Args:
index: Service index from get_service_index()
Returns:
True if successful, False otherwise
Example:
btn_idx = get_service_index("ProbeButton")
while True:
force_service_by_index(btn_idx) # Fastest
button = check_button()
"""
...
def get_service_index(name: str) -> int:
"""Get service index by name for use with force_service_by_index()
Args:
name: Service name
Returns:
Service index (0+), or -1 if not found
Example:
idx = get_service_index("ProbeButton")
if idx >= 0:
force_service_by_index(idx)
"""
...
# ============================================================================
# Terminal Color Functions
# ============================================================================
def change_terminal_color(color: int = -1, flush: bool = True) -> None:
"""Set terminal color by 256-color palette index
Args:
color: Color index (0-255), or -1 for default
flush: Flush output immediately (default: True)
Example:
change_terminal_color(196) # Bright red
print("This is in red")
change_terminal_color(-1) # Reset to default
"""
...
def cycle_term_color(reset: bool = False, step: float = 100.0, flush: bool = True) -> None:
"""Cycle through terminal colors
Args:
reset: If True, reset to start of color sequence
step: Color increment step (default: 100.0)
flush: Flush output immediately (default: True)
Example:
cycle_term_color(reset=True) # Start fresh
for i in range(10):
cycle_term_color() # Next color
print(f"Line {i}")
"""
...
# ============================================================================
# Filesystem Functions
# ============================================================================
def fs_exists(path: str) -> bool:
"""Check if file/directory exists"""
...
def fs_listdir(path: str) -> List[str]:
"""List directory contents"""
...
def fs_read(path: str) -> str:
"""Read file contents"""
...
def fs_write(path: str, content: str) -> bool:
"""Write file contents"""
...
def fs_cwd() -> str:
"""Get current working directory"""
...
# ============================================================================
# Overlay Functions
# ============================================================================
def overlay_set(netNum: int, r: int, g: int, b: int) -> None:
"""Set overlay color for a net (RGB 0-255)"""
...
def overlay_clear(netNum: int) -> None:
"""Clear overlay for a net"""
...
def overlay_clear_all() -> None:
"""Clear all overlays"""
...
def overlay_set_pixel(x: int, y: int, r: int, g: int, b: int) -> None:
"""Set overlay pixel at (x, y) to RGB"""
...
def overlay_count() -> int:
"""Return number of active overlays"""
...
def overlay_shift(dx: int = 0, dy: int = 0) -> None:
"""Shift overlay position"""
...
def overlay_place(netNum: int, x: int, y: int) -> None:
"""Place overlay for net at (x, y)"""
...
def overlay_serialize() -> str:
"""Serialize overlays to YAML string"""
...
# ============================================================================
# Status/Debug Functions
# ============================================================================
def print_bridges() -> None:
"""Print all active bridges"""
...
def print_paths() -> None:
"""Print resolved paths"""
...
def print_crossbars() -> None:
"""Print raw crossbar state"""
...
def print_nets() -> None:
"""Print current nets"""
...
def print_chip_status() -> None:
"""Print CH446Q chip status"""
...
# ============================================================================
# Miscellaneous Functions
# ============================================================================
def arduino_reset() -> None:
"""Reset the Arduino Nano"""
...
def pause_core2(pause: bool) -> None:
"""Pause/resume core2 processing"""
...
def run_app(appName: str) -> None:
"""Launch a built-in app"""
...
def send_raw(chip: Union[int, str], x: int, y: int, setOrClear: int = 1) -> None:
"""Send raw data to crossbar chip"""
...
def change_terminal_color(color: int = -1, flush: bool = True) -> None:
"""Change terminal color"""
...
def cycle_term_color(reset: bool = False, step: float = 100.0, flush: bool = True) -> None:
"""Cycle through terminal colors"""
...
# ============================================================================
# Help Functions
# ============================================================================
def help(section: Optional[str] = None) -> None:
"""Display help for all functions or a specific section
Sections: DAC, ADC, GPIO, PWM, WAVEGEN, INA, NODES, NETS, SLOTS,
OLED, PROBE, STATUS, FILESYSTEM, MISC, EXAMPLES
"""
...
def nodes_help() -> None:
"""Display detailed node reference"""
...
# ============================================================================
# GPIO State Constants
# ============================================================================
HIGH: GPIOState
LOW: GPIOState
FLOATING: GPIOState
# ============================================================================
# GPIO Direction Constants
# ============================================================================
INPUT: GPIODirection
OUTPUT: GPIODirection
# ============================================================================
# Node Constants - Power Rails
# ============================================================================
TOP_RAIL: Node
T_RAIL: Node
BOTTOM_RAIL: Node
BOT_RAIL: Node
B_RAIL: Node
GND: Node
# ============================================================================
# Node Constants - DACs
# ============================================================================
DAC0: Node
DAC_0: Node
DAC1: Node
DAC_1: Node
# ============================================================================
# Node Constants - ADCs
# ============================================================================
ADC0: Node
ADC1: Node
ADC2: Node
ADC3: Node
ADC4: Node
ADC7: Node
# ============================================================================
# Node Constants - Current Sense
# ============================================================================
ISENSE_PLUS: Node
ISENSE_P: Node
I_P: Node
CURRENT_SENSE_P: Node
CURRENT_SENSE_PLUS: Node
ISENSE_MINUS: Node
ISENSE_N: Node
I_N: Node
CURRENT_SENSE_N: Node
CURRENT_SENSE_MINUS: Node
# ============================================================================
# Node Constants - Buffer
# ============================================================================
BUFFER_IN: Node
BUF_IN: Node
BUFFER_OUT: Node
BUF_OUT: Node
# ============================================================================
# Node Constants - UART
# ============================================================================
UART_TX: Node
TX: Node
UART_RX: Node
RX: Node
# ============================================================================
# Node Constants - Arduino Nano Digital Pins
# ============================================================================
D0: Node
D1: Node
D2: Node
D3: Node
D4: Node
D5: Node
D6: Node
D7: Node
D8: Node
D9: Node
D10: Node
D11: Node
D12: Node
D13: Node
NANO_D0: Node
NANO_D1: Node
NANO_D2: Node
NANO_D3: Node
NANO_D4: Node
NANO_D5: Node
NANO_D6: Node
NANO_D7: Node
NANO_D8: Node
NANO_D9: Node
NANO_D10: Node
NANO_D11: Node
NANO_D12: Node
NANO_D13: Node
# ============================================================================
# Node Constants - Arduino Nano Analog Pins
# ============================================================================
A0: Node
A1: Node
A2: Node
A3: Node
A4: Node
A5: Node
A6: Node
A7: Node
NANO_A0: Node
NANO_A1: Node
NANO_A2: Node
NANO_A3: Node
NANO_A4: Node
NANO_A5: Node
NANO_A6: Node
NANO_A7: Node
# ============================================================================
# Node Constants - GPIO Pins
# ============================================================================
GPIO_1: Node
GPIO_2: Node
GPIO_3: Node
GPIO_4: Node
GPIO_5: Node
GPIO_6: Node
GPIO_7: Node
GPIO_8: Node
GP1: Node
GP2: Node
GP3: Node
GP4: Node
GP5: Node
GP6: Node
GP7: Node
GP8: Node
GPIO_20: Node
GPIO_21: Node
GPIO_22: Node
GPIO_23: Node
GPIO_24: Node
GPIO_25: Node
GPIO_26: Node
GPIO_27: Node
# ============================================================================
# Waveform Constants
# ============================================================================
SINE: int
TRIANGLE: int
SAWTOOTH: int
SQUARE: int
RAMP: int
ARBITRARY: int
# ============================================================================
# Probe Button Constants
# ============================================================================
BUTTON_NONE: ProbeButton
BUTTON_CONNECT: ProbeButton
BUTTON_REMOVE: ProbeButton
CONNECT_BUTTON: ProbeButton
REMOVE_BUTTON: ProbeButton
# ============================================================================
# Probe Switch Position Constants
# ============================================================================
SWITCH_MEASURE: int
"""Probe switch in measure mode (0)"""
SWITCH_SELECT: int
"""Probe switch in select mode (1)"""
SWITCH_UNKNOWN: int
"""Probe switch position unknown (-1)"""
# ============================================================================
# Clickwheel Constants
# ============================================================================
CLICKWHEEL_NONE: int
"""No clickwheel movement (0)"""
CLICKWHEEL_UP: int
"""Clickwheel turned clockwise (1)"""
CLICKWHEEL_DOWN: int
"""Clickwheel turned counter-clockwise (2)"""
CLICKWHEEL_IDLE: int
"""Clickwheel button idle (0)"""
CLICKWHEEL_PRESSED: int
"""Clickwheel button pressed (1)"""
CLICKWHEEL_HELD: int
"""Clickwheel button held down (2)"""
CLICKWHEEL_RELEASED: int
"""Clickwheel button released (3)"""
CLICKWHEEL_DOUBLECLICKED: int
"""Clickwheel button double-clicked (4)"""
# ============================================================================
# Probe Pad Constants
# ============================================================================
NO_PAD: ProbePad
LOGO_PAD_TOP: ProbePad
LOGO_PAD_BOTTOM: ProbePad
GPIO_PAD: ProbePad
DAC_PAD: ProbePad
ADC_PAD: ProbePad
BUILDING_PAD_TOP: ProbePad
BUILDING_PAD_BOTTOM: ProbePad
# Nano power/control pad constants
NANO_VIN: ProbePad
VIN_PAD: ProbePad
NANO_RESET_0: ProbePad
RESET_0_PAD: ProbePad
NANO_RESET_1: ProbePad
RESET_1_PAD: ProbePad
NANO_GND_1: ProbePad
GND_1_PAD: ProbePad
NANO_GND_0: ProbePad
GND_0_PAD: ProbePad
NANO_3V3: ProbePad
VIN_3V3_PAD: ProbePad
NANO_5V: ProbePad
VIN_5V_PAD: ProbePad
# Nano digital pin pad constants
D0_PAD: ProbePad
D1_PAD: ProbePad
D2_PAD: ProbePad
D3_PAD: ProbePad
D4_PAD: ProbePad
D5_PAD: ProbePad
D6_PAD: ProbePad
D7_PAD: ProbePad
D8_PAD: ProbePad
D9_PAD: ProbePad
D10_PAD: ProbePad
D11_PAD: ProbePad
D12_PAD: ProbePad
D13_PAD: ProbePad
RESET_PAD: ProbePad
AREF_PAD: ProbePad
# Nano analog pin pad constants
A0_PAD: ProbePad
A1_PAD: ProbePad
A2_PAD: ProbePad
A3_PAD: ProbePad
A4_PAD: ProbePad
A5_PAD: ProbePad
A6_PAD: ProbePad
A7_PAD: ProbePad
# Rail pad constants
TOP_RAIL_PAD: ProbePad
BOTTOM_RAIL_PAD: ProbePad
BOT_RAIL_PAD: ProbePad
TOP_RAIL_GND: ProbePad
TOP_GND_PAD: ProbePad
BOTTOM_RAIL_GND: ProbePad
BOT_RAIL_GND: ProbePad
BOTTOM_GND_PAD: ProbePad
BOT_GND_PAD: ProbePad
# ============================================================================
# JFS Filesystem Module
# ============================================================================
class JFSFile:
"""JFS file object"""
def read(self, size: int = -1) -> Union[str, bytes]: ...
def write(self, data: Union[str, bytes]) -> int: ...
def print(self, *args) -> int: ...
def seek(self, position: int, whence: int = 0) -> bool: ...
def tell(self) -> int: ...
def position(self) -> int: ...
def size(self) -> int: ...
def available(self) -> int: ...
def name(self) -> str: ...
def close(self) -> None: ...
def flush(self) -> None: ...
def __enter__(self) -> 'JFSFile': ...
def __exit__(self, exc_type, exc_val, exc_tb) -> bool: ...
class JFSModule:
"""Jumperless Filesystem Module"""
SEEK_SET: int
SEEK_CUR: int
SEEK_END: int
def open(self, path: str, mode: str = 'r') -> JFSFile:
"""Open a file (modes: 'r', 'w', 'a', 'rb', 'wb', 'ab')"""
...
def read(self, file: JFSFile, size: int = 1024) -> str:
"""Read from file"""
...
def write(self, file: JFSFile, data: str) -> None:
"""Write to file"""
...
def close(self, file: JFSFile) -> None:
"""Close file"""
...
def seek(self, file: JFSFile, position: int, whence: int = 0) -> bool:
"""Seek in file"""
...
def tell(self, file: JFSFile) -> int:
"""Get file position"""
...
def size(self, file: JFSFile) -> int:
"""Get file size"""
...
def available(self, file: JFSFile) -> int:
"""Get bytes available"""
...
def exists(self, path: str) -> bool:
"""Check if path exists"""
...
def listdir(self, path: str) -> List[str]:
"""List directory contents"""
...
def mkdir(self, path: str) -> None:
"""Create directory"""
...
def rmdir(self, path: str) -> None:
"""Remove directory"""
...
def remove(self, path: str) -> None:
"""Remove file"""
...
def rename(self, from_path: str, to_path: str) -> None:
"""Rename/move file"""
...
def stat(self, path: str) -> Tuple[int, ...]:
"""Get file/directory status"""
...
def info(self) -> Tuple[int, int, int]:
"""Get filesystem info (total, used, free)"""
...
jfs: JFSModule