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
34 changes: 29 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ jobs:
publish:
runs-on: ubuntu-latest

# Trusted Publishing (OIDC): exchange a short-lived GitHub token for a NuGet
# API key — no long-lived NUGET_API_KEY secret. Requires id-token: write.
permissions:
id-token: write
contents: read

steps:
# ── Checkout ────────────────────────────────────────────────────────────
- name: Checkout
Expand Down Expand Up @@ -75,6 +81,13 @@ jobs:
--no-build
--output ./nupkgs
${{ steps.versioning.outputs.full_version != '' && format('/p:Version={0}', steps.versioning.outputs.full_version) || (steps.versioning.outputs.suffix != '' && format('--version-suffix {0}', steps.versioning.outputs.suffix) || '') }}
- name: Pack Avr8Sharp.TestKit.Core
run: >
dotnet pack src/Avr8Sharp.TestKit.Core/Avr8Sharp.TestKit.Core.csproj
-c Release
--no-build
--output ./nupkgs
${{ steps.versioning.outputs.full_version != '' && format('/p:Version={0}', steps.versioning.outputs.full_version) || (steps.versioning.outputs.suffix != '' && format('--version-suffix {0}', steps.versioning.outputs.suffix) || '') }}
- name: Pack Avr8Sharp.TestKit
run: >
dotnet pack src/Avr8Sharp.TestKit/Avr8Sharp.TestKit.csproj
Expand All @@ -83,19 +96,30 @@ jobs:
--output ./nupkgs
${{ steps.versioning.outputs.full_version != '' && format('/p:Version={0}', steps.versioning.outputs.full_version) || (steps.versioning.outputs.suffix != '' && format('--version-suffix {0}', steps.versioning.outputs.suffix) || '') }}

# ── Push to nuget.org (optional) ─────────────────────────────────────────
# ── NuGet Trusted Publishing login (OIDC) ────────────────────────────────
# Exchanges the workflow's OIDC token for a short-lived nuget.org API key.
# The trusted-publishing policy (owner + repo + workflow) must exist on
# nuget.org, and the account username is provided via the NUGET_USER var.
- name: NuGet login (Trusted Publishing)
id: nuget_login
if: >
${{ github.server_url == 'https://github.com' &&
(startsWith(github.ref, 'refs/tags/v') ||
github.event.inputs.push_public == 'true') }}
uses: NuGet/login@v1
with:
user: ${{ vars.NUGET_USER }}

# ── Push to nuget.org ────────────────────────────────────────────────────
- name: Push to nuget.org
env:
API_KEY: ${{ secrets.NUGET_API_KEY }}
if: >
${{ github.server_url == 'https://github.com' &&
env.API_KEY != '' &&
(startsWith(github.ref, 'refs/tags/v') ||
github.event.inputs.push_public == 'true') }}
run: >
dotnet nuget push "./nupkgs/*.nupkg"
--source https://api.nuget.org/v3/index.json
--api-key "${{ secrets.NUGET_API_KEY }}"
--api-key "${{ steps.nuget_login.outputs.NUGET_API_KEY }}"
--skip-duplicate

