Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 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
4 changes: 2 additions & 2 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build]
target = "riscv32imc-esp-espidf"
#target = "xtensa-esp32-espidf"
# target = "riscv32imc-esp-espidf"
target = "xtensa-esp32-espidf"

[target.xtensa-esp32-espidf]
linker = "ldproxy"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@
**/*.rs.bk
ulp/ulp_start.o
install-rust-toolchain.sh
/.devcontainer
components_esp32.lock
15 changes: 12 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,17 @@ std = ["alloc", "esp-idf-sys/std"]
alloc = []
nightly = []
wake-from-isr = [] # Only enable if you plan to use the `edge-executor` crate
embassy-sync = [] # For now, the dependecy on the `embassy-sync` crate is non-optional, but this might change in future
embassy-sync = [
] # For now, the dependecy on the `embassy-sync` crate is non-optional, but this might change in future
# Temporary, until (https://github.com/espressif/esp-idf/issues/13938) is addressed
# - When enabled, the code for the legacy ADC oneshot driver will be compiled;
# - When not enabled (default) the code for the new ADC oneshot driver will be compiled;
# - Since we don't wrap the legacy _continuous_ ADC driver, the new _continuous_ ADC driver is always compiled.
adc-oneshot-legacy = []
# Similar to adc-oneshot-legacy
# - When enabled (default), the code for the legacy RMT TX/RX driver will be compiled.
# - When disabled the code for the new onewire RMT driver will be compiled.
rmt-legacy = []
# Propagated esp-idf-sys features
native = ["esp-idf-sys/native"]
pio = ["esp-idf-sys/pio"]
Expand All @@ -42,13 +47,17 @@ libstart = ["esp-idf-sys/libstart"]
nb = "1"
embedded-can = "0.4.1"
embedded-hal = "1"
embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.7", features = ["unproven"] }
embedded-hal-0-2 = { package = "embedded-hal", version = "0.2.7", features = [
"unproven",
] }
embedded-hal-nb = "1"
embedded-hal-async = "1"
embedded-io = "0.6"
embedded-io-async = "0.6"
esp-idf-sys = { version = "0.35", default-features = false }
critical-section = { version = "1.1.1", optional = true, features = ["restore-state-none"] }
critical-section = { version = "1.1.1", optional = true, features = [
"restore-state-none",
] }
heapless = "0.8"
num_enum = { version = "0.7", default-features = false }
enumset = { version = "1.1", default-features = false }
Expand Down
17 changes: 17 additions & 0 deletions examples/rmt_morse_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ use esp_idf_hal::delay::Ets;
use esp_idf_hal::gpio::*;
use esp_idf_hal::peripheral::*;
use esp_idf_hal::peripherals::Peripherals;
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm relatively sure that in the case where rmt-legacy is not enabled, this example will compile with "unused import" warnings, as you import a lot of stuff you don't use. Not the end of the world, but ideally we should fix that too.

The easiest way to do it (and to avoid sprinkling #[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))] all over the example is to just put the whole example in a new module, as in:

#[cfg(not(any(feature = "rmt-legacy", esp_idf_version_major = "4")))]
fn main() -> anyhow::Result<()> {
    println!("This example requires feature `rmt-legacy` enabled or using ESP-IDF v4.4.X");

    loop {
        std::thread::sleep(std::time::Duration::from_millis(1000));
    }
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn main() -> anyhow::Result<()> {
    example::main()
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
mod example {
... /// Here you move the whole code of the example, with imports and whatnot.
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. Will do the other examples soon.

use esp_idf_hal::rmt::config::{CarrierConfig, DutyPercent, Loop, TransmitConfig};
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
use esp_idf_hal::rmt::*;
use esp_idf_hal::units::FromValueType;

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn main() -> anyhow::Result<()> {
esp_idf_hal::sys::link_patches();

Expand Down Expand Up @@ -64,6 +67,16 @@ fn main() -> anyhow::Result<()> {
Ok(())
}

#[cfg(not(any(feature = "rmt-legacy", esp_idf_version_major = "4")))]
fn main() -> anyhow::Result<()> {
println!("This example requires feature `rmt-legacy` enabled or using ESP-IDF v4.4.X");

loop {
std::thread::sleep(std::time::Duration::from_millis(1000));
}
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn send_morse_code<'d>(
channel: impl Peripheral<P = impl RmtChannel> + 'd,
led: impl Peripheral<P = impl OutputPin> + 'd,
Expand All @@ -85,10 +98,12 @@ fn send_morse_code<'d>(
Ok(tx)
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn high() -> Pulse {
Pulse::new(PinState::High, PulseTicks::max())
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn low() -> Pulse {
Pulse::new(PinState::Low, PulseTicks::max())
}
Expand All @@ -99,6 +114,7 @@ enum Code {
WordGap,
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
impl Code {
pub fn push_pulse(&self, pulses: &mut Vec<Pulse>) {
match &self {
Expand All @@ -118,6 +134,7 @@ fn find_codes(c: &char) -> &'static [Code] {
&[]
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn str_pulses(s: &str) -> Vec<Pulse> {
let mut pulses = vec![];
for c in s.chars() {
Expand Down
16 changes: 16 additions & 0 deletions examples/rmt_musical_buzzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ use core::time::Duration;

use esp_idf_hal::delay::Ets;
use esp_idf_hal::peripherals::Peripherals;
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
use esp_idf_hal::rmt::{self, config::TransmitConfig, TxRmtDriver};

use esp_idf_hal::units::Hertz;
use notes::*;

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn main() -> anyhow::Result<()> {
esp_idf_hal::sys::link_patches();

Expand All @@ -28,19 +30,31 @@ fn main() -> anyhow::Result<()> {
}
}

#[cfg(not(any(feature = "rmt-legacy", esp_idf_version_major = "4")))]
fn main() -> anyhow::Result<()> {
println!("This example requires feature `rmt-legacy` enabled or using ESP-IDF v4.4.X");

loop {
std::thread::sleep(Duration::from_millis(1000));
}
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
pub fn play_song(tx: &mut TxRmtDriver<'static>, song: &[NoteValue]) -> anyhow::Result<()> {
for note_value in song {
note_value.play(tx)?;
}
Ok(())
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
pub struct NoteValueIter {
ticks: rmt::PulseTicks,
tone_cycles: u32,
pause_cycles: u32,
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
impl NoteValueIter {
fn new(ticks_per_sec: Hertz, note: &NoteValue) -> Self {
// Calculate the frequency for a piezo buzzer.
Expand All @@ -63,6 +77,7 @@ impl NoteValueIter {
}
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
impl std::iter::Iterator for NoteValueIter {
type Item = rmt::Symbol;

Expand Down Expand Up @@ -113,6 +128,7 @@ pub struct NoteValue {
duration: Duration,
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
impl NoteValue {
pub fn play(&self, tx: &mut TxRmtDriver<'static>) -> anyhow::Result<()> {
let ticks_hz = tx.counter_clock()?;
Expand Down
13 changes: 13 additions & 0 deletions examples/rmt_neopixel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ use anyhow::{bail, Result};
use core::time::Duration;
use esp_idf_hal::delay::FreeRtos;
use esp_idf_hal::peripherals::Peripherals;
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

use esp_idf_hal::rmt::config::TransmitConfig;
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
use esp_idf_hal::rmt::*;

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn main() -> Result<()> {
esp_idf_hal::sys::link_patches();

Expand All @@ -39,6 +42,16 @@ fn main() -> Result<()> {
})
}

#[cfg(not(any(feature = "rmt-legacy", esp_idf_version_major = "4")))]
fn main() -> anyhow::Result<()> {
println!("This example requires feature `rmt-legacy` enabled or using ESP-IDF v4.4.X");

loop {
std::thread::sleep(Duration::from_millis(1000));
}
}

#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))]
fn neopixel(rgb: Rgb, tx: &mut TxRmtDriver) -> Result<()> {
let color: u32 = rgb.into();
let ticks_hz = tx.counter_clock()?;
Expand Down
186 changes: 186 additions & 0 deletions examples/rmt_onewire.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
//! RMT Onewire Example
//!
//! Example demonstrating the use of the onewire component.
//!
//! In order to use this example, an overidden `Cargo.toml` must be defined with the following definitions:
//! ```
//! [[package.metadata.esp-idf-sys.extra_components]]
//! remote_component = { name = "onewire_bus", version = "^1.0.2" }
//!
//!
//! [patch.crates-io]
//! esp-idf-sys = { git = "https://github.com/esp-rs/esp-idf-sys", rev = "2728b85" }
//!
//! ```
//!
//! The example can then be run with
//! `MCU=<target> cargo run --example rmt_onewire --manifest-path /path/to/other/Cargo.toml`
//!
//! Below is a connection sketch, the signal pin must be externally pulled-up
//! with a 4.7kOhm resistor.
//! This example uses gpio 16, but any pin capable of
//! input AND output is suitable.
//!
//! If the example is successful, it should print the address of each
//! onewire device attached to the bus.
//!
//! ┌──────────────────────────┐
//! │ 3.3V├───────┬─────────────┬──────────────────────┐
//! │ │ ┌┴┐ │VDD │VDD
//! │ ESP Board │ 4.7k│ │ ┌──────┴──────┐ ┌──────┴──────┐
//! │ │ └┬┘ DQ│ │ DQ│ │
//! │ ONEWIRE_GPIO_PIN├───────┴──┬───┤ DS18B20 │ ┌───┤ DS18B20 │ ......
//! │ │ └───│-------------│────┴───│-------------│──
//! │ │ └──────┬──────┘ └──────┬──────┘
//! │ │ │GND │GND
//! │ GND├─────────────────────┴──────────────────────┘
//! └──────────────────────────┘
//!
//!
//! This example demonstrates:
//! * A RMT device in both TX and RX mode.
//! * Usage of the onewire bus driver interface.
//! * How to iterate through a device search to discover devices on the bus.

use std::borrow::Borrow;
use std::time::Duration;

use esp_idf_hal::delay::FreeRtos;
#[cfg(all(
esp_idf_soc_rmt_supported,
not(feature = "rmt-legacy"),
esp_idf_comp_espressif__onewire_bus_enabled,
))]
use esp_idf_hal::onewire::{OWCommand, OWDevice, OWDriver};
use esp_idf_hal::peripherals::Peripherals;
use esp_idf_sys::EspError;

#[cfg(all(
esp_idf_soc_rmt_supported,
not(esp_idf_version_major = "4"),
esp_idf_comp_espressif__onewire_bus_enabled,
))]
fn main() -> anyhow::Result<()> {
println!("Starting APP!");

let peripherals = Peripherals::take()?;

let onewire_gpio_pin = peripherals.pins.gpio16;

let onewire_bus: OWDriver = OWDriver::new(onewire_gpio_pin)?;
let mut search = onewire_bus.search()?;
let device = search.next();
if device.is_none() {
println!("No device found");
return Ok(());
}
let device = OWDevice::new(device.unwrap(), &onewire_bus);
// let device = OWDevice::new(search.next()?, &onewire_bus);
// for device in search {
println!("Found Device: {:?}", device);

loop {
ds18b20_trigger_temp_conversion(&device, &onewire_bus)?;
let temp = ds18b20_get_temperature(&device, &onewire_bus)?;
println!("Temperature: {}", temp);
FreeRtos::delay_ms(3000);
}
}

#[cfg(any(
feature = "rmt-legacy",
esp_idf_version_major = "4",
not(esp_idf_comp_espressif__onewire_bus_enabled),
not(esp_idf_soc_rmt_supported),
))]
fn main() -> anyhow::Result<()> {
println!("This example requires feature `rmt-legacy` disabled, using ESP-IDF > v4.4.X, the component included in `Cargo.toml`, or is not supported on this MCU");

loop {
std::thread::sleep(std::time::Duration::from_millis(1000));
}
}

#[cfg(all(
esp_idf_soc_rmt_supported,
not(esp_idf_version_major = "4"),
esp_idf_comp_espressif__onewire_bus_enabled,
))]
fn ds18b20_send_command<'a>(
device: &OWDevice<'a, impl Borrow<OWDriver<'a>>>,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: Below in the code I question why we still use OWDevice? Here I think we simply need device_addr: u64 and that's it. Also because you anyway also pass the bus driver below, with bus.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

bus: &OWDriver,
cmd: u8,
) -> Result<(), EspError> {
let mut buf = [0; 10];
buf[0] = OWCommand::MatchRom as _;
let addr = device.address().to_le_bytes();
buf[1..9].copy_from_slice(&addr);
buf[9] = cmd;
println!(
"seend command{cmd} to addr {} [{:?}], full_msg = {:?}",
device.address(),
addr,
buf
);
let write_size = bus.write(&buf)?;

println!("Sent {write_size} bytes");

Ok(())
}

#[allow(dead_code)]
#[repr(u8)]
enum Ds18b20Command {
ConvertTemp = 0x44,
WriteScratch = 0x4e,
ReadScratch = 0xbe,
}
#[cfg(all(
esp_idf_soc_rmt_supported,
not(esp_idf_version_major = "4"),
esp_idf_comp_espressif__onewire_bus_enabled,
))]
fn ds18b20_trigger_temp_conversion<'a>(
device: &OWDevice<'a, impl Borrow<OWDriver<'a>>>,
bus: &OWDriver,
) -> Result<(), EspError> {
// reset bus and check if the ds18b20 is present
bus.reset()?;
println!(
"Bus reset, bus:{:?} device bus: {:?}",
bus,
device.bus().borrow()
);

ds18b20_send_command(device, bus, Ds18b20Command::ConvertTemp as u8)?;

// delay proper time for temp conversion,
// assume max resolution (12-bits)
std::thread::sleep(Duration::from_millis(800));

Ok(())
}
#[cfg(all(
esp_idf_soc_rmt_supported,
not(esp_idf_version_major = "4"),
esp_idf_comp_espressif__onewire_bus_enabled,
))]
fn ds18b20_get_temperature<'a>(
device: &OWDevice<'a, impl Borrow<OWDriver<'a>>>,
bus: &OWDriver,
) -> Result<f32, EspError> {
bus.reset()?;

ds18b20_send_command(device, bus, Ds18b20Command::ReadScratch as u8)?;

let mut buf = [0u8; 10];
bus.read(&mut buf)?;
println!("buffer = {buf:?}");
let lsb = buf[0];
let msb = buf[1];

let temp_raw: u16 = (u16::from(msb) << 8) | u16::from(lsb);

Ok(f32::from(temp_raw) / 16.0)
}
Loading