Full Code of nrf-rs/microbit for AI

main 349d2991dd4f cached
85 files
151.9 KB
48.5k tokens
271 symbols
1 requests
Download .txt
Repository: nrf-rs/microbit
Branch: main
Commit: 349d2991dd4f
Files: 85
Total size: 151.9 KB

Directory structure:
gitextract_ax2jxq_v/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── changelog.yml
│       ├── ci.yaml
│       ├── clippy.yml
│       └── rustfmt.yml
├── .gitignore
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE-0BSD.txt
├── README.md
├── build.rs
├── examples/
│   ├── analog/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── analog-v1/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── analog-v2/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-blocking/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-nonblocking/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-rtic/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-text-rtic/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-direct-blinky/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-blinky/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-ledbutton/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-printbuttons/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── magnetometer/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── rng-direct/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── rng-hal/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-direct-echo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-direct-helloworld/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-hal-blocking-echo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── main.rs
│   │       └── serial_setup.rs
│   ├── servo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── v2-microphone/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   └── v2-speaker/
│       ├── Cargo.toml
│       └── src/
│           └── main.rs
├── memory.x
├── microbit/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── microbit-common/
│   ├── Cargo.toml
│   └── src/
│       ├── adc.rs
│       ├── board.rs
│       ├── display/
│       │   ├── blocking.rs
│       │   ├── mod.rs
│       │   └── nonblocking/
│       │       ├── control.rs
│       │       ├── image.rs
│       │       ├── matrix.rs
│       │       ├── mod.rs
│       │       └── timer.rs
│       ├── gpio.rs
│       ├── lib.rs
│       ├── v1/
│       │   ├── adc.rs
│       │   ├── board.rs
│       │   ├── gpio.rs
│       │   └── mod.rs
│       └── v2/
│           ├── adc.rs
│           ├── board.rs
│           ├── gpio.rs
│           └── mod.rs
├── microbit-v2/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── tools/
│   └── capture_example_bloat.sh
└── xtask/
    ├── Cargo.toml
    └── src/
        ├── bump.rs
        ├── ci.rs
        ├── lib.rs
        ├── main.rs
        └── publish.rs

================================================
FILE CONTENTS
================================================

================================================
FILE: .cargo/config.toml
================================================
[alias]
xtask = "run --package xtask --"

# For micro:bit v1.x

[target.thumbv6m-none-eabi]
runner = 'probe-rs run --chip nRF51822_xxAA --protocol swd'
rustflags = [
  "-C", "linker=flip-link",
  "-C", "link-arg=-Tlink.x",
  "-C", "link-arg=-Tdefmt.x",
]

# For micro:bit v2

[target.thumbv7em-none-eabi]
runner = "probe-rs run --chip nRF52833_xxAA --protocol swd"
rustflags = [
  "-C", "linker=flip-link",
  "-C", "link-arg=-Tlink.x",
  "-C", "link-arg=-Tdefmt.x",
]

[target.thumbv7em-none-eabihf]
runner = "probe-rs run --chip nRF52833_xxAA --protocol swd"
rustflags = [
  "-C", "linker=flip-link",
  "-C", "link-arg=-Tlink.x",
  "-C", "link-arg=-Tdefmt.x",
]

# Enable printing of defmt debug, info and warning messages by default
[env]
DEFMT_LOG="debug"


================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
  - package-ecosystem: "cargo"
    directory: "/"
    schedule:
      interval: "daily"
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "weekly"


================================================
FILE: .github/workflows/changelog.yml
================================================
on:
  pull_request_target:
    types: [opened, synchronize, reopened, labeled, unlabeled]

name: Changelog check

jobs:
  changelog:
    name: Changelog check
    runs-on: ubuntu-latest
    steps:
      - name: Checkout sources
        uses: actions/checkout@v6

      - name: Changelog updated
        uses: Zomzog/changelog-checker@v1.3.0
        with:
          fileName: CHANGELOG.md
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/ci.yaml
================================================
on:
  push:
    branches: main
  pull_request:
  merge_group:

jobs:
  ci:
    name: CI
    runs-on: ubuntu-latest
    needs: [build]
    if: always()
    steps:
      - name: Done
        run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'

  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        rust:
          - stable
          - beta
          - nightly
        include:
          # Minimum supported rust version (MSRV)
          # Note this needs to be new enough to build the examples as well as
          # the library itself.
          - name: MSRV
            rust: 1.85.0

    name: "build (${{ matrix.name || matrix.rust }})"

    steps:
      - uses: actions/checkout@v6

      - name: Install Rust
        uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: ${{ matrix.rust }}
          override: true
          components: rustfmt, clippy

      - name: rustfmt
        run: cargo fmt -- --check

      - name: build
        run: cargo xtask ci


================================================
FILE: .github/workflows/clippy.yml
================================================
on:
  push:
    branches: main
  pull_request:
  merge_group:

name: Clippy check
jobs:
  clippy_check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - run: rustup component add clippy
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
          target: thumbv6m-none-eabi
          override: true

      - name: microbit V1
        run: cargo clippy --package microbit -- -D warnings

      - name: microbit V2
        run: cargo clippy --package microbit-v2 -- -D warnings


================================================
FILE: .github/workflows/rustfmt.yml
================================================
on:
  push:
    branches: main
  pull_request:
  merge_group:

name: Code formatting check

jobs:
  fmt:
    name: Rustfmt
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: actions-rs/toolchain@v1
        with:
          profile: minimal
          toolchain: stable
          override: true
      - run: rustup component add rustfmt
      - uses: actions-rs/cargo@v1
        with:
          command: fmt
          args: --all -- --check


================================================
FILE: .gitignore
================================================
/target/
**/*.orig
**/*.rs.bk
bloat_log*
!.gitignore
!.github
!.cargo


================================================
FILE: CHANGELOG.md
================================================
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

- Bumped MSRV to 1.85.0
- Updated `examples/hal-rng/` to use latest `rand_pcg`,
  removing `rand` dependency and bumping to Rust 2024
- Added SPIM peripherals to Board struct

## [0.16.0] - 2025-10-11

- Remove dead link to microbit Rust on Windows blog post in README.
- Bumped MSRV to 1.81.0.
- Add metadata for docs.rs
- Bumped dependencies in `examples/` to latest versions.
- Update HAL crates to 0.19.0.

## [0.15.1] - 2024-08-05

- Set MSRV for `microbit` and `microbit-v2` crates.
- Bumped MSRV to 1.79.0.
- Make various `I2C` `Pin` fields `pub`

## [0.15.0] - 2024-06-19

- Update HAL crates to 0.18.0.
- Update installation instructions for `probe-rs`

## [0.14.0] - 2024-04-18

- Fix: non-blocking display on micro:bit V2 could spuriously light LEDs briefly
- Fix the `blocking::Display::set_refresh_rate` calculation for the micro:bit V2
- Double the non-blocking display refresh frequency for the micro:bit V2
- Fix faulty doc test in `blocking.rs`
- Update the non-blocking display documentation to better explain when methods
  should be called from within a critical section
- Bump example dependencies to latest versions to fix build
- Update examples to use RTIC 1.0
- Add ADC for micro:bit V1
- Add analog example
- Increase minimum supported Rust version to 1.73
- Added support for the real time counters RTC1 and RTC2
- Add common types and structs for the edge connector pads and pins
- Add common ADC types and initialization for ADC and SAADC
- Common ADC example
- Add support for PPI
- Servo example using TIMER, GPIOTE and PPI
- (NFC) GitHub CI changes
- Feature: Exposed all remaining peripherals for both boards.
- Update HAL crates to 0.17.1.
- Update to `embedded-hal` 1.0.
- Update magnetometer example to use `lsm303agr` 1.0.
- Update debug tooling from probe-run to probe-rs

## [0.13.0] - 2022-05-24

- Drop ble-beacon example (since rubble is now archived as unmaintained)
- Bump `defmt` versions to 0.3
- Increase minimum supported Rust version to 1.57
- Add display-text-rtic example
- Make `Board::new(p, cp)` public and fix RTIC example
- Fix display-nonblocking example
- Fix timer for LED-display (GreyscaleImage with a empty Row did not work)
- Add SAADC and microphone_pins for micro:bit V2.
- Add microphone example

## [0.12.0] - 2021-11-10

### Changed

- Update dependencies nrf51-hal and nrf52833-hal to 0.14.0
- Added TEMP field to board
- Fixed Issue where columns 2,3 and 4 of the nonblocking display were swapped

## [0.11.0] - 2021-09-13

### Added

- Added support for the thumbv7em-none-eabi target for microbit:v2 (same as
  thumbv7em-none-eabihf but without hardware floating point support)

### Changed

- Rearrange LED display modules under the same root module and change their
  APIs to be more aligned with each other.
- Add BLE Beacon demo.
- Add a simple speaker demo for micro:bit V2.
- Add Board struct following the pattern used in other nrf board support crates.
- Add magnetometer example.
- LEDs on the micro:bit V1 are now turned off per default
- UART(E) is now exposed in the same way as I2C

## [0.10.1] - 2021-05-25

Republished without changes to fix missing README.md in crates.io.

## [0.10.0] - 2021-05-13

### Added

- Add support for micro:bit V2. This is a significant change that splits
  this repository into multiple crates.

## [0.9.0] - 2021-04-29

### Added

- Add `microbit::gpio` module with pins mapped to micro:bit names
- Refactor `microbit::display` and `microbit::led` to accept `gpio::Pins`
- Make probe-run the default runner
- Rewrite `serial_port` as a macro

### Fixed

- Fix rustdoc warnings
- Upgrade nrf51-hal to 0.12.1

[Unreleased]: https://github.com/nrf-rs/microbit/compare/v0.16.0...HEAD
[0.16.0]: https://github.com/nrf-rs/microbit/compare/v0.15.1...v0.16.0
[0.15.1]: https://github.com/nrf-rs/microbit/compare/v0.15.0...v0.15.1
[0.15.0]: https://github.com/nrf-rs/microbit/compare/v0.14.0...v0.15.0
[0.14.0]: https://github.com/nrf-rs/microbit/compare/v0.13.0...v0.14.0
[0.13.0]: https://github.com/nrf-rs/microbit/compare/v0.12.0...v0.13.0
[0.12.0]: https://github.com/nrf-rs/microbit/compare/v0.11.0...v0.12.0
[0.11.0]: https://github.com/nrf-rs/microbit/compare/v0.10.1...v0.11.0
[0.10.1]: https://github.com/nrf-rs/microbit/compare/v0.10.0...v0.10.1
[0.10.0]: https://github.com/nrf-rs/microbit/compare/v0.9.0...v0.10.0
[0.9.0]: https://github.com/nrf-rs/microbit/compare/v0.8.0...v0.9.0


================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = [
  "microbit-common",
  "microbit",
  "microbit-v2",
  "examples/*",
  "xtask",
]

# Modify default build profiles to make debugging easier
[profile.release]
debug = 2
lto = "off"

[profile.dev]
debug = 2
opt-level = 1
lto = "off"


================================================
FILE: LICENSE-0BSD.txt
================================================
Copyright (C) 2018 daniel@eggers-club.de

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


================================================
FILE: README.md
================================================
# microbit

_microbit_ contains everything required getting started using Rust to create firmwares for the fabulous
[BBC micro:bit](https://microbit.org) microcontroller board. This little board has everything and a kitchen sink built-in,
even a capable debugging interface.

## Getting started

All you need to start programming this device is:

* A BBC micro:bit board
* A computer (known to work with macOS, Linux and Windows)
* A bit of open source software

### Know your version

The micro:bit comes in different versions. There is a separate crate for each major board version. See the table below to identify
which crate you need to use.

| Crate                          | Board version | Board image | Docs | crates.io | target |
| ------------------------------ | ------------- | ----------- | ---- | --------- | ------ |
| [`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` |
| [`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` |

### Install dependencies

The examples make use of some of the fantastic tooling from the [knurling](https://knurling.ferrous-systems.com/) and [probe-rs](https://probe.rs/) projects.
In order to run the examples you need to install [`probe-rs`](https://probe.rs/docs/getting-started/installation)
and [`flip-link`](https://github.com/knurling-rs/flip-link#installation).

```bash
> cargo install probe-rs-tools flip-link
```

### Run an example

The first thing to try is one of the [examples](./examples) in this repository. Plug in your micro:bit and
run one of the commands below.

*For micro:bit V1*
```bash
> cargo run --release --manifest-path ./examples/display-blocking/Cargo.toml --features v1 --target thumbv6m-none-eabi
```

*For micro:bit V2*
```bash
> cargo run --release --manifest-path ./examples/display-blocking/Cargo.toml --features v2 --target thumbv7em-none-eabihf
```

You should see a lot of build output, the orange LED on the back of the micro:bit should flash quickly, and
a message should appear on the LED display.

Congratulations! You've flashed your first Rust program onto your micro:bit!

## Further reading

A 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/).

Other useful resources:
- [micro:bit developer community](https://tech.microbit.org)
- [micro:bit hardware overview](https://tech.microbit.org/hardware/)
- [nrf-hal](https://github.com/nrf-rs/nrf-hal#readme) the hardware abstraction layer (HAL) this repository is based on

## License

[0-clause BSD license](LICENSE-0BSD.txt).


================================================
FILE: build.rs
================================================
use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    // Put the linker script somewhere the linker can find it
    let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
    File::create(out.join("memory.x"))
        .unwrap()
        .write_all(include_bytes!("memory.x"))
        .unwrap();
    println!("cargo:rustc-link-search={}", out.display());

    // Only re-run the build script when memory.x is changed,
    // instead of when any part of the source code changes.
    println!("cargo:rerun-if-changed=memory.x");
}


================================================
FILE: examples/analog/Cargo.toml
================================================
[package]
name = "analog"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/analog/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use microbit::{
    adc::{Adc, AdcConfig, Default},
    board::Board,
    display::blocking::Display,
    hal::Timer,
};

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let mut timer = Timer::new(board.TIMER0);
        let mut display = Display::new(board.display_pins);
        let mut adc = Adc::new(board.ADC, AdcConfig::default_10bit());
        let mut anapin = board.edge.e00.into_floating_input(); // PAD0

        let numbers = [
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 1, 0, 0, 0],
                [0, 1, 1, 1, 0],
            ],
            [
                [0, 1, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 1, 1, 0, 0],
            ],
            [
                [0, 1, 0, 0, 0],
                [1, 0, 0, 0, 0],
                [1, 0, 1, 0, 0],
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
            ],
        ];

        let sign_plus = [
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [1, 1, 1, 1, 1],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
        ];

        #[cfg(feature = "v2")]
        #[allow(non_snake_case)]
        let letter_E = [
            [0, 1, 1, 1, 0],
            [0, 1, 0, 0, 0],
            [0, 1, 1, 0, 0],
            [0, 1, 0, 0, 0],
            [0, 1, 1, 1, 0],
        ];

        loop {
            let analog = adc.read_channel(&mut anapin);
            #[cfg(feature = "v2")]
            let Ok(analog) = analog
            else {
                display.show(&mut timer, letter_E, 10);
                continue;
            };
            let n_iter = numbers.iter();
            let mut count: usize = 0;
            for n_val in n_iter {
                if count == usize::from(i16::unsigned_abs(analog / 100)) {
                    display.show(&mut timer, *n_val, 10);
                    break;
                }
                count += 1;
            }
            if count == numbers.len() {
                display.show(&mut timer, sign_plus, 10);
            }
        }
    }
    panic!("End");
}


================================================
FILE: examples/analog-v1/Cargo.toml
================================================
[package]
name = "analog-v1"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

# NOTE: This currently only works with the microbit v1 due to naming issues!
# ADC vs SAADC
[dependencies.microbit]
path = "../../microbit"

[features]
default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/analog-v1/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use microbit::{
    board::Board,
    display::blocking::Display,
    hal::{adc::AdcConfig, Adc, Timer},
};

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let mut timer = Timer::new(board.TIMER0);
        let mut display = Display::new(board.display_pins);
        let mut adc: Adc = Adc::new(board.ADC, AdcConfig::default());
        let mut anapin = board.edge.e00.into_floating_input(); // PAD1

        let numbers = [
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 1, 0, 0, 0],
                [0, 1, 1, 1, 0],
            ],
            [
                [0, 1, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 1, 1, 0, 0],
            ],
            [
                [0, 1, 0, 0, 0],
                [1, 0, 0, 0, 0],
                [1, 0, 1, 0, 0],
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
            ],
        ];

        let sign_plus = [
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [1, 1, 1, 1, 1],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
        ];

        loop {
            let analog_value = adc.read_channel(&mut anapin);
            let n_iter = numbers.iter();
            let mut count: usize = 0;
            for n_val in n_iter {
                if count == usize::from(i16::unsigned_abs(analog_value / 100)) {
                    display.show(&mut timer, *n_val, 10);
                    break;
                }
                count += 1;
            }
            if count == numbers.len() {
                display.show(&mut timer, sign_plus, 10);
            }
        }
    }
    panic!("End");
}


================================================
FILE: examples/analog-v2/Cargo.toml
================================================
[package]
name = "analog-v2"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

# NOTE: This currently only works with the microbit v2 due to naming issues!
# ADC vs SAADC
[dependencies.microbit-v2]
path = "../../microbit-v2"

[features]
default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/analog-v2/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use microbit::{
    board::Board,
    display::blocking::Display,
    hal::{saadc::SaadcConfig, Saadc, Timer},
};

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let mut timer = Timer::new(board.TIMER0);
        let mut display = Display::new(board.display_pins);
        let mut adc: Saadc = Saadc::new(board.ADC, SaadcConfig::default());
        let mut anapin = board.edge.e00.into_floating_input(); // PAD1

        let numbers = [
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 1, 0, 0],
            ],
            [
                [0, 0, 1, 0, 0],
                [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 1, 0, 0, 0],
                [0, 1, 1, 1, 0],
            ],
            [
                [0, 1, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 0, 1, 0, 0],
                [0, 0, 0, 1, 0],
                [0, 1, 1, 0, 0],
            ],
            [
                [0, 1, 0, 0, 0],
                [1, 0, 0, 0, 0],
                [1, 0, 1, 0, 0],
                [1, 1, 1, 1, 0],
                [0, 0, 1, 0, 0],
            ],
        ];

        let sign_plus = [
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [1, 1, 1, 1, 1],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
        ];

        #[allow(non_snake_case)]
        let letter_E = [
            [0, 1, 1, 1, 0],
            [0, 1, 0, 0, 0],
            [0, 1, 1, 0, 0],
            [0, 1, 0, 0, 0],
            [0, 1, 1, 1, 0],
        ];

        loop {
            let analog = adc.read_channel(&mut anapin);
            match analog {
                Ok(v) => {
                    let n_iter = numbers.iter();
                    let mut count: usize = 0;
                    for n_val in n_iter {
                        if count == usize::from(i16::unsigned_abs(v / 100)) {
                            display.show(&mut timer, *n_val, 10);
                            break;
                        }
                        count += 1;
                    }
                    if count == numbers.len() {
                        display.show(&mut timer, sign_plus, 10);
                    }
                }
                Err(_e) => display.show(&mut timer, letter_E, 10),
            }
        }
    }
    panic!("End");
}


================================================
FILE: examples/display-blocking/Cargo.toml
================================================
[package]
name = "display-blocking"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"
embedded-hal = "1.0.0"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/display-blocking/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use microbit::{board::Board, display::blocking::Display, hal::Timer};

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let mut timer = Timer::new(board.TIMER0);
        let mut display = Display::new(board.display_pins);

        #[allow(non_snake_case)]
        let letter_I = [
            [0, 1, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
        ];

        let heart = [
            [0, 1, 0, 1, 0],
            [1, 0, 1, 0, 1],
            [1, 0, 0, 0, 1],
            [0, 1, 0, 1, 0],
            [0, 0, 1, 0, 0],
        ];

        #[allow(non_snake_case)]
        let letter_R = [
            [0, 1, 1, 0, 0],
            [0, 1, 0, 1, 0],
            [0, 1, 1, 0, 0],
            [0, 1, 0, 1, 0],
            [0, 1, 0, 1, 0],
        ];

        #[allow(non_snake_case)]
        let letter_u = [
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 1, 0, 1, 0],
            [0, 1, 0, 1, 0],
            [0, 1, 1, 1, 0],
        ];

        #[allow(non_snake_case)]
        let letter_s = [
            [0, 0, 0, 0, 0],
            [0, 0, 1, 1, 0],
            [0, 1, 0, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
        ];

        #[allow(non_snake_case)]
        let letter_t = [
            [0, 0, 1, 0, 0],
            [0, 1, 1, 1, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
            [0, 0, 1, 0, 0],
        ];
        loop {
            display.show(&mut timer, letter_I, 1000);
            display.show(&mut timer, heart, 1000);
            display.show(&mut timer, letter_R, 1000);
            display.show(&mut timer, letter_u, 1000);
            display.show(&mut timer, letter_s, 1000);
            display.show(&mut timer, letter_t, 1000);
            display.clear();
            timer.delay_ms(250_u32);
        }
    }

    panic!("End");
}


================================================
FILE: examples/display-nonblocking/Cargo.toml
================================================
[package]
name = "display-nonblocking"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/display-nonblocking/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;

use microbit::{
    board::Board,
    display::nonblocking::{Display, GreyscaleImage},
    hal::{
        clocks::Clocks,
        rtc::{Rtc, RtcInterrupt},
    },
    pac::{self, interrupt, RTC0, TIMER1},
};

fn heart_image(inner_brightness: u8) -> GreyscaleImage {
    let b = inner_brightness;
    GreyscaleImage::new(&[
        [0, 7, 0, 7, 0],
        [7, b, 7, b, 7],
        [7, b, b, b, 7],
        [0, 7, b, 7, 0],
        [0, 0, 7, 0, 0],
    ])
}

// We use TIMER1 to drive the display, and RTC0 to update the animation.
// We set the TIMER1 interrupt to a higher priority than RTC0.

static DISPLAY: Mutex<RefCell<Option<Display<TIMER1>>>> = Mutex::new(RefCell::new(None));
static ANIM_TIMER: Mutex<RefCell<Option<Rtc<RTC0>>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    if let Some(mut board) = Board::take() {
        // Starting the low-frequency clock (needed for RTC to work)
        Clocks::new(board.CLOCK).start_lfclk();

        // RTC at 16Hz (32_768 / (2047 + 1))
        // 62.5ms period
        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();
        rtc0.enable_event(RtcInterrupt::Tick);
        rtc0.enable_interrupt(RtcInterrupt::Tick, None);
        rtc0.enable_counter();

        // Create display
        let display = Display::new(board.TIMER1, board.display_pins);

        cortex_m::interrupt::free(move |cs| {
            *DISPLAY.borrow(cs).borrow_mut() = Some(display);
            *ANIM_TIMER.borrow(cs).borrow_mut() = Some(rtc0);
        });
        unsafe {
            board.NVIC.set_priority(pac::Interrupt::RTC0, 64);
            board.NVIC.set_priority(pac::Interrupt::TIMER1, 128);
            pac::NVIC::unmask(pac::Interrupt::RTC0);
            pac::NVIC::unmask(pac::Interrupt::TIMER1);
        }
    }

    loop {
        continue;
    }
}

#[interrupt]
fn TIMER1() {
    cortex_m::interrupt::free(|cs| {
        if let Some(display) = DISPLAY.borrow(cs).borrow_mut().as_mut() {
            display.handle_display_event();
        }
    });
}

#[interrupt]
unsafe fn RTC0() {
    static mut STEP: u8 = 0;

    cortex_m::interrupt::free(|cs| {
        if let Some(rtc) = ANIM_TIMER.borrow(cs).borrow_mut().as_mut() {
            rtc.reset_event(RtcInterrupt::Tick);
        }
    });

    let inner_brightness = match *STEP {
        0..=8 => 9 - *STEP,
        9..=12 => 0,
        _ => unreachable!(),
    };

    cortex_m::interrupt::free(|cs| {
        if let Some(display) = DISPLAY.borrow(cs).borrow_mut().as_mut() {
            display.show(&heart_image(inner_brightness));
        }
    });

    *STEP += 1;
    if *STEP == 13 {
        *STEP = 0
    };
}


================================================
FILE: examples/display-rtic/Cargo.toml
================================================
[package]
name = "display-rtic"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"
cortex-m-rtic = { version = "1.1.4" }

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/display-rtic/src/main.rs
================================================
//! A complete working example.
//!
//! This requires `cortex-m-rtic` v1.0.
//!
//! It uses `TIMER1` to drive the display, and `RTC0` to update a simple
//! animated image.
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use rtic::app;

#[app(device = microbit::pac, peripherals = true)]
mod app {

    use microbit::{
        board::Board,
        display::nonblocking::{Display, GreyscaleImage},
        hal::{
            clocks::Clocks,
            rtc::{Rtc, RtcInterrupt},
        },
        pac,
    };

    fn heart_image(inner_brightness: u8) -> GreyscaleImage {
        let b = inner_brightness;
        GreyscaleImage::new(&[
            [0, 7, 0, 7, 0],
            [7, b, 7, b, 7],
            [7, b, b, b, 7],
            [0, 7, b, 7, 0],
            [0, 0, 7, 0, 0],
        ])
    }

