From 40878e22f60855dca269afecc33106cd0fc94811 Mon Sep 17 00:00:00 2001 From: Iris Artin Date: Wed, 20 Nov 2024 23:10:35 -0500 Subject: [PATCH] Refactor attiny-hal for opt-out deprecated globals --- .github/workflows/ci.yml | 5 + mcu/attiny-hal/Cargo.toml | 69 +++++--- mcu/attiny-hal/src/adc.rs | 209 ------------------------- mcu/attiny-hal/src/attiny167.rs | 122 +++++++++++++++ mcu/attiny-hal/src/attiny2313.rs | 38 +++++ mcu/attiny-hal/src/attiny84.rs | 117 ++++++++++++++ mcu/attiny-hal/src/attiny85.rs | 188 ++++++++++++++++++++++ mcu/attiny-hal/src/attiny88.rs | 169 ++++++++++++++++++++ mcu/attiny-hal/src/eeprom.rs | 56 ------- mcu/attiny-hal/src/globals.rs | 100 ++++++++++++ mcu/attiny-hal/src/impl/adc.rs | 116 ++++++++++++++ mcu/attiny-hal/src/impl/eeprom.rs | 48 ++++++ mcu/attiny-hal/src/impl/mod.rs | 23 +++ mcu/attiny-hal/src/impl/port.rs | 28 ++++ mcu/attiny-hal/src/impl/simple_pwm.rs | 9 ++ mcu/attiny-hal/src/impl/spi.rs | 64 ++++++++ mcu/attiny-hal/src/impl/wdt.rs | 30 ++++ mcu/attiny-hal/src/lib.rs | 100 +++--------- mcu/attiny-hal/src/port.rs | 87 ----------- mcu/attiny-hal/src/simple_pwm.rs | 217 -------------------------- mcu/attiny-hal/src/spi.rs | 72 --------- mcu/attiny-hal/src/wdt.rs | 44 ------ 22 files changed, 1131 insertions(+), 780 deletions(-) delete mode 100644 mcu/attiny-hal/src/adc.rs create mode 100644 mcu/attiny-hal/src/attiny167.rs create mode 100644 mcu/attiny-hal/src/attiny2313.rs create mode 100644 mcu/attiny-hal/src/attiny84.rs create mode 100644 mcu/attiny-hal/src/attiny85.rs create mode 100644 mcu/attiny-hal/src/attiny88.rs delete mode 100644 mcu/attiny-hal/src/eeprom.rs create mode 100644 mcu/attiny-hal/src/globals.rs create mode 100644 mcu/attiny-hal/src/impl/adc.rs create mode 100644 mcu/attiny-hal/src/impl/eeprom.rs create mode 100644 mcu/attiny-hal/src/impl/mod.rs create mode 100644 mcu/attiny-hal/src/impl/port.rs create mode 100644 mcu/attiny-hal/src/impl/simple_pwm.rs create mode 100644 mcu/attiny-hal/src/impl/spi.rs create mode 100644 mcu/attiny-hal/src/impl/wdt.rs delete mode 100644 mcu/attiny-hal/src/port.rs delete mode 100644 mcu/attiny-hal/src/simple_pwm.rs delete mode 100644 mcu/attiny-hal/src/spi.rs delete mode 100644 mcu/attiny-hal/src/wdt.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 507335a20c..c7ef1aee66 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -119,6 +119,11 @@ jobs: - 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" + - name: Test-compile HAL crate for an MCU (no deprecated globals) + if: "${{ matrix.m.create == 'attiny-hal' }}" + run: >- + cd "mcu/${{ matrix.m.crate }}" && + 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..561e90da07 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,66 @@ 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.30 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.3.0 +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.3.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", "_peripheral-simple-pwm", "avr-device/attiny84"] +_mcu-attiny85 = ["_mcu-selected", "_peripheral-adc", "_peripheral-simple-pwm", "avr-device/attiny85"] +_mcu-attiny88 = ["_mcu-selected", "_peripheral-adc", "_peripheral-spi", "_peripheral-simple-pwm", "avr-device/attiny88"] +_mcu-attiny167 = ["_mcu-selected", "_peripheral-adc", "_peripheral-spi", "avr-device/attiny167"] +_mcu-attiny2313 = ["_mcu-selected", "avr-device/attiny2313"] + +_mcu-selected = [] +_peripheral-adc = [] +_peripheral-spi = [] +_peripheral-simple-pwm = [] -# 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 deleted file mode 100644 index 0856312086..0000000000 --- a/mcu/attiny-hal/src/adc.rs +++ /dev/null @@ -1,209 +0,0 @@ -#![allow(non_camel_case_types)] -//! Analog-to-Digital Converter -//! -//! # Example -//! -//! For full source code, please refer to the ATmega ADC example: -//! [`atmega2560-adc.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-adc.rs) -//! -//! ``` -//! let dp = attiny_hal::Peripherals::take().unwrap(); -//! let pins = attiny_hal::pins!(dp); -//! -//! let mut adc = Adc::new(dp.ADC, Default::default()); -//! -//! let channels: [attiny_hal::adc::Channel; 4] = [ -//! pins.pa0.into_analog_input(&mut adc).into_channel(), -//! pins.pa1.into_analog_input(&mut adc).into_channel(), -//! pins.pa2.into_analog_input(&mut adc).into_channel(), -//! pins.pa3.into_analog_input(&mut adc).into_channel(), -//! ]; -//! -//! for (index, channel) in channels.iter().enumerate() { -//! let value = adc.read_blocking(channel); -//! ufmt::uwrite!(&mut serial, "CH{}: {} ", index, value).unwrap(); -//! } -//! ``` - -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, -} - -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, -} - -/// 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; -} - -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(), - } - }); -} - -#[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 = "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 = "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, - }, -} diff --git a/mcu/attiny-hal/src/attiny167.rs b/mcu/attiny-hal/src/attiny167.rs new file mode 100644 index 0000000000..35f8f1cc36 --- /dev/null +++ b/mcu/attiny-hal/src/attiny167.rs @@ -0,0 +1,122 @@ +pub use avr_device::attiny167 as pac; + +pub struct Hal; + +use crate::r#impl::impl_mod_adc; +impl_mod_adc! { + use crate::attiny167::{pac, port, Hal}; + + use crate::r#impl::impl_adc_reference_voltage; + impl_adc_reference_voltage! { + 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, + } + } + + use crate::r#impl::impl_adc_channels; + impl_adc_channels! { + pub struct AVcc_4; + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + use crate::r#impl::impl_adc_peripheral; + impl_adc_peripheral! { + pac: crate::attiny167::pac, + hal: crate::attiny167::Hal, + } + + 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, + }, + } +} + +use crate::r#impl::impl_mod_eeprom; +impl_mod_eeprom! { + pac: crate::attiny167::pac, + hal: crate::attiny167::Hal, + capacity: 512, + addr_width: u16, + addr_reg: eear, +} + +use crate::r#impl::impl_mod_port; +impl_mod_port! { + 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], + } + } + + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + } +} + +use crate::r#impl::impl_mod_spi; +impl_mod_spi! { + pac: crate::attiny167::pac, + hal: crate::attiny167::Hal, + sclk: crate::attiny167::port::PA5, + mosi: crate::attiny167::port::PA4, + miso: crate::attiny167::port::PA2, + cs: crate::attiny167::port::PA6, +} + +use crate::r#impl::impl_mod_wdt; +impl_mod_wdt! { + mcu: crate::attiny167, + wdtcsr_name: wdtcr, +} + +pub use {adc::Adc, eeprom::Eeprom, pac::Peripherals, port::Pins, spi::Spi, wdt::Wdt}; diff --git a/mcu/attiny-hal/src/attiny2313.rs b/mcu/attiny-hal/src/attiny2313.rs new file mode 100644 index 0000000000..ed321d134b --- /dev/null +++ b/mcu/attiny-hal/src/attiny2313.rs @@ -0,0 +1,38 @@ +pub use avr_device::attiny2313 as pac; + +pub struct Hal; + +use crate::r#impl::impl_mod_eeprom; +impl_mod_eeprom! { + pac: crate::attiny2313::pac, + hal: crate::attiny2313::Hal, + capacity: 128, + addr_width: u8, + addr_reg: eear, +} + +use crate::r#impl::impl_mod_port; +impl_mod_port! { + 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], + } + } + + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB, &peripherals.PORTD); + } +} + +use crate::r#impl::impl_mod_wdt; +impl_mod_wdt! { + mcu: crate::attiny2313, + wdtcsr_name: wdtcr, +} + +pub use {eeprom::Eeprom, pac::Peripherals, port::Pins, wdt::Wdt}; diff --git a/mcu/attiny-hal/src/attiny84.rs b/mcu/attiny-hal/src/attiny84.rs new file mode 100644 index 0000000000..65eda9bf34 --- /dev/null +++ b/mcu/attiny-hal/src/attiny84.rs @@ -0,0 +1,117 @@ +pub use avr_device::attiny84 as pac; + +pub struct Hal; + +use crate::r#impl::impl_mod_eeprom; +impl_mod_eeprom! { + pac: crate::attiny84::pac, + hal: crate::attiny84::Hal, + capacity: 512, + addr_width: u16, + addr_reg: eear, +} + +use crate::r#impl::impl_mod_port; +impl_mod_port! { + use super::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], + } + } + + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTA, &peripherals.PORTB); + } +} + +use crate::r#impl::impl_mod_simple_pwm; +impl_mod_simple_pwm! { + use super::port::*; + pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; + + avr_hal_generic::impl_simple_pwm! { + /// Use `TC0` for PWM (pins `PB2`, `PA7`) + pub struct Timer0Pwm { + timer: super::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()); + }, + }, + }, + } + } + + avr_hal_generic::impl_simple_pwm! { + /// Use `TC1` for PWM (pins `PA6`, 'PA5') + pub struct Timer1Pwm { + timer: super::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()); + }, + }, + + PA5: { + ocr: ocr1b, + into_pwm: |tim| if enable { + tim.tccr1a.modify(|_, w| w.com1b().bits(0b10)); + } else { + tim.tccr1a.modify(|_, w| w.com1b().disconnected()); + }, + }, + }, + } + } +} + +use crate::r#impl::impl_mod_wdt; +impl_mod_wdt! { + mcu: crate::attiny84, + wdtcsr_name: wdtcsr, +} + +pub use {eeprom::Eeprom, pac::Peripherals, port::Pins, wdt::Wdt}; diff --git a/mcu/attiny-hal/src/attiny85.rs b/mcu/attiny-hal/src/attiny85.rs new file mode 100644 index 0000000000..82e474ce22 --- /dev/null +++ b/mcu/attiny-hal/src/attiny85.rs @@ -0,0 +1,188 @@ +pub use avr_device::attiny85 as pac; + +pub struct Hal; + +use crate::r#impl::impl_mod_adc; +impl_mod_adc! { + use crate::attiny85::{pac, port, Hal}; + + use crate::r#impl::impl_adc_reference_voltage; + impl_adc_reference_voltage! { + 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, + } + } + + use crate::r#impl::impl_adc_channels; + impl_adc_channels! { + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + use crate::r#impl::impl_adc_peripheral; + impl_adc_peripheral! { + pac: crate::attiny85::pac, + hal: crate::attiny85::Hal, + } + + 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, + }, + } +} + +use crate::r#impl::impl_mod_eeprom; +impl_mod_eeprom! { + pac: crate::attiny85::pac, + hal: crate::attiny85::Hal, + capacity: 512, + addr_width: u16, + addr_reg: eear, +} + +use crate::r#impl::impl_mod_port; +impl_mod_port! { + 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], + } + } + + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new(&peripherals.PORTB); + } +} + +use crate::r#impl::impl_mod_simple_pwm; +impl_mod_simple_pwm! { + 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()); + }, + }, + }, + } + } + + 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()); + }, + }, + }, + } + } +} + +use crate::r#impl::impl_mod_wdt; +impl_mod_wdt! { + mcu: crate::attiny85, + wdtcsr_name: wdtcr, +} + +pub use {adc::Adc, eeprom::Eeprom, pac::Peripherals, port::Pins, wdt::Wdt}; diff --git a/mcu/attiny-hal/src/attiny88.rs b/mcu/attiny-hal/src/attiny88.rs new file mode 100644 index 0000000000..c26c2c9e5e --- /dev/null +++ b/mcu/attiny-hal/src/attiny88.rs @@ -0,0 +1,169 @@ +pub use avr_device::attiny88 as pac; + +pub struct Hal; + +use crate::r#impl::impl_mod_adc; +impl_mod_adc! { + use crate::attiny88::{pac, port, Hal}; + + use crate::r#impl::impl_adc_reference_voltage; + impl_adc_reference_voltage! { + pub enum ReferenceVoltage { + /// Default reference voltage (default). + AVcc, + /// Internal 1.1V reference. + Internal1_1, + } + } + + use crate::r#impl::impl_adc_channels; + impl_adc_channels! { + pub struct Vbg; + pub struct Gnd; + pub struct Temperature; + } + + use crate::r#impl::impl_adc_peripheral; + impl_adc_peripheral! { + pac: crate::attiny88::pac, + hal: crate::attiny88::Hal, + } + + 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, + }, + } +} + +use crate::r#impl::impl_mod_eeprom; +impl_mod_eeprom! { + pac: crate::attiny88::pac, + hal: crate::attiny88::Hal, + capacity: 64, + addr_width: u8, + addr_reg: eearl, +} + +use crate::r#impl::impl_mod_port; +impl_mod_port! { + 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], + } + } + + pub fn pins(peripherals: &pac::Peripherals) -> Pins { + return Pins::new( + &peripherals.PORTA, + &peripherals.PORTB, + &peripherals.PORTC, + &peripherals.PORTD, + ); + } +} + +use crate::r#impl::impl_mod_simple_pwm; +impl_mod_simple_pwm! { + use crate::attiny88::port::*; + pub use avr_hal_generic::simple_pwm::{IntoPwmPin, Prescaler, PwmPinOps}; + + 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()); + }, + }, + }, + } + } +} + +use crate::r#impl::impl_mod_spi; +impl_mod_spi! { + pac: crate::attiny88::pac, + hal: crate::attiny88::Hal, + sclk: crate::attiny88::port::PB5, + mosi: crate::attiny88::port::PB3, + miso: crate::attiny88::port::PB4, + cs: crate::attiny88::port::PB2, +} + +use crate::r#impl::impl_mod_wdt; +impl_mod_wdt! { + mcu: crate::attiny88, + wdtcsr_name: wdtcsr, +} + +pub use {adc::Adc, eeprom::Eeprom, pac::Peripherals, port::Pins, spi::Spi, wdt::Wdt}; diff --git a/mcu/attiny-hal/src/eeprom.rs b/mcu/attiny-hal/src/eeprom.rs deleted file mode 100644 index f325215dfb..0000000000 --- a/mcu/attiny-hal/src/eeprom.rs +++ /dev/null @@ -1,56 +0,0 @@ -//! EEPROM -//! -//! # Example -//! -//! For full source code, please refer to the ATmega EEPROM example: -//! [`atmega2560-eeprom.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-eeprom.rs) -//! -//! ``` -//! const BOOT_COUNT_OFFSET: u16 = 0; -//! -//! let dp = attiny_hal::Peripherals::take().unwrap(); -//! let mut eeprom = Eeprom::new(dp.EEPROM); -//! -//! let mut boot_count = eeprom.read_byte(BOOT_COUNT_OFFSET); -//! boot_count = boot_count.wrapping_add(1); -//! eeprom.write_byte(BOOT_COUNT_OFFSET, boot_count); -//! -//! 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)); - }, -} - -#[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 = "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)); - }, -} diff --git a/mcu/attiny-hal/src/globals.rs b/mcu/attiny-hal/src/globals.rs new file mode 100644 index 0000000000..a50eb6542c --- /dev/null +++ b/mcu/attiny-hal/src/globals.rs @@ -0,0 +1,100 @@ +// 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::{eeprom, pac, port, wdt, Hal as Attiny}; +pub use {eeprom::Eeprom, pac::Peripherals, port::Pins, wdt::Wdt}; + +#[cfg(feature = "_peripheral-simple-pwm")] +pub use mcu::simple_pwm; + +#[cfg(feature = "_peripheral-adc")] +pub use crate::adc::Adc; +#[cfg(feature = "_peripheral-adc")] +pub use mcu::adc; + +#[cfg(feature = "_peripheral-spi")] +pub use crate::spi::Spi; +#[cfg(feature = "_peripheral-spi")] +pub use mcu::spi; + +#[macro_export] +macro_rules! pins { + ($p:expr) => { + $crate::port::pins(&$p) + }; +} diff --git a/mcu/attiny-hal/src/impl/adc.rs b/mcu/attiny-hal/src/impl/adc.rs new file mode 100644 index 0000000000..e4bbc90d46 --- /dev/null +++ b/mcu/attiny-hal/src/impl/adc.rs @@ -0,0 +1,116 @@ +macro_rules! impl_mod_adc { + ($($mod:item)*) => { + pub mod adc { + //! Analog-to-Digital Converter + //! + //! # Example + //! + //! For full source code, please refer to the ATmega ADC example: + //! [`atmega2560-adc.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-adc.rs) + //! + //! ``` + //! let dp = attiny_hal::Peripherals::take().unwrap(); + //! let pins = attiny_hal::pins!(dp); + //! + //! let mut adc = Adc::new(dp.ADC, Default::default()); + //! + //! let channels: [attiny_hal::adc::Channel; 4] = [ + //! pins.pa0.into_analog_input(&mut adc).into_channel(), + //! pins.pa1.into_analog_input(&mut adc).into_channel(), + //! pins.pa2.into_analog_input(&mut adc).into_channel(), + //! pins.pa3.into_analog_input(&mut adc).into_channel(), + //! ]; + //! + //! for (index, channel) in channels.iter().enumerate() { + //! let value = adc.read_blocking(channel); + //! ufmt::uwrite!(&mut serial, "CH{}: {} ", index, value).unwrap(); + //! } + //! ``` + + $($mod)* + } + } +} +pub(crate) use impl_mod_adc; + +macro_rules! impl_adc_reference_voltage { + ($enum:item) => { + /// 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)] + $enum + } +} +pub(crate) use impl_adc_reference_voltage; + +macro_rules! impl_adc_channels { + ($($channel:item)*) => { + /// 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); + /// ``` + #[allow(non_camel_case_types)] + pub mod channel { + $($channel)* + } + } +} +pub(crate) use impl_adc_channels; + + +macro_rules! impl_adc_peripheral { + ( + pac: $($pac:ident)::+, + hal: $($hal:ident)::+ $(,)? + ) => { + pub use avr_hal_generic::adc::{AdcChannel, AdcOps, ClockDivider}; + + 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, + } + + /// Check the [`avr_hal_generic::adc::Adc`] documentation. + pub type Adc = + avr_hal_generic::adc::Adc<$($hal)::+, $($pac)::+::ADC, CLOCK>; + + /// Check the [`avr_hal_generic::adc::Channel`] documentation. + pub type Channel = avr_hal_generic::adc::Channel<$($hal)::+, $($pac)::+::ADC>; + + fn apply_clock(peripheral: &$($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(), + } + }); + } + }; +} + +pub(crate) use impl_adc_peripheral; diff --git a/mcu/attiny-hal/src/impl/eeprom.rs b/mcu/attiny-hal/src/impl/eeprom.rs new file mode 100644 index 0000000000..026526bee2 --- /dev/null +++ b/mcu/attiny-hal/src/impl/eeprom.rs @@ -0,0 +1,48 @@ +macro_rules! impl_mod_eeprom { + ( + pac: $($pac:ident)::+, + hal: $($hal:ident)::+, + capacity: $capacity:expr, + addr_width: $addr_width:ty, + addr_reg: $addr_reg:ident $(,)? + ) => { + pub mod eeprom { + //! EEPROM + //! + //! # Example + //! + //! For full source code, please refer to the ATmega EEPROM example: + //! [`atmega2560-eeprom.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-eeprom.rs) + //! + //! ``` + //! const BOOT_COUNT_OFFSET: u16 = 0; + //! + //! let dp = attiny_hal::Peripherals::take().unwrap(); + //! let mut eeprom = Eeprom::new(dp.EEPROM); + //! + //! let mut boot_count = eeprom.read_byte(BOOT_COUNT_OFFSET); + //! boot_count = boot_count.wrapping_add(1); + //! eeprom.write_byte(BOOT_COUNT_OFFSET, boot_count); + //! + //! 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<$($hal)::+, $($pac)::+::EEPROM>; + + avr_hal_generic::impl_eeprom_attiny! { + hal: $($hal)::+, + peripheral: $($pac)::+::EEPROM, + capacity: $capacity, + addr_width: $addr_width, + set_address: |peripheral, address| { + peripheral.$addr_reg.write(|w| w.bits(address)); + }, + } + } + } +} + +pub(crate) use impl_mod_eeprom; diff --git a/mcu/attiny-hal/src/impl/mod.rs b/mcu/attiny-hal/src/impl/mod.rs new file mode 100644 index 0000000000..4328369349 --- /dev/null +++ b/mcu/attiny-hal/src/impl/mod.rs @@ -0,0 +1,23 @@ +#[cfg(feature = "_peripheral-adc")] +mod adc; +#[cfg(feature = "_peripheral-adc")] +pub(crate) use adc::*; + +mod eeprom; +pub(crate) use eeprom::*; + +mod port; +pub(crate) use port::*; + +#[cfg(feature = "_peripheral-simple-pwm")] +mod simple_pwm; +#[cfg(feature = "_peripheral-simple-pwm")] +pub(crate) use simple_pwm::*; + +#[cfg(feature = "_peripheral-spi")] +mod spi; +#[cfg(feature = "_peripheral-spi")] +pub(crate) use spi::*; + +mod wdt; +pub(crate) use wdt::*; diff --git a/mcu/attiny-hal/src/impl/port.rs b/mcu/attiny-hal/src/impl/port.rs new file mode 100644 index 0000000000..cfc1fa0a39 --- /dev/null +++ b/mcu/attiny-hal/src/impl/port.rs @@ -0,0 +1,28 @@ +macro_rules! impl_mod_port { + ($($mod:item)*) => { + pub mod port { + //! Port + //! + //! # Example + //! + //! For full source code, please refer to the ATmega port example: + //! [`atmega2560-blink.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-blink.rs) + //! + //! ``` + //! let dp = attiny_hal::Peripherals::take().unwrap(); + //! let pins = attiny_hal::pins!(dp); + //! + //! let mut led = pins.pb2.into_output(); + //! + //! loop { + //! led.toggle(); + //! delay_ms(1000); + //! } + //! ``` + + $($mod)* + } + } +} + +pub(crate) use impl_mod_port; diff --git a/mcu/attiny-hal/src/impl/simple_pwm.rs b/mcu/attiny-hal/src/impl/simple_pwm.rs new file mode 100644 index 0000000000..3af849d5fd --- /dev/null +++ b/mcu/attiny-hal/src/impl/simple_pwm.rs @@ -0,0 +1,9 @@ +macro_rules! impl_mod_simple_pwm { + ($($mod:item)*) => { + pub mod simple_pwm { + $($mod)* + } + } +} + +pub(crate) use impl_mod_simple_pwm; diff --git a/mcu/attiny-hal/src/impl/spi.rs b/mcu/attiny-hal/src/impl/spi.rs new file mode 100644 index 0000000000..36a7d781f2 --- /dev/null +++ b/mcu/attiny-hal/src/impl/spi.rs @@ -0,0 +1,64 @@ +macro_rules! impl_mod_spi { + ( + pac: $($pac:ident)::+, + hal: $($hal:ident)::+, + sclk: $($sclk:ident)::+, + mosi: $($mosi:ident)::+, + miso: $($miso:ident)::+, + cs: $($cs:ident)::+ $(,)? + ) => { + pub mod spi { + //! SPI + //! + //! # Example + //! + //! For full source code, please refer to the ATmega SPI example: + //! [`atmega2560-spi-feedback.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-spi-feedback.rs) + //! + //! ``` + //! let dp = attiny_hal::Peripherals::take().unwrap(); + //! let pins = attiny_hal::pins!(dp); + //! + //! let (mut spi, mut cs) = spi::Spi::new( + //! dp.SPI, + //! pins.pa4.into_output(), + //! pins.pa6.into_output(), + //! pins.pa5.into_pull_up_input(), + //! pins.pa3.into_output(), + //! spi::Settings::default(), + //! ); + //! + //! let data_out = b"Hello World!"; + //! let mut data_in = [0u8; 12]; + //! + //! cs.set_low().unwrap(); + //! spi.transfer(&mut data_in, data_out).unwrap(); + //! cs.set_high().unwrap(); + //! + //! ufmt::uwriteln!(&mut serial, "data: {:?}", data_in).unwrap(); + //! ``` + + pub use avr_hal_generic::spi::*; + + pub type Spi = avr_hal_generic::spi::Spi< + $($hal)::+, + $($pac)::+::SPI, + $($sclk)::+, + $($mosi)::+, + $($miso)::+, + $($cs)::+, + >; + + avr_hal_generic::impl_spi! { + hal: $($hal)::+, + peripheral: $($pac)::+::SPI, + sclk: $($sclk)::+, + mosi: $($mosi)::+, + miso: $($miso)::+, + cs: $($cs)::+, + } + } + } +} + +pub(crate) use impl_mod_spi; diff --git a/mcu/attiny-hal/src/impl/wdt.rs b/mcu/attiny-hal/src/impl/wdt.rs new file mode 100644 index 0000000000..5fc96d7841 --- /dev/null +++ b/mcu/attiny-hal/src/impl/wdt.rs @@ -0,0 +1,30 @@ +macro_rules! impl_mod_wdt { + (mcu: $($mcu:ident)::+, wdtcsr_name: $wdtcsr_name:ident $(,)?) => { + pub mod wdt { + 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>; + } + }; +} + +pub(crate) use impl_mod_wdt; diff --git a/mcu/attiny-hal/src/lib.rs b/mcu/attiny-hal/src/lib.rs index a71614a457..2160d4695c 100644 --- a/mcu/attiny-hal/src/lib.rs +++ b/mcu/attiny-hal/src/lib.rs @@ -3,28 +3,19 @@ //! `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 -//! ``` +// 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 = "device-selected"), + 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 +23,28 @@ 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 = "device-selected")] -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(feature = "device-selected")] -pub mod spi; -#[cfg(feature = "device-selected")] -pub use spi::Spi; - -pub struct Attiny; - -#[cfg(feature = "device-selected")] -#[macro_export] -macro_rules! pins { - ($p:expr) => { - $crate::port::pins(&$p) - }; -} +pub(crate) mod r#impl; + +#[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 = "deprecated-globals")] +mod globals; +#[cfg(feature = "deprecated-globals")] +pub use globals::*; diff --git a/mcu/attiny-hal/src/port.rs b/mcu/attiny-hal/src/port.rs deleted file mode 100644 index b2b0692a63..0000000000 --- a/mcu/attiny-hal/src/port.rs +++ /dev/null @@ -1,87 +0,0 @@ -//! Port -//! -//! # Example -//! -//! For full source code, please refer to the ATmega port example: -//! [`atmega2560-blink.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-blink.rs) -//! -//! ``` -//! let dp = attiny_hal::Peripherals::take().unwrap(); -//! let pins = attiny_hal::pins!(dp); -//! -//! let mut led = pins.pb2.into_output(); -//! -//! loop { -//! led.toggle(); -//! delay_ms(1000); -//! } -//! ``` - -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 = "attiny2313")] -pub fn pins(peripherals: &crate::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 = "attiny167")] -pub fn pins(peripherals: &crate::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 = "attiny84")] -pub fn pins(peripherals: &crate::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 = "attiny85")] -pub fn pins(peripherals: &crate::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 = "attiny88")] -pub fn pins(peripherals: &crate::pac::Peripherals) -> Pins { - return Pins::new(&peripherals.PORTA, &peripherals.PORTB, &peripherals.PORTC, &peripherals.PORTD); -} diff --git a/mcu/attiny-hal/src/simple_pwm.rs b/mcu/attiny-hal/src/simple_pwm.rs deleted file mode 100644 index f16a89c9c0..0000000000 --- a/mcu/attiny-hal/src/simple_pwm.rs +++ /dev/null @@ -1,217 +0,0 @@ -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()); - }, - }, - - 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)); - - 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()); - }, - }, - }, - } -} - -#[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()); - }, - }, - - 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)); - - 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)); - - 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()); - }, - }, - }, - } -} diff --git a/mcu/attiny-hal/src/spi.rs b/mcu/attiny-hal/src/spi.rs deleted file mode 100644 index 65ae277263..0000000000 --- a/mcu/attiny-hal/src/spi.rs +++ /dev/null @@ -1,72 +0,0 @@ -//! SPI -//! -//! # Example -//! -//! For full source code, please refer to the ATmega SPI example: -//! [`atmega2560-spi-feedback.rs`](https://github.com/Rahix/avr-hal/blob/main/examples/atmega2560/src/bin/atmega2560-spi-feedback.rs) -//! -//! ``` -//! let dp = attiny_hal::Peripherals::take().unwrap(); -//! let pins = attiny_hal::pins!(dp); -//! -//! let (mut spi, mut cs) = spi::Spi::new( -//! dp.SPI, -//! pins.pa4.into_output(), -//! pins.pa6.into_output(), -//! pins.pa5.into_pull_up_input(), -//! pins.pa3.into_output(), -//! spi::Settings::default(), -//! ); -//! -//! let data_out = b"Hello World!"; -//! let mut data_in = [0u8; 12]; -//! -//! cs.set_low().unwrap(); -//! spi.transfer(&mut data_in, data_out).unwrap(); -//! cs.set_high().unwrap(); -//! -//! ufmt::uwriteln!(&mut serial, "data: {:?}", data_in).unwrap(); -//! ``` - - -#[allow(unused_imports)] -use crate::port; -pub use avr_hal_generic::spi::*; - -#[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, -} - -#[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, -} diff --git a/mcu/attiny-hal/src/wdt.rs b/mcu/attiny-hal/src/wdt.rs deleted file mode 100644 index 1693051483..0000000000 --- a/mcu/attiny-hal/src/wdt.rs +++ /dev/null @@ -1,44 +0,0 @@ -#[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(), - }, -} - -#[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(), - }, -}