Jumperless MicroPython API Reference
Node Connections (Connecting stuff with the Jumperless) - Examples:
connect(node1, node2, [duplicates=-1])- Connect two nodes (duplicates: -1=add, N=force N)disconnect(node1, node2)- Disconnect nodes (node2= -1 clear everything connected tonode1)fast_connect(node1, node2, [duplicates=-1])- Connect, skip LED updatefast_disconnect(node1, node2)- Disconnect, skip LED updateis_connected(node1, node2)- Check if nodes are connectednodes_clear()- Clear all connections
DAC (Digital-to-Analog Converter) - Examples:
dac_set(channel, voltage)- Set DAC output voltagedac_get(channel)- Get DAC output voltage
ADC (Analog-to-Digital Converter) - Examples:
adc_get(channel)- Read ADC input voltage
GPIO (General Purpose Input / Output from the RP2350B) - Examples:
gpio_set(pin, value)- Set GPIO pin stategpio_get(pin)- Read GPIO pin stategpio_set_dir(pin, direction)- Set GPIO pin directiongpio_get_dir(pin)- Get GPIO pin directiongpio_set_pull(pin, pull)- Set GPIO pull-up/downgpio_get_pull(pin)- Get GPIO pull-up/down
INA (Current/Power Monitor) - Examples:
ina_get_current(sensor)- Read current in ampsina_get_voltage(sensor)- Read shunt voltageina_get_bus_voltage(sensor)- Read bus voltageina_get_power(sensor)- Read power in watts
PWM (Pulse Width Modulation) - Examples:
pwm(pin, [frequency], [duty])- Setup PWM on GPIO pinpwm_set_duty_cycle(pin, duty)- Set PWM duty cyclepwm_set_frequency(pin, freq)- Set PWM frequencypwm_stop(pin)- Stop PWM on pin
OLED Display (Organic Light Emitting Diode 128 x 32 pixel display) - Examples:
oled_print("text")- Display textoled_clear()- Clear displayoled_connect()- Connect OLEDoled_disconnect()- Disconnect OLED
Graphic Overlays (Directly controlling the breadboard LEDs) - Examples:
overlay_set(name, row, col, w, h, colors)- Create/update overlayoverlay_clear(name)- Remove overlayoverlay_clear_all()- Remove all overlaysoverlay_shift(name, dRow, dCol)- Move overlay relativeoverlay_place(name, row, col)- Move overlay absoluteoverlay_set_pixel(row, col, color)- Set single pixeloverlay_count()- Get active overlay countoverlay_serialize()- Get overlays as YAML
Probe Functions (Probe status / actions)=L=e==ft - Examples:
probe_read_blocking()- Wait for probe touch (don't return until a pad is touched)probe_read_nonblocking()- Check probe immediately (return -1 if no pad is touched)get_button([blocking=True])- Get button state (default: blocking)probe_button([blocking=True])- Get button state (default: blocking)probe_button_blocking()- Wait for button pressprobe_button_nonblocking()- Check buttons immediatelycheck_button()- Check for probe button pressesget_switch_position()- Get probe switch position (0=measure, 1=select, -1=unknown)set_switch_position(position)- Set switch position manuallycheck_switch_position()- Check switch via current sensingprobe_autoconnect([enable])- Get/set probe auto-connect (True/False, temporary until reboot)
Clickwheel (Rotary Encoder / button on the top left) - Examples:
clickwheel_get_position()- Get raw position counterclickwheel_reset_position()- Reset position to 0clickwheel_get_direction([consume])- Get direction event (NONE/UP/DOWN)clickwheel_get_button()- Get button state
Fake GPIO (Multiplex an ADC to read up to 32 inputs) - Examples:
FakeGpioPin(node, [mode], [v_high], [v_low])- Create virtual GPIOpin.value([val])- Control pin
Net Information (Ask the Jumperless about Nets) - Examples:
get_net_name(netNum)- Get the name of a netset_net_name(netNum, name)- Set a custom net nameget_net_color(netNum)- Get net color as 0xRRGGBBget_net_color_name(netNum)- Get net color as name stringset_net_color(netNum, color)- Set net color by name or RGBset_net_color_hsv(netNum, h, [s], [v])- Set net color by HSV (auto-detects 0-1 or 0-255)get_num_nets()- Get number of active netsget_num_bridges()- Get number of bridgesget_net_nodes(netNum)- Get comma-separated node listget_bridge(bridgeIdx)- Get bridge info tupleget_net_info(netNum)- Get full net info as dict
Path Query API (Info about the internal routing) - Examples:
get_num_paths([include_duplicates])- Get number of routing pathsget_path_info(path_idx)- Get detailed path info as dictget_all_paths()- Get all paths as list of dictsget_path_between(node1, node2)- Query specific path between nodes
JFS (Jumperless File System) - Examples:
jfs.open(path, mode)- Opens file, returns file handlejfs.read(file, size=1024)- Read from filejfs.write(file, data)- Write to filejfs.close(file)- Close filejfs.seek(file, position, whence=0)- Seek in filejfs.tell(file)- Get current positionjfs.size(file)- Get file size-
jfs.available(file)- Get bytes available -
jfs.exists(path)- Check if path exists (returns True/False) jfs.listdir(path)- List directory contents (returns list)jfs.mkdir(path)- Create directoryjfs.rmdir(path)- Remove directoryjfs.remove(path)- Remove filejfs.rename(from, to)- Rename/move file-
jfs.stat(path)- Get file/directory status info -
jfs.info()- Returns (total, used, free) tuple -
file.print(data)- Print to the file (likewritebut auto-flushes)
-
file.flush()- Flush buffered data to file
-
file.position()- Alias forf.tell()
-
file.name()- Get file name
Status (Print status stuff to main Serial) - Examples:
print_bridges()- Print all bridgesprint_paths()- Print path between nodesprint_crossbars()- Print crossbar arrayprint_nets()- Print netsprint_chip_status()- Print chip status
Misc / System Functions (Things that don't have their own category) - Examples:
arduino_reset()- Reset Arduinorun_app('appName')- Run apppause_core2(pause)- Pause/resume core2 processingsend_raw(chip, x, y, setOrClear)- Send raw data to core2change_terminal_color(color, [flush])- Set terminal color (0-255)cycle_term_color([reset], [step], [flush])- Cycle through colorsforce_service(name)- Force run a service by nameforce_service_by_index(idx)- Force run service by index (faster)get_service_index(name)- Get service index for cachingcontext_toggle()- Toggle connection context (global/python)context_get()- Get current context namenodes_save([slot])- Save connections to slotnodes_discard()- Discard unsaved changesnodes_has_changes()- Check for unsaved changesswitch_slot(slot)- Switch to a different slotget_state()- Get complete board state as JSON stringset_state(json, [clear_first=True], [from_wokwi=False])- Apply complete state from JSON string; setfrom_wokwito True to parse Wokwi diagram
help()- Display helpnodes_help()- Show available nodes and how to address them
A Note on Usage
All functions and constants from the jumperless module are automatically imported into the global namespace. This means you can call them directly (e.g., connect(1, 5)) without needing the jumperless. prefix.
There are three primary ways to specify nodes in functions:
- By Number: Use the integer corresponding to the breadboard row (1-60).
- By String Name: Use a case-insensitive string for any named node (e.g.,
"d13","TOP_RAIL"). - By Constant: Use the predefined, case-sensitive constant for a node (e.g.,
D13,TOP_RAIL).
Node Connections
These functions manage the connections between nodes on the breadboard and special function pins.
connect(node1, node2, [duplicates=-1])
Creates a bridge between two nodes.
node1,node2: The nodes to connect. Can be integers, strings, or constants.duplicates(optional): Controls duplicate connection behavior:-1(default): Just add the connection without managing duplicates (standard behavior)0: Force exactly 0 duplicates (removes any existing duplicate paths)1+: Force exactly N duplicates (adds or removes connections to reach that count)
Example:
# Connect breadboard row 1 to row 30
connect(1, 30)
# Connect Arduino D13 to the top power rail
connect(D13, TOP_RAIL)
# Connect GPIO 1 to ADC 0 using strings
connect("GPIO_1", "ADC0")
# Duplicate management examples
connect(1, 5, duplicates=0) # Ensure no duplicate paths
connect(1, 5, duplicates=2) # Force exactly 2 parallel paths
connect(1, 5) # Standard: just add the connection
disconnect(node1, node2)
Removes a specific bridge between two nodes.
node1,node2: The two nodes to disconnect.- To remove all connections from a single node, set
node2to-1.
Example:
# Remove the bridge between rows 1 and 30
disconnect(1, 30)
# Remove all connections from GPIO_1
disconnect(GPIO_1, -1)
is_connected(node1, node2)
Checks if a direct or indirect connection exists between two nodes.
- Returns a custom
ConnectionStateobject which evaluates toTrueif connected (CONNECTED) andFalseif not (DISCONNECTED).
Example:
if is_connected(D13, TOP_RAIL):
print("D13 is connected to the top rail.")
state = is_connected(1, 2)
print(state) # Prints "CONNECTED" or "DISCONNECTED"
nodes_clear()
Removes all connections from the board.
Example:
nodes_clear()
print("All connections cleared.")
node(name_or_id)
Creates a node object from a string name or integer ID. This is useful for storing a node reference in a variable.
Node Type:
Node objects support arithmetic and comparison operations with integers:
- Comparisons:
==,!=,<,<=,>,>= - Arithmetic:
+,-,*,//,% - Conversions:
int(node)converts to integer value
Example:
my_pin = node("D7")
led_pin = node(15)
connect(my_pin, led_pin)
oled_print(my_pin) # Displays 'D7' on the OLED
# Arithmetic and comparison work!
if my_pin <= 20:
next_pin = my_pin + 1 # Returns int 8
connect(next_pin, led_pin)
DAC (Digital-to-Analog Converter)
Functions for controlling the analog voltage outputs.
dac_set(channel, voltage, [save=True])
Sets the output voltage for a specific DAC channel.
channel: The DAC channel to set. Can be an integer (0-3) or a node constant (DAC0,DAC1,TOP_RAIL,BOTTOM_RAIL).voltage: The desired voltage (from -8.0V to 8.0V).save(optional): IfTrue(default), the setting is saved to the config file.- Aliases:
set_dac()
Channels:
* 0 or DAC0: The 5V tolerant DAC output.
* 1 or DAC1: The 8V tolerant DAC output.
* 2 or TOP_RAIL: The top power rail.
* 3 or BOTTOM_RAIL: The bottom power rail.
Example:
# Set the top rail to 5V
dac_set(TOP_RAIL, 5.0)
# Set DAC0 to 1.25V
set_dac(DAC0, 1.25)
dac_get(channel)
Reads the currently set voltage for a DAC channel.
channel: The DAC channel to read.- Returns a float.
- Aliases:
get_dac()
Example:
voltage = dac_get(TOP_RAIL)
print("Top Rail voltage: " + str(voltage))
ADC (Analog-to-Digital Converter)
Functions for measuring analog voltages.
adc_get(channel)
Reads the voltage from a specific ADC channel.
channel: The ADC channel to read (0-4).- Returns a float.
- Aliases:
get_adc()
Channels:
0-3: 8V tolerant ADC inputs.4: 5V tolerant ADC input.
Example:
voltage = adc_get(0)
print("ADC0 voltage: " + str(voltage))
GPIO (General Purpose Input/Output)
Functions for controlling the digital I/O pins.
gpio_set(pin, value)
Sets the output state of a GPIO pin.
pin: The GPIO pin number (1-10).value:Truefor HIGH,Falsefor LOW.- Aliases:
set_gpio()
gpio_get(pin)
Reads the state of a GPIO pin.
pin: The GPIO pin number (1-10).- Returns a
GPIOStateobject (HIGH,LOW, orFLOATING). - Aliases:
get_gpio()
gpio_set_dir(pin, direction)
Sets the direction of a GPIO pin.
pin: The GPIO pin number (1-10).direction:Truefor OUTPUT,Falsefor INPUT.- Aliases:
set_gpio_dir()
gpio_get_dir(pin)
Reads the direction of a GPIO pin.
pin: The GPIO pin number (1-10).- Returns a
GPIODirectionobject (INPUTorOUTPUT). - Aliases:
get_gpio_dir()
gpio_set_pull(pin, pull)
Configures the internal pull resistor for a GPIO pin.
pin: The GPIO pin number (1-10).pull:1for PULLUP,-1for PULLDOWN,0for NONE.- Aliases:
set_gpio_pull()
gpio_get_pull(pin)
Reads the pull resistor configuration of a GPIO pin.
pin: The GPIO pin number (1-10).- Returns a
GPIOPullobject (PULLUP,PULLDOWN, orNONE). - Aliases:
get_gpio_pull()
gpio_set_read_floating(pin, enabled)
Enable or disable special floating detection when reading GPIO inputs. These are all enabled by default.
pin: The GPIO pin number (1-10).enabled:Trueto enable floating-read behavior,Falseto disable.- Aliases:
set_gpio_read_floating()
Description: When enabled, the firmware performs an extra floating-detection check so gpio_get() can return FLOATING for very-high-impedance inputs. To do this it momentarily biases the pin with a very weak internal pull-up (~50 kΩ) while sampling. That transient bias can affect extremely high‑impedance sources (for example, >10 MΩ sensors) and may cause a small leakage current or change the measured state. If your external circuit is super high‑impedance, either disable floating-read for that pin or add a defined pull resistor.
gpio_get_read_floating(pin)
Returns whether floating-read detection is enabled for a GPIO pin.
pin: The GPIO pin number (1-10).- Returns:
Trueif floating-read is enabled, otherwiseFalse. - Aliases:
get_gpio_read_floating()
Example:
# Enable floating detection on GPIO 3
gpio_set_read_floating(3, True)
# Confirm it is enabled
print(gpio_get_read_floating(3)) # True or False
# If a connected high‑impedance sensor behaves oddly, disable floating-read
gpio_set_read_floating(3, False)
Pinout:
* 1-8: Routable GPIO pins GPIO_1 to GPIO_8.
* 9: UART_TX.
* 10: UART_RX.
Example:
# Set GPIO 1 as an output and turn it on
gpio_set_dir(1, True)
gpio_set(1, True)
# Set GPIO 2 as an input with a pull-up
gpio_set_dir(2, False)
gpio_set_pull(2, 1)
# Read the state of GPIO 2
state = gpio_get(2)
if state: # GPIOState is truthy when HIGH, falsy when LOW or FLOATING
print("GPIO 2 is HIGH")
# You can also print it directly - shows "HIGH", "LOW", or "FLOATING"
print("State: " + str(state))
PWM (Pulse-Width Modulation)
Functions for generating PWM signals on GPIO pins.
pwm(pin, [frequency], [duty_cycle])
Sets up and starts a PWM signal on a GPIO pin.
pin: The GPIO pin to use (1-8).frequency(optional): The PWM frequency in Hz (0.001 to 62500000). Defaults to 1000.duty_cycle(optional): The duty cycle from 0.0 to 1.0. Defaults to 0.5.- Aliases:
set_pwm()
Frequency Ranges:
- Hardware PWM: 10Hz to 62.5MHz (high precision, hardware peripheral)
- Slow PWM: 0.001Hz to 10Hz (hardware timer based, precise timing)
- Automatic Selection: System automatically chooses the appropriate mode based on frequency
pwm_set_duty_cycle(pin, duty_cycle)
Changes the duty cycle of an existing PWM signal.
pin: The GPIO pin number (1-8).duty_cycle: The new duty cycle (0.0 to 1.0).- Aliases:
set_pwm_duty_cycle()
pwm_set_frequency(pin, frequency)
Changes the frequency of an existing PWM signal.
pin: The GPIO pin number (1-8).frequency: The new frequency in Hz (0.001 to 62500000).- Aliases:
set_pwm_frequency()
pwm_stop(pin)
Stops the PWM signal on a GPIO pin.
pin: The GPIO pin number (1-8).- Aliases:
stop_pwm()
Example:
# Hardware PWM: 1kHz, 25% duty cycle on GPIO_1
pwm(GPIO_1, 1000, 0.25)
# Slow PWM: 0.1Hz (10 second period), 50% duty cycle on GPIO_2
pwm(GPIO_2, 0.1, 0.5)
# Ultra-slow PWM: 0.001Hz (1000 second period), 25% duty cycle on GPIO_3
pwm(GPIO_3, 0.001, 0.25)
# Change the duty cycle to 75%
pwm_set_duty_cycle(GPIO_1, 0.75)
# Change frequency (will automatically switch between hardware/slow PWM)
pwm_set_frequency(GPIO_1, 500) # 500Hz (hardware PWM)
pwm_set_frequency(GPIO_1, 5) # 5Hz (slow PWM)
# Stop the PWM signal
pwm_stop(GPIO_1)
Graphic Overlays
Functions for creating and manipulating 2D color overlays on the breadboard LEDs.
The breadboard is addressed as a 10-row × 30-column grid: * Row 1-5: Top half (A-E) * Row 6-10: Bottom half (F-J) * Column 1-30: Breadboard columns 1-30
overlay_set(name, x, y, height, width, colors)
Creates or updates a graphic overlay.
name: Unique string identifier for the overlay.x: Starting column (1-30). Matches breadboard column labels.y: Starting row (1-10). 1-5 = Top half (A-E), 6-10 = Bottom half (F-J).height: Height in rows (y-dimension).width: Width in columns (x-dimension).colors: List of 32-bit integer colors (0xRRGGBB). Can be a flat list or 2D list (rows).- Returns the overlay index.
Note: If you pass a 2D array (list of lists) for colors, the outer list represents rows (height) and the inner lists represent columns (width). Make sure your width and height arguments match the data shape.
Example:
# Create a 5-wide, 2-high overlay at x=2, y=5
# x=2 (Column 2), y=5 (Row 5/E)
colors_2d = [
[0x550000, 0x550000, 0x550000, 0x550000, 0x550000], # Row 0
[0x550000, 0x550000, 0x550000, 0x550000, 0x550000] # Row 1
]
overlay_set("box_2d", 12, 5, 2, 5, colors_2d)
overlay_clear(name)
Removes a specific overlay.
name: The identifier of the overlay to remove.- Returns
1if found/removed,0otherwise.
overlay_clear_all()
Removes ALL active overlays.
overlay_shift(name, dx, dy)
Moves an overlay by a relative offset. Wraps around edges.
name: Overlay identifier.dx: Column delta (e.g., 1 for right, -1 for left).dy: Row delta (e.g., 1 for down, -1 for up).- Returns
1if found,0otherwise.
overlay_place(name, x, y)
Moves an overlay to a specific absolute position. Wraps around edges.
name: Overlay identifier.x: New column (1-30).y: New row (1-10).- Returns
1if found,0otherwise.
Example:
# Use the probe to move the box overlay
import jumperless as j
import time
colors_2d = [
[0x550000, 0x104000, 0x005500, 0x001040, 0x000055], # Row 0
[0x550000, 0x104000, 0x005500, 0x001040, 0x000055], # Row 1
]
j.overlay_set("box_2d", 12, 5, 2, 5, colors_2d)
while True:
node = j.probe_read_blocking()
j.overlay_place("box_2d",node, 5)
time.sleep(0.1)
overlay_set_pixel(x, y, color)
Sets a single pixel directly (convenience wrapper).
x: Column (1-30).y: Row (1-10).color: 0xRRGGBB color.
overlay_serialize()
Returns the current state of all overlays as a JSON string.
INA (Current/Power Monitor)
Functions for reading data from the INA219 current sensors.
ina_get_current(sensor)
Reads the current in Amps.
* sensor: The sensor to read (0 or 1).
* Aliases: get_current()
ina_get_voltage(sensor)
Reads the shunt voltage in Volts.
* sensor: The sensor to read (0 or 1).
* Aliases: get_voltage()
ina_get_bus_voltage(sensor)
Reads the bus voltage in Volts.
* sensor: The sensor to read (0 or 1).
* Aliases: get_bus_voltage()
ina_get_power(sensor)
Reads the power in Watts.
* sensor: The sensor to read (0 or 1).
* Aliases: get_power()
Example:
current_mA = ina_get_current(0) * 1000
print("Current: " + str(current_mA) + " mA")
OLED Display
Functions for controlling the onboard OLED display with advanced text, graphics, and bitmap capabilities.
Basic Display Functions
oled_print(text, [size=-1])
Displays text on the OLED screen. It can print strings, numbers, and custom Jumperless types.
text: The content to display.size(optional): Text size (0=small scrolling, 1=normal, 2=large). If -1 or omitted, uses the default size set byoled_set_text_size(). Defaults to 2.
Size Modes: - Size 0: Small scrolling text (perfect for terminal-like output with multiple lines) - Size 1: Normal centered text - Size 2: Large centered text (default)
Example:
oled_print("Hello!") # Uses default size
oled_print("Big Text", 2) # Large text
oled_print("Scrolling", 0) # Small scrolling text
oled_clear([show=True])
Clears the OLED display.
show(optional): IfTrue(default), automatically callsoled_show()after clearing. Set toFalsefor animations to avoid flashing between frames.
Example:
# Normal use - clears and shows
oled_clear()
# Animation loop - clear without showing to prevent flashing
for frame in range(100):
oled_clear(False) # Clear without show
# Draw your frame...
oled_show() # Show once after drawing
oled_show()
Refreshes the OLED display to show the latest changes.
Note: Usually not needed as oled_print() handles display updates automatically. Required after oled_set_pixel() calls.
oled_connect()
Connects the I2C lines to the OLED display.
oled_disconnect()
Disconnects the I2C lines from the OLED display.
Text Size Control
oled_set_text_size(size)
Set the default text size for all subsequent oled_print() calls.
size: Text size (0=small scrolling, 1=normal, 2=large)- Returns:
Trueif successful,Falseif invalid size
Example:
import jumperless as j
# Use small scrolling text for terminal output
j.oled_set_text_size(0)
for i in range(10):
j.oled_print(f"Line {i+1}") # Each creates a new scrolling line
# Switch to large text
j.oled_set_text_size(2)
j.oled_print("BIG TEXT")
oled_get_text_size()
Get the current default text size.
- Returns: Current text size (0, 1, or 2)
Example:
current_size = oled_get_text_size()
print(f"Current OLED text size: {current_size}")
Print Redirection
oled_copy_print(enable)
Enable or disable copying Python print() output to the OLED display in real-time.
When enabled, all print() statements will appear on both the serial console and the OLED in small scrolling text mode. This is perfect for debugging without a serial connection.
enable:Trueto enable,Falseto disable
Example:
import jumperless as j
# Enable print copying
j.oled_copy_print(True)
# These appear on both serial AND OLED
print("Starting test...")
voltage = j.adc_get(0)
print(f"Voltage: {voltage:.2f}V")
print("Test complete!")
# Disable print copying
j.oled_copy_print(False)
print("This only goes to serial")
Font System
oled_get_fonts()
Get a list of all available font families.
- Returns: List of font family names (strings)
Available Fonts:
- Eurostyle - sans serif, futuristic, like Xenon pinball or Star Trek
- Jokerman - decorative font with lots of extra artistic dots and bars
- Comic Sans - sans serif, comic book style lettering
- Courier New - slab serif, typewriter style
- New Science - sans serif, humanist/geometric, like Helvetica
- New Science Ext - wider version of New Science
- Iosevka Regular - fixed spacing sans serif, like Lucida, slashed zero
- Berkeley Mono - fixed spacing, sans serif, large X height
-
Pragmatism - sans serif, vaguely romantic
-
Andale Mono - fixed spacing sans serif, used for small text
(Descriptions by MadBodger)
Example:
import jumperless as j
import time
fonts = j.oled_get_fonts()
print(f"Available fonts: {fonts}")
# Display each font
for font in fonts:
j.oled_set_font(font)
j.oled_print(font, 2)
time.sleep(1.5)
oled_set_font(name)
Set the current font family by name. The font will remain active until changed.
name: Font family name (case-insensitive)- Returns:
Trueif successful,Falseif font not found
Example:
import jumperless as j
# Set to Jokerman
if j.oled_set_font("Jokerman"):
j.oled_print("Fun Font!", 2)
else:
print("Font not found")
# Set to Courier for code-like display
j.oled_set_font("Courier New")
j.oled_print("Code Style", 2)
oled_get_current_font()
Get the name of the currently active font family.
- Returns: Current font family name (string)
Example:
import jumperless as j
current = j.oled_get_current_font()
print(f"Current font: {current}")
# Save and restore font
saved_font = j.oled_get_current_font()
j.oled_set_font("Jokerman")
j.oled_print("Temporary", 2)
j.oled_set_font(saved_font) # Restore original
Bitmap Display
oled_load_bitmap(filepath)
Load a bitmap file into the internal bitmap buffer.
filepath: Path to bitmap file (e.g., "/images/logo.bin")- Returns:
Trueif loaded successfully,Falseon error
Bitmap File Format:
-
Raw Format: Pure bitmap data (guesses dimensions from file size)
-
128x32 = 512 bytes
- 128x64 = 1024 bytes
-
64x32 = 256 bytes
-
Custom Format: 4-byte header + bitmap data
-
Bytes 0-1: Width (16-bit little-endian)
- Bytes 2-3: Height (16-bit little-endian)
- Remaining: Bitmap data (1 bit per pixel, packed)
Example:
if oled_load_bitmap("/images/jogo32h.bin"):
print("Logo loaded!")
else:
print("Failed to load logo")
oled_display_bitmap(x, y, width, height, [data=None])
Display a bitmap on the OLED.
Two modes:
- Use loaded bitmap: If
dataisNone, displays the bitmap fromoled_load_bitmap() -
Direct data: If
datais provided, displays that bitmap immediately -
x: X position on display (0-127) y: Y position on display (0-31)width: Bitmap width in pixels (ignored if using loaded bitmap)height: Bitmap height in pixels (ignored if using loaded bitmap)data(optional): Bitmap data to display directly- Returns:
Trueif successful,Falseon error
Example:
import jumperless as j
# Method 1: Load then display
j.oled_load_bitmap("/images/logo.bin")
j.oled_display_bitmap(0, 0, 0, 0) # width/height ignored for loaded bitmap
# Method 2: Display direct data
bitmap_data = bytes([0xFF, 0x00, 0xFF, 0x00] * 128) # Striped pattern
j.oled_display_bitmap(0, 0, 128, 32, bitmap_data)
oled_show_bitmap_file(filepath, x, y)
Convenience function that loads and displays a bitmap in one call.
filepath: Path to bitmap filex: X position on displayy: Y position on display- Returns:
Trueif successful,Falseon error
Example:
import jumperless as j
import time
# One-liner to show a logo
j.oled_show_bitmap_file("/images/jogo32h.bin", 0, 0)
time.sleep(2)
# Show another image
j.oled_show_bitmap_file("/images/badge.bin", 32, 8)
Framebuffer and Pixel Manipulation
The framebuffer functions provide low-level access to the display memory, enabling advanced graphics, animations, and screen capture.
Framebuffer Format: - 1 bit per pixel (0=black/off, 1=white/on) - Organized in vertical bytes (8 pixels per byte) - Size: 512 bytes (128x32) or 1024 bytes (128x64) - Compatible with Adafruit SSD1306 format
oled_get_framebuffer()
Get a copy of the current OLED framebuffer as a bytes object.
- Returns: Framebuffer data as
bytes(512 or 1024 bytes depending on display size)
oled_set_framebuffer(data)
Set the entire OLED framebuffer from bytes or bytearray.
data: Framebuffer data (must be correct size for display)- Returns:
Trueif successful,Falseif wrong size
Example:
import jumperless as j
import time
# Capture current display
fb = j.oled_get_framebuffer()
print(f"Framebuffer size: {len(fb)} bytes")
# Save to file for later
with open("/screen_capture.bin", "wb") as f:
f.write(fb)
j.oled_clear()
time.sleep(2)
# Load and display saved screen
with open("/screen_capture.bin", "rb") as f:
fb_data = f.read()
if j.oled_set_framebuffer(fb_data):
print("Screen restored!")
else:
print("Wrong framebuffer size")
oled_get_framebuffer_size()
Get the dimensions and size of the framebuffer.
- Returns: Tuple of
(width, height, buffer_size_in_bytes)
Example:
width, height, size = oled_get_framebuffer_size()
print(f"Display: {width}x{height}, {size} bytes")
# Output: Display: 128x32, 512 bytes
# Calculate pixels
total_pixels = width * height
print(f"Total pixels: {total_pixels}")
oled_set_pixel(x, y, color)
Set a single pixel on the OLED.
Note: Call oled_show() after setting pixels to make changes visible.
x: X coordinate (0 to width-1)y: Y coordinate (0 to height-1)color: Pixel color (0=black/off, 1=white/on)- Returns:
Trueif successful,Falseif OLED not connected
Example:
import jumperless as j
# Draw a diagonal line
j.oled_clear()
for i in range(32):
j.oled_set_pixel(i, i, 1)
j.oled_show()
# Draw a box
for x in range(20, 108):
j.oled_set_pixel(x, 10, 1) # Top edge
j.oled_set_pixel(x, 22, 1) # Bottom edge
for y in range(10, 23):
j.oled_set_pixel(20, y, 1) # Left edge
j.oled_set_pixel(107, y, 1) # Right edge
j.oled_show()
oled_get_pixel(x, y)
Get the color value of a single pixel.
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)
Example:
# Check if a pixel is set
pixel = oled_get_pixel(64, 16)
if pixel == 1:
print("Pixel is white/on")
elif pixel == 0:
print("Pixel is black/off")
else:
print("Error reading pixel")
Advanced OLED Examples
Debug Output to OLED
import jumperless as j
import time
# Enable print copying for debugging
j.oled_copy_print(True)
# Your code with debug output
for i in range(10):
voltage = j.adc_get(0)
print(f"V{i}: {voltage:.2f}V")
time.sleep(0.5)
j.oled_copy_print(False)
Simple Oscilloscope
import jumperless as j
import math
import time
# Clear display
j.oled_clear()
width, height, _ = j.oled_get_framebuffer_size()
j.connect(j.ADC0, 11)
# Draw sine wave animation
for offset in range(100):
j.oled_clear(False) # Don't show() after clear to avoid flashing
# Draw axes
for x in range(width):
if (x % 4 == 0):
j.oled_set_pixel(x, height//2, 1) # Dotted center line
# Draw sine wave
for x in range(width):
# y = int(height//2 + 10 * math.sin((x + offset) / 10)) # Dummy sine wave
y = int(j.get_adc(0)) + 16
if 0 <= y < height:
j.oled_set_pixel(x, y, 1)
# time.sleep_ms(10)
j.oled_show()
time.sleep(0.005)
Screen Capture and Manipulation
import jumperless as j
import time
# Capture screen
fb = j.oled_get_framebuffer()
# Invert all pixels
inverted = bytearray(fb)
for i in range(len(inverted)):
inverted[i] = ~inverted[i] & 0xFF
# Display inverted
j.oled_set_framebuffer(inverted)
time.sleep(1)
# Restore original
j.oled_set_framebuffer(fb)
Terminal-like Output
import jumperless as j
import time
# Use small scrolling text
j.oled_set_text_size(0)
j.oled_clear()
for i in range(20):
j.oled_print(f"Line {i}")
time.sleep(0.2)
Font Showcase
import jumperless as j
import time
for font in j.oled_get_fonts():
j.oled_set_font(font)
j.oled_print(font, 2)
time.sleep(1.5)
Probe
Functions for interacting with the physical probe.
probe_read([blocking=True])
Reads the pad currently being touched by the probe.
blocking(optional): IfTrue(default), the function will wait until a pad is touched. IfFalse, it returns immediately.- Returns a
ProbePadobject (e.g.,25,D13_PAD,NO_PAD). - Aliases:
read_probe(),probe_read_blocking(),probe_read_nonblocking(),probe_wait(),wait_probe(),probe_touch(),wait_touch()
ProbePad Type:
ProbePad objects support arithmetic and comparison operations with integers:
- Comparisons:
==,!=,<,<=,>,>= - Arithmetic:
+,-,*,//,% - Conversions:
int(pad)converts to integer value
Example:
pad = probe_read(False) # Non-blocking
if pad != NO_PAD:
print(pad)
if pad <= 60: # Compare with integer
node_1 = pad
node_2 = pad + 3 # Arithmetic with integer
if node_2 > 60: # Works!
node_2 -= 60
connect(node_1, node_2)
probe_button([blocking=True], [consume=False])
Reads the state of the buttons on the probe.
blocking(optional): IfTrue(default), waits for a button press. IfFalse, returns the current state immediately.consume(optional): IfTrue, clears the button press after reading (one-shot detection). IfFalse(default), the button state persists while held, allowing repeated reads in a loop.- Returns a
ProbeButtonobject (CONNECT_BUTTON,REMOVE_BUTTON, orBUTTON_NONE). - Aliases:
get_button(),button_read(),read_button(),probe_button_blocking(),probe_button_nonblocking(),check_button(),button_check()
Consume Behavior:
consume=False(default): Holding the button returns the same state repeatedly - ideal for continuous control (e.g., incrementing values while held)consume=True: Each button press is detected only once - ideal for menu navigation or one-shot actions
Example:
# Continuous control - hold button to keep changing hue
while True:
button = check_button() # consume=False by default
if button == BUTTON_CONNECT:
hue += 1 # Keeps incrementing while button is held
set_net_color_hsv(0, hue)
elif button == BUTTON_REMOVE:
hue -= 1 # Keeps decrementing while button is held
set_net_color_hsv(0, hue)
time.sleep(0.05)
# One-shot detection - each press counted once
presses = 0
while presses < 5:
button = get_button(consume=True) # Each press consumed
if button == BUTTON_CONNECT:
presses += 1
print(f"Press #{presses}")
Example:
print("Touch a pad...")
pad = probe_read()
print("You touched: " + str(pad))
if pad == D13_PAD:
print("That's the Arduino LED pin!")
print("Press a probe button...")
button = get_button()
if button == CONNECT_BUTTON:
print("Connect button pressed.")
get_switch_position()
Gets the current probe switch position.
- Returns:
0(SWITCH_MEASURE),1(SWITCH_SELECT), or-1(SWITCH_UNKNOWN)
Example:
position = get_switch_position()
if position == SWITCH_MEASURE:
print("Probe is in measure mode")
elif position == SWITCH_SELECT:
print("Probe is in select mode")
set_switch_position(position)
Manually sets the probe switch position.
position:0(SWITCH_MEASURE),1(SWITCH_SELECT), or-1(SWITCH_UNKNOWN)
Example:
set_switch_position(SWITCH_SELECT) # Force select mode
check_switch_position()
Checks the probe switch position using current sensing and updates the internal state.
- Returns: Updated switch position
Uses hysteresis thresholds to prevent oscillation between modes: - Switches to SELECT when current > high threshold - Switches to MEASURE when current < low threshold
Example:
# Periodically check and respond to switch changes
while True:
position = check_switch_position()
if position == SWITCH_MEASURE:
voltage = measureMode()
print(f"Voltage: {voltage}V")
elif position == SWITCH_SELECT:
pad = probe_read(blocking=False)
if pad != NO_PAD:
print(f"Touched: {pad}")
time.sleep(0.1)
probe_autoconnect([enable])
Gets or sets whether the probe DAC auto-connects on the routable buffer.
enable(optional):Trueto enable auto-connect,Falseto disable. If omitted, returns the current state without changing it.- Returns:
Trueif auto-connect is enabled,Falseif disabled.
This is a temporary setting that resets to enabled on reboot. Use this when you want to free up the DAC that powers the probe for other purposes without permanently changing the config.
To persistently disable, use config.dacs.auto_connect_probe = -1 in the config file instead.
Example:
# Disable probe auto-connect to free up DAC0
probe_autoconnect(False)
# Check current state
if not probe_autoconnect():
print("Probe auto-connect is disabled")
# Re-enable
probe_autoconnect(True)
Clickwheel
Functions for reading the rotary encoder (clickwheel) position, direction, and button state.
clickwheel_get_position()
Gets the raw clickwheel position counter.
- Returns: Current position value (integer, can be positive or negative)
The position accumulates as you turn the clickwheel - clockwise increases, counter-clockwise decreases.
Example:
pos = clickwheel_get_position()
print(f"Current position: {pos}")
clickwheel_reset_position()
Resets the clickwheel position counter to 0.
Example:
clickwheel_reset_position()
assert clickwheel_get_position() == 0
clickwheel_get_direction([consume=True])
Gets the current clickwheel direction event.
consume(optional): IfTrue(default), clears the direction after reading (one-shot detection). IfFalse, the direction persists until consumed.- Returns:
CLICKWHEEL_NONE(0),CLICKWHEEL_UP(1), orCLICKWHEEL_DOWN(2)
Important: The direction state persists until consumed! This means you won't miss turn events even if you don't check every loop iteration. The UP or DOWN state stays active until you read it with consume=True.
Example (One-shot - Default):
direction = clickwheel_get_direction() # consume=True (default)
if direction == CLICKWHEEL_UP:
value += 1 # Only increments once per turn event
print(f"Turned up: {value}")
elif direction == CLICKWHEEL_DOWN:
value -= 1 # Only decrements once per turn event
print(f"Turned down: {value}")
Example (Persistent - Check Multiple Times):
# Check direction without consuming
direction = clickwheel_get_direction(consume=False)
if direction == CLICKWHEEL_UP:
print("Turning clockwise...")
# Do some work...
# Check again - still UP until consumed!
if clickwheel_get_direction(consume=False) == CLICKWHEEL_UP:
print("Still turning up!")
# Finally consume it
clickwheel_get_direction(consume=True)
clickwheel_get_button()
Gets the current clickwheel button state.
-
Returns:
CLICKWHEEL_IDLE(0) - Not pressedCLICKWHEEL_PRESSED(1) - Just pressedCLICKWHEEL_HELD(2) - Being held downCLICKWHEEL_RELEASED(3) - Just releasedCLICKWHEEL_DOUBLECLICKED(4) - Double-clicked
Example:
button = clickwheel_get_button()
if button == CLICKWHEEL_PRESSED:
print("Button pressed!")
elif button == CLICKWHEEL_HELD:
print("Button held down")
elif button == CLICKWHEEL_DOUBLECLICKED:
print("Double click!")
Complete Example - Menu Navigation:
import jumperless as j
import time
menu_items = ["Option 1", "Option 2", "Option 3", "Option 4"]
selected = 0
j.clickwheel_reset_position()
while True:
# Check direction (consume=True by default - one turn = one event)
direction = j.clickwheel_get_direction()
if direction == j.CLICKWHEEL_UP:
selected = (selected + 1) % len(menu_items)
print(f"> {menu_items[selected]}")
elif direction == j.CLICKWHEEL_DOWN:
selected = (selected - 1) % len(menu_items)
print(f"> {menu_items[selected]}")
# Check button
button = j.clickwheel_get_button()
if button == j.CLICKWHEEL_PRESSED:
print(f"Selected: {menu_items[selected]}")
elif button == j.CLICKWHEEL_DOUBLECLICKED:
print("Exit menu")
break
# Note: Direction persists, so even with slow polling (50ms),
# you won't miss turn events!
time.sleep(0.05)
Example - Value Adjustment with Persistence:
import jumperless as j
import time
value = 50
while True:
# Check direction without consuming
direction = j.clickwheel_get_direction(consume=False)
if direction == j.CLICKWHEEL_UP:
value = min(100, value + 1)
j.oled_print(f"Value: {value}", 2)
time.sleep(0.1) # Delay for visual feedback
# Consume after displaying
j.clickwheel_get_direction(consume=True)
elif direction == j.CLICKWHEEL_DOWN:
value = max(0, value - 1)
j.oled_print(f"Value: {value}", 2)
time.sleep(0.1)
j.clickwheel_get_direction(consume=True)
# Exit on button press
if j.clickwheel_get_button() == j.CLICKWHEEL_PRESSED:
break
time.sleep(0.01)
WaveGen (Waveform Generator)
Functions for generating analog waveforms on DAC outputs.
Setters:
wavegen_set_output(output)- Select output:DAC0,DAC1,TOP_RAIL,BOTTOM_RAIL(defaultDAC1)wavegen_set_freq(hz)- Set frequency: 0.0001–10000.0 Hz (default 100 Hz)wavegen_set_wave(shape)- Set waveform shape (see constants below)wavegen_set_sweep(start_hz, end_hz, seconds)- Configure a linear sweepwavegen_set_amplitude(vpp)- 0.0–16.0 Vpp (default 3.3 Vpp)wavegen_set_offset(v)- -8.0–+8.0 V (default 1.65 V for 0–3.3 V centered)wavegen_start([run=True])- Start/stop output; calling with False stopswavegen_stop()- Stop output immediately
Getters:
wavegen_get_output()- Get current output channelwavegen_get_freq()- Get current frequencywavegen_get_wave()- Get current waveformwavegen_get_amplitude()- Get current amplitude (Vpp)wavegen_get_offset()- Get current offsetwavegen_is_running()- Check if wavegen is active
Aliases: All setters/getters have set_wavegen_* and get_wavegen_* aliases.
Waveform Constants:
SINE(0) - Sine waveTRIANGLE(1) - Triangle waveSAWTOOTH(2) - Sawtooth/ramp waveRAMP(2) - Alias for SAWTOOTHSQUARE(3) - Square waveARBITRARY(4) - Arbitrary waveform (not yet implemented)
Example:
# Generate a 100Hz sine wave on DAC1
wavegen_set_output(DAC1)
wavegen_set_wave(SINE)
wavegen_set_freq(100)
wavegen_set_amplitude(3.3) # 3.3V peak-to-peak
wavegen_set_offset(1.65) # Center at 1.65V (0-3.3V range)
wavegen_start()
# Check if running
if wavegen_is_running():
print("Wavegen active at " + str(wavegen_get_freq()) + "Hz")
# Change waveform while running
wavegen_set_wave(TRIANGLE)
# Stop
wavegen_stop()
Notes:
- Wavegen runs on core 2 and is fully blocking while active; LEDs and routing updates pause until wavegen_stop().
- Frequency, waveform, amplitude, and offset can be changed live while running.
Net Information API
Functions for querying and modifying net metadata. Nets are groups of connected nodes.
get_net_name(netNum)
Gets the name of a specific net.
netNum: The net number (0 to number of nets - 1).- Returns the net name string, or
Noneif the net doesn't exist.
Example:
name = get_net_name(0)
print("Net 0 is called: " + str(name))
set_net_name(netNum, name)
Sets a custom name for a net.
netNum: The net number.name: The new name string. Pass empty string orNoneto reset to default.
Example:
set_net_name(0, "VCC")
set_net_name(1, "Signal_A")
get_net_color(netNum)
Gets the color of a net as a 32-bit RGB value.
netNum: The net number.- Returns the color as
0xRRGGBB.
Example:
color = get_net_color(0)
print("Net color: " + hex(color)) # e.g., "0xff0000" for red
get_net_color_name(netNum)
Gets the color name of a net as a human-readable string.
netNum: The net number.- Returns a color name like "red", "blue", "green", etc.
Example:
color_name = get_net_color_name(0)
print("Net 0 is " + color_name) # e.g., "Net 0 is red"
set_net_color(netNum, color, [r], [g], [b])
Sets the color of a net by name, hex string, or RGB values.
netNum: The net number.color: Color as a name ("red", "blue", "pink") or hex string ("#FF0000", "0xFF0000").r,g,b(optional): If providing RGB values directly, pass them as separate arguments.- Returns
1on success,0on failure (invalid color).
Available color names: red, orange, amber, yellow, chartreuse, green, seafoam, cyan, blue, royal blue, indigo, violet, purple, pink, magenta, brown, white, black, grey
Example:
# Set by color name
set_net_color(0, "red")
set_net_color(1, "cyan")
# Set by hex string
set_net_color(2, "#FF00FF") # Magenta
set_net_color(3, "0x00FF00") # Green
# Set by RGB values
set_net_color(4, 255, 128, 0) # Orange
set_net_color_hsv(netNum, h, [s], [v])
Sets the color of a net using HSV (Hue, Saturation, Value) color space. Automatically detects whether you're using normalized (0.0-1.0) or full-range (0-255) values based on the hue parameter.
netNum: The net number.h: Hue value. Ifhis between 0.0-1.0, all HSV values are treated as normalized (0.0-1.0). Otherwise, values are treated as 0-255 range.s(optional): Saturation value. Defaults to maximum saturation (255) if not provided or negative.v(optional): Value/brightness. Defaults to 32 (reasonable LED brightness) if not provided or negative.- Returns
1on success,0on failure.
Range auto-detection:
- If h ≤ 1.0: Normalized mode (0.0-1.0 for all values)
- If h > 1.0: Full-range mode (0-255 for all values)
Default brightness (32): This provides good visibility without being overly bright. For maximum brightness, explicitly set v to 1.0 (normalized) or 255 (full-range).
Example:
# Normalized mode (0.0-1.0) - detected because h <= 1.0
set_net_color_hsv(0, 0.0) # Pure red, max saturation, default brightness (32)
set_net_color_hsv(1, 0.33) # Green, max saturation, default brightness (32)
set_net_color_hsv(2, 0.66) # Blue, max saturation, default brightness (32)
set_net_color_hsv(3, 0.5, 0.8) # Cyan with 80% saturation, default brightness (32)
set_net_color_hsv(4, 0.5, 1.0, 0.5) # Cyan with max saturation, 50% brightness
set_net_color_hsv(5, 0.0, 1.0, 1.0) # Pure red at MAXIMUM brightness (255)
# Full-range mode (0-255) - detected because h > 1.0
set_net_color_hsv(6, 0) # Pure red, max saturation, default brightness (32)
set_net_color_hsv(7, 85) # Green (85 ≈ 255/3), default brightness (32)
set_net_color_hsv(8, 170) # Blue (170 ≈ 2*255/3), default brightness (32)
set_net_color_hsv(9, 128, 200) # Cyan-ish with 200/255 saturation, default brightness
set_net_color_hsv(10, 128, 255, 128)# Cyan with max saturation, 50% brightness
set_net_color_hsv(11, 128, 255, 255)# Cyan at MAXIMUM brightness (255)
# Using all defaults (h only)
set_net_color_hsv(12, 0.25) # Yellow with full saturation, brightness 32
set_net_color_hsv(13, 64) # Yellow in 0-255 mode, brightness 32
Why use HSV? HSV is often more intuitive for color selection than RGB: - Hue represents the actual color (red → yellow → green → cyan → blue → magenta → red) - Saturation controls color intensity (0 = grayscale, max = vivid color) - Value controls brightness (0 = black, max = full brightness)
get_num_nets()
Gets the number of currently active nets.
- Returns an integer.
Example:
num = get_num_nets()
print("There are " + str(num) + " nets")
get_num_bridges()
Gets the total number of bridges (connections).
- Returns an integer.
Example:
num = get_num_bridges()
print("There are " + str(num) + " bridges")
get_net_nodes(netNum)
Gets all nodes in a net as a comma-separated string.
netNum: The net number.- Returns a string like "D13,TOP_RAIL,GPIO_1".
Example:
nodes = get_net_nodes(0)
print("Net 0 contains: " + nodes)
get_bridge(bridgeIdx)
Gets information about a specific bridge.
bridgeIdx: The bridge index (0 to number of bridges - 1).- Returns a tuple
(node1, node2, duplicates).
Example:
bridge = get_bridge(0)
print("Bridge 0: " + str(bridge[0]) + " to " + str(bridge[1]))
get_net_info(netNum)
Gets comprehensive information about a net as a dictionary.
netNum: The net number.- Returns a dict with keys:
name,number,color,color_name,nodes.
Example:
info = get_net_info(0)
print("Net name: " + info['name'])
print("Net color: " + info['color_name'])
print("Net nodes: " + info['nodes'])
Path Query API
Functions for inspecting the internal routing paths between nodes. Paths represent the actual physical routes through the crossbar chips that connect nodes together.
Understanding Paths vs Bridges
- Bridges: Direct connections you create (e.g.,
connect(1, 5)) - Paths: The actual routing through crossbar chips to implement those bridges
A single bridge may require multiple paths through different chips. The path query API lets you inspect these internal routing details.
get_num_paths([include_duplicates=True])
Gets the number of routing paths currently in use.
include_duplicates(optional): IfTrue(default), count all paths including duplicates. IfFalse, count only primary (non-duplicate) paths.- Returns an integer.
Example:
total = get_num_paths() # All paths including duplicates
primary = get_num_paths(False) # Only primary paths
print(f"Total paths: {total}, Primary: {primary}")
get_path_info(path_idx)
Gets detailed information about a specific routing path.
path_idx: The path index (0 toget_num_paths()-1)- Returns a dict with keys:
node1,node2,net,chips,x,y,duplicate - Returns
Noneif index is invalid
Example:
path = get_path_info(0)
if path:
print(f"Path from {path['node1']} to {path['node2']}")
print(f"Uses chips: {path['chips']}")
print(f"Is duplicate: {path['duplicate']}")
get_all_paths()
Gets all routing paths as a list of dictionaries.
- Returns a list of path dicts (same format as
get_path_info())
Example:
paths = get_all_paths()
for i, path in enumerate(paths):
print(f"Path {i}: {path['node1']} -> {path['node2']} via net {path['net']}")
get_path_between(node1, node2)
Queries the routing path between two specific nodes.
node1,node2: The nodes to query- Returns a path dict if found,
Noneotherwise
Example:
path = get_path_between(1, 5)
if path:
print(f"Route uses chips: {path['chips']}")
print(f"Crossbar coordinates: x={path['x']}, y={path['y']}")
else:
print("No path found between nodes 1 and 5")
Fake GPIO (Virtual GPIO Pins)
Fake GPIO uses the Jumperless' internal crossbar switches to create virtual GPIO pins on any routable node. Unlike the RP2350's hardware GPIO (limited to 10 routable pins at 0-3.3V), Fake GPIO lets you use any node with custom voltage levels from -8V to +8V, or as inputs, you can have as many as you like and the ADC will switch to that node and take a reading on demand.
This is still pretty new and will probably change in the future
Note: Fake GPIO Outputs are currently disabled until I fix the code, they were causing dead shorts between supplies
Why Use Fake GPIO?
The RP2350's hardware GPIO is limited to 10 routable pins (GPIO_1 through GPIO_8, plus UART TX/RX) with fixed 3.3V logic levels. Fake GPIO extends this by using the crossbar switching matrix to create virtual GPIO pins on any routable node with configurable voltage levels.
Configuring INPUT Pins
FakeGpioPin(node, j.INPUT, threshold_high, threshold_low)
Creates a digital input that reads voltage via the ADC.
Parameters:
node(int, required): Any routable node to read frommode(constant, required):j.INPUTthreshold_high(float, optional): Input HIGH threshold in volts (default: 2.0)threshold_low(float, optional): Input LOW threshold in volts (default: 0.8)
Returns: FakeGpioPin object
Example:
import jumperless as j
# Read a digital signal
button = j.FakeGpioPin(20, j.INPUT, 0.8, 2.0)
state = button.value() # Returns 0 or 1
# Custom thresholds for 5V logic
signal_5v = j.FakeGpioPin(25, j.INPUT, 3.5, 1.5)
if signal_5v.value():
print("5V logic HIGH detected")
FakeGpioPin Methods
pin.value([val])
For INPUT: Reads the current pin state (0 or 1).
# Basic usage
pin = j.FakeGpioPin(20, j.INPUT, 0.8, 2.0)
# Using value()
state = pin.value() # Read current state
System Functions
arduino_reset()
Resets the connected Arduino Nano.
run_app(appName)
Launches a built-in Jumperless application.
appName: The name of the app to run (e.g., "File Manager", "I2C Scan").
pause_core2(pause)
Pauses or resumes core2 processing.
pause:Trueto pause core2,Falseto resume.
For doing time sensitive things where you don't want core 2 to cause timing glitches while it periodically updates the LEDs. Core 2 will resume when you exit the REPL no matter what.
send_raw(chip, x, y, setOrClear)
Sends raw data to core2 for direct chip control.
chip: Chip identifier (string, e.g., "A", "B", "C").x,y: Coordinates for the operation.setOrClear:1to set,0to clear.
You should probably be looking at the schematic if you use this. By bypassing all the routing logic, you can make or break connections in ~1 µs. Pretty handy if want to do high speed switching between known states.
change_terminal_color(color, [flush=True])
Sets the terminal text color using 256-color ANSI codes.
color: Color index (0-255), or -1 to reset to defaultflush(optional): Flush output immediately (default:True)
This is the 6x6x6 color cube that terminals use:

Example:
change_terminal_color(196) # Bright red
print("Error message")
change_terminal_color(-1) # Reset to default
change_terminal_color(46) # Cyan
print("Info message")
cycle_term_color([reset=False], [step=1.0], [flush=True])
Cycles through the terminal color palette.
reset(optional): IfTrue, reset to start of color sequencestep(optional): Color increment step (defaults to the last one you set)flush(optional): Flush output immediately (default:True)
Useful for creating rainbow effects or visually distinguishing output sections. This is really just a helper function for me, it only uses a subset of the colors (I think ~44 of them?) above that actually look good. It takes a float so you can use fractional values if you have more than 44 things and you want a smooth spectrum.
This doesn't currently work in Viper IDE because it strips the escape sequences
Example:
cycle_term_color(True, 1.5) # Start fresh
for i in range(10):
cycle_term_color() # Next color
print(f"Line {i} in different color")
# Visual separator in help output
cycle_term_color(True, step=5.0)

force_service(name)
Forces immediate execution of a specific system service by name.
name: Service name as a string (e.g.,"ProbeButton","Peripherals").- Returns:
Trueif service was found and executed,Falseotherwise.
Useful for manually triggering specific services during tight loops where automatic service scheduling might not run frequently enough.
Example:
while True:
# Fast loop that might miss automatic service updates
connect(1, 2)
force_service("ProbeButton") # Ensure button state updates
button = check_button()
time.sleep(0.001)
force_service_by_index(index)
Forces immediate execution of a specific system service by index (faster than name lookup).
index: Service index (integer, obtained viaget_service_index()).- Returns:
Trueif index valid and service executed,Falseotherwise.
Example:
# Cache the index once for maximum speed
btn_idx = get_service_index("ProbeButton")
while True:
connect(1, 2)
force_service_by_index(btn_idx) # Fastest way to force service
button = check_button()
time.sleep(0.001)
get_service_index(name)
Gets the index of a service by name for use with force_service_by_index().
name: Service name as a string.- Returns: Service index (integer, 0 or higher), or
-1if not found.
Cache the returned index for repeated fast calls to force_service_by_index().
Example:
# Look up once, use many times
probe_idx = get_service_index("ProbeButton")
if probe_idx >= 0:
# Use the cached index in your loop
force_service_by_index(probe_idx)
switch_slot(slot)
Switches to a different connection slot.
slot: The slot number to switch to (0-7).- Returns the previous slot number.
Example:
old_slot = switch_slot(2) # Switch to slot 2
print("Was in slot: " + str(old_slot))
context_toggle()
Toggles the connection context between global and python modes.
- In global mode: Connection changes persist after exiting Python.
- In python mode: Connection state is restored when you exit the REPL.
Example:
context_toggle() # Switch from global to python (or vice versa)
print("Now in " + context_get() + " mode")
context_get()
Gets the current connection context name.
- Returns
"global"or"python".
Example:
if context_get() == "global":
print("Changes will persist after exit")
else:
print("Changes will be discarded on exit")
get_state()
Returns the entire board state as a formatted JSON string. This includes nets, power settings, and GPIO configuration.
Example:
state_json = get_state()
print(state_json)
set_state(json, [clear_first=True], [from_wokwi=False])
Applies a board state from a JSON string or, if from_wokwi is True, from a
Wokwi diagram (provided as raw JSON or filepath on the board).
json: A JSON string representing the state (same format as returned byget_state()), or a filename/Wokwi JSON whenfrom_wokwiis used.clear_first(optional): IfTrue(default), clears all existing connections and FakeGPIO state before applying the new state. Set toFalseto merge the new state with the existing one.from_wokwi(optional): IfTrue, interpretjsonas a Wokwi diagram.json and convert it to a Jumperless state before applying.
Examples:
# Apply a simple state from a string
set_state('{"nets": [{"index": 1, "name": "GND", "nodes": ["GND"]}], "power": {"top_rail": 5.0}}')
# Apply directly from a Wokwi diagram file saved on the board
set_state('/python_scripts/diagram1.json', from_wokwi=True)
# or supply raw Wokwi JSON text
set_state(wokwi_json_string, from_wokwi=True)
Status Functions
These functions print detailed status information to the serial console.
print_bridges(): Prints all active bridges.print_paths(): Prints all resolved paths between nodes.print_crossbars(): Prints the raw state of the crossbar matrix.print_nets(): Prints the current net list.print_chip_status(): Prints the status of the CH446Q chips.
JFS (Jumperless FileSystem)
The jfs module is basically like MicroPython's vfs and parts of os, but kinda written in a style that's probably more familiar to Arduino-style C++ people (me). It uses the almost standardized API shared by FatFS (the one Jumperless actually uses), LittleFS, and SDFS, but still has been Pythonified to use types that are easier to work with in MicroPython.
Usage
import jfs #you don't actually need this, jfs is imported globally by default
# List files in the root directory
files = jfs.listdir('/') # returns a python list
print(files)
['config.txt', 'nodeFileSlot0.txt', 'python_scripts/', 'nodeFileSlot1.txt', 'nodeFileSlot2.txt', 'nodeFileSlot3.txt', 'nodeFileSlot4.txt', 'nodeFileSlot5.txt', 'nodeFileSlot6.txt', 'nodeFileSlot7.txt', 'net_colors/']
If you want to make this print with subdirectories
files = jfs.listdir('/')
for file in range(len(files)):
print(files[file])
if files[file].endswith("/"):
subdir = jfs.listdir(files[file])
for i in range(len(subdir)):
print(" - " + subdir[i])
nodeFileSlot0.txt
python_scripts/
- history.txt
- examples/
- fake_gpio.py
- _temp_repl_edit.py
- Hey.txt
- script_1.py
- script_2.py
- script_3.py
- log.txt
- lib/
- script_4.py
- pathtest.py
nodeFileSlot1.txt
nodeFileSlot2.txt
nodeFileSlot3.txt
nodeFileSlot4.txt
nodeFileSlot5.txt
nodeFileSlot6.txt
nodeFileSlot7.txt
net_colors/
- netColorsSlot0.txt
File API
File objects returned by jfs.open() support method calls directly on the object:
# Object-oriented file operations
# Write-only mode
f = jfs.open('hello.txt', 'w')
f.write('Hello, Jumperless!')
f.close()
# Read from the file (need to reopen or use w+/r+ mode)
f = jfs.open('hello.txt', 'r')
content = f.read() # Read from file object
size = f.size() # Get file size
f.close()
# Read-write mode (truncates file)
f = jfs.open('hello.txt', 'w+')
f.write('Hello, Jumperless!')
f.seek(0) # Seek to beginning to read what we wrote
content = f.read() # Now this works!
f.close()
# Context manager support (automatically closes file)
with jfs.open('data.txt', 'w+') as f:
f.write('This file will be automatically closed')
f.seek(0) # Reset to beginning
content = f.read() # Read back what we wrote
pos = f.tell() # Get current position
name = f.name() # Get file name
Using f.print() for logging
The f.print() method works like Python's print() but writes to the file. It automatically converts arguments to strings and flushes after each call - perfect for logging:
# Great for logging - auto-converts types and flushes immediately
with jfs.open('log.txt', 'w+') as f:
f.print("Starting test...")
voltage = adc_get(0)
f.print("Voltage:", voltage, "V") # Multiple args work
f.print("Test complete!")
# Unlike f.write(), f.print() handles non-strings automatically
f = jfs.open('data.txt', 'w')
f.print(123) # OK - converts int to string
f.print(3.14) # OK - converts float to string
f.print("mixed", 42) # OK - multiple args joined with spaces
f.close()
Note: f.print() is a file object method only. There is no jfs.print() module-level function.
Other ways to do the same thing
#### 2. Module-Level Functions You can also use module-level functions with file handles:f = jfs.open('hello.txt', 'w')
jfs.write(f, 'Hello, Jumperless!') # Module-level function
jfs.seek(f, 0) # Module-level function
content = jfs.read(f) # Module-level function
jfs.close(f) # Module-level function
# Write/read entire files at once (no file handles needed)
jfs.write('config.txt', 'key=value\nother=setting')
content = jfs.read('config.txt')
File Modes
When using jfs.open(path, mode), the following modes are supported:
| Mode | Description | Read | Write | Create |
|---|---|---|---|---|
'r' |
Read only | ✅ | ❌ | ❌ |
'w' |
Write only | ❌ | ✅ | ✅ |
'a' |
Append only | ❌ | ✅ | ✅ |
'r+' |
Read + Write | ✅ | ✅ | ❌ |
'w+' |
Read + Write | ✅ | ✅ | ✅ |
'a+' |
Read + Append | ✅ | ✅ | ✅ |
Important: You cannot read from a file opened in write-only mode ('w' or 'a'). Use 'w+', 'r+', or 'a+' if you need both read and write access.
Open a file for writing
f = jfs.open('hello.txt', 'w')
f.write('Hello, Jumperless!') # Now works with object-oriented API!
f.close()
Directory Operations
jfs.listdir(path)
Returns a list containing the names of the entries in the directory given by path.
path(str): The path to the directory.
Example:
# List contents of the root directory
print(jfs.listdir('/'))
# List contents of a subdirectory
jfs.mkdir('/my_dir')
print(jfs.listdir('/my_dir'))
jfs.mkdir(path)
Create a new directory.
path(str): The path of the new directory.
jfs.rmdir(path)
Remove an empty directory.
path(str): The path of the directory to remove.
jfs.remove(path)
Remove a file.
path(str): The path of the file to remove.
jfs.rename(old_path, new_path)
Rename a file or directory.
old_path(str): The current path.new_path(str): The new path.
jfs.exists(path)
Check if a file or directory exists.
path(str): The path to check.- Returns
Trueif it exists,Falseotherwise.
jfs.stat(path)
Get status of a file or directory.
path(str): The path of the file or directory.- Returns a tuple with file information (mode, size, etc.), similar to
os.stat().
Filesystem Information
jfs.info()
Get information about the filesystem.
- Returns a tuple
(total_bytes, used_bytes, free_bytes).
Example:
total, used, free = jfs.info()
print("Filesystem Size: " + str(total / 1024) + " KB")
print("Used: " + str(used / 1024) + " KB")
print("Free: " + str(free / 1024) + " KB")
File I/O
The jfs module supports standard file opening and handling using jfs.open() and file objects, including support for the with statement for automatic resource management.
jfs.open(path, mode='r')
Open a file and return a corresponding file object.
path(str): The path to the file.mode(str, optional): The mode in which the file is opened. Defaults to'r'.'r': Read (default).'w': Write (creates a new file or truncates an existing one).'a': Append.'r+': Read and write.'w+': Write and read (creates/truncates).'a+': Append and read.
Example:
# Open a file for reading
f = jfs.open('config.txt', 'r')
content = f.read()
f.close()
# Use 'with' for automatic closing
with jfs.open('data.log', 'a') as log_file:
log_file.write('New log entry.\\n')
File Object Methods
The file object returned by jfs.open() has the following methods:
file.read([size])
Read size bytes from the file. If size is omitted or negative, the entire file is read.
file.write(data)
Write the given string or bytes data to the file. Returns the number of bytes written.
file.close()
Close the file. A closed file cannot be read or written to.
file.seek(offset, [whence])
Change the stream position.
* offset: The byte offset.
* whence (optional):
* 0: Seek from the start of the stream (default). Use jfs.SEEK_SET.
* 1: Seek from the current position. Use jfs.SEEK_CUR.
* 2: Seek from the end of the stream. Use jfs.SEEK_END.
file.tell()
Return the current stream position.
* Aliases: file.position()
file.size()
Return the total size of the file in bytes.
file.available()
Return the number of bytes available to be read from the current position to the end of the file.
file.name
Returns the name of the file.
Module-Level File Operations
For convenience, the jfs module also provides functions that operate directly on file handles returned by jfs.open(). This can be useful in some scripting scenarios but using file object methods is generally preferred for clarity.
jfs.read(file_handle, [size])jfs.write(file_handle, data)jfs.close(file_handle)jfs.seek(file_handle, offset, [whence])jfs.tell(file_handle)jfs.size(file_handle)jfs.available(file_handle)
Example:
file_handle = jfs.open('temp.txt', 'w')
jfs.write(file_handle, 'some data')
jfs.close(file_handle)
Help Functions
help()
Displays a comprehensive list of all available functions and constants in the jumperless module.
You can also pass it sections, so help("GPIO") will just print that section.
nodes_help()
Displays a detailed reference for all available node names and their aliases.
Node Names and Constants
The Jumperless module provides extensive node name support with multiple aliases for each node:
# Power rails (multiple aliases supported)
TOP_RAIL = 101 # Also: TOPRAIL, T_R, TOP_R
BOTTOM_RAIL = 102 # Also: BOT_RAIL, BOTTOMRAIL, BOTRAIL, B_R, BOT_R
SUPPLY_3V3 = 103 # Also: 3V3, 3.3V
SUPPLY_5V = 105 # Also: 5V, +5V
SUPPLY_8V_P = 120 # Also: 8V_P, 8V_POS
SUPPLY_8V_N = 121 # Also: 8V_N, 8V_NEG
# Ground connections
GND = 100 # Also: GROUND
TOP_RAIL_GND = 104 # Also: TOP_GND (not actually routable but included for PADs)
BOTTOM_RAIL_GND = 126 # Also: BOT_GND, BOTTOM_GND (not actually routable but included for PADs)
# DAC outputs
DAC0 = 106 # Also: DAC_0, DAC0_5V
DAC1 = 107 # Also: DAC_1, DAC1_8V
# ADC inputs
ADC0 = 110 # Also: ADC_0, ADC0_8V
ADC1 = 111 # Also: ADC_1, ADC1_8V
ADC2 = 112 # Also: ADC_2, ADC2_8V
ADC3 = 113 # Also: ADC_3, ADC3_8V
ADC4 = 114 # Also: ADC_4, ADC4_5V
ADC7 = 115 # Also: ADC_7, ADC7_PROBE, PROBE
# Current sensing
ISENSE_PLUS = 108 # Also: ISENSE_POS, ISENSE_P, INA_P, I_P, CURRENT_SENSE_PLUS, ISENSE_POSITIVE, I_POS
ISENSE_MINUS = 109 # Also: ISENSE_NEG, ISENSE_N, INA_N, I_N, CURRENT_SENSE_MINUS, ISENSE_NEGATIVE, I_NEG
# GPIO pins (multiple naming conventions)
GPIO_1 = 131 # Also: RP_GPIO_1, GPIO1, GP_1, GP1
GPIO_2 = 132 # Also: RP_GPIO_2, GPIO2, GP_2, GP2
GPIO_3 = 133 # Also: RP_GPIO_3, GPIO3, GP_3, GP3
GPIO_4 = 134 # Also: RP_GPIO_4, GPIO4, GP_4, GP4
GPIO_5 = 135 # Also: RP_GPIO_5, GPIO5, GP_5, GP5
GPIO_6 = 136 # Also: RP_GPIO_6, GPIO6, GP_6, GP6
GPIO_7 = 137 # Also: RP_GPIO_7, GPIO7, GP_7, GP7
GPIO_8 = 138 # Also: RP_GPIO_8, GPIO8, GP_8, GP8
# UART pins
UART_TX = 116 # Also: RP_UART_TX, TX, RP_GPIO_16
UART_RX = 117 # Also: RP_UART_RX, RX, RP_GPIO_17
# Additional RP GPIOs
RP_GPIO_18 = 118 # Also: GP_18
RP_GPIO_19 = 119 # Also: GP_19
# Buffer connections
BUFFER_IN = 139 # Also: ROUTABLE_BUFFER_IN, BUF_IN, BUFF_IN, BUFFIN
BUFFER_OUT = 140 # Also: ROUTABLE_BUFFER_OUT, BUF_OUT, BUFF_OUT, BUFFOUT
# Arduino Nano pins (extensive support)
D13 = 83 # Also: NANO_D13
D12 = 82 # Also: NANO_D12
D11 = 81 # Also: NANO_D11
D10 = 80 # Also: NANO_D10
D9 = 79 # Also: NANO_D9
D8 = 78 # Also: NANO_D8
D7 = 77 # Also: NANO_D7
D6 = 76 # Also: NANO_D6
D5 = 75 # Also: NANO_D5
D4 = 74 # Also: NANO_D4
D3 = 73 # Also: NANO_D3
D2 = 72 # Also: NANO_D2
D1 = 71 # Also: NANO_D1
D0 = 70 # Also: NANO_D0
# Arduino Nano analog pins
A0 = 86 # Also: NANO_A0
A1 = 87 # Also: NANO_A1
A2 = 88 # Also: NANO_A2
A3 = 89 # Also: NANO_A3
A4 = 90 # Also: NANO_A4
A5 = 91 # Also: NANO_A5
A6 = 92 # Also: NANO_A6
A7 = 93 # Also: NANO_A7
# Arduino Nano non-routable hardwired connections
VIN = 69 # Unconnected to anything
RST0 = 94 # Hardwired to GPIO 18 on the RP2350
RST1 = 95 # Hardwired to GPIO 19 on the RP2350
N_GND0 = 97 # GND
N_GND1 = 96 # GND
NANO_5V = 99 # Hardwired to USB 5V bus (can also be used to power the Jumperless)
NANO_3V3 = 98 # Unconnected (without bridging the solder jumper on the back)
# Probe switch position constants
SWITCH_MEASURE = 0 # Probe in measure mode
SWITCH_SELECT = 1 # Probe in select mode
SWITCH_UNKNOWN = -1 # Position unknown
# Clickwheel direction constants
CLICKWHEEL_NONE = 0 # No movement
CLICKWHEEL_UP = 1 # Turned clockwise
CLICKWHEEL_DOWN = 2 # Turned counter-clockwise
# Clickwheel button state constants
CLICKWHEEL_IDLE = 0 # Not pressed
CLICKWHEEL_PRESSED = 1 # Just pressed
CLICKWHEEL_HELD = 2 # Being held down
CLICKWHEEL_RELEASED = 3 # Just released
CLICKWHEEL_DOUBLECLICKED = 4 # Double-clicked
The entire output of help()
>>> help()
Jumperless Native MicroPython Module
Available help sections:
help() or help("all") - Show all functions
help("DAC") - DAC functions
help("ADC") - ADC functions
help("GPIO") - GPIO functions
help("PWM") - PWM functions
help("WAVEGEN") - Waveform generator
help("INA") - INA current/power monitor
help("NODES") - Node connections
help("NETS") - Net info (names, colors)
help("SLOTS") - Slot management
help("OLED") - OLED display
help("PROBE") - Probe and button functions
help("CLICKWHEEL") - Clickwheel (rotary encoder) functions
help("STATUS") - Status and debug functions
help("FILESYSTEM") - Filesystem functions
help("MISC") - Miscellaneous functions
help("EXAMPLES") - Usage examples
DAC (Digital-to-Analog Converter):
dac_set(channel, voltage) - Set DAC output voltage
dac_get(channel) - Get DAC output voltage
set_dac(channel, voltage) - Alias for dac_set
get_dac(channel) - Alias for dac_get
channel: 0-3, DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL
channel 0/DAC0: DAC 0
channel 1/DAC1: DAC 1
channel 2/TOP_RAIL: top rail
channel 3/BOTTOM_RAIL: bottom rail
voltage: -8.0 to 8.0V
ADC (Analog-to-Digital Converter):
adc_get(channel) - Read ADC input voltage
get_adc(channel) - Alias for adc_get
channel: 0-4
GPIO:
gpio_set(pin, value) - Set GPIO pin state
gpio_get(pin) - Read GPIO pin state
gpio_set_dir(pin, direction) - Set GPIO pin direction
gpio_get_dir(pin) - Get GPIO pin direction
gpio_set_pull(pin, pull) - Set GPIO pull-up/down
gpio_get_pull(pin) - Get GPIO pull-up/down
Aliases: set_gpio, get_gpio, set_gpio_dir, get_gpio_dir, etc.
pin 1-8: GPIO 1-8
pin 9: UART Tx
pin 10: UART Rx
value: True/False for HIGH/LOW
direction: True/False for OUTPUT/INPUT
pull: -1/0/1/2 for PULLDOWN/NO_PULL/PULLUP/BUS_KEEPER
PWM (Pulse Width Modulation):
pwm(pin, [frequency], [duty]) - Setup PWM on GPIO pin
pwm_set_duty_cycle(pin, duty) - Set PWM duty cycle
pwm_set_frequency(pin, freq) - Set PWM frequency
pwm_stop(pin) - Stop PWM on pin
Aliases: set_pwm, set_pwm_duty_cycle, set_pwm_frequency, stop_pwm
pin: 1-8 GPIO pins only
frequency: 0.001Hz-62.5MHz default 1000Hz
duty_cycle: 0.0-1.0 default 0.5 (50%)
WaveGen (Waveform Generator):
wavegen_set_output(channel) - Set output: DAC0, DAC1, TOP_RAIL, BOTTOM_RAIL
wavegen_set_freq(hz) - Set frequency (0.0001-10000 Hz)
wavegen_set_wave(shape) - Set waveform shape
wavegen_set_amplitude(vpp) - Set amplitude (0-16 Vpp)
wavegen_set_offset(v) - Set DC offset (-8 to +8 V)
wavegen_start() - Start waveform generation
wavegen_stop() - Stop waveform generation
Getters: wavegen_get_output(), wavegen_get_freq(), wavegen_get_wave(),
wavegen_get_amplitude(), wavegen_get_offset(), wavegen_is_running()
Waveform constants: SINE, TRIANGLE, SAWTOOTH (RAMP), SQUARE
INA (Current/Power Monitor):
ina_get_current(sensor) - Read current in amps
ina_get_voltage(sensor) - Read shunt voltage
ina_get_bus_voltage(sensor) - Read bus voltage
ina_get_power(sensor) - Read power in watts
Aliases: get_current, get_voltage, get_bus_voltage, get_power
sensor: 0 or 1
Node Connections:
connect(node1, node2) - Connect two nodes
disconnect(node1, node2) - Disconnect nodes
is_connected(node1, node2) - Check if nodes are connected
nodes_clear() - Clear all connections
set node2 to -1 to disconnect everything connected to node1
Net Information:
get_net_name(netNum) - Get net name
set_net_name(netNum, name) - Set custom net name
get_net_color(netNum) - Get net color as 0xRRGGBB
get_net_color_name(netNum) - Get net color name
set_net_color(netNum, color) - Set net color by name or hex
set_net_color_hsv(netNum, h, [s], [v]) - Set by HSV (auto-detects range)
get_num_nets() - Get number of active nets
get_num_bridges() - Get number of bridges
get_net_nodes(netNum) - Get comma-separated node list
get_bridge(bridgeIdx) - Get bridge info tuple
get_net_info(netNum) - Get full net info as dict
get_num_paths(include_duplicates=True) - Get number of paths (optionally exclude duplicates)
Colors: red, orange, yellow, green, cyan, blue, purple, pink, etc.
HSV: h=0.0-1.0 or 0-255 (auto), s=0-1/0-255 (default max), v=0-1/0-255 (default 32)
Slot Management:
nodes_save([slot]) - Save connections to slot
nodes_discard() - Discard unsaved changes
nodes_has_changes() - Check for unsaved changes
switch_slot(slot) - Switch to different slot (0-7)
CURRENT_SLOT - Get current slot number
Context (controls persistence):
context_toggle() - Toggle global/python mode
context_get() - Get current mode name
OLED Display:
oled_print("text") - Display text
oled_clear() - Clear display
oled_connect() - Connect OLED
oled_disconnect() - Disconnect OLED
Probe Functions:
probe_read([blocking=True]) - Read probe (default: blocking)
read_probe([blocking=True]) - Read probe (default: blocking)
probe_read_blocking() - Wait for probe touch (explicit)
probe_read_nonblocking() - Check probe immediately (explicit)
get_button([blocking], [consume]) - Get button (blocking=True, consume=False)
probe_button([blocking], [consume]) - Get button (blocking=True, consume=False)
check_button([consume]) - Check button non-blocking (consume=False)
probe_button_blocking([consume]) - Wait for button (consume=False)
probe_button_nonblocking([consume]) - Check button immediate (consume=False)
consume=False (default): Holding button returns same state (continuous control)
consume=True: Each press detected once (one-shot detection)
Probe Switch Functions:
get_switch_position() - Get current switch position
set_switch_position(pos) - Set switch position manually
check_switch_position() - Check switch via current sensing
Touch returns: ProbePad object (1-60, D13_PAD, TOP_RAIL_PAD, LOGO_PAD_TOP, etc.)
Button returns: CONNECT, REMOVE, or NONE (front=connect, rear=remove)
Switch returns: SWITCH_MEASURE (0), SWITCH_SELECT (1), SWITCH_UNKNOWN (-1)
Clickwheel (Rotary Encoder):
clickwheel_get_position() - Get raw position counter
clickwheel_reset_position() - Reset position to 0
clickwheel_get_direction([consume=True]) - Get direction event
clickwheel_get_button() - Get button state
clickwheel_is_initialized() - Check if clickwheel is ready
consume=True (default): Direction cleared after reading (one-shot detection)
consume=False: Direction persists until consumed (can read multiple times)
Direction returns: CLICKWHEEL_NONE (0), CLICKWHEEL_UP (1), CLICKWHEEL_DOWN (2)
Button returns: CLICKWHEEL_IDLE (0), CLICKWHEEL_PRESSED (1), CLICKWHEEL_HELD (2),
CLICKWHEEL_RELEASED (3), CLICKWHEEL_DOUBLECLICKED (4)
Status:
print_bridges() - Print all bridges
print_paths() - Print path between nodes
print_crossbars() - Print crossbar array
print_nets() - Print nets
print_chip_status() - Print chip status
Filesystem:
jfs.open(path, mode) - Open file
jfs.read(file, size) - Read from file
jfs.write(file, data) - Write to file
jfs.close(file) - Close file
jfs.exists(path) - Check if file exists
jfs.listdir(path) - List directory
jfs.mkdir(path) - Create directory
jfs.remove(path) - Remove file
jfs.rename(from, to) - Rename file
jfs.info() - Get filesystem info
Misc:
arduino_reset() - Reset Arduino
run_app(appName) - Run built-in app
pause_core2(pause) - Pause/unpause Core2 (True/False)
send_raw(chip, x, y, set) - Send raw data to crossbar chip
force_service(name) - Force run a specific service (e.g., "ProbeButton")
force_service_by_index(idx) - Force run service by index (faster)
get_service_index(name) - Get service index by name (cache for fast calls)
Examples (all functions available globally):
dac_set(DAC0, 5.0) # Set DAC0 using node constant
voltage = get_adc(1) # Read ADC1 using alias
connect(TOP_RAIL, D13) # Connect using constants
connect(4, 20) # Connect using numbers
top_rail = node("TOP_RAIL") # Create node object
oled_print("Hello!") # Display text on OLED
current = get_current(0) # Read current using alias
set_gpio(1, True) # Set GPIO pin high
pwm(1, 1000, 0.5) # 1kHz PWM, 50% duty
wavegen_set_wave(SINE); wavegen_start() # Start sine wave
set_net_color(0, "red") # Color net 0 red
set_net_color_hsv(1, 0.5) # Cyan net 1 (HSV hue)
nodes_save() # Save current connections
pad = probe_read() # Wait for probe touch
button = get_button() # Wait for button press
The entire output of nodes_help()
>>> nodes_help()
Jumperless Node Reference
========================
NODE TYPES:
Numbered: 1-60 (breadboard)
Arduino: D0-D13, A0-A7 (nano header)
GPIO: GPIO_1-GPIO_8 (routable GPIO)
Power: TOP_RAIL, BOTTOM_RAIL, GND
DAC: DAC0, DAC1 (analog outputs)
ADC: ADC0-ADC4, PROBE (analog inputs)
Current: ISENSE_PLUS, ISENSE_MINUS
UART: UART_TX, UART_RX
Buffer: BUFFER_IN, BUFFER_OUT
THREE WAYS TO USE NODES:
1. NUMBERS (direct breadboard holes):
connect(1, 30) # Connect holes 1 and 30
connect(15, 42) # Any number 1-60
2. STRINGS (case-insensitive names):
connect("D13", "TOP_RAIL") # Arduino pin to power rail
connect("gpio_1", "adc0") # GPIO to ADC (case-insensitive)
connect("15", "dac1") # Mix numbers and names
3. CONSTANTS (pre-defined objects):
connect(TOP_RAIL, D13) # Using imported constants
connect(GPIO_1, A0) # No quotes needed
connect(DAC0, 25) # Mix constants and numbers
MIXED USAGE:
my_pin = "D13" # Create node object from string
connect(my_pin, TOP_RAIL) # Use node object with constant
oled_print(my_pin) # Display shows 'D13'
COMMON ALIASES (many names work for same node):
"TOP_RAIL" = "T_R"
"GPIO_1" = "GPIO1" = "GP1"
"DAC0" = "DAC_0"
"UART_TX" = "TX"
NOTES:
- String names are case-insensitive: "d13" = "D13" = "nAnO_d13"
- Constants are case-sensitive: use D13, not d13
- All three methods work in any function