Metadata-Version: 2.5
Name: k804IO
Version: 0.1.1
Summary: A simple library to interact with Onlogic K804 computers Digital IO
Author-email: Matheus Kraemer Bastos do Canto <matheuskramer11@gmail.com>
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.8
Requires-Dist: serial
Description-Content-Type: text/markdown

# k804IO

A small Python library for driving the digital I/O (and LED) outputs of
OnLogic Karbon/K804-series computers over their onboard MCU serial
console.

It wraps the `dio set <group> <channel> <true|false>` shell command
exposed by the OnLogic firmware, so instead of opening a serial port and
writing raw commands by hand you get a small Python object model:
find the device, open the port, declare the channels you want to drive,
and turn them on/off.

## How it works

OnLogic Karbon/K804 units expose an MCU shell over a USB-serial
interface. That shell accepts commands such as:

```
dio set LED0 0 true    # turn on LED channel 0 of group LED0
dio set DIO0 2 false    # turn off digital output channel 2 of group DIO0
```

See OnLogic's firmware shell documentation for the full command
reference: https://static.onlogic.com/resources/firmware/documentation/shell.html

`k804IO` automates:

1. **Finding the device** — polling `/dev/serial/by-id` for an entry
   matching `usb-OnLogic_*if00`.
2. **Opening and quieting the serial console** — disabling the
   `shell_uart` and `onlogic_vcom_can` logs and shell echo so the port
   only carries the commands you send.
3. **Modeling digital channels** as Python objects you can turn on,
   turn off, or pulse for a duration, with optional inverted logic.

## Requirements

- Python >= 3.8
- [`pyserial`](https://pypi.org/project/pyserial/)
- Linux, with the device enumerated under `/dev/serial/by-id/` (relies
  on udev's `by-id` symlinks)
- Permission to access the serial device (typically membership in the
  `dialout` group, or running as root)

## Installation

From the project root:

```bash
pip install .
```

or, for local development:

```bash
pip install -e .
```

## Usage

`Karbon804Terminal` is a context manager: on `__enter__` it searches for
the OnLogic serial device, opens the port, silences shell logging/echo,
and hands you a `kK804DigitalIOController` at
`terminal.digitalIoController`. On `__exit__` it closes the port.

```python
from time import sleep

from k804IO.k804 import Karbon804Terminal

with Karbon804Terminal() as terminal:
  # Declare the channels you intend to drive before using them.
  terminal.digitalIoController.createDigitalChannel("LED0", 0)
  terminal.digitalIoController.createDigitalChannel(
      "DIO0", 0, invertLogic=True
  )

  # Turn a channel on / off.
  terminal.digitalIoController.setDigitalOutput("LED0", 0, True)
  sleep(0.5)
  terminal.digitalIoController.setDigitalOutput("LED0", 0, False)

  # Pulse a channel on, then off, after a delay.
  terminal.digitalIoController.setOnAndOff("LED0", 0, 0.05)
```

See [`src/k804IO/example.py`](src/k804IO/example.py) for a longer
example that cycles through the four `LED0` channels and declares an
inverted-logic `DIO0` group.

### Digital groups and channels

- A **digital group** (e.g. `"LED0"`, `"DIO0"`) is a named array of
  outputs on the MCU firmware side; a **channel** is that array's
  index (e.g. `0`-`3`).
- `invertLogic=True` flips the electrical sense of a channel — calling
  `turnOn()` sends the firmware a `false` command and vice versa. Use
  it for outputs wired active-low.
- Channels must be created with `createDigitalChannel` before they can
  be addressed by `setDigitalOutput` / `setOnAndOff` — the controller
  keeps them in a `{group: {channel: OnlogicDigitalOutput}}` dict and
  will raise a `KeyError` for an undeclared group/channel.

### Device discovery and timeouts

`Karbon804Terminal.findOnlogicSerialPort()` polls
`/dev/serial/by-id` once a second for up to 60 seconds looking for an
entry named `usb-OnLogic_*if00`. If no matching device shows up in
that window, or the port can't be opened, the terminal prints the
error and exits the process (`sys.exit(1)`) rather than raising.

## Project layout

```
src/k804IO/
├── k804.py                    # Karbon804Terminal: device discovery + serial session context manager
├── k804_digital_controller.py # kK804DigitalIOController: channel registry / high-level API
├── onlogic_driver.py          # OnlogicDigitalOutput: builds and sends the raw `dio set` commands
└── example.py                 # Runnable example cycling the LED0 and DIO0 groups
```

## License

MIT — see [`LICENSE`](LICENSE).
