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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions avr-hal-generic/src/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ impl Clock for MHz12 {
const FREQ: u32 = 12_000_000;
}

/// 10 MHz Clock
#[derive(ufmt::derive::uDebug, Debug)]
pub struct MHz10;
impl Clock for MHz10 {
const FREQ: u32 = 10_000_000;
}

/// 8 MHz Clock
#[derive(ufmt::derive::uDebug, Debug)]
pub struct MHz8;
Expand Down
17 changes: 17 additions & 0 deletions avr-hal-generic/src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,23 @@ impl delay_v0::DelayUs<u16> for Delay<crate::clock::MHz12> {
}
}

impl delay_v0::DelayUs<u16> for Delay<crate::clock::MHz10> {
fn delay_us(&mut self, mut us: u16) {
// for the 10 crate::clock::MHz clock if somebody is working with USB

// for a 1 microsecond delay, simply return. the overhead
// of the function call takes 14 (16) cycles, which is 1.5us
if us <= 1 {
return;
} // = 3 cycles, (4 when true)

// 4 cycles per busy_loop iteration = 0.4 us per busy loop, so 2.5 times to get 1 us
us = ((us << 2) + us) >> 1; // x2.5

busy_loop(us);
}
}

impl delay_v0::DelayUs<u16> for Delay<crate::clock::MHz8> {
fn delay_us(&mut self, mut us: u16) {
// for the 8 crate::clock::MHz internal clock
Expand Down
28 changes: 8 additions & 20 deletions avr-hal-generic/src/eeprom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ where
#[inline]
pub fn erase_byte(&mut self, offset: u16) {
assert!(offset < Self::CAPACITY);
self.p.raw_erase_byte(offset)
// Write 0xff here because the erase function is borked.
// See also: https://github.com/Rahix/avr-hal/issues/406
self.p.raw_write_byte(offset, 0xff)
}

pub fn read(&self, offset: u16, buf: &mut [u8]) -> Result<(), OutOfBoundsError> {
Expand Down Expand Up @@ -179,26 +181,12 @@ macro_rules! impl_eeprom_common {

// Check if any bits are changed to '1' in the new value.
if (diff_mask & data) != 0 {
// Now we know that _some_ bits need to be erased to '1'.

// Check if any bits in the new value are '0'.
if data != 0xff {
// Now we know that some bits need to be programmed to '0' also.
self.eedr.write(|w| w.bits(data)); // Set EEPROM data register.

{
let $periph_ewmode_var = &self;
$set_erasewrite_mode
}
self.eecr.write(|w| w.eepe().set_bit()); // Start Erase+Write operation.
} else {
// Now we know that all bits should be erased.
{
let $periph_emode_var = &self;
$set_erase_mode
}
self.eecr.write(|w| w.eepe().set_bit()); // Start Erase-only operation.
self.eedr.write(|w| w.bits(data)); // Set EEPROM data register.
{
let $periph_ewmode_var = &self;
$set_erasewrite_mode
}
self.eecr.write(|w| w.eepe().set_bit()); // Start Erase+Write operation.
}
//Now we know that _no_ bits need to be erased to '1'.
else {
Expand Down
25 changes: 25 additions & 0 deletions avr-specs/avr-atmega164pa.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"arch": "avr",
"atomic-cas": false,
"cpu": "atmega164pa",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"eh-frame-header": false,
"exe-suffix": ".elf",
"late-link-args": {
"gcc": [
"-lgcc"
]
},
"linker": "avr-gcc",
"llvm-target": "avr-unknown-unknown",
"max-atomic-width": 8,
"no-default-libraries": false,
"pre-link-args": {
"gcc": [
"-mmcu=atmega164pa"
]
},
"relocation-model": "static",
"target-c-int-width": "16",
"target-pointer-width": "16"
}
3 changes: 3 additions & 0 deletions avr-specs/sync-from-upstream.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
"atmega48p": {
"cpu": "atmega48p",
},
"atmega164pa": {
"cpu": "atmega164pa",
},
"atmega168": {
"cpu": "atmega168",
},
Expand Down
1 change: 1 addition & 0 deletions mcu/atmega-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ rt = ["avr-device/rt"]
device-selected = []
enable-extra-adc = []
atmega48p = ["avr-device/atmega48p", "device-selected"]
atmega164pa = ["avr-device/atmega164pa", "device-selected"]
atmega168 = ["avr-device/atmega168", "device-selected"]
atmega328p = ["avr-device/atmega328p", "device-selected"]
atmega328pb = ["avr-device/atmega328pb", "device-selected"]
Expand Down
28 changes: 28 additions & 0 deletions mcu/atmega-hal/src/adc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pub mod channel {
feature = "atmega128a",
feature = "atmega1284p",
feature = "atmega8",
feature = "atmega164pa",
))]
pub struct Vbg;
#[cfg(any(
Expand All @@ -124,6 +125,7 @@ pub mod channel {
feature = "atmega128a",
feature = "atmega1284p",
feature = "atmega8",
feature = "atmega164pa",
))]
pub struct Gnd;
#[cfg(any(
Expand Down Expand Up @@ -345,3 +347,29 @@ avr_hal_generic::impl_adc! {
channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND,
},
}

