first commit
This commit is contained in:
commit
728e7d5be7
|
@ -0,0 +1,5 @@
|
|||
/target
|
||||
*/target/
|
||||
*/Cargo.lock/
|
||||
Cargo.lock
|
||||
.cargo
|
|
@ -0,0 +1,27 @@
|
|||
[package]
|
||||
name = "static_pins"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
|
||||
[dependencies.static_pins_macros]
|
||||
path = "static_pins_macros"
|
||||
|
||||
[dependencies.arduino-hal]
|
||||
git = "https://github.com/rahix/avr-hal"
|
||||
rev = "3e362624547462928a219c40f9ea8e3a64f21e5f"
|
||||
features = ["sparkfun-promicro"]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
debug = true
|
||||
lto = true
|
||||
opt-level = "s"
|
|
@ -0,0 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-06-13"
|
||||
components = [ "rust-src" ]
|
||||
profile = "minimal"
|
|
@ -0,0 +1,49 @@
|
|||
#![no_std]
|
||||
|
||||
pub use static_pins_macros::*;
|
||||
|
||||
pub trait StaticPinOps {
|
||||
type Port;
|
||||
const PIN_NUM: u8;
|
||||
const PIN_POS: u8;
|
||||
|
||||
fn into_input();
|
||||
fn into_output();
|
||||
fn into_output_high();
|
||||
fn into_pull_up_input();
|
||||
|
||||
fn write(data: u8);
|
||||
fn read() -> u8;
|
||||
|
||||
fn set_low();
|
||||
fn set_high();
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_static_pins {
|
||||
($($pin:expr), +) => {
|
||||
pub trait StaticPinOps {
|
||||
type Port;
|
||||
const PIN_NUM: u8;
|
||||
const PIN_POS: u8;
|
||||
|
||||
fn into_input();
|
||||
fn into_output();
|
||||
fn into_output_high();
|
||||
fn into_pull_up_input();
|
||||
|
||||
fn write(data: u8);
|
||||
fn read() -> u8;
|
||||
|
||||
fn is_low() -> bool;
|
||||
fn is_high() -> bool;
|
||||
|
||||
fn set_low();
|
||||
fn set_high();
|
||||
}
|
||||
|
||||
$(
|
||||
impl_static_pin!($pin);
|
||||
)+
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
[package]
|
||||
name = "static_pins_macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
proc_macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0.39"
|
||||
syn = "2.0.58"
|
||||
proc-macro2 = "1.0.94"
|
||||
|
||||
[dependencies.arduino-hal]
|
||||
git = "https://github.com/rahix/avr-hal"
|
||||
rev = "3e362624547462928a219c40f9ea8e3a64f21e5f"
|
||||
features = ["sparkfun-promicro"]
|
||||
|
||||
[profile.dev]
|
||||
panic = "abort"
|
||||
lto = true
|
||||
opt-level = "s"
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
codegen-units = 1
|
||||
debug = true
|
||||
lto = true
|
||||
opt-level = "s"
|
|
@ -0,0 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-06-13"
|
||||
components = [ "rust-src" ]
|
||||
profile = "minimal"
|
|
@ -0,0 +1,147 @@
|
|||
#![feature(proc_macro_quote)]
|
||||
|
||||
use core::str::FromStr;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::parse;
|
||||
|
||||
const ASCII_DIGIT_OFFSET: u8 = 48;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn impl_static_pin(pin: TokenStream) -> TokenStream {
|
||||
let parsing_result = parse::<syn::Ident>(pin.clone());
|
||||
|
||||
if let Ok(pin) = parsing_result {
|
||||
let mut port = pin.to_string();
|
||||
let writer_method = format_ident!("{}", port.to_ascii_lowercase());
|
||||
port.insert_str(1, "ORT");
|
||||
|
||||
let pin_num = match port.pop() {
|
||||
Some(num) if num.is_ascii_digit() => (num as u8) - ASCII_DIGIT_OFFSET,
|
||||
_ => panic!("Pin number is incorrect"),
|
||||
};
|
||||
|
||||
let pin_pos = 1u8 << pin_num;
|
||||
|
||||
let port_type = proc_macro2::TokenStream::from_str(&port).unwrap();
|
||||
|
||||
let port_register_name = match port.chars().last() {
|
||||
Some(register) if register.is_ascii_alphabetic() => register,
|
||||
_ => panic!("Register name is incorrect"),
|
||||
};
|
||||
|
||||
let target_port = proc_macro2::TokenStream::from_str(&port.to_ascii_lowercase()).unwrap();
|
||||
let target_pin = format_ident!("pin{}", port_register_name.to_ascii_lowercase());
|
||||
let target_data_direction = format_ident!("ddr{}", port_register_name.to_ascii_lowercase());
|
||||
|
||||
let trait_name = proc_macro2::TokenStream::from_str("StaticPinOps").unwrap();
|
||||
|
||||
let impl_trait = quote! {
|
||||
impl #trait_name for #pin {
|
||||
type Port = #port_type;
|
||||
const PIN_NUM: u8 = #pin_num;
|
||||
const PIN_POS: u8 = #pin_pos;
|
||||
|
||||
#[inline(always)]
|
||||
fn write(data: u8) {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.write(|w| w.bits(data));
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn read() -> u8 {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_pin
|
||||
.read()
|
||||
.bits()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_low() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().clear_bit())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn set_high() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().set_bit())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn is_low() -> bool {
|
||||
(Self::read() & Self::PIN_POS) == 0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn is_high() -> bool {
|
||||
(Self::read() & Self::PIN_POS) != 0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn into_input() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_data_direction
|
||||
.modify(|_r, w| w.#writer_method().clear_bit());
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().clear_bit());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn into_output() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_data_direction
|
||||
.modify(|_r, w| w.#writer_method().set_bit());
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().clear_bit());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn into_output_high() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_data_direction
|
||||
.modify(|_r, w| w.#writer_method().set_bit());
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().set_bit());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn into_pull_up_input() {
|
||||
unsafe {
|
||||
(*Self::Port::ptr())
|
||||
.#target_data_direction
|
||||
.modify(|_r, w| w.#writer_method().clear_bit());
|
||||
(*Self::Port::ptr())
|
||||
.#target_port
|
||||
.modify(|_r, w| w.#writer_method().set_bit());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(impl_trait)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue