Do more work
This commit is contained in:
parent
190a3ec8f1
commit
906b548dfa
|
@ -0,0 +1,8 @@
|
||||||
|
[dependencies.std]
|
||||||
|
features = ["panic_unwind"]
|
||||||
|
|
||||||
|
[dependencies.test]
|
||||||
|
stage = 1
|
||||||
|
|
||||||
|
[target.avr-atmega328p.dependencies]
|
||||||
|
core = { git = "https://github.com/avr-rust/libcore", branch = "rust-26015da0" }
|
47
build.rs
47
build.rs
|
@ -6,8 +6,12 @@ use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
fn src_path() -> PathBuf {
|
||||||
|
Path::new(env!("CARGO_MANIFEST_DIR")).join("src")
|
||||||
|
}
|
||||||
|
|
||||||
fn cores_path() -> PathBuf {
|
fn cores_path() -> PathBuf {
|
||||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("src").join("cores")
|
src_path().join("cores")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn core_module_name(mcu: &Mcu) -> String {
|
fn core_module_name(mcu: &Mcu) -> String {
|
||||||
|
@ -21,7 +25,8 @@ fn main() {
|
||||||
|
|
||||||
let current_mcu = avr_mcu::current::mcu()
|
let current_mcu = avr_mcu::current::mcu()
|
||||||
.expect("no target cpu specified");
|
.expect("no target cpu specified");
|
||||||
generate_cores(&[current_mcu]).unwrap()
|
generate_config_module().unwrap();
|
||||||
|
generate_cores(&[current_mcu]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> {
|
fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> {
|
||||||
|
@ -31,6 +36,15 @@ fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> {
|
||||||
generate_cores_mod_rs(mcus)
|
generate_cores_mod_rs(mcus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_config_module() -> Result<(), io::Error> {
|
||||||
|
let path = src_path().join("config.rs");
|
||||||
|
let mut f = File::create(&path)?;
|
||||||
|
|
||||||
|
let clock = env!("AVR_CPU_FREQUENCY");
|
||||||
|
writeln!(f, "pub const CPU_FREQUENCY: u32 = {};", clock)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
fn generate_core_module(mcu: &Mcu) -> Result<(), io::Error> {
|
||||||
let path = cores_path().join(format!("{}.rs", core_module_name(mcu)));
|
let path = cores_path().join(format!("{}.rs", core_module_name(mcu)));
|
||||||
let mut file = File::create(&path)?;
|
let mut file = File::create(&path)?;
|
||||||
|
@ -57,7 +71,7 @@ fn generate_cores_mod_rs(mcus: &[Mcu]) -> Result<(), io::Error> {
|
||||||
fn write_core_module(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> {
|
fn write_core_module(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> {
|
||||||
writeln!(w, "//! Core for {}.", mcu.device.name)?;
|
writeln!(w, "//! Core for {}.", mcu.device.name)?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
writeln!(w, "use {{HardwareUsart, Register}};")?;
|
writeln!(w, "use {{Mask, Bitset, HardwareUsart, Register}};")?;
|
||||||
writeln!(w, "use spi::HardwareSpi;")?;
|
writeln!(w, "use spi::HardwareSpi;")?;
|
||||||
writeln!(w)?;
|
writeln!(w)?;
|
||||||
|
|
||||||
|
@ -82,6 +96,33 @@ mod gen {
|
||||||
if register.name == "GTCCR" { continue; }
|
if register.name == "GTCCR" { continue; }
|
||||||
|
|
||||||
writeln!(w, "pub struct {};", register.name)?;
|
writeln!(w, "pub struct {};", register.name)?;
|
||||||
|
writeln!(w)?;
|
||||||
|
|
||||||
|
writeln!(w, "impl {} {{", register.name)?;
|
||||||
|
for bitfield in register.bitfields.iter() {
|
||||||
|
// Create a mask for the whole bitset.
|
||||||
|
writeln!(w, " pub const {}: Bitset<{}, Self> = Bitset::new(0x{:x});", bitfield.name, ty, bitfield.mask)?;
|
||||||
|
|
||||||
|
// We create masks for the individual bits in the field if there
|
||||||
|
// is more than one bit in the field.
|
||||||
|
if bitfield.mask.count_ones() > 1 {
|
||||||
|
let mut current_mask = bitfield.mask;
|
||||||
|
let mut current_mask_bit_num = 0;
|
||||||
|
for current_register_bit_num in 0..15 {
|
||||||
|
if (current_mask & 0b1) == 0b1 {
|
||||||
|
writeln!(w, " pub const {}{}: Mask<{}, Self> = Mask::new(1<<{});",
|
||||||
|
bitfield.name, current_mask_bit_num, ty, current_register_bit_num)?;
|
||||||
|
current_mask_bit_num += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_mask >>= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(w)?;
|
||||||
|
}
|
||||||
|
writeln!(w, "}}")?;
|
||||||
|
writeln!(w)?;
|
||||||
|
|
||||||
writeln!(w, "impl Register<{}> for {} {{", ty, register.name)?;
|
writeln!(w, "impl Register<{}> for {} {{", ty, register.name)?;
|
||||||
writeln!(w, " const ADDR: *mut {} = 0x{:x} as *mut {};", ty, register.offset, ty)?;
|
writeln!(w, " const ADDR: *mut {} = 0x{:x} as *mut {};", ty, register.offset, ty)?;
|
||||||
writeln!(w, "}}")?;
|
writeln!(w, "}}")?;
|
||||||
|
|
1
build.sh
1
build.sh
|
@ -1,2 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
export AVR_CPU_FREQUENCY=16000000
|
||||||
xargo build --target avr-atmega328p $@
|
xargo build --target avr-atmega328p $@
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
extern crate arduino;
|
||||||
|
use arduino::cores::current;
|
||||||
|
|
||||||
|
// Some devices may have multiple SPI modules.
|
||||||
|
// The ATmega328p only has one.
|
||||||
|
type Spi = current::Spi;
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn main() {
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Generated automatically.
|
||||||
|
config.rs
|
|
@ -4,6 +4,8 @@
|
||||||
#![feature(no_core)]
|
#![feature(no_core)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(associated_consts)]
|
#![feature(associated_consts)]
|
||||||
|
#![feature(associated_type_defaults)]
|
||||||
|
#![feature(const_fn)]
|
||||||
#![feature(lang_items)]
|
#![feature(lang_items)]
|
||||||
#![feature(unwind_attributes)]
|
#![feature(unwind_attributes)]
|
||||||
|
|
||||||
|
@ -11,7 +13,7 @@
|
||||||
|
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub use self::register::{Register, RegisterValue};
|
pub use self::register::{Bitset, Mask, Register, RegisterValue};
|
||||||
pub use self::pin::Pin;
|
pub use self::pin::Pin;
|
||||||
pub use self::usart::HardwareUsart;
|
pub use self::usart::HardwareUsart;
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ pub mod timer1;
|
||||||
pub mod cores;
|
pub mod cores;
|
||||||
|
|
||||||
pub mod spi;
|
pub mod spi;
|
||||||
|
pub mod config;
|
||||||
|
|
||||||
mod register;
|
mod register;
|
||||||
mod pin;
|
mod pin;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use core::{cmp, convert, ops};
|
use core::{cmp, convert, marker, ops};
|
||||||
|
|
||||||
pub trait RegisterValue : Copy + Clone +
|
pub trait RegisterValue : Copy + Clone +
|
||||||
ops::BitAnd<Output=Self> +
|
ops::BitAnd<Output=Self> +
|
||||||
|
@ -14,7 +14,9 @@ pub trait RegisterValue : Copy + Clone +
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A register.
|
/// A register.
|
||||||
pub trait Register<T: RegisterValue> {
|
pub trait Register<T: RegisterValue> : Sized {
|
||||||
|
type Mask = Mask<T, Self>;
|
||||||
|
|
||||||
/// The address of the register.
|
/// The address of the register.
|
||||||
const ADDR: *mut T;
|
const ADDR: *mut T;
|
||||||
|
|
||||||
|
@ -33,6 +35,8 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets a bitmask in a register.
|
/// Sets a bitmask in a register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r |= mask`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn set(mask: T) {
|
fn set(mask: T) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -41,6 +45,8 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clears a bitmask from a register.
|
/// Clears a bitmask from a register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r &= !mask`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn unset(mask: T) {
|
fn unset(mask: T) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -49,6 +55,8 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggles a mask in the register.
|
/// Toggles a mask in the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r ^= mask`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn toggle(mask: T) {
|
fn toggle(mask: T) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -57,6 +65,8 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a mask is set in the register.
|
/// Checks if a mask is set in the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `(r & mask) == mask`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_set(mask: T) -> bool {
|
fn is_set(mask: T) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -65,6 +75,8 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a mask is clear in the register.
|
/// Checks if a mask is clear in the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `(r & mask) == 0`.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn is_clear(mask: T) -> bool {
|
fn is_clear(mask: T) -> bool {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -90,6 +102,64 @@ pub trait Register<T: RegisterValue> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A register bitmask.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Bitset<T: RegisterValue, R: Register<T>> {
|
||||||
|
mask: T,
|
||||||
|
_phantom: marker::PhantomData<R>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A register bitmask.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct Mask<T: RegisterValue, R: Register<T>> {
|
||||||
|
mask: T,
|
||||||
|
_phantom: marker::PhantomData<R>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T,R> Bitset<T,R>
|
||||||
|
where T: RegisterValue, R: Register<T> {
|
||||||
|
/// Creates a new register mask.
|
||||||
|
pub const fn new(mask: T) -> Self {
|
||||||
|
Bitset { mask, _phantom: marker::PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the mask in the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r |= mask`.
|
||||||
|
pub fn set_all(self) {
|
||||||
|
R::set(self.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the mask from the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r &= !mask`.
|
||||||
|
pub fn unset_all(self) {
|
||||||
|
R::unset(self.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Toggles the masked bits in the register.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `r ^= mask`.
|
||||||
|
pub fn toggle_all(self) {
|
||||||
|
R::toggle(self.mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if the mask is clear.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `(r & mask) == 0`.
|
||||||
|
pub fn is_clear(self) -> bool {
|
||||||
|
R::is_clear(self.mask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T,R> Mask<T,R>
|
||||||
|
where T: RegisterValue, R: Register<T> {
|
||||||
|
/// Creates a new register mask.
|
||||||
|
pub const fn new(mask: T) -> Self {
|
||||||
|
Mask { mask, _phantom: marker::PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RegisterValue for u8 { }
|
impl RegisterValue for u8 { }
|
||||||
impl RegisterValue for u16 { }
|
impl RegisterValue for u16 { }
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
use config;
|
||||||
|
|
||||||
|
/// A clock mask.
|
||||||
|
///
|
||||||
|
/// The format looks like this
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// 0b00000<1><0><2x>
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Where
|
||||||
|
///
|
||||||
|
/// * `1` is the value of the `SPR1` bit
|
||||||
|
/// * `0` is the value of the `SPR0` bit
|
||||||
|
/// * `2x` indicates if double speed mode is enabled
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct ClockMask(pub u8);
|
||||||
|
|
||||||
|
impl ClockMask {
|
||||||
|
/// Gets the clock mask for a specific baute rate.
|
||||||
|
pub fn with_clock(spi_clock: u32) -> ClockMask {
|
||||||
|
let mut divider_bits = if spi_clock >= config::CPU_FREQUENCY / 2 {
|
||||||
|
0
|
||||||
|
} else if spi_clock >= config::CPU_FREQUENCY / 4 {
|
||||||
|
1
|
||||||
|
} else if spi_clock >= config::CPU_FREQUENCY / 8 {
|
||||||
|
2
|
||||||
|
} else if spi_clock >= config::CPU_FREQUENCY / 16 {
|
||||||
|
3
|
||||||
|
} else if spi_clock >= config::CPU_FREQUENCY / 32 {
|
||||||
|
4
|
||||||
|
} else if spi_clock >= config::CPU_FREQUENCY / 64 {
|
||||||
|
5
|
||||||
|
} else {
|
||||||
|
6
|
||||||
|
};
|
||||||
|
|
||||||
|
// Invert the SPI2X bit
|
||||||
|
divider_bits ^= 0x1;
|
||||||
|
|
||||||
|
// Compensate for the duplicate F_osc/64
|
||||||
|
if divider_bits == 6 {
|
||||||
|
divider_bits = 7;
|
||||||
|
}
|
||||||
|
ClockMask(divider_bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn control_register_mask(self) -> u8 {
|
||||||
|
// SPR1 and SPR0
|
||||||
|
// These both form bits 1 and 0 of the control register.
|
||||||
|
(self.0 & 0b110) >> 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status_register_mask(self) -> u8 {
|
||||||
|
// SPI2x
|
||||||
|
// This forms bit 0 of the status register.
|
||||||
|
self.0 & 0b1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
mod clock;
|
||||||
|
mod settings;
|
||||||
|
|
||||||
use {Register, Pin};
|
use {Register, Pin};
|
||||||
|
|
||||||
/// An SPI module.
|
/// An SPI module.
|
||||||
|
@ -18,7 +21,7 @@ pub trait HardwareSpi {
|
||||||
type DataRegister: Register<u8>;
|
type DataRegister: Register<u8>;
|
||||||
|
|
||||||
/// Sets up the SPI as a master.
|
/// Sets up the SPI as a master.
|
||||||
fn setup_master() {
|
fn setup_master(clock: u32) {
|
||||||
// Setup DDR registers.
|
// Setup DDR registers.
|
||||||
Self::MasterInSlaveOut::set_input();
|
Self::MasterInSlaveOut::set_input();
|
||||||
Self::MasterOutSlaveIn::set_output();
|
Self::MasterOutSlaveIn::set_output();
|
||||||
|
@ -27,11 +30,11 @@ pub trait HardwareSpi {
|
||||||
|
|
||||||
Self::set_master();
|
Self::set_master();
|
||||||
Self::enable_interrupt();
|
Self::enable_interrupt();
|
||||||
Self::enable();
|
Self::setup_common(clock)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets up the SPI as a slave.
|
/// Sets up the SPI as a slave.
|
||||||
fn setup_slave() {
|
fn setup_slave(clock: u32) {
|
||||||
// Setup DDR registers.
|
// Setup DDR registers.
|
||||||
Self::MasterInSlaveOut::set_output();
|
Self::MasterInSlaveOut::set_output();
|
||||||
Self::MasterOutSlaveIn::set_input();
|
Self::MasterOutSlaveIn::set_input();
|
||||||
|
@ -39,7 +42,19 @@ pub trait HardwareSpi {
|
||||||
Self::SlaveSelect::set_input();
|
Self::SlaveSelect::set_input();
|
||||||
|
|
||||||
Self::set_slave();
|
Self::set_slave();
|
||||||
Self::enable();
|
Self::setup_common(clock)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_common(clock: u32) {
|
||||||
|
Self::set_clock(clock);
|
||||||
|
Self::enable()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the clock speed.
|
||||||
|
fn set_clock(clock: u32) {
|
||||||
|
let mask = clock::ClockMask::with_clock(clock);
|
||||||
|
Self::ControlRegister::set(mask.control_register_mask());
|
||||||
|
Self::StatusRegister::set(mask.status_register_mask());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enables interrupts for the spi module.
|
/// Enables interrupts for the spi module.
|
|
@ -0,0 +1,127 @@
|
||||||
|
use super::clock::ClockMask;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum BitOrder {
|
||||||
|
/// The least significant bit is sent first.
|
||||||
|
LeastSignificantBit,
|
||||||
|
/// The most significant bit is sent first.
|
||||||
|
MostSignificantBit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub enum ClockPhase {
|
||||||
|
LeadingEdge,
|
||||||
|
TrailingEdge,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// SPI settings.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Settings {
|
||||||
|
/// Whether the SPI module is enabled.
|
||||||
|
enabled: bool,
|
||||||
|
/// Whether to be configured as a master or slave.
|
||||||
|
master: bool,
|
||||||
|
/// The clock speed.
|
||||||
|
clock: u32,
|
||||||
|
/// The bit ordering.
|
||||||
|
bit_order: BitOrder,
|
||||||
|
/// The clock phase.
|
||||||
|
clock_phase: ClockPhase,
|
||||||
|
/// Whether interrupts should be enabled.
|
||||||
|
enable_interrupts: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Settings {
|
||||||
|
/// Gets the default settings for the master.
|
||||||
|
pub fn master() -> Self {
|
||||||
|
Settings {
|
||||||
|
master: true,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the default settings for the slave.
|
||||||
|
pub fn slave() -> Self {
|
||||||
|
Settings {
|
||||||
|
master: false,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn control_register_bits(self) -> u8 {
|
||||||
|
let mut bits = 0;
|
||||||
|
|
||||||
|
bits |= self.clock().control_register_mask();
|
||||||
|
|
||||||
|
if self.enable_interrupts {
|
||||||
|
bits |= control_register::INTERRUPT_ENABLE
|
||||||
|
}
|
||||||
|
if self.enabled {
|
||||||
|
bits |= control_register::ENABLE
|
||||||
|
}
|
||||||
|
if let ClockPhase::LeadingEdge = self.clock_phase {
|
||||||
|
bits |= control_register::CPHA;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let BitOrder::LeastSignificantBit = self.bit_order {
|
||||||
|
bits |= control_register::DATA_ORDER_LSB;
|
||||||
|
}
|
||||||
|
bits
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn status_register_bits(self) -> u8 {
|
||||||
|
let mut bits = 0;
|
||||||
|
|
||||||
|
bits |= self.clock().status_register_mask();
|
||||||
|
bits
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clock(self) -> ClockMask {
|
||||||
|
ClockMask::with_clock(self.clock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Settings {
|
||||||
|
fn default() -> Settings {
|
||||||
|
Settings {
|
||||||
|
enabled: true,
|
||||||
|
master: true,
|
||||||
|
// same as Arduino default in `SPI.h`.
|
||||||
|
clock: 4_000_000,
|
||||||
|
bit_order: BitOrder::MostSignificantBit,
|
||||||
|
clock_phase: ClockPhase::LeadingEdge,
|
||||||
|
enable_interrupts: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constants for the control register.
|
||||||
|
pub mod control_register {
|
||||||
|
/// Set if interrupts are enabled.
|
||||||
|
pub const INTERRUPT_ENABLE: u8 = 1<<7;
|
||||||
|
/// Set if the SPI module is enabled.
|
||||||
|
pub const ENABLE: u8 = 1<<6;
|
||||||
|
/// Set if data is sent in LSB format.
|
||||||
|
pub const DATA_ORDER_LSB: u8 = 1<<5;
|
||||||
|
/// Set if we are configuring a master.
|
||||||
|
pub const MASTER: u8 = 1<<4;
|
||||||
|
/// Clock polarity.
|
||||||
|
pub const CPOL: u8 = 1<<3;
|
||||||
|
/// Clock phase.
|
||||||
|
pub const CPHA: u8 = 1<<2;
|
||||||
|
/// Clock rate select 1.
|
||||||
|
pub const SPR1: u8 = 1<<1;
|
||||||
|
/// Clock rate select 2.
|
||||||
|
pub const SPR0: u8 = 1<<0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constants for the status register.
|
||||||
|
pub mod status_register {
|
||||||
|
/// SPI interrupt flag.
|
||||||
|
pub const SPIF: u8 = 1<<7;
|
||||||
|
/// Write collision flag.
|
||||||
|
pub const WCOL: u8 = 1<<6;
|
||||||
|
/// SPI double speed mode.
|
||||||
|
pub const SPI2X: u8 = 1<<0;
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ use core::ptr::write_volatile;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use cores::atmega328p as c;
|
||||||
|
|
||||||
pub enum ClockSource {
|
pub enum ClockSource {
|
||||||
None,
|
None,
|
||||||
Prescale1,
|
Prescale1,
|
||||||
|
@ -121,18 +123,18 @@ impl Timer {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn configure(self) {
|
pub fn configure(self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
write_volatile(TCCR0A, self.a);
|
c::TCCR0A::write(self.a);
|
||||||
write_volatile(TCCR0B, self.b);
|
c::TCCR0B::write(self.b);
|
||||||
|
|
||||||
// Reset counter to zero
|
// Reset counter to zero
|
||||||
write_volatile(TCNT0, 0);
|
c::TCNT0::write(0);
|
||||||
|
|
||||||
if let Some(v) = self.output_compare_1 {
|
if let Some(v) = self.output_compare_1 {
|
||||||
// Set the match
|
// Set the match
|
||||||
write_volatile(OCR0A, v);
|
c::OCR0A::write(v);
|
||||||
|
|
||||||
// Enable compare interrupt
|
// Enable compare interrupt
|
||||||
write_volatile(TIMSK0, OCIE0A);
|
c::TIMSK0::OCIE0A.set_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue