From 0da23e23b2239fbcb1b6baac425903b9f210cf64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sat, 1 Aug 2020 23:59:12 +0200 Subject: [PATCH 01/10] Add COMP module --- Cargo.toml | 1 + examples/comp-demo/Cargo.toml | 17 ++ examples/comp-demo/Embed.toml | 46 ++++++ examples/comp-demo/src/main.rs | 68 ++++++++ nrf-hal-common/src/comp.rs | 277 +++++++++++++++++++++++++++++++++ nrf-hal-common/src/lib.rs | 2 + 6 files changed, 411 insertions(+) create mode 100644 examples/comp-demo/Cargo.toml create mode 100755 examples/comp-demo/Embed.toml create mode 100644 examples/comp-demo/src/main.rs create mode 100644 nrf-hal-common/src/comp.rs diff --git a/Cargo.toml b/Cargo.toml index 05f52eb3..36bf029b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ members = [ "examples/ppi-demo", "examples/gpiote-demo", "examples/wdt-demo", + "examples/comp-demo", ] [profile.dev] diff --git a/examples/comp-demo/Cargo.toml b/examples/comp-demo/Cargo.toml new file mode 100644 index 00000000..26fb3c4f --- /dev/null +++ b/examples/comp-demo/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "comp-demo" +version = "0.1.0" +authors = ["Henrik AlseĢr"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cortex-m = "0.6.2" +cortex-m-rtic = "0.5.3" +rtt-target = {version = "0.2.0", features = ["cortex-m"] } +nrf52840-hal = { features = ["rt"], path = "../../nrf52840-hal" } + +[dependencies.embedded-hal] +version = "0.2.3" +features = ["unproven"] diff --git a/examples/comp-demo/Embed.toml b/examples/comp-demo/Embed.toml new file mode 100755 index 00000000..e10b4bcf --- /dev/null +++ b/examples/comp-demo/Embed.toml @@ -0,0 +1,46 @@ +[probe] +# The index of the probe in the connected probe list. +# probe_index = 0 +# The protocol to be used for communicating with the target. +protocol = "Swd" +# The speed in kHz of the data link to the target. +# speed = 1337 + +[flashing] +# Whether or not the target should be flashed. +enabled = true +# Whether or not the target should be halted after flashing. +halt_afterwards = false +# Whether or not bytes erased but not rewritten with data from the ELF +# should be restored with their contents before erasing. +restore_unwritten_bytes = false +# The path where an SVG of the assembled flash layout should be written to. +# flash_layout_output_path = "out.svg" + +[general] +# The chip name of the chip to be debugged. +chip = "nRF52840" +# A list of chip descriptions to be loaded during runtime. +chip_descriptions = [] +# The default log level to be used. +log_level = "Warn" + +[rtt] +# Whether or not an RTTUI should be opened after flashing. +# This is exclusive and cannot be used with GDB at the moment. +enabled = true +# A list of channel associations to be displayed. If left empty, all channels are displayed. +channels = [ + # { up = 0, down = 0, name = "name" } +] +# The duration in ms for which the logger should retry to attach to RTT. +timeout = 3000 +# Whether timestamps in the RTTUI are enabled +show_timestamps = true + +[gdb] +# Whether or not a GDB server should be opened after flashing. +# This is exclusive and cannot be used with RTT at the moment. +enabled = false +# The connection string in host:port format wher the GDB server will open a socket. +# gdb_connection_string diff --git a/examples/comp-demo/src/main.rs b/examples/comp-demo/src/main.rs new file mode 100644 index 00000000..ad731cd0 --- /dev/null +++ b/examples/comp-demo/src/main.rs @@ -0,0 +1,68 @@ +#![no_std] +#![no_main] + +use embedded_hal::digital::v2::OutputPin; +use { + core::{ + panic::PanicInfo, + sync::atomic::{compiler_fence, Ordering}, + }, + hal::{ + comp::*, + gpio::{Level, Output, Pin, PushPull}, + }, + nrf52840_hal as hal, + rtt_target::{rprintln, rtt_init_print}, +}; + +#[rtic::app(device = crate::hal::pac, peripherals = true)] +const APP: () = { + struct Resources { + comp: Comp, + led1: Pin>, + } + + #[init] + fn init(ctx: init::Context) -> init::LateResources { + let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc(); + rtt_init_print!(); + + let p0 = hal::gpio::p0::Parts::new(ctx.device.P0); + let led1 = p0.p0_13.into_push_pull_output(Level::High).degrade(); + let in_pin = p0.p0_30.into_floating_input(); + let ref_pin = p0.p0_31.into_floating_input(); + + let comp = Comp::new(ctx.device.COMP, &in_pin); + comp.differential(&ref_pin) + .hysteresis(true) + .enable_interrupt(Transition::Cross) + .enable(); + + init::LateResources { comp, led1 } + } + + #[task(binds = COMP_LPCOMP, resources = [comp, led1])] + fn on_comp(ctx: on_comp::Context) { + ctx.resources.comp.reset_event(Transition::Cross); + match ctx.resources.comp.read() { + CompResult::Above => { + rprintln!("Vin > Vref"); + ctx.resources.led1.set_low().ok(); + } + CompResult::Below => { + rprintln!("Vin < Vref"); + ctx.resources.led1.set_high().ok(); + } + } + } +}; + +#[inline(never)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + cortex_m::interrupt::disable(); + rprintln!("{}", info); + loop { + compiler_fence(Ordering::SeqCst); + } +} diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs new file mode 100644 index 00000000..bb8ab65c --- /dev/null +++ b/nrf-hal-common/src/comp.rs @@ -0,0 +1,277 @@ +//! HAL interface for the COMP peripheral. +//! +//! The comparator (COMP) compares an input voltage (Vin) against a second input voltage (Vref). +//! Vin can be derived from an analog input pin (AIN0-AIN7). +//! Vref can be derived from multiple sources depending on the operation mode of the comparator. + +use { + crate::gpio::{Floating, Input}, + crate::pac::comp::{_EVENTS_CROSS, _EVENTS_DOWN, _EVENTS_UP}, + crate::pac::{generic::Reg, COMP}, +}; + +/// A safe wrapper around the `COMP` peripheral. +pub struct Comp { + comp: COMP, +} + +impl Comp { + /// Takes ownership of the `COMP` peripheral, returning a safe wrapper. + pub fn new(comp: COMP, input_pin: &P) -> Self { + comp.psel.write(|w| match input_pin.ain() { + 0 => w.psel().analog_input0(), + 1 => w.psel().analog_input1(), + 2 => w.psel().analog_input2(), + 3 => w.psel().analog_input3(), + 4 => w.psel().analog_input4(), + 5 => w.psel().analog_input5(), + 6 => w.psel().analog_input6(), + 7 => w.psel().analog_input7(), + _ => unreachable!(), + }); + comp.mode.write(|w| w.sp().normal()); + comp.mode.write(|w| w.main().se()); + comp.refsel.write(|w| w.refsel().int1v2()); + Self { comp } + } + + /// Sets the speed and power mode of the comparator. + #[inline(always)] + pub fn power_mode(&self, mode: PowerMode) -> &Self { + match mode { + PowerMode::LowPower => self.comp.mode.write(|w| w.sp().low()), + PowerMode::Normal => self.comp.mode.write(|w| w.sp().normal()), + PowerMode::HighSpeed => self.comp.mode.write(|w| w.sp().high()), + } + self + } + + /// Sets Vref of the comparator in single ended mode. + #[inline(always)] + pub fn vref(&self, vref: VRef) -> &Self { + self.comp.refsel.write(|w| match vref { + VRef::Int1V2 => w.refsel().int1v2(), + VRef::Int1V8 => w.refsel().int1v8(), + VRef::Int2V4 => w.refsel().int2v4(), + VRef::Vdd => w.refsel().vdd(), + VRef::ARef => w.refsel().aref(), + }); + self + } + + /// Sets analog reference pin. + #[inline(always)] + pub fn aref_pin(&self, ref_pin: &P) -> &Self { + self.comp.extrefsel.write(|w| match ref_pin.ain() { + 0 => w.extrefsel().analog_reference0(), + 1 => w.extrefsel().analog_reference1(), + 2 => w.extrefsel().analog_reference2(), + 3 => w.extrefsel().analog_reference3(), + 4 => w.extrefsel().analog_reference4(), + 5 => w.extrefsel().analog_reference5(), + 6 => w.extrefsel().analog_reference6(), + 7 => w.extrefsel().analog_reference7(), + _ => unreachable!(), + }); + self + } + + /// Sets comparator mode to differential with external Vref pin. + #[inline(always)] + pub fn differential(&self, ref_pin: &P) -> &Self { + self.comp.mode.write(|w| w.main().diff()); + self.aref_pin(ref_pin); + self + } + + /// Rising hysteresis threshold in single ended mode `Vup = (value+1)/64*Vref`. + #[inline(always)] + pub fn hysteresis_threshold_up(&self, value: u8) -> &Self { + self.comp + .th + .write(|w| unsafe { w.thup().bits(value.min(63)) }); + self + } + + /// Falling hysteresis threshold in single ended mode `Vdown = (value+1)/64*Vref`. + #[inline(always)] + pub fn hysteresis_threshold_down(&self, value: u8) -> &Self { + self.comp + .th + .write(|w| unsafe { w.thdown().bits(value.min(63)) }); + self + } + + /// Enables/disables differential comparator hysteresis (50mV). + #[inline(always)] + pub fn hysteresis(&self, enabled: bool) -> &Self { + self.comp.hyst.write(|w| match enabled { + true => w.hyst().hyst50m_v(), + false => w.hyst().no_hyst(), + }); + self + } + + /// Enables `COMP_LPCOMP` interrupt triggering on the specified event. + #[inline(always)] + pub fn enable_interrupt(&self, event: Transition) -> &Self { + self.comp.intenset.modify(|_r, w| match event { + Transition::Cross => w.cross().set_bit(), + Transition::Down => w.down().set_bit(), + Transition::Up => w.up().set_bit(), + }); + self + } + + /// Disables `COMP_LPCOMP` interrupt triggering on the specified event. + #[inline(always)] + pub fn disable_interrupt(&self, event: Transition) -> &Self { + self.comp.intenclr.modify(|_r, w| match event { + Transition::Cross => w.cross().set_bit(), + Transition::Down => w.down().set_bit(), + Transition::Up => w.up().set_bit(), + }); + self + } + + /// Enables the comparator and waits until it's ready to use. + #[inline(always)] + pub fn enable(&self) { + self.comp.enable.write(|w| w.enable().enabled()); + self.comp.tasks_start.write(|w| unsafe { w.bits(1) }); + while self.comp.events_ready.read().bits() == 0 {} + } + + /// Disables the comparator. + #[inline(always)] + pub fn disable(&self) { + self.comp.tasks_stop.write(|w| unsafe { w.bits(1) }); + self.comp.enable.write(|w| w.enable().disabled()); + } + + /// Checks if the `Up` transition event has been triggered. + #[inline(always)] + pub fn is_up(&self) -> bool { + self.comp.events_up.read().bits() != 0 + } + + /// Checks if the `Down` transition event has been triggered. + #[inline(always)] + pub fn is_down(&self) -> bool { + self.comp.events_down.read().bits() != 0 + } + + /// Checks if the `Cross` transition event has been triggered. + #[inline(always)] + pub fn is_cross(&self) -> bool { + self.comp.events_cross.read().bits() != 0 + } + + /// Returns reference to `Up` transition event endpoint for PPI. + pub fn event_up(&self) -> &Reg { + &self.comp.events_up + } + + /// Returns reference to `Down` transition event endpoint for PPI. + pub fn event_down(&self) -> &Reg { + &self.comp.events_down + } + + /// Returns reference to `Cross` transition event endpoint for PPI. + pub fn event_cross(&self) -> &Reg { + &self.comp.events_cross + } + + /// Marks event as handled. + #[inline(always)] + pub fn reset_event(&self, event: Transition) { + match event { + Transition::Cross => self.comp.events_cross.write(|w| w), + Transition::Down => self.comp.events_down.write(|w| w), + Transition::Up => self.comp.events_up.write(|w| w), + } + } + + /// Marks all events as handled. + #[inline(always)] + pub fn reset_events(&self) { + self.comp.events_cross.write(|w| w); + self.comp.events_down.write(|w| w); + self.comp.events_up.write(|w| w); + } + + /// Returns the output state of the comparator. + #[inline(always)] + pub fn read(&self) -> CompResult { + self.comp.tasks_sample.write(|w| unsafe { w.bits(1) }); + match self.comp.result.read().result().is_above() { + true => CompResult::Above, + false => CompResult::Below, + } + } + + /// Consumes `self` and returns back the raw `COMP` peripheral. + #[inline(always)] + pub fn free(self) -> COMP { + self.comp + } +} + +pub enum OperationMode { + Differential, + SingleEnded, +} + +pub enum PowerMode { + LowPower, + Normal, + HighSpeed, +} + +pub enum CompResult { + Above, + Below, +} + +pub enum Transition { + Up, + Down, + Cross, +} + +pub enum VRef { + Int1V2, + Int1V8, + Int2V4, + Vdd, + ARef, +} + +/// Trait to represent analog input pins. +pub trait AnalogPin { + /// Returns `AIN` id. + fn ain(&self) -> u8; +} + +macro_rules! analog_pins { + ($($n:expr => $pin:path),*) => { + $( + impl AnalogPin for $pin { + fn ain(&self) -> u8 { + $n + } + } + )* + }; +} + +analog_pins! { + 0 => crate::gpio::p0::P0_02>, + 1 => crate::gpio::p0::P0_03>, + 2 => crate::gpio::p0::P0_04>, + 3 => crate::gpio::p0::P0_05>, + 4 => crate::gpio::p0::P0_28>, + 5 => crate::gpio::p0::P0_29>, + 6 => crate::gpio::p0::P0_30>, + 7 => crate::gpio::p0::P0_31> +} diff --git a/nrf-hal-common/src/lib.rs b/nrf-hal-common/src/lib.rs index 31941626..a307827d 100644 --- a/nrf-hal-common/src/lib.rs +++ b/nrf-hal-common/src/lib.rs @@ -28,6 +28,8 @@ pub mod adc; #[cfg(not(feature = "9160"))] pub mod ccm; pub mod clocks; +#[cfg(not(any(feature = "51", feature = "9160")))] +pub mod comp; #[cfg(not(feature = "51"))] pub mod delay; #[cfg(not(feature = "9160"))] From 02a731cda5f48962f16dcbb2b818ff6d932554a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 00:25:30 +0200 Subject: [PATCH 02/10] Remove analog input 7 for nRF52810 --- nrf-hal-common/src/comp.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index bb8ab65c..5a018efc 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -26,6 +26,7 @@ impl Comp { 4 => w.psel().analog_input4(), 5 => w.psel().analog_input5(), 6 => w.psel().analog_input6(), + #[cfg(not(feature = "52810"))] 7 => w.psel().analog_input7(), _ => unreachable!(), }); @@ -84,7 +85,7 @@ impl Comp { self } - /// Rising hysteresis threshold in single ended mode `Vup = (value+1)/64*Vref`. + /// Upward hysteresis threshold in single ended mode `Vup = (value+1)/64*Vref`. #[inline(always)] pub fn hysteresis_threshold_up(&self, value: u8) -> &Self { self.comp @@ -93,7 +94,7 @@ impl Comp { self } - /// Falling hysteresis threshold in single ended mode `Vdown = (value+1)/64*Vref`. + /// Downward hysteresis threshold in single ended mode `Vdown = (value+1)/64*Vref`. #[inline(always)] pub fn hysteresis_threshold_down(&self, value: u8) -> &Self { self.comp From 44c447ef3d026e4a395ea36cb0ca3a042b73df85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 00:45:22 +0200 Subject: [PATCH 03/10] More inline --- nrf-hal-common/src/comp.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index 5a018efc..077e9ba9 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -169,16 +169,19 @@ impl Comp { } /// Returns reference to `Up` transition event endpoint for PPI. + #[inline(always)] pub fn event_up(&self) -> &Reg { &self.comp.events_up } /// Returns reference to `Down` transition event endpoint for PPI. + #[inline(always)] pub fn event_down(&self) -> &Reg { &self.comp.events_down } /// Returns reference to `Cross` transition event endpoint for PPI. + #[inline(always)] pub fn event_cross(&self) -> &Reg { &self.comp.events_cross } From 9c8537ec98cabfa278163be1d8bdd23fb8de2236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 08:02:08 +0200 Subject: [PATCH 04/10] Update demo cargo-embed to v0.8 --- examples/comp-demo/Embed.toml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/comp-demo/Embed.toml b/examples/comp-demo/Embed.toml index e10b4bcf..400c5562 100755 --- a/examples/comp-demo/Embed.toml +++ b/examples/comp-demo/Embed.toml @@ -1,4 +1,4 @@ -[probe] +[default.probe] # The index of the probe in the connected probe list. # probe_index = 0 # The protocol to be used for communicating with the target. @@ -6,7 +6,7 @@ protocol = "Swd" # The speed in kHz of the data link to the target. # speed = 1337 -[flashing] +[default.flashing] # Whether or not the target should be flashed. enabled = true # Whether or not the target should be halted after flashing. @@ -17,7 +17,7 @@ restore_unwritten_bytes = false # The path where an SVG of the assembled flash layout should be written to. # flash_layout_output_path = "out.svg" -[general] +[default.general] # The chip name of the chip to be debugged. chip = "nRF52840" # A list of chip descriptions to be loaded during runtime. @@ -25,7 +25,7 @@ chip_descriptions = [] # The default log level to be used. log_level = "Warn" -[rtt] +[default.rtt] # Whether or not an RTTUI should be opened after flashing. # This is exclusive and cannot be used with GDB at the moment. enabled = true @@ -38,9 +38,9 @@ timeout = 3000 # Whether timestamps in the RTTUI are enabled show_timestamps = true -[gdb] +[default.gdb] # Whether or not a GDB server should be opened after flashing. # This is exclusive and cannot be used with RTT at the moment. enabled = false # The connection string in host:port format wher the GDB server will open a socket. -# gdb_connection_string +# gdb_connection_string \ No newline at end of file From 384e8611303bb2c3f1ace2dab60f8111372b5d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 09:32:47 +0200 Subject: [PATCH 05/10] Add derives for enums --- nrf-hal-common/src/comp.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index 077e9ba9..5dcf5bb9 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -221,28 +221,33 @@ impl Comp { } } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum OperationMode { Differential, SingleEnded, } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum PowerMode { LowPower, Normal, HighSpeed, } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum CompResult { Above, Below, } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum Transition { Up, Down, Cross, } +#[derive(Debug, Eq, PartialEq, Clone, Copy)] pub enum VRef { Int1V2, Int1V8, From 7eaa48afbacc35211a504c7c8d5e62fcd3c5deb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 10:22:58 +0200 Subject: [PATCH 06/10] Replace analog pin index with enums --- nrf-hal-common/src/comp.rs | 77 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index 5dcf5bb9..f8955b46 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -5,9 +5,12 @@ //! Vref can be derived from multiple sources depending on the operation mode of the comparator. use { - crate::gpio::{Floating, Input}, - crate::pac::comp::{_EVENTS_CROSS, _EVENTS_DOWN, _EVENTS_UP}, - crate::pac::{generic::Reg, COMP}, + crate::gpio::{p0::*, Floating, Input}, + crate::pac::{ + comp::{extrefsel::EXTREFSEL_A, psel::PSEL_A, _EVENTS_CROSS, _EVENTS_DOWN, _EVENTS_UP}, + generic::Reg, + COMP, + }, }; /// A safe wrapper around the `COMP` peripheral. @@ -18,18 +21,7 @@ pub struct Comp { impl Comp { /// Takes ownership of the `COMP` peripheral, returning a safe wrapper. pub fn new(comp: COMP, input_pin: &P) -> Self { - comp.psel.write(|w| match input_pin.ain() { - 0 => w.psel().analog_input0(), - 1 => w.psel().analog_input1(), - 2 => w.psel().analog_input2(), - 3 => w.psel().analog_input3(), - 4 => w.psel().analog_input4(), - 5 => w.psel().analog_input5(), - 6 => w.psel().analog_input6(), - #[cfg(not(feature = "52810"))] - 7 => w.psel().analog_input7(), - _ => unreachable!(), - }); + comp.psel.write(|w| w.psel().variant(input_pin.ain())); comp.mode.write(|w| w.sp().normal()); comp.mode.write(|w| w.main().se()); comp.refsel.write(|w| w.refsel().int1v2()); @@ -63,17 +55,9 @@ impl Comp { /// Sets analog reference pin. #[inline(always)] pub fn aref_pin(&self, ref_pin: &P) -> &Self { - self.comp.extrefsel.write(|w| match ref_pin.ain() { - 0 => w.extrefsel().analog_reference0(), - 1 => w.extrefsel().analog_reference1(), - 2 => w.extrefsel().analog_reference2(), - 3 => w.extrefsel().analog_reference3(), - 4 => w.extrefsel().analog_reference4(), - 5 => w.extrefsel().analog_reference5(), - 6 => w.extrefsel().analog_reference6(), - 7 => w.extrefsel().analog_reference7(), - _ => unreachable!(), - }); + self.comp + .extrefsel + .write(|w| w.extrefsel().variant(ref_pin.aref())); self } @@ -258,29 +242,44 @@ pub enum VRef { /// Trait to represent analog input pins. pub trait AnalogPin { - /// Returns `AIN` id. - fn ain(&self) -> u8; + fn ain(&self) -> PSEL_A; + fn aref(&self) -> EXTREFSEL_A; } macro_rules! analog_pins { - ($($n:expr => $pin:path),*) => { + ($($pin:path => ($ain:expr, $aref:expr),)+) => { $( impl AnalogPin for $pin { - fn ain(&self) -> u8 { - $n + fn ain(&self) -> PSEL_A { + $ain + } + fn aref(&self) -> EXTREFSEL_A { + $aref } } )* }; } +#[cfg(not(feature = "52810"))] +analog_pins! { + P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), + P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), + P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), + P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), + P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), + P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), + P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), + P0_31> => (PSEL_A::ANALOGINPUT7, EXTREFSEL_A::ANALOGREFERENCE7), +} + +#[cfg(feature = "52810")] analog_pins! { - 0 => crate::gpio::p0::P0_02>, - 1 => crate::gpio::p0::P0_03>, - 2 => crate::gpio::p0::P0_04>, - 3 => crate::gpio::p0::P0_05>, - 4 => crate::gpio::p0::P0_28>, - 5 => crate::gpio::p0::P0_29>, - 6 => crate::gpio::p0::P0_30>, - 7 => crate::gpio::p0::P0_31> + P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), + P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), + P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), + P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), + P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), + P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), + P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), } From 18a465d7e6fbbfe5d8d1fc68d5625cdf46c187c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 13:55:27 +0200 Subject: [PATCH 07/10] Add separate traits for input and reference pins --- nrf-hal-common/src/comp.rs | 71 +++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 24 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index f8955b46..111e40d0 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -20,7 +20,7 @@ pub struct Comp { impl Comp { /// Takes ownership of the `COMP` peripheral, returning a safe wrapper. - pub fn new(comp: COMP, input_pin: &P) -> Self { + pub fn new(comp: COMP, input_pin: &P) -> Self { comp.psel.write(|w| w.psel().variant(input_pin.ain())); comp.mode.write(|w| w.sp().normal()); comp.mode.write(|w| w.main().se()); @@ -54,7 +54,7 @@ impl Comp { /// Sets analog reference pin. #[inline(always)] - pub fn aref_pin(&self, ref_pin: &P) -> &Self { + pub fn aref_pin(&self, ref_pin: &P) -> &Self { self.comp .extrefsel .write(|w| w.extrefsel().variant(ref_pin.aref())); @@ -63,7 +63,7 @@ impl Comp { /// Sets comparator mode to differential with external Vref pin. #[inline(always)] - pub fn differential(&self, ref_pin: &P) -> &Self { + pub fn differential(&self, ref_pin: &P) -> &Self { self.comp.mode.write(|w| w.main().diff()); self.aref_pin(ref_pin); self @@ -241,18 +241,30 @@ pub enum VRef { } /// Trait to represent analog input pins. -pub trait AnalogPin { +pub trait CompInputPin { fn ain(&self) -> PSEL_A; +} +/// Trait to represent analog ref pins. +pub trait CompRefPin { fn aref(&self) -> EXTREFSEL_A; } -macro_rules! analog_pins { - ($($pin:path => ($ain:expr, $aref:expr),)+) => { +macro_rules! comp_input_pins { + ($($pin:path => $ain:expr,)+) => { $( - impl AnalogPin for $pin { + impl CompInputPin for $pin { fn ain(&self) -> PSEL_A { $ain } + } + )* + }; +} + +macro_rules! comp_ref_pins { + ($($pin:path => $aref:expr,)+) => { + $( + impl CompRefPin for $pin { fn aref(&self) -> EXTREFSEL_A { $aref } @@ -261,25 +273,36 @@ macro_rules! analog_pins { }; } +comp_input_pins! { + P0_02> => PSEL_A::ANALOGINPUT0, + P0_03> => PSEL_A::ANALOGINPUT1, + P0_04> => PSEL_A::ANALOGINPUT2, + P0_05> => PSEL_A::ANALOGINPUT3, + P0_28> => PSEL_A::ANALOGINPUT4, + P0_29> => PSEL_A::ANALOGINPUT5, + P0_30> => PSEL_A::ANALOGINPUT6, + P0_31> => PSEL_A::ANALOGINPUT7, +} + #[cfg(not(feature = "52810"))] -analog_pins! { - P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), - P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), - P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), - P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), - P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), - P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), - P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), - P0_31> => (PSEL_A::ANALOGINPUT7, EXTREFSEL_A::ANALOGREFERENCE7), +comp_ref_pins! { + P0_02> => EXTREFSEL_A::ANALOGREFERENCE0, + P0_03> => EXTREFSEL_A::ANALOGREFERENCE1, + P0_04> => EXTREFSEL_A::ANALOGREFERENCE2, + P0_05> => EXTREFSEL_A::ANALOGREFERENCE3, + P0_28> => EXTREFSEL_A::ANALOGREFERENCE4, + P0_29> => EXTREFSEL_A::ANALOGREFERENCE5, + P0_30> => EXTREFSEL_A::ANALOGREFERENCE6, + P0_31> => EXTREFSEL_A::ANALOGREFERENCE7, } #[cfg(feature = "52810")] -analog_pins! { - P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), - P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), - P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), - P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), - P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), - P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), - P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), +comp_ref_pins! { + P0_02> => EXTREFSEL_A::ANALOGREFERENCE0, + P0_03> => EXTREFSEL_A::ANALOGREFERENCE1, + P0_04> => EXTREFSEL_A::ANALOGREFERENCE2, + P0_05> => EXTREFSEL_A::ANALOGREFERENCE3, + P0_28> => EXTREFSEL_A::ANALOGREFERENCE4, + P0_29> => EXTREFSEL_A::ANALOGREFERENCE5, + P0_30> => EXTREFSEL_A::ANALOGREFERENCE6, } From 4ddaf710705a6d452216694cd6978e9dbb7406b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 14:06:42 +0200 Subject: [PATCH 08/10] Add associated identifier for VRef::ARef with from_pin helper --- nrf-hal-common/src/comp.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index 111e40d0..6a09bb20 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -47,7 +47,10 @@ impl Comp { VRef::Int1V8 => w.refsel().int1v8(), VRef::Int2V4 => w.refsel().int2v4(), VRef::Vdd => w.refsel().vdd(), - VRef::ARef => w.refsel().aref(), + VRef::ARef(r) => { + self.comp.extrefsel.write(|w| w.extrefsel().variant(r)); + w.refsel().aref() + } }); self } @@ -231,13 +234,19 @@ pub enum Transition { Cross, } -#[derive(Debug, Eq, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Clone, Copy)] pub enum VRef { Int1V2, Int1V8, Int2V4, Vdd, - ARef, + ARef(EXTREFSEL_A), +} + +impl VRef { + pub fn from_pin(pin: &P) -> Self { + VRef::ARef(pin.aref()) + } } /// Trait to represent analog input pins. From 5a1db2c7b4cee27f183e6e11b32d2efc0cc75683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 14:28:46 +0200 Subject: [PATCH 09/10] Fix trait impls for 52810 --- nrf-hal-common/src/comp.rs | 55 +++++++++++++------------------------- 1 file changed, 19 insertions(+), 36 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index 6a09bb20..dd223b40 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -258,21 +258,15 @@ pub trait CompRefPin { fn aref(&self) -> EXTREFSEL_A; } -macro_rules! comp_input_pins { - ($($pin:path => $ain:expr,)+) => { +macro_rules! analog_pins { + ($($pin:path => ($ain:expr, $aref:expr),)+) => { $( impl CompInputPin for $pin { fn ain(&self) -> PSEL_A { $ain } } - )* - }; -} -macro_rules! comp_ref_pins { - ($($pin:path => $aref:expr,)+) => { - $( impl CompRefPin for $pin { fn aref(&self) -> EXTREFSEL_A { $aref @@ -282,36 +276,25 @@ macro_rules! comp_ref_pins { }; } -comp_input_pins! { - P0_02> => PSEL_A::ANALOGINPUT0, - P0_03> => PSEL_A::ANALOGINPUT1, - P0_04> => PSEL_A::ANALOGINPUT2, - P0_05> => PSEL_A::ANALOGINPUT3, - P0_28> => PSEL_A::ANALOGINPUT4, - P0_29> => PSEL_A::ANALOGINPUT5, - P0_30> => PSEL_A::ANALOGINPUT6, - P0_31> => PSEL_A::ANALOGINPUT7, -} - #[cfg(not(feature = "52810"))] -comp_ref_pins! { - P0_02> => EXTREFSEL_A::ANALOGREFERENCE0, - P0_03> => EXTREFSEL_A::ANALOGREFERENCE1, - P0_04> => EXTREFSEL_A::ANALOGREFERENCE2, - P0_05> => EXTREFSEL_A::ANALOGREFERENCE3, - P0_28> => EXTREFSEL_A::ANALOGREFERENCE4, - P0_29> => EXTREFSEL_A::ANALOGREFERENCE5, - P0_30> => EXTREFSEL_A::ANALOGREFERENCE6, - P0_31> => EXTREFSEL_A::ANALOGREFERENCE7, +analog_pins! { + P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), + P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), + P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), + P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), + P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), + P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), + P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), + P0_31> => (PSEL_A::ANALOGINPUT7, EXTREFSEL_A::ANALOGREFERENCE7), } #[cfg(feature = "52810")] -comp_ref_pins! { - P0_02> => EXTREFSEL_A::ANALOGREFERENCE0, - P0_03> => EXTREFSEL_A::ANALOGREFERENCE1, - P0_04> => EXTREFSEL_A::ANALOGREFERENCE2, - P0_05> => EXTREFSEL_A::ANALOGREFERENCE3, - P0_28> => EXTREFSEL_A::ANALOGREFERENCE4, - P0_29> => EXTREFSEL_A::ANALOGREFERENCE5, - P0_30> => EXTREFSEL_A::ANALOGREFERENCE6, +analog_pins! { + P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), + P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), + P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), + P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), + P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), + P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), + P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), } From 71f9027b0c926d006b78c437df96c097a467bdab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Alse=CC=81r?= Date: Sun, 2 Aug 2020 14:43:34 +0200 Subject: [PATCH 10/10] Split macros to not waste ANALOGREFERENCE7 on nRF52810 --- nrf-hal-common/src/comp.rs | 55 +++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/nrf-hal-common/src/comp.rs b/nrf-hal-common/src/comp.rs index dd223b40..f3a8187b 100644 --- a/nrf-hal-common/src/comp.rs +++ b/nrf-hal-common/src/comp.rs @@ -258,15 +258,21 @@ pub trait CompRefPin { fn aref(&self) -> EXTREFSEL_A; } -macro_rules! analog_pins { - ($($pin:path => ($ain:expr, $aref:expr),)+) => { +macro_rules! comp_input_pins { + ($($pin:path => $ain:expr,)+) => { $( impl CompInputPin for $pin { fn ain(&self) -> PSEL_A { $ain } } + )* + }; +} +macro_rules! comp_ref_pins { + ($($pin:path => $aref:expr,)+) => { + $( impl CompRefPin for $pin { fn aref(&self) -> EXTREFSEL_A { $aref @@ -276,25 +282,36 @@ macro_rules! analog_pins { }; } +comp_ref_pins! { + P0_02> => EXTREFSEL_A::ANALOGREFERENCE0, + P0_03> => EXTREFSEL_A::ANALOGREFERENCE1, + P0_04> => EXTREFSEL_A::ANALOGREFERENCE2, + P0_05> => EXTREFSEL_A::ANALOGREFERENCE3, + P0_28> => EXTREFSEL_A::ANALOGREFERENCE4, + P0_29> => EXTREFSEL_A::ANALOGREFERENCE5, + P0_30> => EXTREFSEL_A::ANALOGREFERENCE6, + P0_31> => EXTREFSEL_A::ANALOGREFERENCE7, +} + #[cfg(not(feature = "52810"))] -analog_pins! { - P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), - P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), - P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), - P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), - P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), - P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), - P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), - P0_31> => (PSEL_A::ANALOGINPUT7, EXTREFSEL_A::ANALOGREFERENCE7), +comp_input_pins! { + P0_02> => PSEL_A::ANALOGINPUT0, + P0_03> => PSEL_A::ANALOGINPUT1, + P0_04> => PSEL_A::ANALOGINPUT2, + P0_05> => PSEL_A::ANALOGINPUT3, + P0_28> => PSEL_A::ANALOGINPUT4, + P0_29> => PSEL_A::ANALOGINPUT5, + P0_30> => PSEL_A::ANALOGINPUT6, + P0_31> => PSEL_A::ANALOGINPUT7, } #[cfg(feature = "52810")] -analog_pins! { - P0_02> => (PSEL_A::ANALOGINPUT0, EXTREFSEL_A::ANALOGREFERENCE0), - P0_03> => (PSEL_A::ANALOGINPUT1, EXTREFSEL_A::ANALOGREFERENCE1), - P0_04> => (PSEL_A::ANALOGINPUT2, EXTREFSEL_A::ANALOGREFERENCE2), - P0_05> => (PSEL_A::ANALOGINPUT3, EXTREFSEL_A::ANALOGREFERENCE3), - P0_28> => (PSEL_A::ANALOGINPUT4, EXTREFSEL_A::ANALOGREFERENCE4), - P0_29> => (PSEL_A::ANALOGINPUT5, EXTREFSEL_A::ANALOGREFERENCE5), - P0_30> => (PSEL_A::ANALOGINPUT6, EXTREFSEL_A::ANALOGREFERENCE6), +comp_input_pins! { + P0_02> => PSEL_A::ANALOGINPUT0, + P0_03> => PSEL_A::ANALOGINPUT1, + P0_04> => PSEL_A::ANALOGINPUT2, + P0_05> => PSEL_A::ANALOGINPUT3, + P0_28> => PSEL_A::ANALOGINPUT4, + P0_29> => PSEL_A::ANALOGINPUT5, + P0_30> => PSEL_A::ANALOGINPUT6, }