Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions avr-hal-generic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ features = ["docsrs"]

[features]
docsrs = ["avr-device/docsrs"]
mega0 = []

[dependencies]
nb = "1.1.0"
Expand Down
7 changes: 7 additions & 0 deletions avr-hal-generic/src/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ impl Clock for MHz16 {
const FREQ: u32 = 16_000_000;
}

/// 16 MHz Clock with prescaler divisor of 6 (used for 4809 peripherals)
#[derive(ufmt::derive::uDebug, Debug)]
pub struct MHz16_6;
impl Clock for MHz16_6 {
const FREQ: u32 = 16_000_000 / 6;
}

/// 12 MHz Clock
#[derive(ufmt::derive::uDebug, Debug)]
pub struct MHz12;
Expand Down
225 changes: 225 additions & 0 deletions avr-hal-generic/src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,231 @@ impl<PIN: PinOps> Pin<mode::Analog, PIN> {
}
}

#[macro_export]
macro_rules! impl_port_mega0 {
(
$(#[$pins_attr:meta])*
enum Ports {
$($name:ident: $port:ty = [$($pin:literal),+],)+
}
) => {
/// Type-alias for a pin type which can represent any concrete pin.
///
/// Sometimes it is easier to handle pins if they are all of the same type. By default,
/// each pin gets its own distinct type in `avr-hal`, but by
/// [downgrading][avr_hal_generic::port::Pin#downgrading], you can cast them into this
/// "dynamic" type. Do note, however, that using this dynamic type has a runtime cost.
pub type Pin<MODE, PIN = Dynamic> = $crate::port::Pin<MODE, PIN>;

$crate::paste::paste! {
$(#[$pins_attr])*
pub struct Pins {
$($(pub [<p $name:lower $pin>]: Pin<
mode::Input<mode::Floating>,
[<P $name $pin>],
>,)+)+
}

impl Pins {
pub fn new(
$(_: $port,)+
) -> Self {
Self {
$($([<p $name:lower $pin>]: $crate::port::Pin::new(
[<P $name $pin>] { _private: (), }
),)+)+
}
}
}
}

$crate::paste::paste! {
#[repr(u8)]
pub enum DynamicPort {
$([<PORT $name>]),+
}
}

pub struct Dynamic {
port: DynamicPort,
// We'll store the mask instead of the pin number because this allows much less code to
// be generated for the trait method implementations.
mask: u8,
}

impl Dynamic {
fn new(port: DynamicPort, num: u8) -> Self {
Self {
port,
mask: 1u8 << num,
}
}
}

$crate::paste::paste! {
impl $crate::port::PinOps for Dynamic {
type Dynamic = Self;

#[inline]
fn into_dynamic(self) -> Self::Dynamic {
self
}

#[inline]
unsafe fn out_set(&mut self) {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).outset().write(|w| {
w.bits(self.mask)
});
})+
}
}

#[inline]
unsafe fn out_clear(&mut self) {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).outclr().write(|w| {
w.bits(self.mask)
});
})+
}
}

#[inline]
unsafe fn out_toggle(&mut self) {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).outtgl().write(|w| {
w.bits(self.mask)
});
})+
}
}

#[inline]
unsafe fn out_get(&self) -> bool {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).out().read().bits() & self.mask != 0
})+
}
}

#[inline]
unsafe fn in_get(&self) -> bool {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).in_().read().bits() & self.mask != 0
})+
}
}

#[inline]
unsafe fn make_output(&mut self) {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).dirset().write(|w| {
w.bits(self.mask)
});
})+
}
}

#[inline]
unsafe fn make_input(&mut self, pull_up: bool) {
match self.port {
$(DynamicPort::[<PORT $name>] => {
(*<$port>::ptr()).dirclr().write(|w| {
w.bits(self.mask)
});
$(if self.mask & (1u8 << $pin) != 0{
(*<$port>::ptr()).[<pin $pin ctrl>]().modify(|r, w| {
if pull_up {
w.pullupen().set_bit()
} else {
w.pullupen().clear_bit()
}
});
})+
})+
}
}
}
}

$crate::paste::paste! {
$($(
pub struct [<P $name $pin>] {
_private: ()
}

impl $crate::port::PinOps for [<P $name $pin>] {
type Dynamic = Dynamic;

#[inline]
fn into_dynamic(self) -> Self::Dynamic {
Dynamic::new(DynamicPort::[<PORT $name>], $pin)
}

#[inline]
unsafe fn out_set(&mut self) {
(*<$port>::ptr()).outset().write(|w| {
w.[<p $name:lower $pin>]().set_bit()
});
}

#[inline]
unsafe fn out_clear(&mut self) {
(*<$port>::ptr()).outclr().modify(|_, w| {
w.[<p $name:lower $pin>]().set_bit()
});
}

#[inline]
unsafe fn out_toggle(&mut self) {
(*<$port>::ptr()).outtgl().modify(|_, w| {
w.[<p $name:lower $pin>]().set_bit()
});
}

#[inline]
unsafe fn out_get(&self) -> bool {
(*<$port>::ptr()).out().read().[<p $name:lower $pin>]().bit()
}

#[inline]
unsafe fn in_get(&self) -> bool {
(*<$port>::ptr()).in_().read().[<p $name:lower $pin>]().bit()
}

#[inline]
unsafe fn make_output(&mut self) {
(*<$port>::ptr()).dirset().write(|w| {
w.[<p $name:lower $pin>]().set_bit()
});
}

#[inline]
unsafe fn make_input(&mut self, pull_up: bool) {
(*<$port>::ptr()).dirclr().write(|w| {
w.[<p $name:lower $pin>]().set_bit()
});
(*<$port>::ptr()).[<pin $pin ctrl>]().modify(|r, w| {
if pull_up {
w.pullupen().set_bit()
} else {
w.pullupen().clear_bit()
}
});
}
}
)+)+
}
};
}

#[macro_export]
macro_rules! impl_port_traditional_base {
(
Expand Down
Loading