#[cfg(any(feature = "atmega164pa"))]
avr_hal_generic::impl_adc! {
hal: crate::Atmega,
peripheral: crate::pac::ADC,
settings: AdcSettings,
apply_settings: |peripheral, settings| { apply_settings(peripheral, settings) },
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),
},
channels: {
channel::Vbg: crate::pac::adc::admux::MUX_A::ADC_VBG,
channel::Gnd: crate::pac::adc::admux::MUX_A::ADC_GND,
},
}
2 changes: 1 addition & 1 deletion mcu/atmega-hal/src/eeprom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ avr_hal_generic::impl_eeprom_atmega! {
},
}

#[cfg(feature = "atmega168")]
#[cfg(any(feature = "atmega168", feature = "atmega164pa"))]
avr_hal_generic::impl_eeprom_atmega! {
hal: crate::Atmega,
peripheral: crate::pac::EEPROM,
Expand Down
16 changes: 16 additions & 0 deletions mcu/atmega-hal/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,22 @@ avr_hal_generic::impl_i2c_twi! {
scl: port::PD0,
}

#[cfg(any(feature = "atmega164pa"))]
pub type I2c<CLOCK> = avr_hal_generic::i2c::I2c<
crate::Atmega,
crate::pac::TWI,
port::Pin<port::mode::Input, port::PC1>,
port::Pin<port::mode::Input, port::PC0>,
CLOCK,
>;
#[cfg(any(feature = "atmega164pa"))]
avr_hal_generic::impl_i2c_twi! {
hal: crate::Atmega,
peripheral: crate::pac::TWI,
sda: port::PC1,
scl: port::PC0,
}

#[cfg(any(feature = "atmega328p", feature = "atmega168", feature = "atmega48p", feature = "atmega8"))]
pub type I2c<CLOCK> = avr_hal_generic::i2c::I2c<
crate::Atmega,
Expand Down
12 changes: 12 additions & 0 deletions mcu/atmega-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//!
//! **Note**: This version of the documentation was built for
#![cfg_attr(feature = "atmega48p", doc = "**ATmega48P**.")]
#![cfg_attr(feature = "atmega164pa", doc = "**ATmega164PA**.")]
#![cfg_attr(feature = "atmega168", doc = "**ATmega168**.")]
#![cfg_attr(feature = "atmega328p", doc = "**ATmega328P**.")]
#![cfg_attr(feature = "atmega328pb", doc = "**ATmega328PB**.")]
Expand Down Expand Up @@ -33,6 +34,7 @@ compile_error!(
Please select one of the following

* atmega48p
* atmega164pa
* atmega168
* atmega328p
* atmega328pb
Expand All @@ -48,6 +50,9 @@ compile_error!(
/// Reexport of `atmega1280` from `avr-device`
#[cfg(feature = "atmega1280")]
pub use avr_device::atmega1280 as pac;
/// Reexport of `atmega164pa` from `avr-device`
#[cfg(feature = "atmega164pa")]
pub use avr_device::atmega164pa as pac;
/// Reexport of `atmega168` from `avr-device`
#[cfg(feature = "atmega168")]
pub use avr_device::atmega168 as pac;
Expand Down Expand Up @@ -138,6 +143,13 @@ macro_rules! pins {
$crate::Pins::new($p.PORTB, $p.PORTC, $p.PORTD)
};
}
#[cfg(any(feature = "atmega164pa"))]
#[macro_export]
macro_rules! pins {
($p:expr) => {
$crate::Pins::new($p.PORTA, $p.PORTB, $p.PORTC, $p.PORTD)
};
}
#[cfg(feature = "atmega328pb")]
#[macro_export]
macro_rules! pins {
Expand Down
10 changes: 10 additions & 0 deletions mcu/atmega-hal/src/port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ avr_hal_generic::impl_port_traditional! {
}
}

#[cfg(any(feature = "atmega164pa"))]
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],
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 = "atmega328pb")]
avr_hal_generic::impl_port_traditional! {
enum Ports {
Expand Down
93 changes: 92 additions & 1 deletion mcu/atmega-hal/src/simple_pwm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use avr_hal_generic::simple_pwm::{PwmPinOps, Prescaler};
pub use avr_hal_generic::simple_pwm::{IntoPwmPin, PwmPinOps, Prescaler};

#[allow(unused_imports)]
use crate::port::*;
Expand Down Expand Up @@ -1088,3 +1088,94 @@ avr_hal_generic::impl_simple_pwm! {
},
}
}

