From e1a05bbf96185a325cb1f24439fd5b3b8a43e8d1 Mon Sep 17 00:00:00 2001 From: Dylan McKay Date: Thu, 14 Dec 2017 02:53:28 +1300 Subject: [PATCH] Move the build script into a subdir --- Cargo.toml | 4 + build.rs | 325 ---------------------------------------- core_generator/build.rs | 88 +++++++++++ core_generator/gen.rs | 236 +++++++++++++++++++++++++++++ 4 files changed, 328 insertions(+), 325 deletions(-) delete mode 100644 build.rs create mode 100644 core_generator/build.rs create mode 100644 core_generator/gen.rs diff --git a/Cargo.toml b/Cargo.toml index f6d610c..81a3fe4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,12 +6,16 @@ authors = [ "Jake Goulding ", "Dylan McKay ", ] + license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/avr-rust/ruduino" description = """ Reusable components for the Arduino Uno. """ + +build = "core_generator/build.rs" + keywords = ["avr", "arduino", "uno"] [build-dependencies] diff --git a/build.rs b/build.rs deleted file mode 100644 index b735a9f..0000000 --- a/build.rs +++ /dev/null @@ -1,325 +0,0 @@ -extern crate avr_mcu; - -use avr_mcu::*; -use std::fs::{self, File}; -use std::io; -use std::io::prelude::*; -use std::path::{Path, PathBuf}; - -fn src_path() -> PathBuf { - Path::new(env!("CARGO_MANIFEST_DIR")).join("src") -} - -fn cores_path() -> PathBuf { - src_path().join("cores") -} - -fn core_module_name(mcu: &Mcu) -> String { - mcu.device.name.to_lowercase().to_owned() -} - -fn main() { - if !cores_path().exists() { - fs::create_dir_all(&cores_path()).expect("could not create cores directory"); - } - - let current_mcu = avr_mcu::current::mcu() - .expect("no target cpu specified"); - generate_config_module().unwrap(); - generate_cores(&[current_mcu]).unwrap(); -} - -fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> { - for mcu in mcus { - generate_core_module(mcu).expect("failed to generate mcu core"); - } - 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> { - let path = cores_path().join(format!("{}.rs", core_module_name(mcu))); - let mut file = File::create(&path)?; - write_core_module(mcu, &mut file) -} - -fn generate_cores_mod_rs(mcus: &[Mcu]) -> Result<(), io::Error> { - let path = cores_path().join("mod.rs"); - let mut w = File::create(&path)?; - - writeln!(w, "//! Cores")?; - writeln!(w)?; - for mcu in mcus { - let module_name = core_module_name(mcu); - writeln!(w, "/// The {}.", mcu.device.name)?; - writeln!(w, "pub mod {};", module_name)?; - - writeln!(w, "#[cfg(all(target_arch = \"avr\", target_cpu = \"{}\"))]", module_name)?; - writeln!(w, "pub use self::{} as current;", module_name)?; - } - writeln!(w) -} - -fn write_core_module(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - writeln!(w, "//! Core for {}.", mcu.device.name)?; - writeln!(w)?; - writeln!(w, "use {{Mask, Bitset, Register}};")?; - writeln!(w, "use modules;")?; - writeln!(w)?; - - gen::write_registers(mcu, w)?; - gen::write_pins(mcu, w)?; - gen::write_spi_modules(mcu, w)?; - gen::write_usarts(mcu, w)?; - gen::write_timers(mcu, w)?; - - writeln!(w) -} - -mod gen { - use avr_mcu::*; - use std::io; - use std::io::prelude::*; - - pub fn write_registers(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - for register in mcu.registers() { - let ty = if register.size == 1 { "u8" } else { "u16" }; - - // HACK: Skip, atmeg328p pack defines two of these. - if register.name == "GTCCR" { continue; } - - 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 = Bitset::new(0x{:x});", bitfield.name, bitfield.mask)?; - - // We create masks for the individual bits in the field if there - // is more than one bit in the field. - 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 = Mask::new(1<<{});", - bitfield.name, current_mask_bit_num, current_register_bit_num)?; - current_mask_bit_num += 1; - } - - current_mask >>= 1; - } - writeln!(w)?; - } - writeln!(w, "}}")?; - writeln!(w)?; - - writeln!(w, "impl Register for {} {{", register.name)?; - writeln!(w, " type T = {};", ty)?; - writeln!(w, " const ADDRESS: *mut {} = 0x{:x} as *mut {};", ty, register.offset, ty)?; - writeln!(w, "}}")?; - } - - Ok(()) - } - - pub fn write_pins(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - if let Some(port) = mcu.peripheral("PORT") { - writeln!(w, "pub mod port {{")?; - writeln!(w, " use super::*;")?; - writeln!(w, " use Pin;")?; - writeln!(w)?; - - for instance in port.instances.iter() { - let port_letter = instance.name.chars().rev().next().unwrap(); - - for signal in instance.signals.iter() { - let idx = signal.index.expect("signal with no index"); - let struct_name = format!("{}{}", port_letter, idx); - - let io_module = mcu.modules.iter().find(|m| m.name == "PORT") - .expect("no port io module defined for this port"); - let register_group = io_module.register_groups.iter() - .find(|rg| rg.name == instance.name) - .expect("no register group defined for this port"); - - writeln!(w, " pub struct {};", struct_name)?; - writeln!(w)?; - writeln!(w, " impl Pin for {} {{", struct_name)?; - for reg in register_group.registers.iter() { - let mut const_name = reg.name.clone(); - const_name.pop(); // Pop port character from register name (DDRB/PORTB/etc).. - - writeln!(w, " /// {}.", reg.caption)?; - writeln!(w, " type {} = {};", const_name, reg.name)?; - } - writeln!(w, " /// {}", signal.pad)?; - writeln!(w, " const MASK: u8 = 1<<{};", idx)?; - writeln!(w, " }}")?; - writeln!(w)?; - } - } - - writeln!(w, "}}")?; - writeln!(w)?; - } - Ok(()) - } - - pub fn write_spi_modules(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - if let Some(module) = mcu.module("SPI") { - let peripheral = mcu.peripheral("SPI").expect("found SPI module but no peripheral"); - let port_peripheral = mcu.port_peripheral(); - - writeln!(w, "pub struct Spi;")?; - writeln!(w)?; - writeln!(w, "impl modules::HardwareSpi for Spi {{")?; - - for spi_signal in peripheral.signals() { - let spi_signal_name = spi_signal.group.clone().expect("spi signal does not have group name"); - let (port_instance, port_signal) = port_peripheral.instance_signal_with_pad(&spi_signal.pad) - .expect("no port signal associated with the spi signal pad"); - let pin_name = self::pin_name(port_instance, port_signal); - - let const_name = match &spi_signal_name[..] { - "MISO" => "MasterInSlaveOut", - "MOSI" => "MasterOutSlaveIn", - "SCK" => "Clock", - "SS" => "SlaveSelect", - _ => panic!("unknown spi signal name: '{}'", spi_signal_name), - }; - - writeln!(w, " type {} = {};", const_name, pin_name)?; - } - - for reg in module.registers() { - let const_name = match ®.caption[..] { - "SPI Data Register" => "DataRegister", - "SPI Status Register" => "StatusRegister", - "SPI Control Register" => "ControlRegister", - _ => panic!("unknown SPI module register: {}", reg.caption), - }; - - writeln!(w, " type {} = {};", const_name, reg.name)?; - } - writeln!(w, "}}")?; - writeln!(w)?; - } - Ok(()) - } - - pub fn write_usarts(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - if let Some(module) = mcu.module("USART") { - for usart in module.register_groups.iter() { - writeln!(w, "/// The {} module.", usart.name)?; - writeln!(w, "pub struct {};", usart.name)?; - writeln!(w)?; - writeln!(w, "impl modules::HardwareUsart for {} {{", usart.name)?; - for register in usart.registers.iter() { - let reg_ty = if register.name.starts_with("UDR") { // the data register. - "DataRegister".to_owned() - } else if register.name.starts_with("UCSR") { // one of the three control/status registers. - let suffix = register.name.chars().rev().next().unwrap(); - format!("ControlRegister{}", suffix) - } else if register.name.starts_with("UBRR") { // the baud rate register. - "BaudRateRegister".to_owned() - } else { - panic!("unknown usart register '{}'", register.name); - }; - writeln!(w, " type {} = {};", reg_ty, register.name)?; - } - writeln!(w, "}}")?; - writeln!(w)?; - } - } - Ok(()) - } - - pub fn write_timers(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { - if let Some(tc) = mcu.module("TC8") { // Timer/Counter, 8-bit. - const TYPE_NAME: &'static str = "Timer8"; - - let find_reg = |name: &'static str| { - tc.registers().find(|r| r.name.starts_with(name)) - .expect(&format!("could not find '{}' register", name)) - }; - let find_reg_suffix = |name: &'static str, suffix: &'static str| { - tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix)) - .expect(&format!("could not find '{}' register", name)) - }; - - writeln!(w, "/// 8-bit timer.")?; - writeln!(w, "pub struct {};", TYPE_NAME)?; - writeln!(w)?; - writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?; - writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; - writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; - writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; - writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; - writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; - writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; - writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; - writeln!(w, " const CS0: Mask = Self::ControlB::CS00;")?; - writeln!(w, " const CS1: Mask = Self::ControlB::CS01;")?; - writeln!(w, " const CS2: Mask = Self::ControlB::CS02;")?; - writeln!(w, " const WGM0: Mask = Self::ControlA::WGM00;")?; - writeln!(w, " const WGM1: Mask = Self::ControlA::WGM01;")?; - writeln!(w, " const WGM2: Mask = Self::ControlB::WGM020;")?; - writeln!(w, " const OCIEA: Bitset = Self::InterruptMask::OCIE0A;")?; - writeln!(w, "}}")?; - } - - if let Some(tc) = mcu.module("TC16") { // Timer/Counter, 16-bit. - const TYPE_NAME: &'static str = "Timer16"; - - let find_reg = |name: &'static str| { - tc.registers().find(|r| r.name.starts_with(name)) - .expect(&format!("could not find '{}' register", name)) - }; - let find_reg_suffix = |name: &'static str, suffix: &'static str| { - tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix)) - .expect(&format!("could not find '{}' register", name)) - }; - - writeln!(w, "/// 16-bit timer.")?; - writeln!(w, "pub struct {};", TYPE_NAME)?; - writeln!(w)?; - writeln!(w, "impl modules::Timer16 for {} {{", TYPE_NAME)?; - writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; - writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; - writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; - writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; - writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; - writeln!(w, " type ControlC = {};", find_reg_suffix("TCCR", "C").name)?; - writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; - writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; - writeln!(w, " const CS0: Mask = Self::ControlB::CS10;")?; - writeln!(w, " const CS1: Mask = Self::ControlB::CS11;")?; - writeln!(w, " const CS2: Mask = Self::ControlB::CS12;")?; - writeln!(w, " const WGM0: Mask = Self::ControlA::WGM10;")?; - writeln!(w, " const WGM1: Mask = Self::ControlA::WGM11;")?; - writeln!(w, " const WGM2: Mask = Self::ControlB::WGM10;")?; - writeln!(w, " const WGM3: Mask = Self::ControlB::WGM11;")?; - writeln!(w, " const OCIEA: Bitset = Self::InterruptMask::OCIE1A;")?; - writeln!(w, "}}")?; - } - - Ok(()) - } - - /// Gets the name of a pin. - fn pin_name(instance: &Instance, signal: &Signal) -> String { - let idx = signal.index.expect("signal with no index"); - let letter = instance.name.chars().rev().next().unwrap(); - format!("port::{}{}", letter, idx) - } -} - diff --git a/core_generator/build.rs b/core_generator/build.rs new file mode 100644 index 0000000..d69a66e --- /dev/null +++ b/core_generator/build.rs @@ -0,0 +1,88 @@ +extern crate avr_mcu; + +use avr_mcu::*; +use std::fs::{self, File}; +use std::io; +use std::io::prelude::*; +use std::path::{Path, PathBuf}; + +fn src_path() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("src") +} + +fn cores_path() -> PathBuf { + src_path().join("cores") +} + +fn core_module_name(mcu: &Mcu) -> String { + mcu.device.name.to_lowercase().to_owned() +} + +fn main() { + if !cores_path().exists() { + fs::create_dir_all(&cores_path()).expect("could not create cores directory"); + } + + let current_mcu = avr_mcu::current::mcu() + .expect("no target cpu specified"); + generate_config_module().unwrap(); + generate_cores(&[current_mcu]).unwrap(); +} + +fn generate_cores(mcus: &[Mcu]) -> Result<(), io::Error> { + for mcu in mcus { + generate_core_module(mcu).expect("failed to generate mcu core"); + } + 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> { + let path = cores_path().join(format!("{}.rs", core_module_name(mcu))); + let mut file = File::create(&path)?; + write_core_module(mcu, &mut file) +} + +fn generate_cores_mod_rs(mcus: &[Mcu]) -> Result<(), io::Error> { + let path = cores_path().join("mod.rs"); + let mut w = File::create(&path)?; + + writeln!(w, "//! Cores")?; + writeln!(w)?; + for mcu in mcus { + let module_name = core_module_name(mcu); + writeln!(w, "/// The {}.", mcu.device.name)?; + writeln!(w, "pub mod {};", module_name)?; + + writeln!(w, "#[cfg(all(target_arch = \"avr\", target_cpu = \"{}\"))]", module_name)?; + writeln!(w, "pub use self::{} as current;", module_name)?; + } + writeln!(w) +} + +fn write_core_module(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + writeln!(w, "//! Core for {}.", mcu.device.name)?; + writeln!(w)?; + writeln!(w, "use {{Mask, Bitset, Register}};")?; + writeln!(w, "use modules;")?; + writeln!(w)?; + + gen::write_registers(mcu, w)?; + gen::write_pins(mcu, w)?; + gen::write_spi_modules(mcu, w)?; + gen::write_usarts(mcu, w)?; + gen::write_timers(mcu, w)?; + + writeln!(w) +} + +mod gen; + diff --git a/core_generator/gen.rs b/core_generator/gen.rs new file mode 100644 index 0000000..40fe789 --- /dev/null +++ b/core_generator/gen.rs @@ -0,0 +1,236 @@ +use avr_mcu::*; +use std::io; +use std::io::prelude::*; + +pub fn write_registers(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + for register in mcu.registers() { + let ty = if register.size == 1 { "u8" } else { "u16" }; + + // HACK: Skip, atmeg328p pack defines two of these. + if register.name == "GTCCR" { continue; } + + 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 = Bitset::new(0x{:x});", bitfield.name, bitfield.mask)?; + + // We create masks for the individual bits in the field if there + // is more than one bit in the field. + 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 = Mask::new(1<<{});", + bitfield.name, current_mask_bit_num, current_register_bit_num)?; + current_mask_bit_num += 1; + } + + current_mask >>= 1; + } + writeln!(w)?; + } + writeln!(w, "}}")?; + writeln!(w)?; + + writeln!(w, "impl Register for {} {{", register.name)?; + writeln!(w, " type T = {};", ty)?; + writeln!(w, " const ADDRESS: *mut {} = 0x{:x} as *mut {};", ty, register.offset, ty)?; + writeln!(w, "}}")?; + } + + Ok(()) +} + +pub fn write_pins(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + if let Some(port) = mcu.peripheral("PORT") { + writeln!(w, "pub mod port {{")?; + writeln!(w, " use super::*;")?; + writeln!(w, " use Pin;")?; + writeln!(w)?; + + for instance in port.instances.iter() { + let port_letter = instance.name.chars().rev().next().unwrap(); + + for signal in instance.signals.iter() { + let idx = signal.index.expect("signal with no index"); + let struct_name = format!("{}{}", port_letter, idx); + + let io_module = mcu.modules.iter().find(|m| m.name == "PORT") + .expect("no port io module defined for this port"); + let register_group = io_module.register_groups.iter() + .find(|rg| rg.name == instance.name) + .expect("no register group defined for this port"); + + writeln!(w, " pub struct {};", struct_name)?; + writeln!(w)?; + writeln!(w, " impl Pin for {} {{", struct_name)?; + for reg in register_group.registers.iter() { + let mut const_name = reg.name.clone(); + const_name.pop(); // Pop port character from register name (DDRB/PORTB/etc).. + + writeln!(w, " /// {}.", reg.caption)?; + writeln!(w, " type {} = {};", const_name, reg.name)?; + } + writeln!(w, " /// {}", signal.pad)?; + writeln!(w, " const MASK: u8 = 1<<{};", idx)?; + writeln!(w, " }}")?; + writeln!(w)?; + } + } + + writeln!(w, "}}")?; + writeln!(w)?; + } + Ok(()) +} + +pub fn write_spi_modules(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + if let Some(module) = mcu.module("SPI") { + let peripheral = mcu.peripheral("SPI").expect("found SPI module but no peripheral"); + let port_peripheral = mcu.port_peripheral(); + + writeln!(w, "pub struct Spi;")?; + writeln!(w)?; + writeln!(w, "impl modules::HardwareSpi for Spi {{")?; + + for spi_signal in peripheral.signals() { + let spi_signal_name = spi_signal.group.clone().expect("spi signal does not have group name"); + let (port_instance, port_signal) = port_peripheral.instance_signal_with_pad(&spi_signal.pad) + .expect("no port signal associated with the spi signal pad"); + let pin_name = self::pin_name(port_instance, port_signal); + + let const_name = match &spi_signal_name[..] { + "MISO" => "MasterInSlaveOut", + "MOSI" => "MasterOutSlaveIn", + "SCK" => "Clock", + "SS" => "SlaveSelect", + _ => panic!("unknown spi signal name: '{}'", spi_signal_name), + }; + + writeln!(w, " type {} = {};", const_name, pin_name)?; + } + + for reg in module.registers() { + let const_name = match ®.caption[..] { + "SPI Data Register" => "DataRegister", + "SPI Status Register" => "StatusRegister", + "SPI Control Register" => "ControlRegister", + _ => panic!("unknown SPI module register: {}", reg.caption), + }; + + writeln!(w, " type {} = {};", const_name, reg.name)?; + } + writeln!(w, "}}")?; + writeln!(w)?; + } + Ok(()) +} + +pub fn write_usarts(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + if let Some(module) = mcu.module("USART") { + for usart in module.register_groups.iter() { + writeln!(w, "/// The {} module.", usart.name)?; + writeln!(w, "pub struct {};", usart.name)?; + writeln!(w)?; + writeln!(w, "impl modules::HardwareUsart for {} {{", usart.name)?; + for register in usart.registers.iter() { + let reg_ty = if register.name.starts_with("UDR") { // the data register. + "DataRegister".to_owned() + } else if register.name.starts_with("UCSR") { // one of the three control/status registers. + let suffix = register.name.chars().rev().next().unwrap(); + format!("ControlRegister{}", suffix) + } else if register.name.starts_with("UBRR") { // the baud rate register. + "BaudRateRegister".to_owned() + } else { + panic!("unknown usart register '{}'", register.name); + }; + writeln!(w, " type {} = {};", reg_ty, register.name)?; + } + writeln!(w, "}}")?; + writeln!(w)?; + } + } + Ok(()) +} + +pub fn write_timers(mcu: &Mcu, w: &mut Write) -> Result<(), io::Error> { + if let Some(tc) = mcu.module("TC8") { // Timer/Counter, 8-bit. + const TYPE_NAME: &'static str = "Timer8"; + + let find_reg = |name: &'static str| { + tc.registers().find(|r| r.name.starts_with(name)) + .expect(&format!("could not find '{}' register", name)) + }; + let find_reg_suffix = |name: &'static str, suffix: &'static str| { + tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix)) + .expect(&format!("could not find '{}' register", name)) + }; + + writeln!(w, "/// 8-bit timer.")?; + writeln!(w, "pub struct {};", TYPE_NAME)?; + writeln!(w)?; + writeln!(w, "impl modules::Timer8 for {} {{", TYPE_NAME)?; + writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; + writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; + writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; + writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; + writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; + writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; + writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; + writeln!(w, " const CS0: Mask = Self::ControlB::CS00;")?; + writeln!(w, " const CS1: Mask = Self::ControlB::CS01;")?; + writeln!(w, " const CS2: Mask = Self::ControlB::CS02;")?; + writeln!(w, " const WGM0: Mask = Self::ControlA::WGM00;")?; + writeln!(w, " const WGM1: Mask = Self::ControlA::WGM01;")?; + writeln!(w, " const WGM2: Mask = Self::ControlB::WGM020;")?; + writeln!(w, " const OCIEA: Bitset = Self::InterruptMask::OCIE0A;")?; + writeln!(w, "}}")?; + } + + if let Some(tc) = mcu.module("TC16") { // Timer/Counter, 16-bit. + const TYPE_NAME: &'static str = "Timer16"; + + let find_reg = |name: &'static str| { + tc.registers().find(|r| r.name.starts_with(name)) + .expect(&format!("could not find '{}' register", name)) + }; + let find_reg_suffix = |name: &'static str, suffix: &'static str| { + tc.registers().find(|r| r.name.starts_with(name) && r.name.ends_with(suffix)) + .expect(&format!("could not find '{}' register", name)) + }; + + writeln!(w, "/// 16-bit timer.")?; + writeln!(w, "pub struct {};", TYPE_NAME)?; + writeln!(w)?; + writeln!(w, "impl modules::Timer16 for {} {{", TYPE_NAME)?; + writeln!(w, " type CompareA = {};", find_reg_suffix("OCR", "A").name)?; + writeln!(w, " type CompareB = {};", find_reg_suffix("OCR", "B").name)?; + writeln!(w, " type Counter = {};", find_reg("TCNT").name)?; + writeln!(w, " type ControlA = {};", find_reg_suffix("TCCR", "A").name)?; + writeln!(w, " type ControlB = {};", find_reg_suffix("TCCR", "B").name)?; + writeln!(w, " type ControlC = {};", find_reg_suffix("TCCR", "C").name)?; + writeln!(w, " type InterruptMask = {};", find_reg("TIMSK").name)?; + writeln!(w, " type InterruptFlag = {};", find_reg("TIFR").name)?; + writeln!(w, " const CS0: Mask = Self::ControlB::CS10;")?; + writeln!(w, " const CS1: Mask = Self::ControlB::CS11;")?; + writeln!(w, " const CS2: Mask = Self::ControlB::CS12;")?; + writeln!(w, " const WGM0: Mask = Self::ControlA::WGM10;")?; + writeln!(w, " const WGM1: Mask = Self::ControlA::WGM11;")?; + writeln!(w, " const WGM2: Mask = Self::ControlB::WGM10;")?; + writeln!(w, " const WGM3: Mask = Self::ControlB::WGM11;")?; + writeln!(w, " const OCIEA: Bitset = Self::InterruptMask::OCIE1A;")?; + writeln!(w, "}}")?; + } + + Ok(()) +} + +/// Gets the name of a pin. +fn pin_name(instance: &Instance, signal: &Signal) -> String { + let idx = signal.index.expect("signal with no index"); + let letter = instance.name.chars().rev().next().unwrap(); + format!("port::{}{}", letter, idx) +}