Skip to content
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

Improvement proposal #1

Merged
merged 21 commits into from
Sep 4, 2024
Merged
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: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
run: cargo fmt --all --check

- name: Run clippy
run: cargo clippy --all-targets --all-features
run: cargo clippy --all-targets --features=sync,async

- name: Install cargo-binstall
uses: cargo-bins/cargo-binstall@main
Expand Down
19 changes: 11 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
[package]
authors = ["w3irdrobot <rob@w3ird.tech>"]
categories = ["embedded", "hardware-support", "no-std"]
description = "Platform-agnostic Rust driver for the Maxim DS4432 Dual-Channel, I^2C, 7-Bit Sink/Source Current Digital To Analog (DAC) converter."
description = "Platform-agnostic Rust driver for the Maxim DS4432 Dual-Channel, I2C, 7-Bit Sink/Source Current Digital To Analog (DAC) converter."
documentation = "https://docs.rs/ds4432"
edition = "2021"
keywords = ["no-std", "embedded-hal-driver", "dac"]
license = " AGPL-3.0-only"
name = "ds4432"
repository = "https://github.com/w3irdrobot/ds4432"
rust-version = "1.71.1"
version = "0.1.0"

[dependencies]
defmt = { version = "0.3.8", optional = true }
embedded-hal = { version = "1.0.0", optional = true }
embedded-hal-async = { version = "1.0.0", optional = true }
maybe-async-cfg = "0.2.4"
defmt = { version = "0.3", optional = true }
embedded-hal = { version = "1.0", optional = true }
embedded-hal-async = { version = "1.0", optional = true }
log = { version = "0.4", optional = true }
maybe-async-cfg = "0.2"

[features]
async = ["dep:embedded-hal-async"]
blocking = ["dep:embedded-hal"]
default = ["blocking"]
defmt = ["dep:defmt"]
default = ["sync"]
defmt-03 = ["dep:defmt"]
not-recommended-rfs = []
sync = ["dep:embedded-hal"]

[dev-dependencies]
embedded-hal-mock = { version = "0.11.1", default-features = false, features = [
Expand Down
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
[![Docs][docs-image]][docs-link]
![AGPVv3 licensed][license-image]

Platform-agnostic Rust driver for the Maxim DS4432 Dual-Channel, I^2C, 7-Bit Sink/Source Current Digital To Analog (DAC) converter.
Platform-agnostic Rust driver for the Maxim DS4432 Dual-Channel, I2C, 7-Bit Sink/Source Current Digital To Analog (DAC) converter.

## Resources

Expand All @@ -15,6 +15,14 @@ Platform-agnostic Rust driver for the Maxim DS4432 Dual-Channel, I^2C, 7-Bit Sin

Distributed under the AGPLv3 License. See [LICENSE.txt](./LICENSE.txt) for more information.

## Features

- `defmt-03` add support for defmt Formatting of public enums and structs.
- `sync` (default) use `embedded_hal::i2c::I2c` trait to provide a sync driver.
- `async` use `embedded_hal_async::i2c::I2c` trait to provide an async driver. Both `sync` and `async` can be enable at the same time, but enabling none is pointless.
- `not-recommended-rfs` allow driver to use not recommended Rfs value for microamps convertions


## Support

PRs are more than welcome! I don't know how much more needs to be added, but I'm open to ideas.
Expand Down
18 changes: 18 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// Driver Result type.
pub type Result<T, E> = core::result::Result<T, Error<E>>;

/// Driver errors.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
pub enum Error<E> {
/// I2C bus error.
I2c(E),
/// The given code is too high
InvalidCode(u8),
/// The given Iout is out of range
InvalidIout,
/// The given RFS is out of range
InvalidRfs,
/// Try to set a Current value without giving the Rfs value
UnknownRfs,
}
226 changes: 226 additions & 0 deletions src/fmt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
#![macro_use]
#![allow(unused_macros)]

#[cfg(all(feature = "defmt-03", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");

macro_rules! assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::assert!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::assert!($($x)*);
}
};
}

macro_rules! assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::assert_eq!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::assert_eq!($($x)*);
}
};
}

macro_rules! assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::assert_ne!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::assert_ne!($($x)*);
}
};
}

macro_rules! debug_assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::debug_assert!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::debug_assert!($($x)*);
}
};
}

macro_rules! debug_assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::debug_assert_eq!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::debug_assert_eq!($($x)*);
}
};
}

macro_rules! debug_assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::debug_assert_ne!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::debug_assert_ne!($($x)*);
}
};
}

macro_rules! todo {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::todo!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::todo!($($x)*);
}
};
}

macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::unreachable!($($x)*);
}
};
}

macro_rules! panic {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt-03"))]
::core::panic!($($x)*);
#[cfg(feature = "defmt-03")]
::defmt::panic!($($x)*);
}
};
}

macro_rules! trace {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::trace!($s $(, $x)*);
#[cfg(feature = "defmt-03")]
::defmt::trace!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt-03")))]
let _ = ($( & $x ),*);
}
};
}

macro_rules! debug {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::debug!($s $(, $x)*);
#[cfg(feature = "defmt-03")]
::defmt::debug!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt-03")))]
let _ = ($( & $x ),*);
}
};
}

macro_rules! info {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::info!($s $(, $x)*);
#[cfg(feature = "defmt-03")]
::defmt::info!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt-03")))]
let _ = ($( & $x ),*);
}
};
}

macro_rules! warn {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::warn!($s $(, $x)*);
#[cfg(feature = "defmt-03")]
::defmt::warn!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt-03")))]
let _ = ($( & $x ),*);
}
};
}

macro_rules! error {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::error!($s $(, $x)*);
#[cfg(feature = "defmt-03")]
::defmt::error!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt-03")))]
let _ = ($( & $x ),*);
}
};
}

#[cfg(feature = "defmt-03")]
macro_rules! unwrap {
($($x:tt)*) => {
::defmt::unwrap!($($x)*)
};
}

#[cfg(not(feature = "defmt-03"))]
macro_rules! unwrap {
($arg:expr) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
}
}
};
($arg:expr, $($msg:expr),+ $(,)? ) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
}
}
}
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;

#[allow(dead_code)]
pub trait Try {
type Ok;
type Error;
fn into_result(self) -> Result<Self::Ok, Self::Error>;
}

impl<T> Try for Option<T> {
type Ok = T;
type Error = NoneError;

#[inline]
fn into_result(self) -> Result<T, NoneError> {
self.ok_or(NoneError)
}
}

impl<T, E> Try for Result<T, E> {
type Ok = T;
type Error = E;

#[inline]
fn into_result(self) -> Self {
self
}
}
Loading
Loading