diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 507335a20c..fdde100719 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,7 +118,10 @@ jobs: run: cd "arduino-hal/" && cargo build --features "${{ matrix.m.name }}" - name: Test-compile HAL crate for an MCU if: "${{ matrix.m.type == 'mcu' }}" - run: cd "mcu/${{ matrix.m.crate }}" && cargo build --features "${{ matrix.m.name }}" -Z build-std=core --target "../../avr-specs/avr-${{ matrix.m.spec }}.json" + run: >- + cd "mcu/${{ matrix.m.crate }}" && + cargo build --features "${{ matrix.m.name }}-deprecated-globals" -Z build-std=core --target "../../avr-specs/avr-${{ matrix.m.spec }}.json" && + cargo build --features "${{ matrix.m.name }}-no-deprecated-globals" -Z build-std=core --target "../../avr-specs/avr-${{ matrix.m.spec }}.json" && ravedude: name: "ravedude" diff --git a/mcu/attiny-hal/Cargo.toml b/mcu/attiny-hal/Cargo.toml index 4e11377dcb..2ce6d4272e 100644 --- a/mcu/attiny-hal/Cargo.toml +++ b/mcu/attiny-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "attiny-hal" -version = "0.1.0" +version = "0.2.0" authors = ["Rahix "] edition = "2021" @@ -12,33 +12,63 @@ categories = ["no-std", "embedded", "hardware-support"] [features] rt = ["avr-device/rt"] -device-selected = [] -attiny84 = ["avr-device/attiny84", "device-selected"] -attiny85 = ["avr-device/attiny85", "device-selected"] -attiny88 = ["avr-device/attiny88", "device-selected"] -attiny167 = ["avr-device/attiny167", "device-selected"] -attiny2313 = ["avr-device/attiny2313", "device-selected"] + +# MCU-specific targets. Due to use of deprecated globals, only one MCU can be selected at a time +# In attiny-hal 0.2.0 the defaults will change to no deprecated globals +attiny84 = ["attiny84-deprecated-globals"] +attiny85 = ["attiny85-deprecated-globals"] +attiny88 = ["attiny88-deprecated-globals"] +attiny167 = ["attiny167-deprecated-globals"] +attiny2313 = ["attiny2313-deprecated-globals"] + +# MCU-specific targets with deprecated globals. This is the default in attiny-hal 0.1.x +attiny84-deprecated-globals = ["_mcu-attiny84", "deprecated-globals"] +attiny85-deprecated-globals = ["_mcu-attiny85", "deprecated-globals"] +attiny88-deprecated-globals = ["_mcu-attiny88", "deprecated-globals"] +attiny167-deprecated-globals = ["_mcu-attiny167", "deprecated-globals"] +attiny2313-deprecated-globals = ["_mcu-attiny2313", "deprecated-globals"] + +# MCU-specific targets without deprecated globals. This will be the default in attiny-hal 0.2.0 +attiny84-no-deprecated-globals = ["_mcu-attiny84"] +attiny85-no-deprecated-globals = ["_mcu-attiny85"] +attiny88-no-deprecated-globals = ["_mcu-attiny88"] +attiny167-no-deprecated-globals = ["_mcu-attiny167"] +attiny2313-no-deprecated-globals = ["_mcu-attiny2313"] critical-section-impl = ["avr-device/critical-section-impl"] -# Allow certain downstream crates to overwrite the device selection error by themselves. -disable-device-selection-error = [] +default = [] + +docsrs = [ + "attiny84-no-deprecated-globals", + "attiny85-no-deprecated-globals", + "attiny88-no-deprecated-globals", + "attiny167-no-deprecated-globals", + "attiny2313-no-deprecated-globals", +] + +# Include soon-to-be-deprecated globals in the crate. Only one MCU can be selected if deprecated globals are enabled +deprecated-globals = [] + +# When using this crate from another lib crate, you can use this feature to turn suppress the chip selection error in favor of your own error +disable-device-selection-error = ["_mcu-selected"] + +# MCU-specific implementation features +# Do not use directly; use either an -deprecated-globals feature or any number of -no-deprecated-globals features +_mcu-attiny84 = ["_mcu-selected", "avr-device/attiny84"] +_mcu-attiny85 = ["_mcu-selected", "avr-device/attiny85"] +_mcu-attiny88 = ["_mcu-selected", "avr-device/attiny88"] +_mcu-attiny167 = ["_mcu-selected", "avr-device/attiny167"] +_mcu-attiny2313 = ["_mcu-selected", "avr-device/attiny2313"] + +_mcu-selected = [] -# We must select a microcontroller to build on docs.rs -docsrs = ["attiny85"] [dependencies] avr-hal-generic = { path = "../../avr-hal-generic/" } [dependencies.avr-device] version = "0.5.4" - -# Because this crate has its own check that at least one device is selected, we -# can safely "circumvent" the check in `avr-device`. -# -# Why would we want that? Otherwise, as `avr-device` is compiled first, its -# error will be shown and ours won't which leads to a degraded user experience -# as the displayed error message does not really tell what needs to be done... features = ["device-selected"] [package.metadata.docs.rs] diff --git a/mcu/attiny-hal/src/adc.rs b/mcu/attiny-hal/src/adc.rs index 0856312086..c7410a8153 100644 --- a/mcu/attiny-hal/src/adc.rs +++ b/mcu/attiny-hal/src/adc.rs @@ -25,185 +25,277 @@ //! } //! ``` -use crate::port; -pub use avr_hal_generic::adc::{AdcChannel, AdcOps, ClockDivider}; - -/// 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. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum ReferenceVoltage { - /// Voltage applied to AREF pin. - #[cfg(any(feature = "attiny85", feature = "attiny167",))] - Aref, - /// Default reference voltage (default). - AVcc, - /// Internal 1.1V reference. - Internal1_1, - /// Internal 2.56V reference. - #[cfg(any(feature = "attiny85", feature = "attiny167",))] - Internal2_56, -} +macro_rules! impl_adc { + ($($mcu:ident)::+) => { + pub use avr_hal_generic::adc::{AdcChannel, AdcOps, ClockDivider}; -impl Default for ReferenceVoltage { - fn default() -> Self { - Self::AVcc - } -} + impl Default for ReferenceVoltage { + fn default() -> Self { + Self::AVcc + } + } -/// Configuration for the ADC peripheral. -#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] -pub struct AdcSettings { - pub clock_divider: ClockDivider, - pub ref_voltage: ReferenceVoltage, -} + /// Configuration for the ADC peripheral. + #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] + pub struct AdcSettings { + pub clock_divider: ClockDivider, + pub ref_voltage: ReferenceVoltage, + } -/// Check the [`avr_hal_generic::adc::Adc`] documentation. -pub type Adc = avr_hal_generic::adc::Adc; - -/// Check the [`avr_hal_generic::adc::Channel`] documentation. -pub type Channel = avr_hal_generic::adc::Channel; - -/// Additional channels -/// -/// Some channels are not directly connected to pins. This module provides types which can be used -/// to access them. -/// -/// # Example -/// ``` -/// let dp = attiny_hal::Peripherals::take().unwrap(); -/// let mut adc = attiny_hal::Adc::new(dp.ADC, Default::default()); -/// -/// let value = adc.read_blocking(&channel::Vbg); -/// ``` -pub mod channel { - #[cfg(feature = "attiny167")] - pub struct AVcc_4; - pub struct Vbg; - pub struct Gnd; - pub struct Temperature; -} + /// Check the [`avr_hal_generic::adc::Adc`] documentation. + pub type Adc = + avr_hal_generic::adc::Adc<$($mcu)::+::Hal, $($mcu)::+::pac::ADC, CLOCK>; -fn apply_clock(peripheral: &crate::pac::ADC, settings: AdcSettings) { - peripheral.adcsra.write(|w| { - w.aden().set_bit(); - match settings.clock_divider { - ClockDivider::Factor2 => w.adps().prescaler_2(), - ClockDivider::Factor4 => w.adps().prescaler_4(), - ClockDivider::Factor8 => w.adps().prescaler_8(), - ClockDivider::Factor16 => w.adps().prescaler_16(), - ClockDivider::Factor32 => w.adps().prescaler_32(), - ClockDivider::Factor64 => w.adps().prescaler_64(), - ClockDivider::Factor128 => w.adps().prescaler_128(), + /// Check the [`avr_hal_generic::adc::Channel`] documentation. + pub type Channel = avr_hal_generic::adc::Channel<$($mcu)::+::Hal, $($mcu)::+::pac::ADC>; + + fn apply_clock(peripheral: &$($mcu)::+::pac::ADC, settings: AdcSettings) { + peripheral.adcsra.write(|w| { + w.aden().set_bit(); + match settings.clock_divider { + ClockDivider::Factor2 => w.adps().prescaler_2(), + ClockDivider::Factor4 => w.adps().prescaler_4(), + ClockDivider::Factor8 => w.adps().prescaler_8(), + ClockDivider::Factor16 => w.adps().prescaler_16(), + ClockDivider::Factor32 => w.adps().prescaler_32(), + ClockDivider::Factor64 => w.adps().prescaler_64(), + ClockDivider::Factor128 => w.adps().prescaler_128(), + } + }); } - }); + }; } -#[cfg(feature = "attiny85")] -avr_hal_generic::impl_adc! { - hal: crate::Attiny, - peripheral: crate::pac::ADC, - settings: AdcSettings, - apply_settings: |peripheral, settings| { - apply_clock(peripheral, settings); - peripheral.admux.write(|w| match settings.ref_voltage { - ReferenceVoltage::Aref => w.refs().aref(), - ReferenceVoltage::AVcc => w.refs().vcc(), - ReferenceVoltage::Internal1_1 => w.refs().internal().refs2().clear_bit(), - ReferenceVoltage::Internal2_56 => w.refs().internal().refs2().set_bit(), - }); - }, - channel_id: crate::pac::adc::admux::MUX_A, - set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); - }, - pins: { - port::PB5: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), - port::PB2: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d), - port::PB4: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d), - port::PB3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d), - }, - channels: { - channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG, - channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND, - channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS, - }, +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85 { + use crate::attiny85::{pac, port, Hal}; + /// 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. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(u8)] + pub enum ReferenceVoltage { + /// Voltage applied to AREF pin. + Aref, + /// Default reference voltage (default). + AVcc, + /// Internal 1.1V reference. + Internal1_1, + /// Internal 2.56V reference. + Internal2_56, + } + + /// Additional channels + /// + /// Some channels are not directly connected to pins. This module provides types which can be used + /// to access them. + /// + /// # Example + /// ``` + /// let dp = attiny_hal::Peripherals::take().unwrap(); + /// let mut adc = attiny_hal::Adc::new(dp.ADC, Default::default()); + /// + /// let value = adc.read_blocking(&channel::Vbg); + /// ``` + pub mod channel { + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + impl_adc!(crate::attiny85); + + avr_hal_generic::impl_adc! { + hal: Hal, + peripheral: pac::ADC, + settings: AdcSettings, + apply_settings: |peripheral, settings| { + apply_clock(peripheral, settings); + peripheral.admux.write(|w| match settings.ref_voltage { + ReferenceVoltage::Aref => w.refs().aref(), + ReferenceVoltage::AVcc => w.refs().vcc(), + ReferenceVoltage::Internal1_1 => w.refs().internal().refs2().clear_bit(), + ReferenceVoltage::Internal2_56 => w.refs().internal().refs2().set_bit(), + }); + }, + channel_id: pac::adc::admux::MUX_A, + set_channel: |peripheral, id| { + peripheral.admux.modify(|_, w| w.mux().variant(id)); + }, + pins: { + port::PB5: (pac::adc::admux::MUX_A::ADC0, didr0::adc0d), + port::PB2: (pac::adc::admux::MUX_A::ADC1, didr0::adc1d), + port::PB4: (pac::adc::admux::MUX_A::ADC2, didr0::adc2d), + port::PB3: (pac::adc::admux::MUX_A::ADC3, didr0::adc3d), + }, + channels: { + channel::Vbg: pac::adc::admux::MUX_A::ADC_VBG, + channel::Gnd: pac::adc::admux::MUX_A::ADC_GND, + channel::Temperature: pac::adc::admux::MUX_A::TEMPSENS, + }, + } } -#[cfg(feature = "attiny88")] -avr_hal_generic::impl_adc! { - hal: crate::Attiny, - peripheral: crate::pac::ADC, - settings: AdcSettings, - apply_settings: |peripheral, settings| { - apply_clock(peripheral, settings); - peripheral.admux.write(|w| match settings.ref_voltage { - ReferenceVoltage::AVcc => w.refs0().avcc(), - ReferenceVoltage::Internal1_1 => w.refs0().internal(), - }); - }, - channel_id: crate::pac::adc::admux::MUX_A, - set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); - }, - pins: { - port::PC0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), - port::PC1: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d), - port::PC2: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d), - port::PC3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d), - port::PC4: (crate::pac::adc::admux::MUX_A::ADC4, didr0::adc4d), - port::PC5: (crate::pac::adc::admux::MUX_A::ADC5, didr0::adc5d), - port::PA0: (crate::pac::adc::admux::MUX_A::ADC6, didr0::adc6d), - port::PA1: (crate::pac::adc::admux::MUX_A::ADC7, didr0::adc7d), - }, - channels: { - channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG, - channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND, - channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS, - }, +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + use crate::attiny88::{pac, port, Hal}; + /// 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. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(u8)] + pub enum ReferenceVoltage { + /// Default reference voltage (default). + AVcc, + /// Internal 1.1V reference. + Internal1_1, + } + + /// Additional channels + /// + /// Some channels are not directly connected to pins. This module provides types which can be used + /// to access them. + /// + /// # Example + /// ``` + /// let dp = attiny_hal::Peripherals::take().unwrap(); + /// let mut adc = attiny_hal::Adc::new(dp.ADC, Default::default()); + /// + /// let value = adc.read_blocking(&channel::Vbg); + /// ``` + pub mod channel { + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + impl_adc!(crate::attiny88); + + avr_hal_generic::impl_adc! { + hal: Hal, + peripheral: pac::ADC, + settings: AdcSettings, + apply_settings: |peripheral, settings| { + apply_clock(peripheral, settings); + peripheral.admux.write(|w| match settings.ref_voltage { + ReferenceVoltage::AVcc => w.refs0().avcc(), + ReferenceVoltage::Internal1_1 => w.refs0().internal(), + }); + }, + channel_id: pac::adc::admux::MUX_A, + set_channel: |peripheral, id| { + peripheral.admux.modify(|_, w| w.mux().variant(id)); + }, + pins: { + port::PC0: (pac::adc::admux::MUX_A::ADC0, didr0::adc0d), + port::PC1: (pac::adc::admux::MUX_A::ADC1, didr0::adc1d), + port::PC2: (pac::adc::admux::MUX_A::ADC2, didr0::adc2d), + port::PC3: (pac::adc::admux::MUX_A::ADC3, didr0::adc3d), + port::PC4: (pac::adc::admux::MUX_A::ADC4, didr0::adc4d), + port::PC5: (pac::adc::admux::MUX_A::ADC5, didr0::adc5d), + port::PA0: (pac::adc::admux::MUX_A::ADC6, didr0::adc6d), + port::PA1: (pac::adc::admux::MUX_A::ADC7, didr0::adc7d), + }, + channels: { + channel::Vbg: pac::adc::admux::MUX_A::ADC_VBG, + channel::Gnd: pac::adc::admux::MUX_A::ADC_GND, + channel::Temperature: pac::adc::admux::MUX_A::TEMPSENS, + }, + } } -#[cfg(feature = "attiny167")] -avr_hal_generic::impl_adc! { - hal: crate::Attiny, - peripheral: crate::pac::ADC, - settings: AdcSettings, - apply_settings: |peripheral, settings| { - apply_clock(peripheral, settings); - peripheral.amiscr.write(|w| match settings.ref_voltage { - ReferenceVoltage::Aref => w.arefen().set_bit(), - _ => w.arefen().clear_bit(), - }); - peripheral.admux.write(|w| match settings.ref_voltage { - ReferenceVoltage::Aref => w.refs().avcc(), - ReferenceVoltage::AVcc => w.refs().avcc(), - ReferenceVoltage::Internal1_1 => w.refs().internal_11(), - ReferenceVoltage::Internal2_56 => w.refs().internal_256(), - }); - }, - channel_id: crate::pac::adc::admux::MUX_A, - set_channel: |peripheral, id| { - peripheral.admux.modify(|_, w| w.mux().variant(id)); - }, - pins: { - port::PA0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d), - port::PA1: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d), - port::PA2: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d), - port::PA3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d), - port::PA4: (crate::pac::adc::admux::MUX_A::ADC4, didr0::adc4d), - port::PA5: (crate::pac::adc::admux::MUX_A::ADC5, didr0::adc5d), - port::PA6: (crate::pac::adc::admux::MUX_A::ADC6, didr0::adc6d), - port::PA7: (crate::pac::adc::admux::MUX_A::ADC7, didr0::adc7d), - port::PB5: (crate::pac::adc::admux::MUX_A::ADC8, didr1::adc8d), - port::PB6: (crate::pac::adc::admux::MUX_A::ADC9, didr1::adc9d), - port::PB7: (crate::pac::adc::admux::MUX_A::ADC10, didr1::adc10d), - }, - channels: { - channel::AVcc_4: crate::pac::adc::admux::MUX_A::ADC_AVCC_4, - channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG, - channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND, - channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS, - }, +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167 { + use crate::attiny167::{pac, port, Hal}; + /// 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. + #[derive(Debug, Clone, Copy, PartialEq, Eq)] + #[repr(u8)] + pub enum ReferenceVoltage { + /// Voltage applied to AREF pin. + Aref, + /// Default reference voltage (default). + AVcc, + /// Internal 1.1V reference. + Internal1_1, + /// Internal 2.56V reference. + Internal2_56, + } + + /// Additional channels + /// + /// Some channels are not directly connected to pins. This module provides types which can be used + /// to access them. + /// + /// # Example + /// ``` + /// let dp = attiny_hal::Peripherals::take().unwrap(); + /// let mut adc = attiny_hal::Adc::new(dp.ADC, Default::default()); + /// + /// let value = adc.read_blocking(&channel::Vbg); + /// ``` + pub mod channel { + pub struct AVcc_4; + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + impl_adc!(crate::attiny167); + + avr_hal_generic::impl_adc! { + hal: Hal, + peripheral: pac::ADC, + settings: AdcSettings, + apply_settings: |peripheral, settings| { + apply_clock(peripheral, settings); + peripheral.amiscr.write(|w| match settings.ref_voltage { + ReferenceVoltage::Aref => w.arefen().set_bit(), + _ => w.arefen().clear_bit(), + }); + peripheral.admux.write(|w| match settings.ref_voltage { + ReferenceVoltage::Aref => w.refs().avcc(), + ReferenceVoltage::AVcc => w.refs().avcc(), + ReferenceVoltage::Internal1_1 => w.refs().internal_11(), + ReferenceVoltage::Internal2_56 => w.refs().internal_256(), + }); + }, + channel_id: pac::adc::admux::MUX_A, + set_channel: |peripheral, id| { + peripheral.admux.modify(|_, w| w.mux().variant(id)); + }, + pins: { + port::PA0: (pac::adc::admux::MUX_A::ADC0, didr0::adc0d), + port::PA1: (pac::adc::admux::MUX_A::ADC1, didr0::adc1d), + port::PA2: (pac::adc::admux::MUX_A::ADC2, didr0::adc2d), + port::PA3: (pac::adc::admux::MUX_A::ADC3, didr0::adc3d), + port::PA4: (pac::adc::admux::MUX_A::ADC4, didr0::adc4d), + port::PA5: (pac::adc::admux::MUX_A::ADC5, didr0::adc5d), + port::PA6: (pac::adc::admux::MUX_A::ADC6, didr0::adc6d), + port::PA7: (pac::adc::admux::MUX_A::ADC7, didr0::adc7d), + port::PB5: (pac::adc::admux::MUX_A::ADC8, didr1::adc8d), + port::PB6: (pac::adc::admux::MUX_A::ADC9, didr1::adc9d), + port::PB7: (pac::adc::admux::MUX_A::ADC10, didr1::adc10d), + }, + channels: { + channel::AVcc_4: pac::adc::admux::MUX_A::ADC_AVCC_4, + channel::Vbg: pac::adc::admux::MUX_A::ADC_VBG, + channel::Gnd: pac::adc::admux::MUX_A::ADC_GND, + channel::Temperature: pac::adc::admux::MUX_A::TEMPSENS, + }, + } } + +#[cfg(all( + feature = "deprecated-globals", + any( + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + feature = "_mcu-attiny167" + ) +))] +pub use crate::mcu::adc::*; diff --git a/mcu/attiny-hal/src/attiny167.rs b/mcu/attiny-hal/src/attiny167.rs new file mode 100644 index 0000000000..66fe4d2a4f --- /dev/null +++ b/mcu/attiny-hal/src/attiny167.rs @@ -0,0 +1,16 @@ +pub use avr_device::attiny167 as pac; + +pub struct Hal; + +pub use crate::adc::attiny167 as adc; +pub use crate::eeprom::attiny167 as eeprom; +pub use crate::port::attiny167 as port; +pub use crate::spi::attiny167 as spi; +pub use crate::wdt::attiny167 as wdt; + +pub use adc::Adc; +pub use eeprom::Eeprom; +pub use pac::Peripherals; +pub use port::Pins; +pub use spi::Spi; +pub use wdt::Wdt; diff --git a/mcu/attiny-hal/src/attiny2313.rs b/mcu/attiny-hal/src/attiny2313.rs new file mode 100644 index 0000000000..dfaefab85e --- /dev/null +++ b/mcu/attiny-hal/src/attiny2313.rs @@ -0,0 +1,12 @@ +pub use avr_device::attiny2313 as pac; + +pub struct Hal; + +pub use crate::eeprom::attiny2313 as eeprom; +pub use crate::port::attiny2313 as port; +pub use crate::wdt::attiny2313 as wdt; + +pub use eeprom::Eeprom; +pub use pac::Peripherals; +pub use port::Pins; +pub use wdt::Wdt; diff --git a/mcu/attiny-hal/src/attiny84.rs b/mcu/attiny-hal/src/attiny84.rs new file mode 100644 index 0000000000..c3a9cfad5f --- /dev/null +++ b/mcu/attiny-hal/src/attiny84.rs @@ -0,0 +1,13 @@ +pub use avr_device::attiny84 as pac; + +pub struct Hal; + +pub use crate::eeprom::attiny84 as eeprom; +pub use crate::port::attiny84 as port; +pub use crate::simple_pwm::attiny84 as simple_pwm; +pub use crate::wdt::attiny84 as wdt; + +pub use eeprom::Eeprom; +pub use pac::Peripherals; +pub use port::Pins; +pub use wdt::Wdt; diff --git a/mcu/attiny-hal/src/attiny85.rs b/mcu/attiny-hal/src/attiny85.rs new file mode 100644 index 0000000000..68b6e2cc69 --- /dev/null +++ b/mcu/attiny-hal/src/attiny85.rs @@ -0,0 +1,15 @@ +pub use avr_device::attiny85 as pac; + +pub struct Hal; + +pub use crate::adc::attiny85 as adc; +pub use crate::eeprom::attiny85 as eeprom; +pub use crate::port::attiny85 as port; +pub use crate::simple_pwm::attiny85 as simple_pwm; +pub use crate::wdt::attiny85 as wdt; + +pub use adc::Adc; +pub use eeprom::Eeprom; +pub use pac::Peripherals; +pub use port::Pins; +pub use wdt::Wdt; diff --git a/mcu/attiny-hal/src/attiny88.rs b/mcu/attiny-hal/src/attiny88.rs new file mode 100644 index 0000000000..c68fd0049e --- /dev/null +++ b/mcu/attiny-hal/src/attiny88.rs @@ -0,0 +1,17 @@ +pub use avr_device::attiny88 as pac; + +pub struct Hal; + +pub use crate::adc::attiny88 as adc; +pub use crate::eeprom::attiny88 as eeprom; +pub use crate::port::attiny88 as port; +pub use crate::simple_pwm::attiny88 as simple_pwm; +pub use crate::spi::attiny88 as spi; +pub use crate::wdt::attiny88 as wdt; + +pub use adc::Adc; +pub use eeprom::Eeprom; +pub use pac::Peripherals; +pub use port::Pins; +pub use spi::Spi; +pub use wdt::Wdt; diff --git a/mcu/attiny-hal/src/eeprom.rs b/mcu/attiny-hal/src/eeprom.rs index f325215dfb..4a0527214c 100644 --- a/mcu/attiny-hal/src/eeprom.rs +++ b/mcu/attiny-hal/src/eeprom.rs @@ -18,39 +18,49 @@ //! ufmt::uwriteln!(&mut serial, "Boot count: {}", boot_count).unwrap(); //! ``` -pub use avr_hal_generic::eeprom::{EepromOps, OutOfBoundsError}; - -pub type Eeprom = avr_hal_generic::eeprom::Eeprom; - -#[cfg(feature = "attiny2313")] -avr_hal_generic::impl_eeprom_attiny! { - hal: crate::Attiny, - peripheral: crate::pac::EEPROM, - capacity: 128, - addr_width: u8, - set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); - }, +macro_rules! impl_eeprom { + (mcu: $($mcu:ident)::+, capacity: $capacity:expr, addr_width: $addr_width:ty, addr_reg: $addr_reg:ident $(,)?) => { + pub use avr_hal_generic::eeprom::{EepromOps, OutOfBoundsError}; + + pub type Eeprom = + avr_hal_generic::eeprom::Eeprom<$($mcu)::+::Hal, $($mcu)::+::pac::EEPROM>; + + avr_hal_generic::impl_eeprom_attiny! { + hal: $($mcu)::+::Hal, + peripheral: $($mcu)::+::pac::EEPROM, + capacity: $capacity, + addr_width: $addr_width, + set_address: |peripheral, address| { + peripheral.$addr_reg.write(|w| w.bits(address)); + }, + } + }; } -#[cfg(any(feature = "attiny167", feature = "attiny85"))] -avr_hal_generic::impl_eeprom_attiny! { - hal: crate::Attiny, - peripheral: crate::pac::EEPROM, - capacity: 512, - addr_width: u16, - set_address: |peripheral, address| { - peripheral.eear.write(|w| w.bits(address)); - }, +#[cfg(feature = "_mcu-attiny2313")] +pub mod attiny2313 { + impl_eeprom!(mcu: crate::attiny2313, capacity: 128, addr_width: u8, addr_reg: eear); } -#[cfg(feature = "attiny88")] -avr_hal_generic::impl_eeprom_attiny! { - hal: crate::Attiny, - peripheral: crate::pac::EEPROM, - capacity: 64, - addr_width: u8, - set_address: |peripheral, address| { - peripheral.eearl.write(|w| w.bits(address)); - }, +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167 { + impl_eeprom!(mcu: crate::attiny167, capacity: 512, addr_width: u16, addr_reg: eear); } + +#[cfg(feature = "_mcu-attiny84")] +pub mod attiny84 { + impl_eeprom!(mcu: crate::attiny84, capacity: 512, addr_width: u16, addr_reg: eear); +} + +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85 { + impl_eeprom!(mcu: crate::attiny85, capacity: 512, addr_width: u16, addr_reg: eear); +} + +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + impl_eeprom!(mcu: crate::attiny88, capacity: 64, addr_width: u8, addr_reg: eearl); +} + +#[cfg(feature = "deprecated-globals")] +pub use crate::mcu::eeprom::*; diff --git a/mcu/attiny-hal/src/globals.rs b/mcu/attiny-hal/src/globals.rs new file mode 100644 index 0000000000..851cd96c4e --- /dev/null +++ b/mcu/attiny-hal/src/globals.rs @@ -0,0 +1,102 @@ +// Deprecated globals + +#[cfg(all( + // More than one MCU selected -> error + all( + feature = "_mcu-attiny167", + any( + feature = "_mcu-attiny2313", + feature = "_mcu-attiny84", + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + ) + ), + all( + feature = "_mcu-attiny2313", + any( + feature = "_mcu-attiny167", + feature = "_mcu-attiny84", + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + ) + ), + all( + feature = "_mcu-attiny84", + any( + feature = "_mcu-attiny167", + feature = "_mcu-attiny2313", + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + ) + ), + all( + feature = "_mcu-attiny85", + any( + feature = "_mcu-attiny167", + feature = "_mcu-attiny2313", + feature = "_mcu-attiny84", + feature = "_mcu-attiny88", + ) + ), + all( + feature = "_mcu-attiny88", + any( + feature = "_mcu-attiny167", + feature = "_mcu-attiny2313", + feature = "_mcu-attiny84", + feature = "_mcu-attiny85", + ) + ), +))] +compile_error!( + "When using deprecated globals (default in attiny-hal 0.1.x), you cannot target multiple chips. + + To target multiple chips, turn off deprecated globals by using the following features + + * attiny84-no-deprecated-globals instead of attiny84 + * attiny85-no-deprecated-globals instead of attiny85 + * attiny88-no-deprecated-globals instead of attiny88 + * attiny167-no-deprecated-globals instead of attiny167 + * attiny2313-no-deprecated-globals instead of attiny2313 + " +); + +#[cfg(feature = "_mcu-attiny167")] +pub use crate::attiny167 as mcu; + +#[cfg(feature = "_mcu-attiny2313")] +pub use crate::attiny2313 as mcu; + +#[cfg(feature = "_mcu-attiny84")] +pub use crate::attiny84 as mcu; + +#[cfg(feature = "_mcu-attiny85")] +pub use crate::attiny85 as mcu; + +#[cfg(feature = "_mcu-attiny88")] +pub use crate::attiny88 as mcu; + +pub use mcu::pac; + +pub use pac::Peripherals; + +#[cfg(any( + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + feature = "_mcu-attiny167" +))] +pub use crate::adc::Adc; + +pub use crate::{eeprom::Eeprom, port::Pins, wdt::Wdt}; + +#[cfg(any(feature = "_mcu-attiny88", feature = "_mcu-attiny167"))] +pub use crate::spi::Spi; + +pub use mcu::Hal as Attiny; + +#[macro_export] +macro_rules! pins { + ($p:expr) => { + $crate::port::pins(&$p) + }; +} diff --git a/mcu/attiny-hal/src/lib.rs b/mcu/attiny-hal/src/lib.rs index a71614a457..91b5f3d62b 100644 --- a/mcu/attiny-hal/src/lib.rs +++ b/mcu/attiny-hal/src/lib.rs @@ -3,28 +3,16 @@ //! `attiny-hal` //! ============= //! Common HAL (hardware abstraction layer) for ATtiny* microcontrollers. -//! -//! **Note**: This version of the documentation was built for -#![cfg_attr(feature = "attiny85", doc = "**ATtiny85**.")] -#![cfg_attr(feature = "attiny88", doc = "**ATtiny88**.")] -#![cfg_attr(feature = "attiny167", doc = "**ATtiny167**.")] -#![cfg_attr(feature = "attiny2313", doc = "**ATtiny2313**.")] -//! This means that only items which are available for this MCU are visible. If you are using -//! a different chip, try building the documentation locally with: -//! -//! ```text -//! cargo doc --features --open -//! ``` -#[cfg(all( - not(feature = "device-selected"), - not(feature = "disable-device-selection-error") -))] +// This crate can be configured in one of two ways: either you specify deprecated-globals and exactly one MCU +// Or you don't specify deprecated globals and at least one MCU +#[cfg(all(not(feature = "_mcu-selected"), not(feature = "disable-device-selection-error")))] compile_error!( - "This crate requires you to specify your target chip as a feature. + "You must specify your target chips as a feature. - Please select one of the following + Please select at least one of the following features + * attiny84 * attiny85 * attiny88 * attiny167 @@ -32,73 +20,42 @@ compile_error!( " ); -/// Reexport of `attiny167` from `avr-device` -/// -#[cfg(feature = "attiny167")] -pub use avr_device::attiny167 as pac; -/// Reexport of `attiny2313` from `avr-device` -/// -#[cfg(feature = "attiny2313")] -pub use avr_device::attiny2313 as pac; -/// Reexport of `attiny84` from `avr-device` -/// -#[cfg(feature = "attiny84")] -pub use avr_device::attiny84 as pac; -/// Reexport of `attiny85` from `avr-device` -/// -#[cfg(feature = "attiny85")] -pub use avr_device::attiny85 as pac; -/// Reexport of `attiny88` from `avr-device` -/// -#[cfg(feature = "attiny88")] -pub use avr_device::attiny88 as pac; - /// See [`avr_device::entry`](https://docs.rs/avr-device/latest/avr_device/attr.entry.html). #[cfg(feature = "rt")] pub use avr_device::entry; -#[cfg(feature = "device-selected")] -pub use pac::Peripherals; - pub use avr_hal_generic::clock; pub use avr_hal_generic::delay; pub use avr_hal_generic::prelude; -// ATtiny2313 does not have ADC and will not compile with this module -#[cfg(all(feature = "device-selected", not(feature = "attiny2313")))] -pub mod adc; -#[cfg(all(feature = "device-selected", not(feature = "attiny2313")))] -pub use adc::Adc; +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167; +#[cfg(feature = "_mcu-attiny2313")] +pub mod attiny2313; +#[cfg(feature = "_mcu-attiny84")] +pub mod attiny84; +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85; +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88; -#[cfg(feature = "device-selected")] +pub mod eeprom; pub mod port; -#[cfg(feature = "device-selected")] -pub use port::Pins; - -#[cfg(feature = "device-selected")] pub mod simple_pwm; - -#[cfg(feature = "device-selected")] pub mod wdt; -#[cfg(feature = "device-selected")] -pub use wdt::Wdt; -#[cfg(feature = "device-selected")] -pub mod eeprom; -#[cfg(feature = "device-selected")] -pub use eeprom::Eeprom; +#[cfg(any( + feature = "_mcu-attiny85", + feature = "_mcu-attiny88", + feature = "_mcu-attiny167" +))] +pub mod adc; -#[cfg(feature = "device-selected")] +#[cfg(any(feature = "_mcu-attiny88", feature = "_mcu-attiny167"))] pub mod spi; -#[cfg(feature = "device-selected")] -pub use spi::Spi; -pub struct Attiny; +#[cfg(feature = "deprecated-globals")] +mod globals; -#[cfg(feature = "device-selected")] -#[macro_export] -macro_rules! pins { - ($p:expr) => { - $crate::port::pins(&$p) - }; -} +#[cfg(feature = "deprecated-globals")] +pub use globals::*; diff --git a/mcu/attiny-hal/src/port.rs b/mcu/attiny-hal/src/port.rs index b2b0692a63..7b01984043 100644 --- a/mcu/attiny-hal/src/port.rs +++ b/mcu/attiny-hal/src/port.rs @@ -17,71 +17,97 @@ //! } //! ``` -pub use avr_hal_generic::port::{mode, PinMode, PinOps}; - -#[cfg(feature = "attiny2313")] -avr_hal_generic::impl_port_traditional! { - enum Ports { - A: crate::pac::PORTA = [0, 1, 2], - B: crate::pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], - D: crate::pac::PORTD = [0, 1, 2, 3, 4, 5, 6], +#[cfg(feature = "_mcu-attiny2313")] +pub mod attiny2313 { + use crate::attiny2313::pac; + + pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + avr_hal_generic::impl_port_traditional! { + enum Ports { + A: pac::PORTA = [0, 1, 2], + B: pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], + D: pac::PORTD = [0, 1, 2, 3, 4, 5, 6], + } } -} -#[cfg(feature = "attiny2313")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTA, &peripherals.PORTB, &peripherals.PORTD); + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB, &peripherals.PORTD); + } } -#[cfg(feature = "attiny167")] -avr_hal_generic::impl_port_traditional! { - enum Ports { - A: crate::pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], - B: crate::pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167 { + use crate::attiny167::pac; + + pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + avr_hal_generic::impl_port_traditional! { + enum Ports { + A: pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], + B: pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], + } } -} -#[cfg(feature = "attiny167")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + } } -#[cfg(feature = "attiny84")] -avr_hal_generic::impl_port_traditional! { - enum Ports { - A: crate::pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], - B: crate::pac::PORTB = [0, 1, 2, 3], +#[cfg(feature = "_mcu-attiny84")] +pub mod attiny84 { + use crate::attiny84::pac; + + pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + avr_hal_generic::impl_port_traditional! { + enum Ports { + A: pac::PORTA = [0, 1, 2, 3, 4, 5, 6, 7], + B: pac::PORTB = [0, 1, 2, 3], + } } -} -#[cfg(feature = "attiny84")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + } } -#[cfg(feature = "attiny85")] -avr_hal_generic::impl_port_traditional! { - enum Ports { - B: crate::pac::PORTB = [0, 1, 2, 3, 4, 5], +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85 { + use crate::attiny85::pac; + + pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + avr_hal_generic::impl_port_traditional! { + enum Ports { + B: pac::PORTB = [0, 1, 2, 3, 4, 5], + } } -} -#[cfg(feature = "attiny85")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTB); + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTB); + } } -#[cfg(feature = "attiny88")] -avr_hal_generic::impl_port_traditional! { - enum Ports { - A: crate::pac::PORTA = [0, 1, 2, 3], - B: crate::pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], - C: crate::pac::PORTC = [0, 1, 2, 3, 4, 5, 6, 7], - D: crate::pac::PORTD = [0, 1, 2, 3, 4, 5, 6, 7], +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + use crate::attiny88::pac; + + pub use avr_hal_generic::port::{mode, PinMode, PinOps}; + avr_hal_generic::impl_port_traditional! { + enum Ports { + A: pac::PORTA = [0, 1, 2, 3], + B: pac::PORTB = [0, 1, 2, 3, 4, 5, 6, 7], + C: pac::PORTC = [0, 1, 2, 3, 4, 5, 6, 7], + D: pac::PORTD = [0, 1, 2, 3, 4, 5, 6, 7], + } } -} -#[cfg(feature = "attiny88")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTA, &peripherals.PORTB, &peripherals.PORTC, &peripherals.PORTD); + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new( + &peripherals.PORTA, + &peripherals.PORTB, + &peripherals.PORTC, + &peripherals.PORTD, + ); + } } + +#[cfg(feature = "deprecated-globals")] +pub use crate::mcu::port::*; diff --git a/mcu/attiny-hal/src/simple_pwm.rs b/mcu/attiny-hal/src/simple_pwm.rs index f16a89c9c0..12b013fbbf 100644 --- a/mcu/attiny-hal/src/simple_pwm.rs +++ b/mcu/attiny-hal/src/simple_pwm.rs @@ -1,217 +1,234 @@ -pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; +#[cfg(feature = "_mcu-attiny84")] +pub mod attiny84 { + use crate::attiny84::port::*; + pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; -#[cfg(any(feature = "attiny85", feature = "attiny84", feature = "attiny88"))] -use crate::port::*; - -#[cfg(feature = "attiny84")] -avr_hal_generic::impl_simple_pwm! { - /// Use `TC0` for PWM (pins `PB2`, `PA7`) - pub struct Timer0Pwm { - timer: crate::pac::TC0, - init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { - Prescaler::Direct => w.cs0().direct(), - Prescaler::Prescale8 => w.cs0().prescale_8(), - Prescaler::Prescale64 => w.cs0().prescale_64(), - Prescaler::Prescale256 => w.cs0().prescale_256(), - Prescaler::Prescale1024 => w.cs0().prescale_1024(), - }); - }, - pins: { - PB2: { - ocr: ocr0a, - into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); - } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); - }, + avr_hal_generic::impl_simple_pwm! { + /// Use `TC0` for PWM (pins `PB2`, `PA7`) + pub struct Timer0Pwm { + timer: crate::attiny84::pac::TC0, + init: |tim, prescaler| { + tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs0().direct(), + Prescaler::Prescale8 => w.cs0().prescale_8(), + Prescaler::Prescale64 => w.cs0().prescale_64(), + Prescaler::Prescale256 => w.cs0().prescale_256(), + Prescaler::Prescale1024 => w.cs0().prescale_1024(), + }); }, + pins: { + PB2: { + ocr: ocr0a, + into_pwm: |tim| if enable { + tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + } else { + tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + }, + }, - PA7: { - ocr: ocr0b, - into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); - } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + PA7: { + ocr: ocr0b, + into_pwm: |tim| if enable { + tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + } else { + tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + }, }, }, - }, + } } -} -#[cfg(feature = "attiny84")] -avr_hal_generic::impl_simple_pwm! { - /// Use `TC1` for PWM (pins `PA6`, 'PA5') - pub struct Timer1Pwm { - timer: crate::pac::TC1, - init: |tim, prescaler| { - tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); + avr_hal_generic::impl_simple_pwm! { + /// Use `TC1` for PWM (pins `PA6`, 'PA5') + pub struct Timer1Pwm { + timer: crate::attiny84::pac::TC1, + init: |tim, prescaler| { + tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); + tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_r, w| match prescaler { - Prescaler::Direct => w.cs1().direct(), - Prescaler::Prescale8 => w.cs1().prescale_8(), - Prescaler::Prescale64 => w.cs1().prescale_64(), - Prescaler::Prescale256 => w.cs1().prescale_256(), - Prescaler::Prescale1024 => w.cs1().prescale_1024(), - }); - }, - pins: { - PA6: { - ocr: ocr1a, - into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); - } else { - tim.tccr1a.modify(|_, w| w.com1a().disconnected()); - }, + tim.tccr1b.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs1().direct(), + Prescaler::Prescale8 => w.cs1().prescale_8(), + Prescaler::Prescale64 => w.cs1().prescale_64(), + Prescaler::Prescale256 => w.cs1().prescale_256(), + Prescaler::Prescale1024 => w.cs1().prescale_1024(), + }); }, + pins: { + PA6: { + ocr: ocr1a, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); + } else { + tim.tccr1a.modify(|_, w| w.com1a().disconnected()); + }, + }, - PA5: { - ocr: ocr1b, - into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); - } else { - tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + PA5: { + ocr: ocr1b, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); + } else { + tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + }, }, }, - }, + } } } -#[cfg(feature = "attiny85")] -avr_hal_generic::impl_simple_pwm! { - /// Use `TC0` for PWM (pins `PB0`, `PB1`) - /// - /// # Example - /// ``` - /// let mut timer0 = Timer0Pwm::new(dp.TC0, Prescaler::Prescale64); - /// - /// let mut d0 = pins.d0.into_output().into_pwm(&mut timer0); - /// let mut d1 = pins.d1.into_output().into_pwm(&mut timer0); - /// - /// d0.set_duty(128); - /// d0.enable(); - /// ``` - pub struct Timer0Pwm { - timer: crate::pac::TC0, - init: |tim, prescaler| { - tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); - tim.tccr0b.modify(|_r, w| match prescaler { - Prescaler::Direct => w.cs0().direct(), - Prescaler::Prescale8 => w.cs0().prescale_8(), - Prescaler::Prescale64 => w.cs0().prescale_64(), - Prescaler::Prescale256 => w.cs0().prescale_256(), - Prescaler::Prescale1024 => w.cs0().prescale_1024(), - }); - }, - pins: { - PB0: { - ocr: ocr0a, - into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); - } else { - tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); - }, +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85 { + use crate::attiny85::port::*; + pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; + avr_hal_generic::impl_simple_pwm! { + /// Use `TC0` for PWM (pins `PB0`, `PB1`) + /// + /// # Example + /// ``` + /// let mut timer0 = Timer0Pwm::new(dp.TC0, Prescaler::Prescale64); + /// + /// let mut d0 = pins.d0.into_output().into_pwm(&mut timer0); + /// let mut d1 = pins.d1.into_output().into_pwm(&mut timer0); + /// + /// d0.set_duty(128); + /// d0.enable(); + /// ``` + pub struct Timer0Pwm { + timer: crate::attiny85::pac::TC0, + init: |tim, prescaler| { + tim.tccr0a.modify(|_r, w| w.wgm0().pwm_fast()); + tim.tccr0b.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs0().direct(), + Prescaler::Prescale8 => w.cs0().prescale_8(), + Prescaler::Prescale64 => w.cs0().prescale_64(), + Prescaler::Prescale256 => w.cs0().prescale_256(), + Prescaler::Prescale1024 => w.cs0().prescale_1024(), + }); }, + pins: { + PB0: { + ocr: ocr0a, + into_pwm: |tim| if enable { + tim.tccr0a.modify(|_r, w| w.com0a().match_clear()); + } else { + tim.tccr0a.modify(|_r, w| w.com0a().disconnected()); + }, + }, - PB1: { - ocr: ocr0b, - into_pwm: |tim| if enable { - tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); - } else { - tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + PB1: { + ocr: ocr0b, + into_pwm: |tim| if enable { + tim.tccr0a.modify(|_r, w| w.com0b().match_clear()); + } else { + tim.tccr0a.modify(|_r, w| w.com0b().disconnected()); + }, }, }, - }, + } } -} -#[cfg(feature = "attiny85")] -avr_hal_generic::impl_simple_pwm! { - /// Use `TC1` for PWM (pins `PB4`) - /// - /// # Example - /// ``` - /// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64); - /// - /// let mut d4 = pins.d4.into_output().into_pwm(&mut timer1); - /// - /// d4.set_duty(128); - /// d4.enable(); - /// ``` - pub struct Timer1Pwm { - timer: crate::pac::TC1, - init: |tim, prescaler| { - tim.gtccr.modify(|_, w| w.pwm1b().bit(true)); + avr_hal_generic::impl_simple_pwm! { + /// Use `TC1` for PWM (pins `PB4`) + /// + /// # Example + /// ``` + /// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64); + /// + /// let mut d4 = pins.d4.into_output().into_pwm(&mut timer1); + /// + /// d4.set_duty(128); + /// d4.enable(); + /// ``` + pub struct Timer1Pwm { + timer: crate::attiny85::pac::TC1, + init: |tim, prescaler| { + tim.gtccr.modify(|_, w| w.pwm1b().bit(true)); - tim.tccr1.modify(|_r, w| match prescaler { - Prescaler::Direct => w.cs1().direct(), - Prescaler::Prescale8 => w.cs1().prescale_8(), - Prescaler::Prescale64 => w.cs1().prescale_64(), - Prescaler::Prescale256 => w.cs1().prescale_256(), - Prescaler::Prescale1024 => w.cs1().prescale_1024(), - }); - }, - pins: { - PB4: { - ocr: ocr1b, - into_pwm: |tim| if enable { - tim.gtccr.modify(|_, w| w.com1b().bits(0b10)); - } else { - tim.gtccr.modify(|_, w| w.com1b().disconnected()); + tim.tccr1.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs1().direct(), + Prescaler::Prescale8 => w.cs1().prescale_8(), + Prescaler::Prescale64 => w.cs1().prescale_64(), + Prescaler::Prescale256 => w.cs1().prescale_256(), + Prescaler::Prescale1024 => w.cs1().prescale_1024(), + }); + }, + pins: { + PB4: { + ocr: ocr1b, + into_pwm: |tim| if enable { + tim.gtccr.modify(|_, w| w.com1b().bits(0b10)); + } else { + tim.gtccr.modify(|_, w| w.com1b().disconnected()); + }, }, }, - }, + } } } -#[cfg(feature = "attiny88")] -avr_hal_generic::impl_simple_pwm! { - /// Use `TC1` for PWM (pins `PB1`, 'PB2') - /// - /// # Example - /// ``` - /// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64); - /// - /// let mut d9 = pins.d9.into_output().into_pwm(&mut timer1); - /// let mut d10 = pins.d10.into_output().into_pwm(&mut timer1); - /// - /// d9.set_duty(128); - /// d9.enable(); - /// ``` - pub struct Timer1Pwm { - timer: crate::pac::TC1, - init: |tim, prescaler| { - tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); - tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + use crate::attiny88::port::*; + pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; - tim.tccr1b.modify(|_r, w| match prescaler { - Prescaler::Direct => w.cs1().direct(), - Prescaler::Prescale8 => w.cs1().prescale_8(), - Prescaler::Prescale64 => w.cs1().prescale_64(), - Prescaler::Prescale256 => w.cs1().prescale_256(), - Prescaler::Prescale1024 => w.cs1().prescale_1024(), - }); - }, - pins: { - PB1: { - ocr: ocr1a, - into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); - } else { - tim.tccr1a.modify(|_, w| w.com1a().disconnected()); - }, + avr_hal_generic::impl_simple_pwm! { + /// Use `TC1` for PWM (pins `PB1`, 'PB2') + /// + /// # Example + /// ``` + /// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64); + /// + /// let mut d9 = pins.d9.into_output().into_pwm(&mut timer1); + /// let mut d10 = pins.d10.into_output().into_pwm(&mut timer1); + /// + /// d9.set_duty(128); + /// d9.enable(); + /// ``` + pub struct Timer1Pwm { + timer: crate::attiny88::pac::TC1, + init: |tim, prescaler| { + tim.tccr1a.modify(|_, w| w.wgm1().bits(0b01)); + tim.tccr1b.modify(|_, w| w.wgm1().bits(0b01)); + + tim.tccr1b.modify(|_r, w| match prescaler { + Prescaler::Direct => w.cs1().direct(), + Prescaler::Prescale8 => w.cs1().prescale_8(), + Prescaler::Prescale64 => w.cs1().prescale_64(), + Prescaler::Prescale256 => w.cs1().prescale_256(), + Prescaler::Prescale1024 => w.cs1().prescale_1024(), + }); }, + pins: { + PB1: { + ocr: ocr1a, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_, w| w.com1a().bits(0b10)); + } else { + tim.tccr1a.modify(|_, w| w.com1a().disconnected()); + }, + }, - PB2: { - ocr: ocr1b, - into_pwm: |tim| if enable { - tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); - } else { - tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + PB2: { + ocr: ocr1b, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); + } else { + tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + }, }, }, - }, + } } } + +#[cfg(all( + feature = "deprecated-globals", + any( + feature = "_mcu-attiny84", + feature = "_mcu-attiny85", + feature = "_mcu-attiny88" + ) +))] +pub use crate::mcu::simple_pwm::*; diff --git a/mcu/attiny-hal/src/spi.rs b/mcu/attiny-hal/src/spi.rs index 65ae277263..5bd8f51b4c 100644 --- a/mcu/attiny-hal/src/spi.rs +++ b/mcu/attiny-hal/src/spi.rs @@ -28,45 +28,57 @@ //! ufmt::uwriteln!(&mut serial, "data: {:?}", data_in).unwrap(); //! ``` +macro_rules! impl_spi { + (mcu: $($mcu:ident)::+, sclk: $($sclk:ident)::+, mosi: $($mosi:ident)::+, miso: $($miso:ident)::+, cs: $($cs:ident)::+ $(,)?) => { + pub use avr_hal_generic::spi::*; -#[allow(unused_imports)] -use crate::port; -pub use avr_hal_generic::spi::*; + pub type Spi = avr_hal_generic::spi::Spi< + $($mcu)::+::Hal, + $($mcu)::+::pac::SPI, + $($sclk)::+, + $($mosi)::+, + $($miso)::+, + $($cs)::+, + >; -#[cfg(feature = "attiny88")] -pub type Spi = avr_hal_generic::spi::Spi< - crate::Attiny, - crate::pac::SPI, - port::PB5, - port::PB3, - port::PB4, - port::PB2, ->; -#[cfg(feature = "attiny88")] -avr_hal_generic::impl_spi! { - hal: crate::Attiny, - peripheral: crate::pac::SPI, - sclk: port::PB5, - mosi: port::PB3, - miso: port::PB4, - cs: port::PB2, + avr_hal_generic::impl_spi! { + hal: $($mcu)::+::Hal, + peripheral: $($mcu)::+::pac::SPI, + sclk: $($sclk)::+, + mosi: $($mosi)::+, + miso: $($miso)::+, + cs: $($cs)::+, + } + + } +} + +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + use crate::attiny88 as mcu; + impl_spi! { + mcu: mcu, + sclk: mcu::port::PB5, + mosi: mcu::port::PB3, + miso: mcu::port::PB4, + cs: mcu::port::PB2, + } } -#[cfg(feature = "attiny167")] -pub type Spi = avr_hal_generic::spi::Spi< - crate::Attiny, - crate::pac::SPI, - port::PA5, - port::PA4, - port::PA2, - port::PA6, ->; -#[cfg(feature = "attiny167")] -avr_hal_generic::impl_spi! { - hal: crate::Attiny, - peripheral: crate::pac::SPI, - sclk: port::PA5, - mosi: port::PA4, - miso: port::PA2, - cs: port::PA6, +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167 { + use crate::attiny167 as mcu; + impl_spi! { + mcu: mcu, + sclk: mcu::port::PA5, + mosi: mcu::port::PA4, + miso: mcu::port::PA2, + cs: mcu::port::PA6, + } } + +#[cfg(all( + feature = "deprecated-globals", + any(feature = "_mcu-attiny88", feature = "_mcu-attiny167") +))] +pub use crate::mcu::spi::*; diff --git a/mcu/attiny-hal/src/wdt.rs b/mcu/attiny-hal/src/wdt.rs index 1693051483..c3ce5ca6c4 100644 --- a/mcu/attiny-hal/src/wdt.rs +++ b/mcu/attiny-hal/src/wdt.rs @@ -1,44 +1,69 @@ -#[allow(unused_imports)] -pub use avr_hal_generic::wdt::{Timeout, WdtOps}; - -pub type Wdt = avr_hal_generic::wdt::Wdt; - -#[cfg(any(feature = "attiny85", feature = "attiny167", feature = "attiny2313"))] -avr_hal_generic::impl_wdt! { - hal: crate::Attiny, - peripheral: crate::pac::WDT, - mcusr: crate::pac::cpu::MCUSR, - wdtcsr_name: wdtcr, - timeout: |to, w| match to { - Timeout::Ms16 => w.wdpl().cycles_2k_512k(), - Timeout::Ms32 => w.wdpl().cycles_4k_1024k(), - Timeout::Ms64 => w.wdpl().cycles_8k(), - Timeout::Ms125 => w.wdpl().cycles_16k(), - Timeout::Ms250 => w.wdpl().cycles_32k(), - Timeout::Ms500 => w.wdpl().cycles_64k(), - Timeout::Ms1000 => w.wdpl().cycles_128k(), - Timeout::Ms2000 => w.wdpl().cycles_256k(), - Timeout::Ms4000 => w.wdph().set_bit().wdpl().cycles_2k_512k(), - Timeout::Ms8000 => w.wdph().set_bit().wdpl().cycles_4k_1024k(), - }, +macro_rules! impl_wdt { + (mcu: $($mcu:ident)::+, wdtcsr_name: $wdtcsr_name:ident $(,)?) => { + pub use avr_hal_generic::wdt::{Timeout, WdtOps}; + + avr_hal_generic::impl_wdt! { + hal: $($mcu)::+::Hal, + peripheral: $($mcu)::+::pac::WDT, + mcusr: $($mcu)::+::pac::cpu::MCUSR, + wdtcsr_name: $wdtcsr_name, + timeout: |to, w| match to { + Timeout::Ms16 => w.wdpl().cycles_2k_512k(), + Timeout::Ms32 => w.wdpl().cycles_4k_1024k(), + Timeout::Ms64 => w.wdpl().cycles_8k(), + Timeout::Ms125 => w.wdpl().cycles_16k(), + Timeout::Ms250 => w.wdpl().cycles_32k(), + Timeout::Ms500 => w.wdpl().cycles_64k(), + Timeout::Ms1000 => w.wdpl().cycles_128k(), + Timeout::Ms2000 => w.wdpl().cycles_256k(), + Timeout::Ms4000 => w.wdph().set_bit().wdpl().cycles_2k_512k(), + Timeout::Ms8000 => w.wdph().set_bit().wdpl().cycles_4k_1024k(), + }, + } + + pub type Wdt = avr_hal_generic::wdt::Wdt<$($mcu)::+::Hal, $($mcu)::+::pac::WDT>; + }; +} + +#[cfg(feature = "_mcu-attiny85")] +pub mod attiny85 { + impl_wdt! { + mcu: crate::attiny85, + wdtcsr_name: wdtcr, + } +} + +#[cfg(feature = "_mcu-attiny167")] +pub mod attiny167 { + impl_wdt! { + mcu: crate::attiny167, + wdtcsr_name: wdtcr, + } } -#[cfg(any(feature = "attiny84", feature = "attiny88"))] -avr_hal_generic::impl_wdt! { - hal: crate::Attiny, - peripheral: crate::pac::WDT, - mcusr: crate::pac::cpu::MCUSR, - wdtcsr_name: wdtcsr, - timeout: |to, w| match to { - Timeout::Ms16 => w.wdpl().cycles_2k_512k(), - Timeout::Ms32 => w.wdpl().cycles_4k_1024k(), - Timeout::Ms64 => w.wdpl().cycles_8k(), - Timeout::Ms125 => w.wdpl().cycles_16k(), - Timeout::Ms250 => w.wdpl().cycles_32k(), - Timeout::Ms500 => w.wdpl().cycles_64k(), - Timeout::Ms1000 => w.wdpl().cycles_128k(), - Timeout::Ms2000 => w.wdpl().cycles_256k(), - Timeout::Ms4000 => w.wdph().set_bit().wdpl().cycles_2k_512k(), - Timeout::Ms8000 => w.wdph().set_bit().wdpl().cycles_4k_1024k(), - }, +#[cfg(feature = "_mcu-attiny2313")] +pub mod attiny2313 { + impl_wdt! { + mcu: crate::attiny2313, + wdtcsr_name: wdtcr, + } } + +#[cfg(feature = "_mcu-attiny84")] +pub mod attiny84 { + impl_wdt! { + mcu: crate::attiny84, + wdtcsr_name: wdtcsr, + } +} + +#[cfg(feature = "_mcu-attiny88")] +pub mod attiny88 { + impl_wdt! { + mcu: crate::attiny88, + wdtcsr_name: wdtcsr, + } +} + +#[cfg(feature = "deprecated-globals")] +pub use crate::mcu::wdt::*;