diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f729f45..f43e737 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,14 +25,26 @@ jobs: strategy: fail-fast: false matrix: - environment: [uno, esp32dev, pico] + board: + - fqbn: arduino:avr:uno + name: uno + - fqbn: esp32:esp32:esp32 + name: esp32dev + - fqbn: rp2040:rp2040:rpipico + name: pico + platform: | + - name: rp2040:rp2040 + source-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json + name: compile (${{ matrix.board.name }}) steps: - uses: actions/checkout@v7 - - uses: actions/setup-python@v7 + - uses: arduino/compile-sketches@v1 with: - python-version: "3.14" - - run: python -m pip install "platformio==6.1.18" - - run: pio run -e ${{ matrix.environment }} + fqbn: ${{ matrix.board.fqbn }} + platforms: ${{ matrix.board.platform || '' }} + sketch-paths: | + - examples + enable-warnings-report: true package: runs-on: ubuntu-latest @@ -41,8 +53,9 @@ jobs: - uses: actions/setup-python@v7 with: python-version: "3.14" + - run: python tools/validate_metadata.py - run: python tools/build_release.py - uses: actions/upload-artifact@v7 with: name: ArduinoPatterns - path: dist/ArduinoPatterns-*.zip + path: dist/ArduinoPatterns-*.zip \ No newline at end of file diff --git a/.zenodo.json b/.zenodo.json index fd3d058..0a47b6e 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,21 +1,18 @@ { - "creators": [{"name": "devkyato", "affiliation": "MATA Company"}], + "creators": [{"name": "@dev.mako (devkyato)", "affiliation": "MATA Company"}], "contributors": [{"name": "Cursor Agent", "type": "Other"}], "title": "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino", - "description": "ArduinoPatterns is a small teaching library for coordinating LEDs and other digital outputs without delay(). It provides rollover-safe millis()-based patterns, output banks, and periodic outputs with no heap allocation or board-specific API. Usage: install the library in Arduino IDE or PlatformIO, include ArduinoPatterns.h, and update patterns from loop(). Applications include Arduino lessons, traffic-light demonstrations, ESP32 and RP2040 sketches, responsive user interfaces, and embedded output control.", - "version": "1.0.1", - "keywords": ["Arduino", "LED", "non-blocking", "millis", "library", "education", "ESP32", "RP2040"], + "description": "

Overview

ArduinoPatterns is a compact teaching and prototyping library for coordinating LEDs and other digital outputs without blocking the main loop.

Capabilities

Installation

Download the release ZIP and use Arduino IDE Sketch > Include Library > Add .ZIP Library, or add https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2 to PlatformIO lib_deps.

Quick start

#include <ArduinoPatterns.h>\nconst uint8_t pins[] = {6, 7, 8};\nconst PatternStep steps[] = {{0b001, 5000}, {0b010, 2000}, {0b100, 5000}};\nLedBank lights(pins, 3);\nLedAnimator traffic(lights, steps, 3);\nvoid setup() { lights.begin(); traffic.start(millis()); }\nvoid loop() { traffic.update(millis()); }

Applications

Compatibility, safety, and limitations

The API uses standard Arduino digital I/O and unsigned millisecond arithmetic. CI compile coverage is not hardware validation. GPIO current and voltage limits still apply; use resistors and appropriate drivers for loads. A bank is limited to 32 outputs, callers retain ownership of pin and step arrays, and a zero interval disables periodic toggling.

Documentation

Related software

Arduino Programs Guide is the companion course and introduces the progression that this library generalizes from Exercise B onward.

Citation

@dev.mako (devkyato). (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.2). Zenodo. https://doi.org/10.5281/zenodo.21853284

", + "version": "1.0.2", + "keywords": ["Arduino", "LED", "digital output", "non-blocking", "millis", "state machine", "library", "education", "ESP32", "RP2040"], "license": "mit", "upload_type": "software", "access_right": "open", "language": "eng", "related_identifiers": [ {"identifier": "https://github.com/devkyato/Custom-Arduino-Libraries", "relation": "isSupplementTo", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/Datary", "relation": "references", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/OpenNet", "relation": "references", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/TapAuth", "relation": "references", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/Lowpack", "relation": "references", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/Relay", "relation": "references", "resource_type": "software"}, - {"identifier": "https://github.com/devkyato/Arduino-Programs-Guide", "relation": "references", "resource_type": "software"} + {"identifier": "10.5281/zenodo.21853284", "relation": "isVersionOf", "scheme": "doi"}, + {"identifier": "https://github.com/devkyato/Arduino-Programs-Guide", "relation": "isSupplementTo", "resource_type": "software"}, + {"identifier": "https://docs.arduino.cc/language-reference/en/functions/time/millis/", "relation": "references", "resource_type": "publication"} ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 741b03a..3ec2f21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to ArduinoPatterns are documented here. The project follows [Semantic Versioning](https://semver.org/). +## [1.0.2] - 2026-08-09 + +### Changed + +- Overhaul the README and Zenodo presentation with installation, real code, + applications, limitations, documentation, companion-course links, and an + example-to-concept gallery. +- Expand Citation File Format metadata and align release metadata and attribution + on `@dev.mako (devkyato)`. +- Package API, citation, release-note, and governance documents in the Arduino + IDE ZIP. +- Compile every example across Uno, ESP32, and RP2040 CI targets and validate + release metadata without additional dependencies. + +### Fixed + +- Update the bug-report template's stale example version. + ## [1.0.1] - 2026-08-09 ### Changed @@ -23,3 +41,4 @@ All notable changes to ArduinoPatterns are documented here. The project follows [1.0.0]: https://github.com/devkyato/Custom-Arduino-Libraries/releases/tag/v1.0.0 [1.0.1]: https://github.com/devkyato/Custom-Arduino-Libraries/compare/v1.0.0...v1.0.1 +[1.0.2]: https://github.com/devkyato/Custom-Arduino-Libraries/compare/v1.0.1...v1.0.2 diff --git a/CITATION.cff b/CITATION.cff index 5f97877..91ac2dc 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -2,18 +2,42 @@ cff-version: 1.2.0 message: "If you use this software, please cite it using the metadata from this file." title: "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino" authors: - - family-names: devkyato + - name: "@dev.mako (devkyato)" affiliation: "MATA Company" -version: 1.0.1 +version: 1.0.2 +date-released: 2026-08-09 license: MIT repository-code: "https://github.com/devkyato/Custom-Arduino-Libraries" url: "https://github.com/devkyato/Custom-Arduino-Libraries" -abstract: "Non-blocking LED and digital-output patterns for Arduino." -keywords: [Arduino, LED, non-blocking, millis, library, education, ESP32, RP2040] +doi: 10.5281/zenodo.21853284 +identifiers: + - type: doi + value: 10.5281/zenodo.21853284 +abstract: >- + ArduinoPatterns is a small Arduino library for reusable, non-blocking LED and + digital-output behavior. It provides bit-mask output banks, rollover-safe + millis()-driven animation, and independent periodic outputs without dynamic + allocation, interrupts, external dependencies, or board-specific APIs. Six + examples support teaching and prototyping across Arduino Uno, ESP32, and + RP2040 compile targets. +keywords: + - Arduino + - LED + - digital output + - non-blocking + - millis + - state machine + - embedded systems education + - ESP32 + - RP2040 preferred-citation: type: software title: "ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino" authors: - - family-names: devkyato + - name: "@dev.mako (devkyato)" affiliation: "MATA Company" - version: 1.0.1 + version: 1.0.2 + date-released: 2026-08-09 + repository-code: "https://github.com/devkyato/Custom-Arduino-Libraries" + doi: 10.5281/zenodo.21853284 + license: MIT diff --git a/README.md b/README.md index 645c29a..2d9679f 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,37 @@ # ArduinoPatterns [![CI](https://github.com/devkyato/Custom-Arduino-Libraries/actions/workflows/ci.yml/badge.svg)](https://github.com/devkyato/Custom-Arduino-Libraries/actions/workflows/ci.yml) +[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.21853284.svg)](https://doi.org/10.5281/zenodo.21853284) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) -ArduinoPatterns is a small teaching library for coordinating LEDs and other digital -outputs without `delay()`. It turns the original laboratory sketches in this -repository into reusable components that can run alongside buttons, sensors, -displays, networking, and serial communication. +ArduinoPatterns 1.0.2 is a focused Arduino library for coordinating LEDs and +other digital outputs without blocking `loop()`. It packages common teaching +patterns into reusable components that can run alongside buttons, sensors, +serial communication, displays, or networking. -## Features +## Why ArduinoPatterns - `LedBank`: treat up to 32 output pins as a bit mask. - `LedAnimator`: play timed mask sequences using rollover-safe `millis()` logic. - `PeriodicOutput`: blink independent outputs at different rates. - No heap allocation, third-party dependencies, interrupts, or board-specific API. -- Arduino IDE and PlatformIO examples for traffic lights, scanning, counting, - alternating patterns, and independent blinkers. +- Six compile-checked examples spanning traffic lights, scanners, counters, + alternating masks, and independent blinkers. -## Install +## Installation Download the latest release ZIP and choose **Sketch > Include Library > Add .ZIP Library** in Arduino IDE. In PlatformIO: ```ini lib_deps = - https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.1 + https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2 ``` -## Quick example +To work from source, clone the repository into the Arduino `libraries` folder or +add its root as a local PlatformIO library. + +## Quick start ```cpp #include @@ -53,37 +57,69 @@ void loop() { } ``` -Open **File > Examples > ArduinoPatterns** for complete sketches. The examples map -the original student work into reusable patterns; the original commits remain in -the repository history. +`update()` never waits for a phase to finish, so other application work remains +responsive. + +## Examples gallery + +| Example | Demonstrates | Companion-course connection | +| --- | --- | --- | +| [TrafficLight](examples/TrafficLight/TrafficLight.ino) | timed phases and a three-output mask | elapsed-time scheduling foundation | +| [ScanningLight](examples/ScanningLight/ScanningLight.ino) | forward/reverse animation | [Exercise B](https://github.com/devkyato/Arduino-Programs-Guide/blob/main/docs/lessons/exercise-b.md) and Exercise E | +| [AlternatingPatterns](examples/AlternatingPatterns/AlternatingPatterns.ino) | reusable multi-step mask sequences | Exercise B pattern design | +| [BinaryCounter](examples/BinaryCounter/BinaryCounter.ino) | direct `LedBank` masks and rollover-safe timing | arrays, bit masks, and output mapping | +| [CountUpDown](examples/CountUpDown/CountUpDown.ino) | longer repeating animation tables | progression toward state-machine lessons | +| [IndependentBlink](examples/IndependentBlink/IndependentBlink.ino) | two concurrent periodic outputs | cooperative scheduling used throughout Exercises C–F | -See the [API reference](docs/API.md) for lifecycle, ownership, rollover, and -active-low behavior. +These examples are maintained adaptations of concepts present in the repository's +earlier laboratory sketches; they are not claimed as unchanged originals. Git +history preserves provenance. The companion +[Arduino Programs Guide](https://github.com/devkyato/Arduino-Programs-Guide) +provides a structured course progression and introduces the library as an +optional abstraction from Exercise B onward. + +## Applications -## Compatibility +- Non-blocking traffic lights, scanners, counters, and status indicators. +- Arduino timing, bit-mask, and cooperative state-machine instruction. +- Responsive output patterns alongside sensors, serial, or network activity. +- Active-low LED or relay modules through logical output inversion. + +## Compatibility, safety, and limitations The public API uses only `pinMode`, `digitalWrite`, and unsigned millisecond -arithmetic. CI compiles for Arduino AVR Uno, ESP32, and RP2040. Other Arduino -architectures are expected to work but should be reported as verified only after an -actual compile or hardware test. +arithmetic. CI compiles every example for Arduino AVR Uno, ESP32, and RP2040; +this is source compatibility evidence, not hardware validation. Other Arduino +architectures may work but are unverified. + +- Respect each board's GPIO voltage and current ratings; use a series resistor + for every LED and a suitable driver for relays, motors, or other loads. +- `LedBank` supports 1–32 outputs. The caller must keep pin and pattern arrays + alive for the lifetime of the objects that reference them. +- `millis()` scheduling is rollover-safe, but updates only occur when `update()` + is called; long blocking work elsewhere still delays transitions. +- A zero `PeriodicOutput` interval disables automatic toggling. + +## Documentation index + +- [API reference](docs/API.md) — ownership, lifecycle, active-low behavior, and + rollover semantics. +- [Examples gallery](#examples-gallery) — working sketches mapped to concepts. +- [Contributing guide](CONTRIBUTING.md) — development and test expectations. +- [Security policy](SECURITY.md) — supported release and reporting process. +- [Changelog](CHANGELOG.md) and [1.0.2 release notes](RELEASE_NOTES.md). ## Citation -If you use this software in research or teaching, please cite the Zenodo archive / this repository: +If you use this software in research or teaching, cite the archived release when +available, or use: ```text -devkyato. (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.1). +@dev.mako (devkyato). (2026). ArduinoPatterns: non-blocking LED and digital-output patterns for Arduino (Version 1.0.2). Zenodo. https://doi.org/10.5281/zenodo.21853284 ``` See [CITATION.cff](CITATION.cff) for machine-readable metadata. -## Applications - -- Non-blocking LED and traffic-light demonstrations. -- Arduino timing and state-machine lessons. -- Responsive ESP32 and RP2040 digital-output sketches. -- Reusable output patterns alongside sensors and serial communication. - ## Contributing Student-friendly issues are labeled `good first issue`. Changes should remain diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..47dabbd --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1,31 @@ +# ArduinoPatterns 1.0.2 + +Publication and documentation quality release for Zenodo archival presentation. + +## Highlights + +- Expand README installation, applications, limitations, documentation index, and citation guidance. +- Add an examples gallery that maps each sketch to concepts and the companion Arduino Programs Guide. +- Package `docs/API.md`, `CITATION.cff`, release notes, and governance files in the Arduino IDE ZIP. +- Align metadata attribution on `@dev.mako (devkyato)` and validate release metadata before packaging. +- Compile every example across Uno, ESP32, and RP2040 CI targets. + +## Install + +Arduino IDE: download `ArduinoPatterns-1.0.2.zip` and choose **Sketch > Include Library > Add .ZIP Library**. + +PlatformIO: + +```ini +lib_deps = + https://github.com/devkyato/Custom-Arduino-Libraries.git#v1.0.2 +``` + +## Citation + +Concept DOI: https://doi.org/10.5281/zenodo.21853284 + +See `CITATION.cff` for machine-readable citation metadata. + +Published by @dev.mako (devkyato). Cursor Agent is acknowledged as a non-author contributor. + diff --git a/library.json b/library.json index 5018208..262ef6e 100644 --- a/library.json +++ b/library.json @@ -1,13 +1,13 @@ { "name": "ArduinoPatterns", - "version": "1.0.1", - "description": "Non-blocking LED and digital-output patterns for Arduino.", - "keywords": ["arduino", "led", "non-blocking", "millis", "education"], + "version": "1.0.2", + "description": "Rollover-safe, non-blocking LED and digital-output patterns for Arduino without interrupts or heap allocation.", + "keywords": ["arduino", "led", "digital-output", "non-blocking", "millis", "state-machine", "education"], "repository": { "type": "git", "url": "https://github.com/devkyato/Custom-Arduino-Libraries.git" }, - "authors": [{"name": "devkyato", "maintainer": true}], + "authors": [{"name": "@dev.mako (devkyato)", "maintainer": true}], "license": "MIT", "frameworks": ["arduino"], "platforms": "*", diff --git a/library.properties b/library.properties index e6c489b..0ebee26 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=ArduinoPatterns -version=1.0.1 -author=devkyato and contributors -maintainer=devkyato +version=1.0.2 +author=@dev.mako (devkyato) and contributors +maintainer=@dev.mako (devkyato) sentence=Non-blocking LED and digital-output patterns for Arduino. -paragraph=Coordinate timed LED sequences, bit-mask output banks, and independent periodic outputs without delay() or heap allocation. +paragraph=Coordinate rollover-safe timed LED sequences, bit-mask output banks, and independent periodic outputs without delay(), interrupts, or heap allocation. category=Signal Input/Output url=https://github.com/devkyato/Custom-Arduino-Libraries architectures=* diff --git a/tools/build_release.py b/tools/build_release.py index 6d201ab..3f4cb2e 100644 --- a/tools/build_release.py +++ b/tools/build_release.py @@ -11,8 +11,14 @@ INCLUDED = ( "src", "examples", + "docs", "README.md", "CHANGELOG.md", + "RELEASE_NOTES.md", + "CITATION.cff", + "CONTRIBUTING.md", + "CODE_OF_CONDUCT.md", + "SECURITY.md", "LICENSE", "library.properties", "library.json", @@ -54,6 +60,8 @@ def main() -> None: with zipfile.ZipFile(output) as archive: required = { + "ArduinoPatterns/CITATION.cff", + "ArduinoPatterns/docs/API.md", "ArduinoPatterns/library.properties", "ArduinoPatterns/src/ArduinoPatterns.h", } diff --git a/tools/validate_metadata.py b/tools/validate_metadata.py new file mode 100644 index 0000000..3559ee7 --- /dev/null +++ b/tools/validate_metadata.py @@ -0,0 +1,94 @@ +"""Validate release versions and Zenodo's restricted HTML description.""" + +from __future__ import annotations + +import json +import re +from html.parser import HTMLParser +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[1] +ALLOWED_TAGS = {"p", "h2", "ul", "li", "pre", "code", "a", "strong"} +REQUIRED_SECTIONS = { + "Overview", + "Capabilities", + "Installation", + "Quick start", + "Applications", + "Compatibility, safety, and limitations", + "Documentation", + "Related software", + "Citation", +} + + +class DescriptionValidator(HTMLParser): + def __init__(self) -> None: + super().__init__(convert_charrefs=True) + self.errors: list[str] = [] + self.headings: list[str] = [] + self._in_h2 = False + + def handle_starttag( + self, tag: str, attrs: list[tuple[str, str | None]] + ) -> None: + if tag not in ALLOWED_TAGS: + self.errors.append(f"disallowed HTML tag: {tag}") + if tag == "a": + if {name for name, _ in attrs} - {"href"}: + self.errors.append("links may only use the href attribute") + elif attrs: + self.errors.append(f"attributes are not allowed on {tag}") + self._in_h2 = tag == "h2" + + def handle_endtag(self, tag: str) -> None: + if tag not in ALLOWED_TAGS: + self.errors.append(f"disallowed closing tag: {tag}") + if tag == "h2": + self._in_h2 = False + + def handle_data(self, data: str) -> None: + if self._in_h2: + self.headings.append(data.strip()) + + +def property_version() -> str: + text = (ROOT / "library.properties").read_text(encoding="utf-8") + match = re.search(r"^version=(.+)$", text, re.MULTILINE) + if not match: + raise ValueError("library.properties has no version") + return match.group(1) + + +def main() -> None: + version = property_version() + zenodo = json.loads((ROOT / ".zenodo.json").read_text(encoding="utf-8")) + library_json = json.loads((ROOT / "library.json").read_text(encoding="utf-8")) + cff = (ROOT / "CITATION.cff").read_text(encoding="utf-8") + readme = (ROOT / "README.md").read_text(encoding="utf-8") + + assert version == "1.0.2" + assert zenodo["version"] == version + assert library_json["version"] == version + assert re.search(rf"^version: {re.escape(version)}$", cff, re.MULTILINE) + assert f"ArduinoPatterns {version}" in readme + assert zenodo["creators"] == [ + {"name": "@dev.mako (devkyato)", "affiliation": "MATA Company"} + ] + assert {"name": "Cursor Agent", "type": "Other"} in zenodo["contributors"] + + parser = DescriptionValidator() + parser.feed(zenodo["description"]) + parser.close() + missing = REQUIRED_SECTIONS.difference(parser.headings) + if parser.errors or missing: + raise ValueError( + f"invalid Zenodo description: errors={parser.errors}, " + f"missing sections={sorted(missing)}" + ) + + print(f"metadata valid for ArduinoPatterns {version}") + + +if __name__ == "__main__": + main()