Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .cursor/mcp.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
{
"mcpServers": {
"atopile": {
"command": "/Users/narayanpowderly/projects/atopile/.venv/bin/ato",
"command": "/Users/narayanpowderly/Library/Application Support/Cursor/User/globalStorage/atopile.atopile/uv-bin/uv",
"args": [
"tool",
"run",
"-p",
"3.13",
"--from",
"atopile",
"ato",
"mcp",
"start",
"--no-http"
Expand Down
192 changes: 192 additions & 0 deletions .cursor/rules/ato.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -520,3 +520,195 @@ Passive modules (Resistors, Capacitors) are picked automatically by the constrai
To constrain the package do e.g `package = "0402"`.
To explictly pick a part for a module use `lcsc = "<LCSC_PART_NUMBER>"`.


# Creating a package

Package generation process:

Review structure of other pacakges.

1. Create new Directory in 'packages/packages' with naming convention '<vendor>-<device>' eg 'adi-adau145x'
2. create an ato.yaml file in the new directory with the following content:

```yaml
requires-atopile: '^0.9.0'

paths:
src: '.'
layout: ./layouts

builds:
default:
entry: <device>.ato:<device>_driver
example:
entry: <device>.ato:Example
```

3. Create part using tool call 'search_and_install_jlcpcb_part'
4. Import the part into the <device>.ato file
5. Read the datasheet for the device
6. Find common interfaces in the part eg I2C, I2S, SPI, Power

7. Create interfaces and connect them

power interfaces:
power*<name> = new ElectricPower
power*<name>.required = True # If critical to the device
assert power\*<name>.voltage within <minimum*operating_voltage>V to <maximum_operating_voltage>V
power*<name>.vcc ~ <device>.<vcc pin>
power\_<name>.gnd ~ <device>.<gnd pin>

i2c interfaces:
i2c = new I2C
i2c.scl.line ~ <device>.<i2c scl pin>
i2c.sda.line ~ <device>.<i2c sda pin>

spi interfaces:
spi = new SPI
spi.sclk.line ~ <device>.<spi sclk pin>
spi.mosi.line ~ <device>.<spi mosi pin>
spi.miso.line ~ <device>.<spi miso pin>

8. Add decoupling capacitors

looking at the datasheet, determine the required decoupling capacitors

eg: 2x 100nF 0402:

power_3v3 = new ElectricPower

# Decoupling power_3v3

power_3v3_caps = new Capacitor[2]
for capacitor in power_3v3_caps:
capacitor.capacitance = 100nF +/- 20%
capacitor.package = "0402"
power_3v3.hv ~> capacitor ~> power_3v3.lv

9. If device has pin configurable i2c addresses

If format is: <n x fixed address bits><m x pin configured address bits>
use addressor module:

- Use `Addressor<address_bits=N>` where **N = number of address pins**.
- Connect each `address_lines[i].line` to the corresponding pin, and its `.reference` to a local power rail.
- Set `addressor.base` to the lowest possible address and `assert addressor.address is i2c.address`.

10. Create a README.md

# <Manufacturer> <Manufacturer part number> <Short description>

## Usage

```ato
<copy in example>

```

## Contributing

Contributions to this package are welcome via pull requests on the GitHub repository.

## License

This atopile package is provided under the [MIT License](https://opensource.org/license/mit/).

11. Connect high level interfaces directly in example:

eg:

i2c = new I2C
power = new ElectricPower
sensor = new Sensor

i2c ~ sensor.i2c
power ~ sensor.power_3v3

# Additional Notes & Gotchas (generic)

- Multi-rail devices (VDD / VDDIO, AVDD / DVDD, etc.)

- Model separate `ElectricPower` interfaces for each rail (e.g. `power_core`, `power_io`).
- Mark each `.required = True` if the device cannot function without it, and add voltage assertions per datasheet.

- Optional interfaces (SPI vs I²C)

- If the device supports multiple buses, pick one for the initial driver. Leave unused bus pins as `ElectricLogic` lines or expose a second interface module later.

- Decoupling guidance

- If the datasheet shows multiple caps, model the **minimum required** set so the build passes; you can refine values/packages later.

- File / directory layout recap
- `<vendor>-<device>/` – package root
- `ato.yaml` – build manifest (include `default` **and** `example` targets)
- `<device>.ato` – driver + optional example module
- `parts/<MANUFACTURER_PARTNO>/` – atomic part + footprint/symbol/step files

These tips should prevent common "footprint not found", "pin X missing", and build-time path errors when you add new devices.


# Vibe coding a project

If the user gives you high level description of the project, use the following guide:

# How LLMs can design electronics:

#1 Rule: USE THE TOOLS. If the tools dont work, dont freak out, you are probably using them wrong. Ask for help if you get stuck.

Top level design

1. Research available packages relevant to the user requests using 'find_packages'
2. Inspect promising packages using 'inspect_package'
3. Propose packages to use for project and architucture to user, revise if needed
4. Install needed packages using 'install_package'
5. Import packages into main file
6. Create instances of packages in main module

## Power

1. Review for each package the required voltage and current (current may not be provided, use judement if nessesary)
2. Determine the power rails that need to be generated and a suitable tollerance (typically ~3-5% is acceptable)
3. Determine the input power source, typically a battery, USB connector or other power connector (eg XT30) and install relevant package
4. Find suitable regulators:
a) if input voltage > required voltage and current is low, use an LDO package
b) if input voltage > required voltage and current is high, use buck converter
c) if input votlage < required voltage, use a boost converter
d) if input voltage can be both less than or greater than input voltage, use buck boost (eg battery powered device that needs 3v3)
5. If battery powered, add charger package

Typical power architucture example with LDO:

- USB input power
- Low current output (eg microcontroller)

from "atopile/ti-tlv75901/ti-tlv75901.ato" import TLV75901_driver
from "atopile/usb-connectors/usb-connectors.ato" import USBCConn

module App:

# Rails
power_5v = new Power
power_3v3 = new Power

# Components
ldo = new TLV75901_driver
usb_connector = new USBCConn

# Connections
usb_connector.power ~ power_vbus
power_vbus ~> ldo ~> power_3v3

## Communicaions

1. Review packages required interfaces, typically i2c, spi or ElectricLogics
2. Find suitable pins on the controller, typically a microcontroller or Linux SOC
3. Connect interfaces eg micro.i2c[0] ~ sensor.i2c

## Development process notes

- After making changes, be sure to use 'build_project' to update the PCB
- Builds will often generate errors/warnings, these should be reviewed and fixed
- Prioritize pacakges from 'atopile' over other packages


Loading
Loading