#[cfg(any(feature = "atmega164pa"))]
avr_hal_generic::impl_simple_pwm! {
/// Use `TC0` for PWM (pins `PB3`)
///
/// # Example
/// ```
/// let mut timer0 = Timer0Pwm::new(dp.TC0, Prescaler::Prescale64);
///
/// let mut b3 = pins.pb3.into_output().into_pwm(&mut timer0);
///
/// b3.set_duty(128);
/// b3.enable();
/// ```
pub struct Timer0Pwm {
timer: crate::pac::TC0,
init: |tim, prescaler| {
tim.tccr0a.modify(|_r, w| w.wgm0().bits(0b11));
tim.tccr0a.modify(|_r, w| w.com0a().bits(0b00));

tim.tccr0b.modify(|_r, w| match prescaler {
Prescaler::Direct => w.cs0().running_no_prescaling(),
Prescaler::Prescale8 => w.cs0().running_clk_8(),
Prescaler::Prescale64 => w.cs0().running_clk_64(),
Prescaler::Prescale256 => w.cs0().running_clk_256(),
Prescaler::Prescale1024 => w.cs0().running_clk_1024(),
});
},
pins: {
PB3: {
ocr: ocr0a,
into_pwm: |tim| if enable {
tim.tccr0a.modify(|_r, w| w.com0a().bits(0b11));
} else {
tim.tccr0a.modify(|_r, w| w.com0a().bits(0b00));
},
},
},
}
}

