Serial Utility Module

API for interacting with a Free-Wili over serial.

Serial Examples

Search for FreeWilis connected over USB
    from freewili.serial_util import find_all
    from freewili.types import FreeWiliProcessorType

    # Find all main processors
    devices = serial_util.find_all(FreeWiliProcessorType.Main)
    print(f"Found {len(devices)} Main FreeWili(s)")
    for device in devices:
        print(device)

    # Find all display processors
    devices = serial_util.find_all(FreeWiliProcessorType.Display)
    print(f"Found {len(devices)} Display FreeWili(s)")
    for device in devices:
        print(device)
Send a file to the FreeWili
    from freewili.serial_util import find_all
    from freewili.types import FreeWiliProcessorType

    # Find the first Main Processor.
    first_device = freewili.find_all(FreeWiliProcessorType.Main)[0]
    # Send the file to the Main Processor.
    first_device.send_file("my_script.wasm", "/scripts/my_script.wasm").unwrap()
Force main processor into UF2 bootloader
    from freewili.serial_util import find_all
    from freewili.types import FreeWiliProcessorType

    # Find the first Main Processor.
    first_device = freewili.find_all(FreeWiliProcessorType.Main)[0]
    # Send the file to the Main Processor.
    input(f"WARNING: This will force the processor for {first_device} into UF2 bootloader, press any key to continue...")
    first_device.reset_to_uf2_bootloader().unwrap()

fwi-serial command line interface

Included in the freewili module is command line interfaces to allow easy interactions with this API.

$ fwi-serial --help
usage: fwi-serial [-h] [-l] [-v] [-i INDEX] [-di DISPLAY_INDEX]
                  [-mi MAIN_INDEX] [-s SEND_FILE] [-fn FILE_NAME]
                  [-g GET_FILE GET_FILE] [-w [RUN_SCRIPT]] [-io [IO ...]]
                  [-led LED LED LED LED] [-gi GUI_IMAGE] [-gt GUI_TEXT] [-rb]
                  [-rd] [--version]

options:
  -h, --help            show this help message and exit
  -l, --list            List all FreeWili connected to the computer.
  -v, --verbose         Verbose output
  -i INDEX, --index INDEX
                        Select a specific FreeWili by index. The first
                        FreeWili is 1.
  -di DISPLAY_INDEX, --display_index DISPLAY_INDEX
                        Select a specific FreeWili display processor by index.
                        The first FreeWili is 1.
  -mi MAIN_INDEX, --main_index MAIN_INDEX
                        Select a specific FreeWili main processor by index.
                        The first FreeWili is 1.
  -s SEND_FILE, --send_file SEND_FILE
                        send a file to the FreeWili. Argument should be in the
                        form of: <source_file>
  -fn FILE_NAME, --file_name FILE_NAME
                        Set the name of the file in the FreeWili. Argument
                        should be in the form of: <file_name>
  -g GET_FILE GET_FILE, --get_file GET_FILE GET_FILE
                        Get a file from the FreeWili. Argument should be in
                        the form of: <source_file> <target_name>
  -w [RUN_SCRIPT], --run_script [RUN_SCRIPT]
                        Run a script on the FreeWili. If no argument is
                        provided, -fn will be used.
  -io [IO ...], --io [IO ...]
                        Set IO. Argument should be in the form of: <io_pin>
                        <high/low/toggle/pwm> [pwm_freq] [pwm_duty]. No
                        arguments gets all IO values.
  -led LED LED LED LED, --led LED LED LED LED
                        Set Board LEDs. Argument should be in the form of:
                        <LED #> <red 0-255> <green 0-255> <blue 0-255>
  -gi GUI_IMAGE, --gui_image GUI_IMAGE
                        Show GUI Image. Argument should be in the form of:
                        <image path>
  -gt GUI_TEXT, --gui_text GUI_TEXT
                        Show GUI Text. Argument should be in the form of:
                        <text>
  -rb, --read_buttons   Read buttons.
  -rd, --reset_display  Reset the display back to the main menu.
  --version             show program's version number and exit

