Skip to content

Commit

Permalink
LEDs: Expose presence
Browse files Browse the repository at this point in the history
Merges: #113
  • Loading branch information
chrysn authored Aug 25, 2024
2 parents 294d122 + 2f7bae9 commit 03bd877
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 34 deletions.
32 changes: 7 additions & 25 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ jobs:
with:
repository: RIOT-OS/RIOT
path: RIOT
# common steps end here
- name: Patch .cargo/config.toml to use current checkout
run: |
set -x
Expand All @@ -59,7 +60,6 @@ jobs:
cargo tree --manifest-path $MANIF
echo "::endgroup::"
done
# common steps end here
- name: Build the example
run: |
Expand Down Expand Up @@ -91,40 +91,22 @@ jobs:
board: [native, sltb001a, samr21-xpro, stk3700]
testdir: ${{ fromJSON(needs.enumerate-wrappers-tests.outputs.list) }}
steps:
# common steps start here
# common steps start here (kept in sync even though we wouldn't need to patch RIOT's .cargo/config.toml)
- name: Check out riot-wrappers
uses: actions/checkout@v3
- name: Check out RIOT
uses: actions/checkout@v3
with:
repository: RIOT-OS/RIOT
path: RIOT
- name: Patch .cargo/config.toml to use current checkout
# common steps end here

- name: Patch local .cargo/config.toml to use current checkout
run: |
set -x
cd RIOT
rm -f .cargo/config.toml
mkdir -p .cargo # Keep working if RIOT ever decides it doesn't need overrides any more
mkdir .cargo
echo '[patch.crates-io]' >> .cargo/config.toml
echo 'riot-wrappers = { path = "../", version = "*" }' >> .cargo/config.toml
echo 'riot-wrappers = { path = ".", version = "*" }' >> .cargo/config.toml
echo 'riot-sys = { git = "https://github.com/RIOT-OS/rust-riot-sys" }' >> .cargo/config.toml
- name: Pull cargo updates
# No sense in running this in parallel -- this will download the index
# and all relevant crates once, and after that, just make some notes in Cargo.lock
run: |
set -x
# It is important to cd in early, for otherwise the patch.crates-io
# will not catch on during the update
cd RIOT
for MANIF in $(find -name Cargo.toml)
do
echo "::group::Updating ${MANIF}"
cargo update -p riot-sys -p riot-wrappers --aggressive --manifest-path $MANIF
cargo fetch --manifest-path $MANIF
cargo tree --manifest-path $MANIF
echo "::endgroup::"
done
# common steps end here
- name: Build and run test
run: |
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.4", features = ["u
embedded-hal = "1"
switch-hal = "0.4.0"
nb = "0.1.1"
riot-sys = "0.7.10"
riot-sys = "0.7.13"
num-traits = { version = "0.2", default-features = false }
mutex-trait = "0.2"

Expand Down
44 changes: 44 additions & 0 deletions src/led.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,57 @@ use core::convert::Infallible;
/// The preferred interface for turning a LED on and off is [switch_hal::OutputSwitch].
///
/// LEDs are accessible safely; any not implemented on a board are silently ignored.
#[derive(Debug)]
pub struct LED<const I: u8>(());

/// The indicated LED is not present on the current board.
#[derive(Debug)]
pub struct LedNotPresent;

impl<const I: u8> LED<I> {
#[deprecated(
note = "Use new_unchecked() to retain the behavior this function has always had; future versions of `.new()` will panic when used with a board that does not have that LED.",
since = "0.9.1"
)]
pub const fn new() -> Self {
Self::new_unchecked()
}

/// Accesses the LED numbered `I`.
///
/// It is not an error if this board does not have a LED with that number; the resulting struct
/// will be available but its methods have no effect.
pub const fn new_unchecked() -> Self {
assert!(I < 8, "RIOT only defines LED0..7");
Self(())
}

/// Accesses the LED numbered `I`.
///
/// An LED is returned if present on the board, which is known at build time.
pub const fn new_checked() -> Result<Self, LedNotPresent> {
if Self::is_present() {
Ok(Self(()))
} else {
Err(LedNotPresent)
}
}

const fn is_present() -> bool {
unsafe {
match I {
0 => riot_sys::macro_LED0_IS_PRESENT() != -1,
1 => riot_sys::macro_LED1_IS_PRESENT() != -1,
2 => riot_sys::macro_LED2_IS_PRESENT() != -1,
3 => riot_sys::macro_LED3_IS_PRESENT() != -1,
4 => riot_sys::macro_LED4_IS_PRESENT() != -1,
5 => riot_sys::macro_LED5_IS_PRESENT() != -1,
6 => riot_sys::macro_LED6_IS_PRESENT() != -1,
7 => riot_sys::macro_LED7_IS_PRESENT() != -1,
_ => panic!("RIOT only defines LED0..7"),
}
}
}
}

impl<const I: u8> switch_hal::OutputSwitch for LED<I> {
Expand Down
19 changes: 11 additions & 8 deletions tests/led/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ use riot_wrappers::riot_main;
riot_main!(main);

fn main() {
let mut led0 = LED::<0>::new();
let mut led1 = LED::<1>::new();
let mut led2 = LED::<2>::new();
let mut led3 = LED::<3>::new();
let mut led4 = LED::<4>::new();
let mut led5 = LED::<5>::new();
let mut led6 = LED::<6>::new();
let mut led7 = LED::<7>::new();
// Using the `unchecked` methods because the loop rotates the blinking speeds through all LEDs
// anyway -- so every speed will be on every LED, and that's easier to express if the number of
// considered LEDs is constant.
let mut led0 = LED::<0>::new_unchecked();
let mut led1 = LED::<1>::new_unchecked();
let mut led2 = LED::<2>::new_unchecked();
let mut led3 = LED::<3>::new_unchecked();
let mut led4 = LED::<4>::new_unchecked();
let mut led5 = LED::<5>::new_unchecked();
let mut led6 = LED::<6>::new_unchecked();
let mut led7 = LED::<7>::new_unchecked();
let mut leds: [&mut dyn switch_hal::ToggleableOutputSwitch<Error = _>; 8] = [
&mut led0, &mut led1, &mut led2, &mut led3, &mut led4, &mut led5, &mut led6, &mut led7,
];
Expand Down

0 comments on commit 03bd877

Please sign in to comment.