    #[shared]
    struct Shared {
        display: Display<pac::TIMER1>,
    }

    #[local]
    struct Local {
        anim_timer: Rtc<pac::RTC0>,
    }

    #[init]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
        let board = Board::new(cx.device, cx.core);

        // Starting the low-frequency clock (needed for RTC to work)
        Clocks::new(board.CLOCK).start_lfclk();

        // RTC at 16Hz (32_768 / (2047 + 1))
        // 16Hz; 62.5ms period
        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();
        rtc0.enable_event(RtcInterrupt::Tick);
        rtc0.enable_interrupt(RtcInterrupt::Tick, None);
        rtc0.enable_counter();

        let display = Display::new(board.TIMER1, board.display_pins);
        (
            Shared { display },
            Local { anim_timer: rtc0 },
            init::Monotonics(),
        )
    }

    #[task(binds = TIMER1, priority = 2, shared = [display])]
    fn timer1(mut cx: timer1::Context) {
        cx.shared
            .display
            .lock(|display| display.handle_display_event());
    }

    #[task(binds = RTC0, priority = 1, shared = [display],
           local = [anim_timer, step: u8 = 0])]
    fn rtc0(cx: rtc0::Context) {
        let mut shared = cx.shared;
        let local = cx.local;

        local.anim_timer.reset_event(RtcInterrupt::Tick);

        let inner_brightness = match *local.step {
            0..=8 => 9 - *local.step,
            9..=12 => 0,
            _ => unreachable!(),
        };

        shared.display.lock(|display| {
            display.show(&heart_image(inner_brightness));
        });

        *local.step += 1;
        if *local.step == 13 {
            *local.step = 0
        };
    }
}


================================================
FILE: examples/display-text-rtic/Cargo.toml
================================================
[package]
name = "display-text-rtic"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"
cortex-m-rtic = { version = "1.1.4" }
microbit-text = "1.0.0"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/display-text-rtic/src/main.rs
================================================
//! An example of scrolling static text.
//!
//! It uses `TIMER1` to drive the display, and `RTC0` to animate the text.
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use rtic::app;

#[app(device = microbit::pac, peripherals = true)]
mod app {

    use microbit::{
        board::Board,
        display::nonblocking::{Display, Frame, MicrobitFrame},
        hal::{
            clocks::Clocks,
            rtc::{Rtc, RtcInterrupt},
        },
        pac,
    };
    use microbit_text::scrolling::Animate;
    use microbit_text::scrolling_text::ScrollingStaticText;

    const MESSAGE: &[u8] = b"Hello, world!";

    #[shared]
    struct Shared {
        display: Display<pac::TIMER1>,
    }

    #[local]
    struct Local {
        anim_timer: Rtc<pac::RTC0>,
        scroller: ScrollingStaticText,
    }

    #[init]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
        let board = Board::new(cx.device, cx.core);

        // Starting the low-frequency clock (needed for RTC to work)
        Clocks::new(board.CLOCK).start_lfclk();

        // RTC at 16Hz (32_768 / (2047 + 1))
        // 16Hz; 62.5ms period
        let mut rtc0 = Rtc::new(board.RTC0, 2047).unwrap();
        rtc0.enable_event(RtcInterrupt::Tick);
        rtc0.enable_interrupt(RtcInterrupt::Tick, None);
        rtc0.enable_counter();

        let display = Display::new(board.TIMER1, board.display_pins);

        let mut scroller = ScrollingStaticText::default();
        scroller.set_message(MESSAGE);

        (
            Shared { display },
            Local {
                anim_timer: rtc0,
                scroller,
            },
            init::Monotonics(),
        )
    }

    #[task(binds = TIMER1, priority = 2, shared = [display])]
    fn timer1(mut cx: timer1::Context) {
        cx.shared
            .display
            .lock(|display| display.handle_display_event());
    }

    #[task(binds = RTC0, priority = 1, shared = [display],
           local = [anim_timer, scroller,
                    frame: MicrobitFrame = MicrobitFrame::default()])]
    fn rtc0(cx: rtc0::Context) {
        let mut shared = cx.shared;
        let local = cx.local;
        local.anim_timer.reset_event(RtcInterrupt::Tick);
        if !local.scroller.is_finished() {
            local.scroller.tick();
            local.frame.set(local.scroller);
            shared.display.lock(|display| {
                display.show_frame(local.frame);
            });
        }
    }
}


================================================
FILE: examples/gpio-direct-blinky/Cargo.toml
================================================
[package]
name = "gpio-direct-blinky"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/gpio-direct-blinky/src/main.rs
================================================
#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;

#[cfg(feature = "v1")]
#[entry]
fn main() -> ! {
    if let Some(p) = microbit::Peripherals::take() {
        p.GPIO.pin_cnf[4].write(|w| w.dir().output());
        p.GPIO.pin_cnf[13].write(|w| w.dir().output());

        p.GPIO.out.write(|w| unsafe { w.bits(1 << 13) });

        let mut count: u8 = 0;
        loop {
            count += 1;

            if count & 1 == 1 {
                p.GPIO.out.write(|w| unsafe { w.bits(1 << 13) });
            } else {
                p.GPIO.out.write(|w| unsafe { w.bits(0) });
            }

            for _ in 0..50_000 {
                cortex_m::asm::nop();
            }
        }
    };

    loop {
        continue;
    }
}

#[cfg(feature = "v2")]
#[entry]
fn main() -> ! {
    if let Some(p) = microbit::Peripherals::take() {
        p.P0.pin_cnf[28].write(|w| w.dir().output());
        p.P0.pin_cnf[21].write(|w| w.dir().output());

        p.P0.out.write(|w| unsafe { w.bits(1 << 21) });

        let mut count: u8 = 0;
        loop {
            count += 1;

            if count & 1 == 1 {
                p.P0.out.write(|w| unsafe { w.bits(1 << 21) });
            } else {
                p.P0.out.write(|w| unsafe { w.bits(0) });
            }

            for _ in 0..50_000 {
                cortex_m::asm::nop();
            }
        }
    };

    loop {
        continue;
    }
}


================================================
FILE: examples/gpio-hal-blinky/Cargo.toml
================================================
[package]
name = "gpio-hal-blinky"
version = "0.1.0"
edition = "2018"

[dependencies]
embedded-hal = "1.0.0"
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/gpio-hal-blinky/src/main.rs
================================================
#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;
use embedded_hal::{delay::DelayNs, digital::OutputPin};
use microbit::{board::Board, hal::timer::Timer};

#[entry]
fn main() -> ! {
    let mut board = Board::take().unwrap();

    let mut timer = Timer::new(board.TIMER0);

    let _ = board.display_pins.col1.set_low();
    let mut row1 = board.display_pins.row1;

    loop {
        let _ = row1.set_low();
        timer.delay_ms(1_000);
        let _ = row1.set_high();
        timer.delay_ms(1_000);
    }
}


================================================
FILE: examples/gpio-hal-ledbutton/Cargo.toml
================================================
[package]
name = "gpio-hal-ledbutton"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"
embedded-hal = "1.0.0"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/gpio-hal-ledbutton/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use embedded_hal::digital::{InputPin, OutputPin};
use microbit::board::Board;

#[entry]
fn main() -> ! {
    let mut board = Board::take().unwrap();

    board.display_pins.row1.set_high().unwrap();

    let mut led1 = board.display_pins.col1;
    let mut led2 = board.display_pins.col2;

    loop {
        if let Ok(true) = board.buttons.button_a.is_high() {
            let _ = led1.set_high();
        } else {
            let _ = led1.set_low();
        }

        if let Ok(true) = board.buttons.button_b.is_high() {
            let _ = led2.set_high();
        } else {
            let _ = led2.set_low();
        }
    }
}


================================================
FILE: examples/gpio-hal-printbuttons/Cargo.toml
================================================
[package]
name = "gpio-hal-printbuttons"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/gpio-hal-printbuttons/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use core::cell::RefCell;

use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use microbit::{
    board::Board,
    hal::gpiote::Gpiote,
    pac::{self, interrupt},
};

static GPIO: Mutex<RefCell<Option<Gpiote>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    let board = Board::take().unwrap();

    let gpiote = Gpiote::new(board.GPIOTE);

    let channel0 = gpiote.channel0();
    channel0
        .input_pin(&board.buttons.button_a.degrade())
        .hi_to_lo()
        .enable_interrupt();
    channel0.reset_events();

    let channel1 = gpiote.channel1();
    channel1
        .input_pin(&board.buttons.button_b.degrade())
        .hi_to_lo()
        .enable_interrupt();
    channel1.reset_events();

    cortex_m::interrupt::free(move |cs| {
        /* Enable external GPIO interrupts */
        unsafe {
            pac::NVIC::unmask(pac::Interrupt::GPIOTE);
        }
        pac::NVIC::unpend(pac::Interrupt::GPIOTE);

        *GPIO.borrow(cs).borrow_mut() = Some(gpiote);

        defmt::info!("Welcome to the buttons demo. Press buttons A and/or B for some action.");
    });

    loop {
        continue;
    }
}

// Define an interrupt, i.e. function to call when exception occurs. Here if we receive an
// interrupt from a button press, the function will be called
#[interrupt]
fn GPIOTE() {
    /* Enter critical section */
    cortex_m::interrupt::free(|cs| {
        if let Some(gpiote) = GPIO.borrow(cs).borrow().as_ref() {
            let buttonapressed = gpiote.channel0().is_event_triggered();
            let buttonbpressed = gpiote.channel1().is_event_triggered();

            /* Print buttons to the serial console */
            defmt::info!(
                "Button pressed {:?}",
                match (buttonapressed, buttonbpressed) {
                    (false, false) => "",
                    (true, false) => "A",
                    (false, true) => "B",
                    (true, true) => "A + B",
                }
            );

            /* Clear events */
            gpiote.channel0().reset_events();
            gpiote.channel1().reset_events();
        }
    });
}


================================================
FILE: examples/magnetometer/Cargo.toml
================================================
[package]
name = "magnetometer"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
embedded-hal = "1.0.0"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"
lsm303agr = "1.1.0"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/magnetometer/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use embedded_hal::delay::DelayNs;
use lsm303agr::{
    interface::I2cInterface, mode::MagOneShot, AccelMode, AccelOutputDataRate, Lsm303agr,
};
use microbit::hal::Timer;

#[cfg(feature = "v1")]
use microbit::{
    hal::twi,
    pac::{twi0::frequency::FREQUENCY_A, TWI0},
};
#[cfg(feature = "v2")]
use microbit::{
    hal::twim,
    pac::{twim0::frequency::FREQUENCY_A, TWIM0},
};

#[entry]
fn main() -> ! {
    let board = microbit::Board::take().unwrap();
    let mut timer = Timer::new(board.TIMER0);

    #[cfg(feature = "v1")]
    let i2c = { twi::Twi::new(board.TWI0, board.i2c.into(), FREQUENCY_A::K100) };

    #[cfg(feature = "v2")]
    let i2c = { twim::Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100) };

    let mut sensor = Lsm303agr::new_with_i2c(i2c);
    if let Ok(id) = sensor.accelerometer_id() {
        if !id.is_correct() {
            defmt::panic!("Accelerometer had unexpected ID {:#x}", id.raw());
        }
    } else {
        defmt::panic!("Error getting accelerometer ID");
    }
    sensor.init().unwrap();

    defmt::info!("normal mode");
    sensor
        .set_accel_mode_and_odr(&mut timer, AccelMode::Normal, AccelOutputDataRate::Hz50)
        .unwrap();
    timer.delay_ms(1000_u32);
    get_data(&mut sensor);

    defmt::info!("low power mode");
    sensor
        .set_accel_mode_and_odr(&mut timer, AccelMode::LowPower, AccelOutputDataRate::Hz50)
        .unwrap();
    timer.delay_ms(1000_u32);
    get_data(&mut sensor);

    defmt::info!("high resolution mode");
    sensor
        .set_accel_mode_and_odr(
            &mut timer,
            AccelMode::HighResolution,
            AccelOutputDataRate::Hz50,
        )
        .unwrap();
    timer.delay_ms(1000_u32);
    get_data(&mut sensor);

    loop {
        timer.delay_ms(100_u32);
        get_data(&mut sensor);
    }
}

#[cfg(feature = "v1")]
type Sensor = Lsm303agr<I2cInterface<twi::Twi<TWI0>>, MagOneShot>;

#[cfg(feature = "v2")]
type Sensor = Lsm303agr<I2cInterface<twim::Twim<TWIM0>>, MagOneShot>;

fn get_data(sensor: &mut Sensor) {
    loop {
        if sensor.accel_status().unwrap().xyz_new_data() {
            let data = sensor.acceleration().unwrap();
            defmt::info!("x {} y {} z {}", data.x_mg(), data.y_mg(), data.z_mg());
            return;
        }
    }
}


================================================
FILE: examples/rng-direct/Cargo.toml
================================================
[package]
name = "rng-direct"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/rng-direct/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use core::cell::RefCell;

use microbit::pac::{self, interrupt};

use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;

static RNG: Mutex<RefCell<Option<pac::RNG>>> = Mutex::new(RefCell::new(None));
static RTC: Mutex<RefCell<Option<pac::RTC0>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    if let Some(p) = microbit::Peripherals::take() {
        p.CLOCK.tasks_lfclkstart.write(|w| unsafe { w.bits(1) });

        while p.CLOCK.events_lfclkstarted.read().bits() == 0 {}

        /* And then set it back to 0 again, just because ?!? */
        p.CLOCK.events_lfclkstarted.write(|w| unsafe { w.bits(0) });

        defmt::info!("Welcome to the random number printer!");

        p.RTC0.prescaler.write(|w| unsafe { w.bits(1) });
        p.RTC0.evtenset.write(|w| w.tick().set_bit());
        p.RTC0.intenset.write(|w| w.tick().set_bit());
        p.RTC0.tasks_start.write(|w| unsafe { w.bits(1) });

        /* Enable error correction for better values */
        p.RNG.config.write(|w| w.dercen().enabled());

        /* Enable random number generation */
        p.RNG.tasks_start.write(|w| unsafe { w.bits(1) });

        cortex_m::interrupt::free(move |cs| {
            *RTC.borrow(cs).borrow_mut() = Some(p.RTC0);
            *RNG.borrow(cs).borrow_mut() = Some(p.RNG);
        });

        unsafe {
            pac::NVIC::unmask(pac::Interrupt::RTC0);
        }
        pac::NVIC::unpend(pac::Interrupt::RTC0);
    }

    loop {
        continue;
    }
}

// Define an exception, i.e. function to call when exception occurs. Here if our timer
// trips, we'll print some random number
#[interrupt]
fn RTC0() {
    /* Enter critical section */
    cortex_m::interrupt::free(|cs| {
        if let Some(rtc) = RTC.borrow(cs).borrow().as_ref() {
            let count = if let Some(rng) = RNG.borrow(cs).borrow().as_ref() {
                /* Let's wait until we have a new random value */
                while rng.events_valrdy.read().bits() == 0 {}

                let num = rng.value.read().bits();

                /* Clear event for next random number value */
                rng.events_valrdy.write(|w| unsafe { w.bits(0) });

                num
            } else {
                0
            };

            defmt::info!("{:?}", count);
            rtc.events_tick.write(|w| unsafe { w.bits(0) });
        }
    });
}


================================================
FILE: examples/rng-hal/Cargo.toml
================================================
[package]
name = "rng-hal-printrandserial"
version = "0.1.0"
edition = "2024"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.rand_pcg]
default-features = false
version = "0.10.2"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/rng-hal/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use core::{cell::RefCell, ops::DerefMut};

use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;

use microbit::{
    hal::{clocks, rng, rtc},
    pac::{self, interrupt},
};

use rand_pcg::{
    Pcg32,
    rand_core::{Rng, SeedableRng},
};

static RTC: Mutex<RefCell<Option<rtc::Rtc<pac::RTC0>>>> = Mutex::new(RefCell::new(None));
static RNG: Mutex<RefCell<Option<Pcg32>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    let mut cp = pac::CorePeripherals::take().unwrap();
    let p = microbit::Peripherals::take().unwrap();

    cortex_m::interrupt::free(move |cs| {
        /* Start low frequency clock */
        clocks::Clocks::new(p.CLOCK).start_lfclk();

        defmt::info!("Welcome to the random number printer!");

        /* Use hardware RNG to initialise PRNG */
        let mut rng = rng::Rng::new(p.RNG);

        let mut seed: [u8; 16] = [0; 16];

        /* Read 4 bytes of data from hardware RNG */
        rng.random(&mut seed);

        let rng = Pcg32::from_seed(seed);
        *RNG.borrow(cs).borrow_mut() = Some(rng);

        let mut rtc = rtc::Rtc::new(p.RTC0, 1).unwrap();
        rtc.enable_counter();
        rtc.enable_interrupt(rtc::RtcInterrupt::Tick, Some(&mut cp.NVIC));
        rtc.enable_event(rtc::RtcInterrupt::Tick);

        *RTC.borrow(cs).borrow_mut() = Some(rtc);

        pac::NVIC::unpend(pac::Interrupt::RTC0);
    });

    loop {
        continue;
    }
}

// Define an exception, i.e. function to call when exception occurs. Here if our timer
// trips, we'll print out a random number to the serial port
#[interrupt]
fn RTC0() {
    /* Enter critical section */
    cortex_m::interrupt::free(|cs| {
        if let (Some(rtc), &mut Some(ref mut rng)) = (
            RTC.borrow(cs).borrow().as_ref(),
            RNG.borrow(cs).borrow_mut().deref_mut(),
        ) {
            defmt::info!("{:?}", rng.next_u32());
            rtc.reset_event(rtc::RtcInterrupt::Tick);
        }
    });
}


================================================
FILE: examples/serial-direct-echo/Cargo.toml
================================================
[package]
name = "serial-direct-echo"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"

[dependencies.microbit]
path = "../../microbit"


================================================
FILE: examples/serial-direct-echo/src/main.rs
================================================
#![no_main]
#![no_std]

use panic_halt as _;

use core::str;
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    if let Some(p) = microbit::Peripherals::take() {
        /* Configure RX and TX pins accordingly */
        p.GPIO.pin_cnf[24].write(|w| w.pull().pullup().dir().output());
        p.GPIO.pin_cnf[25].write(|w| w.pull().disabled().dir().input());

        let uart0 = p.UART0;
        /* Tell UART which pins to use for sending and receiving */
        uart0.pseltxd.write(|w| unsafe { w.bits(24) });
        uart0.pselrxd.write(|w| unsafe { w.bits(25) });

        /* Set a typical baud rate of 115200 */
        uart0.baudrate.write(|w| w.baudrate().baud115200());

        /* Enable UART function */
        uart0.enable.write(|w| w.enable().enabled());

        /* Print a nice hello message */
        let _ = write_uart0(&uart0, "Please type characters to echo:\r\n");

        /* Fire up receiving task */
        uart0.tasks_startrx.write(|w| unsafe { w.bits(1) });

        /* Endless loop */
        loop {
            /* Busy wait for reception of data */
            while uart0.events_rxdrdy.read().bits() == 0 {}

            /* We're going to pick up the data soon, let's signal the buffer is already waiting for
             * more data */
            uart0.events_rxdrdy.write(|w| unsafe { w.bits(0) });

            /* Read one 8bit value */
            let c = uart0.rxd.read().bits() as u8;

            /* What comes in must go out, we don't care what it is */
            let _ = write_uart0(&uart0, unsafe { str::from_utf8_unchecked(&[c; 1]) });
        }
    }

    loop {
        continue;
    }
}

fn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Result {
    /* Start UART sender */
    uart0.tasks_starttx.write(|w| unsafe { w.bits(1) });

    for c in s.as_bytes() {
        /* Write the current character to the output register */
        uart0.txd.write(|w| unsafe { w.bits(u32::from(*c)) });

        /* Wait until the UART is clear to send */
        while uart0.events_txdrdy.read().bits() == 0 {}

        /* And then reset it for the next round */
        uart0.events_txdrdy.write(|w| unsafe { w.bits(0) });
    }

    /* Stop UART sender */
    uart0.tasks_stoptx.write(|w| unsafe { w.bits(1) });
    Ok(())
}


================================================
FILE: examples/serial-direct-helloworld/Cargo.toml
================================================
[package]
name = "serial-direct-helloworld"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"

[dependencies.microbit]
path = "../../microbit"


================================================
FILE: examples/serial-direct-helloworld/src/main.rs
================================================
#![no_main]
#![no_std]

use panic_halt as _;

use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    if let Some(p) = microbit::Peripherals::take() {
        p.GPIO.pin_cnf[24].write(|w| w.pull().pullup().dir().output());
        p.GPIO.pin_cnf[25].write(|w| w.pull().disabled().dir().input());

        p.UART0.pseltxd.write(|w| unsafe { w.bits(24) });
        p.UART0.pselrxd.write(|w| unsafe { w.bits(25) });

        p.UART0.baudrate.write(|w| w.baudrate().baud115200());
        p.UART0.enable.write(|w| w.enable().enabled());

        let _ = write_uart0(&p.UART0, "Hello World!\n");
    }

    loop {
        continue;
    }
}

fn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Result {
    uart0.tasks_starttx.write(|w| unsafe { w.bits(1) });
    for c in s.as_bytes() {
        /* Write the current character to the output register */
        uart0.txd.write(|w| unsafe { w.bits(u32::from(*c)) });

        /* Wait until the UART is clear to send */
        while uart0.events_txdrdy.read().bits() == 0 {}

        /* And then set it back to 0 again, just because ?!? */
        uart0.events_txdrdy.write(|w| unsafe { w.bits(0) });
    }
    uart0.tasks_stoptx.write(|w| unsafe { w.bits(1) });
    Ok(())
}


================================================
FILE: examples/serial-hal-blocking-echo/Cargo.toml
================================================
[package]
name = "serial-hal-blocking-echo"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m-rt = "0.7"
panic-halt = "1.0.0"
defmt-rtt = "1.1"
nb = "1.1.0"
embedded-hal = "1.0.0"
embedded-io = "0.7.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]


================================================
FILE: examples/serial-hal-blocking-echo/src/main.rs
================================================
#![no_main]
#![no_std]

use panic_halt as _;

use core::fmt::Write;
use cortex_m_rt::entry;
use embedded_io::Read;

#[cfg(feature = "v1")]
use microbit::{
    hal::uart,
    hal::uart::{Baudrate, Parity},
};

#[cfg(feature = "v2")]
use microbit::{
    hal::uarte,
    hal::uarte::{Baudrate, Parity},
};

#[cfg(feature = "v2")]
mod serial_setup;
#[cfg(feature = "v2")]
use serial_setup::UartePort;

#[entry]
fn main() -> ! {
    let board = microbit::Board::take().unwrap();

    #[cfg(feature = "v1")]
    let mut serial = {
        uart::Uart::new(
            board.UART0,
            board.uart.into(),
            Parity::EXCLUDED,
            Baudrate::BAUD115200,
        )
    };

    #[cfg(feature = "v2")]
    let mut serial = {
        let serial = uarte::Uarte::new(
            board.UARTE0,
            board.uart.into(),
            Parity::EXCLUDED,
            Baudrate::BAUD115200,
        );
        UartePort::new(serial)
    };

    loop {
        write!(serial, "Hello World:\r\n").unwrap();
        let mut input = [0];
        serial.read_exact(&mut input).unwrap();
        write!(serial, "You said: {}\r\n", input[0] as char).unwrap();
    }
}


================================================
FILE: examples/serial-hal-blocking-echo/src/serial_setup.rs
================================================
use core::{fmt, ptr::addr_of_mut};
use microbit::hal::uarte::{Error, Instance, Uarte, UarteRx, UarteTx};

static mut TX_BUF: [u8; 1] = [0; 1];
static mut RX_BUF: [u8; 1] = [0; 1];

pub struct UartePort<T: Instance>(UarteTx<T>, UarteRx<T>);

impl<T: Instance> UartePort<T> {
    pub fn new(serial: Uarte<T>) -> UartePort<T> {
        let (tx, rx) = serial
            .split(unsafe { addr_of_mut!(TX_BUF).as_mut().unwrap() }, unsafe {
                addr_of_mut!(RX_BUF).as_mut().unwrap()
            })
            .unwrap();
        UartePort(tx, rx)
    }
}

impl<T: Instance> fmt::Write for UartePort<T> {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.0.write_str(s)
    }
}

impl<T: Instance> embedded_io::ErrorType for UartePort<T> {
    type Error = Error;
}

impl<T: Instance> embedded_io::Write for UartePort<T> {
    fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {
        self.0.write(buffer)
    }

    fn flush(&mut self) -> Result<(), Self::Error> {
        self.0.flush()
    }
}

impl<T: Instance> embedded_io::Read for UartePort<T> {
    fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
        self.1.read(buffer)
    }
}


================================================
FILE: examples/servo/Cargo.toml
================================================
[package]
name = "servo"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit]
path = "../../microbit"
optional = true

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v1 = ["microbit"]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/servo/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;