Serial Module API

Module for serial communication with FreeWili boards.

This module provides functionality to find and control FreeWili boards.

class freewili.serial_util.FreeWiliAppInfo(processor_type: FreeWiliProcessorType, version: int)

Bases: object

Information of the FreeWili application.

processor_type: FreeWiliProcessorType
version: int
class freewili.serial_util.FreeWiliSerial(port: str, stay_open: bool = False, name: str = '')

Bases: object

Class representing a serial connection to a FreeWili.

DEFAULT_SEGMENT_SIZE: int = 8
close(restore_menu: bool = True, block: bool = True, timeout_sec: float = 6.0) None

Close the serial port.

See also: is_open()

Parameters:

restore_menu: bool:

Re-enable the menu before close if True.

block: bool:

If True, block until the serial port is closed.

timeout_sec: float:

number of seconds to wait when blocking.

Returns:

None

Raises:

TimeoutError:

When blocking is True and time elapsed is greater than timeout_sec

enable_stream(enable: bool) None

TODO: Docstring.

get_app_info() Ok[FreeWiliAppInfo] | Err[str]

Detect the processor type of the FreeWili.

Returns:

Result[FreeWiliProcessorType, str]:

Returns Ok(FreeWiliProcessorType) if the command was sent successfully, Err(str) if not.

get_file(source_file: str, destination_path: Path, event_cb: Callable | None) Ok[str] | Err[str]

Get a file from the FreeWili.

Arguments:

source_file: str

Name of the file in the FreeWili. 8.3 filename limit exists as of V12

destination_path: pathlib.Path

file path to save on the PC

event_cb: Callable | None
event callback function. Takes one arguments - a string.

def user_callback(msg: str) -> None

Returns:

Result[str, str]:

Returns Ok(str) if the command was sent successfully, Err(str) if not.

get_io() Ok[tuple[int, ...]] | Err[str]

Get all the IO values.

Parameters:

None

Returns:

Result[tuple[int], str]:

Ok(tuple[int]) if the command was sent successfully, Err(str) if not.

is_open() bool

Return if the serial port is open.

Parameters:

None

Returns:

bool:

True if open, False if closed.

load_fpga_from_file(file_name: str) Ok[str] | Err[str]

Load an FGPA from a file on the FreeWili.

Arguments:

file_name: str

Name of the file in the FreeWili. 8.3 filename limit exists as of V12

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

static needs_open(enable_menu: bool = False, restore_menu: bool = True) Callable

Decorator to open and close serial port.

Expects the class to have an attribute ‘_serial’ that is a serial.Serial object and a method ‘_init_if_necessary’ that initializes the serial port.

Parameters:

enable_menu: bool

Enable menu if True. Defaults to False.

restore_menu: bool

Restore the menu after we are done. Defaults to True.

Example:

>>> class MyClass:
>>>     @needs_open()
>>>     def my_method(self):
>>>         pass
>>>
open(block: bool = True, timeout_sec: float = 6.0) Ok[None] | Err[str]

Open the serial port.

See also: is_open()

Parameters:

block: bool:

If True, block until the serial port is opened.

timeout_sec: float:

number of seconds to wait when blocking.

Returns:

Result[None, str]:

Ok(None) if successful, Err(str) otherwise.

poll_i2c() Ok[ResponseFrame] | Err[str]

Run a script on the FreeWili.

Arguments:

None

Returns:

Result[ResponseFrame, str]:

Ok(ResponseFrame) if the command was sent successfully, Err(str) if not.

read_all_buttons() Ok[dict[ButtonColor, bool]] | Err[str]

Read all the buttons.

Arguments:

None

Returns:

Result[dict[ButtonColor, bool], str]:

Ok(dict[ButtonColor, bool]) if the command was sent successfully, Err(str) if not.

read_i2c(address: int, register: int, data_size: int) Ok[ResponseFrame] | Err[str]