#[cfg(any(feature = "atmega164pa"))]
avr_hal_generic::impl_simple_pwm! {
/// Use `TC1` for PWM (pins `PD4`, `PD5`)
///
/// # Example
/// ```
/// let mut timer1 = Timer1Pwm::new(dp.TC1, Prescaler::Prescale64);
///
/// let mut d4 = pins.pd4.into_output().into_pwm(&mut timer1);
/// let mut d5 = pins.pd5.into_output().into_pwm(&mut timer1);
///
/// d4.set_duty(128);
/// d4.enable();
/// d5.set_duty(64);
/// d5.enable();
/// ```
pub struct Timer1Pwm {
timer: crate::pac::TC1,
init: |tim, prescaler| {
tim.tccr1a.modify(|_r, w| w.wgm1().bits(0b01));
tim.tccr1a.modify(|_r, w| w.com1a().bits(0b00));
tim.tccr1a.modify(|_r, w| w.com1b().bits(0b00));
tim.tccr1b.modify(|_r, w| match prescaler {
Prescaler::Direct => w.cs1().running_no_prescaling(),
Prescaler::Prescale8 => w.cs1().running_clk_8(),
Prescaler::Prescale64 => w.cs1().running_clk_64(),
Prescaler::Prescale256 => w.cs1().running_clk_256(),
Prescaler::Prescale1024 => w.cs1().running_clk_1024(),
});
},
pins: {
PD4: {
ocr: ocr1a,
into_pwm: |tim| if enable {
tim.tccr1a.modify(|_r, w| w.com1a().bits(0b11));
} else {
tim.tccr1a.modify(|_r, w| w.com1a().bits(0b00));
},
},
PD5: {
ocr: ocr1b,
into_pwm: |tim| if enable {
tim.tccr1a.modify(|_r, w| w.com1b().bits(0b11));
} else {
tim.tccr1a.modify(|_r, w| w.com1b().bits(0b00));
},
},
},
}
}
8 changes: 4 additions & 4 deletions mcu/atmega-hal/src/usart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ pub type UsartWriter<USART, RX, TX, CLOCK> =
pub type UsartReader<USART, RX, TX, CLOCK> =
avr_hal_generic::usart::UsartReader<crate::Atmega, USART, RX, TX, CLOCK>;

#[cfg(any(feature = "atmega168", feature = "atmega328p", feature = "atmega328pb", feature = "atmega1284p"))]
#[cfg(any(feature = "atmega168", feature = "atmega328p", feature = "atmega328pb", feature = "atmega1284p", feature = "atmega164pa"))]
pub type Usart0<CLOCK> = Usart<
crate::pac::USART0,
port::Pin<port::mode::Input, port::PD0>,
port::Pin<port::mode::Output, port::PD1>,
CLOCK,
>;
#[cfg(any(feature = "atmega168", feature = "atmega328p", feature = "atmega328pb", feature = "atmega1284p"))]
#[cfg(any(feature = "atmega168", feature = "atmega328p", feature = "atmega328pb", feature = "atmega1284p", feature = "atmega164pa"))]
avr_hal_generic::impl_usart_traditional! {
hal: crate::Atmega,
peripheral: crate::pac::USART0,
Expand All @@ -41,14 +41,14 @@ avr_hal_generic::impl_usart_traditional! {
tx: port::PB3,
}

#[cfg(any(feature = "atmega32u4",feature = "atmega128a", feature = "atmega1280", feature = "atmega2560", feature = "atmega1284p"))]
#[cfg(any(feature = "atmega32u4",feature = "atmega128a", feature = "atmega1280", feature = "atmega2560", feature = "atmega1284p", feature = "atmega164pa"))]
pub type Usart1<CLOCK> = Usart<
crate::pac::USART1,
port::Pin<port::mode::Input, port::PD2>,
port::Pin<port::mode::Output, port::PD3>,
CLOCK,
>;
#[cfg(any(feature = "atmega32u4", feature = "atmega1280", feature = "atmega2560", feature = "atmega1284p"))]
#[cfg(any(feature = "atmega32u4", feature = "atmega1280", feature = "atmega2560", feature = "atmega1284p", feature = "atmega164pa"))]
avr_hal_generic::impl_usart_traditional! {
hal: crate::Atmega,
peripheral: crate::pac::USART1,
Expand Down