use microbit::{
    board::Board,
    hal::{
        gpio::Level,
        gpiote::*,
        pac::{self, interrupt, TIMER0},
        ppi::{self, ConfigurablePpi, Ppi},
    },
};

static SERVO_TIMER: Mutex<RefCell<Option<TIMER0>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let gpiote = Gpiote::new(board.GPIOTE);
        // Servo output pins
        let servopin1 = board.edge.e01.into_push_pull_output(Level::Low).degrade(); // PAD2
        let servopin2 = board.edge.e02.into_push_pull_output(Level::Low).degrade(); // PAD3

        // Output channel for Servo 1
        gpiote
            .channel0()
            .output_pin(servopin1)
            .task_out_polarity(TaskOutPolarity::Toggle)
            .init_low();
        gpiote.channel0().task_out().write(|w| unsafe { w.bits(1) });
        // Output channel for Servo 2
        gpiote
            .channel1()
            .output_pin(servopin2)
            .task_out_polarity(TaskOutPolarity::Toggle)
            .init_low();
        gpiote.channel1().task_out().write(|w| unsafe { w.bits(1) });

        let ppi_channels = ppi::Parts::new(board.PPI);
        // Set both servo outputs high form Timer0 CC[0]
        // Set each servo output low from the respective Timer0 CC[1] and CC[2]
        // Each timer can run 3 Servos
        let mut ppi0 = ppi_channels.ppi0;
        ppi0.set_task_endpoint(gpiote.channel0().task_out());
        ppi0.set_event_endpoint(&board.TIMER0.events_compare[0]);
        ppi0.enable();
        let mut ppi1 = ppi_channels.ppi1;
        ppi1.set_task_endpoint(gpiote.channel0().task_out());
        ppi1.set_event_endpoint(&board.TIMER0.events_compare[1]);
        ppi1.enable();
        let mut ppi2 = ppi_channels.ppi2;
        ppi2.set_task_endpoint(gpiote.channel1().task_out());
        ppi2.set_event_endpoint(&board.TIMER0.events_compare[0]);
        ppi2.enable();
        let mut ppi3 = ppi_channels.ppi3;
        ppi3.set_task_endpoint(gpiote.channel1().task_out());
        ppi3.set_event_endpoint(&board.TIMER0.events_compare[2]);
        ppi3.enable();

        // The Timer PAC is used directly as the HAL does not give full access to all registers
        board.TIMER0.mode.write(|w| unsafe { w.bits(0) });
        board.TIMER0.bitmode.write(|w| unsafe { w.bits(0) });
        // CC[0] every 20 ms (50 Hz)
        board.TIMER0.cc[0].write(|w| unsafe { w.bits(20000) });
        board.TIMER0.shorts.write(|w| unsafe { w.bits(1) });
        // Servo duty cycle is from 0.5 ms to 2.5 ms with 1.5 ms for center position
        board.TIMER0.cc[1].write(|w| unsafe { w.bits(1500) });
        board.TIMER0.cc[2].write(|w| unsafe { w.bits(1500) });
        board.TIMER0.tasks_start.write(|w| unsafe { w.bits(1) });
        // Timer0 interrupt on CC[0]
        board.TIMER0.intenset.write(|w| unsafe { w.bits(1 << 16) });

        cortex_m::interrupt::free(move |cs| {
            *SERVO_TIMER.borrow(cs).borrow_mut() = Some(board.TIMER0);
        });
        unsafe {
            pac::NVIC::unmask(pac::Interrupt::TIMER0);
        }

        loop {}
    }
    panic!("End");
}

#[interrupt]
fn TIMER0() {
    // Change Servo position at the start of the duty cycle. Then there is no race condition
    // between changing the duty cycle and a CC event.
    static mut SPEED: i32 = 1500;
    static mut DIRECTION: i32 = 1;
    match SPEED {
        i32::MIN..=500 => *DIRECTION = 1,
        2500..=i32::MAX => *DIRECTION = -1,
        _ => {}
    }
    *SPEED += *DIRECTION;
    cortex_m::interrupt::free(|cs| {
        //    if let Some(cc_value) = CC_VALUE.borrow(cs).borrow().as_ref() {
        if let Some(timer) = SERVO_TIMER.borrow(cs).borrow_mut().as_mut() {
            //timer.cc[1].write(|w|unsafe { w.bits(u32::try_from(*cc_value).unwrap_or(1500)) });
            let set_speed = u32::try_from(*SPEED).unwrap_or(1500);
            timer.cc[1].write(|w| unsafe { w.bits(set_speed) });
            timer.cc[2].write(|w| unsafe { w.bits(set_speed) });
            timer.events_compare[0].write(|w| unsafe { w.bits(0) });
        }
        //}
    });
}


================================================
FILE: examples/v2-microphone/Cargo.toml
================================================
[package]
name = "v2-microphone"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
embedded-hal = "1.0.0"
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1.0"
defmt = "1.0.1"

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v2 = ["microbit-v2"]

default = ["defmt-default"]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/v2-microphone/src/main.rs
================================================
#![no_std]
#![no_main]

use defmt_rtt as _;
use panic_halt as _;

use cortex_m_rt::entry;
use microbit::{
    board::Board,
    display::blocking::Display,
    hal::{
        gpio::{Level, OpenDrainConfig},
        saadc::SaadcConfig,
        Saadc, Timer,
    },
};

#[entry]
fn main() -> ! {
    if let Some(board) = Board::take() {
        let mut timer = Timer::new(board.TIMER0);
        let mut display = Display::new(board.display_pins);

        // initialize adc
        let saadc_config = SaadcConfig::default();
        let mut saadc = Saadc::new(board.ADC, saadc_config);
        let mut mic_in = board.microphone_pins.mic_in.into_floating_input();

        // enable microphone
        board
            .microphone_pins
            .mic_run
            .into_open_drain_output(OpenDrainConfig::Disconnect0HighDrive1, Level::High);

        let mut count: u64 = 0;
        let mut sum: u64 = 0;
        let mut max_value: u16 = 0;
        loop {
            let mic_value = saadc
                .read_channel(&mut mic_in)
                .expect("could not read value of microphone") as u16;

            // Smoothen the signal as audio comes in waves
            max_value = max_value.max(mic_value);
            sum += mic_value as u64;
            count += 1;

            if count % 100 == 0 {
                let avg = (sum / count) as u16;
                let image = [
                    [if max_value > avg + 100 { 1 } else { 0 }; 5],
                    [if max_value > avg + 80 { 1 } else { 0 }; 5],
                    [if max_value > avg + 60 { 1 } else { 0 }; 5],
                    [if max_value > avg + 40 { 1 } else { 0 }; 5],
                    [if max_value > avg + 20 { 1 } else { 0 }; 5],
                ];
                display.show(&mut timer, image, 10);
                max_value = 0;
            }
        }
    }

    panic!("End");
}


================================================
FILE: examples/v2-speaker/Cargo.toml
================================================
[package]
name = "v2-speaker"
version = "0.1.0"
edition = "2018"

[dependencies]
cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] }
embedded-hal = "1.0.0"
cortex-m-rt = "0.7.5"
panic-halt = "1.0.0"
defmt-rtt = "1.1"
defmt = "1.0.1"

[dependencies.microbit-v2]
path = "../../microbit-v2"
optional = true

[features]
v2 = ["microbit-v2"]

default = [
  "defmt-default",
]

# do NOT modify these features
defmt-default = []
defmt-trace = []
defmt-debug = []
defmt-info = []
defmt-warn = []
defmt-error = []


================================================
FILE: examples/v2-speaker/src/main.rs
================================================
#![no_main]
#![no_std]

use defmt_rtt as _;
use panic_halt as _;

use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use embedded_hal::digital::OutputPin;
use microbit::{
    hal::{
        clocks::Clocks,
        gpio, pwm,
        rtc::{Rtc, RtcInterrupt},
        time::Hertz,
    },
    pac::{self, interrupt},
    Board,
};

static RTC: Mutex<RefCell<Option<Rtc<pac::RTC0>>>> = Mutex::new(RefCell::new(None));
static SPEAKER: Mutex<RefCell<Option<pwm::Pwm<pac::PWM0>>>> = Mutex::new(RefCell::new(None));

#[entry]
fn main() -> ! {
    if let Some(mut board) = Board::take() {
        cortex_m::interrupt::free(move |cs| {
            // NB: The LF CLK pin is used by the speaker
            let _clocks = Clocks::new(board.CLOCK)
                .enable_ext_hfosc()
                .set_lfclk_src_synth()
                .start_lfclk();

            let mut rtc = Rtc::new(board.RTC0, 511).unwrap();
            rtc.enable_counter();
            rtc.enable_interrupt(RtcInterrupt::Tick, Some(&mut board.NVIC));
            rtc.enable_event(RtcInterrupt::Tick);

            *RTC.borrow(cs).borrow_mut() = Some(rtc);

            let mut speaker_pin = board.speaker_pin.into_push_pull_output(gpio::Level::High);
            let _ = speaker_pin.set_low();

            // Use the PWM peripheral to generate a waveform for the speaker
            let speaker = pwm::Pwm::new(board.PWM0);
            speaker
                // output the waveform on the speaker pin
                .set_output_pin(pwm::Channel::C0, speaker_pin.degrade())
                // Use prescale by 16 to achive darker sounds
                .set_prescaler(pwm::Prescaler::Div16)
                // Initial frequency
                .set_period(Hertz(1u32))
                // Configure for up and down counter mode
                .set_counter_mode(pwm::CounterMode::UpAndDown)
                // Set maximum duty cycle
                .set_max_duty(32767)
                // enable PWM
                .enable();

            speaker
                .set_seq_refresh(pwm::Seq::Seq0, 0)
                .set_seq_end_delay(pwm::Seq::Seq0, 0);

            // Configure 50% duty cycle
            let max_duty = speaker.max_duty();
            speaker.set_duty_on_common(max_duty / 2);

            *SPEAKER.borrow(cs).borrow_mut() = Some(speaker);

            // Configure RTC interrupt
            unsafe {
                pac::NVIC::unmask(pac::Interrupt::RTC0);
            }
            pac::NVIC::unpend(pac::Interrupt::RTC0);
        });
    }

    loop {
        continue;
    }
}

const STOP_FREQUENCY: u32 = 500;

// RTC interrupt, exectued for each RTC tick
#[interrupt]
fn RTC0() {
    static mut FREQUENCY: u32 = 1;
    /* Enter critical section */
    cortex_m::interrupt::free(|cs| {
        /* Borrow devices */
        if let (Some(speaker), Some(rtc)) = (
            SPEAKER.borrow(cs).borrow().as_ref(),
            RTC.borrow(cs).borrow().as_ref(),
        ) {
            if *FREQUENCY < STOP_FREQUENCY {
                // Configure the new frequency, must not be zero.
                // Will change the max_duty
                speaker.set_period(Hertz(*FREQUENCY));
            } else {
                // Continue at frequency
                speaker.set_period(Hertz(STOP_FREQUENCY));
            }
            // Restart the PWM at 50% duty cycle
            let max_duty = speaker.max_duty();
            speaker.set_duty_on_common(max_duty / 2);
            if *FREQUENCY >= STOP_FREQUENCY + 250 {
                defmt::info!("Fin");
                // Stop speaker and RTC
                speaker.disable();
                rtc.disable_counter();
            };
            // Clear the RTC interrupt
            rtc.reset_event(RtcInterrupt::Tick);
        }
    });
    // Increase the frequency
    *FREQUENCY += 1;
}


================================================
FILE: memory.x
================================================
MEMORY
{
  /* NOTE K = KiBi = 1024 bytes */
  FLASH : ORIGIN = 0x00000000, LENGTH = 256K
  RAM : ORIGIN = 0x20000000, LENGTH = 16K
}


================================================
FILE: microbit/Cargo.toml
================================================
[package]
name = "microbit"
version = "0.16.0"
description = "Board support crate for the BBC Micro:bit V1"
edition = "2018"
readme = "../README.md"
rust-version = "1.79.0"

repository = "https://github.com/nrf-rs/microbit"
authors = [
  "Daniel Egger <daniel@eggers-club.de>",
  "Michael Droogleever <droogmic@gmail.com>",
  "Rob Young <rob@robyoung.digital>",
]
categories = ["hardware-support", "embedded", "no-std"]
keywords = ["arm", "cortex-m", "nrf", "hal"]
license = "0BSD"

[dependencies]

[dependencies.microbit-common]
path = "../microbit-common"
features = ["v1"]
version = "=0.16.0"

[features]
embedded-hal-02 = ["microbit-common/embedded-hal-02"]


================================================
FILE: microbit/src/lib.rs
================================================
//! microbit contains everything required to get started with the use of Rust
//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)
//! microcontroller board.
//!
//! This crate is for the original micro:bit (V1) pictured below on the left. If
//! your micro:bit looks like the one on the right you need the
//! [microbit-v2](https://crates.io/crates/microbit-v2) crate.
//!
//! [<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)
//! [<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)
#![doc(html_root_url = "https://docs.rs/microbit/0.16.0")]
#![no_std]
#![deny(missing_docs)]
#![allow(non_camel_case_types)]

pub use microbit_common::*;


================================================
FILE: microbit-common/Cargo.toml
================================================
[package]
name = "microbit-common"
version = "0.16.0"
description = "Implementation details for the BBC Micro:bit board support crates"
edition = "2018"
readme = "../README.md"
rust-version = "1.79.0"

repository = "https://github.com/nrf-rs/microbit"
authors = [
  "Daniel Egger <daniel@eggers-club.de>",
  "Michael Droogleever <droogmic@gmail.com>",
  "Rob Young <rob@robyoung.digital>",
]
categories = ["hardware-support", "embedded", "no-std"]
keywords = ["arm", "cortex-m", "nrf", "hal"]
license = "0BSD"

[dependencies]
tiny-led-matrix = "1.0.2"
embedded-hal = "1.0.0"

[dependencies.nrf51-hal]
optional = true
version = "0.19.0"
default-features = false
features = ["rt", "xxAB-package"]

[dependencies.nrf52833-hal]
optional = true
version = "0.19.0"
default-features = false
features = ["rt"]

[features]
doc = []
v1 = ["nrf51-hal"]
v2 = ["nrf52833-hal"]
embedded-hal-02 = [
  "nrf51-hal?/embedded-hal-02",
  "nrf52833-hal?/embedded-hal-02",
]

[package.metadata.docs.rs]
features = ["v2"]
default-target = "thumbv7em-none-eabihf"


================================================
FILE: microbit-common/src/adc.rs
================================================
//! ADC
#[cfg(feature = "v1")]
pub use crate::v1::adc::*;

#[cfg(feature = "v2")]
pub use crate::v2::adc::*;


================================================
FILE: microbit-common/src/board.rs
================================================
//! Main Board
#[cfg(feature = "v1")]
pub use crate::v1::board::*;

#[cfg(feature = "v2")]
pub use crate::v2::board::*;


================================================
FILE: microbit-common/src/display/blocking.rs
================================================
//! Blocking support for the 5x5 LED display.
//!
//! This module provides a simple blocking interface
//! to the on board 5x5 LED display. If you need a more sophisticated
//! or non-blocking interface use the [`display::nonblocking`](crate::display::nonblocking) module.
//!
//! # Example
//!
//! ```no_run
//! # use microbit_common as microbit;
//! # use microbit::{
//! #     Board,
//! #     hal,
//! #     display::blocking::Display,
//! # };
//! # use embedded_hal::delay::DelayNs;
//! // take the board
//! let board = Board::take().unwrap();
//! // make a timer
//! let mut timer = hal::Timer::new(board.TIMER0);
//! // create the Display
//! let mut display = Display::new(board.display_pins);
//! // and light up some LEDs
//! let heart = [
//!     [0, 1, 0, 1, 0],
//!     [1, 0, 1, 0, 1],
//!     [1, 0, 0, 0, 1],
//!     [0, 1, 0, 1, 0],
//!     [0, 0, 1, 0, 0],
//! ];
//! loop {
//!     display.show(&mut timer, heart, 1000);
//!     display.clear();
//!     timer.delay_ms(250);
//! }
//! ```
//!
//! The coordiante system is oriented so the 'bottom' (x,4) row is the edge with the edge
//! connector. That means that
//!
//! ```no_run
//! # use microbit_common as microbit;
//! # use microbit::{
//! #     Board,
//! #     hal,
//! #     display::blocking::Display,
//! # };
//! # let board = Board::take().unwrap();
//! # let mut timer = hal::Timer::new(board.TIMER0);
//! # let mut display = Display::new(board.display_pins);
//! display.show(
//!    &mut timer,
//!    [
//!        [0, 0, 1, 0, 0],
//!        [0, 1, 1, 1, 0],
//!        [1, 0, 1, 0, 1],
//!        [0, 0, 1, 0, 0],
//!        [0, 0, 1, 0, 0],
//!    ],
//!    1000,
//!);
//! ```
//! Will display an arrow pointing towards the boards usb port.
//!
//! For a working example [`examples/display-blocking`](https://github.com/nrf-rs/microbit/tree/main/examples/display-blocking)
use crate::gpio::{DisplayPins, NUM_COLS, NUM_ROWS};
use crate::hal::gpio::{Output, Pin, PushPull};
use embedded_hal::{delay::DelayNs, digital::OutputPin};

#[allow(clippy::upper_case_acronyms)]
pub(crate) type LED = Pin<Output<PushPull>>;

const DEFAULT_DELAY_MS: u32 = 2;
#[cfg(feature = "v1")]
const LED_LAYOUT: [[(usize, usize); 5]; 5] = [
    [(0, 0), (1, 3), (0, 1), (1, 4), (0, 2)],
    [(2, 3), (2, 4), (2, 5), (2, 6), (2, 7)],
    [(1, 1), (0, 8), (1, 2), (2, 8), (1, 0)],
    [(0, 7), (0, 6), (0, 5), (0, 4), (0, 3)],
    [(2, 2), (1, 6), (2, 0), (1, 5), (2, 1)],
];

/// Blocking interface to the on board LED display
pub struct Display {
    delay_ms: u32,
    rows: [LED; NUM_ROWS],
    cols: [LED; NUM_COLS],
}

impl Display {
    /// Create and initialise the display driver
    ///
    /// The [`display_pins!`](crate::display_pins) macro can be used
    /// to create [`DisplayPins`].
    pub fn new(pins: DisplayPins) -> Self {
        let (cols, rows) = pins.degrade();
        Display {
            delay_ms: DEFAULT_DELAY_MS,
            rows,
            cols,
        }
    }

    /// Clear the display
    pub fn clear(&mut self) {
        for row in &mut self.rows {
            row.set_low().ok();
        }
        for col in &mut self.cols {
            col.set_high().ok();
        }
    }

    /// Set delay, time spent on each matrix row, in ms
    pub fn set_delay_ms(&mut self, delay_ms: u32) {
        self.delay_ms = delay_ms;
    }

    /// Set refresh rate, time for matrix scan
    pub fn set_refresh_rate(&mut self, freq_hz: u32) {
        self.delay_ms = 1000 / freq_hz / (NUM_ROWS as u32);
    }

    /// Convert 5x5 image to 3x9 matrix
    ///
    /// The pins are represented as a [3x9 matrix on the micro:bit
    /// V1](https://tech.microbit.org/hardware/1-5-revision/#display).
    #[cfg(feature = "v1")]
    fn image2matrix(led_image: [[u8; 5]; 5]) -> [[u8; 9]; 3] {
        let mut led_matrix: [[u8; 9]; 3] = [[0; 9]; 3];
        for (led_image_row, layout_row) in led_image.iter().zip(LED_LAYOUT.iter()) {
            for (led_image_val, layout_loc) in led_image_row.iter().zip(layout_row) {
                led_matrix[layout_loc.0][layout_loc.1] = *led_image_val;
            }
        }
        led_matrix
    }

    /// Display 5x5 image for a given duration
    pub fn show<D: DelayNs>(&mut self, delay: &mut D, led_display: [[u8; 5]; 5], duration_ms: u32) {
        #[cfg(feature = "v1")]
        {
            let led_matrix = Display::image2matrix(led_display);
            self.show_inner(delay, led_matrix, duration_ms);
        }
        #[cfg(feature = "v2")]
        self.show_inner(delay, led_display, duration_ms);
    }

    /// Display matrix image for a given duration (3x9 for V1 micro:bit)
    ///
    /// The pins are represented as a [3x9 matrix on the micro:bit
    /// V1](https://tech.microbit.org/hardware/1-5-revision/#display).
    fn show_inner<D: DelayNs>(
        &mut self,
        delay: &mut D,
        led_matrix: [[u8; NUM_COLS]; NUM_ROWS],
        duration_ms: u32,
    ) {
        // TODO: something more intelligent with timers
        let loops = duration_ms / (self.rows.len() as u32 * self.delay_ms);
        for _ in 0..loops {
            for (row_line, led_matrix_row) in self.rows.iter_mut().zip(led_matrix.iter()) {
                row_line.set_high().ok();
                for (col_line, led_matrix_val) in self.cols.iter_mut().zip(led_matrix_row.iter()) {
                    // TODO : use value to set brightness
                    if *led_matrix_val > 0 {
                        col_line.set_low().ok();
                    }
                }
                delay.delay_us(self.delay_ms * 1000);
                for col_line in &mut self.cols {
                    col_line.set_high().ok();
                }
                row_line.set_low().ok();
            }
        }
    }
}


================================================
FILE: microbit-common/src/display/mod.rs
================================================
//! Support for the 5x5 LED display.
//!
//! There are two APIs for controlling the LED display, [`blocking`] and [`nonblocking`].
//! The `blocking` API is the simplest to get started with.
pub mod blocking;
pub mod nonblocking;


================================================
FILE: microbit-common/src/display/nonblocking/control.rs
================================================
//! Implementation of [`DisplayControl`] for the micro:bit's GPIO peripheral.
//!
//! This controls the micro:bit's 5×5 LED display.
//!
//! [`DisplayControl`]: tiny_led_matrix::DisplayControl

use tiny_led_matrix::DisplayControl;

use crate::{
    gpio::{NUM_COLS, NUM_ROWS},
    pac,
};

const fn pin_bits(pins: &[usize]) -> u32 {
    let mut i: usize = 0;
    let mut bits: u32 = 0;
    while i < pins.len() {
        bits |= 1 << pins[i];
        i += 1;
    }
    bits
}

#[cfg(feature = "v1")]
mod pins {
    use super::{NUM_COLS, NUM_ROWS};
    pub(super) const P0_COLS: [usize; NUM_COLS] = [4, 5, 6, 7, 8, 9, 10, 11, 12];
    pub(super) const P0_ROWS: [usize; NUM_ROWS] = [13, 14, 15];
}

#[cfg(feature = "v2")]
mod pins {
    use super::{NUM_COLS, NUM_ROWS};
    pub(super) const P0_COLS: [usize; NUM_COLS - 1] = [28, 11, 31, 30];
    pub(super) const P1_COLS: [usize; 1] = [5];

    pub(super) const P0_ROWS: [usize; NUM_ROWS] = [21, 22, 15, 24, 19];
}

const P0_COL_BITS: u32 = pin_bits(&pins::P0_COLS);
#[cfg(feature = "v2")]
const P1_COL_BITS: u32 = pin_bits(&pins::P1_COLS);

const P0_ROW_BITS: u32 = pin_bits(&pins::P0_ROWS);

#[cfg(feature = "v1")]
type P0 = pac::GPIO;

#[cfg(feature = "v2")]
type P0 = pac::P0;

#[cfg(feature = "v2")]
type P1 = pac::P1;

/// This implements the `DisplayControl` trait.
///
/// [`DisplayControl`]: tiny_led_matrix::DisplayControl
pub(crate) struct MicrobitGpio;

/// Returns the GPIO pin numbers corresponding to the columns in a Column
fn column_pins(mut cols: u32, px_cols: &[usize]) -> u32 {
    let mut result = 0u32;
    for &pin in px_cols.iter() {
        result |= (cols & 1) << pin;
        cols >>= 1;
    }
    result
}

#[cfg(feature = "v1")]
fn split_cols(cols: u32) -> (u32, u32) {
    (cols, 0u32)
}

#[cfg(feature = "v2")]
fn split_cols(cols: u32) -> (u32, u32) {
    // get all except col 2 (4th from least significant)
    let p0_cols = ((cols & 0b10000) >> 1) | (0b00111 & cols);
    // get col 4 (4th from least significant)
    let p1_cols = (cols & 0b01000) >> 3;
    (p0_cols, p1_cols)
}

/// Implementation of [`DisplayControl`] for the micro:bit's GPIO peripheral.
///
/// This controls the micro:bit's 5×5 LED display.
///
/// The `initialise_for display` implementation assumes the port is in the
/// state it would have after system reset.
///
/// [`DisplayControl`]: tiny_led_matrix::DisplayControl
impl DisplayControl for MicrobitGpio {
    fn initialise_for_display(&mut self) {
        unsafe {
            let p0 = &*P0::ptr();
            for ii in pins::P0_COLS.iter() {
                p0.pin_cnf[*ii].write(|w| w.dir().output());
            }
            for ii in pins::P0_ROWS.iter() {
                p0.pin_cnf[*ii].write(|w| w.dir().output());
            }

            // Set all p0 cols high.
            p0.outset
                .write(|w| w.bits(pins::P0_COLS.iter().map(|pin| 1 << pin).sum()));

            #[cfg(feature = "v2")]
            {
                let p1 = &*P1::ptr();
                for ii in pins::P1_COLS.iter() {
                    p1.pin_cnf[*ii].write(|w| w.dir().output());
                }
                // Set all p1 cols high.
                p1.outset
                    .write(|w| w.bits(pins::P1_COLS.iter().map(|pin| 1 << pin).sum()));
            }
        }
    }