- name: Upload NuGet Packages
Expand Down
30 changes: 30 additions & 0 deletions AVR8Sharp.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avr8Sharp.TestKit.Samples",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avr8Sharp", "src\Avr8Sharp\Avr8Sharp.csproj", "{C0AEC60C-FA55-4C55-BC30-2E7941EB783C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avr8Sharp.TestKit.Core", "src\Avr8Sharp.TestKit.Core\Avr8Sharp.TestKit.Core.csproj", "{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avr8Sharp.Native", "src\Avr8Sharp.Native\Avr8Sharp.Native.csproj", "{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -84,6 +88,30 @@ Global
{C0AEC60C-FA55-4C55-BC30-2E7941EB783C}.Release|x64.Build.0 = Release|Any CPU
{C0AEC60C-FA55-4C55-BC30-2E7941EB783C}.Release|x86.ActiveCfg = Release|Any CPU
{C0AEC60C-FA55-4C55-BC30-2E7941EB783C}.Release|x86.Build.0 = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|x64.ActiveCfg = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|x64.Build.0 = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|x86.ActiveCfg = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Debug|x86.Build.0 = Debug|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|Any CPU.Build.0 = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|x64.ActiveCfg = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|x64.Build.0 = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|x86.ActiveCfg = Release|Any CPU
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA}.Release|x86.Build.0 = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|x64.ActiveCfg = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|x64.Build.0 = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|x86.ActiveCfg = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Debug|x86.Build.0 = Debug|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|Any CPU.Build.0 = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|x64.ActiveCfg = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|x64.Build.0 = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|x86.ActiveCfg = Release|Any CPU
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -94,5 +122,7 @@ Global
{0A92DF2E-A13D-4A0B-9CC7-41CD84B85AC4} = {0EAF591C-BC34-4D1F-A9BB-58506ECCEB54}
{8908C29D-3B4B-4E22-AA5D-CB7C11BD4932} = {9B994141-4606-4748-A978-ECA5A59DE073}
{C0AEC60C-FA55-4C55-BC30-2E7941EB783C} = {0EAF591C-BC34-4D1F-A9BB-58506ECCEB54}
{3C04CBC2-72ED-43F4-ABAA-8439414BFFAA} = {0EAF591C-BC34-4D1F-A9BB-58506ECCEB54}
{BB7B9EB7-55E3-45A6-BFB2-A10A816BAC16} = {0EAF591C-BC34-4D1F-A9BB-58506ECCEB54}
EndGlobalSection
EndGlobal
15 changes: 15 additions & 0 deletions bindings/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Python build artifacts
dist/
build/
*.egg-info/
__pycache__/
*.py[cod]

