Skip to content

Commit 1aacefb

Browse files
authored
attiny-hal: Add ATtiny167 and ADC support for all chips
1 parent 9cba3f1 commit 1aacefb

File tree

8 files changed

+292
-0
lines changed

8 files changed

+292
-0
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ jobs:
6262
name: attiny88
6363
spec: attiny88
6464
crate: attiny-hal
65+
- type: mcu
66+
name: attiny167
67+
spec: attiny167
68+
crate: attiny-hal
6569
runs-on: ubuntu-latest
6670
steps:
6771
- name: Checkout code

avr-specs/avr-attiny167.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"arch": "avr",
3+
"atomic-cas": false,
4+
"cpu": "attiny167",
5+
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
6+
"eh-frame-header": false,
7+
"exe-suffix": ".elf",
8+
"executables": true,
9+
"late-link-args": {
10+
"gcc": [
11+
"-lgcc"
12+
]
13+
},
14+
"linker": "avr-gcc",
15+
"linker-is-gnu": true,
16+
"llvm-target": "avr-unknown-unknown",
17+
"max-atomic-width": 8,
18+
"no-default-libraries": false,
19+
"pre-link-args": {
20+
"gcc": [
21+
"-mmcu=attiny167",
22+
"-Wl,--as-needed"
23+
]
24+
},
25+
"target-c-int-width": "16",
26+
"target-pointer-width": "16"
27+
}

avr-specs/sync-from-upstream.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
"attiny88": {
2929
"cpu": "attiny88",
3030
},
31+
"attiny167": {
32+
"cpu": "attiny167",
33+
},
3134
}
3235

3336
COMMON = {

mcu/attiny-hal/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ device-selected = []
1010
attiny84 = ["avr-device/attiny84", "device-selected"]
1111
attiny85 = ["avr-device/attiny85", "device-selected"]
1212
attiny88 = ["avr-device/attiny88", "device-selected"]
13+
attiny167 = ["avr-device/attiny167", "device-selected"]
1314

1415
# Allow certain downstream crates to overwrite the device selection error by themselves.
1516
disable-device-selection-error = []

mcu/attiny-hal/src/adc.rs

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
//! Analog-to-Digital Converter
2+
3+
use crate::port;
4+
pub use avr_hal_generic::adc::{AdcChannel, AdcOps, ClockDivider};
5+
6+
/// Select the voltage reference for the ADC peripheral
7+
///
8+
/// The internal voltage reference options may not be used if an external reference voltage is
9+
/// being applied to the AREF pin.
10+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11+
#[repr(u8)]
12+
pub enum ReferenceVoltage {
13+
/// Voltage applied to AREF pin.
14+
#[cfg(any(
15+
feature = "attiny85",
16+
feature = "attiny167",
17+
))]
18+
Aref,
19+
/// Default reference voltage (default).
20+
AVcc,
21+
/// Internal 1.1V reference.
22+
Internal1_1,
23+
/// Internal 2.56V reference.
24+
#[cfg(any(
25+
feature = "attiny85",
26+
feature = "attiny167",
27+
))]
28+
Internal2_56,
29+
}
30+
31+
impl Default for ReferenceVoltage {
32+
fn default() -> Self {
33+
Self::AVcc
34+
}
35+
}
36+
37+
/// Configuration for the ADC peripheral.
38+
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
39+
pub struct AdcSettings {
40+
pub clock_divider: ClockDivider,
41+
pub ref_voltage: ReferenceVoltage,
42+
}
43+
44+
/// Check the [`avr_hal_generic::adc::Adc`] documentation.
45+
pub type Adc<CLOCK> = avr_hal_generic::adc::Adc<crate::Attiny, crate::pac::ADC, CLOCK>;
46+
47+
/// Check the [`avr_hal_generic::adc::Channel`] documentation.
48+
pub type Channel = avr_hal_generic::adc::Channel<crate::Attiny, crate::pac::ADC>;
49+
50+
/// Additional channels
51+
///
52+
/// Some channels are not directly connected to pins. This module provides types which can be used
53+
/// to access them.
54+
///
55+
/// # Example
56+
/// ```
57+
/// let dp = atmega_hal::Peripherals::take().unwrap();
58+
/// let mut adc = atmega_hal::Adc::new(dp.ADC, Default::default());
59+
///
60+
/// let value = adc.read_blocking(&channel::Vbg);
61+
/// ```
62+
pub mod channel {
63+
#[cfg(feature = "attiny167")]
64+
pub struct AVcc_4;
65+
pub struct Vbg;
66+
pub struct Gnd;
67+
pub struct Temperature;
68+
}
69+
70+
fn apply_clock(peripheral: &crate::pac::ADC, settings: AdcSettings) {
71+
peripheral.adcsra.write(|w| {
72+
w.aden().set_bit();
73+
match settings.clock_divider {
74+
ClockDivider::Factor2 => w.adps().prescaler_2(),
75+
ClockDivider::Factor4 => w.adps().prescaler_4(),
76+
ClockDivider::Factor8 => w.adps().prescaler_8(),
77+
ClockDivider::Factor16 => w.adps().prescaler_16(),
78+
ClockDivider::Factor32 => w.adps().prescaler_32(),
79+
ClockDivider::Factor64 => w.adps().prescaler_64(),
80+
ClockDivider::Factor128 => w.adps().prescaler_128(),
81+
}
82+
});
83+
}
84+
85+
86+
#[cfg(feature = "attiny85")]
87+
avr_hal_generic::impl_adc! {
88+
hal: crate::Attiny,
89+
peripheral: crate::pac::ADC,
90+
settings: AdcSettings,
91+
apply_settings: |peripheral, settings| {
92+
apply_clock(peripheral, settings);
93+
peripheral.admux.write(|w| match settings.ref_voltage {
94+
ReferenceVoltage::Aref => w.refs().aref(),
95+
ReferenceVoltage::AVcc => w.refs().vcc(),
96+
ReferenceVoltage::Internal1_1 => w.refs().internal().refs2().clear_bit(),
97+
ReferenceVoltage::Internal2_56 => w.refs().internal().refs2().set_bit(),
98+
});
99+
},
100+
channel_id: crate::pac::adc::admux::MUX_A,
101+
set_channel: |peripheral, id| {
102+
peripheral.admux.modify(|_, w| w.mux().variant(id));
103+
},
104+
pins: {
105+
port::PB5: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d),
106+
port::PB2: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d),
107+
port::PB4: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d),
108+
port::PB3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d),
109+
},
110+
channels: {
111+
channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG,
112+
channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND,
113+
channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS,
114+
},
115+
}
116+
117+
118+
#[cfg(feature = "attiny88")]
119+
avr_hal_generic::impl_adc! {
120+
hal: crate::Attiny,
121+
peripheral: crate::pac::ADC,
122+
settings: AdcSettings,
123+
apply_settings: |peripheral, settings| {
124+
apply_clock(peripheral, settings);
125+
peripheral.admux.write(|w| match settings.ref_voltage {
126+
ReferenceVoltage::AVcc => w.refs0().avcc(),
127+
ReferenceVoltage::Internal1_1 => w.refs0().internal(),
128+
});
129+
},
130+
channel_id: crate::pac::adc::admux::MUX_A,
131+
set_channel: |peripheral, id| {
132+
peripheral.admux.modify(|_, w| w.mux().variant(id));
133+
},
134+
pins: {
135+
port::PC0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d),
136+
port::PC1: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d),
137+
port::PC2: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d),
138+
port::PC3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d),
139+
port::PC4: (crate::pac::adc::admux::MUX_A::ADC4, didr0::adc4d),
140+
port::PC5: (crate::pac::adc::admux::MUX_A::ADC5, didr0::adc5d),
141+
port::PA0: (crate::pac::adc::admux::MUX_A::ADC6, didr0::adc6d),
142+
port::PA1: (crate::pac::adc::admux::MUX_A::ADC7, didr0::adc7d),
143+
},
144+
channels: {
145+
channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG,
146+
channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND,
147+
channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS,
148+
},
149+
}
150+
151+
152+
#[cfg(feature = "attiny167")]
153+
avr_hal_generic::impl_adc! {
154+
hal: crate::Attiny,
155+
peripheral: crate::pac::ADC,
156+
settings: AdcSettings,
157+
apply_settings: |peripheral, settings| {
158+
apply_clock(peripheral, settings);
159+
peripheral.amiscr.write(|w| match settings.ref_voltage {
160+
ReferenceVoltage::Aref => w.arefen().set_bit(),
161+
_ => w.arefen().clear_bit(),
162+
});
163+
peripheral.admux.write(|w| match settings.ref_voltage {
164+
ReferenceVoltage::Aref => w.refs().avcc(),
165+
ReferenceVoltage::AVcc => w.refs().avcc(),
166+
ReferenceVoltage::Internal1_1 => w.refs().internal_11(),
167+
ReferenceVoltage::Internal2_56 => w.refs().internal_256(),
168+
});
169+
},
170+
channel_id: crate::pac::adc::admux::MUX_A,
171+
set_channel: |peripheral, id| {
172+
peripheral.admux.modify(|_, w| w.mux().variant(id));
173+
},
174+
pins: {
175+
port::PA0: (crate::pac::adc::admux::MUX_A::ADC0, didr0::adc0d),
176+
port::PA1: (crate::pac::adc::admux::MUX_A::ADC1, didr0::adc1d),
177+
port::PA2: (crate::pac::adc::admux::MUX_A::ADC2, didr0::adc2d),
178+
port::PA3: (crate::pac::adc::admux::MUX_A::ADC3, didr0::adc3d),
179+
port::PA4: (crate::pac::adc::admux::MUX_A::ADC4, didr0::adc4d),
180+
port::PA5: (crate::pac::adc::admux::MUX_A::ADC5, didr0::adc5d),
181+
port::PA6: (crate::pac::adc::admux::MUX_A::ADC6, didr0::adc6d),
182+
port::PA7: (crate::pac::adc::admux::MUX_A::ADC7, didr0::adc7d),
183+
port::PB5: (crate::pac::adc::admux::MUX_A::ADC8, didr1::adc8d),
184+
port::PB6: (crate::pac::adc::admux::MUX_A::ADC9, didr1::adc9d),
185+
port::PB7: (crate::pac::adc::admux::MUX_A::ADC10, didr1::adc10d),
186+
},
187+
channels: {
188+
channel::AVcc_4: crate::pac::adc::admux::MUX_A::ADC_AVCC_4,
189+
channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG,
190+
channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND,
191+
channel::Temperature: crate::pac::adc::admux::MUX_A::TEMPSENS,
192+
},
193+
}

mcu/attiny-hal/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//! **Note**: This version of the documentation was built for
88
#![cfg_attr(feature = "attiny85", doc = "**ATtiny85**.")]
99
#![cfg_attr(feature = "attiny88", doc = "**ATtiny88**.")]
10+
#![cfg_attr(feature = "attiny167", doc = "**ATtiny167**.")]
1011
//! This means that only items which are available for this MCU are visible. If you are using
1112
//! a different chip, try building the documentation locally with:
1213
//!
@@ -25,6 +26,7 @@ compile_error!(
2526
2627
* attiny85
2728
* attiny88
29+
* attiny167
2830
"
2931
);
3032

@@ -39,6 +41,10 @@ pub use avr_device::attiny85 as pac;
3941
#[cfg(feature = "attiny88")]
4042
pub use avr_device::attiny88 as pac;
4143

44+
/// Reexport of `attiny167` from `avr-device`
45+
#[cfg(feature = "attiny167")]
46+
pub use avr_device::attiny167 as pac;
47+
4248
/// See [`avr_device::entry`](https://docs.rs/avr-device/latest/avr_device/attr.entry.html).
4349
#[cfg(feature = "rt")]
4450
pub use avr_device::entry;
@@ -49,6 +55,11 @@ pub use pac::Peripherals;
4955
pub use avr_hal_generic::clock;
5056
pub use avr_hal_generic::delay;
5157