    fn display_row_leds(&mut self, row: usize, cols: u32) {
        unsafe {
            let p0 = &*P0::ptr();

            #[allow(unused_variables)]
            let (p0cols, p1cols) = split_cols(cols);

            // To light an LED, we set the row bit and clear the col bit.
            let rows_to_set = 1 << pins::P0_ROWS[row];
            let rows_to_clear = P0_ROW_BITS ^ rows_to_set;

            #[cfg(feature = "v1")]
            {
                let cols_to_clear = column_pins(p0cols, &pins::P0_COLS);
                let cols_to_set = P0_COL_BITS ^ cols_to_clear;
                p0.outset.write(|w| w.bits(rows_to_set | cols_to_set));
                p0.outclr.write(|w| w.bits(rows_to_clear | cols_to_clear));
            }

            #[cfg(feature = "v2")]
            {
                let p1 = &*P1::ptr();
                let p0_cols_to_clear = column_pins(p0cols, &pins::P0_COLS);
                let p0_cols_to_set = P0_COL_BITS ^ p0_cols_to_clear;
                let p1_cols_to_clear = column_pins(p1cols, &pins::P1_COLS);
                let p1_cols_to_set = P1_COL_BITS ^ p1_cols_to_clear;
                // We do the row-clearing write first and the row-setting write last, so that
                // intermediate states never light LEDs which aren't lit in either the old or new state.
                p0.outclr
                    .write(|w| w.bits(rows_to_clear | p0_cols_to_clear));
                p1.outset.write(|w| w.bits(p1_cols_to_set));
                p1.outclr.write(|w| w.bits(p1_cols_to_clear));
                p0.outset.write(|w| w.bits(rows_to_set | p0_cols_to_set));
            }
        }
    }

    fn light_current_row_leds(&mut self, cols: u32) {
        unsafe {
            #[allow(unused_variables)]
            let (p0cols, p1cols) = split_cols(cols);
            let p0 = &*P0::ptr();
            p0.outclr
                .write(|w| w.bits(column_pins(p0cols, &pins::P0_COLS)));

            #[cfg(feature = "v2")]
            {
                let p1 = &*P1::ptr();
                p1.outclr
                    .write(|w| w.bits(column_pins(p1cols, &pins::P1_COLS)));
            }
        }
    }
}


================================================
FILE: microbit-common/src/display/nonblocking/image.rs
================================================
//! Static 5×5 greyscale and black-and-white images.

use tiny_led_matrix::{Render, MAX_BRIGHTNESS};

/// A 5×5 image supporting the full range of brightnesses for each LED.
///
/// Uses 25 bytes of storage.
#[derive(Copy, Clone, Debug)]
pub struct GreyscaleImage([[u8; 5]; 5]);

impl GreyscaleImage {
    /// Constructs a GreyscaleImage from an array of brightnesses.
    ///
    /// The data should be an array of 5 rows (top first), each of which is an
    /// array of 5 brightness values (left first).
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use microbit_common as microbit;
    /// # use microbit::display::nonblocking::GreyscaleImage;
    /// const GREY_HEART: GreyscaleImage = GreyscaleImage::new(&[
    ///     [0, 9, 0, 9, 0],
    ///     [9, 5, 9, 5, 9],
    ///     [9, 5, 5, 5, 9],
    ///     [0, 9, 5, 9, 0],
    ///     [0, 0, 9, 0, 0],
    /// ]);
    /// ```
    pub const fn new(data: &[[u8; 5]; 5]) -> GreyscaleImage {
        GreyscaleImage(*data)
    }

    /// Construct a GreyscaleImage with all LEDs turned off.
    pub const fn blank() -> GreyscaleImage {
        GreyscaleImage([[0; 5]; 5])
    }
}

impl Render for GreyscaleImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        self.0[y][x]
    }
}

impl Render for &GreyscaleImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        GreyscaleImage::brightness_at(self, x, y)
    }
}

/// A 5×5 image supporting only two levels of brightness (on and off).
///
/// Uses 5 bytes of storage.
///
/// For display, each pixel is treated as having brightness either 0 or
/// MAX_BRIGHTNESS.
#[derive(Copy, Clone, Debug)]
pub struct BitImage([u8; 5]);

impl BitImage {
    /// Constructs a BitImage from an array of brightnesses.
    ///
    /// The data should be an array of 5 rows (top first), each of which is an
    /// array of 5 values (left first). Each value should be either 0 or 1.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use microbit_common as microbit;
    /// # use microbit::display::nonblocking::BitImage;
    /// const HEART: BitImage = BitImage::new(&[
    ///     [0, 1, 0, 1, 0],
    ///     [1, 0, 1, 0, 1],
    ///     [1, 0, 0, 0, 1],
    ///     [0, 1, 0, 1, 0],
    ///     [0, 0, 1, 0, 0],
    /// ]);
    /// ```
    pub const fn new(im: &[[u8; 5]; 5]) -> BitImage {
        // FIXME: can we reject values other than 0 or 1?
        const fn row_byte(row: [u8; 5]) -> u8 {
            row[0] | (row[1] << 1) | (row[2] << 2) | (row[3] << 3) | (row[4] << 4)
        }
        BitImage([
            row_byte(im[0]),
            row_byte(im[1]),
            row_byte(im[2]),
            row_byte(im[3]),
            row_byte(im[4]),
        ])
    }

    /// Returns a new blank BitImage.
    ///
    /// All pixel values are 0.
    pub const fn blank() -> BitImage {
        BitImage([0; 5])
    }
}

impl Render for BitImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        let rowdata = self.0[y];
        if rowdata & (1 << x) != 0 {
            MAX_BRIGHTNESS
        } else {
            0
        }
    }
}

impl Render for &BitImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        BitImage::brightness_at(self, x, y)
    }
}


================================================
FILE: microbit-common/src/display/nonblocking/matrix.rs
================================================
//! Implementation of [`Matrix`] and [`Frame`] for the micro:bit's LED display.
//!
//! This module describes the correspondence between the visible layout of
//! micro:bit's LEDs and the pins controlling them.
//!
//! [`Matrix`]: tiny_led_matrix::Matrix
//! [`Frame`]: tiny_led_matrix::Frame

use crate::gpio::{NUM_COLS, NUM_ROWS};
use tiny_led_matrix::{Frame, Matrix, RowPlan};

/// Implementation of [`Matrix`] for the microbit's LED display.
///
/// [`Matrix`]: tiny_led_matrix::Matrix
pub struct MicrobitMatrix();

/// Gives the LED (x, y) coordinates for a given pin row and column.
/// The origin is in the top-left.
#[cfg(feature = "v1")]
const MICROBIT_LED_LAYOUT: [[Option<(usize, usize)>; 3]; 9] = [
    [Some((0, 0)), Some((4, 2)), Some((2, 4))],
    [Some((2, 0)), Some((0, 2)), Some((4, 4))],
    [Some((4, 0)), Some((2, 2)), Some((0, 4))],
    [Some((4, 3)), Some((1, 0)), Some((0, 1))],
    [Some((3, 3)), Some((3, 0)), Some((1, 1))],
    [Some((2, 3)), Some((3, 4)), Some((2, 1))],
    [Some((1, 3)), Some((1, 4)), Some((3, 1))],
    [Some((0, 3)), None, Some((4, 1))],
    [Some((1, 2)), None, Some((3, 2))],
];

impl Matrix for MicrobitMatrix {
    /// The number of pins connected to LED columns (3).
    const MATRIX_COLS: usize = NUM_COLS;
    /// The number of pins connected to LED rows (9).
    const MATRIX_ROWS: usize = NUM_ROWS;
    /// The number of visible LED columns (5).
    const IMAGE_COLS: usize = 5;
    /// The number of visible LED rows (5).
    const IMAGE_ROWS: usize = 5;

    #[cfg(feature = "v1")]
    fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {
        MICROBIT_LED_LAYOUT[col][row]
    }

    #[cfg(feature = "v2")]
    fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {
        Some((col, row))
    }
}

/// A 'Compiled' representation of a 5×5 image to be displayed.
///
/// Use the [`.set()`](`Frame::set`) method to store an image (something
/// implementing [`Render`]) in the frame.
///
/// Note you'll have to `use microbit::display::Frame` to make `set()`
/// available.
///
/// [`Frame`]: tiny_led_matrix::Frame
/// [`Render`]: tiny_led_matrix::Render
#[derive(Copy, Clone, Debug)]
pub struct MicrobitFrame([RowPlan; MicrobitFrame::ROWS]);

impl MicrobitFrame {
    /// Returns a new frame, initially blank.
    pub const fn default() -> MicrobitFrame {
        MicrobitFrame([RowPlan::default(); MicrobitFrame::ROWS])
    }
}

impl Default for MicrobitFrame {
    /// Returns a new frame, initially blank.
    fn default() -> MicrobitFrame {
        MicrobitFrame::default()
    }
}

impl Frame for MicrobitFrame {
    type Mtx = MicrobitMatrix;

    fn row_plan(&self, row: usize) -> &RowPlan {
        &self.0[row]
    }

    fn row_plan_mut(&mut self, row: usize) -> &mut RowPlan {
        &mut self.0[row]
    }
}


================================================
FILE: microbit-common/src/display/nonblocking/mod.rs
================================================
//! Non-blocking support for the 5×5 LED display.
//!
//! Together with [`tiny-led-matrix`](tiny_led_matrix), this module provides:
//! - support for driving the LED display from a timer interrupt
//! - ten levels of brightness for each LED
//! - simple 5×5 greyscale and black-and-white image types.
//!
//! The module doesn't define interrupt handlers directly; instead it provides
//! a function to be called from a timer interrupt. It knows how to program
//! one of the micro:bit's timers to provide that interrupt.
//!
//! ## Example
//!
//! This shows general usage but is not a working example.
//! For a working exaple see
//! [`display_nonblocking`](https://github.com/nrf-rs/microbit/tree/main/examples/display-nonblocking).
//!
//! ```no_run
//! # use microbit_common as microbit;
//! use microbit::{
//!     Board,
//!     hal,
//!     display::nonblocking::{Display, GreyscaleImage},
//! };
//! use embedded_hal::delay::DelayNs;
//!
//! let board = Board::take().unwrap();
//!
//! let mut display = Display::new(board.TIMER1, board.display_pins);
//!
//! // in your main function
//! {
//!     let mut timer2 = hal::Timer::new(board.TIMER0);
//!     loop {
//!         display.show(&GreyscaleImage::new(&[
//!             [0, 7, 0, 7, 0],
//!             [7, 0, 7, 0, 7],
//!             [7, 0, 0, 0, 7],
//!             [0, 7, 0, 7, 0],
//!             [0, 0, 7, 0, 0],
//!         ]));
//!         timer2.delay_ms(1000);
//!
//!         display.clear();
//!         timer2.delay_ms(1000);
//!     }
//! }
//!
//! // in a timer interrupt
//! {
//!     display.handle_display_event();
//! }
//! ```
//!
//! ## Coordinate system
//!
//! The LEDs are identified using (x,y) coordinates as follows:
//!
//! ```text
//! (0,0) ... (4,0)
//!  ...  ...  ...
//! (0,4) ... (4,4)
//! ```
//!
//! where the 'bottom' (x,4) of the board is the edge connector.
//!
//! ## Greyscale model
//!
//! LED brightness levels are described using a scale from 0 (off) to 9
//! (brightest) inclusive.
//!
//! These are converted to time slices using the same timings as used by the
//! [micro:bit MicroPython port][micropython] (this is different to the 0 to
//! 255 scale used by the [micro:bit runtime][dal]).
//!
//! The time slice for each level above 1 is approximately 1.9× the slice for
//! the previous level.
//!
#![cfg_attr(
    feature = "v1",
    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)."
)]
#![cfg_attr(
    feature = "v2",
    doc = "An LED with brightness 9 is lit for one fifth of the time."
)]
//!
//! ## Images
//!
//! An image is a type that implements the [`tiny_led_matrix::Render`] trait. Two image types are provided:
//! - [`GreyscaleImage`](image::GreyscaleImage), allowing all 9 levels (using one byte for each LED)
//! - [`BitImage`](image::BitImage), allowing only 'on' and 'off' (using five bytes)
//!
//! ## Display
//!
//! A [`Display`] instance controls the LEDs and programs a timer. There
//! should normally be a single `Display` instance in the program. It is a wrapper
//! around [`tiny_led_matrix::Display`] to expose an API similar to the blocking API.
//!
//! ## Frames
//!
//! Internally types implementing [`Render`](tiny_led_matrix::Render) aren't used directly with the [`Display`];
//! instead they're used to update a [`MicrobitFrame`] instance which is in
//! turn passed to the `tiny_led_matrix::Display`.
//!
//! A `MicrobitFrame` instance is a 'compiled' representation of a 5×5
//! greyscale image, in a form that's more directly usable by the display
//! code.
//!
//! This is exposed in the public API so that you can construct the
//! `MicrobitFrame` representation in code running at a low priority. Then
//! only [`Display::show_frame()`] has to be called in code that can't be
//! interrupted by the display timer.
//!
//! ## Timer integration
//!
//! The [`Display`] expects to control a single timer. It can use the
//! micro:bit's `TIMER0`, `TIMER1`, or `TIMER2`.
//!
//! For the micro:bit v1 this uses a 6ms period to light each of the three
//! internal LED rows, so that the entire display is updated every 18ms.
//!
//! For the micro:bit v2 this uses a 3ms period to light each of the five
//! internal LED rows, so that the entire display is updated every 15ms.
//!
//! When rendering greyscale images, the `Display` requests extra interrupts
//! within each 6ms or 3ms period. It only requests interrupts for the
//! greyscale levels which are actually required for what's currently being
//! displayed.
//!
//! ### Technical details
//!
//! The timer is set to 16-bit mode, using a 62.5kHz or 135Khz clock (16 µs or
//! 8µs ticks). It resets every 375 ticks.
//!
//! ## Usage
//!
//! Choose a timer to drive the display from (`TIMER0`, `TIMER1`, or `TIMER2`).
//!
//! When your program starts:
//! - create a [`Display`] struct passing the timer and
//! [`gpio::DisplayPins`](crate::gpio::DisplayPins) to [`Display::new()`].
//!
//! In an interrupt handler for the timer call [`.handle_display_event()`](Display::handle_display_event)
//!
//! To change what's displayed; pass an image ([`GreyscaleImage`] or [`BitImage`]) to [`Display::show`].
//!
//! You can call `show()` at any time, so long as you're not interrupting, or interruptable by,
//! [`Display::handle_display_event()`].
//!
//! See [`display_rtic`](https://github.com/nrf-rs/microbit/blob/master/examples/display_rtic) or
//! [`display_nonblocking`](https://github.com/nrf-rs/microbit/blob/master/examples/display_nonblocking)
//! example for a complete working example.
//!
//! [dal]: https://lancaster-university.github.io/microbit-docs/
//! [micropython]: https://microbit-micropython.readthedocs.io/

use tiny_led_matrix;
#[doc(no_inline)]
pub use tiny_led_matrix::{Frame, MAX_BRIGHTNESS};

mod control;
mod image;
mod matrix;
mod timer;

pub use image::{BitImage, GreyscaleImage};
pub use matrix::MicrobitFrame;
use timer::MicrobitDisplayTimer;

use crate::{gpio::DisplayPins, hal::timer::Instance};

use control::MicrobitGpio;

/// Non-blocking interface to the on board 5x5 LED display
pub struct Display<T: Instance> {
    display: tiny_led_matrix::Display<MicrobitFrame>,
    timer: MicrobitDisplayTimer<T>,
    pins: DisplayPins,
    frame: MicrobitFrame,
}

impl<T: Instance> Display<T> {
    /// Create and initialise the display driver
    ///
    /// [`DisplayPins`] can be used from [`Board::display_pins`](crate::Board::display_pins)
    /// or the [`display_pins!`](crate::display_pins) macro can be used is manually.
    pub fn new(timer: T, pins: DisplayPins) -> Self {
        let mut display = Self {
            display: tiny_led_matrix::Display::new(),
            timer: MicrobitDisplayTimer::new(timer),
            pins,
            frame: MicrobitFrame::default(),
        };
        display.initialise();
        display
    }

    /// Release the timer and pins
    pub fn free(self) -> (T, DisplayPins) {
        (self.timer.free(), self.pins)
    }

    /// Initialise the display
    ///
    /// This is usually called immediately after creating the display driver.
    /// It does not need to be called in a critical section.
    fn initialise(&mut self) {
        tiny_led_matrix::initialise_control(&mut MicrobitGpio {});
        tiny_led_matrix::initialise_timer(&mut self.timer);
    }

    /// Update the LED display and timer state
    ///
    /// Call this in an interrupt handler for the timer you're using. This method
    /// takes care of updating the LED display and clearing the timer's event registers
    ///
    /// This may be called at any time, so long as the code calling it is not interrupting, or
    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow
    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method
    /// should be called from within a [critical
    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).
    pub fn handle_display_event(&mut self) {
        self.display
            .handle_event(&mut self.timer, &mut MicrobitGpio {});
    }

    /// Show a new image
    ///
    /// This may be called at any time, so long as the code calling it is not interrupting, or
    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow
    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method
    /// should be called from within a [critical
    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).
    ///
    /// ## Example
    ///
    /// ```ignore
    /// display.show(&GreyscaleImage::new(&[
    ///     [0, 7, 0, 7, 0],
    ///     [7, 0, 7, 0, 7],
    ///     [7, 0, 0, 0, 7],
    ///     [0, 7, 0, 7, 0],
    ///     [0, 0, 7, 0, 0],
    /// ]));
    /// ```
    pub fn show<R: tiny_led_matrix::Render>(&mut self, image: &R) {
        self.frame.set(image);
        self.display.set_frame(&self.frame);
    }

    /// Clear the display
    ///
    /// This may be called at any time, so long as the code calling it is not interrupting, or
    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow
    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method
    /// should be called from within a [critical
    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).
    pub fn clear(&mut self) {
        self.display.set_frame(&MicrobitFrame::default());
    }

    /// Show a new frame
    ///
    /// This is similar to [`show`](Display::show) but accepts a [`MicrobitFrame`] instead.
    /// This may be useful if performance is a concern as calling `set` on the frame
    /// can be done outside the critical section.
    ///
    /// This may be called at any time, so long as the code calling it is not interrupting, or
    /// interruptable by `tiny_led_matrix::Display::handle_event()`. Within safe code, the borrow
    /// checker ensures that this requirement is fulfilled. When writing unsafe code, this method
    /// should be called from within a [critical
    /// section](https://docs.rs/cortex-m/0.7.2/cortex_m/interrupt/fn.free.html).
    ///
    /// ## Example
    ///
    /// ```ignore
    /// FRAME = MicrobitFrame::default();
    /// FRAME.set(&GreyscaleImage::new(&[
    ///     [0, 7, 0, 7, 0],
    ///     [7, 0, 7, 0, 7],
    ///     [7, 0, 0, 0, 7],
    ///     [0, 7, 0, 7, 0],
    ///     [0, 0, 7, 0, 0],
    /// ]));
    ///
    /// // only this needs to be in a critical section
    /// display.show_frame(&FRAME);
    /// ```
    pub fn show_frame(&mut self, frame: &MicrobitFrame) {
        self.display.set_frame(frame);
    }
}


================================================
FILE: microbit-common/src/display/nonblocking/timer.rs
================================================
//! Implementation of [`DisplayTimer`] for the nRF51 `TIMER`s.
//!
//! [`DisplayTimer`]: tiny_led_matrix::DisplayTimer

use tiny_led_matrix::DisplayTimer;

use crate::hal::timer::Instance;

/// A TIMER peripheral programmed to manage the display.
///
/// `MicrobitDisplayTimer` instances implement the [`DisplayTimer`] trait.
///
/// The timer is set to 16-bit mode.
///
/// For micro:bit v1: uses a 62.5kHz clock clock (16 µs ticks).
/// The primary cycle takes 6ms.
///
/// For micro:bit v2: uses a 135kHz clock (8 µs ticks).
/// The primary cycle takes 3ms.
///
/// Uses CC0 for the primary cycle and CC1 for the secondary alarm. Uses the
/// CC0_CLEAR shortcut to implement the primary cycle.
///
/// [`DisplayTimer`]: tiny_led_matrix::DisplayTimer
pub struct MicrobitDisplayTimer<T: Instance>(T);

impl<T: Instance> MicrobitDisplayTimer<T> {
    /// Returns a new `MicrobitDisplayTimer` wrapping the passed TIMER.
    ///
    /// Takes ownership of the TIMER peripheral.
    pub fn new(timer: T) -> MicrobitDisplayTimer<T> {
        MicrobitDisplayTimer(timer)
    }

    /// Gives the underlying `nrf51::TIMER`*n* instance back.
    pub fn free(self) -> T {
        self.0
    }
}

impl<T: Instance> DisplayTimer for MicrobitDisplayTimer<T> {
    fn initialise_cycle(&mut self, ticks: u16) {
        let timer0 = self.0.as_timer0();
        // stop and reset timer
        timer0.tasks_stop.write(|w| unsafe { w.bits(1) });
        timer0.tasks_clear.write(|w| unsafe { w.bits(1) });

        // set as 16 bits
        timer0.bitmode.write(|w| w.bitmode()._16bit());

        #[cfg(feature = "v1")]
        // set frequency to 62500Hz
        let prescaler = 8;
        #[cfg(feature = "v2")]
        // set frequency to 135000Hz
        let prescaler = 7;
        timer0.prescaler.write(|w| unsafe { w.bits(prescaler) });

        // set compare register
        timer0.cc[0].write(|w| unsafe { w.bits(ticks.into()) });

        // enable auto clear
        timer0.shorts.write(|w| w.compare0_clear().enabled());

        // enable compare interrupt
        timer0.intenset.write(|w| w.compare0().set());

        // start
        timer0.tasks_start.write(|w| unsafe { w.bits(1) });
        // maybe?
        // timer0.tasks_start.write(|w| w.tasks_start().set_bit());
    }

    fn enable_secondary(&mut self) {
        self.0.as_timer0().intenset.write(|w| w.compare1().set());
    }

    fn disable_secondary(&mut self) {
        self.0
            .as_timer0()
            .intenclr
            .write(|w| w.compare1().set_bit());
    }

    fn program_secondary(&mut self, ticks: u16) {
        #[cfg(feature = "v1")]
        self.0.as_timer0().cc[1].write(|w| unsafe { w.bits(ticks.into()) });
        #[cfg(feature = "v2")]
        self.0.as_timer0().cc[1].write(|w| unsafe { w.cc().bits(ticks.into()) });
    }

    fn check_primary(&mut self) -> bool {
        // poll compare event
        let reg = &self.0.as_timer0().events_compare[0];
        let fired = reg.read().bits() != 0;
        if fired {
            reg.reset();
        }
        fired
    }

    fn check_secondary(&mut self) -> bool {
        // poll compare event
        let reg = &self.0.as_timer0().events_compare[1];
        let fired = reg.read().bits() != 0;
        if fired {
            reg.reset();
        }
        fired
    }
}


================================================
FILE: microbit-common/src/gpio.rs
================================================
//! Named GPIO pin types
//!
//! This module maps the GPIO pin names as described in the
//! [Pins and Signals section of the micro:bit site](https://tech.microbit.org/hardware/edgeconnector/#pins-and-signals)
//! Where appropriate the pins are restricted with the appropriate `MODE`
//! from `nrf-hal`.
#[cfg(feature = "v1")]
pub use crate::v1::gpio::*;

#[cfg(feature = "v2")]
pub use crate::v2::gpio::*;


================================================
FILE: microbit-common/src/lib.rs
================================================
//! microbit contains everything required to get started with the use of Rust
//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)
//! microcontroller board.
#![doc(html_root_url = "https://docs.rs/microbit-common/0.16.0")]
#![no_std]
#![deny(missing_docs)]
#![allow(non_camel_case_types)]

#[cfg(all(feature = "v1", feature = "v2"))]
compile_error!("canot build for microbit v1 and v2 at the same time");

#[cfg(feature = "v1")]
pub use nrf51_hal as hal;

#[cfg(feature = "v2")]
pub use nrf52833_hal as hal;

pub use hal::pac;
pub use hal::pac::Peripherals;

pub mod adc;
pub mod board;
pub mod display;
pub mod gpio;

pub use board::Board;

#[cfg(feature = "v1")]
mod v1;

#[cfg(feature = "v2")]
mod v2;


================================================
FILE: microbit-common/src/v1/adc.rs
================================================
use crate::hal;

