Skip to content

include examples of generics-based portable routines for AVR serial, ADC, and SPI usage. #264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ members = [
exclude = [
# The RAVEDUDE! Yeah!
"ravedude",
# requires the user of this crate to specify the features for embedded-hal
"examples/avr-portable",
]

[patch.crates-io]
Expand Down
6 changes: 4 additions & 2 deletions examples/arduino-leonardo/src/bin/leonardo-i2cdetect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ fn main() -> ! {
);

ufmt::uwriteln!(&mut serial, "Write direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write)
.void_unwrap();
ufmt::uwriteln!(&mut serial, "\r\nRead direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read)
.void_unwrap();

loop {}
}
5 changes: 4 additions & 1 deletion examples/arduino-mega2560/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ embedded-hal = "0.2.3"

[dependencies.arduino-hal]
path = "../../arduino-hal/"
features = ["arduino-mega2560"]
features = ["arduino-mega2560"]

[dependencies.avr-portable]
path = "../avr-portable"
15 changes: 10 additions & 5 deletions examples/arduino-mega2560/src/bin/mega2560-adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ fn main() -> ! {
];

loop {
for (i, ch) in channels.iter().enumerate() {
let v = adc.read_blocking(ch);
ufmt::uwrite!(&mut serial, "A{}: {} ", i, v).void_unwrap();
if true {
for (i, ch) in channels.iter().enumerate() {
let v = adc.read_blocking(ch);
ufmt::uwrite!(&mut serial, "A{}: {} ", i, v).void_unwrap();
}

ufmt::uwriteln!(&mut serial, "").void_unwrap();
} else {
avr_portable::report_adc_single(&mut serial, &mut adc, 0, &channels[0]);
avr_portable::report_adc_multi(&mut serial, &mut adc, &channels[1..]);
}

ufmt::uwriteln!(&mut serial, "").void_unwrap();
arduino_hal::delay_ms(1000);
}
}
6 changes: 4 additions & 2 deletions examples/arduino-mega2560/src/bin/mega2560-i2cdetect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ fn main() -> ! {
);

ufmt::uwriteln!(&mut serial, "Write direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write)
.void_unwrap();
ufmt::uwriteln!(&mut serial, "\r\nRead direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read)
.void_unwrap();

loop {}
}
12 changes: 8 additions & 4 deletions examples/arduino-mega2560/src/bin/mega2560-spi-feedback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ fn main() -> ! {
);

loop {
// Send a byte
nb::block!(spi.send(0b00001111)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
let data = nb::block!(spi.read()).void_unwrap();
let data = if true {
// Send a byte
nb::block!(spi.send(0b00001111)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
nb::block!(spi.read()).void_unwrap()
} else {
avr_portable::spi_loopback(&mut spi, 0b00001111)
};

ufmt::uwriteln!(&mut serial, "data: {}\r", data).void_unwrap();
arduino_hal::delay_ms(1000);
Expand Down
12 changes: 8 additions & 4 deletions examples/arduino-mega2560/src/bin/mega2560-usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ fn main() -> ! {
ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").void_unwrap();

loop {
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();
if true {
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();

// Answer
ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
// Answer
ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
} else {
avr_portable::report(&mut serial);
}
}
}
3 changes: 3 additions & 0 deletions examples/arduino-uno/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ version = "0.5.1"
version = "1.6.1"
default-features = false

[dependencies.avr-portable]
path = "../avr-portable"

[dependencies.void]
version = "*"
default-features = false
3 changes: 2 additions & 1 deletion examples/arduino-uno/src/bin/uno-16chan-servo-driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ fn main() -> ! {
arduino_hal::delay_ms(500);

pwm.set_channel_off(Channel::C0, current).unwrap();
pwm.set_channel_off(Channel::C1, servo_min + (servo_max - current)).unwrap();
pwm.set_channel_off(Channel::C1, servo_min + (servo_max - current))
.unwrap();

if current == servo_max {
factor -= 1;
Expand Down
37 changes: 19 additions & 18 deletions examples/arduino-uno/src/bin/uno-adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,29 @@ fn main() -> ! {
ufmt::uwriteln!(&mut serial, "Ground: {}", gnd).void_unwrap();
ufmt::uwriteln!(&mut serial, "Temperature: {}", tmp).void_unwrap();

let a0 = pins.a0.into_analog_input(&mut adc);
let a1 = pins.a1.into_analog_input(&mut adc);
let a2 = pins.a2.into_analog_input(&mut adc);
let a3 = pins.a3.into_analog_input(&mut adc);
let a4 = pins.a4.into_analog_input(&mut adc);
let a5 = pins.a5.into_analog_input(&mut adc);
// To store multiple channels in an array, we use the `into_channel()` method.
let channels: [adc::Channel; 6] = [
pins.a0.into_analog_input(&mut adc).into_channel(),
pins.a1.into_analog_input(&mut adc).into_channel(),
pins.a2.into_analog_input(&mut adc).into_channel(),
pins.a3.into_analog_input(&mut adc).into_channel(),
pins.a4.into_analog_input(&mut adc).into_channel(),
pins.a5.into_analog_input(&mut adc).into_channel(),
];

loop {
let values = [
a0.analog_read(&mut adc),
a1.analog_read(&mut adc),
a2.analog_read(&mut adc),
a3.analog_read(&mut adc),
a4.analog_read(&mut adc),
a5.analog_read(&mut adc),
];

for (i, v) in values.iter().enumerate() {
ufmt::uwrite!(&mut serial, "A{}: {} ", i, v).void_unwrap();
if true {
let values = channels.iter().map(|ch| adc.read_blocking(ch));
for (i, v) in values.enumerate() {
ufmt::uwrite!(&mut serial, "A{}: {} ", i, v).void_unwrap();
}

ufmt::uwriteln!(&mut serial, "").void_unwrap();
} else {
avr_portable::report_adc_single(&mut serial, &mut adc, 0, &channels[0]);
avr_portable::report_adc_multi(&mut serial, &mut adc, &channels[1..]);
}

ufmt::uwriteln!(&mut serial, "").void_unwrap();
arduino_hal::delay_ms(1000);
}
}
8 changes: 4 additions & 4 deletions examples/arduino-uno/src/bin/uno-ext-interrupt.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/*!
* Blinks a 4 leds in sequence on pins D3 - D6. When an external interrupt on D2/INT0 comes in
* the sequence is reversed.
*
* Note: The use of the either crate requires the deactivation of std to use it in core. See the Cargo.toml
*
* Note: The use of the either crate requires the deactivation of std to use it in core. See the Cargo.toml
* in this directory for details.
*/
#![no_std]
#![no_main]
#![feature(abi_avr_interrupt)]

use panic_halt as _;
use core::sync::atomic::{AtomicBool, Ordering};
use arduino_hal::port::{mode, Pin};
use core::sync::atomic::{AtomicBool, Ordering};
use either::*;
use panic_halt as _;

static REVERSED: AtomicBool = AtomicBool::new(false);

Expand Down
12 changes: 8 additions & 4 deletions examples/arduino-uno/src/bin/uno-spi-feedback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ fn main() -> ! {
);

loop {
// Send a byte
nb::block!(spi.send(0b00001111)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
let data = nb::block!(spi.read()).void_unwrap();
let data = if true {
// Send a byte
nb::block!(spi.send(0b00001111)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
nb::block!(spi.read()).void_unwrap()
} else {
avr_portable::spi_loopback(&mut spi, 0b00001111)
};

ufmt::uwriteln!(&mut serial, "data: {}\r", data).void_unwrap();
arduino_hal::delay_ms(1000);
Expand Down
12 changes: 8 additions & 4 deletions examples/arduino-uno/src/bin/uno-usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ fn main() -> ! {
ufmt::uwriteln!(&mut serial, "Hello from Arduino!\r").void_unwrap();

loop {
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();
if true {
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();

// Answer
ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
// Answer
ufmt::uwriteln!(&mut serial, "Got {}!\r", b).void_unwrap();
} else {
avr_portable::report(&mut serial);
}
}
}
14 changes: 14 additions & 0 deletions examples/avr-portable/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "avr-portable"
version = "0.1.0"
authors = ["Robert Forsman <[email protected]>"]
edition = "2018"

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

[dependencies]
nb = "*"
ufmt = "*"
void = { version="*", default-features = false }
avr-hal-generic = { path="../../avr-hal-generic" }
embedded-hal = "*"
78 changes: 78 additions & 0 deletions examples/avr-portable/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#![no_std]

//! If you want library routines to be portable between different AVR implementations,
//! it is best to use types from [avr_hal_generic] instead of [arduino_hal]

use avr_hal_generic::adc::AdcChannel;
use embedded_hal::spi;
use ufmt::uWrite;
pub use void::ResultVoidErrExt as _;
pub use void::ResultVoidExt as _;

pub fn report<IO>(serial: &mut IO)
where
IO: embedded_hal::serial::Read<u8, Error = void::Void>
+ embedded_hal::serial::Write<u8, Error = void::Void>
+ uWrite<Error = void::Void>,
{
let _ = serial.read();
// Read a byte from the serial connection
let b = nb::block!(serial.read()).void_unwrap();

nb::block!(serial.write(b'z')).void_unwrap();

// Answer
ufmt::uwriteln!(serial, "Got {}!\r", b).void_unwrap();
}

pub fn report_adc_single<
W: uWrite<Error = void::Void>,
H,
ADCOPS: avr_hal_generic::adc::AdcOps<H>,
CLOCK: avr_hal_generic::clock::Clock,
PIN: AdcChannel<H, ADCOPS>,
>(
serial: &mut W,
adc: &mut avr_hal_generic::adc::Adc<H, ADCOPS, CLOCK>,
i: usize,
analog_pin: &PIN,
) {
let v = adc.read_blocking(analog_pin);
ufmt::uwrite!(serial, "A{}: {} ", i, v).void_unwrap();
}

pub fn report_adc_multi<
W: uWrite<Error = void::Void>,
H,
ADCOPS: avr_hal_generic::adc::AdcOps<H>,
CLOCK: avr_hal_generic::clock::Clock,
>(
serial: &mut W,
adc: &mut avr_hal_generic::adc::Adc<H, ADCOPS, CLOCK>,
channels: &[avr_hal_generic::adc::Channel<H, ADCOPS>],
) {
for (i, ch) in channels.iter().enumerate() {
let v = adc.read_blocking(ch);
ufmt::uwrite!(serial, "A{}: {} ", i, v).void_unwrap();
}

ufmt::uwriteln!(serial, "").void_unwrap();
}

pub fn spi_loopback<SPI>(spi: &mut SPI, val: u8) -> u8
where
SPI: spi::FullDuplex<u8, Error = void::Void>,
{
// Send a byte
nb::block!(spi.send(val)).void_unwrap();
// Because MISO is connected to MOSI, the read data should be the same
nb::block!(spi.read()).void_unwrap()
}

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
6 changes: 4 additions & 2 deletions examples/nano168/src/bin/nano168-i2cdetect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ fn main() -> ! {
);

ufmt::uwriteln!(&mut serial, "Write direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write)
.void_unwrap();
ufmt::uwriteln!(&mut serial, "\r\nRead direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read)
.void_unwrap();

loop {}
}
1 change: 0 additions & 1 deletion examples/nano168/src/bin/nano168-millis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,3 @@ fn main() -> ! {
ufmt::uwriteln!(&mut serial, "Got {} after {} ms!\r", b, time).void_unwrap();
}
}

6 changes: 4 additions & 2 deletions examples/sparkfun-promicro/src/bin/promicro-i2cdetect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ fn main() -> ! {
);

ufmt::uwriteln!(&mut serial, "Write direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Write)
.void_unwrap();
ufmt::uwriteln!(&mut serial, "\r\nRead direction test:\r").void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read).void_unwrap();
i2c.i2cdetect(&mut serial, arduino_hal::i2c::Direction::Read)
.void_unwrap();

loop {}
}