58+
#[cfg(feature = "device-selected")]
59+
pub mod adc;
60+
#[cfg(feature = "device-selected")]
61+
pub use adc::Adc;
62+
5263
#[cfg(feature = "device-selected")]
5364
pub mod port;
5465
#[cfg(feature = "device-selected")]
@@ -80,3 +91,10 @@ macro_rules! pins {
8091
$crate::Pins::new($p.PORTA, $p.PORTB, $p.PORTC, $p.PORTD)
8192
};
8293
}
94+
#[cfg(feature = "attiny167")]
95+
#[macro_export]
96+
macro_rules! pins {
97+
($p:expr) => {
98+
$crate::Pins::new($p.PORTA, $p.PORTB)
99+
};
100+
}

mcu/attiny-hal/src/port.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
#[cfg(feature = "attiny167")]
2+
avr_hal_generic::impl_port_traditional! {
3+
enum Ports {
4+
PORTA: (crate::pac::PORTA, porta, pina, ddra),
5+
PORTB: (crate::pac::PORTB, portb, pinb, ddrb),
6+
}
7+
8+
pub struct Pins {
9+
pa0: PA0 = (crate::pac::PORTA, PORTA, 0, porta, pina, ddra),
10+
pa1: PA1 = (crate::pac::PORTA, PORTA, 1, porta, pina, ddra),
11+
pa2: PA2 = (crate::pac::PORTA, PORTA, 2, porta, pina, ddra),
12+
pa3: PA3 = (crate::pac::PORTA, PORTA, 3, porta, pina, ddra),
13+
pa4: PA4 = (crate::pac::PORTA, PORTA, 4, porta, pina, ddra),
14+
pa5: PA5 = (crate::pac::PORTA, PORTA, 5, porta, pina, ddra),
15+
pa6: PA6 = (crate::pac::PORTA, PORTA, 6, porta, pina, ddra),
16+
pa7: PA7 = (crate::pac::PORTA, PORTA, 7, porta, pina, ddra),
17+
pb0: PB0 = (crate::pac::PORTB, PORTB, 0, portb, pinb, ddrb),
18+
pb1: PB1 = (crate::pac::PORTB, PORTB, 1, portb, pinb, ddrb),
19+
pb2: PB2 = (crate::pac::PORTB, PORTB, 2, portb, pinb, ddrb),
20+
pb3: PB3 = (crate::pac::PORTB, PORTB, 3, portb, pinb, ddrb),
21+
pb4: PB4 = (crate::pac::PORTB, PORTB, 4, portb, pinb, ddrb),
22+
pb5: PB5 = (crate::pac::PORTB, PORTB, 5, portb, pinb, ddrb),
23+
pb6: PB6 = (crate::pac::PORTB, PORTB, 6, portb, pinb, ddrb),
24+
pb7: PB7 = (crate::pac::PORTB, PORTB, 7, portb, pinb, ddrb),
25+
}
26+
}
27+
128
#[cfg(feature = "attiny84")]
229
avr_hal_generic::impl_port_traditional! {
330
enum Ports {

mcu/attiny-hal/src/spi.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,22 @@ avr_hal_generic::impl_spi! {
2020
miso: port::PB4,
2121
cs: port::PB2,
2222
}
23+
24+
#[cfg(feature = "attiny167")]
25+
pub type Spi = avr_hal_generic::spi::Spi<
26+
crate::Atmega,
27+
crate::pac::SPI,
28+
port::PA5,
29+
port::PA4,
30+
port::PA2,
31+
port::PA6,
32+
>;
33+
#[cfg(feature = "attiny167")]
34+
avr_hal_generic::impl_spi! {
35+
hal: crate::Atmega,
36+
peripheral: crate::pac::SPI,
37+
sclk: port::PA5,
38+
mosi: port::PA4,
39+
miso: port::PA2,
40+
cs: port::PA6,
41+
}

0 commit comments

Comments
 (0)