/// Adc alias to unify v1 and v2 names
pub type Adc = hal::Adc;
/// AdcConfig alias to unify v1 and v2 names
pub type AdcConfig = hal::adc::AdcConfig;

/// Same resolution for v1 and v2
pub trait Default {
    /// v1 is limited to 10 bit
    fn default_10bit() -> Self;
}

impl Default for AdcConfig {
    fn default_10bit() -> Self {
        AdcConfig::default()
    }
}


================================================
FILE: microbit-common/src/v1/board.rs
================================================
use super::gpio::{
    DisplayPins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE12, EDGE16, SCL, SDA, UART_RX,
    UART_TX,
};
use crate::{
    hal::{
        gpio::{p0, Disconnected, Level},
        twi, uart,
    },
    pac,
};

/// Provides access to the microbit
#[allow(non_snake_case)]
pub struct Board {
    /// GPIO pins that are not otherwise used
    pub pins: Pins,

    /// Unused GPIO pins on edge connector
    pub edge: Edge,

    /// display pins
    pub display_pins: DisplayPins,

    /// buttons
    pub buttons: Buttons,

    /// I2C shared internal and external bus pins
    pub i2c: I2CPins,

    /// UART to debugger pins
    pub uart: UartPins,

    /// Core peripheral: Cache and branch predictor maintenance operations
    pub CBP: pac::CBP,

    /// Core peripheral: CPUID
    pub CPUID: pac::CPUID,

    /// Core peripheral: Debug Control Block
    pub DCB: pac::DCB,

    /// Core peripheral: Data Watchpoint and Trace unit
    pub DWT: pac::DWT,

    /// Core peripheral: Flash Patch and Breakpoint unit
    pub FPB: pac::FPB,

    /// Core peripheral: Instrumentation Trace Macrocell
    pub ITM: pac::ITM,

    /// Core peripheral: Memory Protection Unit
    pub MPU: pac::MPU,

    /// Core peripheral: Nested Vector Interrupt Controller
    pub NVIC: pac::NVIC,

    /// Core peripheral: System Control Block
    pub SCB: pac::SCB,

    /// Core peripheral: SysTick Timer
    pub SYST: pac::SYST,

    /// Core peripheral: Trace Port Interface Unit
    pub TPIU: pac::TPIU,

    /// nRF51 peripheral: ADC
    pub ADC: pac::ADC,

    /// nRF51 peripheral: CLOCK
    pub CLOCK: pac::CLOCK,

    /// nRF51 peripheral: FICR
    pub FICR: pac::FICR,

    /// nRF51 peripheral: GPIOTE
    pub GPIOTE: pac::GPIOTE,

    /// nRF51 preipheral: PPI
    pub PPI: pac::PPI,

    /// nRF51 peripheral: RADIO
    pub RADIO: pac::RADIO,

    /// nRF51 peripheral: RNG
    pub RNG: pac::RNG,

    /// nRF51 peripheral: RTC0
    pub RTC0: pac::RTC0,

    /// nRF51 peripheral: TEMP <br>
    /// Can be used with [`Temp::new()`](`crate::hal::temp::Temp::new()`)
    pub TEMP: pac::TEMP,

    /// nRF51 peripheral: TIMER0
    pub TIMER0: pac::TIMER0,

    /// nRF51 peripheral: TIMER1
    pub TIMER1: pac::TIMER1,

    /// nRF51 peripheral: TIMER2
    pub TIMER2: pac::TIMER2,

    /// nRF51 peripheral: TWI0
    pub TWI0: pac::TWI0,

    /// nrf51 peripheral: UART0
    pub UART0: pac::UART0,

    /// nrf51 peripheral: POWER
    pub POWER: pac::POWER,

    /// nrf51 peripheral: SPI0
    pub SPI0: pac::SPI0,

    /// nrf51 peripheral: SPI1
    pub SPI1: pac::SPI1,

    /// nrf51 peripheral: TWI1
    pub TWI1: pac::TWI1,

    /// nrf51 peripheral: SPIS1
    pub SPIS1: pac::SPIS1,

    /// nrf51 peripheral: ECB
    pub ECB: pac::ECB,

    /// nrf51 peripheral: AAR
    pub AAR: pac::AAR,

    /// nrf51 peripheral: CCM
    pub CCM: pac::CCM,

    /// nrf51 peripheral: WDT
    pub WDT: pac::WDT,

    /// nrf51 peripheral: RTC1
    pub RTC1: pac::RTC1,

    /// nrf51 peripheral: QDEC
    pub QDEC: pac::QDEC,

    /// nrf51 peripheral: LPCOMP
    pub LPCOMP: pac::LPCOMP,

    /// nrf51 peripheral: SWI
    pub SWI: pac::SWI,

    /// nrf51 peripheral: NVMC
    pub NVMC: pac::NVMC,

    /// nrf51 peripheral: UICR
    pub UICR: pac::UICR,
}

impl Board {
    /// Take the peripherals safely
    ///
    /// This method will return an instance of the board the first time it is
    /// called. It will return only `None` on subsequent calls.
    /// This function can also return `None` if one of the the peripherals was
    /// already taken.
    pub fn take() -> Option<Self> {
        Some(Self::new(
            pac::Peripherals::take()?,
            pac::CorePeripherals::take()?,
        ))
    }

    /// Fallback method in the case peripherals and core peripherals were taken
    /// elsewhere already.
    ///
    /// This method will take the peripherals and core peripherals and
    /// return an instance of the board.
    ///
    /// An exemplary usecase is shown in the rtic display example.
    pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {
        let p0parts = p0::Parts::new(p.GPIO);
        Self {
            pins: Pins {
                //p0_01: p0parts.p0_01,
                //p0_02: p0parts.p0_02,
                //p0_03: p0parts.p0_03,
                //p0_16: p0parts.p0_16,
                //p0_18: p0parts.p0_18,
                p0_19: p0parts.p0_19,
                //p0_20: p0parts.p0_20,
                p0_21: p0parts.p0_21,
                p0_22: p0parts.p0_22,
                p0_23: p0parts.p0_23,
                p0_27: p0parts.p0_27,
                p0_28: p0parts.p0_28,
                p0_29: p0parts.p0_29,
            },
            edge: Edge {
                e00: p0parts.p0_03,
                e01: p0parts.p0_02,
                e02: p0parts.p0_01,
                e08: p0parts.p0_18,
                e12: p0parts.p0_20,
                e16: p0parts.p0_16,
            },
            display_pins: DisplayPins {
                row1: p0parts.p0_13.into_push_pull_output(Level::Low),
                row2: p0parts.p0_14.into_push_pull_output(Level::Low),
                row3: p0parts.p0_15.into_push_pull_output(Level::Low),
                col1: p0parts.p0_04.into_push_pull_output(Level::High),
                col2: p0parts.p0_05.into_push_pull_output(Level::High),
                col3: p0parts.p0_06.into_push_pull_output(Level::High),
                col4: p0parts.p0_07.into_push_pull_output(Level::High),
                col5: p0parts.p0_08.into_push_pull_output(Level::High),
                col6: p0parts.p0_09.into_push_pull_output(Level::High),
                col7: p0parts.p0_10.into_push_pull_output(Level::High),
                col8: p0parts.p0_11.into_push_pull_output(Level::High),
                col9: p0parts.p0_12.into_push_pull_output(Level::High),
            },
            buttons: Buttons {
                button_a: p0parts.p0_17.into_floating_input(),
                button_b: p0parts.p0_26.into_floating_input(),
            },
            i2c: I2CPins {
                scl: p0parts.p0_00.into_floating_input(),
                sda: p0parts.p0_30.into_floating_input(),
            },
            uart: UartPins {
                tx: p0parts.p0_24.into_push_pull_output(Level::Low),
                rx: p0parts.p0_25.into_floating_input(),
            },

            // Core peripherals
            CBP: cp.CBP,
            CPUID: cp.CPUID,
            DCB: cp.DCB,
            DWT: cp.DWT,
            FPB: cp.FPB,
            ITM: cp.ITM,
            MPU: cp.MPU,
            NVIC: cp.NVIC,
            SCB: cp.SCB,
            SYST: cp.SYST,
            TPIU: cp.TPIU,

            // nRF51 peripherals
            ADC: p.ADC,
            CLOCK: p.CLOCK,
            FICR: p.FICR,
            GPIOTE: p.GPIOTE,
            PPI: p.PPI,
            RADIO: p.RADIO,
            RNG: p.RNG,
            RTC0: p.RTC0,
            TEMP: p.TEMP,
            TIMER0: p.TIMER0,
            TIMER1: p.TIMER1,
            TIMER2: p.TIMER2,
            TWI0: p.TWI0,
            UART0: p.UART0,
            POWER: p.POWER,
            SPI0: p.SPI0,
            SPI1: p.SPI1,
            TWI1: p.TWI1,
            SPIS1: p.SPIS1,
            ECB: p.ECB,
            AAR: p.AAR,
            CCM: p.CCM,
            WDT: p.WDT,
            RTC1: p.RTC1,
            QDEC: p.QDEC,
            LPCOMP: p.LPCOMP,
            SWI: p.SWI,
            NVMC: p.NVMC,
            UICR: p.UICR,
        }
    }
}

/// Unused GPIO pins
#[allow(missing_docs)]
pub struct Pins {
    // pub p0_00: p0::P0_00<Disconnected>, // SCL
    // pub p0_01: p0::P0_01<Disconnected>, // PAD2, EDGE02
    // pub p0_02: p0::P0_02<Disconnected>, // PAD1, EDGE01
    // pub p0_03: p0::P0_03<Disconnected>, // PAD0, EDGE00
    // pub p0_04: p0::P0_04<Disconnected>, // LEDs
    // pub p0_05: p0::P0_05<Disconnected>, // LEDs
    // pub p0_06: p0::P0_06<Disconnected>, // LEDs
    // pub p0_07: p0::P0_07<Disconnected>, // LEDs
    // pub p0_08: p0::P0_08<Disconnected>, // LEDs
    // pub p0_09: p0::P0_09<Disconnected>, // LEDs
    // pub p0_10: p0::P0_10<Disconnected>, // LEDs
    // pub p0_11: p0::P0_11<Disconnected>, // LEDs
    // pub p0_12: p0::P0_12<Disconnected>, // LEDs
    // pub p0_13: p0::P0_13<Disconnected>, // LEDs
    // pub p0_14: p0::P0_14<Disconnected>, // LEDs
    // pub p0_15: p0::P0_15<Disconnected>, // LEDs
    // pub p0_16: p0::P0_16<Disconnected>, // EDGE16
    // pub p0_17: p0::P0_17<Disconnected>, // BTN_A
    // pub p0_18: p0::P0_18<Disconnected>, // EDGE08
    pub p0_19: p0::P0_19<Disconnected>,
    // pub p0_20: p0::P0_20<Disconnected>, // EDGE12
    pub p0_21: p0::P0_21<Disconnected>,
    pub p0_22: p0::P0_22<Disconnected>,
    pub p0_23: p0::P0_23<Disconnected>,
    // pub p0_24: p0::P0_24<Disconnected>, // UART TX
    // pub p0_25: p0::P0_25<Disconnected>, // UART RX
    // pub p0_26: p0::P0_26<Disconnected>, // BTN_B
    pub p0_27: p0::P0_27<Disconnected>,
    pub p0_28: p0::P0_28<Disconnected>,
    pub p0_29: p0::P0_29<Disconnected>,
    // pub p0_30: p0::P0_30<Disconnected>, // SDA
}

/// Unused edge connector pins
#[allow(missing_docs)]
pub struct Edge {
    // pub e03: COL1,
    pub e00: EDGE00<Disconnected>, // <- big pad 1
    // pub e04: COL2,
    // pub e05: BTN_A,
    // pub e06: COL9,
    // pub e07: COL8,
    pub e01: EDGE01<Disconnected>, // <- big pad 2
    pub e08: EDGE08<Disconnected>,
    // pub e09: COL7,
    // pub e10: COL3,
    // pub e11: BTN_B,
    pub e12: EDGE12<Disconnected>,
    pub e02: EDGE02<Disconnected>, // <- big pad 3
    //pub e13<MODE>: SCK<MODE>,
    //pub e14<MODE>: MISO<MODE>,
    //pub e15<MODE>: MOSI<MODE>,
    pub e16: EDGE16<Disconnected>,
    // +V
    // +V
    // +V
    // pub e19: SCL,
    // pub e20: SDA,
    // GND
    // GND
    // GND
}

/// Board buttons
pub struct Buttons {
    /// Left hand side button
    pub button_a: BTN_A,
    /// Right hand side button
    pub button_b: BTN_B,
}

/// I2C shared internal and external bus pins
pub struct I2CPins {
    /// I2C control pin
    pub scl: SCL,
    /// I2C data pin
    pub sda: SDA,
}

impl From<I2CPins> for twi::Pins {
    fn from(pins: I2CPins) -> Self {
        Self {
            scl: pins.scl.degrade(),
            sda: pins.sda.degrade(),
        }
    }
}

/// UART to debugger pins
pub struct UartPins {
    tx: UART_TX,
    rx: UART_RX,
}

impl From<UartPins> for uart::Pins {
    fn from(pins: UartPins) -> Self {
        Self {
            rxd: pins.rx.degrade(),
            txd: pins.tx.degrade(),
            cts: None,
            rts: None,
        }
    }
}


================================================
FILE: microbit-common/src/v1/gpio.rs
================================================
//! Named GPIO pin types
//!
//! This module maps the GPIO pin names as described in the
//! [Pins and Signals section of the micro:bit site](https://tech.microbit.org/hardware/edgeconnector/#pins-and-signals)
//! Where appropriate the pins are restricted with the appropriate `MODE`
//! from `nrf-hal`.
#![allow(clippy::upper_case_acronyms, missing_docs)]
use crate::hal::gpio::{p0, Floating, Input, Output, Pin, PushPull};

/* GPIO pads */
pub type PAD0<MODE> = p0::P0_03<MODE>;
pub type PAD1<MODE> = p0::P0_02<MODE>;
pub type PAD2<MODE> = p0::P0_01<MODE>;

/* LED display */
pub const NUM_COLS: usize = 9;
pub type COL1 = p0::P0_04<Output<PushPull>>;
pub type COL2 = p0::P0_05<Output<PushPull>>;
pub type COL3 = p0::P0_06<Output<PushPull>>;
pub type COL4 = p0::P0_07<Output<PushPull>>;
pub type COL5 = p0::P0_08<Output<PushPull>>;
pub type COL6 = p0::P0_09<Output<PushPull>>;
pub type COL7 = p0::P0_10<Output<PushPull>>;
pub type COL8 = p0::P0_11<Output<PushPull>>;
pub type COL9 = p0::P0_12<Output<PushPull>>;

pub const NUM_ROWS: usize = 3;
pub type ROW1 = p0::P0_13<Output<PushPull>>;
pub type ROW2 = p0::P0_14<Output<PushPull>>;
pub type ROW3 = p0::P0_15<Output<PushPull>>;

/// GPIO pins connected to the LED matrix
///
/// The pins are represented as a [3x9 matrix on the micro:bit
/// V1](https://tech.microbit.org/hardware/1-5-revision/#display).
/// This is mapped to the physical 5x5 LED matrix in the [crate::display]
/// modules.
///
/// Use the [display_pins] macro for easier construction.
pub struct DisplayPins {
    pub col1: COL1,
    pub col2: COL2,
    pub col3: COL3,
    pub col4: COL4,
    pub col5: COL5,
    pub col6: COL6,
    pub col7: COL7,
    pub col8: COL8,
    pub col9: COL9,
    pub row1: ROW1,
    pub row2: ROW2,
    pub row3: ROW3,
}

type LED = Pin<Output<PushPull>>;

impl DisplayPins {
    pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {
        (
            [
                self.col1.degrade(),
                self.col2.degrade(),
                self.col3.degrade(),
                self.col4.degrade(),
                self.col5.degrade(),
                self.col6.degrade(),
                self.col7.degrade(),
                self.col8.degrade(),
                self.col9.degrade(),
            ],
            [
                self.row1.degrade(),
                self.row2.degrade(),
                self.row3.degrade(),
            ],
        )
    }
}

/// Create [DisplayPins] from a [GPIO Parts](crate::hal::gpio::p0::Parts)
///
/// # Example
///
/// ```no_run
/// # use microbit_common as microbit;
/// use microbit::{
///     display_pins,
///     pac,
///     hal::gpio::p0::Parts as P0Parts,
/// };
///
/// // take the peripherals
/// let p = pac::Peripherals::take().unwrap();
/// // split off the P0 GPIO port
/// let p0parts = P0Parts::new(p.GPIO);
///
/// let pins = display_pins!(p0parts);
/// ```
#[macro_export]
macro_rules! display_pins {
    ( $p0parts:expr ) => {{
        use microbit::{gpio::DisplayPins, hal::gpio::Level};

        DisplayPins {
            row1: $p0parts.p0_13.into_push_pull_output(Level::Low),
            row2: $p0parts.p0_14.into_push_pull_output(Level::Low),
            row3: $p0parts.p0_15.into_push_pull_output(Level::Low),
            col1: $p0parts.p0_04.into_push_pull_output(Level::Low),
            col2: $p0parts.p0_05.into_push_pull_output(Level::Low),
            col3: $p0parts.p0_06.into_push_pull_output(Level::Low),
            col4: $p0parts.p0_07.into_push_pull_output(Level::Low),
            col5: $p0parts.p0_08.into_push_pull_output(Level::Low),
            col6: $p0parts.p0_09.into_push_pull_output(Level::Low),
            col7: $p0parts.p0_10.into_push_pull_output(Level::Low),
            col8: $p0parts.p0_11.into_push_pull_output(Level::Low),
            col9: $p0parts.p0_12.into_push_pull_output(Level::Low),
        }
    }};
}

/* buttons */
pub type BTN_A = p0::P0_17<Input<Floating>>;
pub type BTN_B = p0::P0_26<Input<Floating>>;

/* spi */
pub type MOSI<MODE> = p0::P0_21<MODE>;
pub type MISO<MODE> = p0::P0_22<MODE>;
pub type SCK<MODE> = p0::P0_23<MODE>;

/* i2c - shared external and internal */
pub type SCL = p0::P0_00<Input<Floating>>;
pub type SDA = p0::P0_30<Input<Floating>>;

/* uart */
pub type UART_TX = p0::P0_24<Output<PushPull>>;
pub type UART_RX = p0::P0_25<Input<Floating>>;

/* edge connector */
pub type EDGE03 = COL1;
pub type EDGE00<MODE> = PAD0<MODE>; // <- big pad 1
pub type EDGE04 = COL2;
pub type EDGE05 = BTN_A;
pub type EDGE06 = COL9;
pub type EDGE07 = COL8;
pub type EDGE01<MODE> = PAD1<MODE>; // <- big pad 2
pub type EDGE08<MODE> = p0::P0_18<MODE>;
pub type EDGE09 = COL7;
pub type EDGE10 = COL3;
pub type EDGE11 = BTN_B;
pub type EDGE12<MODE> = p0::P0_20<MODE>;
pub type EDGE02<MODE> = PAD2<MODE>; // <- big pad 3
pub type EDGE13<MODE> = SCK<MODE>;
pub type EDGE14<MODE> = MISO<MODE>;
pub type EDGE15<MODE> = MOSI<MODE>;
pub type EDGE16<MODE> = p0::P0_16<MODE>;
// EDGE18 -> +V
// EDGE19 -> +V
// EDGE20 -> +V
pub type EDGE19 = SCL;
pub type EDGE20 = SDA;
// EDGE23 -> GND
// EDGE24 -> GND
// EDGE25 -> GND


================================================
FILE: microbit-common/src/v1/mod.rs
================================================
pub mod adc;
pub mod board;
pub mod gpio;


================================================
FILE: microbit-common/src/v2/adc.rs
================================================
use crate::hal;

/// Adc alias to unify v1 and v2 names
pub type Adc = hal::Saadc;
/// AdcConfig alias to unify v1 and v2 names
pub type AdcConfig = hal::saadc::SaadcConfig;

/// Same resolution for v1 and v2
pub trait Default {
    /// v1 is limited to 10 bit
    fn default_10bit() -> Self;
}

impl Default for AdcConfig {
    fn default_10bit() -> Self {
        AdcConfig {
            resolution: hal::saadc::Resolution::_10BIT,
            ..AdcConfig::default()
        }
    }
}


================================================
FILE: microbit-common/src/v2/board.rs
================================================
use super::gpio::{
    DisplayPins, MicrophonePins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE09, EDGE12,
    EDGE16, INT_SCL, INT_SDA, SCL, SDA, UART_RX, UART_TX,
};
use crate::{
    hal::{
        gpio::{p0, p1, Disconnected, Level, OpenDrainConfig::Disconnect0HighDrive1},
        twim, twis, uarte,
    },
    pac,
};

/// Provides access to the microbit
#[allow(non_snake_case)]
pub struct Board {
    /// GPIO pins that are not otherwise used
    pub pins: Pins,

    /// Unused GPIO pins on edge connector
    pub edge: Edge,

    /// display pins
    pub display_pins: DisplayPins,

    /// buttons
    pub buttons: Buttons,

    /// speaker
    pub speaker_pin: p0::P0_00<Disconnected>,

    /// microphone pins
    pub microphone_pins: MicrophonePins,

    /// I2C internal bus pins
    pub i2c_internal: I2CInternalPins,

    /// I2C external bus pins
    pub i2c_external: I2CExternalPins,

    /// UART to debugger pins
    pub uart: UartPins,

    /// Core peripheral: Cache and branch predictor maintenance operations
    pub CBP: pac::CBP,

    /// Core peripheral: CPUID
    pub CPUID: pac::CPUID,

    /// Core peripheral: Debug Control Block
    pub DCB: pac::DCB,

    /// Core peripheral: Data Watchpoint and Trace unit
    pub DWT: pac::DWT,

    /// Core peripheral: Flash Patch and Breakpoint unit
    pub FPB: pac::FPB,

    /// Core peripheral: Floating Point Unit
    pub FPU: pac::FPU,

    /// Core peripheral: Instrumentation Trace Macrocell
    pub ITM: pac::ITM,

    /// Core peripheral: Memory Protection Unit
    pub MPU: pac::MPU,

    /// Core peripheral: Nested Vector Interrupt Controller
    pub NVIC: pac::NVIC,

    /// Core peripheral: System Control Block
    pub SCB: pac::SCB,

    /// Core peripheral: SysTick Timer
    pub SYST: pac::SYST,

    /// Core peripheral: Trace Port Interface Unit
    pub TPIU: pac::TPIU,

    /// nRF52 peripheral: CLOCK
    pub CLOCK: pac::CLOCK,

    /// nRF52 peripheral: FICR
    pub FICR: pac::FICR,

    /// nRF52 peripheral: GPIOTE
    pub GPIOTE: pac::GPIOTE,

    /// nRF52 preipheral: PPI
    pub PPI: pac::PPI,

    /// nRF52 peripheral: PWM0
    pub PWM0: pac::PWM0,

    /// nRF52 peripheral: PWM1
    pub PWM1: pac::PWM1,

    /// nRF52 peripheral: PWM2
    pub PWM2: pac::PWM2,

    /// nRF52 peripheral: PWM3
    pub PWM3: pac::PWM3,

    /// nRF52 peripheral: RADIO
    pub RADIO: pac::RADIO,

    /// nRF52 peripheral: RNG
    pub RNG: pac::RNG,

    /// nRF52 peripheral: RTC0
    pub RTC0: pac::RTC0,

    /// nRF52 peripheral: RTC1
    pub RTC1: pac::RTC1,

    /// nRF52 peripheral: RTC2
    pub RTC2: pac::RTC2,

    /// nRF52 peripheral: SPIM0
    pub SPIM0: pac::SPIM0,

    /// nRF52 peripheral: SPIM1
    pub SPIM1: pac::SPIM1,

    /// nRF52 peripheral: SPIM2
    pub SPIM2: pac::SPIM2,

    /// nRF52 peripheral: SPIM3
    pub SPIM3: pac::SPIM3,

    /// nRF52 peripheral: TEMP <br>
    /// Can be used with [`Temp::new()`](`crate::hal::temp::Temp::new()`)
    pub TEMP: pac::TEMP,

    /// nRF52 peripheral: TIMER0
    pub TIMER0: pac::TIMER0,

    /// nRF52 peripheral: TIMER1
    pub TIMER1: pac::TIMER1,

    /// nRF52 peripheral: TIMER2
    pub TIMER2: pac::TIMER2,

    /// nRF52 peripheral: TIMER3
    pub TIMER3: pac::TIMER3,

    /// nRF52 peripheral: TIMER4
    pub TIMER4: pac::TIMER4,

    /// nRF52 peripheral: TWIM0
    pub TWIM0: pac::TWIM0,

    /// nRF52 peripheral: TWIS0
    pub TWIS0: pac::TWIS0,

    /// nRF52 peripheral: UARTE0
    pub UARTE0: pac::UARTE0,

    /// nRF52 peripheral: UARTE1
    pub UARTE1: pac::UARTE1,

    /// nRF52 peripheral: SAADC
    pub ADC: pac::SAADC,

