From 238a9bd05b47abee236b37a8c1cad8a5c0ba98cc Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Fri, 24 Jul 2020 13:43:18 +0200 Subject: [PATCH 01/17] initial adc --- avr-hal-generic/src/adc.rs | 79 +++++++++++++++++++++++++++++++++ avr-hal-generic/src/lib.rs | 1 + avr-hal-generic/src/port.rs | 3 +- boards/arduino-uno/src/lib.rs | 1 + chips/atmega328p-hal/src/adc.rs | 21 +++++++++ chips/atmega328p-hal/src/lib.rs | 3 ++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 avr-hal-generic/src/adc.rs create mode 100644 chips/atmega328p-hal/src/adc.rs diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs new file mode 100644 index 0000000000..98acb9a82d --- /dev/null +++ b/avr-hal-generic/src/adc.rs @@ -0,0 +1,79 @@ +#[macro_export] +macro_rules! impl_adc { + ( + pub struct $Adc:ident { + type ChannelID = $ID:ty; + peripheral: $ADC:ty, + pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr),)+} + } + ) => { + + use $crate::void::Void; + use $crate::hal::adc::{Channel, OneShot}; + use $crate::nb; + use $crate::port::mode::Analog; + + pub struct $Adc { + peripheral: $ADC, + } + + impl $Adc { + pub fn new(peripheral: $ADC) -> $Adc { + peripheral.adcsra.write(|w| w.aden().set_bit() + .adps().val_0x07()); + Self { peripheral} + } + + pub fn adcsra(&self) -> u8 { + self.peripheral.adcsra.read().bits() + } + + pub fn admux(&self) -> u8 { + self.peripheral.admux.read().bits() + } + } + + impl OneShot<$Adc, WORD, PIN> for $Adc + where + WORD: From, + PIN: Channel<$Adc, ID=$ID>, + { + type Error = (); + + fn read(&mut self, _pin: &mut PIN) -> nb::Result { + + if self.peripheral.adcsra.read().adsc().bit_is_set() { + return Err(nb::Error::WouldBlock) + } + self.peripheral.admux.modify(|_, w| w + .refs().val_0x00() + .adlar().clear_bit() + .mux().variant(PIN::channel())); + + self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); + + if self.peripheral.adcsra.read().adsc().bit_is_set() { + return Err(nb::Error::WouldBlock) + } + Ok(self.peripheral.adc.read().bits().into()) + } + } + + $( + impl Channel<$Adc> for $PXi { + type ID = $ID; + fn channel() -> Self::ID { + $ChannelID + } + } + + impl $PXi { + /// Make this pin a analog input and enable the internal pull-up + pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { + adc.peripheral.didr0.write(|w| w.adc0d().set_bit()); + $PXi { _mode: core::marker::PhantomData } + } + } + )+ + } +} diff --git a/avr-hal-generic/src/lib.rs b/avr-hal-generic/src/lib.rs index 72668a6c43..94e977f742 100644 --- a/avr-hal-generic/src/lib.rs +++ b/avr-hal-generic/src/lib.rs @@ -16,6 +16,7 @@ pub mod port; pub mod serial; pub mod i2c; pub mod spi; +pub mod adc; /// Prelude containing all HAL traits pub mod prelude { diff --git a/avr-hal-generic/src/port.rs b/avr-hal-generic/src/port.rs index ef3620e36f..002648b415 100644 --- a/avr-hal-generic/src/port.rs +++ b/avr-hal-generic/src/port.rs @@ -13,6 +13,7 @@ pub mod mode { } /// Pin configured as a digital output pub struct Output; + pub struct Analog; impl private::Unimplementable for Output {} impl private::Unimplementable for Input {} @@ -246,7 +247,7 @@ macro_rules! impl_port { $( pub struct $PXi { - _mode: marker::PhantomData, + pub(crate)_mode: marker::PhantomData, } // Mode Switch implementations ---------------------------- {{{ diff --git a/boards/arduino-uno/src/lib.rs b/boards/arduino-uno/src/lib.rs index e5b9b6b219..00d9d62097 100644 --- a/boards/arduino-uno/src/lib.rs +++ b/boards/arduino-uno/src/lib.rs @@ -8,6 +8,7 @@ pub use atmega328p_hal::atmega328p; pub use crate::atmega328p::Peripherals; pub use atmega328p_hal::prelude; pub use atmega328p_hal::spi; +pub use atmega328p_hal::adc; pub use crate::pins::*; pub type Delay = hal::delay::Delay; diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs new file mode 100644 index 0000000000..a4cc3ba0bf --- /dev/null +++ b/chips/atmega328p-hal/src/adc.rs @@ -0,0 +1,21 @@ +extern crate avr_hal_generic as avr_hal; + +use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5, PC6}; + +use crate::atmega328p::adc::admux::MUX_A; + +avr_hal::impl_adc! { + pub struct Adc { + type ChannelID = MUX_A; + peripheral: crate::atmega328p::ADC, + pins: { + pc0: (PC0, MUX_A::ADC0), + pc1: (PC1, MUX_A::ADC1), + pc2: (PC2, MUX_A::ADC2), + pc3: (PC3, MUX_A::ADC3), + pc4: (PC4, MUX_A::ADC4), + pc5: (PC5, MUX_A::ADC5), + pc6: (PC6, MUX_A::ADC6), + } + } +} diff --git a/chips/atmega328p-hal/src/lib.rs b/chips/atmega328p-hal/src/lib.rs index 85a681cf93..7323f7f5b1 100644 --- a/chips/atmega328p-hal/src/lib.rs +++ b/chips/atmega328p-hal/src/lib.rs @@ -9,6 +9,9 @@ pub use avr_hal::delay; pub mod port; +pub mod adc; + + pub mod prelude { pub use crate::avr_hal::prelude::*; pub use crate::port::PortExt as _atmega_PortExt; From 0b4443647f2d2a464f3302d69b6667fd1c3f0df1 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 16:32:58 +0200 Subject: [PATCH 02/17] working adc --- avr-hal-generic/src/adc.rs | 98 +++++++++++++++++++++++++-------- chips/atmega328p-hal/src/adc.rs | 15 +++-- 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 98acb9a82d..b4f460c67b 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -1,10 +1,40 @@ + + +pub enum ClockRateDivision { + Factor2, + Factor4, + Factor8, + Factor16, + Factor32, + Factor64, + Factor128, +} + +pub enum ReferenceVoltage { + Aref, + Vcc, + Internal, +} + +pub struct AdcSettings{ + pub adps: ClockRateDivision, + pub aref: ReferenceVoltage +} + + +impl Default for AdcSettings { + fn default() -> Self { + Self { adps: ClockRateDivision::Factor128, aref: ReferenceVoltage::Vcc} + } +} + #[macro_export] macro_rules! impl_adc { ( pub struct $Adc:ident { type ChannelID = $ID:ty; peripheral: $ADC:ty, - pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr),)+} + pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr, $name:ident),)+} } ) => { @@ -12,24 +42,46 @@ macro_rules! impl_adc { use $crate::hal::adc::{Channel, OneShot}; use $crate::nb; use $crate::port::mode::Analog; + pub use avr_hal::adc::*; pub struct $Adc { peripheral: $ADC, + is_reading: bool, } impl $Adc { - pub fn new(peripheral: $ADC) -> $Adc { - peripheral.adcsra.write(|w| w.aden().set_bit() - .adps().val_0x07()); - Self { peripheral} + pub fn new(peripheral: $ADC, settings: AdcSettings) -> $Adc { + let s = Self { peripheral, is_reading: false } ; + s.enable(settings); + s } - pub fn adcsra(&self) -> u8 { - self.peripheral.adcsra.read().bits() + fn enable(&self, settings: AdcSettings) { + self.peripheral.adcsra.write(|w| {w.aden().set_bit(); + match settings.adps { + ClockRateDivision::Factor2 => w.adps().val_0x01(), + ClockRateDivision::Factor4 => w.adps().val_0x02(), + ClockRateDivision::Factor8 => w.adps().val_0x03(), + ClockRateDivision::Factor16 => w.adps().val_0x04(), + ClockRateDivision::Factor32 => w.adps().val_0x05(), + ClockRateDivision::Factor64 => w.adps().val_0x06(), + ClockRateDivision::Factor128 => w.adps().val_0x07(), + }}); + self.peripheral.admux.write(|w| match settings.aref { + ReferenceVoltage::Aref => w.refs().val_0x00(), + ReferenceVoltage::Vcc => w.refs().val_0x01(), + ReferenceVoltage::Internal => w.refs().val_0x03(), + }); + } - pub fn admux(&self) -> u8 { - self.peripheral.admux.read().bits() + fn disable(&self) { + self.peripheral.adcsra.reset(); + } + + pub fn release(self) -> $ADC { + self.disable(); + self.peripheral } } @@ -41,21 +93,19 @@ macro_rules! impl_adc { type Error = (); fn read(&mut self, _pin: &mut PIN) -> nb::Result { - - if self.peripheral.adcsra.read().adsc().bit_is_set() { - return Err(nb::Error::WouldBlock) - } - self.peripheral.admux.modify(|_, w| w - .refs().val_0x00() - .adlar().clear_bit() - .mux().variant(PIN::channel())); - - self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); - - if self.peripheral.adcsra.read().adsc().bit_is_set() { - return Err(nb::Error::WouldBlock) + match (self.is_reading, self.peripheral.adcsra.read().adsc().bit_is_set()) { + (true, true) => Err(nb::Error::WouldBlock), + (true, false) => { + self.is_reading = false; + Ok(self.peripheral.adc.read().bits().into()) + }, + (false, _) => { + self.is_reading = true; self.peripheral.admux.modify(|_, w| w.adlar().clear_bit() + .mux().variant(PIN::channel())); + self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); + Err(nb::Error::WouldBlock) + } } - Ok(self.peripheral.adc.read().bits().into()) } } @@ -70,7 +120,7 @@ macro_rules! impl_adc { impl $PXi { /// Make this pin a analog input and enable the internal pull-up pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { - adc.peripheral.didr0.write(|w| w.adc0d().set_bit()); + adc.peripheral.didr0.modify(|_, w| w.$name().set_bit()); $PXi { _mode: core::marker::PhantomData } } } diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs index a4cc3ba0bf..ab0939ef7d 100644 --- a/chips/atmega328p-hal/src/adc.rs +++ b/chips/atmega328p-hal/src/adc.rs @@ -1,6 +1,6 @@ extern crate avr_hal_generic as avr_hal; -use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5, PC6}; +use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5}; use crate::atmega328p::adc::admux::MUX_A; @@ -9,13 +9,12 @@ avr_hal::impl_adc! { type ChannelID = MUX_A; peripheral: crate::atmega328p::ADC, pins: { - pc0: (PC0, MUX_A::ADC0), - pc1: (PC1, MUX_A::ADC1), - pc2: (PC2, MUX_A::ADC2), - pc3: (PC3, MUX_A::ADC3), - pc4: (PC4, MUX_A::ADC4), - pc5: (PC5, MUX_A::ADC5), - pc6: (PC6, MUX_A::ADC6), + pc0: (PC0, MUX_A::ADC0, adc0d), + pc1: (PC1, MUX_A::ADC1, adc1d), + pc2: (PC2, MUX_A::ADC2, adc2d), + pc3: (PC3, MUX_A::ADC3, adc3d), + pc4: (PC4, MUX_A::ADC4, adc4d), + pc5: (PC5, MUX_A::ADC5, adc5d), } } } From 1995f7eca50fd1092e12bcc1b200f8a79fdeb38b Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 16:40:19 +0200 Subject: [PATCH 03/17] . --- chips/atmega1280-hal/Cargo.toml | 3 ++- chips/atmega328p-hal/Cargo.toml | 3 ++- chips/atmega328p-hal/src/lib.rs | 1 - chips/atmega32u4-hal/Cargo.toml | 3 ++- chips/attiny85-hal/Cargo.toml | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/chips/atmega1280-hal/Cargo.toml b/chips/atmega1280-hal/Cargo.toml index f9926fdd48..a3a74dc05f 100644 --- a/chips/atmega1280-hal/Cargo.toml +++ b/chips/atmega1280-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega1280"] \ No newline at end of file diff --git a/chips/atmega328p-hal/Cargo.toml b/chips/atmega328p-hal/Cargo.toml index eb04dccc45..606c34c244 100644 --- a/chips/atmega328p-hal/Cargo.toml +++ b/chips/atmega328p-hal/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega328p"] diff --git a/chips/atmega328p-hal/src/lib.rs b/chips/atmega328p-hal/src/lib.rs index 7323f7f5b1..191e02cdc9 100644 --- a/chips/atmega328p-hal/src/lib.rs +++ b/chips/atmega328p-hal/src/lib.rs @@ -11,7 +11,6 @@ pub mod port; pub mod adc; - pub mod prelude { pub use crate::avr_hal::prelude::*; pub use crate::port::PortExt as _atmega_PortExt; diff --git a/chips/atmega32u4-hal/Cargo.toml b/chips/atmega32u4-hal/Cargo.toml index b7a229d489..783e302ddb 100644 --- a/chips/atmega32u4-hal/Cargo.toml +++ b/chips/atmega32u4-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega32u4"] diff --git a/chips/attiny85-hal/Cargo.toml b/chips/attiny85-hal/Cargo.toml index 53ece3daa9..0ad228805a 100644 --- a/chips/attiny85-hal/Cargo.toml +++ b/chips/attiny85-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["attiny85"] From fbbc84b470d9d4198c5c90b11b22bddda77120dd Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 19:16:35 +0200 Subject: [PATCH 04/17] revert dependencie overide --- chips/atmega1280-hal/Cargo.toml | 3 +-- chips/atmega328p-hal/Cargo.toml | 3 +-- chips/atmega32u4-hal/Cargo.toml | 3 +-- chips/attiny85-hal/Cargo.toml | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/chips/atmega1280-hal/Cargo.toml b/chips/atmega1280-hal/Cargo.toml index a3a74dc05f..f9926fdd48 100644 --- a/chips/atmega1280-hal/Cargo.toml +++ b/chips/atmega1280-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega1280"] \ No newline at end of file diff --git a/chips/atmega328p-hal/Cargo.toml b/chips/atmega328p-hal/Cargo.toml index 606c34c244..eb04dccc45 100644 --- a/chips/atmega328p-hal/Cargo.toml +++ b/chips/atmega328p-hal/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega328p"] diff --git a/chips/atmega32u4-hal/Cargo.toml b/chips/atmega32u4-hal/Cargo.toml index 783e302ddb..b7a229d489 100644 --- a/chips/atmega32u4-hal/Cargo.toml +++ b/chips/atmega32u4-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega32u4"] diff --git a/chips/attiny85-hal/Cargo.toml b/chips/attiny85-hal/Cargo.toml index 0ad228805a..53ece3daa9 100644 --- a/chips/attiny85-hal/Cargo.toml +++ b/chips/attiny85-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["attiny85"] From 17592abcc61c1f2a512ee9deabe0a393680975d9 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Fri, 24 Jul 2020 13:43:18 +0200 Subject: [PATCH 05/17] initial adc --- avr-hal-generic/src/adc.rs | 79 +++++++++++++++++++++++++++++++++ avr-hal-generic/src/lib.rs | 1 + avr-hal-generic/src/port.rs | 3 +- boards/arduino-uno/src/lib.rs | 1 + chips/atmega328p-hal/src/adc.rs | 21 +++++++++ chips/atmega328p-hal/src/lib.rs | 3 ++ 6 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 avr-hal-generic/src/adc.rs create mode 100644 chips/atmega328p-hal/src/adc.rs diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs new file mode 100644 index 0000000000..98acb9a82d --- /dev/null +++ b/avr-hal-generic/src/adc.rs @@ -0,0 +1,79 @@ +#[macro_export] +macro_rules! impl_adc { + ( + pub struct $Adc:ident { + type ChannelID = $ID:ty; + peripheral: $ADC:ty, + pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr),)+} + } + ) => { + + use $crate::void::Void; + use $crate::hal::adc::{Channel, OneShot}; + use $crate::nb; + use $crate::port::mode::Analog; + + pub struct $Adc { + peripheral: $ADC, + } + + impl $Adc { + pub fn new(peripheral: $ADC) -> $Adc { + peripheral.adcsra.write(|w| w.aden().set_bit() + .adps().val_0x07()); + Self { peripheral} + } + + pub fn adcsra(&self) -> u8 { + self.peripheral.adcsra.read().bits() + } + + pub fn admux(&self) -> u8 { + self.peripheral.admux.read().bits() + } + } + + impl OneShot<$Adc, WORD, PIN> for $Adc + where + WORD: From, + PIN: Channel<$Adc, ID=$ID>, + { + type Error = (); + + fn read(&mut self, _pin: &mut PIN) -> nb::Result { + + if self.peripheral.adcsra.read().adsc().bit_is_set() { + return Err(nb::Error::WouldBlock) + } + self.peripheral.admux.modify(|_, w| w + .refs().val_0x00() + .adlar().clear_bit() + .mux().variant(PIN::channel())); + + self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); + + if self.peripheral.adcsra.read().adsc().bit_is_set() { + return Err(nb::Error::WouldBlock) + } + Ok(self.peripheral.adc.read().bits().into()) + } + } + + $( + impl Channel<$Adc> for $PXi { + type ID = $ID; + fn channel() -> Self::ID { + $ChannelID + } + } + + impl $PXi { + /// Make this pin a analog input and enable the internal pull-up + pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { + adc.peripheral.didr0.write(|w| w.adc0d().set_bit()); + $PXi { _mode: core::marker::PhantomData } + } + } + )+ + } +} diff --git a/avr-hal-generic/src/lib.rs b/avr-hal-generic/src/lib.rs index d9f04aa8b9..34e6c1ae6b 100644 --- a/avr-hal-generic/src/lib.rs +++ b/avr-hal-generic/src/lib.rs @@ -18,6 +18,7 @@ pub mod port; pub mod serial; pub mod i2c; pub mod spi; +pub mod adc; /// Prelude containing all HAL traits pub mod prelude { diff --git a/avr-hal-generic/src/port.rs b/avr-hal-generic/src/port.rs index ef3620e36f..002648b415 100644 --- a/avr-hal-generic/src/port.rs +++ b/avr-hal-generic/src/port.rs @@ -13,6 +13,7 @@ pub mod mode { } /// Pin configured as a digital output pub struct Output; + pub struct Analog; impl private::Unimplementable for Output {} impl private::Unimplementable for Input {} @@ -246,7 +247,7 @@ macro_rules! impl_port { $( pub struct $PXi { - _mode: marker::PhantomData, + pub(crate)_mode: marker::PhantomData, } // Mode Switch implementations ---------------------------- {{{ diff --git a/boards/arduino-uno/src/lib.rs b/boards/arduino-uno/src/lib.rs index e5b9b6b219..00d9d62097 100644 --- a/boards/arduino-uno/src/lib.rs +++ b/boards/arduino-uno/src/lib.rs @@ -8,6 +8,7 @@ pub use atmega328p_hal::atmega328p; pub use crate::atmega328p::Peripherals; pub use atmega328p_hal::prelude; pub use atmega328p_hal::spi; +pub use atmega328p_hal::adc; pub use crate::pins::*; pub type Delay = hal::delay::Delay; diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs new file mode 100644 index 0000000000..a4cc3ba0bf --- /dev/null +++ b/chips/atmega328p-hal/src/adc.rs @@ -0,0 +1,21 @@ +extern crate avr_hal_generic as avr_hal; + +use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5, PC6}; + +use crate::atmega328p::adc::admux::MUX_A; + +avr_hal::impl_adc! { + pub struct Adc { + type ChannelID = MUX_A; + peripheral: crate::atmega328p::ADC, + pins: { + pc0: (PC0, MUX_A::ADC0), + pc1: (PC1, MUX_A::ADC1), + pc2: (PC2, MUX_A::ADC2), + pc3: (PC3, MUX_A::ADC3), + pc4: (PC4, MUX_A::ADC4), + pc5: (PC5, MUX_A::ADC5), + pc6: (PC6, MUX_A::ADC6), + } + } +} diff --git a/chips/atmega328p-hal/src/lib.rs b/chips/atmega328p-hal/src/lib.rs index f3168837b3..b61354da7d 100644 --- a/chips/atmega328p-hal/src/lib.rs +++ b/chips/atmega328p-hal/src/lib.rs @@ -9,6 +9,9 @@ pub use avr_hal::delay; pub mod port; +pub mod adc; + + pub mod prelude { pub use crate::avr_hal::prelude::*; pub use crate::port::PortExt as _; From 0ff76356c011f72ef7d3df5af5ac7dd44b35a2c7 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 16:32:58 +0200 Subject: [PATCH 06/17] working adc --- avr-hal-generic/src/adc.rs | 98 +++++++++++++++++++++++++-------- chips/atmega328p-hal/src/adc.rs | 15 +++-- 2 files changed, 81 insertions(+), 32 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 98acb9a82d..b4f460c67b 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -1,10 +1,40 @@ + + +pub enum ClockRateDivision { + Factor2, + Factor4, + Factor8, + Factor16, + Factor32, + Factor64, + Factor128, +} + +pub enum ReferenceVoltage { + Aref, + Vcc, + Internal, +} + +pub struct AdcSettings{ + pub adps: ClockRateDivision, + pub aref: ReferenceVoltage +} + + +impl Default for AdcSettings { + fn default() -> Self { + Self { adps: ClockRateDivision::Factor128, aref: ReferenceVoltage::Vcc} + } +} + #[macro_export] macro_rules! impl_adc { ( pub struct $Adc:ident { type ChannelID = $ID:ty; peripheral: $ADC:ty, - pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr),)+} + pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr, $name:ident),)+} } ) => { @@ -12,24 +42,46 @@ macro_rules! impl_adc { use $crate::hal::adc::{Channel, OneShot}; use $crate::nb; use $crate::port::mode::Analog; + pub use avr_hal::adc::*; pub struct $Adc { peripheral: $ADC, + is_reading: bool, } impl $Adc { - pub fn new(peripheral: $ADC) -> $Adc { - peripheral.adcsra.write(|w| w.aden().set_bit() - .adps().val_0x07()); - Self { peripheral} + pub fn new(peripheral: $ADC, settings: AdcSettings) -> $Adc { + let s = Self { peripheral, is_reading: false } ; + s.enable(settings); + s } - pub fn adcsra(&self) -> u8 { - self.peripheral.adcsra.read().bits() + fn enable(&self, settings: AdcSettings) { + self.peripheral.adcsra.write(|w| {w.aden().set_bit(); + match settings.adps { + ClockRateDivision::Factor2 => w.adps().val_0x01(), + ClockRateDivision::Factor4 => w.adps().val_0x02(), + ClockRateDivision::Factor8 => w.adps().val_0x03(), + ClockRateDivision::Factor16 => w.adps().val_0x04(), + ClockRateDivision::Factor32 => w.adps().val_0x05(), + ClockRateDivision::Factor64 => w.adps().val_0x06(), + ClockRateDivision::Factor128 => w.adps().val_0x07(), + }}); + self.peripheral.admux.write(|w| match settings.aref { + ReferenceVoltage::Aref => w.refs().val_0x00(), + ReferenceVoltage::Vcc => w.refs().val_0x01(), + ReferenceVoltage::Internal => w.refs().val_0x03(), + }); + } - pub fn admux(&self) -> u8 { - self.peripheral.admux.read().bits() + fn disable(&self) { + self.peripheral.adcsra.reset(); + } + + pub fn release(self) -> $ADC { + self.disable(); + self.peripheral } } @@ -41,21 +93,19 @@ macro_rules! impl_adc { type Error = (); fn read(&mut self, _pin: &mut PIN) -> nb::Result { - - if self.peripheral.adcsra.read().adsc().bit_is_set() { - return Err(nb::Error::WouldBlock) - } - self.peripheral.admux.modify(|_, w| w - .refs().val_0x00() - .adlar().clear_bit() - .mux().variant(PIN::channel())); - - self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); - - if self.peripheral.adcsra.read().adsc().bit_is_set() { - return Err(nb::Error::WouldBlock) + match (self.is_reading, self.peripheral.adcsra.read().adsc().bit_is_set()) { + (true, true) => Err(nb::Error::WouldBlock), + (true, false) => { + self.is_reading = false; + Ok(self.peripheral.adc.read().bits().into()) + }, + (false, _) => { + self.is_reading = true; self.peripheral.admux.modify(|_, w| w.adlar().clear_bit() + .mux().variant(PIN::channel())); + self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); + Err(nb::Error::WouldBlock) + } } - Ok(self.peripheral.adc.read().bits().into()) } } @@ -70,7 +120,7 @@ macro_rules! impl_adc { impl $PXi { /// Make this pin a analog input and enable the internal pull-up pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { - adc.peripheral.didr0.write(|w| w.adc0d().set_bit()); + adc.peripheral.didr0.modify(|_, w| w.$name().set_bit()); $PXi { _mode: core::marker::PhantomData } } } diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs index a4cc3ba0bf..ab0939ef7d 100644 --- a/chips/atmega328p-hal/src/adc.rs +++ b/chips/atmega328p-hal/src/adc.rs @@ -1,6 +1,6 @@ extern crate avr_hal_generic as avr_hal; -use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5, PC6}; +use crate::port::portc::{PC0, PC1, PC2, PC3, PC4, PC5}; use crate::atmega328p::adc::admux::MUX_A; @@ -9,13 +9,12 @@ avr_hal::impl_adc! { type ChannelID = MUX_A; peripheral: crate::atmega328p::ADC, pins: { - pc0: (PC0, MUX_A::ADC0), - pc1: (PC1, MUX_A::ADC1), - pc2: (PC2, MUX_A::ADC2), - pc3: (PC3, MUX_A::ADC3), - pc4: (PC4, MUX_A::ADC4), - pc5: (PC5, MUX_A::ADC5), - pc6: (PC6, MUX_A::ADC6), + pc0: (PC0, MUX_A::ADC0, adc0d), + pc1: (PC1, MUX_A::ADC1, adc1d), + pc2: (PC2, MUX_A::ADC2, adc2d), + pc3: (PC3, MUX_A::ADC3, adc3d), + pc4: (PC4, MUX_A::ADC4, adc4d), + pc5: (PC5, MUX_A::ADC5, adc5d), } } } From 9da8d5910372b5c82dd0e465a7f731d220501faf Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 16:40:19 +0200 Subject: [PATCH 07/17] . --- chips/atmega1280-hal/Cargo.toml | 3 ++- chips/atmega328p-hal/Cargo.toml | 3 ++- chips/atmega328p-hal/src/lib.rs | 1 - chips/atmega32u4-hal/Cargo.toml | 3 ++- chips/attiny85-hal/Cargo.toml | 3 ++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/chips/atmega1280-hal/Cargo.toml b/chips/atmega1280-hal/Cargo.toml index f9926fdd48..a3a74dc05f 100644 --- a/chips/atmega1280-hal/Cargo.toml +++ b/chips/atmega1280-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega1280"] \ No newline at end of file diff --git a/chips/atmega328p-hal/Cargo.toml b/chips/atmega328p-hal/Cargo.toml index eb04dccc45..606c34c244 100644 --- a/chips/atmega328p-hal/Cargo.toml +++ b/chips/atmega328p-hal/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega328p"] diff --git a/chips/atmega328p-hal/src/lib.rs b/chips/atmega328p-hal/src/lib.rs index b61354da7d..f6c9c43a62 100644 --- a/chips/atmega328p-hal/src/lib.rs +++ b/chips/atmega328p-hal/src/lib.rs @@ -11,7 +11,6 @@ pub mod port; pub mod adc; - pub mod prelude { pub use crate::avr_hal::prelude::*; pub use crate::port::PortExt as _; diff --git a/chips/atmega32u4-hal/Cargo.toml b/chips/atmega32u4-hal/Cargo.toml index b7a229d489..783e302ddb 100644 --- a/chips/atmega32u4-hal/Cargo.toml +++ b/chips/atmega32u4-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["atmega32u4"] diff --git a/chips/attiny85-hal/Cargo.toml b/chips/attiny85-hal/Cargo.toml index 53ece3daa9..0ad228805a 100644 --- a/chips/attiny85-hal/Cargo.toml +++ b/chips/attiny85-hal/Cargo.toml @@ -8,5 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -git = "https://github.com/Rahix/avr-device" +# git = "https://github.com/Rahix/avr-device" +path = "../../../avr-device" features = ["attiny85"] From 80afd1dc15e8e5a9fc696b459749f8da644de75e Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 19:16:35 +0200 Subject: [PATCH 08/17] revert dependencie overide --- chips/atmega1280-hal/Cargo.toml | 3 +-- chips/atmega328p-hal/Cargo.toml | 3 +-- chips/atmega32u4-hal/Cargo.toml | 3 +-- chips/attiny85-hal/Cargo.toml | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/chips/atmega1280-hal/Cargo.toml b/chips/atmega1280-hal/Cargo.toml index a3a74dc05f..f9926fdd48 100644 --- a/chips/atmega1280-hal/Cargo.toml +++ b/chips/atmega1280-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega1280"] \ No newline at end of file diff --git a/chips/atmega328p-hal/Cargo.toml b/chips/atmega328p-hal/Cargo.toml index 606c34c244..eb04dccc45 100644 --- a/chips/atmega328p-hal/Cargo.toml +++ b/chips/atmega328p-hal/Cargo.toml @@ -8,7 +8,6 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega328p"] diff --git a/chips/atmega32u4-hal/Cargo.toml b/chips/atmega32u4-hal/Cargo.toml index 783e302ddb..b7a229d489 100644 --- a/chips/atmega32u4-hal/Cargo.toml +++ b/chips/atmega32u4-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["atmega32u4"] diff --git a/chips/attiny85-hal/Cargo.toml b/chips/attiny85-hal/Cargo.toml index 0ad228805a..53ece3daa9 100644 --- a/chips/attiny85-hal/Cargo.toml +++ b/chips/attiny85-hal/Cargo.toml @@ -8,6 +8,5 @@ edition = "2018" avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] -# git = "https://github.com/Rahix/avr-device" -path = "../../../avr-device" +git = "https://github.com/Rahix/avr-device" features = ["attiny85"] From 5a67d8373fd6ff1f3f0a196896cb2499020ce4a4 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 22:28:12 +0200 Subject: [PATCH 09/17] fixed issues --- avr-hal-generic/src/adc.rs | 100 ++++++++++++++++++++++---------- chips/atmega328p-hal/src/adc.rs | 12 ++-- 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index b4f460c67b..7e246d1df5 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -1,5 +1,8 @@ - +/// The division factor between the system clock frequency and the input clock to the AD converter. +/// +/// To get 10bit precision, clock from 50kHz to 200kHz must be supplied. If you need less precision, you can supply higher clock. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ClockRateDivision { Factor2, Factor4, @@ -10,31 +13,47 @@ pub enum ClockRateDivision { Factor128, } + +impl Default for ClockRateDivision { + fn default() -> Self { + Self::Factor128 + } +} + + +/// Select the voltage reference for the ADC peripheral +/// +/// The inernal voltage reference options may not be used if an external reference voltage isbeing applied to the AREF pin. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ReferenceVoltage { + /// Voltage applied to AREF pin. Aref, - Vcc, + /// Default referece voltage. + AVcc, + /// Internal reference voltage Internal, } -pub struct AdcSettings{ - pub adps: ClockRateDivision, - pub aref: ReferenceVoltage -} - - -impl Default for AdcSettings { +impl Default for ReferenceVoltage { fn default() -> Self { - Self { adps: ClockRateDivision::Factor128, aref: ReferenceVoltage::Vcc} + Self::AVcc } } +#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] +pub struct AdcSettings{ + pub clock_divider: ClockRateDivision, + pub ref_voltage: ReferenceVoltage +} + + #[macro_export] macro_rules! impl_adc { ( pub struct $Adc:ident { type ChannelID = $ID:ty; peripheral: $ADC:ty, - pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr, $name:ident),)+} + pins: {$($pxi:ident: ($PXi:ident, $ChannelIDExpr:expr, $ChannelIDPat:pat, $name:ident),)+} } ) => { @@ -46,31 +65,32 @@ macro_rules! impl_adc { pub struct $Adc { peripheral: $ADC, - is_reading: bool, + $( $pxi: bool,)+ } impl $Adc { pub fn new(peripheral: $ADC, settings: AdcSettings) -> $Adc { - let s = Self { peripheral, is_reading: false } ; + let s = Self { peripheral, $( $pxi: false,)+ } ; s.enable(settings); s } fn enable(&self, settings: AdcSettings) { - self.peripheral.adcsra.write(|w| {w.aden().set_bit(); - match settings.adps { - ClockRateDivision::Factor2 => w.adps().val_0x01(), - ClockRateDivision::Factor4 => w.adps().val_0x02(), - ClockRateDivision::Factor8 => w.adps().val_0x03(), - ClockRateDivision::Factor16 => w.adps().val_0x04(), - ClockRateDivision::Factor32 => w.adps().val_0x05(), - ClockRateDivision::Factor64 => w.adps().val_0x06(), - ClockRateDivision::Factor128 => w.adps().val_0x07(), - }}); - self.peripheral.admux.write(|w| match settings.aref { - ReferenceVoltage::Aref => w.refs().val_0x00(), - ReferenceVoltage::Vcc => w.refs().val_0x01(), - ReferenceVoltage::Internal => w.refs().val_0x03(), + self.peripheral.adcsra.write(|w| { + w.aden().set_bit(); + match settings.clock_divider { + ClockRateDivision::Factor2 => w.adps().prescaler_2(), + ClockRateDivision::Factor4 => w.adps().prescaler_4(), + ClockRateDivision::Factor8 => w.adps().prescaler_8(), + ClockRateDivision::Factor16 => w.adps().prescaler_16(), + ClockRateDivision::Factor32 => w.adps().prescaler_32(), + ClockRateDivision::Factor64 => w.adps().prescaler_64(), + ClockRateDivision::Factor128 => w.adps().prescaler_128(), + }}); + self.peripheral.admux.write(|w| match settings.ref_voltage { + ReferenceVoltage::Aref => w.refs().aref(), + ReferenceVoltage::AVcc => w.refs().avcc(), + ReferenceVoltage::Internal => w.refs().internal(), }); } @@ -79,6 +99,20 @@ macro_rules! impl_adc { self.peripheral.adcsra.reset(); } + fn set_reading(&mut self, channel: $ID, state: bool) { + match channel { + $( $ChannelIDPat => self.$pxi = state, )+ + _ => unreachable!(), + } + } + + fn is_reading(&self, channel: $ID) -> bool { + match channel { + $( $ChannelIDPat => self.$pxi, )+ + _ => unreachable!(), + } + } + pub fn release(self) -> $ADC { self.disable(); self.peripheral @@ -93,15 +127,17 @@ macro_rules! impl_adc { type Error = (); fn read(&mut self, _pin: &mut PIN) -> nb::Result { - match (self.is_reading, self.peripheral.adcsra.read().adsc().bit_is_set()) { + let channel = PIN::channel(); + + match (self.is_reading(channel), self.peripheral.adcsra.read().adsc().bit_is_set()) { (true, true) => Err(nb::Error::WouldBlock), (true, false) => { - self.is_reading = false; + self.set_reading(channel, false); Ok(self.peripheral.adc.read().bits().into()) }, (false, _) => { - self.is_reading = true; self.peripheral.admux.modify(|_, w| w.adlar().clear_bit() - .mux().variant(PIN::channel())); + self.set_reading(channel, true); + self.peripheral.admux.modify(|_, w| w.mux().variant(channel)); self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); Err(nb::Error::WouldBlock) } @@ -113,7 +149,7 @@ macro_rules! impl_adc { impl Channel<$Adc> for $PXi { type ID = $ID; fn channel() -> Self::ID { - $ChannelID + $ChannelIDExpr } } diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs index ab0939ef7d..f21b0c6616 100644 --- a/chips/atmega328p-hal/src/adc.rs +++ b/chips/atmega328p-hal/src/adc.rs @@ -9,12 +9,12 @@ avr_hal::impl_adc! { type ChannelID = MUX_A; peripheral: crate::atmega328p::ADC, pins: { - pc0: (PC0, MUX_A::ADC0, adc0d), - pc1: (PC1, MUX_A::ADC1, adc1d), - pc2: (PC2, MUX_A::ADC2, adc2d), - pc3: (PC3, MUX_A::ADC3, adc3d), - pc4: (PC4, MUX_A::ADC4, adc4d), - pc5: (PC5, MUX_A::ADC5, adc5d), + pc0: (PC0, MUX_A::ADC0, MUX_A::ADC0, adc0d), + pc1: (PC1, MUX_A::ADC1, MUX_A::ADC1, adc1d), + pc2: (PC2, MUX_A::ADC2, MUX_A::ADC2, adc2d), + pc3: (PC3, MUX_A::ADC3, MUX_A::ADC3, adc3d), + pc4: (PC4, MUX_A::ADC4, MUX_A::ADC4, adc4d), + pc5: (PC5, MUX_A::ADC5, MUX_A::ADC5, adc5d), } } } From a4259d1aecdff6519a0664be28eae920915f0c61 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 22:28:21 +0200 Subject: [PATCH 10/17] add example --- boards/arduino-uno/examples/uno-adc.rs | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 boards/arduino-uno/examples/uno-adc.rs diff --git a/boards/arduino-uno/examples/uno-adc.rs b/boards/arduino-uno/examples/uno-adc.rs new file mode 100644 index 0000000000..3cd4377059 --- /dev/null +++ b/boards/arduino-uno/examples/uno-adc.rs @@ -0,0 +1,46 @@ +#![no_std] +#![no_main] + +extern crate panic_halt; +use arduino_uno::prelude::*; + +// This example opens a serial connection to the host computer. On most POSIX operating systems (like GNU/Linux or +// OSX), you can interface with the program by running (assuming the device appears as ttyACM0) +// +// $ sudo screen /dev/ttyACM0 9600 + +#[no_mangle] +pub extern fn main() -> ! { + let dp = arduino_uno::Peripherals::take().unwrap(); + + let mut pins = arduino_uno::Pins::new( + dp.PORTB, + dp.PORTC, + dp.PORTD, + ); + + let mut serial = arduino_uno::Serial::new( + dp.USART0, + pins.d0, + pins.d1.into_output(&mut pins.ddr), + 9600, + ); + + + // create the Analog Digital Converter + let mut adc = arduino_uno::adc::Adc::new(dp.ADC, arduino_uno::adc::AdcSettings::default()); + + // Convert pin to Analog input + let mut a0 = pins.a0.into_analog_input(&mut adc); + + + ufmt::uwriteln!(&mut serial, "Reading Analog Input on PORT a0\r").unwrap(); + + loop { + // Read the Analog value + let aread: u16 = nb::block!{adc.read(&mut a0)}.unwrap(); + + // Write it to Serial + ufmt::uwriteln!(&mut serial, "read: {:?}", aread); + } +} From 86539b534f068864a4748076bb7292cd572b4cfe Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 23:23:36 +0200 Subject: [PATCH 11/17] Update boards/arduino-uno/examples/uno-adc.rs Co-authored-by: Rahix --- boards/arduino-uno/examples/uno-adc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/arduino-uno/examples/uno-adc.rs b/boards/arduino-uno/examples/uno-adc.rs index 3cd4377059..77baebab77 100644 --- a/boards/arduino-uno/examples/uno-adc.rs +++ b/boards/arduino-uno/examples/uno-adc.rs @@ -41,6 +41,6 @@ pub extern fn main() -> ! { let aread: u16 = nb::block!{adc.read(&mut a0)}.unwrap(); // Write it to Serial - ufmt::uwriteln!(&mut serial, "read: {:?}", aread); + ufmt::uwriteln!(&mut serial, "read: {}\r", aread); } } From 549b8622ded050c456f4d1fa086799bbd7bd375c Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 23:23:58 +0200 Subject: [PATCH 12/17] fix typo Co-authored-by: Rahix --- avr-hal-generic/src/adc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 7e246d1df5..3c5c665286 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -23,7 +23,7 @@ impl Default for ClockRateDivision { /// Select the voltage reference for the ADC peripheral /// -/// The inernal voltage reference options may not be used if an external reference voltage isbeing applied to the AREF pin. +/// The internal voltage reference options may not be used if an external reference voltage is being applied to the AREF pin. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ReferenceVoltage { /// Voltage applied to AREF pin. From fe4e6d239165455c176c1900e5267121ec63b609 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 23:24:04 +0200 Subject: [PATCH 13/17] fix typo Co-authored-by: Rahix --- avr-hal-generic/src/adc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 3c5c665286..7d8271e0fd 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -28,7 +28,7 @@ impl Default for ClockRateDivision { pub enum ReferenceVoltage { /// Voltage applied to AREF pin. Aref, - /// Default referece voltage. + /// Default reference voltage. AVcc, /// Internal reference voltage Internal, From f4d4a4c1ffd6e8d62c64e6c6718a511c25d536b0 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 23:32:12 +0200 Subject: [PATCH 14/17] make didr generic --- avr-hal-generic/src/adc.rs | 4 ++-- chips/atmega328p-hal/src/adc.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 7d8271e0fd..75537c1a5b 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -53,7 +53,7 @@ macro_rules! impl_adc { pub struct $Adc:ident { type ChannelID = $ID:ty; peripheral: $ADC:ty, - pins: {$($pxi:ident: ($PXi:ident, $ChannelIDExpr:expr, $ChannelIDPat:pat, $name:ident),)+} + pins: {$($pxi:ident: ($PXi:ident, $ChannelIDExpr:expr, $ChannelIDPat:pat, $didr:ident::$didr_method:ident),)+} } ) => { @@ -156,7 +156,7 @@ macro_rules! impl_adc { impl $PXi { /// Make this pin a analog input and enable the internal pull-up pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { - adc.peripheral.didr0.modify(|_, w| w.$name().set_bit()); + adc.peripheral.$didr.modify(|_, w| w.$didr_method().set_bit()); $PXi { _mode: core::marker::PhantomData } } } diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs index f21b0c6616..d15c8f85c6 100644 --- a/chips/atmega328p-hal/src/adc.rs +++ b/chips/atmega328p-hal/src/adc.rs @@ -9,12 +9,12 @@ avr_hal::impl_adc! { type ChannelID = MUX_A; peripheral: crate::atmega328p::ADC, pins: { - pc0: (PC0, MUX_A::ADC0, MUX_A::ADC0, adc0d), - pc1: (PC1, MUX_A::ADC1, MUX_A::ADC1, adc1d), - pc2: (PC2, MUX_A::ADC2, MUX_A::ADC2, adc2d), - pc3: (PC3, MUX_A::ADC3, MUX_A::ADC3, adc3d), - pc4: (PC4, MUX_A::ADC4, MUX_A::ADC4, adc4d), - pc5: (PC5, MUX_A::ADC5, MUX_A::ADC5, adc5d), + pc0: (PC0, MUX_A::ADC0, MUX_A::ADC0, didr0::adc0d), + pc1: (PC1, MUX_A::ADC1, MUX_A::ADC1, didr0::adc1d), + pc2: (PC2, MUX_A::ADC2, MUX_A::ADC2, didr0::adc2d), + pc3: (PC3, MUX_A::ADC3, MUX_A::ADC3, didr0::adc3d), + pc4: (PC4, MUX_A::ADC4, MUX_A::ADC4, didr0::adc4d), + pc5: (PC5, MUX_A::ADC5, MUX_A::ADC5, didr0::adc5d), } } } From c704edad93a29cba42a6b365444880a0a4763924 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sat, 25 Jul 2020 23:56:23 +0200 Subject: [PATCH 15/17] use enum instead of bools --- avr-hal-generic/src/adc.rs | 47 +++++++++++++-------------------- chips/atmega328p-hal/src/adc.rs | 12 ++++----- 2 files changed, 25 insertions(+), 34 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 75537c1a5b..120a071ca4 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -46,6 +46,10 @@ pub struct AdcSettings{ pub ref_voltage: ReferenceVoltage } +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum AdcError { + AlreadyReaddingOtherChannel +} #[macro_export] macro_rules! impl_adc { @@ -53,7 +57,7 @@ macro_rules! impl_adc { pub struct $Adc:ident { type ChannelID = $ID:ty; peripheral: $ADC:ty, - pins: {$($pxi:ident: ($PXi:ident, $ChannelIDExpr:expr, $ChannelIDPat:pat, $didr:ident::$didr_method:ident),)+} + pins: {$($pxi:ident: ($PXi:ident, $ChannelID:expr, $didr:ident::$didr_method:ident),)+} } ) => { @@ -65,12 +69,12 @@ macro_rules! impl_adc { pub struct $Adc { peripheral: $ADC, - $( $pxi: bool,)+ + reading_channel: Option<$ID>, } impl $Adc { pub fn new(peripheral: $ADC, settings: AdcSettings) -> $Adc { - let s = Self { peripheral, $( $pxi: false,)+ } ; + let s = Self { peripheral, reading_channel: None } ; s.enable(settings); s } @@ -99,20 +103,6 @@ macro_rules! impl_adc { self.peripheral.adcsra.reset(); } - fn set_reading(&mut self, channel: $ID, state: bool) { - match channel { - $( $ChannelIDPat => self.$pxi = state, )+ - _ => unreachable!(), - } - } - - fn is_reading(&self, channel: $ID) -> bool { - match channel { - $( $ChannelIDPat => self.$pxi, )+ - _ => unreachable!(), - } - } - pub fn release(self) -> $ADC { self.disable(); self.peripheral @@ -124,20 +114,21 @@ macro_rules! impl_adc { WORD: From, PIN: Channel<$Adc, ID=$ID>, { - type Error = (); + type Error = AdcError; fn read(&mut self, _pin: &mut PIN) -> nb::Result { - let channel = PIN::channel(); - - match (self.is_reading(channel), self.peripheral.adcsra.read().adsc().bit_is_set()) { - (true, true) => Err(nb::Error::WouldBlock), - (true, false) => { - self.set_reading(channel, false); + match (self.reading_channel, self.peripheral.adcsra.read().adsc().bit_is_set()) { + (Some(channel), true) if channel == PIN::channel() => Err(nb::Error::WouldBlock), + (Some(channel), false) if channel == PIN::channel() => { + self.reading_channel = None; Ok(self.peripheral.adc.read().bits().into()) }, - (false, _) => { - self.set_reading(channel, true); - self.peripheral.admux.modify(|_, w| w.mux().variant(channel)); + (Some(channel), _) => { + Err(nb::Error::Other(AdcError::AlreadyReaddingOtherChannel)) + }, + (None, _) => { + self.reading_channel = Some(PIN::channel()); + self.peripheral.admux.modify(|_, w| w.mux().variant(PIN::channel())); self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); Err(nb::Error::WouldBlock) } @@ -149,7 +140,7 @@ macro_rules! impl_adc { impl Channel<$Adc> for $PXi { type ID = $ID; fn channel() -> Self::ID { - $ChannelIDExpr + $ChannelID } } diff --git a/chips/atmega328p-hal/src/adc.rs b/chips/atmega328p-hal/src/adc.rs index d15c8f85c6..fbdedf734f 100644 --- a/chips/atmega328p-hal/src/adc.rs +++ b/chips/atmega328p-hal/src/adc.rs @@ -9,12 +9,12 @@ avr_hal::impl_adc! { type ChannelID = MUX_A; peripheral: crate::atmega328p::ADC, pins: { - pc0: (PC0, MUX_A::ADC0, MUX_A::ADC0, didr0::adc0d), - pc1: (PC1, MUX_A::ADC1, MUX_A::ADC1, didr0::adc1d), - pc2: (PC2, MUX_A::ADC2, MUX_A::ADC2, didr0::adc2d), - pc3: (PC3, MUX_A::ADC3, MUX_A::ADC3, didr0::adc3d), - pc4: (PC4, MUX_A::ADC4, MUX_A::ADC4, didr0::adc4d), - pc5: (PC5, MUX_A::ADC5, MUX_A::ADC5, didr0::adc5d), + pc0: (PC0, MUX_A::ADC0, didr0::adc0d), + pc1: (PC1, MUX_A::ADC1, didr0::adc1d), + pc2: (PC2, MUX_A::ADC2, didr0::adc2d), + pc3: (PC3, MUX_A::ADC3, didr0::adc3d), + pc4: (PC4, MUX_A::ADC4, didr0::adc4d), + pc5: (PC5, MUX_A::ADC5, didr0::adc5d), } } } From 1ed8ff2ca59489605e4b04ef3b6132afb04e3130 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 26 Jul 2020 00:01:23 +0200 Subject: [PATCH 16/17] remove patter binding --- avr-hal-generic/src/adc.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 120a071ca4..473ba2bd0b 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -123,9 +123,7 @@ macro_rules! impl_adc { self.reading_channel = None; Ok(self.peripheral.adc.read().bits().into()) }, - (Some(channel), _) => { - Err(nb::Error::Other(AdcError::AlreadyReaddingOtherChannel)) - }, + (Some(_), _) => Err(nb::Error::Other(AdcError::AlreadyReaddingOtherChannel)), (None, _) => { self.reading_channel = Some(PIN::channel()); self.peripheral.admux.modify(|_, w| w.mux().variant(PIN::channel())); @@ -145,7 +143,7 @@ macro_rules! impl_adc { } impl $PXi { - /// Make this pin a analog input and enable the internal pull-up + /// Make this pin a analog input and set the didr register pub fn into_analog_input(self, adc: &mut $Adc) -> $PXi { adc.peripheral.$didr.modify(|_, w| w.$didr_method().set_bit()); $PXi { _mode: core::marker::PhantomData } From 5ff24c97e96ad81f1894b0e375dadfb8a3dc2b87 Mon Sep 17 00:00:00 2001 From: Liam Perlaki Date: Sun, 26 Jul 2020 10:06:46 +0200 Subject: [PATCH 17/17] change adc wrong channel poll handeling --- avr-hal-generic/src/adc.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/avr-hal-generic/src/adc.rs b/avr-hal-generic/src/adc.rs index 473ba2bd0b..d6edb1dc37 100644 --- a/avr-hal-generic/src/adc.rs +++ b/avr-hal-generic/src/adc.rs @@ -1,4 +1,3 @@ - /// The division factor between the system clock frequency and the input clock to the AD converter. /// /// To get 10bit precision, clock from 50kHz to 200kHz must be supplied. If you need less precision, you can supply higher clock. @@ -13,14 +12,12 @@ pub enum ClockRateDivision { Factor128, } - impl Default for ClockRateDivision { fn default() -> Self { - Self::Factor128 + Self::Factor128 } } - /// Select the voltage reference for the ADC peripheral /// /// The internal voltage reference options may not be used if an external reference voltage is being applied to the AREF pin. @@ -36,19 +33,14 @@ pub enum ReferenceVoltage { impl Default for ReferenceVoltage { fn default() -> Self { - Self::AVcc + Self::AVcc } } #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] -pub struct AdcSettings{ +pub struct AdcSettings { pub clock_divider: ClockRateDivision, - pub ref_voltage: ReferenceVoltage -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum AdcError { - AlreadyReaddingOtherChannel + pub ref_voltage: ReferenceVoltage, } #[macro_export] @@ -96,7 +88,7 @@ macro_rules! impl_adc { ReferenceVoltage::AVcc => w.refs().avcc(), ReferenceVoltage::Internal => w.refs().internal(), }); - + } fn disable(&self) { @@ -114,22 +106,29 @@ macro_rules! impl_adc { WORD: From, PIN: Channel<$Adc, ID=$ID>, { - type Error = AdcError; + type Error = Void; fn read(&mut self, _pin: &mut PIN) -> nb::Result { match (self.reading_channel, self.peripheral.adcsra.read().adsc().bit_is_set()) { - (Some(channel), true) if channel == PIN::channel() => Err(nb::Error::WouldBlock), + // Measurement on current pin is ongoing + (Some(channel), true) if channel == PIN::channel() => Err(nb::Error::WouldBlock), + // Measurement on current pin completed (Some(channel), false) if channel == PIN::channel() => { self.reading_channel = None; Ok(self.peripheral.adc.read().bits().into()) }, - (Some(_), _) => Err(nb::Error::Other(AdcError::AlreadyReaddingOtherChannel)), + // Measurement on other pin is ongoing + (Some(_), _) => { + self.reading_channel = None; + Err(nb::Error::WouldBlock) + }, + // Start measurement (None, _) => { self.reading_channel = Some(PIN::channel()); self.peripheral.admux.modify(|_, w| w.mux().variant(PIN::channel())); self.peripheral.adcsra.modify(|_, w| w.adsc().set_bit()); Err(nb::Error::WouldBlock) - } + }, } } }