[
  {
    "path": ".cargo/config.toml",
    "content": "[alias]\nxtask = \"run --package xtask --\"\n\n# For micro:bit v1.x\n\n[target.thumbv6m-none-eabi]\nrunner = 'probe-rs run --chip nRF51822_xxAA --protocol swd'\nrustflags = [\n  \"-C\", \"linker=flip-link\",\n  \"-C\", \"link-arg=-Tlink.x\",\n  \"-C\", \"link-arg=-Tdefmt.x\",\n]\n\n# For micro:bit v2\n\n[target.thumbv7em-none-eabi]\nrunner = \"probe-rs run --chip nRF52833_xxAA --protocol swd\"\nrustflags = [\n  \"-C\", \"linker=flip-link\",\n  \"-C\", \"link-arg=-Tlink.x\",\n  \"-C\", \"link-arg=-Tdefmt.x\",\n]\n\n[target.thumbv7em-none-eabihf]\nrunner = \"probe-rs run --chip nRF52833_xxAA --protocol swd\"\nrustflags = [\n  \"-C\", \"linker=flip-link\",\n  \"-C\", \"link-arg=-Tlink.x\",\n  \"-C\", \"link-arg=-Tdefmt.x\",\n]\n\n# Enable printing of defmt debug, info and warning messages by default\n[env]\nDEFMT_LOG=\"debug\"\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/changelog.yml",
    "content": "on:\n  pull_request_target:\n    types: [opened, synchronize, reopened, labeled, unlabeled]\n\nname: Changelog check\n\njobs:\n  changelog:\n    name: Changelog check\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout sources\n        uses: actions/checkout@v6\n\n      - name: Changelog updated\n        uses: Zomzog/changelog-checker@v1.3.0\n        with:\n          fileName: CHANGELOG.md\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "on:\n  push:\n    branches: main\n  pull_request:\n  merge_group:\n\njobs:\n  ci:\n    name: CI\n    runs-on: ubuntu-latest\n    needs: [build]\n    if: always()\n    steps:\n      - name: Done\n        run: jq --exit-status 'all(.result == \"success\")' <<< '${{ toJson(needs) }}'\n\n  build:\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        rust:\n          - stable\n          - beta\n          - nightly\n        include:\n          # Minimum supported rust version (MSRV)\n          # Note this needs to be new enough to build the examples as well as\n          # the library itself.\n          - name: MSRV\n            rust: 1.85.0\n\n    name: \"build (${{ matrix.name || matrix.rust }})\"\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - name: Install Rust\n        uses: actions-rs/toolchain@v1\n        with:\n          profile: minimal\n          toolchain: ${{ matrix.rust }}\n          override: true\n          components: rustfmt, clippy\n\n      - name: rustfmt\n        run: cargo fmt -- --check\n\n      - name: build\n        run: cargo xtask ci\n"
  },
  {
    "path": ".github/workflows/clippy.yml",
    "content": "on:\n  push:\n    branches: main\n  pull_request:\n  merge_group:\n\nname: Clippy check\njobs:\n  clippy_check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - run: rustup component add clippy\n      - uses: actions-rs/toolchain@v1\n        with:\n          toolchain: stable\n          target: thumbv6m-none-eabi\n          override: true\n\n      - name: microbit V1\n        run: cargo clippy --package microbit -- -D warnings\n\n      - name: microbit V2\n        run: cargo clippy --package microbit-v2 -- -D warnings\n"
  },
  {
    "path": ".github/workflows/rustfmt.yml",
    "content": "on:\n  push:\n    branches: main\n  pull_request:\n  merge_group:\n\nname: Code formatting check\n\njobs:\n  fmt:\n    name: Rustfmt\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6\n      - uses: actions-rs/toolchain@v1\n        with:\n          profile: minimal\n          toolchain: stable\n          override: true\n      - run: rustup component add rustfmt\n      - uses: actions-rs/cargo@v1\n        with:\n          command: fmt\n          args: --all -- --check\n"
  },
  {
    "path": ".gitignore",
    "content": "/target/\n**/*.orig\n**/*.rs.bk\nbloat_log*\n!.gitignore\n!.github\n!.cargo\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](http://keepachangelog.com/)\nand this project adheres to [Semantic Versioning](http://semver.org/).\n\n## [Unreleased]\n\n- Bumped MSRV to 1.85.0\n- Updated `examples/hal-rng/` to use latest `rand_pcg`,\n  removing `rand` dependency and bumping to Rust 2024\n- Added SPIM peripherals to Board struct\n\n## [0.16.0] - 2025-10-11\n\n- Remove dead link to microbit Rust on Windows blog post in README.\n- Bumped MSRV to 1.81.0.\n- Add metadata for docs.rs\n- Bumped dependencies in `examples/` to latest versions.\n- Update HAL crates to 0.19.0.\n\n## [0.15.1] - 2024-08-05\n\n- Set MSRV for `microbit` and `microbit-v2` crates.\n- Bumped MSRV to 1.79.0.\n- Make various `I2C` `Pin` fields `pub`\n\n## [0.15.0] - 2024-06-19\n\n- Update HAL crates to 0.18.0.\n- Update installation instructions for `probe-rs`\n\n## [0.14.0] - 2024-04-18\n\n- Fix: non-blocking display on micro:bit V2 could spuriously light LEDs briefly\n- Fix the `blocking::Display::set_refresh_rate` calculation for the micro:bit V2\n- Double the non-blocking display refresh frequency for the micro:bit V2\n- Fix faulty doc test in `blocking.rs`\n- Update the non-blocking display documentation to better explain when methods\n  should be called from within a critical section\n- Bump example dependencies to latest versions to fix build\n- Update examples to use RTIC 1.0\n- Add ADC for micro:bit V1\n- Add analog example\n- Increase minimum supported Rust version to 1.73\n- Added support for the real time counters RTC1 and RTC2\n- Add common types and structs for the edge connector pads and pins\n- Add common ADC types and initialization for ADC and SAADC\n- Common ADC example\n- Add support for PPI\n- Servo example using TIMER, GPIOTE and PPI\n- (NFC) GitHub CI changes\n- Feature: Exposed all remaining peripherals for both boards.\n- Update HAL crates to 0.17.1.\n- Update to `embedded-hal` 1.0.\n- Update magnetometer example to use `lsm303agr` 1.0.\n- Update debug tooling from probe-run to probe-rs\n\n## [0.13.0] - 2022-05-24\n\n- Drop ble-beacon example (since rubble is now archived as unmaintained)\n- Bump `defmt` versions to 0.3\n- Increase minimum supported Rust version to 1.57\n- Add display-text-rtic example\n- Make `Board::new(p, cp)` public and fix RTIC example\n- Fix display-nonblocking example\n- Fix timer for LED-display (GreyscaleImage with a empty Row did not work)\n- Add SAADC and microphone_pins for micro:bit V2.\n- Add microphone example\n\n## [0.12.0] - 2021-11-10\n\n### Changed\n\n- Update dependencies nrf51-hal and nrf52833-hal to 0.14.0\n- Added TEMP field to board\n- Fixed Issue where columns 2,3 and 4 of the nonblocking display were swapped\n\n## [0.11.0] - 2021-09-13\n\n### Added\n\n- Added support for the thumbv7em-none-eabi target for microbit:v2 (same as\n  thumbv7em-none-eabihf but without hardware floating point support)\n\n### Changed\n\n- Rearrange LED display modules under the same root module and change their\n  APIs to be more aligned with each other.\n- Add BLE Beacon demo.\n- Add a simple speaker demo for micro:bit V2.\n- Add Board struct following the pattern used in other nrf board support crates.\n- Add magnetometer example.\n- LEDs on the micro:bit V1 are now turned off per default\n- UART(E) is now exposed in the same way as I2C\n\n## [0.10.1] - 2021-05-25\n\nRepublished without changes to fix missing README.md in crates.io.\n\n## [0.10.0] - 2021-05-13\n\n### Added\n\n- Add support for micro:bit V2. This is a significant change that splits\n  this repository into multiple crates.\n\n## [0.9.0] - 2021-04-29\n\n### Added\n\n- Add `microbit::gpio` module with pins mapped to micro:bit names\n- Refactor `microbit::display` and `microbit::led` to accept `gpio::Pins`\n- Make probe-run the default runner\n- Rewrite `serial_port` as a macro\n\n### Fixed\n\n- Fix rustdoc warnings\n- Upgrade nrf51-hal to 0.12.1\n\n[Unreleased]: https://github.com/nrf-rs/microbit/compare/v0.16.0...HEAD\n[0.16.0]: https://github.com/nrf-rs/microbit/compare/v0.15.1...v0.16.0\n[0.15.1]: https://github.com/nrf-rs/microbit/compare/v0.15.0...v0.15.1\n[0.15.0]: https://github.com/nrf-rs/microbit/compare/v0.14.0...v0.15.0\n[0.14.0]: https://github.com/nrf-rs/microbit/compare/v0.13.0...v0.14.0\n[0.13.0]: https://github.com/nrf-rs/microbit/compare/v0.12.0...v0.13.0\n[0.12.0]: https://github.com/nrf-rs/microbit/compare/v0.11.0...v0.12.0\n[0.11.0]: https://github.com/nrf-rs/microbit/compare/v0.10.1...v0.11.0\n[0.10.1]: https://github.com/nrf-rs/microbit/compare/v0.10.0...v0.10.1\n[0.10.0]: https://github.com/nrf-rs/microbit/compare/v0.9.0...v0.10.0\n[0.9.0]: https://github.com/nrf-rs/microbit/compare/v0.8.0...v0.9.0\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"microbit-common\",\n  \"microbit\",\n  \"microbit-v2\",\n  \"examples/*\",\n  \"xtask\",\n]\n\n# Modify default build profiles to make debugging easier\n[profile.release]\ndebug = 2\nlto = \"off\"\n\n[profile.dev]\ndebug = 2\nopt-level = 1\nlto = \"off\"\n"
  },
  {
    "path": "LICENSE-0BSD.txt",
    "content": "Copyright (C) 2018 daniel@eggers-club.de\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\nSPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# microbit\n\n_microbit_ contains everything required getting started using Rust to create firmwares for the fabulous\n[BBC micro:bit](https://microbit.org) microcontroller board. This little board has everything and a kitchen sink built-in,\neven a capable debugging interface.\n\n## Getting started\n\nAll you need to start programming this device is:\n\n* A BBC micro:bit board\n* A computer (known to work with macOS, Linux and Windows)\n* A bit of open source software\n\n### Know your version\n\nThe micro:bit comes in different versions. There is a separate crate for each major board version. See the table below to identify\nwhich crate you need to use.\n\n| Crate                          | Board version | Board image | Docs | crates.io | target |\n| ------------------------------ | ------------- | ----------- | ---- | --------- | ------ |\n| [`microbit`](./microbit)       | V1 | [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-1-5.png\" width=\"124px\" height=\"100px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-1-5.png) | [![docs.rs](https://docs.rs/microbit/badge.svg)](https://docs.rs/microbit) | [![crates.io](https://img.shields.io/crates/d/microbit.svg)](https://crates.io/crates/microbit) | `thumbv6m-none-eabi` |\n| [`microbit-v2`](./microbit-v2) | V2 | [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-2.png\" width=\"124px\" height=\"100px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-2.png) | [![docs.rs](https://docs.rs/microbit-v2/badge.svg)](https://docs.rs/microbit-v2) | [![crates.io](https://img.shields.io/crates/d/microbit-v2.svg)](https://crates.io/crates/microbit-v2) | `thumbv7em-none-eabihf` |\n\n### Install dependencies\n\nThe examples make use of some of the fantastic tooling from the [knurling](https://knurling.ferrous-systems.com/) and [probe-rs](https://probe.rs/) projects.\nIn order to run the examples you need to install [`probe-rs`](https://probe.rs/docs/getting-started/installation)\nand [`flip-link`](https://github.com/knurling-rs/flip-link#installation).\n\n```bash\n> cargo install probe-rs-tools flip-link\n```\n\n### Run an example\n\nThe first thing to try is one of the [examples](./examples) in this repository. Plug in your micro:bit and\nrun one of the commands below.\n\n*For micro:bit V1*\n```bash\n> cargo run --release --manifest-path ./examples/display-blocking/Cargo.toml --features v1 --target thumbv6m-none-eabi\n```\n\n*For micro:bit V2*\n```bash\n> cargo run --release --manifest-path ./examples/display-blocking/Cargo.toml --features v2 --target thumbv7em-none-eabihf\n```\n\nYou should see a lot of build output, the orange LED on the back of the micro:bit should flash quickly, and\na message should appear on the LED display.\n\nCongratulations! You've flashed your first Rust program onto your micro:bit!\n\n## Further reading\n\nA guide to embedded development with Rust on the _micro:bit_ using this crate can be found in the [MicroRust book](https://droogmic.github.io/microrust/).\n\nOther useful resources:\n- [micro:bit developer community](https://tech.microbit.org)\n- [micro:bit hardware overview](https://tech.microbit.org/hardware/)\n- [nrf-hal](https://github.com/nrf-rs/nrf-hal#readme) the hardware abstraction layer (HAL) this repository is based on\n\n## License\n\n[0-clause BSD license](LICENSE-0BSD.txt).\n"
  },
  {
    "path": "build.rs",
    "content": "use std::env;\nuse std::fs::File;\nuse std::io::Write;\nuse std::path::PathBuf;\n\nfn main() {\n    // Put the linker script somewhere the linker can find it\n    let out = &PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n    File::create(out.join(\"memory.x\"))\n        .unwrap()\n        .write_all(include_bytes!(\"memory.x\"))\n        .unwrap();\n    println!(\"cargo:rustc-link-search={}\", out.display());\n\n    // Only re-run the build script when memory.x is changed,\n    // instead of when any part of the source code changes.\n    println!(\"cargo:rerun-if-changed=memory.x\");\n}\n"
  },
  {
    "path": "examples/analog/Cargo.toml",
    "content": "[package]\nname = \"analog\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/analog/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    adc::{Adc, AdcConfig, Default},\n    board::Board,\n    display::blocking::Display,\n    hal::Timer,\n};\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let mut timer = Timer::new(board.TIMER0);\n        let mut display = Display::new(board.display_pins);\n        let mut adc = Adc::new(board.ADC, AdcConfig::default_10bit());\n        let mut anapin = board.edge.e00.into_floating_input(); // PAD0\n\n        let numbers = [\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 0, 0],\n                [0, 1, 1, 1, 0],\n            ],\n            [\n                [0, 1, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 1, 1, 0, 0],\n            ],\n            [\n                [0, 1, 0, 0, 0],\n                [1, 0, 0, 0, 0],\n                [1, 0, 1, 0, 0],\n                [1, 1, 1, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n        ];\n\n        let sign_plus = [\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [1, 1, 1, 1, 1],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n        ];\n\n        #[cfg(feature = \"v2\")]\n        #[allow(non_snake_case)]\n        let letter_E = [\n            [0, 1, 1, 1, 0],\n            [0, 1, 0, 0, 0],\n            [0, 1, 1, 0, 0],\n            [0, 1, 0, 0, 0],\n            [0, 1, 1, 1, 0],\n        ];\n\n        loop {\n            let analog = adc.read_channel(&mut anapin);\n            #[cfg(feature = \"v2\")]\n            let Ok(analog) = analog\n            else {\n                display.show(&mut timer, letter_E, 10);\n                continue;\n            };\n            let n_iter = numbers.iter();\n            let mut count: usize = 0;\n            for n_val in n_iter {\n                if count == usize::from(i16::unsigned_abs(analog / 100)) {\n                    display.show(&mut timer, *n_val, 10);\n                    break;\n                }\n                count += 1;\n            }\n            if count == numbers.len() {\n                display.show(&mut timer, sign_plus, 10);\n            }\n        }\n    }\n    panic!(\"End\");\n}\n"
  },
  {
    "path": "examples/analog-v1/Cargo.toml",
    "content": "[package]\nname = \"analog-v1\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n# NOTE: This currently only works with the microbit v1 due to naming issues!\n# ADC vs SAADC\n[dependencies.microbit]\npath = \"../../microbit\"\n\n[features]\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/analog-v1/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Board,\n    display::blocking::Display,\n    hal::{adc::AdcConfig, Adc, Timer},\n};\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let mut timer = Timer::new(board.TIMER0);\n        let mut display = Display::new(board.display_pins);\n        let mut adc: Adc = Adc::new(board.ADC, AdcConfig::default());\n        let mut anapin = board.edge.e00.into_floating_input(); // PAD1\n\n        let numbers = [\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 0, 0],\n                [0, 1, 1, 1, 0],\n            ],\n            [\n                [0, 1, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 1, 1, 0, 0],\n            ],\n            [\n                [0, 1, 0, 0, 0],\n                [1, 0, 0, 0, 0],\n                [1, 0, 1, 0, 0],\n                [1, 1, 1, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n        ];\n\n        let sign_plus = [\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [1, 1, 1, 1, 1],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n        ];\n\n        loop {\n            let analog_value = adc.read_channel(&mut anapin);\n            let n_iter = numbers.iter();\n            let mut count: usize = 0;\n            for n_val in n_iter {\n                if count == usize::from(i16::unsigned_abs(analog_value / 100)) {\n                    display.show(&mut timer, *n_val, 10);\n                    break;\n                }\n                count += 1;\n            }\n            if count == numbers.len() {\n                display.show(&mut timer, sign_plus, 10);\n            }\n        }\n    }\n    panic!(\"End\");\n}\n"
  },
  {
    "path": "examples/analog-v2/Cargo.toml",
    "content": "[package]\nname = \"analog-v2\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n# NOTE: This currently only works with the microbit v2 due to naming issues!\n# ADC vs SAADC\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\n\n[features]\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/analog-v2/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Board,\n    display::blocking::Display,\n    hal::{saadc::SaadcConfig, Saadc, Timer},\n};\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let mut timer = Timer::new(board.TIMER0);\n        let mut display = Display::new(board.display_pins);\n        let mut adc: Saadc = Saadc::new(board.ADC, SaadcConfig::default());\n        let mut anapin = board.edge.e00.into_floating_input(); // PAD1\n\n        let numbers = [\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 1, 0, 0],\n            ],\n            [\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 1, 0, 0, 0],\n                [0, 1, 1, 1, 0],\n            ],\n            [\n                [0, 1, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 0, 1, 0, 0],\n                [0, 0, 0, 1, 0],\n                [0, 1, 1, 0, 0],\n            ],\n            [\n                [0, 1, 0, 0, 0],\n                [1, 0, 0, 0, 0],\n                [1, 0, 1, 0, 0],\n                [1, 1, 1, 1, 0],\n                [0, 0, 1, 0, 0],\n            ],\n        ];\n\n        let sign_plus = [\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [1, 1, 1, 1, 1],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n        ];\n\n        #[allow(non_snake_case)]\n        let letter_E = [\n            [0, 1, 1, 1, 0],\n            [0, 1, 0, 0, 0],\n            [0, 1, 1, 0, 0],\n            [0, 1, 0, 0, 0],\n            [0, 1, 1, 1, 0],\n        ];\n\n        loop {\n            let analog = adc.read_channel(&mut anapin);\n            match analog {\n                Ok(v) => {\n                    let n_iter = numbers.iter();\n                    let mut count: usize = 0;\n                    for n_val in n_iter {\n                        if count == usize::from(i16::unsigned_abs(v / 100)) {\n                            display.show(&mut timer, *n_val, 10);\n                            break;\n                        }\n                        count += 1;\n                    }\n                    if count == numbers.len() {\n                        display.show(&mut timer, sign_plus, 10);\n                    }\n                }\n                Err(_e) => display.show(&mut timer, letter_E, 10),\n            }\n        }\n    }\n    panic!(\"End\");\n}\n"
  },
  {
    "path": "examples/display-blocking/Cargo.toml",
    "content": "[package]\nname = \"display-blocking\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\nembedded-hal = \"1.0.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/display-blocking/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::delay::DelayNs;\nuse microbit::{board::Board, display::blocking::Display, hal::Timer};\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let mut timer = Timer::new(board.TIMER0);\n        let mut display = Display::new(board.display_pins);\n\n        #[allow(non_snake_case)]\n        let letter_I = [\n            [0, 1, 1, 1, 0],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [0, 1, 1, 1, 0],\n        ];\n\n        let heart = [\n            [0, 1, 0, 1, 0],\n            [1, 0, 1, 0, 1],\n            [1, 0, 0, 0, 1],\n            [0, 1, 0, 1, 0],\n            [0, 0, 1, 0, 0],\n        ];\n\n        #[allow(non_snake_case)]\n        let letter_R = [\n            [0, 1, 1, 0, 0],\n            [0, 1, 0, 1, 0],\n            [0, 1, 1, 0, 0],\n            [0, 1, 0, 1, 0],\n            [0, 1, 0, 1, 0],\n        ];\n\n        #[allow(non_snake_case)]\n        let letter_u = [\n            [0, 0, 0, 0, 0],\n            [0, 0, 0, 0, 0],\n            [0, 1, 0, 1, 0],\n            [0, 1, 0, 1, 0],\n            [0, 1, 1, 1, 0],\n        ];\n\n        #[allow(non_snake_case)]\n        let letter_s = [\n            [0, 0, 0, 0, 0],\n            [0, 0, 1, 1, 0],\n            [0, 1, 0, 0, 0],\n            [0, 0, 1, 0, 0],\n            [0, 1, 1, 1, 0],\n        ];\n\n        #[allow(non_snake_case)]\n        let letter_t = [\n            [0, 0, 1, 0, 0],\n            [0, 1, 1, 1, 0],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n            [0, 0, 1, 0, 0],\n        ];\n        loop {\n            display.show(&mut timer, letter_I, 1000);\n            display.show(&mut timer, heart, 1000);\n            display.show(&mut timer, letter_R, 1000);\n            display.show(&mut timer, letter_u, 1000);\n            display.show(&mut timer, letter_s, 1000);\n            display.show(&mut timer, letter_t, 1000);\n            display.clear();\n            timer.delay_ms(250_u32);\n        }\n    }\n\n    panic!(\"End\");\n}\n"
  },
  {
    "path": "examples/display-nonblocking/Cargo.toml",
    "content": "[package]\nname = \"display-nonblocking\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/display-nonblocking/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\n\nuse microbit::{\n    board::Board,\n    display::nonblocking::{Display, GreyscaleImage},\n    hal::{\n        clocks::Clocks,\n        rtc::{Rtc, RtcInterrupt},\n    },\n    pac::{self, interrupt, RTC0, TIMER1},\n};\n\nfn heart_image(inner_brightness: u8) -> GreyscaleImage {\n    let b = inner_brightness;\n    GreyscaleImage::new(&[\n        [0, 7, 0, 7, 0],\n        [7, b, 7, b, 7],\n        [7, b, b, b, 7],\n        [0, 7, b, 7, 0],\n        [0, 0, 7, 0, 0],\n    ])\n}\n\n// We use TIMER1 to drive the display, and RTC0 to update the animation.\n// We set the TIMER1 interrupt to a higher priority than RTC0.\n\nstatic DISPLAY: Mutex<RefCell<Option<Display<TIMER1>>>> = Mutex::new(RefCell::new(None));\nstatic ANIM_TIMER: Mutex<RefCell<Option<Rtc<RTC0>>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    if let Some(mut board) = Board::take() {\n        // Starting the low-frequency clock (needed for RTC to work)\n        Clocks::new(board.CLOCK).start_lfclk();\n\n        // RTC at 16Hz (32_768 / (2047 + 1))\n        // 62.5ms period\n        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();\n        rtc0.enable_event(RtcInterrupt::Tick);\n        rtc0.enable_interrupt(RtcInterrupt::Tick, None);\n        rtc0.enable_counter();\n\n        // Create display\n        let display = Display::new(board.TIMER1, board.display_pins);\n\n        cortex_m::interrupt::free(move |cs| {\n            *DISPLAY.borrow(cs).borrow_mut() = Some(display);\n            *ANIM_TIMER.borrow(cs).borrow_mut() = Some(rtc0);\n        });\n        unsafe {\n            board.NVIC.set_priority(pac::Interrupt::RTC0, 64);\n            board.NVIC.set_priority(pac::Interrupt::TIMER1, 128);\n            pac::NVIC::unmask(pac::Interrupt::RTC0);\n            pac::NVIC::unmask(pac::Interrupt::TIMER1);\n        }\n    }\n\n    loop {\n        continue;\n    }\n}\n\n#[interrupt]\nfn TIMER1() {\n    cortex_m::interrupt::free(|cs| {\n        if let Some(display) = DISPLAY.borrow(cs).borrow_mut().as_mut() {\n            display.handle_display_event();\n        }\n    });\n}\n\n#[interrupt]\nunsafe fn RTC0() {\n    static mut STEP: u8 = 0;\n\n    cortex_m::interrupt::free(|cs| {\n        if let Some(rtc) = ANIM_TIMER.borrow(cs).borrow_mut().as_mut() {\n            rtc.reset_event(RtcInterrupt::Tick);\n        }\n    });\n\n    let inner_brightness = match *STEP {\n        0..=8 => 9 - *STEP,\n        9..=12 => 0,\n        _ => unreachable!(),\n    };\n\n    cortex_m::interrupt::free(|cs| {\n        if let Some(display) = DISPLAY.borrow(cs).borrow_mut().as_mut() {\n            display.show(&heart_image(inner_brightness));\n        }\n    });\n\n    *STEP += 1;\n    if *STEP == 13 {\n        *STEP = 0\n    };\n}\n"
  },
  {
    "path": "examples/display-rtic/Cargo.toml",
    "content": "[package]\nname = \"display-rtic\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\ncortex-m-rtic = { version = \"1.1.4\" }\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/display-rtic/src/main.rs",
    "content": "//! A complete working example.\n//!\n//! This requires `cortex-m-rtic` v1.0.\n//!\n//! It uses `TIMER1` to drive the display, and `RTC0` to update a simple\n//! animated image.\n#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse rtic::app;\n\n#[app(device = microbit::pac, peripherals = true)]\nmod app {\n\n    use microbit::{\n        board::Board,\n        display::nonblocking::{Display, GreyscaleImage},\n        hal::{\n            clocks::Clocks,\n            rtc::{Rtc, RtcInterrupt},\n        },\n        pac,\n    };\n\n    fn heart_image(inner_brightness: u8) -> GreyscaleImage {\n        let b = inner_brightness;\n        GreyscaleImage::new(&[\n            [0, 7, 0, 7, 0],\n            [7, b, 7, b, 7],\n            [7, b, b, b, 7],\n            [0, 7, b, 7, 0],\n            [0, 0, 7, 0, 0],\n        ])\n    }\n\n    #[shared]\n    struct Shared {\n        display: Display<pac::TIMER1>,\n    }\n\n    #[local]\n    struct Local {\n        anim_timer: Rtc<pac::RTC0>,\n    }\n\n    #[init]\n    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {\n        let board = Board::new(cx.device, cx.core);\n\n        // Starting the low-frequency clock (needed for RTC to work)\n        Clocks::new(board.CLOCK).start_lfclk();\n\n        // RTC at 16Hz (32_768 / (2047 + 1))\n        // 16Hz; 62.5ms period\n        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();\n        rtc0.enable_event(RtcInterrupt::Tick);\n        rtc0.enable_interrupt(RtcInterrupt::Tick, None);\n        rtc0.enable_counter();\n\n        let display = Display::new(board.TIMER1, board.display_pins);\n        (\n            Shared { display },\n            Local { anim_timer: rtc0 },\n            init::Monotonics(),\n        )\n    }\n\n    #[task(binds = TIMER1, priority = 2, shared = [display])]\n    fn timer1(mut cx: timer1::Context) {\n        cx.shared\n            .display\n            .lock(|display| display.handle_display_event());\n    }\n\n    #[task(binds = RTC0, priority = 1, shared = [display],\n           local = [anim_timer, step: u8 = 0])]\n    fn rtc0(cx: rtc0::Context) {\n        let mut shared = cx.shared;\n        let local = cx.local;\n\n        local.anim_timer.reset_event(RtcInterrupt::Tick);\n\n        let inner_brightness = match *local.step {\n            0..=8 => 9 - *local.step,\n            9..=12 => 0,\n            _ => unreachable!(),\n        };\n\n        shared.display.lock(|display| {\n            display.show(&heart_image(inner_brightness));\n        });\n\n        *local.step += 1;\n        if *local.step == 13 {\n            *local.step = 0\n        };\n    }\n}\n"
  },
  {
    "path": "examples/display-text-rtic/Cargo.toml",
    "content": "[package]\nname = \"display-text-rtic\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\ncortex-m-rtic = { version = \"1.1.4\" }\nmicrobit-text = \"1.0.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/display-text-rtic/src/main.rs",
    "content": "//! An example of scrolling static text.\n//!\n//! It uses `TIMER1` to drive the display, and `RTC0` to animate the text.\n#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse rtic::app;\n\n#[app(device = microbit::pac, peripherals = true)]\nmod app {\n\n    use microbit::{\n        board::Board,\n        display::nonblocking::{Display, Frame, MicrobitFrame},\n        hal::{\n            clocks::Clocks,\n            rtc::{Rtc, RtcInterrupt},\n        },\n        pac,\n    };\n    use microbit_text::scrolling::Animate;\n    use microbit_text::scrolling_text::ScrollingStaticText;\n\n    const MESSAGE: &[u8] = b\"Hello, world!\";\n\n    #[shared]\n    struct Shared {\n        display: Display<pac::TIMER1>,\n    }\n\n    #[local]\n    struct Local {\n        anim_timer: Rtc<pac::RTC0>,\n        scroller: ScrollingStaticText,\n    }\n\n    #[init]\n    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {\n        let board = Board::new(cx.device, cx.core);\n\n        // Starting the low-frequency clock (needed for RTC to work)\n        Clocks::new(board.CLOCK).start_lfclk();\n\n        // RTC at 16Hz (32_768 / (2047 + 1))\n        // 16Hz; 62.5ms period\n        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();\n        rtc0.enable_event(RtcInterrupt::Tick);\n        rtc0.enable_interrupt(RtcInterrupt::Tick, None);\n        rtc0.enable_counter();\n\n        let display = Display::new(board.TIMER1, board.display_pins);\n\n        let mut scroller = ScrollingStaticText::default();\n        scroller.set_message(MESSAGE);\n\n        (\n            Shared { display },\n            Local {\n                anim_timer: rtc0,\n                scroller,\n            },\n            init::Monotonics(),\n        )\n    }\n\n    #[task(binds = TIMER1, priority = 2, shared = [display])]\n    fn timer1(mut cx: timer1::Context) {\n        cx.shared\n            .display\n            .lock(|display| display.handle_display_event());\n    }\n\n    #[task(binds = RTC0, priority = 1, shared = [display],\n           local = [anim_timer, scroller,\n                    frame: MicrobitFrame = MicrobitFrame::default()])]\n    fn rtc0(cx: rtc0::Context) {\n        let mut shared = cx.shared;\n        let local = cx.local;\n        local.anim_timer.reset_event(RtcInterrupt::Tick);\n        if !local.scroller.is_finished() {\n            local.scroller.tick();\n            local.frame.set(local.scroller);\n            shared.display.lock(|display| {\n                display.show_frame(local.frame);\n            });\n        }\n    }\n}\n"
  },
  {
    "path": "examples/gpio-direct-blinky/Cargo.toml",
    "content": "[package]\nname = \"gpio-direct-blinky\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/gpio-direct-blinky/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\n\n#[cfg(feature = \"v1\")]\n#[entry]\nfn main() -> ! {\n    if let Some(p) = microbit::Peripherals::take() {\n        p.GPIO.pin_cnf[4].write(|w| w.dir().output());\n        p.GPIO.pin_cnf[13].write(|w| w.dir().output());\n\n        p.GPIO.out.write(|w| unsafe { w.bits(1 << 13) });\n\n        let mut count: u8 = 0;\n        loop {\n            count += 1;\n\n            if count & 1 == 1 {\n                p.GPIO.out.write(|w| unsafe { w.bits(1 << 13) });\n            } else {\n                p.GPIO.out.write(|w| unsafe { w.bits(0) });\n            }\n\n            for _ in 0..50_000 {\n                cortex_m::asm::nop();\n            }\n        }\n    };\n\n    loop {\n        continue;\n    }\n}\n\n#[cfg(feature = \"v2\")]\n#[entry]\nfn main() -> ! {\n    if let Some(p) = microbit::Peripherals::take() {\n        p.P0.pin_cnf[28].write(|w| w.dir().output());\n        p.P0.pin_cnf[21].write(|w| w.dir().output());\n\n        p.P0.out.write(|w| unsafe { w.bits(1 << 21) });\n\n        let mut count: u8 = 0;\n        loop {\n            count += 1;\n\n            if count & 1 == 1 {\n                p.P0.out.write(|w| unsafe { w.bits(1 << 21) });\n            } else {\n                p.P0.out.write(|w| unsafe { w.bits(0) });\n            }\n\n            for _ in 0..50_000 {\n                cortex_m::asm::nop();\n            }\n        }\n    };\n\n    loop {\n        continue;\n    }\n}\n"
  },
  {
    "path": "examples/gpio-hal-blinky/Cargo.toml",
    "content": "[package]\nname = \"gpio-hal-blinky\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\nembedded-hal = \"1.0.0\"\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/gpio-hal-blinky/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::{delay::DelayNs, digital::OutputPin};\nuse microbit::{board::Board, hal::timer::Timer};\n\n#[entry]\nfn main() -> ! {\n    let mut board = Board::take().unwrap();\n\n    let mut timer = Timer::new(board.TIMER0);\n\n    let _ = board.display_pins.col1.set_low();\n    let mut row1 = board.display_pins.row1;\n\n    loop {\n        let _ = row1.set_low();\n        timer.delay_ms(1_000);\n        let _ = row1.set_high();\n        timer.delay_ms(1_000);\n    }\n}\n"
  },
  {
    "path": "examples/gpio-hal-ledbutton/Cargo.toml",
    "content": "[package]\nname = \"gpio-hal-ledbutton\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\nembedded-hal = \"1.0.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/gpio-hal-ledbutton/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::digital::{InputPin, OutputPin};\nuse microbit::board::Board;\n\n#[entry]\nfn main() -> ! {\n    let mut board = Board::take().unwrap();\n\n    board.display_pins.row1.set_high().unwrap();\n\n    let mut led1 = board.display_pins.col1;\n    let mut led2 = board.display_pins.col2;\n\n    loop {\n        if let Ok(true) = board.buttons.button_a.is_high() {\n            let _ = led1.set_high();\n        } else {\n            let _ = led1.set_low();\n        }\n\n        if let Ok(true) = board.buttons.button_b.is_high() {\n            let _ = led2.set_high();\n        } else {\n            let _ = led2.set_low();\n        }\n    }\n}\n"
  },
  {
    "path": "examples/gpio-hal-printbuttons/Cargo.toml",
    "content": "[package]\nname = \"gpio-hal-printbuttons\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/gpio-hal-printbuttons/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\n\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Board,\n    hal::gpiote::Gpiote,\n    pac::{self, interrupt},\n};\n\nstatic GPIO: Mutex<RefCell<Option<Gpiote>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    let board = Board::take().unwrap();\n\n    let gpiote = Gpiote::new(board.GPIOTE);\n\n    let channel0 = gpiote.channel0();\n    channel0\n        .input_pin(&board.buttons.button_a.degrade())\n        .hi_to_lo()\n        .enable_interrupt();\n    channel0.reset_events();\n\n    let channel1 = gpiote.channel1();\n    channel1\n        .input_pin(&board.buttons.button_b.degrade())\n        .hi_to_lo()\n        .enable_interrupt();\n    channel1.reset_events();\n\n    cortex_m::interrupt::free(move |cs| {\n        /* Enable external GPIO interrupts */\n        unsafe {\n            pac::NVIC::unmask(pac::Interrupt::GPIOTE);\n        }\n        pac::NVIC::unpend(pac::Interrupt::GPIOTE);\n\n        *GPIO.borrow(cs).borrow_mut() = Some(gpiote);\n\n        defmt::info!(\"Welcome to the buttons demo. Press buttons A and/or B for some action.\");\n    });\n\n    loop {\n        continue;\n    }\n}\n\n// Define an interrupt, i.e. function to call when exception occurs. Here if we receive an\n// interrupt from a button press, the function will be called\n#[interrupt]\nfn GPIOTE() {\n    /* Enter critical section */\n    cortex_m::interrupt::free(|cs| {\n        if let Some(gpiote) = GPIO.borrow(cs).borrow().as_ref() {\n            let buttonapressed = gpiote.channel0().is_event_triggered();\n            let buttonbpressed = gpiote.channel1().is_event_triggered();\n\n            /* Print buttons to the serial console */\n            defmt::info!(\n                \"Button pressed {:?}\",\n                match (buttonapressed, buttonbpressed) {\n                    (false, false) => \"\",\n                    (true, false) => \"A\",\n                    (false, true) => \"B\",\n                    (true, true) => \"A + B\",\n                }\n            );\n\n            /* Clear events */\n            gpiote.channel0().reset_events();\n            gpiote.channel1().reset_events();\n        }\n    });\n}\n"
  },
  {
    "path": "examples/magnetometer/Cargo.toml",
    "content": "[package]\nname = \"magnetometer\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\nembedded-hal = \"1.0.0\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\nlsm303agr = \"1.1.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/magnetometer/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::delay::DelayNs;\nuse lsm303agr::{\n    interface::I2cInterface, mode::MagOneShot, AccelMode, AccelOutputDataRate, Lsm303agr,\n};\nuse microbit::hal::Timer;\n\n#[cfg(feature = \"v1\")]\nuse microbit::{\n    hal::twi,\n    pac::{twi0::frequency::FREQUENCY_A, TWI0},\n};\n#[cfg(feature = \"v2\")]\nuse microbit::{\n    hal::twim,\n    pac::{twim0::frequency::FREQUENCY_A, TWIM0},\n};\n\n#[entry]\nfn main() -> ! {\n    let board = microbit::Board::take().unwrap();\n    let mut timer = Timer::new(board.TIMER0);\n\n    #[cfg(feature = \"v1\")]\n    let i2c = { twi::Twi::new(board.TWI0, board.i2c.into(), FREQUENCY_A::K100) };\n\n    #[cfg(feature = \"v2\")]\n    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };\n\n    let mut sensor = Lsm303agr::new_with_i2c(i2c);\n    if let Ok(id) = sensor.accelerometer_id() {\n        if !id.is_correct() {\n            defmt::panic!(\"Accelerometer had unexpected ID {:#x}\", id.raw());\n        }\n    } else {\n        defmt::panic!(\"Error getting accelerometer ID\");\n    }\n    sensor.init().unwrap();\n\n    defmt::info!(\"normal mode\");\n    sensor\n        .set_accel_mode_and_odr(&mut timer, AccelMode::Normal, AccelOutputDataRate::Hz50)\n        .unwrap();\n    timer.delay_ms(1000_u32);\n    get_data(&mut sensor);\n\n    defmt::info!(\"low power mode\");\n    sensor\n        .set_accel_mode_and_odr(&mut timer, AccelMode::LowPower, AccelOutputDataRate::Hz50)\n        .unwrap();\n    timer.delay_ms(1000_u32);\n    get_data(&mut sensor);\n\n    defmt::info!(\"high resolution mode\");\n    sensor\n        .set_accel_mode_and_odr(\n            &mut timer,\n            AccelMode::HighResolution,\n            AccelOutputDataRate::Hz50,\n        )\n        .unwrap();\n    timer.delay_ms(1000_u32);\n    get_data(&mut sensor);\n\n    loop {\n        timer.delay_ms(100_u32);\n        get_data(&mut sensor);\n    }\n}\n\n#[cfg(feature = \"v1\")]\ntype Sensor = Lsm303agr<I2cInterface<twi::Twi<TWI0>>, MagOneShot>;\n\n#[cfg(feature = \"v2\")]\ntype Sensor = Lsm303agr<I2cInterface<twim::Twim<TWIM0>>, MagOneShot>;\n\nfn get_data(sensor: &mut Sensor) {\n    loop {\n        if sensor.accel_status().unwrap().xyz_new_data() {\n            let data = sensor.acceleration().unwrap();\n            defmt::info!(\"x {} y {} z {}\", data.x_mg(), data.y_mg(), data.z_mg());\n            return;\n        }\n    }\n}\n"
  },
  {
    "path": "examples/rng-direct/Cargo.toml",
    "content": "[package]\nname = \"rng-direct\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/rng-direct/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\n\nuse microbit::pac::{self, interrupt};\n\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\n\nstatic RNG: Mutex<RefCell<Option<pac::RNG>>> = Mutex::new(RefCell::new(None));\nstatic RTC: Mutex<RefCell<Option<pac::RTC0>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    if let Some(p) = microbit::Peripherals::take() {\n        p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });\n\n        while p.CLOCK.events_lfclkstarted.read().bits() == 0 {}\n\n        /* And then set it back to 0 again, just because ?!? */\n        p.CLOCK.events_lfclkstarted.write(|w| unsafe { w.bits(0) });\n\n        defmt::info!(\"Welcome to the random number printer!\");\n\n        p.RTC0.prescaler.write(|w| unsafe { w.bits(1) });\n        p.RTC0.evtenset.write(|w| w.tick().set_bit());\n        p.RTC0.intenset.write(|w| w.tick().set_bit());\n        p.RTC0.tasks_start.write(|w| unsafe { w.bits(1) });\n\n        /* Enable error correction for better values */\n        p.RNG.config.write(|w| w.dercen().enabled());\n\n        /* Enable random number generation */\n        p.RNG.tasks_start.write(|w| unsafe { w.bits(1) });\n\n        cortex_m::interrupt::free(move |cs| {\n            *RTC.borrow(cs).borrow_mut() = Some(p.RTC0);\n            *RNG.borrow(cs).borrow_mut() = Some(p.RNG);\n        });\n\n        unsafe {\n            pac::NVIC::unmask(pac::Interrupt::RTC0);\n        }\n        pac::NVIC::unpend(pac::Interrupt::RTC0);\n    }\n\n    loop {\n        continue;\n    }\n}\n\n// Define an exception, i.e. function to call when exception occurs. Here if our timer\n// trips, we'll print some random number\n#[interrupt]\nfn RTC0() {\n    /* Enter critical section */\n    cortex_m::interrupt::free(|cs| {\n        if let Some(rtc) = RTC.borrow(cs).borrow().as_ref() {\n            let count = if let Some(rng) = RNG.borrow(cs).borrow().as_ref() {\n                /* Let's wait until we have a new random value */\n                while rng.events_valrdy.read().bits() == 0 {}\n\n                let num = rng.value.read().bits();\n\n                /* Clear event for next random number value */\n                rng.events_valrdy.write(|w| unsafe { w.bits(0) });\n\n                num\n            } else {\n                0\n            };\n\n            defmt::info!(\"{:?}\", count);\n            rtc.events_tick.write(|w| unsafe { w.bits(0) });\n        }\n    });\n}\n"
  },
  {
    "path": "examples/rng-hal/Cargo.toml",
    "content": "[package]\nname = \"rng-hal-printrandserial\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.rand_pcg]\ndefault-features = false\nversion = \"0.10.2\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/rng-hal/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::{cell::RefCell, ops::DerefMut};\n\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\n\nuse microbit::{\n    hal::{clocks, rng, rtc},\n    pac::{self, interrupt},\n};\n\nuse rand_pcg::{\n    Pcg32,\n    rand_core::{Rng, SeedableRng},\n};\n\nstatic RTC: Mutex<RefCell<Option<rtc::Rtc<pac::RTC0>>>> = Mutex::new(RefCell::new(None));\nstatic RNG: Mutex<RefCell<Option<Pcg32>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    let mut cp = pac::CorePeripherals::take().unwrap();\n    let p = microbit::Peripherals::take().unwrap();\n\n    cortex_m::interrupt::free(move |cs| {\n        /* Start low frequency clock */\n        clocks::Clocks::new(p.CLOCK).start_lfclk();\n\n        defmt::info!(\"Welcome to the random number printer!\");\n\n        /* Use hardware RNG to initialise PRNG */\n        let mut rng = rng::Rng::new(p.RNG);\n\n        let mut seed: [u8; 16] = [0; 16];\n\n        /* Read 4 bytes of data from hardware RNG */\n        rng.random(&mut seed);\n\n        let rng = Pcg32::from_seed(seed);\n        *RNG.borrow(cs).borrow_mut() = Some(rng);\n\n        let mut rtc = rtc::Rtc::new(p.RTC0, 1).unwrap();\n        rtc.enable_counter();\n        rtc.enable_interrupt(rtc::RtcInterrupt::Tick, Some(&mut cp.NVIC));\n        rtc.enable_event(rtc::RtcInterrupt::Tick);\n\n        *RTC.borrow(cs).borrow_mut() = Some(rtc);\n\n        pac::NVIC::unpend(pac::Interrupt::RTC0);\n    });\n\n    loop {\n        continue;\n    }\n}\n\n// Define an exception, i.e. function to call when exception occurs. Here if our timer\n// trips, we'll print out a random number to the serial port\n#[interrupt]\nfn RTC0() {\n    /* Enter critical section */\n    cortex_m::interrupt::free(|cs| {\n        if let (Some(rtc), &mut Some(ref mut rng)) = (\n            RTC.borrow(cs).borrow().as_ref(),\n            RNG.borrow(cs).borrow_mut().deref_mut(),\n        ) {\n            defmt::info!(\"{:?}\", rng.next_u32());\n            rtc.reset_event(rtc::RtcInterrupt::Tick);\n        }\n    });\n}\n"
  },
  {
    "path": "examples/serial-direct-echo/Cargo.toml",
    "content": "[package]\nname = \"serial-direct-echo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\n"
  },
  {
    "path": "examples/serial-direct-echo/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse core::str;\nuse cortex_m_rt::entry;\n\n#[entry]\nfn main() -> ! {\n    if let Some(p) = microbit::Peripherals::take() {\n        /* Configure RX and TX pins accordingly */\n        p.GPIO.pin_cnf[24].write(|w| w.pull().pullup().dir().output());\n        p.GPIO.pin_cnf[25].write(|w| w.pull().disabled().dir().input());\n\n        let uart0 = p.UART0;\n        /* Tell UART which pins to use for sending and receiving */\n        uart0.pseltxd.write(|w| unsafe { w.bits(24) });\n        uart0.pselrxd.write(|w| unsafe { w.bits(25) });\n\n        /* Set a typical baud rate of 115200 */\n        uart0.baudrate.write(|w| w.baudrate().baud115200());\n\n        /* Enable UART function */\n        uart0.enable.write(|w| w.enable().enabled());\n\n        /* Print a nice hello message */\n        let _ = write_uart0(&uart0, \"Please type characters to echo:\\r\\n\");\n\n        /* Fire up receiving task */\n        uart0.tasks_startrx.write(|w| unsafe { w.bits(1) });\n\n        /* Endless loop */\n        loop {\n            /* Busy wait for reception of data */\n            while uart0.events_rxdrdy.read().bits() == 0 {}\n\n            /* We're going to pick up the data soon, let's signal the buffer is already waiting for\n             * more data */\n            uart0.events_rxdrdy.write(|w| unsafe { w.bits(0) });\n\n            /* Read one 8bit value */\n            let c = uart0.rxd.read().bits() as u8;\n\n            /* What comes in must go out, we don't care what it is */\n            let _ = write_uart0(&uart0, unsafe { str::from_utf8_unchecked(&[c; 1]) });\n        }\n    }\n\n    loop {\n        continue;\n    }\n}\n\nfn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Result {\n    /* Start UART sender */\n    uart0.tasks_starttx.write(|w| unsafe { w.bits(1) });\n\n    for c in s.as_bytes() {\n        /* Write the current character to the output register */\n        uart0.txd.write(|w| unsafe { w.bits(u32::from(*c)) });\n\n        /* Wait until the UART is clear to send */\n        while uart0.events_txdrdy.read().bits() == 0 {}\n\n        /* And then reset it for the next round */\n        uart0.events_txdrdy.write(|w| unsafe { w.bits(0) });\n    }\n\n    /* Stop UART sender */\n    uart0.tasks_stoptx.write(|w| unsafe { w.bits(1) });\n    Ok(())\n}\n"
  },
  {
    "path": "examples/serial-direct-helloworld/Cargo.toml",
    "content": "[package]\nname = \"serial-direct-helloworld\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\n"
  },
  {
    "path": "examples/serial-direct-helloworld/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\n\n#[entry]\nfn main() -> ! {\n    if let Some(p) = microbit::Peripherals::take() {\n        p.GPIO.pin_cnf[24].write(|w| w.pull().pullup().dir().output());\n        p.GPIO.pin_cnf[25].write(|w| w.pull().disabled().dir().input());\n\n        p.UART0.pseltxd.write(|w| unsafe { w.bits(24) });\n        p.UART0.pselrxd.write(|w| unsafe { w.bits(25) });\n\n        p.UART0.baudrate.write(|w| w.baudrate().baud115200());\n        p.UART0.enable.write(|w| w.enable().enabled());\n\n        let _ = write_uart0(&p.UART0, \"Hello World!\\n\");\n    }\n\n    loop {\n        continue;\n    }\n}\n\nfn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Result {\n    uart0.tasks_starttx.write(|w| unsafe { w.bits(1) });\n    for c in s.as_bytes() {\n        /* Write the current character to the output register */\n        uart0.txd.write(|w| unsafe { w.bits(u32::from(*c)) });\n\n        /* Wait until the UART is clear to send */\n        while uart0.events_txdrdy.read().bits() == 0 {}\n\n        /* And then set it back to 0 again, just because ?!? */\n        uart0.events_txdrdy.write(|w| unsafe { w.bits(0) });\n    }\n    uart0.tasks_stoptx.write(|w| unsafe { w.bits(1) });\n    Ok(())\n}\n"
  },
  {
    "path": "examples/serial-hal-blocking-echo/Cargo.toml",
    "content": "[package]\nname = \"serial-hal-blocking-echo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1\"\nnb = \"1.1.0\"\nembedded-hal = \"1.0.0\"\nembedded-io = \"0.7.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n"
  },
  {
    "path": "examples/serial-hal-blocking-echo/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse core::fmt::Write;\nuse cortex_m_rt::entry;\nuse embedded_io::Read;\n\n#[cfg(feature = \"v1\")]\nuse microbit::{\n    hal::uart,\n    hal::uart::{Baudrate, Parity},\n};\n\n#[cfg(feature = \"v2\")]\nuse microbit::{\n    hal::uarte,\n    hal::uarte::{Baudrate, Parity},\n};\n\n#[cfg(feature = \"v2\")]\nmod serial_setup;\n#[cfg(feature = \"v2\")]\nuse serial_setup::UartePort;\n\n#[entry]\nfn main() -> ! {\n    let board = microbit::Board::take().unwrap();\n\n    #[cfg(feature = \"v1\")]\n    let mut serial = {\n        uart::Uart::new(\n            board.UART0,\n            board.uart.into(),\n            Parity::EXCLUDED,\n            Baudrate::BAUD115200,\n        )\n    };\n\n    #[cfg(feature = \"v2\")]\n    let mut serial = {\n        let serial = uarte::Uarte::new(\n            board.UARTE0,\n            board.uart.into(),\n            Parity::EXCLUDED,\n            Baudrate::BAUD115200,\n        );\n        UartePort::new(serial)\n    };\n\n    loop {\n        write!(serial, \"Hello World:\\r\\n\").unwrap();\n        let mut input = [0];\n        serial.read_exact(&mut input).unwrap();\n        write!(serial, \"You said: {}\\r\\n\", input[0] as char).unwrap();\n    }\n}\n"
  },
  {
    "path": "examples/serial-hal-blocking-echo/src/serial_setup.rs",
    "content": "use core::{fmt, ptr::addr_of_mut};\nuse microbit::hal::uarte::{Error, Instance, Uarte, UarteRx, UarteTx};\n\nstatic mut TX_BUF: [u8; 1] = [0; 1];\nstatic mut RX_BUF: [u8; 1] = [0; 1];\n\npub struct UartePort<T: Instance>(UarteTx<T>, UarteRx<T>);\n\nimpl<T: Instance> UartePort<T> {\n    pub fn new(serial: Uarte<T>) -> UartePort<T> {\n        let (tx, rx) = serial\n            .split(unsafe { addr_of_mut!(TX_BUF).as_mut().unwrap() }, unsafe {\n                addr_of_mut!(RX_BUF).as_mut().unwrap()\n            })\n            .unwrap();\n        UartePort(tx, rx)\n    }\n}\n\nimpl<T: Instance> fmt::Write for UartePort<T> {\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        self.0.write_str(s)\n    }\n}\n\nimpl<T: Instance> embedded_io::ErrorType for UartePort<T> {\n    type Error = Error;\n}\n\nimpl<T: Instance> embedded_io::Write for UartePort<T> {\n    fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {\n        self.0.write(buffer)\n    }\n\n    fn flush(&mut self) -> Result<(), Self::Error> {\n        self.0.flush()\n    }\n}\n\nimpl<T: Instance> embedded_io::Read for UartePort<T> {\n    fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {\n        self.1.read(buffer)\n    }\n}\n"
  },
  {
    "path": "examples/servo/Cargo.toml",
    "content": "[package]\nname = \"servo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit]\npath = \"../../microbit\"\noptional = true\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv1 = [\"microbit\"]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/servo/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\n\nuse microbit::{\n    board::Board,\n    hal::{\n        gpio::Level,\n        gpiote::*,\n        pac::{self, interrupt, TIMER0},\n        ppi::{self, ConfigurablePpi, Ppi},\n    },\n};\n\nstatic SERVO_TIMER: Mutex<RefCell<Option<TIMER0>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let gpiote = Gpiote::new(board.GPIOTE);\n        // Servo output pins\n        let servopin1 = board.edge.e01.into_push_pull_output(Level::Low).degrade(); // PAD2\n        let servopin2 = board.edge.e02.into_push_pull_output(Level::Low).degrade(); // PAD3\n\n        // Output channel for Servo 1\n        gpiote\n            .channel0()\n            .output_pin(servopin1)\n            .task_out_polarity(TaskOutPolarity::Toggle)\n            .init_low();\n        gpiote.channel0().task_out().write(|w| unsafe { w.bits(1) });\n        // Output channel for Servo 2\n        gpiote\n            .channel1()\n            .output_pin(servopin2)\n            .task_out_polarity(TaskOutPolarity::Toggle)\n            .init_low();\n        gpiote.channel1().task_out().write(|w| unsafe { w.bits(1) });\n\n        let ppi_channels = ppi::Parts::new(board.PPI);\n        // Set both servo outputs high form Timer0 CC[0]\n        // Set each servo output low from the respective Timer0 CC[1] and CC[2]\n        // Each timer can run 3 Servos\n        let mut ppi0 = ppi_channels.ppi0;\n        ppi0.set_task_endpoint(gpiote.channel0().task_out());\n        ppi0.set_event_endpoint(&board.TIMER0.events_compare[0]);\n        ppi0.enable();\n        let mut ppi1 = ppi_channels.ppi1;\n        ppi1.set_task_endpoint(gpiote.channel0().task_out());\n        ppi1.set_event_endpoint(&board.TIMER0.events_compare[1]);\n        ppi1.enable();\n        let mut ppi2 = ppi_channels.ppi2;\n        ppi2.set_task_endpoint(gpiote.channel1().task_out());\n        ppi2.set_event_endpoint(&board.TIMER0.events_compare[0]);\n        ppi2.enable();\n        let mut ppi3 = ppi_channels.ppi3;\n        ppi3.set_task_endpoint(gpiote.channel1().task_out());\n        ppi3.set_event_endpoint(&board.TIMER0.events_compare[2]);\n        ppi3.enable();\n\n        // The Timer PAC is used directly as the HAL does not give full access to all registers\n        board.TIMER0.mode.write(|w| unsafe { w.bits(0) });\n        board.TIMER0.bitmode.write(|w| unsafe { w.bits(0) });\n        // CC[0] every 20 ms (50 Hz)\n        board.TIMER0.cc[0].write(|w| unsafe { w.bits(20000) });\n        board.TIMER0.shorts.write(|w| unsafe { w.bits(1) });\n        // Servo duty cycle is from 0.5 ms to 2.5 ms with 1.5 ms for center position\n        board.TIMER0.cc[1].write(|w| unsafe { w.bits(1500) });\n        board.TIMER0.cc[2].write(|w| unsafe { w.bits(1500) });\n        board.TIMER0.tasks_start.write(|w| unsafe { w.bits(1) });\n        // Timer0 interrupt on CC[0]\n        board.TIMER0.intenset.write(|w| unsafe { w.bits(1 << 16) });\n\n        cortex_m::interrupt::free(move |cs| {\n            *SERVO_TIMER.borrow(cs).borrow_mut() = Some(board.TIMER0);\n        });\n        unsafe {\n            pac::NVIC::unmask(pac::Interrupt::TIMER0);\n        }\n\n        loop {}\n    }\n    panic!(\"End\");\n}\n\n#[interrupt]\nfn TIMER0() {\n    // Change Servo position at the start of the duty cycle. Then there is no race condition\n    // between changing the duty cycle and a CC event.\n    static mut SPEED: i32 = 1500;\n    static mut DIRECTION: i32 = 1;\n    match SPEED {\n        i32::MIN..=500 => *DIRECTION = 1,\n        2500..=i32::MAX => *DIRECTION = -1,\n        _ => {}\n    }\n    *SPEED += *DIRECTION;\n    cortex_m::interrupt::free(|cs| {\n        //    if let Some(cc_value) = CC_VALUE.borrow(cs).borrow().as_ref() {\n        if let Some(timer) = SERVO_TIMER.borrow(cs).borrow_mut().as_mut() {\n            //timer.cc[1].write(|w|unsafe { w.bits(u32::try_from(*cc_value).unwrap_or(1500)) });\n            let set_speed = u32::try_from(*SPEED).unwrap_or(1500);\n            timer.cc[1].write(|w| unsafe { w.bits(set_speed) });\n            timer.cc[2].write(|w| unsafe { w.bits(set_speed) });\n            timer.events_compare[0].write(|w| unsafe { w.bits(0) });\n        }\n        //}\n    });\n}\n"
  },
  {
    "path": "examples/v2-microphone/Cargo.toml",
    "content": "[package]\nname = \"v2-microphone\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\nembedded-hal = \"1.0.0\"\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1.0\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv2 = [\"microbit-v2\"]\n\ndefault = [\"defmt-default\"]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/v2-microphone/src/main.rs",
    "content": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Board,\n    display::blocking::Display,\n    hal::{\n        gpio::{Level, OpenDrainConfig},\n        saadc::SaadcConfig,\n        Saadc, Timer,\n    },\n};\n\n#[entry]\nfn main() -> ! {\n    if let Some(board) = Board::take() {\n        let mut timer = Timer::new(board.TIMER0);\n        let mut display = Display::new(board.display_pins);\n\n        // initialize adc\n        let saadc_config = SaadcConfig::default();\n        let mut saadc = Saadc::new(board.ADC, saadc_config);\n        let mut mic_in = board.microphone_pins.mic_in.into_floating_input();\n\n        // enable microphone\n        board\n            .microphone_pins\n            .mic_run\n            .into_open_drain_output(OpenDrainConfig::Disconnect0HighDrive1, Level::High);\n\n        let mut count: u64 = 0;\n        let mut sum: u64 = 0;\n        let mut max_value: u16 = 0;\n        loop {\n            let mic_value = saadc\n                .read_channel(&mut mic_in)\n                .expect(\"could not read value of microphone\") as u16;\n\n            // Smoothen the signal as audio comes in waves\n            max_value = max_value.max(mic_value);\n            sum += mic_value as u64;\n            count += 1;\n\n            if count % 100 == 0 {\n                let avg = (sum / count) as u16;\n                let image = [\n                    [if max_value > avg + 100 { 1 } else { 0 }; 5],\n                    [if max_value > avg + 80 { 1 } else { 0 }; 5],\n                    [if max_value > avg + 60 { 1 } else { 0 }; 5],\n                    [if max_value > avg + 40 { 1 } else { 0 }; 5],\n                    [if max_value > avg + 20 { 1 } else { 0 }; 5],\n                ];\n                display.show(&mut timer, image, 10);\n                max_value = 0;\n            }\n        }\n    }\n\n    panic!(\"End\");\n}\n"
  },
  {
    "path": "examples/v2-speaker/Cargo.toml",
    "content": "[package]\nname = \"v2-speaker\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", features = [\"critical-section-single-core\"] }\nembedded-hal = \"1.0.0\"\ncortex-m-rt = \"0.7.5\"\npanic-halt = \"1.0.0\"\ndefmt-rtt = \"1.1\"\ndefmt = \"1.0.1\"\n\n[dependencies.microbit-v2]\npath = \"../../microbit-v2\"\noptional = true\n\n[features]\nv2 = [\"microbit-v2\"]\n\ndefault = [\n  \"defmt-default\",\n]\n\n# do NOT modify these features\ndefmt-default = []\ndefmt-trace = []\ndefmt-debug = []\ndefmt-info = []\ndefmt-warn = []\ndefmt-error = []\n"
  },
  {
    "path": "examples/v2-speaker/src/main.rs",
    "content": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mutex;\nuse cortex_m_rt::entry;\nuse embedded_hal::digital::OutputPin;\nuse microbit::{\n    hal::{\n        clocks::Clocks,\n        gpio, pwm,\n        rtc::{Rtc, RtcInterrupt},\n        time::Hertz,\n    },\n    pac::{self, interrupt},\n    Board,\n};\n\nstatic RTC: Mutex<RefCell<Option<Rtc<pac::RTC0>>>> = Mutex::new(RefCell::new(None));\nstatic SPEAKER: Mutex<RefCell<Option<pwm::Pwm<pac::PWM0>>>> = Mutex::new(RefCell::new(None));\n\n#[entry]\nfn main() -> ! {\n    if let Some(mut board) = Board::take() {\n        cortex_m::interrupt::free(move |cs| {\n            // NB: The LF CLK pin is used by the speaker\n            let _clocks = Clocks::new(board.CLOCK)\n                .enable_ext_hfosc()\n                .set_lfclk_src_synth()\n                .start_lfclk();\n\n            let mut rtc = Rtc::new(board.RTC0, 511).unwrap();\n            rtc.enable_counter();\n            rtc.enable_interrupt(RtcInterrupt::Tick, Some(&mut board.NVIC));\n            rtc.enable_event(RtcInterrupt::Tick);\n\n            *RTC.borrow(cs).borrow_mut() = Some(rtc);\n\n            let mut speaker_pin = board.speaker_pin.into_push_pull_output(gpio::Level::High);\n            let _ = speaker_pin.set_low();\n\n            // Use the PWM peripheral to generate a waveform for the speaker\n            let speaker = pwm::Pwm::new(board.PWM0);\n            speaker\n                // output the waveform on the speaker pin\n                .set_output_pin(pwm::Channel::C0, speaker_pin.degrade())\n                // Use prescale by 16 to achive darker sounds\n                .set_prescaler(pwm::Prescaler::Div16)\n                // Initial frequency\n                .set_period(Hertz(1u32))\n                // Configure for up and down counter mode\n                .set_counter_mode(pwm::CounterMode::UpAndDown)\n                // Set maximum duty cycle\n                .set_max_duty(32767)\n                // enable PWM\n                .enable();\n\n            speaker\n                .set_seq_refresh(pwm::Seq::Seq0, 0)\n                .set_seq_end_delay(pwm::Seq::Seq0, 0);\n\n            // Configure 50% duty cycle\n            let max_duty = speaker.max_duty();\n            speaker.set_duty_on_common(max_duty / 2);\n\n            *SPEAKER.borrow(cs).borrow_mut() = Some(speaker);\n\n            // Configure RTC interrupt\n            unsafe {\n                pac::NVIC::unmask(pac::Interrupt::RTC0);\n            }\n            pac::NVIC::unpend(pac::Interrupt::RTC0);\n        });\n    }\n\n    loop {\n        continue;\n    }\n}\n\nconst STOP_FREQUENCY: u32 = 500;\n\n// RTC interrupt, exectued for each RTC tick\n#[interrupt]\nfn RTC0() {\n    static mut FREQUENCY: u32 = 1;\n    /* Enter critical section */\n    cortex_m::interrupt::free(|cs| {\n        /* Borrow devices */\n        if let (Some(speaker), Some(rtc)) = (\n            SPEAKER.borrow(cs).borrow().as_ref(),\n            RTC.borrow(cs).borrow().as_ref(),\n        ) {\n            if *FREQUENCY < STOP_FREQUENCY {\n                // Configure the new frequency, must not be zero.\n                // Will change the max_duty\n                speaker.set_period(Hertz(*FREQUENCY));\n            } else {\n                // Continue at frequency\n                speaker.set_period(Hertz(STOP_FREQUENCY));\n            }\n            // Restart the PWM at 50% duty cycle\n            let max_duty = speaker.max_duty();\n            speaker.set_duty_on_common(max_duty / 2);\n            if *FREQUENCY >= STOP_FREQUENCY + 250 {\n                defmt::info!(\"Fin\");\n                // Stop speaker and RTC\n                speaker.disable();\n                rtc.disable_counter();\n            };\n            // Clear the RTC interrupt\n            rtc.reset_event(RtcInterrupt::Tick);\n        }\n    });\n    // Increase the frequency\n    *FREQUENCY += 1;\n}\n"
  },
  {
    "path": "memory.x",
    "content": "MEMORY\n{\n  /* NOTE K = KiBi = 1024 bytes */\n  FLASH : ORIGIN = 0x00000000, LENGTH = 256K\n  RAM : ORIGIN = 0x20000000, LENGTH = 16K\n}\n"
  },
  {
    "path": "microbit/Cargo.toml",
    "content": "[package]\nname = \"microbit\"\nversion = \"0.16.0\"\ndescription = \"Board support crate for the BBC Micro:bit V1\"\nedition = \"2018\"\nreadme = \"../README.md\"\nrust-version = \"1.79.0\"\n\nrepository = \"https://github.com/nrf-rs/microbit\"\nauthors = [\n  \"Daniel Egger <daniel@eggers-club.de>\",\n  \"Michael Droogleever <droogmic@gmail.com>\",\n  \"Rob Young <rob@robyoung.digital>\",\n]\ncategories = [\"hardware-support\", \"embedded\", \"no-std\"]\nkeywords = [\"arm\", \"cortex-m\", \"nrf\", \"hal\"]\nlicense = \"0BSD\"\n\n[dependencies]\n\n[dependencies.microbit-common]\npath = \"../microbit-common\"\nfeatures = [\"v1\"]\nversion = \"=0.16.0\"\n\n[features]\nembedded-hal-02 = [\"microbit-common/embedded-hal-02\"]\n"
  },
  {
    "path": "microbit/src/lib.rs",
    "content": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)\n//! microcontroller board.\n//!\n//! This crate is for the original micro:bit (V1) pictured below on the left. If\n//! your micro:bit looks like the one on the right you need the\n//! [microbit-v2](https://crates.io/crates/microbit-v2) crate.\n//!\n//! [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-1-5.png\" width=\"372px\" height=\"300px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-1-5.png)\n//! [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-2.png\" width=\"372px\" height=\"300px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-2.png)\n#![doc(html_root_url = \"https://docs.rs/microbit/0.16.0\")]\n#![no_std]\n#![deny(missing_docs)]\n#![allow(non_camel_case_types)]\n\npub use microbit_common::*;\n"
  },
  {
    "path": "microbit-common/Cargo.toml",
    "content": "[package]\nname = \"microbit-common\"\nversion = \"0.16.0\"\ndescription = \"Implementation details for the BBC Micro:bit board support crates\"\nedition = \"2018\"\nreadme = \"../README.md\"\nrust-version = \"1.79.0\"\n\nrepository = \"https://github.com/nrf-rs/microbit\"\nauthors = [\n  \"Daniel Egger <daniel@eggers-club.de>\",\n  \"Michael Droogleever <droogmic@gmail.com>\",\n  \"Rob Young <rob@robyoung.digital>\",\n]\ncategories = [\"hardware-support\", \"embedded\", \"no-std\"]\nkeywords = [\"arm\", \"cortex-m\", \"nrf\", \"hal\"]\nlicense = \"0BSD\"\n\n[dependencies]\ntiny-led-matrix = \"1.0.2\"\nembedded-hal = \"1.0.0\"\n\n[dependencies.nrf51-hal]\noptional = true\nversion = \"0.19.0\"\ndefault-features = false\nfeatures = [\"rt\", \"xxAB-package\"]\n\n[dependencies.nrf52833-hal]\noptional = true\nversion = \"0.19.0\"\ndefault-features = false\nfeatures = [\"rt\"]\n\n[features]\ndoc = []\nv1 = [\"nrf51-hal\"]\nv2 = [\"nrf52833-hal\"]\nembedded-hal-02 = [\n  \"nrf51-hal?/embedded-hal-02\",\n  \"nrf52833-hal?/embedded-hal-02\",\n]\n\n[package.metadata.docs.rs]\nfeatures = [\"v2\"]\ndefault-target = \"thumbv7em-none-eabihf\"\n"
  },
  {
    "path": "microbit-common/src/adc.rs",
    "content": "//! ADC\n#[cfg(feature = \"v1\")]\npub use crate::v1::adc::*;\n\n#[cfg(feature = \"v2\")]\npub use crate::v2::adc::*;\n"
  },
  {
    "path": "microbit-common/src/board.rs",
    "content": "//! Main Board\n#[cfg(feature = \"v1\")]\npub use crate::v1::board::*;\n\n#[cfg(feature = \"v2\")]\npub use crate::v2::board::*;\n"
  },
  {
    "path": "microbit-common/src/display/blocking.rs",
    "content": "//! Blocking support for the 5x5 LED display.\n//!\n//! This module provides a simple blocking interface\n//! to the on board 5x5 LED display. If you need a more sophisticated\n//! or non-blocking interface use the [`display::nonblocking`](crate::display::nonblocking) module.\n//!\n//! # Example\n//!\n//! ```no_run\n//! # use microbit_common as microbit;\n//! # use microbit::{\n//! #     Board,\n//! #     hal,\n//! #     display::blocking::Display,\n//! # };\n//! # use embedded_hal::delay::DelayNs;\n//! // take the board\n//! let board = Board::take().unwrap();\n//! // make a timer\n//! let mut timer = hal::Timer::new(board.TIMER0);\n//! // create the Display\n//! let mut display = Display::new(board.display_pins);\n//! // and light up some LEDs\n//! let heart = [\n//!     [0, 1, 0, 1, 0],\n//!     [1, 0, 1, 0, 1],\n//!     [1, 0, 0, 0, 1],\n//!     [0, 1, 0, 1, 0],\n//!     [0, 0, 1, 0, 0],\n//! ];\n//! loop {\n//!     display.show(&mut timer, heart, 1000);\n//!     display.clear();\n//!     timer.delay_ms(250);\n//! }\n//! ```\n//!\n//! The coordiante system is oriented so the 'bottom' (x,4) row is the edge with the edge\n//! connector. That means that\n//!\n//! ```no_run\n//! # use microbit_common as microbit;\n//! # use microbit::{\n//! #     Board,\n//! #     hal,\n//! #     display::blocking::Display,\n//! # };\n//! # let board = Board::take().unwrap();\n//! # let mut timer = hal::Timer::new(board.TIMER0);\n//! # let mut display = Display::new(board.display_pins);\n//! display.show(\n//!    &mut timer,\n//!    [\n//!        [0, 0, 1, 0, 0],\n//!        [0, 1, 1, 1, 0],\n//!        [1, 0, 1, 0, 1],\n//!        [0, 0, 1, 0, 0],\n//!        [0, 0, 1, 0, 0],\n//!    ],\n//!    1000,\n//!);\n//! ```\n//! Will display an arrow pointing towards the boards usb port.\n//!\n//! For a working example [`examples/display-blocking`](https://github.com/nrf-rs/microbit/tree/main/examples/display-blocking)\nuse crate::gpio::{DisplayPins, NUM_COLS, NUM_ROWS};\nuse crate::hal::gpio::{Output, Pin, PushPull};\nuse embedded_hal::{delay::DelayNs, digital::OutputPin};\n\n#[allow(clippy::upper_case_acronyms)]\npub(crate) type LED = Pin<Output<PushPull>>;\n\nconst DEFAULT_DELAY_MS: u32 = 2;\n#[cfg(feature = \"v1\")]\nconst LED_LAYOUT: [[(usize, usize); 5]; 5] = [\n    [(0, 0), (1, 3), (0, 1), (1, 4), (0, 2)],\n    [(2, 3), (2, 4), (2, 5), (2, 6), (2, 7)],\n    [(1, 1), (0, 8), (1, 2), (2, 8), (1, 0)],\n    [(0, 7), (0, 6), (0, 5), (0, 4), (0, 3)],\n    [(2, 2), (1, 6), (2, 0), (1, 5), (2, 1)],\n];\n\n/// Blocking interface to the on board LED display\npub struct Display {\n    delay_ms: u32,\n    rows: [LED; NUM_ROWS],\n    cols: [LED; NUM_COLS],\n}\n\nimpl Display {\n    /// Create and initialise the display driver\n    ///\n    /// The [`display_pins!`](crate::display_pins) macro can be used\n    /// to create [`DisplayPins`].\n    pub fn new(pins: DisplayPins) -> Self {\n        let (cols, rows) = pins.degrade();\n        Display {\n            delay_ms: DEFAULT_DELAY_MS,\n            rows,\n            cols,\n        }\n    }\n\n    /// Clear the display\n    pub fn clear(&mut self) {\n        for row in &mut self.rows {\n            row.set_low().ok();\n        }\n        for col in &mut self.cols {\n            col.set_high().ok();\n        }\n    }\n\n    /// Set delay, time spent on each matrix row, in ms\n    pub fn set_delay_ms(&mut self, delay_ms: u32) {\n        self.delay_ms = delay_ms;\n    }\n\n    /// Set refresh rate, time for matrix scan\n    pub fn set_refresh_rate(&mut self, freq_hz: u32) {\n        self.delay_ms = 1000 / freq_hz / (NUM_ROWS as u32);\n    }\n\n    /// Convert 5x5 image to 3x9 matrix\n    ///\n    /// The pins are represented as a [3x9 matrix on the micro:bit\n    /// V1](https://tech.microbit.org/hardware/1-5-revision/#display).\n    #[cfg(feature = \"v1\")]\n    fn image2matrix(led_image: [[u8; 5]; 5]) -> [[u8; 9]; 3] {\n        let mut led_matrix: [[u8; 9]; 3] = [[0; 9]; 3];\n        for (led_image_row, layout_row) in led_image.iter().zip(LED_LAYOUT.iter()) {\n            for (led_image_val, layout_loc) in led_image_row.iter().zip(layout_row) {\n                led_matrix[layout_loc.0][layout_loc.1] = *led_image_val;\n            }\n        }\n        led_matrix\n    }\n\n    /// Display 5x5 image for a given duration\n    pub fn show<D: DelayNs>(&mut self, delay: &mut D, led_display: [[u8; 5]; 5], duration_ms: u32) {\n        #[cfg(feature = \"v1\")]\n        {\n            let led_matrix = Display::image2matrix(led_display);\n            self.show_inner(delay, led_matrix, duration_ms);\n        }\n        #[cfg(feature = \"v2\")]\n        self.show_inner(delay, led_display, duration_ms);\n    }\n\n    /// Display matrix image for a given duration (3x9 for V1 micro:bit)\n    ///\n    /// The pins are represented as a [3x9 matrix on the micro:bit\n    /// V1](https://tech.microbit.org/hardware/1-5-revision/#display).\n    fn show_inner<D: DelayNs>(\n        &mut self,\n        delay: &mut D,\n        led_matrix: [[u8; NUM_COLS]; NUM_ROWS],\n        duration_ms: u32,\n    ) {\n        // TODO: something more intelligent with timers\n        let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms);\n        for _ in 0..loops {\n            for (row_line, led_matrix_row) in self.rows.iter_mut().zip(led_matrix.iter()) {\n                row_line.set_high().ok();\n                for (col_line, led_matrix_val) in self.cols.iter_mut().zip(led_matrix_row.iter()) {\n                    // TODO : use value to set brightness\n                    if *led_matrix_val > 0 {\n                        col_line.set_low().ok();\n                    }\n                }\n                delay.delay_us(self.delay_ms * 1000);\n                for col_line in &mut self.cols {\n                    col_line.set_high().ok();\n                }\n                row_line.set_low().ok();\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/display/mod.rs",
    "content": "//! Support for the 5x5 LED display.\n//!\n//! There are two APIs for controlling the LED display, [`blocking`] and [`nonblocking`].\n//! The `blocking` API is the simplest to get started with.\npub mod blocking;\npub mod nonblocking;\n"
  },
  {
    "path": "microbit-common/src/display/nonblocking/control.rs",
    "content": "//! Implementation of [`DisplayControl`] for the micro:bit's GPIO peripheral.\n//!\n//! This controls the micro:bit's 5×5 LED display.\n//!\n//! [`DisplayControl`]: tiny_led_matrix::DisplayControl\n\nuse tiny_led_matrix::DisplayControl;\n\nuse crate::{\n    gpio::{NUM_COLS, NUM_ROWS},\n    pac,\n};\n\nconst fn pin_bits(pins: &[usize]) -> u32 {\n    let mut i: usize = 0;\n    let mut bits: u32 = 0;\n    while i < pins.len() {\n        bits |= 1 << pins[i];\n        i += 1;\n    }\n    bits\n}\n\n#[cfg(feature = \"v1\")]\nmod pins {\n    use super::{NUM_COLS, NUM_ROWS};\n    pub(super) const P0_COLS: [usize; NUM_COLS] = [4, 5, 6, 7, 8, 9, 10, 11, 12];\n    pub(super) const P0_ROWS: [usize; NUM_ROWS] = [13, 14, 15];\n}\n\n#[cfg(feature = \"v2\")]\nmod pins {\n    use super::{NUM_COLS, NUM_ROWS};\n    pub(super) const P0_COLS: [usize; NUM_COLS - 1] = [28, 11, 31, 30];\n    pub(super) const P1_COLS: [usize; 1] = [5];\n\n    pub(super) const P0_ROWS: [usize; NUM_ROWS] = [21, 22, 15, 24, 19];\n}\n\nconst P0_COL_BITS: u32 = pin_bits(&pins::P0_COLS);\n#[cfg(feature = \"v2\")]\nconst P1_COL_BITS: u32 = pin_bits(&pins::P1_COLS);\n\nconst P0_ROW_BITS: u32 = pin_bits(&pins::P0_ROWS);\n\n#[cfg(feature = \"v1\")]\ntype P0 = pac::GPIO;\n\n#[cfg(feature = \"v2\")]\ntype P0 = pac::P0;\n\n#[cfg(feature = \"v2\")]\ntype P1 = pac::P1;\n\n/// This implements the `DisplayControl` trait.\n///\n/// [`DisplayControl`]: tiny_led_matrix::DisplayControl\npub(crate) struct MicrobitGpio;\n\n/// Returns the GPIO pin numbers corresponding to the columns in a Column\nfn column_pins(mut cols: u32, px_cols: &[usize]) -> u32 {\n    let mut result = 0u32;\n    for &pin in px_cols.iter() {\n        result |= (cols & 1) << pin;\n        cols >>= 1;\n    }\n    result\n}\n\n#[cfg(feature = \"v1\")]\nfn split_cols(cols: u32) -> (u32, u32) {\n    (cols, 0u32)\n}\n\n#[cfg(feature = \"v2\")]\nfn split_cols(cols: u32) -> (u32, u32) {\n    // get all except col 2 (4th from least significant)\n    let p0_cols = ((cols & 0b10000) >> 1) | (0b00111 & cols);\n    // get col 4 (4th from least significant)\n    let p1_cols = (cols & 0b01000) >> 3;\n    (p0_cols, p1_cols)\n}\n\n/// Implementation of [`DisplayControl`] for the micro:bit's GPIO peripheral.\n///\n/// This controls the micro:bit's 5×5 LED display.\n///\n/// The `initialise_for display` implementation assumes the port is in the\n/// state it would have after system reset.\n///\n/// [`DisplayControl`]: tiny_led_matrix::DisplayControl\nimpl DisplayControl for MicrobitGpio {\n    fn initialise_for_display(&mut self) {\n        unsafe {\n            let p0 = &*P0::ptr();\n            for ii in pins::P0_COLS.iter() {\n                p0.pin_cnf[*ii].write(|w| w.dir().output());\n            }\n            for ii in pins::P0_ROWS.iter() {\n                p0.pin_cnf[*ii].write(|w| w.dir().output());\n            }\n\n            // Set all p0 cols high.\n            p0.outset\n                .write(|w| w.bits(pins::P0_COLS.iter().map(|pin| 1 << pin).sum()));\n\n            #[cfg(feature = \"v2\")]\n            {\n                let p1 = &*P1::ptr();\n                for ii in pins::P1_COLS.iter() {\n                    p1.pin_cnf[*ii].write(|w| w.dir().output());\n                }\n                // Set all p1 cols high.\n                p1.outset\n                    .write(|w| w.bits(pins::P1_COLS.iter().map(|pin| 1 << pin).sum()));\n            }\n        }\n    }\n\n    fn display_row_leds(&mut self, row: usize, cols: u32) {\n        unsafe {\n            let p0 = &*P0::ptr();\n\n            #[allow(unused_variables)]\n            let (p0cols, p1cols) = split_cols(cols);\n\n            // To light an LED, we set the row bit and clear the col bit.\n            let rows_to_set = 1 << pins::P0_ROWS[row];\n            let rows_to_clear = P0_ROW_BITS ^ rows_to_set;\n\n            #[cfg(feature = \"v1\")]\n            {\n                let cols_to_clear = column_pins(p0cols, &pins::P0_COLS);\n                let cols_to_set = P0_COL_BITS ^ cols_to_clear;\n                p0.outset.write(|w| w.bits(rows_to_set | cols_to_set));\n                p0.outclr.write(|w| w.bits(rows_to_clear | cols_to_clear));\n            }\n\n            #[cfg(feature = \"v2\")]\n            {\n                let p1 = &*P1::ptr();\n                let p0_cols_to_clear = column_pins(p0cols, &pins::P0_COLS);\n                let p0_cols_to_set = P0_COL_BITS ^ p0_cols_to_clear;\n                let p1_cols_to_clear = column_pins(p1cols, &pins::P1_COLS);\n                let p1_cols_to_set = P1_COL_BITS ^ p1_cols_to_clear;\n                // We do the row-clearing write first and the row-setting write last, so that\n                // intermediate states never light LEDs which aren't lit in either the old or new state.\n                p0.outclr\n                    .write(|w| w.bits(rows_to_clear | p0_cols_to_clear));\n                p1.outset.write(|w| w.bits(p1_cols_to_set));\n                p1.outclr.write(|w| w.bits(p1_cols_to_clear));\n                p0.outset.write(|w| w.bits(rows_to_set | p0_cols_to_set));\n            }\n        }\n    }\n\n    fn light_current_row_leds(&mut self, cols: u32) {\n        unsafe {\n            #[allow(unused_variables)]\n            let (p0cols, p1cols) = split_cols(cols);\n            let p0 = &*P0::ptr();\n            p0.outclr\n                .write(|w| w.bits(column_pins(p0cols, &pins::P0_COLS)));\n\n            #[cfg(feature = \"v2\")]\n            {\n                let p1 = &*P1::ptr();\n                p1.outclr\n                    .write(|w| w.bits(column_pins(p1cols, &pins::P1_COLS)));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/display/nonblocking/image.rs",
    "content": "//! Static 5×5 greyscale and black-and-white images.\n\nuse tiny_led_matrix::{Render, MAX_BRIGHTNESS};\n\n/// A 5×5 image supporting the full range of brightnesses for each LED.\n///\n/// Uses 25 bytes of storage.\n#[derive(Copy, Clone, Debug)]\npub struct GreyscaleImage([[u8; 5]; 5]);\n\nimpl GreyscaleImage {\n    /// Constructs a GreyscaleImage from an array of brightnesses.\n    ///\n    /// The data should be an array of 5 rows (top first), each of which is an\n    /// array of 5 brightness values (left first).\n    ///\n    /// # Example\n    ///\n    /// ```no_run\n    /// # use microbit_common as microbit;\n    /// # use microbit::display::nonblocking::GreyscaleImage;\n    /// const GREY_HEART: GreyscaleImage = GreyscaleImage::new(&[\n    ///     [0, 9, 0, 9, 0],\n    ///     [9, 5, 9, 5, 9],\n    ///     [9, 5, 5, 5, 9],\n    ///     [0, 9, 5, 9, 0],\n    ///     [0, 0, 9, 0, 0],\n    /// ]);\n    /// ```\n    pub const fn new(data: &[[u8; 5]; 5]) -> GreyscaleImage {\n        GreyscaleImage(*data)\n    }\n\n    /// Construct a GreyscaleImage with all LEDs turned off.\n    pub const fn blank() -> GreyscaleImage {\n        GreyscaleImage([[0; 5]; 5])\n    }\n}\n\nimpl Render for GreyscaleImage {\n    fn brightness_at(&self, x: usize, y: usize) -> u8 {\n        self.0[y][x]\n    }\n}\n\nimpl Render for &GreyscaleImage {\n    fn brightness_at(&self, x: usize, y: usize) -> u8 {\n        GreyscaleImage::brightness_at(self, x, y)\n    }\n}\n\n/// A 5×5 image supporting only two levels of brightness (on and off).\n///\n/// Uses 5 bytes of storage.\n///\n/// For display, each pixel is treated as having brightness either 0 or\n/// MAX_BRIGHTNESS.\n#[derive(Copy, Clone, Debug)]\npub struct BitImage([u8; 5]);\n\nimpl BitImage {\n    /// Constructs a BitImage from an array of brightnesses.\n    ///\n    /// The data should be an array of 5 rows (top first), each of which is an\n    /// array of 5 values (left first). Each value should be either 0 or 1.\n    ///\n    /// # Example\n    ///\n    /// ```no_run\n    /// # use microbit_common as microbit;\n    /// # use microbit::display::nonblocking::BitImage;\n    /// const HEART: BitImage = BitImage::new(&[\n    ///     [0, 1, 0, 1, 0],\n    ///     [1, 0, 1, 0, 1],\n    ///     [1, 0, 0, 0, 1],\n    ///     [0, 1, 0, 1, 0],\n    ///     [0, 0, 1, 0, 0],\n    /// ]);\n    /// ```\n    pub const fn new(im: &[[u8; 5]; 5]) -> BitImage {\n        // FIXME: can we reject values other than 0 or 1?\n        const fn row_byte(row: [u8; 5]) -> u8 {\n            row[0] | (row[1] << 1) | (row[2] << 2) | (row[3] << 3) | (row[4] << 4)\n        }\n        BitImage([\n            row_byte(im[0]),\n            row_byte(im[1]),\n            row_byte(im[2]),\n            row_byte(im[3]),\n            row_byte(im[4]),\n        ])\n    }\n\n    /// Returns a new blank BitImage.\n    ///\n    /// All pixel values are 0.\n    pub const fn blank() -> BitImage {\n        BitImage([0; 5])\n    }\n}\n\nimpl Render for BitImage {\n    fn brightness_at(&self, x: usize, y: usize) -> u8 {\n        let rowdata = self.0[y];\n        if rowdata & (1 << x) != 0 {\n            MAX_BRIGHTNESS\n        } else {\n            0\n        }\n    }\n}\n\nimpl Render for &BitImage {\n    fn brightness_at(&self, x: usize, y: usize) -> u8 {\n        BitImage::brightness_at(self, x, y)\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/display/nonblocking/matrix.rs",
    "content": "//! Implementation of [`Matrix`] and [`Frame`] for the micro:bit's LED display.\n//!\n//! This module describes the correspondence between the visible layout of\n//! micro:bit's LEDs and the pins controlling them.\n//!\n//! [`Matrix`]: tiny_led_matrix::Matrix\n//! [`Frame`]: tiny_led_matrix::Frame\n\nuse crate::gpio::{NUM_COLS, NUM_ROWS};\nuse tiny_led_matrix::{Frame, Matrix, RowPlan};\n\n/// Implementation of [`Matrix`] for the microbit's LED display.\n///\n/// [`Matrix`]: tiny_led_matrix::Matrix\npub struct MicrobitMatrix();\n\n/// Gives the LED (x, y) coordinates for a given pin row and column.\n/// The origin is in the top-left.\n#[cfg(feature = \"v1\")]\nconst MICROBIT_LED_LAYOUT: [[Option<(usize, usize)>; 3]; 9] = [\n    [Some((0, 0)), Some((4, 2)), Some((2, 4))],\n    [Some((2, 0)), Some((0, 2)), Some((4, 4))],\n    [Some((4, 0)), Some((2, 2)), Some((0, 4))],\n    [Some((4, 3)), Some((1, 0)), Some((0, 1))],\n    [Some((3, 3)), Some((3, 0)), Some((1, 1))],\n    [Some((2, 3)), Some((3, 4)), Some((2, 1))],\n    [Some((1, 3)), Some((1, 4)), Some((3, 1))],\n    [Some((0, 3)), None, Some((4, 1))],\n    [Some((1, 2)), None, Some((3, 2))],\n];\n\nimpl Matrix for MicrobitMatrix {\n    /// The number of pins connected to LED columns (3).\n    const MATRIX_COLS: usize = NUM_COLS;\n    /// The number of pins connected to LED rows (9).\n    const MATRIX_ROWS: usize = NUM_ROWS;\n    /// The number of visible LED columns (5).\n    const IMAGE_COLS: usize = 5;\n    /// The number of visible LED rows (5).\n    const IMAGE_ROWS: usize = 5;\n\n    #[cfg(feature = \"v1\")]\n    fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {\n        MICROBIT_LED_LAYOUT[col][row]\n    }\n\n    #[cfg(feature = \"v2\")]\n    fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {\n        Some((col, row))\n    }\n}\n\n/// A 'Compiled' representation of a 5×5 image to be displayed.\n///\n/// Use the [`.set()`](`Frame::set`) method to store an image (something\n/// implementing [`Render`]) in the frame.\n///\n/// Note you'll have to `use microbit::display::Frame` to make `set()`\n/// available.\n///\n/// [`Frame`]: tiny_led_matrix::Frame\n/// [`Render`]: tiny_led_matrix::Render\n#[derive(Copy, Clone, Debug)]\npub struct MicrobitFrame([RowPlan; MicrobitFrame::ROWS]);\n\nimpl MicrobitFrame {\n    /// Returns a new frame, initially blank.\n    pub const fn default() -> MicrobitFrame {\n        MicrobitFrame([RowPlan::default(); MicrobitFrame::ROWS])\n    }\n}\n\nimpl Default for MicrobitFrame {\n    /// Returns a new frame, initially blank.\n    fn default() -> MicrobitFrame {\n        MicrobitFrame::default()\n    }\n}\n\nimpl Frame for MicrobitFrame {\n    type Mtx = MicrobitMatrix;\n\n    fn row_plan(&self, row: usize) -> &RowPlan {\n        &self.0[row]\n    }\n\n    fn row_plan_mut(&mut self, row: usize) -> &mut RowPlan {\n        &mut self.0[row]\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/display/nonblocking/mod.rs",
    "content": "//! Non-blocking support for the 5×5 LED display.\n//!\n//! Together with [`tiny-led-matrix`](tiny_led_matrix), this module provides:\n//! - support for driving the LED display from a timer interrupt\n//! - ten levels of brightness for each LED\n//! - simple 5×5 greyscale and black-and-white image types.\n//!\n//! The module doesn't define interrupt handlers directly; instead it provides\n//! a function to be called from a timer interrupt. It knows how to program\n//! one of the micro:bit's timers to provide that interrupt.\n//!\n//! ## Example\n//!\n//! This shows general usage but is not a working example.\n//! For a working exaple see\n//! [`display_nonblocking`](https://github.com/nrf-rs/microbit/tree/main/examples/display-nonblocking).\n//!\n//! ```no_run\n//! # use microbit_common as microbit;\n//! use microbit::{\n//!     Board,\n//!     hal,\n//!     display::nonblocking::{Display, GreyscaleImage},\n//! };\n//! use embedded_hal::delay::DelayNs;\n//!\n//! let board = Board::take().unwrap();\n//!\n//! let mut display = Display::new(board.TIMER1, board.display_pins);\n//!\n//! // in your main function\n//! {\n//!     let mut timer2 = hal::Timer::new(board.TIMER0);\n//!     loop {\n//!         display.show(&GreyscaleImage::new(&[\n//!             [0, 7, 0, 7, 0],\n//!             [7, 0, 7, 0, 7],\n//!             [7, 0, 0, 0, 7],\n//!             [0, 7, 0, 7, 0],\n//!             [0, 0, 7, 0, 0],\n//!         ]));\n//!         timer2.delay_ms(1000);\n//!\n//!         display.clear();\n//!         timer2.delay_ms(1000);\n//!     }\n//! }\n//!\n//! // in a timer interrupt\n//! {\n//!     display.handle_display_event();\n//! }\n//! ```\n//!\n//! ## Coordinate system\n//!\n//! The LEDs are identified using (x,y) coordinates as follows:\n//!\n//! ```text\n//! (0,0) ... (4,0)\n//!  ...  ...  ...\n//! (0,4) ... (4,4)\n//! ```\n//!\n//! where the 'bottom' (x,4) of the board is the edge connector.\n//!\n//! ## Greyscale model\n//!\n//! LED brightness levels are described using a scale from 0 (off) to 9\n//! (brightest) inclusive.\n//!\n//! These are converted to time slices using the same timings as used by the\n//! [micro:bit MicroPython port][micropython] (this is different to the 0 to\n//! 255 scale used by the [micro:bit runtime][dal]).\n//!\n//! The time slice for each level above 1 is approximately 1.9× the slice for\n//! the previous level.\n//!\n#![cfg_attr(\n    feature = \"v1\",\n    doc = \"An LED with brightness 9 is lit for one third of the time (because internally there are three 'rows' of LEDs which have to be addressed one at a time).\"\n)]\n#![cfg_attr(\n    feature = \"v2\",\n    doc = \"An LED with brightness 9 is lit for one fifth of the time.\"\n)]\n//!\n//! ## Images\n//!\n//! An image is a type that implements the [`tiny_led_matrix::Render`] trait. Two image types are provided:\n//! - [`GreyscaleImage`](image::GreyscaleImage), allowing all 9 levels (using one byte for each LED)\n//! - [`BitImage`](image::BitImage), allowing only 'on' and 'off' (using five bytes)\n//!\n//! ## Display\n//!\n//! A [`Display`] instance controls the LEDs and programs a timer. There\n//! should normally be a single `Display` instance in the program. It is a wrapper\n//! around [`tiny_led_matrix::Display`] to expose an API similar to the blocking API.\n//!\n//! ## Frames\n//!\n//! Internally types implementing [`Render`](tiny_led_matrix::Render) aren't used directly with the [`Display`];\n//! instead they're used to update a [`MicrobitFrame`] instance which is in\n//! turn passed to the `tiny_led_matrix::Display`.\n//!\n//! A `MicrobitFrame` instance is a 'compiled' representation of a 5×5\n//! greyscale image, in a form that's more directly usable by the display\n//! code.\n//!\n//! This is exposed in the public API so that you can construct the\n//! `MicrobitFrame` representation in code running at a low priority. Then\n//! only [`Display::show_frame()`] has to be called in code that can't be\n//! interrupted by the display timer.\n//!\n//! ## Timer integration\n//!\n//! The [`Display`] expects to control a single timer. It can use the\n//! micro:bit's `TIMER0`, `TIMER1`, or `TIMER2`.\n//!\n//! For the micro:bit v1 this uses a 6ms period to light each of the three\n//! internal LED rows, so that the entire display is updated every 18ms.\n//!\n//! For the micro:bit v2 this uses a 3ms period to light each of the five\n//! internal LED rows, so that the entire display is updated every 15ms.\n//!\n//! When rendering greyscale images, the `Display` requests extra interrupts\n//! within each 6ms or 3ms period. It only requests interrupts for the\n//! greyscale levels which are actually required for what's currently being\n//! displayed.\n//!\n//! ### Technical details\n//!\n//! The timer is set to 16-bit mode, using a 62.5kHz or 135Khz clock (16 µs or\n//! 8µs ticks). It resets every 375 ticks.\n//!\n//! ## Usage\n//!\n//! Choose a timer to drive the display from (`TIMER0`, `TIMER1`, or `TIMER2`).\n//!\n//! When your program starts:\n//! - create a [`Display`] struct passing the timer and\n//! [`gpio::DisplayPins`](crate::gpio::DisplayPins) to [`Display::new()`].\n//!\n//! In an interrupt handler for the timer call [`.handle_display_event()`](Display::handle_display_event)\n//!\n//! To change what's displayed; pass an image ([`GreyscaleImage`] or [`BitImage`]) to [`Display::show`].\n//!\n//! You can call `show()` at any time, so long as you're not interrupting, or interruptable by,\n//! [`Display::handle_display_event()`].\n//!\n//! See [`display_rtic`](https://github.com/nrf-rs/microbit/blob/master/examples/display_rtic) or\n//! [`display_nonblocking`](https://github.com/nrf-rs/microbit/blob/master/examples/display_nonblocking)\n//! example for a complete working example.\n//!\n//! [dal]: https://lancaster-university.github.io/microbit-docs/\n//! [micropython]: https://microbit-micropython.readthedocs.io/\n\nuse tiny_led_matrix;\n#[doc(no_inline)]\npub use tiny_led_matrix::{Frame, MAX_BRIGHTNESS};\n\nmod control;\nmod image;\nmod matrix;\nmod timer;\n\npub use image::{BitImage, GreyscaleImage};\npub use matrix::MicrobitFrame;\nuse timer::MicrobitDisplayTimer;\n\nuse crate::{gpio::DisplayPins, hal::timer::Instance};\n\nuse control::MicrobitGpio;\n\n/// Non-blocking interface to the on board 5x5 LED display\npub struct Display<T: Instance> {\n    display: tiny_led_matrix::Display<MicrobitFrame>,\n    timer: MicrobitDisplayTimer<T>,\n    pins: DisplayPins,\n    frame: MicrobitFrame,\n}\n\nimpl<T: Instance> Display<T> {\n    /// Create and initialise the display driver\n    ///\n    /// [`DisplayPins`] can be used from [`Board::display_pins`](crate::Board::display_pins)\n    /// or the [`display_pins!`](crate::display_pins) macro can be used is manually.\n    pub fn new(timer: T, pins: DisplayPins) -> Self {\n        let mut display = Self {\n            display: tiny_led_matrix::Display::new(),\n            timer: MicrobitDisplayTimer::new(timer),\n            pins,\n            frame: MicrobitFrame::default(),\n        };\n        display.initialise();\n        display\n    }\n\n    /// Release the timer and pins\n    pub fn free(self) -> (T, DisplayPins) {\n        (self.timer.free(), self.pins)\n    }\n\n    /// Initialise the display\n    ///\n    /// This is usually called immediately after creating the display driver.\n    /// It does not need to be called in a critical section.\n    fn initialise(&mut self) {\n        tiny_led_matrix::initialise_control(&mut MicrobitGpio {});\n        tiny_led_matrix::initialise_timer(&mut self.timer);\n    }\n\n    /// Update the LED display and timer state\n    ///\n    /// Call this in an interrupt handler for the timer you're using. This method\n    /// takes care of updating the LED display and clearing the timer's event registers\n    ///\n    /// This may be called at any time, so long as the code calling it is not interrupting, or\n    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow\n    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method\n    /// should be called from within a [critical\n    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).\n    pub fn handle_display_event(&mut self) {\n        self.display\n            .handle_event(&mut self.timer, &mut MicrobitGpio {});\n    }\n\n    /// Show a new image\n    ///\n    /// This may be called at any time, so long as the code calling it is not interrupting, or\n    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow\n    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method\n    /// should be called from within a [critical\n    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).\n    ///\n    /// ## Example\n    ///\n    /// ```ignore\n    /// display.show(&GreyscaleImage::new(&[\n    ///     [0, 7, 0, 7, 0],\n    ///     [7, 0, 7, 0, 7],\n    ///     [7, 0, 0, 0, 7],\n    ///     [0, 7, 0, 7, 0],\n    ///     [0, 0, 7, 0, 0],\n    /// ]));\n    /// ```\n    pub fn show<R: tiny_led_matrix::Render>(&mut self, image: &R) {\n        self.frame.set(image);\n        self.display.set_frame(&self.frame);\n    }\n\n    /// Clear the display\n    ///\n    /// This may be called at any time, so long as the code calling it is not interrupting, or\n    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow\n    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method\n    /// should be called from within a [critical\n    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).\n    pub fn clear(&mut self) {\n        self.display.set_frame(&MicrobitFrame::default());\n    }\n\n    /// Show a new frame\n    ///\n    /// This is similar to [`show`](Display::show) but accepts a [`MicrobitFrame`] instead.\n    /// This may be useful if performance is a concern as calling `set` on the frame\n    /// can be done outside the critical section.\n    ///\n    /// This may be called at any time, so long as the code calling it is not interrupting, or\n    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow\n    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method\n    /// should be called from within a [critical\n    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).\n    ///\n    /// ## Example\n    ///\n    /// ```ignore\n    /// FRAME = MicrobitFrame::default();\n    /// FRAME.set(&GreyscaleImage::new(&[\n    ///     [0, 7, 0, 7, 0],\n    ///     [7, 0, 7, 0, 7],\n    ///     [7, 0, 0, 0, 7],\n    ///     [0, 7, 0, 7, 0],\n    ///     [0, 0, 7, 0, 0],\n    /// ]));\n    ///\n    /// // only this needs to be in a critical section\n    /// display.show_frame(&FRAME);\n    /// ```\n    pub fn show_frame(&mut self, frame: &MicrobitFrame) {\n        self.display.set_frame(frame);\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/display/nonblocking/timer.rs",
    "content": "//! Implementation of [`DisplayTimer`] for the nRF51 `TIMER`s.\n//!\n//! [`DisplayTimer`]: tiny_led_matrix::DisplayTimer\n\nuse tiny_led_matrix::DisplayTimer;\n\nuse crate::hal::timer::Instance;\n\n/// A TIMER peripheral programmed to manage the display.\n///\n/// `MicrobitDisplayTimer` instances implement the [`DisplayTimer`] trait.\n///\n/// The timer is set to 16-bit mode.\n///\n/// For micro:bit v1: uses a 62.5kHz clock clock (16 µs ticks).\n/// The primary cycle takes 6ms.\n///\n/// For micro:bit v2: uses a 135kHz clock (8 µs ticks).\n/// The primary cycle takes 3ms.\n///\n/// Uses CC0 for the primary cycle and CC1 for the secondary alarm. Uses the\n/// CC0_CLEAR shortcut to implement the primary cycle.\n///\n/// [`DisplayTimer`]: tiny_led_matrix::DisplayTimer\npub struct MicrobitDisplayTimer<T: Instance>(T);\n\nimpl<T: Instance> MicrobitDisplayTimer<T> {\n    /// Returns a new `MicrobitDisplayTimer` wrapping the passed TIMER.\n    ///\n    /// Takes ownership of the TIMER peripheral.\n    pub fn new(timer: T) -> MicrobitDisplayTimer<T> {\n        MicrobitDisplayTimer(timer)\n    }\n\n    /// Gives the underlying `nrf51::TIMER`*n* instance back.\n    pub fn free(self) -> T {\n        self.0\n    }\n}\n\nimpl<T: Instance> DisplayTimer for MicrobitDisplayTimer<T> {\n    fn initialise_cycle(&mut self, ticks: u16) {\n        let timer0 = self.0.as_timer0();\n        // stop and reset timer\n        timer0.tasks_stop.write(|w| unsafe { w.bits(1) });\n        timer0.tasks_clear.write(|w| unsafe { w.bits(1) });\n\n        // set as 16 bits\n        timer0.bitmode.write(|w| w.bitmode()._16bit());\n\n        #[cfg(feature = \"v1\")]\n        // set frequency to 62500Hz\n        let prescaler = 8;\n        #[cfg(feature = \"v2\")]\n        // set frequency to 135000Hz\n        let prescaler = 7;\n        timer0.prescaler.write(|w| unsafe { w.bits(prescaler) });\n\n        // set compare register\n        timer0.cc[0].write(|w| unsafe { w.bits(ticks.into()) });\n\n        // enable auto clear\n        timer0.shorts.write(|w| w.compare0_clear().enabled());\n\n        // enable compare interrupt\n        timer0.intenset.write(|w| w.compare0().set());\n\n        // start\n        timer0.tasks_start.write(|w| unsafe { w.bits(1) });\n        // maybe?\n        // timer0.tasks_start.write(|w| w.tasks_start().set_bit());\n    }\n\n    fn enable_secondary(&mut self) {\n        self.0.as_timer0().intenset.write(|w| w.compare1().set());\n    }\n\n    fn disable_secondary(&mut self) {\n        self.0\n            .as_timer0()\n            .intenclr\n            .write(|w| w.compare1().set_bit());\n    }\n\n    fn program_secondary(&mut self, ticks: u16) {\n        #[cfg(feature = \"v1\")]\n        self.0.as_timer0().cc[1].write(|w| unsafe { w.bits(ticks.into()) });\n        #[cfg(feature = \"v2\")]\n        self.0.as_timer0().cc[1].write(|w| unsafe { w.cc().bits(ticks.into()) });\n    }\n\n    fn check_primary(&mut self) -> bool {\n        // poll compare event\n        let reg = &self.0.as_timer0().events_compare[0];\n        let fired = reg.read().bits() != 0;\n        if fired {\n            reg.reset();\n        }\n        fired\n    }\n\n    fn check_secondary(&mut self) -> bool {\n        // poll compare event\n        let reg = &self.0.as_timer0().events_compare[1];\n        let fired = reg.read().bits() != 0;\n        if fired {\n            reg.reset();\n        }\n        fired\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/gpio.rs",
    "content": "//! Named GPIO pin types\n//!\n//! This module maps the GPIO pin names as described in the\n//! [Pins and Signals section of the micro:bit site](https://tech.microbit.org/hardware/edgeconnector/#pins-and-signals)\n//! Where appropriate the pins are restricted with the appropriate `MODE`\n//! from `nrf-hal`.\n#[cfg(feature = \"v1\")]\npub use crate::v1::gpio::*;\n\n#[cfg(feature = \"v2\")]\npub use crate::v2::gpio::*;\n"
  },
  {
    "path": "microbit-common/src/lib.rs",
    "content": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)\n//! microcontroller board.\n#![doc(html_root_url = \"https://docs.rs/microbit-common/0.16.0\")]\n#![no_std]\n#![deny(missing_docs)]\n#![allow(non_camel_case_types)]\n\n#[cfg(all(feature = \"v1\", feature = \"v2\"))]\ncompile_error!(\"canot build for microbit v1 and v2 at the same time\");\n\n#[cfg(feature = \"v1\")]\npub use nrf51_hal as hal;\n\n#[cfg(feature = \"v2\")]\npub use nrf52833_hal as hal;\n\npub use hal::pac;\npub use hal::pac::Peripherals;\n\npub mod adc;\npub mod board;\npub mod display;\npub mod gpio;\n\npub use board::Board;\n\n#[cfg(feature = \"v1\")]\nmod v1;\n\n#[cfg(feature = \"v2\")]\nmod v2;\n"
  },
  {
    "path": "microbit-common/src/v1/adc.rs",
    "content": "use crate::hal;\n\n/// Adc alias to unify v1 and v2 names\npub type Adc = hal::Adc;\n/// AdcConfig alias to unify v1 and v2 names\npub type AdcConfig = hal::adc::AdcConfig;\n\n/// Same resolution for v1 and v2\npub trait Default {\n    /// v1 is limited to 10 bit\n    fn default_10bit() -> Self;\n}\n\nimpl Default for AdcConfig {\n    fn default_10bit() -> Self {\n        AdcConfig::default()\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/v1/board.rs",
    "content": "use super::gpio::{\n    DisplayPins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE12, EDGE16, SCL, SDA, UART_RX,\n    UART_TX,\n};\nuse crate::{\n    hal::{\n        gpio::{p0, Disconnected, Level},\n        twi, uart,\n    },\n    pac,\n};\n\n/// Provides access to the microbit\n#[allow(non_snake_case)]\npub struct Board {\n    /// GPIO pins that are not otherwise used\n    pub pins: Pins,\n\n    /// Unused GPIO pins on edge connector\n    pub edge: Edge,\n\n    /// display pins\n    pub display_pins: DisplayPins,\n\n    /// buttons\n    pub buttons: Buttons,\n\n    /// I2C shared internal and external bus pins\n    pub i2c: I2CPins,\n\n    /// UART to debugger pins\n    pub uart: UartPins,\n\n    /// Core peripheral: Cache and branch predictor maintenance operations\n    pub CBP: pac::CBP,\n\n    /// Core peripheral: CPUID\n    pub CPUID: pac::CPUID,\n\n    /// Core peripheral: Debug Control Block\n    pub DCB: pac::DCB,\n\n    /// Core peripheral: Data Watchpoint and Trace unit\n    pub DWT: pac::DWT,\n\n    /// Core peripheral: Flash Patch and Breakpoint unit\n    pub FPB: pac::FPB,\n\n    /// Core peripheral: Instrumentation Trace Macrocell\n    pub ITM: pac::ITM,\n\n    /// Core peripheral: Memory Protection Unit\n    pub MPU: pac::MPU,\n\n    /// Core peripheral: Nested Vector Interrupt Controller\n    pub NVIC: pac::NVIC,\n\n    /// Core peripheral: System Control Block\n    pub SCB: pac::SCB,\n\n    /// Core peripheral: SysTick Timer\n    pub SYST: pac::SYST,\n\n    /// Core peripheral: Trace Port Interface Unit\n    pub TPIU: pac::TPIU,\n\n    /// nRF51 peripheral: ADC\n    pub ADC: pac::ADC,\n\n    /// nRF51 peripheral: CLOCK\n    pub CLOCK: pac::CLOCK,\n\n    /// nRF51 peripheral: FICR\n    pub FICR: pac::FICR,\n\n    /// nRF51 peripheral: GPIOTE\n    pub GPIOTE: pac::GPIOTE,\n\n    /// nRF51 preipheral: PPI\n    pub PPI: pac::PPI,\n\n    /// nRF51 peripheral: RADIO\n    pub RADIO: pac::RADIO,\n\n    /// nRF51 peripheral: RNG\n    pub RNG: pac::RNG,\n\n    /// nRF51 peripheral: RTC0\n    pub RTC0: pac::RTC0,\n\n    /// nRF51 peripheral: TEMP <br>\n    /// Can be used with [`Temp::new()`](`crate::hal::temp::Temp::new()`)\n    pub TEMP: pac::TEMP,\n\n    /// nRF51 peripheral: TIMER0\n    pub TIMER0: pac::TIMER0,\n\n    /// nRF51 peripheral: TIMER1\n    pub TIMER1: pac::TIMER1,\n\n    /// nRF51 peripheral: TIMER2\n    pub TIMER2: pac::TIMER2,\n\n    /// nRF51 peripheral: TWI0\n    pub TWI0: pac::TWI0,\n\n    /// nrf51 peripheral: UART0\n    pub UART0: pac::UART0,\n\n    /// nrf51 peripheral: POWER\n    pub POWER: pac::POWER,\n\n    /// nrf51 peripheral: SPI0\n    pub SPI0: pac::SPI0,\n\n    /// nrf51 peripheral: SPI1\n    pub SPI1: pac::SPI1,\n\n    /// nrf51 peripheral: TWI1\n    pub TWI1: pac::TWI1,\n\n    /// nrf51 peripheral: SPIS1\n    pub SPIS1: pac::SPIS1,\n\n    /// nrf51 peripheral: ECB\n    pub ECB: pac::ECB,\n\n    /// nrf51 peripheral: AAR\n    pub AAR: pac::AAR,\n\n    /// nrf51 peripheral: CCM\n    pub CCM: pac::CCM,\n\n    /// nrf51 peripheral: WDT\n    pub WDT: pac::WDT,\n\n    /// nrf51 peripheral: RTC1\n    pub RTC1: pac::RTC1,\n\n    /// nrf51 peripheral: QDEC\n    pub QDEC: pac::QDEC,\n\n    /// nrf51 peripheral: LPCOMP\n    pub LPCOMP: pac::LPCOMP,\n\n    /// nrf51 peripheral: SWI\n    pub SWI: pac::SWI,\n\n    /// nrf51 peripheral: NVMC\n    pub NVMC: pac::NVMC,\n\n    /// nrf51 peripheral: UICR\n    pub UICR: pac::UICR,\n}\n\nimpl Board {\n    /// Take the peripherals safely\n    ///\n    /// This method will return an instance of the board the first time it is\n    /// called. It will return only `None` on subsequent calls.\n    /// This function can also return `None` if one of the the peripherals was\n    /// already taken.\n    pub fn take() -> Option<Self> {\n        Some(Self::new(\n            pac::Peripherals::take()?,\n            pac::CorePeripherals::take()?,\n        ))\n    }\n\n    /// Fallback method in the case peripherals and core peripherals were taken\n    /// elsewhere already.\n    ///\n    /// This method will take the peripherals and core peripherals and\n    /// return an instance of the board.\n    ///\n    /// An exemplary usecase is shown in the rtic display example.\n    pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {\n        let p0parts = p0::Parts::new(p.GPIO);\n        Self {\n            pins: Pins {\n                //p0_01: p0parts.p0_01,\n                //p0_02: p0parts.p0_02,\n                //p0_03: p0parts.p0_03,\n                //p0_16: p0parts.p0_16,\n                //p0_18: p0parts.p0_18,\n                p0_19: p0parts.p0_19,\n                //p0_20: p0parts.p0_20,\n                p0_21: p0parts.p0_21,\n                p0_22: p0parts.p0_22,\n                p0_23: p0parts.p0_23,\n                p0_27: p0parts.p0_27,\n                p0_28: p0parts.p0_28,\n                p0_29: p0parts.p0_29,\n            },\n            edge: Edge {\n                e00: p0parts.p0_03,\n                e01: p0parts.p0_02,\n                e02: p0parts.p0_01,\n                e08: p0parts.p0_18,\n                e12: p0parts.p0_20,\n                e16: p0parts.p0_16,\n            },\n            display_pins: DisplayPins {\n                row1: p0parts.p0_13.into_push_pull_output(Level::Low),\n                row2: p0parts.p0_14.into_push_pull_output(Level::Low),\n                row3: p0parts.p0_15.into_push_pull_output(Level::Low),\n                col1: p0parts.p0_04.into_push_pull_output(Level::High),\n                col2: p0parts.p0_05.into_push_pull_output(Level::High),\n                col3: p0parts.p0_06.into_push_pull_output(Level::High),\n                col4: p0parts.p0_07.into_push_pull_output(Level::High),\n                col5: p0parts.p0_08.into_push_pull_output(Level::High),\n                col6: p0parts.p0_09.into_push_pull_output(Level::High),\n                col7: p0parts.p0_10.into_push_pull_output(Level::High),\n                col8: p0parts.p0_11.into_push_pull_output(Level::High),\n                col9: p0parts.p0_12.into_push_pull_output(Level::High),\n            },\n            buttons: Buttons {\n                button_a: p0parts.p0_17.into_floating_input(),\n                button_b: p0parts.p0_26.into_floating_input(),\n            },\n            i2c: I2CPins {\n                scl: p0parts.p0_00.into_floating_input(),\n                sda: p0parts.p0_30.into_floating_input(),\n            },\n            uart: UartPins {\n                tx: p0parts.p0_24.into_push_pull_output(Level::Low),\n                rx: p0parts.p0_25.into_floating_input(),\n            },\n\n            // Core peripherals\n            CBP: cp.CBP,\n            CPUID: cp.CPUID,\n            DCB: cp.DCB,\n            DWT: cp.DWT,\n            FPB: cp.FPB,\n            ITM: cp.ITM,\n            MPU: cp.MPU,\n            NVIC: cp.NVIC,\n            SCB: cp.SCB,\n            SYST: cp.SYST,\n            TPIU: cp.TPIU,\n\n            // nRF51 peripherals\n            ADC: p.ADC,\n            CLOCK: p.CLOCK,\n            FICR: p.FICR,\n            GPIOTE: p.GPIOTE,\n            PPI: p.PPI,\n            RADIO: p.RADIO,\n            RNG: p.RNG,\n            RTC0: p.RTC0,\n            TEMP: p.TEMP,\n            TIMER0: p.TIMER0,\n            TIMER1: p.TIMER1,\n            TIMER2: p.TIMER2,\n            TWI0: p.TWI0,\n            UART0: p.UART0,\n            POWER: p.POWER,\n            SPI0: p.SPI0,\n            SPI1: p.SPI1,\n            TWI1: p.TWI1,\n            SPIS1: p.SPIS1,\n            ECB: p.ECB,\n            AAR: p.AAR,\n            CCM: p.CCM,\n            WDT: p.WDT,\n            RTC1: p.RTC1,\n            QDEC: p.QDEC,\n            LPCOMP: p.LPCOMP,\n            SWI: p.SWI,\n            NVMC: p.NVMC,\n            UICR: p.UICR,\n        }\n    }\n}\n\n/// Unused GPIO pins\n#[allow(missing_docs)]\npub struct Pins {\n    // pub p0_00: p0::P0_00<Disconnected>, // SCL\n    // pub p0_01: p0::P0_01<Disconnected>, // PAD2, EDGE02\n    // pub p0_02: p0::P0_02<Disconnected>, // PAD1, EDGE01\n    // pub p0_03: p0::P0_03<Disconnected>, // PAD0, EDGE00\n    // pub p0_04: p0::P0_04<Disconnected>, // LEDs\n    // pub p0_05: p0::P0_05<Disconnected>, // LEDs\n    // pub p0_06: p0::P0_06<Disconnected>, // LEDs\n    // pub p0_07: p0::P0_07<Disconnected>, // LEDs\n    // pub p0_08: p0::P0_08<Disconnected>, // LEDs\n    // pub p0_09: p0::P0_09<Disconnected>, // LEDs\n    // pub p0_10: p0::P0_10<Disconnected>, // LEDs\n    // pub p0_11: p0::P0_11<Disconnected>, // LEDs\n    // pub p0_12: p0::P0_12<Disconnected>, // LEDs\n    // pub p0_13: p0::P0_13<Disconnected>, // LEDs\n    // pub p0_14: p0::P0_14<Disconnected>, // LEDs\n    // pub p0_15: p0::P0_15<Disconnected>, // LEDs\n    // pub p0_16: p0::P0_16<Disconnected>, // EDGE16\n    // pub p0_17: p0::P0_17<Disconnected>, // BTN_A\n    // pub p0_18: p0::P0_18<Disconnected>, // EDGE08\n    pub p0_19: p0::P0_19<Disconnected>,\n    // pub p0_20: p0::P0_20<Disconnected>, // EDGE12\n    pub p0_21: p0::P0_21<Disconnected>,\n    pub p0_22: p0::P0_22<Disconnected>,\n    pub p0_23: p0::P0_23<Disconnected>,\n    // pub p0_24: p0::P0_24<Disconnected>, // UART TX\n    // pub p0_25: p0::P0_25<Disconnected>, // UART RX\n    // pub p0_26: p0::P0_26<Disconnected>, // BTN_B\n    pub p0_27: p0::P0_27<Disconnected>,\n    pub p0_28: p0::P0_28<Disconnected>,\n    pub p0_29: p0::P0_29<Disconnected>,\n    // pub p0_30: p0::P0_30<Disconnected>, // SDA\n}\n\n/// Unused edge connector pins\n#[allow(missing_docs)]\npub struct Edge {\n    // pub e03: COL1,\n    pub e00: EDGE00<Disconnected>, // <- big pad 1\n    // pub e04: COL2,\n    // pub e05: BTN_A,\n    // pub e06: COL9,\n    // pub e07: COL8,\n    pub e01: EDGE01<Disconnected>, // <- big pad 2\n    pub e08: EDGE08<Disconnected>,\n    // pub e09: COL7,\n    // pub e10: COL3,\n    // pub e11: BTN_B,\n    pub e12: EDGE12<Disconnected>,\n    pub e02: EDGE02<Disconnected>, // <- big pad 3\n    //pub e13<MODE>: SCK<MODE>,\n    //pub e14<MODE>: MISO<MODE>,\n    //pub e15<MODE>: MOSI<MODE>,\n    pub e16: EDGE16<Disconnected>,\n    // +V\n    // +V\n    // +V\n    // pub e19: SCL,\n    // pub e20: SDA,\n    // GND\n    // GND\n    // GND\n}\n\n/// Board buttons\npub struct Buttons {\n    /// Left hand side button\n    pub button_a: BTN_A,\n    /// Right hand side button\n    pub button_b: BTN_B,\n}\n\n/// I2C shared internal and external bus pins\npub struct I2CPins {\n    /// I2C control pin\n    pub scl: SCL,\n    /// I2C data pin\n    pub sda: SDA,\n}\n\nimpl From<I2CPins> for twi::Pins {\n    fn from(pins: I2CPins) -> Self {\n        Self {\n            scl: pins.scl.degrade(),\n            sda: pins.sda.degrade(),\n        }\n    }\n}\n\n/// UART to debugger pins\npub struct UartPins {\n    tx: UART_TX,\n    rx: UART_RX,\n}\n\nimpl From<UartPins> for uart::Pins {\n    fn from(pins: UartPins) -> Self {\n        Self {\n            rxd: pins.rx.degrade(),\n            txd: pins.tx.degrade(),\n            cts: None,\n            rts: None,\n        }\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/v1/gpio.rs",
    "content": "//! Named GPIO pin types\n//!\n//! This module maps the GPIO pin names as described in the\n//! [Pins and Signals section of the micro:bit site](https://tech.microbit.org/hardware/edgeconnector/#pins-and-signals)\n//! Where appropriate the pins are restricted with the appropriate `MODE`\n//! from `nrf-hal`.\n#![allow(clippy::upper_case_acronyms, missing_docs)]\nuse crate::hal::gpio::{p0, Floating, Input, Output, Pin, PushPull};\n\n/* GPIO pads */\npub type PAD0<MODE> = p0::P0_03<MODE>;\npub type PAD1<MODE> = p0::P0_02<MODE>;\npub type PAD2<MODE> = p0::P0_01<MODE>;\n\n/* LED display */\npub const NUM_COLS: usize = 9;\npub type COL1 = p0::P0_04<Output<PushPull>>;\npub type COL2 = p0::P0_05<Output<PushPull>>;\npub type COL3 = p0::P0_06<Output<PushPull>>;\npub type COL4 = p0::P0_07<Output<PushPull>>;\npub type COL5 = p0::P0_08<Output<PushPull>>;\npub type COL6 = p0::P0_09<Output<PushPull>>;\npub type COL7 = p0::P0_10<Output<PushPull>>;\npub type COL8 = p0::P0_11<Output<PushPull>>;\npub type COL9 = p0::P0_12<Output<PushPull>>;\n\npub const NUM_ROWS: usize = 3;\npub type ROW1 = p0::P0_13<Output<PushPull>>;\npub type ROW2 = p0::P0_14<Output<PushPull>>;\npub type ROW3 = p0::P0_15<Output<PushPull>>;\n\n/// GPIO pins connected to the LED matrix\n///\n/// The pins are represented as a [3x9 matrix on the micro:bit\n/// V1](https://tech.microbit.org/hardware/1-5-revision/#display).\n/// This is mapped to the physical 5x5 LED matrix in the [crate::display]\n/// modules.\n///\n/// Use the [display_pins] macro for easier construction.\npub struct DisplayPins {\n    pub col1: COL1,\n    pub col2: COL2,\n    pub col3: COL3,\n    pub col4: COL4,\n    pub col5: COL5,\n    pub col6: COL6,\n    pub col7: COL7,\n    pub col8: COL8,\n    pub col9: COL9,\n    pub row1: ROW1,\n    pub row2: ROW2,\n    pub row3: ROW3,\n}\n\ntype LED = Pin<Output<PushPull>>;\n\nimpl DisplayPins {\n    pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {\n        (\n            [\n                self.col1.degrade(),\n                self.col2.degrade(),\n                self.col3.degrade(),\n                self.col4.degrade(),\n                self.col5.degrade(),\n                self.col6.degrade(),\n                self.col7.degrade(),\n                self.col8.degrade(),\n                self.col9.degrade(),\n            ],\n            [\n                self.row1.degrade(),\n                self.row2.degrade(),\n                self.row3.degrade(),\n            ],\n        )\n    }\n}\n\n/// Create [DisplayPins] from a [GPIO Parts](crate::hal::gpio::p0::Parts)\n///\n/// # Example\n///\n/// ```no_run\n/// # use microbit_common as microbit;\n/// use microbit::{\n///     display_pins,\n///     pac,\n///     hal::gpio::p0::Parts as P0Parts,\n/// };\n///\n/// // take the peripherals\n/// let p = pac::Peripherals::take().unwrap();\n/// // split off the P0 GPIO port\n/// let p0parts = P0Parts::new(p.GPIO);\n///\n/// let pins = display_pins!(p0parts);\n/// ```\n#[macro_export]\nmacro_rules! display_pins {\n    ( $p0parts:expr ) => {{\n        use microbit::{gpio::DisplayPins, hal::gpio::Level};\n\n        DisplayPins {\n            row1: $p0parts.p0_13.into_push_pull_output(Level::Low),\n            row2: $p0parts.p0_14.into_push_pull_output(Level::Low),\n            row3: $p0parts.p0_15.into_push_pull_output(Level::Low),\n            col1: $p0parts.p0_04.into_push_pull_output(Level::Low),\n            col2: $p0parts.p0_05.into_push_pull_output(Level::Low),\n            col3: $p0parts.p0_06.into_push_pull_output(Level::Low),\n            col4: $p0parts.p0_07.into_push_pull_output(Level::Low),\n            col5: $p0parts.p0_08.into_push_pull_output(Level::Low),\n            col6: $p0parts.p0_09.into_push_pull_output(Level::Low),\n            col7: $p0parts.p0_10.into_push_pull_output(Level::Low),\n            col8: $p0parts.p0_11.into_push_pull_output(Level::Low),\n            col9: $p0parts.p0_12.into_push_pull_output(Level::Low),\n        }\n    }};\n}\n\n/* buttons */\npub type BTN_A = p0::P0_17<Input<Floating>>;\npub type BTN_B = p0::P0_26<Input<Floating>>;\n\n/* spi */\npub type MOSI<MODE> = p0::P0_21<MODE>;\npub type MISO<MODE> = p0::P0_22<MODE>;\npub type SCK<MODE> = p0::P0_23<MODE>;\n\n/* i2c - shared external and internal */\npub type SCL = p0::P0_00<Input<Floating>>;\npub type SDA = p0::P0_30<Input<Floating>>;\n\n/* uart */\npub type UART_TX = p0::P0_24<Output<PushPull>>;\npub type UART_RX = p0::P0_25<Input<Floating>>;\n\n/* edge connector */\npub type EDGE03 = COL1;\npub type EDGE00<MODE> = PAD0<MODE>; // <- big pad 1\npub type EDGE04 = COL2;\npub type EDGE05 = BTN_A;\npub type EDGE06 = COL9;\npub type EDGE07 = COL8;\npub type EDGE01<MODE> = PAD1<MODE>; // <- big pad 2\npub type EDGE08<MODE> = p0::P0_18<MODE>;\npub type EDGE09 = COL7;\npub type EDGE10 = COL3;\npub type EDGE11 = BTN_B;\npub type EDGE12<MODE> = p0::P0_20<MODE>;\npub type EDGE02<MODE> = PAD2<MODE>; // <- big pad 3\npub type EDGE13<MODE> = SCK<MODE>;\npub type EDGE14<MODE> = MISO<MODE>;\npub type EDGE15<MODE> = MOSI<MODE>;\npub type EDGE16<MODE> = p0::P0_16<MODE>;\n// EDGE18 -> +V\n// EDGE19 -> +V\n// EDGE20 -> +V\npub type EDGE19 = SCL;\npub type EDGE20 = SDA;\n// EDGE23 -> GND\n// EDGE24 -> GND\n// EDGE25 -> GND\n"
  },
  {
    "path": "microbit-common/src/v1/mod.rs",
    "content": "pub mod adc;\npub mod board;\npub mod gpio;\n"
  },
  {
    "path": "microbit-common/src/v2/adc.rs",
    "content": "use crate::hal;\n\n/// Adc alias to unify v1 and v2 names\npub type Adc = hal::Saadc;\n/// AdcConfig alias to unify v1 and v2 names\npub type AdcConfig = hal::saadc::SaadcConfig;\n\n/// Same resolution for v1 and v2\npub trait Default {\n    /// v1 is limited to 10 bit\n    fn default_10bit() -> Self;\n}\n\nimpl Default for AdcConfig {\n    fn default_10bit() -> Self {\n        AdcConfig {\n            resolution: hal::saadc::Resolution::_10BIT,\n            ..AdcConfig::default()\n        }\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/v2/board.rs",
    "content": "use super::gpio::{\n    DisplayPins, MicrophonePins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE09, EDGE12,\n    EDGE16, INT_SCL, INT_SDA, SCL, SDA, UART_RX, UART_TX,\n};\nuse crate::{\n    hal::{\n        gpio::{p0, p1, Disconnected, Level, OpenDrainConfig::Disconnect0HighDrive1},\n        twim, twis, uarte,\n    },\n    pac,\n};\n\n/// Provides access to the microbit\n#[allow(non_snake_case)]\npub struct Board {\n    /// GPIO pins that are not otherwise used\n    pub pins: Pins,\n\n    /// Unused GPIO pins on edge connector\n    pub edge: Edge,\n\n    /// display pins\n    pub display_pins: DisplayPins,\n\n    /// buttons\n    pub buttons: Buttons,\n\n    /// speaker\n    pub speaker_pin: p0::P0_00<Disconnected>,\n\n    /// microphone pins\n    pub microphone_pins: MicrophonePins,\n\n    /// I2C internal bus pins\n    pub i2c_internal: I2CInternalPins,\n\n    /// I2C external bus pins\n    pub i2c_external: I2CExternalPins,\n\n    /// UART to debugger pins\n    pub uart: UartPins,\n\n    /// Core peripheral: Cache and branch predictor maintenance operations\n    pub CBP: pac::CBP,\n\n    /// Core peripheral: CPUID\n    pub CPUID: pac::CPUID,\n\n    /// Core peripheral: Debug Control Block\n    pub DCB: pac::DCB,\n\n    /// Core peripheral: Data Watchpoint and Trace unit\n    pub DWT: pac::DWT,\n\n    /// Core peripheral: Flash Patch and Breakpoint unit\n    pub FPB: pac::FPB,\n\n    /// Core peripheral: Floating Point Unit\n    pub FPU: pac::FPU,\n\n    /// Core peripheral: Instrumentation Trace Macrocell\n    pub ITM: pac::ITM,\n\n    /// Core peripheral: Memory Protection Unit\n    pub MPU: pac::MPU,\n\n    /// Core peripheral: Nested Vector Interrupt Controller\n    pub NVIC: pac::NVIC,\n\n    /// Core peripheral: System Control Block\n    pub SCB: pac::SCB,\n\n    /// Core peripheral: SysTick Timer\n    pub SYST: pac::SYST,\n\n    /// Core peripheral: Trace Port Interface Unit\n    pub TPIU: pac::TPIU,\n\n    /// nRF52 peripheral: CLOCK\n    pub CLOCK: pac::CLOCK,\n\n    /// nRF52 peripheral: FICR\n    pub FICR: pac::FICR,\n\n    /// nRF52 peripheral: GPIOTE\n    pub GPIOTE: pac::GPIOTE,\n\n    /// nRF52 preipheral: PPI\n    pub PPI: pac::PPI,\n\n    /// nRF52 peripheral: PWM0\n    pub PWM0: pac::PWM0,\n\n    /// nRF52 peripheral: PWM1\n    pub PWM1: pac::PWM1,\n\n    /// nRF52 peripheral: PWM2\n    pub PWM2: pac::PWM2,\n\n    /// nRF52 peripheral: PWM3\n    pub PWM3: pac::PWM3,\n\n    /// nRF52 peripheral: RADIO\n    pub RADIO: pac::RADIO,\n\n    /// nRF52 peripheral: RNG\n    pub RNG: pac::RNG,\n\n    /// nRF52 peripheral: RTC0\n    pub RTC0: pac::RTC0,\n\n    /// nRF52 peripheral: RTC1\n    pub RTC1: pac::RTC1,\n\n    /// nRF52 peripheral: RTC2\n    pub RTC2: pac::RTC2,\n\n    /// nRF52 peripheral: SPIM0\n    pub SPIM0: pac::SPIM0,\n\n    /// nRF52 peripheral: SPIM1\n    pub SPIM1: pac::SPIM1,\n\n    /// nRF52 peripheral: SPIM2\n    pub SPIM2: pac::SPIM2,\n\n    /// nRF52 peripheral: SPIM3\n    pub SPIM3: pac::SPIM3,\n\n    /// nRF52 peripheral: TEMP <br>\n    /// Can be used with [`Temp::new()`](`crate::hal::temp::Temp::new()`)\n    pub TEMP: pac::TEMP,\n\n    /// nRF52 peripheral: TIMER0\n    pub TIMER0: pac::TIMER0,\n\n    /// nRF52 peripheral: TIMER1\n    pub TIMER1: pac::TIMER1,\n\n    /// nRF52 peripheral: TIMER2\n    pub TIMER2: pac::TIMER2,\n\n    /// nRF52 peripheral: TIMER3\n    pub TIMER3: pac::TIMER3,\n\n    /// nRF52 peripheral: TIMER4\n    pub TIMER4: pac::TIMER4,\n\n    /// nRF52 peripheral: TWIM0\n    pub TWIM0: pac::TWIM0,\n\n    /// nRF52 peripheral: TWIS0\n    pub TWIS0: pac::TWIS0,\n\n    /// nRF52 peripheral: UARTE0\n    pub UARTE0: pac::UARTE0,\n\n    /// nRF52 peripheral: UARTE1\n    pub UARTE1: pac::UARTE1,\n\n    /// nRF52 peripheral: SAADC\n    pub ADC: pac::SAADC,\n\n    /// nRF52 peripheral: POWER\n    pub POWER: pac::POWER,\n\n    /// nRF52 peripheral: SPI0\n    pub SPI0: pac::SPI0,\n\n    /// nRF52 peripheral: SPI1\n    pub SPI1: pac::SPI1,\n\n    /// nRF52 peripheral: SPI2\n    pub SPI2: pac::SPI2,\n\n    /// nRF52 peripheral: UART0\n    pub UART0: pac::UART0,\n\n    /// nRF52 peripheral: TWI0\n    pub TWI0: pac::TWI0,\n\n    /// nRF52 peripheral: TWI1\n    pub TWI1: pac::TWI1,\n\n    /// nRF52 peripheral: SPIS1\n    pub SPIS1: pac::SPIS1,\n\n    /// nRF52 peripheral: ECB\n    pub ECB: pac::ECB,\n\n    /// nRF52 peripheral: AAR\n    pub AAR: pac::AAR,\n\n    /// nRF52 peripheral: CCM\n    pub CCM: pac::CCM,\n\n    /// nRF52 peripheral: WDT\n    pub WDT: pac::WDT,\n\n    /// nRF52 peripheral: QDEC\n    pub QDEC: pac::QDEC,\n\n    /// nRF52 peripheral: LPCOMP\n    pub LPCOMP: pac::LPCOMP,\n\n    /// nRF52 peripheral: NVMC\n    pub NVMC: pac::NVMC,\n\n    /// nRF52 peripheral: UICR\n    pub UICR: pac::UICR,\n}\n\nimpl Board {\n    /// Take the peripherals safely\n    ///\n    /// This method will return an instance of the board the first time it is\n    /// called. It will return only `None` on subsequent calls.\n    /// This function can also return `None` if one of the the peripherals was\n    /// already taken.\n    pub fn take() -> Option<Self> {\n        Some(Self::new(\n            pac::Peripherals::take()?,\n            pac::CorePeripherals::take()?,\n        ))\n    }\n\n    /// Fallback method in the case peripherals and core peripherals were taken\n    /// elsewhere already.\n    ///\n    /// This method will take the peripherals and core peripherals and\n    /// return an instance of the board.\n    ///\n    /// An exemplary usecase is shown in the rtic display example.\n    pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {\n        let p0parts = p0::Parts::new(p.P0);\n        let p1parts = p1::Parts::new(p.P1);\n        Self {\n            pins: Pins {\n                p0_01: p0parts.p0_01,\n                //p0_02: p0parts.p0_02,\n                //p0_03: p0parts.p0_03,\n                //p0_04: p0parts.p0_04,\n                p0_07: p0parts.p0_07,\n                //p0_09: p0parts.p0_09,\n                //p0_10: p0parts.p0_10,\n                //p0_12: p0parts.p0_12,\n                p0_13: p0parts.p0_13,\n                p0_17: p0parts.p0_17,\n                p0_18: p0parts.p0_18,\n                p0_25: p0parts.p0_25,\n                p0_27: p0parts.p0_27,\n                p0_29: p0parts.p0_29,\n                p1_01: p1parts.p1_01,\n                //p1_02: p1parts.p1_02,\n                p1_03: p1parts.p1_03,\n                p1_04: p1parts.p1_04,\n                p1_06: p1parts.p1_06,\n                p1_07: p1parts.p1_07,\n                p1_09: p1parts.p1_09,\n            },\n            edge: Edge {\n                e00: p0parts.p0_02,\n                e01: p0parts.p0_03,\n                e02: p0parts.p0_04,\n                e08: p0parts.p0_10,\n                e09: p0parts.p0_09,\n                e12: p0parts.p0_12,\n                e16: p1parts.p1_02,\n            },\n            display_pins: DisplayPins {\n                col1: p0parts.p0_28.into_push_pull_output(Level::High),\n                col2: p0parts.p0_11.into_push_pull_output(Level::High),\n                col3: p0parts.p0_31.into_push_pull_output(Level::High),\n                col4: p1parts.p1_05.into_push_pull_output(Level::High),\n                col5: p0parts.p0_30.into_push_pull_output(Level::High),\n                row1: p0parts.p0_21.into_push_pull_output(Level::Low),\n                row2: p0parts.p0_22.into_push_pull_output(Level::Low),\n                row3: p0parts.p0_15.into_push_pull_output(Level::Low),\n                row4: p0parts.p0_24.into_push_pull_output(Level::Low),\n                row5: p0parts.p0_19.into_push_pull_output(Level::Low),\n            },\n            buttons: Buttons {\n                button_a: p0parts.p0_14.into_floating_input(),\n                button_b: p0parts.p0_23.into_floating_input(),\n            },\n            speaker_pin: p0parts.p0_00,\n            microphone_pins: MicrophonePins {\n                mic_in: p0parts.p0_05.into_floating_input(),\n                mic_run: p0parts\n                    .p0_20\n                    .into_open_drain_output(Disconnect0HighDrive1, Level::Low),\n            },\n            i2c_internal: I2CInternalPins {\n                scl: p0parts.p0_08.into_floating_input(),\n                sda: p0parts.p0_16.into_floating_input(),\n            },\n            i2c_external: I2CExternalPins {\n                scl: p0parts.p0_26.into_floating_input(),\n                sda: p1parts.p1_00.into_floating_input(),\n            },\n            uart: UartPins {\n                tx: p0parts.p0_06.into_push_pull_output(Level::High),\n                rx: p1parts.p1_08.into_floating_input(),\n            },\n\n            // Core peripherals\n            CBP: cp.CBP,\n            CPUID: cp.CPUID,\n            DCB: cp.DCB,\n            DWT: cp.DWT,\n            FPB: cp.FPB,\n            FPU: cp.FPU,\n            ITM: cp.ITM,\n            MPU: cp.MPU,\n            NVIC: cp.NVIC,\n            SCB: cp.SCB,\n            SYST: cp.SYST,\n            TPIU: cp.TPIU,\n\n            // nRF52 peripherals\n            CLOCK: p.CLOCK,\n            FICR: p.FICR,\n            GPIOTE: p.GPIOTE,\n            PPI: p.PPI,\n            PWM0: p.PWM0,\n            PWM1: p.PWM1,\n            PWM2: p.PWM2,\n            PWM3: p.PWM3,\n            RADIO: p.RADIO,\n            RNG: p.RNG,\n            RTC0: p.RTC0,\n            RTC1: p.RTC1,\n            RTC2: p.RTC2,\n            SPIM0: p.SPIM0,\n            SPIM1: p.SPIM1,\n            SPIM2: p.SPIM2,\n            SPIM3: p.SPIM3,\n            TEMP: p.TEMP,\n            TIMER0: p.TIMER0,\n            TIMER1: p.TIMER1,\n            TIMER2: p.TIMER2,\n            TIMER3: p.TIMER3,\n            TIMER4: p.TIMER4,\n            TWIM0: p.TWIM0,\n            TWIS0: p.TWIS0,\n            UARTE0: p.UARTE0,\n            UARTE1: p.UARTE1,\n            ADC: p.SAADC,\n            SPI0: p.SPI0,\n            SPI1: p.SPI1,\n            SPI2: p.SPI2,\n            POWER: p.POWER,\n            UART0: p.UART0,\n            TWI0: p.TWI0,\n            TWI1: p.TWI1,\n            SPIS1: p.SPIS1,\n            ECB: p.ECB,\n            AAR: p.AAR,\n            CCM: p.CCM,\n            WDT: p.WDT,\n            QDEC: p.QDEC,\n            LPCOMP: p.LPCOMP,\n            NVMC: p.NVMC,\n            UICR: p.UICR,\n        }\n    }\n}\n\n/// Unused GPIO pins\n#[allow(missing_docs)]\npub struct Pins {\n    // pub p0_00: p0::P0_00<Disconnected>, // Speaker\n    pub p0_01: p0::P0_01<Disconnected>,\n    // pub p0_02: p0::P0_02<Disconnected>, // PAD0, EDGE00\n    // pub p0_03: p0::P0_03<Disconnected>, // PAD1, EDGE01\n    // pub p0_04: p0::P0_04<Disconnected>, // PAD2, EDGE02\n    // pub p0_05: p0::P0_05<Disconnected>, // Microphone IN\n    // pub p0_06: p0::P0_06<Disconnected>, // UART RX\n    pub p0_07: p0::P0_07<Disconnected>,\n    // pub p0_08: p0::P0_08<Disconnected>, // INT_SCL\n    // pub p0_09: p0::P0_09<Disconnected>, // EDGE09\n    // pub p0_10: p0::P0_10<Disconnected>, // EDGE08\n    // pub p0_11: p0::P0_11<Disconnected>, // LEDs\n    // pub p0_12: p0::P0_12<Disconnected>, // EDGE12\n    pub p0_13: p0::P0_13<Disconnected>,\n    // pub p0_14: p0::P0_14<Disconnected>, // BTN_A\n    // pub p0_15: p0::P0_15<Disconnected>, // LEDs\n    // pub p0_16: p0::P0_16<Disconnected>, // INT_SDA\n    pub p0_17: p0::P0_17<Disconnected>,\n    pub p0_18: p0::P0_18<Disconnected>,\n    // pub p0_19: p0::P0_19<Disconnected>, // LEDs\n    // pub p0_20: p0::P0_20<Disconnected>, // Microphone RUN\n    // pub p0_21: p0::P0_21<Disconnected>, // LEDs\n    // pub p0_22: p0::P0_22<Disconnected>, // LEDs\n    // pub p0_23: p0::P0_23<Disconnected>, // BTN_B\n    // pub p0_24: p0::P0_24<Disconnected>, // LEDs\n    pub p0_25: p0::P0_25<Disconnected>,\n    // pub p0_26: p0::P0_26<Disconnected>, // SCL\n    pub p0_27: p0::P0_27<Disconnected>,\n    // pub p0_28: p0::P0_28<Disconnected>, // LEDs\n    pub p0_29: p0::P0_29<Disconnected>,\n    // pub p0_30: p0::P0_30<Disconnected>, // LEDs\n    // pub p0_31: p0::P0_31<Disconnected>, // LEDs\n    // pub p1_00: p1::P1_00<Disconnected>, // SDA\n    pub p1_01: p1::P1_01<Disconnected>,\n    // pub p1_02: p1::P1_02<Disconnected>, // EDGE16\n    pub p1_03: p1::P1_03<Disconnected>,\n    pub p1_04: p1::P1_04<Disconnected>,\n    // pub p1_05: p1::P1_05<Disconnected>, // LEDs\n    pub p1_06: p1::P1_06<Disconnected>,\n    pub p1_07: p1::P1_07<Disconnected>,\n    // pub p1_08: p1::P1_08<Disconnected>, // UART TX\n    pub p1_09: p1::P1_09<Disconnected>,\n}\n\n/// Unused edge connector pins\n#[allow(missing_docs)]\npub struct Edge {\n    /* edge connector */\n    // pub e03: COL3,\n    pub e00: EDGE00<Disconnected>, // <- big pad 1\n    // pub e04: COL1,\n    // pub e05: BTN_A,\n    // pub e06: COL4,\n    // pub e07: COL2,\n    pub e01: EDGE01<Disconnected>, // <- big pad 2\n    pub e08: EDGE08<Disconnected>,\n    pub e09: EDGE09<Disconnected>,\n    // pub e10: COL5,\n    // pub e11: BTN_B,\n    pub e12: EDGE12<Disconnected>,\n    pub e02: EDGE02<Disconnected>, // <- big pad 3\n    //pub e13<MODE>: SCK<MODE>,\n    //pub e14<MODE>: MISO<MODE>,\n    //pub e15<MODE>: MOSI<MODE>,\n    pub e16: EDGE16<Disconnected>,\n    // +V\n    // +V\n    // +V\n    // pub e19: SCL,\n    // pub e20: SDA,\n    // GND\n    // GND\n    // GND\n}\n\n/// Buttons\npub struct Buttons {\n    /// Left hand button\n    pub button_a: BTN_A,\n    /// Right hand button\n    pub button_b: BTN_B,\n}\n\n/// I2C internal bus pins\npub struct I2CInternalPins {\n    /// Internal I2C clock pin\n    pub scl: INT_SCL,\n    /// Internal I2C data pin\n    pub sda: INT_SDA,\n}\n\nimpl From<I2CInternalPins> for twim::Pins {\n    fn from(pins: I2CInternalPins) -> Self {\n        Self {\n            scl: pins.scl.degrade(),\n            sda: pins.sda.degrade(),\n        }\n    }\n}\n\nimpl From<I2CInternalPins> for twis::Pins {\n    fn from(pins: I2CInternalPins) -> Self {\n        Self {\n            scl: pins.scl.degrade(),\n            sda: pins.sda.degrade(),\n        }\n    }\n}\n\n/// I2C external bus pins\npub struct I2CExternalPins {\n    /// External I2C clock pin\n    pub scl: SCL,\n    /// External I2C data pin\n    pub sda: SDA,\n}\n\nimpl From<I2CExternalPins> for twim::Pins {\n    fn from(pins: I2CExternalPins) -> Self {\n        Self {\n            scl: pins.scl.degrade(),\n            sda: pins.sda.degrade(),\n        }\n    }\n}\n\nimpl From<I2CExternalPins> for twis::Pins {\n    fn from(pins: I2CExternalPins) -> Self {\n        Self {\n            scl: pins.scl.degrade(),\n            sda: pins.sda.degrade(),\n        }\n    }\n}\n\n/// UART to debugger pins\npub struct UartPins {\n    tx: UART_TX,\n    rx: UART_RX,\n}\n\nimpl From<UartPins> for uarte::Pins {\n    fn from(pins: UartPins) -> Self {\n        Self {\n            txd: pins.tx.degrade(),\n            rxd: pins.rx.degrade(),\n            cts: None,\n            rts: None,\n        }\n    }\n}\n"
  },
  {
    "path": "microbit-common/src/v2/gpio.rs",
    "content": "#![allow(clippy::upper_case_acronyms, missing_docs)]\nuse nrf52833_hal::gpio::{p0, p1, Floating, Input, OpenDrain, Output, Pin, PushPull};\n\n/* GPIO pads */\npub type PAD0<MODE> = p0::P0_02<MODE>;\npub type PAD1<MODE> = p0::P0_03<MODE>;\npub type PAD2<MODE> = p0::P0_04<MODE>;\n\n/* LED display */\npub const NUM_COLS: usize = 5;\npub type COL1 = p0::P0_28<Output<PushPull>>;\npub type COL2 = p0::P0_11<Output<PushPull>>;\npub type COL3 = p0::P0_31<Output<PushPull>>;\npub type COL4 = p1::P1_05<Output<PushPull>>;\npub type COL5 = p0::P0_30<Output<PushPull>>;\n\npub const NUM_ROWS: usize = 5;\npub type ROW1 = p0::P0_21<Output<PushPull>>;\npub type ROW2 = p0::P0_22<Output<PushPull>>;\npub type ROW3 = p0::P0_15<Output<PushPull>>;\npub type ROW4 = p0::P0_24<Output<PushPull>>;\npub type ROW5 = p0::P0_19<Output<PushPull>>;\n\n/// GPIO pins connected to the LED matrix\n///\n/// Use the [display_pins] macro for easier construction.\npub struct DisplayPins {\n    pub col1: COL1,\n    pub col2: COL2,\n    pub col3: COL3,\n    pub col4: COL4,\n    pub col5: COL5,\n    pub row1: ROW1,\n    pub row2: ROW2,\n    pub row3: ROW3,\n    pub row4: ROW4,\n    pub row5: ROW5,\n}\n\n/// GPIO pins connected to the microphone\npub struct MicrophonePins {\n    pub mic_in: p0::P0_05<Input<Floating>>,\n    pub mic_run: p0::P0_20<Output<OpenDrain>>,\n}\n\ntype LED = Pin<Output<PushPull>>;\n\nimpl DisplayPins {\n    pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {\n        (\n            [\n                self.col1.degrade(),\n                self.col2.degrade(),\n                self.col3.degrade(),\n                self.col4.degrade(),\n                self.col5.degrade(),\n            ],\n            [\n                self.row1.degrade(),\n                self.row2.degrade(),\n                self.row3.degrade(),\n                self.row4.degrade(),\n                self.row5.degrade(),\n            ],\n        )\n    }\n}\n\n/// Create [DisplayPins] from a [GPIO Parts](crate::hal::gpio::p0::Parts)\n///\n/// # Example\n///\n/// ```no_run\n/// # use microbit_common as microbit;\n/// use microbit::{\n///     display_pins,\n///     pac,\n///     hal::gpio::{p0::Parts as P0Parts, p1::Parts as P1Parts},\n/// };\n///\n/// // take the peripherals\n/// let p = pac::Peripherals::take().unwrap();\n/// // split off the P0 GPIO port\n/// let p0parts = P0Parts::new(p.P0);\n/// // split off the P1 GPIO port\n/// let p1parts = P1Parts::new(p.P1);\n///\n/// let pins = display_pins!(p0parts, p1parts);\n/// ```\n#[macro_export]\nmacro_rules! display_pins {\n    ( $p0parts:expr, $p1parts:expr ) => {{\n        use microbit::{gpio::DisplayPins, hal::gpio::Level};\n\n        DisplayPins {\n            col1: $p0parts.p0_28.into_push_pull_output(Level::Low),\n            col2: $p0parts.p0_11.into_push_pull_output(Level::Low),\n            col3: $p0parts.p0_31.into_push_pull_output(Level::Low),\n            col4: $p1parts.p1_05.into_push_pull_output(Level::Low),\n            col5: $p0parts.p0_30.into_push_pull_output(Level::Low),\n            row1: $p0parts.p0_21.into_push_pull_output(Level::Low),\n            row2: $p0parts.p0_22.into_push_pull_output(Level::Low),\n            row3: $p0parts.p0_15.into_push_pull_output(Level::Low),\n            row4: $p0parts.p0_24.into_push_pull_output(Level::Low),\n            row5: $p0parts.p0_19.into_push_pull_output(Level::Low),\n        }\n    }};\n}\n\n/* buttons */\npub type BTN_A = p0::P0_14<Input<Floating>>;\npub type BTN_B = p0::P0_23<Input<Floating>>;\n\n/* spi */\npub type MOSI<MODE> = p0::P0_13<MODE>;\npub type MISO<MODE> = p0::P0_01<MODE>;\npub type SCK<MODE> = p0::P0_17<MODE>;\n\n/* i2c - internal */\npub type INT_SCL = p0::P0_08<Input<Floating>>;\npub type INT_SDA = p0::P0_16<Input<Floating>>;\n\n/* i2c - external */\npub type SCL = p0::P0_26<Input<Floating>>;\npub type SDA = p1::P1_00<Input<Floating>>;\n\n/* uart */\npub type UART_TX = p0::P0_06<Output<PushPull>>;\npub type UART_RX = p1::P1_08<Input<Floating>>;\n\n/* speaker */\npub type SPEAKER = p0::P0_00<Output<PushPull>>;\n\n/* edge connector */\npub type EDGE03 = COL3;\npub type EDGE00<MODE> = PAD0<MODE>; // <- big pad 1\npub type EDGE04 = COL1;\npub type EDGE05 = BTN_A;\npub type EDGE06 = COL4;\npub type EDGE07 = COL2;\npub type EDGE01<MODE> = PAD1<MODE>; // <- big pad 2\npub type EDGE08<MODE> = p0::P0_10<MODE>;\npub type EDGE09<MODE> = p0::P0_09<MODE>;\npub type EDGE10 = COL5;\npub type EDGE11 = BTN_B;\npub type EDGE12<MODE> = p0::P0_12<MODE>;\npub type EDGE02<MODE> = PAD2<MODE>; // <- big pad 3\npub type EDGE13<MODE> = SCK<MODE>;\npub type EDGE14<MODE> = MISO<MODE>;\npub type EDGE15<MODE> = MOSI<MODE>;\npub type EDGE16<MODE> = p1::P1_02<MODE>;\n// EDGE18 -> +V\n// EDGE19 -> +V\n// EDGE20 -> +V\npub type EDGE19 = SCL;\npub type EDGE20 = SDA;\n// EDGE23 -> GND\n// EDGE24 -> GND\n// EDGE25 -> GND\n"
  },
  {
    "path": "microbit-common/src/v2/mod.rs",
    "content": "pub mod adc;\npub mod board;\npub mod gpio;\n"
  },
  {
    "path": "microbit-v2/Cargo.toml",
    "content": "[package]\nname = \"microbit-v2\"\nversion = \"0.16.0\"\ndescription = \"Board support crate for the BBC Micro:bit V2\"\nedition = \"2018\"\nreadme = \"../README.md\"\nrust-version = \"1.79.0\"\n\nrepository = \"https://github.com/nrf-rs/microbit\"\nauthors = [\n  \"Daniel Egger <daniel@eggers-club.de>\",\n  \"Michael Droogleever <droogmic@gmail.com>\",\n  \"Rob Young <rob@robyoung.digital>\",\n]\ncategories = [\"hardware-support\", \"embedded\", \"no-std\"]\nkeywords = [\"arm\", \"cortex-m\", \"nrf\", \"hal\"]\nlicense = \"0BSD\"\n\n[lib]\nname = \"microbit\"\npath = \"src/lib.rs\"\n\n[dependencies]\n\n[dependencies.microbit-common]\npath = \"../microbit-common\"\nfeatures = [\"v2\"]\nversion = \"=0.16.0\"\n\n[features]\nembedded-hal-02 = [\"microbit-common/embedded-hal-02\"]\n"
  },
  {
    "path": "microbit-v2/src/lib.rs",
    "content": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)\n//! microcontroller board.\n//!\n//! This crate is for the new micro:bit (V2) pictured below on the right. If\n//! your micro:bit looks like the one on the left you need the\n//! [microbit](https://crates.io/crates/microbit) crate.\n//!\n//! [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-1-5.png\" width=\"372px\" height=\"300px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-1-5.png)\n//! [<img src=\"https://github.com/microbit-foundation/microbit-svg/raw/master/microbit-drawing-back-2.png\" width=\"372px\" height=\"300px\">](https://github.com/microbit-foundation/microbit-svg/blob/master/microbit-drawing-back-2.png)\n#![doc(html_root_url = \"https://docs.rs/microbit-v2/0.16.0\")]\n#![no_std]\n#![deny(missing_docs)]\n#![allow(non_camel_case_types)]\n\npub use microbit_common::*;\n"
  },
  {
    "path": "tools/capture_example_bloat.sh",
    "content": "#!/bin/bash\n\nfilename=\"bloat_log_\"`date -Iminutes`\".txt\"\n\nfor i in `find examples -name \"*.rs\"`; do\n        name=$(echo $i | sed -e \"s,examples/,,g\" -e \"s,\\.rs,,g\")\n        echo \"Processing example $name\"\n        echo >>$filename\n        echo \"Bloat for example $name\" >>$filename\n        cargo bloat --release --example $name >>$filename\ndone\n\necho \"Captures bloat for all examples into $filename\"\n"
  },
  {
    "path": "xtask/Cargo.toml",
    "content": "[package]\nname = \"xtask\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncargo_toml = \"0.22.3\"\nchrono = \"0.4.44\"\n"
  },
  {
    "path": "xtask/src/bump.rs",
    "content": "//! This has been copied pretty much wholesale from https://github.com/nrf-rs/nrf-hal/blob/master/xtask/src/lib.rs\nuse super::CRATES;\nuse chrono::Local;\nuse std::fs;\n\nfn file_replace(path: &str, from: &str, to: &str, dry_run: bool) {\n    let old_contents = fs::read_to_string(path).unwrap();\n    let new_contents = old_contents.replacen(from, to, 1);\n    if old_contents == new_contents {\n        panic!(\"failed to replace `{}` -> `{}` in `{}`\", from, to, path);\n    }\n\n    if !dry_run {\n        fs::write(path, new_contents).unwrap();\n    }\n}\n\n/// Bumps the versions of all crates and the changelog to `new_version`.\n///\n/// Dependency declarations are updated automatically. `html_root_url` is updated automatically.\npub fn bump_versions(new_version: &str, dry_run: bool) {\n    let common_toml_path = \"microbit-common/Cargo.toml\";\n    let toml = fs::read_to_string(common_toml_path).unwrap();\n\n    let needle = \"version = \\\"\";\n    let version_pos = toml.find(needle).unwrap() + needle.len();\n    let version_rest = &toml[version_pos..];\n    let end_pos = version_rest.find('\"').unwrap();\n    let old_version = &version_rest[..end_pos];\n\n    {\n        // Bump the changelog first, also check that it isn't empty.\n        let changelog_path = \"CHANGELOG.md\";\n        let changelog = fs::read_to_string(changelog_path).unwrap();\n        // (ignore empty changelog when this is a dry_run, since that runs in normal CI)\n        assert!(\n            dry_run || !changelog.contains(\"(no changes)\"),\n            \"changelog contains `(no changes)`; please fill it\"\n        );\n\n        // Prepend empty \"[Unreleased]\" section, promote the current one.\n        let today = Local::now().date_naive().format(\"%Y-%m-%d\").to_string();\n        let from = String::from(\"## [Unreleased]\");\n        let to = format!(\n            \"## [Unreleased]\\n\\n(no changes)\\n\\n## [{}] - {}\",\n            new_version, today\n        );\n        file_replace(changelog_path, &from, &to, dry_run);\n\n        // Replace the Unreleased link\n        let from = format!(\n            r#\"[Unreleased]: https://github.com/nrf-rs/microbit/compare/v{old_version}...HEAD\"#,\n            old_version = old_version,\n        );\n        let to = format!(\n            \"[Unreleased]: https://github.com/nrf-rs/microbit/compare/v{new_version}...HEAD\\n\\\n             [{new_version}]: https://github.com/nrf-rs/microbit/compare/v{old_version}...v{new_version}\",\n            new_version = new_version,\n            old_version = old_version,\n        );\n        file_replace(changelog_path, &from, &to, dry_run);\n    }\n\n    {\n        println!(\"microbit-common: {} -> {}\", old_version, new_version);\n\n        // Bump `microbit-common`'s version.\n        let from = format!(r#\"version = \"{}\"\"#, old_version);\n        let to = format!(r#\"version = \"{}\"\"#, new_version);\n        file_replace(\"microbit-common/Cargo.toml\", &from, &to, dry_run);\n\n        // Bump the `html_root_url`.\n        let from = format!(\n            r#\"#![doc(html_root_url = \"https://docs.rs/microbit-common/{old_version}\")]\"#,\n            old_version = old_version\n        );\n        let to = format!(\n            r#\"#![doc(html_root_url = \"https://docs.rs/microbit-common/{new_version}\")]\"#,\n            new_version = new_version\n        );\n        let librs_path = \"microbit-common/src/lib.rs\";\n        file_replace(librs_path, &from, &to, dry_run);\n    }\n\n    for (crate_name, _, _) in CRATES {\n        println!(\"{}: {} -> {}\", crate_name, old_version, new_version);\n        let toml_path = format!(\"{}/Cargo.toml\", crate_name);\n\n        // Bump the crate's version.\n        let from = format!(r#\"version = \"{}\"\"#, old_version);\n        let to = format!(r#\"version = \"{}\"\"#, new_version);\n        file_replace(&toml_path, &from, &to, dry_run);\n\n        // Bump the crate's dependency on `microbit-common`.\n        let from = format!(r#\"version = \"={}\"\"#, old_version);\n        let to = format!(r#\"version = \"={}\"\"#, new_version);\n        file_replace(&toml_path, &from, &to, dry_run);\n\n        // Bump the crate's `html_root_url`.\n        let from = format!(\n            r#\"#![doc(html_root_url = \"https://docs.rs/{crate}/{old_version}\")]\"#,\n            crate = crate_name,\n            old_version = old_version\n        );\n        let to = format!(\n            r#\"#![doc(html_root_url = \"https://docs.rs/{crate}/{new_version}\")]\"#,\n            crate = crate_name,\n            new_version = new_version\n        );\n        let librs_path = format!(\"{}/src/lib.rs\", crate_name);\n        file_replace(&librs_path, &from, &to, dry_run);\n    }\n}\n"
  },
  {
    "path": "xtask/src/ci.rs",
    "content": "use super::CRATES;\nuse std::{collections::HashMap, env, fs, path, process::Command};\n\npub static DEPENDENCIES: &[&str] = &[\"flip-link\"];\n\nfn install_targets() {\n    let targets = CRATES\n        .iter()\n        .map(|(_, target, _)| *target)\n        .collect::<Vec<_>>();\n\n    let mut rustup = Command::new(\"rustup\");\n    rustup.args(&[\"target\", \"add\"]).args(&targets);\n    let status = rustup\n        .status()\n        .map_err(|e| format!(\"couldn't execute {:?}: {}\", rustup, e))\n        .unwrap();\n    assert!(\n        status.success(),\n        \"failed to install targets with rustup: {:?}\",\n        rustup\n    );\n}\n\n/// Install global dependencies\nfn install_dependencies() {\n    for dependency in DEPENDENCIES {\n        let exists = Command::new(\"which\")\n            .arg(dependency)\n            .output()\n            .expect(\"failed to execute\");\n        if !exists.status.success() {\n            let mut cargo = Command::new(\"cargo\");\n            cargo.args(&[\"install\", dependency]);\n            let status = cargo\n                .status()\n                .map_err(|e| format!(\"couldn't execute {:?}: {}\", cargo, e))\n                .unwrap();\n            assert!(status.success(),);\n        }\n    }\n}\n\n/// Build-test each board support crate\nfn build_crates() {\n    for (hal, target, _) in CRATES {\n        let mut cargo = Command::new(\"cargo\");\n        let toml_path = format!(\"{}/Cargo.toml\", hal);\n        let status = cargo\n            .args(&[\"build\", \"--manifest-path\", &toml_path, \"--target\", target])\n            .status()\n            .map_err(|e| format!(\"could not execute {:?}: {}\", cargo, e))\n            .unwrap();\n        assert!(\n            status.success(),\n            \"command exited with error status: {:?}\",\n            cargo\n        );\n    }\n}\n\n/// Build/Run doc-tests in `microbit-common` for each version.\nfn build_run_doc_tests() {\n    for (_, _, feature) in CRATES {\n        let mut cargo = Command::new(\"cargo\");\n        let status = cargo\n            .current_dir(\"microbit-common\")\n            .args(&[\"test\", \"--features\", feature])\n            .status()\n            .map_err(|e| format!(\"could not execute {:?}: {}\", cargo, e))\n            .unwrap();\n        assert!(\n            status.success(),\n            \"command exited with error status: {:?}\",\n            cargo\n        );\n    }\n}\n\n/// Build all examples with the boards they support\nfn build_examples() {\n    let feature_targets = CRATES\n        .iter()\n        .map(|(_, target, feature)| (feature.to_string(), target.to_string()))\n        .collect::<HashMap<_, _>>();\n\n    let crate_targets = CRATES\n        .iter()\n        .map(|(name, target, _)| (name.to_string(), target.to_string()))\n        .collect::<HashMap<_, _>>();\n\n    for example in fs::read_dir(\"examples\").unwrap() {\n        let dir = example.unwrap();\n        let manifest_path = dir.path().join(\"Cargo.toml\");\n\n        // Skip if there is no manifest\n        if !manifest_path.exists() {\n            continue;\n        }\n\n        let manifest = cargo_toml::Manifest::from_path(&manifest_path).unwrap();\n\n        // find features and their targets supported by the example\n        let mut features = manifest\n            .features\n            .keys()\n            .filter_map(|feature| {\n                feature_targets\n                    .get(feature)\n                    .map(|target| (Some(feature.to_owned()), target.to_owned()))\n            })\n            .collect::<Vec<_>>();\n\n        // if there are no features find the target from the dependencies\n        if features.is_empty() {\n            features = manifest\n                .dependencies\n                .keys()\n                .filter_map(|name| {\n                    crate_targets\n                        .get(name)\n                        .map(|target| (None, target.to_owned()))\n                })\n                .collect::<Vec<_>>();\n            assert_eq!(\n                features.len(),\n                1,\n                \"examples must depend on either microbit or microbit-v2\"\n            );\n        }\n\n        for (feature, target) in features {\n            build_example(&manifest_path, feature, target);\n        }\n    }\n}\n\nfn build_example(manifest_path: &path::Path, feature: Option<String>, target: String) {\n    let mut cargo = Command::new(\"cargo\");\n    cargo.args(&[\n        \"build\",\n        \"--target\",\n        &target,\n        \"--manifest-path\",\n        manifest_path.to_str().unwrap(),\n    ]);\n    if let Some(feature) = feature {\n        cargo.args(&[\"--features\", &feature]);\n    }\n\n    let status = cargo\n        .status()\n        .map_err(|e| format!(\"could not execute {:?}: {}\", cargo, e))\n        .unwrap();\n\n    assert!(\n        status.success(),\n        \"command exited with error status: {:?}\",\n        cargo\n    );\n}\n\nfn start_group(is_ci: bool, name: &str) {\n    if is_ci {\n        println!(\"::group::{}\", name);\n    }\n}\n\nfn end_group(is_ci: bool) {\n    if is_ci {\n        println!(\"::endgroup::\");\n    }\n}\n\nfn wrap_in_group(is_ci: bool, name: &str, callable: &dyn Fn()) {\n    start_group(is_ci, name);\n    callable();\n    end_group(is_ci);\n}\n\npub fn ci() {\n    let is_ci = env::var(\"CI\").map_or(false, |ci| ci == \"true\");\n\n    // move up if we're running from inside xtask\n    if env::current_dir().unwrap().ends_with(\"xtask\") {\n        env::set_current_dir(\"..\").unwrap();\n    }\n\n    wrap_in_group(is_ci, \"install targets\", &install_targets);\n    wrap_in_group(is_ci, \"install dependencies\", &install_dependencies);\n    wrap_in_group(is_ci, \"build crates\", &build_crates);\n    wrap_in_group(is_ci, \"build examples\", &build_examples);\n    wrap_in_group(is_ci, \"run doc tests\", &build_run_doc_tests);\n}\n"
  },
  {
    "path": "xtask/src/lib.rs",
    "content": "mod bump;\nmod ci;\nmod publish;\n\npub static CRATES: &[(&str, &str, &str)] = &[\n    (\"microbit\", \"thumbv6m-none-eabi\", \"v1\"),\n    (\"microbit-v2\", \"thumbv7em-none-eabihf\", \"v2\"),\n];\n\npub use bump::bump_versions;\npub use ci::ci;\npub use publish::publish;\n"
  },
  {
    "path": "xtask/src/main.rs",
    "content": "use std::env;\n\nuse xtask::{bump_versions, ci, publish};\n\nfn main() {\n    let mut args = env::args().skip(1);\n    let subcommand = args.next();\n    match subcommand.as_deref() {\n        Some(\"bump\") => {\n            let new_version = args.next().expect(\"missing <semver> argument\");\n            bump_versions(&new_version, false);\n        }\n        Some(\"ci\") => ci(),\n        Some(\"publish\") => publish(),\n        _ => {\n            eprintln!(\"usage: cargo xtask <subcommand>\");\n            eprintln!();\n            eprintln!(\"subcommands:\");\n            eprintln!(\"  ci      - run continuous integration checks (build and clippy)\");\n            eprintln!(\"  bump    - bump the crate version and update docs and changelog\");\n            eprintln!(\"  publish - publish all crates to crates.io\");\n        }\n    }\n}\n"
  },
  {
    "path": "xtask/src/publish.rs",
    "content": "use std::process::Command;\n\nuse crate::CRATES;\n\npub fn publish() {\n    publish_package(\"microbit-common\", \"thumbv7em-none-eabihf\", Some(\"v2\"));\n\n    for (name, target, _) in CRATES {\n        publish_package(name, target, None);\n    }\n}\n\nfn publish_package(package: &str, target: &str, feature: Option<&str>) {\n    let mut cargo = Command::new(\"cargo\");\n    cargo.args(&[\"publish\", \"--target\", target, \"--package\", package]);\n    if let Some(feature) = feature {\n        cargo.args(&[\"--features\", feature]);\n    }\n\n    let status = cargo\n        .status()\n        .map_err(|e| format!(\"could not execute {:?}: {}\", cargo, e))\n        .unwrap();\n\n    assert!(\n        status.success(),\n        \"command exited with error status: {:?}\",\n        cargo\n    );\n}\n"
  }
]