    /// nRF52 peripheral: POWER
    pub POWER: pac::POWER,

    /// nRF52 peripheral: SPI0
    pub SPI0: pac::SPI0,

    /// nRF52 peripheral: SPI1
    pub SPI1: pac::SPI1,

    /// nRF52 peripheral: SPI2
    pub SPI2: pac::SPI2,

    /// nRF52 peripheral: UART0
    pub UART0: pac::UART0,

    /// nRF52 peripheral: TWI0
    pub TWI0: pac::TWI0,

    /// nRF52 peripheral: TWI1
    pub TWI1: pac::TWI1,

    /// nRF52 peripheral: SPIS1
    pub SPIS1: pac::SPIS1,

    /// nRF52 peripheral: ECB
    pub ECB: pac::ECB,

    /// nRF52 peripheral: AAR
    pub AAR: pac::AAR,

    /// nRF52 peripheral: CCM
    pub CCM: pac::CCM,

    /// nRF52 peripheral: WDT
    pub WDT: pac::WDT,

    /// nRF52 peripheral: QDEC
    pub QDEC: pac::QDEC,

    /// nRF52 peripheral: LPCOMP
    pub LPCOMP: pac::LPCOMP,

    /// nRF52 peripheral: NVMC
    pub NVMC: pac::NVMC,

    /// nRF52 peripheral: UICR
    pub UICR: pac::UICR,
}

impl Board {
    /// Take the peripherals safely
    ///
    /// This method will return an instance of the board the first time it is
    /// called. It will return only `None` on subsequent calls.
    /// This function can also return `None` if one of the the peripherals was
    /// already taken.
    pub fn take() -> Option<Self> {
        Some(Self::new(
            pac::Peripherals::take()?,
            pac::CorePeripherals::take()?,
        ))
    }

    /// Fallback method in the case peripherals and core peripherals were taken
    /// elsewhere already.
    ///
    /// This method will take the peripherals and core peripherals and
    /// return an instance of the board.
    ///
    /// An exemplary usecase is shown in the rtic display example.
    pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {
        let p0parts = p0::Parts::new(p.P0);
        let p1parts = p1::Parts::new(p.P1);
        Self {
            pins: Pins {
                p0_01: p0parts.p0_01,
                //p0_02: p0parts.p0_02,
                //p0_03: p0parts.p0_03,
                //p0_04: p0parts.p0_04,
                p0_07: p0parts.p0_07,
                //p0_09: p0parts.p0_09,
                //p0_10: p0parts.p0_10,
                //p0_12: p0parts.p0_12,
                p0_13: p0parts.p0_13,
                p0_17: p0parts.p0_17,
                p0_18: p0parts.p0_18,
                p0_25: p0parts.p0_25,
                p0_27: p0parts.p0_27,
                p0_29: p0parts.p0_29,
                p1_01: p1parts.p1_01,
                //p1_02: p1parts.p1_02,
                p1_03: p1parts.p1_03,
                p1_04: p1parts.p1_04,
                p1_06: p1parts.p1_06,
                p1_07: p1parts.p1_07,
                p1_09: p1parts.p1_09,
            },
            edge: Edge {
                e00: p0parts.p0_02,
                e01: p0parts.p0_03,
                e02: p0parts.p0_04,
                e08: p0parts.p0_10,
                e09: p0parts.p0_09,
                e12: p0parts.p0_12,
                e16: p1parts.p1_02,
            },
            display_pins: DisplayPins {
                col1: p0parts.p0_28.into_push_pull_output(Level::High),
                col2: p0parts.p0_11.into_push_pull_output(Level::High),
                col3: p0parts.p0_31.into_push_pull_output(Level::High),
                col4: p1parts.p1_05.into_push_pull_output(Level::High),
                col5: p0parts.p0_30.into_push_pull_output(Level::High),
                row1: p0parts.p0_21.into_push_pull_output(Level::Low),
                row2: p0parts.p0_22.into_push_pull_output(Level::Low),
                row3: p0parts.p0_15.into_push_pull_output(Level::Low),
                row4: p0parts.p0_24.into_push_pull_output(Level::Low),
                row5: p0parts.p0_19.into_push_pull_output(Level::Low),
            },
            buttons: Buttons {
                button_a: p0parts.p0_14.into_floating_input(),
                button_b: p0parts.p0_23.into_floating_input(),
            },
            speaker_pin: p0parts.p0_00,
            microphone_pins: MicrophonePins {
                mic_in: p0parts.p0_05.into_floating_input(),
                mic_run: p0parts
                    .p0_20
                    .into_open_drain_output(Disconnect0HighDrive1, Level::Low),
            },
            i2c_internal: I2CInternalPins {
                scl: p0parts.p0_08.into_floating_input(),
                sda: p0parts.p0_16.into_floating_input(),
            },
            i2c_external: I2CExternalPins {
                scl: p0parts.p0_26.into_floating_input(),
                sda: p1parts.p1_00.into_floating_input(),
            },
            uart: UartPins {
                tx: p0parts.p0_06.into_push_pull_output(Level::High),
                rx: p1parts.p1_08.into_floating_input(),
            },

            // Core peripherals
            CBP: cp.CBP,
            CPUID: cp.CPUID,
            DCB: cp.DCB,
            DWT: cp.DWT,
            FPB: cp.FPB,
            FPU: cp.FPU,
            ITM: cp.ITM,
            MPU: cp.MPU,
            NVIC: cp.NVIC,
            SCB: cp.SCB,
            SYST: cp.SYST,
            TPIU: cp.TPIU,

            // nRF52 peripherals
            CLOCK: p.CLOCK,
            FICR: p.FICR,
            GPIOTE: p.GPIOTE,
            PPI: p.PPI,
            PWM0: p.PWM0,
            PWM1: p.PWM1,
            PWM2: p.PWM2,
            PWM3: p.PWM3,
            RADIO: p.RADIO,
            RNG: p.RNG,
            RTC0: p.RTC0,
            RTC1: p.RTC1,
            RTC2: p.RTC2,
            SPIM0: p.SPIM0,
            SPIM1: p.SPIM1,
            SPIM2: p.SPIM2,
            SPIM3: p.SPIM3,
            TEMP: p.TEMP,
            TIMER0: p.TIMER0,
            TIMER1: p.TIMER1,
            TIMER2: p.TIMER2,
            TIMER3: p.TIMER3,
            TIMER4: p.TIMER4,
            TWIM0: p.TWIM0,
            TWIS0: p.TWIS0,
            UARTE0: p.UARTE0,
            UARTE1: p.UARTE1,
            ADC: p.SAADC,
            SPI0: p.SPI0,
            SPI1: p.SPI1,
            SPI2: p.SPI2,
            POWER: p.POWER,
            UART0: p.UART0,
            TWI0: p.TWI0,
            TWI1: p.TWI1,
            SPIS1: p.SPIS1,
            ECB: p.ECB,
            AAR: p.AAR,
            CCM: p.CCM,
            WDT: p.WDT,
            QDEC: p.QDEC,
            LPCOMP: p.LPCOMP,
            NVMC: p.NVMC,
            UICR: p.UICR,
        }
    }
}

/// Unused GPIO pins
#[allow(missing_docs)]
pub struct Pins {
    // pub p0_00: p0::P0_00<Disconnected>, // Speaker
    pub p0_01: p0::P0_01<Disconnected>,
    // pub p0_02: p0::P0_02<Disconnected>, // PAD0, EDGE00
    // pub p0_03: p0::P0_03<Disconnected>, // PAD1, EDGE01
    // pub p0_04: p0::P0_04<Disconnected>, // PAD2, EDGE02
    // pub p0_05: p0::P0_05<Disconnected>, // Microphone IN
    // pub p0_06: p0::P0_06<Disconnected>, // UART RX
    pub p0_07: p0::P0_07<Disconnected>,
    // pub p0_08: p0::P0_08<Disconnected>, // INT_SCL
    // pub p0_09: p0::P0_09<Disconnected>, // EDGE09
    // pub p0_10: p0::P0_10<Disconnected>, // EDGE08
    // pub p0_11: p0::P0_11<Disconnected>, // LEDs
    // pub p0_12: p0::P0_12<Disconnected>, // EDGE12
    pub p0_13: p0::P0_13<Disconnected>,
    // pub p0_14: p0::P0_14<Disconnected>, // BTN_A
    // pub p0_15: p0::P0_15<Disconnected>, // LEDs
    // pub p0_16: p0::P0_16<Disconnected>, // INT_SDA
    pub p0_17: p0::P0_17<Disconnected>,
    pub p0_18: p0::P0_18<Disconnected>,
    // pub p0_19: p0::P0_19<Disconnected>, // LEDs
    // pub p0_20: p0::P0_20<Disconnected>, // Microphone RUN
    // pub p0_21: p0::P0_21<Disconnected>, // LEDs
    // pub p0_22: p0::P0_22<Disconnected>, // LEDs
    // pub p0_23: p0::P0_23<Disconnected>, // BTN_B
    // pub p0_24: p0::P0_24<Disconnected>, // LEDs
    pub p0_25: p0::P0_25<Disconnected>,
    // pub p0_26: p0::P0_26<Disconnected>, // SCL
    pub p0_27: p0::P0_27<Disconnected>,
    // pub p0_28: p0::P0_28<Disconnected>, // LEDs
    pub p0_29: p0::P0_29<Disconnected>,
    // pub p0_30: p0::P0_30<Disconnected>, // LEDs
    // pub p0_31: p0::P0_31<Disconnected>, // LEDs
    // pub p1_00: p1::P1_00<Disconnected>, // SDA
    pub p1_01: p1::P1_01<Disconnected>,
    // pub p1_02: p1::P1_02<Disconnected>, // EDGE16
    pub p1_03: p1::P1_03<Disconnected>,
    pub p1_04: p1::P1_04<Disconnected>,
    // pub p1_05: p1::P1_05<Disconnected>, // LEDs
    pub p1_06: p1::P1_06<Disconnected>,
    pub p1_07: p1::P1_07<Disconnected>,
    // pub p1_08: p1::P1_08<Disconnected>, // UART TX
    pub p1_09: p1::P1_09<Disconnected>,
}

/// Unused edge connector pins
#[allow(missing_docs)]
pub struct Edge {
    /* edge connector */
    // pub e03: COL3,
    pub e00: EDGE00<Disconnected>, // <- big pad 1
    // pub e04: COL1,
    // pub e05: BTN_A,
    // pub e06: COL4,
    // pub e07: COL2,
    pub e01: EDGE01<Disconnected>, // <- big pad 2
    pub e08: EDGE08<Disconnected>,
    pub e09: EDGE09<Disconnected>,
    // pub e10: COL5,
    // pub e11: BTN_B,
    pub e12: EDGE12<Disconnected>,
    pub e02: EDGE02<Disconnected>, // <- big pad 3
    //pub e13<MODE>: SCK<MODE>,
    //pub e14<MODE>: MISO<MODE>,
    //pub e15<MODE>: MOSI<MODE>,
    pub e16: EDGE16<Disconnected>,
    // +V
    // +V
    // +V
    // pub e19: SCL,
    // pub e20: SDA,
    // GND
    // GND
    // GND
}

/// Buttons
pub struct Buttons {
    /// Left hand button
    pub button_a: BTN_A,
    /// Right hand button
    pub button_b: BTN_B,
}

/// I2C internal bus pins
pub struct I2CInternalPins {
    /// Internal I2C clock pin
    pub scl: INT_SCL,
    /// Internal I2C data pin
    pub sda: INT_SDA,
}

impl From<I2CInternalPins> for twim::Pins {
    fn from(pins: I2CInternalPins) -> Self {
        Self {
            scl: pins.scl.degrade(),
            sda: pins.sda.degrade(),
        }
    }
}

impl From<I2CInternalPins> for twis::Pins {
    fn from(pins: I2CInternalPins) -> Self {
        Self {
            scl: pins.scl.degrade(),
            sda: pins.sda.degrade(),
        }
    }
}

/// I2C external bus pins
pub struct I2CExternalPins {
    /// External I2C clock pin
    pub scl: SCL,
    /// External I2C data pin
    pub sda: SDA,
}

impl From<I2CExternalPins> for twim::Pins {
    fn from(pins: I2CExternalPins) -> Self {
        Self {
            scl: pins.scl.degrade(),
            sda: pins.sda.degrade(),
        }
    }
}

impl From<I2CExternalPins> for twis::Pins {
    fn from(pins: I2CExternalPins) -> Self {
        Self {
            scl: pins.scl.degrade(),
            sda: pins.sda.degrade(),
        }
    }
}

/// UART to debugger pins
pub struct UartPins {
    tx: UART_TX,
    rx: UART_RX,
}

impl From<UartPins> for uarte::Pins {
    fn from(pins: UartPins) -> Self {
        Self {
            txd: pins.tx.degrade(),
            rxd: pins.rx.degrade(),
            cts: None,
            rts: None,
        }
    }
}


================================================
FILE: microbit-common/src/v2/gpio.rs
================================================
#![allow(clippy::upper_case_acronyms, missing_docs)]
use nrf52833_hal::gpio::{p0, p1, Floating, Input, OpenDrain, Output, Pin, PushPull};

/* GPIO pads */
pub type PAD0<MODE> = p0::P0_02<MODE>;
pub type PAD1<MODE> = p0::P0_03<MODE>;
pub type PAD2<MODE> = p0::P0_04<MODE>;

/* LED display */
pub const NUM_COLS: usize = 5;
pub type COL1 = p0::P0_28<Output<PushPull>>;
pub type COL2 = p0::P0_11<Output<PushPull>>;
pub type COL3 = p0::P0_31<Output<PushPull>>;
pub type COL4 = p1::P1_05<Output<PushPull>>;
pub type COL5 = p0::P0_30<Output<PushPull>>;

pub const NUM_ROWS: usize = 5;
pub type ROW1 = p0::P0_21<Output<PushPull>>;
pub type ROW2 = p0::P0_22<Output<PushPull>>;
pub type ROW3 = p0::P0_15<Output<PushPull>>;
pub type ROW4 = p0::P0_24<Output<PushPull>>;
pub type ROW5 = p0::P0_19<Output<PushPull>>;

/// GPIO pins connected to the LED matrix
///
/// Use the [display_pins] macro for easier construction.
pub struct DisplayPins {
    pub col1: COL1,
    pub col2: COL2,
    pub col3: COL3,
    pub col4: COL4,
    pub col5: COL5,
    pub row1: ROW1,
    pub row2: ROW2,
    pub row3: ROW3,
    pub row4: ROW4,
    pub row5: ROW5,
}

/// GPIO pins connected to the microphone
pub struct MicrophonePins {
    pub mic_in: p0::P0_05<Input<Floating>>,
    pub mic_run: p0::P0_20<Output<OpenDrain>>,
}

type LED = Pin<Output<PushPull>>;

impl DisplayPins {
    pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {
        (
            [
                self.col1.degrade(),
                self.col2.degrade(),
                self.col3.degrade(),
                self.col4.degrade(),
                self.col5.degrade(),
            ],
            [
                self.row1.degrade(),
                self.row2.degrade(),
                self.row3.degrade(),
                self.row4.degrade(),
                self.row5.degrade(),
            ],
        )
    }
}

/// Create [DisplayPins] from a [GPIO Parts](crate::hal::gpio::p0::Parts)
///
/// # Example
///
/// ```no_run
/// # use microbit_common as microbit;
/// use microbit::{
///     display_pins,
///     pac,
///     hal::gpio::{p0::Parts as P0Parts, p1::Parts as P1Parts},
/// };
///
/// // take the peripherals
/// let p = pac::Peripherals::take().unwrap();
/// // split off the P0 GPIO port
/// let p0parts = P0Parts::new(p.P0);
/// // split off the P1 GPIO port
/// let p1parts = P1Parts::new(p.P1);
///
/// let pins = display_pins!(p0parts, p1parts);
/// ```
#[macro_export]
macro_rules! display_pins {
    ( $p0parts:expr, $p1parts:expr ) => {{
        use microbit::{gpio::DisplayPins, hal::gpio::Level};

        DisplayPins {
            col1: $p0parts.p0_28.into_push_pull_output(Level::Low),
            col2: $p0parts.p0_11.into_push_pull_output(Level::Low),
            col3: $p0parts.p0_31.into_push_pull_output(Level::Low),
            col4: $p1parts.p1_05.into_push_pull_output(Level::Low),
            col5: $p0parts.p0_30.into_push_pull_output(Level::Low),
            row1: $p0parts.p0_21.into_push_pull_output(Level::Low),
            row2: $p0parts.p0_22.into_push_pull_output(Level::Low),
            row3: $p0parts.p0_15.into_push_pull_output(Level::Low),
            row4: $p0parts.p0_24.into_push_pull_output(Level::Low),
            row5: $p0parts.p0_19.into_push_pull_output(Level::Low),
        }
    }};
}

/* buttons */
pub type BTN_A = p0::P0_14<Input<Floating>>;
pub type BTN_B = p0::P0_23<Input<Floating>>;

/* spi */
pub type MOSI<MODE> = p0::P0_13<MODE>;
pub type MISO<MODE> = p0::P0_01<MODE>;
pub type SCK<MODE> = p0::P0_17<MODE>;

/* i2c - internal */
pub type INT_SCL = p0::P0_08<Input<Floating>>;
pub type INT_SDA = p0::P0_16<Input<Floating>>;

/* i2c - external */
pub type SCL = p0::P0_26<Input<Floating>>;
pub type SDA = p1::P1_00<Input<Floating>>;

/* uart */
pub type UART_TX = p0::P0_06<Output<PushPull>>;
pub type UART_RX = p1::P1_08<Input<Floating>>;

/* speaker */
pub type SPEAKER = p0::P0_00<Output<PushPull>>;

/* edge connector */
pub type EDGE03 = COL3;
pub type EDGE00<MODE> = PAD0<MODE>; // <- big pad 1
pub type EDGE04 = COL1;
pub type EDGE05 = BTN_A;
pub type EDGE06 = COL4;
pub type EDGE07 = COL2;
pub type EDGE01<MODE> = PAD1<MODE>; // <- big pad 2
pub type EDGE08<MODE> = p0::P0_10<MODE>;
pub type EDGE09<MODE> = p0::P0_09<MODE>;
pub type EDGE10 = COL5;
pub type EDGE11 = BTN_B;
pub type EDGE12<MODE> = p0::P0_12<MODE>;
pub type EDGE02<MODE> = PAD2<MODE>; // <- big pad 3
pub type EDGE13<MODE> = SCK<MODE>;
pub type EDGE14<MODE> = MISO<MODE>;
pub type EDGE15<MODE> = MOSI<MODE>;
pub type EDGE16<MODE> = p1::P1_02<MODE>;
// EDGE18 -> +V
// EDGE19 -> +V
// EDGE20 -> +V
pub type EDGE19 = SCL;
pub type EDGE20 = SDA;
// EDGE23 -> GND
// EDGE24 -> GND
// EDGE25 -> GND


================================================
FILE: microbit-common/src/v2/mod.rs
================================================
pub mod adc;
pub mod board;
pub mod gpio;


================================================
FILE: microbit-v2/Cargo.toml
================================================
[package]
name = "microbit-v2"
version = "0.16.0"
description = "Board support crate for the BBC Micro:bit V2"
edition = "2018"
readme = "../README.md"
rust-version = "1.79.0"

repository = "https://github.com/nrf-rs/microbit"
authors = [
  "Daniel Egger <daniel@eggers-club.de>",
  "Michael Droogleever <droogmic@gmail.com>",
  "Rob Young <rob@robyoung.digital>",
]
categories = ["hardware-support", "embedded", "no-std"]
keywords = ["arm", "cortex-m", "nrf", "hal"]
license = "0BSD"

[lib]
name = "microbit"
path = "src/lib.rs"

[dependencies]

[dependencies.microbit-common]
path = "../microbit-common"
features = ["v2"]
version = "=0.16.0"

[features]
embedded-hal-02 = ["microbit-common/embedded-hal-02"]


================================================
FILE: microbit-v2/src/lib.rs
================================================
//! microbit contains everything required to get started with the use of Rust
//! to create firmwares for the fabulous [BBC micro:bit](https://microbit.org)
//! microcontroller board.
//!
//! This crate is for the new micro:bit (V2) pictured below on the right. If
//! your micro:bit looks like the one on the left you need the
//! [microbit](https://crates.io/crates/microbit) crate.
//!
//! [<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)
//! [<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)
#![doc(html_root_url = "https://docs.rs/microbit-v2/0.16.0")]
#![no_std]
#![deny(missing_docs)]
#![allow(non_camel_case_types)]

pub use microbit_common::*;


================================================
FILE: tools/capture_example_bloat.sh
================================================
#!/bin/bash

filename="bloat_log_"`date -Iminutes`".txt"

for i in `find examples -name "*.rs"`; do
        name=$(echo $i | sed -e "s,examples/,,g" -e "s,\.rs,,g")
        echo "Processing example $name"
        echo >>$filename
        echo "Bloat for example $name" >>$filename
        cargo bloat --release --example $name >>$filename
done

echo "Captures bloat for all examples into $filename"


================================================
FILE: xtask/Cargo.toml
================================================
[package]
name = "xtask"
version = "0.1.0"
edition = "2018"

[dependencies]
cargo_toml = "0.22.3"
chrono = "0.4.44"


================================================
FILE: xtask/src/bump.rs
================================================
//! This has been copied pretty much wholesale from https://github.com/nrf-rs/nrf-hal/blob/master/xtask/src/lib.rs
use super::CRATES;
use chrono::Local;
use std::fs;

fn file_replace(path: &str, from: &str, to: &str, dry_run: bool) {
    let old_contents = fs::read_to_string(path).unwrap();
    let new_contents = old_contents.replacen(from, to, 1);
    if old_contents == new_contents {
        panic!("failed to replace `{}` -> `{}` in `{}`", from, to, path);
    }

    if !dry_run {
        fs::write(path, new_contents).unwrap();
    }
}