Read I2C data.

Parameters:

addressint

The address to write to.

registerint

The register to write to.

data_sizeint

The number of bytes to read.

Returns:

Result[ResponseFrame, str]:

Ok(ResponseFrame) if the command was sent successfully, Err(str) if not.

read_radio(data: bytes) Ok[bytes] | Err[str]

Read radio data.

Parameters:

databytes

The data to write.

Returns:

Result[bytes, str]:

Ok(bytes) if the command was sent successfully, Err(str) if not.

read_write_spi_data(data: bytes) Ok[bytes] | Err[str]

Read and Write SPI data.

Parameters:

databytes

The data to write.

Returns:

Result[bytes, str]:

Ok(bytes) if the command was sent successfully, Err(str) if not.

reset_display() Ok[str] | Err[str]

Reset the display back to the main menu.

Arguments:

None

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

reset_to_uf2_bootloader() Ok[None] | Err[str]

Reset the FreeWili to the uf2 bootloader.

Returns:

Result[None, str]:

Returns Ok(None) if the command was sent successfully, Err(str) if not.

run_script(file_name: str) Ok[str] | Err[str]

Run a script on the FreeWili.

Arguments:

file_name: str

Name of the file in the FreeWili. 8.3 filename limit exists as of V12

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

send_file(source_file: Path, target_name: str, event_cb: Callable | None, chunk_size: int = 0) Ok[str] | Err[str]

Send a file to the FreeWili.

Arguments:

source_file: pathlib.Path

Path to the file to be sent.

target_name: str

Name of the file in the FreeWili.

event_cb: Callable | None
event callback function. Takes one arguments - a string.

def user_callback(msg: str) -> None

chunk_size: int

Size of the chunks to send in bytes. Typically this should be left at the default value.

Returns:

Result[str, str]:

Returns Ok(str) if the command was sent successfully, Err(str) if not.

set_board_leds(io: int, red: int, green: int, blue: int) Ok[str] | Err[str]

Set the GUI RGB LEDs.

Parameters:

ioint

The number of the IO pin to set.

redint

Red Color 0-255

greenint

Green Color 0-255

blueint

Blue Color 0-255

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

set_io(io: int, menu_cmd: IOMenuCommand, pwm_freq: None | int = None, pwm_duty: None | int = None) Ok[str] | Err[str]

Set the state of an IO pin to high or low.

Parameters:

ioint

The number of the IO pin to set.

menu_cmdIOMenuCommand

Whether to set the pin to high, low, toggle, or pwm.

pwm_freq: None | int

PWM frequency in Hertz

pwm_duty: None | int

PWM Duty cycle (0-100)

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

show_gui_image(fwi_path: str) Ok[str] | Err[str]

Show a fwi image on the display.

Arguments:

fwi_path: str

path to the fwi image

Returns:

Result[ResponseFrame, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

show_text_display(text: str) Ok[str] | Err[str]

Show text on the display.

Arguments:

text: str

text to display on screen.

Returns:

Result[str, str]:

Ok(str) if the command was sent successfully, Err(str) if not.

property stay_open: bool

Keep serial port open, if True.

Returns:

bool

write_i2c(address: int, register: int, data: bytes) Ok[ResponseFrame] | Err[str]

Write I2C data.

Parameters:

addressint

The address to write to.

registerint

The register to write to.

databytes

The data to write.

Returns:

Result[ResponseFrame, str]:

Ok(ResponseFrame) if the command was sent successfully, Err(str) if not.

write_radio(data: bytes) Ok[bytes] | Err[str]

Write radio data.

Parameters:

databytes

The data to write.

Returns:

Result[bytes, str]:

Ok(bytes) if the command was sent successfully, Err(str) if not.

write_uart(data: bytes) Ok[bytes] | Err[str]

Write uart data.

Parameters:

databytes

The data to write.

Returns:

Result[bytes, str]:

Ok(bytes) if the command was sent successfully, Err(str) if not.