# Native libraries copied in by hatch_build.py at build time
src/avr8sharp/*.dylib
src/avr8sharp/*.so
src/avr8sharp/*.dll

# Virtualenvs
.venv/
venv/
80 changes: 80 additions & 0 deletions bindings/python/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
Business Source License 1.1

License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
"Business Source License" is a trademark of MariaDB Corporation Ab.

-----------------------------------------------------------------------------

Parameters

Licensor: Iván Montiel Cardona
Licensed Work: avr8sharp (the Python bindings and the Avr8Sharp.Native
and Avr8Sharp.TestKit(.Core) layers of the avr8sharp
repository). The Licensed Work is (c) 2025-present
Iván Montiel Cardona.
Additional Use Grant: You may make production use of the Licensed Work,
provided such use does not include offering the Licensed
Work to third parties as a hosted or managed service whose
primary value is the AVR emulation or test-harness
functionality of the Licensed Work.
Change Date: 2029-06-24
Change License: Apache License, Version 2.0

-----------------------------------------------------------------------------

Terms

The Licensor hereby grants you the right to copy, modify, create derivative
works, redistribute, and make non-production use of the Licensed Work. The
Licensor may make an Additional Use Grant, above, permitting limited production
use.

Effective on the Change Date, or the fourth anniversary of the first publicly
available distribution of a specific version of the Licensed Work under this
License, whichever comes first, the Licensor hereby grants you rights under
the terms of the Change License, and the rights granted in the paragraph
above terminate.

If your use of the Licensed Work does not comply with the requirements
currently in effect as described in this License, you must purchase a
commercial license from the Licensor, its affiliated entities, or authorized
resellers, or you must refrain from using the Licensed Work.

All copies of the original and modified Licensed Work, and derivative works
of the Licensed Work, are subject to this License. This License applies
separately for each version of the Licensed Work and the Change Date may vary
for each version of the Licensed Work released by Licensor.

You must conspicuously display this License on each original or modified copy
of the Licensed Work. If you receive the Licensed Work in original or modified
form from a third party, the terms and conditions set forth in this License
apply to your use of that work.

Any use of the Licensed Work in violation of this License will automatically
terminate your rights under this License for the current and all other
versions of the Licensed Work.

This License does not grant you any right in any trademark or logo of
Licensor or its affiliates (provided that you may use a trademark or logo of
Licensor as expressly required by this License).

TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
TITLE.

-----------------------------------------------------------------------------

Notice

The Business Source License (this document, or the "License") is not an Open
Source license. However, the Licensed Work will eventually be made available
under an Open Source License, as stated in this License.

For more information on the use of the Business Source License for the
avr8sharp project, and on how to use it for your own works, see the README and
THIRD_PARTY_NOTICES files distributed with the Licensed Work.

The third-party AVR emulation core (derived from avr8js) bundled in this
package remains under the MIT License; see THIRD_PARTY_NOTICES.
53 changes: 53 additions & 0 deletions bindings/python/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# avr8sharp (Python)

Fast AVR-8 emulator with a pytest-friendly test harness.

`avr8sharp` is a Python binding over the C# [Avr8Sharp](https://github.com/begeistert/avr8sharp)
emulator (itself a port of [avr8js](https://github.com/wokwi/avr8js)), compiled to a
**self-contained Native AOT shared library**. There is **no .NET runtime to install** — the
engine ships inside the wheel.

The per-instruction execution loop stays entirely on the native side. Python only drives
coarse-grained `run_*` calls, so the binding adds negligible overhead and the emulator keeps
its full speed.

## Install

```bash
pip install avr8sharp
```

## Usage

```python
from avr8sharp import ArduinoUno

uno = ArduinoUno().with_hex(open("blink.hex").read())
uno.run_ms(500)

assert uno.port_b.pin_high(5) # digital pin 13
assert "Hello" in uno.serial.text
assert uno.cpu.cycles <= 8_000_000
```

Inline assembly, custom boards, and fast per-test reset are supported too:

```python
from avr8sharp import ArduinoUno

uno = ArduinoUno()
uno.snapshot() # capture power-on state once

uno.with_asm("ldi r16, 0x20\nout 0x04, r16\nout 0x05, r16\nbreak\n").run_to_break()
assert uno.port_b.pin_high(5)

uno.restore() # cheap reset to power-on state between tests
```

Boards: `ArduinoUno` (ATmega328P), `ArduinoMega` (ATmega2560), `ATtiny85`, plus a blank
`Simulation.create(flash, sram)` with manual `add_gpio` / `add_usart0` / `add_timer` wiring.

## License

Business Source License 1.1 (see `LICENSE`). The bundled AVR emulation core (derived from
avr8js) and the .NET runtime remain under the MIT License (see `THIRD_PARTY_NOTICES`).
48 changes: 48 additions & 0 deletions bindings/python/THIRD_PARTY_NOTICES
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
THIRD-PARTY NOTICES
===================

The avr8sharp wheel bundles a self-contained Native AOT shared library
(libavr8sharp.{dylib,so} / avr8sharp.dll). That binary statically links the
following third-party components, whose licenses and notices are reproduced
below. The avr8sharp Python code and the Avr8Sharp.Native / Avr8Sharp.TestKit
layers themselves are licensed under the Business Source License 1.1 (see
LICENSE); the components below are NOT — they retain their own permissive
licenses.

-----------------------------------------------------------------------------
1. Avr8Sharp emulator core (derived from avr8js)
-----------------------------------------------------------------------------

The MIT License (MIT)

Copyright (c) 2019-2023 Uri Shaked
Copyright (c) 2025-present Iván Montiel Cardona

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

-----------------------------------------------------------------------------
2. .NET runtime and base class libraries (Native AOT)
-----------------------------------------------------------------------------

Copyright (c) .NET Foundation and Contributors

Licensed under the MIT License. The .NET runtime libraries statically linked
into the native binary by Native AOT are distributed by Microsoft and the
.NET Foundation under the MIT License:
https://github.com/dotnet/runtime/blob/main/LICENSE.TXT
Loading
Loading