/// Bumps the versions of all crates and the changelog to `new_version`.
///
/// Dependency declarations are updated automatically. `html_root_url` is updated automatically.
pub fn bump_versions(new_version: &str, dry_run: bool) {
    let common_toml_path = "microbit-common/Cargo.toml";
    let toml = fs::read_to_string(common_toml_path).unwrap();

    let needle = "version = \"";
    let version_pos = toml.find(needle).unwrap() + needle.len();
    let version_rest = &toml[version_pos..];
    let end_pos = version_rest.find('"').unwrap();
    let old_version = &version_rest[..end_pos];

    {
        // Bump the changelog first, also check that it isn't empty.
        let changelog_path = "CHANGELOG.md";
        let changelog = fs::read_to_string(changelog_path).unwrap();
        // (ignore empty changelog when this is a dry_run, since that runs in normal CI)
        assert!(
            dry_run || !changelog.contains("(no changes)"),
            "changelog contains `(no changes)`; please fill it"
        );

        // Prepend empty "[Unreleased]" section, promote the current one.
        let today = Local::now().date_naive().format("%Y-%m-%d").to_string();
        let from = String::from("## [Unreleased]");
        let to = format!(
            "## [Unreleased]\n\n(no changes)\n\n## [{}] - {}",
            new_version, today
        );
        file_replace(changelog_path, &from, &to, dry_run);

        // Replace the Unreleased link
        let from = format!(
            r#"[Unreleased]: https://github.com/nrf-rs/microbit/compare/v{old_version}...HEAD"#,
            old_version = old_version,
        );
        let to = format!(
            "[Unreleased]: https://github.com/nrf-rs/microbit/compare/v{new_version}...HEAD\n\
             [{new_version}]: https://github.com/nrf-rs/microbit/compare/v{old_version}...v{new_version}",
            new_version = new_version,
            old_version = old_version,
        );
        file_replace(changelog_path, &from, &to, dry_run);
    }

    {
        println!("microbit-common: {} -> {}", old_version, new_version);

        // Bump `microbit-common`'s version.
        let from = format!(r#"version = "{}""#, old_version);
        let to = format!(r#"version = "{}""#, new_version);
        file_replace("microbit-common/Cargo.toml", &from, &to, dry_run);

        // Bump the `html_root_url`.
        let from = format!(
            r#"#![doc(html_root_url = "https://docs.rs/microbit-common/{old_version}")]"#,
            old_version = old_version
        );
        let to = format!(
            r#"#![doc(html_root_url = "https://docs.rs/microbit-common/{new_version}")]"#,
            new_version = new_version
        );
        let librs_path = "microbit-common/src/lib.rs";
        file_replace(librs_path, &from, &to, dry_run);
    }

    for (crate_name, _, _) in CRATES {
        println!("{}: {} -> {}", crate_name, old_version, new_version);
        let toml_path = format!("{}/Cargo.toml", crate_name);

        // Bump the crate's version.
        let from = format!(r#"version = "{}""#, old_version);
        let to = format!(r#"version = "{}""#, new_version);
        file_replace(&toml_path, &from, &to, dry_run);

        // Bump the crate's dependency on `microbit-common`.
        let from = format!(r#"version = "={}""#, old_version);
        let to = format!(r#"version = "={}""#, new_version);
        file_replace(&toml_path, &from, &to, dry_run);

        // Bump the crate's `html_root_url`.
        let from = format!(
            r#"#![doc(html_root_url = "https://docs.rs/{crate}/{old_version}")]"#,
            crate = crate_name,
            old_version = old_version
        );
        let to = format!(
            r#"#![doc(html_root_url = "https://docs.rs/{crate}/{new_version}")]"#,
            crate = crate_name,
            new_version = new_version
        );
        let librs_path = format!("{}/src/lib.rs", crate_name);
        file_replace(&librs_path, &from, &to, dry_run);
    }
}


================================================
FILE: xtask/src/ci.rs
================================================
use super::CRATES;
use std::{collections::HashMap, env, fs, path, process::Command};

pub static DEPENDENCIES: &[&str] = &["flip-link"];

fn install_targets() {
    let targets = CRATES
        .iter()
        .map(|(_, target, _)| *target)
        .collect::<Vec<_>>();

    let mut rustup = Command::new("rustup");
    rustup.args(&["target", "add"]).args(&targets);
    let status = rustup
        .status()
        .map_err(|e| format!("couldn't execute {:?}: {}", rustup, e))
        .unwrap();
    assert!(
        status.success(),
        "failed to install targets with rustup: {:?}",
        rustup
    );
}

/// Install global dependencies
fn install_dependencies() {
    for dependency in DEPENDENCIES {
        let exists = Command::new("which")
            .arg(dependency)
            .output()
            .expect("failed to execute");
        if !exists.status.success() {
            let mut cargo = Command::new("cargo");
            cargo.args(&["install", dependency]);
            let status = cargo
                .status()
                .map_err(|e| format!("couldn't execute {:?}: {}", cargo, e))
                .unwrap();
            assert!(status.success(),);
        }
    }
}

/// Build-test each board support crate
fn build_crates() {
    for (hal, target, _) in CRATES {
        let mut cargo = Command::new("cargo");
        let toml_path = format!("{}/Cargo.toml", hal);
        let status = cargo
            .args(&["build", "--manifest-path", &toml_path, "--target", target])
            .status()
            .map_err(|e| format!("could not execute {:?}: {}", cargo, e))
            .unwrap();
        assert!(
            status.success(),
            "command exited with error status: {:?}",
            cargo
        );
    }
}

/// Build/Run doc-tests in `microbit-common` for each version.
fn build_run_doc_tests() {
    for (_, _, feature) in CRATES {
        let mut cargo = Command::new("cargo");
        let status = cargo
            .current_dir("microbit-common")
            .args(&["test", "--features", feature])
            .status()
            .map_err(|e| format!("could not execute {:?}: {}", cargo, e))
            .unwrap();
        assert!(
            status.success(),
            "command exited with error status: {:?}",
            cargo
        );
    }
}

/// Build all examples with the boards they support
fn build_examples() {
    let feature_targets = CRATES
        .iter()
        .map(|(_, target, feature)| (feature.to_string(), target.to_string()))
        .collect::<HashMap<_, _>>();

    let crate_targets = CRATES
        .iter()
        .map(|(name, target, _)| (name.to_string(), target.to_string()))
        .collect::<HashMap<_, _>>();

    for example in fs::read_dir("examples").unwrap() {
        let dir = example.unwrap();
        let manifest_path = dir.path().join("Cargo.toml");

        // Skip if there is no manifest
        if !manifest_path.exists() {
            continue;
        }

        let manifest = cargo_toml::Manifest::from_path(&manifest_path).unwrap();

        // find features and their targets supported by the example
        let mut features = manifest
            .features
            .keys()
            .filter_map(|feature| {
                feature_targets
                    .get(feature)
                    .map(|target| (Some(feature.to_owned()), target.to_owned()))
            })
            .collect::<Vec<_>>();

        // if there are no features find the target from the dependencies
        if features.is_empty() {
            features = manifest
                .dependencies
                .keys()
                .filter_map(|name| {
                    crate_targets
                        .get(name)
                        .map(|target| (None, target.to_owned()))
                })
                .collect::<Vec<_>>();
            assert_eq!(
                features.len(),
                1,
                "examples must depend on either microbit or microbit-v2"
            );
        }

        for (feature, target) in features {
            build_example(&manifest_path, feature, target);
        }
    }
}

fn build_example(manifest_path: &path::Path, feature: Option<String>, target: String) {
    let mut cargo = Command::new("cargo");
    cargo.args(&[
        "build",
        "--target",
        &target,
        "--manifest-path",
        manifest_path.to_str().unwrap(),
    ]);
    if let Some(feature) = feature {
        cargo.args(&["--features", &feature]);
    }

    let status = cargo
        .status()
        .map_err(|e| format!("could not execute {:?}: {}", cargo, e))
        .unwrap();

    assert!(
        status.success(),
        "command exited with error status: {:?}",
        cargo
    );
}

fn start_group(is_ci: bool, name: &str) {
    if is_ci {
        println!("::group::{}", name);
    }
}

fn end_group(is_ci: bool) {
    if is_ci {
        println!("::endgroup::");
    }
}

fn wrap_in_group(is_ci: bool, name: &str, callable: &dyn Fn()) {
    start_group(is_ci, name);
    callable();
    end_group(is_ci);
}

pub fn ci() {
    let is_ci = env::var("CI").map_or(false, |ci| ci == "true");

    // move up if we're running from inside xtask
    if env::current_dir().unwrap().ends_with("xtask") {
        env::set_current_dir("..").unwrap();
    }

    wrap_in_group(is_ci, "install targets", &install_targets);
    wrap_in_group(is_ci, "install dependencies", &install_dependencies);
    wrap_in_group(is_ci, "build crates", &build_crates);
    wrap_in_group(is_ci, "build examples", &build_examples);
    wrap_in_group(is_ci, "run doc tests", &build_run_doc_tests);
}


================================================
FILE: xtask/src/lib.rs
================================================
mod bump;
mod ci;
mod publish;

pub static CRATES: &[(&str, &str, &str)] = &[
    ("microbit", "thumbv6m-none-eabi", "v1"),
    ("microbit-v2", "thumbv7em-none-eabihf", "v2"),
];

pub use bump::bump_versions;
pub use ci::ci;
pub use publish::publish;


================================================
FILE: xtask/src/main.rs
================================================
use std::env;

use xtask::{bump_versions, ci, publish};

fn main() {
    let mut args = env::args().skip(1);
    let subcommand = args.next();
    match subcommand.as_deref() {
        Some("bump") => {
            let new_version = args.next().expect("missing <semver> argument");
            bump_versions(&new_version, false);
        }
        Some("ci") => ci(),
        Some("publish") => publish(),
        _ => {
            eprintln!("usage: cargo xtask <subcommand>");
            eprintln!();
            eprintln!("subcommands:");
            eprintln!("  ci      - run continuous integration checks (build and clippy)");
            eprintln!("  bump    - bump the crate version and update docs and changelog");
            eprintln!("  publish - publish all crates to crates.io");
        }
    }
}


================================================
FILE: xtask/src/publish.rs
================================================
use std::process::Command;

use crate::CRATES;

pub fn publish() {
    publish_package("microbit-common", "thumbv7em-none-eabihf", Some("v2"));

    for (name, target, _) in CRATES {
        publish_package(name, target, None);
    }
}

fn publish_package(package: &str, target: &str, feature: Option<&str>) {
    let mut cargo = Command::new("cargo");
    cargo.args(&["publish", "--target", target, "--package", package]);
    if let Some(feature) = feature {
        cargo.args(&["--features", feature]);
    }

    let status = cargo
        .status()
        .map_err(|e| format!("could not execute {:?}: {}", cargo, e))
        .unwrap();

    assert!(
        status.success(),
        "command exited with error status: {:?}",
        cargo
    );
}
Download .txt
gitextract_ax2jxq_v/

├── .cargo/
│   └── config.toml
├── .github/
│   ├── dependabot.yml
│   └── workflows/
│       ├── changelog.yml
│       ├── ci.yaml
│       ├── clippy.yml
│       └── rustfmt.yml
├── .gitignore
├── CHANGELOG.md
├── Cargo.toml
├── LICENSE-0BSD.txt
├── README.md
├── build.rs
├── examples/
│   ├── analog/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── analog-v1/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── analog-v2/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-blocking/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-nonblocking/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-rtic/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── display-text-rtic/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-direct-blinky/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-blinky/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-ledbutton/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── gpio-hal-printbuttons/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── magnetometer/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── rng-direct/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── rng-hal/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-direct-echo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-direct-helloworld/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── serial-hal-blocking-echo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── main.rs
│   │       └── serial_setup.rs
│   ├── servo/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   ├── v2-microphone/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       └── main.rs
│   └── v2-speaker/
│       ├── Cargo.toml
│       └── src/
│           └── main.rs
├── memory.x
├── microbit/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── microbit-common/
│   ├── Cargo.toml
│   └── src/
│       ├── adc.rs
│       ├── board.rs
│       ├── display/
│       │   ├── blocking.rs
│       │   ├── mod.rs
│       │   └── nonblocking/
│       │       ├── control.rs
│       │       ├── image.rs
│       │       ├── matrix.rs
│       │       ├── mod.rs
│       │       └── timer.rs
│       ├── gpio.rs
│       ├── lib.rs
│       ├── v1/
│       │   ├── adc.rs
│       │   ├── board.rs
│       │   ├── gpio.rs
│       │   └── mod.rs
│       └── v2/
│           ├── adc.rs
│           ├── board.rs
│           ├── gpio.rs
│           └── mod.rs
├── microbit-v2/
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs
├── tools/
│   └── capture_example_bloat.sh
└── xtask/
    ├── Cargo.toml
    └── src/
        ├── bump.rs
        ├── ci.rs
        ├── lib.rs
        ├── main.rs
        └── publish.rs
Download .txt
SYMBOL INDEX (271 symbols across 38 files)

FILE: build.rs
  function main (line 6) | fn main() {

FILE: examples/analog-v1/src/main.rs
  function main (line 15) | fn main() -> ! {

FILE: examples/analog-v2/src/main.rs
  function main (line 15) | fn main() -> ! {

FILE: examples/analog/src/main.rs
  function main (line 16) | fn main() -> ! {

FILE: examples/display-blocking/src/main.rs
  function main (line 12) | fn main() -> ! {

FILE: examples/display-nonblocking/src/main.rs
  function heart_image (line 21) | fn heart_image(inner_brightness: u8) -> GreyscaleImage {
  function main (line 39) | fn main() -> ! {
  function TIMER1 (line 72) | fn TIMER1() {
  function RTC0 (line 81) | unsafe fn RTC0() {

FILE: examples/display-rtic/src/main.rs
  function heart_image (line 28) | fn heart_image(inner_brightness: u8) -> GreyscaleImage {
  type Shared (line 40) | struct Shared {
  type Local (line 45) | struct Local {
  function init (line 50) | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
  function timer1 (line 72) | fn timer1(mut cx: timer1::Context) {
  function rtc0 (line 80) | fn rtc0(cx: rtc0::Context) {

FILE: examples/display-text-rtic/src/main.rs
  constant MESSAGE (line 27) | const MESSAGE: &[u8] = b"Hello, world!";
  type Shared (line 30) | struct Shared {
  type Local (line 35) | struct Local {
  function init (line 41) | fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {
  function timer1 (line 70) | fn timer1(mut cx: timer1::Context) {
  function rtc0 (line 79) | fn rtc0(cx: rtc0::Context) {

FILE: examples/gpio-direct-blinky/src/main.rs
  function main (line 10) | fn main() -> ! {
  function main (line 40) | fn main() -> ! {

FILE: examples/gpio-hal-blinky/src/main.rs
  function main (line 11) | fn main() -> ! {

FILE: examples/gpio-hal-ledbutton/src/main.rs
  function main (line 12) | fn main() -> ! {

FILE: examples/gpio-hal-printbuttons/src/main.rs
  function main (line 20) | fn main() -> ! {
  function GPIOTE (line 59) | fn GPIOTE() {

FILE: examples/magnetometer/src/main.rs
  function main (line 26) | fn main() -> ! {
  type Sensor (line 78) | type Sensor = Lsm303agr<I2cInterface<twi::Twi<TWI0>>, MagOneShot>;
  type Sensor (line 81) | type Sensor = Lsm303agr<I2cInterface<twim::Twim<TWIM0>>, MagOneShot>;
  function get_data (line 83) | fn get_data(sensor: &mut Sensor) {

FILE: examples/rng-direct/src/main.rs
  function main (line 18) | fn main() -> ! {
  function RTC0 (line 59) | fn RTC0() {

FILE: examples/rng-hal/src/main.rs
  function main (line 26) | fn main() -> ! {
  function RTC0 (line 65) | fn RTC0() {

FILE: examples/serial-direct-echo/src/main.rs
  function main (line 10) | fn main() -> ! {
  function write_uart0 (line 55) | fn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Resu...

FILE: examples/serial-direct-helloworld/src/main.rs
  function main (line 9) | fn main() -> ! {
  function write_uart0 (line 28) | fn write_uart0(uart0: &microbit::pac::UART0, s: &str) -> core::fmt::Resu...

FILE: examples/serial-hal-blocking-echo/src/main.rs
  function main (line 28) | fn main() -> ! {

FILE: examples/serial-hal-blocking-echo/src/serial_setup.rs
  type UartePort (line 7) | pub struct UartePort<T: Instance>(UarteTx<T>, UarteRx<T>);
  function new (line 10) | pub fn new(serial: Uarte<T>) -> UartePort<T> {
  function write_str (line 21) | fn write_str(&mut self, s: &str) -> fmt::Result {
  type Error (line 27) | type Error = Error;
  function write (line 31) | fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {
  function flush (line 35) | fn flush(&mut self) -> Result<(), Self::Error> {
  function read (line 41) | fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {

FILE: examples/servo/src/main.rs
  function main (line 24) | fn main() -> ! {
  function TIMER0 (line 93) | fn TIMER0() {

FILE: examples/v2-microphone/src/main.rs
  function main (line 19) | fn main() -> ! {

FILE: examples/v2-speaker/src/main.rs
  function main (line 26) | fn main() -> ! {
  constant STOP_FREQUENCY (line 84) | const STOP_FREQUENCY: u32 = 500;
  function RTC0 (line 88) | fn RTC0() {

FILE: microbit-common/src/display/blocking.rs
  type LED (line 71) | pub(crate) type LED = Pin<Output<PushPull>>;
  constant DEFAULT_DELAY_MS (line 73) | const DEFAULT_DELAY_MS: u32 = 2;
  constant LED_LAYOUT (line 75) | const LED_LAYOUT: [[(usize, usize); 5]; 5] = [
  type Display (line 84) | pub struct Display {
    method new (line 95) | pub fn new(pins: DisplayPins) -> Self {
    method clear (line 105) | pub fn clear(&mut self) {
    method set_delay_ms (line 115) | pub fn set_delay_ms(&mut self, delay_ms: u32) {
    method set_refresh_rate (line 120) | pub fn set_refresh_rate(&mut self, freq_hz: u32) {
    method image2matrix (line 129) | fn image2matrix(led_image: [[u8; 5]; 5]) -> [[u8; 9]; 3] {
    method show (line 140) | pub fn show<D: DelayNs>(&mut self, delay: &mut D, led_display: [[u8; 5...
    method show_inner (line 154) | fn show_inner<D: DelayNs>(

FILE: microbit-common/src/display/nonblocking/control.rs
  function pin_bits (line 14) | const fn pin_bits(pins: &[usize]) -> u32 {
  constant P0_COLS (line 27) | pub(super) const P0_COLS: [usize; NUM_COLS] = [4, 5, 6, 7, 8, 9, 10, 11,...
  constant P0_ROWS (line 28) | pub(super) const P0_ROWS: [usize; NUM_ROWS] = [13, 14, 15];
  constant P0_COLS (line 34) | pub(super) const P0_COLS: [usize; NUM_COLS - 1] = [28, 11, 31, 30];
  constant P1_COLS (line 35) | pub(super) const P1_COLS: [usize; 1] = [5];
  constant P0_ROWS (line 37) | pub(super) const P0_ROWS: [usize; NUM_ROWS] = [21, 22, 15, 24, 19];
  constant P0_COL_BITS (line 40) | const P0_COL_BITS: u32 = pin_bits(&pins::P0_COLS);
  constant P1_COL_BITS (line 42) | const P1_COL_BITS: u32 = pin_bits(&pins::P1_COLS);
  constant P0_ROW_BITS (line 44) | const P0_ROW_BITS: u32 = pin_bits(&pins::P0_ROWS);
  type P0 (line 47) | type P0 = pac::GPIO;
  type P0 (line 50) | type P0 = pac::P0;
  type P1 (line 53) | type P1 = pac::P1;
  type MicrobitGpio (line 58) | pub(crate) struct MicrobitGpio;
  function column_pins (line 61) | fn column_pins(mut cols: u32, px_cols: &[usize]) -> u32 {
  function split_cols (line 71) | fn split_cols(cols: u32) -> (u32, u32) {
  function split_cols (line 76) | fn split_cols(cols: u32) -> (u32, u32) {
  method initialise_for_display (line 93) | fn initialise_for_display(&mut self) {
  method display_row_leds (line 120) | fn display_row_leds(&mut self, row: usize, cols: u32) {
  method light_current_row_leds (line 157) | fn light_current_row_leds(&mut self, cols: u32) {

FILE: microbit-common/src/display/nonblocking/image.rs
  type GreyscaleImage (line 9) | pub struct GreyscaleImage([[u8; 5]; 5]);
    method new (line 30) | pub const fn new(data: &[[u8; 5]; 5]) -> GreyscaleImage {
    method blank (line 35) | pub const fn blank() -> GreyscaleImage {
  method brightness_at (line 41) | fn brightness_at(&self, x: usize, y: usize) -> u8 {
  method brightness_at (line 47) | fn brightness_at(&self, x: usize, y: usize) -> u8 {
  type BitImage (line 59) | pub struct BitImage([u8; 5]);
    method new (line 80) | pub const fn new(im: &[[u8; 5]; 5]) -> BitImage {
    method blank (line 97) | pub const fn blank() -> BitImage {
  method brightness_at (line 103) | fn brightness_at(&self, x: usize, y: usize) -> u8 {
  method brightness_at (line 114) | fn brightness_at(&self, x: usize, y: usize) -> u8 {

FILE: microbit-common/src/display/nonblocking/matrix.rs
  type MicrobitMatrix (line 15) | pub struct MicrobitMatrix();
  constant MICROBIT_LED_LAYOUT (line 20) | const MICROBIT_LED_LAYOUT: [[Option<(usize, usize)>; 3]; 9] = [
  constant MATRIX_COLS (line 34) | const MATRIX_COLS: usize = NUM_COLS;
  constant MATRIX_ROWS (line 36) | const MATRIX_ROWS: usize = NUM_ROWS;
  constant IMAGE_COLS (line 38) | const IMAGE_COLS: usize = 5;
  constant IMAGE_ROWS (line 40) | const IMAGE_ROWS: usize = 5;
  method image_coordinates (line 43) | fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {
  method image_coordinates (line 48) | fn image_coordinates(col: usize, row: usize) -> Option<(usize, usize)> {
  type MicrobitFrame (line 64) | pub struct MicrobitFrame([RowPlan; MicrobitFrame::ROWS]);
    method default (line 68) | pub const fn default() -> MicrobitFrame {
  method default (line 75) | fn default() -> MicrobitFrame {
  type Mtx (line 81) | type Mtx = MicrobitMatrix;
  method row_plan (line 83) | fn row_plan(&self, row: usize) -> &RowPlan {
  method row_plan_mut (line 87) | fn row_plan_mut(&mut self, row: usize) -> &mut RowPlan {

FILE: microbit-common/src/display/nonblocking/mod.rs
  type Display (line 176) | pub struct Display<T: Instance> {
  function new (line 188) | pub fn new(timer: T, pins: DisplayPins) -> Self {
  function free (line 200) | pub fn free(self) -> (T, DisplayPins) {
  function initialise (line 208) | fn initialise(&mut self) {
  function handle_display_event (line 223) | pub fn handle_display_event(&mut self) {
  function show (line 247) | pub fn show<R: tiny_led_matrix::Render>(&mut self, image: &R) {
  function clear (line 259) | pub fn clear(&mut self) {
  function show_frame (line 290) | pub fn show_frame(&mut self, frame: &MicrobitFrame) {

FILE: microbit-common/src/display/nonblocking/timer.rs
  type MicrobitDisplayTimer (line 25) | pub struct MicrobitDisplayTimer<T: Instance>(T);
  function new (line 31) | pub fn new(timer: T) -> MicrobitDisplayTimer<T> {
  function free (line 36) | pub fn free(self) -> T {
  method initialise_cycle (line 42) | fn initialise_cycle(&mut self, ticks: u16) {
  method enable_secondary (line 74) | fn enable_secondary(&mut self) {
  method disable_secondary (line 78) | fn disable_secondary(&mut self) {
  method program_secondary (line 85) | fn program_secondary(&mut self, ticks: u16) {
  method check_primary (line 92) | fn check_primary(&mut self) -> bool {
  method check_secondary (line 102) | fn check_secondary(&mut self) -> bool {

FILE: microbit-common/src/v1/adc.rs
  type Adc (line 4) | pub type Adc = hal::Adc;
  type AdcConfig (line 6) | pub type AdcConfig = hal::adc::AdcConfig;
  type Default (line 9) | pub trait Default {
    method default_10bit (line 11) | fn default_10bit() -> Self;
    method default_10bit (line 15) | fn default_10bit() -> Self {

FILE: microbit-common/src/v1/board.rs
  type Board (line 15) | pub struct Board {
    method take (line 163) | pub fn take() -> Option<Self> {
    method new (line 177) | pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {
  type Pins (line 279) | pub struct Pins {
  type Edge (line 315) | pub struct Edge {
  type Buttons (line 344) | pub struct Buttons {
  type I2CPins (line 352) | pub struct I2CPins {
  function from (line 360) | fn from(pins: I2CPins) -> Self {
  type UartPins (line 369) | pub struct UartPins {
  function from (line 375) | fn from(pins: UartPins) -> Self {

FILE: microbit-common/src/v1/gpio.rs
  type PAD0 (line 11) | pub type PAD0<MODE> = p0::P0_03<MODE>;
  type PAD1 (line 12) | pub type PAD1<MODE> = p0::P0_02<MODE>;
  type PAD2 (line 13) | pub type PAD2<MODE> = p0::P0_01<MODE>;
  constant NUM_COLS (line 16) | pub const NUM_COLS: usize = 9;
  type COL1 (line 17) | pub type COL1 = p0::P0_04<Output<PushPull>>;
  type COL2 (line 18) | pub type COL2 = p0::P0_05<Output<PushPull>>;
  type COL3 (line 19) | pub type COL3 = p0::P0_06<Output<PushPull>>;
  type COL4 (line 20) | pub type COL4 = p0::P0_07<Output<PushPull>>;
  type COL5 (line 21) | pub type COL5 = p0::P0_08<Output<PushPull>>;
  type COL6 (line 22) | pub type COL6 = p0::P0_09<Output<PushPull>>;
  type COL7 (line 23) | pub type COL7 = p0::P0_10<Output<PushPull>>;
  type COL8 (line 24) | pub type COL8 = p0::P0_11<Output<PushPull>>;
  type COL9 (line 25) | pub type COL9 = p0::P0_12<Output<PushPull>>;
  constant NUM_ROWS (line 27) | pub const NUM_ROWS: usize = 3;
  type ROW1 (line 28) | pub type ROW1 = p0::P0_13<Output<PushPull>>;
  type ROW2 (line 29) | pub type ROW2 = p0::P0_14<Output<PushPull>>;
  type ROW3 (line 30) | pub type ROW3 = p0::P0_15<Output<PushPull>>;
  type DisplayPins (line 40) | pub struct DisplayPins {
    method degrade (line 58) | pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {
  type LED (line 55) | type LED = Pin<Output<PushPull>>;
  type BTN_A (line 122) | pub type BTN_A = p0::P0_17<Input<Floating>>;
  type BTN_B (line 123) | pub type BTN_B = p0::P0_26<Input<Floating>>;
  type MOSI (line 126) | pub type MOSI<MODE> = p0::P0_21<MODE>;
  type MISO (line 127) | pub type MISO<MODE> = p0::P0_22<MODE>;
  type SCK (line 128) | pub type SCK<MODE> = p0::P0_23<MODE>;
  type SCL (line 131) | pub type SCL = p0::P0_00<Input<Floating>>;
  type SDA (line 132) | pub type SDA = p0::P0_30<Input<Floating>>;
  type UART_TX (line 135) | pub type UART_TX = p0::P0_24<Output<PushPull>>;
  type UART_RX (line 136) | pub type UART_RX = p0::P0_25<Input<Floating>>;
  type EDGE03 (line 139) | pub type EDGE03 = COL1;
  type EDGE00 (line 140) | pub type EDGE00<MODE> = PAD0<MODE>;
  type EDGE04 (line 141) | pub type EDGE04 = COL2;
  type EDGE05 (line 142) | pub type EDGE05 = BTN_A;
  type EDGE06 (line 143) | pub type EDGE06 = COL9;
  type EDGE07 (line 144) | pub type EDGE07 = COL8;
  type EDGE01 (line 145) | pub type EDGE01<MODE> = PAD1<MODE>;
  type EDGE08 (line 146) | pub type EDGE08<MODE> = p0::P0_18<MODE>;
  type EDGE09 (line 147) | pub type EDGE09 = COL7;
  type EDGE10 (line 148) | pub type EDGE10 = COL3;
  type EDGE11 (line 149) | pub type EDGE11 = BTN_B;
  type EDGE12 (line 150) | pub type EDGE12<MODE> = p0::P0_20<MODE>;
  type EDGE02 (line 151) | pub type EDGE02<MODE> = PAD2<MODE>;
  type EDGE13 (line 152) | pub type EDGE13<MODE> = SCK<MODE>;
  type EDGE14 (line 153) | pub type EDGE14<MODE> = MISO<MODE>;
  type EDGE15 (line 154) | pub type EDGE15<MODE> = MOSI<MODE>;
  type EDGE16 (line 155) | pub type EDGE16<MODE> = p0::P0_16<MODE>;
  type EDGE19 (line 159) | pub type EDGE19 = SCL;
  type EDGE20 (line 160) | pub type EDGE20 = SDA;

FILE: microbit-common/src/v2/adc.rs
  type Adc (line 4) | pub type Adc = hal::Saadc;
  type AdcConfig (line 6) | pub type AdcConfig = hal::saadc::SaadcConfig;
  type Default (line 9) | pub trait Default {
    method default_10bit (line 11) | fn default_10bit() -> Self;
    method default_10bit (line 15) | fn default_10bit() -> Self {

FILE: microbit-common/src/v2/board.rs
  type Board (line 15) | pub struct Board {
    method take (line 220) | pub fn take() -> Option<Self> {
    method new (line 234) | pub fn new(p: pac::Peripherals, cp: pac::CorePeripherals) -> Self {
  type Pins (line 371) | pub struct Pins {
  type Edge (line 418) | pub struct Edge {
  type Buttons (line 448) | pub struct Buttons {
  type I2CInternalPins (line 456) | pub struct I2CInternalPins {
  function from (line 464) | fn from(pins: I2CInternalPins) -> Self {
  function from (line 473) | fn from(pins: I2CInternalPins) -> Self {
  type I2CExternalPins (line 482) | pub struct I2CExternalPins {
  function from (line 490) | fn from(pins: I2CExternalPins) -> Self {
  function from (line 499) | fn from(pins: I2CExternalPins) -> Self {
  type UartPins (line 508) | pub struct UartPins {
  function from (line 514) | fn from(pins: UartPins) -> Self {

FILE: microbit-common/src/v2/gpio.rs
  type PAD0 (line 5) | pub type PAD0<MODE> = p0::P0_02<MODE>;
  type PAD1 (line 6) | pub type PAD1<MODE> = p0::P0_03<MODE>;
  type PAD2 (line 7) | pub type PAD2<MODE> = p0::P0_04<MODE>;
  constant NUM_COLS (line 10) | pub const NUM_COLS: usize = 5;
  type COL1 (line 11) | pub type COL1 = p0::P0_28<Output<PushPull>>;
  type COL2 (line 12) | pub type COL2 = p0::P0_11<Output<PushPull>>;
  type COL3 (line 13) | pub type COL3 = p0::P0_31<Output<PushPull>>;
  type COL4 (line 14) | pub type COL4 = p1::P1_05<Output<PushPull>>;
  type COL5 (line 15) | pub type COL5 = p0::P0_30<Output<PushPull>>;
  constant NUM_ROWS (line 17) | pub const NUM_ROWS: usize = 5;
  type ROW1 (line 18) | pub type ROW1 = p0::P0_21<Output<PushPull>>;
  type ROW2 (line 19) | pub type ROW2 = p0::P0_22<Output<PushPull>>;
  type ROW3 (line 20) | pub type ROW3 = p0::P0_15<Output<PushPull>>;
  type ROW4 (line 21) | pub type ROW4 = p0::P0_24<Output<PushPull>>;
  type ROW5 (line 22) | pub type ROW5 = p0::P0_19<Output<PushPull>>;
  type DisplayPins (line 27) | pub struct DisplayPins {
    method degrade (line 49) | pub fn degrade(self) -> ([LED; NUM_COLS], [LED; NUM_ROWS]) {
  type MicrophonePins (line 41) | pub struct MicrophonePins {
  type LED (line 46) | type LED = Pin<Output<PushPull>>;
  type BTN_A (line 111) | pub type BTN_A = p0::P0_14<Input<Floating>>;
  type BTN_B (line 112) | pub type BTN_B = p0::P0_23<Input<Floating>>;
  type MOSI (line 115) | pub type MOSI<MODE> = p0::P0_13<MODE>;
  type MISO (line 116) | pub type MISO<MODE> = p0::P0_01<MODE>;
  type SCK (line 117) | pub type SCK<MODE> = p0::P0_17<MODE>;
  type INT_SCL (line 120) | pub type INT_SCL = p0::P0_08<Input<Floating>>;
  type INT_SDA (line 121) | pub type INT_SDA = p0::P0_16<Input<Floating>>;
  type SCL (line 124) | pub type SCL = p0::P0_26<Input<Floating>>;
  type SDA (line 125) | pub type SDA = p1::P1_00<Input<Floating>>;
  type UART_TX (line 128) | pub type UART_TX = p0::P0_06<Output<PushPull>>;
  type UART_RX (line 129) | pub type UART_RX = p1::P1_08<Input<Floating>>;
  type SPEAKER (line 132) | pub type SPEAKER = p0::P0_00<Output<PushPull>>;
  type EDGE03 (line 135) | pub type EDGE03 = COL3;
  type EDGE00 (line 136) | pub type EDGE00<MODE> = PAD0<MODE>;
  type EDGE04 (line 137) | pub type EDGE04 = COL1;
  type EDGE05 (line 138) | pub type EDGE05 = BTN_A;
  type EDGE06 (line 139) | pub type EDGE06 = COL4;
  type EDGE07 (line 140) | pub type EDGE07 = COL2;
  type EDGE01 (line 141) | pub type EDGE01<MODE> = PAD1<MODE>;
  type EDGE08 (line 142) | pub type EDGE08<MODE> = p0::P0_10<MODE>;
  type EDGE09 (line 143) | pub type EDGE09<MODE> = p0::P0_09<MODE>;
  type EDGE10 (line 144) | pub type EDGE10 = COL5;
  type EDGE11 (line 145) | pub type EDGE11 = BTN_B;
  type EDGE12 (line 146) | pub type EDGE12<MODE> = p0::P0_12<MODE>;
  type EDGE02 (line 147) | pub type EDGE02<MODE> = PAD2<MODE>;
  type EDGE13 (line 148) | pub type EDGE13<MODE> = SCK<MODE>;
  type EDGE14 (line 149) | pub type EDGE14<MODE> = MISO<MODE>;
  type EDGE15 (line 150) | pub type EDGE15<MODE> = MOSI<MODE>;
  type EDGE16 (line 151) | pub type EDGE16<MODE> = p1::P1_02<MODE>;
  type EDGE19 (line 155) | pub type EDGE19 = SCL;
  type EDGE20 (line 156) | pub type EDGE20 = SDA;

FILE: xtask/src/bump.rs
  function file_replace (line 6) | fn file_replace(path: &str, from: &str, to: &str, dry_run: bool) {
  function bump_versions (line 21) | pub fn bump_versions(new_version: &str, dry_run: bool) {

FILE: xtask/src/ci.rs
  function install_targets (line 6) | fn install_targets() {
  function install_dependencies (line 26) | fn install_dependencies() {
  function build_crates (line 45) | fn build_crates() {
  function build_run_doc_tests (line 63) | fn build_run_doc_tests() {
  function build_examples (line 81) | fn build_examples() {
  function build_example (line 138) | fn build_example(manifest_path: &path::Path, feature: Option<String>, ta...
  function start_group (line 163) | fn start_group(is_ci: bool, name: &str) {
  function end_group (line 169) | fn end_group(is_ci: bool) {
  function wrap_in_group (line 175) | fn wrap_in_group(is_ci: bool, name: &str, callable: &dyn Fn()) {
  function ci (line 181) | pub fn ci() {

FILE: xtask/src/main.rs
  function main (line 5) | fn main() {

FILE: xtask/src/publish.rs
  function publish (line 5) | pub fn publish() {
  function publish_package (line 13) | fn publish_package(package: &str, target: &str, feature: Option<&str>) {
Condensed preview — 85 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (167K chars).
[
  {
    "path": ".cargo/config.toml",
    "chars": 759,
    "preview": "[alias]\nxtask = \"run --package xtask --\"\n\n# For micro:bit v1.x\n\n[target.thumbv6m-none-eabi]\nrunner = 'probe-rs run --chi"
  },
  {
    "path": ".github/dependabot.yml",
    "chars": 206,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n  - package-"
  },
  {
    "path": ".github/workflows/changelog.yml",
    "chars": 453,
    "preview": "on:\n  pull_request_target:\n    types: [opened, synchronize, reopened, labeled, unlabeled]\n\nname: Changelog check\n\njobs:\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "chars": 1044,
    "preview": "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    n"
  },
  {
    "path": ".github/workflows/clippy.yml",
    "chars": 536,
    "preview": "on:\n  push:\n    branches: main\n  pull_request:\n  merge_group:\n\nname: Clippy check\njobs:\n  clippy_check:\n    runs-on: ubu"
  },
  {
    "path": ".github/workflows/rustfmt.yml",
    "chars": 473,
    "preview": "on:\n  push:\n    branches: main\n  pull_request:\n  merge_group:\n\nname: Code formatting check\n\njobs:\n  fmt:\n    name: Rustf"
  },
  {
    "path": ".gitignore",
    "chars": 70,
    "preview": "/target/\n**/*.orig\n**/*.rs.bk\nbloat_log*\n!.gitignore\n!.github\n!.cargo\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 4646,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
  },
  {
    "path": "Cargo.toml",
    "chars": 269,
    "preview": "[workspace]\nresolver = \"2\"\nmembers = [\n  \"microbit-common\",\n  \"microbit\",\n  \"microbit-v2\",\n  \"examples/*\",\n  \"xtask\",\n]\n"
  },
  {
    "path": "LICENSE-0BSD.txt",
    "chars": 649,
    "preview": "Copyright (C) 2018 daniel@eggers-club.de\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpo"
  },
  {
    "path": "README.md",
    "chars": 3413,
    "preview": "# microbit\n\n_microbit_ contains everything required getting started using Rust to create firmwares for the fabulous\n[BBC"
  },
  {
    "path": "build.rs",
    "chars": 571,
    "preview": "use std::env;\nuse std::fs::File;\nuse std::io::Write;\nuse std::path::PathBuf;\n\nfn main() {\n    // Put the linker script s"
  },
  {
    "path": "examples/analog/Cargo.toml",
    "chars": 687,
    "preview": "[package]\nname = \"analog\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.rust-"
  },
  {
    "path": "examples/analog/src/main.rs",
    "chars": 2706,
    "preview": "#![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,"
  },
  {
    "path": "examples/analog-v1/Cargo.toml",
    "chars": 655,
    "preview": "[package]\nname = \"analog-v1\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.ru"
  },
  {
    "path": "examples/analog-v1/src/main.rs",
    "chars": 2271,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Boa"
  },
  {
    "path": "examples/analog-v2/Cargo.toml",
    "chars": 661,
    "preview": "[package]\nname = \"analog-v2\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n# See more keys and their definitions at https://doc.ru"
  },
  {
    "path": "examples/analog-v2/src/main.rs",
    "chars": 2730,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Boa"
  },
  {
    "path": "examples/display-blocking/Cargo.toml",
    "chars": 622,
    "preview": "[package]\nname = \"display-blocking\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", f"
  },
  {
    "path": "examples/display-blocking/src/main.rs",
    "chars": 2066,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::delay::Delay"
  },
  {
    "path": "examples/display-nonblocking/Cargo.toml",
    "chars": 602,
    "preview": "[package]\nname = \"display-nonblocking\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\""
  },
  {
    "path": "examples/display-nonblocking/src/main.rs",
    "chars": 2786,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mute"
  },
  {
    "path": "examples/display-rtic/Cargo.toml",
    "chars": 611,
    "preview": "[package]\nname = \"display-rtic\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", featu"
  },
  {
    "path": "examples/display-rtic/src/main.rs",
    "chars": 2549,
    "preview": "//! A complete working example.\n//!\n//! This requires `cortex-m-rtic` v1.0.\n//!\n//! It uses `TIMER1` to drive the displa"
  },
  {
    "path": "examples/display-text-rtic/Cargo.toml",
    "chars": 640,
    "preview": "[package]\nname = \"display-text-rtic\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", "
  },
  {
    "path": "examples/display-text-rtic/src/main.rs",
    "chars": 2495,
    "preview": "//! An example of scrolling static text.\n//!\n//! It uses `TIMER1` to drive the display, and `RTC0` to animate the text.\n"
  },
  {
    "path": "examples/gpio-direct-blinky/Cargo.toml",
    "chars": 581,
    "preview": "[package]\nname = \"gpio-direct-blinky\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\","
  },
  {
    "path": "examples/gpio-direct-blinky/src/main.rs",
    "chars": 1419,
    "preview": "#![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"
  },
  {
    "path": "examples/gpio-hal-blinky/Cargo.toml",
    "chars": 543,
    "preview": "[package]\nname = \"gpio-hal-blinky\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\nembedded-hal = \"1.0.0\"\ncortex-m-rt"
  },
  {
    "path": "examples/gpio-hal-blinky/src/main.rs",
    "chars": 532,
    "preview": "#![no_main]\n#![no_std]\n\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::{delay::DelayNs, digital::Output"
  },
  {
    "path": "examples/gpio-hal-ledbutton/Cargo.toml",
    "chars": 624,
    "preview": "[package]\nname = \"gpio-hal-ledbutton\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\","
  },
  {
    "path": "examples/gpio-hal-ledbutton/src/main.rs",
    "chars": 721,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::digital::{In"
  },
  {
    "path": "examples/gpio-hal-printbuttons/Cargo.toml",
    "chars": 604,
    "preview": "[package]\nname = \"gpio-hal-printbuttons\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7."
  },
  {
    "path": "examples/gpio-hal-printbuttons/src/main.rs",
    "chars": 2205,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\n\nuse cortex_m::interrupt::Mut"
  },
  {
    "path": "examples/magnetometer/Cargo.toml",
    "chars": 638,
    "preview": "[package]\nname = \"magnetometer\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", featu"
  },
  {
    "path": "examples/magnetometer/src/main.rs",
    "chars": 2400,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse embedded_hal::delay::Delay"
  },
  {
    "path": "examples/rng-direct/Cargo.toml",
    "chars": 593,
    "preview": "[package]\nname = \"rng-direct\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", feature"
  },
  {
    "path": "examples/rng-direct/src/main.rs",
    "chars": 2421,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\n\nuse microbit::pac::{self, in"
  },
  {
    "path": "examples/rng-hal/Cargo.toml",
    "chars": 675,
    "preview": "[package]\nname = \"rng-hal-printrandserial\"\nversion = \"0.1.0\"\nedition = \"2024\"\n\n[dependencies]\ncortex-m = { version = \"0."
  },
  {
    "path": "examples/rng-hal/src/main.rs",
    "chars": 2020,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::{cell::RefCell, ops::DerefMut};\n\nuse cortex_"
  },
  {
    "path": "examples/serial-direct-echo/Cargo.toml",
    "chars": 201,
    "preview": "[package]\nname = \"serial-direct-echo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7.5\"\npanic-hal"
  },
  {
    "path": "examples/serial-direct-echo/src/main.rs",
    "chars": 2281,
    "preview": "#![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 l"
  },
  {
    "path": "examples/serial-direct-helloworld/Cargo.toml",
    "chars": 207,
    "preview": "[package]\nname = \"serial-direct-helloworld\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7.5\"\npan"
  },
  {
    "path": "examples/serial-direct-helloworld/src/main.rs",
    "chars": 1234,
    "preview": "#![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) = mi"
  },
  {
    "path": "examples/serial-hal-blocking-echo/Cargo.toml",
    "chars": 399,
    "preview": "[package]\nname = \"serial-hal-blocking-echo\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m-rt = \"0.7\"\npanic"
  },
  {
    "path": "examples/serial-hal-blocking-echo/src/main.rs",
    "chars": 1169,
    "preview": "#![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#[cf"
  },
  {
    "path": "examples/serial-hal-blocking-echo/src/serial_setup.rs",
    "chars": 1201,
    "preview": "use core::{fmt, ptr::addr_of_mut};\nuse microbit::hal::uarte::{Error, Instance, Uarte, UarteRx, UarteTx};\n\nstatic mut TX_"
  },
  {
    "path": "examples/servo/Cargo.toml",
    "chars": 686,
    "preview": "[package]\nname = \"servo\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n# See more keys and their definitions at https://doc.rust-l"
  },
  {
    "path": "examples/servo/src/main.rs",
    "chars": 4274,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mute"
  },
  {
    "path": "examples/v2-microphone/Cargo.toml",
    "chars": 531,
    "preview": "[package]\nname = \"v2-microphone\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", feat"
  },
  {
    "path": "examples/v2-microphone/src/main.rs",
    "chars": 1881,
    "preview": "#![no_std]\n#![no_main]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse cortex_m_rt::entry;\nuse microbit::{\n    board::Boa"
  },
  {
    "path": "examples/v2-speaker/Cargo.toml",
    "chars": 531,
    "preview": "[package]\nname = \"v2-speaker\"\nversion = \"0.1.0\"\nedition = \"2018\"\n\n[dependencies]\ncortex-m = { version = \"0.7.7\", feature"
  },
  {
    "path": "examples/v2-speaker/src/main.rs",
    "chars": 3861,
    "preview": "#![no_main]\n#![no_std]\n\nuse defmt_rtt as _;\nuse panic_halt as _;\n\nuse core::cell::RefCell;\nuse cortex_m::interrupt::Mute"
  },
  {
    "path": "memory.x",
    "chars": 133,
    "preview": "MEMORY\n{\n  /* NOTE K = KiBi = 1024 bytes */\n  FLASH : ORIGIN = 0x00000000, LENGTH = 256K\n  RAM : ORIGIN = 0x20000000, LE"
  },
  {
    "path": "microbit/Cargo.toml",
    "chars": 662,
    "preview": "[package]\nname = \"microbit\"\nversion = \"0.16.0\"\ndescription = \"Board support crate for the BBC Micro:bit V1\"\nedition = \"2"
  },
  {
    "path": "microbit/src/lib.rs",
    "chars": 1020,
    "preview": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous ["
  },
  {
    "path": "microbit-common/Cargo.toml",
    "chars": 1040,
    "preview": "[package]\nname = \"microbit-common\"\nversion = \"0.16.0\"\ndescription = \"Implementation details for the BBC Micro:bit board "
  },
  {
    "path": "microbit-common/src/adc.rs",
    "chars": 109,
    "preview": "//! 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",
    "chars": 120,
    "preview": "//! 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",
    "chars": 5749,
    "preview": "//! Blocking support for the 5x5 LED display.\n//!\n//! This module provides a simple blocking interface\n//! to the on boa"
  },
  {
    "path": "microbit-common/src/display/mod.rs",
    "chars": 230,
    "preview": "//! Support for the 5x5 LED display.\n//!\n//! There are two APIs for controlling the LED display, [`blocking`] and [`nonb"
  },
  {
    "path": "microbit-common/src/display/nonblocking/control.rs",
    "chars": 5465,
    "preview": "//! Implementation of [`DisplayControl`] for the micro:bit's GPIO peripheral.\n//!\n//! This controls the micro:bit's 5×5 "
  },
  {
    "path": "microbit-common/src/display/nonblocking/image.rs",
    "chars": 3239,
    "preview": "//! Static 5×5 greyscale and black-and-white images.\n\nuse tiny_led_matrix::{Render, MAX_BRIGHTNESS};\n\n/// A 5×5 image su"
  },
  {
    "path": "microbit-common/src/display/nonblocking/matrix.rs",
    "chars": 2825,
    "preview": "//! Implementation of [`Matrix`] and [`Frame`] for the micro:bit's LED display.\n//!\n//! This module describes the corres"
  },
  {
    "path": "microbit-common/src/display/nonblocking/mod.rs",
    "chars": 10786,
    "preview": "//! Non-blocking support for the 5×5 LED display.\n//!\n//! Together with [`tiny-led-matrix`](tiny_led_matrix), this modul"
  },
  {
    "path": "microbit-common/src/display/nonblocking/timer.rs",
    "chars": 3326,
    "preview": "//! Implementation of [`DisplayTimer`] for the nRF51 `TIMER`s.\n//!\n//! [`DisplayTimer`]: tiny_led_matrix::DisplayTimer\n\n"
  },
  {
    "path": "microbit-common/src/gpio.rs",
    "chars": 407,
    "preview": "//! Named GPIO pin types\n//!\n//! This module maps the GPIO pin names as described in the\n//! [Pins and Signals section o"
  },
  {
    "path": "microbit-common/src/lib.rs",
    "chars": 732,
    "preview": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous ["
  },
  {
    "path": "microbit-common/src/v1/adc.rs",
    "chars": 389,
    "preview": "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 "
  },
  {
    "path": "microbit-common/src/v1/board.rs",
    "chars": 10637,
    "preview": "use super::gpio::{\n    DisplayPins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE12, EDGE16, SCL, SDA, UART_RX,\n   "
  },
  {
    "path": "microbit-common/src/v1/gpio.rs",
    "chars": 5087,
    "preview": "//! Named GPIO pin types\n//!\n//! This module maps the GPIO pin names as described in the\n//! [Pins and Signals section o"
  },
  {
    "path": "microbit-common/src/v1/mod.rs",
    "chars": 42,
    "preview": "pub mod adc;\npub mod board;\npub mod gpio;\n"
  },
  {
    "path": "microbit-common/src/v2/adc.rs",
    "chars": 487,
    "preview": "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 v"
  },
  {
    "path": "microbit-common/src/v2/board.rs",
    "chars": 14392,
    "preview": "use super::gpio::{\n    DisplayPins, MicrophonePins, BTN_A, BTN_B, EDGE00, EDGE01, EDGE02, EDGE08, EDGE09, EDGE12,\n    ED"
  },
  {
    "path": "microbit-common/src/v2/gpio.rs",
    "chars": 4697,
    "preview": "#![allow(clippy::upper_case_acronyms, missing_docs)]\nuse nrf52833_hal::gpio::{p0, p1, Floating, Input, OpenDrain, Output"
  },
  {
    "path": "microbit-common/src/v2/mod.rs",
    "chars": 42,
    "preview": "pub mod adc;\npub mod board;\npub mod gpio;\n"
  },
  {
    "path": "microbit-v2/Cargo.toml",
    "chars": 710,
    "preview": "[package]\nname = \"microbit-v2\"\nversion = \"0.16.0\"\ndescription = \"Board support crate for the BBC Micro:bit V2\"\nedition ="
  },
  {
    "path": "microbit-v2/src/lib.rs",
    "chars": 1012,
    "preview": "//! microbit contains everything required to get started with the use of Rust\n//! to create firmwares for the fabulous ["
  },
  {
    "path": "tools/capture_example_bloat.sh",
    "chars": 399,
    "preview": "#!/bin/bash\n\nfilename=\"bloat_log_\"`date -Iminutes`\".txt\"\n\nfor i in `find examples -name \"*.rs\"`; do\n        name=$(echo "
  },
  {
    "path": "xtask/Cargo.toml",
    "chars": 116,
    "preview": "[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",
    "chars": 4555,
    "preview": "//! This has been copied pretty much wholesale from https://github.com/nrf-rs/nrf-hal/blob/master/xtask/src/lib.rs\nuse s"
  },
  {
    "path": "xtask/src/ci.rs",
    "chars": 5668,
    "preview": "use super::CRATES;\nuse std::{collections::HashMap, env, fs, path, process::Command};\n\npub static DEPENDENCIES: &[&str] ="
  },
  {
    "path": "xtask/src/lib.rs",
    "chars": 251,
    "preview": "mod bump;\nmod ci;\nmod publish;\n\npub static CRATES: &[(&str, &str, &str)] = &[\n    (\"microbit\", \"thumbv6m-none-eabi\", \"v1"
  },
  {
    "path": "xtask/src/main.rs",
    "chars": 813,
    "preview": "use std::env;\n\nuse xtask::{bump_versions, ci, publish};\n\nfn main() {\n    let mut args = env::args().skip(1);\n    let sub"
  },
  {
    "path": "xtask/src/publish.rs",
    "chars": 758,
    "preview": "use std::process::Command;\n\nuse crate::CRATES;\n\npub fn publish() {\n    publish_package(\"microbit-common\", \"thumbv7em-non"
  }
]

About this extraction

This page contains the full source code of the nrf-rs/microbit GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 85 files (151.9 KB), approximately 48.5k tokens, and a symbol index with 271 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!